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!");
});
});
Related
I've been trying to learn the basics of Eel through their documentation. I struggled learning how to trigger a javascript function through python so I tried to download their Hello World example straight from their github. You can open it here.
But I still get the same error, namely: Exception has occurred: AttributeError
module 'eel' has no attribute 'say_hello_js'
The code is as following: (you can also look it up on github in the link abov)
hello.py
import eel
# Set web files folder
eel.init('web')
#eel.expose # Expose this function to Javascript
def say_hello_py(x):
print('Hello from %s' % x)
say_hello_py('Python World!')
eel.say_hello_js('Python World!') # Call a Javascript function
eel.start('hello.html', size=(300, 200)) # Start
web/index.html
<!DOCTYPE html>
<html>
<head>
<title>Hello, World!</title>
<!-- Include eel.js - note this file doesn't exist in the 'web' directory -->
<script type="text/javascript" src="/eel.js"></script>
<script type="text/javascript">
eel.expose(say_hello_js); // Expose this function to Python
function say_hello_js(x) {
console.log("Hello from " + x);
}
say_hello_js("Javascript World!");
eel.say_hello_py("Javascript World!"); // Call a Python function
</script>
</head>
<body>
Hello, World!
</body>
</html>
Could it be that I have a wrong version of python or Eel? I am running Python 3.8.10. I ran pip install eel --upgrade but the issue still occurs.
I cannot pin point the exact issue based on the details you provided. But you can try the following these steps if you're using VSC:
Run this command py -m venv .venv and it will create your virtual environment.
Select the virtual environment's Python interpreter with CTRL + SHIFT + K.
Close out your terminal with the trash icon.
Start the terminal using the virtual environment's Python interpreter with CTRL + J.
Run the command pip install eel.
Create the file hello.py.
Create the directory web.
In web create the file hello.html.
In hello.py use this code:
import eel
eel.init('web')
eel.say_hello_js('Hi from Python')
eel.start('hello.html')
In hello.html use this code:
<!DOCTYPE html>
<html>
<head>
<title>Hello, World!</title>
<!-- Include eel.js - note this file doesn't exist in the 'web' directory -->
<script type="text/javascript" src="/eel.js"></script>
<script type="text/javascript">
eel.expose(say_hello_js); // Expose this function to Python
function say_hello_js(x) {
alert("Hello from " + x);
}
</script>
</head>
<body>
Hello, World!
</body>
</html>
If you followed these steps, you should see the alert box pop up. To trigger a JS function from Python you need to precede the function with the eel expose function like this eel.expose(your_js_function_name);. From Python you would call this function using the eel module and calling that function name like this eel.your_js_function_name(parameter_if_any). Make sure that in your HTML file you have the eel script element in the head. Then another script element after that one with all your functions.
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.
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 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.