Skip to content

Commit f772f79

Browse files
committed
Add unit tests 🍢
1 parent e3e87f7 commit f772f79

File tree

9 files changed

+95
-31
lines changed

9 files changed

+95
-31
lines changed

src/helpers.ts

Lines changed: 1 addition & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -32,16 +32,6 @@ export const nextTick = (): Promise<void> => {
3232
});
3333
};
3434

35-
/** Check if an element has overflow */
36-
export const hasOverflow = ({
37-
clientWidth,
38-
clientHeight,
39-
scrollWidth,
40-
scrollHeight,
41-
}: HTMLElement) => {
42-
return scrollHeight > clientHeight || scrollWidth > clientWidth;
43-
};
44-
4535
/**
4636
* Minimal debounce function.
4737
* @see https://www.joshwcomeau.com/snippets/javascript/debounce/
@@ -91,7 +81,7 @@ export function isScrollState(value: unknown): value is ScrollState {
9181
* Get stored restore-scroll state, filter out invalid records
9282
*/
9383
export function getScrollState(): ScrollState {
94-
const state = window.history.state?.scrollState;
84+
const state = window.history.state?.restoreScroll;
9585
return isScrollState(state) ? state : {};
9686
}
9787

@@ -184,14 +174,3 @@ export function readStorageSelector(
184174

185175
return selector;
186176
}
187-
188-
/**
189-
* Query a scroll container by selector
190-
*/
191-
export function getScrollContainer(selector: string): Element | null {
192-
try {
193-
return document.querySelector(selector);
194-
} catch (e) {
195-
return null;
196-
}
197-
}

src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import restoreScroll from "./restoreScroll.js";
22
import type { Options } from "./defs.js";
3+
34
export { restoreScroll };
45
export type { Options };

src/restoreScroll.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ let hookedIntoBeforeUnlad = false;
1818
export default function restoreScroll(
1919
target: Target | null,
2020
options: Partial<Options> = {}
21-
): void {
21+
) {
2222
const settings = { ...defaults, ...options };
2323
const logger = settings.debug ? createLogger() : undefined;
2424

@@ -63,4 +63,5 @@ export default function restoreScroll(
6363
hookedIntoBeforeUnlad = true;
6464
window.addEventListener("beforeunload", storeAll);
6565
}
66+
return {element};
6667
}

