Skip to content

Commit

Permalink
feat(Mocketeer): QA-12 mocketeer.getRequest throws error when matchin…
Browse files Browse the repository at this point in the history
…g request was not found
  • Loading branch information
lukaszfiszer committed Jul 23, 2019
1 parent e4c0444 commit 6d37898
Show file tree
Hide file tree
Showing 3 changed files with 82 additions and 17 deletions.
39 changes: 32 additions & 7 deletions src/rest-mock.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,15 @@ import {
QueryObject,
RequestFilter,
} from './types';
import { waitFor } from './utils';
import { waitFor, TimeoutError, nth } from './utils';
import isEqual from 'lodash.isequal';
import { parse } from 'url';
import { stringify } from 'querystring';

const debug = dbg('mocketeer:rest');

const GET_REQUEST_TIMEOUT = 100;

let debugId = 1;

export class RestMock implements IMock {
Expand Down Expand Up @@ -54,13 +57,29 @@ export class RestMock implements IMock {
);
}

public async getRequest(
n: number = 0
): Promise<MatchedRequest | undefined> {
public async getRequest(index: number = 0): Promise<MatchedRequest> {
try {
await waitFor(() => Boolean(this.requests[n]));
} catch (e) {}
return this.requests[n];
await waitFor(
() => Boolean(this.requests[index]),
GET_REQUEST_TIMEOUT
);
} catch (e) {
if (e instanceof TimeoutError) {
if (this.requests.length === 0 && index === 0) {
throw new Error(
`No request matching mock [${this.prettyPrint()}] found`
);
} else {
throw new Error(
`${nth(
index + 1
)} request matching mock [${this.prettyPrint()}] was not found`
);
}
}
throw e;
}
return this.requests[index];
}

public getResponseForRequest(
Expand Down Expand Up @@ -160,4 +179,10 @@ export class RestMock implements IMock {
public static sortByPriority(a: RestMock, b: RestMock) {
return b.options.priority - a.options.priority;
}

private prettyPrint(): string {
const qs = stringify(this.filter.query);
return `(${this.debugId}) ${this.filter.method} ${this.filter.path +
(qs ? '?' + qs : '')}`;
}
}
26 changes: 21 additions & 5 deletions src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,20 +29,22 @@ function toJson(data: string | undefined): any | undefined {
} catch (e) {}
}

export class TimeoutError extends Error {}

export function waitFor(fn: () => boolean, timeout = 100): Promise<void> {
const timeStart = Date.now();
return new Promise((resolve, reject) => {
const intervalId = setInterval(() => {
if (Date.now() - timeStart > timeout) {
if (fn()) {
clearInterval(intervalId);
return resolve();
} else if (Date.now() - timeStart > timeout) {
clearInterval(intervalId);
return reject(
new Error(
new TimeoutError(
`waitFor timeout - provided function did not return true in ${timeout}ms`
)
);
} else if (fn()) {
resolve();
clearInterval(intervalId);
}
});
});
Expand All @@ -51,3 +53,17 @@ export function waitFor(fn: () => boolean, timeout = 100): Promise<void> {
export function printRequest(request: Request): string {
return `${request.resourceType()} ${request.method()} ${request.url()}`;
}

export function nth(d: number): string {
if (d > 3 && d < 21) return `${d}th`;
switch (d % 10) {
case 1:
return `${d}st`;
case 2:
return `${d}nd`;
case 3:
return `${d}rd`;
default:
return `${d}th`;
}
}
34 changes: 29 additions & 5 deletions test/integration/mocketeer.int.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -359,6 +359,30 @@ describe('Mocketeer integration', () => {
});
});

it('.getRequest() rejects when request matching mock was not found', async () => {
const mock = await mocketeer.addRestMock(
{ method: 'GET', url: '/some_endpoint' },
{ status: 200, body: 'OK' }
);

await expect(mock.getRequest(0)).rejects.toMatchObject({
message: expect.stringMatching(
/No request matching mock \[\(\d+\) GET \/some_endpoint\] found/
),
});

await page.evaluate(() => {
return fetch('/some_endpoint');
});

await expect(mock.getRequest(0)).resolves.toEqual(expect.anything());
await expect(mock.getRequest(1)).rejects.toMatchObject({
message: expect.stringMatching(
/2nd request matching mock \[\(\d+\) GET \/some_endpoint\] was not found/
),
});
});

it('notifies when mock was called', async () => {
const mock = await mocketeer.mockREST(requestGetFoo, response200Empty);

Expand Down Expand Up @@ -388,10 +412,10 @@ describe('Mocketeer integration', () => {

await page.waitFor(100);

await expect(mock.getRequest()).resolves.toBeUndefined();
await expect(
mockWithPriority.getRequest()
).resolves.not.toBeUndefined();
await expect(mock.getRequest()).rejects.toEqual(expect.anything());
await expect(mockWithPriority.getRequest()).resolves.toEqual(
expect.anything()
);
});

it('can remove mock so it is no longer called', async () => {
Expand Down Expand Up @@ -440,6 +464,6 @@ describe('Mocketeer integration', () => {

await page.click('body');

await expect(mock.getRequest()).resolves.not.toBeFalsy();
await expect(mock.getRequest()).resolves.toEqual(expect.anything());
});
});

0 comments on commit 6d37898

Please sign in to comment.