one
Version:
One is a new React Framework that makes Vite serve both native and web.
145 lines • 3.86 kB
JavaScript
var import_vitest = require("vitest");
var import_createMemoryHistory = require("./createMemoryHistory.cjs");
let dom;
function setupDomMock(initialPath = "/") {
const entries = [{
state: null,
path: initialPath
}];
let cursor = 0;
const listeners = [];
const mockHistory = {
get state() {
return entries[cursor].state;
},
pushState(state, _title, url) {
entries.length = cursor + 1;
entries.push({
state,
path: url
});
cursor = entries.length - 1;
},
replaceState(state, _title, url) {
entries[cursor] = {
state,
path: url
};
},
go() {},
get length() {
return entries.length;
}
};
const mockLocation = {
get pathname() {
const p = entries[cursor].path;
return p.split("?")[0].split("#")[0];
},
get search() {
const p = entries[cursor].path;
const q = p.indexOf("?");
if (q === -1) return "";
return p.slice(q).split("#")[0];
},
get hash() {
const p = entries[cursor].path;
const h = p.indexOf("#");
return h === -1 ? "" : p.slice(h);
}
};
const mockDocument = {
title: ""
};
const mockWindow = {
history: mockHistory,
location: mockLocation,
document: mockDocument,
addEventListener(type, handler) {
if (type === "popstate") listeners.push(handler);
},
removeEventListener(type, handler) {
if (type === "popstate") {
const i = listeners.indexOf(handler);
if (i > -1) listeners.splice(i, 1);
}
}
};
globalThis.window = mockWindow;
globalThis.location = mockLocation;
globalThis.document = mockDocument;
return {
entries,
getCursor: () => cursor,
firePopState: delta => {
const next = cursor + delta;
if (next < 0 || next >= entries.length) return;
cursor = next;
for (const l of listeners.slice()) l({
state: entries[cursor].state
});
}
};
}
function teardownDomMock() {
delete globalThis.window;
delete globalThis.location;
delete globalThis.document;
}
const stackState = (routeNames, index) => ({
key: "stack-root",
index,
routeNames,
routes: routeNames.map(name => ({
key: `${name}-k`,
name
})),
stale: false,
type: "stack"
});
(0, import_vitest.beforeEach)(() => {
dom = setupDomMock();
});
(0, import_vitest.afterEach)(() => {
teardownDomMock();
});
(0, import_vitest.test)("browser back then forward restores the pushed stack (regression for external-popstate index drift)", () => {
const history = (0, import_createMemoryHistory.createMemoryHistory)();
const s0 = stackState(["index"], 0);
history.replace({
path: "/",
state: s0
});
(0, import_vitest.expect)(history.index).toBe(0);
const s1 = stackState(["index", "todo"], 1);
history.push({
path: "/todo/abc",
state: s1
});
(0, import_vitest.expect)(history.index).toBe(1);
(0, import_vitest.expect)(history.get(1)?.state).toBe(s1);
const popStateLog = [];
const unlisten = history.listen(() => {
const idx = history.index;
const rec = history.get(idx);
popStateLog.push({
path: globalThis.window.location.pathname,
recordPath: rec?.path,
recordState: rec?.state
});
history.replace({
path: "/",
state: s0
});
});
dom.firePopState(-1);
(0, import_vitest.expect)(popStateLog).toHaveLength(1);
(0, import_vitest.expect)(popStateLog[0].recordPath).toBe("/");
(0, import_vitest.expect)(popStateLog[0].recordState).toBe(s0);
dom.firePopState(1);
(0, import_vitest.expect)(popStateLog).toHaveLength(2);
(0, import_vitest.expect)(popStateLog[1].recordPath).toBe("/todo/abc");
(0, import_vitest.expect)(popStateLog[1].recordState).toBe(s1);
(0, import_vitest.expect)(history.index).toBe(1);
unlisten();
});