I just found qHint, a method to integrate jsHint testing into Qunit... but it doesn't work locally (I don't mean localhost) except in Firefox.
So I wanted to add a "warning" or "notice", NOT a test failure, showing that the test was skipped:
// do unit test if not local or local and running Firefox
t = QUnit.isLocal;
if (!t || (t && /Firefox/.test(navigator.userAgent))) {
jsHintTest('JSHint core check', 'js/myplugin.js');
} else {
test('JSHint core check (skipped)', function(){
ok( true, 'check not done locally' );
});
}
I would just like to make it more obvious that a test was skipped, is this possible?
Update: Thanks to Odi for the answer!, but I had to make a slight modification to make the code work in QUnit v1.11.0pre:
QUnit.testSkip = function( testName, callback ) {
QUnit.test(testName + ' (SKIPPED)', function() {
if (typeof callback === "function") {
callback();
}
var li = document.getElementById(QUnit.config.current.id);
QUnit.done(function() {
li.style.background = '#FFFF99';
});
});
};
testSkip = QUnit.testSkip;
I had the same requirement and I simply defined a new kind of test() that I called testSkip().
This test method simply replaces your test function and changes the name to <test name> (SKIPPED). After that the test is considered passed by QUnit.
To further indicate that this is a skipped test, I added a callback function to QUnit.done for each skipped test to change the color of the test in the HTML output to yellow. These callbacks are executed when the test suite is done. Setting the value directly does not work, because QUnit applies the styles for passed/failed tests at the end of the run.
QUnit.testSkip = function() {
QUnit.test(arguments[0] + ' (SKIPPED)', function() {
QUnit.expect(0);//dont expect any tests
var li = document.getElementById(QUnit.config.current.id);
QUnit.done(function() {
li.style.background = '#FFFF99';
});
});
};
testSkip = QUnit.testSkip;
Then you can use testSkip() instead of test() for skipped tests.
For my test suite the result looks like that:
For anyone who may have glazed over the comments, Mottie's comment on the question points out that Qunit now has a skip() function. Just replace any call to test() with skip() to skip that test.
Related
I have a constructor of a js object that looks like this:
function SomeThing(window, document) {
var self = this;
self.window = window;
self.document = document;
if (!self.window.sessionStorage.getItem('page-reloaded')) {
self.window.sessionStorage.setItem('page-reloaded', true);
self.window.location.reload(true); // PROBLEM ON THIS LINE
return;
}
}
my mock test looks like this:
beforeEach(function() {
mockWindowObj = {
'location': {
'href': '',
'search': '?hello=world',
'pathname': '/some/path',
'replace': function () {},
'reload': jasmine.createSpy()
}
};
spyOn(mockWindowObj.location, 'reload').and.callFake(function(){}); ;
some = new SomeThing(mockWindowObj, mockDocumentObj);
});
When I run a test I get this error:
PhantomJS 2.1.1 (Mac OS X 0.0.0) ERROR
{
"message": "Some of your tests did a full page reload!",
"str": "Some of your tests did a full page reload!"
}
If I comment out the line window.location.reload(true) all of my test run fine and pass. I'm sort of new to unit tests and I'm not sure how to get around this. Any help would be very much appreciated. Thanks in advance.
Your posted code cannot be what you actually ran. The line containing self.window.sessionStorage.getItem would have to fail since you did not define sessionStorage on your mock.
I guess the SomeThing function is being called with window pointing to the real window object. That explains what you observe.
Is it possible to set a message (mentioning reason) why a particular test is skipped, so that it could be used in reporters.
describe('xxx', function() {
checkToSkip(1)("test1", function() {\*test goes here*\});
checkToSkip(4)("test2", function() {\*test goes here*\});
});
function checkToSkip(now) {
return now > 3 ? it : xit;
//return now > 3 ? it : it.skip;
}
Here 'test1' will be skipped as 'checkToSkip' returns 'xit' (or it.skip). Is it possible to pass a message to reporter mentioning the reason for the test skip? something like below (or any other possible way).
checkToSkip(4)("test2", function() { \\ test goes here}, "My Skip message!!!!" );
Note: Im using mocha in webdriverIO.
Thanks.
I'd just slightly modify the checkToSkip function and used Pending Tests instead of skip().
function checkToSkip(now, title, testCallable) {
if (now > 3) {
it(title, testCallable);
} else {
it(title+"#My Skip message!#");
}
}
Then use it like:
describe('xxx', function() {
checkToSkip(1, "test1", function() {\*test goes here*\});
});
It's possible to modify the test title itself inside the test before skipping:
it('My cool test', async function() {
if (this.response.status !== 201) {
this._runnable.title += ' - Skipped with reason: wrong response code'
this.skip()
}
expect(this.response.data).to.have.property('mycoolproperty')
})
Also possible to formalize the check and move it to the external function:
function skipIf(that, condition, reason){
if (condition) {
that._runnable.title += ` - Skipped with reason: ${reason}`
that.skip()
}
}
So the test will look like that:
it('My cool test', async function() {
skipIf(this, this.response.status !==201, 'Wrong response status')
expect(this.response.data).to.have.property('mycoolproperty')
})
I have a suite which includes multiple specs. Each spec uses code on some libraries that return a rejected promise upon failure.
I can easily catch those rejected promises inside my spec. What I'm wondering about is that if I can make Protractor exit the whole suite inside that catch function, because the next specs inside the same suite are dependent on the success of the previous specs.
Pretend I have a suite called testEverything which has these specs openApp,signIn,checkUser,logout. If openApp fails, all next specs will fail due to dependency.
Consider this code for openApp:
var myLib = require('./myLib.js');
describe('App', function() {
it('should get opened', function(done) {
myLib.openApp()
.then(function() {
console.log('Successfully opened app');
})
.catch(function(error) {
console.log('Failed opening app');
if ( error.critical ) {
// Prevent next specs from running or simply quit test
}
})
.finally(function() {
done();
});
});
});
How would I exit the whole test?
There is a module for npm called protractor-fail-fast. Install the module npm install protractor-fail-fast. Here's an example from their site where you would place this code into your conf file:
var failFast = require('protractor-fail-fast');
exports.config = {
plugins: [{
package: 'protractor-fail-fast'
}],
onPrepare: function() {
jasmine.getEnv().addReporter(failFast.init());
},
afterLaunch: function() {
failFast.clean(); // Cleans up the "fail file" (see below)
}
}
Their url is here.
I have managed to come up with a workaround. Now the actual code that I used is way more complex, but the idea is the same.
I added a global variable inside protractor's config file called bail. Consider the following code at the top of config file:
(function () {
global.bail = false;
})();
exports.config: { ...
The above code uses an IIFE (Immediately Invoked Function Expression) which defines bail variable on protractor's global object (which would be available throughout the whole test).
I also have written asynchronous wrappers for the Jasmine matchers I need, which would execute an expect expression followed by a comparison, and return a promise (using Q module). Example:
var q = require('q');
function check(actual) {
return {
sameAs: function(expected) {
var deferred = q.defer();
var expectation = {};
expect(actual).toBe(expected);
expectation.result = (actual === expected);
if ( expectation.result ) {
deferred.resolve(expectation);
}
else {
deferred.reject(expectation);
}
return deferred.promise;
}
};
}
module.exports = check;
Then at the end of each spec, I set the bail value based on the spec's progress, which would be determined by the promise of those asynchronous matchers. Consider the following as first spec:
var check = require('myAsyncWrappers'); // Whatever the path is
describe('Test', function() {
it('should bail on next spec if expectation fails', function(done) {
var myValue = 123;
check(myValue).sameAs('123')
.then(function(expectation) {
console.log('Expectation was met'); // Won't happen
})
.catch(function(expectation) {
console.log('Expectation was not met'); // Will happen
bail = true; // The global variable
})
.finally(function() {
done();
});
});
});
Finally, on the beginning of next specs, I check for bail and return if necessary:
describe('Test', function() {
it('should be skipped due to bail being true', function(done) {
if ( bail ) {
console.log('Skipping spec due to previous failure');
done();
return;
}
// The rest of spec
});
});
Now I want to mention that there's one module out there called protractor-fail-fast which bails on the whole test whenever an expectation fails.
But in my case, I needed to set that bail global variable depending on which type of expectation has been failed. I ended up writing a library (really small) that distinguishes failures as critical and non-critical and then using that, specs would be stopped only if a critical failure has occurred.
In Jasmine 1.3, we had this option to the get current spec and suite names:
describe("name for describe", function () {
it("name for it", function () {
console.log(this.suite.getFullName()); // would print "name for describe"
console.log(this.description); // would print "name for it"
});
});
This does not longer work in Jasmine 2.x.
Anyone knows how to fetch those?
Thanks.
I add a new jasmine reporter, then get the spec name without define N variable on each spec. Hope can help, thanks.
var reporterCurrentSpec = {
specStarted: function(result) {
this.name = result.fullName;
}
};
jasmine.getEnv().addReporter(reporterCurrentSpec);
The reason this no longer works is because this is not the test. You can introduce a subtle change to your declarations however that fix it. Instead of just doing:
it("name for it", function() {});
Define the it as a variable:
var spec = it("name for it", function() {
console.log(spec.description); // prints "name for it"
});
This requires no plug-ins and works with standard Jasmine.
As far as Jasmine 2 is concerned currentSpec is discontinued on purpose. However there is a custom plugin/library developed that is based on jasmine reporter plugin which you can use. Here's the Link. Hope it helps with your requirement.
Its very simple to use, install the package with npm command -
npm install -g jasmine-test-container-support
Get the test container support by writing below lines before your describe or test suite -
var JasmineTestContainerSupport = window.JasmineTestContainerSupport || require('jasmine-test-container-support');
JasmineTestContainerSupport.extend(jasmine);
Later use the test container in your spec's to get its description -
var specDesc = jasmine.getEnv().getTestContainer();
Hope this helps.
var currentSpecName = describe('Test1', function() {
var currentStepName = it("Step1", function(){
console.log(currentStepName.description); // Prints It Name
console.log(currentSpecName.getFullName()); //Prints Describe Name
});
});
This worked for me in jasmine 3.5+
I know this is a relatively old question but found something which worked for me
describe('Desc1',() => {
afterEach(() => {
const myReporter = {
specDone: (result) => {
console.log('Spec FullName: ' + result.fullName);
console.log('Spec Result: ' + result.status);
}
};
jasmine.getEnv().addReporter(myReporter);
});
})
Credit for the solution : https://groups.google.com/g/jasmine-js/c/qqOk6Nh7m4c/m/Nyovy2EjAgAJ
This is probably a bit late but you can get the suite name outside the spec.
Please try the following code:
describe("name for describe", function () {
console.log(this.getFullName()); // would print "name for describe"
it("name for it", function () {
//Your test spec
});
});
I have a bunch of failing specs from a rather large architectural change. I'd like to work on fixing them one by one by tagging each one with 'focus'.
Does jasmine.js have a feature like this? I swore I read at one point that it does but I don't see it in the docs.
When using Karma, you can enable only one test with fit or fdescribe (iit and ddescribe in Jasmine before 2.1).
This only runs Spec1:
// or "ddescribe" in Jasmine prior 2.1
fdescribe('Spec1', function () {
it('should do something', function () {
// ...
});
});
describe('Spec2', function () {
it('should do something', function () {
// ...
});
});
This only runs testA:
describe('Spec1', function () {
// or "iit" in Jasmine prior 2.1
fit('testA', function () {
// ...
});
it('testB', function () {
// ...
});
});
In core since 2.1 with fit and fdescribe.
You can run a single spec by using the url for the spec
describe("MySpec", function() {
it('function 1', function() {
//...
})
it('function 2', function() {
//...
}
})
Now you can run just the whole spec by this url http://localhost:8888?spec=MySpec and a the first test with http://localhost:8888?spec=MySpec+function+1
There are a few ways you can do it.
There is: Jasmine's feature Focused Specs (2.2): http://jasmine.github.io/2.2/focused_specs.html
Focusing specs will make it so that they are the only specs that run. Any spec declared with fit is focused.
describe("Focused specs", function() {
fit("is focused and will run", function() {
expect(true).toBeTruthy();
});
it('is not focused and will not run', function(){
expect(true).toBeFalsy();
});
});
However, I don't really like the idea of editing my tests (fit and fdescribe) to run them selectively. I prefer to use a test runner like karma which can filter out tests using a regular expression.
Here's an example using grunt.
$ grunt karma:dev watch --grep=mypattern
If you're using gulp (which is my favourite task runner), you can pass args into gulp-karma with yargs and match patterns by setting karma's config.
Kinda like this:
var Args = function(yargs) {
var _match = yargs.m || yargs.match;
var _file = yargs.f || yargs.file;
return {
match: function() { if (_match) { return {args: ['--grep', _match]} } }
};
}(args.argv);
var Tasks = function() {
var test = function() {
return gulp.src(Files.testFiles)
.pipe(karma({ configFile: 'karma.conf.js', client: Args.match()}))
.on('error', function(err) { throw err; });
};
return {
test: function() { return test() }
}
}(Args);
gulp.task('default', ['build'], Tasks.test);
See my gist: https://gist.github.com/rimian/0f9b88266a0f63696f21
So now, I can run a single spec using the description:
My local test run: (Executed 1 of 14 (skipped 13))
gulp -m 'triggers the event when the API returns success'
[20:59:14] Using gulpfile ~/gulpfile.js
[20:59:14] Starting 'clean'...
[20:59:14] Finished 'clean' after 2.25 ms
[20:59:14] Starting 'build'...
[20:59:14] Finished 'build' after 17 ms
[20:59:14] Starting 'default'...
[20:59:14] Starting Karma server...
INFO [karma]: Karma v0.12.31 server started at http://localhost:9876/
INFO [launcher]: Starting browser Chrome
WARN [watcher]: All files matched by "/spec/karma.conf.js" were excluded.
INFO [Chrome 42.0.2311 (Mac OS X 10.10.3)]: Connected on socket hivjQFvQbPdNT5Hje2x2 with id 44705181
Chrome 42.0.2311 (Mac OS X 10.10.3): Executed 1 of 14 (skipped 13) SUCCESS (0.012 secs / 0.009 secs)
[20:59:16] Finished 'default' after 2.08 s
Also see: https://github.com/karma-runner/karma-jasmine
For anyone stumbling upon this, a better approach, which you can set up from the code itself, is to use this plugin: https://github.com/davemo/jasmine-only
It allows you set the spec exclusivity right on the code like this:
describe.only("MySpec", function() {
it('function 1', function() {
//...
})
it.only('function 2', function() {
//...
}
})
// This won't be run if there are specs using describe.only/ddescribe or it.only/iit
describe("Spec 2", function(){})
There has been a long discussion to get this added to Jasmine core, see: https://github.com/pivotal/jasmine/pull/309
If you happen to be using Jasmine via Karma/Testacular you should already have access to ddescribe() and iit()
You can create your all your specs up front but disable them with xdescribe and xit until you're ready to test them.
describe('BuckRogers', function () {
it('shoots aliens', function () {
// this will be tested
});
xit('rescues women', function () {
// this won't
});
});
// this whole function will be ignored
xdescribe('Alien', function () {
it('dies when shot', function () {
});
});
This is the most simplified answer with a practical example .Even in fdescribe you can run few it blocks using it. f means focus.
Also in a none fdescribe block which is just describe, you can select only specific it blocks by marking them as fit.
Please run the below code and observe the console log, also read the comments in the code.
Read this author's article it helps too . https://davidtang.io/2016/01/03/controlling-which-tests-run-in-jasmine.html
//If you want to run few describe only add f so using focus those describe blocks and it's it block get run
fdescribe("focus description i get run with all my it blocks ", function() {
it("1 it in fdescribe get executed", function() {
console.log("1 it in fdescribe get executed unless no fit within describe");
});
it("2 it in fdescribe get executed", function() {
console.log("2 it in fdescribe get executed unless no fit within describe");
});
//but if you and fit in fdescribe block only the fit blocks get executed
fit("3 only fit blocks in fdescribe get executed", function() {
console.log("If there is a fit in fdescribe only fit blocks get executed");
});
});
describe("none description i get skipped with all my it blocks ", function() {
it("1 it in none describe get skipped", function() {
console.log("1 it in none describe get skipped");
});
it("2 it in none describe get skipped", function() {
console.log("2 it in none describe get skipped");
});
//What happen if we had fit in a none fdescribe block will it get run ? yes
fit("3 fit in none describe get executed too eventhough it;s just describe ", function() {
console.log("3 fit in none describe get executed too");
});
});
With stand-alone Jasmine(2.0.0), on the spec_runner.htlm, I could click a specific spec and focus on that one spec. I should have noticed this feature earlier.
Not exactly what you've asked for but adding iit will test only that particular spec and ignore all others in the file, ddescribe works in the same way. So you can focus on a particular spec using iit or ddescribe