chore: sync marketing pages, CMS extensions, tests and project docs
同步工作区剩余变更,主要包括: - 营销页面组件与布局持续优化(about/news/services/solutions/team 等) - 详情页四层叙事组件、布局组件、UI 组件调整 - CMS 数据模型、API 路由、权限、工作流、站内通知、媒体管理扩展 - 新增/补充单元测试与 E2E 测试(cms-workflow.spec.ts 等) - ESLint 9 迁移、jest/tsconfig 配置更新、依赖调整 - 新增 ADR、CMS 评估文档、Release Review / Acceptance 报告 - 移除水墨装饰组件与大体积未使用字体文件
This commit is contained in:
@@ -0,0 +1,106 @@
|
||||
import { describe, it, expect, beforeAll } from '@jest/globals';
|
||||
import sharp from 'sharp';
|
||||
import {
|
||||
isImage,
|
||||
getImageMetadata,
|
||||
generateDerivatives,
|
||||
THUMBNAIL_SIZE,
|
||||
} from './image-processor';
|
||||
|
||||
describe('image-processor', () => {
|
||||
let testPng: Buffer;
|
||||
let testJpeg: Buffer;
|
||||
const txtBuffer = Buffer.from('not an image');
|
||||
|
||||
beforeAll(async () => {
|
||||
testPng = await sharp({
|
||||
create: {
|
||||
width: 800,
|
||||
height: 600,
|
||||
channels: 3,
|
||||
background: { r: 255, g: 0, b: 0 },
|
||||
},
|
||||
})
|
||||
.png()
|
||||
.toBuffer();
|
||||
|
||||
testJpeg = await sharp({
|
||||
create: {
|
||||
width: 400,
|
||||
height: 300,
|
||||
channels: 3,
|
||||
background: { r: 0, g: 0, b: 255 },
|
||||
},
|
||||
})
|
||||
.jpeg()
|
||||
.toBuffer();
|
||||
});
|
||||
|
||||
describe('isImage', () => {
|
||||
it('returns true for common image mime types', () => {
|
||||
expect(isImage('image/png')).toBe(true);
|
||||
expect(isImage('image/jpeg')).toBe(true);
|
||||
expect(isImage('image/webp')).toBe(true);
|
||||
expect(isImage('image/avif')).toBe(true);
|
||||
expect(isImage('image/gif')).toBe(true);
|
||||
});
|
||||
|
||||
it('returns false for non-image mime types', () => {
|
||||
expect(isImage('application/pdf')).toBe(false);
|
||||
expect(isImage('text/plain')).toBe(false);
|
||||
expect(isImage('video/mp4')).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('getImageMetadata', () => {
|
||||
it('returns width and height for a valid image buffer', async () => {
|
||||
const meta = await getImageMetadata(testPng);
|
||||
expect(meta).toEqual({ width: 800, height: 600 });
|
||||
});
|
||||
|
||||
it('returns null for non-image buffer', async () => {
|
||||
const meta = await getImageMetadata(txtBuffer);
|
||||
expect(meta).toBeNull();
|
||||
});
|
||||
});
|
||||
|
||||
describe('generateDerivatives', () => {
|
||||
it('generates thumbnail, webp and avif for image/png', async () => {
|
||||
const derivatives = await generateDerivatives(testPng, 'image/png');
|
||||
|
||||
expect(derivatives.thumbnail).toBeDefined();
|
||||
expect(derivatives.webp).toBeDefined();
|
||||
expect(derivatives.avif).toBeDefined();
|
||||
|
||||
expect(derivatives.thumbnail!.width).toBeLessThanOrEqual(THUMBNAIL_SIZE);
|
||||
expect(derivatives.thumbnail!.height).toBeLessThanOrEqual(THUMBNAIL_SIZE);
|
||||
expect(derivatives.thumbnail!.path).toMatch(/-thumbnail\./);
|
||||
expect(derivatives.thumbnail!.url).toMatch(/-thumbnail\./);
|
||||
|
||||
expect(derivatives.webp!.path).toMatch(/\.webp$/);
|
||||
expect(derivatives.webp!.url).toMatch(/\.webp$/);
|
||||
|
||||
expect(derivatives.avif!.path).toMatch(/\.avif$/);
|
||||
expect(derivatives.avif!.url).toMatch(/\.avif$/);
|
||||
});
|
||||
|
||||
it('keeps original aspect ratio for thumbnail', async () => {
|
||||
const derivatives = await generateDerivatives(testPng, 'image/png');
|
||||
const thumb = derivatives.thumbnail!;
|
||||
expect(thumb.width / thumb.height).toBeCloseTo(800 / 600, 1);
|
||||
});
|
||||
|
||||
it('returns empty derivatives for non-image files', async () => {
|
||||
const derivatives = await generateDerivatives(txtBuffer, 'text/plain');
|
||||
expect(Object.keys(derivatives)).toHaveLength(0);
|
||||
});
|
||||
|
||||
it('generates webp/avif with same dimensions as original', async () => {
|
||||
const derivatives = await generateDerivatives(testJpeg, 'image/jpeg');
|
||||
expect(derivatives.webp!.width).toBe(400);
|
||||
expect(derivatives.webp!.height).toBe(300);
|
||||
expect(derivatives.avif!.width).toBe(400);
|
||||
expect(derivatives.avif!.height).toBe(300);
|
||||
});
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user