element can't seem to be located in webdriverio script - webdriver-io

Currently trying to test out the responsiveness on webdriverio. I adjust the viewport of my screen and then try to search for a table that exists at the bottom of the page (need to scroll to get into view port). For some reason, it can't locate the element and the test case fails.
it('should resize the table when screen width is mobile', () => {
let mobileTable = $('.overview-table.mobile-table');
browser.setViewportSize({
width: 767,
height: 500
});
//browser.pause(1500);
mobileTable.waitForExist(10000);
console.log(mobileTable);
mobileTable.scroll();
browser.debug();
});
I'm not sure if I'm getting the element right in the above code. I set mobileTable = $('.overview-table.mobile-table') because it is a table element with those classes
<table class="overview-table mobile-table"> ... </table>
I get the following error:
An element could not be located on the page using the given search parameters (".overview-table.mobile-table").
running firefox
Error: An element could not be located on the page using the given search parameters (".overview-table.mobile-table").
at scroll() - index.js:312:3

The problem most likely is in your selector.
You can verify if your selector is correct by testing it into your browser javascript console.
In chrome it goes like this:
Right click the page
Inspect
Select the "console" tab within the dev tool panel
Then simply type $$('.overview-table.mobile-table')
If that's an empty array, then you know the selector is wrong.

Related

What can i use to interact with the search bar on this website using cypress

