Files
Genarrative/apps/ai-game-creator-shell/tests/gameRunToolbarActionsStyle.test.ts
T
suzmii b8849b8c01 优化 AGC 工作台顶栏布局:一行到底、版本入口钉右分级、播放并入运行页签
- 顶栏去掉两侧 flex-wrap、工具条改 overflow: hidden,空间不足按 data-layout 三档降级而不是换行
- 新增 workbenchToolbarModel(档位顺序与 1px 判据)与 useWorkbenchToolbarLayout(ResizeObserver 管宽度、MutationObserver 管内容,实测内容宽度写档位)
- 版本入口 margin-left: auto 钉在动作区最右,标识改「版本 N(原因 · 时间)」,窄档只留「版本 N」(序号复用资源画布版本卡编号口径)
- 新增 WorkbenchMoreActionsMenu:「打开项目目录 / 资源面板 / 整理画布」在 collapsed-actions 档收进「更多」下拉
- 删除独立「播放」按钮,运行页签前加 ▶ 图标,点页签即切视图并载入游戏资源
- 运行画面右下角新增「刷新运行画面」,LocalGamePreviewFrame 新增 reloadNonce 换 iframe 元素身份重新载入页面
- 用例:新增 workbenchToolbarLayout / runPreviewRefresh;改写 appSurface 顶栏与播放/刷新断言、版本标识断言与顶栏样式断言
2026-10-04 14:04:02 +08:00

88 lines
4.1 KiB
TypeScript

// @vitest-environment jsdom
import { readFileSync } from 'node:fs';
import { describe, expect, test } from 'vitest';
import { repoPath } from './repoPath';
import {
declaration,
parseStyleSheet,
resolveDeclarations,
} from './styleCascade';
/**
* 运行页顶栏动作区的声明级断言。
*
* jsdom 不加载全局样式表,所以这里按仓库既有做法(`styleCascade`)解析真实生效的声明:
* 「版本入口与「在浏览器打开」跟其他动作按钮同一套皮」只由样式决定,用例必须钉在声明上,
* 否则下一次改动给版本入口单开一套 border / background / hover 时没有任何东西会红。
*/
const GLOBAL_CSS_PATH = repoPath('apps/ai-game-creator-shell/src/styles.css');
const rules = parseStyleSheet(readFileSync(GLOBAL_CSS_PATH, 'utf8'));
// 同一个求值器限制:全局表里也有 `prefers-reduced-motion` 档,求值时先排除掉。
const widthRules = rules.filter(
(rule) => !(rule.media ?? '').includes('prefers-reduced-motion'),
);
function resolved(selectors: readonly string[]): Map<string, string> {
return resolveDeclarations(widthRules, selectors, 1280);
}
function hasRule(selector: string): boolean {
return widthRules.some((rule) => rule.selectors.includes(selector));
}
describe('运行页顶栏动作区样式', () => {
test('运行画面回到两行,页面里不再有预览地址状态行', () => {
const surface = resolved(['.game-run-surface']);
expect(declaration(surface, 'grid-template-rows')).toBe(
'minmax(300px, 1fr) auto',
);
// 状态行与那行小字整体退役:地址不再以文字常驻在页面上。
expect(hasRule('.game-run-status-bar')).toBe(false);
expect(hasRule('.game-run-status-hint')).toBe(false);
});
test('版本入口住进顶栏动作区,皮由那一组的基础规则给', () => {
// 动作区的按钮共用一套基础外观(这一组是「在浏览器打开」与版本入口的共同来源)。
const actionsButton = resolved(['.game-workbench-view-actions button']);
expect(declaration(actionsButton, 'min-height')).toBe('30px');
expect(declaration(actionsButton, 'border-radius')).toBe('999px');
expect(declaration(actionsButton, 'font-size')).toBe('12px');
expect(declaration(actionsButton, 'font-weight')).toBe('700');
// 版本入口只补「版本名可能很长」这一件事,不再自带边框 / 底色 / 文字色 / hover。
const trigger = resolved(['.game-run-version-trigger']);
expect(trigger.has('border')).toBe(false);
expect(trigger.has('background')).toBe(false);
expect(trigger.has('color')).toBe(false);
// 入口默认不参与收缩(`max-content`):收缩 + 省略号会把溢出「吃掉」,顶栏的档位判定
// 就永远量不到真实溢出。只有降到最后一档(动作已全收进「更多」)才允许它省略兜底。
expect(declaration(trigger, 'min-width')).toBe('max-content');
expect(
declaration(
resolved([
".game-workbench-toolbar[data-layout='collapsed-actions'] .game-run-version-trigger",
]),
'min-width',
),
).toBe('0');
// 省略号要真的生效:按钮是 flex 容器,文本必须挂在自带 overflow 的 span 上。
const label = resolved(['.game-run-version-trigger-label']);
expect(declaration(label, 'overflow')).toBe('hidden');
expect(declaration(label, 'text-overflow')).toBe('ellipsis');
expect(declaration(label, 'white-space')).toBe('nowrap');
// 括号里那一截(原因 + 时间)单独一层,窄档位收掉的就是它,序号永远留着。
expect(hasRule('.game-run-version-trigger-detail')).toBe(true);
expect(hasRule('.game-run-version-trigger-title')).toBe(true);
expect(hasRule('.game-run-version-trigger:hover')).toBe(false);
expect(hasRule('.game-run-version-trigger:focus-visible')).toBe(false);
// 版本入口不再绝对定位压在游戏画面上。
const picker = resolved(['.game-run-version-picker']);
expect(picker.has('position')).toBe(false);
expect(picker.has('top')).toBe(false);
expect(picker.has('right')).toBe(false);
});
});