feat: add Today environment summary
ci / gitleaks (push) Successful in 51s
ci / docker (push) Successful in 4m34s

This commit is contained in:
2026-09-16 12:23:59 +08:00
parent ed6d999ffb
commit 0a4d5f2f05
12 changed files with 1405 additions and 7 deletions
+55
View File
@@ -0,0 +1,55 @@
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:repeat\(2,minmax\(0,auto\)\)/)
expect(css).toMatch(/\.today-environment__status\{[^}]*grid-row:1/)
expect(css).not.toContain('.today-environment__refreshing')
})
it('places one full-width information row inside the existing cream board', () => {
expect(app.match(/class="today-board"/g)).toHaveLength(1)
expect(css).toMatch(/\.today-environment\{[^}]*grid-column:1\/-1/)
expect(css).toMatch(/@container\(min-width:560px\)\{\.today-environment\{[^}]*flex-wrap:nowrap/)
expect(css).toMatch(/@container\(max-width:559px\)\{\.today-environment\{[^}]*grid-template-columns:/)
expect(css).toMatch(/\.today-environment__item\{[^}]*min-width:0/)
expect(css).not.toMatch(/\.today-environment[^}]*overflow-x:auto/)
})
})