mcp4openapi 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE.md +7 -0
- package/README.md +489 -0
- package/dist/composite-executor.d.ts +65 -0
- package/dist/composite-executor.d.ts.map +1 -0
- package/dist/composite-executor.js +147 -0
- package/dist/composite-executor.js.map +1 -0
- package/dist/constants.d.ts +36 -0
- package/dist/constants.d.ts.map +1 -0
- package/dist/constants.js +36 -0
- package/dist/constants.js.map +1 -0
- package/dist/http-transport.d.ts +195 -0
- package/dist/http-transport.d.ts.map +1 -0
- package/dist/http-transport.js +760 -0
- package/dist/http-transport.js.map +1 -0
- package/dist/interceptors.d.ts +74 -0
- package/dist/interceptors.d.ts.map +1 -0
- package/dist/interceptors.js +220 -0
- package/dist/interceptors.js.map +1 -0
- package/dist/logger.d.ts +81 -0
- package/dist/logger.d.ts.map +1 -0
- package/dist/logger.js +264 -0
- package/dist/logger.js.map +1 -0
- package/dist/mcp-server.d.ts +110 -0
- package/dist/mcp-server.d.ts.map +1 -0
- package/dist/mcp-server.js +568 -0
- package/dist/mcp-server.js.map +1 -0
- package/dist/metrics.d.ts +86 -0
- package/dist/metrics.d.ts.map +1 -0
- package/dist/metrics.js +229 -0
- package/dist/metrics.js.map +1 -0
- package/dist/openapi-parser.d.ts +35 -0
- package/dist/openapi-parser.d.ts.map +1 -0
- package/dist/openapi-parser.js +160 -0
- package/dist/openapi-parser.js.map +1 -0
- package/dist/profile-loader.d.ts +25 -0
- package/dist/profile-loader.d.ts.map +1 -0
- package/dist/profile-loader.js +134 -0
- package/dist/profile-loader.js.map +1 -0
- package/dist/schema-validator.d.ts +32 -0
- package/dist/schema-validator.d.ts.map +1 -0
- package/dist/schema-validator.js +126 -0
- package/dist/schema-validator.js.map +1 -0
- package/dist/scripts/validate-profile.d.ts +9 -0
- package/dist/scripts/validate-profile.d.ts.map +1 -0
- package/dist/scripts/validate-profile.js +289 -0
- package/dist/scripts/validate-profile.js.map +1 -0
- package/dist/scripts/validate-schema.d.ts +9 -0
- package/dist/scripts/validate-schema.d.ts.map +1 -0
- package/dist/scripts/validate-schema.js +84 -0
- package/dist/scripts/validate-schema.js.map +1 -0
- package/dist/src/composite-executor.d.ts +75 -0
- package/dist/src/composite-executor.d.ts.map +1 -0
- package/dist/src/composite-executor.js +175 -0
- package/dist/src/composite-executor.js.map +1 -0
- package/dist/src/constants.d.ts +36 -0
- package/dist/src/constants.d.ts.map +1 -0
- package/dist/src/constants.js +36 -0
- package/dist/src/constants.js.map +1 -0
- package/dist/src/dag-executor.d.ts +49 -0
- package/dist/src/dag-executor.d.ts.map +1 -0
- package/dist/src/dag-executor.js +138 -0
- package/dist/src/dag-executor.js.map +1 -0
- package/dist/src/errors.d.ts +47 -0
- package/dist/src/errors.d.ts.map +1 -0
- package/dist/src/errors.js +99 -0
- package/dist/src/errors.js.map +1 -0
- package/dist/src/generated-schemas.d.ts +661 -0
- package/dist/src/generated-schemas.d.ts.map +1 -0
- package/dist/src/generated-schemas.js +66 -0
- package/dist/src/generated-schemas.js.map +1 -0
- package/dist/src/http-client-factory.d.ts +62 -0
- package/dist/src/http-client-factory.d.ts.map +1 -0
- package/dist/src/http-client-factory.js +121 -0
- package/dist/src/http-client-factory.js.map +1 -0
- package/dist/src/http-transport.d.ts +194 -0
- package/dist/src/http-transport.d.ts.map +1 -0
- package/dist/src/http-transport.js +851 -0
- package/dist/src/http-transport.js.map +1 -0
- package/dist/src/index.d.ts +8 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/index.js +59 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/interceptors.d.ts +78 -0
- package/dist/src/interceptors.d.ts.map +1 -0
- package/dist/src/interceptors.js +252 -0
- package/dist/src/interceptors.js.map +1 -0
- package/dist/src/jsonrpc-validator.d.ts +27 -0
- package/dist/src/jsonrpc-validator.d.ts.map +1 -0
- package/dist/src/jsonrpc-validator.js +58 -0
- package/dist/src/jsonrpc-validator.js.map +1 -0
- package/dist/src/lib.d.ts +8 -0
- package/dist/src/lib.d.ts.map +1 -0
- package/dist/src/lib.js +7 -0
- package/dist/src/lib.js.map +1 -0
- package/dist/src/logger.d.ts +81 -0
- package/dist/src/logger.d.ts.map +1 -0
- package/dist/src/logger.js +264 -0
- package/dist/src/logger.js.map +1 -0
- package/dist/src/mcp-server.d.ts +117 -0
- package/dist/src/mcp-server.d.ts.map +1 -0
- package/dist/src/mcp-server.js +621 -0
- package/dist/src/mcp-server.js.map +1 -0
- package/dist/src/metrics.d.ts +86 -0
- package/dist/src/metrics.d.ts.map +1 -0
- package/dist/src/metrics.js +229 -0
- package/dist/src/metrics.js.map +1 -0
- package/dist/src/naming-warnings.d.ts +23 -0
- package/dist/src/naming-warnings.d.ts.map +1 -0
- package/dist/src/naming-warnings.js +83 -0
- package/dist/src/naming-warnings.js.map +1 -0
- package/dist/src/naming.d.ts +58 -0
- package/dist/src/naming.d.ts.map +1 -0
- package/dist/src/naming.js +510 -0
- package/dist/src/naming.js.map +1 -0
- package/dist/src/openapi-parser.d.ts +49 -0
- package/dist/src/openapi-parser.d.ts.map +1 -0
- package/dist/src/openapi-parser.js +216 -0
- package/dist/src/openapi-parser.js.map +1 -0
- package/dist/src/profile-loader.d.ts +77 -0
- package/dist/src/profile-loader.d.ts.map +1 -0
- package/dist/src/profile-loader.js +443 -0
- package/dist/src/profile-loader.js.map +1 -0
- package/dist/src/schema-validator.d.ts +30 -0
- package/dist/src/schema-validator.d.ts.map +1 -0
- package/dist/src/schema-validator.js +115 -0
- package/dist/src/schema-validator.js.map +1 -0
- package/dist/src/testing/fixtures.d.ts +268 -0
- package/dist/src/testing/fixtures.d.ts.map +1 -0
- package/dist/src/testing/fixtures.js +210 -0
- package/dist/src/testing/fixtures.js.map +1 -0
- package/dist/src/testing/mock-gitlab-server.d.ts +34 -0
- package/dist/src/testing/mock-gitlab-server.d.ts.map +1 -0
- package/dist/src/testing/mock-gitlab-server.js +351 -0
- package/dist/src/testing/mock-gitlab-server.js.map +1 -0
- package/dist/src/testing/mock-utils.d.ts +41 -0
- package/dist/src/testing/mock-utils.d.ts.map +1 -0
- package/dist/src/testing/mock-utils.js +59 -0
- package/dist/src/testing/mock-utils.js.map +1 -0
- package/dist/src/testing/test-http-utils.d.ts +52 -0
- package/dist/src/testing/test-http-utils.d.ts.map +1 -0
- package/dist/src/testing/test-http-utils.js +109 -0
- package/dist/src/testing/test-http-utils.js.map +1 -0
- package/dist/src/testing/test-types.d.ts +76 -0
- package/dist/src/testing/test-types.d.ts.map +1 -0
- package/dist/src/testing/test-types.js +7 -0
- package/dist/src/testing/test-types.js.map +1 -0
- package/dist/src/tool-generator.d.ts +43 -0
- package/dist/src/tool-generator.d.ts.map +1 -0
- package/dist/src/tool-generator.js +123 -0
- package/dist/src/tool-generator.js.map +1 -0
- package/dist/src/types/http-transport.d.ts +45 -0
- package/dist/src/types/http-transport.d.ts.map +1 -0
- package/dist/src/types/http-transport.js +8 -0
- package/dist/src/types/http-transport.js.map +1 -0
- package/dist/src/types/openapi.d.ts +50 -0
- package/dist/src/types/openapi.d.ts.map +1 -0
- package/dist/src/types/openapi.js +9 -0
- package/dist/src/types/openapi.js.map +1 -0
- package/dist/src/types/profile.d.ts +80 -0
- package/dist/src/types/profile.d.ts.map +1 -0
- package/dist/src/types/profile.js +9 -0
- package/dist/src/types/profile.js.map +1 -0
- package/dist/src/validation-utils.d.ts +15 -0
- package/dist/src/validation-utils.d.ts.map +1 -0
- package/dist/src/validation-utils.js +25 -0
- package/dist/src/validation-utils.js.map +1 -0
- package/dist/testing/fixtures.d.ts +186 -0
- package/dist/testing/fixtures.d.ts.map +1 -0
- package/dist/testing/fixtures.js +135 -0
- package/dist/testing/fixtures.js.map +1 -0
- package/dist/testing/http-integration.test.d.ts +7 -0
- package/dist/testing/http-integration.test.d.ts.map +1 -0
- package/dist/testing/http-integration.test.js +383 -0
- package/dist/testing/http-integration.test.js.map +1 -0
- package/dist/testing/http-multiuser.test.d.ts +10 -0
- package/dist/testing/http-multiuser.test.d.ts.map +1 -0
- package/dist/testing/http-multiuser.test.js +255 -0
- package/dist/testing/http-multiuser.test.js.map +1 -0
- package/dist/testing/integration.test.d.ts +8 -0
- package/dist/testing/integration.test.d.ts.map +1 -0
- package/dist/testing/integration.test.js +247 -0
- package/dist/testing/integration.test.js.map +1 -0
- package/dist/testing/mock-gitlab-server.d.ts +34 -0
- package/dist/testing/mock-gitlab-server.d.ts.map +1 -0
- package/dist/testing/mock-gitlab-server.js +224 -0
- package/dist/testing/mock-gitlab-server.js.map +1 -0
- package/dist/testing/test-types.d.ts +59 -0
- package/dist/testing/test-types.d.ts.map +1 -0
- package/dist/testing/test-types.js +7 -0
- package/dist/testing/test-types.js.map +1 -0
- package/dist/tool-generator.d.ts +43 -0
- package/dist/tool-generator.d.ts.map +1 -0
- package/dist/tool-generator.js +123 -0
- package/dist/tool-generator.js.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/dist/types/http-transport.d.ts +39 -0
- package/dist/types/http-transport.d.ts.map +1 -0
- package/dist/types/http-transport.js +8 -0
- package/dist/types/http-transport.js.map +1 -0
- package/dist/types/openapi.d.ts +50 -0
- package/dist/types/openapi.d.ts.map +1 -0
- package/dist/types/openapi.js +9 -0
- package/dist/types/openapi.js.map +1 -0
- package/dist/types/profile.d.ts +76 -0
- package/dist/types/profile.d.ts.map +1 -0
- package/dist/types/profile.js +9 -0
- package/dist/types/profile.js.map +1 -0
- package/package.json +84 -0
- package/profile-schema.json +369 -0
|
@@ -0,0 +1,351 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Mock GitLab API server for integration testing
|
|
3
|
+
*
|
|
4
|
+
* Why: Enables end-to-end testing without real GitLab instance.
|
|
5
|
+
* Tests actual HTTP flow, parameter handling, error scenarios.
|
|
6
|
+
*/
|
|
7
|
+
import { http, HttpResponse } from 'msw';
|
|
8
|
+
import { setupServer } from 'msw/node';
|
|
9
|
+
import * as fixtures from './fixtures.js';
|
|
10
|
+
import { parsePaginationParams, parseSearchParam, parseBranchParams, parseScopeParam } from './mock-utils.js';
|
|
11
|
+
const BASE_URL = 'https://gitlab.com/api/v4';
|
|
12
|
+
/**
|
|
13
|
+
* Helper: Extract and validate IID from URL
|
|
14
|
+
*
|
|
15
|
+
* Why: Prevents path traversal and invalid integer attacks
|
|
16
|
+
* Returns null if invalid (caller should return 400 Bad Request)
|
|
17
|
+
*/
|
|
18
|
+
function extractIidFromUrl(url) {
|
|
19
|
+
const parts = url.split('/');
|
|
20
|
+
const iidStr = parts[parts.length - 1];
|
|
21
|
+
// Validate it's a positive integer
|
|
22
|
+
if (!iidStr || !/^\d+$/.test(iidStr)) {
|
|
23
|
+
return null;
|
|
24
|
+
}
|
|
25
|
+
const iid = parseInt(iidStr, 10);
|
|
26
|
+
if (isNaN(iid) || iid < 1 || iid > 2147483647) {
|
|
27
|
+
return null;
|
|
28
|
+
}
|
|
29
|
+
return iid;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Mock GitLab API endpoints
|
|
33
|
+
*
|
|
34
|
+
* Why ordered by resource: Mirrors actual GitLab API structure for maintainability
|
|
35
|
+
* Why wildcard patterns: GitLab accepts URL-encoded paths like my-org/my-project
|
|
36
|
+
*/
|
|
37
|
+
export const handlers = [
|
|
38
|
+
// Project Badges
|
|
39
|
+
http.get(`${BASE_URL}/projects/*/badges`, ({ request, params }) => {
|
|
40
|
+
const { page } = parsePaginationParams(request);
|
|
41
|
+
// Simple pagination
|
|
42
|
+
if (page === 1) {
|
|
43
|
+
return HttpResponse.json(fixtures.mockBadgesList);
|
|
44
|
+
}
|
|
45
|
+
return HttpResponse.json([]);
|
|
46
|
+
}),
|
|
47
|
+
http.get(`${BASE_URL}/projects/*/badges/*`, ({ request }) => {
|
|
48
|
+
const badgeId = extractIidFromUrl(request.url);
|
|
49
|
+
if (badgeId === null) {
|
|
50
|
+
return HttpResponse.json({ error: 'Invalid badge ID' }, { status: 400 });
|
|
51
|
+
}
|
|
52
|
+
if (badgeId === 1) {
|
|
53
|
+
return HttpResponse.json(fixtures.mockBadge);
|
|
54
|
+
}
|
|
55
|
+
return HttpResponse.json({ message: 'Not Found' }, { status: 404 });
|
|
56
|
+
}),
|
|
57
|
+
http.post(`${BASE_URL}/projects/*/badges`, async ({ request }) => {
|
|
58
|
+
const body = await request.json();
|
|
59
|
+
if (!body.link_url || !body.image_url) {
|
|
60
|
+
return HttpResponse.json({ error: 'link_url and image_url are required' }, { status: 400 });
|
|
61
|
+
}
|
|
62
|
+
return HttpResponse.json({
|
|
63
|
+
...fixtures.mockBadge,
|
|
64
|
+
id: 3,
|
|
65
|
+
name: body.name || 'New Badge',
|
|
66
|
+
link_url: body.link_url,
|
|
67
|
+
image_url: body.image_url,
|
|
68
|
+
}, { status: 201 });
|
|
69
|
+
}),
|
|
70
|
+
http.put(`${BASE_URL}/projects/*/badges/*`, async ({ request }) => {
|
|
71
|
+
const badgeId = extractIidFromUrl(request.url);
|
|
72
|
+
if (badgeId === null) {
|
|
73
|
+
return HttpResponse.json({ error: 'Invalid badge ID' }, { status: 400 });
|
|
74
|
+
}
|
|
75
|
+
const body = await request.json();
|
|
76
|
+
if (badgeId === 1) {
|
|
77
|
+
return HttpResponse.json({
|
|
78
|
+
...fixtures.mockBadge,
|
|
79
|
+
name: body.name || fixtures.mockBadge.name,
|
|
80
|
+
link_url: body.link_url || fixtures.mockBadge.link_url,
|
|
81
|
+
image_url: body.image_url || fixtures.mockBadge.image_url,
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
return HttpResponse.json({ message: 'Not Found' }, { status: 404 });
|
|
85
|
+
}),
|
|
86
|
+
http.delete(`${BASE_URL}/projects/*/badges/*`, ({ request }) => {
|
|
87
|
+
const badgeId = extractIidFromUrl(request.url);
|
|
88
|
+
if (badgeId === null) {
|
|
89
|
+
return HttpResponse.json({ error: 'Invalid badge ID' }, { status: 400 });
|
|
90
|
+
}
|
|
91
|
+
if (badgeId === 1) {
|
|
92
|
+
return new HttpResponse(null, { status: 204 });
|
|
93
|
+
}
|
|
94
|
+
return HttpResponse.json({ message: 'Not Found' }, { status: 404 });
|
|
95
|
+
}),
|
|
96
|
+
// Group Badges (similar structure)
|
|
97
|
+
http.get(`${BASE_URL}/groups/*/badges`, () => {
|
|
98
|
+
return HttpResponse.json(fixtures.mockBadgesList);
|
|
99
|
+
}),
|
|
100
|
+
http.post(`${BASE_URL}/groups/*/badges`, async ({ request }) => {
|
|
101
|
+
const body = await request.json();
|
|
102
|
+
return HttpResponse.json({
|
|
103
|
+
...fixtures.mockBadge,
|
|
104
|
+
id: 4,
|
|
105
|
+
kind: 'group',
|
|
106
|
+
name: body.name || 'Group Badge',
|
|
107
|
+
}, { status: 201 });
|
|
108
|
+
}),
|
|
109
|
+
// Branches
|
|
110
|
+
http.get(`${BASE_URL}/projects/*/repository/branches`, ({ request }) => {
|
|
111
|
+
const search = parseSearchParam(request);
|
|
112
|
+
if (search) {
|
|
113
|
+
return HttpResponse.json(fixtures.mockBranchesList.filter(b => b.name.includes(search)));
|
|
114
|
+
}
|
|
115
|
+
return HttpResponse.json(fixtures.mockBranchesList);
|
|
116
|
+
}),
|
|
117
|
+
http.get(`${BASE_URL}/projects/*/repository/branches/*`, ({ request }) => {
|
|
118
|
+
const branch = decodeURIComponent(request.url.split('/').pop() || '');
|
|
119
|
+
const found = fixtures.mockBranchesList.find(b => b.name === branch);
|
|
120
|
+
if (found) {
|
|
121
|
+
return HttpResponse.json(found);
|
|
122
|
+
}
|
|
123
|
+
return HttpResponse.json({ message: 'Branch Not Found' }, { status: 404 });
|
|
124
|
+
}),
|
|
125
|
+
http.post(`${BASE_URL}/projects/*/repository/branches`, async ({ request }) => {
|
|
126
|
+
const { branch, ref } = parseBranchParams(request);
|
|
127
|
+
if (!branch || !ref) {
|
|
128
|
+
return HttpResponse.json({ error: 'branch and ref parameters are required' }, { status: 400 });
|
|
129
|
+
}
|
|
130
|
+
return HttpResponse.json({
|
|
131
|
+
name: branch,
|
|
132
|
+
commit: fixtures.mockBranch.commit,
|
|
133
|
+
merged: false,
|
|
134
|
+
protected: false,
|
|
135
|
+
default: false,
|
|
136
|
+
}, { status: 201 });
|
|
137
|
+
}),
|
|
138
|
+
http.delete(`${BASE_URL}/projects/*/repository/branches/*`, ({ request }) => {
|
|
139
|
+
const branch = decodeURIComponent(request.url.split('/').pop() || '');
|
|
140
|
+
if (branch !== 'main') {
|
|
141
|
+
return new HttpResponse(null, { status: 204 });
|
|
142
|
+
}
|
|
143
|
+
return HttpResponse.json({ message: 'Cannot delete default branch' }, { status: 403 });
|
|
144
|
+
}),
|
|
145
|
+
http.put(`${BASE_URL}/projects/*/repository/branches/*/protect`, ({ request }) => {
|
|
146
|
+
const parts = request.url.split('/');
|
|
147
|
+
const branch = decodeURIComponent(parts[parts.length - 2]); // second-to-last part
|
|
148
|
+
return HttpResponse.json({
|
|
149
|
+
...fixtures.mockBranch,
|
|
150
|
+
name: branch,
|
|
151
|
+
protected: true,
|
|
152
|
+
});
|
|
153
|
+
}),
|
|
154
|
+
http.put(`${BASE_URL}/projects/*/repository/branches/*/unprotect`, ({ request }) => {
|
|
155
|
+
const parts = request.url.split('/');
|
|
156
|
+
const branch = decodeURIComponent(parts[parts.length - 2]); // second-to-last part
|
|
157
|
+
return HttpResponse.json({
|
|
158
|
+
...fixtures.mockBranch,
|
|
159
|
+
name: branch,
|
|
160
|
+
protected: false,
|
|
161
|
+
});
|
|
162
|
+
}),
|
|
163
|
+
// Access Requests
|
|
164
|
+
http.get(`${BASE_URL}/projects/*/access_requests`, () => {
|
|
165
|
+
return HttpResponse.json(fixtures.mockAccessRequestsList);
|
|
166
|
+
}),
|
|
167
|
+
http.get(`${BASE_URL}/groups/*/access_requests`, () => {
|
|
168
|
+
return HttpResponse.json(fixtures.mockAccessRequestsList);
|
|
169
|
+
}),
|
|
170
|
+
http.post(`${BASE_URL}/projects/*/access_requests`, () => {
|
|
171
|
+
return HttpResponse.json(fixtures.mockAccessRequest, { status: 201 });
|
|
172
|
+
}),
|
|
173
|
+
http.put(`${BASE_URL}/projects/*/access_requests/*/approve`, async ({ request }) => {
|
|
174
|
+
const body = await request.json();
|
|
175
|
+
const parts = request.url.split('/');
|
|
176
|
+
const userId = parseInt(parts[parts.length - 2], 10); // second-to-last part
|
|
177
|
+
return HttpResponse.json({
|
|
178
|
+
...fixtures.mockAccessRequest,
|
|
179
|
+
id: userId,
|
|
180
|
+
access_level: body.access_level || 30,
|
|
181
|
+
});
|
|
182
|
+
}),
|
|
183
|
+
http.delete(`${BASE_URL}/projects/*/access_requests/*`, () => {
|
|
184
|
+
return new HttpResponse(null, { status: 204 });
|
|
185
|
+
}),
|
|
186
|
+
// Jobs
|
|
187
|
+
http.get(`${BASE_URL}/projects/*/jobs`, ({ request }) => {
|
|
188
|
+
const scope = parseScopeParam(request);
|
|
189
|
+
if (scope.length > 0 && scope.includes('failed')) {
|
|
190
|
+
return HttpResponse.json(fixtures.mockJobsList.filter(j => j.status === 'failed'));
|
|
191
|
+
}
|
|
192
|
+
return HttpResponse.json(fixtures.mockJobsList);
|
|
193
|
+
}),
|
|
194
|
+
http.get(`${BASE_URL}/projects/*/jobs/*`, ({ request }) => {
|
|
195
|
+
const jobId = extractIidFromUrl(request.url);
|
|
196
|
+
if (jobId === null) {
|
|
197
|
+
return HttpResponse.json({ error: 'Invalid job ID' }, { status: 400 });
|
|
198
|
+
}
|
|
199
|
+
if (jobId === 1234) {
|
|
200
|
+
return HttpResponse.json(fixtures.mockJob);
|
|
201
|
+
}
|
|
202
|
+
return HttpResponse.json({ message: 'Not Found' }, { status: 404 });
|
|
203
|
+
}),
|
|
204
|
+
http.post(`${BASE_URL}/projects/*/jobs/*/play`, ({ request }) => {
|
|
205
|
+
const parts = request.url.split('/');
|
|
206
|
+
const jobId = parseInt(parts[parts.length - 2], 10); // second-to-last part
|
|
207
|
+
return HttpResponse.json({
|
|
208
|
+
...fixtures.mockJob,
|
|
209
|
+
id: jobId,
|
|
210
|
+
status: 'pending',
|
|
211
|
+
});
|
|
212
|
+
}),
|
|
213
|
+
// Rate limiting simulation
|
|
214
|
+
http.get(`${BASE_URL}/rate-limit-test`, () => {
|
|
215
|
+
return HttpResponse.json({ message: 'Rate limit exceeded' }, { status: 429, headers: { 'Retry-After': '60' } });
|
|
216
|
+
}),
|
|
217
|
+
// Merge Requests
|
|
218
|
+
http.get(`${BASE_URL}/projects/*/merge_requests`, ({ request, params }) => {
|
|
219
|
+
const { page } = parsePaginationParams(request);
|
|
220
|
+
// Simple pagination
|
|
221
|
+
if (page === 1) {
|
|
222
|
+
return HttpResponse.json(fixtures.mockMergeRequestsList);
|
|
223
|
+
}
|
|
224
|
+
return HttpResponse.json([]);
|
|
225
|
+
}),
|
|
226
|
+
http.get(`${BASE_URL}/projects/*/merge_requests/*`, ({ request }) => {
|
|
227
|
+
const mergeRequestIid = extractIidFromUrl(request.url);
|
|
228
|
+
if (mergeRequestIid === null) {
|
|
229
|
+
return HttpResponse.json({ error: 'Invalid merge request IID' }, { status: 400 });
|
|
230
|
+
}
|
|
231
|
+
if (mergeRequestIid === 1) {
|
|
232
|
+
return HttpResponse.json(fixtures.mockMergeRequest);
|
|
233
|
+
}
|
|
234
|
+
return HttpResponse.json({ message: 'Not Found' }, { status: 404 });
|
|
235
|
+
}),
|
|
236
|
+
http.post(`${BASE_URL}/projects/*/merge_requests`, async ({ request }) => {
|
|
237
|
+
const body = await request.json();
|
|
238
|
+
if (!body.source_branch || !body.target_branch || !body.title) {
|
|
239
|
+
return HttpResponse.json({ error: 'source_branch, target_branch, and title are required' }, { status: 400 });
|
|
240
|
+
}
|
|
241
|
+
// Return created merge request
|
|
242
|
+
const createdMR = {
|
|
243
|
+
...fixtures.mockMergeRequest,
|
|
244
|
+
iid: 3,
|
|
245
|
+
id: 3,
|
|
246
|
+
title: body.title,
|
|
247
|
+
source_branch: body.source_branch,
|
|
248
|
+
target_branch: body.target_branch,
|
|
249
|
+
description: body.description,
|
|
250
|
+
web_url: 'https://gitlab.com/my-org/my-project/-/merge_requests/3',
|
|
251
|
+
};
|
|
252
|
+
return HttpResponse.json(createdMR, { status: 201 });
|
|
253
|
+
}),
|
|
254
|
+
http.delete(`${BASE_URL}/projects/*/merge_requests/*`, ({ request }) => {
|
|
255
|
+
// Check for forbidden project
|
|
256
|
+
if (request.url.includes('/forbidden-project/')) {
|
|
257
|
+
return HttpResponse.json({ message: 'Forbidden', error: 'You do not have permission to delete this merge request' }, { status: 403 });
|
|
258
|
+
}
|
|
259
|
+
const mergeRequestIid = extractIidFromUrl(request.url);
|
|
260
|
+
if (mergeRequestIid === null) {
|
|
261
|
+
return HttpResponse.json({ error: 'Invalid merge request IID' }, { status: 400 });
|
|
262
|
+
}
|
|
263
|
+
if (mergeRequestIid === 1) {
|
|
264
|
+
return new HttpResponse(null, { status: 204 });
|
|
265
|
+
}
|
|
266
|
+
return HttpResponse.json({ message: 'Not Found' }, { status: 404 });
|
|
267
|
+
}),
|
|
268
|
+
// Issues
|
|
269
|
+
http.get(`${BASE_URL}/projects/*/issues`, ({ request }) => {
|
|
270
|
+
const { page } = parsePaginationParams(request);
|
|
271
|
+
// Simple pagination
|
|
272
|
+
if (page === 1) {
|
|
273
|
+
return HttpResponse.json(fixtures.mockIssuesList);
|
|
274
|
+
}
|
|
275
|
+
return HttpResponse.json([]);
|
|
276
|
+
}),
|
|
277
|
+
http.get(`${BASE_URL}/projects/*/issues/*`, ({ request }) => {
|
|
278
|
+
const issueIid = extractIidFromUrl(request.url);
|
|
279
|
+
if (issueIid === null) {
|
|
280
|
+
return HttpResponse.json({ error: 'Invalid issue IID' }, { status: 400 });
|
|
281
|
+
}
|
|
282
|
+
if (issueIid === 1) {
|
|
283
|
+
return HttpResponse.json(fixtures.mockIssue);
|
|
284
|
+
}
|
|
285
|
+
return HttpResponse.json({ message: 'Not Found' }, { status: 404 });
|
|
286
|
+
}),
|
|
287
|
+
http.post(`${BASE_URL}/projects/*/issues`, async ({ request }) => {
|
|
288
|
+
const body = await request.json();
|
|
289
|
+
// Validate required fields
|
|
290
|
+
if (!body.title) {
|
|
291
|
+
return HttpResponse.json({ error: 'title is required' }, { status: 400 });
|
|
292
|
+
}
|
|
293
|
+
// Return created issue
|
|
294
|
+
const createdIssue = {
|
|
295
|
+
...fixtures.mockIssue,
|
|
296
|
+
iid: 3,
|
|
297
|
+
id: 3,
|
|
298
|
+
title: body.title,
|
|
299
|
+
description: body.description || '',
|
|
300
|
+
state: 'opened',
|
|
301
|
+
web_url: 'https://gitlab.com/my-org/my-project/-/issues/3',
|
|
302
|
+
created_at: new Date().toISOString(),
|
|
303
|
+
};
|
|
304
|
+
return HttpResponse.json(createdIssue, { status: 201 });
|
|
305
|
+
}),
|
|
306
|
+
http.delete(`${BASE_URL}/projects/*/issues/*`, ({ request }) => {
|
|
307
|
+
// Check for forbidden project
|
|
308
|
+
if (request.url.includes('/forbidden-project/')) {
|
|
309
|
+
return HttpResponse.json({ message: 'Forbidden', error: 'You do not have permission to delete this issue' }, { status: 403 });
|
|
310
|
+
}
|
|
311
|
+
const issueIid = extractIidFromUrl(request.url);
|
|
312
|
+
if (issueIid === null) {
|
|
313
|
+
return HttpResponse.json({ error: 'Invalid issue IID' }, { status: 400 });
|
|
314
|
+
}
|
|
315
|
+
if (issueIid === 1) {
|
|
316
|
+
return new HttpResponse(null, { status: 204 });
|
|
317
|
+
}
|
|
318
|
+
return HttpResponse.json({ message: 'Not Found' }, { status: 404 });
|
|
319
|
+
}),
|
|
320
|
+
// Server error simulation
|
|
321
|
+
http.get(`${BASE_URL}/server-error-test`, () => {
|
|
322
|
+
return HttpResponse.json({ message: 'Internal Server Error' }, { status: 503 });
|
|
323
|
+
}),
|
|
324
|
+
];
|
|
325
|
+
/**
|
|
326
|
+
* Create and configure mock server
|
|
327
|
+
*
|
|
328
|
+
* Why setupServer: MSW's node integration for testing environments
|
|
329
|
+
*/
|
|
330
|
+
export const mockServer = setupServer(...handlers);
|
|
331
|
+
/**
|
|
332
|
+
* Helper: start server before tests
|
|
333
|
+
*/
|
|
334
|
+
export function startMockServer() {
|
|
335
|
+
mockServer.listen({ onUnhandledRequest: 'error' });
|
|
336
|
+
}
|
|
337
|
+
/**
|
|
338
|
+
* Helper: reset handlers between tests
|
|
339
|
+
*
|
|
340
|
+
* Why: Prevents test pollution from runtime handler modifications
|
|
341
|
+
*/
|
|
342
|
+
export function resetMockServer() {
|
|
343
|
+
mockServer.resetHandlers();
|
|
344
|
+
}
|
|
345
|
+
/**
|
|
346
|
+
* Helper: stop server after tests
|
|
347
|
+
*/
|
|
348
|
+
export function stopMockServer() {
|
|
349
|
+
mockServer.close();
|
|
350
|
+
}
|
|
351
|
+
//# sourceMappingURL=mock-gitlab-server.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mock-gitlab-server.js","sourceRoot":"","sources":["../../../src/testing/mock-gitlab-server.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Mock server utilities for parsing HTTP requests
|
|
3
|
+
*
|
|
4
|
+
* Why: Eliminates code duplication in mock server handlers
|
|
5
|
+
* Provides consistent parameter parsing and validation
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Parse URL from MSW request
|
|
9
|
+
*/
|
|
10
|
+
export declare function parseUrl(request: Request): URL;
|
|
11
|
+
/**
|
|
12
|
+
* Parse pagination parameters (page, per_page)
|
|
13
|
+
*/
|
|
14
|
+
export declare function parsePaginationParams(request: Request): {
|
|
15
|
+
page: number;
|
|
16
|
+
perPage: number;
|
|
17
|
+
};
|
|
18
|
+
/**
|
|
19
|
+
* Parse search parameter
|
|
20
|
+
*/
|
|
21
|
+
export declare function parseSearchParam(request: Request): string | null;
|
|
22
|
+
/**
|
|
23
|
+
* Parse branch and ref parameters for repository operations
|
|
24
|
+
*/
|
|
25
|
+
export declare function parseBranchParams(request: Request): {
|
|
26
|
+
branch?: string;
|
|
27
|
+
ref?: string;
|
|
28
|
+
};
|
|
29
|
+
/**
|
|
30
|
+
* Parse scope array parameter (GitLab style: scope[]=value1&scope[]=value2)
|
|
31
|
+
*/
|
|
32
|
+
export declare function parseScopeParam(request: Request): string[];
|
|
33
|
+
/**
|
|
34
|
+
* Calculate pagination offset
|
|
35
|
+
*/
|
|
36
|
+
export declare function calculateOffset(page: number, perPage: number): number;
|
|
37
|
+
/**
|
|
38
|
+
* Apply pagination to array data
|
|
39
|
+
*/
|
|
40
|
+
export declare function applyPagination<T>(data: T[], page: number, perPage: number): T[];
|
|
41
|
+
//# sourceMappingURL=mock-utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mock-utils.d.ts","sourceRoot":"","sources":["../../../src/testing/mock-utils.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH;;GAEG;AACH,wBAAgB,QAAQ,CAAC,OAAO,EAAE,OAAO,GAAG,GAAG,CAE9C;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,OAAO,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAKzF;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM,GAAG,IAAI,CAGhE;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,OAAO,GAAG;IAAE,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,GAAG,CAAC,EAAE,MAAM,CAAA;CAAE,CAMrF;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM,EAAE,CAG1D;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAErE;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,CAAC,EAC/B,IAAI,EAAE,CAAC,EAAE,EACT,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,GACd,CAAC,EAAE,CAGL"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Mock server utilities for parsing HTTP requests
|
|
3
|
+
*
|
|
4
|
+
* Why: Eliminates code duplication in mock server handlers
|
|
5
|
+
* Provides consistent parameter parsing and validation
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Parse URL from MSW request
|
|
9
|
+
*/
|
|
10
|
+
export function parseUrl(request) {
|
|
11
|
+
return new URL(request.url);
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Parse pagination parameters (page, per_page)
|
|
15
|
+
*/
|
|
16
|
+
export function parsePaginationParams(request) {
|
|
17
|
+
const url = parseUrl(request);
|
|
18
|
+
const page = parseInt(url.searchParams.get('page') || '1', 10);
|
|
19
|
+
const perPage = parseInt(url.searchParams.get('per_page') || '20', 10);
|
|
20
|
+
return { page, perPage };
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Parse search parameter
|
|
24
|
+
*/
|
|
25
|
+
export function parseSearchParam(request) {
|
|
26
|
+
const url = parseUrl(request);
|
|
27
|
+
return url.searchParams.get('search');
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Parse branch and ref parameters for repository operations
|
|
31
|
+
*/
|
|
32
|
+
export function parseBranchParams(request) {
|
|
33
|
+
const url = parseUrl(request);
|
|
34
|
+
return {
|
|
35
|
+
branch: url.searchParams.get('branch') || undefined,
|
|
36
|
+
ref: url.searchParams.get('ref') || undefined,
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Parse scope array parameter (GitLab style: scope[]=value1&scope[]=value2)
|
|
41
|
+
*/
|
|
42
|
+
export function parseScopeParam(request) {
|
|
43
|
+
const url = parseUrl(request);
|
|
44
|
+
return url.searchParams.getAll('scope[]');
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Calculate pagination offset
|
|
48
|
+
*/
|
|
49
|
+
export function calculateOffset(page, perPage) {
|
|
50
|
+
return (page - 1) * perPage;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Apply pagination to array data
|
|
54
|
+
*/
|
|
55
|
+
export function applyPagination(data, page, perPage) {
|
|
56
|
+
const offset = calculateOffset(page, perPage);
|
|
57
|
+
return data.slice(offset, offset + perPage);
|
|
58
|
+
}
|
|
59
|
+
//# sourceMappingURL=mock-utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mock-utils.js","sourceRoot":"","sources":["../../../src/testing/mock-utils.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH;;GAEG;AACH,MAAM,UAAU,QAAQ,CAAC,OAAgB;IACvC,OAAO,IAAI,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;AAC9B,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,qBAAqB,CAAC,OAAgB;IACpD,MAAM,GAAG,GAAG,QAAQ,CAAC,OAAO,CAAC,CAAC;IAC9B,MAAM,IAAI,GAAG,QAAQ,CAAC,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,GAAG,EAAE,EAAE,CAAC,CAAC;IAC/D,MAAM,OAAO,GAAG,QAAQ,CAAC,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,UAAU,CAAC,IAAI,IAAI,EAAE,EAAE,CAAC,CAAC;IACvE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;AAC3B,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,gBAAgB,CAAC,OAAgB;IAC/C,MAAM,GAAG,GAAG,QAAQ,CAAC,OAAO,CAAC,CAAC;IAC9B,OAAO,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;AACxC,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,iBAAiB,CAAC,OAAgB;IAChD,MAAM,GAAG,GAAG,QAAQ,CAAC,OAAO,CAAC,CAAC;IAC9B,OAAO;QACL,MAAM,EAAE,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,SAAS;QACnD,GAAG,EAAE,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,SAAS;KAC9C,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,eAAe,CAAC,OAAgB;IAC9C,MAAM,GAAG,GAAG,QAAQ,CAAC,OAAO,CAAC,CAAC;IAC9B,OAAO,GAAG,CAAC,YAAY,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;AAC5C,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,eAAe,CAAC,IAAY,EAAE,OAAe;IAC3D,OAAO,CAAC,IAAI,GAAG,CAAC,CAAC,GAAG,OAAO,CAAC;AAC9B,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,eAAe,CAC7B,IAAS,EACT,IAAY,EACZ,OAAe;IAEf,MAAM,MAAM,GAAG,eAAe,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;IAC9C,OAAO,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC;AAC9C,CAAC"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Test utilities for HTTP client setup and mocking
|
|
3
|
+
*
|
|
4
|
+
* Why: Eliminates code duplication in HTTP client test setup
|
|
5
|
+
* Provides consistent mocking and client creation patterns
|
|
6
|
+
*/
|
|
7
|
+
import { HttpClient } from '../interceptors.js';
|
|
8
|
+
import type { InterceptorConfig } from '../types/profile.js';
|
|
9
|
+
type RequestInput = any;
|
|
10
|
+
/**
|
|
11
|
+
* Create HTTP client with interceptors for testing
|
|
12
|
+
*/
|
|
13
|
+
export declare function createTestHttpClient(baseUrl?: RequestInput, interceptors?: InterceptorConfig): HttpClient;
|
|
14
|
+
/**
|
|
15
|
+
* Setup fetch mock that captures request headers
|
|
16
|
+
*/
|
|
17
|
+
export declare function setupFetchMock(responseBody?: any, responseOptions?: ResponseInit): {
|
|
18
|
+
capturedHeaders: Record<RequestInput, RequestInput>;
|
|
19
|
+
};
|
|
20
|
+
/**
|
|
21
|
+
* Setup fetch mock that returns error response
|
|
22
|
+
*/
|
|
23
|
+
export declare function setupErrorFetchMock(status?: number, message?: RequestInput): void;
|
|
24
|
+
/**
|
|
25
|
+
* Setup fetch mock for network errors
|
|
26
|
+
*/
|
|
27
|
+
export declare function setupNetworkErrorFetchMock(): void;
|
|
28
|
+
/**
|
|
29
|
+
* Setup fetch mock for rate limiting
|
|
30
|
+
*/
|
|
31
|
+
export declare function setupRateLimitFetchMock(): void;
|
|
32
|
+
/**
|
|
33
|
+
* Restore original fetch
|
|
34
|
+
*/
|
|
35
|
+
export declare function restoreFetch(): void;
|
|
36
|
+
/**
|
|
37
|
+
* Test helper for HTTP client tests
|
|
38
|
+
*/
|
|
39
|
+
export declare class HttpTestHelper {
|
|
40
|
+
private baseUrl;
|
|
41
|
+
private interceptors;
|
|
42
|
+
private capturedHeaders;
|
|
43
|
+
constructor(baseUrl?: RequestInput, interceptors?: InterceptorConfig);
|
|
44
|
+
private setupMock;
|
|
45
|
+
getClient(): HttpClient;
|
|
46
|
+
getCapturedHeaders(): Record<RequestInput, RequestInput>;
|
|
47
|
+
setResponse(responseBody: any, options?: ResponseInit): void;
|
|
48
|
+
setErrorResponse(status: number, message: RequestInput): void;
|
|
49
|
+
cleanup(): void;
|
|
50
|
+
}
|
|
51
|
+
export {};
|
|
52
|
+
//# sourceMappingURL=test-http-utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"test-http-utils.d.ts","sourceRoot":"","sources":["../../../src/testing/test-http-utils.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,UAAU,EAAoB,MAAM,oBAAoB,CAAC;AAClE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAG7D,KAAK,YAAY,GAAG,GAAG,CAAC;AAExB;;GAEG;AACH,wBAAgB,oBAAoB,CAClC,OAAO,GAAE,YAAwC,EACjD,YAAY,GAAE,iBAAsB,GACnC,UAAU,CAGZ;AAED;;GAEG;AACH,wBAAgB,cAAc,CAC5B,YAAY,GAAE,GAAkB,EAChC,eAAe,GAAE,YAA+E,GAC/F;IAAE,eAAe,EAAE,MAAM,CAAC,YAAY,EAAE,YAAY,CAAC,CAAA;CAAE,CAUzD;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,GAAE,MAAY,EAAE,OAAO,GAAE,YAAsC,GAAG,IAAI,CAK/G;AAED;;GAEG;AACH,wBAAgB,0BAA0B,IAAI,IAAI,CAIjD;AAED;;GAEG;AACH,wBAAgB,uBAAuB,IAAI,IAAI,CAK9C;AAED;;GAEG;AACH,wBAAgB,YAAY,IAAI,IAAI,CAEnC;AAED;;GAEG;AACH,qBAAa,cAAc;IAIvB,OAAO,CAAC,OAAO;IACf,OAAO,CAAC,YAAY;IAJtB,OAAO,CAAC,eAAe,CAA0C;gBAGvD,OAAO,GAAE,YAAwC,EACjD,YAAY,GAAE,iBAAsB;IAK9C,OAAO,CAAC,SAAS;IAUjB,SAAS,IAAI,UAAU;IAIvB,kBAAkB,IAAI,MAAM,CAAC,YAAY,EAAE,YAAY,CAAC;IAIxD,WAAW,CAAC,YAAY,EAAE,GAAG,EAAE,OAAO,CAAC,EAAE,YAAY,GAAG,IAAI;IAW5D,gBAAgB,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,YAAY,GAAG,IAAI;IAU7D,OAAO,IAAI,IAAI;CAGhB"}
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Test utilities for HTTP client setup and mocking
|
|
3
|
+
*
|
|
4
|
+
* Why: Eliminates code duplication in HTTP client test setup
|
|
5
|
+
* Provides consistent mocking and client creation patterns
|
|
6
|
+
*/
|
|
7
|
+
import { HttpClient, InterceptorChain } from '../interceptors.js';
|
|
8
|
+
/**
|
|
9
|
+
* Create HTTP client with interceptors for testing
|
|
10
|
+
*/
|
|
11
|
+
export function createTestHttpClient(baseUrl = 'https://api.example.com', interceptors = {}) {
|
|
12
|
+
const interceptorChain = new InterceptorChain(interceptors);
|
|
13
|
+
return new HttpClient(baseUrl, interceptorChain);
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Setup fetch mock that captures request headers
|
|
17
|
+
*/
|
|
18
|
+
export function setupFetchMock(responseBody = { ok: true }, responseOptions = { status: 200, headers: { 'Content-Type': 'application/json' } }) {
|
|
19
|
+
const capturedHeaders = {};
|
|
20
|
+
global.fetch = async (url, init) => {
|
|
21
|
+
// Copy headers to the shared object
|
|
22
|
+
Object.assign(capturedHeaders, init?.headers || {});
|
|
23
|
+
return new Response(JSON.stringify(responseBody), responseOptions);
|
|
24
|
+
};
|
|
25
|
+
return { capturedHeaders };
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Setup fetch mock that returns error response
|
|
29
|
+
*/
|
|
30
|
+
export function setupErrorFetchMock(status = 500, message = 'Internal Server Error') {
|
|
31
|
+
global.fetch = async () => new Response(JSON.stringify({ message }), {
|
|
32
|
+
status,
|
|
33
|
+
headers: { 'Content-Type': 'application/json' }
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Setup fetch mock for network errors
|
|
38
|
+
*/
|
|
39
|
+
export function setupNetworkErrorFetchMock() {
|
|
40
|
+
global.fetch = async () => {
|
|
41
|
+
throw new Error('Network error');
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Setup fetch mock for rate limiting
|
|
46
|
+
*/
|
|
47
|
+
export function setupRateLimitFetchMock() {
|
|
48
|
+
global.fetch = async () => new Response(null, {
|
|
49
|
+
status: 429,
|
|
50
|
+
headers: { 'Retry-After': '60' }
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Restore original fetch
|
|
55
|
+
*/
|
|
56
|
+
export function restoreFetch() {
|
|
57
|
+
delete global.fetch;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Test helper for HTTP client tests
|
|
61
|
+
*/
|
|
62
|
+
export class HttpTestHelper {
|
|
63
|
+
baseUrl;
|
|
64
|
+
interceptors;
|
|
65
|
+
capturedHeaders = {};
|
|
66
|
+
constructor(baseUrl = 'https://api.example.com', interceptors = {}) {
|
|
67
|
+
this.baseUrl = baseUrl;
|
|
68
|
+
this.interceptors = interceptors;
|
|
69
|
+
this.setupMock();
|
|
70
|
+
}
|
|
71
|
+
setupMock() {
|
|
72
|
+
global.fetch = async (url, init) => {
|
|
73
|
+
this.capturedHeaders = init?.headers;
|
|
74
|
+
return new Response(JSON.stringify({ ok: true }), {
|
|
75
|
+
status: 200,
|
|
76
|
+
headers: { 'Content-Type': 'application/json' }
|
|
77
|
+
});
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
getClient() {
|
|
81
|
+
return createTestHttpClient(this.baseUrl, this.interceptors);
|
|
82
|
+
}
|
|
83
|
+
getCapturedHeaders() {
|
|
84
|
+
return { ...this.capturedHeaders };
|
|
85
|
+
}
|
|
86
|
+
setResponse(responseBody, options) {
|
|
87
|
+
global.fetch = async (url, init) => {
|
|
88
|
+
Object.assign(this.capturedHeaders, init?.headers || {});
|
|
89
|
+
return new Response(JSON.stringify(responseBody), {
|
|
90
|
+
status: 200,
|
|
91
|
+
headers: { 'Content-Type': 'application/json' },
|
|
92
|
+
...options
|
|
93
|
+
});
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
setErrorResponse(status, message) {
|
|
97
|
+
global.fetch = async (url, init) => {
|
|
98
|
+
Object.assign(this.capturedHeaders, init?.headers || {});
|
|
99
|
+
return new Response(JSON.stringify({ message }), {
|
|
100
|
+
status,
|
|
101
|
+
headers: { 'Content-Type': 'application/json' }
|
|
102
|
+
});
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
cleanup() {
|
|
106
|
+
restoreFetch();
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
//# sourceMappingURL=test-http-utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"test-http-utils.js","sourceRoot":"","sources":["../../../src/testing/test-http-utils.ts"],"names":[],"mappings":"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"}
|