How can I write this xpath expression in WATIR methods - watir

I have to form the following xpath via watir methods,
//span[#class='fieldTitle-small required z-label'][contains(.,'Address Type')]/../following-sibling::div//input
Is there a way to call the watir methods one after another to form this xpath?

That XPath could be done using Watir methods as:
browser.span(class: %w(fieldTitle-small required z-label), text: /Address Type/) # //span[#class='fieldTitle-small required z-label'][contains(.,'Address Type')]
.parent # /..
.following_sibling(tag_name: 'div') # /following-sibling::div
.input # //input
Note that when using a :class locator, an Array can be used to specify multiple classes that can appear in any order. The element only has to include those classes, but it can also include any others. For example, browser.span(class: %w(fieldTitle-small z-label), text: /Address Type/), which has the "required" class removed, would match <span class="fieldTitle-small required z-label"> and <span class="fieldTitle-small z-label">.

Related

Selenium, element not accesible by keyboard [duplicate]

The error is :
Exception in thread "main"
org.openqa.selenium.ElementNotInteractableException: Element is not reachable by keyboard
The code is:
System.setProperty("webdriver.gecko.driver","//Users//rozali//Documents//Selenium//geckodriver");
WebDriver driver = new FirefoxDriver();
driver.get("http://www.facebook.com");
driver.manage().window().maximize();
//entering first name
driver.findElement(By.id("u_0_b")).click();
driver.findElement(By.id("u_0_b")).sendKeys("testing it ");
//DOB
Select sel1 = new Select(driver.findElement(By.xpath(".//*[#id='month']")));
sel1.selectByIndex(4);
Select sel2 = new Select(driver.findElement(By.xpath(".//*[#id='day']")));
sel2.selectByValue("6");
Select sel3 = new Select(driver.findElement(By.xpath(".//*[#id='year']")));
sel3.selectByValue("2013");
//clicking sign up
driver.findElement(By.id("u_0_t")).click();
ElementNotInteractableException: Element is not reachable by keyboard
Element is not reachable by keyboard in plain words means that the element can’t be reached using the keyboard, which means you won't even physically interact with it.
Reason
There can be multiple reasons behind the error Element is not reachable by keyboard which can be either of the following:
The element is hidden, as modern JavaScript-centric UI styles always keep the ugly raw HTML input field hidden. The hidden attribute could have been implemented through either of the following ways:
A temporary overlay of some other element over the desired element.
A permanent overlay of some other element over the desired element.
Presence of attributes e.g. class="ng-hide", style="display: none", etc
As per best practices while sending character sequence, you must not attempt to invoke click() or sendKeys() on any <p> or <div> tag; instead, invoke click() on the desired <input> tag following the Official locator strategies for the webdriver.
Solution
There are different approaches to address this issue.
Incase of temporary overlay, use WebDriverWait inconjunction with ExpectedConditions for the desired element to be visible/clickable as follows:
import org.openqa.selenium.support.ui.WebDriverWait;
import org.openqa.selenium.support.ui.ExpectedConditions;
new WebDriverWait(driver, 20).until(ExpectedConditions.elementToBeClickable(By.cssSelector("button.nsg-button"))).click();
Incase of permanent overlay, use executeScript() method from JavascriptExecutor interface as follows:
import org.openqa.selenium.JavascriptExecutor;
String inputText = "Rozmeen";
WebElement myElement = driver.findElement(By.id("u_0_b"));
String js = "arguments[0].setAttribute('value','"+inputText+"')"
((JavascriptExecutor) driver).executeScript(js, myElement);
You will find a detailed discussion in Using JS to enter text, but if I input text in one text box, the value already entered is getting deleted.
Incase presence of attributes e.g. class="ng-hide", style="display: none", etc., use executeScript() method from the JavascriptExecutor interface to edit and reset the style="display: none" attribute to style="display: block" as follows:
import org.openqa.selenium.JavascriptExecutor;
((JavascriptExecutor) driver).executeScript("document.getElementById('ID').style.display='block';");
You will find a detailed discussion in Can't fill in the Hidden text area element.
References
For input[type=file], should allow sendKeys even when display=none
Special-casing file upload controls in keyboard-interactability check
Element is not reachable by keyboard
Input field with display: none is not interactable at all?
This particular issue
If you look into the HTML of Facebook login page, the application contains React Native elements. So an element once represented with id as u_0_b in your system may not be represented by the same id as u_0_b in the next run on your system. Hence, we have to take the help of Dynamic Locator Strategy. You can use the following code block to perform your intended steps :
Code Block :
System.setProperty("webdriver.gecko.driver", "C:\\Utility\\BrowserDrivers\\geckodriver.exe");
WebDriver driver = new FirefoxDriver();
driver.get("https://www.facebook.com");
driver.findElement(By.xpath("//input[#name='firstname' and contains(#class,'inputtext')]")).sendKeys("testing it ");
//DOB
Select sel1 = new Select(driver.findElement(By.xpath(".//*[#id='month']")));
sel1.selectByIndex(4);
Select sel2 = new Select(driver.findElement(By.xpath(".//*[#id='day']")));
sel2.selectByValue("6");
Select sel3 = new Select(driver.findElement(By.xpath(".//*[#id='year']")));
sel3.selectByValue("2013");
//clicking sign up
driver.findElement(By.xpath("//button[#name='websubmit' and contains(.,'Sign Up')]")).click();
Browser Client :
Update
Addressing the error:
org.openqa.selenium.ElementNotInteractableException: Element is not
reachable by keyboard
has become easier with the availability of Firefox capability moz:webdriverClick
moz:webdriverClick()
Through webdriverClick(), you can pass a boolean value to indicate which kind of interactability checks to run when performing a click or sending keys to an element. For Firefoxen prior to v58.0, some legacy code as imported from an older version of FirefoxDriver was in use. With the availability of Firefox v58, the interactability checks as required by the WebDriver specification are enabled by default. This means that geckodriver will additionally check if an element is obscured by another when clicking and if an element is focusable for sending keys. Because of this change in behaviour, we are aware that some extra errors could be returned. In most cases, the test in question might have to be updated so it conforms with the new checks.
To temporarily disable the WebDriver conformant checks, use false as value for this capability.
Note: This capability exists only temporarily, and it will be removed once the interactability checks have been stabilized.
You can try this code :
public class Rozmeen{
static WebDriver driver;
static WebDriverWait wait;
public static void main(String[] args) throws InterruptedException {
System.setProperty("webdriver.gecko.driver", "F:\\Automation\\geckodriver.exe");
driver = new FirefoxDriver();
driver.manage().window().maximize();
WebDriverWait wait = new WebDriverWait(driver, 40);
driver.get("http://www.facebook.com");
//entering first name
wait.until(ExpectedConditions.visibilityOf(driver.findElement(By.id("pagelet_bluebar"))));
driver.findElement(By.name("firstname")).sendKeys("testing it ");
//DOB
selectFromDropDown(driver.findElement(By.name("birthday_day")), "4");
selectFromDropDown(driver.findElement(By.name("birthday_month")), "Jun");
selectFromDropDown(driver.findElement(By.name("birthday_year")), "2013");
//clicking sign up
wait.until(ExpectedConditions.elementToBeClickable(driver.findElement(By.name("websubmit"))));
driver.findElement(By.name("websubmit")).click();
}
public static void selectFromDropDown(WebElement element , String Visibletext){
Select select = new Select(element);
select.selectByVisibleText(Visibletext);
}
}
try out this code and let me know the status.
In one of the use cases I had the same issue:
Exception in thread "main" org.openqa.selenium.ElementNotInteractableException: Element <div id="search"> is not reachable by keyboard
using id for identifying an element before sending keys. Something like:
driver.findElement(By.id("search")).sendKeys("...");
After testing I changed to CSS Selector and it solved the issue:
driver.findElement(By.cssSelector("#search > input:nth-child(2)")).sendKeys("...");
So, I highly recommend to use different methods to interact with the elements, because something else can save your time solving problems.
Sometimes it is also an issue by using name/id like this:
driver.findElement(By.name("phone")).sendKeys("99999999");
Instead of this, use Xpath. This solved the issue for me:
driver.findElement(By.xpath("//*[#id='load_form']/input")).sendKeys("Java");
I got a similar error on a button when the click() operation was performed:
org.openqa.selenium.ElementNotInteractableException Exception
As mentioned by DebanjanB in his answer, the element was not reachable by keyboard.
To solve this, I replaced click() with sendKeys(Keys.ENTER), and the button got clicked.

