JEST Change pre-formatted output from test case - jestjs

I have an application that runs a Jest test suite from the command line, then takes the JSON output, parses it and then fills table in a database as per the output file. The application runs shell command:
npm run all
and in the package.json file the all script looks like this:
"scripts": {
"all": "../node_modules/.bin/jest --json --outputFile=testResults.json",`
......
}
So I get the testResults.json file and I am able to parse it - so far so good.
But during the test case run I would like to add some extra data to the output. Something like details - where the problems is, how to fix it, some troubleshooting information etc. For example to put one more field in :
require('testResults.json').testResults[x].assertionResults[y].details
You see, the detail property is not part of the json output file format. But can I create it from within the test case (pseudo example):
test('Industry code should match ind_full_code', async () => {
result = await stageDb.query(QUERY);
// And here I want to add this custom information to some global property available?
reporter.thisTestCase.assertionResults.details = "Here is what you should do to fix this ...." // <- Ideally this is how easy I imagine it to be.
expect(result.results).toEqual([]);
}, 2 * 100 * 1000)
I just want to give a little bit more information to the QA or whomever on test failure.
In other words I need the option to change the output from within the test case.
I've been looking into custom reporters, but their listeners are passed the same information as to the json reported.

I've found a need for a similar feature in Jest. The ability to add documentation to the test is rarely supported by test frameworks.
However I found a way to do this with the soon to be default runner: Jest Circus. I then made my own Jest Circus environment. A custom Jest Circus environment provides more test events/lifecycles and access to the actual test code that is being ran.
// Example of a custom Jest Circus environment
export default class MyCustomNodeEnvironment extends NodeEnvironment {
handleTestEvent(event: Circus.Event, state: Circus.State) {
if(event.name === 'test_fn_start') {
console.log(event.test.toString())
// will log the actual test code.
}
}
}
// jest.config.js
{
"testEnvironment": "<rootDir>/my-custom-environment.js",
"testRunner": "jest-circus/runner"
}
I then used regex patterns to find comments in the test functions and add them to the Allure report (Allure report demo).
If you'd like to create your own Jest environment and implement this yourself I've made a template repo or if you prefer a gist of a basic Jest Circus environment.
If you like how Allure reports look you should checkout my open source project jest-circus-allure-environment.

Related

BeforeEach step is repeated with cy.session using cypress-cucumber-preprocessor

I have a Cypress project where I use the Cypress session API to maintain a session throughout features.
Now I try switching from the deprecated Klaveness Cypress Cucumber Preprocessor to the replacement, Badeball's Cypress Cucumber Preprocessor. But I am running into an issue; the beforeEach() step where my authentication takes place gets repeated several times before the tests start. Eventually, Cypress "snaps out of it" and starts running the actual tests - but obviously this is very resource and time intensive, something is going wrong.
My setup:
Dependencies:
"cypress": "^9.6.1",
"#badeball/cypress-cucumber-preprocessor": "^9.1.3",
index.ts:
beforeEach(() => {
let isAuthInitialized = false;
function spyOnAuthInitialized(window: Window) {
window.addEventListener('react:authIsInitialized', () => {
isAuthInitialized = true;
});
}
login();
cy.visit('/', { onBeforeLoad: spyOnAuthInitialized });
cy.waitUntil(() => isAuthInitialized, { timeout: 30000 });
});
login() function:
export function login() {
cy.session('auth', () => {
cy.authenticate();
});
}
As far as I can see, I follow the docs for cy.session almost literally.
My authenticate command has only application specific steps, it does include a cy.visit('/') - after which my application is redirected to a login service (different domain) and then continues.
The problem
cy.session works OK, it creates a session on the first try - then each subsequent time it logs a succesful restore of a valid session. But this happens a number of times, it seems to get stuck in a loop.
Screenshot:
It looks to me like cy.visit() is somehow triggering the beforeEach() again. Perhaps clearing some session data (localstorage?) that causes my authentication redirect to happen again - or somehow makes Cypress think the test starts fresh. But of course beforeEach() should only happen once per feature.
I am looking at a diff of my code changes, and the only difference except the preprocessor change is:
my .cypress-cucumber-preprocessorrc.json (which I set up according to the docs
typing changes, this preprocessor is stricter about typings
plugins/index.ts file, also set up according to the docs
Am I looking at a bug in the preprocessor? Did I make a mistake? Or something else?
There are two aspects of Cypress + Cucumber with preprocessor that make this potentially confusing
Cypress >10 "Run all specs" behaviour
As demonstrated in Gleb Bahmutov PhD's great blog post, if you don't configure Cypress to do otherwise, running all specs runs each hook before each test. His proposed solution is to not use the "run all specs" button, which I find excessive - because there are ways around this; see below for a working solution with the Cucumber preprocessor.
Note: as of Cypress 10, "run all specs" is no longer supported (for reasons related to this unclarity).
Cucumber preprocessor config
The Cypress Cucumber preprocessor recommends to not use the config option nonGlobalStepDefinitions, but instead configure specific paths like (source):
"stepDefinitions": [
"cypress/integration/[filepath]/**/*.{js,ts}",
"cypress/integration/[filepath].{js,ts}",
"cypress/support/step_definitions/**/*.{js,ts}",
]
}
What it doesn't explicitly state though, is that the file which includes your hooks (in my case index.ts) should be excluded from these paths if you don't want them to run for each test! I could see how one might think this is obvious, but it's easy to accidentally include your hooks' file in this filepath config.
TLDR: If I exclude my index.ts file which includes my hooks from my stepDefinitions config, I can use "run all specs" as intended - with beforeEach() running only once before each test.

Cypress with BDD Cucumber how to create my own data type

I am using cypress with cucumber-js and i need to define my own data type. I did exactly same things like is described in https://github.com/TheBrainFamily/cypress-cucumber-preprocessor#custom-parameter-type-resolves.
That means:
cypress > support > step_definitions > customParameterTypes.js
I wrote:
const blogType = ["sport", "gaming"]
defineParameterType({
name: "blogType",
regexp: new RegExp(blogType.join("|"))
})
and in my BDD .feature file i have:
Given I have empty blog
And Blog has default structure for sport
and in my cypress file:
Given(' Blog has default structure for {blogType}', blogType => {...})
When i start my test i get:
The following error originated from your test code, not from Cypress.
> Undefined parameter type {blogType}
When Cypress detects uncaught errors originating from your test code it will automatically fail the current test.
Cypress could not associate this error to any specific test.
For some reasons, I've had problems using defineParameterType() in the past, and am now using regexp in all my BDD projects.
In your .js file:
Given(/^Blog has default structure for (sport|gaming)$/, blogType => {...});
Using the above, you won't need customParameterTypes.js and your .feature file stays the same.

how to remove console.warn message when i ran npm run test?

I am new to react when i run npm run test i get flood of below warnings please give your inputs
console.warn node_modules/react-intl-universal/lib/index.js:101
react-intl-universal locales data "null" not exists
You likely need to initialize react-intl-universal somewhere in your test setup.
A good place to start is how react-intl-universal tests their own code.
Basically you'll need this executed before your tests run that depend on it (sounds like a lot of them?):
import intl from 'react-intl-universal';
// common locale data
require('intl/locale-data/jsonp/en.js');
// app locale data
const locales = {
"en-US": require('./locales/en-US.js'),
};
intl.init({ locales, currentLocale: "en-US" });
If it's just a few places then I'd do it how they do, but if it's your entire codebase you're better off moving it into your test configs/setup.

How to add images to mochawesome report using Codeceptjs?

I'm doing E2E Tests on my own and I found really useful node libraries such as CodeceptJS, WebdriverIO and mocha (mochawesome).
Mochawesome permit to add images in the report but in the way that is explained in its docs with addContext https://www.npmjs.com/package/mochawesome doesn't work with CodeceptJS.
I didn't find any reference about this feature used in CodeceptJS, I only found a git request https://github.com/Codeception/CodeceptJS/issues/379
Is there a way to add images to mochawesome reported generated by mocha using CodeceptJS?
I have my file_test.js with one Before, one After and one Scenario.
What I did is const addContext = require('mochawesome/addContext');
and than add the 'addContext(this,imagePath)' function but I get error
[mochawesome] Error adding context: Invalid test object.
I think the this object you're looking for is this.ctx in Codeceptjs.
Try with addContext(this.ctx, imagePath)
Test should look like:
I.addMochawesomeContext('<screenshot path and name here>');
.......test steps
You can find more information about mocha reporting directly on Codeceptjs web-site: http://codecept.io/reports/
Btw. you cannnot add context in Before and After, context should be unique for each scenario.

How to create a data driven test in Node.js

In Node.js unit tests, what is the way to create data driven unit tests?
For Example, I've a common function / method, which I want to re-use in multiple unit tests with different sets of data. I tried looking into nodeunit, vows, whiskey, qunit, expresso; But I wasn't able to figure out a way to achieve this functionality.
I was not looking at calling the function literally in multiple tests, but rather use the common method in a loop to pick up the data in each iteration and execute it, as a unittest
The reason for this is, I've atleast 1000 rows of parameterized data, for which I want to write unittest. Obviously I cannot go on writing 1000 unittests physically.
Anyone could you please point me a way to achieve the above.
There is qunit addon which allows to run parameterized quint tests
https://github.com/AStepaniuk/qunit-parameterize
So you can separate test data and test method and run the same test method against different data sets.
This is a pretty old post, but I just hit this problem myself and wasn't able to find a clean solution for QUnit without using the plugin referenced by the other comment (qunit-parameterize). Honestly, I couldn't figure out how to integrate the plugin with my company's project and gave up after about an hour.
This is how I ended up solving it:
Just define an array with your inputs (and expected outputs, if needed), iterate over your array, and define the QUnit test in the callback! Super simple, really, but worked quite well.
const testCases = [
{ input: "01/01/2015", expected: "2015-01-01" },
{ input: "09/25/2015", expected: "2015-09-01" },
{ input: "12/31/2015", expected: "2015-12-01" }
];
testCases.forEach(testCase => {
QUnit.test("gets first of month",
() => {
const actual = new classUnderTest().getFirstOfMonth(testCase.input);
strictEqual(actual, testCase.expected);
});
});
I wasn't sure that QUnit would discover the test if it were nested as such, but it does just fine.
Enjoy!

Resources