open-design/apps/web/tests/components/RecentProjectsStrip.test.tsx
Eli-tangerine 10e11531a1
Improve deck home previews and plugin gallery performance (#2698)
Co-authored-by: qiongyu1999 <2694684348@qq.com>
2026-05-22 17:47:28 +08:00

134 lines
4.2 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// @vitest-environment jsdom
import { cleanup, render, screen, waitFor } from '@testing-library/react';
import { afterEach, describe, expect, it, vi } from 'vitest';
import { RecentProjectsStrip } from '../../src/components/RecentProjectsStrip';
import type { Project } from '../../src/types';
vi.mock('../../src/providers/registry', () => ({
fetchProjectFiles: vi.fn(async (projectId: string) => {
if (projectId === 'project-ds') {
return [{ name: 'logo.svg', path: 'assets/logo.svg', kind: 'image', mtime: 3 }];
}
if (projectId === 'project-html') {
return [{ name: 'index.html', kind: 'html', mtime: 2 }];
}
if (projectId === 'project-deck') {
return [{ name: 'index.html', kind: 'html', mtime: 2 }];
}
return [];
}),
projectFileUrl: (projectId: string, fileName: string) =>
`/api/projects/${projectId}/files/${fileName}`,
}));
afterEach(() => {
cleanup();
vi.unstubAllGlobals();
});
function project(overrides: Partial<Project>): Project {
return {
id: 'project-1',
name: 'Project',
skillId: null,
designSystemId: null,
createdAt: 1,
updatedAt: 2,
status: { value: 'not_started' },
...overrides,
};
}
describe('RecentProjectsStrip', () => {
it('matches project cards with previews and design-system tags', async () => {
const { container } = render(
<RecentProjectsStrip
projects={[
project({
id: 'project-ds',
name: 'Acme Design System',
updatedAt: 4,
metadata: {
kind: 'other',
importedFrom: 'design-system',
},
}),
project({
id: 'project-html',
name: 'Web Prototype',
updatedAt: 3,
}),
]}
onOpen={() => {}}
onViewAll={() => {}}
/>,
);
expect(screen.getByText('Design System')).toBeTruthy();
expect(screen.getAllByText('Prototype').length).toBeGreaterThan(0);
const designSystemCard = container.querySelector('.recent-projects__card.is-design-system-project');
expect(designSystemCard).toBeTruthy();
expect(designSystemCard?.querySelectorAll('.design-card-tag')).toHaveLength(1);
await waitFor(() => {
expect(designSystemCard?.querySelector('.recent-projects__card-thumb-logo img')).toBeTruthy();
expect(container.querySelector('.recent-projects__card-thumb-html iframe')).toBeTruthy();
});
});
it('renders deck project covers without deck navigation controls', async () => {
vi.stubGlobal(
'fetch',
vi.fn(async () => ({
ok: true,
text: async () => `
<!doctype html>
<html>
<head><title>Deck</title></head>
<body>
<section class="slide active">First slide</section>
<section class="slide">Second slide</section>
<div class="deck-counter"><button id="deck-prev"></button><span>1 / 10</span><button id="deck-next"></button></div>
</body>
</html>
`,
})),
);
const { container } = render(
<RecentProjectsStrip
projects={[
project({
id: 'project-deck',
name: 'Simple Deck',
updatedAt: 4,
metadata: { kind: 'deck' },
}),
project({
id: 'project-html',
name: 'Web Prototype',
updatedAt: 3,
}),
]}
onOpen={() => {}}
onViewAll={() => {}}
/>,
);
const deckCard = container.querySelector('[data-project-id="project-deck"]');
const htmlCard = container.querySelector('[data-project-id="project-html"]');
await waitFor(() => {
const deckIframe = deckCard?.querySelector('iframe') as HTMLIFrameElement | null;
expect(deckIframe?.getAttribute('srcdoc')).toContain('First slide');
expect(deckIframe?.getAttribute('srcdoc')).toContain('od-recent-deck-real-preview');
expect(deckIframe?.getAttribute('srcdoc')).not.toContain('<script');
expect(deckIframe?.getAttribute('src')).toBeNull();
expect(htmlCard?.querySelector('iframe')?.getAttribute('src')).toBe(
'/api/projects/project-html/files/index.html',
);
});
});
});