Global beforeEach and afterEach in protractor - javascript

In each spec I have beforeEach and afterEach statements. Is it possible to add it somehow globally to avoid code duplication between specs ?

Purpose of beforeEach() and afterEach() functions are to add a block of repetitive code that you would need to execute every time you start or complete executing each spec(it). There are other ways to add generalised code to avoid code repetition, here are few -
If you have a piece of code that you would require to run only once before starting a test suite(describe), then you can use beforeAll() and afterAll() functions that jasmine provides.
If you want to run a piece of code that you want to run only once when the execution starts before starting all the test scripts, then add it in your onPrepare() and onComplete() function.
If you want to add a piece of code that should run even before protractor has started instantiating itself or after it has shut itself down, then use beforeLaunch and afterLaunch.
So it all depends on the scenario that you want to use them in. Hope it helps.

My team has the same desire, to run bits of boilerplate code at the start of every test file. From the discussion here, it doesn't sound like there are hooks to globally add to the beforeEach(), afterEach(), etc.
However, we do use the onPrepare() function to abbreviate the amount of before/after boilerplate code that gets repeated in each spec file. Below is a beforeAll() example, but the pattern could be used for beforeEach()/afterEach(). In this case, we're setting up test users in the database with a DataSeeder class, which we do in the outer-most describe() block in every spec file. (I'm also leaving in my catchProtractorErrorInLocation pattern, because it's super useful for us.)
In protractor.conf.ts add boilerplate code to browser.params object.
onPrepare: function () {
...
const browser = require('protractor').browser;
// Define the ConsoleHelper & DataSeeder instances, which will be used by all tests.
const DataSeeder = require('./e2e/support/data-seeder.js');
browser.params.dataSeeder = new DataSeeder();
browser.catchProtractorErrorInLocation = (error, location) => {
throw new Error(`Error in ${location}\n ${error}`);
};
browser.catchProtractorErrorInBeforeAll = (error) => browser.catchProtractorErrorInLocation(error, 'beforeAll()');
// Return a promise that resolves when DataSeeder is connected to service and ready to go
return browser.params.dataSeeder.waitForConnect();
},
With that in place, we can easily do beforeAll() setup code in an abbreviated set of lines.
beforeAll(() => {
return browser.params.dataSeeder.createTestUsers()
.catch(browser.catchProtractorErrorInBeforeAll);
});
You obviously need to do different things in your setup, but you can see how the pattern can apply.

Related

Run a test in Jest only if certain condition are met