I am trying to complete a test case that involved opening propertypal.com, entering some values and validating the responses using the software cypress. I've never used cypress before but the company asking me to do this test want me to utilise it.
This is the website i'm testing https://www.propertypal.com/
I want to type bt6 into that text box, but I cant work out the correct locator to use. Everything I try either returns multiple elements or doesn't find anything.
Below are some of the things I tried with no success. The main things I have been honing in on are the placeholder text, the ID and element name.
I'm very new to this type of automation so any help would be amazing.
cy.get('query').type('bt6')
cy.get('input:first').should('have.attr', 'placeholder', 'Search Area, Address, Agent').click()
cy.get('search-form-textbox').type('bt6')
With this element
<input id="query"
type="text"
name="q"
class="search-form-textbox"
autocorrect="off"
spellcheck="false"
value=""
placeholder="Search Area, Address, Agent">
Using the id="query" should be best,
cy.get('input#query') // should only be one id "query" on the page
.type('bt6');
If there's multiple id's "query" and you want to flag it,
cy.get('input#query')
.then($els => {
expect($els.length).to.eq(1) // assert there's only one id found, otherwise fail
})
.type('bt6');
If there's multiple id's "query" and you don't really care, you can select the third which is the visible one.
cy.get('input#query')
.eq(2) // take the third, which is at center of the page
.type('bt6');
Taking the "nth" element found is always a bit fragile, but placeholder text is pretty good instead (provided the page isn't multi-lingual)
cy.get('input[placeholder="Search Area, Address, Agent"]') // easier with attribute in selector
.eq(1) // take the second, as the are two of these
.type('bt6');
Class is not so good, as can often be applied to multiple elements, but in this case it's pretty good because it's specific to the role,
cy.get('input.search-form-textbox') // prefix class with "."
.eq(2) // take the third, which is at center of the page
.type('bt6')
Web pages can often have multiple elements with the same selector, for example cy.get('input#query') has three elements with this id.
What happens is the developer creates a component, adds an id like <input id="query"> then adds the component in several places, so the page actually ends up with multiple ids of the same name.
When the page is complex with hidden sections, to find the element you want start by testing with a console.log
cy.get('input#query') // finds 3 elements
.then(console.log) // log them to dev tools
Open dev tools, click open the object printed and you can see the list of elements selected.
Now you can hover each element, and the corresponding element on the page is highlighted.
In this case the first two are hidden behind menu items, but the third is the one we need.
So now we can add an .eq(2) to select the third element
cy.get('input#query') // finds 3 elements
.eq(2) // take the third element
.type('bt6');
So when I ran the cypress Test for your website, I got an uncaught exception that is originating from your Application. This is something that should be analyzed and is possibly fixed.
If this is something that is not going to be fixed, then you can add the below in your test, so that cypress ignores the exception and doesn't throw an error.
Cypress.on('uncaught:exception', (err, runnable) => {
return false
})
Now I tried using the locator id(#query) to input the test, as it is always good to use id because it's unique, but unfortunately, it gave me an error as the element is not visible. Unfortunately adding {force: true} also didn't help me solve the issue.
cy.get('#query').type('bt6')
1.So, the locator that worked for me was .search-ctrl. So your Final Test will look like this:
cy.visit('https://www.propertypal.com/')
Cypress.on('uncaught:exception', (err, runnable) => {
return false
})
cy.get('.search-ctrl').type('bt6')
2.Now, if you want to globally handle the exception, then go to cypress/support/index.js and then write there:
Cypress.on('uncaught:exception', (err, runnable) => {
return false
})
And then in this case your test will just have:
cy.visit('https://www.propertypal.com/')
cy.get('.search-ctrl').type('bt6')

Im unable to switch values in a dropdown in cypress. The dropdown is not select type

In my scenario i need to switch to the values available in the dropdown and verify the results based on the selection.I have 'In-Network' and 'Out-of-Network' values in the dropdown. By default one value will be shown and another one is hidden. This dropdown is not a select type. So when i try,
cy.get('#react-select-dropdown-value-value').select('Out-of-Network'); - Script fails and the error says, the element is not select type.
Then tried,
cy.get('#react-select-dropdown-value-value').eq(0).click(); -
it clicks the dropdown, and doesnt click on the value intended. i have tried click({multiple: true}). but didnt work. force:true, is not clicking either.
cy.get('#react-select-dropdown-value-value').contains(Out-of-Network').click(); - did not work, says the element is not found
cy.get('#dropdown-value')
.should('be.visible')
.eq(0)
.contains('Out-of-Network')
.click();
CypressError: Timed out retrying: expected '' to be 'visible'
This element '' is not visible because its content is being clipped by one of its parent elements, which has a CSS property of overflow: 'hidden', 'scroll' or 'auto'
The react-select-dropdown is a bit special indeed. What we do to select a value from a react-select-dropdown is the following:
cy.get('[id*="start-shift-floats"]').click()
cy.get('[id^="react-select-"]')
.contains('Out-of-Network')
.click()
What you should know about this:
cy.get('[id*="start-shift-floats"]') is the actual get() to open up the dropdown. So it will be named different in your application.
cy.get('[id^="react-select-"]') is the usual get() for the options in a react-select-dropdown. By checking it which contains 'Out-of-Network', we can let Cypress click that specific option.

PageSource() gets different code than appium inspector code

I am having a really hard time understanding the following problem, i have an app, i use appium inspector to see the elements, but when i use the elements, i get that the element is not found, therefore i printed the code using the driver.getPageSource() method, and i realized that the xml code that is created while running the app, is actually different to what appium inspector sees, what is the problem and how can it be solved? i could ask to the developers to fix it once i know the root cause, thanks in advance.
This is an example of a difference
Under < XCUIElementTypeOther name = Picture, Left Rear Corner> there are 4 more elements 2 StaticText, 2 Buttons (appium inspector) and on the the same element but in the java console, there are only 2 tags, so i do not see the 2 static text and the 2 buttons (which is what i want to click)
As you can see the code in the console is different to what i see in appium iinspector. this is for IOS app.
while (driver.findElementsById("Additional Videos").size() == 0) {
swipeScreenDown();
}
driver.getPageSource();
WebElement additionalVideos = driver.findElementByXPath("//XCUIElementTypeOther[#name=\"Picture, Left Front Corner\"]");
driver.getPageSource();
List<WebElement> idf = additionalVideos.findElements(By.className("XCUIElementTypeButton"));
driver.getPageSource();
System.out.println(idf.size());
driver.getPageSource();
idf.get(0).click();
driver.getPageSource();
Error got:
java.lang.IndexOutOfBoundsException: Index: 0, Size: 0
PageSource() action can print the visual elements at the screen.
As per my understanding, You are currently performing PageSource() action when loading the screen.
You need to click at the selected element
After click on this element use PageSource() action.
You get that element in the log of the PageSource().

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();
});

HTML code - how to find out absolute position on the page?

Is there any browser engine or plugin which would give user information about position of given HTML element ? I want to know where is element located e.g. left corner or center of the page.
It should not be a huge problem as Firefox and Chrome marks you elements within page as you go through html code in Developer Tools > "Element tab".
Example of highlighted element : http://imgur.com/mUHd51q we see that selected element is currently in the centre of the screen - how to get this information programatically ?
Selenium-webdriver can give you information about any DOM element you want:
d = Selenium::WebDriver.for :chrome
d.get "http://www.google.com"
elem = d.find_element(:name, "btnI")
elem.location
=> #<struct Selenium::WebDriver::Point x=532, y=356>