I need close and open new browser in protractor - javascript

I have a simple test:
beforeEach(function () {
lib.startApp(constants.ENVIRONMENT, browser);//get url
loginPageLoc.loginAs(constants.ADMIN_LOGIN,constants.ADMIN_PASSWORD,
browser);// log in
browser.driver.sleep(5000); //wait
});
afterEach(function() {
browser.restart(); //or browser.close()
});
it('Test1' , async() => {
lib.waitUntilClickable(adminManagersPage.ButtonManagers, browser);
adminManagersPage.ButtonManagers.click();
expect(element(by.css('.common-popup')).isPresent()).toBe(false);
});
it('Test2' , async() => {
lib.waitUntilClickable(adminManagersPage.ButtonManagers, browser);
adminManagersPage.ButtonManagers.click();
expect(element(by.css('.common-popup')).isPresent()).toBe(false);
});
The first iteration looks fine, but after .restart() I get:
Failed: This driver instance does not have a valid session ID (did you
call WebDriver.quit()?) and may no longer be used. NoSuchSessionError:
This driver instance does not have a valid session ID (did you call
WebDriver.quit()?) and may no longer be used.
If I use .close() I get:
Failed: invalid session id
But if I change Test2 on simple console.log('case 1'); it looks fine.
Please explain what am I doing wrong?

You are declaring your functions as async but are not awaiting the any actions within. If you are not setting your SELENIUM_PROMISE_MANAGER to false in your config then you will see unexpected behavior throughout your test when declaring async functions. This async behavior is likely the cause of your issue so I would ensure SELENIUM_PROMISE_MANAGER:false and ensure your awaiting your actions in each function.
The reason your test passes if you change the second test to just be console.log() is because you are not interacting with the browser and therefore the selenium session ID is not required. Every time the browser is closed the selenium session id will be destroyed and a new one created when a new browser window is launched.
Also you should be aware that there is a config setting you can enable so you do not need to do it manually in your test.
Update: Adding code examples of what I have described:
Note: If you have a lot of code already developed it will take serious effort to convert your framework to Async/await syntax. For a quicker solution you could try removing the async keywords from your it blocks
Add these to your config
SELENIUM_PROMISE_MANAGER:false,
restartBrowserBetweenTests:true
and change you spec to
beforeEach(async function () {
await lib.startApp(constants.ENVIRONMENT, browser);//get url
await loginPageLoc.loginAs(constants.ADMIN_LOGIN, constants.ADMIN_PASSWORD,
browser);// log in
await browser.driver.sleep(5000); //wait
});
it('Test1', async () => {
await lib.waitUntilClickable(adminManagersPage.ButtonManagers, browser);
await adminManagersPage.ButtonManagers.click();
expect(await element(by.css('.common-popup')).isPresent()).toBe(false);
});
it('Test2', async () => {
await lib.waitUntilClickable(adminManagersPage.ButtonManagers, browser);
await adminManagersPage.ButtonManagers.click();
expect(await element(by.css('.common-popup')).isPresent()).toBe(false);
});

There is a relevant configuration option:
// If true, protractor will restart the browser between each test.
restartBrowserBetweenTests: true,
Add the above in your config to restart browser between your tests.
Hope it helps you.

Related

Is it possible to create custom commands in Playwright?

I'm looking for a way to write custom commands in Playwright like it's done in Cypress. Playwright Issues has one page related to it but I have never seen any code example.
I'm working on one test case where I'm trying to improve code reusability. Here's the code:
import { test, chromium } from '#playwright/test';
config();
let context;
let page;
test.beforeEach(async () => {
context = await chromium.launchPersistentContext(
'C:\\Users\\User\\AppData\\Local\\Microsoft\\Edge\\User Data\\Default',
{
headless: false,
executablePath: 'C:\\Program Files (x86)\\Microsoft\\Edge\\Application\\msedge.exe',
}
);
page = await context.newPage();
await page.goto('http://localhost:3000/');
});
test.afterEach(async () => {
await page.close();
await context.close();
});
test('Sample test', async () => {
await page.click('text=Open popup');
await page.click('_react=Button >> nth=0');
await page.click('text=Close popup');
});
I'm trying to create a function that will call hooks test.beforeEach() and test.afterEach() and the code inside them.
In the Playwright Issue page, it says that I need to move it to a separate Node module and then I would be able to use it but I'm struggling to understand how to do it.
The example you're giving can be solved by implementing a custom fixture.
Fixtures are #playwright/test's solution to customizing/extending the test framework. You can define your own objects (similar to browser, context, page) that you inject into your test, so the test has access to it. But they can also do things before and after each test such as setting up preconditions and tearing them down. You can also override existing fixtures.
For more information including examples have a look here:
https://playwright.dev/docs/test-fixtures

