Skip to content

Commit

Permalink
Merge pull request #159 from angrykoala/dev
Browse files Browse the repository at this point in the history
0.8.1
  • Loading branch information
angrykoala authored Jun 16, 2018
2 parents cc1d92f + 5a8dd6d commit 10def31
Show file tree
Hide file tree
Showing 13 changed files with 391 additions and 247 deletions.
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
0.8.1 / 2018-06-16
==================

* Delay option for request mocks
* Auto option for request mocks
* Trigger method for request mocks
* UserAgent option in createBrowser settings

0.8.0 / 2018-06-15
==================

Expand Down
19 changes: 18 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ Will create and return a [Browser](#Browser) instance. It will automatically lau

* _settings_ is an optional object with the settings to build the browser
* `log: false`: If true, it will log all the console events of the browser.
* `userAgent`: If defined, the default user agent will be overridden.
* Any settings that can be passed to Puppeteer can be passed in createdBrowser, for example:
* `headless: true`: If true, the browser will run on headless mode.
* `slowMo: 0`: Slows the execution of commands by given number of milliseconds
Expand Down Expand Up @@ -852,9 +853,11 @@ Response is an object with the following attributes:
* `headers` Optional response headers.
* `contentType` If set, equals to setting Content-Type response header.
* `body` Optional response body. It can be a string or a json-serializable object
* `delay` Optional delay to wait for the response to be fullfilled, in ms
* `auto` if set to false, the request won't be fullfilled automatically and a manual trigger must be defined,default to true


> This object matches the interface with Puppeteer's [respond method](https://github.com/GoogleChrome/puppeteer/blob/master/docs/api.md#requestrespondresponse)
> This object properties will be used with the interface of Puppeteer's [respond method](https://github.com/GoogleChrome/puppeteer/blob/master/docs/api.md#requestrespondresponse)
```js
// All requests made to /api will return 200 with the given body
Expand All @@ -869,7 +872,9 @@ Mock will return a RequestMock object, with the following properties:
* `timesCalled`: The times the mock has been called
* `response` : The response the mock is returning (read only)
* `url`: Mocked url
* `immediate`: If the mock will return immediately (delay=0)
* `assert.called(times?)`: asserts that the mock has been called the given number of times, if times parameter is not given, the assertion will throw if no calls were made
* `auto`: If the request will be completed automatically

```js
const mock=browser.requests.mock("http://localhost:8000/api", {
Expand All @@ -885,6 +890,18 @@ mock.timesCalled; // true

All mocks are removed when opening a different page with `browser.open` unless the option `clearRequestMocks` is set to false.

If the mock is not auto, it can be manually triggered with the method `trigger()`, this method cannot be called with auto mocks:

```js

const mock=browser.requests.mock("http://localhost:8000/api", {
body: {result: "ok"},
auto: false()
});
callApi();
mock.trigger();
```

**removeMock(url, method?)**
Removes the mock with the given url and method. If the original mock has a method, removeMock must provide the same method.

Expand Down
12 changes: 9 additions & 3 deletions lib/browser_core.js
Original file line number Diff line number Diff line change
Expand Up @@ -67,9 +67,15 @@ module.exports = class BrowserCore {
}

_beforeOpen(options) {
return Promise.all(this._components.map((c) => {
return this[c]._beforeOpen(options);
}));
let p = Promise.resolve();
if(this._settings.userAgent) {
p = this.page.setUserAgent(this._settings.userAgent);
}
return p.then(() => {
return Promise.all(this._components.map((c) => {
return this[c]._beforeOpen(options);
}));
});
}

_failIfNotLoaded() {
Expand Down
7 changes: 2 additions & 5 deletions lib/mixins/browser_wait.js
Original file line number Diff line number Diff line change
@@ -1,17 +1,14 @@
/* global WendigoUtils */
"use strict";

const utils = require('../utils');

module.exports = function BrowserWaitMixin(s) {
return class BrowserWait extends s {

wait(ms = 250) {
this._failIfNotLoaded();
return new Promise((resolve) => {
setTimeout(() => {
resolve();
}, ms);
});
return utils.delay(ms);
}

waitFor(selector, timeout = 500, ...args) {
Expand Down
21 changes: 18 additions & 3 deletions lib/modules/browser_requests.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
const RequestFilter = require('../request_filter');
const RequestMocker = require('../request_mocker');
const BrowserModule = require('./browser_module');
const utils = require('../utils');

module.exports = class BrowserRequests extends BrowserModule {
constructor(browser) {
Expand Down Expand Up @@ -49,14 +50,28 @@ module.exports = class BrowserRequests extends BrowserModule {
this.clearRequests();
}

_respondWithMock(request, mock) {
if(mock.auto && mock.immediate) {
return request.respond(mock.response);
} else if(mock.auto) {
return utils.delay(mock.delay).then(() => {
return request.respond(mock.response);
});
} else{
mock.onTrigger(() => {
return request.respond(mock.response);
});
}
}

_startRequestInterceptor() {
this._interceptorReady = true;
return this._browser.page.setRequestInterception(true).then(() => {
return this._browser.page.on('request', request => {
this._requests.push(request);
const mockedResponse = this._requestMocker.getMockedResponse(request);
if(mockedResponse) {
return request.respond(mockedResponse);
const mock = this._requestMocker.getMockedResponse(request);
if(mock) {
return this._respondWithMock(request, mock);
} else {
return request.continue();
}
Expand Down
28 changes: 25 additions & 3 deletions lib/request_mocker.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ const RequestMethods = {
ALL: "ALL"
};

const EventEmitter = require('events');

const ErrorFactory = require('./errors/error_factory');


Expand All @@ -16,7 +18,10 @@ class RequestMock {
contentType: options.contentType,
body: this._processBody(options.body)
};
this.delay = options.delay || 0;
this._timesCalled = 0;
this._auto = options.auto !== false;
this._events = new EventEmitter();
}

get called() {
Expand All @@ -37,6 +42,23 @@ class RequestMock {
};
}

get immediate() {
return this.delay === 0;
}

get auto() {
return this._auto;
}

onTrigger(cb) {
this._events.once("respond", cb);
}

trigger() {
if(this.auto) throw ErrorFactory.generateFatalError(`Cannot trigger auto request mock.`)
this._events.emit("respond");
}

increaseCalled() {
this._timesCalled++;
}
Expand Down Expand Up @@ -69,7 +91,7 @@ module.exports = class RequestMocker {
getMockedResponse(request) {
const url = request.url();
const method = request.method();
return this._getMockData(url, method);
return this._getMock(url, method);
}

mockRequest(url, response, method = RequestMethods.ALL) {
Expand All @@ -89,12 +111,12 @@ module.exports = class RequestMocker {
this._mockedRequests.clear();
}

_getMockData(url, method = RequestMethods.ALL) {
_getMock(url, method = RequestMethods.ALL) {
const mockData = this._mockedRequests.get(url) || {};
const mock = mockData[method] || mockData[RequestMethods.ALL];
if(mock) {
mock.increaseCalled();
return mock.response;
return mock;
}
}

Expand Down
7 changes: 7 additions & 0 deletions lib/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,5 +30,12 @@ module.exports = {
element = JSON.stringify(element);
}
return String(element);
},
delay(ms) {
return new Promise((resolve) => {
setTimeout(() => {
resolve();
}, ms);
});
}
};
Loading

0 comments on commit 10def31

Please sign in to comment.