Skip to content

Commit

Permalink
back to mocha + chai
Browse files Browse the repository at this point in the history
  • Loading branch information
evantahler committed Dec 18, 2016
1 parent 1cb0bbf commit 186f370
Show file tree
Hide file tree
Showing 39 changed files with 1,261 additions and 1,220 deletions.
84 changes: 0 additions & 84 deletions __tests__/core/developerMode.js

This file was deleted.

6 changes: 3 additions & 3 deletions bin/methods/generate.js
Expand Up @@ -38,7 +38,7 @@ module.exports = function (api, next) {
publicChat: '/public/chat.html',
publicLogo: '/public/logo/actionhero.png',
publicCss: '/public/css/cosmo.css',
exampleTest: '/__tests__/template.js.example'
exampleTest: '/test/template.js.example'
}

for (let name in oldFileMap) {
Expand Down Expand Up @@ -69,7 +69,7 @@ module.exports = function (api, next) {
'/public/css',
'/public/logo',
'/tasks',
'/__tests__'
'/test'
].forEach(function (dir) {
api.utils.createDirSafely(api.projectRoot + dir)
})
Expand All @@ -95,7 +95,7 @@ module.exports = function (api, next) {
'/public/css/cosmo.css': 'publicCss',
'/public/logo/actionhero.png': 'publicLogo',
'/README.md': 'readmeMd',
'/__tests__/example.js': 'exampleTest'
'/test/example.js': 'exampleTest'
}

for (let file in newFileMap) {
Expand Down
10 changes: 6 additions & 4 deletions bin/templates/package.json
Expand Up @@ -13,11 +13,13 @@
"ioredis" : "latest"
},
"devDependencies" : {
"jest" : "latest"
"cross-env" : "latest",
"chai" : "latest",
"mocha" : "latest"
},
"scripts" : {
"start" : "actionhero start",
"actionhero" : "actionhero",
"test" : "jest"
"start" : "actionhero start",
"actionhero" : "actionhero",
"test" : "cross-env NODE_ENV=test mocha"
}
}
2 changes: 1 addition & 1 deletion config/api.js
Expand Up @@ -68,7 +68,7 @@ exports['default'] = {
exports.test = {
general: function (api) {
return {
id: 'test-server',
id: 'test-server-' + process.pid,
serverToken: 'serverToken-' + process.pid,
developmentMode: true,
startingChatRooms: {
Expand Down
2 changes: 1 addition & 1 deletion config/logger.js
Expand Up @@ -57,7 +57,7 @@ exports['default'] = {
exports.test = {
logger: function (api) {
return {
transports: null
// transports: null
}
}
}
92 changes: 48 additions & 44 deletions docs/_includes/docs/deployment/testing.html
Expand Up @@ -2,13 +2,13 @@
<h1 id="testing" class="page-header">Testing</h1>

<p>ActionHero provides test helpers so that you may try your actions and tasks within a headless environment. We do this by including a <code>specHelper</code> initializer which creates a server, <code>testServer</code> when running within the test environment. Via the <code>testServer</code>, you can easily call actions or tasks without making a real request.</p>
<p>We have chosen <a href="https://facebook.github.io/jest/">Jest</a> as our test framework which is included as a dev-dependency within all new projects (<a href="/docs/overview/#install-and-quickstart">generated</a> with <code>./node_modules/.bin/actionhero generate</code>). You do not need to use these testing tools, but an example will be provided which makes use of them.</p>
<p>We have chosen <a href="http://mochajs.org/">mocha</a> as our test framework and <a href="http://chaijs.com/">chai</a> as our assertion tool which are included as dependencies within all new projects (<a href="/docs/overview/#install-and-quickstart">generated</a> with <code>./node_modules/.bin/actionhero generate</code>). We also use <code>cross-env</code> to set NODE_ENV in a way that works for all operating systems, including Windows. You do not need to use these testing tools, but an example will be provided which makes use of them.</p>
<p>You also don't need to use these test helpers, and you may want to make a ‘real' http or websocket request to test something specific. If this is the case, you can <a href="https://github.com/evantahler/actionhero/tree/master/test/servers">check out how ActionHero tests its own servers</a> for examples.</p>

<h2 id="testing-getting-started">Getting Started</h2>

{% highlight javascript %}
// package.json from a new actionhero project with `jest` included
// package.json from a new actionhero project with `mocha` and `chai` included
{
"author" : "YOU <YOU@example.com>",
"name" : "my_actionhero_project",
Expand All @@ -22,65 +22,69 @@ <h2 id="testing-getting-started">Getting Started</h2>
"ws" : "latest"
},
"devDependencies" : {
"jest" : "latest"
"cross-env": "latest",
"mocha" : "latest",
"chai" : "latest"
},
"scripts" : {
"help" : "actionhero help",
"start" : "actionhero start",
"actionhero" : "actionhero",
"start cluster": "actionhero start cluster",
"test" : "jest"
"test" : "cross-env NODE_ENV=test mocha"
}
}
{% endhighlight %}

<p>To run a jest test suite, you invoke the jest binary, <code>./node_modules/.bin/jest</code>. This will tell jest to look in your <code>./__tests__</code> folder and run any tests that it can find. There are ways to change the test folder location, only run specific tests, change the reporting format and more which you can learn about on <a href="https://facebook.github.io/jest/">Jest's website</a>. We asume that you have <code>jest</code> (and <code>should</code>) installed to your project by listing it in your <code>package.json</code>. If you used <code>ActionHero generate</code> to create your project, this should already be configured for your.</p>
<p>The majority of the time, you'll be testing actions and other methods you have written, so you'll need to "run" an actionhero server as part of your test suite. Many times you'll want to have ActionHero behave in a slightly unique way while testing (perhaps connect to a special database, don't log, etc). To do this, you can change the behavior of the config files for the <code>test</code> environment. Here's how we tell ActionHero <a href="https://github.com/evantahler/actionhero/blob/master/config/logger.js#L48-L54">not to write any logs when testing</a>. Note thest test-specific configuration overrides the defaults. Jest will force NODE_ENV=test when run. You can lock this in as the <a href="https://github.com/evantahler/actionhero/blob/master/package.json#L63"><code>test</code> script in your <code>package.json</code></a> so you can simplify the running of tests with just <code>npm test</code>.</p>
<p>To run a mocha test suite, you invoke the mocha binary, <code>./node_modules/.bin/mocha</code>. This will tell mocha to look in your <code>./test</code> folder and run any tests that it can find. There are ways to change the test folder location, only run specific tests, change the reporting format and more which you can learn about on <a href="http://mochajs.org/">Mocha's website</a>. We asume that you have <code>mocha</code> (and <code>chai</code>) installed to your project by listing it in your <code>package.json</code>. If you used <code>ActionHero generate</code> to create your project, this should already be configured for your.</p>
<p>The majority of the time, you'll be testing actions and other methods you have written, so you'll need to "run" an actionhero server as part of your test suite. Many times you'll want to have ActionHero behave in a slightly unique way while testing (perhaps connect to a special database, don't log, etc). To do this, you can change the behavior of the config files for the <code>test</code> environment. Here's how we tell ActionHero <a href="https://github.com/evantahler/actionhero/blob/master/config/logger.js#L48-L54">not to write any logs when testing</a>. Note thest test-specific configuration overrides the defaults. To ensure that ActionHero boots with the <code>test</code> environment loaded, the test command you run should explicitly do this, AKA: <code>NODE_ENV=test ./node_modules/.bin/mocha</code>. You can log this in as the <a href="https://github.com/evantahler/actionhero/blob/master/package.json#L63"><code>test</code> script in your <code>package.json</code></a> so you can simplify the running of tests with just <code>npm test</code>.</p>
<p>ActionHero comes with a <code>specHelper</code> to make it easier to test tasks and actions. This specHelper is a special <a href="/docs/core/#servers">server</a> which can check things without needing to make an HTTP, websocket, etc request. If you need to check the true behavior of a server (perhaps how the router works for an HTTP request), you should make a real HTTP request in your test suite, using something like the <a href="https://github.com/request/request">request</a> library (<a href="https://github.com/evantahler/actionhero/blob/master/test/servers/web.js#L178-L184">example</a>).</p>

<h2 id="testing-example-test">Example Test</h2>

{% highlight javascript %}
// ./test/integartion/actions/randomNumber.js

var should = require('should');
var actionheroPrototype = require('actionhero');
var actionhero = new actionheroPrototype();
var api, firstNumber;

describe('Action: RandomNumber', function(){
'use strict'

let path = require('path')
var expect = require('chai').expect
var ActionheroPrototype = require(path.join(__dirname, '/../../actionhero.js'))
var actionhero = new ActionheroPrototype()
var api

describe('Action: RandomNumber', () => {
before((done) => {
actionhero.start((error, a) => {
expect(error).to.be.null
api = a
done()
})
})

before(function(done){
actionhero.start(function(error, a){
api = a;
done();
after((done) => {
actionhero.stop(() => {
done()
})
});

after(function(done){
actionhero.stop(function(){
done();
});
});

it('generates random numbers', function(done){
api.specHelper.runAction('randomNumber', function(response){
response.randomNumber.should.be.a.Number;
response.randomNumber.should.be.within(0,1);
firstNumber = response.randomNumber;
done();
});
});

it('is unique / random', function(done){
api.specHelper.runAction('randomNumber', function(response){
response.randomNumber.should.be.a.Number;
response.randomNumber.should.not.equal(firstNumber);
done();
});
});

});
})

var firstNumber = null
it('generates random numbers', (done) => {
api.specHelper.runAction('randomNumber', (response) => {
expect(response.randomNumber).to.be.at.least(0)
expect(response.randomNumber).to.be.at.most(1)
firstNumber = response.randomNumber
done()
})
})

it('is unique / random', (done) => {
api.specHelper.runAction('randomNumber', (response) => {
expect(response.randomNumber).to.be.at.least(0)
expect(response.randomNumber).to.be.at.most(1)
expect(response.randomNumber).not.to.equal(firstNumber)
done()
})
})
})
{% endhighlight %}

<p>Say you had an action that was supposed to respond with a <code>randomNumber</code>, and you wanted to write a test for it.</p>
Expand Down
2 changes: 1 addition & 1 deletion initializers/tasks.js
Expand Up @@ -112,7 +112,7 @@ module.exports = {

validateTask: function (task) {
const fail = (msg) => {
api.log(msg + '; exiting.', 'emerg')
api.log(msg, 'emerg')
}

if (typeof task.name !== 'string' || task.name.length < 1) {
Expand Down
13 changes: 7 additions & 6 deletions package.json
Expand Up @@ -49,7 +49,9 @@
"ws": "^1.1.1"
},
"devDependencies": {
"jest": "^17.0.3",
"chai": "^3.5.0",
"cross-env": "^3.1.3",
"mocha": "^3.2.0",
"request": "^2.75.0",
"standard": "^8.6.0"
},
Expand All @@ -64,19 +66,18 @@
],
"globals": [
"describe",
"beforeAll",
"before",
"beforeEach",
"afterAll",
"after",
"afterEach",
"it",
"expect",
"jest"
"expect"
]
},
"scripts": {
"postinstall": "echo 'To generate a new actionhero project, run \"node ./node_modules/.bin/actionhero generate\"'",
"help": "node ./bin/actionhero help",
"test": "jest",
"test": "cross-env NODE_ENV=test mocha",
"pretest": "standard",
"start": "node ./bin/actionhero"
}
Expand Down
@@ -1,65 +1,66 @@
'use strict'

let path = require('path')
var expect = require('chai').expect
var ActionheroPrototype = require(path.join(__dirname, '/../../actionhero.js'))
var actionhero = new ActionheroPrototype()
var api

describe('Action: Cache', () => {
beforeAll((done) => {
before((done) => {
actionhero.start((error, a) => {
expect(error).toBeNull()
expect(error).to.be.null
api = a
done()
})
})

afterAll((done) => {
after((done) => {
actionhero.stop(() => {
done()
})
})

it('no params', (done) => {
api.specHelper.runAction('cacheTest', {}, (response) => {
expect(response.error).toBe('Error: key is a required parameter for this action')
expect(response.error).to.equal('Error: key is a required parameter for this action')
done()
})
})

it('just key', (done) => {
api.specHelper.runAction('cacheTest', {key: 'test key'}, (response) => {
expect(response.error).toBe('Error: value is a required parameter for this action')
expect(response.error).to.equal('Error: value is a required parameter for this action')
done()
})
})

it('just value', (done) => {
api.specHelper.runAction('cacheTest', {value: 'abc123'}, (response) => {
expect(response.error).toBe('Error: key is a required parameter for this action')
expect(response.error).to.equal('Error: key is a required parameter for this action')
done()
})
})

it('gibberish param', (done) => {
api.specHelper.runAction('cacheTest', {thingy: 'abc123'}, (response) => {
expect(response.error).toBe('Error: key is a required parameter for this action')
expect(response.error).to.equal('Error: key is a required parameter for this action')
done()
})
})

it('requires value to be longer than 2 letters', (done) => {
api.specHelper.runAction('cacheTest', {key: 'abc123', value: 'v'}, (response) => {
expect(response.error).toBe('Error: `value` should be at least 3 letters long')
expect(response.error).to.equal('Error: `value` should be at least 3 letters long')
done()
})
})

it('correct params', (done) => {
api.specHelper.runAction('cacheTest', {key: 'testKey', value: 'abc123'}, (response) => {
expect(response.cacheTestResults.saveResp).toBe(true)
expect(response.cacheTestResults.loadResp.value).toBe('abc123')
expect(response.cacheTestResults.deleteResp).toBe(true)
expect(response.cacheTestResults.saveResp).to.equal(true)
expect(response.cacheTestResults.loadResp.value).to.equal('abc123')
expect(response.cacheTestResults.deleteResp).to.equal(true)
done()
})
})
Expand Down

0 comments on commit 186f370

Please sign in to comment.