fix test issues
Build & Deploy / Build & Push Docker Image (push) Successful in 3m1s
Test / Type Check (all packages) (push) Successful in 55s
Build & Deploy / Deploy to VPS (push) Successful in 5s
Test / API Unit Tests (push) Successful in 47s
Test / Homepage Unit Tests (push) Successful in 42s
Test / Carplace Unit Tests (push) Successful in 42s
Test / Admin Unit Tests (push) Successful in 40s
Test / Dashboard Unit Tests (push) Successful in 41s
Test / API Integration Tests (push) Successful in 1m0s

This commit is contained in:
root
2026-07-02 18:50:03 -04:00
parent e3f40410e9
commit f330efb1ad
8 changed files with 102 additions and 21 deletions
+54
View File
@@ -16,6 +16,7 @@ afterEach(() => {
Reflect.deleteProperty(globalThis, 'window')
Reflect.deleteProperty(globalThis, 'fetch')
delete process.env.NEXT_PUBLIC_API_URL
delete process.env.API_INTERNAL_URL
vi.resetModules()
})
@@ -54,6 +55,59 @@ describe('dashboard apiFetch', () => {
expect(fetchMock).toHaveBeenCalledWith('https://api.rentaldrivego.ma/api/v1/auth/account/start', expect.any(Object))
})
it.each([
['https://api.rentaldrivego.ma', 'https://api.rentaldrivego.ma/api/v1/auth/account/start'],
['https://api.rentaldrivego.ma/', 'https://api.rentaldrivego.ma/api/v1/auth/account/start'],
['https://api.rentaldrivego.ma/api', 'https://api.rentaldrivego.ma/api/v1/auth/account/start'],
['https://api.rentaldrivego.ma/api/v1', 'https://api.rentaldrivego.ma/api/v1/auth/account/start'],
['/dashboard/api/v1', '/dashboard/api/v1/auth/account/start'],
])('normalizes API base %s', async (configuredBase, expectedUrl) => {
installBrowser()
process.env.NEXT_PUBLIC_API_URL = configuredBase
const fetchMock = vi.fn(async () => ({
ok: true,
json: async () => ({ data: { ok: true } }),
}))
Object.defineProperty(globalThis, 'fetch', { configurable: true, value: fetchMock })
const { apiFetch } = await import('./api')
await apiFetch('/auth/account/start', { method: 'POST', body: JSON.stringify({}) })
expect(fetchMock).toHaveBeenCalledWith(expectedUrl, expect.any(Object))
})
it('falls back to the dashboard proxy when no public API URL is configured', async () => {
installBrowser()
const fetchMock = vi.fn(async () => ({
ok: true,
json: async () => ({ data: { ok: true } }),
}))
Object.defineProperty(globalThis, 'fetch', { configurable: true, value: fetchMock })
const { apiFetch } = await import('./api')
await apiFetch('/auth/account/start')
expect(fetchMock).toHaveBeenCalledWith('/dashboard/api/v1/auth/account/start', expect.any(Object))
})
it('does not add a dashboard prefix when an absolute API origin is configured', async () => {
installBrowser()
process.env.NEXT_PUBLIC_API_URL = 'https://api.rentaldrivego.ma/api/v1'
const fetchMock = vi.fn(async () => ({
ok: true,
json: async () => ({ data: { ok: true } }),
}))
Object.defineProperty(globalThis, 'fetch', { configurable: true, value: fetchMock })
const { apiFetch } = await import('./api')
await apiFetch('/auth/account/start')
const calledUrl = (fetchMock as any).mock.calls[0]?.[0]
expect(calledUrl).toBe('https://api.rentaldrivego.ma/api/v1/auth/account/start')
expect(calledUrl).not.toContain('/dashboard')
expect(calledUrl).not.toContain('/api/v1/api/v1')
})
it('does not force JSON content type for FormData payloads', async () => {
installBrowser()
const fetchMock = vi.fn(async () => ({ ok: true, json: async () => ({ data: { uploaded: true } }) }))
+12 -9
View File
@@ -1,15 +1,18 @@
function normalizeApiBase(value: string): string {
export function normalizeApiBase(value: string): string {
const base = value.replace(/\/+$/, '')
if (/\/api$/.test(base)) return `${base}/v1`
return /\/api\/v1$/.test(base) ? base : `${base}/api/v1`
}
export const API_BASE = normalizeApiBase(
typeof window === 'undefined'
export function resolveApiBase(): string {
const value = typeof window === 'undefined'
? (process.env.API_INTERNAL_URL || 'http://localhost:4000/api/v1')
: (process.env.NEXT_PUBLIC_DASHBOARD_DIRECT_API === 'true' && process.env.NEXT_PUBLIC_API_URL
? process.env.NEXT_PUBLIC_API_URL
: '/dashboard/api/v1'),
)
: (process.env.NEXT_PUBLIC_API_URL || '/dashboard/api/v1')
return normalizeApiBase(value)
}
export const API_BASE = resolveApiBase()
export const EMPLOYEE_PROFILE_KEY = 'employee_profile'
@@ -24,7 +27,7 @@ export async function apiFetch<T>(path: string, options?: RequestInit): Promise<
headers['Content-Type'] = 'application/json'
}
const res = await fetch(`${API_BASE}${path}`, {
const res = await fetch(`${resolveApiBase()}${path}`, {
...options,
headers,
credentials: 'include',
@@ -49,7 +52,7 @@ export async function apiFetch<T>(path: string, options?: RequestInit): Promise<
export async function apiFetchServer<T>(path: string, token: string, options?: RequestInit): Promise<T> {
const isFormData = typeof FormData !== 'undefined' && options?.body instanceof FormData
const res = await fetch(`${API_BASE}${path}`, {
const res = await fetch(`${resolveApiBase()}${path}`, {
...options,
headers: {
...(isFormData ? {} : { 'Content-Type': 'application/json' }),