fix architecture and write new tests
This commit is contained in:
@@ -0,0 +1,47 @@
|
||||
import { afterEach, describe, expect, it, vi } from 'vitest'
|
||||
|
||||
afterEach(() => {
|
||||
delete process.env.API_INTERNAL_URL
|
||||
delete process.env.NEXT_PUBLIC_API_URL
|
||||
vi.restoreAllMocks()
|
||||
Reflect.deleteProperty(globalThis, 'fetch')
|
||||
vi.resetModules()
|
||||
})
|
||||
|
||||
describe('adminFetch', () => {
|
||||
it('requests through the server API base and returns the data envelope', async () => {
|
||||
process.env.API_INTERNAL_URL = 'http://internal-api/api/v1'
|
||||
const fetchMock = vi.fn(async () => ({
|
||||
ok: true,
|
||||
json: async () => ({ data: { companies: [] } }),
|
||||
}))
|
||||
Object.defineProperty(globalThis, 'fetch', { configurable: true, value: fetchMock })
|
||||
|
||||
const { adminFetch } = await import('./api')
|
||||
await expect(adminFetch('/admin/companies', 'admin-token')).resolves.toEqual({ companies: [] })
|
||||
|
||||
expect(fetchMock).toHaveBeenCalledWith('http://internal-api/api/v1/admin/companies', {
|
||||
cache: 'no-store',
|
||||
credentials: 'include',
|
||||
})
|
||||
})
|
||||
|
||||
it('omits authorization when no token is supplied', async () => {
|
||||
delete process.env.API_INTERNAL_URL
|
||||
const fetchMock = vi.fn(async () => ({ ok: true, json: async () => ({ data: { ok: true } }) }))
|
||||
Object.defineProperty(globalThis, 'fetch', { configurable: true, value: fetchMock })
|
||||
|
||||
const { adminFetch } = await import('./api')
|
||||
await adminFetch('/public')
|
||||
|
||||
expect((fetchMock as any).mock.calls[0]?.[1]).toEqual({ cache: 'no-store', credentials: 'include' })
|
||||
})
|
||||
|
||||
it('throws the API message from failed responses', async () => {
|
||||
const fetchMock = vi.fn(async () => ({ ok: false, json: async () => ({ message: 'Admin only' }) }))
|
||||
Object.defineProperty(globalThis, 'fetch', { configurable: true, value: fetchMock })
|
||||
|
||||
const { adminFetch } = await import('./api')
|
||||
await expect(adminFetch('/admin/menu')).rejects.toThrow('Admin only')
|
||||
})
|
||||
})
|
||||
@@ -3,10 +3,10 @@ export const ADMIN_API_BASE =
|
||||
? (process.env.API_INTERNAL_URL ?? process.env.NEXT_PUBLIC_API_URL ?? 'http://localhost:4000/api/v1')
|
||||
: (process.env.NEXT_PUBLIC_API_URL ?? '/admin/api/v1')
|
||||
|
||||
export async function adminFetch<T>(path: string, token?: string): Promise<T> {
|
||||
export async function adminFetch<T>(path: string, _token?: string): Promise<T> {
|
||||
const res = await fetch(`${ADMIN_API_BASE}${path}`, {
|
||||
cache: 'no-store',
|
||||
headers: token ? { Authorization: `Bearer ${token}` } : undefined,
|
||||
credentials: 'include',
|
||||
})
|
||||
const json = await res.json()
|
||||
if (!res.ok) throw new Error(json?.message ?? 'Request failed')
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
import { afterEach, describe, expect, it } from 'vitest'
|
||||
import { resolveBrowserAppUrl, resolveServerAppUrl } from './appUrls'
|
||||
|
||||
function installWindow(hostname: string, protocol = 'https:') {
|
||||
Object.defineProperty(globalThis, 'window', {
|
||||
configurable: true,
|
||||
value: { location: { hostname, protocol } },
|
||||
})
|
||||
}
|
||||
|
||||
afterEach(() => {
|
||||
Reflect.deleteProperty(globalThis, 'window')
|
||||
})
|
||||
|
||||
describe('admin app URL resolution', () => {
|
||||
it('keeps server fallback unchanged without a browser window', () => {
|
||||
expect(resolveBrowserAppUrl('http://localhost:3002/admin')).toBe('http://localhost:3002/admin')
|
||||
})
|
||||
|
||||
it('removes trailing slash for localhost browser fallbacks', () => {
|
||||
installWindow('127.0.0.1')
|
||||
expect(resolveBrowserAppUrl('http://localhost:3002/admin/')).toBe('http://localhost:3002/admin')
|
||||
})
|
||||
|
||||
it('rewrites fallback origin to the current browser host in production', () => {
|
||||
installWindow('admin.rentaldrivego.ma')
|
||||
expect(resolveBrowserAppUrl('http://localhost:3002/admin')).toBe('https://admin.rentaldrivego.ma/admin')
|
||||
})
|
||||
|
||||
it('resolves server app URLs from forwarded host and protocol', () => {
|
||||
expect(resolveServerAppUrl('http://localhost:3002/admin', 'admin.example.com', 'https')).toBe('https://admin.example.com:3002/admin')
|
||||
})
|
||||
|
||||
it('falls back when host is missing or the fallback is not parseable', () => {
|
||||
expect(resolveServerAppUrl('http://localhost:3002/admin', null)).toBe('http://localhost:3002/admin')
|
||||
expect(resolveServerAppUrl('/admin', 'admin.example.com')).toBe('/admin')
|
||||
})
|
||||
})
|
||||
Reference in New Issue
Block a user