Browse Source

web: Use SyntheticMouseEvent as a type for a value in mouse events listeners (#862)

* web: Use SyntheticMouseEvent as a type for a value in mouse events listeners

* add tests for mouse event

Co-authored-by: Oleksandr Karpovich <oleksandr.karpovich@jetbrains.com>
pull/893/head
Oleksandr Karpovich 3 years ago committed by GitHub
parent
commit
ac76dc5f0e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 199
      web/core/src/jsMain/kotlin/org/jetbrains/compose/web/attributes/EventsListenerBuilder.kt
  2. 33
      web/core/src/jsMain/kotlin/org/jetbrains/compose/web/attributes/InputAttrsBuilder.kt
  3. 2
      web/core/src/jsMain/kotlin/org/jetbrains/compose/web/attributes/TextAreaAttrsBuilder.kt
  4. 24
      web/core/src/jsMain/kotlin/org/jetbrains/compose/web/events/SyntheticEvent.kt
  5. 67
      web/core/src/jsMain/kotlin/org/jetbrains/compose/web/events/SyntheticMouseEvent.kt
  6. 4
      web/core/src/jsMain/kotlin/org/jetbrains/compose/web/events/WrappedEvent.kt
  7. 73
      web/integration-core/src/jsMain/kotlin/androidx/compose/web/sample/tests/EventsTests.kt
  8. 62
      web/integration-core/src/jvmTest/kotlin/org/jetbrains/compose/web/tests/integration/EventTests.kt

199
web/core/src/jsMain/kotlin/org/jetbrains/compose/web/attributes/EventsListenerBuilder.kt

@ -1,45 +1,148 @@
package org.jetbrains.compose.web.attributes package org.jetbrains.compose.web.attributes
import org.jetbrains.compose.web.events.WrappedCheckBoxInputEvent import androidx.compose.web.events.SyntheticDragEvent
import androidx.compose.web.events.SyntheticMouseEvent
import androidx.compose.web.events.SyntheticWheelEvent
import org.jetbrains.compose.web.events.WrappedClipboardEvent import org.jetbrains.compose.web.events.WrappedClipboardEvent
import org.jetbrains.compose.web.events.WrappedDragEvent
import org.jetbrains.compose.web.events.WrappedEvent import org.jetbrains.compose.web.events.WrappedEvent
import org.jetbrains.compose.web.events.WrappedFocusEvent import org.jetbrains.compose.web.events.WrappedFocusEvent
import org.jetbrains.compose.web.events.WrappedInputEvent import org.jetbrains.compose.web.events.WrappedInputEvent
import org.jetbrains.compose.web.events.WrappedKeyboardEvent import org.jetbrains.compose.web.events.WrappedKeyboardEvent
import org.jetbrains.compose.web.events.WrappedMouseEvent
import org.jetbrains.compose.web.events.WrappedRadioInputEvent
import org.jetbrains.compose.web.events.WrappedTextInputEvent
import org.jetbrains.compose.web.events.WrappedTouchEvent import org.jetbrains.compose.web.events.WrappedTouchEvent
import org.jetbrains.compose.web.events.WrappedWheelEvent
import org.jetbrains.compose.web.events.GenericWrappedEvent import org.jetbrains.compose.web.events.GenericWrappedEvent
private typealias SyntheticMouseEventListener = (SyntheticMouseEvent) -> Unit
private typealias SyntheticWheelEventListener = (SyntheticWheelEvent) -> Unit
private typealias SyntheticDragEventListener = (SyntheticDragEvent) -> Unit
open class EventsListenerBuilder { open class EventsListenerBuilder {
protected val listeners = mutableListOf<WrappedEventListener<*>>() protected val listeners = mutableListOf<WrappedEventListener<*>>()
fun onCopy(options: Options = Options.DEFAULT, listener: (WrappedClipboardEvent) -> Unit) { /* Mouse Events */
listeners.add(ClipboardEventListener(COPY, options, listener))
private fun createMouseEventListener(
name: String, options: Options, listener: SyntheticMouseEventListener
): MouseEventListener {
return MouseEventListener(
event = name,
options = options,
listener = {
listener(SyntheticMouseEvent(it.nativeEvent))
}
)
} }
fun onCut(options: Options = Options.DEFAULT, listener: (WrappedClipboardEvent) -> Unit) { private fun createMouseWheelEventListener(
listeners.add(ClipboardEventListener(CUT, options, listener)) name: String, options: Options, listener: SyntheticWheelEventListener
): MouseWheelEventListener {
return MouseWheelEventListener(
event = name,
options = options,
listener = {
listener(SyntheticWheelEvent(it.nativeEvent))
}
)
} }
fun onPaste(options: Options = Options.DEFAULT, listener: (WrappedClipboardEvent) -> Unit) { fun onContextMenu(options: Options = Options.DEFAULT, listener: SyntheticMouseEventListener) {
listeners.add(ClipboardEventListener(PASTE, options, listener)) listeners.add(createMouseEventListener(CONTEXTMENU, options, listener))
}
fun onClick(options: Options = Options.DEFAULT, listener: SyntheticMouseEventListener) {
listeners.add(createMouseEventListener(CLICK, options, listener))
}
fun onDoubleClick(options: Options = Options.DEFAULT, listener: SyntheticMouseEventListener) {
listeners.add(createMouseEventListener(DBLCLICK, options, listener))
}
fun onMouseDown(options: Options = Options.DEFAULT, listener: SyntheticMouseEventListener) {
listeners.add(createMouseEventListener(MOUSEDOWN, options, listener))
}
fun onMouseUp(options: Options = Options.DEFAULT, listener: SyntheticMouseEventListener) {
listeners.add(createMouseEventListener(MOUSEUP, options, listener))
}
fun onMouseEnter(options: Options = Options.DEFAULT, listener: SyntheticMouseEventListener) {
listeners.add(createMouseEventListener(MOUSEENTER, options, listener))
}
fun onMouseLeave(options: Options = Options.DEFAULT, listener: SyntheticMouseEventListener) {
listeners.add(createMouseEventListener(MOUSELEAVE, options, listener))
}
fun onMouseMove(options: Options = Options.DEFAULT, listener: SyntheticMouseEventListener) {
listeners.add(createMouseEventListener(MOUSEMOVE, options, listener))
}
fun onMouseOut(options: Options = Options.DEFAULT, listener: SyntheticMouseEventListener) {
listeners.add(createMouseEventListener(MOUSEOUT, options, listener))
}
fun onMouseOver(options: Options = Options.DEFAULT, listener: SyntheticMouseEventListener) {
listeners.add(createMouseEventListener(MOUSEOVER, options, listener))
}
fun onWheel(options: Options = Options.DEFAULT, listener: (SyntheticWheelEvent) -> Unit) {
listeners.add(createMouseWheelEventListener(WHEEL, options, listener))
}
/* Drag Events */
private fun createDragEventListener(
name: String, options: Options, listener: SyntheticDragEventListener
): DragEventListener {
return DragEventListener(
event = name,
options = options,
listener = {
listener(SyntheticDragEvent(it.nativeEvent))
}
)
}
fun onDrag(options: Options = Options.DEFAULT, listener: SyntheticDragEventListener) {
listeners.add(createDragEventListener(DRAG, options, listener))
}
fun onDrop(options: Options = Options.DEFAULT, listener: SyntheticDragEventListener) {
listeners.add(createDragEventListener(DROP, options, listener))
}
fun onDragStart(options: Options = Options.DEFAULT, listener: SyntheticDragEventListener) {
listeners.add(createDragEventListener(DRAGSTART, options, listener))
}
fun onDragEnd(options: Options = Options.DEFAULT, listener: SyntheticDragEventListener) {
listeners.add(createDragEventListener(DRAGEND, options, listener))
}
fun onDragOver(options: Options = Options.DEFAULT, listener: SyntheticDragEventListener) {
listeners.add(createDragEventListener(DRAGOVER, options, listener))
} }
fun onContextMenu(options: Options = Options.DEFAULT, listener: (WrappedMouseEvent) -> Unit) { fun onDragEnter(options: Options = Options.DEFAULT, listener: SyntheticDragEventListener) {
listeners.add(MouseEventListener(CONTEXTMENU, options, listener)) listeners.add(createDragEventListener(DRAGENTER, options, listener))
} }
fun onClick(options: Options = Options.DEFAULT, listener: (WrappedMouseEvent) -> Unit) { fun onDragLeave(options: Options = Options.DEFAULT, listener: SyntheticDragEventListener) {
listeners.add(MouseEventListener(CLICK, options, listener)) listeners.add(createDragEventListener(DRAGLEAVE, options, listener))
} }
fun onDoubleClick(options: Options = Options.DEFAULT, listener: (WrappedMouseEvent) -> Unit) { /* End of Drag Events */
listeners.add(MouseEventListener(DBLCLICK, options, listener))
fun onCopy(options: Options = Options.DEFAULT, listener: (WrappedClipboardEvent) -> Unit) {
listeners.add(ClipboardEventListener(COPY, options, listener))
}
fun onCut(options: Options = Options.DEFAULT, listener: (WrappedClipboardEvent) -> Unit) {
listeners.add(ClipboardEventListener(CUT, options, listener))
}
fun onPaste(options: Options = Options.DEFAULT, listener: (WrappedClipboardEvent) -> Unit) {
listeners.add(ClipboardEventListener(PASTE, options, listener))
} }
fun onGenericInput( fun onGenericInput(
@ -85,38 +188,6 @@ open class EventsListenerBuilder {
listeners.add(KeyboardEventListener(KEYUP, options, listener)) listeners.add(KeyboardEventListener(KEYUP, options, listener))
} }
fun onMouseDown(options: Options = Options.DEFAULT, listener: (WrappedMouseEvent) -> Unit) {
listeners.add(MouseEventListener(MOUSEDOWN, options, listener))
}
fun onMouseUp(options: Options = Options.DEFAULT, listener: (WrappedMouseEvent) -> Unit) {
listeners.add(MouseEventListener(MOUSEUP, options, listener))
}
fun onMouseEnter(options: Options = Options.DEFAULT, listener: (WrappedMouseEvent) -> Unit) {
listeners.add(MouseEventListener(MOUSEENTER, options, listener))
}
fun onMouseLeave(options: Options = Options.DEFAULT, listener: (WrappedMouseEvent) -> Unit) {
listeners.add(MouseEventListener(MOUSELEAVE, options, listener))
}
fun onMouseMove(options: Options = Options.DEFAULT, listener: (WrappedMouseEvent) -> Unit) {
listeners.add(MouseEventListener(MOUSEMOVE, options, listener))
}
fun onMouseOut(options: Options = Options.DEFAULT, listener: (WrappedMouseEvent) -> Unit) {
listeners.add(MouseEventListener(MOUSEOUT, options, listener))
}
fun onMouseOver(options: Options = Options.DEFAULT, listener: (WrappedMouseEvent) -> Unit) {
listeners.add(MouseEventListener(MOUSEOVER, options, listener))
}
fun onWheel(options: Options = Options.DEFAULT, listener: (WrappedWheelEvent) -> Unit) {
listeners.add(MouseWheelEventListener(WHEEL, options, listener))
}
fun onScroll(options: Options = Options.DEFAULT, listener: (WrappedEvent) -> Unit) { fun onScroll(options: Options = Options.DEFAULT, listener: (WrappedEvent) -> Unit) {
listeners.add(WrappedEventListener(SCROLL, options, listener)) listeners.add(WrappedEventListener(SCROLL, options, listener))
} }
@ -157,34 +228,6 @@ open class EventsListenerBuilder {
listeners.add(InputEventListener(BEFOREINPUT, options, listener)) listeners.add(InputEventListener(BEFOREINPUT, options, listener))
} }
fun onDrag(options: Options = Options.DEFAULT, listener: (WrappedDragEvent) -> Unit) {
listeners.add(DragEventListener(DRAG, options, listener))
}
fun onDrop(options: Options = Options.DEFAULT, listener: (WrappedDragEvent) -> Unit) {
listeners.add(DragEventListener(DROP, options, listener))
}
fun onDragStart(options: Options = Options.DEFAULT, listener: (WrappedDragEvent) -> Unit) {
listeners.add(DragEventListener(DRAGSTART, options, listener))
}
fun onDragEnd(options: Options = Options.DEFAULT, listener: (WrappedDragEvent) -> Unit) {
listeners.add(DragEventListener(DRAGEND, options, listener))
}
fun onDragOver(options: Options = Options.DEFAULT, listener: (WrappedDragEvent) -> Unit) {
listeners.add(DragEventListener(DRAGOVER, options, listener))
}
fun onDragEnter(options: Options = Options.DEFAULT, listener: (WrappedDragEvent) -> Unit) {
listeners.add(DragEventListener(DRAGENTER, options, listener))
}
fun onDragLeave(options: Options = Options.DEFAULT, listener: (WrappedDragEvent) -> Unit) {
listeners.add(DragEventListener(DRAGLEAVE, options, listener))
}
fun collectListeners(): List<WrappedEventListener<*>> = listeners fun collectListeners(): List<WrappedEventListener<*>> = listeners
fun addEventListener( fun addEventListener(

33
web/core/src/jsMain/kotlin/org/jetbrains/compose/web/attributes/InputAttrsBuilder.kt

@ -5,42 +5,29 @@
package androidx.compose.web.attributes package androidx.compose.web.attributes
import androidx.compose.web.events.SyntheticEvent
import org.jetbrains.compose.web.attributes.AttrsBuilder import org.jetbrains.compose.web.attributes.AttrsBuilder
import org.jetbrains.compose.web.attributes.InputType import org.jetbrains.compose.web.attributes.InputType
import org.jetbrains.compose.web.attributes.Options import org.jetbrains.compose.web.attributes.Options
import org.w3c.dom.HTMLElement
import org.w3c.dom.HTMLInputElement import org.w3c.dom.HTMLInputElement
import org.w3c.dom.events.Event import org.w3c.dom.events.Event
import org.w3c.dom.events.EventTarget import org.w3c.dom.events.EventTarget
class SyntheticInputEvent<ValueType, Element : HTMLElement>( class SyntheticInputEvent<ValueType, Element : EventTarget>(
val value: ValueType, val value: ValueType,
val target: Element, nativeEvent: Event
val nativeEvent: Event ) : SyntheticEvent<Element>(
) { nativeEvent = nativeEvent
)
val bubbles: Boolean = nativeEvent.bubbles class InputAttrsBuilder<T>(
val cancelable: Boolean = nativeEvent.cancelable val inputType: InputType<T>
val composed: Boolean = nativeEvent.composed ) : AttrsBuilder<HTMLInputElement>() {
val currentTarget: HTMLElement? = nativeEvent.currentTarget.unsafeCast<HTMLInputElement?>()
val eventPhase: Short = nativeEvent.eventPhase
val defaultPrevented: Boolean = nativeEvent.defaultPrevented
val timestamp: Number = nativeEvent.timeStamp
val type: String = nativeEvent.type
val isTrusted: Boolean = nativeEvent.isTrusted
fun preventDefault(): Unit = nativeEvent.preventDefault()
fun stopPropagation(): Unit = nativeEvent.stopPropagation()
fun stopImmediatePropagation(): Unit = nativeEvent.stopImmediatePropagation()
fun composedPath(): Array<EventTarget> = nativeEvent.composedPath()
}
class InputAttrsBuilder<T>(val inputType: InputType<T>) : AttrsBuilder<HTMLInputElement>() {
fun onInput(options: Options = Options.DEFAULT, listener: (SyntheticInputEvent<T, HTMLInputElement>) -> Unit) { fun onInput(options: Options = Options.DEFAULT, listener: (SyntheticInputEvent<T, HTMLInputElement>) -> Unit) {
addEventListener(INPUT, options) { addEventListener(INPUT, options) {
val value = inputType.inputValue(it.nativeEvent) val value = inputType.inputValue(it.nativeEvent)
listener(SyntheticInputEvent(value, it.nativeEvent.target as HTMLInputElement, it.nativeEvent)) listener(SyntheticInputEvent(value, it.nativeEvent))
} }
} }
} }

2
web/core/src/jsMain/kotlin/org/jetbrains/compose/web/attributes/TextAreaAttrsBuilder.kt

@ -17,7 +17,7 @@ class TextAreaAttrsBuilder : AttrsBuilder<HTMLTextAreaElement>() {
) { ) {
addEventListener(INPUT, options) { addEventListener(INPUT, options) {
val text = it.nativeEvent.target.asDynamic().value.unsafeCast<String>() val text = it.nativeEvent.target.asDynamic().value.unsafeCast<String>()
listener(SyntheticInputEvent(text, it.nativeEvent.target as HTMLTextAreaElement, it.nativeEvent)) listener(SyntheticInputEvent(text, it.nativeEvent))
} }
} }
} }

24
web/core/src/jsMain/kotlin/org/jetbrains/compose/web/events/SyntheticEvent.kt

@ -0,0 +1,24 @@
package androidx.compose.web.events
import org.w3c.dom.events.Event
import org.w3c.dom.events.EventTarget
open class SyntheticEvent<Element : EventTarget>(
val nativeEvent: Event
) {
val target: Element = nativeEvent.target.unsafeCast<Element>()
val bubbles: Boolean = nativeEvent.bubbles
val cancelable: Boolean = nativeEvent.cancelable
val composed: Boolean = nativeEvent.composed
val currentTarget: EventTarget? = nativeEvent.currentTarget
val eventPhase: Short = nativeEvent.eventPhase
val defaultPrevented: Boolean = nativeEvent.defaultPrevented
val timestamp: Number = nativeEvent.timeStamp
val type: String = nativeEvent.type
val isTrusted: Boolean = nativeEvent.isTrusted
fun preventDefault(): Unit = nativeEvent.preventDefault()
fun stopPropagation(): Unit = nativeEvent.stopPropagation()
fun stopImmediatePropagation(): Unit = nativeEvent.stopImmediatePropagation()
fun composedPath(): Array<EventTarget> = nativeEvent.composedPath()
}

67
web/core/src/jsMain/kotlin/org/jetbrains/compose/web/events/SyntheticMouseEvent.kt

@ -0,0 +1,67 @@
package androidx.compose.web.events
import org.w3c.dom.DataTransfer
import org.w3c.dom.DragEvent
import org.w3c.dom.HTMLElement
import org.w3c.dom.events.EventTarget
import org.w3c.dom.events.MouseEvent
import org.w3c.dom.events.WheelEvent
/**
* https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent
*/
open class SyntheticMouseEvent(
nativeEvent: MouseEvent
) : SyntheticEvent<EventTarget>(nativeEvent) {
private val mouseEvent = nativeEvent
val altKey: Boolean = nativeEvent.altKey
val button: Short = nativeEvent.button
val buttons: Short = nativeEvent.buttons
val clientX: Int = nativeEvent.clientX
val clientY: Int = nativeEvent.clientY
val ctrlKey: Boolean = nativeEvent.ctrlKey
val metaKey: Boolean = nativeEvent.metaKey
val movementX: Int = nativeEvent.asDynamic().movementX as Int
val movementY: Int = nativeEvent.asDynamic().movementY as Int
val offsetX: Double = nativeEvent.offsetX
val offsetY: Double = nativeEvent.offsetY
val pageX: Double = nativeEvent.pageX
val pageY: Double = nativeEvent.pageY
val region: String? = nativeEvent.region
val relatedTarget: EventTarget? = nativeEvent.relatedTarget
val screenX: Int = nativeEvent.screenX
val screenY: Int = nativeEvent.screenY
val shiftKey: Boolean = nativeEvent.shiftKey
val x: Double = nativeEvent.x
val y: Double = nativeEvent.y
fun getModifierState(keyArg: String): Boolean = mouseEvent.getModifierState(keyArg)
}
/**
* https://developer.mozilla.org/en-US/docs/Web/API/WheelEvent
*/
class SyntheticWheelEvent(
nativeEvent: WheelEvent
) : SyntheticMouseEvent(
nativeEvent
) {
val deltaX: Double = nativeEvent.deltaX
val deltaY: Double = nativeEvent.deltaY
val deltaZ: Double = nativeEvent.deltaZ
val deltaMode: Int = nativeEvent.deltaMode
}
/**
* https://developer.mozilla.org/en-US/docs/Web/API/DragEvent
*/
class SyntheticDragEvent(
nativeEvent: DragEvent
) : SyntheticMouseEvent(
nativeEvent
) {
val dataTransfer: DataTransfer? = nativeEvent.dataTransfer
}

4
web/core/src/jsMain/kotlin/org/jetbrains/compose/web/events/WrappedEvent.kt

@ -18,7 +18,7 @@ interface GenericWrappedEvent<T : Event> {
interface WrappedEvent : GenericWrappedEvent<Event> interface WrappedEvent : GenericWrappedEvent<Event>
open class WrappedMouseEvent( internal open class WrappedMouseEvent(
override val nativeEvent: MouseEvent override val nativeEvent: MouseEvent
) : GenericWrappedEvent<MouseEvent> { ) : GenericWrappedEvent<MouseEvent> {
@ -29,7 +29,7 @@ open class WrappedMouseEvent(
get() = nativeEvent.asDynamic().movementY as Double get() = nativeEvent.asDynamic().movementY as Double
} }
open class WrappedWheelEvent( internal open class WrappedWheelEvent(
override val nativeEvent: WheelEvent override val nativeEvent: WheelEvent
) : GenericWrappedEvent<WheelEvent> ) : GenericWrappedEvent<WheelEvent>

73
web/integration-core/src/jsMain/kotlin/androidx/compose/web/sample/tests/EventsTests.kt

@ -101,4 +101,77 @@ class EventsTests {
} }
}) })
} }
val mouseEnterPlusExtraButtonsPressedUpdatesText by testCase {
var state by remember { mutableStateOf("None") }
P(
attrs = {
style { height(50.px) }
}
) { TestText(state) }
Div(attrs = {
id("box")
style {
backgroundColor("red")
padding(50.px)
width(300.px)
}
onMouseEnter {
val buttonsPressed = mutableListOf<String>()
if (it.altKey) buttonsPressed.add("ALT")
if (it.ctrlKey) buttonsPressed.add("CTRL")
if (it.shiftKey) buttonsPressed.add("SHIFT")
if (it.metaKey) buttonsPressed.add("META")
state = "ENTERED+${buttonsPressed.joinToString(separator = ",")}"
}
}) {
Text("Enter mouse over me with buttons pressed (META, ALT, SHIFT, CTRL)")
}
}
val onMouseContextMenuUpdatesText by testCase {
var state by remember { mutableStateOf("None") }
P(
attrs = {
id("box")
style { height(50.px) }
onContextMenu {
if (it.button == 2.toShort()) {
it.preventDefault()
it.stopImmediatePropagation()
state = "MOUSE CONTEXT MENU"
}
}
}
) { TestText(state) }
}
val displayMouseCoordinates by testCase {
var state by remember { mutableStateOf("None") }
Div(
attrs = {
id("box")
style {
width(200.px)
height(200.px)
backgroundColor("red")
}
onMouseMove {
state = "${it.x},${it.y}|${it.offsetX},${it.offsetY}"
}
}
)
P(
attrs = {
style { height(50.px) }
}
) { TestText(state) }
}
} }

