Merge remote-tracking branch 'origin/main' into feat/ks4-destinations
PR Checks / Frontend Typecheck + Tests (pull_request) Successful in 1m3s
PR Checks / Backend Smoke (pull_request) Successful in 9s
PR Checks / Build Backend (no push) (pull_request) Successful in 16s
PR Checks / Build Frontend (no push) (pull_request) Successful in 45s
PR Checks / Build Pipeline (no push) (pull_request) Successful in 1m12s
PR Checks / AI Code Review (Claude) (pull_request) Failing after 4m4s
PR Checks / Frontend Typecheck + Tests (pull_request) Successful in 1m3s
PR Checks / Backend Smoke (pull_request) Successful in 9s
PR Checks / Build Backend (no push) (pull_request) Successful in 16s
PR Checks / Build Frontend (no push) (pull_request) Successful in 45s
PR Checks / Build Pipeline (no push) (pull_request) Successful in 1m12s
PR Checks / AI Code Review (Claude) (pull_request) Failing after 4m4s
# Conflicts: # nextjs-app/__tests__/components/darkThemeSafety.test.ts
This commit is contained in:
commit
68a192e430
14 files changed
+421
-21
No files matched your search
@@ -62,3 +62,97 @@ describe('getNavigationSource', () => {
|
||||
expect(getNavigationSource()).toBe('direct');
|
||||
});
|
||||
});
|
||||
|
||||
/*
|
||||
* The defect the existing suite could not see.
|
||||
*
|
||||
* Every test above sets document.referrer, which the browser writes only when
|
||||
* a *document* loads. Every internal navigation in this app is an App Router
|
||||
* soft navigation — history.pushState, no new document — so document.referrer
|
||||
* keeps naming whatever opened the tab for the whole session. Verified on
|
||||
* staging: /schools/brentwood → click a school → URL changes to /school/…
|
||||
* and document.referrer is still "".
|
||||
*
|
||||
* So `from` reported 'direct' for essentially every in-app journey, and the
|
||||
* suite passed because it only ever exercised the full-page-load path.
|
||||
*/
|
||||
function freshAnalytics() {
|
||||
let mod!: typeof import('@/lib/analytics');
|
||||
jest.isolateModules(() => {
|
||||
mod = require('@/lib/analytics');
|
||||
});
|
||||
return mod;
|
||||
}
|
||||
|
||||
function at(path: string) {
|
||||
window.history.pushState({}, '', path);
|
||||
}
|
||||
|
||||
describe('getNavigationSource across a soft navigation', () => {
|
||||
afterEach(() => {
|
||||
referrer('');
|
||||
at('/');
|
||||
});
|
||||
|
||||
it('attributes a school view to the place page the user actually came from', () => {
|
||||
const { recordVisitedPath, getNavigationSource: source } = freshAnalytics();
|
||||
at('/schools/brentwood');
|
||||
recordVisitedPath('/schools/brentwood');
|
||||
|
||||
at('/school/115429-brentwood-school');
|
||||
recordVisitedPath('/school/115429-brentwood-school');
|
||||
|
||||
expect(source()).toBe('place');
|
||||
});
|
||||
|
||||
it('does not depend on whether the new path was recorded first', () => {
|
||||
// The trail is written by a layout-level effect and read by a page-level
|
||||
// one. React orders those by tree position, which is not a contract worth
|
||||
// resting a measurement on, so the answer must be the same either way.
|
||||
const { recordVisitedPath, getNavigationSource: source } = freshAnalytics();
|
||||
recordVisitedPath('/rankings');
|
||||
at('/school/115429-brentwood-school');
|
||||
|
||||
expect(source()).toBe('rankings');
|
||||
});
|
||||
|
||||
it('names the previous page, not the current one, when both are schools', () => {
|
||||
const { recordVisitedPath, getNavigationSource: source } = freshAnalytics();
|
||||
at('/school/100010-brecknock-primary-school');
|
||||
recordVisitedPath('/school/100010-brecknock-primary-school');
|
||||
|
||||
at('/school/115429-brentwood-school');
|
||||
recordVisitedPath('/school/115429-brentwood-school');
|
||||
|
||||
expect(source()).toBe('detail');
|
||||
});
|
||||
|
||||
it('looks past a return visit to the page the user came back from', () => {
|
||||
const { recordVisitedPath, getNavigationSource: source } = freshAnalytics();
|
||||
for (const p of ['/schools/brentwood', '/school/115429-brentwood-school',
|
||||
'/schools/brentwood']) {
|
||||
at(p);
|
||||
recordVisitedPath(p);
|
||||
}
|
||||
expect(source()).toBe('detail');
|
||||
});
|
||||
|
||||
it('falls back to the referrer on a real document load, where it is true', () => {
|
||||
// A fresh module is a fresh document: nothing has been recorded, and
|
||||
// document.referrer is meaningful again.
|
||||
const { getNavigationSource: source } = freshAnalytics();
|
||||
at('/school/115429-brentwood-school');
|
||||
referrer(`${ORIGIN}/schools/barnet`);
|
||||
|
||||
expect(source()).toBe('place');
|
||||
});
|
||||
|
||||
it('still reads an arrival from outside as direct', () => {
|
||||
const { recordVisitedPath, getNavigationSource: source } = freshAnalytics();
|
||||
at('/schools/brentwood');
|
||||
recordVisitedPath('/schools/brentwood');
|
||||
referrer('https://www.google.com/search?q=schools+in+brentwood');
|
||||
|
||||
expect(source()).toBe('direct');
|
||||
});
|
||||
});
|
||||
Reference in new issue
Block a user