Is it possible to create function inside `conf.js`? - javascript

Is it possible to create function which is used for every spec to test, for example login function inside the conf.js file or directly sendKeys from conf.js as from spec.js

From nodejs syntax, it supports to do that as following:
// conf.js
exports.config = {
// put config at here as usual
};
exports.login = function(username, password) {
browser.get('');
element.sendKeys('');
};
// spec.js
var login = require('./conf.js').login;
// actually, you can move the login function to another .js file to keep
// conf.js more dedicated on configuration purpose.
describe("A spec (with setup and tear-down)", function() {
it('', function(){
login('username', 'password')
});
});
But that is not a good practice. Because main test framework supports to do something before each test case. For jasmine it supplys beforeEach:
describe("A spec (with setup and tear-down)", function() {
var foo;
beforeEach(function() {
foo = 0;
foo += 1;
});
afterEach(function() {
foo = 0;
});
it("is just a function, so it can contain any code", function() {
expect(foo).toEqual(1);
});
it("can have more than one expectation", function() {
expect(foo).toEqual(1);
expect(true).toEqual(true);
});
});
At last, I can't see the benefit/advantage to do as you required.

Related

mocha test (and babel) using global variables

I am writing library using es6, transpiling it with babel via webpack and npm.
The problem is, that my lib is dependent on some code, that I can not change but need to use. I don't know how to load var stuff (from the following example) in my tests so that it is visible for the module.
See the example:
external-stuff.js - this one can not be changed and is loaded before my lib is loaded on prod env.
var stuff = {
get some() { return "some"; }
get stuff() { return "stuff"; }
}
some-module.js - this is one of the modules in the library
export class foo {
static get whatever() { return stuff.some; }
static get whichever() { return stuff.stuff; }
}
test
import {foo} from "../src/foo.js";
let assert = require('assert');
describe('foo', function() {
describe('#whatever()', function() {
it("should do some", function () {
assert.equals(foo.whatever(), "some");
});
});
});
If I run this I get "ReferenceError: stuff is not defined"
I already tried to define "stuff" in before() hook, but no success.
In the end I found a solution that's 'good enough'. I am not sure it would be sufficient for some advanced library though.
I have created file called globals.js
var g = typeof(window) === 'undefined' ? global : window;
// Dependencies - add as many global stuff as needed
g.stuff= typeof(stuff) === 'undefined' ? {} : stuff;
And I import this 'es6module' at the beginning of test
import * as globals from "../lib/global/globals"
import {foo} from "../src/foo.js";
And then I use node-import npm module with which I load the global to the tests in beforeEach hook.
beforeEach(function () {
global.stuff = imports.module("lib/global/stuff.js").stuff;
});
This is perfect for unit testing because I can also mock stuff. And its even more awesome because this way I have a place where I 'define' global dependencies. It would be nice to improve on it and make it per es6modul dependencies... and build on it something fancy... ya know.. dependency injection.
complete test
require('node-import'); // +
import * as globals from "../lib/global/globals"; // +
import {foo} from "../src/foo.js";
let assert = require('assert');
describe('foo', function() {
beforeEach(function () { // +
global.stuff = imports.module("lib/global/stuff.js").stuff; // +
}); // +
describe('#whatever()', function() {
it("should do some", function () {
assert.equals(foo.whatever(), "some");
});
});
});

How to rewire only some object parameters during unit testing?

