I'm having trouble getting the simplest mocha-phantomjs test to work on Windows, from the command-line. It seems to run the javascript - as I can see some output from console.log, but I'm not seeing any test output.
I did npm install on the following packages
mocha-phantomjs (4.0.2)
phantomjs (2.1.3)
mocha (2.4.4)
chai (3.5.0)
test\cow-test.js:
console.log("fred1");
describe("OnePlusFour", function() {
it("should be able to add two numbers", function() {
chai = require('chai');
var expect = chai.expect;
var first = 1;
var second = 4;
expect(first + second).to.equal(5);
});
});
console.log("fred2");
cow.html:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Cow tests</title>
<link rel="stylesheet" media="all" href="./node_modules/mocha/mocha.css">
</head>
<body>
<div id="mocha"></div>
<script src="./node_modules/mocha/mocha.js"></script>
<script src="./node_modules/chai/chai.js"></script>
<script>
mocha.setup('bdd');
</script>
<script src="test/cow-test.js"></script>
<script>
mocha.run();
</script>
</body>
</html>
When I run mocha on the javascript file, I get the correct test output:
D:\Sandbox\GummyBear>mocha test\cow-test.js
fred1
fred2
OnePlusFour
√ should be able to add two numbers
1 passing (10ms)
Yay! But when I run mocha-phantomjs on the HTML file, I only get console output and nothing from the test:
D:\Sandbox\GummyBear>mocha-phantomjs cow.html
fred1
fred2
^CTerminate batch job (Y/N)? y
and I have to use Ctrl+Break to terminate it, or it will stay there forever. Boo.
What am I doing wrong?
BTW eventually I want to get this working with gulp. I used the MVC Boilerplate templates to create a project structure with ASP.NET Core, bower and gulp etc, but I got stuck at the javascript unit test stage (gulp-mocha-phantomjs gave the error "mocha was not found in the page within 10000ms of the page loading."). So in order to solve that, I wanted to get my head around the basics of JS unit testing first.
Related
In Win10.64 I'm running the test on the command line with expected results:
>mocha test
Array
#indexOf()
√ should return -1 when the value is not present
1 passing (16ms)
But in Chrome, console error is: Uncaught ReferenceError: require is not defined(anonymous function) # test.lead-helper.js:1
test.lead-helper.js:
var assert = require("assert");
describe('Array', function() {
describe('#indexOf()', function () {
it('should return -1 when the value is not present', function () {
assert.equal(-1, [1,2,3].indexOf(5));
assert.equal(-1, [1,2,3].indexOf(0));
});
});
});
and the HTML test runner:
<html>
<head>
<meta charset="utf-8">
<title>Mocha Tests</title>
<link href="https://cdn.rawgit.com/mochajs/mocha/2.2.5/mocha.css" rel="stylesheet" />
</head>
<body>
<div id="mocha"></div>
<div id="messages"></div>
<div id="fixtures"></div>
<script src="https://cdn.rawgit.com/jquery/jquery/2.1.4/dist/jquery.min.js"></script>
<script src="https://cdn.rawgit.com/Automattic/expect.js/0.3.1/index.js"></script>
<script src="https://cdn.rawgit.com/mochajs/mocha/2.2.5/mocha.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/chai/3.3.0/chai.js"></script>
<script src="lead-helper.js"></script>
<script>mocha.setup('bdd')</script>
<script src="test/test.lead-helper.js"></script>
<script>
mocha.checkLeaks();
mocha.globals(['jQuery']);
mocha.run();
</script>
</body>
</html>
Your code seems to be working at cross-purpose. You load Chai:
<script src="https://cdnjs.cloudflare.com/ajax/libs/chai/3.3.0/chai.js"></script>
which is a full-featured assertion library but then you use require("assert") which seems to be an attempt at loading Node's assert library into your browser. There may be a way to get this to load by using Browserify but I don't see why you'd do that, seeing as you already load Chai, and there is no indication that the rest of your code needs Browserify.
I would just remove the require call and instead have:
var assert = chai.assert;
This happens because there is no require() method in browser environment by default, so you have to make some changes in your script moduling. There are some ways you can go:
Use other method to load scripts, for example with the help
<script> tag.
Use CommonJS implementation, like Browserify, or Component.
Use AMD implementation like RequireJs.
I am trying to set up unit/e2e tests for the angular app. Following the instructions on the protractor web site and numerous other samples I have set it up and being able to run tests unless they are referring to the angular objects.
Here is the sample html page I want to have tests for:
<!DOCTYPE html>
<html ng-app="app">
<head>
<script type="text/javascript" src="libraries/angular.js"></script>
<script type="text/javascript" src="libraries/angular-route.js"></script>
<script type="text/javascript" src="libraries/angular-touch.js"></script>
<script type="text/javascript" src="libraries/angular-sanitize.js"></script>
<script type="text/javascript" src="libraries/angular-mocks.js"></script>
.....
</head>
<body ng-controller="DefaultController">
...
The test:
describe('Logon page', function ()
{
beforeEach(function ()
{
browser.get('default.html');
angular.module("app");
});
it('should have a title', function ()
{
expect(browser.getTitle()).toEqual('Logon');
});
});
as soon as I run it I got an exception: "ReferenceEror: angular is not defined".
If I remove line "angular.module("app");" - it works fine.
By looking at console output of the protractor it looks like Protractor.waitForAngular() is internally called after I try to access "angular" object. But as far as I understand browser.get - should load it before?
I use angular 1.3.4 and protractor 1.4.0.
Thanks in advance.
Why do you need the angular.module("app"); part? The code you write in a Protractor test does not run in the browser. It uses the browser API (through Selenium) but you don't have direct access to angular modules or other structures on the page you're testing.
I think you may have mixed up the concepts of unit tests and E2E tests. You'll need angular.module("app"); just for unit tests.
Because I'm using vagrant it looks like the automatic tests when I save a file wont work: grunt karma testing on vagrant when host changes sources grunt/karma doesn't detect it
Trying to run the same tests in a browser however gives me an error I didn't get in grunt. This is the test (simplified as the original tests an angularjs directive):
describe('Unit test the login directive', function() {
var promise = {
then:function(s,f){
this.success=s;
this.fail=f;
},
resolve:function(result){
console.log("calling resolve with:",result);
this.success(result);
}
}
beforeEach(function(){
spyOn($, "get").andReturn(promise);
});
it('Fetch if user is undefined.', function() {
var user={name:'not set'};
$.get("").then(function(data){
user=data;
});
promise.resolve({name:"Ben"});
expect(user.name).toBe("Ben");
});
});
The html file to do the test:
<!DOCTYPE html>
<html>
<head>
<link href="app/bower_components/jasmine-standalone/jasmine.css" rel="stylesheet">
<title>GSA test</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
</head>
<body>
<script>
var loader = {
loaded:-1,
sources:[],
add:function(file){
this.sources.push(file);
},
load:function(){
var i = ++this.loaded,
me=this;
if(i>=this.sources.length){
return;
}
console.log("adding source:",this.sources[i]);
el=document.createElement("script");
el.setAttribute('src',this.sources[i]);
el.onload=function(){
me.load();
}
document.head.appendChild(el);
}
};
loader.add('app/bower_components/jasmine-standalone/jasmine.js');
loader.add('app/bower_components/jasmine-standalone/jasmine-html.js');
loader.add('app/bower_components/jasmine-standalone/jasmine-boot.js');
loader.add('app/bower_components/angular/angular.js');
loader.add('app/bower_components/angular-ui-bootstrap-bower/ui-bootstrap.js');
loader.add('app/bower_components/jquery/dist/jquery.js');
loader.add('app/bower_components/angular-mocks/angular-mocks.js');
</script>
<script src="sources.js"></script>
<script>
loader.load();
</script>
</body>
</html>
Output is:
TypeError: spyOn(...).andReturn is not a function in
url /test/test/unit/loginSpec.js (line 13)
and
TypeError: $.get(...) is undefined in url /test/test/unit/loginSpec.js
(line 17)
Same tests in grunt give me:
[vagrant#localhost html]$ touch -d "now" test/unit/loginSpec.js
INFO [watcher]: Changed file "/var/www/html/test/unit/loginSpec.js".
LOG: 'calling resolve with:', Object{name: 'Ben'}
PhantomJS 1.9.7 (Linux): Executed 3 of 3 SUCCESS (0.033 secs / 0.029 secs)
This could be browser related (test in Firefox instead of PhantomJS) but I'm not sure how to mock $.get in a browser test.
It looks like grunt karma is using an old jasmine that supports andReturn but newer jasmine actually doesn't have such a method when using spyOn.
spyOn($, "get").and.returnValue(promise);
Now works in a browser but fails in grunt. So after changing the package.json to use a newer karma-jasmine "karma-jasmine":"~0.2.2", and an npm install they both work the same.
I've been generating some tests using NodeJS and Mocha, and I'd like to find a way to place the results into a browser. I know that Mocha has support for this using 'html' reporter and mocha init <dir> however neither seem to be working for me (the reporter actually throws errors without even running a test).
Could someone give me a good example of running a test via Mocha and generating a HTML report?An example I want to mimic is on the visionmedia site. Also, for examples sake we'll say I'm using a test file called example.js.
Thanks in advance for any assistance, it's surprising there are so few example pieces around.
You try to use the html reporter, which throws when you try to use it in Node:
$ mocha --reporter html > report.html
/usr/local/lib/node_modules/mocha/lib/reporters/html.js:194
, div = document.createElement('div')
^
ReferenceError: document is not defined
Per the Mocha documentation (and relevant issue in Github), the htmlreporter only works in the browser, ie. to test client-side code in the browser.
If you want to output HTML for a Node.js test script, use the doc reporter, which will generate HTML.
To get Mocha to run your test in both browser and in the terminal follow this small tutorial:
I'm assuming the following plugins for a normal node.js mocha test suite.
Node.js
Mocha
And the following tree structure:
/root
/test
my_something_spec.js
/javascript
index.html
index.html
Disclaimer: I've blatantly forgone all kinds of best practices but just to point you in the right direction.
<html>
<head>
<meta charset="utf-8">
<title>Mocha Tests</title>
<link rel="stylesheet" href="node_modules/mocha/mocha.css" />
</head>
<body>
<div id="mocha"></div>
<script src="node_modules/mocha/mocha.js"></script>
<script>mocha.setup('bdd')</script>
<script src="test/my_something_spec.js"></script>
<script>
mocha.checkLeaks();
mocha.run();
</script>
</body>
</html>
test/my_something_spec.js
describe("my function", function() {
it("is a function", function() {
expect(true).to.be(true);
});
});
Serving this up with a simple python server python -m SimpleHTTPServer 8080 from the root and visit localhost:8080 will give you a nice and failing test.
And running mocha from the terminal will give you the same output, that expect isn't defined.
I like to test the same code through Node.js and in a browser, depending on the situation. I know you were asking to "place the results into a browser" (from Node.js?), but I hope this will suffice.
This example was created on a windows machine, but it will work on a Mac and Linux also.
You do not require a web-server (Node.js or other) for this to work.
To run the tests in a browser, open up the ./test/index.html file.
To run the tests in command-line, just execute "mocha".
Starting from nothing:
C:\TEMP>mkdir mocha_node_browser
C:\TEMP>cd mocha_node_browser
C:\TEMP\mocha_node_browser>dir
Volume in drive C is MessedUp
Volume Serial Number is CAB2-E609
Directory of C:\TEMP\mocha_node_browser
2014-08-09 12:17 <DIR> .
2014-08-09 12:17 <DIR> ..
0 File(s) 0 bytes
2 Dir(s) 287,218,769,920 bytes free
Initialize the directory that will hold all of your tests. Always call it "test":
C:\TEMP\mocha_node_browser>mocha init test
Edit and/or create some files:
C:\TEMP\mocha_node_browser>gvim -p test_me.js test\index.html test\tests.js
I use Chai. The same chai.js file will be used in both tests.
C:\TEMP\mocha_node_browser>cd test
C:\TEMP\mocha_node_browser\test>curl -O http://chaijs.com/chai.js
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 117k 100 117k 0 0 99902 0 0:00:01 0:00:01 --:--:-- 99902
C:\TEMP\mocha_node_browser\test>cd ..
After creating/editing the files, run the tests via command-line:
C:\TEMP\mocha_node_browser>mocha
.
1 passing (15ms)
...or point your browser at ./test/index.html.
passes: 1
failures: 0
duration: 0.03s
whatever
should return "it worked!"
File contents:
C:\TEMP\mocha_node_browser>type test_me.js
// the function to be tested
function whatever() {
return 'it worked!';
}
// only kicks in when running in Node.js via "mocha"
if (typeof module !== 'undefined') {
module.exports = whatever;
}
Add Chai and your source that you want to test into test/index.html:
C:\TEMP\mocha_node_browser>type test\index.html
<!DOCTYPE html>
<html>
<head>
<title>Mocha</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="mocha.css" />
</head>
<body>
<div id="mocha"></div>
<script src="mocha.js"></script>
<script>mocha.setup('bdd')</script>
<!-- added to index.html: -->
<script src="./chai.js"></script>
<script src="../test_me.js"></script>
<script src="tests.js"></script>
<script>
mocha.run();
</script>
</body>
</html>
Make your tests compatible with command-line and browser
C:\TEMP\mocha_node_browser>type test\tests.js
if (typeof require !== 'undefined') {
// testing in command-line
var chai = require('./chai');
var whatever = require('../test_me');
}
var expect = chai.expect;
describe('whatever', function() {
it('should return "it worked!"', function() {
expect(whatever()).to.equal("it worked!");
});
});
I have a project loaded using RequireJS and I would like to test the models.
I have the following test :
require(['../../js/models/lead_sharing'], function(Lead_sharing_Model) {
describe('when instantiated', function () {
it('should exhibit attributes', function() {
var test = new Lead_sharing_Model({
attribute : 3
});
expect(test.get('attribute')).toEqual(3);
});
});
});
But I have a error " failed with error: SyntaxError: Unexpected token"...
In reality , I don't know if it's possible to test a backbone/requireJs project with Jasmine. Indeed, how can I include my views/Models... without require config (like definition of the paths...)
Thanks you
Ps : just a small edit to specify that I would like test with a a js cmd. no in a browser. :)
It is certainly possible to test a backbone/requirejs project with jasmine. Pull the same require config used by the app into the html page that drives the unit tests. For example:
<!doctype html>
<html lang="en">
<head>
<link rel="stylesheet" href="vendor/jasmine.css">
</head>
<body>
<script src="vendor/jasmine.js"></script>
<script src="vendor/jasmine-html.js"></script>
<script src="../assets/js/libs/jquery.js"></script>
<script src="../assets/js/libs/underscore.js"></script>
<script src="../assets/js/libs/backbone.js"></script>
<!-- This points to the require config that is also used by the main app. -->
<script data-main="../app/config" src="../assets/js/libs/require.js"></script>
<script>
require({ paths: { spec: "../test/spec" } }, [
// Pull in all your modules containing unit tests here.
"spec/lead-sharing-specs"
], function() {
jasmine.getEnv().addReporter(new jasmine.TrivialReporter());
jasmine.getEnv().execute();
});
</script>
</body>
</html>
Since you want to run this outside of the browser, check out PhantomJS, grunt, and grunt-jasmine-task.