Skip to content

Commit dbfc7c6

Browse files
authored
feat(java): ⚡ updated mouse related actions (#959)
1 parent 6db08b2 commit dbfc7c6

File tree

8 files changed

+317
-94
lines changed

8 files changed

+317
-94
lines changed

core-java/src/main/java/io/github/boykaframework/actions/CommonActions.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -179,7 +179,7 @@ public static void performMobileGestures (final Collection<Sequence> sequences)
179179
private static void highlight (final String color, final WebElement element) {
180180
if (getSession ().getWebSetting ()
181181
.isHighlight ()) {
182-
final var style = element.getAttribute ("style");
182+
final var style = element.getDomAttribute ("style");
183183
getSession ().setSharedData (HIGHLIGHT_STYLE, style);
184184
withDriver ().executeScript ("arguments[0].setAttribute('style', arguments[1] + arguments[2]);", element,
185185
style, format ("color: {0}; border: 3px solid {0};", color));

core-java/src/main/java/io/github/boykaframework/actions/elements/ClickableActions.java

Lines changed: 63 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -18,23 +18,18 @@
1818

1919
import static io.github.boykaframework.actions.CommonActions.pause;
2020
import static io.github.boykaframework.actions.CommonActions.performElementAction;
21-
import static io.github.boykaframework.actions.elements.ElementFinder.find;
22-
import static io.github.boykaframework.enums.ApplicationType.WEB;
21+
import static io.github.boykaframework.actions.CommonActions.performMobileGestures;
2322
import static io.github.boykaframework.enums.ListenerType.CLICKABLE_ACTION;
24-
import static io.github.boykaframework.enums.PlatformType.IOS;
25-
import static io.github.boykaframework.enums.WaitStrategy.CLICKABLE;
2623
import static io.github.boykaframework.manager.ParallelSession.getSession;
27-
import static io.github.boykaframework.utils.Validator.validateDelay;
24+
import static java.util.Collections.singletonList;
2825
import static java.util.Optional.ofNullable;
2926
import static org.apache.logging.log4j.LogManager.getLogger;
3027

3128
import io.github.boykaframework.actions.interfaces.elements.IClickableActions;
3229
import io.github.boykaframework.actions.interfaces.listeners.elements.IClickableActionsListener;
3330
import io.github.boykaframework.builders.Locator;
34-
import io.github.boykaframework.enums.PlatformType;
3531
import org.apache.logging.log4j.Logger;
3632
import org.openqa.selenium.WebElement;
37-
import org.openqa.selenium.interactions.Actions;
3833

3934
/**
4035
* Handles all mouse related actions
@@ -68,16 +63,11 @@ public void click () {
6863
LOGGER.traceEntry ();
6964
LOGGER.info ("Clicking on element: {}", this.locator.getName ());
7065
ofNullable (this.listener).ifPresent (l -> l.onClick (this.locator));
71-
final var session = getSession ();
72-
if (session.getPlatformType () == PlatformType.WEB || (session.getMobileSetting ()
73-
.getDevice ()
74-
.getApplication ()
75-
.getType () == WEB && session.getPlatformType () == IOS)) {
76-
pause (this.delaySetting.getBeforeClick ());
77-
performElementAction (WebElement::click, this.locator);
78-
} else {
79-
tap ();
80-
}
66+
pause (this.delaySetting.getBeforeClick ());
67+
MouseActionBuilder.builder ()
68+
.sourceLocator (this.locator)
69+
.build ()
70+
.click ();
8171
LOGGER.traceExit ();
8272
}
8373

@@ -86,12 +76,10 @@ public void clickAndHold () {
8676
LOGGER.traceEntry ();
8777
LOGGER.info ("Click and hold on element: {}", this.locator.getName ());
8878
ofNullable (this.listener).ifPresent (l -> l.onClickAndHold (this.locator));
89-
performElementAction ((driver, element) -> {
90-
final var actions = new Actions (driver);
91-
actions.pause (validateDelay (this.delaySetting.getBeforeClick ()))
92-
.clickAndHold (element)
93-
.perform ();
94-
}, this.locator);
79+
MouseActionBuilder.builder ()
80+
.sourceLocator (this.locator)
81+
.build ()
82+
.clickAndHold ();
9583
LOGGER.traceExit ();
9684
}
9785

@@ -100,12 +88,10 @@ public void doubleClick () {
10088
LOGGER.traceEntry ();
10189
LOGGER.info ("Double Click on element: {}", this.locator.getName ());
10290
ofNullable (this.listener).ifPresent (l -> l.onDoubleClick (this.locator));
103-
performElementAction ((driver, element) -> {
104-
final var actions = new Actions (driver);
105-
actions.pause (validateDelay (this.delaySetting.getBeforeClick ()))
106-
.doubleClick (element)
107-
.perform ();
108-
}, this.locator);
91+
MouseActionBuilder.builder ()
92+
.sourceLocator (this.locator)
93+
.build ()
94+
.doubleClick ();
10995
LOGGER.traceExit ();
11096
}
11197

@@ -114,12 +100,10 @@ public void dragTo (final Locator destination) {
114100
LOGGER.traceEntry ();
115101
LOGGER.info ("Drag and Drop on element: {} , {}", this.locator.getName (), destination.getName ());
116102
ofNullable (this.listener).ifPresent (l -> l.onDragTo (this.locator, destination));
117-
performElementAction ((driver, element) -> {
118-
final var actions = new Actions (driver);
119-
actions.pause (validateDelay (this.delaySetting.getBeforeMouseMove ()))
120-
.dragAndDrop (element, find (destination, CLICKABLE))
121-
.perform ();
122-
}, this.locator);
103+
MouseActionBuilder.builder ()
104+
.sourceLocator (this.locator)
105+
.build ()
106+
.dragAndDrop (destination);
123107
LOGGER.traceExit ();
124108
}
125109

@@ -128,12 +112,34 @@ public void hover () {
128112
LOGGER.traceEntry ();
129113
LOGGER.info ("Hover on element: {}", this.locator.getName ());
130114
ofNullable (this.listener).ifPresent (l -> l.onHover (this.locator));
131-
performElementAction ((driver, element) -> {
132-
final var actions = new Actions (driver);
133-
actions.pause (validateDelay (this.delaySetting.getBeforeMouseMove ()))
134-
.moveToElement (element)
135-
.perform ();
136-
}, this.locator);
115+
MouseActionBuilder.builder ()
116+
.sourceLocator (this.locator)
117+
.build ()
118+
.moveTo ();
119+
LOGGER.traceExit ();
120+
}
121+
122+
@Override
123+
public void pressBackButton () {
124+
LOGGER.traceEntry ();
125+
LOGGER.info ("Pressing the Mouse Back button...");
126+
ofNullable (this.listener).ifPresent (IClickableActionsListener::onPressBackButton);
127+
final var sequence = MouseActionBuilder.builder ()
128+
.build ()
129+
.backButtonClick ();
130+
performMobileGestures (singletonList (sequence));
131+
LOGGER.traceExit ();
132+
}
133+
134+
@Override
135+
public void pressForwardButton () {
136+
LOGGER.traceEntry ();
137+
LOGGER.info ("Pressing the Mouse Forward button...");
138+
ofNullable (this.listener).ifPresent (IClickableActionsListener::onPressForwardButton);
139+
final var sequence = MouseActionBuilder.builder ()
140+
.build ()
141+
.forwardButtonClick ();
142+
performMobileGestures (singletonList (sequence));
137143
LOGGER.traceExit ();
138144
}
139145

@@ -142,12 +148,22 @@ public void rightClick () {
142148
LOGGER.traceEntry ();
143149
LOGGER.info ("Right Click on element: {}", this.locator.getName ());
144150
ofNullable (this.listener).ifPresent (l -> l.onRightClick (this.locator));
145-
performElementAction ((driver, element) -> {
146-
final var actions = new Actions (driver);
147-
actions.pause (validateDelay (this.delaySetting.getBeforeClick ()))
148-
.contextClick (element)
149-
.perform ();
150-
}, this.locator);
151+
MouseActionBuilder.builder ()
152+
.sourceLocator (this.locator)
153+
.build ()
154+
.rightClick ();
155+
LOGGER.traceExit ();
156+
}
157+
158+
@Override
159+
public void scrollToElement () {
160+
LOGGER.traceEntry ();
161+
LOGGER.info ("Scrolling to element: {}", this.locator.getName ());
162+
ofNullable (this.listener).ifPresent (l -> l.onScrollToElement (this.locator));
163+
MouseActionBuilder.builder ()
164+
.sourceLocator (this.locator)
165+
.build ()
166+
.scrollTo ();
151167
LOGGER.traceExit ();
152168
}
153169

Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
/*
2+
* MIT License
3+
*
4+
* Copyright (c) 2024, Boyka Framework
5+
*
6+
* Permission is hereby granted, free of charge, to any person obtaining a copy
7+
* of this software and associated documentation files (the "Software"), to deal
8+
* in the Software without restriction, including without limitation the rights
9+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10+
* copies of the Software, and to permit persons to whom the Software is
11+
* furnished to do so, subject to the following conditions:
12+
*
13+
* The above copyright notice and this permission notice shall be included in all
14+
* copies or substantial portions of the Software.
15+
*/
16+
17+
package io.github.boykaframework.actions.elements;
18+
19+
import static io.github.boykaframework.actions.CommonActions.performDriverAction;
20+
import static io.github.boykaframework.actions.CommonActions.performElementAction;
21+
import static io.github.boykaframework.actions.elements.ElementFinder.find;
22+
import static io.github.boykaframework.enums.Message.ELEMENT_CANNOT_BE_NULL;
23+
import static io.github.boykaframework.enums.WaitStrategy.CLICKABLE;
24+
import static io.github.boykaframework.manager.ParallelSession.getSession;
25+
import static io.github.boykaframework.utils.Validator.requireNonNull;
26+
import static java.time.Duration.ofMillis;
27+
import static java.util.Objects.isNull;
28+
import static org.openqa.selenium.interactions.PointerInput.Kind.MOUSE;
29+
import static org.openqa.selenium.interactions.PointerInput.MouseButton.BACK;
30+
import static org.openqa.selenium.interactions.PointerInput.MouseButton.FORWARD;
31+
32+
import java.util.function.BiFunction;
33+
34+
import io.github.boykaframework.builders.Locator;
35+
import lombok.Builder;
36+
import org.openqa.selenium.interactions.Actions;
37+
import org.openqa.selenium.interactions.Pause;
38+
import org.openqa.selenium.interactions.PointerInput;
39+
import org.openqa.selenium.interactions.Sequence;
40+
41+
/**
42+
* Handle all the mouse specific actions.
43+
*
44+
* @author Wasiq Bhamla
45+
* @since 27-Dec-2024
46+
*/
47+
@Builder
48+
public class MouseActionBuilder {
49+
private Locator sourceLocator;
50+
51+
Sequence backButtonClick () {
52+
return mouseAction (BACK);
53+
}
54+
55+
void click () {
56+
performElementAction ((d, e) -> new Actions (d).click (e)
57+
.perform (), this.sourceLocator);
58+
}
59+
60+
void clickAndHold () {
61+
performElementAction ((d, e) -> new Actions (d).clickAndHold (e)
62+
.perform (), this.sourceLocator);
63+
}
64+
65+
void doubleClick () {
66+
performElementAction ((d, e) -> new Actions (d).doubleClick (e)
67+
.perform (), this.sourceLocator);
68+
}
69+
70+
void dragAndDrop (final Locator targetLocator) {
71+
final var targetElement = find (requireNonNull (targetLocator, ELEMENT_CANNOT_BE_NULL), CLICKABLE);
72+
performElementAction ((d, e) -> new Actions (d).dragAndDrop (e, targetElement)
73+
.perform (), this.sourceLocator);
74+
}
75+
76+
Sequence forwardButtonClick () {
77+
return mouseAction (FORWARD);
78+
}
79+
80+
void moveTo () {
81+
performElementAction ((d, e) -> new Actions (d).moveToElement (e)
82+
.perform (), this.sourceLocator);
83+
}
84+
85+
void rightClick () {
86+
if (isNull (this.sourceLocator)) {
87+
performDriverAction ((d) -> new Actions (d).contextClick ()
88+
.perform ());
89+
} else {
90+
performElementAction ((d, e) -> new Actions (d).contextClick (e)
91+
.perform (), this.sourceLocator);
92+
}
93+
}
94+
95+
void scrollTo () {
96+
performElementAction ((d, e) -> new Actions (d).scrollToElement (e)
97+
.perform (), this.sourceLocator);
98+
}
99+
100+
private Sequence composeMouseSequence (final BiFunction<PointerInput, Sequence, Sequence> steps) {
101+
final var mouse = new PointerInput (MOUSE, "Default Mouse");
102+
final var sequence = new Sequence (mouse, 0);
103+
return steps.apply (mouse, sequence);
104+
}
105+
106+
private Sequence mouseAction (final PointerInput.MouseButton button) {
107+
final var delaySetting = getSession ().getSetting ()
108+
.getUi ()
109+
.getDelay ();
110+
111+
return composeMouseSequence ((mouse, steps) -> {
112+
steps.addAction (mouse.createPointerDown (button.asArg ()));
113+
steps.addAction (new Pause (mouse, ofMillis (delaySetting.getBeforeSwipe ())));
114+
steps.addAction (mouse.createPointerUp (button.asArg ()));
115+
return steps;
116+
});
117+
}
118+
}

core-java/src/main/java/io/github/boykaframework/actions/interfaces/elements/IClickableActions.java

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,11 +43,26 @@ public interface IClickableActions extends IFingersActions {
4343
*/
4444
void hover ();
4545

46+
/**
47+
* Presses the back button on Mouse.
48+
*/
49+
void pressBackButton ();
50+
51+
/**
52+
* Presses the forward button on Mouse.
53+
*/
54+
void pressForwardButton ();
55+
4656
/**
4757
* RightClick on element
4858
*/
4959
void rightClick ();
5060

61+
/**
62+
* Scroll to element.
63+
*/
64+
void scrollToElement ();
65+
5166
/**
5267
* Submit the element.
5368
*/

core-java/src/main/java/io/github/boykaframework/actions/interfaces/listeners/elements/IClickableActionsListener.java

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,20 @@ default void onHover (final Locator locator) {
7272
// not implemented.
7373
}
7474

75+
/**
76+
* Handles the pressBackButton method.
77+
*/
78+
default void onPressBackButton () {
79+
// not implemented.
80+
}
81+
82+
/**
83+
* Handles the pressForwardButton method.
84+
*/
85+
default void onPressForwardButton () {
86+
// not implemented.
87+
}
88+
7589
/**
7690
* Handle right click method.
7791
*
@@ -81,6 +95,15 @@ default void onRightClick (final Locator locator) {
8195
// not implemented.
8296
}
8397

98+
/**
99+
* Scroll to the element.
100+
*
101+
* @param locator locator of the element.
102+
*/
103+
default void onScrollToElement (final Locator locator) {
104+
// not implemented.
105+
}
106+
84107
/**
85108
* Handle submit method.
86109
*

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@
5454
"lerna": "8.1.9",
5555
"lerna-changelog": "^2.2.0",
5656
"lerna-version": "^6.6.2",
57-
"lint-staged": "^15.2.11",
57+
"lint-staged": "^15.3.0",
5858
"lodash": "^4.17.21",
5959
"nx": "^20.3.0",
6060
"prettier": "^3.4.2",

0 commit comments

Comments
 (0)