Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

With delay #34

Open
wants to merge 8 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions __tests__/route-matching-general-tests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -295,4 +295,23 @@ describe('Route Matching - willReturn', () => {
expect(fakeServer.hasMade(route.call.withPath(actualPath).withBodyText(actualBody))).toEqual(true);
expect(fakeServer.hasMade(route.call.withBodyText(actualBody).withPath(actualPath))).toEqual(true);
});

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add some tests for multiple restrictions now that it's supported?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's not supported

test('with delay', async () => {
const delay = 1000;
const path = '/somePath';

const route = fakeServer.http
.get()
.to(path)
.withDelay(delay)
.willSucceed();

const startTime = Date.now();
const res = await fetch(`http://localhost:${port}${path}`, {method: 'GET'});
const duration = Date.now() - startTime;

expect(res.status).toEqual(200);
expect(fakeServer.hasMade(route.call)).toEqual(true);
expect(duration).toBeGreaterThan(delay);
});
});
3 changes: 2 additions & 1 deletion http-host/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,8 @@ describe('test', () => {
url: 'api/v1/keys/foo',
response: JSON.stringify("bar"),
isJson: true,
statusCode: 200
statusCode: 200,
delay: 500
});

await axios.post('http://localhost:3000/action');
Expand Down
16 changes: 8 additions & 8 deletions http-host/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,14 @@ let mockedCalls = {};

app.use(bodyParser.json());

