@loopback/testlab 4.0.0-alpha.6 → 4.0.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.
Files changed (82) hide show
  1. package/LICENSE +25 -0
  2. package/README.md +411 -20
  3. package/dist/client.d.ts +25 -0
  4. package/dist/client.js +40 -0
  5. package/dist/client.js.map +1 -0
  6. package/dist/expect.d.ts +2 -0
  7. package/{lib/testlab.js → dist/expect.js} +4 -11
  8. package/dist/expect.js.map +1 -0
  9. package/dist/http-error-logger.d.ts +9 -0
  10. package/dist/http-error-logger.js +23 -0
  11. package/dist/http-error-logger.js.map +1 -0
  12. package/dist/http-server-config.d.ts +26 -0
  13. package/dist/http-server-config.js +76 -0
  14. package/dist/http-server-config.js.map +1 -0
  15. package/dist/index.d.ts +31 -0
  16. package/dist/index.js +39 -0
  17. package/dist/index.js.map +1 -0
  18. package/dist/request.d.ts +13 -0
  19. package/dist/request.js +40 -0
  20. package/dist/request.js.map +1 -0
  21. package/dist/shot.d.ts +24 -0
  22. package/dist/shot.js +108 -0
  23. package/dist/shot.js.map +1 -0
  24. package/dist/sinon.d.ts +25 -0
  25. package/dist/sinon.js +35 -0
  26. package/dist/sinon.js.map +1 -0
  27. package/dist/skip.d.ts +49 -0
  28. package/dist/skip.js +65 -0
  29. package/dist/skip.js.map +1 -0
  30. package/dist/test-sandbox.d.ts +89 -0
  31. package/dist/test-sandbox.js +139 -0
  32. package/dist/test-sandbox.js.map +1 -0
  33. package/dist/to-json.d.ts +23 -0
  34. package/dist/to-json.js +12 -0
  35. package/dist/to-json.js.map +1 -0
  36. package/dist/validate-api-spec.d.ts +1 -0
  37. package/dist/validate-api-spec.js +16 -0
  38. package/dist/validate-api-spec.js.map +1 -0
  39. package/fixtures/README.md +9 -0
  40. package/fixtures/cert.pem +21 -0
  41. package/fixtures/copy-me.txt +1 -0
  42. package/fixtures/key.pem +28 -0
  43. package/fixtures/pfx.pfx +0 -0
  44. package/package.json +46 -32
  45. package/should-as-function.d.ts +12 -3
  46. package/src/client.ts +57 -0
  47. package/src/expect.ts +15 -0
  48. package/src/http-error-logger.ts +35 -0
  49. package/src/http-server-config.ts +97 -0
  50. package/src/index.ts +37 -0
  51. package/src/request.ts +45 -0
  52. package/src/shot.ts +191 -0
  53. package/src/sinon.ts +38 -0
  54. package/src/skip.ts +76 -0
  55. package/src/test-sandbox.ts +181 -0
  56. package/src/to-json.ts +54 -0
  57. package/src/validate-api-spec.ts +14 -0
  58. package/index.d.ts +0 -6
  59. package/index.js +0 -9
  60. package/lib/client.d.ts +0 -23
  61. package/lib/client.js +0 -34
  62. package/lib/client.js.map +0 -1
  63. package/lib/shot.d.ts +0 -17
  64. package/lib/shot.js +0 -36
  65. package/lib/shot.js.map +0 -1
  66. package/lib/testlab.d.ts +0 -9
  67. package/lib/testlab.js.map +0 -1
  68. package/lib/validate-api-spec.d.ts +0 -2
  69. package/lib/validate-api-spec.js +0 -29
  70. package/lib/validate-api-spec.js.map +0 -1
  71. package/lib6/client.d.ts +0 -23
  72. package/lib6/client.js +0 -44
  73. package/lib6/client.js.map +0 -1
  74. package/lib6/shot.d.ts +0 -17
  75. package/lib6/shot.js +0 -36
  76. package/lib6/shot.js.map +0 -1
  77. package/lib6/testlab.d.ts +0 -9
  78. package/lib6/testlab.js +0 -22
  79. package/lib6/testlab.js.map +0 -1
  80. package/lib6/validate-api-spec.d.ts +0 -2
  81. package/lib6/validate-api-spec.js +0 -39
  82. package/lib6/validate-api-spec.js.map +0 -1