62
web/integration-core/src/jvmTest/kotlin/org/jetbrains/compose/web/tests/integration/EventTests.kt

@ -174,4 +174,66 @@ class EventTests : BaseIntegrationTests() {
driver.waitTextToBe(value = "childInput") driver.waitTextToBe(value = "childInput")
driver.waitTextToBe(textId = "txt2", value = "None") driver.waitTextToBe(textId = "txt2", value = "None")
} }
@ResolveDrivers
fun mouseEnterPlusExtraButtonsPressedUpdatesText(driver: WebDriver) {
driver.openTestPage("mouseEnterPlusExtraButtonsPressedUpdatesText")
driver.waitTextToBe(value = "None")
val box = driver.findElement(By.id("box"))
Actions(driver).moveToElement(box).perform()
driver.waitTextToBe(value = "ENTERED+")
Actions(driver).moveByOffset(0, 100)
.keyDown(Keys.CONTROL)
.moveToElement(box)
.keyUp(Keys.CONTROL)
.perform()
driver.waitTextToBe(value = "ENTERED+CTRL")
Actions(driver).moveByOffset(0, 100)
.keyDown(Keys.SHIFT)
.moveToElement(box)
.keyUp(Keys.SHIFT)
.perform()
driver.waitTextToBe(value = "ENTERED+SHIFT")
Actions(driver).moveByOffset(0, 100)
.keyDown(Keys.ALT)
.moveToElement(box)
.keyUp(Keys.ALT)
.perform()
driver.waitTextToBe(value = "ENTERED+ALT")
}
@ResolveDrivers
fun onMouseContextMenuUpdatesText(driver: WebDriver) {
driver.openTestPage("onMouseContextMenuUpdatesText")
driver.waitTextToBe(value = "None")
val box = driver.findElement(By.id("box"))
Actions(driver).contextClick(box).perform()
driver.waitTextToBe(value = "MOUSE CONTEXT MENU")
}
@ResolveDrivers
fun displayMouseCoordinates(driver: WebDriver) {
driver.openTestPage("displayMouseCoordinates")
driver.waitTextToBe(value = "None")
val box = driver.findElement(By.id("box"))
Actions(driver).moveToElement(box).perform()
driver.waitTextToBe(value = "108,108|100,100")
Actions(driver).moveToElement(box).moveByOffset(-20, -20).perform()
driver.waitTextToBe(value = "88,88|80,80")
}
} }

Loading…
Cancel
Save