React & Jest global.confirm not updating between tests - reactjs

I have an existing application that I am trying to write tests for. I have a component function that uses a window.confirm box to get user input (not my code) like this:
if (window.confirm('Are you sure to unassign?')) {
NetworkWebAPIUtils.unassignSeat(this.state.seatnetwork.seat.id, this.state.seatnetwork.network.id, this.props.rank);
}
I am trying to write tests for both paths:
it('should call endpoint when user selects yes', function () {
global.confirm = jest.fn(() => true);
seatUpdateRow.instance().handleChangeAssigned({target: {value: true}});
expect(NetworkWebAPIUtils.unassignSeat.mock.calls.length).toBe(1);
expect(NetworkWebAPIUtils.unassignSeat.mock.calls[0].length).toBe(3);
expect(NetworkWebAPIUtils.unassignSeat.mock.calls[0][0]).toBe(1234);
expect(NetworkWebAPIUtils.unassignSeat.mock.calls[0][1]).toBe(5678);
expect(NetworkWebAPIUtils.unassignSeat.mock.calls[0][2]).toBe(1);
});
it('should not call endpoint when user selects no', function () {
global.confirm = jest.fn(() => false);
seatUpdateRow.instance().handleChangeAssigned({target: {value: true}});
expect(NetworkWebAPIUtils.unassignSeat).not.toHaveBeenCalled();
});
The problem is that global.confirm will not update for the second test. If I set the first test to false then it obviously fails but the second one passes. If I set the first to true then the first passes but the second fails because global.confirm = jest.fn(() => false) doesn't actually cause window.confirm to evaluate to false. If I comment out the first then the second passes just fine.
I have tried mocking window.confirm and I get the exact same behavior.

It was an obvious issue. I forgot to clear the mock calls from NetworkWebAPIUtils.unassignSeat.
afterEach(function () {
NetworkWebAPIUtils.unassignSeat.mockClear();
});

Related

Jest testing a class in window

I'm super lost how to do this.
We've got a class in window for Loqate called window.pca.Addresses
Then in our code we run this snippet of code in a react method:
const shippingControl = new pca.Address(shippingFields, { key: process.env.LOQATE_API_KEY });
window.setTimeout(() => {
shippingControl.load();
}, 3000);
My question is how do I write a jest test to mock the Address class in the window and then also add the load() method so we can test if it has been fired or not.
I've tried to spyOn the window object as both global and window as well as mocking it with jest.mock() which also hasn't worked.
I'm wondering if anyone else can guide me on how to do this?
Many thanks
You can add beforeEach to your test something like that:
beforeEach(() => {
Object.defineProperty(window, "pca", {
value: {
Addresses: { load: jest.fn(() => null) }
},
writable: true
});
});
You can test if it has been fired like this:
expect(window.pca.Addresses.load).toHaveBeenCalledTimes(1);

Reactjs & jest -> How to use global varaiables for tests

I am trying to set a JS variable set by facebook sdk in my test file
beforeall() { global.FB = true; }
I want to change this to false, for one specific test case,Can this be achieved?
I tried setting setting it to false within the test case, and updating the wrapper. but it does not refresh
it('test case', () => {
global.FB = false;
wrapper.update();
});

How can I make my protractor test pass?

I created a simple protractor test for my angular app. When I click a button an input value gets set:
$scope.fillForm=function(){
console.log('fillform');
$scope.myText='hoera';
};
The e2e test expects the input to be populated with 'hoera':
describe('fill in form e2e test', function () {
it('should test form', function () {
browser.get('http://localhost:63342/protractor_new/index.html');
element(by.buttonText('go')).click().then(function () {
var el = element(by.model('myText')).getText();
expect(el).toEqual('hoera');
});
});
});
When I run the test with 'protractor conf' I get:
Expected '' to equal 'hoera'.
I would expect something like : expected 'hoera' to equal 'hoera'? How can I make it pass maybe there is a delay before angular sets the value? Here is a link to the code: https://github.com/dimitri-a/protractor_new
You were close. Your get and click should be added to the controlFlow, so no need to have a then on the click. But you DO need a then on your getText. This should work...
describe('fill in form e2e test', function () {
it('should test form', function () {
browser.get('http://localhost:63342/protractor_new/index.html');
element(by.buttonText('go')).click();
element(by.model('myText')).getText().then(function(el) {
expect(el).toEqual('hoera');
});
});
});

