feat: API route POST /api/images/upload (TDD)
This commit is contained in:
@@ -0,0 +1,75 @@
|
|||||||
|
import { POST } from '@/app/api/images/upload/route'
|
||||||
|
import { NextRequest } from 'next/server'
|
||||||
|
|
||||||
|
jest.mock('@/lib/shopify', () => ({
|
||||||
|
uploadProductImage: jest.fn(),
|
||||||
|
}))
|
||||||
|
|
||||||
|
import { uploadProductImage } from '@/lib/shopify'
|
||||||
|
const mockUpload = uploadProductImage as jest.Mock
|
||||||
|
|
||||||
|
describe('POST /api/images/upload', () => {
|
||||||
|
beforeEach(() => jest.clearAllMocks())
|
||||||
|
|
||||||
|
it('retourne 400 si shopifyProductId manquant', async () => {
|
||||||
|
const req = new NextRequest('http://localhost/api/images/upload', {
|
||||||
|
method: 'POST',
|
||||||
|
body: JSON.stringify({ imageBase64: 'abc', filename: 'test.jpg' }),
|
||||||
|
headers: { 'Content-Type': 'application/json' },
|
||||||
|
})
|
||||||
|
const res = await POST(req)
|
||||||
|
expect(res.status).toBe(400)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('retourne 400 si imageBase64 manquant', async () => {
|
||||||
|
const req = new NextRequest('http://localhost/api/images/upload', {
|
||||||
|
method: 'POST',
|
||||||
|
body: JSON.stringify({ shopifyProductId: '123', filename: 'test.jpg' }),
|
||||||
|
headers: { 'Content-Type': 'application/json' },
|
||||||
|
})
|
||||||
|
const res = await POST(req)
|
||||||
|
expect(res.status).toBe(400)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('retourne 400 si filename manquant', async () => {
|
||||||
|
const req = new NextRequest('http://localhost/api/images/upload', {
|
||||||
|
method: 'POST',
|
||||||
|
body: JSON.stringify({ shopifyProductId: '123', imageBase64: 'abc' }),
|
||||||
|
headers: { 'Content-Type': 'application/json' },
|
||||||
|
})
|
||||||
|
const res = await POST(req)
|
||||||
|
expect(res.status).toBe(400)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('retourne l\'URL après upload réussi', async () => {
|
||||||
|
mockUpload.mockResolvedValue({ url: 'https://cdn.shopify.com/image.jpg' })
|
||||||
|
const req = new NextRequest('http://localhost/api/images/upload', {
|
||||||
|
method: 'POST',
|
||||||
|
body: JSON.stringify({
|
||||||
|
shopifyProductId: '123456',
|
||||||
|
imageBase64: 'base64data==',
|
||||||
|
filename: 'REF-1042.jpg',
|
||||||
|
}),
|
||||||
|
headers: { 'Content-Type': 'application/json' },
|
||||||
|
})
|
||||||
|
const res = await POST(req)
|
||||||
|
expect(res.status).toBe(200)
|
||||||
|
expect(await res.json()).toEqual({ url: 'https://cdn.shopify.com/image.jpg' })
|
||||||
|
expect(mockUpload).toHaveBeenCalledWith('123456', 'base64data==', 'REF-1042.jpg')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('retourne 500 en cas d\'erreur Shopify', async () => {
|
||||||
|
mockUpload.mockRejectedValue(new Error('Shopify upload error: 422'))
|
||||||
|
const req = new NextRequest('http://localhost/api/images/upload', {
|
||||||
|
method: 'POST',
|
||||||
|
body: JSON.stringify({
|
||||||
|
shopifyProductId: '123',
|
||||||
|
imageBase64: 'abc',
|
||||||
|
filename: 'test.jpg',
|
||||||
|
}),
|
||||||
|
headers: { 'Content-Type': 'application/json' },
|
||||||
|
})
|
||||||
|
const res = await POST(req)
|
||||||
|
expect(res.status).toBe(500)
|
||||||
|
})
|
||||||
|
})
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
import { NextRequest, NextResponse } from 'next/server'
|
||||||
|
import { uploadProductImage } from '@/lib/shopify'
|
||||||
|
|
||||||
|
export async function POST(req: NextRequest) {
|
||||||
|
let body: Record<string, unknown>
|
||||||
|
try {
|
||||||
|
body = await req.json()
|
||||||
|
} catch {
|
||||||
|
return NextResponse.json({ error: 'Corps JSON invalide' }, { status: 400 })
|
||||||
|
}
|
||||||
|
|
||||||
|
const { shopifyProductId, imageBase64, filename } = body
|
||||||
|
|
||||||
|
if (!shopifyProductId || typeof shopifyProductId !== 'string') {
|
||||||
|
return NextResponse.json({ error: 'shopifyProductId requis' }, { status: 400 })
|
||||||
|
}
|
||||||
|
if (!imageBase64 || typeof imageBase64 !== 'string') {
|
||||||
|
return NextResponse.json({ error: 'imageBase64 requis' }, { status: 400 })
|
||||||
|
}
|
||||||
|
if (!filename || typeof filename !== 'string') {
|
||||||
|
return NextResponse.json({ error: 'filename requis' }, { status: 400 })
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const result = await uploadProductImage(shopifyProductId, imageBase64, filename)
|
||||||
|
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