I've been having trouble setting up a test framework for a NodeJS + Backbone app with the constant "require is not defined" error. I finally got it working using an in-browser test framework which picks up all of the dependencies I need and running a test.js file.
Currently, I'm only doing basic testing of my Backbone models, views, and collections. Now, I want to add in API testing but I'm back to the same "require is not defined" error. What is causing this? It's clear that I'm missing something fundamental here. I just want to add:
var request = require('supertest')
, express = require('express');
var app = express();
Snippet of test.js:
describe('Application', function(){
it("creates a global variable for the namespace", function() {
should.exist(App);
})
});
describe('Models', function() {
describe('SearchFormModel', function() {
beforeEach(function() {
this.SearchFormModel = new App.Model.SearchFormModel();
this.defaultFields = this.SearchFormModel.attributes;
})
it("created a SearchFormModel", function() {
should.exist(this.SearchFormModel);
})
it("should have 7 default fields", function() {
Object.keys(this.SearchFormModel).length.should.equal(7);
})
it("should default all fields to empty string", function() {
for (var key in this.defaultFields) {
this.defaultFields[key].should.equal("");
}
})
});
});
test-runner.html:
<!DOCTYPE html>
<html lang="en">
<head>
<!-- Title & Meta -->
<title>Frontend tests</title>
<meta charset="utf-8">
<!-- Stylesheets -->
<link rel="stylesheet" href="../node_modules/mocha/mocha.css">
</head>
<body>
<div id="mocha"></div>
<!-- Testing Libraries -->
<script src="../node_modules/mocha/mocha.js"></script>
<script src="../node_modules/chai/chai.js"></script>
<script>
// Use the expect version of chai assertions - http://chaijs.com/api/bdd
var should = chai.should();
// Tell mocha we want TDD syntax
mocha.setup('tdd');
</script>
<!-- Libs -->
<script src="../public/lib/jquery-1.8.2.min.js"></script>
<script src="../public/lib/underscore-min.js"></script>
<script src="../public/lib/backbone-min.js"></script>
<script src="../public/lib/bootstrap.min.js"></script>
<script src="../public/lib/highcharts.js"></script>
<script src="../public/lib/bootstrap-datepicker.js"></script>
<script src="../public/js/modules/exporting.js"></script>
<!-- Source files -->
<script src="../public/js/namespace.js"></script>
<script src="../public/js/jst.js"></script>
<script src="../public/js/utils.js"></script>
<script src="../public/js/models/models.js"></script>
<script src="../public/js/models/search.js"></script>
<script src="../public/js/models/plot.js"></script>
<script src="../public/js/models/search_result.js"></script>
<script src="../public/js/views/header.js"></script>
<script src="../public/js/views/plot.js"></script>
<script src="../public/js/views/list.js"></script>
<script src="../public/js/views/search.js"></script>
<script src="../public/js/router.js"></script>
<script src="../public/js/app.js"></script>
<!-- Test -->
<script src="test.js"></script>
<script>
mocha.run();
</script>
</body>
</html>
require and commonjs only works in Node.js
If you run Browser test, then you need to code it like you'll run it in the browser. Also note that Unit Test should be done in isolation, you shouldn't need to load you app server (express) to run your test.
I'd like to point you to an easy solution from there, but there's just too many choices. Very basically, you should start running browser test in the browser by loading an html file.
Then, you'll want to automatize this and run browser test from the terminal. That's when you want to run test in PhantomJs and the likes and output browser results on the terminal. Around this, you can checkout Karma and Testem who're two browser test runner (remember here Mocha alone won't run browser test via command line).
As you're using Backbone, you might be interested in the Backbone-Boilerplate Karma + Grunt test setup as a starting point. See more on this here: https://github.com/backbone-boilerplate/backbone-boilerplate
Related
My start HTML:
<!DOCTYPE html>
<html lang="en">
<head>
<script type="module" src="/way/to/app.js" defer></script>
</head>
<body>...</body>
</html>
My app.js script is an EcmaScript Module and loads another EcmaScript Module:
import Mod from "./path/to/module.js";
...
this is module.js:
// const url = ???
export default class Module {
constructor() {
// console.log(url);
}
}
Does exist any method to get loading URL "/way/to/path/to/module.js" in module.js? Something like these variables in nodejs but for browser:
const dir = __dirname;
const file = __filename;
location.href gives an URL for start html page.
Google Chrome and Firefox both support import.meta:
<script type="module">
console.log(import.meta);
</script>
In my console that prints:
Object { url: "file:///D:/testImportMeta.html" }
I think it's not really suited for production, unless Babel supports it. But if you're not over-concerned with lazy browsers, it works well.
It does not work in Node.JS yet.
enter image description here
var express = require ('express');
//create our app
var app = express();
app.use(express.static('public'));
app.listen(3000,function(){
console.log('Sever is up on port 3000');
});
This is code of Server.js file.
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/babel-core/6.1.19/browser.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.4.1/react.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.4.1/react-dom.js"></script>
</head>
<body>
<script type="text/babel" src="app.jsx"></script>
</body>
</html>
Code of index.html file
var Greeter = React.createClass({
render: function(){
return(
<div>
<h1> Howdy! </h1>
</div>
);
}
});
ReactDOM.render(
<Greeter/>,
document.getElementbyId('app')
);
Code of app.jsx file
where is error? i don't find any error.
But when I am opening http://localhost:3000, I am getting a blank page.
Am using Windows 10 and node -v 6.9.1
Any help would be highly appreciated! Thanks.
You forgot to add html element with id='app', Include this in html file, it will work.
<div id="app"></div>
There is an error in this part:
ReactDOM.render(
<Greeter/>,
document.getElementbyId('app')
);
check the spelling of getElementbyId, instead of that put this getElementById.
Try babel 5.8.23.
You forgot to put in the app HTML element.
<div id="app"></div>
Also, there's a typo in getElementById. The B should be caps.
ReactDOM.render(
<Greeter/>,
document.getElementById('app')
);
Please update a Div with id as app since React is not able find an Div with id app
<div id="app"/>
continued to the answer by #MayankShukla. Try adding script for babel transpiler to transform jsx code, include this reference:
<script src="https://cdnjs.cloudflare.com/ajax/libs/babel-standalone/6.19.0/babel.min.js"></script>
I have added to my Node ExpressJS app some components in ReactJS. Since I introduced these components, my tests are failing due to timeout error.
My test suites is including mocha, zombie, chai and sinon, but the first two are enough to reproduce the error.
This is the test:
// tests/home-tests.js
process.env.NODE_ENV = 'test';
var app = require('../index.js');
var Browser = require('zombie');
describe('Homepage Tests', function() {
before(function(){
server = app.listen(3002);
browser = new Browser({ site: 'http://localhost:3002' });
})
it('should render title', function(done){
browser.visit('/', function() {
browser.assert.text('h1', 'A test page for ReactJS');
done();
})
});
after(function(done) {
server.close(done);
});
});
This is the layout:
// views/layouts/main.handlebars
<!doctype html>
<!--[if IE 8]> <html class="ie ie8"> <![endif]-->
<!--[if IE 9]> <html class="ie ie9"> <![endif]-->
<!--[if gt IE 9]><!-->
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Zombie ReactJS Test!</title>
{{{_sections.page_stylesheets}}}
</head>
<body>
{{{body}}}
{{{_sections.page_javascripts}}}
</body>
</html>
This is the view I want to test:
<h1>A test page for ReactJS</h1>
<div id="example"></div>
{{#section 'page_stylesheets'}}
<!-- ReactJS -->
<script src="https://npmcdn.com/react#15.3.1/dist/react.js"></script>
<script src="https://npmcdn.com/react-dom#15.3.1/dist/react-dom.js"></script>
<script src="https://npmcdn.com/babel-core#5.8.38/browser.min.js"></script>
{{/section}}
{{#section 'page_javascripts'}}
<script type="text/babel">
ReactDOM.render(
<p>Hello, world!</p>,
document.getElementById('example')
);
</script>
{{/section}}
I have reproduced the error in this small repo.
It seems that it could be easily fixed with a timeout like it follows:
// tests/home-tests.js
// ...
it('should render title', function(done){
this.timeout(5000);
browser.visit('/', function() {
browser.assert.text('h1', 'A test page for ReactJS');
done();
})
});
However, this doesn't appear to be the most suitable solution. In particular, would you be able to suggest a way to run test only after the page is fully loaded (without timeouts to be set)?
Thank you in advance
Hello I am trying to learn the mean stack and seem to be stuck.
I created a node.js, express angular and mongo project.
I have installed mongo with npm install mongodb
How do I pass data from mongo to the angular view?
my index.ejs file looks like this
<!DOCTYPE html>
<html ng-app="phonecatApp">
<head>
<title><%= title %></title>
<link rel='stylesheet' href='/stylesheets/style.css' />
<script src="/javascripts/countriesCtrl.js"></script>
<script src="/javascripts/angular.min.js" ></script>
</head>
<body>
<h1><%= title %></h1>
<p>Welcome to <%= title %></p>
<div ng-controller="PhoneListCtrl">
<table border="1" cellspacing="0" cellpadding=3>
<tr><td>Abbreviation</td><td>Name</td></tr>
<tr ng-repeat="state in states">
<td>{{state.abbreviation}}</td><td>{{state.name}}</td>
</tr>
</table>
</div>
</body>
</html>
my countriesCtrl.js looks like this
var MongoClient = require('mongodb').MongoClient;
//var mongoClient = new MongoClient(new Server('localhost', 27017));
var phonecatApp = angular.module('phonecatApp', []);
phonecatApp.controller('PhoneListCtrl', function ($scope) {
$scope.lkp_states = function() {
MongoClient.connect("mongodb://localhost:27017/website", function(err, db) {
if(err) {
return console.dir(err);
}
else
{
console.log("connected to mongo");
}
})
return db.collection('states');
}
});
The error I get is this
GET http://localhost:3000/ [HTTP/1.1 200 OK 35ms]
Use of getUserData() or setUserData() is deprecated. Use WeakMap or element.dataset instead. requestNotifier.js:63
GET http://localhost:3000/stylesheets/style.css [HTTP/1.1 304 Not Modified 17ms]
GET http://localhost:3000/javascripts/countriesCtrl.js [HTTP/1.1 304 Not Modified 15ms]
GET http://localhost:3000/javascripts/angular.min.js [HTTP/1.1 304 Not Modified 7ms]
ReferenceError: require is not defined countriesCtrl.js:2
http://localhost:3000/javascripts/angular.min.js is being assigned a //# sourceMappingURL, but already has one
Error: [$injector:modulerr] http://errors.angularjs.org/1.2.21/$injector/modulerr?p0=phonecatApp&p1=%5B%24injector%3Anomod%5D%20http%3A%2F%2Ferrors.angularjs.org%2F1.2.21%2F%24injector%2Fnomod%3Fp0%3DphonecatApp%0Ay%2F%3C%40http%3A%2F%2Flocalhost%3A3000%2Fjavascripts%2Fangular.min.js%3A6%3A443%0AZc%2Fb.module%3C%2F%3C%2Fb%5Be%5D%3C%40http%3A%2F%2Flocalhost%3A3000%2Fjavascripts%2Fangular.min.js%3A20%3A385%0AZc%2Fb.module%3C%2F%3C%40http%3A%2F%2Flocalhost%3A3000%2Fjavascripts%2Fangular.min.js%3A20%3A273%0Ae%2F%3C%40http%3A%2F%2Flocalhost%3A3000%2Fjavascripts%2Fangular.min.js%3A33%3A206%0Aq%40http%3A%2F%2Flocalhost%3A3000%2Fjavascripts%2Fangular.min.js%3A7%3A288%0Ae%40http%3A%2F%2Flocalhost%3A3000%2Fjavascripts%2Fangular.min.js%3A33%3A148%0Agc%40http%3A%2F%2Flocalhost%3A3000%2Fjavascripts%2Fangular.min.js%3A36%3A250%0Afc%2Fc%40http%3A%2F%2Flocalhost%3A3000%2Fjavascripts%2Fangular.min.js%3A18%3A58%0Afc%40http%3A%2F%2Flocalhost%3A3000%2Fjavascripts%2Fangular.min.js%3A18%3A270%0AXc%40http%3A%2F%2Flocalhost%3A3000%2Fjavascripts%2Fangular.min.js%3A17%3A369%0A%40http%3A%2F%2Flocalhost%3A3000%2Fjavascripts%2Fangular.min.js%3A213%3A58%0Aa%40http%3A%2F%2Flocalhost%3A3000%2Fjavascripts%2Fangular.min.js%3A144%3A399%0Aoe%2Fc%2F%3C%40http%3A%2F%2Flocalhost%3A3000%2Fjavascripts%2Fangular.min.js%3A31%3A159%0Aq%40http%3A%2F%2Flocalhost%3A3000%2Fjavascripts%2Fangular.min.js%3A7%3A288%0Aoe%2Fc%40http%3A%2F%2Flocalhost%3A3000%2Fjavascripts%2Fangular.min.js%3A31%3A143%0A angular.min.js:6
GET http://localhost:3000/stylesheets/style.css
The MongoClient uses require.js, which is a common way to include libraries in node.js. In this case, however, you aren't running this code on the server in node.js, you are running it on the client in the browser, and thus don't have require.js defined by default.
You have three options to solve this situation:
Include require.js and register it as a script in your HTML.
Load the MongoClient manually by using a <script> tag in your HTML and using the new MongoClient() function.
Refactor your application to perform the Mongo Database access at the server level in node.js and only have your client HTML perform a request for the query results rather than perform the query itself. (recommended)
I am trying to load local javascripts with jsdom.
Now I am wondering how I can make jsdom loading the javascripts from "__dirname/../public".
Can someone help me?
My current code is:
var fs = require('fs');
var jsdom = require('jsdom');
jsdom.defaultDocumentFeatures = {
FetchExternalResources: ["script"],
ProcessExternalResources: ["script"],
MutationEvents : '2.0',
QuerySelector : false
};
exports.test = function(req, res) {
var html = fs.readFileSync(__dirname+'/../public/html/lame.html');
var document = jsdom.jsdom(html, null, {documentRoot: __dirname+'/../public/'});
var window = document.createWindow();
window.addEventListener('load', function () {
//window.$('script').remove();
//window.$('[id]').removeAttr('id');
res.send(window.document.innerHTML);
window.close();
});
}
The simple HTML page is:
<html>
<head>
<title id="title">bum</title>
<script type="text/javascript" src="/javascripts/jquery.min.js"></script>
<script type="text/javascript" src="/javascripts/stuff.js"></script>
</head>
<body>
<h1>hello world</h1>
<h2 id="bam">XXX</h2>
</body>
</html>
I've run into the same issue and got it to work. Try these, in order:
documentRoot is not documented. The option which is documented is url. So replace documentRoot with url.
If the above is not enough, then add a base element. I've set my templates like this:
<head>
<base href="#BASE#"></base>
<!-- ... -->
</head>
where #BASE# is replaced with the same value as the one passed to url.
The solutions above are extracted from actual code in use in a test suite.