How to increase the mocha timeout per suite in a typescript test

I am trying to increase the timeout for mocha tests as they are web requests that form part of an automated UI test suite and therefore can take longer than the default 2000ms.
The code itself works great if I call mocha with the --timeout set to 5000ms or so but the default 2000ms is not enough.
I want to be able to set the timeout per test suite so that the timeout becomes part of the success criteria which might be different on a case by case basis.
before(()=>{
var sw = require('selenium-webdriver');
this.driver = new sw.Builder().withCapabilities(sw.Capabilities.chrome()).build();
var c = require('chai');
c.use(require('chai-webdriver')(this.driver));
this.expect = c.expect;
return this.driver.getWindowHandle();
})
after(() => {
return this.driver.quit();
})
describe('Looking at github', () => {
beforeEach(() => {
this.driver.get('http://stackoverflow.com/');
})
describe('When we take a look at the stack overflow home page', () => {
return it('It does not have crazy cat text in it!', () => {
return this.expect('#h-top-questions').dom.to.not.contain.text("Just cats here!");
});
});
})
Use function intead of an arrow and then just call this.timeout(5000); e.g.
describe('When we take a look at the stack overflow home page', () => {
return it('It does not have crazy cat text in it!', function() {
this.timeout(5000);
return this.expect('#h-top-questions').dom.to.not.contain.text("Just cats here!");
});
});
This is because ()=> captures the surrounding this. More http://basarat.gitbooks.io/typescript/content/docs/arrow-functions.html
An alternative to basarat's answer, along similar lines that uses different syntax (that is effectively confusing in a different way!):
describe('When we take a look at the stack overflow home page', () => {
it('does not have crazy cat text in it!', () => {
expect('#h-top-questions').dom.to.not.contain.text("Just cats here!");
}).timeout(5000);
});

How to correctly step through tests on different pages in Protractor e2e test?

We want to use protractor to visit a page, run some tests, and then go to another page for more tests. But the later navigation appears to interfere the tests on the previous page.
Here is the structure:
describe('When user is an admin', function () {
browser.get(browser.baseUrl + 'login');
loginAs(roles.admin);
wait();
describe('After log in', function () {
it('should redirect to the home page', function () {
expect(browser.getCurrentUrl()).toBe(browser.baseUrl + 'home');
expect(true).toBeTruthy();
});
it('should contain a "Locations" tab', function () {
var tabLocations = element(by.id('tabLocations'));
expect(tabLocations.isPresent()).toBeTruthy();
});
it('should contain a link to location list', function () {
var linkLocation = element(by.linkText('Manage Locations'));
expect(linkLocation.isPresent()).toBeTruthy();
});
});
});
Pasted above is the tests on the first page.
Then we want to run the tests on another page: (full coded pasted below)
describe('When user is an admin', function () {
browser.get(browser.baseUrl + 'login');
loginAs(roles.admin);
wait();
describe('After log in', function () {
it('should redirect to the home page', function () {
expect(browser.getCurrentUrl()).toBe(browser.baseUrl + 'home');
expect(true).toBeTruthy();
});
it('should contain a "Locations" tab', function () {
var tabLocations = element(by.id('tabLocations'));
expect(tabLocations.isPresent()).toBeTruthy();
});
it('should contain a link to location list', function () {
var linkLocation = element(by.linkText('Manage Locations'));
expect(linkLocation.isPresent()).toBeTruthy();
});
});
describe('at location manage page', function () {
var listPage = new ListPage();
listPage.visit('Manage Locations');
wait();
it('should be at the location list page', function () {
expect(browser.getCurrentUrl()).toBe(browser.baseUrl + 'locations/list');
expect(true).toBeTruthy();
});
});
});
It appears the navigation in my second describe runs before the execution of it statements in the first describe, therefore my tests on the first page failed.
I've tried placing the second describe ("at location manage page") inside the first describe ("After log in"), but still got the same problem.
So my question is, what is the correct way to arrange the tests in protractor, so as the navigation in later tests will be held until the previous tests are completed?
Do not put code inside a describe. Put it inside a beforeAll(function(){}) (jasmine 2) or a beforeEach(function() {})
That should fix your problem.

Resources