diff --git a/src/utils/charts-catalog-example.ts b/src/utils/charts-catalog-example.ts index 8e2c826b2..627bee248 100644 --- a/src/utils/charts-catalog-example.ts +++ b/src/utils/charts-catalog-example.ts @@ -5,7 +5,7 @@ import { } from './example-workspace' const catalogSourceRoot = 'benchmarks/conformance/' -const generatedEntryPath = '/__catalog.ts' +const generatedEntryPath = '/__catalog.tsx' const generatedDocumentPath = '/index.html' const revisionPattern = /^[a-f0-9]{40}$/ const exactVersionPattern = @@ -48,7 +48,10 @@ export function createChartsCatalogExampleDefinition({ } const initialFile = normalizeCatalogSourcePath(entryPath) - const expectedInitialFile = `/cases/${caseId}/tanstack.ts` + const isPublicExample = initialFile.endsWith('/example.tsx') + const expectedInitialFile = isPublicExample + ? `/cases/${caseId}/example.tsx` + : `/cases/${caseId}/tanstack.ts` if (initialFile !== expectedInitialFile) { throw new Error( @@ -74,6 +77,7 @@ export function createChartsCatalogExampleDefinition({ initialFile, chartHeight, renderRevision, + isPublicExample, ) workspaceFiles[generatedDocumentPath] = createCatalogDocument(chartHeight) @@ -171,6 +175,50 @@ function createCatalogEntry( initialFile: string, chartHeight: number, renderRevision: number, + isPublicExample: boolean, +) { + if (!isPublicExample) { + return createLegacyCatalogEntry(initialFile, chartHeight, renderRevision) + } + + return `import { createRoot } from 'react-dom/client' +import type { ComponentType } from 'react' +import Example from ${JSON.stringify(initialFile)} + +const root = document.querySelector('#root') +if (!root) throw new Error('Charts catalog root not found') + +const height = ${chartHeight} +let width = Math.max(1, Math.floor(root.getBoundingClientRect().width)) +const CatalogExample = Example as ComponentType<{ + width?: number + height?: number + revision?: number +}> +const reactRoot = createRoot(root) +const render = () => reactRoot.render( + +) +render() +const observer = new ResizeObserver(() => { + const nextWidth = Math.max(1, Math.floor(root.getBoundingClientRect().width)) + if (nextWidth === width) return + width = nextWidth + render() +}) + +observer.observe(root) +window.addEventListener('pagehide', () => { + observer.disconnect() + reactRoot.unmount() +}, { once: true }) +` +} + +function createLegacyCatalogEntry( + initialFile: string, + chartHeight: number, + renderRevision: number, ) { return `import { mount } from ${JSON.stringify(initialFile)} diff --git a/src/utils/charts-catalog-index.ts b/src/utils/charts-catalog-index.ts index a691ffc0e..f10889df2 100644 --- a/src/utils/charts-catalog-index.ts +++ b/src/utils/charts-catalog-index.ts @@ -32,22 +32,29 @@ const httpsUrlSchema = v.pipe( v.url(), v.check((value) => new URL(value).protocol === 'https:', 'Expected HTTPS'), ) -const referenceRendererSchema = v.picklist([ +const legacyReferenceRendererSchema = v.picklist([ 'observable-plot', 'recharts', 'echarts', ]) -const caseEntryPathSchema = v.pipe( +const legacyCaseEntryPathSchema = v.pipe( v.string(), v.regex( /^benchmarks\/conformance\/cases\/[a-z0-9]+(?:-[a-z0-9]+)*\/(?:tanstack|plot|recharts|echarts)\.ts$/, + 'Invalid legacy catalog entry path', + ), +) +const caseEntryPathSchema = v.pipe( + v.string(), + v.regex( + /^benchmarks\/conformance\/cases\/[a-z0-9]+(?:-[a-z0-9]+)*\/example\.tsx$/, 'Invalid catalog entry path', ), ) // Deliberately use `object` here. The Charts benchmark owns geometry and // interaction metadata; the site validates and retains only its UI contract. -const catalogCaseSchema = v.pipe( +const legacyCatalogCaseSchema = v.pipe( v.object({ schemaVersion: v.literal(1), order: nonNegativeIntegerSchema, @@ -67,10 +74,10 @@ const catalogCaseSchema = v.pipe( maintain: nonEmptyStringSchema, }), entries: v.strictObject({ - tanstack: caseEntryPathSchema, + tanstack: legacyCaseEntryPathSchema, reference: v.strictObject({ - renderer: referenceRendererSchema, - path: caseEntryPathSchema, + renderer: legacyReferenceRendererSchema, + path: legacyCaseEntryPathSchema, }), }), }), @@ -83,7 +90,7 @@ const catalogCaseSchema = v.pipe( (catalogCase) => catalogCase.entries.tanstack === `benchmarks/conformance/cases/${catalogCase.id}/tanstack.ts`, - 'Catalog case TanStack entry must match its ID', + 'Legacy catalog case TanStack entry must match its ID', ), v.check((catalogCase) => { const filename = @@ -94,18 +101,64 @@ const catalogCaseSchema = v.pipe( catalogCase.entries.reference.path === `benchmarks/conformance/cases/${catalogCase.id}/${filename}.ts` ) - }, 'Catalog case reference entry must match its ID and renderer'), + }, 'Legacy catalog case reference entry must match its ID and renderer'), ) -const catalogIndexSchema = v.pipe( - v.strictObject({ +const catalogCaseSchema = v.pipe( + v.object({ schemaVersion: v.literal(1), + order: nonNegativeIntegerSchema, + id: caseIdSchema, + collection: v.optional(caseIdSchema), + title: nonEmptyStringSchema, + family: nonEmptyStringSchema, + intent: nonEmptyStringSchema, + support: v.picklist(['native', 'composed', 'gap', 'deferred']), + features: v.array(nonEmptyStringSchema), source: v.strictObject({ - repo: v.literal(chartsCatalogIndexRepo), - pathRoot: v.literal('benchmarks/conformance/'), + title: nonEmptyStringSchema, + url: httpsUrlSchema, + }), + ai: v.strictObject({ + create: nonEmptyStringSchema, + maintain: nonEmptyStringSchema, + }), + entries: v.strictObject({ + example: caseEntryPathSchema, }), - cases: v.pipe(v.array(catalogCaseSchema), v.minLength(1)), }), + v.check( + (catalogCase) => + new Set(catalogCase.features).size === catalogCase.features.length, + 'Catalog case features must be unique', + ), + v.check( + (catalogCase) => + catalogCase.entries.example === + `benchmarks/conformance/cases/${catalogCase.id}/example.tsx`, + 'Catalog case example entry must match its ID', + ), +) + +const catalogIndexSchema = v.pipe( + v.union([ + v.strictObject({ + schemaVersion: v.literal(1), + source: v.strictObject({ + repo: v.literal(chartsCatalogIndexRepo), + pathRoot: v.literal('benchmarks/conformance/'), + }), + cases: v.pipe(v.array(legacyCatalogCaseSchema), v.minLength(1)), + }), + v.strictObject({ + schemaVersion: v.literal(2), + source: v.strictObject({ + repo: v.literal(chartsCatalogIndexRepo), + pathRoot: v.literal('benchmarks/conformance/'), + }), + cases: v.pipe(v.array(catalogCaseSchema), v.minLength(1)), + }), + ]), v.check((index) => { const ids = index.cases.map((catalogCase) => catalogCase.id) return new Set(ids).size === ids.length diff --git a/src/utils/charts-catalog.server.ts b/src/utils/charts-catalog.server.ts index ca471f8fb..da950f1c7 100644 --- a/src/utils/charts-catalog.server.ts +++ b/src/utils/charts-catalog.server.ts @@ -7,7 +7,10 @@ import { chartsCatalogRepo, type ChartsCatalogAuthoredSource, } from './charts-catalog' -import type { ChartsCatalogIndexPublication } from './charts-catalog-index' +import type { + ChartsCatalogIndexCase, + ChartsCatalogIndexPublication, +} from './charts-catalog-index' import { createChartsCatalogExampleDefinition, type ChartsCatalogExampleVersions, @@ -83,11 +86,12 @@ export async function getChartsCatalogExample( `Charts catalog case not found: ${caseId}`, ) } + const entryPath = getChartsCatalogEntryPath(catalogCase) const [files, versions] = await Promise.all([ getChartsCatalogExampleFiles( publication.revision, - catalogCase.entries.tanstack, + entryPath, publication.sourceKind, ), getChartsCatalogExampleVersions( @@ -103,18 +107,21 @@ export async function getChartsCatalogExample( title: catalogCase.title, description: catalogCase.intent, revision: publication.revision, - entryPath: catalogCase.entries.tanstack, + entryPath, files, renderRevision: options?.renderRevision, versions, }), - authoredSource: createChartsCatalogAuthoredSource( - files, - catalogCase.entries.tanstack, - ), + authoredSource: createChartsCatalogAuthoredSource(files, entryPath), } } +function getChartsCatalogEntryPath(catalogCase: ChartsCatalogIndexCase) { + return 'example' in catalogCase.entries + ? catalogCase.entries.example + : catalogCase.entries.tanstack +} + export async function getChartsCatalogExampleDefinition( publication: ChartsCatalogIndexPublication, caseId: string, @@ -181,6 +188,8 @@ async function getChartsCatalogExampleFiles( entryPath: string, sourceKind: ChartsCatalogIndexPublication['sourceKind'], ) { + const caseDirectory = entryPath.slice(0, entryPath.lastIndexOf('/') + 1) + const isSelfContainedExample = entryPath.endsWith('/example.tsx') const sourcePaths = sourceKind === 'local' ? undefined @@ -211,6 +220,13 @@ async function getChartsCatalogExampleFiles( resolveCatalogExampleModule(path, specifier, sourcePaths, revision), ), ) + for (const dependency of dependencies) { + if (isSelfContainedExample && !dependency.startsWith(caseDirectory)) { + throw new ChartsCatalogIntegrityError( + `Charts catalog example import leaves its case directory: ${dependency}`, + ) + } + } await Promise.all(dependencies.map(load)) } diff --git a/tests/charts-catalog-example.test.ts b/tests/charts-catalog-example.test.ts index ff464225c..45536efa9 100644 --- a/tests/charts-catalog-example.test.ts +++ b/tests/charts-catalog-example.test.ts @@ -20,20 +20,16 @@ const versions: ChartsCatalogExampleVersions = { describe('Charts catalog example workspaces', () => { test('preserves Git source files and generates a runnable workspace', () => { - const entrySource = `import { tanstackMount } from '../../shared/mount'\nexport const mount = tanstackMount(() => ({}), 'Sorted bars')` - const mountSource = `export function tanstackMount() {}` - const typesSource = `export interface ConformanceInput { width: number }` + const entrySource = `export default function Example() { return
Sorted bars
}` const definition = createChartsCatalogExampleDefinition({ caseId: 'bar-vertical-sorted', title: 'Sorted vertical bars', description: 'Compare English letter frequencies.', revision, - entryPath: 'benchmarks/conformance/cases/bar-vertical-sorted/tanstack.ts', + entryPath: 'benchmarks/conformance/cases/bar-vertical-sorted/example.tsx', files: { - 'benchmarks/conformance/cases/bar-vertical-sorted/tanstack.ts': + 'benchmarks/conformance/cases/bar-vertical-sorted/example.tsx': entrySource, - 'benchmarks/conformance/shared/mount.ts': mountSource, - 'benchmarks/conformance/types.ts': typesSource, }, versions, }) @@ -41,22 +37,20 @@ describe('Charts catalog example workspaces', () => { assert.equal(definition.id, 'bar-vertical-sorted') assert.equal( definition.initialFile, - '/cases/bar-vertical-sorted/tanstack.ts', + '/cases/bar-vertical-sorted/example.tsx', ) - assert.equal(definition.workspace.entry, '/__catalog.ts') + assert.equal(definition.workspace.entry, '/__catalog.tsx') assert.equal( - definition.workspace.files['/cases/bar-vertical-sorted/tanstack.ts'], + definition.workspace.files['/cases/bar-vertical-sorted/example.tsx'], entrySource, ) - assert.equal(definition.workspace.files['/shared/mount.ts'], mountSource) - assert.equal(definition.workspace.files['/types.ts'], typesSource) assert.equal(definition.workspace.files['/package.json'], undefined) assert.match( - definition.workspace.files['/__catalog.ts'] ?? '', - /import \{ mount \} from "\/cases\/bar-vertical-sorted\/tanstack\.ts"/, + definition.workspace.files['/__catalog.tsx'] ?? '', + /import Example from "\/cases\/bar-vertical-sorted\/example\.tsx"/, ) assert.match( - definition.workspace.files['/__catalog.ts'] ?? '', + definition.workspace.files['/__catalog.tsx'] ?? '', /new ResizeObserver/, ) assert.match( @@ -65,14 +59,38 @@ describe('Charts catalog example workspaces', () => { ) }) - test('pins framework, dependency, atlas, and dataset imports', () => { + test('runs the legacy adapter entry during a schema v1 rollout', () => { + const entrySource = 'export function mount() {}' const definition = createChartsCatalogExampleDefinition({ caseId: 'bar-vertical-sorted', title: 'Sorted vertical bars', revision, entryPath: 'cases/bar-vertical-sorted/tanstack.ts', files: { - '/cases/bar-vertical-sorted/tanstack.ts': 'export function mount() {}', + 'cases/bar-vertical-sorted/tanstack.ts': entrySource, + }, + versions, + }) + + assert.equal( + definition.initialFile, + '/cases/bar-vertical-sorted/tanstack.ts', + ) + assert.match( + definition.workspace.files['/__catalog.tsx'] ?? '', + /import \{ mount \} from "\/cases\/bar-vertical-sorted\/tanstack\.ts"/, + ) + }) + + test('pins framework, dependency, atlas, and dataset imports', () => { + const definition = createChartsCatalogExampleDefinition({ + caseId: 'bar-vertical-sorted', + title: 'Sorted vertical bars', + revision, + entryPath: 'cases/bar-vertical-sorted/example.tsx', + files: { + '/cases/bar-vertical-sorted/example.tsx': + 'export default function Example() {}', }, versions, }) @@ -114,20 +132,21 @@ describe('Charts catalog example workspaces', () => { chartHeight: 640, renderRevision: 42, revision, - entryPath: 'cases/bar-vertical-sorted/tanstack.ts', + entryPath: 'cases/bar-vertical-sorted/example.tsx', files: { - '/cases/bar-vertical-sorted/tanstack.ts': 'export function mount() {}', + '/cases/bar-vertical-sorted/example.tsx': + 'export default function Example() {}', }, versions, }) assert.match( - definition.workspace.files['/__catalog.ts'] ?? '', + definition.workspace.files['/__catalog.tsx'] ?? '', /const height = 640/, ) assert.match( - definition.workspace.files['/__catalog.ts'] ?? '', - /revision: 42/, + definition.workspace.files['/__catalog.tsx'] ?? '', + /revision=\{42\}/, ) assert.match( definition.workspace.files['/index.html'] ?? '', @@ -140,7 +159,7 @@ describe('Charts catalog example workspaces', () => { caseId: 'bar-vertical-sorted', title: 'Sorted vertical bars', revision, - entryPath: 'cases/bar-vertical-sorted/tanstack.ts', + entryPath: 'cases/bar-vertical-sorted/example.tsx', versions, } @@ -150,9 +169,10 @@ describe('Charts catalog example workspaces', () => { assert.throws(() => createChartsCatalogExampleDefinition({ ...base, - entryPath: 'cases/another-case/tanstack.ts', + entryPath: 'cases/another-case/example.tsx', files: { - 'cases/another-case/tanstack.ts': 'export function mount() {}', + 'cases/another-case/example.tsx': + 'export default function Example() {}', }, }), ) @@ -160,8 +180,8 @@ describe('Charts catalog example workspaces', () => { createChartsCatalogExampleDefinition({ ...base, files: { - 'cases/bar-vertical-sorted/tanstack.ts': 'first', - 'benchmarks/conformance/cases/bar-vertical-sorted/tanstack.ts': + 'cases/bar-vertical-sorted/example.tsx': 'first', + 'benchmarks/conformance/cases/bar-vertical-sorted/example.tsx': 'second', }, }), @@ -170,7 +190,7 @@ describe('Charts catalog example workspaces', () => { createChartsCatalogExampleDefinition({ ...base, files: { - 'cases/bar-vertical-sorted/tanstack.ts': 'entry', + 'cases/bar-vertical-sorted/example.tsx': 'entry', 'cases/bar-vertical-sorted/../other.ts': 'unsafe', }, }), diff --git a/tests/charts-catalog-index.test.ts b/tests/charts-catalog-index.test.ts index 4f5d9970a..d581defc0 100644 --- a/tests/charts-catalog-index.test.ts +++ b/tests/charts-catalog-index.test.ts @@ -34,18 +34,14 @@ function createCatalogCase( maintain: 'Keep the gaps visible.', }, entries: { - tanstack: `benchmarks/conformance/cases/${id}/tanstack.ts`, - reference: { - renderer: 'observable-plot', - path: `benchmarks/conformance/cases/${id}/plot.ts`, - }, + example: `benchmarks/conformance/cases/${id}/example.tsx`, }, } } function createCatalogIndex(collection?: string) { return { - schemaVersion: 1, + schemaVersion: 2, source: { repo: 'tanstack/charts', pathRoot: 'benchmarks/conformance/', @@ -54,6 +50,29 @@ function createCatalogIndex(collection?: string) { } } +function createLegacyCatalogIndex() { + const catalogCase = createCatalogCase() + return { + schemaVersion: 1, + source: { + repo: 'tanstack/charts', + pathRoot: 'benchmarks/conformance/', + }, + cases: [ + { + ...catalogCase, + entries: { + tanstack: 'benchmarks/conformance/cases/01-line-gaps/tanstack.ts', + reference: { + renderer: 'observable-plot', + path: 'benchmarks/conformance/cases/01-line-gaps/plot.ts', + }, + }, + }, + ], + } +} + test('catalog index retains only the site-owned contract', () => { const index = parseChartsCatalogIndex(createCatalogIndex('shadcn')) @@ -66,6 +85,13 @@ test('catalog index retains only the site-owned contract', () => { ) }) +test('catalog index accepts the legacy adapter contract during rollout', () => { + const index = parseChartsCatalogIndex(createLegacyCatalogIndex()) + + assert.equal(index.schemaVersion, 1) + assert.equal(index.cases[0]?.id, '01-line-gaps') +}) + test('catalog index rejects broken case and ordering relationships', () => { const duplicate = createCatalogIndex() duplicate.cases.push(createCatalogCase('01-line-gaps', 2)) @@ -76,8 +102,8 @@ test('catalog index rejects broken case and ordering relationships', () => { assert.throws(() => parseChartsCatalogIndex(unsorted)) const mismatchedEntry = createCatalogIndex() - mismatchedEntry.cases[0]!.entries.tanstack = - 'benchmarks/conformance/cases/other/tanstack.ts' + mismatchedEntry.cases[0]!.entries.example = + 'benchmarks/conformance/cases/other/example.tsx' assert.throws(() => parseChartsCatalogIndex(mismatchedEntry)) }) diff --git a/tests/charts-catalog-site-contracts.test.ts b/tests/charts-catalog-site-contracts.test.ts index 5a49c028b..7dd090024 100644 --- a/tests/charts-catalog-site-contracts.test.ts +++ b/tests/charts-catalog-site-contracts.test.ts @@ -14,7 +14,7 @@ import { test('sitemap exposes catalog pages but not runtime resources', () => { const index = parseChartsCatalogIndex({ - schemaVersion: 1, + schemaVersion: 2, source: { repo: 'tanstack/charts', pathRoot: 'benchmarks/conformance/', @@ -39,11 +39,7 @@ test('sitemap exposes catalog pages but not runtime resources', () => { maintain: 'Keep the line visible.', }, entries: { - tanstack: 'benchmarks/conformance/cases/01-line/tanstack.ts', - reference: { - renderer: 'observable-plot', - path: 'benchmarks/conformance/cases/01-line/plot.ts', - }, + example: 'benchmarks/conformance/cases/01-line/example.tsx', }, }, ], diff --git a/tests/charts-catalog-source-previews.test.ts b/tests/charts-catalog-source-previews.test.ts index 947430a82..b7f8f0c65 100644 --- a/tests/charts-catalog-source-previews.test.ts +++ b/tests/charts-catalog-source-previews.test.ts @@ -328,7 +328,7 @@ function requestPreview({ function createCatalogIndex() { return { - schemaVersion: 1, + schemaVersion: 2, source: { repo: 'tanstack/charts', pathRoot: 'benchmarks/conformance/', @@ -352,11 +352,7 @@ function createCatalogIndex() { maintain: 'Keep the gaps visible.', }, entries: { - tanstack: 'benchmarks/conformance/cases/01-line-gaps/tanstack.ts', - reference: { - renderer: 'observable-plot', - path: 'benchmarks/conformance/cases/01-line-gaps/plot.ts', - }, + example: 'benchmarks/conformance/cases/01-line-gaps/example.tsx', }, }, ], diff --git a/tests/charts-catalog-source.test.ts b/tests/charts-catalog-source.test.ts index 1fac922b9..11c3660d7 100644 --- a/tests/charts-catalog-source.test.ts +++ b/tests/charts-catalog-source.test.ts @@ -5,7 +5,8 @@ import { parseChartsCatalogIndexPublication } from '../src/utils/charts-catalog- import { resetGitHubContentCacheForTest } from '../src/utils/github-content-cache.server' const revision = '4'.repeat(40) -const entryPath = 'benchmarks/conformance/cases/01-line/tanstack.ts' +const entryPath = 'benchmarks/conformance/cases/01-line/example.tsx' +const legacyEntryPath = 'benchmarks/conformance/cases/01-line/tanstack.ts' const dependencyVersions = Object.fromEntries( [ 'd3-array', @@ -31,6 +32,41 @@ const dependencyVersions = Object.fromEntries( ) const publication = parseChartsCatalogIndexPublication({ + revision, + sourceKind: 'remote', + index: { + schemaVersion: 2, + source: { + repo: 'tanstack/charts', + pathRoot: 'benchmarks/conformance/', + }, + cases: [ + { + schemaVersion: 1, + order: 1, + id: '01-line', + title: 'Line chart', + family: 'trend', + intent: 'Show a line.', + support: 'native', + features: ['line'], + source: { + title: 'Source', + url: 'https://example.com/source', + }, + ai: { + create: 'Create a line chart.', + maintain: 'Keep the line visible.', + }, + entries: { + example: entryPath, + }, + }, + ], + }, +}) + +const legacyPublication = parseChartsCatalogIndexPublication({ revision, sourceKind: 'remote', index: { @@ -58,7 +94,7 @@ const publication = parseChartsCatalogIndexPublication({ maintain: 'Keep the line visible.', }, entries: { - tanstack: entryPath, + tanstack: legacyEntryPath, reference: { renderer: 'observable-plot', path: 'benchmarks/conformance/cases/01-line/plot.ts', @@ -72,21 +108,12 @@ const publication = parseChartsCatalogIndexPublication({ const sources: Record = { [entryPath]: [ "import { rows } from './data'", - "import { tanstackMount } from '../../shared/mount'", - 'export const mount = tanstackMount(() => rows)', + 'export default function Example() {', + ' return
{JSON.stringify(rows)}
', + '}', ].join('\n'), 'benchmarks/conformance/cases/01-line/data.ts': 'export const rows = [{ x: 1, y: 2 }]', - 'benchmarks/conformance/shared/mount.ts': [ - "import type { ConformanceInput } from '../types'", - 'export const tanstackMount =', - ' (create: (input: ConformanceInput) => unknown) => () => ({', - ' update: create,', - ' destroy() {},', - ' })', - ].join('\n'), - 'benchmarks/conformance/types.ts': - 'export type ConformanceInput = { width: number }', 'packages/charts-core/package.json': JSON.stringify({ version: '0.10.0' }), 'package.json': JSON.stringify({ devDependencies: { @@ -108,14 +135,12 @@ test('catalog example follows Git source without a catalog package or build outp '01-line', ) - assert.equal(example.initialFile, '/cases/01-line/tanstack.ts') + assert.equal(example.initialFile, '/cases/01-line/example.tsx') assert.deepEqual(Object.keys(example.workspace.files).sort(), [ - '/__catalog.ts', + '/__catalog.tsx', '/cases/01-line/data.ts', - '/cases/01-line/tanstack.ts', + '/cases/01-line/example.tsx', '/index.html', - '/shared/mount.ts', - '/types.ts', ]) assert.equal(example.workspace.files['/package.json'], undefined) assert.equal( @@ -126,9 +151,7 @@ test('catalog example follows Git source without a catalog package or build outp authoredSource.files.map((file) => [file.kind, file.path]), [ ['dependency', 'cases/01-line/data.ts'], - ['entry', 'cases/01-line/tanstack.ts'], - ['dependency', 'shared/mount.ts'], - ['dependency', 'types.ts'], + ['entry', 'cases/01-line/example.tsx'], ], ) } finally { @@ -137,6 +160,38 @@ test('catalog example follows Git source without a catalog package or build outp } }) +test('catalog example follows a legacy adapter closure during rollout', async () => { + const originalFetch = globalThis.fetch + resetGitHubContentCacheForTest() + globalThis.fetch = createSourceFetch({ + ...sources, + [legacyEntryPath]: + "import { mountExample } from '../../shared/mount'\nexport const mount = mountExample", + 'benchmarks/conformance/shared/mount.ts': + 'export function mountExample() {}', + }) + + try { + const { authoredSource, example } = await getChartsCatalogExample( + legacyPublication, + '01-line', + ) + + assert.equal(example.initialFile, '/cases/01-line/tanstack.ts') + assert.deepEqual( + authoredSource.files.map((file) => file.path), + ['cases/01-line/tanstack.ts', 'shared/mount.ts'], + ) + assert.match( + example.workspace.files['/__catalog.tsx'] ?? '', + /import \{ mount \}/, + ) + } finally { + globalThis.fetch = originalFetch + resetGitHubContentCacheForTest() + } +}) + test('catalog example rejects an unresolved relative source import', async () => { const originalFetch = globalThis.fetch resetGitHubContentCacheForTest()