How to find the right testId - Testcafe Error E24 - javascript

Creating tests using testcafe, this is pre-existing code written:
When(/^I click on username button$/, async () => {
await get TestCafeController().click(stepsHelper.getElementByTestId('user'));
});
getElementByTestId(dataTestId) returns:
Selector(`[data-testid="${dataTestId}"]`).with({ boundTestRun: getTestCafeController() });
'user' is the wrong test id. I'm pretty new to testing so how would I find the correct data-testid? Here's an image of the error I'm receiving:
TestCafe Error Code: E24
I tried different data-testids and looked through the code I was testing. The app I'm testing has two different modes and I'm trying to find the id of the user button. One mode works with 'user' but the mode I'm writing a test for doesn't work with 'user'.

Related

Cypress error when testing nested iframes in headless mode - race condition

I am testing a web app and the test runs reliably in headed mode (cypress open) but has errors in headless mode (cypress run), so it's likely a race condition that I cannot resolve. The error message is:
[36819:0223/163815.745047:ERROR:system_services.cc(34)] SetApplicationIsDaemon: Error Domain=NSOSStatusErrorDomain Code=-50 "paramErr: error in user parameter list" (-50)
This error is mentioned again when Cypress creates a video of the incident:
- Started processing: Compressing to 32 CRF
2022-02-23 17:00:19.700 Cypress Helper[37571:416134] In -[NSApplication(NSQuietSafeQuit) _updateCanQuitQuietlyAndSafely], _LSSetApplicationInformationItem(NSCanQuitQuietlyAndSafely) returned error -50
- Finished processing: /Users/malte.wirz/Documents/iframes-cypress-issue/cypress/videos/iframe-github.js.mp4 (3 seconds)
I created a demo repository here. To reproduce, clone it, run yarn to install, and yarn cypress:run. The test does pass, but with the error mentioned above.
I assume that the error stems from accessing the nested iframes and I tested 5 different approaches so far, but to no avail. I especially made sure that the function getIframeBody waits until each iframe and the requested element is ready. The error also creates a video, but you can only see the successful run, the error message is not visible there.
Any help on how to debug this further is much appreciated.
describe('Testing Iframe within Iframes', () => {
it('Visits the iframe website and accesses the iframe within the iframe', () => {
const getIframeBody = (iframeSelector, elementSelectorInIframe) => {
return cy
.get(iframeSelector)
.its('0.contentDocument.body', {timeout: 30000})
.should((body) => {
expect(Cypress.$(body).has(elementSelectorInIframe).length).gt(0)
})
.then(cy.wrap)
}
// Visiting the page index.html and getting iframe A
cy.visit('index.html').contains('XHR in iframe')
getIframeBody('iframe[data-cy="bankid"]', 'iframe[src="https://tools.bankid.no/bankid-test/auth"]').as('iframeA')
cy.get('#iframeA').within(() => {
getIframeBody('iframe[src="https://tools.bankid.no/bankid-test/auth"]', 'iframe[src^="https://csfe.bankid.no/CentralServerFEJS"]').as('iframeB')
cy.get('#iframeB').within(() => {
getIframeBody('iframe[src^="https://csfe.bankid.no/CentralServerFEJS"]', 'input[type="tel"]').as('iframeC')
// Now we are in the right place and it finds the correct input element.
// However, normal cypress command .type() fails and we have to use library cypress-real-events,
// which provides an event firing system that works literally like in puppeteer
cy.get('#iframeC').find('input[type="tel"]').should('be.visible').realType('12345678912')
// But for the button below, this library now doesn't help anymore:
// "Failed to execute 'getComputedStyle' on 'Window': parameter 1 is not of type 'Element'."
// This was solved by using {scrollBehavior:false}.
cy.get('#iframeC').find('button[type="submit"]').should('be.visible').first().realClick({scrollBehavior:false})
})
})
})
})
I got some feedback that the above "ERROR:system_services.cc(34)" is not critical and does not cause flaky or unsuccessful tests, therefore there are no action points.

Cypress Iframe Handling - Failure to interact with Button

