Using an attribute value from one element locator as a dependency to another locator #2412
-
Hi there, I'm a new user to serenity-js and I"m prototyping it as the de facto tool to do end to end testing for the company I'm with. To start with it's an amazing tool and I like using it so far. I have been looking at your documentation regarding querying on the page, for reference I'm looking at this https://serenity-js.org/handbook/web-testing/page-element-query-language/#retrieving-text-of-multiple-elements. I have this use case for an app I'm testing and I'm wondering what could be the best approach to use here. I detail my use case below: Sample HTML
In terms of the UI these items appear beside each other but in terms of the html source they are a good bit away from each other if that makes sense. My ambition with the above would be to do something like the following:
I wanted to have this as a questions api as it would be something that could be used over and over again, albeit the approach may raise eyebrows in terms of best practices it would be very handy in the case of the above. For example the signature of the api would be something like so:
Would any have any suggestions on best approaches to solve this? Many thanks for any input regarding the above. |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment 2 replies
-
Sure, the way you want to approach it makes perfect sense. Here's how you can do it step by step. Getting all the labelsimport { PageElements, By } from '@serenity-js/web'
const labels = () =>
PageElements.located(By.css('[data-automation-id="formLabel"]'))
.describedAs('labels') Getting a label by its text contentimport { PageElements, By, Text } from '@serenity-js/web'
import { includes } from '@serenity-js/assertions'
const labels = () =>
PageElements.located(By.css('[data-automation-id="formLabel"]'))
.describedAs('labels')
const labelCalled = (name: string) =>
labels()
.where(Text, includes(name))
.first() Getting and attributeimport { Attribute, PageElements, By, Text } from '@serenity-js/web'
import { includes } from '@serenity-js/assertions'
const labels = () =>
PageElements.located(By.css('[data-automation-id="formLabel"]'))
.describedAs('labels')
const labelCalled = (name: string) =>
labels()
.where(Text, includes(name))
.first()
const inputIdFor = (labelName: string) =>
Attribute.called('for')
.of(labelCalled(labelName)) Getting all the inputsimport { PageElements, By } from '@serenity-js/web'
const inputs = () =>
PageElements.located(By.css('[data-automation-id="textInputBox"]'))
.describedAs('inputs') Getting an input based on its label textThe first way to get an input based on its label text is to use the import { Attribute, PageElements, By, Text } from '@serenity-js/web'
import { includes } from '@serenity-js/assertions'
const labels = () =>
PageElements.located(By.css('[data-automation-id="formLabel"]'))
.describedAs('labels')
const labelCalled = (name: string) =>
labels()
.where(Text, includes(name))
.first()
const inputIdFor = (labelName: string) =>
Attribute.called('for')
.of(labelCalled(labelName))
const inputs = () =>
PageElements.located(By.css('[data-automation-id="textInputBox"]'))
.describedAs('inputs')
const inputCalled = (name: string) =>
inputs()
.where(Attribute.called('id'), equals( inputIdFor(name) ))
.first()
.describedAs(`input for ${name}`) The other way to do it is to generate the CSS selector dynamically (note that all const inputCalled = (name: string) =>
PageElements.located(By.id(inputIdFor(name)))
.describedAs(`input for ${name}`)
.first() |
Beta Was this translation helpful? Give feedback.
Sure, the way you want to approach it makes perfect sense.
Here's how you can do it step by step.
Getting all the labels
Getting a label by its text content
Getting and attribute