Files
hermes-ui/tests/client/style-system.test.ts
T
toor 836d0228d2 Phase 007: migrate every remaining view from naive-ui to Arco Design Vue
The project now has exactly one UI library. Every naive-ui component in
packages/client/src is replaced by its Arco equivalent across 24 views and
roughly 80 components, and naive-ui is dropped from package.json along with
its transitive vueuc / @css-render / vdirs / seemly dependencies.

The migration is rendering-layer only. No store logic, no API contract, and
no /chat-run payload was touched.

Three classes of leftover were invisible to `grep naive-ui` and are now
covered by tests/client/no-naive-ui.test.ts, which asserts all three:
  - dead .n-* class names in style blocks
  - dead --n-* custom properties
  - naive-ui in package.json

Notable behavioural traps handled along the way, recorded in
docs/arco-migration-rules.md:
  - a-input-password defaults to masked; passing default-visibility="false"
    would have exposed API keys in clear text
  - a-upload fires a real XHR unless auto-upload is false
  - nested Trigger components fight over the first element child, so the
    group-chat settings dropdown was flattened
  - Arco renders tooltip default-slot text inline, which was silently
    collapsing the chat and group-chat toolbars
2026-10-18 22:57:25 +08:00

54 lines
2.2 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { readFileSync } from 'fs'
import { describe, expect, it } from 'vitest'
const readClientFile = (path: string) => readFileSync(`packages/client/src/${path}`, 'utf8')
describe('client style system', () => {
it('keeps shared page headers on one layout baseline', () => {
const globalStyles = readClientFile('styles/global.scss')
expect(globalStyles).toContain('min-height: 64px;')
expect(globalStyles).toContain('padding: 14px 20px;')
expect(globalStyles).toContain('.page-header > .header-actions')
})
it('aligns SCSS surfaces and radii with the shared theme tokens', () => {
const variables = readClientFile('styles/variables.scss')
expect(variables).toContain('--bg-card: #ffffff;')
// 深色主题必须重新定义 card surface,否则浅色值会漏到深色模式
expect(variables).toContain('--bg-card: #2a2a2a;')
expect(variables).toContain('$radius-sm: 6px;')
expect(variables).toContain('$radius-md: 8px;')
expect(variables).toContain('$radius-lg: 8px;')
})
it('exports the frozen Arco theme tokens', async () => {
const { arcoTheme } = await import('../../packages/client/src/styles/arco-theme')
expect(arcoTheme.colorPrimary).toBeTruthy()
expect(arcoTheme.colorBgLayout).toBeTruthy()
expect(arcoTheme.colorBgContainer).toBeTruthy()
expect(arcoTheme.borderRadius).toBeTypeOf('number')
expect(arcoTheme.fontFamily).toContain('Inter')
expect(arcoTheme.fontFamilyMono).toContain('JetBrains Mono')
})
it('carries dark mode through the arco-theme attribute on the root element', () => {
// 不 import useTheme:它在模块顶层读 localStorage,node 环境下会抛。
// 断言源码契约即可,真实行为由 useTheme 自己的测试覆盖。
const source = readClientFile('composables/useTheme.ts')
expect(source).toContain("setAttribute('arco-theme'")
expect(source).toMatch(/'dark' : 'light'|'dark'|'light'/)
})
it('keeps mobile inputs at 16px so iOS does not zoom on focus', () => {
const globalStyles = readClientFile('styles/global.scss')
// Arco 的输入框类名,不是 naive 的 .n-input__*
expect(globalStyles).toContain('.arco-input')
expect(globalStyles).not.toMatch(/\.n-input/)
})
})