Skip to content

Instantly share code, notes, and snippets.

@jjrasche
Created June 25, 2019 19:45
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jjrasche/af6b6dbe3dac8ccfa5ce7da873298715 to your computer and use it in GitHub Desktop.
Save jjrasche/af6b6dbe3dac8ccfa5ce7da873298715 to your computer and use it in GitHub Desktop.
// Angular
import { HttpRequest } from "@angular/common/http";
import { HttpTestingController, TestRequest } from "@angular/common/http/testing";
import { async, TestBed } from "@angular/core/testing";
// Models
import { HttpMockModel } from "./http-mock.model";
// tslint:disable: max-line-length
export class BaseHttpTest {
public defaultMockResponses: Array<HttpMockModel>;
public httpMock: HttpTestingController;
public settings: HttpTestingSettings = {
verifyAllCalls: true
};
// overwritten by implementation
public wait: () => void;
protected setupHttpMock(): void {
beforeEach(async(() => {
this.httpMock = TestBed.get(HttpTestingController);
}));
afterEach(() => {
if (this.settings.verifyAllCalls) {
this.httpMock.verify();
}
});
}
public expectSingleRequest(match: (req: HttpRequest<any>) => boolean, response: any = null): HttpRequest<any> {
const saveRequest = new HttpMockModel(
(req: HttpRequest<any>) => {
return match(req);
}, response);
return this.waitAndRespondToRequest([saveRequest]);
}
/**
* Expects some particular http request, does not require that it is the only request
*/
public expectRequest(match: (req: HttpRequest<any>) => boolean, response: any = null) {
this.wait();
const testRequest = this.httpMock.match(match);
if (testRequest.length === 0) {
throw new Error("No requests were found matching the request type.");
}
if (testRequest.length > 1) {
throw new Error("More than 1 request found mathing the given criteria.");
}
testRequest[0].flush(response);
this.wait();
}
public waitAndRespondToRequest(mocks: Array<HttpMockModel> = null): HttpRequest<any> {
if (!mocks && !this.defaultMockResponses) {
throw new Error("Must specify default mock responses if calling 'waitAndRespondToRequest' without argument");
}
this.wait(); // wait for requests to go out
const req = this.listenAndRespondToMockHttpCalls(mocks ? mocks : this.defaultMockResponses);
this.wait(); // wait for results to get loaded
return req;
}
public listenAndRespondToMockHttpCalls(httpMocks: Array<HttpMockModel>): HttpRequest<any> {
let req: TestRequest;
httpMocks.forEach((mock: HttpMockModel) => {
req = this.httpMock.expectOne(mock.match);
req.flush(mock.response);
});
return req.request;
}
public flushAllRequests() {
const allRequests = this.httpMock.match((req: HttpRequest<any>) => true);
allRequests.forEach(req => req.flush({data : {}}));
}
/**
*
* @param urlSuffix
* @param expectedVerb
* @param expectedBody
* @param shouldError in scenarios where it is ok to have multiple requests, this method is used to determine which of the multiple
* requests match criteria, therefore all but one request will likely fail and should not throw an error.
*/
public verifyRequest(urlSuffix: string = null, expectedVerb: "GET" | "POST" | "PUT" | "DELETE" = null, expectedBody: any = null, shouldError: boolean = true): (req: HttpRequest<any>) => boolean {
return (req: HttpRequest<any>) => {
if (!urlSuffix && !expectedVerb && !expectedBody) {
console.error("Intentionally performing a mock service call without verifying url matchs. I hope you know what you're doing");
return true;
}
const expectedUrl = `test${urlSuffix}`;
const actualUrl = req.url;
if (expectedUrl !== actualUrl) {
if (shouldError) {
throw new Error(`Expected url ${actualUrl} to equal ${expectedUrl}.`);
}
return false;
}
const actualVerb = req.method;
if (!!expectedVerb && expectedVerb !== actualVerb) {
if (shouldError) {
throw new Error(`Expected verb ${actualVerb} to equal ${expectedVerb}.`);
}
return false;
}
const actualBodyString = JSON.stringify(req.body);
const expectedBodyString = JSON.stringify(expectedBody);
if (!!expectedBody && expectedBodyString !== actualBodyString) {
if (shouldError) {
throw new Error(`Expected body ${actualBodyString} to equal ${expectedBodyString}.`);
}
return false;
}
return true;
};
}
}
export interface HttpTestingSettings {
verifyAllCalls: boolean;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment