I want to evaluate my content blocks before running my test suite but the closures' property names is in bytecode already. I'm ooking for the cleanest solution (compared with parsing source manually).
Already tried solution outlined in this post (and I'd still wind up doing some RegEx/parsing) but could only get it to work via script execution engine. It failed in IDE and GroovyConsole. Rather than embedding a Groovy script in project's code, I thought I'd try using Geb's native classes.
Is building on the suggestion about extending Geb Navigators here viable for Geb's PageContentSupport class whose contentTemplates contain a LinkedHashMap of exactly what I need? If yes, would someone provide guidance? If no, any suggestions?
It is currently not possible to get hold of all content elements for a given page/module. Feel free to create an issue for this in Geb's bug tracker, but remember that all that Geb can provide is either a list of content element names or a map from these names to closures that create these elements.
Having that information isn't a generic solution to your problem because it's possible for content elements to take parameters and there are situations where your content elements will be available on the page only after some other actions are performed (for example you have to click on button to reveal a section of a page that uses ajax to retrieve it's content). So I'm afraid that simply going over all elements and checking if they don't throw any errors will not cut it.
I'm still struggling to see what would "evaluating" all content elements prior to running the suite buy you. Are you after verifying that your content elements still work to get a faster feedback than running the whole suite? I'm pretty sure that you won't be able to fully automate detection of content definitions that don't work anymore. In my view it will be more effort than it's worth.
Related
I'm currently in the process of setting up Cypress for my project. Currently we're only using testing library for frontend tests. And reading the Cypress documentation has gotten me a bit confused as the two libraries seem to have opposite philosophies in regards to how you're supposed to query for elements.
Testing library basically says test what the user can see/touch and only use data-testid if all else fails. Cypress on the other hand states that best practice is that you should query elements by data-testid / data-cy attributes.
I feel conflicted between the two approaches. I get the point about we should test what the user actually sees (testing library). But I do also get that those things often change (cypress) and we need to spend time updating tests whenever we make small changes (i.e "Ok" -> "Done"). And when testing with data-cy attributes, are we not also ignoring accessibility / screen readers?
What are your thoughts on this?
React Testing library(RTL) is specifically made to write tests from a user perspective. From their Guiding Principles:
The more your tests resemble the way your software is used, the more confidence they can give you.
Meaning, RTL wants you to use accessibility queries like getByRole and only fallback to getByTestId for cases where you can't match by role or text, or it doesn't make sense (e.g. the text is dynamic).
However, thanks to the render method allowing us to specify props (compared to Cypress), we have much more flexibility and may entirely omit dynamic text.
Cypress, on the other hand, runs with all dependencies. In case of dynamic content from a C.M.S or multi-language application, things are not that easy using getByRole("heading", {name: /welcome/i }). In this case, the recommendation of testId's make sense.
My personal recommendation is to use accessibility query selectors in both Cypress and RTL, unless the text is dynamic. Then testId's in Cypress and a combination of testId's & accessibility query selectors provide the best solution.
It should also be noted that Playwright and Cypress test-generator tools select by accessibility query selectors.
I thought a lot for a few days before answering this question and I even got to do some tests, and after that time I came to the conclusion that the Cypress approach is the best.
The main reason that led me to this answer was that when the testing library says that we should test what the user actually sees, it is already applicable in Cypress even when we use a data-testid, because let's suppose you have a button that exists in the DOM, but it is not visible when you select this button, with the data-testid when you try to click in this button Cypress will return an error saying that the button is not visible and if you really want to do this action you must apply force:true. The same happens if the button is not clickable or if there is another element in front of the button.
Cypress already checks by default in click and type actions if the element:
element is into view
it is visible
it is not disabled
it is not detached
it is not readonly
it is not animating
it is not covered
fire the event at a
descendent
Also if you fetch the element by text, placeholder, or class, this does not guarantee that the element is actually visible to the user, as the element can be in the DOM and not be visible to the user for various reasons.
So the best way to make tests easier to maintain, easier to read, and avoid flaky tests is to use the data-testid and whenever possible or necessary combine the location of the element with an assertion to ensure that the element is visible. Example:
cy.get('[data-testid="button"]').should('be.visible')
I hope I had contributed to the discussion and would love to hear other people's points of view.
I would like to know the best design pattern for Selenium for automating large scale SaaS Product.
Looking for all your comments on this.
and for large scale application i preferred keeping my xpath's for web elements in page object file. but my lead wants me to keep xpath's in Properties file and we should access Properties file for every xpath's. Is this a good approach of keeping xpath's in properties file for Large Scale SaaS application?
Your leed wants you to implement Object Repository Pattern.
I think this idea is as old as HP QTP (QuickTest Professional) where it is extensively used - but I may be wrong, it's only my opinion.
In short (a quote from the above link):
Object Repository is a centralized location where we can store objects
information, it acts as interface between Test script and application
in order to identify the objects during the execution.
We always recommend using external file for object repository rather than hard coding the objects and its properties
directly into our code. If you are asking me why this is? Reason is as
it reduces the maintenance effort and provides positive ROI, for
example say any of the object properties change within our application
under test, we can easily change it in external object repository
file, rather than searching and doing updates for that object
individually in the code
Think of a scenario where you have a Webpage and it has multiple
sections, multiple frames and hundreds of WebElements. Obviously you
do not want that once you type the page name and it will give you all
the elements available on the webpage. If there are few elements, it
is fine to have the same structure but if there are many then it is
advisable to divide your page in to different sections for e.g.
header, footer, left navigation, center content and right navigation.
Then categories each WebElement under their parent element.
I think this pattern does not stand in contradiction to the Page Object Pattern, they can both work very well together. It brings greater transparency to the project and forces developers/testers to maintain better readability of the project, which helps in maintaining it in the future.
But the above is only a bit of theory, one may ask how this pattern can help in real life?
Consider a simple example. Let say that there is a piece of code:
public class SomePageObject{
.....
.....
public void doSomething(String value){
findElement( By.xpath("//*[ #class='left-content']//button[ contains( ., 'list-selector' )]") ).click();
wait.until( ExpectedConditions.visibilityOfElementLocated( By.xpath( String.format( "//li[ *[ text() = '%s' ]]", value ))).click();
}
I have seen code like this hundred of times. What do you think about this code ? Yes, it follows the well known Page Object Pattern. But it is horrible.
Looking at this code, can you guess what is it doing? Definitelly No.
What error message will you get in the log when this code will break due to change in UI of second element ? Most likely something like this:
org.openqa.selenium.TimeoutException: Timed out after 30 seconds
waiting for visibility of element located by By.selector: //li[ *[ text() = 'New York' ]]
Can you guess, looking only at this error message, which part of the application it concerns and where it can be found in the code ? No.
An automation engineer can find it in code looking at stack trace but a junior tester who doesn't know java, selenium etc. cannot fix it looking only on the error and a printscreen (if available).
In many cases in order to fix the error, the automation engineer needs to run this test case on a local machine to replicate the issue.
How can it look like using Object Repository Pattern ?
There can be a property file which may look like this:
....
orderPage.citySelectButton=//*[ #class='left-content']//button[ contains( ., 'list-selector' )]
orderPage.citySelectListElement=//li[ *[ text() = '%s' ]]
...
...
and a code which may look like this:
public class SomePageObject{
.....
.....
public void doSomething(String value){
objRepoFacade( "orderPage.citySelectButton" ).click();
objRepoFacade( "orderPage.citySelectListElement", value ).wait().click();
...
)
}
The error message in the log may look like this:
RuntimeException: time out waiting for element: orderPage.citySelectListElement
located by By.selector: //li[ *[ text() = 'New York' ]]
And now even the junior tester, looking only on this error message, is able to easily guess in which part of the application the error occurred, and which exactly element is broken. The tester may be trained how to inspect an element on the page using the developer console (F12), correct the selector in the procerties file, and fix the issue on his own without the help of automation engineer and without touching the code at all.
Preasumbly from your leed's point of view the latter (Object repository) is a better solution because it can employ more junior testers and fewer automation engineers and reduce costs.
I am new to writing intellij plugins, so I apologize in advance if my question might be a bit unclear.
I know that (live) code inspections are achieved via Annotators or LocalInspectionTools. I also know there is an API to write a custom Annotator or Inspection tool and I have seen several examples.
What I do not know (my question): is there a manager/helper/"global inspector" that can provide me with the results of an existing code annotator/inspection process (done by the IDE's plugins or by some 3rd party plugin)?
For instance: I do not want to write a custom Lint annotator/inspection plugin for WebStorm. One can configure JSLint/JSHint inside WebStorm settings. The results of the live inspection can be seen over the current file/current open editor.
I would like to get the results of this live inspection, that occurs in the current open editor (inside my own custom code). For this I am interested in the API to get this annotator/inspector and/or the results it provides.
(I apologize for maybe using annotator and inspection terms in a confusing manner)
If there is another question (which I could not find) that duplicates what I have asked above, please re-direct me.
Thank you in advance!
Andrei.
Unfortunately regular annotating process for the linters is asynchronous so you cannot get the annotation results directly (by calling 'Manager' method).
You can create instances of JSLintInspection, JSHintInspection, etc. and call #createVisitor().visit(File) method but the operation is very slow and you must call it outside of AWT thread.
Also you can try to run the method com.intellij.codeInsight.daemon.impl.DaemonCodeAnalyzerEx#processHighlights but as I mentioned above the annotation results for linters can be not available (or outdated)
I wanted to implement a walkthrough tutorial but to do that I realised I needed to be able to select HTML elements from a property value (eg. name or id), ie get the value of a property from an HTML node. I think there currentlyis no way of getting an element's name in elm: could anybody please confirm? Does that mean I need to add something to virtual-dom package?
No, there is no way to really read a tree of Virtual DOM in Elm. If you look at the source for VirtualDom.elm, you'll see that nearly every function is implemented in native JavaScript, in the Native/VirtualDom.js file.
Sure, you could write some kind of native API to cheat the system and inspect the html like you're talking about, but the Virtual DOM was never meant to be used or queried in that way. The model with which you build your view should be the source of truth. Perhaps if you tweaked your design a bit, you would find that you don't really need this requirement after all.
I've read the documentation and understand that this is to be expected:
Scripts are injected into the top-level page and any children with HTML sources, such as iframes. Do not assume that there is only one instance of your script per browser tab.
I'm wondering, though:
Other than iframes, what other elements have "HTML sources" (images? objects?)? The term "HTML sources" is uncomfortably vague to my ears.
Is there any way to detect which element is executing the script?
I've filtered out iframes by determining that window === window.top, as recommended, but other elements are still executing the script and it's executing a lot more than I'd like.
Thanks.
It's really my own fault that I'm answering my own question because I didn't really provide enough information in my question. In my defense, I didn't know at the time that I was providing too little information.
Anyway, while traveling down the road to a solution for this, I asked a question on Apple's dev forum and included the following bit of key info:
Everything in the script occurs on the beforeload event of the document (or was supposed to).
What I learned was that the beforeload event only fires for subresources within the document. Not for the document (or window) itself. I removed the event handler and made sure that the script was applied as a start script (it was). I'd already applied the test for the window as top window so I was covered. Now my injection script only fires once.
Other HTML sources may be frames or object tags (with HTML contents). I don't think it can be anything else. However, to the extent of my knowledge, they should also be filtered off with window === window.top. Try console.loging the document.location variable to see which URL runs your injected script, and maybe you can find what loads them.