rxrest-assert
Version:
Assert library for RxRest
210 lines • 8.36 kB
JavaScript
"use strict";
/// <reference path="../node-status-code.d.ts" />
Object.defineProperty(exports, "__esModule", { value: true });
const rxjs_1 = require("rxjs");
const nodeStatusCodes = require("node-status-codes");
class RxRestAssertionError extends TypeError {
}
exports.RxRestAssertionError = RxRestAssertionError;
class RxRestAssert {
constructor(config, options = { log: false }) {
this.$expectations = [];
this.$whens = new Map();
this.$requestInterceptorIndex = 0;
this.$responseInterceptorIndex = 0;
this.$requestCount = 0;
this.log = options.log;
this.config = config;
this.$requestInterceptorIndex = config.requestInterceptors.push((request) => {
this.$requestCount++;
let expect = this.$expectations[this.$expectations.length - 1];
let requestURL = this.$getRequestURL(request);
if (expect) {
this.$current = 'expectation';
return;
}
for (let key of this.$whens.keys()) {
if (key.method === request.method && this.$matchURL(key.url, requestURL)) {
this.$current = key;
return;
}
}
this.$current = null;
});
config.fetch = (request) => {
const defaultResponse = new Response('{}', {
status: 200,
statusText: 'OK',
headers: new Headers()
});
this.$log(`Doing a request ${request.method} ${request.url}`);
if (this.$current === null) {
return rxjs_1.of(defaultResponse);
}
let expectation;
if (this.$current === 'expectation') {
expectation = this.$expectations.shift();
}
else if (this.$current !== null) {
expectation = this.$whens.get(this.$current);
}
if (expectation !== undefined) {
expectation(request);
this.$requestCount--;
}
else {
this.$throw(`Request ${request.method} ${request.url} not expected`);
}
let response = expectation.response ? expectation.response : defaultResponse;
return rxjs_1.of(response);
};
this.$responseInterceptorIndex = config.responseInterceptors.push((response) => {
if (this.$current !== null && this.$current !== 'expectation') {
this.$whens.delete(this.$current);
}
});
}
$expectation(method, url, data, assertion = true) {
const self = this;
this.$log(`Preparing expectation on ${method} ${url}`);
const assert = function (request) {
if (assertion === false) {
return;
}
if (request.method !== method) {
self.$throw(`Method should be "${method}", got "${request.method}"`);
}
let requestURL = self.$getRequestURL(request);
if (!self.$matchURL(url, requestURL)) {
self.$throw(`URL should ${url instanceof RegExp ? `match "${url.toString()}"` : `be "${url}"`}, got "${requestURL}"`);
}
if (typeof data === 'function' && !data(request)) {
self.$throw('The request test failed');
}
else if (data instanceof Request) {
for (let header of data.headers) {
let requestHeaderValue = request.headers.get(header[0]);
if (requestHeaderValue !== header[1]) {
self.$throw(`Header "${header[0]}" does not match on Request, found "${requestHeaderValue}" but "${header[1]}" was expected`);
}
}
let expectedQueryParamsString = data.url.match(/\?(.+)/);
let expectedQueryParams = expectedQueryParamsString === null ? new URLSearchParams() : new URLSearchParams(expectedQueryParamsString[1]);
let requestQueryParamsString = request.url.match(/\?(.+)/);
let requestQueryParams = requestQueryParamsString === null ? new URLSearchParams() : new URLSearchParams(requestQueryParamsString[1]);
if (expectedQueryParams.toString().length) {
for (let param of expectedQueryParams) {
let requestQueryParam = requestQueryParams.get(param[0]);
if (requestQueryParam !== param[1]) {
self.$throw(`Query param "${param[0]}" does not match on Request, found "${requestQueryParam}" but "${param[1]}" was expected`);
}
}
}
}
};
assert.url = url;
assert.method = method;
assert.respond = (response) => {
let statusCode = response;
if (!isNaN(statusCode) && isFinite(statusCode)) {
assert.response = new Response('{}', { status: statusCode, statusText: nodeStatusCodes[statusCode], headers: new Headers() });
return;
}
assert.response = response instanceof Response ? response : new Response(JSON.stringify(response), { status: 200, statusText: 'OK', headers: new Headers() });
};
return assert;
}
$log(message) {
if (this.log === false) {
return;
}
console.error(message);
}
$throw(message) {
this.$requestCount--;
throw new RxRestAssertionError(message);
}
$getRequestURL(request) {
return request.url.replace(this.config.baseURL, '').replace(/\?.+/, '').replace(/\/$/, '');
}
$matchURL(url, requestURL) {
return (url instanceof RegExp && url.test(requestURL)) || url === requestURL;
}
expect(method, url, data) {
method = method.toUpperCase();
let expect = this.$expectation(method, url, data);
let index = this.$expectations.push(expect);
return { respond: expect.respond };
}
expectGET(url, data) {
return this.expect('GET', url, data);
}
expectPOST(url, data) {
return this.expect('POST', url, data);
}
expectPUT(url, data) {
return this.expect('PUT', url, data);
}
expectHEAD(url, data) {
return this.expect('HEAD', url, data);
}
expectPATCH(url, data) {
return this.expect('PATCH', url, data);
}
expectDELETE(url, data) {
return this.expect('DELETE', url, data);
}
when(method, url, data) {
method = method.toUpperCase();
let expect = this.$expectation(method, url, data, false);
this.$whens.set({ url: url, method: method }, expect);
return { respond: expect.respond };
}
whenGET(url, data) {
return this.when('GET', url, data);
}
whenPOST(url, data) {
return this.when('POST', url, data);
}
whenPUT(url, data) {
return this.when('PUT', url, data);
}
whenHEAD(url, data) {
return this.when('HEAD', url, data);
}
whenPATCH(url, data) {
return this.when('PATCH', url, data);
}
whenDELETE(url, data) {
return this.when('DELETE', url, data);
}
resetExpectations() {
this.$expectations.length = 0;
}
verifyNoOutstandingExpectation() {
if (this.$expectations.length) {
throw new RxRestAssertionError(`There is ${this.$expectations.length} pending expectation`);
}
}
verifyNoOutstandingRequest() {
if (this.$requestCount > 0) {
throw new RxRestAssertionError(`There is ${this.$requestCount} pending request`);
}
}
destroy() {
this.resetExpectations();
this.$whens = new Map();
this.$requestCount = 0;
this.config.fetch = null;
this.config.requestInterceptors = this.config.requestInterceptors
.filter((e, i) => {
return i === this.$requestInterceptorIndex;
});
this.config.responseInterceptors = this.config.responseInterceptors
.filter((e, i) => {
return i === this.$responseInterceptorIndex;
});
}
}
exports.RxRestAssert = RxRestAssert;
//# sourceMappingURL=index.js.map