Files
Genarrative/scripts/image-canvas-portal-theme.test.ts
T
kdletters 06c12f40b6 修复画板 Portal 菜单主题继承
新增画板 Portal 主题桥接并同步亮暗主题
让编辑器根节点与 Portal 菜单共享完整品牌 Token
补充静音开关、角色动画与样式契约回归测试
同步图片画布技术方案和 Portal 排障记忆
2026-07-20 20:56:36 +08:00

84 lines
2.5 KiB
TypeScript

import fs from 'node:fs';
import path from 'node:path';
import { describe, expect, it } from 'vitest';
function readIndexCss() {
return fs.readFileSync(path.resolve(process.cwd(), 'src/index.css'), 'utf8');
}
function getCssBlock(source: string, selector: string) {
const selectorIndex = source.indexOf(selector);
expect(selectorIndex, `${selector} should exist`).toBeGreaterThanOrEqual(0);
const openBraceIndex = source.indexOf('{', selectorIndex);
expect(
openBraceIndex,
`${selector} should open a CSS block`,
).toBeGreaterThanOrEqual(0);
let depth = 0;
for (let index = openBraceIndex; index < source.length; index += 1) {
const char = source[index];
if (char === '{') {
depth += 1;
} else if (char === '}') {
depth -= 1;
if (depth === 0) {
return source.slice(openBraceIndex + 1, index);
}
}
}
throw new Error(`${selector} block is not closed`);
}
describe('image canvas portal theme contract', () => {
it('exposes every image canvas brand token to body-level portal menus', () => {
const css = readIndexCss();
const sharedTokenBlock = getCssBlock(
css,
'.image-canvas-editor,\n.image-canvas-editor__portal-theme,\n.image-canvas-editor__portal-menu',
);
const editorBlock = getCssBlock(css, '.image-canvas-editor {');
const pressedToggleTrackBlock = getCssBlock(
css,
".image-canvas-editor__video-toggle[aria-pressed='true'] span",
);
for (const token of [
'--image-canvas-brand-accent:',
'--image-canvas-brand-accent-strong:',
'--image-canvas-brand-fill:',
'--image-canvas-brand-text-on-fill:',
'--image-canvas-brand-border:',
'--image-canvas-brand-border-strong:',
'--image-canvas-brand-border-soft:',
'--image-canvas-brand-soft:',
'--image-canvas-brand-soft-strong:',
'--image-canvas-brand-shadow:',
'--image-canvas-brand-focus-ring:',
]) {
expect(sharedTokenBlock).toContain(token);
}
for (const editorOnlyDeclaration of [
'position:',
'display:',
'height:',
'overflow:',
'background:',
'color:',
'user-select:',
]) {
expect(sharedTokenBlock).not.toContain(editorOnlyDeclaration);
}
expect(editorBlock).not.toContain('--image-canvas-brand-accent:');
expect(pressedToggleTrackBlock).toContain(
'background: var(--image-canvas-brand-accent);',
);
expect(pressedToggleTrackBlock).not.toContain('#00ff00');
});
});