@loopback/testlab 4.0.0-alpha.7 → 4.0.1

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/src/request.ts ADDED
@@ -0,0 +1,45 @@
1
+ // Copyright IBM Corp. 2018,2020. All Rights Reserved.
2
+ // Node module: @loopback/testlab
3
+ // This file is licensed under the MIT License.
4
+ // License text available at https://opensource.org/licenses/MIT
5
+
6
+ import http, {IncomingMessage} from 'http';
7
+ import https from 'https';
8
+ import url from 'url';
9
+
10
+ /**
11
+ * Async wrapper for making HTTP GET requests
12
+ * @param urlString
13
+ */
14
+ export function httpGetAsync(
15
+ urlString: string,
16
+ agent?: http.Agent,
17
+ ): Promise<IncomingMessage> {
18
+ return new Promise((resolve, reject) => {
19
+ const urlOptions = url.parse(urlString);
20
+ const options = {agent, ...urlOptions};
21
+ http.get(options, resolve).on('error', reject);
22
+ });
23
+ }
24
+
25
+ /**
26
+ * Async wrapper for making HTTPS GET requests
27
+ * @param urlString
28
+ */
29
+ export function httpsGetAsync(
30
+ urlString: string,
31
+ agent?: https.Agent,
32
+ ): Promise<IncomingMessage> {
33
+ agent =
34
+ agent ??
35
+ new https.Agent({
36
+ rejectUnauthorized: false,
37
+ });
38
+
39
+ const urlOptions = url.parse(urlString);
40
+ const options = {agent, ...urlOptions};
41
+
42
+ return new Promise((resolve, reject) => {
43
+ https.get(options, resolve).on('error', reject);
44
+ });
45
+ }
package/src/shot.ts ADDED
@@ -0,0 +1,191 @@
1
+ // Copyright IBM Corp. 2017,2019. All Rights Reserved.
2
+ // Node module: @loopback/testlab
3
+ // This file is licensed under the MIT License.
4
+ // License text available at https://opensource.org/licenses/MIT
5
+
6
+ /*
7
+ * HTTP Request/Response mocks
8
+ * https://github.com/hapijs/shot
9
+ */
10
+
11
+ /* eslint-disable @typescript-eslint/no-explicit-any */
12
+
13
+ import express from 'express';
14
+ import {IncomingMessage, ServerResponse} from 'http';
15
+ import {
16
+ Listener as ShotListener,
17
+ RequestOptions as ShotRequestOptions,
18
+ ResponseObject,
19
+ } from 'shot'; // <-- workaround for missing type-defs for @hapi/shot
20
+ import util from 'util';
21
+
22
+ const inject: (
23
+ dispatchFunc: ShotListener,
24
+ options: ShotRequestOptions,
25
+ ) => Promise<ResponseObject> = require('@hapi/shot');
26
+ // ^^ workaround for missing type-defs for @hapi/shot
27
+
28
+ export {inject, ShotRequestOptions};
29
+
30
+ const ShotRequest: ShotRequestCtor = require('@hapi/shot/lib/request');
31
+ type ShotRequestCtor = new (options: ShotRequestOptions) => IncomingMessage;
32
+
33
+ export function stubServerRequest(
34
+ options: ShotRequestOptions,
35
+ ): IncomingMessage {
36
+ const stub = new ShotRequest(options);
37
+ // Hacky workaround for Express, see
38
+ // https://github.com/expressjs/express/blob/4.16.3/lib/middleware/init.js
39
+ // https://github.com/hapijs/shot/issues/82#issuecomment-247943773
40
+ // https://github.com/jfhbrook/pickleback
41
+ Object.assign(stub, ShotRequest.prototype);
42
+ return stub;
43
+ }
44
+
45
+ const ShotResponse: ShotResponseCtor = require('@hapi/shot/lib/response');
46
+ export type ShotCallback = (response: ResponseObject) => void;
47
+
48
+ export type ShotResponseCtor = new (
49
+ request: IncomingMessage,
50
+ onEnd: ShotCallback,
51
+ ) => ServerResponse;
52
+
53
+ export function stubServerResponse(
54
+ request: IncomingMessage,
55
+ onEnd: ShotCallback,
56
+ ): ServerResponse {
57
+ const stub = new ShotResponse(request, onEnd);
58
+ // Hacky workaround for Express, see
59
+ // https://github.com/expressjs/express/blob/4.16.3/lib/middleware/init.js
60
+ // https://github.com/hapijs/shot/issues/82#issuecomment-247943773
61
+ // https://github.com/jfhbrook/pickleback
62
+ Object.assign(stub, ShotResponse.prototype);
63
+ return stub;
64
+ }
65
+
66
+ export type ObservedResponse = ResponseObject;
67
+
68
+ export interface HandlerContextStub {
69
+ request: IncomingMessage;
70
+ response: ServerResponse;
71
+ result: Promise<ObservedResponse>;
72
+ }
73
+
74
+ export function stubHandlerContext(
75
+ requestOptions: ShotRequestOptions = {url: '/'},
76
+ ): HandlerContextStub {
77
+ const request = stubServerRequest(requestOptions);
78
+ let response: ServerResponse | undefined;
79
+ const result = new Promise<ObservedResponse>(resolve => {
80
+ response = new ShotResponse(request, resolve);
81
+ });
82
+
83
+ const context = {request, response: response!, result};
84
+ defineCustomContextInspect(context, requestOptions);
85
+ return context;
86
+ }
87
+
88
+ export interface ExpressContextStub extends HandlerContextStub {
89
+ app: express.Application;
90
+ request: express.Request;
91
+ response: express.Response;
92
+ result: Promise<ObservedResponse>;
93
+ }
94
+
95
+ export function stubExpressContext(
96
+ requestOptions: ShotRequestOptions = {url: '/'},
97
+ ): ExpressContextStub {
98
+ const app = express();
99
+
100
+ const request = new ShotRequest(requestOptions) as express.Request;
101
+ // mix in Express Request API
102
+ const RequestApi = (express as any).request;
103
+ for (const key of Object.getOwnPropertyNames(RequestApi)) {
104
+ Object.defineProperty(
105
+ request,
106
+ key,
107
+ Object.getOwnPropertyDescriptor(RequestApi, key)!,
108
+ );
109
+ }
110
+ request.app = app;
111
+ request.originalUrl = request.url;
112
+ parseQuery(request);
113
+
114
+ let response: express.Response | undefined;
115
+ const result = new Promise<ObservedResponse>(resolve => {
116
+ response = new ShotResponse(request, resolve) as express.Response;
117
+ // mix in Express Response API
118
+ Object.assign(response, (express as any).response);
119
+ const ResponseApi = (express as any).response;
120
+ for (const key of Object.getOwnPropertyNames(ResponseApi)) {
121
+ Object.defineProperty(
122
+ response,
123
+ key,
124
+ Object.getOwnPropertyDescriptor(ResponseApi, key)!,
125
+ );
126
+ }
127
+ response.app = app;
128
+ (response as any).req = request;
129
+ (request as any).res = response;
130
+ });
131
+
132
+ const context = {app, request, response: response!, result};
133
+ defineCustomContextInspect(context, requestOptions);
134
+ return context;
135
+ }
136
+
137
+ /**
138
+ * Use `express.query` to parse the query string into `request.query` object
139
+ * @param request - Express http request object
140
+ */
141
+ function parseQuery(request: express.Request) {
142
+ // Use `express.query` to parse the query string
143
+ // See https://github.com/expressjs/express/blob/master/lib/express.js#L79
144
+ // See https://github.com/expressjs/express/blob/master/lib/middleware/query.js
145
+ (express as any).query()(request, {}, () => {});
146
+ }
147
+
148
+ function defineCustomContextInspect(
149
+ context: HandlerContextStub,
150
+ requestOptions: ShotRequestOptions,
151
+ ) {
152
+ // Setup custom inspect functions to make test error messages easier to read
153
+ const inspectOpts = (depth: number, opts: any) =>
154
+ util.inspect(requestOptions, opts);
155
+
156
+ defineCustomInspect(
157
+ context.request,
158
+ (depth, opts) => `[RequestStub with options ${inspectOpts(depth, opts)}]`,
159
+ );
160
+
161
+ defineCustomInspect(
162
+ context.response,
163
+ (depth, opts) =>
164
+ `[ResponseStub for request with options ${inspectOpts(depth, opts)}]`,
165
+ );
166
+
167
+ context.result = context.result.then(r => {
168
+ defineCustomInspect(
169
+ r,
170
+ (depth, opts) =>
171
+ `[ObservedResponse for request with options ${inspectOpts(
172
+ depth,
173
+ opts,
174
+ )}]`,
175
+ );
176
+ return r;
177
+ });
178
+ }
179
+
180
+ // @types/node@v10.17.29 seems to miss the type definition of `util.inspect.custom`
181
+ // error TS2339: Property 'custom' does not exist on type 'typeof inspect'.
182
+ // Use a workaround for now to access the `custom` symbol for now.
183
+ // https://nodejs.org/api/util.html#util_util_inspect_custom
184
+ const custom = Symbol.for('nodejs.util.inspect.custom');
185
+
186
+ function defineCustomInspect(
187
+ obj: any,
188
+ inspectFn: (depth: number, opts: any) => {},
189
+ ) {
190
+ obj[custom] = inspectFn;
191
+ }
package/src/sinon.ts ADDED
@@ -0,0 +1,38 @@
1
+ // Copyright IBM Corp. 2018,2020. All Rights Reserved.
2
+ // Node module: @loopback/testlab
3
+ // This file is licensed under the MIT License.
4
+ // License text available at https://opensource.org/licenses/MIT
5
+
6
+ import sinon, {SinonSpy} from 'sinon';
7
+
8
+ export {sinon, SinonSpy};
9
+
10
+ export type StubbedInstanceWithSinonAccessor<T> = T & {
11
+ stubs: sinon.SinonStubbedInstance<T>;
12
+ };
13
+
14
+ /**
15
+ * Creates a new object with the given functions as the prototype and stubs all
16
+ * implemented functions.
17
+ *
18
+ * Note: The given constructor function is not invoked. See also the stub API.
19
+ *
20
+ * This is a helper method replacing `sinon.createStubInstance` and working
21
+ * around the limitations of TypeScript and Sinon, where Sinon is not able to
22
+ * list private/protected members in the type definition of the stub instance
23
+ * and therefore the stub instance cannot be assigned to places expecting TType.
24
+ * See also
25
+ * - https://github.com/Microsoft/TypeScript/issues/13543
26
+ * - https://github.com/DefinitelyTyped/DefinitelyTyped/issues/14811
27
+ *
28
+ * @typeParam TType - Type being stubbed.
29
+ * @param constructor - Object or class to stub.
30
+ * @returns A stubbed version of the constructor, with an extra property `stubs`
31
+ * providing access to stub API for individual methods.
32
+ */
33
+ export function createStubInstance<TType>(
34
+ constructor: sinon.StubbableType<TType>,
35
+ ): StubbedInstanceWithSinonAccessor<TType> {
36
+ const stub = sinon.createStubInstance(constructor);
37
+ return Object.assign(stub as TType, {stubs: stub});
38
+ }
package/src/skip.ts ADDED
@@ -0,0 +1,76 @@
1
+ // Copyright IBM Corp. 2019,2020. All Rights Reserved.
2
+ // Node module: @loopback/testlab
3
+ // This file is licensed under the MIT License.
4
+ // License text available at https://opensource.org/licenses/MIT
5
+
6
+ /**
7
+ * A function defining a new test case or a test suite, e.g. `it` or `describe`.
8
+ */
9
+ export type TestDefinition<ARGS extends unknown[], RETVAL> = (
10
+ name: string,
11
+ ...args: ARGS
12
+ ) => RETVAL;
13
+
14
+ /**
15
+ * Helper function for skipping tests when a certain condition is met.
16
+ *
17
+ * @example
18
+ * ```ts
19
+ * skipIf(
20
+ * !features.freeFormProperties,
21
+ * describe,
22
+ * 'free-form properties (strict: false)',
23
+ * () => {
24
+ * // the tests
25
+ * }
26
+ * );
27
+ * ```
28
+ *
29
+ * @param skip - Should the test case/suite be skipped?
30
+ * @param verb - The function to invoke to define the test case or the test
31
+ * suite, e.g. `it` or `describe`.
32
+ * @param name - The test name (the first argument of `verb` function).
33
+ * @param args - Additional arguments (framework specific), typically a function
34
+ * implementing the test.
35
+ */
36
+ export function skipIf<ARGS extends unknown[], RETVAL>(
37
+ skip: boolean,
38
+ verb: TestDefinition<ARGS, RETVAL> & {skip: TestDefinition<ARGS, RETVAL>},
39
+ name: string,
40
+ ...args: ARGS
41
+ ): RETVAL {
42
+ if (skip) {
43
+ return verb.skip(`[SKIPPED] ${name}`, ...args);
44
+ } else {
45
+ return verb(name, ...args);
46
+ }
47
+ }
48
+
49
+ /**
50
+ * Helper function for skipping tests on Travis CI.
51
+ *
52
+ * @example
53
+ *
54
+ * ```ts
55
+ * skipOnTravis(it, 'does something when some condition', async () => {
56
+ * // the test
57
+ * });
58
+ * ```
59
+ *
60
+ * @param verb - The function to invoke to define the test case or the test
61
+ * suite, e.g. `it` or `describe`.
62
+ * @param name - The test name (the first argument of `verb` function).
63
+ * @param args - Additional arguments (framework specific), typically a function
64
+ * implementing the test.
65
+ */
66
+ export function skipOnTravis<ARGS extends unknown[], RETVAL>(
67
+ verb: TestDefinition<ARGS, RETVAL> & {skip: TestDefinition<ARGS, RETVAL>},
68
+ name: string,
69
+ ...args: ARGS
70
+ ): RETVAL {
71
+ if (process.env.TRAVIS) {
72
+ return verb.skip(`[SKIPPED ON TRAVIS] ${name}`, ...args);
73
+ } else {
74
+ return verb(name, ...args);
75
+ }
76
+ }
@@ -0,0 +1,181 @@
1
+ // Copyright IBM Corp. 2018,2020. All Rights Reserved.
2
+ // Node module: @loopback/testlab
3
+ // This file is licensed under the MIT License.
4
+ // License text available at https://opensource.org/licenses/MIT
5
+
6
+ import {
7
+ appendFile,
8
+ copy,
9
+ emptyDir,
10
+ ensureDir,
11
+ ensureDirSync,
12
+ mkdtempSync,
13
+ outputFile,
14
+ outputJson,
15
+ pathExists,
16
+ readFile,
17
+ remove,
18
+ } from 'fs-extra';
19
+ import {join, parse, resolve} from 'path';
20
+
21
+ /**
22
+ * Options for a test sandbox
23
+ */
24
+ export interface TestSandboxOptions {
25
+ /**
26
+ * The `subdir` controls if/how the sandbox creates a subdirectory under the
27
+ * root path. It has one of the following values:
28
+ *
29
+ * - `true`: Creates a unique subdirectory. This will be the default behavior.
30
+ * - `false`: Uses the root path as the target directory without creating a
31
+ * subdirectory.
32
+ * - a string such as `sub-dir-1`: creates a subdirectory with the given value.
33
+ */
34
+ subdir: boolean | string;
35
+ }
36
+
37
+ /**
38
+ * TestSandbox class provides a convenient way to get a reference to a
39
+ * sandbox folder in which you can perform operations for testing purposes.
40
+ */
41
+ export class TestSandbox {
42
+ // Path of the TestSandbox
43
+ private _path?: string;
44
+
45
+ public get path(): string {
46
+ if (!this._path) {
47
+ throw new Error(
48
+ `TestSandbox instance was deleted. Create a new instance.`,
49
+ );
50
+ }
51
+ return this._path;
52
+ }
53
+
54
+ /**
55
+ * Will create a directory if it doesn't already exist. If it exists, you
56
+ * still get an instance of the TestSandbox.
57
+ *
58
+ * @example
59
+ * ```ts
60
+ * // Create a sandbox as a unique temporary subdirectory under the rootPath
61
+ * const sandbox = new TestSandbox(rootPath);
62
+ * const sandbox = new TestSandbox(rootPath, {subdir: true});
63
+ *
64
+ * // Create a sandbox in the root path directly
65
+ * // This is same as the old behavior
66
+ * const sandbox = new TestSandbox(rootPath, {subdir: false});
67
+ *
68
+ * // Create a sandbox in the `test1` subdirectory of the root path
69
+ * const sandbox = new TestSandbox(rootPath, {subdir: 'test1'});
70
+ * ```
71
+ *
72
+ * @param rootPath - Root path of the TestSandbox. If relative it will be
73
+ * resolved against the current directory.
74
+ * @param options - Options to control if/how the sandbox creates a
75
+ * subdirectory for the sandbox. If not provided, the sandbox
76
+ * will automatically creates a unique temporary subdirectory. This allows
77
+ * sandboxes with the same root path can be used in parallel during testing.
78
+ */
79
+ constructor(rootPath: string, options?: TestSandboxOptions) {
80
+ rootPath = resolve(rootPath);
81
+ ensureDirSync(rootPath);
82
+ options = {subdir: true, ...options};
83
+ const subdir = typeof options.subdir === 'string' ? options.subdir : '.';
84
+ if (options.subdir !== true) {
85
+ this._path = resolve(rootPath, subdir);
86
+ } else {
87
+ // Create a unique temporary directory under the root path
88
+ // See https://nodejs.org/api/fs.html#fs_fs_mkdtempsync_prefix_options
89
+ this._path = mkdtempSync(join(rootPath, `/${process.pid}`));
90
+ }
91
+ }
92
+
93
+ /**
94
+ * Resets the TestSandbox. (Remove all files in it).
95
+ */
96
+ async reset(): Promise<void> {
97
+ // Decache files from require's cache so future tests aren't affected incase
98
+ // a file is recreated in sandbox with the same file name but different
99
+ // contents after resetting the sandbox.
100
+ for (const key in require.cache) {
101
+ if (key.startsWith(this.path)) {
102
+ delete require.cache[key];
103
+ }
104
+ }
105
+
106
+ await emptyDir(this.path);
107
+ }
108
+
109
+ /**
110
+ * Deletes the TestSandbox.
111
+ */
112
+ async delete(): Promise<void> {
113
+ await remove(this.path);
114
+ delete this._path;
115
+ }
116
+
117
+ /**
118
+ * Makes a directory in the TestSandbox
119
+ *
120
+ * @param dir - Name of directory to create (relative to TestSandbox path)
121
+ */
122
+ async mkdir(dir: string): Promise<void> {
123
+ await ensureDir(resolve(this.path, dir));
124
+ }
125
+
126
+ /**
127
+ * Copies a file from src to the TestSandbox. If copying a `.js` file which
128
+ * has an accompanying `.js.map` file in the src file location, the dest file
129
+ * will have its sourceMappingURL updated to point to the original file as
130
+ * an absolute path so you don't need to copy the map file.
131
+ *
132
+ * @param src - Absolute path of file to be copied to the TestSandbox
133
+ * @param dest - Optional. Destination filename of the copy operation
134
+ * (relative to TestSandbox). Original filename used if not specified.
135
+ * @param transform - Optional. A function to transform the file content.
136
+ */
137
+ async copyFile(
138
+ src: string,
139
+ dest?: string,
140
+ transform?: (content: string) => string,
141
+ ): Promise<void> {
142
+ dest = dest
143
+ ? resolve(this.path, dest)
144
+ : resolve(this.path, parse(src).base);
145
+
146
+ if (transform == null) {
147
+ await copy(src, dest);
148
+ } else {
149
+ let content = await readFile(src, 'utf-8');
150
+ content = transform(content);
151
+ await outputFile(dest, content, {encoding: 'utf-8'});
152
+ }
153
+
154
+ if (parse(src).ext === '.js' && (await pathExists(src + '.map'))) {
155
+ const srcMap = src + '.map';
156
+ await appendFile(dest, `\n//# sourceMappingURL=${srcMap}`);
157
+ }
158
+ }
159
+
160
+ /**
161
+ * Creates a new file and writes the given data serialized as JSON.
162
+ *
163
+ * @param dest - Destination filename, optionally including a relative path.
164
+ * @param data - The data to write.
165
+ */
166
+ async writeJsonFile(dest: string, data: unknown): Promise<void> {
167
+ dest = resolve(this.path, dest);
168
+ return outputJson(dest, data, {spaces: 2});
169
+ }
170
+
171
+ /**
172
+ * Creates a new file and writes the given data as a UTF-8-encoded text.
173
+ *
174
+ * @param dest - Destination filename, optionally including a relative path.
175
+ * @param data - The text to write.
176
+ */
177
+ async writeTextFile(dest: string, data: string): Promise<void> {
178
+ dest = resolve(this.path, dest);
179
+ return outputFile(dest, data, 'utf-8');
180
+ }
181
+ }
package/src/to-json.ts ADDED
@@ -0,0 +1,54 @@
1
+ // Copyright IBM Corp. 2018,2019. All Rights Reserved.
2
+ // Node module: @loopback/testlab
3
+ // This file is licensed under the MIT License.
4
+ // License text available at https://opensource.org/licenses/MIT
5
+
6
+ /* eslint-disable @typescript-eslint/unified-signatures */
7
+
8
+ // Important! Date.prototype.toJSON() returns a string.
9
+ export function toJSON(value: Date): string;
10
+
11
+ // Important! Functions cannot be encoded in JSON.
12
+ export function toJSON(value: Function): undefined;
13
+
14
+ // Distinguish arrays from objects (an array is an object too)
15
+ export function toJSON(value: unknown[]): unknown[];
16
+
17
+ /**
18
+ * JSON encoding does not preserve properties that are undefined
19
+ * As a result, deepEqual checks fail because the expected model
20
+ * value contains these undefined property values, while the actual
21
+ * result returned by REST API does not.
22
+ * Use this function to convert a model instance into a data object
23
+ * as returned by REST API
24
+ */
25
+ export function toJSON(value: object): object;
26
+
27
+ // The following overloads are provided for convenience.
28
+ // In practice, they should not be necessary, as they simply return the input
29
+ // value without any modifications.
30
+
31
+ export function toJSON(value: undefined): undefined;
32
+ export function toJSON(value: null): null;
33
+ export function toJSON(value: number): number;
34
+ export function toJSON(value: boolean): boolean;
35
+ export function toJSON(value: string): string;
36
+
37
+ // The following overloads are required to allow TypesScript handle
38
+ // commonly used union types.
39
+
40
+ export function toJSON(value: unknown[] | null): unknown[] | null;
41
+ export function toJSON(value: unknown[] | undefined): unknown[] | undefined;
42
+ export function toJSON(
43
+ value: unknown[] | null | undefined,
44
+ ): unknown[] | null | undefined;
45
+
46
+ export function toJSON(value: object | null): object | null;
47
+ export function toJSON(value: object | undefined): object | undefined;
48
+ export function toJSON(
49
+ value: object | null | undefined,
50
+ ): object | null | undefined;
51
+
52
+ export function toJSON<T>(value: T) {
53
+ return JSON.parse(JSON.stringify({value})).value;
54
+ }
@@ -0,0 +1,14 @@
1
+ // Copyright IBM Corp. 2017,2019. All Rights Reserved.
2
+ // Node module: @loopback/testlab
3
+ // This file is licensed under the MIT License.
4
+ // License text available at https://opensource.org/licenses/MIT
5
+
6
+ const validator = require('oas-validator');
7
+ import {promisify} from 'util';
8
+
9
+ const validateAsync = promisify(validator.validate);
10
+
11
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
12
+ export async function validateApiSpec(spec: any): Promise<void> {
13
+ await validateAsync(spec, {});
14
+ }
package/index.d.ts DELETED
@@ -1,6 +0,0 @@
1
- // Copyright IBM Corp. 2013,2017. All Rights Reserved.
2
- // Node module: @loopback/testlab
3
- // This file is licensed under the MIT License.
4
- // License text available at https://opensource.org/licenses/MIT
5
-
6
- export * from './lib/testlab';
package/index.js DELETED
@@ -1,9 +0,0 @@
1
- // Copyright IBM Corp. 2013,2017. All Rights Reserved.
2
- // Node module: @loopback/testlab
3
- // This file is licensed under the MIT License.
4
- // License text available at https://opensource.org/licenses/MIT
5
-
6
- const nodeMajorVersion = +process.versions.node.split('.')[0];
7
- module.exports = nodeMajorVersion >= 7 ?
8
- require('./lib/testlab') :
9
- require('./lib6/testlab');
package/lib/client.d.ts DELETED
@@ -1,23 +0,0 @@
1
- /// <reference types="supertest" />
2
- /// <reference types="node" />
3
- import * as http from 'http';
4
- import supertest = require('supertest');
5
- export { supertest };
6
- export declare type Client = supertest.SuperTest<supertest.Test>;
7
- /**
8
- * Create a SuperTest client connected to an HTTP server listening
9
- * on an ephemeral port and calling `handler` to handle incoming requests.
10
- * @param handler
11
- */
12
- export declare function createClientForHandler(handler: (req: http.ServerRequest, res: http.ServerResponse) => void): Client;
13
- export interface Server {
14
- config: {
15
- port: number;
16
- };
17
- start(): Promise<void>;
18
- }
19
- export declare function createClientForServer(server: Server): Promise<Client>;
20
- export interface Application {
21
- handleHttp(req: http.ServerRequest, res: http.ServerResponse): void;
22
- }
23
- export declare function createClientForApp(app: Application): Client;
package/lib/client.js DELETED
@@ -1,34 +0,0 @@
1
- "use strict";
2
- // Copyright IBM Corp. 2013,2017. 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
- /*
8
- * HTTP client utilities
9
- */
10
- const http = require("http");
11
- const supertest = require("supertest");
12
- exports.supertest = supertest;
13
- /**
14
- * Create a SuperTest client connected to an HTTP server listening
15
- * on an ephemeral port and calling `handler` to handle incoming requests.
16
- * @param handler
17
- */
18
- function createClientForHandler(handler) {
19
- const server = http.createServer(handler);
20
- return supertest(server);
21
- }
22
- exports.createClientForHandler = createClientForHandler;
23
- async function createClientForServer(server) {
24
- await server.start();
25
- const url = `http://127.0.0.1:${server.config.port}`;
26
- // TODO(bajtos) Find a way how to stop the server after all tests are done
27
- return supertest(url);
28
- }
29
- exports.createClientForServer = createClientForServer;
30
- function createClientForApp(app) {
31
- return createClientForHandler(app.handleHttp);
32
- }
33
- exports.createClientForApp = createClientForApp;
34
- //# sourceMappingURL=client.js.map
package/lib/client.js.map DELETED
@@ -1 +0,0 @@
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,6BAA6B;AAC7B,uCAAwC;AAEhC,8BAAS;AAIjB;;;;GAIG;AACH,gCACE,OAAoE;IAEpE,MAAM,MAAM,GAAG,IAAI,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC;IAC1C,MAAM,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;AAC3B,CAAC;AALD,wDAKC;AAOM,KAAK,gCAAgC,MAAc;IACxD,MAAM,MAAM,CAAC,KAAK,EAAE,CAAC;IACrB,MAAM,GAAG,GAAG,oBAAoB,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;IACrD,0EAA0E;IAC1E,MAAM,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;AACxB,CAAC;AALD,sDAKC;AAMD,4BAAmC,GAAgB;IACjD,MAAM,CAAC,sBAAsB,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;AAChD,CAAC;AAFD,gDAEC"}