package/LICENSE ADDED
@@ -0,0 +1,25 @@
1
+ Copyright (c) IBM Corp. 2017,2019.
2
+ Node module: @loopback/testlab
3
+ This project is licensed under the MIT License, full text below.
4
+
5
+ --------
6
+
7
+ MIT license
8
+
9
+ Permission is hereby granted, free of charge, to any person obtaining a copy
10
+ of this software and associated documentation files (the "Software"), to deal
11
+ in the Software without restriction, including without limitation the rights
12
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13
+ copies of the Software, and to permit persons to whom the Software is
14
+ furnished to do so, subject to the following conditions:
15
+
16
+ The above copyright notice and this permission notice shall be included in
17
+ all copies or substantial portions of the Software.
18
+
19
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25
+ THE SOFTWARE.
package/README.md CHANGED
@@ -4,35 +4,62 @@ A collection of test utilities we use to write LoopBack tests.
4
4
 
5
5
  ## Overview
6
6
 
7
- Test utilities to help writing loopback-next tests:
7
+ Test utilities to help writing LoopBack 4 tests:
8
+
8
9
  - `expect` - behavior-driven development (BDD) style assertions
9
10
  - `sinon`
10
- - test spies: functions recording arguments and other information for all of their calls
11
- - stubs: functions (spies) with pre-programmed behavior
12
- - mocks: fake methods (like spies) with pre-programmed behavior (like stubs) as well as pre-programmed expectations
11
+ - test spies: functions recording arguments and other information for all of
12
+ their calls
13
+ - stubs: functions (spies) with pre-programmed behavior
14
+ - mocks: fake methods (like spies) with pre-programmed behavior (like stubs)
15
+ as well as pre-programmed expectations
13
16
  - Helpers for creating `supertest` clients for LoopBack applications
14
17
  - HTTP request/response stubs for writing tests without a listening HTTP server
15
18
  - Swagger/OpenAPI spec validation
19
+ - Test sandbox
16
20
 
17
21
  ## Installation
18
22
 
19
- ```
20
- $ npm install --save-dev @loopback/testlab
23
+ ```sh
24
+ npm install --save-dev @loopback/testlab
21
25
  ```
22
26
 
23
- _This package is typically used in tests, save it to `devDependencies` via `--save-dev`._
27
+ _This package is typically used in tests, save it to `devDependencies` via
28
+ `--save-dev`._
24
29
 
25
30
  ## Basic use
26
31
 
27
32
  ```ts
28
- import { expect } from '@loopback/testlab';
33
+ import {expect} from '@loopback/testlab';
29
34
 
