refactor: extract validateGalleryImages helper
This commit is contained in:
@@ -0,0 +1,32 @@
|
|||||||
|
import { describe, it, expect, vi } from 'vitest'
|
||||||
|
import { validateGalleryImages } from '../validate-gallery-images.js'
|
||||||
|
|
||||||
|
describe('validateGalleryImages', () => {
|
||||||
|
it('returns null when urls is empty', async () => {
|
||||||
|
const prisma = { galleryImage: { findMany: vi.fn() } }
|
||||||
|
const result = await validateGalleryImages(prisma, [])
|
||||||
|
expect(result).toBeNull()
|
||||||
|
})
|
||||||
|
|
||||||
|
it('throws 400 when image not found', async () => {
|
||||||
|
const prisma = { galleryImage: { findMany: vi.fn().mockResolvedValue([]) } }
|
||||||
|
await expect(validateGalleryImages(prisma, ['/uploads/missing.jpg'])).rejects.toMatchObject({ statusCode: 400 })
|
||||||
|
})
|
||||||
|
|
||||||
|
it('throws 400 when image not yet resized', async () => {
|
||||||
|
const prisma = {
|
||||||
|
galleryImage: { findMany: vi.fn().mockResolvedValue([{ url: '/uploads/img.jpg', isResized: false }]) },
|
||||||
|
}
|
||||||
|
await expect(validateGalleryImages(prisma, ['/uploads/img.jpg'])).rejects.toMatchObject({ statusCode: 400 })
|
||||||
|
})
|
||||||
|
|
||||||
|
it('returns existing images when all valid and resized', async () => {
|
||||||
|
const images = [
|
||||||
|
{ url: '/uploads/img1.jpg', isResized: true },
|
||||||
|
{ url: '/uploads/img2.jpg', isResized: true },
|
||||||
|
]
|
||||||
|
const prisma = { galleryImage: { findMany: vi.fn().mockResolvedValue(images) } }
|
||||||
|
const result = await validateGalleryImages(prisma, ['/uploads/img1.jpg', '/uploads/img2.jpg'])
|
||||||
|
expect(result).toEqual(images)
|
||||||
|
})
|
||||||
|
})
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
export async function validateGalleryImages(prisma, urls) {
|
||||||
|
if (!urls || urls.length === 0) return null
|
||||||
|
|
||||||
|
const existing = await prisma.galleryImage.findMany({
|
||||||
|
where: { url: { in: urls } },
|
||||||
|
select: { url: true, isResized: true },
|
||||||
|
})
|
||||||
|
|
||||||
|
const galleryMap = new Map(existing.map((g) => [g.url, g]))
|
||||||
|
const notFound = urls.filter((u) => !galleryMap.has(u))
|
||||||
|
if (notFound.length > 0) {
|
||||||
|
throw Object.assign(new Error(`Gallery images not found: ${notFound.join(', ')}`), { statusCode: 400 })
|
||||||
|
}
|
||||||
|
|
||||||
|
const notResized = urls.filter((u) => galleryMap.get(u) && !galleryMap.get(u).isResized)
|
||||||
|
if (notResized.length > 0) {
|
||||||
|
throw Object.assign(new Error('Some gallery images have not been processed yet. Please try again later.'), {
|
||||||
|
statusCode: 400,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return existing
|
||||||
|
}
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
import { prisma } from '../../lib/prisma.js'
|
import { prisma } from '../../lib/prisma.js'
|
||||||
|
import { validateGalleryImages } from '../../lib/validate-gallery-images.js'
|
||||||
|
|
||||||
const CREATE_PRODUCT_SCHEMA = {
|
const CREATE_PRODUCT_SCHEMA = {
|
||||||
body: {
|
body: {
|
||||||
@@ -87,20 +88,10 @@ export async function registerAdminProductRoutes(fastify) {
|
|||||||
if (Array.isArray(body.imageUrls) && body.imageUrls.length > 0) {
|
if (Array.isArray(body.imageUrls) && body.imageUrls.length > 0) {
|
||||||
const urls = body.imageUrls.map((u) => String(u || '').trim()).filter(Boolean)
|
const urls = body.imageUrls.map((u) => String(u || '').trim()).filter(Boolean)
|
||||||
if (urls.length > 0) {
|
if (urls.length > 0) {
|
||||||
const galleryImages = await prisma.galleryImage.findMany({
|
try {
|
||||||
where: { url: { in: urls } },
|
await validateGalleryImages(prisma, urls)
|
||||||
select: { url: true, isResized: true },
|
} catch (err) {
|
||||||
})
|
return reply.code(err.statusCode || 400).send({ error: err.message })
|
||||||
const galleryMap = new Map(galleryImages.map((g) => [g.url, g]))
|
|
||||||
const notFound = urls.filter((u) => !galleryMap.has(u))
|
|
||||||
const notResized = urls.filter((u) => galleryMap.get(u) && !galleryMap.get(u).isResized)
|
|
||||||
if (notFound.length > 0) {
|
|
||||||
return reply.code(400).send({ error: 'Некоторые изображения не найдены в галерее' })
|
|
||||||
}
|
|
||||||
if (notResized.length > 0) {
|
|
||||||
return reply
|
|
||||||
.code(400)
|
|
||||||
.send({ error: 'Изображения должны быть обработаны (resize) перед прикреплением к товару' })
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -214,20 +205,10 @@ export async function registerAdminProductRoutes(fastify) {
|
|||||||
if (body.imageUrls !== undefined && Array.isArray(body.imageUrls)) {
|
if (body.imageUrls !== undefined && Array.isArray(body.imageUrls)) {
|
||||||
const urls = body.imageUrls.map((u) => String(u || '').trim()).filter(Boolean)
|
const urls = body.imageUrls.map((u) => String(u || '').trim()).filter(Boolean)
|
||||||
if (urls.length > 0) {
|
if (urls.length > 0) {
|
||||||
const galleryImages = await prisma.galleryImage.findMany({
|
try {
|
||||||
where: { url: { in: urls } },
|
await validateGalleryImages(prisma, urls)
|
||||||
select: { url: true, isResized: true },
|
} catch (err) {
|
||||||
})
|
return reply.code(err.statusCode || 400).send({ error: err.message })
|
||||||
const galleryMap = new Map(galleryImages.map((g) => [g.url, g]))
|
|
||||||
const notFound = urls.filter((u) => !galleryMap.has(u))
|
|
||||||
const notResized = urls.filter((u) => galleryMap.get(u) && !galleryMap.get(u).isResized)
|
|
||||||
if (notFound.length > 0) {
|
|
||||||
return reply.code(400).send({ error: 'Некоторые изображения не найдены в галерее' })
|
|
||||||
}
|
|
||||||
if (notResized.length > 0) {
|
|
||||||
return reply
|
|
||||||
.code(400)
|
|
||||||
.send({ error: 'Изображения должны быть обработаны (resize) перед прикреплением к товару' })
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user