Create React App changes behaviour of jest.fn() when mocking async function

I am confused about the below behaviour of jest.fn() when run from a clean CRA project created using npx create-react-app jest-fn-behaviour.
Example:
describe("jest.fn behaviour", () => {
const getFunc = async () => {
return new Promise((res) => {
setTimeout(() => {
res("some-response");
}, 500)
});;
}
const getFuncOuterMock = jest.fn(getFunc);
test("works fine", async () => {
const getFuncInnerMock = jest.fn(getFunc);
const result = await getFuncInnerMock();
expect(result).toBe("some-response"); // passes
})
test("does not work", async () => {
const result = await getFuncOuterMock();
expect(result).toBe("some-response"); // fails - Received: undefined
})
});
The above test will work as expected in a clean JavaScript project but not in a CRA project.
Can someone please explain why the second test fails? It appears to me that when mocking an async function jest.fn() will not work as expected when called within a non-async function (e.g. describe above). It will work only when called within an async function (test above). But why would CRA alter the behaviour in such a way?
The reason for this is, as I mentioned in another answer, that CRA's default Jest setup includes the following line:
resetMocks: true,
Per the Jest docs, that means (emphasis mine):
Automatically reset mock state before every test. Equivalent to
calling jest.resetAllMocks() before each test. This will lead to
any mocks having their fake implementations removed but does not
restore their initial implementation.
As I pointed out in the comments, your mock is created at test discovery time, when Jest is locating all of the specs and calling the describe (but not it/test) callbacks, not at execution time, when it calls the spec callbacks. Therefore its mock implementation is pointless, as it's cleared before any test gets to run.
Instead, you have three options:
As you've seen, creating the mock inside the test itself works. Reconfiguring an existing mock inside the test would also work, e.g. getFuncOuterMock.mockImplementation(getFunc) (or just getFuncOuterMock.mockResolvedValue("some-response")).
You could move the mock creation and/or configuration into a beforeEach callback; these are executed after all the mocks get reset:
describe("jest.fn behaviour", () => {
let getFuncOuterMock;
// or `const getFuncOuterMock = jest.fn();`
beforeEach(() => {
getFuncOuterMock = jest.fn(getFunc);
// or `getFuncOuterMock.mockImplementation(getFunc);`
});
...
});
resetMocks is one of CRA's supported keys for overriding Jest configuration, so you could add:
"jest": {
"resetMocks": false
},
into your package.json.
However, note that this can lead to false positive tests where you expect(someMock).toHaveBeenCalledWith(some, args) and it passes due to an interaction with the mock in a different test. If you're going to disable the automatic resetting, you should also change the implementation to create the mock in beforeEach (i.e. the let getFuncOuterMock; example in option 2) to avoid state leaking between tests.
Note that this is nothing to do with sync vs. async, or anything other than mock lifecycle; you'd see the same behaviour with the following example in a CRA project (or a vanilla JS project with the resetMocks: true Jest configuration):
describe("the problem", () => {
const mock = jest.fn(() => "foo");
it("got reset before I was executed", () => {
expect(mock()).toEqual("foo");
});
});
● the problem › got reset before I was executed
expect(received).toEqual(expected) // deep equality
Expected: "foo"
Received: undefined

How to reload a page in testcafe cucumberjs

