Skip to content

Commit f9dd352

Browse files
committed
reduce pr size
1 parent 6f30446 commit f9dd352

File tree

5 files changed

+54
-310
lines changed

5 files changed

+54
-310
lines changed

src/app/catalog/[repoName]/[serverName]/[version]/actions.test.ts

Lines changed: 0 additions & 77 deletions
This file was deleted.

src/app/catalog/actions.test.ts

Lines changed: 33 additions & 177 deletions
Original file line numberDiff line numberDiff line change
@@ -19,199 +19,55 @@ describe("getServers", () => {
1919
vi.clearAllMocks();
2020
});
2121

22-
describe("successful responses", () => {
23-
it("returns servers from default fixture", async () => {
24-
const servers = await getServers();
22+
it("returns servers from default fixture", async () => {
23+
const servers = await getServers();
2524

26-
expect(servers.length).toBeGreaterThan(0);
27-
expect(servers[0].name).toBe("awslabs/aws-nova-canvas");
28-
expect(servers[0].title).toBe("AWS Nova Canvas");
29-
});
30-
31-
it("returns empty array when API returns no servers", async () => {
32-
mockedGetRegistryV01Servers.useScenario("empty-servers");
33-
34-
const servers = await getServers();
35-
36-
expect(servers).toEqual([]);
37-
});
38-
39-
// Using overrideHandler - needed when returning non-JSON responses like null
40-
it("returns empty array when API returns null data", async () => {
41-
mockedGetRegistryV01Servers.overrideHandler(() =>
42-
HttpResponse.json(null),
43-
);
44-
45-
const servers = await getServers();
46-
47-
expect(servers).toEqual([]);
48-
});
25+
expect(servers.length).toBeGreaterThan(0);
26+
expect(servers[0].name).toBe("awslabs/aws-nova-canvas");
4927
});
5028

51-
describe("error handling", () => {
52-
// Using scenario - reusable error scenario defined in fixture
53-
it("throws on 500 server error", async () => {
54-
mockedGetRegistryV01Servers.useScenario("server-error");
55-
56-
await expect(getServers()).rejects.toBeDefined();
57-
});
29+
// Demo: using .useScenario() for reusable test scenarios
30+
it("returns empty array when using empty-servers scenario", async () => {
31+
mockedGetRegistryV01Servers.useScenario("empty-servers");
5832

59-
it("throws on 401 unauthorized", async () => {
60-
mockedGetRegistryV01Servers.overrideHandler(() =>
61-
HttpResponse.json({ error: "Unauthorized" }, { status: 401 }),
62-
);
33+
const servers = await getServers();
6334

64-
await expect(getServers()).rejects.toBeDefined();
65-
});
66-
67-
it("throws on network error", async () => {
68-
mockedGetRegistryV01Servers.overrideHandler(() => HttpResponse.error());
69-
70-
await expect(getServers()).rejects.toBeDefined();
71-
});
35+
expect(servers).toEqual([]);
7236
});
7337

74-
describe("data transformation", () => {
75-
// Using overrideHandler - needed when testing invalid data shapes (null servers)
76-
it("filters out null servers from response", async () => {
77-
mockedGetRegistryV01Servers.overrideHandler((data) =>
78-
HttpResponse.json({
79-
...data,
80-
servers: [
81-
{ server: { name: "valid/server", title: "Valid" } },
82-
{ server: null },
83-
{ server: { name: "another/server", title: "Another" } },
84-
],
85-
metadata: { count: 3 },
86-
}),
87-
);
88-
89-
const servers = await getServers();
90-
91-
expect(servers).toHaveLength(2);
92-
expect(servers.map((s) => s.name)).toEqual([
93-
"valid/server",
94-
"another/server",
95-
]);
96-
});
97-
98-
// Using overrideHandler - needed when testing invalid data shapes (undefined servers)
99-
it("filters out undefined servers from response", async () => {
100-
mockedGetRegistryV01Servers.overrideHandler(() =>
101-
HttpResponse.json({
102-
servers: [
103-
{ server: { name: "valid/server", title: "Valid" } },
104-
{ server: undefined },
105-
{},
106-
],
107-
metadata: { count: 3 },
108-
}),
109-
);
110-
111-
const servers = await getServers();
112-
113-
expect(servers).toHaveLength(1);
114-
expect(servers[0].name).toBe("valid/server");
115-
});
38+
// Demo: using .useScenario() for error scenarios
39+
it("throws on server error scenario", async () => {
40+
mockedGetRegistryV01Servers.useScenario("server-error");
11641

117-
it("extracts server objects from nested response structure", async () => {
118-
mockedGetRegistryV01Servers.override(() => ({
119-
servers: [
120-
{
121-
server: {
122-
name: "test/server",
123-
title: "Test Server",
124-
description: "A test server",
125-
version: "2.0.0",
126-
},
127-
},
128-
],
129-
metadata: { count: 1 },
130-
}));
131-
132-
const servers = await getServers();
133-
134-
expect(servers).toHaveLength(1);
135-
expect(servers[0]).toEqual({
136-
name: "test/server",
137-
title: "Test Server",
138-
description: "A test server",
139-
version: "2.0.0",
140-
});
141-
});
42+
await expect(getServers()).rejects.toBeDefined();
14243
});
14344

144-
describe("using default data in overrides", () => {
145-
it("can modify specific server titles", async () => {
146-
mockedGetRegistryV01Servers.override((data) => ({
147-
...data,
148-
servers: data.servers?.map((item) => ({
149-
...item,
45+
// Demo: using .override() for type-safe response modifications
46+
it("can override response data with type safety", async () => {
47+
mockedGetRegistryV01Servers.override(() => ({
48+
servers: [
49+
{
15050
server: {
151-
...item.server,
152-
title: `Modified: ${item.server?.title}`,
51+
name: "test/server",
52+
title: "Test Server",
15353
},
154-
})),
155-
}));
156-
157-
const servers = await getServers();
158-
159-
expect(servers[0].title).toBe("Modified: AWS Nova Canvas");
160-
});
161-
162-
it("can limit the number of returned servers", async () => {
163-
mockedGetRegistryV01Servers.override((data) => ({
164-
...data,
165-
servers: data.servers?.slice(0, 3),
166-
metadata: { count: 3 },
167-
}));
168-
169-
const servers = await getServers();
54+
},
55+
],
56+
metadata: { count: 1 },
57+
}));
17058

171-
expect(servers).toHaveLength(3);
172-
});
59+
const servers = await getServers();
17360

174-
it("can filter servers by criteria", async () => {
175-
mockedGetRegistryV01Servers.override((data) => ({
176-
...data,
177-
servers: data.servers?.filter((item) =>
178-
item.server?.name?.includes("google"),
179-
),
180-
}));
181-
182-
const servers = await getServers();
183-
184-
expect(servers.every((s) => s.name?.includes("google"))).toBe(true);
185-
});
61+
expect(servers).toHaveLength(1);
62+
expect(servers[0].name).toBe("test/server");
18663
});
18764

188-
describe("request-aware overrides", () => {
189-
it("can access request info in override", async () => {
190-
let capturedUrl: string | undefined;
191-
192-
mockedGetRegistryV01Servers.override((data, info) => {
193-
capturedUrl = info.request.url;
194-
return data;
195-
});
196-
197-
await getServers();
198-
199-
expect(capturedUrl).toContain("/registry/v0.1/servers");
200-
});
201-
202-
// Using overrideHandler - needed when response depends on request and may return different status codes
203-
it("can vary response based on request headers", async () => {
204-
mockedGetRegistryV01Servers.overrideHandler((data, info) => {
205-
const authHeader = info.request.headers.get("Authorization");
206-
if (authHeader?.includes("mock-token")) {
207-
return HttpResponse.json(data);
208-
}
209-
return HttpResponse.json({ error: "Unauthorized" }, { status: 401 });
210-
});
65+
// Demo: using .overrideHandler() for error status codes
66+
it("can use overrideHandler for custom error responses", async () => {
67+
mockedGetRegistryV01Servers.overrideHandler(() =>
68+
HttpResponse.json({ error: "Unauthorized" }, { status: 401 }),
69+
);
21170

212-
// Our mock provides "mock-token", so this should succeed
213-
const servers = await getServers();
214-
expect(servers.length).toBeGreaterThan(0);
215-
});
71+
await expect(getServers()).rejects.toBeDefined();
21672
});
21773
});

src/mocks/autoAPIMock.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ import type { HttpResponseResolver, JsonBodyType } from "msw";
22
import { HttpResponse } from "msw";
33
import type { MockScenarioName } from "./scenarioNames";
44

5+
const SCENARIO_HEADER = "x-mock-scenario";
6+
57
type ResponseResolverInfo = Parameters<HttpResponseResolver>[0];
68

79
type OverrideHandlerFn<T> = (data: T, info: ResponseResolverInfo) => Response;
@@ -42,6 +44,23 @@ export function AutoAPIMock<T>(defaultValue: T): AutoAPIMockInstance<T> {
4244
defaultValue,
4345

4446
generatedHandler(info: ResponseResolverInfo) {
47+
// Check for header-based scenario activation (for browser/dev testing)
48+
const headerScenario = info.request.headers.get(SCENARIO_HEADER);
49+
if (headerScenario) {
50+
const scenarioFn = scenarios.get(headerScenario as MockScenarioName);
51+
if (scenarioFn) {
52+
// Temporarily apply scenario and get the handler
53+
const previousHandler = overrideHandlerFn;
54+
scenarioFn(instance);
55+
const result = overrideHandlerFn
56+
? overrideHandlerFn(defaultValue, info)
57+
: HttpResponse.json(defaultValue as JsonBodyType);
58+
// Restore previous state
59+
overrideHandlerFn = previousHandler;
60+
return result;
61+
}
62+
}
63+
4564
if (overrideHandlerFn) {
4665
return overrideHandlerFn(defaultValue, info);
4766
}

src/mocks/handlers.ts

Lines changed: 2 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,11 @@
11
import type { RequestHandler } from "msw";
2-
import { HttpResponse } from "msw";
32
import { autoGeneratedHandlers } from "./mocker";
4-
import { mockScenario } from "./mockScenario";
53
import { serverDetailHandlers } from "./server-detail";
64

7-
// Scenario handlers (activate via cookie: mock-scenario=<name>)
8-
const scenarioHandlers = [
9-
mockScenario("empty-servers").get("*/registry/v0.1/servers", () => {
10-
return HttpResponse.json({ servers: [], metadata: { count: 0 } });
11-
}),
12-
mockScenario("server-error").get("*/registry/v0.1/servers", () => {
13-
return HttpResponse.json(
14-
{ error: "Internal Server Error" },
15-
{ status: 500 },
16-
);
17-
}),
18-
];
5+
// Scenarios are now handled via the x-mock-scenario header in AutoAPIMock.generatedHandler
6+
// See src/mocks/scenarioNames.ts for available scenarios
197

208
export const handlers: RequestHandler[] = [
21-
// Scenario handlers must come first (MSW uses first match)
22-
...scenarioHandlers,
239
...serverDetailHandlers,
2410
...autoGeneratedHandlers,
2511
];

0 commit comments

Comments
 (0)