How to use jsdom.jQueryify with jasmine-node? - javascript

Is it possible to user jasmine-node with the jQueryify feature of jsdom? What I'm trying to do is use NodeJS to test some JavaScript that depends on the presence of the DOM.
Here is a reduced case of what I tried. When I run the script, jasmine-node recognizes the spec, but doesn't run the expect():
var fs = require('fs'),
jsdom = require('jsdom'),
window = jsdom.createWindow(),
jasmine = require('jasmine-node')
describe("jQueryify", function() {
it('should run the test!', function () {
jsdom.jQueryify(window, function (window, jquery) {
expect(1).toEqual(1)
})
})
})
Alternately, is there a different/better way to test stuff in NodeJS that assumes a browser-like environment?

OK, based on one this answer to a semi-related question, I was able to get the expect() to execute. I guess the answer to my question is not to use the built-in jQueryify function, but to pull in jQuery 'manually'.
var fs = require('fs'),
window = require('jsdom').jsdom('<html><head></head><body></body></html>').createWindow(),
script = window.document.createElement('script'),
jasmine = require('jasmine-node')
describe("jQueryify", function() {
it('should run the test!', function () {
script.src = './path/to/jquery.js'
script.onload = function () {
expect(typeof window.$).toEqual('function')
asyncSpecDone()
}
window.document.head.appendChild(script)
asyncSpecWait()
})
})

Related

$ is not defined in mocha chai test script

i am trying to write a unit test case for a js function, its inside a .js file am loading that to a test.js file and then run
npm test test.js
my test script contains
const app = require('../js/customJs/myjs.js');
var assert = require('chai').assert;
const jsdom = require("jsdom");
const { JSDOM } = jsdom;
describe('Testing my test functions', function () {
console.log("ready 2 test d dom");
const dom = new JSDOM('<!DOCTYPE html><p id="myid"></div>');
it('check the return value of helloworld module', function () {
assert.equal(dashboard_tab.helloworld(),"hello");
});
});
'myjs.js' file has helloworld function which gets a value from a dom element and call an ajax call ,
so i am trying to unit test if the return value is "hello"('of course this test fails, since that function will not be returning hello'),but while running this test script i was getting error like '$ is not defined'
myjs.js
var count = 0;
function helloworld(){
var id_Val = $("#myid").val(); //i was getting $ is not defined here when i run test.js
$.ajax({
url: "test/",
data: { 'id': id_Val },
dataType: 'json',
success: function (data) {
//some code
}
});
}
i tried
global.$ = require('jquery')(window); // now, window is not defined
how to unit test a js function which includes jquery ($)
This might be caused by $ conflict
Please click here to know how to avoid it.
$conflict also occurs when you load jQuery file multiple times. Could you please check that also

ReferenceError: $ is not defined (WebdriverIO)

