temba 0.17.0 → 0.19.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/README.md +58 -10
- package/package.json +17 -17
- package/{config → src/config}/index.d.ts +15 -8
- package/src/config/index.d.ts.map +1 -0
- package/{config → src/config}/index.js +23 -28
- package/src/config/index.js.map +1 -0
- package/src/delay/delayMiddleware.d.ts +3 -0
- package/src/delay/delayMiddleware.d.ts.map +1 -0
- package/src/delay/delayMiddleware.js +13 -0
- package/src/delay/delayMiddleware.js.map +1 -0
- package/src/index.d.ts +6 -0
- package/src/index.d.ts.map +1 -0
- package/src/index.js +83 -0
- package/src/index.js.map +1 -0
- package/src/queries/in-memory.d.ts +3 -0
- package/src/queries/in-memory.d.ts.map +1 -0
- package/src/queries/in-memory.js +61 -0
- package/src/queries/in-memory.js.map +1 -0
- package/src/queries/mongo.d.ts +3 -0
- package/src/queries/mongo.d.ts.map +1 -0
- package/src/queries/mongo.js +75 -0
- package/src/queries/mongo.js.map +1 -0
- package/src/queries/queries.d.ts +2 -0
- package/src/queries/queries.d.ts.map +1 -0
- package/src/queries/queries.js +10 -0
- package/src/queries/queries.js.map +1 -0
- package/src/queries/types.d.ts +15 -0
- package/src/queries/types.d.ts.map +1 -0
- package/src/queries/types.js +2 -0
- package/src/queries/types.js.map +1 -0
- package/src/requestBodyInterceptor/interceptRequestBody.d.ts +3 -0
- package/src/requestBodyInterceptor/interceptRequestBody.d.ts.map +1 -0
- package/src/requestBodyInterceptor/interceptRequestBody.js +14 -0
- package/src/requestBodyInterceptor/interceptRequestBody.js.map +1 -0
- package/src/requestBodyInterceptor/types.d.ts +12 -0
- package/src/requestBodyInterceptor/types.d.ts.map +1 -0
- package/src/requestBodyInterceptor/types.js +2 -0
- package/src/requestBodyInterceptor/types.js.map +1 -0
- package/src/requestHandlers/delete.d.ts +12 -0
- package/src/requestHandlers/delete.d.ts.map +1 -0
- package/src/requestHandlers/delete.js +22 -0
- package/src/requestHandlers/delete.js.map +1 -0
- package/src/requestHandlers/get.d.ts +22 -0
- package/src/requestHandlers/get.d.ts.map +1 -0
- package/src/requestHandlers/get.js +47 -0
- package/src/requestHandlers/get.js.map +1 -0
- package/src/requestHandlers/index.d.ts +54 -0
- package/src/requestHandlers/index.d.ts.map +1 -0
- package/src/requestHandlers/index.js +21 -0
- package/src/requestHandlers/index.js.map +1 -0
- package/src/requestHandlers/patch.d.ts +9 -0
- package/src/requestHandlers/patch.d.ts.map +1 -0
- package/src/requestHandlers/patch.js +35 -0
- package/src/requestHandlers/patch.js.map +1 -0
- package/src/requestHandlers/post.d.ts +18 -0
- package/src/requestHandlers/post.d.ts.map +1 -0
- package/src/requestHandlers/post.js +37 -0
- package/src/requestHandlers/post.js.map +1 -0
- package/src/requestHandlers/put.d.ts +9 -0
- package/src/requestHandlers/put.d.ts.map +1 -0
- package/src/requestHandlers/put.js +35 -0
- package/src/requestHandlers/put.js.map +1 -0
- package/src/requestHandlers/types.d.ts +38 -0
- package/src/requestHandlers/types.d.ts.map +1 -0
- package/src/requestHandlers/types.js +2 -0
- package/src/requestHandlers/types.js.map +1 -0
- package/src/requestHandlers/utils.d.ts +2 -0
- package/src/requestHandlers/utils.d.ts.map +1 -0
- package/src/requestHandlers/utils.js +6 -0
- package/src/requestHandlers/utils.js.map +1 -0
- package/src/resourceRouter.d.ts +5 -0
- package/src/resourceRouter.d.ts.map +1 -0
- package/src/resourceRouter.js +95 -0
- package/src/resourceRouter.js.map +1 -0
- package/src/responseBodyInterceptor/interceptResponseBody.d.ts +3 -0
- package/src/responseBodyInterceptor/interceptResponseBody.d.ts.map +1 -0
- package/src/responseBodyInterceptor/interceptResponseBody.js +7 -0
- package/src/responseBodyInterceptor/interceptResponseBody.js.map +1 -0
- package/src/responseBodyInterceptor/types.d.ts +11 -0
- package/src/responseBodyInterceptor/types.d.ts.map +1 -0
- package/src/responseBodyInterceptor/types.js +2 -0
- package/src/responseBodyInterceptor/types.js.map +1 -0
- package/src/schema/compile.d.ts +3 -0
- package/src/schema/compile.d.ts.map +1 -0
- package/src/schema/compile.js +26 -0
- package/src/schema/compile.js.map +1 -0
- package/src/schema/types.d.ts +25 -0
- package/src/schema/types.d.ts.map +1 -0
- package/src/schema/types.js +2 -0
- package/{routes → src/schema}/types.js.map +1 -1
- package/src/schema/validate.d.ts +4 -0
- package/src/schema/validate.d.ts.map +1 -0
- package/src/schema/validate.js +14 -0
- package/src/schema/validate.js.map +1 -0
- package/src/urls/urlParser.d.ts +5 -0
- package/src/urls/urlParser.d.ts.map +1 -0
- package/src/urls/urlParser.js +9 -0
- package/src/urls/urlParser.js.map +1 -0
- package/test/integration/api-prefix.test.d.ts +2 -0
- package/test/integration/api-prefix.test.d.ts.map +1 -0
- package/test/integration/api-prefix.test.js +69 -0
- package/test/integration/api-prefix.test.js.map +1 -0
- package/test/integration/createServer.d.ts +4 -0
- package/test/integration/createServer.d.ts.map +1 -0
- package/test/integration/createServer.js +4 -0
- package/test/integration/createServer.js.map +1 -0
- package/test/integration/crud.test.d.ts +2 -0
- package/test/integration/crud.test.d.ts.map +1 -0
- package/test/integration/crud.test.js +173 -0
- package/test/integration/crud.test.js.map +1 -0
- package/test/integration/custom-router.test.d.ts +2 -0
- package/test/integration/custom-router.test.d.ts.map +1 -0
- package/test/integration/custom-router.test.js +74 -0
- package/test/integration/custom-router.test.js.map +1 -0
- package/test/integration/head-method.test.d.ts +2 -0
- package/test/integration/head-method.test.d.ts.map +1 -0
- package/test/integration/head-method.test.js +38 -0
- package/test/integration/head-method.test.js.map +1 -0
- package/test/integration/options-method.test.d.ts +2 -0
- package/test/integration/options-method.test.d.ts.map +1 -0
- package/test/integration/options-method.test.js +30 -0
- package/test/integration/options-method.test.js.map +1 -0
- package/test/integration/requestBodyInterceptor/requestBodyInterceptor-change-requestBody.test.d.ts +2 -0
- package/test/integration/requestBodyInterceptor/requestBodyInterceptor-change-requestBody.test.d.ts.map +1 -0
- package/test/integration/requestBodyInterceptor/requestBodyInterceptor-change-requestBody.test.js +76 -0
- package/test/integration/requestBodyInterceptor/requestBodyInterceptor-change-requestBody.test.js.map +1 -0
- package/test/integration/requestBodyInterceptor/requestBodyInterceptor-error-string.test.d.ts +2 -0
- package/test/integration/requestBodyInterceptor/requestBodyInterceptor-error-string.test.d.ts.map +1 -0
- package/test/integration/requestBodyInterceptor/requestBodyInterceptor-error-string.test.js +60 -0
- package/test/integration/requestBodyInterceptor/requestBodyInterceptor-error-string.test.js.map +1 -0
- package/test/integration/requestBodyInterceptor/requestBodyInterceptor-invalid-return-types.test.d.ts +2 -0
- package/test/integration/requestBodyInterceptor/requestBodyInterceptor-invalid-return-types.test.d.ts.map +1 -0
- package/test/integration/requestBodyInterceptor/requestBodyInterceptor-invalid-return-types.test.js +89 -0
- package/test/integration/requestBodyInterceptor/requestBodyInterceptor-invalid-return-types.test.js.map +1 -0
- package/test/integration/requestBodyInterceptor/requestBodyInterceptor-void.test.d.ts +2 -0
- package/test/integration/requestBodyInterceptor/requestBodyInterceptor-void.test.d.ts.map +1 -0
- package/test/integration/requestBodyInterceptor/requestBodyInterceptor-void.test.js +47 -0
- package/test/integration/requestBodyInterceptor/requestBodyInterceptor-void.test.js.map +1 -0
- package/test/integration/responseBodyInterceptor.test.d.ts +2 -0
- package/test/integration/responseBodyInterceptor.test.d.ts.map +1 -0
- package/test/integration/responseBodyInterceptor.test.js +107 -0
- package/test/integration/responseBodyInterceptor.test.js.map +1 -0
- package/test/integration/returnNullFields.test.d.ts +2 -0
- package/test/integration/returnNullFields.test.d.ts.map +1 -0
- package/test/integration/returnNullFields.test.js +51 -0
- package/test/integration/returnNullFields.test.js.map +1 -0
- package/test/integration/root-url.test.d.ts +2 -0
- package/test/integration/root-url.test.d.ts.map +1 -0
- package/test/integration/root-url.test.js +29 -0
- package/test/integration/root-url.test.js.map +1 -0
- package/test/integration/schema-validation.test.d.ts +2 -0
- package/test/integration/schema-validation.test.d.ts.map +1 -0
- package/test/integration/schema-validation.test.js +169 -0
- package/test/integration/schema-validation.test.js.map +1 -0
- package/test/unit/config/config.test.d.ts +2 -0
- package/test/unit/config/config.test.d.ts.map +1 -0
- package/test/unit/config/config.test.js +121 -0
- package/test/unit/config/config.test.js.map +1 -0
- package/test/unit/urls/urlParser.test.d.ts +2 -0
- package/test/unit/urls/urlParser.test.d.ts.map +1 -0
- package/test/unit/urls/urlParser.test.js +43 -0
- package/test/unit/urls/urlParser.test.js.map +1 -0
- package/tsconfig.tsbuildinfo +1 -0
- package/vitest.config.d.ts +3 -0
- package/vitest.config.d.ts.map +1 -0
- package/vitest.config.js +10 -0
- package/vitest.config.js.map +1 -0
- package/config/index.js.map +0 -1
- package/delay/delayMiddleware.d.ts +0 -2
- package/delay/delayMiddleware.js +0 -16
- package/delay/delayMiddleware.js.map +0 -1
- package/index.d.ts +0 -5
- package/index.js +0 -94
- package/index.js.map +0 -1
- package/queries/in-memory.d.ts +0 -19
- package/queries/in-memory.js +0 -66
- package/queries/in-memory.js.map +0 -1
- package/queries/mongo.d.ts +0 -19
- package/queries/mongo.js +0 -106
- package/queries/mongo.js.map +0 -1
- package/queries/queries.d.ts +0 -20
- package/queries/queries.js +0 -17
- package/queries/queries.js.map +0 -1
- package/routes/delete.d.ts +0 -4
- package/routes/delete.js +0 -39
- package/routes/delete.js.map +0 -1
- package/routes/get.d.ts +0 -4
- package/routes/get.js +0 -71
- package/routes/get.js.map +0 -1
- package/routes/interceptors.d.ts +0 -3
- package/routes/interceptors.js +0 -22
- package/routes/interceptors.js.map +0 -1
- package/routes/patch.d.ts +0 -4
- package/routes/patch.js +0 -47
- package/routes/patch.js.map +0 -1
- package/routes/post.d.ts +0 -4
- package/routes/post.js +0 -47
- package/routes/post.js.map +0 -1
- package/routes/put.d.ts +0 -4
- package/routes/put.js +0 -47
- package/routes/put.js.map +0 -1
- package/routes/routes.d.ts +0 -6
- package/routes/routes.js +0 -61
- package/routes/routes.js.map +0 -1
- package/routes/types.d.ts +0 -17
- package/routes/types.js +0 -3
- package/routes/utils.d.ts +0 -3
- package/routes/utils.js +0 -8
- package/routes/utils.js.map +0 -1
- package/urls/urlMiddleware.d.ts +0 -3
- package/urls/urlMiddleware.js +0 -30
- package/urls/urlMiddleware.js.map +0 -1
- package/urls/urlParser.d.ts +0 -5
- package/urls/urlParser.js +0 -13
- package/urls/urlParser.js.map +0 -1
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import { describe, beforeEach, test, expect } from 'vitest';
|
|
2
|
+
import request from 'supertest';
|
|
3
|
+
import createServer from './createServer';
|
|
4
|
+
describe('responseBodyInterceptor unusual (but allowed) implementations', () => {
|
|
5
|
+
const noReturnValues = [undefined, null];
|
|
6
|
+
test.each(noReturnValues)('When responseBodyInterceptor returns nothing, return original response body', async (returnValue) => {
|
|
7
|
+
const tembaServer = createServer({
|
|
8
|
+
responseBodyInterceptor: () => {
|
|
9
|
+
//do not return anything when returnValue is undefined
|
|
10
|
+
if (typeof returnValue !== 'undefined')
|
|
11
|
+
return returnValue;
|
|
12
|
+
},
|
|
13
|
+
});
|
|
14
|
+
// Delete all items.
|
|
15
|
+
await request(tembaServer).delete('/stuff');
|
|
16
|
+
// As the responseBodyInterceptor returns nothing, the response body should be the same
|
|
17
|
+
// as it would be without the responseBodyInterceptor.
|
|
18
|
+
const response = await request(tembaServer).get('/stuff');
|
|
19
|
+
expect(response.statusCode).toEqual(200);
|
|
20
|
+
expect(response.text).toEqual('[]');
|
|
21
|
+
// Create an item
|
|
22
|
+
const { body: { id: newId }, } = await request(tembaServer).post('/stuff').send({ name: 'newItem' });
|
|
23
|
+
// As the responseBodyInterceptor returns nothing, the response body should be the same
|
|
24
|
+
// as it would be without the responseBodyInterceptor.
|
|
25
|
+
const response2 = await request(tembaServer).get('/stuff');
|
|
26
|
+
expect(response2.body.length).toBe(1);
|
|
27
|
+
expect(response2.body[0].name).toBe('newItem');
|
|
28
|
+
// Now get the item by its id, which should also just return the same item.
|
|
29
|
+
const response3 = await request(tembaServer).get('/stuff/' + newId);
|
|
30
|
+
expect(response3.body.name).toEqual('newItem');
|
|
31
|
+
});
|
|
32
|
+
test('When responseBodyInterceptor throws an exception, return a 500 status with error details', async () => {
|
|
33
|
+
const tembaServer = createServer({
|
|
34
|
+
responseBodyInterceptor: () => {
|
|
35
|
+
throw new Error('Something went wrong');
|
|
36
|
+
},
|
|
37
|
+
});
|
|
38
|
+
const response = await request(tembaServer).get('/stuff');
|
|
39
|
+
expect(response.statusCode).toEqual(500);
|
|
40
|
+
expect(response.body.message).toEqual(`Something went wrong`);
|
|
41
|
+
});
|
|
42
|
+
test('When responseBodyInterceptor does not return an object or array, still return the intercepted value', async () => {
|
|
43
|
+
const tembaServer = createServer({
|
|
44
|
+
responseBodyInterceptor: (info) => {
|
|
45
|
+
if ('id' in info) {
|
|
46
|
+
return 'A string, instead of an object';
|
|
47
|
+
}
|
|
48
|
+
else {
|
|
49
|
+
return 'A string, instead of an array';
|
|
50
|
+
}
|
|
51
|
+
},
|
|
52
|
+
});
|
|
53
|
+
const { body: { id }, } = await request(tembaServer).post('/stuff').send({ name: 'newItem' });
|
|
54
|
+
const response = await request(tembaServer).get('/stuff');
|
|
55
|
+
expect(response.statusCode).toEqual(200);
|
|
56
|
+
expect(response.body).toEqual('A string, instead of an array');
|
|
57
|
+
const response2 = await request(tembaServer).get('/stuff/' + id);
|
|
58
|
+
expect(response2.statusCode).toEqual(200);
|
|
59
|
+
expect(response2.body).toEqual('A string, instead of an object');
|
|
60
|
+
});
|
|
61
|
+
});
|
|
62
|
+
describe('responseBodyInterceptor returns an updated response', () => {
|
|
63
|
+
const tembaServer = createServer({
|
|
64
|
+
responseBodyInterceptor: (info) => {
|
|
65
|
+
if (info.resource === 'stuff') {
|
|
66
|
+
if ('id' in info) {
|
|
67
|
+
return { ...info.body, extra: 'stuff' };
|
|
68
|
+
}
|
|
69
|
+
else {
|
|
70
|
+
return info.body.map((item, index) => ({
|
|
71
|
+
...item,
|
|
72
|
+
extra: 'stuff ' + index,
|
|
73
|
+
}));
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
},
|
|
77
|
+
});
|
|
78
|
+
beforeEach(async () => {
|
|
79
|
+
// Delete all items
|
|
80
|
+
await request(tembaServer).delete('/stuff');
|
|
81
|
+
});
|
|
82
|
+
test('GET a collection just returns the same collection', async () => {
|
|
83
|
+
// Create 2 items
|
|
84
|
+
await request(tembaServer).post('/stuff').send({ name: 'newItem1' });
|
|
85
|
+
await request(tembaServer).post('/stuff').send({ name: 'newItem2' });
|
|
86
|
+
// Now get the collection, which should have extra stuff
|
|
87
|
+
const getAllResponse = await request(tembaServer).get('/stuff');
|
|
88
|
+
expect(getAllResponse.status).toBe(200);
|
|
89
|
+
expect(getAllResponse.body.length).toBe(2);
|
|
90
|
+
expect(getAllResponse.body[0].name).toBe('newItem1');
|
|
91
|
+
expect(getAllResponse.body[0].extra).toBe('stuff 0');
|
|
92
|
+
expect(getAllResponse.body[1].name).toBe('newItem2');
|
|
93
|
+
expect(getAllResponse.body[1].extra).toBe('stuff 1');
|
|
94
|
+
});
|
|
95
|
+
test('GET an item just returns the same item', async () => {
|
|
96
|
+
// Create an item
|
|
97
|
+
const newItem = { name: 'newItem' };
|
|
98
|
+
const { body: { id }, } = await request(tembaServer).post('/stuff').send(newItem);
|
|
99
|
+
// Now get the item, which should just return the same item.
|
|
100
|
+
const response = await request(tembaServer).get('/stuff/' + id);
|
|
101
|
+
expect(response.statusCode).toEqual(200);
|
|
102
|
+
expect(response.body.name).toEqual('newItem');
|
|
103
|
+
expect(response.body.id).toEqual(id);
|
|
104
|
+
expect(response.body.extra).toEqual('stuff');
|
|
105
|
+
});
|
|
106
|
+
});
|
|
107
|
+
//# sourceMappingURL=responseBodyInterceptor.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"responseBodyInterceptor.test.js","sourceRoot":"","sources":["../../../test/integration/responseBodyInterceptor.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAA;AAC3D,OAAO,OAAO,MAAM,WAAW,CAAA;AAE/B,OAAO,YAAY,MAAM,gBAAgB,CAAA;AAEzC,QAAQ,CAAC,+DAA+D,EAAE,GAAG,EAAE;IAC7E,MAAM,cAAc,GAAG,CAAC,SAAS,EAAE,IAAI,CAAC,CAAA;IACxC,IAAI,CAAC,IAAI,CAAC,cAAc,CAAC,CACvB,6EAA6E,EAC7E,KAAK,EAAE,WAAW,EAAE,EAAE;QACpB,MAAM,WAAW,GAAG,YAAY,CAAC;YAC/B,uBAAuB,EAAE,GAAG,EAAE;gBAC5B,sDAAsD;gBACtD,IAAI,OAAO,WAAW,KAAK,WAAW;oBAAE,OAAO,WAAW,CAAA;YAC5D,CAAC;SACmB,CAAC,CAAA;QAEvB,oBAAoB;QACpB,MAAM,OAAO,CAAC,WAAW,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAA;QAE3C,uFAAuF;QACvF,sDAAsD;QACtD,MAAM,QAAQ,GAAG,MAAM,OAAO,CAAC,WAAW,CAAC,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAA;QACzD,MAAM,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,CAAA;QACxC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,CAAA;QAEnC,iBAAiB;QACjB,MAAM,EACJ,IAAI,EAAE,EAAE,EAAE,EAAE,KAAK,EAAE,GACpB,GAAG,MAAM,OAAO,CAAC,WAAW,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC,CAAA;QAEvE,uFAAuF;QACvF,sDAAsD;QACtD,MAAM,SAAS,GAAG,MAAM,OAAO,CAAC,WAAW,CAAC,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAA;QAC1D,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;QACrC,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAA;QAE9C,2EAA2E;QAC3E,MAAM,SAAS,GAAG,MAAM,OAAO,CAAC,WAAW,CAAC,CAAC,GAAG,CAAC,SAAS,GAAG,KAAK,CAAC,CAAA;QACnE,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,SAAS,CAAC,CAAA;IAChD,CAAC,CACF,CAAA;IAED,IAAI,CAAC,0FAA0F,EAAE,KAAK,IAAI,EAAE;QAC1G,MAAM,WAAW,GAAG,YAAY,CAAC;YAC/B,uBAAuB,EAAE,GAAG,EAAE;gBAC5B,MAAM,IAAI,KAAK,CAAC,sBAAsB,CAAC,CAAA;YACzC,CAAC;SACmB,CAAC,CAAA;QAEvB,MAAM,QAAQ,GAAG,MAAM,OAAO,CAAC,WAAW,CAAC,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAA;QACzD,MAAM,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,CAAA;QACxC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,sBAAsB,CAAC,CAAA;IAC/D,CAAC,CAAC,CAAA;IAEF,IAAI,CAAC,qGAAqG,EAAE,KAAK,IAAI,EAAE;QACrH,MAAM,WAAW,GAAG,YAAY,CAAC;YAC/B,uBAAuB,EAAE,CAAC,IAAI,EAAE,EAAE;gBAChC,IAAI,IAAI,IAAI,IAAI,EAAE,CAAC;oBACjB,OAAO,gCAAgC,CAAA;gBACzC,CAAC;qBAAM,CAAC;oBACN,OAAO,+BAA+B,CAAA;gBACxC,CAAC;YACH,CAAC;SACmB,CAAC,CAAA;QAEvB,MAAM,EACJ,IAAI,EAAE,EAAE,EAAE,EAAE,GACb,GAAG,MAAM,OAAO,CAAC,WAAW,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC,CAAA;QAEvE,MAAM,QAAQ,GAAG,MAAM,OAAO,CAAC,WAAW,CAAC,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAA;QACzD,MAAM,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,CAAA;QACxC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,+BAA+B,CAAC,CAAA;QAE9D,MAAM,SAAS,GAAG,MAAM,OAAO,CAAC,WAAW,CAAC,CAAC,GAAG,CAAC,SAAS,GAAG,EAAE,CAAC,CAAA;QAChE,MAAM,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,CAAA;QACzC,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,gCAAgC,CAAC,CAAA;IAClE,CAAC,CAAC,CAAA;AACJ,CAAC,CAAC,CAAA;AAEF,QAAQ,CAAC,qDAAqD,EAAE,GAAG,EAAE;IACnE,MAAM,WAAW,GAAG,YAAY,CAAC;QAC/B,uBAAuB,EAAE,CAAC,IAAI,EAAE,EAAE;YAChC,IAAI,IAAI,CAAC,QAAQ,KAAK,OAAO,EAAE,CAAC;gBAC9B,IAAI,IAAI,IAAI,IAAI,EAAE,CAAC;oBACjB,OAAO,EAAE,GAAG,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE,OAAO,EAAE,CAAA;gBACzC,CAAC;qBAAM,CAAC;oBACN,OAAO,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC,CAAC;wBACrC,GAAG,IAAI;wBACP,KAAK,EAAE,QAAQ,GAAG,KAAK;qBACxB,CAAC,CAAC,CAAA;gBACL,CAAC;YACH,CAAC;QACH,CAAC;KACmB,CAAC,CAAA;IAEvB,UAAU,CAAC,KAAK,IAAI,EAAE;QACpB,mBAAmB;QACnB,MAAM,OAAO,CAAC,WAAW,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAA;IAC7C,CAAC,CAAC,CAAA;IAEF,IAAI,CAAC,mDAAmD,EAAE,KAAK,IAAI,EAAE;QACnE,iBAAiB;QACjB,MAAM,OAAO,CAAC,WAAW,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,CAAC,CAAA;QACpE,MAAM,OAAO,CAAC,WAAW,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,CAAC,CAAA;QAEpE,wDAAwD;QACxD,MAAM,cAAc,GAAG,MAAM,OAAO,CAAC,WAAW,CAAC,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAA;QAC/D,MAAM,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;QACvC,MAAM,CAAC,cAAc,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;QAC1C,MAAM,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAA;QACpD,MAAM,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAA;QACpD,MAAM,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAA;QACpD,MAAM,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAA;IACtD,CAAC,CAAC,CAAA;IAEF,IAAI,CAAC,wCAAwC,EAAE,KAAK,IAAI,EAAE;QACxD,iBAAiB;QACjB,MAAM,OAAO,GAAG,EAAE,IAAI,EAAE,SAAS,EAAE,CAAA;QACnC,MAAM,EACJ,IAAI,EAAE,EAAE,EAAE,EAAE,GACb,GAAG,MAAM,OAAO,CAAC,WAAW,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;QAE3D,4DAA4D;QAC5D,MAAM,QAAQ,GAAG,MAAM,OAAO,CAAC,WAAW,CAAC,CAAC,GAAG,CAAC,SAAS,GAAG,EAAE,CAAC,CAAA;QAE/D,MAAM,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,CAAA;QACxC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,SAAS,CAAC,CAAA;QAC7C,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAA;QACpC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,CAAA;IAC9C,CAAC,CAAC,CAAA;AACJ,CAAC,CAAC,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"returnNullFields.test.d.ts","sourceRoot":"","sources":["../../../test/integration/returnNullFields.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { test, expect } from 'vitest';
|
|
2
|
+
import request from 'supertest';
|
|
3
|
+
import createServer from './createServer';
|
|
4
|
+
/*
|
|
5
|
+
Tests when configuring returnNullFields.
|
|
6
|
+
*/
|
|
7
|
+
test.each([true, false])('returnNullFields setting is %s', async (returnNullFields) => {
|
|
8
|
+
const tembaServer = createServer({ returnNullFields });
|
|
9
|
+
// Create a car
|
|
10
|
+
const createResponse = await request(tembaServer)
|
|
11
|
+
.post('/cars')
|
|
12
|
+
.send({ brand: 'Mercedes-Benz', color: null });
|
|
13
|
+
expect(createResponse.body.brand).toBe('Mercedes-Benz');
|
|
14
|
+
if (returnNullFields)
|
|
15
|
+
expect(createResponse.body.color).toBeNull();
|
|
16
|
+
else
|
|
17
|
+
expect(createResponse.body.color).toBeUndefined();
|
|
18
|
+
// Fetch all cars
|
|
19
|
+
const getAllResponse = await request(tembaServer).get('/cars');
|
|
20
|
+
expect(getAllResponse.body[0].brand).toBe('Mercedes-Benz');
|
|
21
|
+
if (returnNullFields)
|
|
22
|
+
expect(getAllResponse.body[0].color).toBeNull();
|
|
23
|
+
else
|
|
24
|
+
expect(getAllResponse.body[0].color).toBeUndefined();
|
|
25
|
+
// Fetch one car
|
|
26
|
+
const getOneResponse = await request(tembaServer).get('/cars/' + createResponse.body.id);
|
|
27
|
+
expect(getOneResponse.body.brand).toBe('Mercedes-Benz');
|
|
28
|
+
if (returnNullFields)
|
|
29
|
+
expect(getOneResponse.body.color).toBeNull();
|
|
30
|
+
else
|
|
31
|
+
expect(getOneResponse.body.color).toBeUndefined();
|
|
32
|
+
// Replace one car
|
|
33
|
+
const replaceResponse = await request(tembaServer)
|
|
34
|
+
.put('/cars/' + createResponse.body.id)
|
|
35
|
+
.send({ brand: 'Mercedes-Benz', color: null });
|
|
36
|
+
expect(replaceResponse.body.brand).toBe('Mercedes-Benz');
|
|
37
|
+
if (returnNullFields)
|
|
38
|
+
expect(replaceResponse.body.color).toBeNull();
|
|
39
|
+
else
|
|
40
|
+
expect(replaceResponse.body.color).toBeUndefined();
|
|
41
|
+
// Update one car
|
|
42
|
+
const updateResponse = await request(tembaServer)
|
|
43
|
+
.patch('/cars/' + createResponse.body.id)
|
|
44
|
+
.send({ brand: 'Mercedes-Benz', color: null });
|
|
45
|
+
expect(updateResponse.body.brand).toBe('Mercedes-Benz');
|
|
46
|
+
if (returnNullFields)
|
|
47
|
+
expect(updateResponse.body.color).toBeNull();
|
|
48
|
+
else
|
|
49
|
+
expect(updateResponse.body.color).toBeUndefined();
|
|
50
|
+
});
|
|
51
|
+
//# sourceMappingURL=returnNullFields.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"returnNullFields.test.js","sourceRoot":"","sources":["../../../test/integration/returnNullFields.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"root-url.test.d.ts","sourceRoot":"","sources":["../../../test/integration/root-url.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { test, expect } from 'vitest';
|
|
2
|
+
import request from 'supertest';
|
|
3
|
+
import createServer from './createServer';
|
|
4
|
+
/*
|
|
5
|
+
Tests on the root URL: "/"
|
|
6
|
+
*/
|
|
7
|
+
// This Temba server is created with the default configuration, i.e. no config object is supplied.
|
|
8
|
+
const tembaServer = createServer();
|
|
9
|
+
test('GET on root URL returns welcome text', async () => {
|
|
10
|
+
const response = await request(tembaServer).get('/');
|
|
11
|
+
expect(response.statusCode).toEqual(200);
|
|
12
|
+
expect(response.text).toEqual('It works! ツ');
|
|
13
|
+
});
|
|
14
|
+
test('POST on root URL returns Method Not Allowed error', async () => {
|
|
15
|
+
const response = await request(tembaServer).post('/');
|
|
16
|
+
expect(response.statusCode).toEqual(405);
|
|
17
|
+
expect(response.body.message).toEqual('Method Not Allowed');
|
|
18
|
+
});
|
|
19
|
+
test('PUT on root URL returns Method Not Allowed error', async () => {
|
|
20
|
+
const response = await request(tembaServer).put('/');
|
|
21
|
+
expect(response.statusCode).toEqual(405);
|
|
22
|
+
expect(response.body.message).toEqual('Method Not Allowed');
|
|
23
|
+
});
|
|
24
|
+
test('DELETE on root URL returns Method Not Allowed error', async () => {
|
|
25
|
+
const response = await request(tembaServer).delete('/');
|
|
26
|
+
expect(response.statusCode).toEqual(405);
|
|
27
|
+
expect(response.body.message).toEqual('Method Not Allowed');
|
|
28
|
+
});
|
|
29
|
+
//# sourceMappingURL=root-url.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"root-url.test.js","sourceRoot":"","sources":["../../../test/integration/root-url.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAA;AACrC,OAAO,OAAO,MAAM,WAAW,CAAA;AAC/B,OAAO,YAAY,MAAM,gBAAgB,CAAA;AAEzC;;EAEE;AAEF,kGAAkG;AAClG,MAAM,WAAW,GAAG,YAAY,EAAE,CAAA;AAElC,IAAI,CAAC,sCAAsC,EAAE,KAAK,IAAI,EAAE;IACtD,MAAM,QAAQ,GAAG,MAAM,OAAO,CAAC,WAAW,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;IAEpD,MAAM,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,CAAA;IACxC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,aAAa,CAAC,CAAA;AAC9C,CAAC,CAAC,CAAA;AAEF,IAAI,CAAC,mDAAmD,EAAE,KAAK,IAAI,EAAE;IACnE,MAAM,QAAQ,GAAG,MAAM,OAAO,CAAC,WAAW,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;IAErD,MAAM,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,CAAA;IACxC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,oBAAoB,CAAC,CAAA;AAC7D,CAAC,CAAC,CAAA;AAEF,IAAI,CAAC,kDAAkD,EAAE,KAAK,IAAI,EAAE;IAClE,MAAM,QAAQ,GAAG,MAAM,OAAO,CAAC,WAAW,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;IAEpD,MAAM,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,CAAA;IACxC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,oBAAoB,CAAC,CAAA;AAC7D,CAAC,CAAC,CAAA;AAEF,IAAI,CAAC,qDAAqD,EAAE,KAAK,IAAI,EAAE;IACrE,MAAM,QAAQ,GAAG,MAAM,OAAO,CAAC,WAAW,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAA;IAEvD,MAAM,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,CAAA;IACxC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,oBAAoB,CAAC,CAAA;AAC7D,CAAC,CAAC,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema-validation.test.d.ts","sourceRoot":"","sources":["../../../test/integration/schema-validation.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
import { test, expect } from 'vitest';
|
|
2
|
+
import request from 'supertest';
|
|
3
|
+
import createServer from './createServer';
|
|
4
|
+
/*
|
|
5
|
+
Tests for JSON Schema validation
|
|
6
|
+
*/
|
|
7
|
+
const resourceUrl = `/cars/`;
|
|
8
|
+
test('Schema validation POST/PUT/PATCH', async () => {
|
|
9
|
+
const schemaCreateReplace = {
|
|
10
|
+
type: 'object',
|
|
11
|
+
properties: {
|
|
12
|
+
price: { type: 'integer' },
|
|
13
|
+
brand: { type: 'string' },
|
|
14
|
+
},
|
|
15
|
+
required: ['brand'],
|
|
16
|
+
additionalProperties: false,
|
|
17
|
+
};
|
|
18
|
+
const schemaUpdate = { ...schemaCreateReplace, required: [] };
|
|
19
|
+
const tembaServer = createServer({
|
|
20
|
+
schemas: {
|
|
21
|
+
cars: {
|
|
22
|
+
post: schemaCreateReplace,
|
|
23
|
+
put: schemaCreateReplace,
|
|
24
|
+
patch: schemaUpdate,
|
|
25
|
+
},
|
|
26
|
+
},
|
|
27
|
+
});
|
|
28
|
+
// POST only the required brand
|
|
29
|
+
let response = await request(tembaServer)
|
|
30
|
+
.post(resourceUrl)
|
|
31
|
+
.send({ brand: 'Mercedes-Benz' })
|
|
32
|
+
.set('Content-Type', 'application/json');
|
|
33
|
+
expect(response.statusCode).toEqual(201);
|
|
34
|
+
expect(response.body.message).toBeUndefined();
|
|
35
|
+
const mercedesId = response.body.id;
|
|
36
|
+
// PUT the required brand and the optional price
|
|
37
|
+
response = await request(tembaServer)
|
|
38
|
+
.put(resourceUrl + mercedesId)
|
|
39
|
+
.send({ brand: 'Mercedes-Benz', price: 100000 })
|
|
40
|
+
.set('Content-Type', 'application/json');
|
|
41
|
+
expect(response.statusCode).toEqual(200);
|
|
42
|
+
expect(response.body.message).toBeUndefined();
|
|
43
|
+
// PUT without the required brand
|
|
44
|
+
response = await request(tembaServer)
|
|
45
|
+
.put(resourceUrl + mercedesId)
|
|
46
|
+
.send({})
|
|
47
|
+
.set('Content-Type', 'application/json');
|
|
48
|
+
expect(response.statusCode).toEqual(400);
|
|
49
|
+
expect(response.body.message.length).toBeGreaterThan(0);
|
|
50
|
+
// PUT with an unknown property
|
|
51
|
+
response = await request(tembaServer)
|
|
52
|
+
.put(resourceUrl + mercedesId)
|
|
53
|
+
.send({ unknown: 'property' })
|
|
54
|
+
.set('Content-Type', 'application/json');
|
|
55
|
+
expect(response.statusCode).toEqual(400);
|
|
56
|
+
expect(response.body.message.length).toBeGreaterThan(0);
|
|
57
|
+
// PATCH with an empty body, because none of the properties are required
|
|
58
|
+
response = await request(tembaServer)
|
|
59
|
+
.patch(resourceUrl + mercedesId)
|
|
60
|
+
.send({})
|
|
61
|
+
.set('Content-Type', 'application/json');
|
|
62
|
+
expect(response.statusCode).toEqual(200);
|
|
63
|
+
expect(response.body.message).toBeUndefined();
|
|
64
|
+
// PATCH with a brand
|
|
65
|
+
response = await request(tembaServer)
|
|
66
|
+
.patch(resourceUrl + mercedesId)
|
|
67
|
+
.send({ brand: 'Mercedes-Benz' })
|
|
68
|
+
.set('Content-Type', 'application/json');
|
|
69
|
+
expect(response.statusCode).toEqual(200);
|
|
70
|
+
expect(response.body.message).toBeUndefined();
|
|
71
|
+
// PATCH with a price
|
|
72
|
+
response = await request(tembaServer)
|
|
73
|
+
.patch(resourceUrl + mercedesId)
|
|
74
|
+
.send({ price: 100000 })
|
|
75
|
+
.set('Content-Type', 'application/json');
|
|
76
|
+
expect(response.statusCode).toEqual(200);
|
|
77
|
+
expect(response.body.message).toBeUndefined();
|
|
78
|
+
// PATCH with a brand and price
|
|
79
|
+
response = await request(tembaServer)
|
|
80
|
+
.patch(resourceUrl + mercedesId)
|
|
81
|
+
.send({ brand: 'Mercedes-Benz', price: 100000 })
|
|
82
|
+
.set('Content-Type', 'application/json');
|
|
83
|
+
expect(response.statusCode).toEqual(200);
|
|
84
|
+
expect(response.body.message).toBeUndefined();
|
|
85
|
+
// PATCH with an unknown property
|
|
86
|
+
response = await request(tembaServer)
|
|
87
|
+
.patch(resourceUrl + mercedesId)
|
|
88
|
+
.send({ unknown: 'property' })
|
|
89
|
+
.set('Content-Type', 'application/json');
|
|
90
|
+
expect(response.statusCode).toEqual(400);
|
|
91
|
+
expect(response.body.message.length).toBeGreaterThan(0);
|
|
92
|
+
// POST the required brand and the optional price
|
|
93
|
+
response = await request(tembaServer)
|
|
94
|
+
.post(resourceUrl)
|
|
95
|
+
.send({ brand: 'BMW', price: 100000 })
|
|
96
|
+
.set('Content-Type', 'application/json');
|
|
97
|
+
expect(response.statusCode).toEqual(201);
|
|
98
|
+
expect(response.body.message).toBeUndefined();
|
|
99
|
+
// POST without the required brand
|
|
100
|
+
response = await request(tembaServer)
|
|
101
|
+
.post(resourceUrl)
|
|
102
|
+
.send({})
|
|
103
|
+
.set('Content-Type', 'application/json');
|
|
104
|
+
expect(response.statusCode).toEqual(400);
|
|
105
|
+
expect(response.body.message.length).toBeGreaterThan(0);
|
|
106
|
+
// POST an invalid brand
|
|
107
|
+
response = await request(tembaServer)
|
|
108
|
+
.post(resourceUrl)
|
|
109
|
+
.send({ brand: 123 })
|
|
110
|
+
.set('Content-Type', 'application/json');
|
|
111
|
+
expect(response.statusCode).toEqual(400);
|
|
112
|
+
expect(response.body.message.length).toBeGreaterThan(0);
|
|
113
|
+
// POST the required brand and an invalid price
|
|
114
|
+
response = await request(tembaServer)
|
|
115
|
+
.post(resourceUrl)
|
|
116
|
+
.send({ brand: 'Mercedes-Benz', price: 'not a number' })
|
|
117
|
+
.set('Content-Type', 'application/json');
|
|
118
|
+
expect(response.statusCode).toEqual(400);
|
|
119
|
+
expect(response.body.message.length).toBeGreaterThan(0);
|
|
120
|
+
// POST with an unknown property
|
|
121
|
+
response = await request(tembaServer)
|
|
122
|
+
.post(resourceUrl)
|
|
123
|
+
.send({ unknown: 'property' })
|
|
124
|
+
.set('Content-Type', 'application/json');
|
|
125
|
+
expect(response.statusCode).toEqual(400);
|
|
126
|
+
expect(response.body.message.length).toBeGreaterThan(0);
|
|
127
|
+
});
|
|
128
|
+
test('Schema validation per resource', async () => {
|
|
129
|
+
const schema = {
|
|
130
|
+
type: 'object',
|
|
131
|
+
properties: {
|
|
132
|
+
brand: { type: 'string' },
|
|
133
|
+
},
|
|
134
|
+
required: ['brand'],
|
|
135
|
+
};
|
|
136
|
+
const tembaServer = createServer({
|
|
137
|
+
schemas: {
|
|
138
|
+
cars: {
|
|
139
|
+
post: schema,
|
|
140
|
+
},
|
|
141
|
+
},
|
|
142
|
+
});
|
|
143
|
+
// A car with a brand is valid
|
|
144
|
+
let response = await request(tembaServer)
|
|
145
|
+
.post(resourceUrl)
|
|
146
|
+
.send({ brand: 'Mercedes-Benz' })
|
|
147
|
+
.set('Content-Type', 'application/json');
|
|
148
|
+
expect(response.statusCode).toEqual(201);
|
|
149
|
+
// A car without a brand is invalid
|
|
150
|
+
response = await request(tembaServer)
|
|
151
|
+
.post(resourceUrl)
|
|
152
|
+
.send({})
|
|
153
|
+
.set('Content-Type', 'application/json');
|
|
154
|
+
expect(response.statusCode).toEqual(400);
|
|
155
|
+
// However, the bikes resource does not have a schema,
|
|
156
|
+
// so a bike without a brand is valid
|
|
157
|
+
response = await request(tembaServer)
|
|
158
|
+
.post('/bikes/')
|
|
159
|
+
.send({})
|
|
160
|
+
.set('Content-Type', 'application/json');
|
|
161
|
+
expect(response.statusCode).toEqual(201);
|
|
162
|
+
// You can even POST nonsense to the bikes resource
|
|
163
|
+
response = await request(tembaServer)
|
|
164
|
+
.post('/bikes/')
|
|
165
|
+
.send({ foo: 'bar' })
|
|
166
|
+
.set('Content-Type', 'application/json');
|
|
167
|
+
expect(response.statusCode).toEqual(201);
|
|
168
|
+
});
|
|
169
|
+
//# sourceMappingURL=schema-validation.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema-validation.test.js","sourceRoot":"","sources":["../../../test/integration/schema-validation.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.test.d.ts","sourceRoot":"","sources":["../../../../test/unit/config/config.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import { test, expect } from 'vitest';
|
|
2
|
+
import { initConfig } from '../../../src/config';
|
|
3
|
+
import express from 'express';
|
|
4
|
+
const defaultConfig = {
|
|
5
|
+
resources: [],
|
|
6
|
+
validateResources: false,
|
|
7
|
+
staticFolder: null,
|
|
8
|
+
apiPrefix: null,
|
|
9
|
+
connectionString: null,
|
|
10
|
+
cacheControl: 'no-store',
|
|
11
|
+
delay: 0,
|
|
12
|
+
requestBodyInterceptor: null,
|
|
13
|
+
responseBodyInterceptor: null,
|
|
14
|
+
customRouter: null,
|
|
15
|
+
returnNullFields: true,
|
|
16
|
+
isTesting: false,
|
|
17
|
+
port: 3000,
|
|
18
|
+
schemas: null,
|
|
19
|
+
};
|
|
20
|
+
test('No config returns default config', () => {
|
|
21
|
+
const initializedConfig = initConfig();
|
|
22
|
+
expect(initializedConfig.resources).toEqual(defaultConfig.resources);
|
|
23
|
+
expect(initializedConfig.validateResources).toBe(defaultConfig.validateResources);
|
|
24
|
+
expect(initializedConfig.staticFolder).toBe(defaultConfig.staticFolder);
|
|
25
|
+
expect(initializedConfig.apiPrefix).toBe(defaultConfig.apiPrefix);
|
|
26
|
+
expect(initializedConfig.connectionString).toBe(defaultConfig.connectionString);
|
|
27
|
+
expect(initializedConfig.cacheControl).toBe(defaultConfig.cacheControl);
|
|
28
|
+
expect(initializedConfig.delay).toBe(defaultConfig.delay);
|
|
29
|
+
expect(initializedConfig.requestBodyInterceptor?.post).toBe(defaultConfig.requestBodyInterceptor?.post);
|
|
30
|
+
expect(initializedConfig.requestBodyInterceptor?.patch).toBe(defaultConfig.requestBodyInterceptor?.patch);
|
|
31
|
+
expect(initializedConfig.requestBodyInterceptor?.put).toBe(defaultConfig.requestBodyInterceptor?.put);
|
|
32
|
+
expect(initializedConfig.responseBodyInterceptor).toBe(defaultConfig.responseBodyInterceptor);
|
|
33
|
+
expect(initializedConfig.customRouter).toBe(defaultConfig.customRouter);
|
|
34
|
+
expect(initializedConfig.returnNullFields).toBe(defaultConfig.returnNullFields);
|
|
35
|
+
expect(initializedConfig.isTesting).toBe(defaultConfig.isTesting);
|
|
36
|
+
expect(initializedConfig.port).toBe(defaultConfig.port);
|
|
37
|
+
expect(initializedConfig.schemas).toBe(defaultConfig.schemas);
|
|
38
|
+
});
|
|
39
|
+
test('Full user config overrides all defaults', () => {
|
|
40
|
+
const customRouter = express.Router();
|
|
41
|
+
customRouter.get('/hello', async (_, res) => {
|
|
42
|
+
return res.send('Hello, World!');
|
|
43
|
+
});
|
|
44
|
+
const config = initConfig({
|
|
45
|
+
resources: ['movies'],
|
|
46
|
+
staticFolder: 'build',
|
|
47
|
+
apiPrefix: 'api',
|
|
48
|
+
connectionString: 'mongodb://localhost:27017',
|
|
49
|
+
cacheControl: 'no-cache',
|
|
50
|
+
delay: 1000,
|
|
51
|
+
requestBodyInterceptor: {
|
|
52
|
+
post: () => {
|
|
53
|
+
// do nothing
|
|
54
|
+
},
|
|
55
|
+
patch: () => {
|
|
56
|
+
// do nothing
|
|
57
|
+
},
|
|
58
|
+
put: () => {
|
|
59
|
+
// do nothing
|
|
60
|
+
},
|
|
61
|
+
},
|
|
62
|
+
responseBodyInterceptor: ({ body }) => {
|
|
63
|
+
return body;
|
|
64
|
+
},
|
|
65
|
+
customRouter,
|
|
66
|
+
returnNullFields: false,
|
|
67
|
+
isTesting: true,
|
|
68
|
+
port: 3001,
|
|
69
|
+
schemas: {
|
|
70
|
+
stuff: {
|
|
71
|
+
post: {
|
|
72
|
+
type: 'object',
|
|
73
|
+
},
|
|
74
|
+
put: {
|
|
75
|
+
type: 'object',
|
|
76
|
+
},
|
|
77
|
+
patch: {
|
|
78
|
+
type: 'object',
|
|
79
|
+
},
|
|
80
|
+
},
|
|
81
|
+
},
|
|
82
|
+
});
|
|
83
|
+
expect(config.resources).toEqual(['movies']);
|
|
84
|
+
expect(config.validateResources).toBe(true);
|
|
85
|
+
expect(config.staticFolder).toBe('build');
|
|
86
|
+
expect(config.apiPrefix).toBe('/api/');
|
|
87
|
+
expect(config.connectionString).toBe('mongodb://localhost:27017');
|
|
88
|
+
expect(config.cacheControl).toBe('no-cache');
|
|
89
|
+
expect(config.delay).toBe(1000);
|
|
90
|
+
expect(config.requestBodyInterceptor.post).toBeInstanceOf(Function);
|
|
91
|
+
expect(config.requestBodyInterceptor.patch).toBeInstanceOf(Function);
|
|
92
|
+
expect(config.requestBodyInterceptor.put).toBeInstanceOf(Function);
|
|
93
|
+
expect(config.responseBodyInterceptor).toBeInstanceOf(Function);
|
|
94
|
+
expect(config.customRouter).not.toBeNull();
|
|
95
|
+
expect(config.returnNullFields).toBe(false);
|
|
96
|
+
expect(config.isTesting).toBe(true);
|
|
97
|
+
expect(config.port).toBe(3001);
|
|
98
|
+
expect(config.schemas).not.toBeNull();
|
|
99
|
+
});
|
|
100
|
+
test('Partial user config applies those, but leaves the rest at default', () => {
|
|
101
|
+
const config = initConfig({
|
|
102
|
+
apiPrefix: 'api',
|
|
103
|
+
});
|
|
104
|
+
expect(config.resources).toEqual(defaultConfig.resources);
|
|
105
|
+
expect(config.validateResources).toBe(defaultConfig.validateResources);
|
|
106
|
+
expect(config.staticFolder).toBe(defaultConfig.staticFolder);
|
|
107
|
+
expect(config.apiPrefix).toBe('/api/');
|
|
108
|
+
expect(config.connectionString).toBe(defaultConfig.connectionString);
|
|
109
|
+
expect(config.cacheControl).toBe(defaultConfig.cacheControl);
|
|
110
|
+
expect(config.delay).toBe(defaultConfig.delay);
|
|
111
|
+
expect(config.requestBodyInterceptor?.post).toBe(defaultConfig.requestBodyInterceptor?.post);
|
|
112
|
+
expect(config.requestBodyInterceptor?.patch).toBe(defaultConfig.requestBodyInterceptor?.patch);
|
|
113
|
+
expect(config.requestBodyInterceptor?.put).toBe(defaultConfig.requestBodyInterceptor?.put);
|
|
114
|
+
expect(config.responseBodyInterceptor).toBe(defaultConfig.responseBodyInterceptor);
|
|
115
|
+
expect(config.customRouter).toBe(defaultConfig.customRouter);
|
|
116
|
+
expect(config.returnNullFields).toBe(defaultConfig.returnNullFields);
|
|
117
|
+
expect(config.isTesting).toBe(defaultConfig.isTesting);
|
|
118
|
+
expect(config.port).toBe(defaultConfig.port);
|
|
119
|
+
expect(config.schemas).toBe(defaultConfig.schemas);
|
|
120
|
+
});
|
|
121
|
+
//# sourceMappingURL=config.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.test.js","sourceRoot":"","sources":["../../../../test/unit/config/config.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"urlParser.test.d.ts","sourceRoot":"","sources":["../../../../test/unit/urls/urlParser.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { test, expect } from 'vitest';
|
|
2
|
+
import { parseUrl } from '../../../src/urls/urlParser';
|
|
3
|
+
const noResourceAndNoId = { resource: null, id: null };
|
|
4
|
+
const resourceOnly = { resource: 'stuff', id: null };
|
|
5
|
+
const resourceAndId = { resource: 'stuff', id: 'foo' };
|
|
6
|
+
test.each([
|
|
7
|
+
['stuff', resourceOnly],
|
|
8
|
+
['/stuff', resourceOnly],
|
|
9
|
+
['stuff/', resourceOnly],
|
|
10
|
+
['/stuff/', resourceOnly],
|
|
11
|
+
['//stuff/', resourceOnly],
|
|
12
|
+
['/stuff//', resourceOnly],
|
|
13
|
+
])("URL '%s' only has a resource: %o", (url, expected) => {
|
|
14
|
+
const actual = parseUrl(url);
|
|
15
|
+
expect(actual).toEqual(expected);
|
|
16
|
+
});
|
|
17
|
+
test.each([
|
|
18
|
+
['stuff/foo', resourceAndId],
|
|
19
|
+
['/stuff/foo', resourceAndId],
|
|
20
|
+
['stuff/foo/', resourceAndId],
|
|
21
|
+
['/stuff/foo/', resourceAndId],
|
|
22
|
+
['/stuff//foo/', resourceAndId],
|
|
23
|
+
])("URL '%s' has both a resource and id: %o", (url, expected) => {
|
|
24
|
+
const actual = parseUrl(url);
|
|
25
|
+
expect(actual).toEqual(expected);
|
|
26
|
+
});
|
|
27
|
+
test.each([
|
|
28
|
+
['stuff/foo/bar', resourceAndId],
|
|
29
|
+
['/stuff/foo/bar', resourceAndId],
|
|
30
|
+
['stuff/foo/bar/', resourceAndId],
|
|
31
|
+
['/stuff/foo/bar/', resourceAndId],
|
|
32
|
+
])("URL '%s' has additional path items next to a resource and id: %o", (url, expected) => {
|
|
33
|
+
const actual = parseUrl(url);
|
|
34
|
+
expect(actual).toEqual(expected);
|
|
35
|
+
});
|
|
36
|
+
test.each([
|
|
37
|
+
['', noResourceAndNoId],
|
|
38
|
+
[' ', noResourceAndNoId],
|
|
39
|
+
])("URL '%s' has no resource and id: %o", (url, expected) => {
|
|
40
|
+
const actual = parseUrl(url);
|
|
41
|
+
expect(actual).toEqual(expected);
|
|
42
|
+
});
|
|
43
|
+
//# sourceMappingURL=urlParser.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"urlParser.test.js","sourceRoot":"","sources":["../../../../test/unit/urls/urlParser.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAA;AACrC,OAAO,EAAE,QAAQ,EAAE,MAAM,6BAA6B,CAAA;AAEtD,MAAM,iBAAiB,GAAG,EAAE,QAAQ,EAAE,IAAI,EAAE,EAAE,EAAE,IAAI,EAAE,CAAA;AACtD,MAAM,YAAY,GAAG,EAAE,QAAQ,EAAE,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,CAAA;AACpD,MAAM,aAAa,GAAG,EAAE,QAAQ,EAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,CAAA;AAEtD,IAAI,CAAC,IAAI,CAAC;IACR,CAAC,OAAO,EAAE,YAAY,CAAC;IACvB,CAAC,QAAQ,EAAE,YAAY,CAAC;IACxB,CAAC,QAAQ,EAAE,YAAY,CAAC;IACxB,CAAC,SAAS,EAAE,YAAY,CAAC;IACzB,CAAC,UAAU,EAAE,YAAY,CAAC;IAC1B,CAAC,UAAU,EAAE,YAAY,CAAC;CAC3B,CAAC,CAAC,kCAAkC,EAAE,CAAC,GAAG,EAAE,QAAQ,EAAE,EAAE;IACvD,MAAM,MAAM,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAA;IAC5B,MAAM,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAA;AAClC,CAAC,CAAC,CAAA;AAEF,IAAI,CAAC,IAAI,CAAC;IACR,CAAC,WAAW,EAAE,aAAa,CAAC;IAC5B,CAAC,YAAY,EAAE,aAAa,CAAC;IAC7B,CAAC,YAAY,EAAE,aAAa,CAAC;IAC7B,CAAC,aAAa,EAAE,aAAa,CAAC;IAC9B,CAAC,cAAc,EAAE,aAAa,CAAC;CAChC,CAAC,CAAC,yCAAyC,EAAE,CAAC,GAAG,EAAE,QAAQ,EAAE,EAAE;IAC9D,MAAM,MAAM,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAA;IAC5B,MAAM,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAA;AAClC,CAAC,CAAC,CAAA;AAEF,IAAI,CAAC,IAAI,CAAC;IACR,CAAC,eAAe,EAAE,aAAa,CAAC;IAChC,CAAC,gBAAgB,EAAE,aAAa,CAAC;IACjC,CAAC,gBAAgB,EAAE,aAAa,CAAC;IACjC,CAAC,iBAAiB,EAAE,aAAa,CAAC;CACnC,CAAC,CAAC,kEAAkE,EAAE,CAAC,GAAG,EAAE,QAAQ,EAAE,EAAE;IACvF,MAAM,MAAM,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAA;IAC5B,MAAM,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAA;AAClC,CAAC,CAAC,CAAA;AAEF,IAAI,CAAC,IAAI,CAAC;IACR,CAAC,EAAE,EAAE,iBAAiB,CAAC;IACvB,CAAC,GAAG,EAAE,iBAAiB,CAAC;CACzB,CAAC,CAAC,qCAAqC,EAAE,CAAC,GAAG,EAAE,QAAQ,EAAE,EAAE;IAC1D,MAAM,MAAM,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAA;IAC5B,MAAM,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAA;AAClC,CAAC,CAAC,CAAA"}
|