test: add server tests for image resize library
This commit is contained in:
@@ -0,0 +1,99 @@
|
|||||||
|
import crypto from 'node:crypto'
|
||||||
|
import fs from 'node:fs'
|
||||||
|
import path from 'node:path'
|
||||||
|
import { afterAll, beforeAll, describe, expect, it } from 'vitest'
|
||||||
|
import { findOriginalFile, getOrCreateResized } from '../image-resize.js'
|
||||||
|
|
||||||
|
const TEST_DIR = path.join(process.cwd(), 'uploads', '.test-tmp')
|
||||||
|
const UPLOADS_DIR = path.join(process.cwd(), 'uploads')
|
||||||
|
|
||||||
|
beforeAll(async () => {
|
||||||
|
await fs.promises.mkdir(TEST_DIR, { recursive: true })
|
||||||
|
// Create a small test PNG file
|
||||||
|
const sharp = (await import('sharp')).default
|
||||||
|
const testPng = path.join(TEST_DIR, 'test-original.png')
|
||||||
|
await sharp({
|
||||||
|
create: { width: 100, height: 100, channels: 3, background: { r: 255, g: 0, b: 0 } },
|
||||||
|
})
|
||||||
|
.png()
|
||||||
|
.toFile(testPng)
|
||||||
|
})
|
||||||
|
|
||||||
|
afterAll(async () => {
|
||||||
|
await fs.promises.rm(TEST_DIR, { recursive: true, force: true })
|
||||||
|
// Clean up any cache files created during tests
|
||||||
|
const cacheDir = path.join(UPLOADS_DIR, '.cache')
|
||||||
|
try {
|
||||||
|
await fs.promises.rm(cacheDir, { recursive: true, force: true })
|
||||||
|
} catch {
|
||||||
|
// ignore
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('image-resize', () => {
|
||||||
|
it('findOriginalFile locates file by UUID', async () => {
|
||||||
|
const files = await fs.promises.readdir(TEST_DIR)
|
||||||
|
const pngFile = files.find((f) => f.endsWith('.png'))
|
||||||
|
const uuid = pngFile.replace('.png', '')
|
||||||
|
|
||||||
|
// Copy file to actual uploads directory
|
||||||
|
const destPath = path.join(UPLOADS_DIR, pngFile)
|
||||||
|
await fs.promises.copyFile(path.join(TEST_DIR, pngFile), destPath)
|
||||||
|
|
||||||
|
const found = await findOriginalFile(uuid)
|
||||||
|
expect(found).not.toBeNull()
|
||||||
|
expect(found).toBe(destPath)
|
||||||
|
|
||||||
|
// Cleanup
|
||||||
|
await fs.promises.unlink(destPath)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('getOrCreateResized generates AVIF file', async () => {
|
||||||
|
const sharp = (await import('sharp')).default
|
||||||
|
const uuid = crypto.randomUUID()
|
||||||
|
const testPath = path.join(UPLOADS_DIR, `${uuid}.png`)
|
||||||
|
await sharp({
|
||||||
|
create: { width: 200, height: 200, channels: 3, background: { r: 0, g: 255, b: 0 } },
|
||||||
|
})
|
||||||
|
.png()
|
||||||
|
.toFile(testPath)
|
||||||
|
|
||||||
|
const result = await getOrCreateResized(uuid, 100, 'avif')
|
||||||
|
expect(result).not.toBeNull()
|
||||||
|
expect(result.isNew).toBe(true)
|
||||||
|
expect(result.path).toContain('.cache')
|
||||||
|
expect(result.path).toContain('_w100.avif')
|
||||||
|
|
||||||
|
const exists = await fs.promises.access(result.path).then(() => true).catch(() => false)
|
||||||
|
expect(exists).toBe(true)
|
||||||
|
|
||||||
|
// Verify it's actually AVIF (sharp reports AVIF as 'heif' in metadata)
|
||||||
|
expect(result.path).toMatch(/\.avif$/)
|
||||||
|
|
||||||
|
// Cleanup
|
||||||
|
await fs.promises.unlink(testPath)
|
||||||
|
await fs.promises.unlink(result.path)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('getOrCreateResized returns cached file on second call', async () => {
|
||||||
|
const sharp = (await import('sharp')).default
|
||||||
|
const uuid = crypto.randomUUID()
|
||||||
|
const testPath = path.join(UPLOADS_DIR, `${uuid}.png`)
|
||||||
|
await sharp({
|
||||||
|
create: { width: 200, height: 200, channels: 3, background: { r: 0, g: 0, b: 255 } },
|
||||||
|
})
|
||||||
|
.png()
|
||||||
|
.toFile(testPath)
|
||||||
|
|
||||||
|
const first = await getOrCreateResized(uuid, 100, 'webp')
|
||||||
|
expect(first.isNew).toBe(true)
|
||||||
|
|
||||||
|
const second = await getOrCreateResized(uuid, 100, 'webp')
|
||||||
|
expect(second.isNew).toBe(false)
|
||||||
|
expect(second.path).toBe(first.path)
|
||||||
|
|
||||||
|
// Cleanup
|
||||||
|
await fs.promises.unlink(testPath)
|
||||||
|
await fs.promises.unlink(first.path)
|
||||||
|
})
|
||||||
|
})
|
||||||
Reference in New Issue
Block a user