app.post('/fake_server_admin/calls', ({ body: { method: mockedMethod, url: mockedUrl, body: mockedReqBody, query, response: mockedResponse, isJson, statusCode } }, res) => {
app.post('/fake_server_admin/calls', ({ body: { method: mockedMethod, url: mockedUrl, body: mockedReqBody, query, response: mockedResponse, isJson, statusCode, delay } }, res) => {
console.log(`Simple-Fake-Server got mock call to ${mockedMethod} ${mockedUrl} \n mocked Body : ${mockedReqBody}, mockedStatus: ${statusCode}`);
const callId = uuid();
let call;
let mock;

if (mockedReqBody) {
mock = fakeServer.http[mockedMethod]()
mock = fakeServer.http[mockedMethod]()
.to(mockedUrl)
.withBody(JSON.parse(mockedReqBody));
} else if (query) {
Expand All @@ -33,14 +33,14 @@ app.post('/fake_server_admin/calls', ({ body: { method: mockedMethod, url: mocke
mock = fakeServer.http[mockedMethod]()
.to(mockedUrl);
}
if (statusCode && statusCode !== 200) {
call = mock
.willFail(statusCode);
} else {
call = mock
.willReturn(isJson ? JSON.parse(mockedResponse) : mockedResponse);

if (delay) {
mock = mock.withDelay(delay);
}

call = mock
.willReturn(isJson ? JSON.parse(mockedResponse || '{}') : mockedResponse, statusCode);

mockedCalls[callId] = call;
res.send({ callId });
});
Expand Down
11 changes: 5 additions & 6 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,7 @@
"prepare": "npm run build",
"build": "rimraf dist && tsc -p tsconfig.json",
"test": "jest --config jest.config.json",
"prettify": "prettier --write **/*.ts **/*.tsx",
"prepush": "npm run test"
"prettify": "prettier --write **/*.ts **/*.tsx"
},
"dependencies": {
"deep-equal": "1.0.1",
Expand All @@ -24,17 +23,17 @@
"query-string": "5.0.1"
},
"devDependencies": {
"@types/jest": "^22.0.1",
"@types/jest": "^24.0.11",
"@types/node": "^9.3.0",
"@types/query-string": "^5.1.0",
"husky": "^0.14.3",
"jest": "^22.1.4",
"jest": "^24.7.0",
"lint-staged": "^6.0.1",
"node-fetch": "^1.7.3",
"prettier": "^1.10.2",
"rimraf": "^2.6.2",
"ts-jest": "^22.0.1",
"typescript": "^2.6.2"
"ts-jest": "^24.0.1",
"typescript": "^3.4.1"
},
"repository": {
"type": "git",
Expand Down
8 changes: 8 additions & 0 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ const route = fakeServer.http
.get() // Http Method (mandatory). See Supported HTTP Methods section.
.to(pathRegex) // Route Path (mandatory). May be regex
.withBody(object) // Route Restriction (optional). See Route Restrictions section.
.withDelay(ms) // Delay response in ms (optional)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not related to this line, but please update the Route Restrictions section that several restrictions are now supported.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's not supported

.willSucceed() // Route Response (mandatory). See Response Section
```

Expand Down Expand Up @@ -110,6 +111,13 @@ NOTES:
* A request that failed to fulfill a restriction will return 400 and will result in false when asserting with `hasMade` (more on this on the next section).
* When setting 2 or more routes with the same path, but with different body restrictions, it's enough to fulfill just 1 of the restrictions to get a match.


### Extras (optional)

* **`withDelay(delayMs: number)`** - will delay the response.
i.e. route defined with `withDelay(2000)` will return a response after 2 seconds.


## Assertions

Each defined route exposes a `RouteCallTester` that can be accessed from `route.call`:
Expand Down
166 changes: 94 additions & 72 deletions src/FakeHttpCalls.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,25 +2,33 @@ import RouteCallTester from './RouteCallTester';
import {default as FakeServer} from './FakeServer';
import {BodyRestriction} from './models/BodyRestriction';

export interface WithRestrictions extends With {
withBodyThatMatches(regex: string): With;
withBodyThatContains(minimalObject: {}): With;
withBody(object: {}): With;
withQueryParams(queryParamsObject: {}): With;
}

export interface With extends Will {
withBodyThatMatches(regex: string): Will;
withBodyThatContains(minimalObject: {}): Will;
withBody(object: {}): Will;
withQueryParams(queryParamsObject: {}): Will;
withDelay(delay: number): With;
}

export interface Will {
willReturn(response: any, statusCode?: number): FakeRoute;
willSucceed(): FakeRoute;
willFail(errorStatus: number): FakeRoute;
willFail(errorStatus?: number): FakeRoute;
}

export interface FakeRoute {
call: RouteCallTester;
}

export interface FakeHttpMethod {
to(pathRegex: string): With;
export const enum HTTPMethod {
get = 'GET',
post = 'POST',
put = 'PUT',
patch = 'PATCH',
delete = 'DELETE',
}

export default class FakeHttpCalls {
Expand All @@ -30,83 +38,97 @@ export default class FakeHttpCalls {
this.fakeServer = fakeServer;
}

public post(): FakeHttpMethod {
return this.create('POST');
}

// tslint:disable-next-line:no-reserved-keywords
public get(): FakeHttpMethod {
return this.create('GET');
}
public post = () => this.method(HTTPMethod.post);
public get = () => this.method(HTTPMethod.get);
public put = () => this.method(HTTPMethod.put);
public patch = () => this.method(HTTPMethod.patch);
public delete = () => this.method(HTTPMethod.delete);

public put(): FakeHttpMethod {
return this.create('PUT');
}
private method = (method: HTTPMethod) => new FakeHttpCallBuilder(this.fakeServer, method);
}

public patch(): FakeHttpMethod {
return this.create('PATCH');
}
class FakeHttpCallBuilder {
private fakeServer: FakeServer;
private method: HTTPMethod;
private pathRegex: string;
private bodyRestriction: BodyRestriction = {};
private queryParamsObject: object;
private delay: number;

// tslint:disable-next-line:no-reserved-keywords
public delete(): FakeHttpMethod {
return this.create('DELETE');
constructor(fakeServer: FakeServer, method: HTTPMethod) {
this.fakeServer = fakeServer;
this.method = method;
}

private will(method: string, pathRegex: string, bodyRestriction: BodyRestriction, queryParamsObject?: {}): Will {
const fakeRoute: FakeRoute = {call: new RouteCallTester(method, pathRegex, bodyRestriction, queryParamsObject)};

return {
willReturn: (response: any, statusCode: number = 200): FakeRoute => {
this.fakeServer.set(method, pathRegex, bodyRestriction, queryParamsObject, response, statusCode);
public to = (pathRegex: string) => {
this.pathRegex = pathRegex;

return fakeRoute;
},
willSucceed: (): FakeRoute => {
this.fakeServer.set(method, pathRegex, bodyRestriction, queryParamsObject, {}, 200);
return this.createWithRestrictions();
};

return fakeRoute;
},
willFail: (errorStatus: number = 500): FakeRoute => {
this.fakeServer.set(method, pathRegex, bodyRestriction, queryParamsObject, {}, errorStatus);
private withBodyThatMatches = (regex: string) => {
this.bodyRestriction.regex = regex;
return this.createWithRestrictions();
};

return fakeRoute;
},
};
}
private withBodyThatContains = (minimalObject: {}) => {
this.bodyRestriction.minimalObject = minimalObject;
return this.createWithRestrictions();
};

private withBodyThatMatches(method: string, pathRegex: string) {
return {
withBodyThatMatches: (regex: string): Will => this.will(method, pathRegex, {regex}),
};
}
private withBody = (object: {}) => {
this.bodyRestriction.object = object;
return this.createWithRestrictions();
};

private withBodyThatContains(method: string, pathRegex: string) {
return {
withBodyThatContains: (minimalObject: {}): Will => this.will(method, pathRegex, {minimalObject}),
};
}
private withQueryParams = (queryParamsObject: {}) => {
this.queryParamsObject = queryParamsObject;
return this.createWithRestrictions();
};

private withBody(method: string, pathRegex: string) {
return {
withBody: (object: {}): Will => this.will(method, pathRegex, {object}),
};
}
private withDelay = (delayMs: number) => {
this.delay = delayMs;
return this.createWithRestrictions();
};

private withQueryParams(method: string, pathRegex: string) {
return {
withQueryParams: (queryParamsObject: {}): Will => this.will(method, pathRegex, {}, queryParamsObject),
private willReturn = (response: any, statusCode: number = 200): FakeRoute => {
const fakeRoute: FakeRoute = {
call: new RouteCallTester(this.method, this.pathRegex, this.bodyRestriction, this.queryParamsObject),
};
}

private create(method: string): FakeHttpMethod {
return {
to: (pathRegex: string): With => ({
...this.withBodyThatMatches(method, pathRegex),
...this.withBodyThatContains(method, pathRegex),
...this.withBody(method, pathRegex),
...this.withQueryParams(method, pathRegex),
...this.will(method, pathRegex, {}),
}),
};
}
this.fakeServer.set(
this.method,
this.pathRegex,
this.bodyRestriction,
this.queryParamsObject,
response,
statusCode,
this.delay
);

return fakeRoute;
};

private willSucceed = (): FakeRoute => this.willReturn({}, 200);

private willFail = (errorStatus: number = 500) => this.willReturn({}, errorStatus);

private createWithRestrictions = (): WithRestrictions => ({
...this.createWith(),
withBodyThatMatches: this.withBodyThatMatches,
withBodyThatContains: this.withBodyThatContains,
withBody: this.withBody,
withQueryParams: this.withQueryParams,
});

private createWith = (): With => ({
...this.createWill(),
withDelay: this.withDelay,
});

private createWill = (): Will => ({
willReturn: this.willReturn,
willSucceed: this.willSucceed,
willFail: this.willFail,
});
}
Loading