Skip to content

Commit 7713dc1

Browse files
author
RahulTinku
committed
feat: test cases for fastify 5
1 parent 9775502 commit 7713dc1

5 files changed

Lines changed: 341 additions & 6 deletions

File tree

README.md

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -212,7 +212,6 @@ Configure electrode provided options.
212212
- A function to install event listeners for the electrode server startup lifecycle.
213213

214214
- The following events are supported:
215-
216215
- `config-composed` - All configurations have been composed into a single one
217216
- `server-created` - Fastify server created
218217
- `plugins-sorted` - Plugins processed and sorted by priority
@@ -450,11 +449,9 @@ The electrode server exports a single API.
450449

451450
- `config` is the [electrode server config](#configuration-options)
452451
- `decors` - Optional extra `config` or array of `config`. In case you have common config you want to put inside a dedicated module, you can pass them in here.
453-
454452
- If it's an array like `[ decor1, decor2, decor3 ]` then each one is composed into the main config. ie: something similar to `_.merge(mainConfig, decor1, decor2, decor3)`.
455453

456454
- `callback` is an optional errback with the signature `function (err, server)`
457-
458455
- where `server` is the Fastify server
459456

460457
- **Returns:** a promise resolving to the Fastify server if callback is not provided
@@ -496,7 +493,7 @@ identity (no compression)
496493

497494
```js
498495
server: {
499-
bodyLimit: 1048576 // new size limit in bytes (1MB)
496+
bodyLimit: 1048576; // new size limit in bytes (1MB)
500497
}
501498
```
502499

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@
7171
"@types/node": "^22.0.0",
7272
"@typescript-eslint/eslint-plugin": "^5.0.0",
7373
"@typescript-eslint/parser": "^5.0.0",
74+
"@xarc/run": "^2.2.0",
7475
"eslint": "^7.16.0",
7576
"eslint-config-walmart": "^2.2.1",
7677
"eslint-plugin-filenames": "^1.1.0",

src/types.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -208,7 +208,7 @@ export type ElectrodeServerConfig = {
208208
* - `requestIdHeader` now defaults to `false` instead of `"request-id"`
209209
* - Router options like `maxParamLength`, `ignoreTrailingSlash`, etc. should be
210210
* moved under `routerOptions` to avoid deprecation warnings
211-
* - Example:
211+
* - Example:
212212
* ```js
213213
* {
214214
* server: {

test/spec/check-node-env.spec.ts

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,18 @@ describe("process-env-abbr", function () {
2121
checkNodeEnv();
2222
});
2323

24+
it("should do nothing for undefined NODE_ENV", function () {
25+
delete process.env.NODE_ENV;
26+
checkNodeEnv();
27+
});
28+
29+
it("should do nothing for null NODE_ENV", function () {
30+
process.env.NODE_ENV = null as any;
31+
checkNodeEnv();
32+
});
33+
2434
it("should do nothing for full NODE_ENV", function () {
25-
["production", "staging", "development"].forEach(x => {
35+
["production", "staging", "development", "qa", "test"].forEach(x => {
2636
process.env.NODE_ENV = x;
2737
checkNodeEnv();
2838
});

test/spec/fastify5-config.spec.ts

Lines changed: 327 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,327 @@
1+
// Test to verify Fastify 5 configuration and plugin compatibility
2+
import { electrodeServer } from "../../src/electrode-server";
3+
import { ElectrodeFastifyInstance } from "../../src/types";
4+
5+
describe("Fastify 5 Compatibility", () => {
6+
let server: ElectrodeFastifyInstance | undefined;
7+
8+
afterEach(async () => {
9+
if (server) {
10+
await server.close();
11+
server = undefined;
12+
}
13+
});
14+
15+
describe("Migration Verification", () => {
16+
it("should use Fastify 5.x", async () => {
17+
server = await electrodeServer({
18+
deferStart: true,
19+
connection: {
20+
port: 0 // Use random port
21+
},
22+
plugins: {}
23+
});
24+
25+
expect(server.version).toMatch(/^5\./);
26+
expect(server.version).toBe("5.6.1");
27+
});
28+
29+
it("should work with Fastify 5 plugin system", async () => {
30+
const pluginCalled = jest.fn();
31+
32+
server = await electrodeServer({
33+
deferStart: true,
34+
connection: {
35+
port: 0
36+
},
37+
plugins: {
38+
testPlugin: {
39+
register: async fastify => {
40+
pluginCalled();
41+
fastify.get("/test-plugin", async () => {
42+
return { message: "Plugin working with Fastify 5" };
43+
});
44+
}
45+
}
46+
}
47+
});
48+
49+
await server.start();
50+
51+
expect(pluginCalled).toHaveBeenCalled();
52+
53+
const response = await server.inject({
54+
method: "GET",
55+
url: "/test-plugin"
56+
});
57+
58+
expect(response.statusCode).toBe(200);
59+
expect(JSON.parse(response.body)).toEqual({
60+
message: "Plugin working with Fastify 5"
61+
});
62+
});
63+
64+
it("should handle Node.js 20+ features", async () => {
65+
// Verify we're running on Node 20+
66+
const nodeVersion = process.version;
67+
const majorVersion = parseInt(nodeVersion.split(".")[0].substring(1), 10);
68+
expect(majorVersion).toBeGreaterThanOrEqual(20);
69+
70+
server = await electrodeServer({
71+
deferStart: true,
72+
connection: {
73+
port: 0
74+
},
75+
plugins: {}
76+
});
77+
78+
// Test that the server starts and works properly
79+
await server.start();
80+
expect(server.info.port).toBeGreaterThan(0);
81+
});
82+
83+
it("should maintain compatibility with existing decorator patterns", async () => {
84+
server = await electrodeServer({
85+
deferStart: true,
86+
connection: {
87+
port: 0
88+
},
89+
plugins: {}
90+
});
91+
92+
// Test that all the custom decorators still work
93+
expect(server.app).toBeDefined();
94+
expect(server.app.config).toBeDefined();
95+
expect(server.info).toBeDefined();
96+
expect(server.start).toBeDefined();
97+
expect(typeof server.start).toBe("function");
98+
});
99+
});
100+
101+
describe("Configuration Compatibility", () => {
102+
it("should handle all common FastifyServerOptions with Fastify 5", async () => {
103+
server = await electrodeServer({
104+
deferStart: true,
105+
connection: {
106+
port: 0
107+
},
108+
server: {
109+
// Test common Fastify server options that might have changed
110+
logger: false,
111+
disableRequestLogging: true,
112+
bodyLimit: 1048576,
113+
connectionTimeout: 0,
114+
keepAliveTimeout: 72000,
115+
forceCloseConnections: false,
116+
requestIdHeader: false, // This changed default in Fastify 5
117+
requestIdLogLabel: "reqId",
118+
http2: false,
119+
https: false,
120+
maxRequestsPerSocket: 0,
121+
requestTimeout: 0,
122+
pluginTimeout: 10000,
123+
trustProxy: false,
124+
// Router options should be under routerOptions in newer versions
125+
routerOptions: {
126+
maxParamLength: 1000,
127+
ignoreTrailingSlash: false,
128+
ignoreDuplicateSlashes: false,
129+
caseSensitive: true,
130+
allowUnsafeRegex: false
131+
}
132+
}
133+
});
134+
135+
expect(server.version).toMatch(/^5\./);
136+
await server.start();
137+
expect(server.info.port).toBeGreaterThan(0);
138+
});
139+
140+
it("should handle logger configuration with Fastify 5", async () => {
141+
server = await electrodeServer({
142+
deferStart: true,
143+
connection: {
144+
port: 0
145+
},
146+
server: {
147+
logger: {
148+
level: "warn",
149+
serializers: {
150+
req: false,
151+
res: false
152+
}
153+
}
154+
}
155+
});
156+
157+
expect(server.version).toMatch(/^5\./);
158+
await server.start();
159+
});
160+
161+
it("should work with requestIdHeader set to false (Fastify 5 default)", async () => {
162+
server = await electrodeServer({
163+
deferStart: true,
164+
connection: {
165+
port: 0
166+
},
167+
server: {
168+
requestIdHeader: false // This is now the default in Fastify 5
169+
}
170+
});
171+
172+
await server.start();
173+
174+
const response = await server.inject({
175+
method: "GET",
176+
url: "/non-existent-route"
177+
});
178+
179+
// Should not have a request-id header by default
180+
expect(response.headers["request-id"]).toBeUndefined();
181+
});
182+
183+
it("should still work with requestIdHeader enabled", async () => {
184+
server = await electrodeServer({
185+
deferStart: true,
186+
connection: {
187+
port: 0
188+
},
189+
server: {
190+
requestIdHeader: "x-request-id"
191+
},
192+
plugins: {
193+
testRoute: {
194+
register: async fastify => {
195+
fastify.get("/test-req-id", async request => {
196+
return { requestId: request.id };
197+
});
198+
}
199+
}
200+
}
201+
});
202+
203+
await server.start();
204+
205+
const response = await server.inject({
206+
method: "GET",
207+
url: "/test-req-id"
208+
});
209+
210+
// Check that the request ID was generated and returned
211+
const body = JSON.parse(response.body);
212+
expect(body.requestId).toBeDefined();
213+
expect(typeof body.requestId).toBe("string");
214+
});
215+
216+
it("should handle new Fastify 5 options if any", async () => {
217+
server = await electrodeServer({
218+
deferStart: true,
219+
connection: {
220+
port: 0
221+
},
222+
server: {
223+
// Any new Fastify 5 specific options would go here
224+
// Currently testing that it doesn't break with standard options
225+
jsonShorthand: true,
226+
ajv: {
227+
customOptions: {
228+
coerceTypes: "array"
229+
}
230+
}
231+
}
232+
});
233+
234+
expect(server.version).toMatch(/^5\./);
235+
await server.start();
236+
});
237+
});
238+
239+
describe("Plugin Registration Compatibility", () => {
240+
it("should handle plugin registration with .after() pattern in Fastify 5", async () => {
241+
let pluginExecuted = false;
242+
let afterExecuted = false;
243+
244+
server = await electrodeServer({
245+
deferStart: true,
246+
connection: {
247+
port: 0
248+
},
249+
plugins: {
250+
testPlugin: {
251+
register: async fastify => {
252+
pluginExecuted = true;
253+
254+
// Add a simple route to verify the plugin works
255+
fastify.get("/test-after", async () => {
256+
return { message: "Plugin with .after() works in Fastify 5" };
257+
});
258+
259+
// Test that we can use .after() functionality
260+
fastify.after(() => {
261+
afterExecuted = true;
262+
});
263+
},
264+
options: {}
265+
}
266+
}
267+
});
268+
269+
expect(pluginExecuted).toBe(true);
270+
271+
await server.start();
272+
273+
// Test the route works
274+
const response = await server.inject({
275+
method: "GET",
276+
url: "/test-after"
277+
});
278+
279+
expect(response.statusCode).toBe(200);
280+
expect(JSON.parse(response.body)).toEqual({
281+
message: "Plugin with .after() works in Fastify 5"
282+
});
283+
284+
// Verify .after() was called
285+
expect(afterExecuted).toBe(true);
286+
});
287+
288+
it("should handle multiple plugins with .after() callbacks", async () => {
289+
const pluginOrder: string[] = [];
290+
291+
server = await electrodeServer({
292+
deferStart: true,
293+
connection: {
294+
port: 0
295+
},
296+
plugins: {
297+
firstPlugin: {
298+
priority: 1,
299+
register: async fastify => {
300+
pluginOrder.push("first-register");
301+
fastify.after(() => {
302+
pluginOrder.push("first-after");
303+
});
304+
}
305+
},
306+
secondPlugin: {
307+
priority: 2,
308+
register: async fastify => {
309+
pluginOrder.push("second-register");
310+
fastify.after(() => {
311+
pluginOrder.push("second-after");
312+
});
313+
}
314+
}
315+
}
316+
});
317+
318+
await server.start();
319+
320+
// Verify the execution order
321+
expect(pluginOrder).toContain("first-register");
322+
expect(pluginOrder).toContain("second-register");
323+
expect(pluginOrder).toContain("first-after");
324+
expect(pluginOrder).toContain("second-after");
325+
});
326+
});
327+
});

0 commit comments

Comments
 (0)