Should ("...") be used in templates?

In lit-element # Templates # Bind properties to child elements (documentation) for
Attribute: <p id="${...}"></p>
Boolean attribute: ?checked="${...}"
Property: .value="${...}"
Event handler: #event="${...}"
a pair of " is always used.
On the contrary, in lit-html # Writing templates (documentation) a pair of " is never used, eg:
Attribute: <p id=${...}></p>
Boolean attribute: ?checked=${...}
Property: .value=${...}
Event handler: #event=${...}
Is there any reason for that? Is any style more preferable than the other?
There's no real difference, both are valid syntax and you should just use the style that suits you the best

Jest - how to test if a component does not exist?

How do I check if a component is not present, i.e. that a specific component has not been rendered?
.contains receives a React Node or array of Nodes as an argument. Instead, use .find:
expect(wrapper.find('selector').exists()).toBeTruthy()
You can use enzymes contains to check if the component was rendered:
expect(component.contains(<ComponentName />)).toBe(false)
If you're using react-testing-library (I know the OP wasn't but I found this question via web search) then this will work:
expect(component.queryByText("Text I care about")).not.toBeInTheDocument();
You can query by Text, Role, and several others. See docs for more info.
Note: queryBy* will return null if it is not found. If you use getBy* then it will error out for elements not found.
Providing a slightly updated answer based on the documentation for enzyme-matchers's toExist. This will require you to install the enzyme-matchers package.
function Fixture() {
return (
<div>
<span className="foo" />
<span className="bar baz" />
</div>
);
}
const wrapper = mount(<Fixture />); // mount/render/shallow when applicable
expect(wrapper.find('span')).toExist();
expect(wrapper.find('ul')).not.toExist();
.contains does not expect a selector, unlike find. You can look at the length attribute of the ShallowWrapper
expect(wrapper.find('...')).toHaveLength(0)
I found I needed to use this syntax with Enzyme and Jest to test if a Connected Component existed in the rendered output.
We use Jest and Enzyme, and I've found the only good test is to import the sub-component and test this way:
expect(component.find(SubComponent).length).toEqual(0); // or (1) for exists, obvs
I tried all the other answers and none worked reliably.
If you are using react-testing-library, then this also will work:
expect(component.queryByText("Text I care about").toBeNull());
expect(within(component).queryByText("Text I care about")).toBeNull();
Note: In my case, I needed to use queryBy* because it doesn´t error out when the text element (that contains the text: Text I care about) does not exist. Therefore, I could evaluate whether there is an existence of a text component or not.