I have one module that contains an object. I would like to rewire only some of the object's parameters. Let's say my module 'module.js' looks like this:
var obj = {
param_A: 'valueA',
param_B: 'valueB',
param_C: 'valueC'
}
And in the test file I import the module and use rewire.
var rewire = require('rewire');
var module = rewire('../module.js');
describe('Unit-Test', function () {
beforeEach(function () {
module.__set__({
'obj': { param_B: 'newValueB' }
});
});
...
});
Now I have overwritten the entire object and the parameters A and C do not exist anymore. How can keep them? The only thing that comes to my mind is something like this
module.__set__({
'obj': {
param_A: module.obj.param_A,
param_B: 'newValueB',
param_C: module.obj.param_C
}
}
But I feel like there must be a better way.
Can I suggest that you take a look at the 'with' function in require. github/jhnns/rewire
myModule.__with__({
port: 3000
})(function () {
// within this function port is 3000
});
// now port is the previous value again

Mock a variable value in JS unit-tests

How could I mock(stub?) variable from external module in unit-tests?
I have a lib which would be running at browser as well as at node.js:
exports.Utils = (function (Config) {
return {
sum: function (val) {
return Config.defaultVal + val;
}
};
}(exports.Config));
Because tests run with only one (Utils.js) file, Config would be undefined here.
Tests runs in node.js enviroment.
var expect = require('chai').expect;
var Utils = require('./src/Utils.js').Utils;
describe("Test for Utils sum", function () {
it("example sum test", function () {
//How could I specify Config.defaultVal here?
expect(Utils.sum(1)).to.be.equal(2);
});
});
Perhaps I should use sinonjs, but I didn't find clear example for my case.

Using external class during client side Mocha unit testing

I am running unit tests on a javascript class using Mocha using the follow methodology, firstly the test:
var base = require('../moduleone.js');
describe("some test", function() {
it("description", function() {
var check = base.toBeTested(dummyValue)
//test is here ...
});
});
the moduleone.js containing function to be tested:
function toBeTested(category){
//below I calling an assert function defined in moduletwo
//works fine when running in browser
assert(type(category)=='string','category is string type');
//more code..
return something
module.exports.toBeTested = toBeTested;
moduletwo.js:
function assert(outcome, description) {
//see code.tutsplus.com quick and easy javascript testing with assert
var li = outcome ? 'pass' : 'fail';
if (li == 'fail') {
console.log('FAIL: '+description);
}
else {
console.log('PASS: '+description);
}
}
The issue I have is mocha doesn't know anything about moduletwo and when the moduleone function calles the function in moduletwo mocha throws a ReferenceError: assert is not defined. How can I link all my dependencies so that mocha can see them?
In your moduleone.js be sure that you are requireing moduletwo.js to bring your assert function into scope for moduleone.js. Otherwise, you get a ReferenceError, not for any reasons with mocha, but because moduleone does not have access to assert.
// moduletwo.js
function assert(outcome, description) { /* your functionality */ }
module.exports = assert
// moduleone.js
var assert = require('./moduletwo')
function toBeTested(category) { /* your functionality that uses assert */ }
module.exports.toBeTested = toBeTested
Now, with regards to that tutorial. If you are following it to learn how to make an easy assert module, that is fine. But if you are trying to test some code that does something else, consider using an existing assertion library like chai. For example:
// example.test.js
var expect = require('chai').expect
var isValidCategory = require('./is-valid-category')
describe('isValidCategory(category)', function () {
it('validates string categories', function () {
expect(isValidCategory('A String Category')).to.be.true
})
it('does not validate non-string categories', function () {
expect(isValidCategory(['an', 'array', 'somehow'])).to.be.false
})
})
// is-valid-category.js
module.exports = function isValidCategory(category) {
return typeof category === 'string'
}

Angular js unit test mock document

I am trying to test angular service which does some manipulations to DOM via $document service with jasmine.
Let's say it simply appends some directive to the <body> element.
Such service could look like
(function(module) {
module.service('myService', [
'$document',
function($document) {
this.doTheJob = function() {
$document.find('body').append('<my-directive></my directive>');
};
}
]);
})(angular.module('my-app'));
And I want to test it like this
describe('Sample test' function() {
var myService;
var mockDoc;
beforeEach(function() {
module('my-app');
// Initialize mock somehow. Below won't work indeed, it just shows the intent
mockDoc = angular.element('<html><head></head><body></body></html>');
module(function($provide) {
$provide.value('$document', mockDoc);
});
});
beforeEach(inject(function(_myService_) {
myService = _myService_;
}));
it('should append my-directive to body element', function() {
myService.doTheJob();
// Check mock's body to contain target directive
expect(mockDoc.find('body').html()).toContain('<my-directive></my-directive>');
});
});
So the question is what would be the best way to create such mock?
Testing with real document will give us much trouble cleaning up after each test and does not look like a way to go with.
I've also tried to create a new real document instance before each test, yet ended up with different failures.
Creating an object like below and checking whatever variable works but looks very ugly
var whatever = [];
var fakeDoc = {
find: function(tag) {
if (tag == 'body') {
return function() {
var self = this;
this.append = function(content) {
whatever.add(content);
return self;
};
};
}
}
}
I feel that I'm missing something important here and doing something very wrong.
Any help is much appreciated.
You don't need to mock the $document service in such a case. It's easier just to use its actual implementation:
describe('Sample test', function() {
var myService;
var $document;
beforeEach(function() {
module('plunker');
});
beforeEach(inject(function(_myService_, _$document_) {
myService = _myService_;
$document = _$document_;
}));
it('should append my-directive to body element', function() {
myService.doTheJob();
expect($document.find('body').html()).toContain('<my-directive></my-directive>');
});
});
Plunker here.
If you really need to mock it out, then I guess you'll have to do it the way you did:
$documentMock = { ... }
But that can break other things that rely on the $document service itself (such a directive that uses createElement, for instance).
UPDATE
If you need to restore the document back to a consistent state after each test, you can do something along these lines:
afterEach(function() {
$document.find('body').html(''); // or $document.find('body').empty()
// if jQuery is available
});
Plunker here (I had to use another container otherwise Jasmine results wouldn't be rendered).
As #AlexanderNyrkov pointed out in the comments, both Jasmine and Karma have their own stuff inside the body tag, and wiping them out by emptying the document body doesn't seem like a good idea.
UPDATE 2
I've managed to partially mock the $document service so you can use the actual page document and restore everything to a valid state:
beforeEach(function() {
module('plunker');
$document = angular.element(document); // This is exactly what Angular does
$document.find('body').append('<content></content>');
var originalFind = $document.find;
$document.find = function(selector) {
if (selector === 'body') {
return originalFind.call($document, 'body').find('content');
} else {
return originalFind.call($document, selector);
}
}
module(function($provide) {
$provide.value('$document', $document);
});
});
afterEach(function() {
$document.find('body').html('');
});
Plunker here.
The idea is to replace the body tag with a new one that your SUT can freely manipulate and your test can safely clear at the end of every spec.
You can create an empty test document using DOMImplementation#createHTMLDocument():
describe('myService', function() {
var $body;
beforeEach(function() {
var doc;
// Create an empty test document based on the current document.
doc = document.implementation.createHTMLDocument();
// Save a reference to the test document's body, for asserting
// changes to it in our tests.
$body = $(doc.body);
// Load our app module and a custom, anonymous module.
module('myApp', function($provide) {
// Declare that this anonymous module provides a service
// called $document that will supersede the built-in $document
// service, injecting our empty test document instead.
$provide.value('$document', $(doc));
});
// ...
});
// ...
});
Because you're creating a new, empty document for each test, you won't interfere with the page running your tests and you won't have to explicitly clean up after your service between tests.

Categories

Resources