2026-05-20 21:00:47 +08:00
|
|
|
import assert from 'node:assert/strict'
|
2026-06-02 14:01:51 +08:00
|
|
|
import { readFileSync, statSync } from 'node:fs'
|
2026-05-20 21:00:47 +08:00
|
|
|
import test from 'node:test'
|
|
|
|
|
import { fileURLToPath } from 'node:url'
|
|
|
|
|
|
2026-05-30 15:46:51 +08:00
|
|
|
import { assistantCapabilities } from '../src/data/personalWorkbench.js'
|
|
|
|
|
import {
|
|
|
|
|
buildWorkbenchCapabilityAssistantPayload,
|
|
|
|
|
resolveWorkbenchCapabilityAssistantEntry
|
|
|
|
|
} from '../src/utils/personalWorkbenchAssistantEntry.js'
|
|
|
|
|
|
2026-05-20 21:00:47 +08:00
|
|
|
const workbench = readFileSync(
|
|
|
|
|
fileURLToPath(new URL('../src/components/business/PersonalWorkbench.vue', import.meta.url)),
|
|
|
|
|
'utf8'
|
|
|
|
|
)
|
2026-06-09 08:32:00 +00:00
|
|
|
const workbenchProgressPanel = readFileSync(
|
|
|
|
|
fileURLToPath(new URL('../src/components/business/PersonalWorkbenchProgressPanel.vue', import.meta.url)),
|
|
|
|
|
'utf8'
|
|
|
|
|
)
|
|
|
|
|
const workbenchProgressStyles = readFileSync(
|
|
|
|
|
fileURLToPath(new URL('../src/assets/styles/components/personal-workbench-progress.css', import.meta.url)),
|
|
|
|
|
'utf8'
|
|
|
|
|
)
|
2026-06-02 14:01:51 +08:00
|
|
|
const workbenchStyles = readFileSync(
|
|
|
|
|
fileURLToPath(new URL('../src/assets/styles/components/personal-workbench.css', import.meta.url)),
|
|
|
|
|
'utf8'
|
|
|
|
|
)
|
|
|
|
|
const workbenchGlassStyles = readFileSync(
|
|
|
|
|
fileURLToPath(new URL('../src/assets/styles/components/personal-workbench-glass.css', import.meta.url)),
|
|
|
|
|
'utf8'
|
|
|
|
|
)
|
|
|
|
|
const workbenchCardStyles = `${workbenchStyles}\n${workbenchGlassStyles}`
|
|
|
|
|
const workbenchResponsiveStyles = readFileSync(
|
|
|
|
|
fileURLToPath(new URL('../src/assets/styles/components/personal-workbench-responsive.css', import.meta.url)),
|
|
|
|
|
'utf8'
|
|
|
|
|
)
|
|
|
|
|
const workbenchInsightStyles = readFileSync(
|
|
|
|
|
fileURLToPath(new URL('../src/assets/styles/components/personal-workbench-insights.css', import.meta.url)),
|
|
|
|
|
'utf8'
|
|
|
|
|
)
|
|
|
|
|
const capabilityGlassAsset = fileURLToPath(
|
|
|
|
|
new URL('../src/assets/personal-workbench-card-glass-capability.webp', import.meta.url)
|
|
|
|
|
)
|
|
|
|
|
const panelGlassAsset = fileURLToPath(
|
|
|
|
|
new URL('../src/assets/personal-workbench-card-glass-panel.webp', import.meta.url)
|
|
|
|
|
)
|
2026-05-20 21:00:47 +08:00
|
|
|
|
2026-06-18 22:12:24 +08:00
|
|
|
test('traditional workbench uses compact real reimbursement trend chart instead of assistant composer', () => {
|
2026-05-20 21:00:47 +08:00
|
|
|
assert.doesNotMatch(workbench, /assistant-tag/)
|
|
|
|
|
assert.doesNotMatch(workbench, /AI 报销助手/)
|
2026-06-18 22:12:24 +08:00
|
|
|
assert.doesNotMatch(workbench, /class="panel assistant-hero workbench-trend-hero"/)
|
|
|
|
|
assert.match(workbench, /class="workbench-trend-card"/)
|
|
|
|
|
assert.match(workbench, /报销趋势/)
|
|
|
|
|
assert.match(workbench, /import TrendChart from '\.\.\/charts\/TrendChart\.vue'/)
|
|
|
|
|
assert.match(workbench, /<TrendChart[\s\S]*mode="compareAmount"/)
|
|
|
|
|
assert.match(workbench, /:labels="reimbursementTrendLabels"/)
|
|
|
|
|
assert.match(workbench, /:claim-amount="reimbursementTrendAmounts"/)
|
|
|
|
|
assert.match(workbench, /:comparison-amount="reimbursementTrendPreviousAmounts"/)
|
|
|
|
|
assert.match(workbench, /compact/)
|
|
|
|
|
assert.match(workbench, /与分析看板同源/)
|
|
|
|
|
assert.doesNotMatch(workbench, /class="trend-chart-svg"/)
|
|
|
|
|
assert.doesNotMatch(workbench, /currentTrendPath/)
|
|
|
|
|
assert.doesNotMatch(workbench, /comparisonTrendPath/)
|
|
|
|
|
assert.doesNotMatch(workbench, /reimbursementTrendPoints/)
|
|
|
|
|
assert.doesNotMatch(workbench, /FALLBACK_REIMBURSEMENT_TREND_ROWS/)
|
|
|
|
|
assert.doesNotMatch(workbench, /assistant-composer/)
|
|
|
|
|
assert.doesNotMatch(workbench, /textarea/)
|
|
|
|
|
assert.doesNotMatch(workbench, /quick-prompts/)
|
|
|
|
|
assert.doesNotMatch(workbench, /useWorkbenchComposerDate/)
|
2026-05-30 15:46:51 +08:00
|
|
|
assert.match(workbench, /const displayUserName = computed/)
|
2026-05-20 21:00:47 +08:00
|
|
|
assert.match(workbench, /user\.name/)
|
2026-06-18 22:12:24 +08:00
|
|
|
assert.match(workbenchStyles, /--hero-title-size:\s*34px;/)
|
|
|
|
|
assert.match(workbenchStyles, /--trend-card-min-height:\s*260px;/)
|
|
|
|
|
assert.match(workbenchStyles, /\.workbench\s*\{[\s\S]*display:\s*flex;[\s\S]*flex-direction:\s*column;/)
|
|
|
|
|
assert.match(workbenchStyles, /\.workbench-trend-hero\s*\{[\s\S]*height:\s*var\(--trend-card-min-height\);[\s\S]*min-height:\s*0;/)
|
|
|
|
|
assert.match(workbenchStyles, /\.workbench-trend-card\s*\{[\s\S]*grid-template-columns:\s*minmax\(200px,\s*0\.28fr\) minmax\(0,\s*1fr\);/)
|
|
|
|
|
assert.match(workbenchStyles, /\.workbench-trend-card\s*\{[\s\S]*height:\s*100%;[\s\S]*min-height:\s*0;/)
|
|
|
|
|
assert.match(workbenchStyles, /\.workbench-trend-card\s*\{[\s\S]*background:\s*transparent;[\s\S]*box-shadow:\s*none;/)
|
|
|
|
|
assert.match(workbenchStyles, /\.trend-total\s*\{[\s\S]*font-size:\s*clamp\(38px,\s*3\.3vw,\s*54px\);/)
|
|
|
|
|
assert.match(workbenchStyles, /\.capability-grid\s*\{[\s\S]*flex:\s*0 0 var\(--capability-row-height\);/)
|
|
|
|
|
assert.match(workbenchStyles, /\.workbench-content-grid\s*\{[\s\S]*flex:\s*1 1 auto;/)
|
|
|
|
|
assert.match(workbenchStyles, /\.trend-chart-panel\s*\{[\s\S]*min-height:\s*0;/)
|
2026-05-20 21:00:47 +08:00
|
|
|
})
|
2026-05-30 15:46:51 +08:00
|
|
|
|
|
|
|
|
test('workbench capability cards open assistant without injecting canned prompts', () => {
|
|
|
|
|
assert.match(workbench, /@click="openCapabilityAssistant\(item\)"/)
|
|
|
|
|
assert.doesNotMatch(workbench, /openPromptAssistant\(item\.prompt\)/)
|
|
|
|
|
|
|
|
|
|
for (const item of assistantCapabilities) {
|
|
|
|
|
const payload = buildWorkbenchCapabilityAssistantPayload(item, {
|
|
|
|
|
prompt: '',
|
|
|
|
|
source: 'workbench',
|
|
|
|
|
files: []
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
assert.equal(payload.prompt, '')
|
|
|
|
|
assert.equal(payload.conversation, null)
|
|
|
|
|
assert.notEqual(payload.prompt, item.prompt)
|
|
|
|
|
assert.ok(resolveWorkbenchCapabilityAssistantEntry(item).sessionType)
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
test('workbench capability cards keep user-entered context only', () => {
|
|
|
|
|
const [expenseApplication] = assistantCapabilities
|
|
|
|
|
const files = [{ name: 'invoice.pdf' }]
|
|
|
|
|
const payload = buildWorkbenchCapabilityAssistantPayload(expenseApplication, {
|
|
|
|
|
prompt: '我需要申请下周出差费用',
|
|
|
|
|
source: 'workbench',
|
|
|
|
|
files
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
assert.equal(payload.prompt, '我需要申请下周出差费用')
|
|
|
|
|
assert.equal(payload.source, 'application')
|
|
|
|
|
assert.equal(payload.sessionType, 'application')
|
|
|
|
|
assert.equal(payload.files, files)
|
|
|
|
|
})
|
|
|
|
|
|
2026-06-18 22:12:24 +08:00
|
|
|
test('workbench trend panel is a single compact surface without background art overlay', () => {
|
|
|
|
|
assert.match(workbench, /class="workbench-trend-card"/)
|
|
|
|
|
assert.doesNotMatch(workbench, /hero-3d-banner\.png/)
|
2026-06-09 08:32:00 +00:00
|
|
|
assert.doesNotMatch(workbench, /personal-workbench-hero-bg-theme-base\.(webp|png)/)
|
2026-06-18 22:12:24 +08:00
|
|
|
assert.doesNotMatch(workbenchStyles, /url\("\.\.\/\.\.\/images\/workbench-hero-right-bg\.png"\)/)
|
|
|
|
|
assert.doesNotMatch(workbenchStyles, /\.assistant-hero::after/)
|
|
|
|
|
assert.doesNotMatch(workbenchResponsiveStyles, /--assistant-bg-position/)
|
|
|
|
|
assert.doesNotMatch(workbenchResponsiveStyles, /\.assistant-hero/)
|
2026-06-02 14:01:51 +08:00
|
|
|
assert.doesNotMatch(workbenchResponsiveStyles, /homepage_backgraound/)
|
2026-06-18 22:12:24 +08:00
|
|
|
})
|
|
|
|
|
|
|
|
|
|
test('workbench hero does not own the global AI mode switch', () => {
|
|
|
|
|
assert.doesNotMatch(workbench, /workbench-mode-switch/)
|
|
|
|
|
assert.doesNotMatch(workbench, /ai-mode-toggle/)
|
|
|
|
|
assert.doesNotMatch(workbenchStyles, /workbench-mode-switch/)
|
|
|
|
|
assert.doesNotMatch(workbenchResponsiveStyles, /workbench-mode-switch/)
|
2026-06-02 14:01:51 +08:00
|
|
|
})
|
|
|
|
|
|
|
|
|
|
test('workbench cards use layered glass material instead of texture-led cards', () => {
|
|
|
|
|
assert.match(workbench, /personal-workbench-glass\.css/)
|
|
|
|
|
assert.match(workbenchGlassStyles, /--workbench-capability-bg-image:\s*url\("\.\.\/\.\.\/personal-workbench-card-glass-capability\.webp"\)/)
|
|
|
|
|
assert.match(workbenchGlassStyles, /--workbench-panel-bg-image:\s*url\("\.\.\/\.\.\/personal-workbench-card-glass-panel\.webp"\)/)
|
|
|
|
|
assert.match(workbenchGlassStyles, /--workbench-glass-base:/)
|
|
|
|
|
assert.match(workbenchGlassStyles, /--workbench-glass-highlight:/)
|
|
|
|
|
assert.match(workbenchGlassStyles, /--workbench-glass-noise-opacity:\s*0\.012;/)
|
|
|
|
|
assert.match(workbenchGlassStyles, /--workbench-glass-blur:\s*blur\(18px\) saturate\(1\.28\);/)
|
2026-06-09 08:32:00 +00:00
|
|
|
assert.match(workbenchGlassStyles, /\.capability-card\s*\{[\s\S]*background:\s*rgba\(255,\s*255,\s*255,\s*0\.96\);[\s\S]*backdrop-filter:\s*blur\(12px\) saturate\(150%\)/)
|
|
|
|
|
assert.match(workbenchGlassStyles, /\.workbench-card\s*\{[\s\S]*background:\s*rgba\(255,\s*255,\s*255,\s*0\.96\);[\s\S]*backdrop-filter:\s*blur\(12px\) saturate\(150%\)/)
|
2026-06-02 14:01:51 +08:00
|
|
|
assert.match(workbenchGlassStyles, /\.capability-card::before,[\s\S]*\.capability-card::after/)
|
|
|
|
|
assert.match(workbenchGlassStyles, /\.capability-card::after\s*\{[\s\S]*var\(--workbench-glass-highlight\)/)
|
2026-06-09 08:32:00 +00:00
|
|
|
assert.match(workbenchGlassStyles, /\.workbench-card::before,[\s\S]*\.workbench-card::after\s*\{[\s\S]*display:\s*none !important;/)
|
2026-06-02 14:01:51 +08:00
|
|
|
assert.doesNotMatch(workbenchGlassStyles, /\.capability-card::after\s*\{[^}]*radial-gradient/)
|
|
|
|
|
assert.doesNotMatch(workbenchGlassStyles, /\.workbench-card::after\s*\{[^}]*radial-gradient/)
|
|
|
|
|
assert.match(workbenchGlassStyles, /\.workbench-card > \*\s*\{[\s\S]*z-index:\s*1;/)
|
|
|
|
|
assert.match(workbenchGlassStyles, /--workbench-capability-tile-size:\s*384px 384px;/)
|
|
|
|
|
assert.match(workbenchGlassStyles, /--workbench-panel-tile-size:\s*512px 512px;/)
|
|
|
|
|
assert.doesNotMatch(workbenchCardStyles, /var\(--workbench-capability-bg-image\)[^;]*cover no-repeat/)
|
|
|
|
|
assert.doesNotMatch(workbenchCardStyles, /var\(--workbench-panel-bg-image\)[^;]*cover no-repeat/)
|
|
|
|
|
assert.match(workbenchGlassStyles, /--workbench-glass-theme-tint:[\s\S]*--theme-primary-rgb/)
|
|
|
|
|
assert.doesNotMatch(workbenchCardStyles, /background-blend-mode:\s*normal,\s*color,\s*normal;/)
|
|
|
|
|
assert.match(workbenchResponsiveStyles, /--workbench-glass-noise-opacity:\s*0\.008;/)
|
|
|
|
|
assert.match(workbenchResponsiveStyles, /--workbench-glass-blur:\s*blur\(14px\) saturate\(1\.2\);/)
|
2026-06-03 09:25:23 +08:00
|
|
|
assert.match(workbenchGlassStyles, /\.progress-row\s*\{[\s\S]*background:\s*transparent;[\s\S]*box-shadow:\s*inset 0 1px 0 rgba\(var\(--theme-primary-rgb/)
|
|
|
|
|
assert.doesNotMatch(workbench, /<h2>我的待办<\/h2>/)
|
|
|
|
|
assert.doesNotMatch(workbench, /<h2>关键动作<\/h2>/)
|
|
|
|
|
assert.doesNotMatch(workbenchGlassStyles, /\.todo-row/)
|
2026-06-02 14:01:51 +08:00
|
|
|
assert.doesNotMatch(workbenchGlassStyles, /\.progress-row\s*\{[\s\S]*border-top:\s*1px solid var\(--workbench-line-soft\)/)
|
|
|
|
|
assert.match(workbenchInsightStyles, /\.insight-metric-row,[\s\S]*\.insight-profile-card\s*\{[\s\S]*backdrop-filter:\s*blur\(10px\) saturate\(1\.16\)/)
|
|
|
|
|
assert.doesNotMatch(workbenchInsightStyles, /background:\s*#ffffff;/)
|
|
|
|
|
assert.ok(statSync(capabilityGlassAsset).size > 1024)
|
|
|
|
|
assert.ok(statSync(panelGlassAsset).size > 1024)
|
|
|
|
|
assert.ok(statSync(capabilityGlassAsset).size < 24 * 1024)
|
|
|
|
|
assert.ok(statSync(panelGlassAsset).size < 24 * 1024)
|
|
|
|
|
})
|
|
|
|
|
|
2026-06-18 22:12:24 +08:00
|
|
|
test('traditional workbench no longer keeps composer pending state', () => {
|
|
|
|
|
assert.doesNotMatch(workbench, /class="assistant-intent-status"/)
|
|
|
|
|
assert.doesNotMatch(workbench, /正在识别意图,准备进入对应助手/)
|
|
|
|
|
assert.doesNotMatch(workbench, /startPendingAction\('intent'\)/)
|
|
|
|
|
assert.doesNotMatch(workbench, /isComposerPending/)
|
|
|
|
|
assert.doesNotMatch(workbench, /assistantDraft/)
|
|
|
|
|
assert.doesNotMatch(workbench, /fetchLatestConversation/)
|
|
|
|
|
assert.doesNotMatch(workbench, /clearUserConversations/)
|
|
|
|
|
assert.match(workbench, /function openCapabilityAssistant\(item\)/)
|
|
|
|
|
assert.match(workbench, /buildWorkbenchCapabilityAssistantPayload\(item,\s*buildAssistantPayload\(\)\)/)
|
2026-05-30 15:46:51 +08:00
|
|
|
})
|
2026-06-03 12:28:21 +08:00
|
|
|
|
2026-06-09 08:32:00 +00:00
|
|
|
test('workbench document progress has range filter, document types and empty state', () => {
|
|
|
|
|
assert.match(workbench, /import PersonalWorkbenchProgressPanel from '\.\/PersonalWorkbenchProgressPanel\.vue'/)
|
|
|
|
|
assert.match(workbench, /<PersonalWorkbenchProgressPanel[\s\S]*:progress-items="workbenchSummary\.progressItems \|\| \[\]"[\s\S]*@open-target="openWorkbenchTarget"/)
|
|
|
|
|
assert.match(workbenchProgressPanel, /<h2>单据进度<\/h2>/)
|
|
|
|
|
assert.match(workbenchProgressPanel, /personal-workbench-progress\.css/)
|
|
|
|
|
assert.match(workbenchProgressPanel, /EnterpriseSelect/)
|
|
|
|
|
assert.match(workbenchProgressPanel, /近10日/)
|
|
|
|
|
assert.match(workbenchProgressPanel, /近30日/)
|
|
|
|
|
assert.match(workbenchProgressPanel, /近3个月/)
|
|
|
|
|
assert.match(workbenchProgressPanel, /class="progress-range-control"[\s\S]*@click\.stop[\s\S]*@mousedown\.stop[\s\S]*@pointerdown\.stop/)
|
|
|
|
|
assert.match(workbenchProgressPanel, /:teleported="true"/)
|
|
|
|
|
assert.match(workbenchProgressPanel, /@click="handleProgressItemClick\(\$event, item\)"/)
|
|
|
|
|
assert.match(workbenchProgressPanel, /function handleProgressItemClick\(event, item\)/)
|
|
|
|
|
assert.match(workbenchProgressPanel, /return true/)
|
|
|
|
|
assert.match(workbenchProgressPanel, /class="progress-time"/)
|
|
|
|
|
assert.match(workbenchProgressPanel, /class="progress-applicant"/)
|
|
|
|
|
assert.match(workbenchProgressPanel, /class="progress-table-shell"/)
|
|
|
|
|
assert.match(workbenchProgressPanel, />\u66f4\u65b0\u65f6\u95f4<\/span>/)
|
|
|
|
|
assert.doesNotMatch(workbenchProgressPanel, /\u5355\u636e\u52a8\u6001/)
|
|
|
|
|
assert.doesNotMatch(workbenchProgressPanel, /time-capsule/)
|
|
|
|
|
assert.doesNotMatch(workbenchProgressPanel, /<small>\u7533\u8bf7\u4eba<\/small>/)
|
|
|
|
|
assert.match(workbenchProgressPanel, /\{\{ item\.applicantLabel \|\| '待补充' \}\}/)
|
|
|
|
|
assert.match(workbenchProgressPanel, /class="progress-type"/)
|
|
|
|
|
assert.match(workbenchProgressPanel, /\{\{ item\.documentTypeLabel \}\} · \{\{ item\.expenseTypeLabel \|\| '其他费用' \}\}/)
|
|
|
|
|
assert.match(workbenchProgressPanel, /当前范围暂无单据/)
|
|
|
|
|
assert.match(workbenchProgressPanel, /没有申请单或报销单进度/)
|
2026-06-03 15:14:44 +08:00
|
|
|
assert.match(workbench, /source:\s*'workbench'/)
|
|
|
|
|
assert.match(workbench, /returnTo:\s*'workbench'/)
|
2026-06-09 08:32:00 +00:00
|
|
|
assert.doesNotMatch(workbenchProgressPanel, /has-long-duration-divider/)
|
|
|
|
|
assert.doesNotMatch(workbenchProgressPanel, /LONG_DURATION_DAYS/)
|
|
|
|
|
assert.doesNotMatch(workbenchProgressPanel, /10日以上/)
|
|
|
|
|
assert.doesNotMatch(workbenchStyles, /10日以上/)
|
|
|
|
|
assert.doesNotMatch(workbenchStyles, /has-long-duration-divider/)
|
|
|
|
|
assert.doesNotMatch(workbench, />费用进度</)
|
|
|
|
|
assert.match(workbenchProgressPanel, /<time :datetime="item\.updatedAt \|\| ''">\{\{ item\.displayTime \}\}<\/time>/)
|
|
|
|
|
assert.match(workbenchProgressPanel, /function formatProgressTime\(value\)/)
|
|
|
|
|
assert.match(workbenchStyles, /\.progress-row\s*\{[\s\S]*grid-template-columns:\s*minmax\(118px,\s*0\.58fr\)[\s\S]*minmax\(84px,\s*0\.42fr\)/)
|
2026-06-03 15:21:38 +08:00
|
|
|
assert.match(workbenchStyles, /\.progress-type\s*\{[\s\S]*justify-self:\s*stretch;[\s\S]*justify-items:\s*center;[\s\S]*text-align:\s*center;/)
|
|
|
|
|
assert.match(workbenchStyles, /\.progress-type strong\s*\{[\s\S]*justify-content:\s*center;/)
|
2026-06-03 15:14:44 +08:00
|
|
|
assert.match(workbenchStyles, /\.progress-type strong\s*\{[\s\S]*var\(--workbench-primary-active\)/)
|
2026-06-09 08:32:00 +00:00
|
|
|
assert.match(workbenchStyles, /\.progress-list\s*\{[\s\S]*overflow-y:\s*auto;/)
|
|
|
|
|
assert.match(workbenchStyles, /\.progress-empty-state\s*\{[\s\S]*border:\s*1px dashed/)
|
|
|
|
|
assert.match(workbenchStyles, /\.progress-range-select\s*\{[\s\S]*width:\s*124px;/)
|
|
|
|
|
assert.match(workbenchProgressStyles, /\.progress-panel\s*\{[\s\S]*grid-template-rows:\s*auto minmax\(0,\s*1fr\);/)
|
|
|
|
|
assert.match(workbenchProgressStyles, /--progress-table-columns:[\s\S]*minmax\(96px,\s*0\.44fr\);/)
|
|
|
|
|
assert.match(workbenchProgressStyles, /\.progress-table-shell\s*\{[\s\S]*grid-template-rows:\s*36px minmax\(0,\s*1fr\);[\s\S]*overflow:\s*hidden;/)
|
|
|
|
|
assert.match(workbenchProgressStyles, /\.progress-table-header\s*\{[\s\S]*grid-template-columns:\s*var\(--progress-table-columns\);/)
|
|
|
|
|
assert.match(workbenchProgressStyles, /\.progress-table-header\s*\{[\s\S]*height:\s*36px;[\s\S]*max-height:\s*36px;[\s\S]*overflow:\s*hidden;/)
|
|
|
|
|
assert.match(workbenchProgressStyles, /\.header-cell\s*\{[\s\S]*justify-content:\s*center;[\s\S]*white-space:\s*nowrap;/)
|
|
|
|
|
assert.match(workbenchProgressStyles, /\.progress-list\s*\{[\s\S]*grid-auto-rows:\s*minmax\(76px,\s*auto\)/)
|
|
|
|
|
assert.match(workbenchProgressStyles, /\.progress-row\s*\{[\s\S]*grid-template-columns:\s*var\(--progress-table-columns\);[\s\S]*gap:\s*8px;[\s\S]*min-height:\s*76px;[\s\S]*text-align:\s*center;/)
|
|
|
|
|
assert.match(workbenchProgressStyles, /\.progress-time-wrapper\s*\{[\s\S]*justify-content:\s*center;/)
|
|
|
|
|
assert.match(workbenchProgressStyles, /\.progress-identity\s*\{[\s\S]*align-items:\s*center;[\s\S]*text-align:\s*center;/)
|
|
|
|
|
assert.match(workbenchProgressStyles, /\.progress-applicant\s*\{[\s\S]*justify-items:\s*center;/)
|
|
|
|
|
assert.match(workbenchProgressStyles, /\.progress-result\s*\{[\s\S]*justify-self:\s*stretch;[\s\S]*justify-content:\s*center;[\s\S]*justify-items:\s*center;/)
|
|
|
|
|
assert.match(workbenchProgressStyles, /\.progress-result strong\s*\{[\s\S]*width:\s*100%;[\s\S]*text-align:\s*center;/)
|
|
|
|
|
assert.match(workbenchProgressStyles, /\.progress-steps\s*\{[\s\S]*justify-items:\s*stretch;/)
|
|
|
|
|
assert.match(workbenchProgressStyles, /\.progress-step\s*\{[\s\S]*justify-items:\s*center;/)
|
|
|
|
|
assert.match(workbenchProgressStyles, /\.progress-range-control\s*\{[\s\S]*z-index:\s*6;/)
|
|
|
|
|
assert.match(workbenchProgressStyles, /\.progress-range-select:deep\(\.el-select__wrapper\)/)
|
|
|
|
|
assert.match(workbenchProgressStyles, /\.progress-empty-state\s*\{[\s\S]*border:\s*1px dashed/)
|
2026-06-03 12:28:21 +08:00
|
|
|
assert.match(workbenchStyles, /\.progress-time\s*\{[\s\S]*color:\s*var\(--workbench-muted\);/)
|
2026-06-03 15:14:44 +08:00
|
|
|
assert.match(workbenchResponsiveStyles, /grid-template-areas:[\s\S]*"time identity result"[\s\S]*"type type type"[\s\S]*"steps steps steps"/)
|
|
|
|
|
assert.match(workbenchResponsiveStyles, /\.progress-type\s*\{[\s\S]*grid-area:\s*type;/)
|
2026-06-03 12:28:21 +08:00
|
|
|
})
|
2026-06-03 14:59:55 +08:00
|
|
|
|
|
|
|
|
test('workbench expense stats detail opens a local modal instead of the assistant', () => {
|
|
|
|
|
assert.match(workbench, /import ExpenseStatsDetailModal from '\.\/ExpenseStatsDetailModal\.vue'/)
|
|
|
|
|
assert.match(workbench, /<ExpenseStatsDetailModal/)
|
|
|
|
|
assert.match(workbench, /const expenseStatsModalOpen = ref\(false\)/)
|
|
|
|
|
assert.match(workbench, /const expenseStatsDetail = computed\(\(\) => props\.workbenchSummary\.expenseStatsDetail \|\| \{\}\)/)
|
|
|
|
|
assert.match(workbench, /@click="openExpenseStatsModal"/)
|
|
|
|
|
assert.match(workbench, /:aria-expanded="expenseStatsModalOpen"/)
|
|
|
|
|
assert.match(workbench, /function openExpenseStatsModal\(\)/)
|
|
|
|
|
assert.match(workbench, /function closeExpenseStatsModal\(\)/)
|
|
|
|
|
assert.doesNotMatch(workbench, /查看我的费用统计详情/)
|
|
|
|
|
})
|