Comments (10)
Serenity/JS interactions that accept custom configuration or overrides typically have a .using(configuration)
method. For example:
await actor.attemptsTo(
Send.a(GetRequest.to('/books/0-688-00230-7').using({ headers: { ... } }),
)
You might want to consider something like this:
Scroll.to(pageElement).using(configuration)
However, some differences between WebdriverIO, Protractor and Playwright might make deciding how this interaction should behave tricky.
For example:
- Playwright allows
scroll
to be configured with just the timeout, so Playwright flavour would most likely need to use the JavaScript API directly (similarly to howExecuteScript
works under the hood) - WebdriverIO uses the standard JavaScript API - https://webdriver.io/docs/api/element/scrollIntoView/
- Protractor doesn't have an API to support this behaviour, so similarly to Playwright - you'd need to rely on evaluating JavaScript in the browser
Another interesting challenge is that the element.scrollIntoView
API is not particularly well designed as it allows either a boolean
or a configuration
object (instead of just the configuration object).
Following that design could make Serenity/JS interaction look awkward:
Scroll.to(pageElement).using(true) // meh
However, since true
is really just an alias for {block: "start", inline: "nearest"}
and false
means scrollIntoViewOptions: {block: "end", inline: "nearest"}
, we could have some pre-set configurations to make people's lives easier:
Scroll.to(pageElement).using(Scroll.Top)
// where Scroll.Top == `{block: "start", inline: "nearest"}`
Alternatively, we could have alias methods on Scroll itself:
Scroll.toTopOf(pageElement)
// alias for Scroll.to(pageElement).using({block: "start", inline: "nearest"})
from serenity-js.
Click
relies on whatever a given web integration tool considers the "default scrolling behaviour". If you'd like to use a different behaviour, then you could introduce custom interactions and then compose them into a task:
const MyClick = (pageElement: Answerable<PageElement>) =>
Interaction.where(d`#actor clicks on ${pageElement}`, async actor => {
const element = await actor.answer(pageElement);
// note no scrolling
await element.click();
})
const MyScrollAndClick = (element: Answerable<PageElement>) =>
Task.where(d`#actor clicks on ${ element }`,
Scroll.toCentreOf(element), // as discussed previously
MyClick(element),
)
Another alternative is to:
- make the scrolling behaviour of the built-in
Click
configurable - override the default behaviour of web integration tools to provide different defaults
- or remove scrolling behaviour from
Click
altogether, relying instead on developers to addScroll
when needed
from serenity-js.
Certainly, you can use script injection:
import { Answerable, d, Interaction } from '@serenity-js/core'
import { BrowseTheWeb, PageElement } from '@serenity-js/web'
const ScrollToTopOf = (pageElement: Answerable<PageElement>) =>
Interaction.where(d`#actor scrolls to top of ${ pageElement }`, async actor => {
const element = await actor.answer(pageElement);
const page = await BrowseTheWeb.as(actor).currentPage();
await page.executeScript(
function scrollIntoView(nativeElement: any) {
nativeElement.scrollIntoView({block: "start", inline: "nearest"});
},
element,
)
})
from serenity-js.
Sorry, it was a typo; I've updated the original snippet.
As you can see there, I use Page.executeScript
to inject a function that then calls the native scrollIntoView
, which you can parameterise as per the MDN docs.
from serenity-js.
Click
relies on whatever a given web integration tool considers the "default scrolling behaviour". If you'd like to use a different behaviour, then you could introduce custom interactions and then compose them into a task:const MyClick = (pageElement: Answerable<PageElement>) => Interaction.where(d`#actor clicks on ${pageElement}`, async actor => { const element = await actor.answer(pageElement); // note no scrolling await element.click(); }) const MyScrollAndClick = (element: Answerable<PageElement>) => Task.where(d`#actor clicks on ${ element }`, Scroll.toCentreOf(element), // as discussed previously MyClick(element), )Another alternative is to:
- make the scrolling behaviour of the built-in
Click
configurable- override the default behaviour of web integration tools to provide different defaults
- or remove scrolling behaviour from
Click
altogether, relying instead on developers to addScroll
when needed
Yes, it works. Thanks @jan-molak 😄
from serenity-js.
I like this idea! However, some differences across the supported web integration tools make the implementation a bit more challenging.
You can see the first attempt at implementing this feature at #1235
Happy to guide you through raising a PR if this feature is something you'd like to pick up.
from serenity-js.
Indeed, I'm interested in working on this. I would greatly appreciate your guidance in creating a custom interaction that mirrors the Click activity. This will allow me to explore and experiment with the scrollIntoView behavior within this custom activity, which I'll refer to as "CustomClick."
from serenity-js.
Hi @jan-molak,
While I'm currently working on this, could you propose an alternative solution for this issue, specially tailored for a Serenity + Webdriverio setup? I'm in the process of implementing Serenity/JS in one of my projects, and I've encountered an issue with the scrollIntoView method used within the Click interaction.
The problem is that scrollIntoView places the target element at the top of the page. Consequently, the element I want to click on gets positioned behind a navigation bar, and the click action is intercepted by two overlapping elements.
from serenity-js.
Certainly, you can use script injection:
import { Answerable, d, Interaction } from '@serenity-js/core' import { BrowseTheWeb, PageElement } from '@serenity-js/web' const ScrollToTopOf = (pageElement: Answerable<PageElement>) => Interaction.where(d`#actor scrolls to top of ${ pageElement }`, async actor => { const element = await actor.answer(pageElement); const page = await BrowseTheWeb.as(actor).currentPage(); await page.executeScript( function scrollIntoView(element: any) { element.scrollIntoView({block: "start", inline: "nearest"}); }, await field, ) })
@jan-molak Would you mind providing clarification regarding the term 'field' in the code snippet you shared? My goal is to ensure that when the scrollIntoView method is employed, the element is centered within the viewport.
from serenity-js.
However, @jan-molak , this approach won't be sufficient for overriding the scrollIntoView()
method used within the Click interaction. How can I address this? As you can observe from the source code of the Click Interaction here:
class Click extends PageElementInteraction_1.PageElementInteraction {
/**
* Instantiates this Interaction.
*
* @param pageElement
* The element to be clicked on
*/
static on(pageElement) {
return new Click(pageElement);
}
constructor(element) {
super((0, core_1.d) `#actor clicks on ${element}`);
this.element = element;
}
/**
* @inheritDoc
*/
async performAs(actor) {
const element = await this.resolve(actor, this element);
await element.scrollIntoView(); // I'm interested in customizing this scrolling behavior within the Click interaction
await element.click();
}
}
In this code, I'd like to emphasize my intent to customize the scrolling behavior within the Click interaction, which is not achievable using the previous approach. How should I proceed?
from serenity-js.
Related Issues (20)
- Serenity/JS should allow to attach files or other attachments to test cases and show them in the html report HOT 1
- Serenity/JS should contain templates with Selenium HOT 1
- Serenity/JS docs should explain how to set window size when using Playwright without Playwright Test
- Serenity/JS should have a "Community" page
- Serenity/JS should automatically propose updates when they're available
- SerenityBDD report still contains dead links in nested spec structures HOT 1
- Serenity/JS should provide the actual value of a note in reports HOT 14
- Serenity/JS Github main README.md - Deadlink to playwright-test in handbook HOT 1
- Serenity Console reporter improvements HOT 10
- How to create a question that would Round number and convert to string.
- Documentation: Official Playwright component testing tutorial
- Getting TypeError [ERR_INVALID_URL]: Invalid URL for Switch.to
- serenity-bdd: The id generated doesn't include the path to the feature, so the context of the feature is lost. HOT 6
- Serenity/JS could show where the changes between releases have been made in SCM tool (git) and highlight areas that have not been retested HOT 2
- After Switching to iFrame not able to click on any other element which is outside of the page HOT 2
- Playwright 1.43.1 not compatible. HOT 1
- serenity-js/cucumber/playwright can't able to run the example tests with NODE v20.12.2 HOT 3
- Serenity/JS own integration test reports for web specs are not complete HOT 2
- Inconsistency when injecting Playwright Browser with mocha as test runner HOT 1
- Inconsistency between WDIO and Playwright with reload and onbeforeunload event
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from serenity-js.