Skip to content

Commit 5d5e42c

Browse files
committed
feat: adding in plain endpoint
1 parent f7c5dc9 commit 5d5e42c

4 files changed

Lines changed: 155 additions & 0 deletions

File tree

src/mock-http.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ import {
4040
import {
4141
cacheRoutes,
4242
etagRoutes,
43+
plainRoute,
4344
responseHeadersRoutes,
4445
} from "./routes/response-inspection/index.js";
4546
import { sitemapRoute } from "./routes/sitemap.js";
@@ -424,6 +425,7 @@ export class MockHttp extends Hookified {
424425
const fastify = fastifyInstance ?? this._server;
425426
await fastify.register(cacheRoutes);
426427
await fastify.register(etagRoutes);
428+
await fastify.register(plainRoute);
427429
await fastify.register(responseHeadersRoutes);
428430
}
429431

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
export { cacheRoutes } from "./cache.js";
22
export { etagRoutes } from "./etag.js";
3+
export { plainRoute } from "./plain.js";
34
export { responseHeadersRoutes } from "./response-headers.js";
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
import type { FastifyInstance, FastifyRequest, FastifySchema } from "fastify";
2+
3+
const plainSchema: FastifySchema = {
4+
description: "Returns random plain text content",
5+
tags: ["Response Inspection"],
6+
// @ts-expect-error
7+
response: {
8+
// eslint-disable-next-line @typescript-eslint/naming-convention
9+
200: {
10+
type: "string",
11+
description: "Random plain text content",
12+
},
13+
},
14+
};
15+
16+
const randomTexts = [
17+
"The quick brown fox jumps over the lazy dog.",
18+
"Lorem ipsum dolor sit amet, consectetur adipiscing elit.",
19+
"To be or not to be, that is the question.",
20+
"All work and no play makes Jack a dull boy.",
21+
"The only way to do great work is to love what you do.",
22+
"In the beginning was the Word, and the Word was with God.",
23+
"Once upon a time in a galaxy far, far away...",
24+
"It was the best of times, it was the worst of times.",
25+
"The journey of a thousand miles begins with a single step.",
26+
"Knowledge is power. France is bacon.",
27+
];
28+
29+
export const plainRoute = (fastify: FastifyInstance) => {
30+
// @ts-expect-error
31+
fastify.get(
32+
"/plain",
33+
{ schema: plainSchema },
34+
// biome-ignore lint/suspicious/noExplicitAny: reply
35+
async (_request: FastifyRequest, reply: any) => {
36+
const randomIndex = Math.floor(Math.random() * randomTexts.length);
37+
const text = randomTexts[randomIndex];
38+
39+
reply.type("text/plain");
40+
return text;
41+
},
42+
);
43+
};
Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
import Fastify from "fastify";
2+
import { afterAll, beforeAll, describe, expect, it } from "vitest";
3+
import { plainRoute } from "../../../src/routes/response-inspection/index.js";
4+
5+
describe("Plain Text Route", () => {
6+
// eslint-disable-next-line new-cap
7+
const fastify = Fastify();
8+
9+
beforeAll(async () => {
10+
await fastify.register(plainRoute);
11+
});
12+
13+
afterAll(async () => {
14+
await fastify.close();
15+
});
16+
17+
it("should return plain text with correct content type", async () => {
18+
const response = await fastify.inject({
19+
method: "GET",
20+
url: "/plain",
21+
});
22+
23+
expect(response.statusCode).toBe(200);
24+
expect(response.headers["content-type"]).toContain("text/plain");
25+
expect(typeof response.body).toBe("string");
26+
expect(response.body.length).toBeGreaterThan(0);
27+
});
28+
29+
it("should return one of the predefined random texts", async () => {
30+
const expectedTexts = [
31+
"The quick brown fox jumps over the lazy dog.",
32+
"Lorem ipsum dolor sit amet, consectetur adipiscing elit.",
33+
"To be or not to be, that is the question.",
34+
"All work and no play makes Jack a dull boy.",
35+
"The only way to do great work is to love what you do.",
36+
"In the beginning was the Word, and the Word was with God.",
37+
"Once upon a time in a galaxy far, far away...",
38+
"It was the best of times, it was the worst of times.",
39+
"The journey of a thousand miles begins with a single step.",
40+
"Knowledge is power. France is bacon.",
41+
];
42+
43+
const response = await fastify.inject({
44+
method: "GET",
45+
url: "/plain",
46+
});
47+
48+
expect(expectedTexts).toContain(response.body);
49+
});
50+
51+
it("should return different texts on multiple requests (randomness test)", async () => {
52+
const responses = new Set();
53+
const numberOfRequests = 20;
54+
55+
for (let i = 0; i < numberOfRequests; i++) {
56+
const response = await fastify.inject({
57+
method: "GET",
58+
url: "/plain",
59+
});
60+
responses.add(response.body);
61+
}
62+
63+
// With 10 possible texts and 20 requests, we should get at least 2 different texts
64+
// This is a probabilistic test but the chance of failure is extremely low
65+
expect(responses.size).toBeGreaterThanOrEqual(2);
66+
});
67+
68+
it("should handle the random index calculation correctly", async () => {
69+
// This test verifies that the endpoint doesn't crash regardless of Math.random() output
70+
// We'll make multiple requests to ensure stability
71+
const requests = 100;
72+
73+
for (let i = 0; i < requests; i++) {
74+
const response = await fastify.inject({
75+
method: "GET",
76+
url: "/plain",
77+
});
78+
79+
expect(response.statusCode).toBe(200);
80+
expect(response.body).toBeTruthy();
81+
expect(response.headers["content-type"]).toContain("text/plain");
82+
}
83+
});
84+
85+
it("should set reply type to text/plain", async () => {
86+
const response = await fastify.inject({
87+
method: "GET",
88+
url: "/plain",
89+
});
90+
91+
// Verify that the content-type header is set correctly
92+
expect(response.headers["content-type"]).toContain("text/plain");
93+
});
94+
95+
it("should return the selected text directly without JSON wrapping", async () => {
96+
const response = await fastify.inject({
97+
method: "GET",
98+
url: "/plain",
99+
});
100+
101+
// Ensure the response is plain text, not JSON
102+
expect(() => JSON.parse(response.body)).toThrow();
103+
104+
// Ensure the response doesn't contain JSON-like structures
105+
expect(response.body).not.toContain("{");
106+
expect(response.body).not.toContain("}");
107+
expect(response.body).not.toContain('"text"');
108+
});
109+
});

0 commit comments

Comments
 (0)