Skip to content

Commit

Permalink
Implemented Net stub
Browse files Browse the repository at this point in the history
  • Loading branch information
etki committed Aug 31, 2017
1 parent 5078e6b commit 9fb6a09
Show file tree
Hide file tree
Showing 9 changed files with 258 additions and 11 deletions.
4 changes: 2 additions & 2 deletions README.md
Expand Up @@ -148,8 +148,8 @@ http:
# headers:
# - key: Server
# value: elasticsearch/5.5.2
# raw_headers:
# - 'Server: elasticsearch/5.5.2'
# raw_headers: |
# Server: elasticsearch/5.5.2
# text: '{"acknowledged":true}'
responses: []
# whether to throw when last response have been reached or
Expand Down
2 changes: 1 addition & 1 deletion lib/Stub/Factory.js
Expand Up @@ -9,7 +9,7 @@ var Defaults = require('./GlobalDefaults')
var Factory = {
/**
* @param {string} symbol
* @param {TMockSettings} settings
* @param {TStubSettings} settings
* @return {IStub}
*/
create: function (symbol, settings) {
Expand Down
94 changes: 94 additions & 0 deletions lib/Stub/Net.js
@@ -0,0 +1,94 @@
var Factory = require('./Factory').Factory

var HttpRequestOptions = function () {
this.headers = []
this.method = 'GET'
this.params = {}
this.postData = ''
this.rawOutput = false
this.timeout = 90
}

Object.defineProperty(HttpRequestOptions, 'name', {
value: 'Net.HttpRequestOptions',
writable: false
})

var HttpRequestResult = function () {
this.code = 200
this.data = undefined
this.error = ''
this.headers = []
this.raw_headers = ''
this.text = ''
}

Object.defineProperty(HttpRequestResult, 'name', {
value: 'Net.HttpRequestResult',
writable: false
})

var definition = {
defaults: {
http: {
responses: [],
roundRobin: false
}
},
state: {
http: {},
log: {
http: []
}
},
properties: {
HttpRequestOptions: HttpRequestOptions,
HttpRequestResult: HttpRequestResult
},
handlers: {
httpRequest: function (self, url, callback, options) {
if (!self._state.http.responses) {
self._state.http.responses = self._settings.http.responses.slice()
}
var responses = self._state.http.responses
var index = -1
for (var i = 0; i < responses.length; i++) {
var cursor = responses[i]
if (!cursor.matcher || cursor.matcher(url, options)) {
index = i
break
}
}
if (index === -1) {
var message = 'Failed to find matching response for url ' + url +
' and options ' + JSON.stringify(options)
throw new Error(message)
}
var response = responses.splice(index, 1)[0]
if (self._settings.http.roundRobin) {
responses.push(response)
}
var structure = new HttpRequestResult()
var properties = ['code', 'headers', 'data', 'raw_headers', 'text']
properties.forEach(function (property) {
if (response.hasOwnProperty(property)) {
structure[property] = response[property]
}
})
if (response.delay) {
response.delay().then(callback.bind(null, structure))
} else {
callback(structure)
}
},
httpRequestAsync: function (self, url, options) {
return new Promise(function (resolve) {
definition.handlers.httpRequest(self, url, resolve, options)
})
}
}
}

module.exports = {
Net: Factory.create('Net', definition)
}
3 changes: 2 additions & 1 deletion lib/Stub/index.js
Expand Up @@ -2,5 +2,6 @@ module.exports = {
Logger: require('./Logger').Logger,
AppEvents: require('./AppEvents').AppEvents,
CallEvents: require('./CallEvents').CallEvents,
VoxEngine: require('./VoxEngine').VoxEngine
VoxEngine: require('./VoxEngine').VoxEngine,
Net: require('./Net')
}
5 changes: 0 additions & 5 deletions lib/Types/FOnMockFlush.js

This file was deleted.

5 changes: 5 additions & 0 deletions lib/Types/FOnStubFlush.js
@@ -0,0 +1,5 @@
/**
* @callback FOnStubFlush
*
* @param {IStub} self
*/
4 changes: 2 additions & 2 deletions lib/Types/TMockSettings.js → lib/Types/TStubSettings.js
Expand Up @@ -3,11 +3,11 @@
*/

/**
* @typedef {object} TMockSettings
* @typedef {object} TStubSettings
*
* @property {object} defaults
* @property {*} state Default state
* @property {object.<string, *>} properties
* @property {object.<string, function>} handlers
* @property {FOnMockFlush} onFlush
* @property {FOnStubFlush} onFlush
*/
1 change: 1 addition & 0 deletions package.json
Expand Up @@ -29,6 +29,7 @@
"@ama-team/allure-polyfill": "^0.1.0",
"allure-mocha": "0.0.1",
"chai": "^4.1.1",
"chai-as-promised": "^7.1.1",
"coveralls": "^2.13.1",
"fs-extra": "^4.0.1",
"istanbul": "^0.4.5",
Expand Down
151 changes: 151 additions & 0 deletions test/suite/integration/Stub/Net.spec.js
@@ -0,0 +1,151 @@
/* eslint-env mocha */
/* eslint-disable no-unused-expressions */

var Sinon = require('sinon')
var Chai = require('chai')
var expect = Chai.expect

Chai.use(require('chai-as-promised'))

var Net = require('../../../../lib/Stub/Net').Net

describe('Integration', function () {
describe('/Stub', function () {
describe('/Net.js', function () {
describe('.Net', function () {
describe('.httpRequestAsync', function () {
var options
var instance
var response

beforeEach(function () {
response = {
code: 200,
headers: []
}
options = {
http: {
responses: [response]
}
}
autoFactory()
})

var autoFactory = function () {
instance = new Net(options)
return instance
}

it('uses first response if it has no matcher', function () {
options.http.responses = [{code: 200}]
autoFactory()
return instance
.httpRequestAsync('test')
.then(function (value) {
expect(value).to.have.property('code').eq(response.code)
})
})

it('uses next response if first didn\'t match', function () {
var expectedCode = 200
options.http.responses = [
{
code: 404,
matcher: function () {
return false
}
},
{
code: expectedCode,
matcher: function () {
return true
}
}
]
autoFactory()
return instance
.httpRequestAsync('test')
.then(function (value) {
expect(value).to.have.property('code').eq(expectedCode)
})
})

it('throws if no responses have matched', function () {
options.http.responses = []
autoFactory()
var promise = instance.httpRequestAsync('url')
return expect(promise).to.eventually.be.rejected
})

it('discards response if roundRobin is turned off', function () {
options.http.roundRobin = false
autoFactory()
return instance
.httpRequestAsync('url')
.then(function () {
var promise = instance.httpRequestAsync('url')
return expect(promise).to.eventually.be.rejected
})
})

it('places response in the end if roundRobin is turned on', function () {
options.http.roundRobin = true
options.http.responses = [
{code: 200},
{code: 201}
]
autoFactory()
return instance
.httpRequestAsync('url')
.then(function (response) {
expect(response.code).to.eq(200)
return instance.httpRequestAsync('url')
})
.then(function (response) {
expect(response.code).to.eq(201)
return instance.httpRequestAsync('url')
})
.then(function (response) {
expect(response.code).to.eq(200)
})
})

it('uses 200 as default code', function () {
response = {}
autoFactory()
return instance
.httpRequestAsync('url')
.then(function (value) {
expect(value.code).to.eq(200)
})
})

it('respects provided delay', function () {
var handler = Sinon.spy(function () {
return Promise.resolve()
})
options.http.responses = [
{delay: handler}
]
autoFactory()
return instance
.httpRequestAsync('url')
.then(function () {
expect(handler.callCount).to.eq(1)
})
})
})

describe('.HttpRequestOptions', function () {
it('is instantiable', function () {
var lambda = function () {
var net = new Net()
return new net.HttpRequestOptions()
}
expect(lambda).not.to.throw()
})
})
})
})
})
})

0 comments on commit 9fb6a09

Please sign in to comment.