Skip to content

Commit 92caad9

Browse files
authored
feat: add history package and createMemoryHistory implementation (#8702)
* feat: add initial empty history package * feat: add createMemoryHistory + tests * chore: add rollup buld for history * chore: change state type from unknown -> any * feat: Change listen interface to be pop only * chore: fix lint warning * Add history package to yarn workspace * chore: Address PR feedback
1 parent 1100224 commit 92caad9

28 files changed

+1131
-0
lines changed

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@
6363
},
6464
"workspaces": {
6565
"packages": [
66+
"packages/history",
6667
"packages/react-router",
6768
"packages/react-router-dom",
6869
"packages/react-router-native"

packages/history/.eslintrc

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
{
2+
"env": {
3+
"browser": true,
4+
"commonjs": true
5+
},
6+
"globals": {
7+
"__DEV__": true
8+
},
9+
"rules": {
10+
"strict": 0
11+
}
12+
}

packages/history/README.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# history
2+
3+
The `history` library lets you easily manage session history anywhere JavaScript runs. A `history` object abstracts away the differences in various environments and provides a minimal API that lets you manage the history stack, navigate, and persist state between sessions.
4+
5+
This internal package is an evolution of the [`history`](https://www.npmjs.com/package/history) `npm` package from https://github.com/remix-run/history, and has now been internalized to `react-router`.
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
{
2+
"env": {
3+
"jest": true
4+
},
5+
"rules": {
6+
"no-console": 0
7+
}
8+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import type { History } from "../../index";
2+
3+
export default function EncodeReservedCharacters(history: History) {
4+
let pathname;
5+
6+
// encoded string
7+
pathname = "/view/%23abc";
8+
history.replace(pathname);
9+
expect(history.location).toMatchObject({
10+
pathname: "/view/%23abc",
11+
});
12+
13+
// encoded object
14+
pathname = "/view/%23abc";
15+
history.replace({ pathname });
16+
expect(history.location).toMatchObject({
17+
pathname: "/view/%23abc",
18+
});
19+
20+
// unencoded string
21+
pathname = "/view/#abc";
22+
history.replace(pathname);
23+
expect(history.location).toMatchObject({
24+
pathname: "/view/",
25+
hash: "#abc",
26+
});
27+
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import type { History } from "../../index";
2+
3+
export default function GoBack(history: History, spy: jest.SpyInstance) {
4+
expect(history.location).toMatchObject({
5+
pathname: "/",
6+
});
7+
8+
history.push("/home");
9+
expect(history.action).toEqual("PUSH");
10+
expect(history.location).toMatchObject({
11+
pathname: "/home",
12+
});
13+
expect(spy).not.toHaveBeenCalled();
14+
15+
history.go(-1);
16+
expect(history.action).toEqual("POP");
17+
expect(history.location).toMatchObject({
18+
pathname: "/",
19+
});
20+
expect(spy).toHaveBeenCalledWith({
21+
action: "POP",
22+
location: {
23+
hash: "",
24+
key: expect.any(String),
25+
pathname: "/",
26+
search: "",
27+
state: null,
28+
},
29+
});
30+
expect(spy.mock.calls.length).toBe(1);
31+
}
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
import type { History } from "../../index";
2+
3+
export default function GoForward(history: History, spy: jest.SpyInstance) {
4+
expect(history.location).toMatchObject({
5+
pathname: "/",
6+
});
7+
8+
history.push("/home");
9+
expect(history.action).toEqual("PUSH");
10+
expect(history.location).toMatchObject({
11+
pathname: "/home",
12+
});
13+
expect(spy).not.toHaveBeenCalled();
14+
15+
history.go(-1);
16+
expect(history.action).toEqual("POP");
17+
expect(history.location).toMatchObject({
18+
pathname: "/",
19+
});
20+
expect(spy).toHaveBeenCalledWith({
21+
action: "POP",
22+
location: {
23+
hash: "",
24+
key: expect.any(String),
25+
pathname: "/",
26+
search: "",
27+
state: null,
28+
},
29+
});
30+
expect(spy.mock.calls.length).toBe(1);
31+
32+
history.go(1);
33+
expect(history.action).toEqual("POP");
34+
expect(history.location).toMatchObject({
35+
pathname: "/home",
36+
});
37+
expect(spy).toHaveBeenCalledWith({
38+
action: "POP",
39+
location: {
40+
hash: "",
41+
key: expect.any(String),
42+
pathname: "/home",
43+
search: "",
44+
state: null,
45+
},
46+
});
47+
expect(spy.mock.calls.length).toBe(2);
48+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
import type { History } from "../../index";
2+
3+
export default function InitialLocationDefaultKey(history: History) {
4+
expect(history.location.key).toBe("default");
5+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
import type { History } from "../../index";
2+
3+
export default function InitialLocationHasKey(history: History) {
4+
expect(history.location.key).toBeTruthy();
5+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import type { History } from "../../index";
2+
3+
export default function Listen(history: History) {
4+
let spy = jest.fn();
5+
let unlisten = history.listen(spy);
6+
7+
expect(spy).not.toHaveBeenCalled();
8+
9+
unlisten();
10+
}

0 commit comments

Comments
 (0)