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

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()
})

Related

Jest to test JS in a php file

I need to test some javascript I have in a php file (cannot be turned in any other extension file, for a few reasons, including it also contains php).
How can I achieve this using Jest?
For example, I have tried the following:
const parse = require('regenerator-runtime/runtime');
const jsdom = require("jsdom");
const { JSDOM } = jsdom;
test("test JavaScript code in PHP file", async () => {
//create a mock of the DOM
const dom = new JSDOM(`<!DOCTYPE html><body>
<script>
// Add JS code from php file in here
let sum = function sum(a, b) {
return a + b
}
</script>
</body>`);
global.document = dom.window.document;
global.window = dom.window;
global.navigator = dom.window.navigator;
// run your tests here
expect(sum(1, 2)).toBe(3);
});
Unfortunately gives me an error:
ReferenceError: sum is not defined
How can I test the JS within the mock of the DOM since it is in it's own scope?
Is there a better way to test javascript in a php file?

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.

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');

'ReferenceError: document is not defined' error

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;

Test context missing in before and after test hook in nightwatch js globals

I have multiple nightwatch tests with setup and teardown in every single test. I am trying to unify it into globalModule.js in before after(path set in globals_path in nightwatch.json).
//globalModule.js
before:function(test, callback){
// do something with test object
}
//sampletest.js
before: function(test){
..
},
'testing':function(test){
....
}
My problem is test context is not available in globalsModule.js. How do i get it there? Can someone let me know?
Test contex not available now. As said beatfactor, it will available soon.
While it not available try use local before first file, but it hack.
Also you can export all your file into one object and export it into nightwatch, but then you can use local before just in time.
For example:
var tests = {};
var befores = [];
var fs =require('fs');
var requireDir = require('require-dir');
var dirs = fs.readdirSync('build');
//if you have dirs that should exclude
var usefull = dirs.filter(function(item){
return !(item=='data')
});
usefull.forEach(function(item){
var dirObj = requireDir('../build/' + item);
for(key in dirObj){
if(dirObj.hasOwnProperty(key))
for(testMethod in dirObj[key])
if(dirObj[key].hasOwnProperty(testMethod))
if(testMethod == 'before')
befores.push(dirObj[key][testMethod]);
else
tests[testMethod] = dirObj[key][testMethod];
}
});
tests.before = function(browser){
//some global before actions here
//...
befores.forEach(function(item){
item.call(tests,browser);
});
};
module.exports = tests;
For more information https://github.com/beatfactor/nightwatch/issues/388

Categories

Resources