-
-
Notifications
You must be signed in to change notification settings - Fork 3.4k
Expand file tree
/
Copy pathSupport.data.test.jsx
More file actions
100 lines (87 loc) · 3.07 KB
/
Support.data.test.jsx
File metadata and controls
100 lines (87 loc) · 3.07 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
/**
* @jest-environment jsdom
*/
// eslint-disable-next-line import/no-extraneous-dependencies
import { beforeEach, describe, expect, it, jest } from "@jest/globals";
import { act, fireEvent, render, screen } from "@testing-library/react";
import SmallIcon from "../../assets/icon-square-small-slack.png";
// Data must be inline - jest.mock is hoisted before const declarations (TDZ)
jest.mock("./AdditionalSupporters.mjs", () => []);
jest.mock(
"./_supporters.json",
() => [
{
slug: "gold-org",
name: "Gold Org",
totalDonations: 2000000, // $20,000 - gold range ($10k-$50k)
monthlyDonations: 100000,
avatar: "https://example.com/avatar.png",
firstDonation: new Date(
Date.now() - 5 * 24 * 60 * 60 * 1000,
).toISOString(),
},
],
{ virtual: true },
);
// eslint-disable-next-line import/first
import Support from "./Support.jsx";
const AVATAR_URL = "https://example.com/avatar.png";
describe("Support with supporter data", () => {
let intersectionCallback;
let mockObserve;
let mockDisconnect;
beforeEach(() => {
mockObserve = jest.fn();
mockDisconnect = jest.fn();
Object.defineProperty(window, "IntersectionObserver", {
writable: true,
configurable: true,
value: class {
observe() {}
disconnect() {}
},
});
jest.spyOn(window, "IntersectionObserver").mockImplementation((cb) => {
intersectionCallback = cb;
return { observe: mockObserve, disconnect: mockDisconnect };
});
});
it("renders supporter links", () => {
render(<Support rank="gold" type="total" />);
// supporter link + become a sponsor link
expect(screen.getAllByRole("link").length).toBeGreaterThanOrEqual(2);
});
it("shows SmallIcon before intersection observer fires", () => {
render(<Support rank="gold" type="total" />);
const imgs = screen.getAllByRole("img");
expect(imgs[0].getAttribute("src")).toBe(SmallIcon);
});
it("shows avatar src after intersection observer fires", () => {
render(<Support rank="gold" type="total" />);
act(() => {
intersectionCallback([{ isIntersecting: true }]);
});
const imgs = screen.getAllByRole("img");
expect(imgs[0].getAttribute("src")).toBe(AVATAR_URL);
});
it("falls back to SmallIcon on image error", () => {
render(<Support rank="gold" type="total" />);
act(() => {
intersectionCallback([{ isIntersecting: true }]);
});
const imgs = screen.getAllByRole("img");
fireEvent.error(imgs[0]);
expect(imgs[0].getAttribute("src")).toBe(SmallIcon);
});
it("does not replace src if image already shows SmallIcon on error", () => {
render(<Support rank="gold" type="total" />);
// inView is false so src is already SmallIcon - error should not loop
const imgs = screen.getAllByRole("img");
fireEvent.error(imgs[0]);
expect(imgs[0].getAttribute("src")).toBe(SmallIcon);
});
it("matches snapshot with supporter data", () => {
const { container } = render(<Support rank="gold" type="total" />);
expect(container.firstChild).toMatchSnapshot();
});
});