redesign the homepage
Build & Deploy / Build & Push Docker Image (push) Failing after 47s
Build & Deploy / Deploy to VPS (push) Has been skipped
Test / API Unit Tests (push) Failing after 5m4s
Test / Marketplace Unit Tests (push) Failing after 4m55s
Test / Admin Unit Tests (push) Successful in 9m37s
Test / Dashboard Unit Tests (push) Successful in 9m37s
Test / API Integration Tests (push) Successful in 9m54s
Build & Deploy / Build & Push Docker Image (push) Failing after 47s
Build & Deploy / Deploy to VPS (push) Has been skipped
Test / API Unit Tests (push) Failing after 5m4s
Test / Marketplace Unit Tests (push) Failing after 4m55s
Test / Admin Unit Tests (push) Successful in 9m37s
Test / Dashboard Unit Tests (push) Successful in 9m37s
Test / API Integration Tests (push) Successful in 9m54s
This commit is contained in:
@@ -0,0 +1,146 @@
|
||||
import { beforeEach, describe, expect, it, vi } from 'vitest'
|
||||
|
||||
const nextServer = vi.hoisted(() => {
|
||||
const next = vi.fn((init?: { request?: { headers?: Headers } }) => ({
|
||||
kind: 'next',
|
||||
init,
|
||||
cookies: {
|
||||
set: vi.fn(),
|
||||
},
|
||||
}))
|
||||
const redirect = vi.fn((url: URL, status?: number) => ({
|
||||
kind: 'redirect',
|
||||
url: url.toString(),
|
||||
status,
|
||||
}))
|
||||
const MockNextResponse = vi.fn((body?: string, init?: { status?: number }) => ({
|
||||
kind: 'response',
|
||||
body,
|
||||
status: init?.status,
|
||||
})) as any
|
||||
MockNextResponse.next = next
|
||||
MockNextResponse.redirect = redirect
|
||||
return { next, redirect, MockNextResponse }
|
||||
})
|
||||
|
||||
vi.mock('next/server', () => ({
|
||||
NextResponse: nextServer.MockNextResponse,
|
||||
}))
|
||||
|
||||
function request(options: { cookies?: Record<string, string>; headers?: Record<string, string> } = {}) {
|
||||
const cookies = new Map(Object.entries(options.cookies ?? {}))
|
||||
const headers = new Headers(options.headers ?? {})
|
||||
return {
|
||||
nextUrl: cloneableUrl('http://localhost:3000/'),
|
||||
cookies: {
|
||||
get: vi.fn((name: string) => {
|
||||
const value = cookies.get(name)
|
||||
return value ? { value } : undefined
|
||||
}),
|
||||
},
|
||||
headers,
|
||||
}
|
||||
}
|
||||
|
||||
function cloneableUrl(input: string): URL {
|
||||
const url = new URL(input)
|
||||
;(url as URL & { clone: () => URL }).clone = () => cloneableUrl(url.toString())
|
||||
return url
|
||||
}
|
||||
|
||||
function middlewareRequest(input: string) {
|
||||
return {
|
||||
cookies: {
|
||||
get: vi.fn(),
|
||||
},
|
||||
headers: new Headers(),
|
||||
nextUrl: cloneableUrl(input),
|
||||
}
|
||||
}
|
||||
|
||||
beforeEach(() => {
|
||||
nextServer.next.mockClear()
|
||||
nextServer.redirect.mockClear()
|
||||
})
|
||||
|
||||
describe('marketplace proxy language bootstrap', () => {
|
||||
|
||||
it('rejects proxy subrequest headers before language handling', async () => {
|
||||
const { proxy } = await import('./proxy')
|
||||
|
||||
const response = proxy(request({
|
||||
headers: { 'x-middleware-subrequest': 'middleware:middleware' },
|
||||
}) as never) as any
|
||||
|
||||
expect(response).toEqual({ kind: 'response', body: 'Unsupported internal request header', status: 400 })
|
||||
expect(nextServer.next).not.toHaveBeenCalled()
|
||||
})
|
||||
it('does nothing when the canonical shared language cookie is valid', async () => {
|
||||
const { proxy } = await import('./proxy')
|
||||
|
||||
const response = proxy(request({ cookies: { 'rentaldrivego-language': 'fr' } }) as never) as any
|
||||
|
||||
expect(response.kind).toBe('next')
|
||||
expect(nextServer.next).toHaveBeenCalledWith()
|
||||
expect(response.cookies.set).not.toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it('migrates the legacy marketplace language cookie into the shared cookie and request headers', async () => {
|
||||
const { proxy } = await import('./proxy')
|
||||
|
||||
const response = proxy(request({
|
||||
cookies: { 'marketplace-language': 'ar' },
|
||||
headers: { cookie: 'session=abc' },
|
||||
}) as never) as any
|
||||
|
||||
expect(response.cookies.set).toHaveBeenCalledWith('rentaldrivego-language', 'ar', expect.objectContaining({
|
||||
path: '/',
|
||||
sameSite: 'lax',
|
||||
}))
|
||||
expect(response.init?.request?.headers?.get('cookie')).toBe('session=abc; rentaldrivego-language=ar')
|
||||
})
|
||||
|
||||
it('detects Arabic and French from Accept-Language before falling back to English', async () => {
|
||||
const { proxy } = await import('./proxy')
|
||||
|
||||
const arabic = proxy(request({ headers: { 'accept-language': 'ar-MA,fr;q=0.8,en;q=0.6' } }) as never) as any
|
||||
expect(arabic.cookies.set).toHaveBeenCalledWith('rentaldrivego-language', 'ar', expect.any(Object))
|
||||
expect(arabic.init?.request?.headers?.get('cookie')).toBe('rentaldrivego-language=ar')
|
||||
|
||||
const french = proxy(request({ headers: { 'accept-language': 'de-DE,fr-FR;q=0.7,en;q=0.3' } }) as never) as any
|
||||
expect(french.cookies.set).toHaveBeenCalledWith('rentaldrivego-language', 'fr', expect.any(Object))
|
||||
|
||||
const fallback = proxy(request({ headers: { 'accept-language': 'de-DE,es;q=0.9' } }) as never) as any
|
||||
expect(fallback.cookies.set).toHaveBeenCalledWith('rentaldrivego-language', 'en', expect.any(Object))
|
||||
})
|
||||
|
||||
it('rejects invalid shared and legacy language values before resolving from headers', async () => {
|
||||
const { proxy } = await import('./proxy')
|
||||
|
||||
const response = proxy(request({
|
||||
cookies: { 'rentaldrivego-language': 'es', 'marketplace-language': 'it' },
|
||||
headers: { 'accept-language': 'fr-CA,ar;q=0.5' },
|
||||
}) as never) as any
|
||||
|
||||
expect(response.cookies.set).toHaveBeenCalledWith('rentaldrivego-language', 'fr', expect.any(Object))
|
||||
expect(response.init?.request?.headers?.get('cookie')).toBe('rentaldrivego-language=fr')
|
||||
})
|
||||
})
|
||||
|
||||
describe('marketplace middleware dashboard path canonicalization', () => {
|
||||
it('redirects duplicate dashboard prefixes to the clean dashboard URL', async () => {
|
||||
const { proxy } = await import('./proxy')
|
||||
|
||||
const response = proxy(middlewareRequest('http://localhost:3000/dashboard/dashboard') as never)
|
||||
|
||||
expect(response).toEqual({ kind: 'redirect', url: 'http://localhost:3000/dashboard', status: 307 })
|
||||
})
|
||||
|
||||
it('preserves nested dashboard paths while removing the duplicate prefix', async () => {
|
||||
const { proxy } = await import('./proxy')
|
||||
|
||||
const response = proxy(middlewareRequest('http://localhost:3000/dashboard/dashboard/fleet?tab=active') as never)
|
||||
|
||||
expect(response).toEqual({ kind: 'redirect', url: 'http://localhost:3000/dashboard/fleet?tab=active', status: 307 })
|
||||
})
|
||||
})
|
||||
Reference in New Issue
Block a user