Skip to content

Commit 17e8afa

Browse files
committed
chore: Add tests for publisher metrics
1 parent e1d52a0 commit 17e8afa

7 files changed

Lines changed: 271 additions & 69 deletions

File tree

static/js/publisher/pages/Metrics/ActiveDeviceMetricFilter.tsx

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,11 @@ export const ActiveDeviceMetricFilter = ({
1616
return (
1717
<>
1818
<Col size={3} key="periodFilter">
19+
<label className="u-off-screen" htmlFor="period-selector">
20+
Period
21+
</label>
1922
<Select
23+
id="period-selector"
2024
className="p-form__control"
2125
disabled={isEmpty}
2226
value={period}
@@ -54,7 +58,11 @@ export const ActiveDeviceMetricFilter = ({
5458
/>
5559
</Col>
5660
<Col size={3} key="typeFilter">
61+
<label className="u-off-screen" htmlFor="category-selector">
62+
Category
63+
</label>
5764
<Select
65+
id="category-selector"
5866
className="p-form__control"
5967
disabled={isEmpty}
6068
value={type}

static/js/publisher/pages/Metrics/__tests__/ActiveDeviceMetrics.test.tsx

Lines changed: 2 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ import "@testing-library/jest-dom";
44
import { QueryClient, QueryClientProvider, useQuery } from "react-query";
55
import * as MetricsRenderMethods from "../metrics/metrics";
66

7+
import { mockActiveDeviceMetrics } from "../../../test-utils";
8+
79
import ActiveDeviceMetrics from "../ActiveDeviceMetrics";
810

911
const queryClient = new QueryClient();
@@ -21,55 +23,6 @@ const renderComponent = (isEmpty: boolean) => {
2123
);
2224
};
2325

24-
const mockActiveDeviceMetrics = {
25-
active_devices: {
26-
buckets: [
27-
"2024-08-19",
28-
"2024-08-20",
29-
"2024-08-21",
30-
"2024-08-22",
31-
"2024-08-23",
32-
"2024-08-24",
33-
"2024-08-25",
34-
"2024-08-26",
35-
"2024-08-27",
36-
"2024-08-28",
37-
"2024-08-29",
38-
"2024-08-30",
39-
"2024-08-31",
40-
"2024-09-01",
41-
"2024-09-02",
42-
"2024-09-03",
43-
"2024-09-04",
44-
"2024-09-05",
45-
"2024-09-06",
46-
"2024-09-07",
47-
"2024-09-08",
48-
"2024-09-09",
49-
"2024-09-10",
50-
"2024-09-11",
51-
"2024-09-12",
52-
"2024-09-13",
53-
"2024-09-14",
54-
"2024-09-15",
55-
"2024-09-16",
56-
"2024-09-17",
57-
"2024-09-18",
58-
],
59-
name: "weekly_installed_base_by_version",
60-
series: [
61-
{
62-
name: "1.0",
63-
values: [
64-
9, 9, 8, 8, 9, 8, 7, 7, 7, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 5, 5, 5, 5,
65-
5, 6, 6, 5, 5, 5, 5, 5,
66-
],
67-
},
68-
],
69-
},
70-
latest_active_devices: 5,
71-
};
72-
7326
jest.mock("react-query", () => ({
7427
...jest.requireActual("react-query"),
7528
useQuery: jest.fn(),
Lines changed: 188 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,188 @@
1+
import { BrowserRouter } from "react-router-dom";
2+
import { QueryClient, QueryClientProvider } from "react-query";
3+
import { http, HttpResponse } from "msw";
4+
import { setupServer } from "msw/node";
5+
import { render, screen, waitFor } from "@testing-library/react";
6+
import "@testing-library/jest-dom";
7+
8+
import * as worldData from "../../../../world-110m.v1.json";
9+
import {
10+
mockActiveDeviceMetrics,
11+
mockTerritoryMetrics,
12+
} from "../../../test-utils";
13+
14+
import Metrics from "../Metrics";
15+
16+
Object.defineProperty(global.SVGElement.prototype, "getBBox", {
17+
writable: true,
18+
value: jest.fn().mockReturnValue({
19+
x: 0,
20+
y: 0,
21+
}),
22+
});
23+
24+
jest.mock("react-router-dom", () => ({
25+
...jest.requireActual("react-router-dom"),
26+
useParams: () => ({
27+
snapId: "test-snap-id",
28+
}),
29+
}));
30+
31+
const queryClient = new QueryClient();
32+
33+
function renderComponent() {
34+
render(
35+
<QueryClientProvider client={queryClient}>
36+
<BrowserRouter>
37+
<Metrics />
38+
</BrowserRouter>
39+
</QueryClientProvider>,
40+
);
41+
}
42+
43+
const handlers = [
44+
http.get("/test-snap-id/metrics/active-device-annotation", () => {
45+
return HttpResponse.json({
46+
buckets: [],
47+
name: "annotations",
48+
series: [],
49+
});
50+
}),
51+
http.get("/test-snap-id/metrics/active-latest-devices", () => {
52+
return HttpResponse.json({
53+
latest_active_devices: 0,
54+
});
55+
}),
56+
http.get("/test-snap-id/metrics/active-devices", () => {
57+
return HttpResponse.json({
58+
active_devices: {
59+
buckets: [],
60+
name: "weekly_installed_base_by_version",
61+
series: [],
62+
},
63+
latest_archive_devices: 0,
64+
total_page_num: 1,
65+
});
66+
}),
67+
http.get("/test-snap-id/metrics/country-metric", () => {
68+
return HttpResponse.json({
69+
active_devices: {},
70+
territories_total: 0,
71+
});
72+
}),
73+
http.get("/static/js/world-110m.v1.json", () => {
74+
return HttpResponse.json(worldData);
75+
}),
76+
];
77+
78+
const server = setupServer(...handlers);
79+
80+
beforeAll(() => {
81+
server.listen();
82+
});
83+
84+
afterEach(() => {
85+
server.resetHandlers();
86+
queryClient.clear();
87+
});
88+
89+
afterAll(() => {
90+
server.close();
91+
});
92+
93+
describe("Metrics", () => {
94+
test("shows correct heading", () => {
95+
renderComponent();
96+
expect(
97+
screen.getByRole("heading", {
98+
level: 1,
99+
name: "My snaps / test-snap-id / Metrics",
100+
}),
101+
).toBeInTheDocument();
102+
});
103+
104+
test("highlights correct tab", () => {
105+
renderComponent();
106+
expect(screen.getByRole("link", { name: "Metrics" })).toHaveAttribute(
107+
"aria-selected",
108+
"true",
109+
);
110+
});
111+
112+
test("shows empty state if no data", async () => {
113+
renderComponent();
114+
await waitFor(() => {
115+
expect(
116+
screen.getByRole("heading", {
117+
level: 2,
118+
name: "Measure your snap's performance",
119+
}),
120+
).toBeInTheDocument();
121+
expect(
122+
screen.getByText(
123+
"You'll be able to see active devices and territories when people start using your snap.",
124+
),
125+
).toBeInTheDocument();
126+
});
127+
});
128+
129+
test("disables filters if no data", async () => {
130+
renderComponent();
131+
await waitFor(() => {
132+
expect(screen.getByLabelText("Period")).toBeDisabled();
133+
expect(screen.getByLabelText("Category")).toBeDisabled();
134+
});
135+
});
136+
137+
test("enables filters if data", async () => {
138+
server.use(
139+
http.get("/test-snap-id/metrics/active-devices", () => {
140+
return HttpResponse.json(mockActiveDeviceMetrics);
141+
}),
142+
);
143+
server.use(
144+
http.get("/test-snap-id/metrics/country-metric", () => {
145+
return HttpResponse.json(mockTerritoryMetrics);
146+
}),
147+
);
148+
renderComponent();
149+
await waitFor(() => {
150+
expect(screen.getByLabelText("Period")).not.toBeDisabled();
151+
expect(screen.getByLabelText("Category")).not.toBeDisabled();
152+
});
153+
});
154+
155+
test("renders active devices graph if data", async () => {
156+
server.use(
157+
http.get("/test-snap-id/metrics/active-devices", () => {
158+
return HttpResponse.json(mockActiveDeviceMetrics);
159+
}),
160+
);
161+
server.use(
162+
http.get("/test-snap-id/metrics/country-metric", () => {
163+
return HttpResponse.json(mockTerritoryMetrics);
164+
}),
165+
);
166+
renderComponent();
167+
await waitFor(() => {
168+
expect(document.getElementById("activeDevices")).toBeInTheDocument();
169+
});
170+
});
171+
172+
test("renders territories graph if data", async () => {
173+
server.use(
174+
http.get("/test-snap-id/metrics/active-devices", () => {
175+
return HttpResponse.json(mockActiveDeviceMetrics);
176+
}),
177+
);
178+
server.use(
179+
http.get("/test-snap-id/metrics/country-metric", () => {
180+
return HttpResponse.json(mockTerritoryMetrics);
181+
}),
182+
);
183+
renderComponent();
184+
await waitFor(() => {
185+
expect(document.getElementById("territories")).toBeInTheDocument();
186+
});
187+
});
188+
});

static/js/publisher/pages/Metrics/__tests__/TerritoryMetrics.test.tsx

Lines changed: 2 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ import * as MetricsRenderMethods from "../metrics/metrics";
66

77
import { TerritoryMetrics } from "../TerritoryMetrics";
88

9+
import { mockTerritoryMetrics } from "../../../test-utils";
10+
911
const queryClient = new QueryClient();
1012

1113
const renderComponent = (isEmpty: boolean) => {
@@ -21,26 +23,6 @@ const renderComponent = (isEmpty: boolean) => {
2123
);
2224
};
2325

24-
const mockTerritoryMetrics = {
25-
active_devices: {
26-
"528": {
27-
code: "NL",
28-
color_rgb: [8, 48, 107],
29-
name: "Netherlands",
30-
number_of_users: 1,
31-
percentage_of_users: 1,
32-
},
33-
"826": {
34-
code: "GB",
35-
color_rgb: [8, 48, 107],
36-
name: "United Kingdom",
37-
number_of_users: 4,
38-
percentage_of_users: 4,
39-
},
40-
},
41-
territories_total: 5,
42-
};
43-
4426
jest.mock("react-query", () => ({
4527
...jest.requireActual("react-query"),
4628
useQuery: jest.fn(),

static/js/publisher/test-utils/index.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
import { mockListingData } from "./mockListingData";
2+
import { mockActiveDeviceMetrics } from "./mockActiveDeviceMetrics";
3+
import { mockTerritoryMetrics } from "./mockTerritoryMetrics";
24
import RecoilObserver from "./RecoilObserver";
35
import brandStoreRequests from "./brand-store-requests";
46
import {
@@ -16,4 +18,6 @@ export {
1618
snapsResponse,
1719
membersResponse,
1820
storesResponse,
21+
mockActiveDeviceMetrics,
22+
mockTerritoryMetrics,
1923
};
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
export const mockActiveDeviceMetrics = {
2+
active_devices: {
3+
buckets: [
4+
"2024-08-19",
5+
"2024-08-20",
6+
"2024-08-21",
7+
"2024-08-22",
8+
"2024-08-23",
9+
"2024-08-24",
10+
"2024-08-25",
11+
"2024-08-26",
12+
"2024-08-27",
13+
"2024-08-28",
14+
"2024-08-29",
15+
"2024-08-30",
16+
"2024-08-31",
17+
"2024-09-01",
18+
"2024-09-02",
19+
"2024-09-03",
20+
"2024-09-04",
21+
"2024-09-05",
22+
"2024-09-06",
23+
"2024-09-07",
24+
"2024-09-08",
25+
"2024-09-09",
26+
"2024-09-10",
27+
"2024-09-11",
28+
"2024-09-12",
29+
"2024-09-13",
30+
"2024-09-14",
31+
"2024-09-15",
32+
"2024-09-16",
33+
"2024-09-17",
34+
"2024-09-18",
35+
],
36+
name: "weekly_installed_base_by_version",
37+
series: [
38+
{
39+
name: "1.0",
40+
values: [
41+
9, 9, 8, 8, 9, 8, 7, 7, 7, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 5, 5, 5, 5,
42+
5, 6, 6, 5, 5, 5, 5, 5,
43+
],
44+
},
45+
],
46+
},
47+
latest_active_devices: 5,
48+
};
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
export const mockTerritoryMetrics = {
2+
active_devices: {
3+
"528": {
4+
code: "NL",
5+
color_rgb: [8, 48, 107],
6+
name: "Netherlands",
7+
number_of_users: 1,
8+
percentage_of_users: 1,
9+
},
10+
"826": {
11+
code: "GB",
12+
color_rgb: [8, 48, 107],
13+
name: "United Kingdom",
14+
number_of_users: 4,
15+
percentage_of_users: 4,
16+
},
17+
},
18+
territories_total: 5,
19+
};

0 commit comments

Comments
 (0)