I'm launching native apps with the help of WebdriverIO and mocha, but unable to communicate with the device, but able to launch the application but not interact with the element.
android_app_test.js
const webdriverio = require('webdriverio');
const androidOptions = require('../../../helpers/caps').androidOptions;
const assert = require('chai').assert;
androidOptions.capabilities.appPackage = "com.google.android.calculator"
androidOptions.capabilities.appActivity = "com.android.calculator2.Calculator"
describe('Create Chrome web session', function () {
let client;
before(async function () {
client = await webdriverio.remote(androidOptions)
});
after(async function () {
await client.deleteSession();
});
it('should create and destroy Android browser session', async function () {
const elem = await $('#digit_2')
elem.waitForDisplayed(3000);
await client.touchClick('digit_2');
});
});
config.js
var Mocha = require('mocha'), fs = require('fs');
var mocha = new Mocha({
reporter: 'mochawesome-screenshots',
reporterOptions: {
reportDir: 'customReportDir',
reportName: 'customReportName',
reportTitle: 'customReportTitle',
reportPageTitle: 'customReportPageTitle',
takePassedScreenshot: true,
clearOldScreenshots: true,
shortScrFileNames: true,
jsonReport: false,
multiReport: false
},
timeout: 600000,
})
var file = ['./test/basic/app/']; //location of the test js
for (var i = 0; i < file.length; i++) {
fs.readdirSync(file[i]).forEach(function (filename) {
mocha.addFile(file[i] + filename);
});
}
mocha.run(function (failures) {
process.on('exit', function () {
process.exit(failures);
});
});
package.json
"scripts": {
"test": "mocha config.js"
},
Not sure about that, i think something was wrong in my configuration or else
The $ global is added through the WebdriverIO test runner. Since you're using wdio through standalone mode, you don't get access to those globals. Try this instead:
const elem = await client.$('#digit_2')
Make sure you're using the newest version of Webdriver.io. Webdriver.io v5 is the latest version that also implements the $('selector') shortcut.
If you're using Webdriver.io v4 - you may still need to use browser.element('selector') to find your elements.
It appears from the tags in your question, and the code you posted you maybe on version 4.
$ is usually used as a shorthand to run JQuery functions (such as your $('#digit_2'), in the "android_app_test.js" file).
From the WebdriverIO's doc:
The $ command is a short way to call the findElement command in order to fetch a single element on the page. It returns an object that with an extended prototype to call action commands without passing in a selector. However if you still pass in a selector it will look for that element first and call the action on that element.
To fix this you have to install JQuery with this commands:
In a terminal run:
npm install --save jquery
npm install --save-dev #types/jquery
then import it at the top of your "android_app_test.js" file like this
import * as $ from "jquery";

Mocking console.log()/Any Other Function in MOCHA testing framework

I am writing test cases for NODE JS API. But wherever console.log() is there in routes or services of NODE JS File, it gets printed to CLI. Is there a way to mock these so that these won't get printed in CLI.
I have explored couple of libraries like Sinon, Stub for mocking. But couldn't grasp the working of those libraries.
You can override function entirely: console.log = function () {}.
You should not try to mock console.log itself, a better approach is for your node modules to take a logging object. This allows you to provide an alternative (ie. a mock) during testing. For example:
<my_logger.js>
module.exports = {
err: function(message) {
console.log(message);
}
}
<my_module.js>
var DefaultLogger = require('my_logger.js');
module.exports = function(logger) {
this.log = logger || DefaultLogger;
// Other setup goes here
};
module.exports.prototype.myMethod = function() {
this.log.err('Error message.');
};
<my_module_test.js>
var MyModule = require('my_module.js');
describe('Test Example', function() {
var log_mock = { err: function(msg) {} };
it('Should not output anything.', function() {
var obj = new MyModule(log_mock);
obj.myMethod();
});
});
The code here I've simplified, as the actual test isn't the reason for the example. Merely the insertion of alternative logging.
If you have a large codebase with lots of console.log calls, it is better to simply update the code as you add tests for each method. Making your logging pluggable in this way makes your code easier and more receptive to testing. Also, there are many logging frameworks available for node. console.log is fine during development when you just want to dump out something to see what's going on. But, if possible, try to avoid using it as your logging solution.
I could not find a solution which only hides the console.log calls in the module to be tested, and mocks none of the calls of the testing framework (mocha/chai in my case).
I came up with using a copy of console in the app code:
/* console.js */
module.exports = console;
/* app.js */
const console = require('./console');
console.log("I'm hidden in the tests");
/* app.spec.js */
const mockery = require('mockery');
var app;
before(() => {
// Mock console
var consoleMock = {
log: () => {}
}
mockery.registerMock('./console', consoleMock);
// Require test module after mocking
app = require('./app');
});
after(() => {
mockery.deregisterAll();
mockery.disable();
});
it('works', () => {});
You could do something along the lines of adding these before/after blocks to your tests, but the issue is that mocha actually uses console.log to print the pretty messages about the results of the test, so you would lose those
describe('Test Name', function() {
var originalLog;
beforeEach(function() {
originalLog = console.log;
console.log = function () {};
});
// test code here
afterEach(function() {
console.log = originalLog;
})
})
The problem is that your output would just look like
Test Name
X passing (Yms)
Without any intermediate text

