From 02172f799552a94c9708ff02205d083021b1d1db Mon Sep 17 00:00:00 2001 From: Kirill Date: Sun, 17 May 2026 17:56:21 +0500 Subject: [PATCH] test(server): add gallery resize test, adapt upload tests --- .../src/lib/__tests__/upload-images.test.js | 78 +------------------ .../api/__tests__/admin-gallery.test.js | 56 +++++++++++++ 2 files changed, 58 insertions(+), 76 deletions(-) create mode 100644 server/src/routes/api/__tests__/admin-gallery.test.js diff --git a/server/src/lib/__tests__/upload-images.test.js b/server/src/lib/__tests__/upload-images.test.js index ee02537..bfea05c 100644 --- a/server/src/lib/__tests__/upload-images.test.js +++ b/server/src/lib/__tests__/upload-images.test.js @@ -1,4 +1,4 @@ -import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest' +import { describe, it, expect, afterEach } from 'vitest' import fs from 'node:fs' import path from 'node:path' import { persistMultipartImages } from '../upload-images.js' @@ -6,7 +6,7 @@ import { persistMultipartImages } from '../upload-images.js' const UPLOADS_DIR = path.join(process.cwd(), 'uploads') const TEST_PREFIX = 'upload-test-' -describe('persistMultipartImages with eager mode', () => { +describe('persistMultipartImages with eager=false', () => { afterEach(async () => { const files = await fs.promises.readdir(UPLOADS_DIR).catch(() => []) for (const file of files) { @@ -16,50 +16,6 @@ describe('persistMultipartImages with eager mode', () => { } }) - it('returns WebP URLs when eager=true', async () => { - const sharp = (await import('sharp')).default - const testImagePath = path.join(UPLOADS_DIR, `${TEST_PREFIX}original.png`) - - const filesBefore = await fs.promises.readdir(UPLOADS_DIR) - - await sharp({ create: { width: 100, height: 100, channels: 3, background: { r: 255, g: 0, b: 0 } } }) - .png() - .toFile(testImagePath) - - const mockRequest = { - isMultipart: () => true, - parts: async function* () { - const buffer = await fs.promises.readFile(testImagePath) - yield { - file: true, - filename: 'test.png', - toBuffer: async () => buffer, - } - }, - } - - const urls = await persistMultipartImages(mockRequest, { - maxFiles: 1, - maxFileBytes: 20 * 1024 * 1024, - subdir: '', - eager: true, - }) - - expect(urls).toHaveLength(1) - expect(urls[0]).toMatch(/\/uploads\/[a-f0-9-]+\.webp$/) - - // Verify the intermediate PNG file written by persistMultipartImages was deleted - const filesAfter = await fs.promises.readdir(UPLOADS_DIR) - const newPngFiles = filesAfter.filter( - (f) => - !filesBefore.includes(f) && - f.endsWith('.png') && - f !== path.basename(testImagePath) && - !f.startsWith('test-eager-uuid-'), - ) - expect(newPngFiles).toHaveLength(0) - }) - it('returns original format URLs when eager=false', async () => { const sharp = (await import('sharp')).default const testImagePath = path.join(UPLOADS_DIR, `${TEST_PREFIX}original2.png`) @@ -90,34 +46,4 @@ describe('persistMultipartImages with eager mode', () => { expect(urls[0]).toMatch(/\/uploads\/[a-f0-9-]+\.png$/) }) - it('cleans up original file on eager processing error', async () => { - const invalidBuffer = Buffer.from('not an image') - - const filesBefore = await fs.promises.readdir(UPLOADS_DIR) - - const mockRequest = { - isMultipart: () => true, - parts: async function* () { - yield { - file: true, - filename: 'test.png', - toBuffer: async () => invalidBuffer, - } - }, - } - - await expect( - persistMultipartImages(mockRequest, { - maxFiles: 1, - maxFileBytes: 20 * 1024 * 1024, - subdir: '', - eager: true, - }), - ).rejects.toThrow() - - // The intermediate file written by persistMultipartImages should be cleaned up - const filesAfter = await fs.promises.readdir(UPLOADS_DIR) - const newFiles = filesAfter.filter((f) => !filesBefore.includes(f) && f !== '.cache') - expect(newFiles).toHaveLength(0) - }) }) diff --git a/server/src/routes/api/__tests__/admin-gallery.test.js b/server/src/routes/api/__tests__/admin-gallery.test.js new file mode 100644 index 0000000..27c0acd --- /dev/null +++ b/server/src/routes/api/__tests__/admin-gallery.test.js @@ -0,0 +1,56 @@ +import { describe, it, expect, beforeAll, afterAll } from 'vitest' +import fs from 'node:fs' +import path from 'node:path' + +const UPLOADS_DIR = path.join(process.cwd(), 'uploads') + +import { generateAllSizes, convertOriginalToWebp } from '../../../lib/image-resize.js' + +describe('Admin gallery resize integration', () => { + const testUuid = 'gallery-test-resize-uuid' + const testOriginalPath = path.join(UPLOADS_DIR, `${testUuid}.png`) + + beforeAll(async () => { + const sharp = (await import('sharp')).default + await sharp({ create: { width: 200, height: 200, channels: 3, background: { r: 255, g: 0, b: 0 } } }) + .png() + .toFile(testOriginalPath) + }) + + afterAll(async () => { + await fs.promises.unlink(testOriginalPath).catch(() => {}) + const webpPath = path.join(UPLOADS_DIR, `${testUuid}.webp`) + await fs.promises.unlink(webpPath).catch(() => {}) + const cacheDir = path.join(UPLOADS_DIR, '.cache') + for (const width of [320, 640, 1024, 1600]) { + for (const format of ['avif', 'webp']) { + await fs.promises.unlink(path.join(cacheDir, `${testUuid}_w${width}.${format}`)).catch(() => {}) + } + } + }) + + it('generateAllSizes + convertOriginalToWebp works on raw upload', async () => { + await generateAllSizes(testUuid, '', testOriginalPath) + const newUrl = await convertOriginalToWebp(testUuid, '') + + expect(newUrl).toBe(`/uploads/${testUuid}.webp`) + + // Verify original PNG is deleted + const pngExists = await fs.promises.access(testOriginalPath).then(() => true).catch(() => false) + expect(pngExists).toBe(false) + + // Verify cached files exist + const cacheDir = path.join(UPLOADS_DIR, '.cache') + for (const width of [320, 640, 1024, 1600]) { + for (const format of ['avif', 'webp']) { + const cachePath = path.join(cacheDir, `${testUuid}_w${width}.${format}`) + const exists = await fs.promises.access(cachePath).then(() => true).catch(() => false) + expect(exists).toBe(true) + } + } + + // Verify webp original exists + const webpExists = await fs.promises.access(path.join(UPLOADS_DIR, `${testUuid}.webp`)).then(() => true).catch(() => false) + expect(webpExists).toBe(true) + }) +})