Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/lighthouse-smoke-authority-guides.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@app/ratewise': patch
---

Lighthouse CI smoke paths 擴充 3 篇 Authority Guide 內容頁,PR 性能守門同步覆蓋主戰內容頁;GA E2E 補強 hostname gate 回歸監測窗。純測試與 CI 覆蓋改善,無使用者可見行為變更。
12 changes: 10 additions & 2 deletions apps/ratewise/seo-paths.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,17 @@ export const CONTENT_SEO_PATHS = [
* Lighthouse CI smoke audit paths.
*
* Keep this list small enough for PR latency, but canonical and representative:
* homepage app shell, FAQ structured-data page, and About E-E-A-T page.
* homepage app shell, FAQ structured-data page, About E-E-A-T page,
* and the 3 Authority Guide content pages (issue #344).
*/
export const LIGHTHOUSE_CI_SMOKE_PATHS = ['/', '/faq/', '/about/'];
export const LIGHTHOUSE_CI_SMOKE_PATHS = [
'/',
'/faq/',
'/about/',
'/sell-rate-vs-mid-rate/',
'/cash-vs-spot-rate/',
'/card-rate-guide/',
];

/** 法律頁:需預渲染,但維持 noindex,不納入 sitemap。 */
export const LEGAL_SSG_PATHS = ['/privacy/'];
Expand Down
9 changes: 8 additions & 1 deletion apps/ratewise/src/config/__tests__/seo-paths.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,14 @@ describe('SEO Paths Configuration', () => {

it('Lighthouse CI smoke paths 應使用 canonical trailing slash 路徑', () => {
expect(APP_CONFIG.lighthouseSmokePaths).toEqual(LIGHTHOUSE_CI_SMOKE_PATHS);
expect(LIGHTHOUSE_CI_SMOKE_PATHS).toEqual(['/', '/faq/', '/about/']);
expect(LIGHTHOUSE_CI_SMOKE_PATHS).toEqual([
'/',
'/faq/',
'/about/',
'/sell-rate-vs-mid-rate/',
'/cash-vs-spot-rate/',
'/card-rate-guide/',
]);

LIGHTHOUSE_CI_SMOKE_PATHS.forEach((path) => {
expect(SEO_PATHS).toContain(path);
Expand Down
12 changes: 10 additions & 2 deletions apps/ratewise/src/config/seo-paths.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,17 @@ export const CONTENT_SEO_PATHS = [
* Lighthouse CI smoke audit paths.
*
* Keep this list small enough for PR latency, but canonical and representative:
* homepage app shell, FAQ structured-data page, and About E-E-A-T page.
* homepage app shell, FAQ structured-data page, About E-E-A-T page,
* and the 3 Authority Guide content pages (issue #344).
*/
export const LIGHTHOUSE_CI_SMOKE_PATHS = ['/', '/faq/', '/about/'] as const;
export const LIGHTHOUSE_CI_SMOKE_PATHS = [
'/',
'/faq/',
'/about/',
'/sell-rate-vs-mid-rate/',
'/cash-vs-spot-rate/',
'/card-rate-guide/',
] as const;

/** 法律頁:需預渲染,但維持 noindex,不納入 sitemap。 */
export const LEGAL_SSG_PATHS = ['/privacy/'] as const;
Expand Down
24 changes: 24 additions & 0 deletions apps/ratewise/tests/e2e/ga-defer-lcp.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,25 @@ const APP_ROOT = fileURLToPath(new URL('../..', new URL('.', import.meta.url)));
// 期望 config 次數依「建置內嵌 GA ID 且 執行 host 為正式站」決定,hostname 來源與 runtime 同一 SSOT。
const IS_PRODUCTION_HOST = new URL(BASE).hostname === PRODUCTION_HOSTNAME;

// gate 回歸監測窗(PR #629 review):initGA 於 load 後 ANALYTICS_INIT_DELAY_MS 再經
// requestIdleCallback(timeout ANALYTICS_IDLE_TIMEOUT_MS)才執行;取樣需晚於此窗口,
// 否則 hostname gate 回歸時 GA 仍會在 6 秒後初始化而測試已提前通過。
// 預設值鏡射 src/config/performance.ts(該檔依賴 import.meta.env,node 端無法直接 import)。
const parsePositiveInteger = (value: string | undefined, fallback: number): number => {
if (value === undefined || value.trim() === '') return fallback;
const parsed = Number.parseInt(value, 10);
return Number.isFinite(parsed) && parsed > 0 ? parsed : fallback;
};
const ANALYTICS_INIT_DELAY_MS = parsePositiveInteger(
process.env['VITE_ANALYTICS_INIT_DELAY_MS'],
6_000,
);
const ANALYTICS_IDLE_TIMEOUT_MS = parsePositiveInteger(
process.env['VITE_ANALYTICS_IDLE_TIMEOUT_MS'],
2_000,
);
const GATE_REGRESSION_WAIT_MS = ANALYTICS_INIT_DELAY_MS + ANALYTICS_IDLE_TIMEOUT_MS + 1_000;

function detectBuiltGaRuntime(): boolean {
try {
const assetDir = join(APP_ROOT, 'dist', 'assets');
Expand Down Expand Up @@ -188,7 +207,12 @@ test.describe('GA4 延後初始化 + LCP 效能', () => {
null,
{ timeout: 10_000 },
);
} else if (HAS_BUILT_GA_RUNTIME) {
// 建置內嵌 GA ID 但非正式站 host:等待超過完整 analytics 初始化窗口再取樣,
// 確保 hostname gate 回歸(#606)時能觀測到延後出現的 config 而非提前通過。
await page.waitForTimeout(GATE_REGRESSION_WAIT_MS);
} else {
// 建置未內嵌 GA ID:initGA 無 ID 可用,任何時點都不可能送 config,短取樣即可。
await page.waitForTimeout(300);
}

Expand Down
Loading
Loading