veza/tests/e2e/28-storybook.spec.ts
senke 6fad0ad68d fix: stabilize frontend — 98 TS errors to 0, align API endpoints, optimize bundle
- Fix 98 TypeScript errors across 37 files:
  - Service layer double-unwrapping (subscriptionService, distributionService, gearService)
  - Self-referencing variables in SearchPageResults
  - FeedView/ExploreView .posts→.items alignment
  - useQueueSync Zustand subscribe API
  - AdminAuditLogsView missing interface fields
  - Toast proxy type, interceptor type narrowing
  - 22 unused imports/variables removed
  - 5 storybook mock data fixes

- Align frontend API calls with backend endpoints:
  - Analytics: useAnalyticsView now calls /creator/analytics/dashboard (was /analytics)
  - Chat: chatService uses /conversations (was mock data), WS URL from backend token
  - Dashboard StatsSection: uses real /dashboard API data (was hardcoded zeros)
  - Settings: suppress 2FA toast error when endpoint unavailable

- Fix marketplace products: seed uses 'active' status (was 'published')
- Enrich seed: admin follows all creators (feed has content)

- Optimize bundle: vendor catch-all 793KB→318KB gzip (-60%)
  Split into vendor-charts, vendor-emoji, vendor-swagger, vendor-media, etc.

- Clean repo: remove ~100 orphaned screenshots, audit reports, logs from root

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-24 21:18:49 +01:00

96 lines
2.6 KiB
TypeScript

import { test, expect } from '@chromatic-com/playwright';
import * as fs from 'fs';
import * as path from 'path';
/**
* Storybook - All Stories Test
*
* Iterates over every story in the built Storybook index and verifies
* that each story renders without console errors or page errors.
*
* Prerequisites:
* npm run build-storybook
* npx serve storybook-static -l 6007
*/
const INDEX_PATH = path.join(process.cwd(), 'storybook-static', 'index.json');
const IFRAME_URL = (id: string) =>
`/iframe.html?id=${encodeURIComponent(id)}&viewMode=story`;
const NAV_TIMEOUT_MS = 20000;
const POST_LOAD_MS = 200;
/** Story IDs from built Storybook index (available at load time). */
function getStoryIds(): string[] {
if (!fs.existsSync(INDEX_PATH)) return [];
try {
const index = JSON.parse(fs.readFileSync(INDEX_PATH, 'utf8'));
const entries = index.entries ?? {};
return Object.values(entries)
.map((e: { id?: string }) => e.id)
.filter(Boolean) as string[];
} catch {
return [];
}
}
/** Ignore known benign Storybook/addon or runtime messages. */
function isIgnoredConsoleError(text: string): boolean {
const ignored = [
'ResizeObserver',
'Warning: ReactDOM.render',
'Download the React DevTools',
'sb-manager',
'sb-addons',
'sb-common-assets',
'mockServiceWorker',
'Failed to load resource: net::ERR_ABORTED',
'ChunkLoadError',
'Loading chunk',
'hydration',
];
return ignored.some((s) => text.includes(s));
}
const storyIds = getStoryIds();
test.describe('STORYBOOK - ALL STORIES', () => {
if (storyIds.length === 0) {
test('run build-storybook first', async () => {
// No stories found — run npm run build-storybook first.
});
return;
}
for (const storyId of storyIds) {
test(storyId, async ({ page }) => {
const consoleErrors: string[] = [];
const pageErrors: string[] = [];
page.on('console', (msg) => {
const type = msg.type();
if (type === 'error') {
const text = msg.text();
if (!isIgnoredConsoleError(text)) consoleErrors.push(text);
}
});
page.on('pageerror', (err) => {
pageErrors.push(err.message);
});
const response = await page.goto(IFRAME_URL(storyId), {
waitUntil: 'domcontentloaded',
timeout: NAV_TIMEOUT_MS,
});
expect(response?.status()).toBe(200);
await page.waitForTimeout(POST_LOAD_MS);
const errors = [...pageErrors, ...consoleErrors];
expect(
errors,
errors.length
? `Story ${storyId}: ${errors.slice(0, 3).join('; ')}`
: undefined,
).toHaveLength(0);
});
}
});