I'm working with my jasmine test suite, and I'm getting a weird error that causes the test to fail. The code works, and I've verified by debugging the tests that the values I expect are the values present, but the test fails. I get this as output:
Failed
at stack (/Users/username/code/source/client/node_modules/jasmine-core/lib/jasmine-core/jasmine.js:2200:17)
at buildExpectationResult (/Users/username/code/source/client/node_modules/jasmine-core/lib/jasmine-core/jasmine.js:2170:14)
at Spec.expectationResultFactory (/Users/username/code/source/client/node_modules/jasmine-core/lib/jasmine-core/jasmine.js:777:18)
at Spec.addExpectationResult (/Users/username/code/source/client/node_modules/jasmine-core/lib/jasmine-core/jasmine.js:450:34)
at Env.fail (/Users/username/code/source/client/node_modules/jasmine-core/lib/jasmine-core/jasmine.js:1192:25)
at next.fail (/Users/username/code/source/client/node_modules/jasmine-core/lib/jasmine-core/jasmine.js:4046:19)
This is what my tests look like
describe('the returned type', () => {
afterEach(store.clearActions);
beforeEach(done => {
mock.onPatch(url).replyOnce(200, { updated_at: moment().toISOString() });
save(4, value)(store.dispatch, store.getState)
.then(() => setTimeout(done, 750));
});
it('should have correct type', () => {
const action = store.getActions()[0];
expect(action.type).toEqual(LAST_SAVED_UPDATE);
});
});
Related
It works fine for the same click event if I've coded within the single 'it' block as below.
Working code:
describe('Test Suite', () => {
it('Test case 1', () => {
//Test 1
//Test 2
})
})
Not working:
describe('Test Suite', () => {
it('Test case 1', () => {
//Test 1
})
it('Test case 2', () => {
//Test 2
})
})
Below is my code snippet, First 'it' block works fine after login method executes. Then second it blocks just clicking the right element but the page never loads.
P.S. If I written the code under the single 'it' block, Page loads and works fine.
describe('Fund Manager Suite', () => {
//Checking Fund Manager page loading
before(() => {
cy.visit('xxxxxxxxxxxxx')
cy.login('xxxxx', 'xxxxx')
})
it('fund manager navigation works', () => {
cy.location('pathname').should('equal', '/xxxxx')
cy.get('#appSwitcher').click()
cy.get('#appSwitcher > .dropdown > .dropdown-menu > :nth-child(2) > a').click()
cy.location('pathname').should('equal', '/xxxxx')
cy.get('.k-grid-table').find('tr').should('have.length', 5)
})
it('fund detail works', () => {
cy.get('.product > :nth-child(2)').click()
cy.location('pathname').should('equal', '/xxxxx')
// Fund Detail - Search
cy.get('#s2id_autogen31').type('Rach')
cy.get('#select2-result-label-32').click()
cy.get('#searchSubmit').click()
cy.get('#DataTables_Table_0').find('tr').should('have.length', 10)
})
})
Execution Screen shot
Code snippet screen shot
You have to preserve your cookies in beforeEach() to make sure that you stay logged in, in all it() blocks. You can read more in cypress docs.
describe('Dashboard', () => {
before(() => {
// log in only once before any of the tests run.
// your app will likely set some sort of session cookie.
// you'll need to know the name of the cookie(s), which you can find
// in your Resources -> Cookies panel in the Chrome Dev Tools.
cy.login()
})
beforeEach(() => {
// before each test, we can automatically preserve the
// 'session_id' and 'remember_token' cookies. this means they
// will not be cleared before the NEXT test starts.
//
// the name of your cookies will likely be different
// this is an example
Cypress.Cookies.preserveOnce('session_id', 'remember_token')
})
it('displays stats', () => {
// ...
})
it('can do something', () => {
// ...
})
it('opens a modal', () => {
// ...
})
})
I Have seen this kind of behavior, when the first it case start and doesn`t finish some xhr request in the site - and in result cypress continues the process during the start of the second it case. The best solution for clean slate for each case I had found is to separate every case in different file
Update:
Able to resolve this issue by storing the session_id.
Cypress.Cookies.defaults({
preserve: "session_id"
})
Getting started with Cypress, I'm noticing my test fails about passing:
describe('Sessions Page', () => {
it('Loads', () => {
// Set up alias
cy.server()
.route('POST', '/graphql')
.as('graphql');
// Visit site
cy.visit('/', { timeout: 30000 })
.wait('#graphql')
.its('Status')
.should('be', 200);
});
});
When I run this, it passes, then after a few seconds it fails.
I see this output:
Another thing I found strange is that the test says Passed immediately but it's still waiting for the route to resolve:
Disclaimer; I'm a bit new to react-testing-library (been using an admittedly older version of Enzyme) and the Apollo Query/MockedProvider components (been using the client via a JS service object), so this may be a stupid question...
I have a component that receives a list of countries for which I am trying to write tests. What I would like to do is something like:
import React from 'react';
import { MockedProvider } from '#apollo/react-testing';
import { render, act } from '#testing-library/react';
import wait from 'waait';
import Countries, { countryQuery } from './Countries';
import { isTerminating } from 'apollo-link/lib/linkUtils';
const mockCountryName = 'sample country';
const mocks = [
{
request: {
query: countryQuery,
vairables: {},
},
result: {
data: {
countries: [{ name: mockCountryName }],
},
},
},
];
describe('when working with the countries component', () => {
describe('and the component is loading', () => {
let component;
beforeAll(async (done) => {
await act(async () => {
component = render(
<MockedProvider mocks={[]}>
<Countries />
</MockedProvider>
);
});
done();
});
it('should have a title', () => {
expect(component.getByText('Countries Component')).not.toBeUndefined();
});
it('should have a loading status', () => {
expect(component.getByText('Loading...')).not.toBeUndefined();
});
});
});
When this runs, the second test (about loading status) fails as it looks like the component is only a body tag at that point. I tried changing beforeAll to beforeEach, but that just produced a component that had an Error indicator. I put some console.log statements in my component, and this is what they are showing me:
console.log src/components/Countries.js:45
Loading is: true
console.log src/components/Countries.js:46
Error is: undefined
console.log src/components/Countries.js:45
Loading is: false
console.log src/components/Countries.js:46
Error is: Error: Network error: No more mocked responses for the query: {
countries {
name
phone
__typename
}
}
, variables: {}
I'm wondering if it does not like the empty array passed in as the mocks property for the MockedProvider. But every example I've seen does it that way, so...
As an experiment, I added a second set of test to the spec file to see if it was just a weird timing issue with the component that was causing the issue. Here's the second test:
describe('and the component has data', () => {
let component;
beforeAll(async (done) => {
await act(async () => {
component = render(
<MockedProvider mocks={mocks} addTypename={false}>
<Countries />
</MockedProvider>
);
await wait(0);
});
done();
});
it('should have a title', () => {
expect(component.getByText('Countries Component')).not.toBeUndefined();
});
it('should have a loading status', () => {
expect(component.getByText(mockCountryName)).not.toBeUndefined();
});
});
This has the same problem; the first test works (if I reorder the test, the one that first always works) but the second one fails, and the component seems to be an empty body tag.
Is there a way to make this type of test structure work? I don't like the idea of having to put everything into a single test, let alone the setup code for the component.
Thanks!
I'm not sure if it's the best approach, but I think I found a workaround.
First, the empty array/loading issue was not an issue; I traced everything back to testing-library resetting/re-rendering the component between tests.
Here's what I did:
describe('and the component is loading', () => {
let component, pageTitle, loadingMessage;
beforeAll(async (done) => {
await act(async () => {
component = render(
<MockedProvider mocks={[]}>
<Countries />
</MockedProvider>
);
pageTitle = component.getByText(mockPageTitle);
loadingMessage = component.getByText(mockLoadingMessage);
});
done();
});
it('should have a title', () => {
expect(pageTitle).not.toBeUndefined();
});
it('should have a loading status', () => {
expect(loadingMessage).not.toBeUndefined();
});
});
Instead of trying to call component.getTextBy in each test, I moved them into the beforeAll, and assigned the output to variables. Each test uses the variables for their tests. I also wrote a test for my Routes component, and I was still able to call fireEvent.click() on the components.
I would be very interested in any feedback from anyone who has a more experience with testing-library on this. It seems better than what I had, but I want to make sure it's really the best approach.
Thanks.
I build simple e2e test with Nightwatch. This simple e2e test is passed successfully.
Next, I build second test to use Chai.js / Mocha.js. But this test raises exception.
// First(successfully passed)
module.exports = {
'increment counter': browser => {
browser
.url(process.env.VUE_DEV_SERVER_URL)
.click("button#plus-btn")
.assert.containsText('h1', '1')
.end()
},
"decrement counter": browser => {
browser
.url(process.env.VUE_DEV_SERVER_URL)
.click("button#minus-btn")
.assert.containsText('h1', '-1')
.end()
}
}
// Second
describe('counter testing', () => {
describe('press plus button', () => {
it('increments counter', (browser) => {
browser
.url(process.env.VUE_DEV_SERVER_URL)
.click("button#plus-btn")
.expect.element('h1').text.to.equal('1')
.end()
})
})
describe('press minus button', () => {
it('decrements counter', (browser) => {
browser
.url(process.env.VUE_DEV_SERVER_URL)
.click("button#minus-btn")
.expect.element('h1').text.to.equal('-1')
.end()
})
})
})
Exception message
TypeError: browser.url(...).click(...).expect.element(...).text.to.equal(...).end is not a function
What should I do next?
As per the docs, you should call end in a different way when using expect for assertions. I think it's because the expect way is based on chai. Changing your tests to look like this will work
it("increments counter", browser => {
browser
.url(process.env.VUE_DEV_SERVER_URL)
.click("button#plus-btn")
.expect.element("h1")
.text.to.equal("1");
// See how end is called differently
browser.end();
});
I am stuck on a part of my test code with mocha, where the test is included in the callback of getUserMedia:
it("should work without error", function() {
navigator.getUserMedia({fake:true}, function(stream) {
expect(3).to.equal(3);
done(); // done is not defined if expect() is valid
},console.error);
});
Here, done() is not defined, but the test is successful.
it("should NOT work", function() {
navigator.getUserMedia({fake:true},function(stream) {
expect(3).to.equal(4);
done();
},console.error);
});
Here, I am getting an error:
AssertionError: expected 3 to equal 4
, but the mocha interface still shows the test as validated. (green tick)
Am i doing something wrong, or is done() is bugged?
Your function should get a done argument.
it("should get done", function(done) {
expect(3).to.equal(3);
expect(3).not.to.equal(4);
});
However you should use done only if you have async function at the test
if not the test should be like this:
it("should not be async", function() {
expect(3).to.equal(3);
}