'ReferenceError: document is not defined' error - javascript

I'm trying to integrate Mocha into my app, but am getting document is not defined error. I've also tried to integrate JSDOM to resolve this but no luck there. Perhaps my implementation is wrong. Thanks in advance!
Note: I'm testing this locally, but will host this on Amazon EC2 later. Would the document error go away on it's own when hosted live on a server?
test.js
var test = require('../index.js');
var assert = require('assert');
var jsdom = require('mocha-jsdom');
global.document = jsdom();
describe('Mutliply', function() {
jsdom();
it('should equal 9 when multiply is called', function() {
assert.equal(9, test.multiply());
});
});
index.js
'use strict';
let test = {};
let movieList = document.getElementById('movie-list');
//bunch of code
test.multiply = function() {
return 3*3;
}
module.exports = test;

The problem is you're requireing the code that uses document in the global scope before you declare the document.
var assert = require('assert');
var jsdom = require('mocha-jsdom');
global.document = jsdom();
var test = require('../index.js');
describe('Mutliply', function() { ...
should work, or even
var assert = require('assert');
var jsdom = require('mocha-jsdom');
global.document = jsdom();
describe('Mutliply', function() {
var test = require('../index.js'); // late import
it('should equal 9 when multiply is called', function() {
assert.equal(9, test.multiply());
});
});

You could try to use JSDom to add Dom support to Node:
const jsdom = require("jsdom");
const { JSDOM } = jsdom;
global.document = new JSDOM(html).window.document;

Related

Jest unable to return value from jQuery

I need jest tests to fail if a jQuery selector returns 0. So if there is a typo, the test should fail.
Here's my index.js:
const sample = $('.someClass');
module.exports = sample;
This is how my index.test.js file looks like:
window.$ = window.jQuery = require('jquery');
const sample = require('./index');
test('test for selector', () => {
expect(sample.length).toBe(1);
});
If I run a console.log(sample.length), it returns 1 on browser console but always 0 on jest. Can someone please help me with this?
For now I managed to go around the problem as follows:
const sampleClassName = '.someClass';
const sample = $(sampleClassName); // For later usage
module.exports = sampleClassName;
And in the test file:
window.$ = window.jQuery = require('jquery');
const sampleClassName = require('./index');
test('test for selector', () => {
expect(someClassName).toBe('.someClass');
});
So this temporarily solves my problem but it would still be great to know if a better solution exists.

mocha unit test - how to clear cached javascript after each test

I'm trying to test a javascript file (let's call it hello.js) using mocha and jsdom. I have several unit tests; each test basically sets up some window properties, calls hello.js, and checks window property values. Tests seem to be running somehow; however, it seems like mocha uses "cached" hello.js after the first test (logging only shows in the first test).
Can someone tell me how I can ensure that I reload hello.js in each test?
const expect = require('chai').expect;
const jsdom = require('jsdom');
const { JSDOM } = jsdom;
var dom = (new JSDOM(`<!DOCTYPE html><html><head></head><body></body></html>`));
describe('hello', ()=>{
afterEach(()=>{
dom = (new JSDOM(`<!DOCTYPE html><html><head></head><body></body></html>`));
global.window = {};
document = {};
location = {};
});
it('should test A', ()=> {
global.window = dom.window;
global.window.document.cookie = "test=kiwi";
document = global.window.document;
const hello = require('../public/hello.js');
expect(document.getElementsByTagName('IFRAME').length).to.equal(1);
});
it('should test B', ()=> {
global.window = dom.window;
global.window.document.cookie = "test=apple";
document = global.window.document;
const hello = require('../public/hello.js');
expect(document.getElementsByTagName('IFRAME').length).to.equal(0);
});
});
There's a library that you can pull in to do this for you:
Example:
const resetCache = require('resnap')(); // Capture "clean" cache state
Reference: Resnap
you can use flush-cache
npm i flush-cache --save-dev
beforeEach(function () {
flush()
})

Exporting two module under same directory not working when requiring from same file

I have two js file under same directory:
main/file1.js and main/file2.js. Then I call it under my test folder test/files.js
If I have this in my file1.js:
function file1(){
let result = "a";
return result;
}
module.exports = file1
Then my file2.js:
let v = "c" //this is the error that make file2 undefined. scope issue.
function file2(){
let result = "b";
return v;
}
module.exports = file2
Then in my test file I am requiring both files. file1's steps function works fine but the file2's steps2 is undefined. Any thought?
const assert = require('assert');
const steps = require('../main/steps');
const steps2 = require('../main/steps2');
describe('steps', function(){
it('make steps', function(){
assert.equal(file1(), 'a');
});
it('make steps2', function(){
assert.equal(file2(), 'b');
});
})
You're requiring the function name when you should be requiring the file name. Your requires should look something like this:
const steps = require('../main/file1');
const steps2 = require('../main/file2');

Chai expect - expect(browser.getTitle()) errors with - browser.getTitle is not a function

I have the following code which uses Chai, but when executed fails and console returns "TypeError: browser.getTitle is not a function."
My path to Globals.js is correct because if I do something like this, it works - expect('Test abc').toContain('abc'). Please help.
const Globals = require('../utilities/Globals');
const browser = require('protractor');
const { Given } = require('cucumber');
// Chai
const globals = new Globals();
const expect = globals.expect;
Given('I am on google page with title {string}', function (title) {
return expect(browser.getTitle()).to.eventually.equal(title);
});
This is Globals.js -
const chai = require('chai');
const chaiAsPromised = require('chai-as-promised');
class Globals {
constructor() {
this.expect = chai.expect;
chai.use(chaiAsPromised);
}
}
module.exports = Globals;
browser is global variable, you can use it directly without to require it. Thus following line is unnecessary:
const browser = require('protractor');

jsdom.env not working on node.js C9

So I've been working with Node.js on C9 recently and ran into this problem in a javascript file:
jsdom.env("", function(err, window) {
TypeError: jsdom.env is not a function
Here is my code:
var jsdom = require('jsdom');
var $;
jsdom.env("", function(err, window) {
console.log("what");
if (err) {
console.error(err);
return;
}
$ = require("jquery")(window);
$.ajax(settings).done(function (response) {
console.log(response);
});
});
I updated all my dependencies as well as Node itself but still get this problem. Does anyone know what's up?
I was facing the same issue. Was looking for the solution all over the web. It turned out that jsdom has updated some of their features since v10. So, I wanted to use jQuery in the Node.js end of an express app.
For those who are just looking for answers about how to include jQuery in Node, I would like to mention that you'll need to install jsdom using npm install jsdom and jQuery using npm install jquery. Then:
For jQuery to work in Node, a window with a document is required. Since no such window exists natively in Node, one can be mocked by jsdom as below:
var jsdom = require('jsdom');
const { JSDOM } = jsdom;
const { window } = new JSDOM();
const { document } = (new JSDOM('')).window;
global.document = document;
var $ = jQuery = require('jquery')(window);
.env() is deprecated since v10. Hope this helps you or anyone who has been facing these types of issues.
As mentioned above, .env() is deprecated.
Use the following:
const { window } = new JSDOM(``, { runScripts: "dangerously" });
const myLibrary = fs.readFileSync("../../whatever.js", { encoding: "utf-8" });
const scriptEl = window.document.createElement("script");
scriptEl.textContent = myLibrary;
window.document.body.appendChild(scriptEl);
In regard to the answer above, and from the jsdom docs:
Don't stuff jsdom globals onto the Node global
A common antipattern we see when people use jsdom is copying globals
from a jsdom window onto the Node.js global, and then trying to run
the code---intended for a browser---inside Node.js. This is very bad
and you should not do it. It runs code intended for the web browser in
some kind of hybrid franken-environment polluted with a ton of globals
that don't make sense there, and loses all benefits of isolating your
code into a jsdom window.
https://github.com/jsdom/jsdom/wiki/Don%27t-stuff-jsdom-globals-onto-the-Node-global
Step 1: npm install jquery
Step 2: npm install jsdom
<!-- language: lang-js -->
//add dummy function to test jquery in Node
function fn1( value ){ console.log( "fn1 says " + value );}
function fn2( value ) {console.log( "fn2 says " + value ); return false;}
var jsdom = require('jsdom');
const { JSDOM } = jsdom;
const { window } = new JSDOM();
const { document } = (new JSDOM('')).window;
//comment out the line below it create problem
//global.document = document;
var $ = jQuery = require('jquery')(window);
var callbacks = $.Callbacks();
callbacks.add(fn1);
callbacks.fire("foo!");
callbacks.add( fn2 );
callbacks.fire( "fool!" );

Categories

Resources