72 lines
5.1 KiB
TypeScript
72 lines
5.1 KiB
TypeScript
import { readFileSync } from 'node:fs'
|
|
import { describe, expect, it } from 'vitest'
|
|
|
|
const app = readFileSync('src/App.vue', 'utf8')
|
|
const css = readFileSync('src/style.css', 'utf8')
|
|
|
|
describe('Today environment integration', () => {
|
|
it('loads environment independently alongside Today task work', () => {
|
|
expect(app).toContain("import TodayEnvironmentStrip, { type TodayEnvironment } from './components/TodayEnvironmentStrip.vue'")
|
|
expect(app).toContain('let todayEnvironmentLoadToken = 0')
|
|
expect(app).toContain("api('/today/environment')")
|
|
expect(app).toContain('void loadTodayEnvironment()')
|
|
expect(app).toContain('++todayEnvironmentLoadToken')
|
|
expect(app).toContain("activeView.value !== 'today'")
|
|
expect(app).toContain('<TodayEnvironmentStrip :environment="todayEnvironment" :loading="todayEnvironmentLoading" :failed="todayEnvironmentError" />')
|
|
})
|
|
|
|
it('keeps environment failures local and retains old values during refresh', () => {
|
|
const loader = app.slice(app.indexOf('async function loadTodayEnvironment'), app.indexOf('async function loadOverdueTasks'))
|
|
expect(loader).toContain('todayEnvironmentLoading.value = true')
|
|
expect(loader).not.toContain('todayEnvironment.value = null')
|
|
expect(loader).not.toContain('fail(')
|
|
expect(loader).not.toContain('toast(')
|
|
expect(loader).toContain('todayEnvironmentError.value = true')
|
|
})
|
|
|
|
it('refreshes Today environment on Shanghai date rollover and page restoration', () => {
|
|
expect(app).toContain("import { shanghaiDateKey, useTaskDueClock, watchShanghaiDateRollover } from './lib/task-due-clock'")
|
|
expect(app).toContain('watchShanghaiDateRollover(taskDueNowMs, handleTodayEnvironmentResume)')
|
|
expect(app).toContain('todayEnvironmentDateKey')
|
|
expect(app).toContain("document.addEventListener('visibilitychange', handleTodayEnvironmentResume)")
|
|
expect(app).toContain("window.addEventListener('focus', handleTodayEnvironmentResume)")
|
|
expect(app).toContain("window.addEventListener('pageshow', handleTodayEnvironmentResume)")
|
|
expect(app).toContain("document.removeEventListener('visibilitychange', handleTodayEnvironmentResume)")
|
|
expect(app).toContain("window.removeEventListener('focus', handleTodayEnvironmentResume)")
|
|
expect(app).toContain("window.removeEventListener('pageshow', handleTodayEnvironmentResume)")
|
|
expect(app).toContain('if (document.visibilityState === \'hidden\' || activeView.value !== \'today\') return')
|
|
expect(app).toContain('if (todayEnvironmentDateKey.value !== shanghaiDateKey()) void loadTodayEnvironment()')
|
|
})
|
|
|
|
it('keeps mobile environment copy to two rows including refresh states', () => {
|
|
expect(css).toMatch(/@container\(max-width:559px\)\{\.today-environment\{[^}]*grid-template-rows:40px 66px/)
|
|
expect(css).toMatch(/\.today-environment__status\{[^}]*grid-column:auto;grid-row:auto/)
|
|
expect(css).not.toContain('.today-environment__refreshing')
|
|
})
|
|
|
|
it('renders方案 A as one labelled paper surface with a grouped progress region', () => {
|
|
expect(app.match(/class="today-board"/g)).toHaveLength(1)
|
|
expect(app).toContain('<section v-if="activeView===\'today\'" class="today-board" aria-labelledby="today-board-title">')
|
|
expect(app).toContain('<h2 id="today-board-title" class="sr-only">今日纸笺</h2>')
|
|
expect(app).toContain('<div class="today-board__progress" aria-label="今日任务与习惯进度">')
|
|
expect(app).toMatch(/today-board__progress[\s\S]*today-task-track[\s\S]*today-habit-track[\s\S]*<\/div>/)
|
|
expect(css).toMatch(/\.today-board\{[^}]*grid-template-rows:76px 62px[^}]*gap:1px/)
|
|
expect(css).toMatch(/\.today-board__progress\{[^}]*min-height:62px[^}]*display:grid[^}]*grid-template-columns:repeat\(2,minmax\(0,1fr\)\)/)
|
|
expect(css).toContain('@media(max-width:559px){.today-board{grid-template-rows:106px 70px;padding:0 12px}.today-board__progress{min-height:70px}')
|
|
expect(css).not.toMatch(/\.today-(?:board|track)[^{]*\{[^}]*(?:gradient|backdrop-filter)/)
|
|
})
|
|
|
|
it('keeps the editorial environment layout readable at desktop and narrow widths', () => {
|
|
expect(css).toMatch(/\.today-environment\{[^}]*grid-column:1\/-1/)
|
|
expect(css).toMatch(/@container\(min-width:560px\)\{\.today-environment\{[^}]*grid-template-columns:minmax\(0,1\.45fr\) minmax\(0,1fr\) minmax\(0,1fr\)/)
|
|
expect(css).toMatch(/\.today-environment__calendar strong\{[^}]*font-size:25px/)
|
|
expect(css).toMatch(/@container\(max-width:559px\)\{\.today-environment\{[^}]*grid-template-columns:minmax\(0,1fr\) minmax\(0,1fr\)[^}]*grid-template-rows:40px 66px/)
|
|
expect(css).toMatch(/\.today-environment__calendar\{[^}]*grid-column:1\/-1[^}]*grid-row:1/)
|
|
expect(css).toMatch(/\.today-environment__weather\{[^}]*grid-column:1[^}]*grid-row:2/)
|
|
expect(css).toMatch(/\.today-environment__gold\{[^}]*grid-column:2[^}]*grid-row:2/)
|
|
expect(css).toMatch(/\.today-environment__weather,\.today-environment__gold\{[^}]*flex-direction:column/)
|
|
expect(css).not.toMatch(/\.today-environment[^}]*overflow-x:auto/)
|
|
expect(css).not.toMatch(/@container\(max-width:559px\)[\s\S]*?\.today-environment[^}]*text-overflow:ellipsis/)
|
|
})
|
|
})
|