Files
thu-maic--openmaic/tests/lib/agent/tools/build-image-resources.test.ts
wehub-resource-sync c48612c494
CI / E2E Tests (push) Has been cancelled
CI / Lint, Typecheck & Unit Tests (push) Has been cancelled
Docs Build / Build docs site (push) Has been cancelled
Publish @openmaic packages / Build, validate & publish (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 13:03:23 +08:00

117 lines
3.9 KiB
TypeScript

/**
* `buildImageResources` — feeds existing slide images to the slide generator as
* RESOURCES (the same `assignedImages` + `imageMapping` channel as
* course-generation) instead of trying to preserve them across the round-trip
* (which can't work — the generator re-mints every element id). Each real image
* src becomes `img_N` in `imageMapping`, is described in `assignedImages`, and
* the returned baseline carries the small id-ref instead of the payload.
*/
import { describe, expect, it } from 'vitest';
import { buildImageResources } from '@/lib/agent/tools/regenerate-scene';
import type { GeneratedSlideContent } from '@/lib/types/generation';
import type { PPTElement } from '@openmaic/dsl';
function img(id: string, src: string): PPTElement {
return {
id,
type: 'image',
left: 0,
top: 0,
width: 120,
height: 80,
src,
fixedRatio: true,
rotate: 0,
} as unknown as PPTElement;
}
function txt(id: string, content: string): PPTElement {
return {
id,
type: 'text',
left: 0,
top: 0,
width: 100,
height: 40,
content,
defaultFontName: '',
defaultColor: '#000',
rotate: 0,
} as unknown as PPTElement;
}
describe('buildImageResources', () => {
it('lifts a data: image src into resources and rewrites the baseline to an id-ref', () => {
const real = 'data:image/png;base64,AAAA';
const baseline: GeneratedSlideContent = { elements: [img('image_x', real)] };
const out = buildImageResources(baseline);
// Baseline element src rewritten to the small img_N reference (no base64).
expect((out.baseline.elements[0] as { src: string }).src).toBe('img_1');
// Resource channel carries the real src + dimensions + a description.
expect(out.imageMapping).toEqual({ img_1: real });
expect(out.assignedImages).toHaveLength(1);
expect(out.assignedImages[0]).toMatchObject({
id: 'img_1',
src: real,
pageNumber: 0,
width: 120,
height: 80,
description: 'Existing slide image',
});
});
it('lifts an http(s) image src too', () => {
const real = 'https://cdn.example.com/a.png';
const baseline: GeneratedSlideContent = { elements: [img('image_y', real)] };
const out = buildImageResources(baseline);
expect((out.baseline.elements[0] as { src: string }).src).toBe('img_1');
expect(out.imageMapping).toEqual({ img_1: real });
});
it('assigns distinct ids to multiple images and leaves non-image elements untouched', () => {
const baseline: GeneratedSlideContent = {
elements: [
img('image_1', 'data:image/png;base64,AAAA'),
txt('text_1', '<p>hi</p>'),
img('image_2', 'https://cdn.example.com/b.png'),
],
};
const out = buildImageResources(baseline);
expect((out.baseline.elements[0] as { src: string }).src).toBe('img_1');
// Non-image element passes through verbatim.
expect(out.baseline.elements[1]).toBe(baseline.elements[1]);
expect((out.baseline.elements[2] as { src: string }).src).toBe('img_2');
expect(out.imageMapping).toEqual({
img_1: 'data:image/png;base64,AAAA',
img_2: 'https://cdn.example.com/b.png',
});
expect(out.assignedImages.map((i) => i.id)).toEqual(['img_1', 'img_2']);
});
it('leaves an already-id-ref image src untouched and produces no resource for it', () => {
const baseline: GeneratedSlideContent = { elements: [img('image_z', 'img_3')] };
const out = buildImageResources(baseline);
expect((out.baseline.elements[0] as { src: string }).src).toBe('img_3');
expect(out.assignedImages).toHaveLength(0);
expect(out.imageMapping).toEqual({});
});
it('does not mutate the input baseline', () => {
const real = 'data:image/png;base64,AAAA';
const baseline: GeneratedSlideContent = { elements: [img('image_x', real)] };
buildImageResources(baseline);
expect((baseline.elements[0] as { src: string }).src).toBe(real);
});
});