feat(plan4): API GET /api/products/list avec filtre statut (TDD)
This commit is contained in:
@@ -0,0 +1,59 @@
|
||||
import { GET } from './route'
|
||||
import * as shopifySync from '@/lib/shopifySync'
|
||||
import type { ShopifyProductFull } from '@/types/sync'
|
||||
|
||||
jest.mock('@/lib/shopifySync')
|
||||
const mockFetch = shopifySync.fetchAllShopifyProducts as jest.MockedFunction<typeof shopifySync.fetchAllShopifyProducts>
|
||||
|
||||
const PRODUCTS: ShopifyProductFull[] = [
|
||||
{ shopifyId: '1', ref: 'REF-001', handle: 'ref-001', title: 'Brique rouge', description: '', price: '12.50', stock: 100, status: 'active' },
|
||||
{ shopifyId: '2', ref: 'REF-002', handle: 'ref-002', title: 'Parpaing', description: '', price: '5.00', stock: 0, status: 'draft' },
|
||||
{ shopifyId: '3', ref: 'REF-003', handle: 'ref-003', title: 'Ardoise', description: '', price: '80.00', stock: 20, status: 'active' },
|
||||
]
|
||||
|
||||
describe('GET /api/products/list', () => {
|
||||
beforeEach(() => {
|
||||
process.env.SHOPIFY_STORE_DOMAIN = 'test.myshopify.com'
|
||||
process.env.SHOPIFY_ADMIN_API_TOKEN = 'token'
|
||||
mockFetch.mockResolvedValue(PRODUCTS)
|
||||
})
|
||||
afterEach(() => jest.clearAllMocks())
|
||||
|
||||
it('retourne tous les produits sans filtre', async () => {
|
||||
const req = new Request('http://localhost/api/products/list')
|
||||
const res = await GET(req as never)
|
||||
const body = await res.json()
|
||||
expect(body.total).toBe(3)
|
||||
expect(body.products).toHaveLength(3)
|
||||
})
|
||||
|
||||
it('filtre par status=active', async () => {
|
||||
const req = new Request('http://localhost/api/products/list?status=active')
|
||||
const res = await GET(req as never)
|
||||
const body = await res.json()
|
||||
expect(body.total).toBe(2)
|
||||
body.products.forEach((p: { status: string }) => expect(p.status).toBe('active'))
|
||||
})
|
||||
|
||||
it('filtre par status=draft', async () => {
|
||||
const req = new Request('http://localhost/api/products/list?status=draft')
|
||||
const res = await GET(req as never)
|
||||
const body = await res.json()
|
||||
expect(body.total).toBe(1)
|
||||
expect(body.products[0].ref).toBe('REF-002')
|
||||
})
|
||||
|
||||
it('retourne shopifyUrl pour chaque produit', async () => {
|
||||
const req = new Request('http://localhost/api/products/list')
|
||||
const res = await GET(req as never)
|
||||
const body = await res.json()
|
||||
expect(body.products[0].shopifyUrl).toContain('test.myshopify.com/admin/products/1')
|
||||
})
|
||||
|
||||
it('retourne 500 si Shopify inaccessible', async () => {
|
||||
mockFetch.mockRejectedValue(new Error('network error'))
|
||||
const req = new Request('http://localhost/api/products/list')
|
||||
const res = await GET(req as never)
|
||||
expect(res.status).toBe(500)
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,33 @@
|
||||
import { NextRequest, NextResponse } from 'next/server'
|
||||
import { fetchAllShopifyProducts } from '@/lib/shopifySync'
|
||||
import type { CatalogProduct, ProductListResponse } from '@/types/products'
|
||||
|
||||
export async function GET(req: NextRequest): Promise<NextResponse<ProductListResponse | { error: string }>> {
|
||||
try {
|
||||
const { searchParams } = new URL(req.url)
|
||||
const statusFilter = searchParams.get('status') ?? 'all'
|
||||
|
||||
const domain = process.env.SHOPIFY_STORE_DOMAIN ?? ''
|
||||
const shopifyProducts = await fetchAllShopifyProducts()
|
||||
|
||||
let products: CatalogProduct[] = shopifyProducts.map((p) => ({
|
||||
shopifyId: p.shopifyId,
|
||||
ref: p.ref,
|
||||
handle: p.handle,
|
||||
title: p.title,
|
||||
price: p.price,
|
||||
stock: p.stock,
|
||||
status: p.status as CatalogProduct['status'],
|
||||
shopifyUrl: `https://${domain}/admin/products/${p.shopifyId}`,
|
||||
}))
|
||||
|
||||
if (statusFilter !== 'all') {
|
||||
products = products.filter((p) => p.status === statusFilter)
|
||||
}
|
||||
|
||||
return NextResponse.json({ products, total: products.length })
|
||||
} 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