Skip to content

Commit 4b5390b

Browse files
committed
test: enhance OptimizeController tests with comprehensive validation scenarios
1 parent adbb173 commit 4b5390b

File tree

2 files changed

+261
-12
lines changed

2 files changed

+261
-12
lines changed

src/controllers/metrics/metrics.controller.spec.ts

Lines changed: 48 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { Test, TestingModule } from "@nestjs/testing";
22
import { MetricsController } from "./metrics.controller";
3+
import { Response } from "express";
34

45
describe("MetricsController", () => {
56
let appController: MetricsController;
@@ -13,10 +14,53 @@ describe("MetricsController", () => {
1314
appController = app.get<MetricsController>(MetricsController);
1415
});
1516

16-
describe("root", () => {
17-
it('should return "Hello World!"', () => {
18-
expect(typeof appController).toBe("object");
19-
expect("Hello World!").toBe("Hello World!");
17+
describe("getMetrics", () => {
18+
it("should return metrics with correct content type and response", async () => {
19+
const mockSet = jest.fn().mockReturnThis();
20+
const mockSend = jest.fn().mockReturnThis();
21+
const mockResponse = {
22+
set: mockSet,
23+
send: mockSend,
24+
} as unknown as Response;
25+
26+
const result = await appController.getMetrics(mockResponse);
27+
28+
// Check that response methods are called correctly
29+
expect(mockSet).toHaveBeenCalledTimes(1);
30+
expect(mockSet).toHaveBeenCalledWith(
31+
"Content-Type",
32+
expect.stringContaining("text/plain"),
33+
);
34+
35+
expect(mockSend).toHaveBeenCalledTimes(1);
36+
37+
// Check that result contains Prometheus metrics
38+
expect(mockSend).toHaveBeenCalledWith(
39+
expect.stringContaining("# HELP"),
40+
);
41+
expect(mockSend).toHaveBeenCalledWith(
42+
expect.stringContaining("# TYPE"),
43+
);
44+
45+
// Check that metrics contain CPU and RAM consumption values
46+
expect(mockSend).toHaveBeenCalledWith(
47+
expect.stringContaining("process_cpu_user_seconds_total"),
48+
);
49+
expect(mockSend).toHaveBeenCalledWith(
50+
expect.stringContaining("process_cpu_system_seconds_total"),
51+
);
52+
expect(mockSend).toHaveBeenCalledWith(
53+
expect.stringContaining("process_resident_memory_bytes"),
54+
);
55+
expect(mockSend).toHaveBeenCalledWith(
56+
expect.stringContaining("nodejs_heap_size_total_bytes"),
57+
);
58+
expect(mockSend).toHaveBeenCalledWith(
59+
expect.stringContaining("nodejs_heap_size_used_bytes"),
60+
);
61+
62+
// Check method result
63+
expect(result).toBe(mockResponse);
2064
});
2165
});
2266
});
Lines changed: 213 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,231 @@
1-
import { AllowService } from "./../../services/allow.service";
2-
import { OptimizeService } from "./../../services/optimize.service";
31
import { Test, TestingModule } from "@nestjs/testing";
42
import { OptimizeController } from "./optimize.controller";
3+
import { OptimizeService } from "../../services/optimize.service";
4+
import { AllowService } from "../../services/allow.service";
55
import { ImgLoaderService } from "../../services/img-loader.service";
6+
import { BadRequestException } from "@nestjs/common";
7+
import { Response } from "express";
68

79
describe("OptimizeController", () => {
810
let optimizeController: OptimizeController;
11+
let allowService: AllowService;
912

1013
beforeEach(async () => {
14+
const mockAllowService = {
15+
isAllowedSources: jest.fn(),
16+
isAllowedSizes: jest.fn(),
17+
};
18+
19+
const mockImgLoaderService = {
20+
getImage: jest.fn(),
21+
};
22+
23+
const mockOptimizeService = {
24+
getOptimizedImage: jest.fn(),
25+
};
26+
1127
const app: TestingModule = await Test.createTestingModule({
1228
controllers: [OptimizeController],
13-
providers: [OptimizeService, AllowService, ImgLoaderService],
29+
providers: [
30+
{
31+
provide: OptimizeService,
32+
useValue: mockOptimizeService,
33+
},
34+
{
35+
provide: AllowService,
36+
useValue: mockAllowService,
37+
},
38+
{
39+
provide: ImgLoaderService,
40+
useValue: mockImgLoaderService,
41+
},
42+
],
1443
}).compile();
1544

1645
optimizeController = app.get<OptimizeController>(OptimizeController);
46+
allowService = app.get<AllowService>(AllowService);
1747
});
1848

19-
describe("root", () => {
20-
it('should return "Hello World!"', () => {
21-
// write tests later
22-
expect(optimizeController).toBeInstanceOf(OptimizeController);
23-
expect("Hello World!").toBe("Hello World!");
49+
describe("getPreview - negative scenarios for query parameters", () => {
50+
let mockResponse: Partial<Response>;
51+
52+
beforeEach(() => {
53+
mockResponse = {
54+
setHeader: jest.fn().mockReturnThis(),
55+
status: jest.fn().mockReturnThis(),
56+
send: jest.fn(),
57+
};
58+
});
59+
60+
it("should throw BadRequestException if src parameter is missing", async () => {
61+
await expect(
62+
optimizeController.getPreview(
63+
"",
64+
"1920",
65+
"jpeg",
66+
"80",
67+
mockResponse as Response,
68+
),
69+
).rejects.toThrow(
70+
new BadRequestException("Parameter 'src' is required."),
71+
);
72+
});
73+
74+
it("should throw BadRequestException if size parameter is missing", async () => {
75+
await expect(
76+
optimizeController.getPreview(
77+
"https://example.com/image.jpg",
78+
"",
79+
"jpeg",
80+
"80",
81+
mockResponse as Response,
82+
),
83+
).rejects.toThrow(
84+
new BadRequestException("Parameter 'size' is required."),
85+
);
86+
});
87+
88+
it("should throw BadRequestException if size is zero", async () => {
89+
await expect(
90+
optimizeController.getPreview(
91+
"https://example.com/image.jpg",
92+
"0",
93+
"jpeg",
94+
"80",
95+
mockResponse as Response,
96+
),
97+
).rejects.toThrow(
98+
new BadRequestException(
99+
"Parameter 'size' should be a positive integer.",
100+
),
101+
);
102+
});
103+
104+
it("should throw BadRequestException if size is negative", async () => {
105+
await expect(
106+
optimizeController.getPreview(
107+
"https://example.com/image.jpg",
108+
"-100",
109+
"jpeg",
110+
"80",
111+
mockResponse as Response,
112+
),
113+
).rejects.toThrow(
114+
new BadRequestException(
115+
"Parameter 'size' should be a positive integer.",
116+
),
117+
);
118+
});
119+
120+
it("should throw BadRequestException if format parameter is missing", async () => {
121+
await expect(
122+
optimizeController.getPreview(
123+
"https://example.com/image.jpg",
124+
"1920",
125+
"",
126+
"80",
127+
mockResponse as Response,
128+
),
129+
).rejects.toThrow(
130+
new BadRequestException("Parameter 'format' is required."),
131+
);
132+
});
133+
134+
it("should throw BadRequestException if format is not supported", async () => {
135+
await expect(
136+
optimizeController.getPreview(
137+
"https://example.com/image.jpg",
138+
"1920",
139+
"gif",
140+
"80",
141+
mockResponse as Response,
142+
),
143+
).rejects.toThrow(
144+
new BadRequestException("Parameter 'format' is not supported."),
145+
);
146+
});
147+
148+
it("should throw BadRequestException if quality is not a number", async () => {
149+
await expect(
150+
optimizeController.getPreview(
151+
"https://example.com/image.jpg",
152+
"1920",
153+
"jpeg",
154+
"abc",
155+
mockResponse as Response,
156+
),
157+
).rejects.toThrow(
158+
new BadRequestException("Parameter 'quality' is not a number."),
159+
);
160+
});
161+
162+
it("should throw BadRequestException if quality is less than 1", async () => {
163+
await expect(
164+
optimizeController.getPreview(
165+
"https://example.com/image.jpg",
166+
"1920",
167+
"jpeg",
168+
"0",
169+
mockResponse as Response,
170+
),
171+
).rejects.toThrow(
172+
new BadRequestException(
173+
"Parameter 'quality' must be in range 1-100.",
174+
),
175+
);
176+
});
177+
178+
it("should throw BadRequestException if quality is greater than 100", async () => {
179+
await expect(
180+
optimizeController.getPreview(
181+
"https://example.com/image.jpg",
182+
"1920",
183+
"jpeg",
184+
"101",
185+
mockResponse as Response,
186+
),
187+
).rejects.toThrow(
188+
new BadRequestException(
189+
"Parameter 'quality' must be in range 1-100.",
190+
),
191+
);
192+
});
193+
194+
it("should throw BadRequestException if src is not allowed", async () => {
195+
(allowService.isAllowedSources as jest.Mock).mockReturnValue(false);
196+
197+
await expect(
198+
optimizeController.getPreview(
199+
"https://malicious.com/image.jpg",
200+
"1920",
201+
"jpeg",
202+
"80",
203+
mockResponse as Response,
204+
),
205+
).rejects.toThrow(
206+
new BadRequestException(
207+
"Parameter 'src' has an not allowed value.",
208+
),
209+
);
210+
});
211+
212+
it("should throw BadRequestException if size is not allowed", async () => {
213+
(allowService.isAllowedSources as jest.Mock).mockReturnValue(true);
214+
(allowService.isAllowedSizes as jest.Mock).mockReturnValue(false);
215+
216+
await expect(
217+
optimizeController.getPreview(
218+
"https://example.com/image.jpg",
219+
"5000",
220+
"jpeg",
221+
"80",
222+
mockResponse as Response,
223+
),
224+
).rejects.toThrow(
225+
new BadRequestException(
226+
"Parameter 'size' has an not allowed value.",
227+
),
228+
);
24229
});
25230
});
26231
});

0 commit comments

Comments
 (0)