/** @jest-environment node */ import { readPerformanceSurveyWebpDimensions, validatePerformanceSurveyProcessedImages, } from '@/lib/performance-survey-processed-images' function record(overrides: Record = {}) { return { uploadId: 'upload-1', mimeType: 'image/webp', width: 1600, height: 1500, kind: 'slice', sourceName: '详情长图.png', sourceIndex: 0, sliceIndex: 0, sliceCount: 1, ...overrides, } } function vp8xHeader(width: number, height: number) { const buffer = Buffer.alloc(30) buffer.write('RIFF', 0, 'ascii') buffer.write('WEBP', 8, 'ascii') buffer.write('VP8X', 12, 'ascii') buffer.writeUIntLE(width - 1, 24, 3) buffer.writeUIntLE(height - 1, 27, 3) return buffer } describe('performance survey processed image contract', () => { test('accepts one optional preview plus ordered slices from one long source', () => { const groups = validatePerformanceSurveyProcessedImages([ record({ uploadId: 'slice-2', sliceIndex: 1, sliceCount: 2, height: 800 }), record({ uploadId: 'preview', kind: 'preview', width: 720, height: 560, sliceCount: 2 }), record({ uploadId: 'slice-1', sliceIndex: 0, sliceCount: 2 }), ]) expect(groups).toHaveLength(1) expect(groups[0].preview?.uploadId).toBe('preview') expect(groups[0].slices.map((item) => item.uploadId)).toEqual(['slice-1', 'slice-2']) }) test('accepts pre-cut files as independent source groups without previews', () => { const groups = validatePerformanceSurveyProcessedImages([ record({ uploadId: 'part-1', sourceName: '1.webp' }), record({ uploadId: 'part-2', sourceName: '2.webp', sourceIndex: 1 }), ]) expect(groups).toHaveLength(2) expect(groups.every((group) => group.preview === null && group.sliceCount === 1)).toBe(true) }) test('rejects missing or duplicated slice positions', () => { expect(() => validatePerformanceSurveyProcessedImages([ record({ uploadId: 'slice-1', sliceIndex: 0, sliceCount: 2 }), record({ uploadId: 'slice-duplicate', sliceIndex: 0, sliceCount: 2 }), ])).toThrow('切片序号不连续') }) test('limits final ordered slices to 60 per work item', () => { const sixtySlices = Array.from({ length: 60 }, (_, index) => record({ uploadId: `long-${index}`, sliceIndex: index, sliceCount: 60, })) expect(validatePerformanceSurveyProcessedImages(sixtySlices)[0].slices).toHaveLength(60) expect(() => validatePerformanceSurveyProcessedImages([ ...sixtySlices, record({ uploadId: 'part-61', sourceName: '2.webp', sourceIndex: 1 }), ])).toThrow('最多上传 60 张有序切片') }) test('requires safe WebP dimensions declared by the browser', () => { expect(() => validatePerformanceSurveyProcessedImages([ record({ mimeType: 'image/png' }), ])).toThrow('只接受 WebP') expect(() => validatePerformanceSurveyProcessedImages([ record({ height: 1501 }), ])).toThrow('图片高度无效') }) test('reads VP8X dimensions without decoding image pixels', () => { expect(readPerformanceSurveyWebpDimensions(vp8xHeader(1600, 900))).toEqual({ width: 1600, height: 900 }) expect(() => readPerformanceSurveyWebpDimensions(Buffer.from('not-webp'))).toThrow('不是有效的 WebP') }) })