30
- expect({key:'value'}).to.deepEqual({key: 'value'});
31
- expect.exists(1);
35
+ describe('Basic assertions', => {
36
+ it('asserts equal values', => {
37
+ expect({key: 'value'}).to.deepEqual({key: 'value'});
38
+ expect.exists(1);
39
+ });
40
+ });
32
41
  ```
33
42
 
34
43
  ## API documentation
35
44
 
45
+ Table of contents:
46
+
47
+ - [expect](#expect) - Better assertions.
48
+ - [sinon](#sinon) - Mocks, stubs and more.
49
+ - [shot](#shot) - HTTP Request/Response stubs.
50
+ - [validateApiSpec](#validateapispec) - Open API Spec validator.
51
+ - [skipIf](#skipif) - Skip tests when a condition is met.
52
+ - [skipOnTravis](#skipontravis) - Skip tests on Travis env.
53
+ - [createRestAppClient](#createrestappclient) - Create a supertest client
54
+ connected to a running RestApplication.
55
+ - [givenHttpServerConfig](#givenhttpserverconfig) - Generate HTTP server config.
56
+ - [httpGetAsync](#httpgetasync) - Async wrapper for HTTP GET requests.
57
+ - [httpsGetAsync](#httpsgetasync) - Async wrapper for HTTPS GET requests.
58
+ - [toJSON](#toJSON) - A helper to obtain JSON data representing a given object.
59
+ - [createUnexpectedHttpErrorLogger](#createunexpectedhttprrrorlogger) - An error
60
+ logger that only logs errors for unexpected HTTP statuses.
61
+ - [TestSandbox](#testsandbox) - A sandbox directory for tests
62
+
36
63
  ### `expect`
37
64
 
38
65
  [Should.js](https://shouldjs.github.io/) configured in "as-function" mode
@@ -40,11 +67,253 @@ expect.exists(1);
40
67
 
41
68
  ### `sinon`
42
69
 
43
- Spies, mocks and stubs. Learn more at [http://sinonjs.org/](http://sinonjs.org/).
70
+ Spies, mocks and stubs. Learn more at <http://sinonjs.org/>.
44
71
 
45
72
  ### `shot`
46
73
 
47
- Shot [API Reference](https://github.com/hapijs/shot/blob/master/API.md)
74
+ Stub implementation of HTTP Request and Response objects, useful for unit tests.
75
+
76
+ Besides the API provided by `shot` module (see
77
+ [API Reference](https://github.com/hapijs/shot/blob/master/API.md)), we provide
78
+ additional APIs to better support async/await flow control and usage in
79
+ Express-based code.
80
+
81
+ There are three primary situations where you can leverage stub objects provided
82
+ by Shot in your unit tests:
83
+
84
+ - Code parsing core HTTP Request
85
+ - Code modifying core HTTP Response, including full request/response handlers
86
+ - Code parsing Express HTTP Request or modifying Express HTTP Response
87
+
88
+ #### Test request parsing
89
+
90
+ Use the factory function `stubServerRequest` to create a stub request that can
91
+ be passed to methods expecting core HTTP Request on input.
92
+
93
+ ```ts
94
+ import {stubServerRequest, expect} from '@loopback/testlab';
95
+
96
+ describe('parseParams', () => {
97
+ it('parses query string arguments', () => {
98
+ const request = stubServerRequest({
99
+ method: 'GET',
100
+ url: '/api/products?count=10',
101
+ });
102
+
103
+ const args = parseParams(request, [
104
+ {name: 'count', in: 'query', type: 'number'},
105
+ ]);
106
+
107
+ expect(args).to.eql([10]);
108
+ });
109
+ });
110
+ ```
111
+
112
+ #### Test response producers
113
+
114
+ Use the factory function `stubHandlerContext` to create request & response stubs
115
+ and a promise to observe the actual response as received by clients.
116
+
117
+ ```ts
118
+ import {stubHandlerContext, expect} from '@loopback/testlab';
119
+
120
+ describe('app REST handler', () => {
121
+ it('returns 404 with JSON body when URL not found', async () => {
122
+ const app = express();
123
+ const context = stubHandlerContext({
124
+ method: 'GET',
125
+ url: '/path-does-not-exist',
126
+ });
127
+
128
+ // Invoke Express' request handler with stubbed request/response objects
129
+ app(context.request, context.response);
130
+
131
+ // Wait until Express finishes writing the response
132
+ const actualResponse = await context.result;
133
+
134
+ // Verify the response seen by clients
135
+ expect(actualResponse.statusCode).to.equal(404);
136
+ expect(JSON.parse(actualResponse.payload)).to.containEql({
137
+ error: {
138
+ statusCode: 404,
139
+ message: 'Not Found',
140
+ },
141
+ });
142
+ });
143
+ });
144
+ ```
145
+
146
+ #### Test code expecting Express Request or Response
147
+
148
+ Express modifies core HTTP request and response objects with additional
149
+ properties and methods, it also cross-links request with response and vice
150
+ versa. As a result, it's not possible to create Express Request object without
151
+ the accompanying Response object.
152
+
153
+ Use the factory function `stubExpressContext` to create Express-flavored request
154
+ & response stubs and a promise to observe the actual response as received by
155
+ clients.
156
+
157
+ If your tested function is expecting a request object only:
158
+
159
+ ```ts
160
+ import {stubExpressContext, expect} from '@loopback/testlab';
161
+
162
+ describe('operationArgsParser', () => {
163
+ it('parses body parameter', async () => {
164
+ const req = givenRequest({
165
+ url: '/',
166
+ payload: {key: 'value'},
167
+ });
168
+
169
+ const spec = givenOperationWithRequestBody({
170
+ description: 'data',
171
+ content: {'application/json': {schema: {type: 'object'}}},
172
+ });
173
+ const route = givenResolvedRoute(spec);
174
+
175
+ const args = await parseOperationArgs(req, route);
176
+
177
+ expect(args).to.eql([{key: 'value'}]);
178
+ });
179
+
180
+ function givenRequest(options?: ShotRequestOptions): Request {
181
+ return stubExpressContext(options).request;
182
+ }
183
+ });
184
+ ```
185
+
186
+ Tests verifying code producing HTTP response can await `context.result` to
187
+ receive the response as returned to clients.
188
+
189
+ ```ts
190
+ import {stubExpressContext, expect} from '@loopback/testlab';
191
+
192
+ describe('response writer', () => {
193
+ it('writes object result to response as JSON', async () => {
194
+ const context = stubExpressContext();
195
+
196
+ writeResultToResponse(context.response, {name: 'Joe'});
197
+ const result = await context.result;
198
+
199
+ expect(result.headers['content-type']).to.eql('application/json');
200
+ expect(result.payload).to.equal('{"name":"Joe"}');
201
+ });
202
+ });
203
+ ```
204
+
205
+ ### `skipIf`
206
+
207
+ Helper function for skipping tests when a certain condition is met. Use this
208
+ helper together with `it` or `describe`.
209
+
210
+ ```ts
211
+ skipIf(someCondition, it, 'does something', async () => {
212
+ // the test code
213
+ });
214
+ ```
215
+
216
+ Unfortunately, type inference does not work well for `describe`, you have to
217
+ help the compiler to figure out the correct types.
218
+
219
+ ```ts
220
+ skipIf<[(this: Suite) => void], void>(
221
+ someCondition,
222
+ describe,
223
+ 'some suite name',
224
+ () => {
225
+ // define the test cases
226
+ },
227
+ );
228
+ ```
229
+
230
+ Under the hood, `skipIf` invokes the provided test verb by default (e.g. `it`).
231
+ When the provided condition was true, then it calls `.skip` instead (e.g.
232
+ `it.skip`).
233
+
234
+ ### `skipOnTravis`
235
+
236
+ Helper function for skipping tests on Travis environment. If you need to skip
237
+ testing on Travis for any reason, use this helper together with `it` or
238
+ `describe`.
239
+
240
+ ```ts
241
+ skipOnTravis(it, 'does something when some condition', async () => {
242
+ // the test code
243
+ });
244
+ ```
245
+
246
+ Under the hood, `skipOnTravis` invokes the provided test verb by default (e.g.
247
+ `it`). When the helper detects Travis CI environment variables, then it calls
248
+ `.skip` instead (e.g. `it.skip`).
249
+
250
+ ### `createRestAppClient`
251
+
252
+ Helper function to create a `supertest` client connected to a running
253
+ RestApplication. It is the responsibility of the caller to ensure that the app
254
+ is running and to stop the application after all tests are done.
255
+
256
+ Example use:
257
+
258
+ ```ts
259
+ import {Client, createRestAppClient} from '@loopback/testlab';
260
+
261
+ describe('My application', () => {
262
+ app: MyApplication; // extends RestApplication
263
+ client: Client;
264
+
265
+ before(givenRunningApplication);
266
+ before(() => {
267
+ client = createRestAppClient(app);
268
+ });
269
+ after(() => app.stop());
270
+
271
+ it('invokes GET /ping', async () => {
272
+ await client.get('/ping?msg=world').expect(200);
273
+ });
274
+ });
275
+ ```
276
+
277
+ ### `givenHttpServerConfig`
278
+
279
+ Helper function for generating Travis-friendly host (127.0.0.1). This is
280
+ required because Travis is not able to handle IPv6 addresses.
281
+
282
+ ### `httpGetAsync`
283
+
284
+ Async wrapper for making HTTP GET requests.
285
+
286
+ ```ts
287
+ import {httpGetAsync} from '@loopback/testlab';
288
+ const response = await httpGetAsync('http://example.com');
289
+ ```
290
+
291
+ ### `httpsGetAsync`
292
+
293
+ Async wrapper for making HTTPS GET requests.
294
+
295
+ ```ts
296
+ import {httpsGetAsync} from '@loopback/testlab';
297
+ const response = await httpsGetAsync('https://example.com');
298
+ ```
299
+
300
+ ### `toJSON`
301
+
302
+ JSON encoding does not preserve properties that are undefined. As a result,
303
+ `deepEqual` checks fail because the expected model value contains these
304
+ undefined property values, while the actual result returned by REST API does
305
+ not. Use this function to convert a model instance into a data object as
306
+ returned by REST API.
307
+
308
+ ```ts
309
+ import {createClientForHandler, toJSON} from '@loopback/testlab';
310
+
311
+ it('gets a todo by ID', () => {
312
+ return client
313
+ .get(`/todos/${persistedTodo.id}`)
314
+ .expect(200, toJSON(persistedTodo));
315
+ });
316
+ ```
48
317
 
49
318
  ### `validateApiSpec`
50
319
 
@@ -52,31 +321,153 @@ Verify that your application API specification is a valid OpenAPI spec document.
52
321
 
53
322
  ```js
