feat: add baby object match edutainment flow
Some checks failed
CI / verify (push) Has been cancelled

This commit is contained in:
2026-05-12 16:08:59 +08:00
parent cf074837a4
commit d41f260a2a
58 changed files with 5628 additions and 466 deletions

View File

@@ -0,0 +1,105 @@
/* @vitest-environment jsdom */
import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { expect, test, vi } from 'vitest';
import type { BabyObjectMatchDraft } from '../../../packages/shared/src/contracts/edutainmentBabyObject';
import {
BABY_OBJECT_MATCH_EDUTAINMENT_TAG,
BABY_OBJECT_MATCH_TEMPLATE_ID,
BABY_OBJECT_MATCH_TEMPLATE_NAME,
} from '../../../packages/shared/src/contracts/edutainmentBabyObject';
import { BabyObjectMatchResultView } from './BabyObjectMatchResultView';
vi.mock('../ResolvedAssetImage', () => ({
ResolvedAssetImage: ({
src,
alt,
className,
}: {
src?: string | null;
alt?: string;
className?: string;
}) => (src ? <img src={src} alt={alt} className={className} /> : null),
}));
function createDraft(overrides: Partial<BabyObjectMatchDraft> = {}) {
const draft: BabyObjectMatchDraft = {
draftId: 'baby-object-draft-1',
profileId: 'baby-object-profile-1',
templateId: BABY_OBJECT_MATCH_TEMPLATE_ID,
templateName: BABY_OBJECT_MATCH_TEMPLATE_NAME,
workTitle: '宝贝识物',
workDescription: '苹果和香蕉识物分类',
itemNames: ['苹果', '香蕉'],
itemAssets: [
{
itemId: 'baby-object-item-1',
itemName: '苹果',
imageSrc: 'data:image/svg+xml;utf8,a',
assetObjectId: null,
generationProvider: 'placeholder',
prompt: '苹果',
},
{
itemId: 'baby-object-item-2',
itemName: '香蕉',
imageSrc: 'data:image/svg+xml;utf8,b',
assetObjectId: null,
generationProvider: 'placeholder',
prompt: '香蕉',
},
],
themeTags: ['宝贝识物'],
publicationStatus: 'draft',
createdAt: '2026-05-11T00:00:00.000Z',
updatedAt: '2026-05-11T00:00:00.000Z',
publishedAt: null,
...overrides,
};
return draft;
}
test('baby object result publishes with exact edutainment tag', async () => {
const user = userEvent.setup();
const onPublish = vi.fn();
render(
<BabyObjectMatchResultView
draft={createDraft()}
onBack={() => {}}
onPublish={onPublish}
/>,
);
await user.click(screen.getByRole('button', { name: '发布' }));
expect(onPublish).toHaveBeenCalledTimes(1);
expect(onPublish.mock.calls[0]?.[0].themeTags[0]).toBe(
BABY_OBJECT_MATCH_EDUTAINMENT_TAG,
);
expect(onPublish.mock.calls[0]?.[0].themeTags).toContain('宝贝识物');
});
test('baby object result exposes save and test run actions', async () => {
const user = userEvent.setup();
const onSaveDraft = vi.fn();
const onStartTestRun = vi.fn();
render(
<BabyObjectMatchResultView
draft={createDraft()}
onBack={() => {}}
onSaveDraft={onSaveDraft}
onStartTestRun={onStartTestRun}
/>,
);
await user.click(screen.getByRole('button', { name: '保存草稿' }));
await user.click(screen.getByRole('button', { name: '试玩' }));
expect(onSaveDraft).toHaveBeenCalledTimes(1);
expect(onStartTestRun).toHaveBeenCalledTimes(1);
});