Skip to content

Commit e637a8a

Browse files
committed
fix: unit tests
1 parent 2dbcdba commit e637a8a

7 files changed

Lines changed: 434 additions & 462 deletions

File tree

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
import { renderHook } from "@testing-library/react-native";
2+
import { useAnimatedRef } from "react-native-reanimated";
3+
4+
import type { useExtraContentPadding } from "..";
5+
import type { SharedValue } from "react-native-reanimated";
6+
import type Reanimated from "react-native-reanimated";
7+
8+
export const mockScrollTo = jest.fn();
9+
export let reactionEffect: (current: number, previous: number | null) => void;
10+
11+
jest.mock("react-native-reanimated", () => ({
12+
...require("react-native-reanimated/mock"),
13+
scrollTo: (...args: unknown[]) => mockScrollTo(...args),
14+
useAnimatedReaction: (
15+
_producer: () => number,
16+
effect: (current: number, previous: number | null) => void,
17+
) => {
18+
reactionEffect = effect;
19+
},
20+
}));
21+
22+
export const sv = <T>(initial: T): SharedValue<T> => {
23+
return { value: initial } as SharedValue<T>;
24+
};
25+
26+
type RenderOptions = Omit<
27+
Parameters<typeof useExtraContentPadding>[0],
28+
"scrollViewRef"
29+
>;
30+
31+
export const createRender = () => {
32+
return function render(options: RenderOptions) {
33+
// eslint-disable-next-line @typescript-eslint/no-var-requires
34+
const mod = require("..") as {
35+
useExtraContentPadding: typeof useExtraContentPadding;
36+
};
37+
38+
return renderHook(() => {
39+
const ref = useAnimatedRef<Reanimated.ScrollView>();
40+
41+
mod.useExtraContentPadding({ scrollViewRef: ref, ...options });
42+
});
43+
};
44+
};
45+
46+
beforeEach(() => {
47+
jest.resetModules();
48+
mockScrollTo.mockClear();
49+
});
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
import {
2+
createRender,
3+
mockScrollTo,
4+
reactionEffect,
5+
sv,
6+
} from "../__fixtures__/setup";
7+
8+
describe("useExtraContentPadding — always behavior", () => {
9+
it("should scrollTo on grow when at end (non-inverted)", () => {
10+
const render = createRender();
11+
12+
render({
13+
extraContentPadding: sv(20),
14+
keyboardPadding: sv(300),
15+
scroll: sv(1200),
16+
layout: sv({ width: 390, height: 800 }),
17+
size: sv({ width: 390, height: 2000 }),
18+
inverted: false,
19+
keyboardLiftBehavior: "always",
20+
freeze: false,
21+
});
22+
23+
reactionEffect(20, 0);
24+
25+
expect(mockScrollTo).toHaveBeenCalledWith(
26+
expect.anything(),
27+
0,
28+
1220,
29+
false,
30+
);
31+
});
32+
33+
it("should scrollTo on grow when NOT at end (non-inverted)", () => {
34+
const render = createRender();
35+
36+
render({
37+
extraContentPadding: sv(20),
38+
keyboardPadding: sv(300),
39+
scroll: sv(100),
40+
layout: sv({ width: 390, height: 800 }),
41+
size: sv({ width: 390, height: 2000 }),
42+
inverted: false,
43+
keyboardLiftBehavior: "always",
44+
freeze: false,
45+
});
46+
47+
reactionEffect(20, 0);
48+
49+
expect(mockScrollTo).toHaveBeenCalledWith(expect.anything(), 0, 120, false);
50+
});
51+
52+
it("should scrollTo on shrink (non-inverted)", () => {
53+
const render = createRender();
54+
55+
render({
56+
extraContentPadding: sv(0),
57+
keyboardPadding: sv(300),
58+
scroll: sv(1220),
59+
layout: sv({ width: 390, height: 800 }),
60+
size: sv({ width: 390, height: 2000 }),
61+
inverted: false,
62+
keyboardLiftBehavior: "always",
63+
freeze: false,
64+
});
65+
66+
reactionEffect(0, 20);
67+
68+
expect(mockScrollTo).toHaveBeenCalledWith(
69+
expect.anything(),
70+
0,
71+
1200,
72+
false,
73+
);
74+
});
75+
76+
it("should scrollTo on grow (inverted)", () => {
77+
const render = createRender();
78+
79+
render({
80+
extraContentPadding: sv(20),
81+
keyboardPadding: sv(300),
82+
scroll: sv(5),
83+
layout: sv({ width: 390, height: 800 }),
84+
size: sv({ width: 390, height: 2000 }),
85+
inverted: true,
86+
keyboardLiftBehavior: "always",
87+
freeze: false,
88+
});
89+
90+
reactionEffect(20, 0);
91+
92+
expect(mockScrollTo).toHaveBeenCalledWith(expect.anything(), 0, -15, false);
93+
});
94+
});
Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
import {
2+
createRender,
3+
mockScrollTo,
4+
reactionEffect,
5+
sv,
6+
} from "../__fixtures__/setup";
7+
8+
describe("useExtraContentPadding — edge cases", () => {
9+
it("should not scrollTo when delta is 0", () => {
10+
const render = createRender();
11+
12+
render({
13+
extraContentPadding: sv(20),
14+
keyboardPadding: sv(0),
15+
scroll: sv(100),
16+
layout: sv({ width: 390, height: 800 }),
17+
size: sv({ width: 390, height: 2000 }),
18+
inverted: false,
19+
keyboardLiftBehavior: "always",
20+
freeze: false,
21+
});
22+
23+
reactionEffect(20, 20);
24+
25+
expect(mockScrollTo).not.toHaveBeenCalled();
26+
});
27+
28+
it("should not scrollTo on first render (previous is null)", () => {
29+
const render = createRender();
30+
31+
render({
32+
extraContentPadding: sv(20),
33+
keyboardPadding: sv(0),
34+
scroll: sv(100),
35+
layout: sv({ width: 390, height: 800 }),
36+
size: sv({ width: 390, height: 2000 }),
37+
inverted: false,
38+
keyboardLiftBehavior: "always",
39+
freeze: false,
40+
});
41+
42+
reactionEffect(20, null);
43+
44+
expect(mockScrollTo).not.toHaveBeenCalled();
45+
});
46+
47+
it("should not scrollTo when freeze is true", () => {
48+
const render = createRender();
49+
50+
render({
51+
extraContentPadding: sv(20),
52+
keyboardPadding: sv(0),
53+
scroll: sv(1200),
54+
layout: sv({ width: 390, height: 800 }),
55+
size: sv({ width: 390, height: 2000 }),
56+
inverted: false,
57+
keyboardLiftBehavior: "always",
58+
freeze: true,
59+
});
60+
61+
reactionEffect(20, 0);
62+
63+
expect(mockScrollTo).not.toHaveBeenCalled();
64+
});
65+
66+
it("should clamp to maxScroll (non-inverted)", () => {
67+
const render = createRender();
68+
69+
render({
70+
extraContentPadding: sv(50),
71+
keyboardPadding: sv(300),
72+
scroll: sv(1490),
73+
layout: sv({ width: 390, height: 800 }),
74+
size: sv({ width: 390, height: 2000 }),
75+
inverted: false,
76+
keyboardLiftBehavior: "always",
77+
freeze: false,
78+
});
79+
80+
// delta = 50, scroll + delta = 1540, maxScroll = 2000 - 800 + 300 + 50 = 1550
81+
reactionEffect(50, 0);
82+
83+
expect(mockScrollTo).toHaveBeenCalledWith(
84+
expect.anything(),
85+
0,
86+
1540,
87+
false,
88+
);
89+
});
90+
91+
it("should clamp to -totalPadding (inverted)", () => {
92+
const render = createRender();
93+
94+
render({
95+
extraContentPadding: sv(50),
96+
keyboardPadding: sv(300),
97+
scroll: sv(-280),
98+
layout: sv({ width: 390, height: 800 }),
99+
size: sv({ width: 390, height: 2000 }),
100+
inverted: true,
101+
keyboardLiftBehavior: "always",
102+
freeze: false,
103+
});
104+
105+
// delta = 50, target = -280 - 50 = -330, clamp to -350
106+
reactionEffect(50, 0);
107+
108+
expect(mockScrollTo).toHaveBeenCalledWith(
109+
expect.anything(),
110+
0,
111+
-330,
112+
false,
113+
);
114+
});
115+
});
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import {
2+
createRender,
3+
mockScrollTo,
4+
reactionEffect,
5+
sv,
6+
} from "../__fixtures__/setup";
7+
8+
describe("useExtraContentPadding — never behavior", () => {
9+
it("should NOT scrollTo on grow", () => {
10+
const render = createRender();
11+
12+
render({
13+
extraContentPadding: sv(20),
14+
keyboardPadding: sv(0),
15+
scroll: sv(1200),
16+
layout: sv({ width: 390, height: 800 }),
17+
size: sv({ width: 390, height: 2000 }),
18+
inverted: false,
19+
keyboardLiftBehavior: "never",
20+
freeze: false,
21+
});
22+
23+
reactionEffect(20, 0);
24+
25+
expect(mockScrollTo).not.toHaveBeenCalled();
26+
});
27+
});
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
import {
2+
createRender,
3+
mockScrollTo,
4+
reactionEffect,
5+
sv,
6+
} from "../__fixtures__/setup";
7+
8+
describe("useExtraContentPadding — persistent behavior", () => {
9+
it("should scrollTo on grow", () => {
10+
const render = createRender();
11+
12+
render({
13+
extraContentPadding: sv(20),
14+
keyboardPadding: sv(300),
15+
scroll: sv(100),
16+
layout: sv({ width: 390, height: 800 }),
17+
size: sv({ width: 390, height: 2000 }),
18+
inverted: false,
19+
keyboardLiftBehavior: "persistent",
20+
freeze: false,
21+
});
22+
23+
reactionEffect(20, 0);
24+
25+
expect(mockScrollTo).toHaveBeenCalledWith(expect.anything(), 0, 120, false);
26+
});
27+
28+
it("should NOT scrollTo on shrink when NOT at end", () => {
29+
const render = createRender();
30+
31+
render({
32+
extraContentPadding: sv(0),
33+
keyboardPadding: sv(300),
34+
scroll: sv(100),
35+
layout: sv({ width: 390, height: 800 }),
36+
size: sv({ width: 390, height: 2000 }),
37+
inverted: false,
38+
keyboardLiftBehavior: "persistent",
39+
freeze: false,
40+
});
41+
42+
reactionEffect(0, 20);
43+
44+
expect(mockScrollTo).not.toHaveBeenCalled();
45+
});
46+
47+
it("should scrollTo on shrink when at end", () => {
48+
const render = createRender();
49+
50+
render({
51+
extraContentPadding: sv(0),
52+
keyboardPadding: sv(300),
53+
scroll: sv(1200),
54+
layout: sv({ width: 390, height: 800 }),
55+
size: sv({ width: 390, height: 2000 }),
56+
inverted: false,
57+
keyboardLiftBehavior: "persistent",
58+
freeze: false,
59+
});
60+
61+
reactionEffect(0, 20);
62+
63+
expect(mockScrollTo).toHaveBeenCalled();
64+
});
65+
});

0 commit comments

Comments
 (0)