Catch error when created custome expect in jest - jestjs

I created testing Helper Functions as Globals in Jest to be able to use them throughout our application in every single one of our test files.
I am going to cut this out of our testing file. I am going to go to setup-global.js file, and then I will say global.loopExpect = expect() // for looping case
global.loopExpect = (actuals) => {
return {
toContainKeys: (keys) => {
if (actuals.length > 0) {
for(var i = 0; i < actuals.length && i < 5; i++){
expect(actuals[i]).toContainKeys(keys)
}
}
}
}
}
get_array.test.js
test('check contains Book property', async () => {
loopExpect([{title: 'SOLID Principles', author: 'Uncle Bob Martin'}])
.toContainKeys(['year'])
})
And when the test is run, I should get an error because the actuals object does not containr object's year property, right .
But I get an error report on my terminal, and showing the error from at Object.toContainKeys in the file setup-global.js. Even though I want the error message on the failed test to appear at Object.toContainKeys in in the test file get_array.test.js.
How to the test file catch the error or global.loopExpect() function throwing error so JEST thinks the error coming from the test file ???

First, I don't think you need loopExpect, because there is a simpler and more durable way to implement this:
test('check contains Book property', async () =>
[{title: 'SOLID Principles', author: 'Uncle Bob Martin'}].forEach(book =>
expect(book).toContainKeys(['year'])
)
)
But if you really want a helper function and you need to know where the test failed, one way to know is to look at the stack trace. And if you want the error to have a different stack trace, with the line from your test file on top, then you can wrap your test in a try block, and throw a new error from the catch block.

Related

Node JS: How to catch the individual errors while reading files, in case multiple files are read on Promise.all?

I am having 10 different files and I need to read their content and merge it in one object (in NodeJS). I am successfully doing that with the code below:
const fs = require('fs');
const path = require('path');
const { promisify } = require("util");
const readFileAsync = promisify(fs.readFile);
let filePathArray = ['path/to/file/one', ... , 'path/to/file/ten'];
Promise.all(
filePathArray.map(filePath => {
return readFileAsync(filePath);
})
).then(responses => { //array of 10 reponses
let combinedFileContent = {};
responses.forEach((itemFileContent, index) => {
let tempContent = JSON.parse(itemFileContent);
//merge tempContent into combinedFileContent
}
});
But what I wonder is, how to catch if there is some error while trying to read the files? When reading a single file, this works like:
fs.readFile(singleFilePath, (singleFileErr, singleFileContent) => {
if (singleFileErr) {
//do something on error, while trying to read the file
}
});
So my question here is, how can I access to the error inn the first code snippet, which corresponds to singleFileErr from this second code snippet?
The issue I am facing is: in case some of the files does not exists, I want to check the error and to skip this file, but since I can not detect the error with current implementation, my whole block crashes and I am not able to merge the other 9 files because of this one. I want to use the error check I mentioned in the second snippet.
Check out the Promise.allSettled function, which will run every Promise passed to it, and will tell you at the end which ones succeeded and which ones failed.
Maybe try something like this:
in the map() callback, return a promise that resolves to null if the file is not found.
Introduce a middle stage in the promise chain filtering out null responses.
This would look something like this:
Promise.all(
filePathArray.map(filePath => {
return readFileAsync(filePath).catch(function(error){
if(isErrorFileDoesNotExist(error)) return null
throw error;
})
});
).then(responses => {
return responses.filter(response => response != null)
})
.then(filteredResponses => {
// .. do something
});
Would that work for you? Note this presupposes you are actually able to discriminate between missing file errors from other errors the promise returned by readFileAsync() may reject - presumably via the isErrorFileDoesNotExist() function in this snippet.

tap.throws() doesn't work when called with prototypically inherited function?

I'm using constructor functions with prototypical inheritance to build a small library. I'm trying to test that one of the methods throws an error.
Sample code:
function Thing() {
this.x = 'ok'
}
Thing.prototype.trySomething = function() {
throw new Error('test error')
}
const thing = new Thing()
tap.throws(function() { throw new Error('before')}) // this is fine
tap.throws(thing.trySomething()) // urgh
tap.throws(function() { throw new Error('after')}) // never runs
Looks like tap is just throwing the error from trySomething. Running the tests gives me the following results:
ok 1 - expected to throw
not ok 2 - test error
And test 3 doesn't run.
I'm using node-tap (https://github.com/tapjs/node-tap).
t.throws(fn, [expectedError], message, extra)
Expect the function to throw an error. If an expected error is provided, then also verify that the thrown error matches the expected error.
but the same thing seems to happen with native assert.
Any idea what is going on here and how to write a passing test?
The tap.throws assert function accepts a fn/function
Just do this
tap.throws(thing.trySomething, {})
remove the (), it will work fine

jestjs see progress of rest execution

i have test which dynamic and can run 20min
but i am getting output only at the end
is there any way to see progress ?
my code
describe('scenarios', () => {
function doTest(path) {
it(`should pass ${path}`, () => {
...
});
});
for(var i = 0; i < 100; i++) {
doTest(i);
}
});
Unfortunately, there's no such possibility.
But, since Jest treats files as test suites, you could split your test across separate files, name them accordingly and let them be ran by CLI. I know it can get cumbersome, but at least that's an option.
You can also get some inspiration from prettier on how to handle loads of tests with customised functions:
https://github.com/prettier/prettier/blob/master/tests_config/run_spec.js

