How to add dynamic steps like dynamic data to automation testing - automation

Having test with iterations which is steps like
Iteration 1 click on button in page Iteration 2 click on button in page 2 with same steps and same insertions.
I don’t want to repeat test case.

Test case steps can be dynamic like data by passing actions and func.
For example we need to automate reports page which have buttons for report1, report2, ..., report 10, when any button is clicked, confirming popup is displayed. This test case can be automated in one test case by passing dynamic steps to test case so no need to repeat test case.
For example nuit TestCaseSource returns IEnumerable.
GetTestCaseData IEnumerable<TestCaseData> (){
Yield return new Action( () => report1.Click())
.
.
}
By passing this method to test case like below. There is no need for repeating test cases by dividing iterations to different test cases. Iterations can be passed to test case.
[Test,TestCaseSource(nameof(GetTestCaseData))]
Public void TestCase (Action report){
//Act
NavigateToReport();
report.Invoke();
//Assert
}
Action can be used when no need to return. Func can be used if you need to assert on return.

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')

How to test window scroll event with vue-testing-library?

I want to trigger user interaction for window scroll to change the isScrolled data so that the div class can change. Right now I just test the component when the isScrolled data is changed. Is this the right way to test?
This is acceptable way to test. However, instead of directly setting the isScrolled to true, call the method using the vm as (ensure that you have mocked the document.documentElement.topScroll to something other than zero):
wrapper.vm.onScrollHandler();
Finally, if you need to really test for scroll event, you can manually fire one using the dispatchEvent() method as following:
window.dispatchEvent(new CustomEvent('scroll', { detail: 'anything' }));
You use this and then run your assertion.
On a side note, instead of pictures of your code, paste actual snippets so that they are easy to copy and paste. And, you onScrollHandler can be shortened to:
onScrollHandler() {
this.isScrolled = document.documentElement.topScroll > 0;
}

Karate UI automation, is it possible to make locators dynamic

Thanks Peter for API,Perf karate framework.
Now I am trying UI automation and it looks perfect as of now.
I have below question:
I have a menu bar with 15 items in it. they are named as following:
-Home
-Account
-groups
-settings
etc etc.
Locator for each one is like this "a[name=Home]" , "a[name=Account]", "a[name=groups]" . So ony the part after name= is something that is dynamic in nature. So my question is that is it possible to somehow make this dynamic locator?
I have written a called feature in which i have written steps to login and select a menu item. and I want to pass the menu item from calling feature in json like below:
if I want to click on Account menu
* call read(menuItem.feature) {menuItem: Account}
menuItem.feature looks something like below:
Given url 'xyz'
And input (username, userID)
And input (password, password)
And click("button[name=login]")
And click("a[name=Home]")
Here I want to make Home as dynamic in last click step on menuItem.feature so that I can pass other menu items and reuse all above steps/feature file to login everytime with different menu items passed from calling feature file in json{.
Again its just a query. I have currently written multiple scenarios to click on menu item and then in calling feature I call the called feature with tags like #Home,#account etc. and this works perfectly fine.
Also if there is any other better way to achieve this then please suggest
Yes. Let me put it this way, the things you see such as input('foo', 'bar') is pure JS behind the scenes. So normal programming-language rules apply. For example:
* def dynamic = 'foo'
* def locator = 'a[name=' + dynamic + ']'
* input(locator, 'some value')

How to input the value of a hidden field into a textbox with Test Cafe Studio?

I am attempting to input the value of a hidden field into a textbox in Testcafe, ideally in some sort of manner that simulates typing. Is there a way to do that? Every time I try to do it via javascript it just throws a javascript error.
Essentially I am testing a pretty standard web app - I fill out a form, go page to page, and then must type in a value that is kept in a hidden html input field on the page. I honestly have no idea where to start - every time I've tried to do this with javascript via the "Run Test Cafe Script" it has thrown a javascript error - I really don't know where to start if javascript can't be used.
TestCafe cannot type text in a zero-size input element. I suggest you try the Run TestCafe Script action with ClientFunction that puts a value to the input element directly:
const setValue = ClientFunction(() => {
document.querySelector('input[type="hidden"]').value = 'John Smith';
});
await setValue();

Making dynamic code in Cucumber with the Page Object Model

Is there a way perform actions dynamically using Cucumber?
Example:
Feature File:
Scenario: Click all the boxes
Given On the checkbox page
When Click checkboxA
And Click checkboxB
Step Definition:
#When("Click checkboxA")
public void clickCheckBoxA()
{
pageObject.checkBoxA.click();
}
#And("Click checkboxB")
public void clickCheckBoxB()
{
pageObject.checkBoxB.click();
}
In this scenario, there are two very similar step definitions. The reason why there are two different definitions is because each WebElement is defined in the pageObject Class. Is there a way to dynamically pass which checkbox we want to click, rather than having two separate methods performing the same action?
The only way I can think to do this is by passing a selector as a parameter in the feature step and instantiating the webElement within the step definition method. But that seems like bad practice to me.
Click is your step. It should not be unique for each item you may want to click. You should match what you want to click with a regular expression. The following combines your two steps into one.
#When("^Click (.*)$")
public void clickElement(String elementToClick) {
switch (elementToClick) {
case "checkBoxA":
pageObject.checkBoxA.click();
case "checkBoxB":
pageObject.checkBoxB.click();
}
}
I'd suggest using a smarter regex match (this one is lazy and sloppy) and you could also create a new variable for the element to be clicked, assign its value to your existing element in each case and have a single call to click() after the switch statement.
Regarding your question of doing this "dynamically," you cannot do so in Java (I think you were thinking of having a single line in the example I gave above of pageObject.elementToClick.click();?) because it's a compiled programming language; your code can't be altered at runtime.
I would prefer to use #mike's solution, but in some cases I tend to create a locator as string in POM so that it reduces lines of code in the step definition.
Feature File:
Scenario: Click all the boxes
Given On the checkbox page
When Click checkbox A
And Click checkbox B
POM:
private String checkBox = "//input[text()='checkBox%s']";
Step Definition:
#When("Click checkbox (.*)")
public void handleCheckBox(String checkBoxName) {
driver.findElement(By.xpath(String.format(checkBox, checkBoxName))).click();
}