Skip to content

Commit c51bf71

Browse files
authored
Merge pull request #76 from jaredwray/feat-adding-in-html-endpoint
feat: adding in html endpoint
2 parents 05244a7 + 3ae0fb5 commit c51bf71

3 files changed

Lines changed: 215 additions & 4 deletions

File tree

package.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,12 +41,12 @@
4141
"homepage": "https://github.com/jaredwray/mockhttp#readme",
4242
"devDependencies": {
4343
"@biomejs/biome": "^2.2.2",
44-
"@swc/core": "^1.13.4",
44+
"@swc/core": "^1.13.5",
4545
"@types/html-escaper": "^3.0.4",
4646
"@vitest/coverage-v8": "^3.2.4",
4747
"rimraf": "^6.0.1",
4848
"tsup": "^8.5.0",
49-
"tsx": "^4.20.4",
49+
"tsx": "^4.20.5",
5050
"typescript": "^5.9.2",
5151
"vitest": "^3.2.4"
5252
},
@@ -56,7 +56,7 @@
5656
"@fastify/static": "^8.2.0",
5757
"@fastify/swagger": "^9.5.1",
5858
"@fastify/swagger-ui": "^5.2.3",
59-
"@scalar/api-reference": "^1.34.4",
59+
"@scalar/api-reference": "^1.34.6",
6060
"detect-port": "^2.1.0",
6161
"fastify": "^5.5.0",
6262
"hookified": "^1.12.0",

src/routes/response-inspection/plain.ts

Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,19 @@ const textSchema: FastifySchema = {
2626
},
2727
};
2828