src/store.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,19 +6,19 @@ import { getScrollState, readStorageSelector } from "./helpers.js";
66
*/
77
export function store(element: ScrollContainer, logger?: Logger): void {
88
const state = window.history.state || {};
9-
const scrollState = getScrollState();
9+
const restoreScroll = getScrollState();
1010

1111
const selector = readStorageSelector(element, logger);
1212
if (!selector) {
1313
return;
1414
}
1515

1616
const { scrollTop: top, scrollLeft: left } = element;
17-
scrollState[selector] = { top, left };
17+
restoreScroll[selector] = { top, left };
1818

1919
const newState = {
2020
...state,
21-
scrollState,
21+
restoreScroll,
2222
};
2323

2424
window.history.replaceState(newState, "");
@@ -30,23 +30,23 @@ export function store(element: ScrollContainer, logger?: Logger): void {
3030
* Store all positions before unload
3131
*/
3232
export function storeAll(): void {
33-
const state: ScrollState = {};
33+
const restoreScroll: ScrollState = {};
3434

3535
document
3636
.querySelectorAll<ScrollContainer>("[data-restore-scroll]")
3737
.forEach((el) => {
3838
const selector = readStorageSelector(el);
3939
if (!selector) return;
4040

41-
state[selector] = {
41+
restoreScroll[selector] = {
4242
top: el.scrollTop,
4343
left: el.scrollLeft,
4444
};
4545
});
4646

4747
const newState = {
4848
...(window.history.state || {}),
49-
state,
49+
restoreScroll,
5050
};
5151

5252
window.history.replaceState(newState, "");

tests/unit/tests/logger.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { vi, describe, expect, it, beforeEach, afterEach } from "vitest";
22

33
import { restoreScroll } from "../../../src/index.js";
4-
import { createElement } from "./support.js";
4+
import { createElement } from "../support.js";
55

66
describe("Logger", () => {
77
let warnSpy: ReturnType<typeof vi.spyOn>;
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import { describe, expect, it } from "vitest";
2+
3+
import { getScrollState } from "../../../src/helpers.ts";
4+
5+
describe("getScrollState", () => {
6+
it("should return the scroll state from the history", () => {
7+
const expected = { ":root": { top: 100, left: 200 } };
8+
window.history.replaceState(
9+
{ restoreScroll: expected },
10+
"",
11+
window.location.href
12+
);
13+
expect(getScrollState()).toEqual(expected);
14+
});
15+
16+
it("should return an empty object on failure", () => {
17+
window.history.replaceState(
18+
{ restoreScroll: { anything: { top: 100 } } },
19+
"",
20+
window.location.href
21+
);
22+
expect(getScrollState()).toEqual({});
23+
});
24+
});

tests/unit/tests/createStorageSelector.test.ts renamed to tests/unit/tests/storageSelector.test.ts

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
import { afterEach, describe, expect, it } from "vitest";
22

33
import { createStorageSelector } from "../../../src/helpers.ts";
4-
import { createElement } from "./support.ts";
4+
import { createElement } from "../support.ts";
5+
import restoreScroll from "../../../src/restoreScroll.ts";
6+
import { ScrollContainer } from "../../../src/defs.ts";
57

68
describe("createStorageSelector", () => {
79
afterEach(() => {
@@ -23,6 +25,11 @@ describe("createStorageSelector", () => {
2325
);
2426
});
2527

28+
it("should use ':root' if not inside the body", () => {
29+
expect(createStorageSelector(document.documentElement)).toEqual(":root");
30+
expect(createStorageSelector(document.body)).toEqual(":root");
31+
});
32+
2633
it("should use the [id] attribute if available", () => {
2734
document.body.append(
2835
createElement(/*html*/ `
@@ -38,4 +45,21 @@ describe("createStorageSelector", () => {
3845
"#scroller"
3946
);
4047
});
48+
49+
it("should inject the storage selector into the element", () => {
50+
document.body.append(
51+
createElement(/*html*/ `
52+
<main>
53+
<div></div>
54+
<div></div>
55+
<div class="scroller"></div>
56+
</main>
57+
`)
58+
);
59+
restoreScroll(document.querySelector(".scroller"));
60+
expect(
61+
document.querySelector<ScrollContainer>(".scroller")?.__restore_scroll
62+
?.selector
63+
).toEqual("html > body:nth-child(2) > main > div.scroller:nth-child(3)");
64+
});
4165
});
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import { describe, expect, it } from "vitest";
2+
3+
import {
4+
getScrollState,
5+
isScrollPosition,
6+
isScrollState,
7+
} from "../../../src/helpers.ts";
8+
9+
describe("isScrollPosition", () => {
10+
it("should accept a valid scroll position", () => {
11+
expect(isScrollPosition({ top: 0, left: 200 })).toEqual(true);
12+
});
13+
14+
it("should allow extra properties", () => {
15+
expect(isScrollPosition({ top: 0, left: 200, extra: "foo" })).toEqual(true);
16+
});
17+
18+
it("should detect missing properties", () => {
19+
expect(isScrollPosition({ top: 0 })).toEqual(false);
20+
});
21+
});
22+
23+
describe("isScrollState", () => {
24+
it("should accept a valid scroll state", () => {
25+
expect(
26+
isScrollState({
27+
":root": { top: 0, left: 200 },
28+
})
29+
).toEqual(true);
30+
});
31+
32+
it("should reject an invalid scroll state", () => {
33+
expect(isScrollState([{ top: 0, left: 200 }])).toEqual(false);
34+
});
35+
});

0 commit comments

Comments
 (0)