Cypress wait for table to load - vue.js

I'm trying to test and click the table row that appears after I type text in the input component.
The table loads after delay (after getting response from external API). What woroked is using timeout that waits until certain element is loaded:
cy.get('[data-cy=searchBar]').type("Name")
cy.get('[data-cy=dataTable]').get('tbody').contains("td", "Result of name search", {timeout: 15000}).click()
So cypress waits until there is such row with given value, but the value my change and wont always be the same so is there a way to do exatcly same thing as above but selecting second row after table loads? (by default there are no items in the table)
I tried using this:
cy.get('[data-cy=searchBar]').type("Name")
cy.get('[data-cy=dataTable]').get('tbody').get("tr").eq(2, {timeout: 15000}).click()
But it seems cypress loads the table after checking for the second tr which fails the test.

See Cypress - how to wait for second of two elements to appear, you can add a should() to check the row length
cy.get('[data-cy=dataTable]')
.find('tbody tr') // ignore thead rows
.should('have.length', 3) // retries above cy.find() until true
.eq(2)
.click()
I'm not sure if you want to click the row (tr) or the cell (td). Looking at your first example (the one that works), it's the cell you want to click.
So you can add a cell selector
cy.get('[data-cy=dataTable]')
.find('tbody tr') // ignore thead rows
.should('have.length', 3) // retries above cy.find() until true
.eq(2) // take 3rd row
.find('td').eq(5) // take 6th cell
.click()

Cypress requires parameter values to be in quotation marks also if you know exactly the text you will find I suggest the following approach that is working for me:
cy.get('[data-cy="searchBar"]').type("Name")
cy.contains('[data-cy="dataTable"] td', "Result of name search")
.should('be.visible')
.click()

One way to make sure that cypress waits till the timeout, is to add the nth location of tr inside cy.get(), something like:
cy.get('[data-cy=dataTable] > tbody > tr:nth-child(3)', {timeout: 15000}).click()

Related

Check if an input field is empty or not is not working properly in Cypress tests

I got 2 step definitions in Cypress that check if an input field is empty or not (depends on how I build the sentence I setup with RegEx).
First my problem was, that cypress said the test failed because the input field is empty while it was not.
My defined steps:
/** We check if the input field with the given name is empty */
Given(/^The input field "(.*)" is (not )?empty$/, (inputFieldName, negation) => {
if (negation === 'not ') {
CypressTools.getByName(inputFieldName).should('not.be.empty');
} else {
CypressTools.getByName(inputFieldName).should('be.empty');
}
});
/** We check if the input field with the given name is visible and empty */
Given(/^The input field "(.*)" is visible and empty$/, (inputFieldName) => {
CypressTools.getByName(inputFieldName).should('be.visible').should('be.empty');
});
In my specific test cypress should check a value filled input field and the step is defined like that:
The input field "XYZ" is not empty
I can see, that the if-condition is working fine, so no problems on the definition or RegEx site.
But the test fails because Cypress say the input field is empty but it's not.
I suspect, that Cypress test the input fields for values between the input tags, but doesn't check for a value attribute in the input tag.
At least, I tried to add an invoke('val') in the step definition:
CypressTools.getByName(inputFieldName).invoke('val').should('not.be.empty');
and it works for the first step definition, but when I do that for the 2nd one aswell, cypress tests fail and tell me this:
Timed out retrying: You attempted to make a chai-jQuery assertion on an object that is neither a DOM object or a jQuery object.
The chai-jQuery assertion you used was:
> visible
The invalid subject you asserted on was:
>
To use chai-jQuery assertions your subject must be valid.
This can sometimes happen if a previous assertion changed the subject.
I don't understand the problem here. Is this method valid with invoke() or is there a better solution to cover all cases?
Thanks a lot for your help.
The problem your error message is pointing to is that the subject being passed along the command chain in not appropriate for the next step,
CypressTools.getByName(inputFieldName)
.invoke('val') // changes subject to the text of the input
// (not a DOM element)
.should('be.visible') // needs a DOM element
.should('not.be.empty');
The surest way around it is to break the testing into two steps
CypressTools.getByName(inputFieldName).should('be.visible');
CypressTools.getByName(inputFieldName)
.invoke('val')
.should('not.be.empty');
but I think a simple reordering will also work
CypressTools.getByName(inputFieldName)
.should('be.visible') // check the DOM element, passes it on as subject
.invoke('val') // changes subject to the text of the input
.should('not.be.empty'); // check the text is not empty

How to wait untill drop down values load in if else condition in robot framework