29+
const htmlSchema: FastifySchema = {
30+
description: "Returns random HTML content",
31+
tags: ["Response Inspection"],
32+
// @ts-expect-error
33+
response: {
34+
// eslint-disable-next-line @typescript-eslint/naming-convention
35+
200: {
36+
type: "string",
37+
description: "Random HTML content",
38+
},
39+
},
40+
};
41+
2942
const randomTexts = [
3043
"The quick brown fox jumps over the lazy dog.",
3144
"Lorem ipsum dolor sit amet, consectetur adipiscing elit.",
@@ -39,6 +52,93 @@ const randomTexts = [
3952
"Knowledge is power. France is bacon.",
4053
];
4154

55+
const randomHtmlContent = [
56+
`<!DOCTYPE html>
57+
<html lang="en">
58+
<head>
59+
<title>Sample Page</title>
60+
</head>
61+
<body>
62+
<h1>Welcome to MockHTTP</h1>
63+
<p>This is a sample HTML page with random content.</p>
64+
</body>
65+
</html>`,
66+
`<!DOCTYPE html>
67+
<html>
68+
<head>
69+
<meta charset="UTF-8">
70+
<title>Test Document</title>
71+
</head>
72+
<body>
73+
<header>
74+
<h1>Test Page</h1>
75+
<nav>
76+
<ul>
77+
<li><a href="#">Home</a></li>
78+
<li><a href="#">About</a></li>
79+
<li><a href="#">Contact</a></li>
80+
</ul>
81+
</nav>
82+
</header>
83+
<main>
84+
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p>
85+
</main>
86+
</body>
87+
</html>`,
88+
`<!DOCTYPE html>
89+
<html lang="en">
90+
<head>
91+
<title>Article Page</title>
92+
<style>
93+
body { font-family: Arial, sans-serif; }
94+
article { max-width: 800px; margin: 0 auto; }
95+
</style>
96+
</head>
97+
<body>
98+
<article>
99+
<h1>The Journey Begins</h1>
100+
<p>Once upon a time in a digital world...</p>
101+
<blockquote>
102+
"The only way to do great work is to love what you do."
103+
</blockquote>
104+
</article>
105+
</body>
106+
</html>`,
107+
`<!DOCTYPE html>
108+
<html>
109+
<head>
110+
<title>Form Example</title>
111+
</head>
112+
<body>
113+
<h2>Contact Form</h2>
114+
<form action="/submit" method="post">
115+
<label for="name">Name:</label>
116+
<input type="text" id="name" name="name" required>
117+
<br>
118+
<label for="email">Email:</label>
119+
<input type="email" id="email" name="email" required>
120+
<br>
121+
<button type="submit">Submit</button>
122+
</form>
123+
</body>
124+
</html>`,
125+
`<!DOCTYPE html>
126+
<html lang="en">
127+
<head>
128+
<meta charset="UTF-8">
129+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
130+
<title>Responsive Page</title>
131+
</head>
132+
<body>
133+
<div class="container">
134+
<h1>Responsive Design</h1>
135+
<p>This page adapts to different screen sizes.</p>
136+
<img src="placeholder.jpg" alt="Placeholder" style="max-width: 100%; height: auto;">
137+
</div>
138+
</body>
139+
</html>`,
140+
];
141+
42142
export const plainRoute = (fastify: FastifyInstance) => {
43143
// @ts-expect-error
44144
fastify.get(
@@ -67,4 +167,18 @@ export const plainRoute = (fastify: FastifyInstance) => {
67167
return text;
68168
},
69169
);
170+
171+
// @ts-expect-error
172+
fastify.get(
173+
"/html",
174+
{ schema: htmlSchema },
175+
// biome-ignore lint/suspicious/noExplicitAny: reply
176+
async (_request: FastifyRequest, reply: any) => {
177+
const randomIndex = Math.floor(Math.random() * randomHtmlContent.length);
178+
const html = randomHtmlContent[randomIndex];
179+
180+
reply.type("text/html");
181+
return html;
182+
},
183+
);
70184
};

test/routes/response-inspection/plain.test.ts

Lines changed: 98 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import Fastify from "fastify";
22
import { afterAll, beforeAll, describe, expect, it } from "vitest";
33
import { plainRoute } from "../../../src/routes/response-inspection/index.js";
44

5-
describe("Plain and Text Routes", () => {
5+
describe("Plain, Text, and HTML Routes", () => {
66
// eslint-disable-next-line new-cap
77
const fastify = Fastify();
88

@@ -185,4 +185,101 @@ describe("Plain and Text Routes", () => {
185185
expect(response.body).not.toContain('"text"');
186186
});
187187
});
188+
189+
// Tests for /html endpoint
190+
describe("/html endpoint", () => {
191+
it("should return HTML with correct content type", async () => {
192+
const response = await fastify.inject({
193+
method: "GET",
194+
url: "/html",
195+
});
196+
197+
expect(response.statusCode).toBe(200);
198+
expect(response.headers["content-type"]).toContain("text/html");
199+
expect(typeof response.body).toBe("string");
200+
expect(response.body.length).toBeGreaterThan(0);
201+
});
202+
203+
it("should return valid HTML document", async () => {
204+
const response = await fastify.inject({
205+
method: "GET",
206+
url: "/html",
207+
});
208+
209+
// Check for HTML document structure
210+
expect(response.body).toContain("<!DOCTYPE html");
211+
expect(response.body).toContain("<html");
212+
expect(response.body).toContain("</html>");
213+
expect(response.body).toContain("<head");
214+
expect(response.body).toContain("</head>");
215+
expect(response.body).toContain("<body");
216+
expect(response.body).toContain("</body>");
217+
});
218+
219+
it("should return one of the predefined HTML templates", async () => {
220+
const response = await fastify.inject({
221+
method: "GET",
222+
url: "/html",
223+
});
224+
225+
// Check that response contains at least one of the expected titles
226+
const expectedTitles = [
227+
"<title>Sample Page</title>",
228+
"<title>Test Document</title>",
229+
"<title>Article Page</title>",
230+
"<title>Form Example</title>",
231+
"<title>Responsive Page</title>",
232+
];
233+
234+
const containsExpectedTitle = expectedTitles.some((title) =>
235+
response.body.includes(title),
236+
);
237+
expect(containsExpectedTitle).toBe(true);
238+
});
239+
240+
it("should return different HTML on multiple requests", async () => {
241+
const responses = new Set();
242+
const numberOfRequests = 20;
243+
244+
for (let i = 0; i < numberOfRequests; i++) {
245+
const response = await fastify.inject({
246+
method: "GET",
247+
url: "/html",
248+
});
249+
responses.add(response.body);
250+
}
251+
252+
// With 5 HTML templates and 20 requests, we should get at least 2 different templates
253+
expect(responses.size).toBeGreaterThanOrEqual(2);
254+
});
255+
256+
it("should handle the random index calculation correctly for HTML", async () => {
257+
const requests = 100;
258+
259+
for (let i = 0; i < requests; i++) {
260+
const response = await fastify.inject({
261+
method: "GET",
262+
url: "/html",
263+
});
264+
265+
expect(response.statusCode).toBe(200);
266+
expect(response.body).toBeTruthy();
267+
expect(response.headers["content-type"]).toContain("text/html");
268+
expect(response.body).toContain("<!DOCTYPE html");
269+
}
270+
});
271+
272+
it("should return HTML without being wrapped in JSON", async () => {
273+
const response = await fastify.inject({
274+
method: "GET",
275+
url: "/html",
276+
});
277+
278+
// Should not be valid JSON
279+
expect(() => JSON.parse(response.body)).toThrow();
280+
281+
// Should be raw HTML
282+
expect(response.body.startsWith("<!DOCTYPE html")).toBe(true);
283+
});
284+
});
188285
});

0 commit comments

Comments
 (0)