I am trying to E2E test an auth flow with Cypress that includes a third party method called BankID. BankId is integrated through three nested iframes that I can successfully access. However, when I type into the input field via cy.type('12345678912'), BankId does not register this as trusted events and never unlocks the submit button with the arrow.
According to this issue here, Cypress does not intend to support native browser events and suggests to use the package cypress-real-events. When using this via cy.realType('12345678912'), it actually succeeds in unlocking the submit button. However i can never successfully click the submit button, neither with .click() or even the package method .realClick().
The error is: "Failed to execute 'getComputedStyle' on 'Window': parameter 1 is not of type 'Element'."
I uploaded a sample repository with an minimal testing version here.
Any feedback or hints would be greatly appreciated :)
Here is the relevant code:
/// <reference types="cypress" />
import { skipOn } from '#cypress/skip-test'
describe('Recipe: blogs__iframes', () => {
skipOn('firefox', () => {
it('do it more generically', () => {
const getIframeBody = (identifier) => {
return cy
.get(identifier)
.its('0.contentDocument.body')
.should('not.be.empty')
.then(cy.wrap)
}
// Visiting the page index.html and getting iframe A
cy.visit('index.html').contains('XHR in iframe')
getIframeBody('iframe[data-cy="bankid"]').as('iframeA')
cy.get('#iframeA').within(() => {
getIframeBody('iframe[src="https://tools.bankid.no/bankid-test/auth"]').as('iframeB')
cy.get('#iframeB').within(() => {
getIframeBody('iframe[src^="https://csfe.bankid.no/CentralServerFEJS"]').as('iframeC')
// Now we are in the right place and it finds the correct input element.
// However, normal cypress command .type() fails and we have to use library cypress-real-events,
// which provides an event firing system that works literally like in puppeteer
cy.get('#iframeC').find('input[type="tel"]').should('be.visible').realType('12345678912')
// But for the button below, this library now doesn't help anymore:
// "Failed to execute 'getComputedStyle' on 'Window': parameter 1 is not of type 'Element'."
cy.get('#iframeC').find('button[type="submit"]').should('be.visible').first().realClick()
})
})
})
})
})
I also posted this problem on https://github.com/dmtrKovalenko/cypress-real-events/issues/226 and got an answer there:
Using .realClick({ scrollBehavior: false }); solved the issue.
The problem is if the webapp is not scrolling as expected, therefore leading to Cypress not finding the element. In my case, i made the iframe wider to avoid needing to scroll and the issue was still there, but the workaround solved it anyway.

Firestore SDK cannot mock DocumentSnapshot

So I am trying to create a unit test for a firestore trigger, triggered by an onCreate event. The firebase documentation said to do this as so: Firebase Unit Testing Background Functions
I copy the documentation pretty closely:
const snapshot = test.firestore.makeDocumentSnapshot(
{owner: 'testUserA', text: 'response from test user a'},
'users/testUserA/questions/testQuestion/responses/testResponse'
);
This line gives the error:
UnhandledPromiseRejectionWarning: SyntaxError: Unexpected token u in JSON at position 0
At first I thought it might have to do with the refPath because it starts with u, but after changing it, the error is identical, so I assume it has to do with the first parameter, which seems like correct json, but apparently not. I'm kind of stumped.
Any ideas? Thanks!
Do you have test.cleanup() in any other testing cases before you use test.firestore.makeDocumentSnapshot()? If any, remove them and run the test again

How to create new instance of contract for whole test suite truffle

I am setting up an ERC20 token ICO on the ethereum network using Solidity and Truffle.
Can anyone tell me why this is not working, I have 4 test files (as I would ideally like to keep them as short and concise as possible), one for testing the token, one for testing the set-up of the crowdsale, one for testing a successful run through (where the cap is reached) and one for testing the emergency stop functionality.
For this reason, I would like to run through multiple it() test cases which use the preceding values to test their own thing in each file i.e.
In the set-up test file:
First it() tests if the contract is deployed
Second it() tests if the contracts variables are set correctly etc.
I have then attempted to create a new instance of the token and contract on each file so that I can run through various test cases.
Each file starts with:
Token.new(initialAmount, tokenName, decimalUnits,tokenSymbol, {from: account_one});
Sale.new(softCap, hardCap, etherCostOfEachToken, account_one, token, durationInMinutes, {from: account_one});
However, when running through my tests I get the error:
AssertionError: State of contract was not 'Waiting approval': expected '4' to equal 1
at /Users/jackpickering/Desktop/Development/Capped_ICO/test/4Crowdsale_EmergencyStop_Test.js:28:14
at <anonymous>
at process._tickDomainCallback (internal/process/next_tick.js:228:7)
The status has not been reset back to 1 after finishing the Successful crowdsale test file had ran and therefore, the Sale.new() line must not work.
Is there a better way to do this? Am I missing anything?
Thanks in advance.
The reason I was getting this error was because I was not waiting until the contract had been deployed to the network, instead I changed these to be performed within an asynchronous function and used the 'await' function to wait until the contract had been deployed before carrying on with the rest of the tests.
My working code is as follows:
it("should create new token", async function() {
token = await Token.new(initialAmount, tokenName, decimalUnits,tokenSymbol)
supply = await token.totalSupply();
assert.equal(supply, 10000000, "New crowdsale was not created");
});
it("should create new crowdsale", async function() {
sale = await Sale.new(softCap, hardCap, etherCostOfEachToken, account_one, Token(token), durationInMinutes);
state = await sale.getState();
assert.equal(state, 1, "New crowdsale was not created");
});

