feat: API route GET /api/products/search (TDD)
Implémentation test-driven du endpoint de recherche de produits par référence. - Tests unitaires complets validant les cas nominaux et d'erreur - Validation du paramètre ref avec gestion des chaînes vides - Intégration avec searchProductByRef de lib/shopify - Gestion appropriée des erreurs HTTP (400, 500) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,53 @@
|
|||||||
|
import { GET } from '@/app/api/products/search/route'
|
||||||
|
import { NextRequest } from 'next/server'
|
||||||
|
|
||||||
|
jest.mock('@/lib/shopify', () => ({
|
||||||
|
searchProductByRef: jest.fn(),
|
||||||
|
}))
|
||||||
|
|
||||||
|
import { searchProductByRef } from '@/lib/shopify'
|
||||||
|
const mockSearch = searchProductByRef as jest.Mock
|
||||||
|
|
||||||
|
describe('GET /api/products/search', () => {
|
||||||
|
beforeEach(() => jest.clearAllMocks())
|
||||||
|
|
||||||
|
it('retourne 400 si le paramètre ref est absent', async () => {
|
||||||
|
const req = new NextRequest('http://localhost/api/products/search')
|
||||||
|
const res = await GET(req)
|
||||||
|
expect(res.status).toBe(400)
|
||||||
|
const data = await res.json()
|
||||||
|
expect(data.error).toMatch(/ref/)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('retourne 400 si ref est une chaîne vide', async () => {
|
||||||
|
const req = new NextRequest('http://localhost/api/products/search?ref=')
|
||||||
|
const res = await GET(req)
|
||||||
|
expect(res.status).toBe(400)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('retourne { found: false } si produit introuvable', async () => {
|
||||||
|
mockSearch.mockResolvedValue({ found: false })
|
||||||
|
const req = new NextRequest('http://localhost/api/products/search?ref=REF-9999')
|
||||||
|
const res = await GET(req)
|
||||||
|
expect(res.status).toBe(200)
|
||||||
|
expect(await res.json()).toEqual({ found: false })
|
||||||
|
expect(mockSearch).toHaveBeenCalledWith('REF-9999')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('retourne le produit trouvé', async () => {
|
||||||
|
mockSearch.mockResolvedValue({ found: true, shopifyId: '123456', title: 'Carrelage REF-1042' })
|
||||||
|
const req = new NextRequest('http://localhost/api/products/search?ref=REF-1042')
|
||||||
|
const res = await GET(req)
|
||||||
|
expect(res.status).toBe(200)
|
||||||
|
expect(await res.json()).toEqual({ found: true, shopifyId: '123456', title: 'Carrelage REF-1042' })
|
||||||
|
})
|
||||||
|
|
||||||
|
it('retourne 500 en cas d\'erreur Shopify', async () => {
|
||||||
|
mockSearch.mockRejectedValue(new Error('Shopify API error: 503'))
|
||||||
|
const req = new NextRequest('http://localhost/api/products/search?ref=REF-1042')
|
||||||
|
const res = await GET(req)
|
||||||
|
expect(res.status).toBe(500)
|
||||||
|
const data = await res.json()
|
||||||
|
expect(data.error).toBeTruthy()
|
||||||
|
})
|
||||||
|
})
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
import { NextRequest, NextResponse } from 'next/server'
|
||||||
|
import { searchProductByRef } from '@/lib/shopify'
|
||||||
|
|
||||||
|
export async function GET(req: NextRequest) {
|
||||||
|
const ref = req.nextUrl.searchParams.get('ref')
|
||||||
|
|
||||||
|
if (!ref || ref.trim() === '') {
|
||||||
|
return NextResponse.json({ error: 'Paramètre ref requis' }, { status: 400 })
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const result = await searchProductByRef(ref.trim())
|
||||||
|
return NextResponse.json(result)
|
||||||
|
} catch (err) {
|
||||||
|
const message = err instanceof Error ? err.message : 'Erreur inconnue'
|
||||||
|
return NextResponse.json({ error: message }, { status: 500 })
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user