I am using TestCafe with Cucumber.js and I don't know how to reload the page. Testcafe documentation says to use .eval(() => location.reload(true))
which gives me the following error:
eval cannot implicitly resolve the test run in the context of which it should be executed. If you need to call eval from the Node.js API callback, pass the test controller manually via eval's .with({ boundTestRun: t }) method first. Note that you cannot execute eval outside the test code.
Here is my BDD scenario:
When('User hard refreshes the page', async () => {
await testController
.eval(() => location.reload(true))
});
You can use ClientFunction instead of t.eval:
import { ClientFunction } from 'testcafe';
When('User hard refreshes the page', async () => {
const reloadPage = ClientFunction(() => location.reload(true), { boundTestRun: testController });
await reloadPage();
});

Can't get metadata selector text

This is a duplicate question to
node js puppeteer metadata
At the time of writing this question I don't have enough reputation to comment on the question.
I am writing some test scripts for a project and I want to test some seo metadata tags.
I check my selector in the chrome dev tools and it works fine.
document.querySelectorAll("head > meta[name='description']")[0].content;
and I receive the data no problem
but when I try to get it to work inside my testing script I can't seem to get a hold of the selector.
describe('guest jobs page', function () {
const {expect} = require('chai');
let page;
before(async function () {
page = await browser.newPage();
await page.goto('https://page');
});
after(async function () {
await page.close();
})
it('should have the correct page title', async function () {
expect(await page.title()).to.eql('page - Jobs');
});
it('should have the correct page description', async function () {
const DESCRIPTION_SELECTOR = "head > meta[name='description']";
await console.log( await page.evaluate((DESCRIPTION_SELECTOR) => document.querySelectorAll(DESCRIPTION_SELECTOR)));
expect(await page.$eval(DESCRIPTION_SELECTOR, element => element.textContent)).to.eql('page description content');
//this fails as no content is returned
//AssertionError: expected '' to deeply equal 'page description content'
});
});
any help would be appreciated, I don't know how to attach this question to the previous one without commenting so if someone could enlighten me about that I would also be very grateful. Thanks.
I believe console.log will be empty because DESCRIPTION_SELECTOR is undefined inside of page.evaluate.
In order to use a variable from the main script inside of page.evaluate one must explicitly pass it into the evaluating function:
await page.evaluate(DESCRIPTION_SELECTOR => document.querySelectorAll(DESCRIPTION_SELECTOR), DESCRIPTION_SELECTOR);
This is because page.evaluate operates in a kind of a sandbox and only has access to functions and variables declared at the web page opened by puppeteer (the so called "page context"). Since that page has no DESCRIPTION_SELECTOR, we must pass it in arguments of the page.evaluate, after the function to be evaluated. See also: documentation
As for page.$eval, it returns empty string because there is no textContent in meta tag, you need to use just content:
page.$eval(DESCRIPTION_SELECTOR, element => element.content)

close browser session after failed assertion with nightwatch

I implement a new testframework for automated tests in node.js with Nightwatch-Cucumber that based on Nightwatch.js. So, sometimes I use node.js Assertions to check some values. I work with the PageObject Pattern in my framework. My problem is that the browser session doen't close after a failed assertion and I don't know why and I don't know how to solve the problem.
Here is my StepDefinition:
const {
client
} = require('nightwatch-cucumber');
const {
defineSupportCode
} = require('cucumber');
const page = client.page.page();
defineSupportCode(({Given, When, Then}) => {
When(/^test$/, () => {
return page.test();
});
});
And that's my PageObject function:
module.exports = {
elements: {},
commands: [{
test() {
//here the assertion failed and the browser session still exist and doen't close
this.assert.equal(false, true);
return this.api;
}
}]
};
So, what can I do to realize it to close the browser and the session for ths test? It happened only if the node.js assertions fail.
Use an after or afterEach hook to always close the browser at the end of a test, regardless of outcome. See http://nightwatchjs.org/guide#using-before-each-and-after-each-hooks
after : function(browser) {
console.log('Closing down...');
browser.end();
},
To close your session after each test you have to add afterEach hook to your test file and use it like this:
afterEach : function(browser, done) {
browser.end(function(){
done();
});
}

Categories

Resources