54
323
  import {validateApiSpec} from '@loopback/testlab';
324
+ import {RestServer} from '@loopback/rest';
55
325
 
56
- describe('MyApp', () => {)
326
+ describe('MyApp', () => {
57
327
  it('has valid spec', async () => {
58
328
  const app = new MyApp();
59
- await validateApiSpec(app.getApiSpec());
60
- })
329
+ const server = await app.getServer(RestServer);
330
+ await validateApiSpec(server.getApiSpec());
331
+ });
332
+ });
333
+ ```
334
+
335
+ ### `createUnexpectedHttpErrorLogger`
336
+
337
+ An error logger that logs the error only when the HTTP status code is not the
338
+ expected HTTP status code. This is useful when writing tests for error
339
+ responses:
340
+
341
+ - When we don't want any error messages printed to the console when the server
342
+ responds with the expected error and the test passes.
343
+
344
+ - When something else goes wrong and the server returns an unexpected error
345
+ status code, and we do want an error message to be printed to the console so
346
+ that we have enough information to troubleshoot the failing test.
347
+
348
+ ```ts
349
+ import {createUnexpectedHttpErrorLogger} from '@loopback/testlab';
350
+ import {RestApplication} from '@loopback/rest';
351
+
352
+ describe('MyApp', () => {
353
+ it('does not log a known 401 error to console', async () => {
354
+ const app = new RestApplication();
355
+
356
+ const errorLogger = createUnexpectedHttpErrorLogger(401);
357
+ // binds the custom error logger
358
+ app.bind(SequenceActions.LOG_ERROR).to(errorLogger);
359
+
360
+ const spec = {
361
+ responses: {
362
+ /*...*/
363
+ },
364
+ };
365
+ function throwUnauthorizedError() {
366
+ throw new HttpErrors.Unauthorized('Unauthorized!');
367
+ }
368
+
369
+ app.route('get', '/', spec, throwUnauthorizedError);
370
+
371
+ await app.start();
372
+ // make `GET /` request, assert that 401 is returned
373
+ });
61
374
  });
