Introduce balena-api-mock module to simplify api mocking.

Upgrade nock to latest.

Change-type: minor
Signed-off-by: Scott Lowe <scott@balena.io>
This commit is contained in:
Scott Lowe 2019-12-05 09:55:17 +01:00
parent c2a0e457c0
commit 33210b896b
4 changed files with 118 additions and 17 deletions

35
npm-shrinkwrap.json generated
View File

@ -681,12 +681,12 @@
}
},
"@types/nock": {
"version": "10.0.3",
"resolved": "https://registry.npmjs.org/@types/nock/-/nock-10.0.3.tgz",
"integrity": "sha512-OthuN+2FuzfZO3yONJ/QVjKmLEuRagS9TV9lEId+WHL9KhftYG+/2z+pxlr0UgVVXSpVD8woie/3fzQn8ft/Ow==",
"version": "11.1.0",
"resolved": "https://registry.npmjs.org/@types/nock/-/nock-11.1.0.tgz",
"integrity": "sha512-jI/ewavBQ7X5178262JQR0ewicPAcJhXS/iFaNJl0VHLfyosZ/kwSrsa6VNQNSO8i9d8SqdRgOtZSOKJ/+iNMw==",
"dev": true,
"requires": {
"@types/node": "*"
"nock": "*"
}
},
"@types/node": {
@ -12711,20 +12711,25 @@
}
},
"nock": {
"version": "10.0.6",
"resolved": "https://registry.npmjs.org/nock/-/nock-10.0.6.tgz",
"integrity": "sha512-b47OWj1qf/LqSQYnmokNWM8D88KvUl2y7jT0567NB3ZBAZFz2bWp2PC81Xn7u8F2/vJxzkzNZybnemeFa7AZ2w==",
"version": "11.7.0",
"resolved": "https://registry.npmjs.org/nock/-/nock-11.7.0.tgz",
"integrity": "sha512-7c1jhHew74C33OBeRYyQENT+YXQiejpwIrEjinh6dRurBae+Ei4QjeUaPlkptIF0ZacEiVCnw8dWaxqepkiihg==",
"dev": true,
"requires": {
"chai": "^4.1.2",
"debug": "^4.1.0",
"deep-equal": "^1.0.0",
"json-stringify-safe": "^5.0.1",
"lodash": "^4.17.5",
"lodash": "^4.17.13",
"mkdirp": "^0.5.0",
"propagate": "^1.0.0",
"qs": "^6.5.1",
"semver": "^5.5.0"
"propagate": "^2.0.0"
},
"dependencies": {
"lodash": {
"version": "4.17.15",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz",
"integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==",
"dev": true
}
}
},
"node-abi": {
@ -13873,9 +13878,9 @@
"integrity": "sha1-cflVSpic9r+Jh7Q6UhMtXHkxJlc="
},
"propagate": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/propagate/-/propagate-1.0.0.tgz",
"integrity": "sha1-AMLa7t2iDofjeCs0Stuhzd1q1wk=",
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/propagate/-/propagate-2.0.1.tgz",
"integrity": "sha512-vGrhOavPSTz4QVNuBNdcNXePNdNMaO1xj9yBeH1ScQPjk/rhg9sSlCXPhMkFuaNNW/syTvYqsnbIJxMBfRbbag==",
"dev": true
},
"proper-lockfile": {

View File

@ -111,7 +111,7 @@
"@types/mocha": "^5.2.7",
"@types/mz": "0.0.32",
"@types/net-keepalive": "^0.4.0",
"@types/nock": "^10.0.3",
"@types/nock": "^11.0.7",
"@types/node": "10.14.5",
"@types/prettyjson": "0.0.28",
"@types/raven": "2.5.1",
@ -136,7 +136,7 @@
"husky": "^3.0.9",
"intercept-stdout": "^0.1.2",
"mocha": "^6.2.0",
"nock": "^10.0.6",
"nock": "^11.0.7",
"parse-link-header": "~1.0.1",
"pkg": "^4.4.0",
"prettier": "1.17.0",

92
tests/balena-api-mock.ts Normal file
View File

@ -0,0 +1,92 @@
/**
* @license
* Copyright 2019 Balena Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import * as nock from 'nock';
class BalenaAPIMock {
public static basePathPattern = /api\.balena-cloud\.com/;
public readonly scope: nock.Scope;
// Expose `scope` as `expect` to allow for better semantics in tests
public readonly expect = this.scope;
// For debugging tests
get unfulfilledCallCount(): number {
return this.scope.pendingMocks().length;
}
constructor() {
nock.cleanAll();
if (!nock.isActive()) {
nock.activate();
}
this.scope = nock(BalenaAPIMock.basePathPattern);
nock.emitter.on('no match', this.handleUnexpectedRequest);
}
public done() {
// scope.done() will throw an error if there are expected api calls that have not happened.
// So ensures that all expected calls have been made.
this.scope.done();
// Remove 'no match' handler, for tests using nock without this module
nock.emitter.removeListener('no match', this.handleUnexpectedRequest);
// Restore unmocked behaviour
nock.cleanAll();
nock.restore();
}
public expectConfigVars() {
this.scope.get('/config/vars').reply(200, {
reservedNames: [],
reservedNamespaces: [],
invalidRegex: '/^d|W/',
whiteListedNames: [],
whiteListedNamespaces: [],
blackListedNames: [],
configVarSchema: [],
});
}
// User details are cached in the SDK
// so often we don't know if we can expect the whoami request
public expectOptionalWhoAmI() {
this.scope
.get('/user/v1/whoami')
.optionally()
.reply(200, {
id: 99999,
username: 'testuser',
email: 'testuser@test.com',
});
}
public expectMixpanel() {
this.scope.get(/^\/mixpanel\/track/).reply(200, {});
}
protected handleUnexpectedRequest(req: any) {
console.error(`Unexpected http request!: ${req.path}`);
// Errors thrown here are not causing the tests to fail for some reason.
// Possibly due to CLI global error handlers? (error.js)
// (Also, nock should automatically throw an error, but also not happening)
// For now, the console.error is sufficient (will fail the test)
}
}
export { BalenaAPIMock };

View File

@ -67,6 +67,10 @@ export const runCommand = async (cmd: string) => {
};
export const balenaAPIMock = () => {
if (!nock.isActive()) {
nock.activate();
}
return nock(/./)
.get('/config/vars')
.reply(200, {