fix(examples): merge circuitExamples via array spread, not side-effect push
Previously examples.ts pushed to exampleProjects[] after declaration, which some bundlers can treat as dead code under aggressive tree-shaking. This also made HMR unreliable when examples-circuits.ts changed. Now: const legacyExamples = [...] export const exampleProjects = [...legacyExamples, ...circuitExamples] Single immutable export. Guaranteed to include all 150 examples at import time. The gallery (ExamplesGallery.tsx) and SSR prerender (entry-server.tsx) both pick up the new circuit examples automatically. Also adds frontend/src/__tests__/examples-circuits.test.ts with 5 assertions to catch future regressions (all circuit ids present, no duplicates, valid required fields, expected categories covered). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
df37fdf6a4
commit
635bc2a952
|
|
@ -0,0 +1,45 @@
|
|||
/**
|
||||
* Ensures that circuitExamples (examples-circuits.ts) are merged into
|
||||
* exampleProjects so the /examples gallery and SSR prerender include them.
|
||||
*/
|
||||
import { describe, it, expect } from 'vitest';
|
||||
import { exampleProjects } from '../data/examples';
|
||||
import { circuitExamples } from '../data/examples-circuits';
|
||||
|
||||
describe('circuitExamples integration', () => {
|
||||
it('circuitExamples has at least 30 new examples', () => {
|
||||
expect(circuitExamples.length).toBeGreaterThanOrEqual(30);
|
||||
});
|
||||
|
||||
it('every circuitExample id appears in exampleProjects', () => {
|
||||
const allIds = new Set(exampleProjects.map((e) => e.id));
|
||||
const missing = circuitExamples.map((e) => e.id).filter((id) => !allIds.has(id));
|
||||
expect(missing).toEqual([]);
|
||||
});
|
||||
|
||||
it('no duplicate ids in exampleProjects', () => {
|
||||
const ids = exampleProjects.map((e) => e.id);
|
||||
const dupes = ids.filter((id, i) => ids.indexOf(id) !== i);
|
||||
expect(dupes).toEqual([]);
|
||||
});
|
||||
|
||||
it('circuit examples cover all expected categories', () => {
|
||||
const cats = new Set(circuitExamples.map((e) => e.category));
|
||||
expect(cats.has('basics')).toBe(true);
|
||||
expect(cats.has('sensors')).toBe(true);
|
||||
expect(cats.has('robotics')).toBe(true);
|
||||
});
|
||||
|
||||
it('every example has valid required fields', () => {
|
||||
for (const e of circuitExamples) {
|
||||
expect(e.id, `missing id: ${JSON.stringify(e)}`).toBeTypeOf('string');
|
||||
expect(e.title).toBeTypeOf('string');
|
||||
expect(e.description).toBeTypeOf('string');
|
||||
expect(e.category).toMatch(/^(basics|sensors|displays|communication|games|robotics)$/);
|
||||
expect(e.difficulty).toMatch(/^(beginner|intermediate|advanced)$/);
|
||||
expect(e.code).toBeTypeOf('string');
|
||||
expect(Array.isArray(e.components)).toBe(true);
|
||||
expect(Array.isArray(e.wires)).toBe(true);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
|
@ -4,6 +4,8 @@
|
|||
* Collection of example projects that users can load and run
|
||||
*/
|
||||
|
||||
import { circuitExamples } from './examples-circuits';
|
||||
|
||||
/** Per-board setup for multi-board examples */
|
||||
export interface ExampleBoard {
|
||||
/** Must match a BoardKind — determines the board instance ID (first board of a kind → boardKind string) */
|
||||
|
|
@ -52,7 +54,7 @@ export interface ExampleProject {
|
|||
libraries?: string[];
|
||||
}
|
||||
|
||||
export const exampleProjects: ExampleProject[] = [
|
||||
const legacyExamples: ExampleProject[] = [
|
||||
{
|
||||
id: 'blink-led',
|
||||
title: 'Blink LED',
|
||||
|
|
@ -4799,9 +4801,10 @@ void loop() {
|
|||
},
|
||||
];
|
||||
|
||||
// Append circuit-focused examples (analog, digital gates, electromechanical)
|
||||
import { circuitExamples } from './examples-circuits';
|
||||
exampleProjects.push(...circuitExamples);
|
||||
// Merge legacy examples with circuit-focused examples (analog, digital gates,
|
||||
// electromechanical). Declared after both arrays exist so the export is a
|
||||
// single immutable value — safe from tree-shaking quirks.
|
||||
export const exampleProjects: ExampleProject[] = [...legacyExamples, ...circuitExamples];
|
||||
|
||||
// Get examples by category
|
||||
export function getExamplesByCategory(category: ExampleProject['category']): ExampleProject[] {
|
||||
|
|
|
|||
Loading…
Reference in New Issue