How to debug this Testcafe case?

I've written 12 tests in total so far for this project and there is one error that is occurring in different places depending on the tests composition.
My question is about how to debug this issue.
I'll share the error and the test sample in hope that someone else had a similar problem and has an idea on how to approach it.
The Uncaught TypeError: Cannot read property 'type' of undefined is the error in question, and there is no reference to the where it occurred.
From the tests perspective, the next action was supposed to be clicking a button and getting a popup for creating a new product.
The application works correctly and without problems, it's just the e2e tests that report the problem.
The reported test in question works in isolation.
Excluding this test, the error manifests on another test.
At the end of this post, you'll be able to see the error thrown when this test is skipped.
fixture('Select a product from the list:')
.page('http://localhost:3000/products');
// #TODO Fix e2e test
test
.before(generateProducts(page, 1))
('clicking the "Close detail" button should return us to the products page.', async t => {
const productsListItem = await page.listContainer.child(0);
await t
.click(productsListItem)
.click(page.closeDetail)
.expect(page.productsPageTitle.innerText).eql('PRODUCTS')
})
.after(removeGeneratedProducts(detailedProductPage, 1));
test
.before(generateProducts(page, 2))
('selecting another product, while the previous is still opened, should refresh the preview with the new selection.', async(t) => {
const productListItems = await page.listContainer.find('li');
const productsListItem0 = await productListItems.nth(0);
const productsListItem0Title = await productsListItem0.find('[data-test-id="name"]').innerText;
const productsListItem1 = await productListItems.nth(1);
const productsListItem1Title = await productsListItem1.find('[data-test-id="name"]').innerText;
await t
.click(productsListItem0)
.expect(page.productTitle.textContent).eql(productsListItem0Title || 'Missing product\'s name')
.click(productsListItem1)
.expect(page.productTitle.textContent).eql(productsListItem1Title || 'Missing product\'s name')
})
.after(removeGeneratedProducts(detailedProductPage, 2));
fixture('Field state updating when switching between products with an open Quick Edit view')
.page('http://localhost:3000/products');
test
.before(async t => {
await t
.click(page.showAddProductFormButton)
.typeText(page.nameField, `${chance.name()} ${Math.floor(Math.random() * 100000) + 1}`)
.click(page.createNewProductButton)
.click(page.showAddProductFormButton)
.click(page.createNewProductButton);
})
('Products quick edit navigation should update the view, and not inherit the values of the previous product', async(t) => {
const productListItems = await page.listContainer.find('li');
const productsListItem0 = await productListItems.nth(0);
const productsListItem1 = await productListItems.nth(1);
await t
.click(productsListItem0)
.expect(page.productTitle.textContent).eql('Missing product\'s name')
.click(productsListItem1)
.click(productsListItem0)
.click(productsListItem1)
.click(productsListItem0)
.expect(page.productTitle.textContent).eql('Missing product\'s name')
.click(productsListItem0)
})
.after(removeGeneratedProducts(detailedProductPage, 2));
Don't expect results when running the code. I've used this feature to nicely import the code, nothing more.
The same error on a different test when the original test is skipped.
In the current product version (0.23.0), we've introduced the Stop Test Run After the First Test Fail option. You can now configure TestCafe to stop the entire test run after the first test failure. This saves your time when you fix problems with your tests one by one.
Using the mentioned --debug-on-fail option, you can specify whether to automatically enter the debug mode when a test fails. If this option is enabled, TestCafe pauses the test when it fails. This allows you to view the tested page and determine the cause of the failure.
In addition, you can use the --debug-mode option. In this mode, test execution is paused before the first action or assertion allowing you to invoke the developer tools and debug.
See also: TestCafe Debugging

Categories

Resources