Complications with Selenium's GetAttribute method - c#

I recently attempted to use selenium RC's GetAttribute method but immediately ran into a challenge. I tried to execute a very simple selenium.GetAttribute("//a/#href") but the code threw a SeleniumException with the message "ERROR: Could not find element attribute: //a/#href".
By substituting selenium.GetText("//a[#href]") in place of the GetAttribute call, I confirmed that an element was definitely present, as this statement properly returned the text of the link.
I then tried:
pointing to a different web page with a different protocol (file:/// vs http://) -- same problem.
using a different xpath locator pointing to a different attribute -- same problem.
using a DOM locator selenium.GetAttribute("document.getElementsByTagName('a')[0].getAttribute('href')") -- same problem; slightly different error message (and the error message is missing the final parenthesis): "ERROR: Element document.getElementsByTagName('a')[0].getAttribute('href' not found". Note that this exact expression works correctly in Firebug's console.
using absolute instead of relative xpath addressing, with selenium.GetText("xpath=/html/body/a[#href]") to confirm the existence and then selenium.GetAttribute("xpath=/html/body/a/#href") to get the attribute -- and it worked!
While the manual clearly states that relative xpath locators do not need an explicit locator type (i.e. the "xpath=" prefix) it is silent about absolute xpath locators; I interpret from this that the prefix is required. But out of curiousity, I went back to my relative expression and added the explicit prefix--changing selenium.GetAttribute("//a/#href") to selenium.GetAttribute("xpath=//a/#href") -- and this also worked!
Finally, my experiments with the very handy Find button in Selenium IDE show that it does fine with elements but fails with attributes. I can understand that it is not meaningful to highlight an attribute since attributes are not visible page elements, but why not highlight the element containing the attribute, and make it in a different color? Perhaps not a trivial task...
My questions:
I distilled the results of the above experiments down to these questions; this is the whole purpose of my posting here! Each of these seems like a bug to me but let me know if you think my usage is incorrect or there is a workaround:
Why does GetAttribute with an XPath locator type uniquely require an explicit locator type when other methods (e.g. GetText) do not?
Why did the DOM locator fail with a 'not found' error? (The manual also clearly states that DOM locators do not require an explicit locator type prefix, but I nevertheless tried adding "dom=" as a prefix on the DOM test; it still failed.)
Why does Selenium IDE not fail more gracefully when attempting to highlight (Find) an attribute? With the same "xpath=//a/#href" locator, pressing the Find button yields this ugly message: "[error] locator not found: xpath=//a/#href, error = [Exception... "Could not convert JavaScript argument arg 0 [inIFlasher.scrollElementIntoView]" nsresult: "0x80570009 (NS_ERROR_XPC_BAD_CONVERT_JS)" location: "JS frame :: chrome://selenium-ide/content/selenium-runner.js :: showElement :: line 386" data: no]"
Your input is also requested for the following: The pattern I wanted for each test here was (A) GetText(locator-for-element-with-attribute) to confirm the presence of the element then (B) GetAttribute(locator-for-attribute-itself). Of the 6 slots in the table below I solved 3 of them successfully as just detailed, and a 4th seems to be a bug. Are there solutions for the remaining two slots?
Type GetText GetAttribute
XPath //a[#href] xpath=//a/#href
CSS css=a[href] ??
DOM ?? document.getElementsByTagName('a')[0].getAttribute('href')
(Details: Selenium RC version 1.0.3, Browser: Firefox 3.6.13, My target code in C#)

Selenium RC's GetAttribute method returns the value of the element\attribute locator. The general form for these locators is
"[locator (id, xpath, css, etc)]#[attribute name]"
for example
"SaveButton#href"
returns the value of the href attribute on the element with the id SaveButton. Xpath locators can also be used:
"xpath=//a[contains(#id, 'SaveButton')]#href"
returns the value of the href attribute on the element whose id contains the text SaveButton.
To answer your questions,
1: I don't really know, this is a question for the designers of Selenium.
2: The Selenium commands execute several different "contexts". In some of the commands, document refers to the web page under test, in other commands, document refers to the page containing the Selenium frame (testRunner.html I believe).
3: The error message says that it cannot find the element you requested. The information after that could be useful to the Selenium team if there is actually a bug present, but doesn't really affect you. The more information the better, right?

http://release.seleniumhq.org/selenium-remote-control/0.9.2/doc/java/com/thoughtworks/selenium/Selenium.html#getAttribute%28java.lang.String%29
getAttribute
java.lang.String getAttribute(java.lang.String attributeLocator)
Gets the value of an element attribute.
Parameters:
attributeLocator - an element locator followed by an # sign and then the name of the attribute, e.g. "foo#bar"
Returns:
the value of the specified attribute
So you should say selenium.GetAttribute("locator#href") Locator being id or name. If your a element does not have id or name, you should use xpath, selenium.GetAttribute("xpath=/html/body/a/#href") like you already successfully tried.

Related

Finding all XPaths in a XQuery using Saxon-HE with C#

Situational Background: XSD with SCH
XML Schema (XSD)
I have an XML schema definition ("the schema") that includes several other XSDs, all in the same namespace. Some of those import other XSDs from foreign namespaces. All in all, the schema declares several global elements that can be instantiated as XML documents. Let's call them Global_1, Global_2 and Global_3.
Business Rules (SCH)
The schema is augmented by a Schematron file that defines the "business rules". It defines a number of abstract rules, and each abstract rule contains a number of assertions using the data model defined via XSD. For instance:
<sch:pattern>
<sch:rule id="rule_A" abstract="true">
<sch:assert test="if (abc:a/abc:b = '123') then abc:x/abc:y = ('aaa', 'bbb', 'ccc') else true()" id="A-01">Error message</sch:assert>
<sch:assert test="not(abc:c = 'abcd' and abc:d = 'zz')" id="A-02">Some other error message</sch:assert>
</sch:rule>
<!-- (...) -->
</sch:pattern>
Each abstract rule is extended by one or more non-abstract (concrete) rule that defines a specific context in which the abstract rule's assertions are to be validated. For example:
<sch:pattern>
<!-- (...) -->
<sch:rule context="abc:Global_1/abc:x/abc:y">
<sch:extends rule="rule_A"/>
</sch:rule>
<sch:rule context="abc:Global_2/abc:j//abc:k/abc:l">
<sch:extends rule="rule_A"/>
</sch:rule>
<!-- (...) -->
</sch:pattern>
In other words, all the assertions defined within the abstract rule_A are being applied to their specific contexts.
Both "the schema" and "the business rules" are subject to change - my program gets them at run-time and I don't know their content at design-time. The only thing I can safely assume is that there are no endless recursive structures in the schema: There is always one definite leaf node for every type and no type contains itself. Put differently, there are no "infinite loops" possible in the instances.
The Problem I want To Solve
Basically, I want to evaluate programmatically if each of the defined rules is correct. Since correctness can be quite a problematic topic, here by correctness I simply mean: Each XPath used in a rule (i.e. its context and within the XQueries of its inherited assertions) is "possible", meaning it can exist according to the data model defined in the schema. If, for instance, a namespace prefix is forgotten (abc:a/b instead of abc:a/abc:b), this XPath will never return anything other than an empty node set. The same is true if one step in the XPath is accidentally omitted, or spelled wrong, etc. This is obviously not a very strong claim for "correctness" of such a rule, but it'll do for a first step.
My Approach Towards A Solution For This
At least to me it doesn't seem like a trivial problem to evaluate an XPath (not to speak of the entire XQuery!) designed for the instance of a schema against the actual schema, given how it may contain axis steps like //, ancestor::, sibling::, etc. So I decided to construct something I would call a "maximum instance": By recursively iterating through all global elements and their children (and the structure of their respective complex types etc.), I build an XML instance at run-time that contains every possible element and attribute where it would be in the normal instance, but all at once. So every optional element/attribute, every element within a choice block and so on. So, said maximum instance would look something like this:
<maximumInstance>
<Global_1>
<abc:a>
<abc:b additionalAttribute="some_fixed_value">
<abc:j/>
<abc:k/>
<abc:l/>
</abc:b>
</abc:a>
</Global_1>
<Global_2>
<abc:x>
<abc:y>
<abc:a/>
<abc:z>
<abc:l/>
</abc:z>
</abc:y>
</abc:x>
</Global_2>
<Global_3>
<!-- ... -->
</Global_3>
<!-- ... -->
</maximumInstance>
All it takes now is to iterate over all abstract rules: And for every assertion in each abstract rule it must be checked that for every context the respective abstract rule is extended by, every XPath within an assertion results in a non-empty node set when evaluated against the maximum instance.
Where I'm stuck
I have written a C# (.NET Framework 4.8) program that parses "the schema" into said "maximum instance" (which is an XDocument at run-time). It also parses the business rules into a structure that makes it easy to get each abstract rule, its assertions, and the contexts these assertions are to be validated against.
But currently, I only have each complete XQuery (just like they are in the Schematron file) which effectively creates an assertion. But I actually need to break the XQuery down into its components (I guess I'd need the abstract syntax tree) so that I would have all individual XPaths. For instance, when given the XQuery if (abc:a/abc:b = '123') then abc:x/abc:y = ('aaa', 'bbb', 'ccc') else true(), I would need to retrieve abc:a/abc:b and abc:x/abc:y.
I assume that this could be done using Saxon-HE (or maybe another Parser/Compiler currently available for C# I don't know about). Unfortunately, I have yet to understand how to make use of Saxon well enough to even find at least a valid starting point for what I want to achieve. I've been trying to use the abstract syntax tree (so I can access the respective XPaths in the XQuery) seemingly accessible via XQueryExecutable:
Processor processor = new Processor();
XQueryCompiler xqueryCompiler = processor.NewXQueryCompiler();
XQueryExecutable exe = xqueryCompiler.Compile(xquery);
var AST = exe.getUnderlyingCompiledQuery();
var st = new XDocument();
st.Add(new XElement("root"));
XdmNode node = processor.NewDocumentBuilder().Build(st.CreateReader());
AST.explain((node); // <-- this is an error!
But that doesn't get me anywhere: I don't find any properties exposed I could work with? And while VS offers me to use AST.explain(...) (which seems promising), I'm unable to figure out what to parametrize here. I tried using a XdmNode which I thought would be a Destination? But also, I am using Saxon 10 (via NuGet), while Destination seems to be from Saxon 9: net.sf.saxon.s9api.Destination?!
Does anybody who was kind enough to read through all of this have any advice for me on how to tackle this? :-) Or, maybe there's a better way to solve my problem I haven't thought of - I'm also grateful for suggestions.
TL;DR
Sorry for the wall of text! In short: I have Schematron rules that augment an XML schema with business logic. To evaluate these rules (not: validate instances against the rules!) without actual XML instances, I need to break down the XQueries which make up the Schematron's assertions into their components so that I can handle all XPaths used in them. I think it can be done with Saxon-HE, but my knowledge is too limited to even understand what a good starting point what be for that. I'm also open for suggestions regarding a possibly better approach to solve my actual problem (as described in detail above).
Thank you for taking the time to read this.
If this were an XSD schema rather than a Schematron schema, then Saxon-EE would do the job for you automatically: this is very similar what a schema-aware XQuery processor attempts to do. But another difference is that in schema-aware XQuery, you can't assume that every element named foo is a valid instance of the element declaration named foo in the schema; it's quite legitimate, for example, for a query to transform valid instances into invalid instances, or vice versa. The input and output, after all, might conform to different schemas.
Saxon uses path analysis to do this: it looks at path expressions to see "where they might lead". Path analysis is also used to assess streamability, and to support document projection (building a trimmed-down tree representation of the source document that leaves out the parts that the query cannot reach). The path analysis in Saxon is by no means complete, for example it doesn't attempt to handle recursive functions. Although all these operations require Saxon-EE, the basic path analysis code is actually present in Saxon-HE, but I would offer no guarantee that it works for any purpose other than those described.
You're basically right that this is a tough problem you've set yourself, and I wish you luck with it.
Another approach you could adopt that wouldn't involve grovelling around the Saxon internals is to convert the XQuery to XQueryX, which is an XML representation of the parse tree, and then inspect the XQueryX (presumably using XQuery) to find the parts you need.
While XQueryX (as pointed out by Michael Kay) would theoretically have been exactly what I was looking for, unfortunately I could not find anything useful regarding an implementation for .NET during my research.
So I eventually solved the whole thing by creating my own parser using the XPath3.1 grammar for ANTLR4 as an ideal starting point. This way, I am now able to retrieve a syntax tree of any Schematron rule expression, allowing me to extract each contained XPath expression (and its sub expressions) separately.
Note that another stumbling block has been the fact that .NET still (!) only handles XPath 1.0 genuinely: While my parser does everything as supposed to, for some of the found expressions .NET gave me "illegal token" errors when trying to evaluate them. Installing the XPath2 NuGet package by Chertkov/Heyenrath was the solution.

Problem selecting attribute using XPath in Selenium .NET Core Project

I have a curious issue for which I can not seem to find a solution on this forum (or elsewhere on the internet)
I am building a test automation application using Selenium and .NET Core 3.1. I am trying to select an element in the DOM using a OpenQA.Selenium.IWebDriver and previously selected OpenQA.Selenium.IWebElement and an Xpath selector like so:
IWebElement parent => driver.FindElement(By.CssSelector("#parent"));
IWebElement child(string t) = parent.FindElement(By.XPath($".//li[#data-original-title=\"{t}\"]"))
...
var el = child("'title-1'");
Where the DOM is the following:
<div id="parent">
... <!-- child element is nested multiple levels -->
<li title data-original-title="'title-1'"></li>
<li title data-original-title="'title-2'"></li>
...
</div>
When I try to perform this action i get the following error:
OpenQA.Selenium.NoSuchElementException : no such element: Unable to locate element: {"method":"xpath","selector":".//li[#data-original-title="'title-1'"]"}
(Session info: chrome=85.0.4183.102)
However when I copy this xpath which is apparently non existent and search the dom using chrome debugger it does match the element.
Then I tried to figure out what could be the cause, maybe I made a mistake with the parent or smth. So I try the following XPath for the child selector, matching the other attribute (with out value)
IWebElement child(string t) = parent.FindElement(By.XPath($".//li[#title]"))
This does return an element, and after checking the debugger it is my intended child element. Now I assume something must go wrong with the formatting of the string so I try the following selector (without the value)
IWebElement child(string t) = parent.FindElement(By.XPath($".//li[#data-original-title]"))
This produces (roughly) the same error as before:
OpenQA.Selenium.NoSuchElementException : no such element: Unable to locate element: {"method":"xpath","selector":".//li[#data-original-title]"}
(Session info: chrome=85.0.4183.102)
And again when I try to find the element in the DOM using the search function in the chrome debugger using the above xpath .//li[#data-original-title] it does match my expected child element.
So I am now thinking the hyphens must cause the problem. I tried some research on the issue but the only real thing I could find was this stackoverflow article
Here they recommend to use an CSS selector instead, which I tried and also did not work, furthermore I believe the relative to parent function does not work with the CSS selector.
In this article the poster comments that the problem in the end was caused by DOM structure, which does not help me very much and also makes me think I just made a big mistake somewhere along the line that I just have been overlooking.
Conclusion
Based on the above XPath selector is there anything I have done wrong that causes my mismatch, or is there maybe a difference in implementation of XPath in chrome debugger vs the .NET Core Selenium library that I should know of that could cause this issue?
Thanks in advance and sorry for the long post :$
So as it turned out it was something I overlooked. The data-original-tile attribute is set reactively, based on user mouse input (as it is used for conditionally displaying a tooltip) and title property is cleared. Since selenium only fires a click event and does not actually hover above the element without specifically clarifying so the attributes won't be swapped during automation.
Conclusion
I should have checked the source HTML more thoroughly for updates to the DOM on user interaction.

Could not access element by ID

I am facing with problem when I tried to access Android element by ID in C#, I also tried with Appium-desktop version and seems not accessible for example:
I tried with and without package name and there is an exception every time which says could not find element. Also from Appium desktop selector.
AndroidElement selectPlant = driver.FindElementById("com.heidelbergcement.aom.stage.dev:id/loginForm-plantSelection")
You're misunderstanding something.
FindElementById refers to the unique identifier of the element which in most cases is the RuntimeId of the UI element.
What you should use is findElementByAccessibilityId, which refers to AutomationId of the UI element as shown in the inspect tool.
Total credit to this.

How to escape special character {{ or skip interpretation of a string in visual studio web test [duplicate]

I am trying to work out how to pass a particular piece of data in a POST via a Visual Studio Web Test, without it being recognized and treated as a Context Parameter.
The POST contains a (string) body that is a json document. Part of the body includes something like the following:
"My Attribute":"Some test surrounding this {{SomeValue}} other stuff"
The issue is that the Web Test is trying to match {{SomeValue}} to a Context Parameter (which doesn't exist) and so this request fails.
The value is legitimate, and needs to be sent with the request as is.
I've done some Googling and can't find any documentation that talks about, for example, escaping this string so that the value will be passed correct, and won't be treated as a Context Parameter.
I guess I could write a Web Test plugin to intercept this particular request, and do some token replacement, but that feels like a sledgehammer approach.
Any other ideas?
You could create the context parameter SomeValue and set its value to {{SomeValue}}.
You could create the two context parameters OpenDoubleCurly and CloseDoubleCurly set to the values {{ and }} respectively. Then modify the POST text to be:
"My Attribute":"Some test surrounding this {{OpenDoubleCurly}}SomeValue{{CloseDoubleCurly}} other stuff"
Normally web tests only do one level of context parameter expansion. You need to use (or for this question avoid using) plugins that do multiple expansion passes.

Not finding all of the symbols I need,How to find more symbols using the Roslyn API

I am using the roslyn API and ace text editor to create a web IDE.
When i hover over data i need it to find the symbol at the given location. This works in some situations by calling the roslyn method:
var symbol = SymbolFinder.FindSymbolAtPosition(semanticModel, offset, dotNetCodeManager.Solution.Workspace, cancellationToken);
An example of the situations where this works is when i hover my mouse over the word "table" in the below example.
var SchemaName = table.Schema.Name;
However when i hover my mouse over the word Schema or Name SymbolFinder.FindSymbolAtPosition returns null.
However:
If I go to the end of the word table and ask for autocomplete information I do get Schema in the list of recommended symbols
var result = Recommender.GetRecommendedSymbolsAtPosition(semanticModel, offset, solution.Workspace);
How do I get roslyn to find symbols that are properties, methods, or fields of objects?
So FindSymbolAtPosition should work just fine -- it's after all the same API we use for things like go to definition or any other core language feature. What I would guess here is your compilation or semantic model isn't complete, and so when we try to bind Schema or Name we for some reason. The recommendation API might be able to figure out the type of the parent and know it has members, but for some reason those members aren't properly binding.
What I would recommend you try is in your semantic model or compilation, call GetDiagnostics and verify there aren't any unexpected errors there. You might be missing a reference that's causing everything to go sideways, and clearing that will make this work fine.

Categories

Resources