Can I mock console in NodeJs?

In my JS test, I need to check if the console.info is called. That's why I want to mock console. However, it seems that the console variable cannot be assigned with a different object. Did I make any mistake?
Here is the code I used:
var oldConsole = console;
var infoContent;
console = {
info: function(content) {
infoContent = content;
}
};
game.process('a command');
infoContent.should.equal('a command is processed');
console = oldConsole;
You can use rewire to replace the whole of console to silence it, or to inject a mock. I use deride but sinon would also work.
var rewire = require('rewire');
var deride = require('deride');
var Game = rewire('../lib/game');
describe('game testing', function() {
var stubConsole, game;
beforeEach(function() {
stubConsole = deride.stub(['info']);
stubConsole.setup.info.toReturn();
Game.__set__({
console: stubConsole
});
game = new Game();
});
it('logs info messages', function() {
game.process('a command');
stubConsole.expect.info.called.withArgs(['a command is processed']);
});
});
I find the solution. I can change the method info of console.
console.info = function(content) {
infoContent = content;
};
The question is now why console object itself cannot be reassigned?
you can use sinon npm to count the call to a function :
it("calls the original function only once", function () {
var callback = sinon.spy();
var proxy = once(callback);
proxy();
proxy();
assert(callback.calledOnce);
// ...or:
// assert.equals(callback.callCount, 1);
});
You can find the docs here : sinonjs.org
I thought I had the same problem and my solution was using this std-mocks module:
https://github.com/neoziro/std-mocks
This has the advantage of not taking over the global "console" but allows you to see what gets logged to the stdout / stderr. This solves the problem in a different way than the question was explicitly looking for; however I believe it is a good answer for the problem the question implies and may be useful for others.
const stdMocks = require('std-mocks');
stdMocks.use(); console.log('test'); stdMocks.restore();
// => undefined [nothing gets output, stdout intercepted]
const logged = stdMocks.flush();
console.log(logged)
// => { stdout: [ 'test\n' ], stderr: [] }

Appium & Webdriver (webdriverjs) - cannot execute javascript code

I am trying to execute javascript Appium test using WD. My code should look something like this:
"use strict";
var wd = require("wd");
var chai = require("chai");
var chaiAsPromised = require("chai-as-promised");
var jQuery = require("jQuery");
chai.use(chaiAsPromised);
chai.should();
chaiAsPromised.transferPromiseness = wd.transferPromiseness;
var desired = {
"appium-version": "1.0",
platformName: "iOS",
platformVersion: "7.1",
deviceName: "iPhone Retina (3.5-inch)",
app: "/Users/{myuser}/Library/Developer/Xcode/DerivedData/{MyApp}/Build/Products/Debug-iphonesimulator/MyApp.app",
};
var browser = wd.promiseChainRemote("0.0.0.0", 4723);
browser.init(desired).then(function() {
var getIframe = function(){
//var r = jQuery('#myIframe');
return {'response':"1"};//only for testing that this method works...
};
return browser
.elementByName("Show Webview").click()
.sleep(10000)
.contexts().then(function (contexts) { // get list of available views. Returns array: ["NATIVE_APP","WEBVIEW_1"]
return browser.context(contexts[1]); // choose the webview context
})
.execute(getIframe).then(function(res){
console.log(res);
})
.sleep(10000)
.fin(function() {
//return browser.quit();
});
}, function(e){console.log(e);}).done();
I am running this code using node mytest.js.
The problem is that I cannot execute js code. In this case I am getting the following error:
Error: [execute()] Not JSON response
What am I doing wrong?
Comments:
What I finally am trying to do here is access and manipulate an iFrame in my code (in the same domain), using iFrame.contentDocument
My insperation for using 'execute like this is from this post
tnx,
Yaniv
UPDATE:
I have managed to execute javascript using "safeExecute" method, instead of "execute".
My issue now is that I do not have access to "window" object, so I cannot run "jQuery" or "window.document.getElementById"...

Categories