Skip to content

Commit 9a04d30

Browse files
committed
chore: add mock for "no servers" example
1 parent b2f3e36 commit 9a04d30

File tree

4 files changed

+83
-4
lines changed

4 files changed

+83
-4
lines changed

src/lib/api-client.ts

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,16 @@
1313

1414
"use server";
1515

16-
import { headers as nextHeaders } from "next/headers";
16+
import { cookies, headers as nextHeaders } from "next/headers";
1717
import { redirect } from "next/navigation";
1818
import { createClient, createConfig } from "@/generated/client";
1919
import * as apiServices from "@/generated/sdk.gen";
2020
import { auth } from "./auth/auth";
2121
import { getValidOidcToken } from "./auth/token";
2222

23+
const MOCK_SCENARIO_COOKIE = "mock-scenario";
24+
const MOCK_SCENARIO_HEADER = "X-Mock-Scenario";
25+
2326
// Validate required environment variables at module load time (fail-fast)
2427
const API_BASE_URL = process.env.API_BASE_URL;
2528

@@ -65,13 +68,22 @@ export async function getAuthenticatedClient(accessToken?: string) {
6568
accessToken = token;
6669
}
6770

71+
// Check for mock scenario cookie (development only)
72+
const requestHeaders: Record<string, string> = {
73+
Authorization: `Bearer ${accessToken}`,
74+
};
75+
76+
const cookieStore = await cookies();
77+
const mockScenario = cookieStore.get(MOCK_SCENARIO_COOKIE)?.value;
78+
if (mockScenario) {
79+
requestHeaders[MOCK_SCENARIO_HEADER] = mockScenario;
80+
}
81+
6882
// Create a new client instance per request to avoid race conditions
6983
const authenticatedClient = createClient(
7084
createConfig({
7185
baseUrl: API_BASE_URL,
72-
headers: {
73-
Authorization: `Bearer ${accessToken}`,
74-
},
86+
headers: requestHeaders,
7587
}),
7688
);
7789

src/mocks/handlers.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,13 @@
11
import type { RequestHandler } from "msw";
22
import { autoGeneratedHandlers } from "./mocker";
3+
import { emptyServersHandlers } from "./scenarios/empty-servers";
34
import { serverDetailHandlers } from "./server-detail";
45

56
export const handlers: RequestHandler[] = [
7+
// Scenario handlers (cookie-activated) - must come first
8+
...emptyServersHandlers,
9+
// Custom handlers
610
...serverDetailHandlers,
11+
// Auto-generated handlers (fallback)
712
...autoGeneratedHandlers,
813
];

src/mocks/mockScenario.ts

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
import { type HttpHandler, http } from "msw";
2+
3+
type HttpMethod =
4+
| "get"
5+
| "post"
6+
| "put"
7+
| "patch"
8+
| "delete"
9+
| "head"
10+
| "options";
11+
12+
const SCENARIO_HEADER = "x-mock-scenario";
13+
14+
/**
15+
* Creates scenario-specific mock handlers that only activate when the X-Mock-Scenario header matches.
16+
* The header is set by the API client based on the "mock-scenario" cookie.
17+
*/
18+
export function mockScenario(
19+
scenario: string,
20+
): Record<HttpMethod, typeof http.get> {
21+
return new Proxy({} as Record<HttpMethod, typeof http.get>, {
22+
get(_, method: HttpMethod) {
23+
const httpMethod = http[method];
24+
if (typeof httpMethod !== "function") return undefined;
25+
26+
return (
27+
path: string,
28+
handler: Parameters<typeof httpMethod>[1],
29+
): HttpHandler =>
30+
httpMethod(path, (info) => {
31+
const headerValue = info.request.headers.get(SCENARIO_HEADER);
32+
console.log(
33+
`[mockScenario] ${method.toUpperCase()} ${info.request.url}`,
34+
`| header "${SCENARIO_HEADER}"="${headerValue}"`,
35+
`| expected="${scenario}"`,
36+
`| match=${headerValue === scenario}`,
37+
);
38+
39+
if (headerValue !== scenario) {
40+
return;
41+
}
42+
console.log(`[mockScenario] ACTIVATED scenario "${scenario}"`);
43+
return handler(info);
44+
});
45+
},
46+
});
47+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import { HttpResponse } from "msw";
2+
import { mockScenario } from "../mockScenario";
3+
4+
/**
5+
* Empty servers scenario - returns an empty list of servers.
6+
* Activate by setting cookie: mock-scenario=empty-servers
7+
*/
8+
export const emptyServersHandlers = [
9+
mockScenario("empty-servers").get("*/registry/v0.1/servers", () => {
10+
return HttpResponse.json({
11+
servers: [],
12+
metadata: { count: 0 },
13+
});
14+
}),
15+
];

0 commit comments

Comments
 (0)