How can I deactivate some Markdown parsing rules in Mistune?

How can I deactivate some Markdown parsing rules in Mistune?
For instance I would like enable only **bold** and *italic* and deactivate all other rule parsing.
Is that possible?
You need to create a custom renderer.
A renderer is a class and each rule is a method of that renderer class.
To have your own rules, you need to either override a method and make it do nothing (Method A below), or to replace the full list of default_rules (method B below)
Method A)
Override a rule method: Here is the full list of rules.
E.G.:
class YourRenderer(mistune.Renderer):
#example of rule
def block_code(self, code, lang):
pass
renderer = YourRenderer()
markdown = mistune.Markdown(renderer=renderer) # this renderer won't have the block_code rule
Method B)
Tamper with default_rules array
A renderer has an own property called default_rules. You just need to create a custom renderer and modify that array to your liking. Here's a sample class to get you started
class CustomRenderer(InlineLexer):
# Modify this array as you like
# you can insert or delete whatever rules it has
self.default_rules.insert(3, 'some_function')
I didn't test this

global variables not parsing as parameters

I am having troubles with global variables not parsing when passed as parameters.
{exp:channel:entries
disable="categories|category_fields|member_data|pagination|trackbacks"
dynamic="no"
entry_id="{structure:child_ids_for:21}"
}
(0.012500 / 3.36MB) Tag: {exp:channel:entries disable="categories|category_fields|member_data|pagination|trackbacks" dynamic="no" entry_id="{structure:child_ids_for:21}" }
The same result is produced with and without parse="inward"
However this works fine and grabs the data I need
{exp:channel:entries
disable="categories|category_fields|member_data|pagination|trackbacks"
dynamic="no"
entry_id="{exp:query sql='SELECT exp_structure.entry_id,
exp_structure.parent_id,
exp_structure.lft
FROM exp_structure
WHERE parent_id = 21
ORDER BY exp_structure.lft ASC'}{entry_id}|{/exp:query}"
parse="inward"
}
But, then if I add in a global variable author_id="{logged_in_member_id}" it fails to work, if I hard code that value as 1 then it functions.
Any thoughts as to what could be happening here?
You can avoid the overhead of embeds by using Stash for this sort of thing. It has the insanely useful ability to let you explicitly state your preferred parse order for different chunks of code. In this case the first thing you'd do is store the two variables via {exp:stash:set}, then you can retrieve them in the second chunk of code via {exp:stash:get}. The magic bit is the parse priority tag; because the first item has a priority of 10 it will be executed first, which ensures the vars are available for use as channel entries parameters in the second {exp:stash:parse} tag.
{exp:stash:parse priority="10" process="end"}
{exp:stash:set}
{stash:structure_ids}{structure:sibling_ids}{/stash:structure_ids}
{stash:logged_in_member}{logged_in_member_id}{/stash:logged_in_member}
{/exp:stash:set}
{/exp:stash:parse}
{exp:stash:parse priority="20" process="end"}
{exp:channel:entries
disable="categories|category_fields|member_data|pagination|trackbacks"
dynamic="no"
entry_id="{exp:stash:get name='structure_ids'}"
author_id="{exp:stash:get name='logged_in_member'}"
parse="inward"
}
...
{/exp:channel:entries}
{/exp:stash:parse}
I can't speak for Structure's global variables, but {logged_in_member_id} is a late-parsed global variable, meaning you can't use it in a module tag parameter. I can only only assume that the same goes for the Structure variables.
You can use the CURRENT_USER constant in the author_id parameter though (docs).
Unfortunately, the solution for your {structure:child_ids_for:21} issue is to pass that as an embed variable, and put your Channel Entries loop in an embed. (I say unfortunately because embeds do incur some overhead.)
One note: parse="inward" has no effect on module tag pairs - they always parse inward. It only affects plugin tag pairs.

Resources