Files
mermaid-live-editor/tests/configMigration.spec.ts
Sidharth VinodandClaude Fable 5.1 f87e6429dd feat: keep the diagram theme in step with the diagram type and site mode
Instead of leaving the config empty, the editor now manages the theme: after every validation and on site light/dark changes, syncManagedTheme sets it to the diagram type's own mermaid default (the config section's theme, e.g. redux-color for flowcharts, else the global default) or, in dark mode, the redux -dark variant (redux-dark-color) or dark.

Only editor-set themes are replaced: a missing theme, the global default, a section default or any of their dark variants (isManagedTheme). A theme the user chose, such as forest, is never touched.

Detector ids that do not match their config section (flowchart-v2, flowchart-elk, classDiagram, stateDiagram, xychart, railroadAbnf/Ebnf/Peg) are aliased in mermaid.ts; ids without a section (wardley, zenuml) use the global default.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-11 00:39:12 +05:30

67 lines
2.5 KiB
TypeScript

import { C } from '$/constants';
import { expect, test, type Page } from '@playwright/test';
// What a pre-mermaid-12 install left in localStorage: the editor seeded every
// config with the default theme.
const legacyCodeStore = JSON.stringify({
code: 'graph TD\n A[Legacy] --> B[Config]',
grid: true,
mermaid: '{\n "theme": "default"\n}',
panZoom: true,
rough: false,
updateDiagram: true
});
// Seeds the legacy install with the history-id migration already applied (v0).
// Guarded so reloads do not re-seed.
const seedLegacyInstall = (page: Page) =>
page.addInitScript(
([codeStore, chooserKey]) => {
if (localStorage.getItem('migrations') === null) {
localStorage.setItem('migrations', JSON.stringify({ version: 0 }));
localStorage.setItem('codeStore', codeStore);
localStorage.setItem(chooserKey, 'true');
}
},
[legacyCodeStore, C.editorChooserDismissedKey]
);
const openEditor = async (page: Page) => {
await page.goto('/edit');
// Mounting can take a while on a cold dev server; the sidebar marks it done.
await page.getByText('Sample Diagrams', { exact: true }).waitFor();
};
const storedConfig = (page: Page) =>
page.evaluate(
() => (JSON.parse(localStorage.getItem('codeStore') ?? '{}') as { mermaid?: string }).mermaid
);
const migrationVersion = (page: Page) =>
page.evaluate(
() => (JSON.parse(localStorage.getItem('migrations') ?? '{}') as { version?: number }).version
);
test.describe('Default theme config migration', () => {
test('replaces a legacy default-theme config with the diagram default', async ({ page }) => {
await page.emulateMedia({ colorScheme: 'light' });
await seedLegacyInstall(page);
await openEditor(page);
await expect(page.locator('#view')).toContainText('Legacy');
await expect.poll(() => migrationVersion(page)).toBe(1);
// A flowchart: mermaid 12's own default for it is redux-color.
await expect.poll(() => storedConfig(page)).toBe('{\n "theme": "redux-color"\n}');
});
test('uses the redux dark variant when the site is dark', async ({ page }) => {
await page.emulateMedia({ colorScheme: 'dark' });
await seedLegacyInstall(page);
await openEditor(page);
await expect(page.locator('#view')).toContainText('Legacy');
await expect.poll(() => migrationVersion(page)).toBe(1);
await expect
.poll(async () => JSON.parse((await storedConfig(page)) ?? '{}') as unknown)
.toEqual({ theme: 'redux-dark-color' });
});
});