casperJS - grunt-casper: Running multiple Test-Suites in a loop

Preparation
Hi i am using CasperJS in combination with grunt-casper (github.com/iamchrismiller/grunt-casper) for running automated functional and regression tests in our GUI Development process for verification.
We use it like this, casper runner in gruntfile.js:
casper: {
componentTests: {
options: {
args: ['--ssl-protocol=any', '--ignore-ssl-errors=true', '--web-security=no'],
test: true,
includes: ['tests/testutils/testutils.js']
},
files: {
'tests/testruns/logfiles/<%= grunt.template.today("yyyy-mm-dd-hhMMss") %>/componenttests/concat-testresults.xml': [
'tests/functionaltests/componenttests/componentTestController.js']
}
},
so as it can be seen here we just normally run casper tests with SSL params and calling only ONE Controllerclass here instead of listing the single tests (this is one of the roots of my problem). grunt-casper delivers the object which is in charge for testing and inside every single Controllerclass the tests are included and concatenated....
...now the componentTestController.js looks like the following:
var config = require('../../../testconfiguration');
var urls = config.test_styleguide_components.urls;
var viewportSizes = config.test_styleguide_components.viewportSizes;
var testfiles = config.test_styleguide_components.testfiles;
var tempCaptureFolder = 'tests/testruns/temprun/';
var testutils = new testutils();
var x = require('casper').selectXPath;
casper.test.begin('COMPONENT TEST CONTROLLER', function(test) {
casper.start();
/* Run tests for all given URLs */
casper.each(urls, function(self, url, i) {
casper.thenOpen(url, function() {
/* Test different viewport resolutions for every URL */
casper.each(viewportSizes, function(self, actViewport, j) {
/* Reset the viewport */
casper.then(function() {
casper.viewport(actViewport[0], actViewport[1]);
});
/* Run the respective tests */
casper.then(function() {
/* Single tests for every resolution and link */
casper.each(testfiles, function(self, actTest, k) {
casper.then(function() {
require('.'+actTest);
});
});
});
});
});
});
casper.run(function() {
test.done();
});
});
Here you can see that we running a 3 level loop for testing
ALL URLs given in a JSON config file which are contained in an ARRAY of String ["url1.com","url2.com"....."urln.com"]
ALL VIEWPORT SIZES so that every URL is tested in our desired Viewport resolutions to test the correct Responsibility behaviour of the components
ALL TESTFILES, all testfiles only include a TEST STUB what means, no start, begin or something else, its all in a large Testsourrounding.
MAYBE this is already mocky and can be done in a bette way, so if this is the case i would glad if someone has proposals here, but don't forget that grunt-casper is involved as runner.
Question
So far, so good, the tool in general works fine and the construction we built works as we desired. But the problem is, because all testfiles are ran in a large single context, one failing component fails the whole suite.
In normal cases this is a behaviour i would support, but in our circumstances i do not see any proper solution than log the error / fail the single testcomponent and run on.
Example:
I run a test, which is setUp like described above and in this part:
/* Single tests for every resolution and link */
casper.each(testfiles, function(self, actTest, k) {
casper.then(function() {
require('.'+actTest);
});
});
we include 2 testfiles looking like the following:
Included testfile1.js
casper.then(function () {
casper.waitForSelector(x("//a[normalize-space(text())='Atoms']"),
function success() {
casper.test.assertExists(x("//a[normalize-space(text())='Atoms']"));
casper.click(x("//a[normalize-space(text())='Atoms']"));
},
function fail() {
casper.test.assertExists(x("//a[normalize-space(text())='Atoms']"));
});
});
Included testfile2.js
casper.then(function () {
casper.waitForSelector(x("//a[normalize-space(text())='Buttons']"),
function success() {
casper.test.assertExists(x("//a[normalize-space(text())='Buttons']"));
casper.click(x("//a[normalize-space(text())='Buttons']"));
},
function fail() {
testutils.createErrorScreenshot('#menu > li.active > ul > li:nth-child(7)', tempCaptureFolder, casper, 'BUTTONGROUPS#2-buttons-menu-does-not-exist.png');
casper.test.assertExists(x("//a[normalize-space(text())='Buttons']"));
});
});
So if the assert in testfile1.js fails, everthing failes. So how can i move on to testfile2.js, even if the first fails? Is this possible to configure? Can it be encapsulated somehow?
FYI, this did not work:
https://groups.google.com/d/msg/casperjs/3jlBIx96Tb8/RRPA9X8v6w4J
Almost similar problems
My problem is almost the same like this here:
https://stackoverflow.com/a/27755205/4353553
And this guy here has almost another approach i tried but got his problems too because multiple testsuites ran in a loop occuring problems:
groups.google.com/forum/#!topic/casperjs/VrtkdGQl3FA
MUCH THANKS IN ADVICE
Hopefully I understood what you ware asking - is there a way to suppress the failed assertion's exception throwing behavior?
The Tester's assert method actually allows for overriding the default behavior of throwing an exception on a failed assertion:
var message = "This test will always fail, but never throw an exception and fail the whole suite.";
test.assert(false, message, { doThrow: false });
Not all assert helpers have this option though and the only other solution I can think of is catching the exception:
var message = "This test will always fail, but never throw an exception and fail the whole suite.";
try {
test.assertEquals(true, false, message);
} catch (e) { /* Ignore thrown exception. */ }
Both of these approaches are far from ideal since the requirement in our cases is to not throw for all assertions.
Another short term solution that requires overriding the Tester instance's core assert method is (but is still quite hacky):
// Override the default assert method. Hopefully the test
// casper property doesn't change between running suites.
casper.test.assert =
casper.test.assertTrue = (function () {
// Save original assert.
var __assert = casper.test.assert;
return function (subject, message, context) {
casper.log('Custom assert called!', 'debug');
try {
return __assert.apply(casper.test, arguments);
}
catch (error) {
casper.test.processAssertionResult(error.result);
return false;
}
};
})();
That said, I'm currently looking for a non-intrusive solution to this "issue" (not being able to set a default value for doThrow) as well. The above is relative to Casper JS 1.1-beta3 which I'm currently using.

Is there a way to get mocha print the error object instead of error message?

Let me take an example.
before(function (done)
{
...
testUtils.someInitWork(done);
});
testUtils = {
someInitWork: function (done)
{
...
if (e)
// wrap the error into another error object and add contextual information.
e2 = errorManager.getError('myerror', e, { context: "more context for the error });
}
};
when test initialization code fails deep down a util function, it passes required contextual information into the error object. This error object is passed to before's done callback eventually. mocha prints the error message on console (I am using reporter spec). Instead if I can get it to print util.inspect(e) - that information will be more useful to debug the issue.
Of course, I can modify the test code to print it. but is there a way to modify how mocha reports the error (passed to before callback) on console?

Resources