@centeredgesoft/runtime-mock-routes 2.1.0 → 2.5.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/.devcontainer/Dockerfile +16 -0
- package/.devcontainer/devcontainer.json +32 -0
- package/LICENSE +20 -20
- package/README.md +100 -93
- package/build/index.d.ts +2 -2
- package/build/index.js +24 -24
- package/build/run.d.ts +2 -2
- package/build/run.js +32 -32
- package/build/src/app.d.ts +27 -27
- package/build/src/app.js +188 -180
- package/build/src/appV2.d.ts +30 -23
- package/build/src/appV2.js +196 -177
- package/index.ts +1 -1
- package/jest.config.js +3 -3
- package/package.json +53 -55
- package/run.ts +38 -38
- package/src/app.test.ts +212 -212
- package/src/app.ts +234 -234
- package/src/appV2.test.ts +320 -261
- package/src/appV2.ts +257 -227
- package/tsconfig.json +15 -15
- package/.env +0 -0
package/src/app.test.ts
CHANGED
|
@@ -1,213 +1,213 @@
|
|
|
1
|
-
import request from 'supertest';
|
|
2
|
-
import { appFactory, isMethodBasedRuntimeRequestCollection, MethodBasedRuntimeRequestCollection, RuntimeRequestBody, SupportedMethodsColection } from './app';
|
|
3
|
-
|
|
4
|
-
describe('appFactory', () => {
|
|
5
|
-
test('Creates app with no seed', () => {
|
|
6
|
-
const app = appFactory();
|
|
7
|
-
expect(app).toBeDefined();
|
|
8
|
-
});
|
|
9
|
-
|
|
10
|
-
test('Creates app with empty seed', () => {
|
|
11
|
-
const app = appFactory({});
|
|
12
|
-
expect(app).toBeDefined();
|
|
13
|
-
});
|
|
14
|
-
|
|
15
|
-
test('Creates app with properly configured seed', () => {
|
|
16
|
-
const seed: MethodBasedRuntimeRequestCollection = {
|
|
17
|
-
GET: {
|
|
18
|
-
"/test": {
|
|
19
|
-
path: "/test",
|
|
20
|
-
body: { test: true },
|
|
21
|
-
method: 'GET'
|
|
22
|
-
}
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
const app = appFactory(seed);
|
|
26
|
-
expect(app).toBeDefined();
|
|
27
|
-
expect(app["runtimeRequestCollection"]).toEqual(seed);
|
|
28
|
-
});
|
|
29
|
-
|
|
30
|
-
test('Creates app with semi-properly configured seed', () => {
|
|
31
|
-
const seed: MethodBasedRuntimeRequestCollection = {
|
|
32
|
-
GET: {
|
|
33
|
-
"/test": {
|
|
34
|
-
path: "/test",
|
|
35
|
-
body: { test: true },
|
|
36
|
-
method: 'GET'
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
const semiSeed: MethodBasedRuntimeRequestCollection = {
|
|
41
|
-
GET: {
|
|
42
|
-
"/test": {
|
|
43
|
-
path: "/test1",
|
|
44
|
-
body: { test: true },
|
|
45
|
-
method: 'PUT'
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
const app = appFactory(semiSeed);
|
|
50
|
-
expect(app).toBeDefined();
|
|
51
|
-
expect(app["runtimeRequestCollection"]).toEqual(seed);
|
|
52
|
-
});
|
|
53
|
-
|
|
54
|
-
test('throws error on improperly configured seed', () => {
|
|
55
|
-
const seed = {
|
|
56
|
-
"/test": {
|
|
57
|
-
path: "/test",
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
expect(() => appFactory(seed as any)).toThrowError('Intial requests JSON is invalid')
|
|
62
|
-
});
|
|
63
|
-
});
|
|
64
|
-
|
|
65
|
-
describe('GET /', () => {
|
|
66
|
-
const empty: MethodBasedRuntimeRequestCollection = {};
|
|
67
|
-
const seeded: MethodBasedRuntimeRequestCollection = {
|
|
68
|
-
GET: {
|
|
69
|
-
"/test": {
|
|
70
|
-
path: "/test",
|
|
71
|
-
body: { test: true },
|
|
72
|
-
method: 'GET'
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
test.each([['empty', empty], ['seeded', seeded]])('should get current collection - %s', async (_, seed) => {
|
|
77
|
-
const app = appFactory(seed);
|
|
78
|
-
const response = await request(app).get('/')
|
|
79
|
-
.expect('Content-Type', /json/)
|
|
80
|
-
.expect(200);
|
|
81
|
-
|
|
82
|
-
expect(response.body).toEqual(app["runtimeRequestCollection"]);
|
|
83
|
-
})
|
|
84
|
-
});
|
|
85
|
-
|
|
86
|
-
describe('POST /', () => {
|
|
87
|
-
test('should accept a valid RuntimeRequestBody', async () => {
|
|
88
|
-
const app = appFactory();
|
|
89
|
-
const reqeustBody: RuntimeRequestBody = {
|
|
90
|
-
path: '/test',
|
|
91
|
-
body: { hello: 'world' },
|
|
92
|
-
method: 'POST'
|
|
93
|
-
};
|
|
94
|
-
await request(app)
|
|
95
|
-
.post('/')
|
|
96
|
-
.send(reqeustBody)
|
|
97
|
-
.expect(204);
|
|
98
|
-
|
|
99
|
-
expect(app["runtimeRequestCollection"]).toEqual(expect.objectContaining({
|
|
100
|
-
[reqeustBody.method]: { [reqeustBody.path]: reqeustBody }
|
|
101
|
-
}));
|
|
102
|
-
});
|
|
103
|
-
|
|
104
|
-
test('should deny an invalid RuntimeRequestBody', async () => {
|
|
105
|
-
const app = appFactory();
|
|
106
|
-
const reqeustBody = {
|
|
107
|
-
path: '/test',
|
|
108
|
-
};
|
|
109
|
-
await request(app)
|
|
110
|
-
.post('/')
|
|
111
|
-
.send(reqeustBody)
|
|
112
|
-
.expect(400)
|
|
113
|
-
.catch(() => { });
|
|
114
|
-
});
|
|
115
|
-
});
|
|
116
|
-
|
|
117
|
-
describe('DELETE /?path=<path>&method=<method>', () => {
|
|
118
|
-
test('should remove an existing path', async () => {
|
|
119
|
-
const body: RuntimeRequestBody = {
|
|
120
|
-
path: '/test',
|
|
121
|
-
body: {},
|
|
122
|
-
method: 'GET'
|
|
123
|
-
};
|
|
124
|
-
const collection: MethodBasedRuntimeRequestCollection = {
|
|
125
|
-
[body.method]: { [body.path]: body }
|
|
126
|
-
};
|
|
127
|
-
const app = appFactory(collection);
|
|
128
|
-
await request(app)
|
|
129
|
-
.delete('/')
|
|
130
|
-
.query({ path: [body.path], method: body.method })
|
|
131
|
-
.expect(204);
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
expect(app["runtimeRequestCollection"]).toEqual(expect.not.objectContaining({
|
|
135
|
-
[body.method]: expect.objectContaining({ [body.path]: body })
|
|
136
|
-
}));
|
|
137
|
-
})
|
|
138
|
-
|
|
139
|
-
test('should return 204 when nothing needs to be removed', async () => {
|
|
140
|
-
const body: RuntimeRequestBody = {
|
|
141
|
-
path: '/test',
|
|
142
|
-
body: {},
|
|
143
|
-
method: 'GET'
|
|
144
|
-
};
|
|
145
|
-
const collection: MethodBasedRuntimeRequestCollection = {
|
|
146
|
-
|
|
147
|
-
};
|
|
148
|
-
const app = appFactory(collection);
|
|
149
|
-
await request(app)
|
|
150
|
-
.delete('/')
|
|
151
|
-
.query({ path: [body.path], method: body.method })
|
|
152
|
-
.expect(204);
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
expect(app["runtimeRequestCollection"]).toEqual(expect.not.objectContaining({
|
|
156
|
-
[body.path]: body
|
|
157
|
-
}));
|
|
158
|
-
})
|
|
159
|
-
});
|
|
160
|
-
|
|
161
|
-
describe('METHOD /*', () => {
|
|
162
|
-
const methods = SupportedMethodsColection.map(m => [m])
|
|
163
|
-
test.each(methods)('%s should render JSON hbs template', async (method) => {
|
|
164
|
-
const requestBody: RuntimeRequestBody = {
|
|
165
|
-
path: '/test/:id',
|
|
166
|
-
body: `{"id": {{params.id}} }`,
|
|
167
|
-
method
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
const collection: MethodBasedRuntimeRequestCollection = {
|
|
171
|
-
[requestBody.method]: { [requestBody.path]: requestBody }
|
|
172
|
-
};
|
|
173
|
-
const id = 42;
|
|
174
|
-
|
|
175
|
-
const app = appFactory(collection);
|
|
176
|
-
|
|
177
|
-
const response = await request(app)[method.toLocaleLowerCase()](`/test/${id}`)
|
|
178
|
-
.expect(200)
|
|
179
|
-
.expect('Content-Type', /json/);
|
|
180
|
-
|
|
181
|
-
expect(response.body).toEqual({ id })
|
|
182
|
-
});
|
|
183
|
-
});
|
|
184
|
-
|
|
185
|
-
describe('isMethodBasedRuntimeRequestCollection', () => {
|
|
186
|
-
test('should be true', () => {
|
|
187
|
-
const obj: MethodBasedRuntimeRequestCollection = {
|
|
188
|
-
GET: {
|
|
189
|
-
'/test': {
|
|
190
|
-
path: '/test',
|
|
191
|
-
method: 'GET',
|
|
192
|
-
body: {},
|
|
193
|
-
status: 200
|
|
194
|
-
}
|
|
195
|
-
}
|
|
196
|
-
};
|
|
197
|
-
expect(isMethodBasedRuntimeRequestCollection(obj)).toBeTruthy();
|
|
198
|
-
});
|
|
199
|
-
|
|
200
|
-
test('should be false', () => {
|
|
201
|
-
const obj = {
|
|
202
|
-
GETter: {
|
|
203
|
-
'/test': {
|
|
204
|
-
path: '/test',
|
|
205
|
-
method: 'GET',
|
|
206
|
-
body: {},
|
|
207
|
-
status: 200
|
|
208
|
-
}
|
|
209
|
-
}
|
|
210
|
-
};
|
|
211
|
-
expect(isMethodBasedRuntimeRequestCollection(obj)).toBeFalsy();
|
|
212
|
-
});
|
|
1
|
+
import request from 'supertest';
|
|
2
|
+
import { appFactory, isMethodBasedRuntimeRequestCollection, MethodBasedRuntimeRequestCollection, RuntimeRequestBody, SupportedMethodsColection } from './app';
|
|
3
|
+
|
|
4
|
+
describe('appFactory', () => {
|
|
5
|
+
test('Creates app with no seed', () => {
|
|
6
|
+
const app = appFactory();
|
|
7
|
+
expect(app).toBeDefined();
|
|
8
|
+
});
|
|
9
|
+
|
|
10
|
+
test('Creates app with empty seed', () => {
|
|
11
|
+
const app = appFactory({});
|
|
12
|
+
expect(app).toBeDefined();
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
test('Creates app with properly configured seed', () => {
|
|
16
|
+
const seed: MethodBasedRuntimeRequestCollection = {
|
|
17
|
+
GET: {
|
|
18
|
+
"/test": {
|
|
19
|
+
path: "/test",
|
|
20
|
+
body: { test: true },
|
|
21
|
+
method: 'GET'
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
const app = appFactory(seed);
|
|
26
|
+
expect(app).toBeDefined();
|
|
27
|
+
expect(app["runtimeRequestCollection"]).toEqual(seed);
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
test('Creates app with semi-properly configured seed', () => {
|
|
31
|
+
const seed: MethodBasedRuntimeRequestCollection = {
|
|
32
|
+
GET: {
|
|
33
|
+
"/test": {
|
|
34
|
+
path: "/test",
|
|
35
|
+
body: { test: true },
|
|
36
|
+
method: 'GET'
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
const semiSeed: MethodBasedRuntimeRequestCollection = {
|
|
41
|
+
GET: {
|
|
42
|
+
"/test": {
|
|
43
|
+
path: "/test1",
|
|
44
|
+
body: { test: true },
|
|
45
|
+
method: 'PUT'
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
const app = appFactory(semiSeed);
|
|
50
|
+
expect(app).toBeDefined();
|
|
51
|
+
expect(app["runtimeRequestCollection"]).toEqual(seed);
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
test('throws error on improperly configured seed', () => {
|
|
55
|
+
const seed = {
|
|
56
|
+
"/test": {
|
|
57
|
+
path: "/test",
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
expect(() => appFactory(seed as any)).toThrowError('Intial requests JSON is invalid')
|
|
62
|
+
});
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
describe('GET /', () => {
|
|
66
|
+
const empty: MethodBasedRuntimeRequestCollection = {};
|
|
67
|
+
const seeded: MethodBasedRuntimeRequestCollection = {
|
|
68
|
+
GET: {
|
|
69
|
+
"/test": {
|
|
70
|
+
path: "/test",
|
|
71
|
+
body: { test: true },
|
|
72
|
+
method: 'GET'
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
test.each([['empty', empty], ['seeded', seeded]])('should get current collection - %s', async (_, seed) => {
|
|
77
|
+
const app = appFactory(seed);
|
|
78
|
+
const response = await request(app).get('/')
|
|
79
|
+
.expect('Content-Type', /json/)
|
|
80
|
+
.expect(200);
|
|
81
|
+
|
|
82
|
+
expect(response.body).toEqual(app["runtimeRequestCollection"]);
|
|
83
|
+
})
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
describe('POST /', () => {
|
|
87
|
+
test('should accept a valid RuntimeRequestBody', async () => {
|
|
88
|
+
const app = appFactory();
|
|
89
|
+
const reqeustBody: RuntimeRequestBody = {
|
|
90
|
+
path: '/test',
|
|
91
|
+
body: { hello: 'world' },
|
|
92
|
+
method: 'POST'
|
|
93
|
+
};
|
|
94
|
+
await request(app)
|
|
95
|
+
.post('/')
|
|
96
|
+
.send(reqeustBody)
|
|
97
|
+
.expect(204);
|
|
98
|
+
|
|
99
|
+
expect(app["runtimeRequestCollection"]).toEqual(expect.objectContaining({
|
|
100
|
+
[reqeustBody.method]: { [reqeustBody.path]: reqeustBody }
|
|
101
|
+
}));
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
test('should deny an invalid RuntimeRequestBody', async () => {
|
|
105
|
+
const app = appFactory();
|
|
106
|
+
const reqeustBody = {
|
|
107
|
+
path: '/test',
|
|
108
|
+
};
|
|
109
|
+
await request(app)
|
|
110
|
+
.post('/')
|
|
111
|
+
.send(reqeustBody)
|
|
112
|
+
.expect(400)
|
|
113
|
+
.catch(() => { });
|
|
114
|
+
});
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
describe('DELETE /?path=<path>&method=<method>', () => {
|
|
118
|
+
test('should remove an existing path', async () => {
|
|
119
|
+
const body: RuntimeRequestBody = {
|
|
120
|
+
path: '/test',
|
|
121
|
+
body: {},
|
|
122
|
+
method: 'GET'
|
|
123
|
+
};
|
|
124
|
+
const collection: MethodBasedRuntimeRequestCollection = {
|
|
125
|
+
[body.method]: { [body.path]: body }
|
|
126
|
+
};
|
|
127
|
+
const app = appFactory(collection);
|
|
128
|
+
await request(app)
|
|
129
|
+
.delete('/')
|
|
130
|
+
.query({ path: [body.path], method: body.method })
|
|
131
|
+
.expect(204);
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
expect(app["runtimeRequestCollection"]).toEqual(expect.not.objectContaining({
|
|
135
|
+
[body.method]: expect.objectContaining({ [body.path]: body })
|
|
136
|
+
}));
|
|
137
|
+
})
|
|
138
|
+
|
|
139
|
+
test('should return 204 when nothing needs to be removed', async () => {
|
|
140
|
+
const body: RuntimeRequestBody = {
|
|
141
|
+
path: '/test',
|
|
142
|
+
body: {},
|
|
143
|
+
method: 'GET'
|
|
144
|
+
};
|
|
145
|
+
const collection: MethodBasedRuntimeRequestCollection = {
|
|
146
|
+
|
|
147
|
+
};
|
|
148
|
+
const app = appFactory(collection);
|
|
149
|
+
await request(app)
|
|
150
|
+
.delete('/')
|
|
151
|
+
.query({ path: [body.path], method: body.method })
|
|
152
|
+
.expect(204);
|
|
153
|
+
|
|
154
|
+
|
|
155
|
+
expect(app["runtimeRequestCollection"]).toEqual(expect.not.objectContaining({
|
|
156
|
+
[body.path]: body
|
|
157
|
+
}));
|
|
158
|
+
})
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
describe('METHOD /*', () => {
|
|
162
|
+
const methods = SupportedMethodsColection.map(m => [m])
|
|
163
|
+
test.each(methods)('%s should render JSON hbs template', async (method) => {
|
|
164
|
+
const requestBody: RuntimeRequestBody = {
|
|
165
|
+
path: '/test/:id',
|
|
166
|
+
body: `{"id": {{params.id}} }`,
|
|
167
|
+
method
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
const collection: MethodBasedRuntimeRequestCollection = {
|
|
171
|
+
[requestBody.method]: { [requestBody.path]: requestBody }
|
|
172
|
+
};
|
|
173
|
+
const id = 42;
|
|
174
|
+
|
|
175
|
+
const app = appFactory(collection);
|
|
176
|
+
|
|
177
|
+
const response = await request(app)[method.toLocaleLowerCase()](`/test/${id}`)
|
|
178
|
+
.expect(200)
|
|
179
|
+
.expect('Content-Type', /json/);
|
|
180
|
+
|
|
181
|
+
expect(response.body).toEqual({ id })
|
|
182
|
+
});
|
|
183
|
+
});
|
|
184
|
+
|
|
185
|
+
describe('isMethodBasedRuntimeRequestCollection', () => {
|
|
186
|
+
test('should be true', () => {
|
|
187
|
+
const obj: MethodBasedRuntimeRequestCollection = {
|
|
188
|
+
GET: {
|
|
189
|
+
'/test': {
|
|
190
|
+
path: '/test',
|
|
191
|
+
method: 'GET',
|
|
192
|
+
body: {},
|
|
193
|
+
status: 200
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
};
|
|
197
|
+
expect(isMethodBasedRuntimeRequestCollection(obj)).toBeTruthy();
|
|
198
|
+
});
|
|
199
|
+
|
|
200
|
+
test('should be false', () => {
|
|
201
|
+
const obj = {
|
|
202
|
+
GETter: {
|
|
203
|
+
'/test': {
|
|
204
|
+
path: '/test',
|
|
205
|
+
method: 'GET',
|
|
206
|
+
body: {},
|
|
207
|
+
status: 200
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
};
|
|
211
|
+
expect(isMethodBasedRuntimeRequestCollection(obj)).toBeFalsy();
|
|
212
|
+
});
|
|
213
213
|
});
|