Theme Builder: Layout/Axes/Legend/Type panels, scheme-render fix, fail-loud gallery

This commit is contained in:
2026-06-14 13:08:29 +03:00
parent b03c3b08ab
commit 91b8b1e7fe
19 changed files with 1381 additions and 135 deletions
+48
View File
@@ -0,0 +1,48 @@
/**
* Chart-renderer contract regression: the `range` scheme config form.
*
* The Theme Builder's Color panel writes a named scheme into `config.range.*`.
* A bare scheme-name *string* passes vega-lite compile but Vega rejects it at
* run ("Unrecognized scale range value"), silently blanking the chart — so the
* panel must write the object form `{ scheme: name }`. This drives a real
* vega-lite compile → vega parse → view run (renderer 'none', no DOM) over an
* actual gallery spec to lock that in. (renderSpec itself is integration-heavy —
* vega-embed + a live DOM — and is mocked in component tests; this covers the
* config contract underneath it.)
*/
import { describe, expect, it } from 'vitest';
import { compile } from 'vega-lite';
import * as vega from 'vega';
import type { TopLevelSpec } from 'vega-lite';
import type { Config } from 'vega-lite';
import { THEME_PREVIEW_SPECS } from '@core/theme-preview-specs';
const nominalColorSpec = THEME_PREVIEW_SPECS.find((c) => c.id === 'line')!
.spec as unknown as TopLevelSpec;
async function run(config: Config): Promise<void> {
const view = new vega.View(vega.parse(compile(nominalColorSpec, { config }).spec), {
renderer: 'none',
});
await view.runAsync();
view.finalize();
}
describe('range scheme config form', () => {
it('renders with the { scheme } object form (what the Color panel writes)', async () => {
await expect(run({ range: { category: { scheme: 'category20b' } } })).resolves.toBeUndefined();
});
it('renders with an explicit color array', async () => {
await expect(
run({ range: { category: ['#111111', '#222222', '#333333'] } }),
).resolves.toBeUndefined();
});
it('rejects a bare scheme-name string (the bug this guards against)', async () => {
await expect(
run({ range: { category: 'category20b' } as unknown as Config['range'] }),
).rejects.toThrow(/Unrecognized scale range value/);
});
});