62
375
  ```
63
376
 
377
+ ### TestSandbox
378
+
379
+ Many tests need use a temporary directory as the sandbox to mimic a tree of
380
+ files. The `TestSandbox` class provides such facilities to create and manage a
381
+ sandbox on the file system.
382
+
383
+ #### Create a sandbox
384
+
385
+ ```ts
386
+ // Create a sandbox as a unique temporary subdirectory under the rootPath
387
+ const sandbox = new TestSandbox(rootPath);
388
+ const sandbox = new TestSandbox(rootPath, {subdir: true});
389
+
390
+ // Create a sandbox in the root path directly
391
+ // This is same as the old behavior
392
+ const sandbox = new TestSandbox(rootPath, {subdir: false});
393
+
394
+ // Create a sandbox in the `test1` subdirectory of the root path
395
+ const sandbox = new TestSandbox(rootPath, {subdir: 'test1'});
396
+
397
+ // To access the target directory of a sandbox
398
+ console.log(sandbox.path);
399
+ ```
400
+
401
+ #### Reset a sandbox
402
+
403
+ All files inside a sandbox will be removed when the sandbox is reset. We also
404
+ try to remove cache from `require`.
405
+
406
+ ```ts
407
+ await sandbox.reset();
408
+ ```
409
+
410
+ #### Delete a sandbox
411
+
412
+ Removes all files and mark the sandbox unusable.
413
+
414
+ ```ts
415
+ await sandbox.delete();
416
+ ```
417
+
418
+ #### Create a directory
419
+
420
+ Recursively creates a directory within the sandbox.
421
+
422
+ ```ts
423
+ await sandbox.mkdir(dir);
424
+ ```
425
+
426
+ #### Copy a file
427
+
428
+ Copies a file from src to the TestSandbox. If copying a `.js` file which has an
429
+ accompanying `.js.map` file in the src file location, the dest file will have
430
+ its sourceMappingURL updated to point to the original file as an absolute path
431
+ so you don't need to copy the map file.
432
+
433
+ ```ts
434
+ await sandbox.copyFile(src, dest);
435
+ ```
436
+
437
+ #### Write a json file
438
+
439
+ Creates a new file and writes the given data serialized as JSON.
440
+
441
+ ```ts
442
+ await sandbox.writeJsonFile(dest, data);
443
+ ```
444
+
445
+ #### Write a file
446
+
447
+ Creates a new file and writes the given data as a UTF-8-encoded text.
448
+
449
+ ```ts
450
+ await sandbox.writeFile(dest, data);
451
+ ```
452
+
64
453
  ## Related resources
65
454
 
66
- For more info about `supertest`, please refer to [supertest](https://www.npmjs.com/package/supertest)
455
+ For more info about `supertest`, please refer to
456
+ [supertest](https://www.npmjs.com/package/supertest)
67
457
 
68
458
  ## Contributions
69
459
 
70
- - [Guidelines](https://github.com/strongloop/loopback-next/wiki/Contributing##guidelines)
71
- - [Join the team](https://github.com/strongloop/loopback-next/issues/110)
460
+ - [Guidelines](https://github.com/loopbackio/loopback-next/blob/master/docs/CONTRIBUTING.md)
461
+ - [Join the team](https://github.com/loopbackio/loopback-next/issues/110)
72
462
 
73
463
  ## Tests
74
464
 
75
- run 'npm test' from the root folder.
465
+ Run `npm test` from the root folder.
76
466
 
77
467
  ## Contributors
78
468
 
79
- See [all contributors](https://github.com/strongloop/loopback-next/graphs/contributors).
469
+ See
470
+ [all contributors](https://github.com/loopbackio/loopback-next/graphs/contributors).
80
471
 
81
472
  ## License
82
473
 
@@ -0,0 +1,25 @@
1
+ /// <reference types="node" />
2
+ import http from 'http';
3
+ import supertest = require('supertest');
4
+ export { supertest };
5
+ export declare type Client = supertest.SuperTest<supertest.Test>;
6
+ /**
7
+ * Create a SuperTest client connected to an HTTP server listening
8
+ * on an ephemeral port and calling `handler` to handle incoming requests.
9
+ * @param handler
10
+ */
11
+ export declare function createClientForHandler(handler: (req: http.IncomingMessage, res: http.ServerResponse) => void): Client;
12
+ /**
13
+ * Create a SuperTest client for a running RestApplication instance.
14
+ * It is the responsibility of the caller to ensure that the app
15
+ * is running and to stop the application after all tests are done.
16
+ * @param app - A running (listening) instance of a RestApplication.
17
+ */
18
+ export declare function createRestAppClient(app: RestApplicationLike): supertest.SuperTest<supertest.Test>;
19
+ export interface RestApplicationLike {
20
+ restServer: RestServerLike;
21
+ }
22
+ export interface RestServerLike {
23
+ url?: string;
24
+ rootUrl?: string;
25
+ }
package/dist/client.js ADDED
@@ -0,0 +1,40 @@
1
+ "use strict";
2
+ // Copyright IBM Corp. 2017,2020. All Rights Reserved.
3
+ // Node module: @loopback/testlab
4
+ // This file is licensed under the MIT License.
5
+ // License text available at https://opensource.org/licenses/MIT
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.createRestAppClient = exports.createClientForHandler = exports.supertest = void 0;
8
+ const tslib_1 = require("tslib");
9
+ /*
10
+ * HTTP client utilities
11
+ */
12
+ const http_1 = (0, tslib_1.__importDefault)(require("http"));
13
+ const supertest = require("supertest");
14
+ exports.supertest = supertest;
15
+ /**
16
+ * Create a SuperTest client connected to an HTTP server listening
17
+ * on an ephemeral port and calling `handler` to handle incoming requests.
18
+ * @param handler
19
+ */
20
+ function createClientForHandler(handler) {
21
+ const server = http_1.default.createServer(handler);
22
+ return supertest(server);
23
+ }
24
+ exports.createClientForHandler = createClientForHandler;
25
+ /**
26
+ * Create a SuperTest client for a running RestApplication instance.
27
+ * It is the responsibility of the caller to ensure that the app
28
+ * is running and to stop the application after all tests are done.
29
+ * @param app - A running (listening) instance of a RestApplication.
30
+ */
31
+ function createRestAppClient(app) {
32
+ var _a;
33
+ const url = (_a = app.restServer.rootUrl) !== null && _a !== void 0 ? _a : app.restServer.url;
34
+ if (!url) {
35
+ throw new Error(`Cannot create client for ${app.constructor.name}, it is not listening.`);
36
+ }
37
+ return supertest(url);
38
+ }
39
+ exports.createRestAppClient = createRestAppClient;
40
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":";AAAA,sDAAsD;AACtD,iCAAiC;AACjC,+CAA+C;AAC/C,gEAAgE;;;;AAEhE;;GAEG;AAEH,6DAAwB;AACxB,uCAAwC;AAEhC,8BAAS;AAIjB;;;;GAIG;AACH,SAAgB,sBAAsB,CACpC,OAAsE;IAEtE,MAAM,MAAM,GAAG,cAAI,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC;IAC1C,OAAO,SAAS,CAAC,MAAM,CAAC,CAAC;AAC3B,CAAC;AALD,wDAKC;AAED;;;;;GAKG;AACH,SAAgB,mBAAmB,CAAC,GAAwB;;IAC1D,MAAM,GAAG,GAAG,MAAA,GAAG,CAAC,UAAU,CAAC,OAAO,mCAAI,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC;IACzD,IAAI,CAAC,GAAG,EAAE;QACR,MAAM,IAAI,KAAK,CACb,4BAA4B,GAAG,CAAC,WAAW,CAAC,IAAI,wBAAwB,CACzE,CAAC;KACH;IACD,OAAO,SAAS,CAAC,GAAG,CAAC,CAAC;AACxB,CAAC;AARD,kDAQC"}
@@ -0,0 +1,2 @@
1
+ /// <reference path="../should-as-function.d.ts" />
2
+ export declare const expect: Internal;
@@ -1,22 +1,15 @@
1
1
  "use strict";
2
- // Copyright IBM Corp. 2013,2017. All Rights Reserved.
2
+ // Copyright IBM Corp. 2018,2020. All Rights Reserved.
3
3
  // Node module: @loopback/testlab
4
4
  // This file is licensed under the MIT License.
5
5
  // License text available at https://opensource.org/licenses/MIT
6
- function __export(m) {
7
- for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p];
8
- }
9
6
  Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.expect = void 0;
8
+ // eslint-disable-next-line @typescript-eslint/triple-slash-reference
10
9
  /// <reference path="../should-as-function.d.ts" />
11
10
  const shouldAsFunction = require('should/as-function');
12
- require("should-sinon");
13
- const sinon = require("sinon");
14
- exports.sinon = sinon;
15
11
  shouldAsFunction.use((should, assertion) => {
16
12
  assertion.addChain('to');
17
13
  });
18
14
  exports.expect = shouldAsFunction;
19
- __export(require("./client"));
20
- __export(require("./shot"));
21
- __export(require("./validate-api-spec"));
22
- //# sourceMappingURL=testlab.js.map
15
+ //# sourceMappingURL=expect.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"expect.js","sourceRoot":"","sources":["../src/expect.ts"],"names":[],"mappings":";AAAA,sDAAsD;AACtD,iCAAiC;AACjC,+CAA+C;AAC/C,gEAAgE;;;AAEhE,qEAAqE;AACrE,mDAAmD;AAEnD,MAAM,gBAAgB,GAAa,OAAO,CAAC,oBAAoB,CAAC,CAAC;AAEjE,gBAAgB,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,SAAS,EAAE,EAAE;IACzC,SAAS,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;AAC3B,CAAC,CAAC,CAAC;AAEU,QAAA,MAAM,GAAG,gBAAgB,CAAC"}
@@ -0,0 +1,9 @@
1
+ import { Request } from 'express';
2
+ /**
3
+ * Creates a Logger that logs an Error if the HTTP status code is not expected
4
+ *
5
+ * @param expectedStatusCode - HTTP status code that is expected
6
+ */
7
+ export declare function createUnexpectedHttpErrorLogger(expectedStatusCode?: number): LogError;
8
+ declare type LogError = (err: Error, statusCode: number, request: Request) => void;
9
+ export {};
@@ -0,0 +1,23 @@
1
+ "use strict";
2
+ // Copyright IBM Corp. 2019. All Rights Reserved.
3
+ // Node module: @loopback/testlab
4
+ // This file is licensed under the MIT License.
5
+ // License text available at https://opensource.org/licenses/MIT
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.createUnexpectedHttpErrorLogger = void 0;
8
+ /**
9
+ * Creates a Logger that logs an Error if the HTTP status code is not expected
10
+ *
11
+ * @param expectedStatusCode - HTTP status code that is expected
12
+ */
13
+ function createUnexpectedHttpErrorLogger(expectedStatusCode) {
14
+ return function logUnexpectedHttpError(err, statusCode, req) {
15
+ var _a;
16
+ if (statusCode === expectedStatusCode)
17
+ return;
18
+ /* istanbul ignore next */
19
+ console.error('Unhandled error in %s %s: %s %s', req.method, req.url, statusCode, (_a = err.stack) !== null && _a !== void 0 ? _a : err);
20
+ };
21
+ }
22
+ exports.createUnexpectedHttpErrorLogger = createUnexpectedHttpErrorLogger;
23
+ //# sourceMappingURL=http-error-logger.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"http-error-logger.js","sourceRoot":"","sources":["../src/http-error-logger.ts"],"names":[],"mappings":";AAAA,iDAAiD;AACjD,iCAAiC;AACjC,+CAA+C;AAC/C,gEAAgE;;;AAKhE;;;;GAIG;AACH,SAAgB,+BAA+B,CAC7C,kBAA2B;IAE3B,OAAO,SAAS,sBAAsB,CACpC,GAAU,EACV,UAAkB,EAClB,GAAoB;;QAEpB,IAAI,UAAU,KAAK,kBAAkB;YAAE,OAAO;QAE9C,0BAA0B;QAC1B,OAAO,CAAC,KAAK,CACX,iCAAiC,EACjC,GAAG,CAAC,MAAM,EACV,GAAG,CAAC,GAAG,EACP,UAAU,EACV,MAAA,GAAG,CAAC,KAAK,mCAAI,GAAG,CACjB,CAAC;IACJ,CAAC,CAAC;AACJ,CAAC;AAnBD,0EAmBC"}
@@ -0,0 +1,26 @@
1
+ /// <reference types="node" />
2
+ import { ServerOptions as HttpsServerOptions } from 'https';
3
+ import { ListenOptions } from 'net';
4
+ export interface HttpOptions extends ListenOptions {
5
+ protocol?: 'http';
6
+ }
7
+ export interface HttpsOptions extends ListenOptions, HttpsServerOptions {
8
+ protocol: 'https';
9
+ }
10
+ /**
11
+ * An object that requires host and port properties
12
+ */
13
+ export interface HostPort {
14
+ host: string;
15
+ port: number;
16
+ }
17
+ /**
18
+ * Create an HTTP-server configuration that works well in test environments.
19
+ * - Ask the operating system to assign a free (ephemeral) port.
20
+ * - Use IPv4 localhost `127.0.0.1` to avoid known IPv6 issues in Docker-based
21
+ * environments like Travis-CI.
22
+ * - Provide default TLS key & cert when `protocol` is set to `https`.
23
+ *
24
+ * @param customConfig - Additional configuration options to apply.
25
+ */
26
+ export declare function givenHttpServerConfig<T extends HttpOptions | HttpsOptions>(customConfig?: T): HostPort & T;