fix: match Today paper concept
ci / gitleaks (push) Successful in 9s
ci / docker (push) Successful in 7m11s

This commit is contained in:
2026-09-17 16:05:19 +08:00
parent ea2dc12ec1
commit 40162aaa54
6 changed files with 106 additions and 50 deletions
@@ -28,15 +28,13 @@ describe('TodayEnvironmentStrip', () => {
it('renders date, fixed-location weather, and delayed SGE Au99.99 quote', async () => {
const host = await mountStrip({ environment })
expect(host.querySelector('.today-environment')?.getAttribute('aria-label')).toBe('今日环境信息')
expect(host.textContent).toContain('2026年9月16日')
expect(host.textContent).toContain('星期三')
expect(host.textContent).toContain('9月16日 周三')
expect(host.textContent).toContain('农历八月初六')
expect(host.textContent).toContain('宁波海曙')
expect(host.textContent).toContain('多云')
expect(host.textContent).toContain('27°C')
expect(host.textContent).toContain('Au99.99 ¥782.35/g')
expect(host.textContent).toContain('上金所延时')
expect(host.textContent).toContain('2026-09-15')
expect(host.textContent).toContain('27° 多云')
expect(host.textContent).toContain('Au99.99 延时')
expect(host.textContent).toContain('¥782.35/g')
expect(host.textContent).toContain('市场日期 09-15')
expect(host.querySelector('.today-environment__gold')?.classList.contains('is-stale')).toBe(true)
})
@@ -46,10 +44,12 @@ describe('TodayEnvironmentStrip', () => {
weather: { temperature_c: 28.4, weather_code: 2, observed_at: '2026-09-16T14:15:00+08:00', source: 'Open-Meteo', stale: false },
gold: { contract: 'Au99.99', latest_price: '935.990', market_date: '2026-09-16', delayed: true, source: '上海黄金交易所', stale: true },
} as TodayEnvironment })
expect(host.textContent).toContain('2026-09-16 星期三')
expect(host.textContent).toMatch(/宁波海曙 · 多云\s+28\.4°C/)
expect(host.textContent).toContain('Au99.99 ¥935.99/g')
expect(host.textContent).toContain('上金所延时 · 2026-09-16')
expect(host.textContent).toContain('9月16日 周三')
expect(host.textContent).toContain('宁波海曙')
expect(host.textContent).toMatch(/28\.4°\s+多云/)
expect(host.textContent).toContain('Au99.99 延时')
expect(host.textContent).toContain('¥935.99/g')
expect(host.textContent).toContain('市场日期 09-16')
expect(host.querySelector('.today-environment__gold')?.classList.contains('is-stale')).toBe(true)
})
@@ -70,14 +70,16 @@ describe('TodayEnvironmentStrip', () => {
it('keeps existing values visible while a refresh is in progress', async () => {
const host = await mountStrip({ environment, loading: true })
expect(host.textContent).toContain('27°C')
expect(host.textContent).toContain('Open-Meteo · 09:00')
expect(host.textContent).toContain('27° 多云')
expect(host.textContent).toContain('Open-Meteo 09:00')
expect(host.textContent).not.toContain('Open-Meteo · 09:00')
expect(host.textContent).toContain('¥782.35/g')
expect(host.querySelector('.today-environment')?.getAttribute('aria-busy')).toBe('true')
const status = host.querySelector('.today-environment__status')
expect(status?.getAttribute('role')).toBe('status')
expect(status?.getAttribute('aria-live')).toBe('polite')
expect(status?.textContent).toContain('更新中')
expect(status?.classList.contains('sr-only')).toBe(true)
})
it('announces refresh failure through the same live status slot', async () => {
@@ -91,12 +93,15 @@ describe('TodayEnvironmentStrip', () => {
it('renders compact mobile date copy while preserving desktop and gold date semantics', async () => {
const host = await mountStrip({ environment })
expect(host.querySelector('.today-environment__calendar-main--desktop')?.textContent).toBe('2026年9月16日 星期三')
expect(host.querySelector('.today-environment__calendar-main--desktop')?.textContent).toBe('9月16日 三')
expect(host.querySelector('.today-environment__calendar-main--mobile')?.textContent).toBe('9月16日 周三')
const goldDate = host.querySelector('.today-environment__gold-date--mobile')
expect(goldDate?.textContent).toBe('09-15')
expect(goldDate?.getAttribute('title')).toBe('市场日期 2026-09-15')
expect(goldDate?.getAttribute('aria-label')).toBe('市场日期 2026-09-15')
const desktopGoldDate = host.querySelector('.today-environment__gold-date--desktop')
expect(desktopGoldDate?.textContent).toBe('09-15')
expect(desktopGoldDate?.getAttribute('aria-label')).toBe('市场日期 2026-09-15')
})
it('shows edit-line state only when attention is required', async () => {
@@ -124,28 +129,28 @@ describe('TodayEnvironmentStrip', () => {
expect(host.querySelectorAll('.today-environment__gold > .today-environment__skeleton')).toHaveLength(2)
})
it('uses the approved cream edit-line typography and separators', () => {
it('uses the selected landing-page typography and full-height separators', () => {
const css = readFileSync(resolve(process.cwd(), 'src/style.css'), 'utf8')
expect(css).toContain('.today-environment{grid-column:1/-1;position:relative;min-width:0;min-height:76px;')
expect(css).toContain('color:#302a24;font-size:25px;line-height:1;font-weight:680')
expect(css).toContain('color:#655b50;font-size:12px;font-weight:450')
expect(css).toContain('color:#8b8275;font-size:11px;font-weight:400')
expect(css).toContain('.today-environment:after{content:"";position:absolute;left:10px;right:10px;bottom:0;height:1px;background:#e4d5c0}')
expect(css).toContain('.today-environment.has-attention:before{content:"";position:absolute;left:0;top:50%;width:2px;height:14px;background:#f15a29')
expect(css).not.toContain('border-left:1px solid var(--border-cream)')
expect(css).toContain('.today-environment{grid-column:1/-1;position:relative;min-width:0;display:grid;grid-template-columns:minmax(0,1.25fr) minmax(0,1fr) minmax(0,1fr);align-items:stretch')
expect(css).toContain('color:#302a24;font-size:23px;line-height:1.15;font-weight:760')
expect(css).toContain('margin-top:6px;color:#655b50;font-size:12px;font-weight:450')
expect(css).toContain('.today-environment__eyeline{color:#8b8275;font-size:11px')
expect(css).toContain('.today-environment__item+.today-environment__item{border-left:1px solid var(--line)}')
expect(css).not.toMatch(/\.today-environment[^}]*gradient|\.today-environment[^}]*box-shadow|\.today-environment[^}]*backdrop-filter/)
})
it('keeps mobile content to exactly two parent rows with stacked source columns', () => {
it('matches the selected two-row mobile composition', () => {
const css = readFileSync(resolve(process.cwd(), 'src/style.css'), 'utf8')
expect(css).toContain('@container(max-width:559px){.today-environment{min-height:106px;display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr);grid-template-rows:40px 66px;column-gap:14px;')
expect(css).toContain('.today-environment__calendar{grid-column:1/-1;grid-row:1;display:flex;flex-direction:row;')
expect(css).toContain('.today-environment__weather,.today-environment__gold{display:flex;flex-direction:column;align-items:flex-start;justify-content:center;gap:4px;overflow:visible;white-space:normal}')
expect(css).toContain('.today-environment__gold{grid-column:2;grid-row:2;padding-left:14px}')
expect(css).toContain('.today-environment__gold:before{content:"";position:absolute;left:0;top:8px;width:5px;height:1px;background:#cbbda9}')
expect(css).toContain('.today-track-head{display:flex;align-items:baseline;justify-content:space-between;gap:12px;color:#776c60;font-size:12px}')
expect(css).toContain('.today-track-head strong{font-size:14px;line-height:1.2;color:#403a32}')
expect(css).toContain('@media(max-width:720px){.today-environment{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr);grid-template-rows:auto auto}')
expect(css).toContain('.today-environment__calendar{grid-column:1/-1;grid-row:1;display:flex;flex-direction:column;align-items:flex-start')
expect(css).toContain('.today-environment__weather{grid-column:1;grid-row:2;border-top:1px solid var(--line);border-left:0!important}')
expect(css).toContain('.today-environment__gold{grid-column:2;grid-row:2;border-top:1px solid var(--line)}')
expect(css).toContain('.today-environment__weather,.today-environment__gold{padding:13px 10px;display:flex;flex-direction:column;')
expect(css).toContain('.today-environment__calendar-main--desktop,.today-environment__gold-date--desktop{display:none}')
expect(css).toContain('.today-environment__calendar-main--mobile,.today-environment__gold-date--mobile{display:inline}')
const mobileBlock = css.slice(css.indexOf('@container(max-width:559px){.today-environment'), css.indexOf('/* Solid cream material system'))
const mobileBlock = css.slice(css.indexOf('@media(max-width:720px){.today-environment'), css.indexOf('/* Solid cream material system'))
expect(mobileBlock).not.toContain('text-overflow:ellipsis')
})
})