I want to run certain tests depending on certain conditions. If the condition is met then run, otherwise skip the test. I want to do that before being in the test (or maybe jest provide a function to cancel a test inside it? So that it doesn't throw an error)
You can see here what I have :
The setup: I'm testing different crypto-wallet for a DEX, so I have a battery of tests that runs for all those wallets. By design, some features are on some wallets and others don't have them. Here I'm trying to sign a transaction running on an EVM chain different from Ethereum (AVAX here). This will not work on all wallets (normal) like ethwallet, but will for others. I want to test only those that I know support this feature.
My problem: wallet is initialized in beforeAll, and I don't have access to this object outside test() (the expected log is k2, k1 is out of scope and return gibberish). How can I access it then and know if I run the test or skip it? You can see that I tried to implement testif() but unfortunately not working because I have not the good value outside of test().
According with this Github issue you can do something like:
const runTest = wallet ? it : it.skip
runTest( "testName", async () => {
// ...
}
And the code will execute it or it.skip.

How to remove all cy.route from beforeEach in Cypress

I'm creating a lot of tests for application in my firm. Before each test I need to create a state to work on it, and it's always the same, so I created some routes in my own method and then in support/index.js file I created beforeEach that looks like this
beforeEach(() => {
cy.server();
cy.mockSearches(SHORTEN_SEARCHES); // this only creates mocks
cy.loginAdmin();
});
And in 99% percent of tests it's working fine, but there is one test, that needs to work on real data. What should I do? Is there a way to ignore global beforeEach? I guess I can move this part of code to each test before each, but that's code repetition? Or maybe I should override this cy.route with empty responses?
You can add a condition to your beforeEach() to exit before your setup:
beforeEach(() => {
if (shouldUseRealData) return;
cy.server();
cy.mockSearches(SHORTEN_SEARCHES); // this only creates mocks
cy.loginAdmin();
});
As stated in the docs about environment variables, you can set an environment variable in different ways. One way would be to set it in your command line when calling cypress run:
cypress run --env use_mock=true
And then you would use it with Cypress.env('use_mock').
beforeEach(() => {
if (Cypress.env('use_mock')) {
cy.server();
cy.mockSearches(SHORTEN_SEARCHES); // this only creates mocks
cy.loginAdmin();
}
});

Change syntax for protractor step definitions from promises to async syntax

I have a protractor-cucumber framework whose step definitions are somewhat structured as per this: https://github.com/cucumber/cucumber-js/blob/master/docs/support_files/step_definitions.md
I use a return and chain the promises together. Recently, I came across a different syntax called the async function. But, when I try to convert my step definitions to async, all the help files in the framework where I use say module.exports and require() display the following warning:
[ts] File is a CommonJS module; it may be converted to an ES6 module.
When I run test cases since I can't access these helper files due to the error my tests cases fail. Like, my page object files, I am not able to access them from my tests. I think they don't get exported like they used to.
Could someone please advice me as to how I can change my test cases to async syntax without breaking them? How do I resolve the above issue without disrupting my tests in a major way.
Adding code
Here is a step from my step definition before the change
let { Given, Then, When } = require('cucumber');
Given(/^I am on the "([^"]*)" page$/, function (home) {
home = this.url.FDI_HOME;
return browser.get(home);
});
Here is a step definition, after I change it to an async function
let { Given, Then, When } = require('cucumber');
Given(/^I am on the "([^"]*)" page$/, async function (home) {
home = this.url.HOME
await browser.get(home);
});
And I will change my other steps in similar fashion. Problem arises when I try to run the above step it fails saying that it is not able to access this.url.HOME. I have another file to supply URLs called the urls.js looks something like this
let targetStore = browser.params.store || 'bestbuy';
let FDI_HOST = browser.params.fdi;
module.exports = {
HOME Page: 'https://homepage.com',
Shop_Page: 'https://shop.com',
storeLink: `http://www.${targetStore}.com`,
};
I see three dots under the word "module.exports" in VS code and when I hover over it, it displays an error saying: [ts] File is a CommonJS module; it may be converted to an ES6 module.
I have tried to find a resolution to this but not been able to successfully make it. if I use the syntax as "async()=>{}" the test cases fails but when I use "async function(){}" then a few of the steps pass but not the other.
These are suggestions/hints. They visually indicate that vscode can perform an action to possibly refactor/improve your code, but they are not treated as errors.
You can disable them by adding "javascript.suggestionActions.enabled": false to your user/workspace settings.
Source: https://github.com/Microsoft/vscode/issues/47299

Jest testing, make the variable accessible for all test files

The thing is that I have some preparations to do before starting tests. I've got several test files and each of them requires rabbit connection to be opened before each test file, and close it after the ending of all tests in every file. The thing is that I've got to duplicate code in test files to open and close connection. How can deal with connection in one file. I am using TypeScript so several solutions as jest-environment-node, jest-set are not helpful in this case. Also there is a chance that I can solve this proble using setup files as:
"setupFiles": [
"./src/inttests/partial/mocks/setup.ts"
],
And write in setup file something like:
let channel: PubChannel;
beforeAll(() => {
channel = new PubChannel('amqp://localhost', true);
exports.ss = new SystemService(channel); // or using globals but it doesn't actually work in both cases.
});
afterAll(async () => {
await channel.closeConnection();
}
);
The thing is that I need ss variable to use in tests in order to call some functions. But I don't know how to make them available from setupt.ts file as I can't use export kew word because the value has been modified inside beforeAll scope. Is there any chance to solve this ridiculous problem?

Disable Jasmine expectation, like xdescribe or xit?

On the Jasmine website I see that we can disable suites by xdescribe or individual specs by xit. Is there a way to disable only an expectation (like xexpect)?
The reason why I'm asking this is because I'm writing e2e tests with Protractor and in our continuous integration we don't yet (if ever) have access to the database, though locally we can run real end to end tests with access to the database, for example.
I would like to mark individual expectations as optional, depending on a configuration or environment variable. It would be nice to make a switch once, and then create a wrapper around expect, that only fails if we are running the tests locally (with access to the database).
So for example I can create a new spec family:
if (process.env.DB_AVAILABLE) {
dbit = it;
} else {
dbit = xit;
}
and write specs that depend on database connection as following:
dbit('creates new user', function () {});
Is there a way to do the same with expect (e.g. dbexpect)?
If there is something fundamentally wrong with my approach, don't hold it back and let me know.
You could create your own xexpect by implementing all the methods/properties with an empty function:
var xexpect = function() {
return xexpect;
};
Object.getOwnPropertyNames(jasmine.Expectation.prototype).forEach(function(name){
xexpect[name] = xexpect;
});
Object.defineProperty(xexpect, 'not', {get: xexpect});
Usage :
xexpect(1).toBeGreaterThan(2);
xexpect(true).not.toEqual(true);

Categories

Resources