i am trying a drag and drop in an iframe and to do that i need to pass xpath in find since i cant find a unique element to pass in cy.get()
currently i am trying
cy.xpath('//div[#class="unlayer-editor"]//iframe[#src]')
.should("be.visible")
.find('//div[#class = "blopockbder-coent-tols43 col-sm-12"]//div[#aria-describedby="t8ppy-tooltip-9"]')
but this isnt working
i am using cypress for automation
Not an expert on xpath, but I think .find() can't be mixed with an xpath selector.
Two things to try
// chain 2nd xpath in place of .find()
cy.get('div[class="unlayer-editor"] iframe[id="my-iframes-id"]')
.should("be.visible")
.xpath('//div[#class = "blopockbder-coent-tols43 col-sm-12"]//div[#aria-describedby="t8ppy-tooltip-9"]')
or
// use .within() instead of .find() (roughly equivalent)
cy.get('div[class="unlayer-editor"] iframe[id="my-iframes-id"]')
.should("be.visible")
.within(() => {
cy.xpath('//div[#class = "blopockbder-coent-tols43 col-sm-12"]//div[#aria-describedby="t8ppy-tooltip-9"]')
})
Other things that might need adjusting
The iframe selection generally needs a follow-up command to get it's document body (ref Working with iframes)
// get the iframe document body any select within it
cy.get('div[class="unlayer-editor"] iframe[id="my-iframes-id"]')
.its('0.contentDocument.body', { log: false }).should('not.be.empty')
.within(() => {
cy.xpath('//div[#class = "blopockbder-coent-tols43 col-sm-12"]//div[#aria-describedby="t8ppy-tooltip-9"]')
})
Some of those classes in the path like col-sm-12 are purely display-oriented and may be different if you test at different devices. Once the test works, try removing them to make the test more robust.
Related
I am trying to go to this simple webpage and perform a click action on an element. It fails even though I'm using unique selectors (I tried different Xpath and css selectors). By debugging it points to the locator's element still cant perform click action on it, showing error Test timeout of 60000ms exceeded.- locator.click: Target closed` waiting for the locator
Here is the code:
test.only('click on date picker', async ({page})=>{
await page.goto('https://www.globalsqa.com/demo-site/datepicker/#Simple%20Date%20Picker')
const clickFirst = page.locator("input[class='hasDatepicker']")
await clickFirst.click()
})
The element you want is in a frame, so locate the frame first:
import {test} from "#playwright/test"; // ^1.30.0
test.only("click on date picker", async ({page}) => {
await page.goto(
"https://www.globalsqa.com/demo-site/datepicker/#Simple%20Date%20Picker"
);
await page.frameLocator(".demo-frame").nth(0).locator("#datepicker").click();
});
Attribute selectors like input[class='hasDatepicker'] should be avoided, because they're overly strict, forcing an exact match in a specific order. Your selector fails on elements with additional classes beyond the hasDatepicker class. Almost always, use input.hasDatepicker instead, although here, we have an id, so prefer that as I've done above.
You could just use the id to target the date picker.
If I look at the page something like this should work:
await page.locator("#datepicker").click();
The playwright extension for Vs Code also offers an option to pick locators from a website, this makes it easier to find a fitting selector.
I want to do some checks on an element but also check whether it's located in a specific parent.
here is part of original code:
it("shows right panel elements", () => {
cy.get(selectors.rightPanel).find(selectors.logo)
cy.get(selectors.rightPanel)
.find(selectors.menuBar)
.find(selectors.wishlistIcon)
.closest("a")
.should("have.attr", "href", selectors.wishlistUrl)
.should("be.visible")
cy.get(selectors.rightPanel)
.find(selectors.menuBar)
.find(selectors.cartIcon)
.closest("a")
.should("have.attr", "href", selectors.cartUrl)
.should("be.visible")
})
My colleagues told me to avoid chaining with find to prevent flakiness.
I have tried to use within, but it looks quite ugly, especially if I need to go multiple levels down.
cy.get(selectors.rightPanel).within($panel => {
cy.get(selectors.logo)
cy.get(selectors.menuBar)
cy.get(selectors.logo)
cy.get(selectors.wishlistIcon)
.closest("a")
.should("have.attr", "href", selectors.wishlistUrl)
.and("be.visible")
}).
what would be a good solution?
I don't seem to fully grasp the problem from your code but the below command from the dom API might do the trick
Cypress.dom.isChild(possibleChild, possibleParent);
Presume the nesting is something like
<rightPanel>
<menuBar>
<wishlistIcon>
You could use this to specifically test the child-parent relationship
cy.get(selectors.wishlistIcon)
.parents(selectors.menuBar) // does wishlistIcon have a parent with menuBar selector?
but I see nothing wrong with
cy.get(selectors.rightPanel)
.find(selectors.menuBar) // find within rightPanel
.find(selectors.wishlistIcon) // find within menuBar
and this is the better direction to go since you want the href to be part of the story.
I can't see why find might be considered flakey. It has a timeout option, which means it has the Cypress retry mechanism (the primary defense against flakiness).
I have a window-box with two buttons 'add' and 'close'. I need to test below scenario:
When clicked on 'add' button it throws error and the window remains open. I need to click on 'close' button to proceed.
I used below code:
if(element(by.xpath("xpath_of_error_box")).isEnabled())
{
element(by.xpath("xpath_of_close_button")).click();
}
But it throws below error:
No element found using locator: By(xpath, xpath_of_error_box)
Is there any way to handle this?
According to the error, it seems that your xpath locator didn't match any element. And according to the additional clarification in the question you could try:
element(by.xpath("xpath_of_error_box")).isDisplayed().then(isDisplayed => {
if (isDisplayed) {
// do what you need when it is visible
} else {
// if not then proceed
}
});
As it was pointed out, isEnabled might not be the proper method you should use in this case. If it seems that the element you try to find is always present in the dom, you might better try to check for its visibility using isDisplay instead.
An advice. It's not a good idea to use xpath locators in your tests, because this ties them to the html DOM structire of the web page you are observing. As we know, the UI happens to change often, which would make your tests to brake often as well. Although this is of cource a personal preference, it is such until you end up with tons of brocken tests after a single small change in the html.
If you need to check if an element is present you can use the following code:
if (element(by.xpath("yourXpath")).isPresent())
But your problem is not on your if code, your problem is that the xpath your are searching doesn't exist.
isEnabled() and isPresent() returns promise (not boolean) and have to be resolved.
isEnabled() could be only used for <button>.
You can use XPath all the time, don't listen to anyone.
PS. Of course it would be glad to see your HTML to check the correctness of your XPath.
I'm working with CasperJS on a webpage that has a search box. Using Casper, I'm successfully able to perform a search and see that the form is filled and execute the search, however I'm having trouble specifically getting the number of results to test that it's valid.
When I look at the source of the webpage, I have the XPath of the element and it's nested in a few divs.
But when I try to either do assertExists() on that path, or even return the result of getElementByXPath() to a var, it doesn't work. In the first case the test fails and in the second case it prints null.
This is the XPath:
//*[#id="total"]
Here is what the snippet of source looks like:
<div id="pgContent"><div id="results_pagination1_container">
<span style="float: right; font-size: .9em">
Found <span id="total">721</span> item(s)</span>
</div>
This is the CasperJS code, relevant to here.
casper.test.begin(
'Testing that we get the right amount of results for a search query',
2, function suite(test) {
casper.start(catapult, function() {
test.assertTitle("Search", "Search"); // Good
test.assertExists('#input-searchbox'); // Good
this.fillSelectors('form#inputForm', {
'input[name="queryStr"]' : 'airplane'
}, true);
//this.click('input#btnSearch');
});
casper.then(function() {
var resultsNum = __utils__.getElementByXPath('//*[#id="total"]');
this.echo(resultsNum);
test.assertExists('//*[#id="total"]');
});
Clientutils and DOM access only in page context
The CasperJS clientutils module is only defined in the page context. Whenever CasperJS starts, it injects those utils into the page for later convenience. The problem is that the page and its DOM are only accessible from inside of the evaluate() function.
Another thing to remember is that you cannot get DOM nodes out of the page context. Either you do your stuff completely in the page context (inside of evaluate()) or you get a representation of the node like the textContent property:
var resultsNum = this.evaluate(function(){
return __utils__.getElementByXPath('//*[#id="total"]').textContent;
});
Here is the bit from the documentation (since CasperJS is built on top of PhantomJS):
Note: The arguments and the return value to the evaluate function must be a simple primitive object. The rule of thumb: if it can be serialized via JSON, then it is fine.
Closures, functions, DOM nodes, etc. will not work!
Difference between CSS selectors and XPath expressions
The other thing is that if not otherwise noted through the name all functions assume that the selectors are CSS selectors. Looking at test.assertExists('//*[#id="total"]'); makes it clear that '//*[#id="total"]' is not a CSS selector, but an XPath expression. You can use XPath expressions in CasperJS through the XPath utility:
var x = require('casper').selectXPath;
test.assertExists(x('//*[#id="total"]'));
or you can simply use the equivalent CSS selector:
test.assertExists('#total');
In a tree built with jsTree, I have the text within the <a> tag sitting in a variable. I would like to check that node. How can I do so?
I am currently finding that node, using jQuery, and altering its class. However, this does not repair the parent node by making the parent undetermined in its class. I tried doing $('.colors').jstree("checkbox_repair"), but that didn't seem to do anything.
It would be great if someone could actually answer both those questions, since they are related to the same problem.
Here is a jsFiddle, illustrating the issue--> http://jsfiddle.net/thapar/5XAjU/
In js_tree there are .check_node ( node ) and .uncheck_node ( node ) functions, i think this is what you are asking for. Soe the documentation here: http://www.jstree.com/documentation/checkbox
This is an excerpt from the documentation in the link above, "how to perform an operation":
/* METHOD ONE */
jQuery("some-selector-to-container-node-here")
.jstree("operation_name" [, argument_1, argument_2, ...]);
/* METHOD TWO */
jQuery.jstree._reference(needle)
/* NEEDLE can be a DOM node or selector for the container or a node within the container */
.operation_name([ argument_1, argument_2, ...]);
So I think this syntax should work
$.jstree._reference(".colors").check_node('li#tree_3');
Also i am not sure you should be using a class to reference your tree. Probably use an ID to reference your tree, and then use this syntax:
$.jstree._reference("#colors").check_node('li#tree_3');
//EDIT: Please keep in mind that the newest version of jsTree doesn't have a function called _reference anymore. It got renamed to reference (without the leading underscore). (Last checked 24/08/2015 15:45 by #mkli90)
Link: https://www.jstree.com/api/#/?f=$.jstree.reference(needle)
If you want to check jsTree nodes on load for example like this:
$(document).ready(function()
{
$.jstree._reference('#menu').check_node('#pih2');
});
it does not work. For me works following:
$(function () {
$('#mainMenu1').bind('loaded.jstree', function(e, data){ //waiting for loading
$.jstree._reference('#menu').check_node('#pih2'); //check node with id pih2
$.jstree._reference('#menu').check_node('#pih6'); //check node with id pih6
});
});
I use jsTree 1.0-rc3 and JQuery 1.7.1.
Aloe
In current versions of jstree the following syntax works:
$("#my_tree").jstree("check_node", node_id);
I would like to add this solution, the select_node function does the same function as check_node. we can use it as follows;
$('#jstree_id').on('loaded.jstree', function() {
$("#jstree_id").jstree("select_node", ["list of nodes go here"]);
});
You can use it to select multiple nodes in an array or a single node.