My scenarios are: I have two drop down values side by side if the first drop down-selected based on the value selected second drop-down values will be loaded from that we need to pick one value. in one case from the first drop down if I select unknown or any legal purpose I should not go for the second dropdown. this is what the requirement I have please help me out. Below is the code I have written
Variables
${var1}= Unknown
${var2}= Any legal purpose
The user selects random NAICS code and subcode from the drop-down
${selectedNAICScode}= User selects NAICS code from the drop down
${NAICS_code} run keyword if
${selectedNAICScode}!=${var1} or ${selectedNAICScode}!=${var2} run keywords
... element should be visible xpath://select[#id="ddlNAICSSubCode"]
# ... is visible ${NAICS_subcode}
... User selects NAICS-sub code from the drop down
... ELSE run keywords
... element should not be visible xpath://select[#id='ddlNAICSSubCode']
Even though we are giving one argument when I run the script it is saying expecting 1 to 2 arguments but got 0. my question is how we can wait until the drop-down values load into the drop-down in else condition.
You can use the following functionality:
WebDriverWait wait = new WebDriverWait(driver, INSERT_INTEGER_WAITING_TIME);
boolean waitUntil = wait.until(ExpectedConditions.invisibilityOfElementLocated(By.xpath("ENTER_YOUR_XPATH_OR_OTHER_ATTRIBUTE")));
In this way, your action will happen only when the element is going to be visible.
If you need further information check this link

For loop on test case titles in robot frame work

On one page there are various item. I am able to iterate over all items/elements on the page.
Though would like to keep every iteration is a separate test cases.
As in below Test case title First Page Item No expand
Is there any way to put test case name in for loop.
For example First Page and Item No both can be variable and controlled by for loop.
*** Test Cases ***
First Page Item No expand
: FOR ${INDEX} IN RANGE 1 80
\ Click Element xpath=/html/body/div[1]/div[2]/section/div/div[2]/div[2]/div[${INDEX}]/div[1]/div/p[2]
From my understanding this should not be possible. However there are two ways to get around:
Treat is as one test case, have a keyword that does the FOR loop
Have 80 test cases calling one keyword with an ${index} attribute

How to force the parse (only one time ) of a Dojo's button [Err: widget is already registered]

I have a function which adds a button to a div "dettaglio_utenti". After calling the function with this instruction
tab+="<button data-dojo-type='dojox.mobile.Button' id='apri_mappa' onClick=\" location.href='tel:"+telefono+"'\">apri mappa</button>"
var vText = document.getElementById("dettaglio_utente");
vText.innerHTML = tab;
require(["dojo/parser"], function(parser){
parser.parse(vText);
});
It works only the first time that I display the page. The second time the button is not parsed and I see this error in the browser console: dojo/parser::parse() error Error: Tried to register widget with id==apri_mappa but that id is already registered
When you display the page for the second time, the first page must still be part of the dom. (Maybe this is a worklight feature, single page app?). So when dojo parses the second page it gives the error because the button with that id has already been created.
I don't believe preventing the parsing of the button a second time will accomplish what you need. I think your options are:
Destroy the widgets from the first page.
If you don't need an id on the button, you can omit it and Dojo will create an id that won't collide.
If you need the id, you can or use a counter when emitting the id of the button.
id='apri_mappa_' + i where i is the counter.
Only knowing what you wrote above, I think the order of preference is 2,1,3.
EDIT - How to destroy a widget
require(['dijit/registry'], function(registry) {
registry.byId('apri_mappa').destroy();
});

Selenium WebDriver access a sub element

I have a div with a unique ID. Under that div are a bunch of span elements that have className=foo. There are several span elements with className=foo but they are unique to each div (if that's clear). So my Selenium code first gets the unique div as a web element then tries to take that element and get by class name the span like so
element = sDriver.findElement(By.id("c_"+cID));
String sTest = element.findElement(By.className("actions")).getText();
On the second line it throws an exception every time
org.openqa.selenium.StaleElementReferenceException: Element not found in the cache - perhaps the page has changed since it was looked up
Command duration or timeout: 22 milliseconds
Do I misunderstand how to get that span from under a unique div?
Nope you'right accessing the span but the problem is that the Dom has changed since StaleReferenceException is about (see StaleReferenceException )
This may be caused because the page isn't loaded completely when the code starts or changes when the code is executed. You can either try to wait a little longer for the element or catch the StaleReferenceException and try again finding the div and the span.
My solution is not fancy but it works like a Swiss watch (in my situation of course). So my code is calling the parent element in a loop looking for different child elements in it. Nothing got changed at all - just simple querying and the exception began to occur. So! I've added the Thread.Sleep(2000) command before every search of parent element and it solver the problem. Not elegant but works every time with minimum code to debug afterwards.