Ações de Caneta

Uma representação de uma entrada de ponteiro do tipo caneta stylus para interagir com uma página da web.

Chromium Only

Uma caneta é um tipo de entrada de ponteiro que possui a maior parte do mesmo comportamento que um mouse, mas também pode ter propriedades de evento únicas para uma caneta stylus. Além disso, enquanto um mouse possui 5 botões, uma caneta possui 3 estados equivalentes de botão:

  • 0 — Contato por Toque (o padrão; equivalente a um clique com o botão esquerdo)
  • 2 — Botão do Barril (equivalente a um clique com o botão direito)
  • 5 — Botão de Borracha (atualmente não suportado pelos drivers)

Usando uma Caneta

Selenium v4.2

        WebElement pointerArea = driver.findElement(By.id("pointerArea"));
        new Actions(driver)
                .setActivePointer(PointerInput.Kind.PEN, "default pen")
                .moveToElement(pointerArea)
                .clickAndHold()
                .moveByOffset(2, 2)
                .release()
                .perform();
Show full example
package dev.selenium.actions_api;

import dev.selenium.BaseChromeTest;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.openqa.selenium.By;
import org.openqa.selenium.Rectangle;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.interactions.Actions;
import org.openqa.selenium.interactions.PointerInput;
import org.openqa.selenium.interactions.Sequence;
import org.openqa.selenium.remote.RemoteWebDriver;

import java.time.Duration;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

public class PenTest extends BaseChromeTest {
    @Test
    public void usePen() {
        driver.get("https://www.selenium.dev/selenium/web/pointerActionsPage.html");

        WebElement pointerArea = driver.findElement(By.id("pointerArea"));
        new Actions(driver)
                .setActivePointer(PointerInput.Kind.PEN, "default pen")
                .moveToElement(pointerArea)
                .clickAndHold()
                .moveByOffset(2, 2)
                .release()
                .perform();

        List<WebElement> moves = driver.findElements(By.className("pointermove"));
        Map<String, String> moveTo = getPropertyInfo(moves.get(0));
        Map<String, String> down = getPropertyInfo(driver.findElement(By.className("pointerdown")));
        Map<String, String> moveBy = getPropertyInfo(moves.get(1));
        Map<String, String> up = getPropertyInfo(driver.findElement(By.className("pointerup")));

        Rectangle rect = pointerArea.getRect();

        int centerX = (int) Math.floor(rect.width / 2 + rect.getX());
        int centerY = (int) Math.floor(rect.height / 2 + rect.getY());
        Assertions.assertEquals("-1", moveTo.get("button"));
        Assertions.assertEquals("pen", moveTo.get("pointerType"));
        Assertions.assertEquals(String.valueOf(centerX), moveTo.get("pageX"));
        Assertions.assertEquals(String.valueOf(centerY), moveTo.get("pageY"));
        Assertions.assertEquals("0", down.get("button"));
        Assertions.assertEquals("pen", down.get("pointerType"));
        Assertions.assertEquals(String.valueOf(centerX), down.get("pageX"));
        Assertions.assertEquals(String.valueOf(centerY), down.get("pageY"));
        Assertions.assertEquals("-1", moveBy.get("button"));
        Assertions.assertEquals("pen", moveBy.get("pointerType"));
        Assertions.assertEquals(String.valueOf(centerX + 2), moveBy.get("pageX"));
        Assertions.assertEquals(String.valueOf(centerY + 2), moveBy.get("pageY"));
        Assertions.assertEquals("0", up.get("button"));
        Assertions.assertEquals("pen", up.get("pointerType"));
        Assertions.assertEquals(String.valueOf(centerX + 2), up.get("pageX"));
        Assertions.assertEquals(String.valueOf(centerY + 2), up.get("pageY"));
    }

    @Test
    public void setPointerEventProperties() {
        driver.get("https://selenium.dev/selenium/web/pointerActionsPage.html");

        WebElement pointerArea = driver.findElement(By.id("pointerArea"));
        PointerInput pen = new PointerInput(PointerInput.Kind.PEN, "default pen");
        PointerInput.PointerEventProperties eventProperties = PointerInput.eventProperties()
                .setTiltX(-72)
                .setTiltY(9)
                .setTwist(86);
        PointerInput.Origin origin = PointerInput.Origin.fromElement(pointerArea);

        Sequence actionListPen = new Sequence(pen, 0)
                .addAction(pen.createPointerMove(Duration.ZERO, origin, 0, 0))
                .addAction(pen.createPointerDown(0))
                .addAction(pen.createPointerMove(Duration.ZERO, origin, 2, 2, eventProperties))
                .addAction(pen.createPointerUp(0));

        ((RemoteWebDriver) driver).perform(Collections.singletonList(actionListPen));

        List<WebElement> moves = driver.findElements(By.className("pointermove"));
        Map<String, String> moveTo = getPropertyInfo(moves.get(0));
        Map<String, String> down = getPropertyInfo(driver.findElement(By.className("pointerdown")));
        Map<String, String> moveBy = getPropertyInfo(moves.get(1));
        Map<String, String> up = getPropertyInfo(driver.findElement(By.className("pointerup")));

        Rectangle rect = pointerArea.getRect();
        int centerX = (int) Math.floor(rect.width / 2 + rect.getX());
        int centerY = (int) Math.floor(rect.height / 2 + rect.getY());
        Assertions.assertEquals("-1", moveTo.get("button"));
        Assertions.assertEquals("pen", moveTo.get("pointerType"));
        Assertions.assertEquals(String.valueOf(centerX), moveTo.get("pageX"));
        Assertions.assertEquals(String.valueOf(centerY), moveTo.get("pageY"));
        Assertions.assertEquals("0", down.get("button"));
        Assertions.assertEquals("pen", down.get("pointerType"));
        Assertions.assertEquals(String.valueOf(centerX), down.get("pageX"));
        Assertions.assertEquals(String.valueOf(centerY), down.get("pageY"));
        Assertions.assertEquals("-1", moveBy.get("button"));
        Assertions.assertEquals("pen", moveBy.get("pointerType"));
        Assertions.assertEquals(String.valueOf(centerX + 2), moveBy.get("pageX"));
        Assertions.assertEquals(String.valueOf(centerY + 2), moveBy.get("pageY"));
        Assertions.assertEquals("-72", moveBy.get("tiltX"));
        Assertions.assertEquals("9", moveBy.get("tiltY"));
        Assertions.assertEquals("86", moveBy.get("twist"));
        Assertions.assertEquals("0", up.get("button"));
        Assertions.assertEquals("pen", up.get("pointerType"));
        Assertions.assertEquals(String.valueOf(centerX + 2), up.get("pageX"));
        Assertions.assertEquals(String.valueOf(centerY + 2), up.get("pageY"));
    }

    private Map<String, String> getPropertyInfo(WebElement element) {
        String text = element.getText();
        text = text.substring(text.indexOf(' ') + 1);

        return Arrays.stream(text.split(", "))
                .map(s -> s.split(": "))
                .collect(Collectors.toMap(
                        a -> a[0],
                        a -> a[1]
                ));
    }
}

Selenium v4.2

    pointer_area = driver.find_element(By.ID, "pointerArea")
    pen_input = PointerInput(POINTER_PEN, "default pen")
    action = ActionBuilder(driver, mouse=pen_input)
    action.pointer_action\
        .move_to(pointer_area)\
        .pointer_down()\
        .move_by(2, 2)\
        .pointer_up()
    action.perform()
Show full example
import math

from selenium.webdriver.common.actions.action_builder import ActionBuilder
from selenium.webdriver.common.actions.interaction import POINTER_PEN
from selenium.webdriver.common.actions.pointer_input import PointerInput
from selenium.webdriver.common.by import By


def test_use_pen(driver):
    driver.get('https://www.selenium.dev/selenium/web/pointerActionsPage.html')

    pointer_area = driver.find_element(By.ID, "pointerArea")
    pen_input = PointerInput(POINTER_PEN, "default pen")
    action = ActionBuilder(driver, mouse=pen_input)
    action.pointer_action\
        .move_to(pointer_area)\
        .pointer_down()\
        .move_by(2, 2)\
        .pointer_up()
    action.perform()

    moves = driver.find_elements(By.CLASS_NAME, "pointermove")
    move_to = properties(moves[0])
    down = properties(driver.find_element(By.CLASS_NAME, "pointerdown"))
    move_by = properties(moves[1])
    up = properties(driver.find_element(By.CLASS_NAME, "pointerup"))

    rect = pointer_area.rect
    center_x = rect["x"] + rect["width"] / 2
    center_y = rect["y"] + rect["height"] / 2

    assert move_to["button"] == "-1"
    assert move_to["pointerType"] == "pen"
    assert move_to["pageX"] == str(math.floor(center_x))
    assert move_to["pageY"] == str(math.floor(center_y))
    assert down["button"] == "0"
    assert down["pointerType"] == "pen"
    assert down["pageX"] == str(math.floor(center_x))
    assert down["pageY"] == str(math.floor(center_y))
    assert move_by["button"] == "-1"
    assert move_by["pointerType"] == "pen"
    assert move_by["pageX"] == str(math.floor(center_x + 2))
    assert move_by["pageY"] == str(math.floor(center_y + 2))
    assert up["button"] == "0"
    assert up["pointerType"] == "pen"
    assert up["pageX"] == str(math.floor(center_x + 2))
    assert up["pageY"] == str(math.floor(center_y + 2))


def test_set_pointer_event_properties(driver):
    driver.get('https://www.selenium.dev/selenium/web/pointerActionsPage.html')

    pointer_area = driver.find_element(By.ID, "pointerArea")
    pen_input = PointerInput(POINTER_PEN, "default pen")
    action = ActionBuilder(driver, mouse=pen_input)
    action.pointer_action\
        .move_to(pointer_area)\
        .pointer_down()\
        .move_by(2, 2, tilt_x=-72, tilt_y=9, twist=86)\
        .pointer_up(0)
    action.perform()

    moves = driver.find_elements(By.CLASS_NAME, "pointermove")
    move_to = properties(moves[0])
    down = properties(driver.find_element(By.CLASS_NAME, "pointerdown"))
    move_by = properties(moves[1])
    up = properties(driver.find_element(By.CLASS_NAME, "pointerup"))

    rect = pointer_area.rect
    center_x = rect["x"] + rect["width"] / 2
    center_y = rect["y"] + rect["height"] / 2

    assert move_to["button"] == "-1"
    assert move_to["pointerType"] == "pen"
    assert move_to["pageX"] == str(math.floor(center_x))
    assert move_to["pageY"] == str(math.floor(center_y))
    assert down["button"] == "0"
    assert down["pointerType"] == "pen"
    assert down["pageX"] == str(math.floor(center_x))
    assert down["pageY"] == str(math.floor(center_y))
    assert move_by["button"] == "-1"
    assert move_by["pointerType"] == "pen"
    assert move_by["pageX"] == str(math.floor(center_x + 2))
    assert move_by["pageY"] == str(math.floor(center_y + 2))
    assert move_by["tiltX"] == "-72"
    assert move_by["tiltY"] == "9"
    assert move_by["twist"] == "86"
    assert up["button"] == "0"
    assert up["pointerType"] == "pen"
    assert up["pageX"] == str(math.floor(center_x + 2))
    assert up["pageY"] == str(math.floor(center_y + 2))


def properties(element):
    kv = element.text.split(' ', 1)[1].split(', ')
    return {x[0]:x[1] for x in list(map(lambda item: item.split(': '), kv))}


            IWebElement pointerArea = driver.FindElement(By.Id("pointerArea"));
            ActionBuilder actionBuilder = new ActionBuilder();
            PointerInputDevice pen = new PointerInputDevice(PointerKind.Pen, "default pen");
            
            actionBuilder.AddAction(pen.CreatePointerMove(pointerArea, 0, 0, TimeSpan.FromMilliseconds(800)));
            actionBuilder.AddAction(pen.CreatePointerDown(MouseButton.Left));
            actionBuilder.AddAction(pen.CreatePointerMove(CoordinateOrigin.Pointer,
                2, 2, TimeSpan.Zero));
            actionBuilder.AddAction(pen.CreatePointerUp(MouseButton.Left));
            ((IActionExecutor)driver).PerformActions(actionBuilder.ToActionSequenceList());
Show full example
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using OpenQA.Selenium;
using OpenQA.Selenium.Interactions;

namespace SeleniumDocs.ActionsAPI
{
    [TestClass]
    public class PenTest : BaseChromeTest
    {
        [TestMethod]
        public void UsePen()
        {
            driver.Url = "https://selenium.dev/selenium/web/pointerActionsPage.html";

            IWebElement pointerArea = driver.FindElement(By.Id("pointerArea"));
            ActionBuilder actionBuilder = new ActionBuilder();
            PointerInputDevice pen = new PointerInputDevice(PointerKind.Pen, "default pen");
            
            actionBuilder.AddAction(pen.CreatePointerMove(pointerArea, 0, 0, TimeSpan.FromMilliseconds(800)));
            actionBuilder.AddAction(pen.CreatePointerDown(MouseButton.Left));
            actionBuilder.AddAction(pen.CreatePointerMove(CoordinateOrigin.Pointer,
                2, 2, TimeSpan.Zero));
            actionBuilder.AddAction(pen.CreatePointerUp(MouseButton.Left));
            ((IActionExecutor)driver).PerformActions(actionBuilder.ToActionSequenceList());

            var moves = driver.FindElements(By.ClassName("pointermove"));
            var moveTo = getProperties(moves.ElementAt(0));
            var down = getProperties(driver.FindElement(By.ClassName("pointerdown")));
            var moveBy = getProperties(moves.ElementAt(1));
            var up = getProperties(driver.FindElement(By.ClassName("pointerup")));

            Point location = pointerArea.Location;
            Size size = pointerArea.Size;
            decimal centerX = location.X + size.Width / 2;
            decimal centerY = location.Y + size.Height / 2;

            Assert.AreEqual("-1", moveTo["button"]);
            Assert.AreEqual("pen", moveTo["pointerType"]);
            Assert.IsTrue(VerifyEquivalent(centerX, moveTo["pageX"]));
            Assert.IsTrue(VerifyEquivalent(centerY, moveTo["pageY"]));
            Assert.AreEqual("0", down["button"]);
            Assert.AreEqual("pen", down["pointerType"]);
            Assert.IsTrue(VerifyEquivalent(centerX, down["pageX"]));
            Assert.IsTrue(VerifyEquivalent(centerY, down["pageY"]));
            Assert.AreEqual("-1", moveBy["button"]);
            Assert.AreEqual("pen", moveBy["pointerType"]);
            Assert.IsTrue(VerifyEquivalent(centerX + 2, moveBy["pageX"]));
            Assert.IsTrue(VerifyEquivalent(centerY + 2, moveBy["pageY"]));
            Assert.AreEqual("0", up["button"]);
            Assert.AreEqual("pen", up["pointerType"]);
            Assert.IsTrue(VerifyEquivalent(centerX + 2, up["pageX"]));
            Assert.IsTrue(VerifyEquivalent(centerY + 2, up["pageY"]));
        }

        [TestMethod]
        public void SetPointerEventProperties()
        {
            driver.Url = "https://selenium.dev/selenium/web/pointerActionsPage.html";

            IWebElement pointerArea = driver.FindElement(By.Id("pointerArea"));
            ActionBuilder actionBuilder = new ActionBuilder();
            PointerInputDevice pen = new PointerInputDevice(PointerKind.Pen, "default pen");
            PointerInputDevice.PointerEventProperties properties = new PointerInputDevice.PointerEventProperties() {
                TiltX = -72,
                TiltY = 9,
                Twist = 86,
            };            
            actionBuilder.AddAction(pen.CreatePointerMove(pointerArea, 0, 0, TimeSpan.FromMilliseconds(800)));
            actionBuilder.AddAction(pen.CreatePointerDown(MouseButton.Left));
            actionBuilder.AddAction(pen.CreatePointerMove(CoordinateOrigin.Pointer,
                2, 2, TimeSpan.Zero, properties));
            actionBuilder.AddAction(pen.CreatePointerUp(MouseButton.Left));
            ((IActionExecutor)driver).PerformActions(actionBuilder.ToActionSequenceList());
            
            var moves = driver.FindElements(By.ClassName("pointermove"));
            var moveTo = getProperties(moves.ElementAt(0));
            var down = getProperties(driver.FindElement(By.ClassName("pointerdown")));
            var moveBy = getProperties(moves.ElementAt(1));
            var up = getProperties(driver.FindElement(By.ClassName("pointerup")));

            Point location = pointerArea.Location;
            Size size = pointerArea.Size;
            decimal centerX = location.X + size.Width / 2;
            decimal centerY = location.Y + size.Height / 2;

            Assert.AreEqual("-1", moveTo["button"]);
            Assert.AreEqual("pen", moveTo["pointerType"]);
            Assert.IsTrue(VerifyEquivalent(centerX, moveTo["pageX"]));
            Assert.IsTrue(VerifyEquivalent(centerY, moveTo["pageY"]));
            Assert.AreEqual("0", down["button"]);
            Assert.AreEqual("pen", down["pointerType"]);
            Assert.IsTrue(VerifyEquivalent(centerX, down["pageX"]));
            Assert.IsTrue(VerifyEquivalent(centerY, down["pageY"]));
            Assert.AreEqual("-1", moveBy["button"]);
            Assert.AreEqual("pen", moveBy["pointerType"]);
            Assert.IsTrue(VerifyEquivalent(centerX + 2, moveBy["pageX"]));
            Assert.IsTrue(VerifyEquivalent(centerY + 2, moveBy["pageY"]));
            Assert.AreEqual((-72).ToString(), moveBy["tiltX"]);
            Assert.AreEqual((9).ToString(), moveBy["tiltY"]);
            Assert.AreEqual((86).ToString(), moveBy["twist"]);
            Assert.AreEqual("0", up["button"]);
            Assert.AreEqual("pen", up["pointerType"]);
            Assert.IsTrue(VerifyEquivalent(centerX + 2, up["pageX"]));
            Assert.IsTrue(VerifyEquivalent(centerY + 2, up["pageY"]));
        }

        private Dictionary<string, string> getProperties(IWebElement element)
        {
            var str = element.Text;
            str = str[(str.Split()[0].Length + 1)..];
            IEnumerable<string[]> keyValue = str.Split(", ").Select(part => part.Split(":"));
            return keyValue.ToDictionary(split => split[0].Trim(), split => split[1].Trim());
        }

        private bool VerifyEquivalent(decimal expected, string actual)
        {
            var absolute = Math.Abs(expected - decimal.Parse(actual));
            if (absolute <= 1)
            {
                return true;
            }

            throw new Exception("Expected: " + expected + "; but received: " + actual);
        }
    }
}

Selenium v4.2

    pointer_area = driver.find_element(id: 'pointerArea')
    driver.action(devices: :pen)
          .move_to(pointer_area)
          .pointer_down
          .move_by(2, 2)
          .pointer_up
          .perform
Show full example
# frozen_string_literal: true

require 'spec_helper'

RSpec.describe 'Pen' do
  let(:driver) { start_session }

  it 'uses a pen' do
    driver.get 'https://www.selenium.dev/selenium/web/pointerActionsPage.html'

    pointer_area = driver.find_element(id: 'pointerArea')
    driver.action(devices: :pen)
          .move_to(pointer_area)
          .pointer_down
          .move_by(2, 2)
          .pointer_up
          .perform

    moves = driver.find_elements(class: 'pointermove')
    move_to = properties(moves[0])
    down = properties(driver.find_element(class: 'pointerdown'))
    move_by = properties(moves[1])
    up = properties(driver.find_element(class: 'pointerup'))

    rect = pointer_area.rect
    center_x = rect.x + (rect.width / 2)
    center_y = rect.y + (rect.height / 2)

    expect(move_to).to include('button' => '-1',
                               'pointerType' => 'pen',
                               'pageX' => center_x.to_s,
                               'pageY' => center_y.floor.to_s)
    expect(down).to include('button' => '0',
                            'pointerType' => 'pen',
                            'pageX' => center_x.to_s,
                            'pageY' => center_y.floor.to_s)
    expect(move_by).to include('button' => '-1',
                               'pointerType' => 'pen',
                               'pageX' => (center_x + 2).to_s,
                               'pageY' => (center_y + 2).floor.to_s)
    expect(up).to include('button' => '0',
                          'pointerType' => 'pen',
                          'pageX' => (center_x + 2).to_s,
                          'pageY' => (center_y + 2).floor.to_s)
  end

  it 'sets pointer event attributes' do
    driver.get 'https://www.selenium.dev/selenium/web/pointerActionsPage.html'

    pointer_area = driver.find_element(id: 'pointerArea')
    driver.action(devices: :pen)
          .move_to(pointer_area)
          .pointer_down
          .move_by(2, 2, tilt_x: -72, tilt_y: 9, twist: 86)
          .pointer_up
          .perform

    moves = driver.find_elements(class: 'pointermove')
    move_to = properties(moves[0])
    down = properties(driver.find_element(class: 'pointerdown'))
    move_by = properties(moves[1])
    up = properties(driver.find_element(class: 'pointerup'))

    rect = pointer_area.rect
    center_x = rect.x + (rect.width / 2)
    center_y = rect.y + (rect.height / 2)

    expect(move_to).to include('button' => '-1',
                               'pointerType' => 'pen',
                               'pageX' => center_x.to_s,
                               'pageY' => center_y.floor.to_s)
    expect(down).to include('button' => '0',
                            'pointerType' => 'pen',
                            'pageX' => center_x.to_s,
                            'pageY' => center_y.floor.to_s)
    expect(move_by).to include('button' => '-1',
                               'pointerType' => 'pen',
                               'pageX' => (center_x + 2).to_s,
                               'pageY' => (center_y + 2).floor.to_s,
                               'tiltX' => -72.to_s,
                               'tiltY' => 9.to_s,
                               'twist' => 86.to_s)
    expect(up).to include('button' => '0',
                          'pointerType' => 'pen',
                          'pageX' => (center_x + 2).to_s,
                          'pageY' => (center_y + 2).floor.to_s)
  end

  def properties(element)
    element.text.sub(/.*?\s/, '').split(',').to_h { |item| item.lstrip.split(/\s*:\s*/) }
  end
end
        val pointerArea = driver.findElement(By.id("pointerArea"))
        Actions(driver)
                .setActivePointer(PointerInput.Kind.PEN, "default pen")
                .moveToElement(pointerArea)
                .clickAndHold()
                .moveByOffset(2, 2)
                .release()
                .perform()
Show full example
package dev.selenium.actions_api

import dev.selenium.BaseTest
import org.junit.jupiter.api.Assertions
import org.junit.jupiter.api.Test
import org.openqa.selenium.By
import org.openqa.selenium.Rectangle
import org.openqa.selenium.WebElement
import org.openqa.selenium.interactions.Actions
import org.openqa.selenium.interactions.PointerInput
import org.openqa.selenium.interactions.Sequence
import org.openqa.selenium.remote.RemoteWebDriver

import kotlin.collections.Map
import java.time.Duration

class PenTest : BaseTest() {
  
    @Test
    fun usePen() {
        driver.get("https://www.selenium.dev/selenium/web/pointerActionsPage.html")
        
        val pointerArea = driver.findElement(By.id("pointerArea"))
        Actions(driver)
                .setActivePointer(PointerInput.Kind.PEN, "default pen")
                .moveToElement(pointerArea)
                .clickAndHold()
                .moveByOffset(2, 2)
                .release()
                .perform()

        val moves = driver.findElements(By.className("pointermove"))
        val moveTo = getPropertyInfo(moves.get(0))
        val down = getPropertyInfo(driver.findElement(By.className("pointerdown")))
        val moveBy = getPropertyInfo(moves.get(1))
        val up = getPropertyInfo(driver.findElement(By.className("pointerup")))
        
        val rect = pointerArea.getRect()

        val centerX = Math.floor(rect.width.toDouble() / 2 + rect.getX()).toInt()
        val centerY = Math.floor(rect.height.toDouble() / 2 + rect.getY()).toInt()
        Assertions.assertEquals("-1", moveTo.get("button"))
        Assertions.assertEquals("pen", moveTo.get("pointerType"))
        Assertions.assertEquals(centerX.toString(), moveTo.get("pageX"))
        Assertions.assertEquals(centerY.toString(), moveTo.get("pageY"))
        Assertions.assertEquals("0", down.get("button"))
        Assertions.assertEquals("pen", down.get("pointerType"))
        Assertions.assertEquals(centerX.toString(), down.get("pageX"))
        Assertions.assertEquals(centerY.toString(), down.get("pageY"))
        Assertions.assertEquals("-1", moveBy.get("button"))
        Assertions.assertEquals("pen", moveBy.get("pointerType"))
        Assertions.assertEquals((centerX + 2).toString(), moveBy.get("pageX"))
        Assertions.assertEquals((centerY + 2).toString(), moveBy.get("pageY"))
        Assertions.assertEquals("0", up.get("button"))
        Assertions.assertEquals("pen", up.get("pointerType"))
        Assertions.assertEquals((centerX + 2).toString(), up.get("pageX"))
        Assertions.assertEquals((centerY + 2).toString(), up.get("pageY"))
    }

    @Test
    fun setPointerEventProperties() {
        driver.get("https://selenium.dev/selenium/web/pointerActionsPage.html")
        
        val pointerArea = driver.findElement(By.id("pointerArea"))
        val pen = PointerInput(PointerInput.Kind.PEN, "default pen")
        val eventProperties = PointerInput.eventProperties()
                .setTiltX(-72)
                .setTiltY(9)
                .setTwist(86)
        val origin = PointerInput.Origin.fromElement(pointerArea)
        
        val actionListPen = Sequence(pen, 0)
                .addAction(pen.createPointerMove(Duration.ZERO, origin, 0, 0))
                .addAction(pen.createPointerDown(0))
                .addAction(pen.createPointerMove(Duration.ZERO, origin, 2, 2, eventProperties))
                .addAction(pen.createPointerUp(0))

        (driver as RemoteWebDriver).perform(listOf(actionListPen))
                    

        val moves = driver.findElements(By.className("pointermove"))
        val moveTo = getPropertyInfo(moves.get(0))
        val down = getPropertyInfo(driver.findElement(By.className("pointerdown")))
        val moveBy = getPropertyInfo(moves.get(1))
        val up = getPropertyInfo(driver.findElement(By.className("pointerup")))
        
        val rect = pointerArea.getRect()

        val centerX = Math.floor(rect.width.toDouble() / 2 + rect.getX()).toInt()
        val centerY = Math.floor(rect.height.toDouble() / 2 + rect.getY()).toInt()
        Assertions.assertEquals("-1", moveTo.get("button"))
        Assertions.assertEquals("pen", moveTo.get("pointerType"))
        Assertions.assertEquals(centerX.toString(), moveTo.get("pageX"))
        Assertions.assertEquals(centerY.toString(), moveTo.get("pageY"))
        Assertions.assertEquals("0", down.get("button"))
        Assertions.assertEquals("pen", down.get("pointerType"))
        Assertions.assertEquals(centerX.toString(), down.get("pageX"))
        Assertions.assertEquals(centerY.toString(), down.get("pageY"))
        Assertions.assertEquals("-1", moveBy.get("button"))
        Assertions.assertEquals("pen", moveBy.get("pointerType"))
        Assertions.assertEquals((centerX + 2).toString(), moveBy.get("pageX"))
        Assertions.assertEquals((centerY + 2).toString(), moveBy.get("pageY"))
        Assertions.assertEquals("0", up.get("button"))
        Assertions.assertEquals("pen", up.get("pointerType"))
        Assertions.assertEquals((centerX + 2).toString(), up.get("pageX"))
        Assertions.assertEquals((centerY + 2).toString(), up.get("pageY")) 
	    
        Assertions.assertEquals("-72", moveBy.get("tiltX"))
        Assertions.assertEquals("9", moveBy.get("tiltY"))
        Assertions.assertEquals("86", moveBy.get("twist"))
    }
    
    fun getPropertyInfo(element: WebElement): Map<String, String> {
        var text = element.getText()  
        text = text.substring(text.indexOf(" ")+1)
        return text.split(", ")
        .map { it.split(": ") }
        .map { it.first() to it.last() }
        .toMap() 
    }
}

Adicionando Atributos de Evento de Ponteiro

Selenium v4.2

        WebElement pointerArea = driver.findElement(By.id("pointerArea"));
        PointerInput pen = new PointerInput(PointerInput.Kind.PEN, "default pen");
        PointerInput.PointerEventProperties eventProperties = PointerInput.eventProperties()
                .setTiltX(-72)
                .setTiltY(9)
                .setTwist(86);
        PointerInput.Origin origin = PointerInput.Origin.fromElement(pointerArea);

        Sequence actionListPen = new Sequence(pen, 0)
                .addAction(pen.createPointerMove(Duration.ZERO, origin, 0, 0))
                .addAction(pen.createPointerDown(0))
                .addAction(pen.createPointerMove(Duration.ZERO, origin, 2, 2, eventProperties))
                .addAction(pen.createPointerUp(0));

        ((RemoteWebDriver) driver).perform(Collections.singletonList(actionListPen));
Show full example
package dev.selenium.actions_api;

import dev.selenium.BaseChromeTest;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.openqa.selenium.By;
import org.openqa.selenium.Rectangle;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.interactions.Actions;
import org.openqa.selenium.interactions.PointerInput;
import org.openqa.selenium.interactions.Sequence;
import org.openqa.selenium.remote.RemoteWebDriver;

import java.time.Duration;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

public class PenTest extends BaseChromeTest {
    @Test
    public void usePen() {
        driver.get("https://www.selenium.dev/selenium/web/pointerActionsPage.html");

        WebElement pointerArea = driver.findElement(By.id("pointerArea"));
        new Actions(driver)
                .setActivePointer(PointerInput.Kind.PEN, "default pen")
                .moveToElement(pointerArea)
                .clickAndHold()
                .moveByOffset(2, 2)
                .release()
                .perform();

        List<WebElement> moves = driver.findElements(By.className("pointermove"));
        Map<String, String> moveTo = getPropertyInfo(moves.get(0));
        Map<String, String> down = getPropertyInfo(driver.findElement(By.className("pointerdown")));
        Map<String, String> moveBy = getPropertyInfo(moves.get(1));
        Map<String, String> up = getPropertyInfo(driver.findElement(By.className("pointerup")));

        Rectangle rect = pointerArea.getRect();

        int centerX = (int) Math.floor(rect.width / 2 + rect.getX());
        int centerY = (int) Math.floor(rect.height / 2 + rect.getY());
        Assertions.assertEquals("-1", moveTo.get("button"));
        Assertions.assertEquals("pen", moveTo.get("pointerType"));
        Assertions.assertEquals(String.valueOf(centerX), moveTo.get("pageX"));
        Assertions.assertEquals(String.valueOf(centerY), moveTo.get("pageY"));
        Assertions.assertEquals("0", down.get("button"));
        Assertions.assertEquals("pen", down.get("pointerType"));
        Assertions.assertEquals(String.valueOf(centerX), down.get("pageX"));
        Assertions.assertEquals(String.valueOf(centerY), down.get("pageY"));
        Assertions.assertEquals("-1", moveBy.get("button"));
        Assertions.assertEquals("pen", moveBy.get("pointerType"));
        Assertions.assertEquals(String.valueOf(centerX + 2), moveBy.get("pageX"));
        Assertions.assertEquals(String.valueOf(centerY + 2), moveBy.get("pageY"));
        Assertions.assertEquals("0", up.get("button"));
        Assertions.assertEquals("pen", up.get("pointerType"));
        Assertions.assertEquals(String.valueOf(centerX + 2), up.get("pageX"));
        Assertions.assertEquals(String.valueOf(centerY + 2), up.get("pageY"));
    }

    @Test
    public void setPointerEventProperties() {
        driver.get("https://selenium.dev/selenium/web/pointerActionsPage.html");

        WebElement pointerArea = driver.findElement(By.id("pointerArea"));
        PointerInput pen = new PointerInput(PointerInput.Kind.PEN, "default pen");
        PointerInput.PointerEventProperties eventProperties = PointerInput.eventProperties()
                .setTiltX(-72)
                .setTiltY(9)
                .setTwist(86);
        PointerInput.Origin origin = PointerInput.Origin.fromElement(pointerArea);

        Sequence actionListPen = new Sequence(pen, 0)
                .addAction(pen.createPointerMove(Duration.ZERO, origin, 0, 0))
                .addAction(pen.createPointerDown(0))
                .addAction(pen.createPointerMove(Duration.ZERO, origin, 2, 2, eventProperties))
                .addAction(pen.createPointerUp(0));

        ((RemoteWebDriver) driver).perform(Collections.singletonList(actionListPen));

        List<WebElement> moves = driver.findElements(By.className("pointermove"));
        Map<String, String> moveTo = getPropertyInfo(moves.get(0));
        Map<String, String> down = getPropertyInfo(driver.findElement(By.className("pointerdown")));
        Map<String, String> moveBy = getPropertyInfo(moves.get(1));
        Map<String, String> up = getPropertyInfo(driver.findElement(By.className("pointerup")));

        Rectangle rect = pointerArea.getRect();
        int centerX = (int) Math.floor(rect.width / 2 + rect.getX());
        int centerY = (int) Math.floor(rect.height / 2 + rect.getY());
        Assertions.assertEquals("-1", moveTo.get("button"));
        Assertions.assertEquals("pen", moveTo.get("pointerType"));
        Assertions.assertEquals(String.valueOf(centerX), moveTo.get("pageX"));
        Assertions.assertEquals(String.valueOf(centerY), moveTo.get("pageY"));
        Assertions.assertEquals("0", down.get("button"));
        Assertions.assertEquals("pen", down.get("pointerType"));
        Assertions.assertEquals(String.valueOf(centerX), down.get("pageX"));
        Assertions.assertEquals(String.valueOf(centerY), down.get("pageY"));
        Assertions.assertEquals("-1", moveBy.get("button"));
        Assertions.assertEquals("pen", moveBy.get("pointerType"));
        Assertions.assertEquals(String.valueOf(centerX + 2), moveBy.get("pageX"));
        Assertions.assertEquals(String.valueOf(centerY + 2), moveBy.get("pageY"));
        Assertions.assertEquals("-72", moveBy.get("tiltX"));
        Assertions.assertEquals("9", moveBy.get("tiltY"));
        Assertions.assertEquals("86", moveBy.get("twist"));
        Assertions.assertEquals("0", up.get("button"));
        Assertions.assertEquals("pen", up.get("pointerType"));
        Assertions.assertEquals(String.valueOf(centerX + 2), up.get("pageX"));
        Assertions.assertEquals(String.valueOf(centerY + 2), up.get("pageY"));
    }

    private Map<String, String> getPropertyInfo(WebElement element) {
        String text = element.getText();
        text = text.substring(text.indexOf(' ') + 1);

        return Arrays.stream(text.split(", "))
                .map(s -> s.split(": "))
                .collect(Collectors.toMap(
                        a -> a[0],
                        a -> a[1]
                ));
    }
}
    pointer_area = driver.find_element(By.ID, "pointerArea")
    pen_input = PointerInput(POINTER_PEN, "default pen")
    action = ActionBuilder(driver, mouse=pen_input)
    action.pointer_action\
        .move_to(pointer_area)\
        .pointer_down()\
        .move_by(2, 2, tilt_x=-72, tilt_y=9, twist=86)\
        .pointer_up(0)
    action.perform()
Show full example
import math

from selenium.webdriver.common.actions.action_builder import ActionBuilder
from selenium.webdriver.common.actions.interaction import POINTER_PEN
from selenium.webdriver.common.actions.pointer_input import PointerInput
from selenium.webdriver.common.by import By


def test_use_pen(driver):
    driver.get('https://www.selenium.dev/selenium/web/pointerActionsPage.html')

    pointer_area = driver.find_element(By.ID, "pointerArea")
    pen_input = PointerInput(POINTER_PEN, "default pen")
    action = ActionBuilder(driver, mouse=pen_input)
    action.pointer_action\
        .move_to(pointer_area)\
        .pointer_down()\
        .move_by(2, 2)\
        .pointer_up()
    action.perform()

    moves = driver.find_elements(By.CLASS_NAME, "pointermove")
    move_to = properties(moves[0])
    down = properties(driver.find_element(By.CLASS_NAME, "pointerdown"))
    move_by = properties(moves[1])
    up = properties(driver.find_element(By.CLASS_NAME, "pointerup"))

    rect = pointer_area.rect
    center_x = rect["x"] + rect["width"] / 2
    center_y = rect["y"] + rect["height"] / 2

    assert move_to["button"] == "-1"
    assert move_to["pointerType"] == "pen"
    assert move_to["pageX"] == str(math.floor(center_x))
    assert move_to["pageY"] == str(math.floor(center_y))
    assert down["button"] == "0"
    assert down["pointerType"] == "pen"
    assert down["pageX"] == str(math.floor(center_x))
    assert down["pageY"] == str(math.floor(center_y))
    assert move_by["button"] == "-1"
    assert move_by["pointerType"] == "pen"
    assert move_by["pageX"] == str(math.floor(center_x + 2))
    assert move_by["pageY"] == str(math.floor(center_y + 2))
    assert up["button"] == "0"
    assert up["pointerType"] == "pen"
    assert up["pageX"] == str(math.floor(center_x + 2))
    assert up["pageY"] == str(math.floor(center_y + 2))


def test_set_pointer_event_properties(driver):
    driver.get('https://www.selenium.dev/selenium/web/pointerActionsPage.html')

    pointer_area = driver.find_element(By.ID, "pointerArea")
    pen_input = PointerInput(POINTER_PEN, "default pen")
    action = ActionBuilder(driver, mouse=pen_input)
    action.pointer_action\
        .move_to(pointer_area)\
        .pointer_down()\
        .move_by(2, 2, tilt_x=-72, tilt_y=9, twist=86)\
        .pointer_up(0)
    action.perform()

    moves = driver.find_elements(By.CLASS_NAME, "pointermove")
    move_to = properties(moves[0])
    down = properties(driver.find_element(By.CLASS_NAME, "pointerdown"))
    move_by = properties(moves[1])
    up = properties(driver.find_element(By.CLASS_NAME, "pointerup"))

    rect = pointer_area.rect
    center_x = rect["x"] + rect["width"] / 2
    center_y = rect["y"] + rect["height"] / 2

    assert move_to["button"] == "-1"
    assert move_to["pointerType"] == "pen"
    assert move_to["pageX"] == str(math.floor(center_x))
    assert move_to["pageY"] == str(math.floor(center_y))
    assert down["button"] == "0"
    assert down["pointerType"] == "pen"
    assert down["pageX"] == str(math.floor(center_x))
    assert down["pageY"] == str(math.floor(center_y))
    assert move_by["button"] == "-1"
    assert move_by["pointerType"] == "pen"
    assert move_by["pageX"] == str(math.floor(center_x + 2))
    assert move_by["pageY"] == str(math.floor(center_y + 2))
    assert move_by["tiltX"] == "-72"
    assert move_by["tiltY"] == "9"
    assert move_by["twist"] == "86"
    assert up["button"] == "0"
    assert up["pointerType"] == "pen"
    assert up["pageX"] == str(math.floor(center_x + 2))
    assert up["pageY"] == str(math.floor(center_y + 2))


def properties(element):
    kv = element.text.split(' ', 1)[1].split(', ')
    return {x[0]:x[1] for x in list(map(lambda item: item.split(': '), kv))}


            IWebElement pointerArea = driver.FindElement(By.Id("pointerArea"));
            ActionBuilder actionBuilder = new ActionBuilder();
            PointerInputDevice pen = new PointerInputDevice(PointerKind.Pen, "default pen");
            PointerInputDevice.PointerEventProperties properties = new PointerInputDevice.PointerEventProperties() {
                TiltX = -72,
                TiltY = 9,
                Twist = 86,
            };            
            actionBuilder.AddAction(pen.CreatePointerMove(pointerArea, 0, 0, TimeSpan.FromMilliseconds(800)));
            actionBuilder.AddAction(pen.CreatePointerDown(MouseButton.Left));
            actionBuilder.AddAction(pen.CreatePointerMove(CoordinateOrigin.Pointer,
                2, 2, TimeSpan.Zero, properties));
            actionBuilder.AddAction(pen.CreatePointerUp(MouseButton.Left));
            ((IActionExecutor)driver).PerformActions(actionBuilder.ToActionSequenceList());
Show full example
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using OpenQA.Selenium;
using OpenQA.Selenium.Interactions;

namespace SeleniumDocs.ActionsAPI
{
    [TestClass]
    public class PenTest : BaseChromeTest
    {
        [TestMethod]
        public void UsePen()
        {
            driver.Url = "https://selenium.dev/selenium/web/pointerActionsPage.html";

            IWebElement pointerArea = driver.FindElement(By.Id("pointerArea"));
            ActionBuilder actionBuilder = new ActionBuilder();
            PointerInputDevice pen = new PointerInputDevice(PointerKind.Pen, "default pen");
            
            actionBuilder.AddAction(pen.CreatePointerMove(pointerArea, 0, 0, TimeSpan.FromMilliseconds(800)));
            actionBuilder.AddAction(pen.CreatePointerDown(MouseButton.Left));
            actionBuilder.AddAction(pen.CreatePointerMove(CoordinateOrigin.Pointer,
                2, 2, TimeSpan.Zero));
            actionBuilder.AddAction(pen.CreatePointerUp(MouseButton.Left));
            ((IActionExecutor)driver).PerformActions(actionBuilder.ToActionSequenceList());

            var moves = driver.FindElements(By.ClassName("pointermove"));
            var moveTo = getProperties(moves.ElementAt(0));
            var down = getProperties(driver.FindElement(By.ClassName("pointerdown")));
            var moveBy = getProperties(moves.ElementAt(1));
            var up = getProperties(driver.FindElement(By.ClassName("pointerup")));

            Point location = pointerArea.Location;
            Size size = pointerArea.Size;
            decimal centerX = location.X + size.Width / 2;
            decimal centerY = location.Y + size.Height / 2;

            Assert.AreEqual("-1", moveTo["button"]);
            Assert.AreEqual("pen", moveTo["pointerType"]);
            Assert.IsTrue(VerifyEquivalent(centerX, moveTo["pageX"]));
            Assert.IsTrue(VerifyEquivalent(centerY, moveTo["pageY"]));
            Assert.AreEqual("0", down["button"]);
            Assert.AreEqual("pen", down["pointerType"]);
            Assert.IsTrue(VerifyEquivalent(centerX, down["pageX"]));
            Assert.IsTrue(VerifyEquivalent(centerY, down["pageY"]));
            Assert.AreEqual("-1", moveBy["button"]);
            Assert.AreEqual("pen", moveBy["pointerType"]);
            Assert.IsTrue(VerifyEquivalent(centerX + 2, moveBy["pageX"]));
            Assert.IsTrue(VerifyEquivalent(centerY + 2, moveBy["pageY"]));
            Assert.AreEqual("0", up["button"]);
            Assert.AreEqual("pen", up["pointerType"]);
            Assert.IsTrue(VerifyEquivalent(centerX + 2, up["pageX"]));
            Assert.IsTrue(VerifyEquivalent(centerY + 2, up["pageY"]));
        }

        [TestMethod]
        public void SetPointerEventProperties()
        {
            driver.Url = "https://selenium.dev/selenium/web/pointerActionsPage.html";

            IWebElement pointerArea = driver.FindElement(By.Id("pointerArea"));
            ActionBuilder actionBuilder = new ActionBuilder();
            PointerInputDevice pen = new PointerInputDevice(PointerKind.Pen, "default pen");
            PointerInputDevice.PointerEventProperties properties = new PointerInputDevice.PointerEventProperties() {
                TiltX = -72,
                TiltY = 9,
                Twist = 86,
            };            
            actionBuilder.AddAction(pen.CreatePointerMove(pointerArea, 0, 0, TimeSpan.FromMilliseconds(800)));
            actionBuilder.AddAction(pen.CreatePointerDown(MouseButton.Left));
            actionBuilder.AddAction(pen.CreatePointerMove(CoordinateOrigin.Pointer,
                2, 2, TimeSpan.Zero, properties));
            actionBuilder.AddAction(pen.CreatePointerUp(MouseButton.Left));
            ((IActionExecutor)driver).PerformActions(actionBuilder.ToActionSequenceList());
            
            var moves = driver.FindElements(By.ClassName("pointermove"));
            var moveTo = getProperties(moves.ElementAt(0));
            var down = getProperties(driver.FindElement(By.ClassName("pointerdown")));
            var moveBy = getProperties(moves.ElementAt(1));
            var up = getProperties(driver.FindElement(By.ClassName("pointerup")));

            Point location = pointerArea.Location;
            Size size = pointerArea.Size;
            decimal centerX = location.X + size.Width / 2;
            decimal centerY = location.Y + size.Height / 2;

            Assert.AreEqual("-1", moveTo["button"]);
            Assert.AreEqual("pen", moveTo["pointerType"]);
            Assert.IsTrue(VerifyEquivalent(centerX, moveTo["pageX"]));
            Assert.IsTrue(VerifyEquivalent(centerY, moveTo["pageY"]));
            Assert.AreEqual("0", down["button"]);
            Assert.AreEqual("pen", down["pointerType"]);
            Assert.IsTrue(VerifyEquivalent(centerX, down["pageX"]));
            Assert.IsTrue(VerifyEquivalent(centerY, down["pageY"]));
            Assert.AreEqual("-1", moveBy["button"]);
            Assert.AreEqual("pen", moveBy["pointerType"]);
            Assert.IsTrue(VerifyEquivalent(centerX + 2, moveBy["pageX"]));
            Assert.IsTrue(VerifyEquivalent(centerY + 2, moveBy["pageY"]));
            Assert.AreEqual((-72).ToString(), moveBy["tiltX"]);
            Assert.AreEqual((9).ToString(), moveBy["tiltY"]);
            Assert.AreEqual((86).ToString(), moveBy["twist"]);
            Assert.AreEqual("0", up["button"]);
            Assert.AreEqual("pen", up["pointerType"]);
            Assert.IsTrue(VerifyEquivalent(centerX + 2, up["pageX"]));
            Assert.IsTrue(VerifyEquivalent(centerY + 2, up["pageY"]));
        }

        private Dictionary<string, string> getProperties(IWebElement element)
        {
            var str = element.Text;
            str = str[(str.Split()[0].Length + 1)..];
            IEnumerable<string[]> keyValue = str.Split(", ").Select(part => part.Split(":"));
            return keyValue.ToDictionary(split => split[0].Trim(), split => split[1].Trim());
        }

        private bool VerifyEquivalent(decimal expected, string actual)
        {
            var absolute = Math.Abs(expected - decimal.Parse(actual));
            if (absolute <= 1)
            {
                return true;
            }

            throw new Exception("Expected: " + expected + "; but received: " + actual);
        }
    }
}
    pointer_area = driver.find_element(id: 'pointerArea')
    driver.action(devices: :pen)
          .move_to(pointer_area)
          .pointer_down
          .move_by(2, 2, tilt_x: -72, tilt_y: 9, twist: 86)
          .pointer_up
          .perform
Show full example
# frozen_string_literal: true

require 'spec_helper'

RSpec.describe 'Pen' do
  let(:driver) { start_session }

  it 'uses a pen' do
    driver.get 'https://www.selenium.dev/selenium/web/pointerActionsPage.html'

    pointer_area = driver.find_element(id: 'pointerArea')
    driver.action(devices: :pen)
          .move_to(pointer_area)
          .pointer_down
          .move_by(2, 2)
          .pointer_up
          .perform

    moves = driver.find_elements(class: 'pointermove')
    move_to = properties(moves[0])
    down = properties(driver.find_element(class: 'pointerdown'))
    move_by = properties(moves[1])
    up = properties(driver.find_element(class: 'pointerup'))

    rect = pointer_area.rect
    center_x = rect.x + (rect.width / 2)
    center_y = rect.y + (rect.height / 2)

    expect(move_to).to include('button' => '-1',
                               'pointerType' => 'pen',
                               'pageX' => center_x.to_s,
                               'pageY' => center_y.floor.to_s)
    expect(down).to include('button' => '0',
                            'pointerType' => 'pen',
                            'pageX' => center_x.to_s,
                            'pageY' => center_y.floor.to_s)
    expect(move_by).to include('button' => '-1',
                               'pointerType' => 'pen',
                               'pageX' => (center_x + 2).to_s,
                               'pageY' => (center_y + 2).floor.to_s)
    expect(up).to include('button' => '0',
                          'pointerType' => 'pen',
                          'pageX' => (center_x + 2).to_s,
                          'pageY' => (center_y + 2).floor.to_s)
  end

  it 'sets pointer event attributes' do
    driver.get 'https://www.selenium.dev/selenium/web/pointerActionsPage.html'

    pointer_area = driver.find_element(id: 'pointerArea')
    driver.action(devices: :pen)
          .move_to(pointer_area)
          .pointer_down
          .move_by(2, 2, tilt_x: -72, tilt_y: 9, twist: 86)
          .pointer_up
          .perform

    moves = driver.find_elements(class: 'pointermove')
    move_to = properties(moves[0])
    down = properties(driver.find_element(class: 'pointerdown'))
    move_by = properties(moves[1])
    up = properties(driver.find_element(class: 'pointerup'))

    rect = pointer_area.rect
    center_x = rect.x + (rect.width / 2)
    center_y = rect.y + (rect.height / 2)

    expect(move_to).to include('button' => '-1',
                               'pointerType' => 'pen',
                               'pageX' => center_x.to_s,
                               'pageY' => center_y.floor.to_s)
    expect(down).to include('button' => '0',
                            'pointerType' => 'pen',
                            'pageX' => center_x.to_s,
                            'pageY' => center_y.floor.to_s)
    expect(move_by).to include('button' => '-1',
                               'pointerType' => 'pen',
                               'pageX' => (center_x + 2).to_s,
                               'pageY' => (center_y + 2).floor.to_s,
                               'tiltX' => -72.to_s,
                               'tiltY' => 9.to_s,
                               'twist' => 86.to_s)
    expect(up).to include('button' => '0',
                          'pointerType' => 'pen',
                          'pageX' => (center_x + 2).to_s,
                          'pageY' => (center_y + 2).floor.to_s)
  end

  def properties(element)
    element.text.sub(/.*?\s/, '').split(',').to_h { |item| item.lstrip.split(/\s*:\s*/) }
  end
end
        val pointerArea = driver.findElement(By.id("pointerArea"))
        val pen = PointerInput(PointerInput.Kind.PEN, "default pen")
        val eventProperties = PointerInput.eventProperties()
                .setTiltX(-72)
                .setTiltY(9)
                .setTwist(86)
        val origin = PointerInput.Origin.fromElement(pointerArea)
        
        val actionListPen = Sequence(pen, 0)
                .addAction(pen.createPointerMove(Duration.ZERO, origin, 0, 0))
                .addAction(pen.createPointerDown(0))
                .addAction(pen.createPointerMove(Duration.ZERO, origin, 2, 2, eventProperties))
                .addAction(pen.createPointerUp(0))

        (driver as RemoteWebDriver).perform(listOf(actionListPen))
Show full example
package dev.selenium.actions_api

import dev.selenium.BaseTest
import org.junit.jupiter.api.Assertions
import org.junit.jupiter.api.Test
import org.openqa.selenium.By
import org.openqa.selenium.Rectangle
import org.openqa.selenium.WebElement
import org.openqa.selenium.interactions.Actions
import org.openqa.selenium.interactions.PointerInput
import org.openqa.selenium.interactions.Sequence
import org.openqa.selenium.remote.RemoteWebDriver

import kotlin.collections.Map
import java.time.Duration

class PenTest : BaseTest() {
  
    @Test
    fun usePen() {
        driver.get("https://www.selenium.dev/selenium/web/pointerActionsPage.html")
        
        val pointerArea = driver.findElement(By.id("pointerArea"))
        Actions(driver)
                .setActivePointer(PointerInput.Kind.PEN, "default pen")
                .moveToElement(pointerArea)
                .clickAndHold()
                .moveByOffset(2, 2)
                .release()
                .perform()

        val moves = driver.findElements(By.className("pointermove"))
        val moveTo = getPropertyInfo(moves.get(0))
        val down = getPropertyInfo(driver.findElement(By.className("pointerdown")))
        val moveBy = getPropertyInfo(moves.get(1))
        val up = getPropertyInfo(driver.findElement(By.className("pointerup")))
        
        val rect = pointerArea.getRect()

        val centerX = Math.floor(rect.width.toDouble() / 2 + rect.getX()).toInt()
        val centerY = Math.floor(rect.height.toDouble() / 2 + rect.getY()).toInt()
        Assertions.assertEquals("-1", moveTo.get("button"))
        Assertions.assertEquals("pen", moveTo.get("pointerType"))
        Assertions.assertEquals(centerX.toString(), moveTo.get("pageX"))
        Assertions.assertEquals(centerY.toString(), moveTo.get("pageY"))
        Assertions.assertEquals("0", down.get("button"))
        Assertions.assertEquals("pen", down.get("pointerType"))
        Assertions.assertEquals(centerX.toString(), down.get("pageX"))
        Assertions.assertEquals(centerY.toString(), down.get("pageY"))
        Assertions.assertEquals("-1", moveBy.get("button"))
        Assertions.assertEquals("pen", moveBy.get("pointerType"))
        Assertions.assertEquals((centerX + 2).toString(), moveBy.get("pageX"))
        Assertions.assertEquals((centerY + 2).toString(), moveBy.get("pageY"))
        Assertions.assertEquals("0", up.get("button"))
        Assertions.assertEquals("pen", up.get("pointerType"))
        Assertions.assertEquals((centerX + 2).toString(), up.get("pageX"))
        Assertions.assertEquals((centerY + 2).toString(), up.get("pageY"))
    }

    @Test
    fun setPointerEventProperties() {
        driver.get("https://selenium.dev/selenium/web/pointerActionsPage.html")
        
        val pointerArea = driver.findElement(By.id("pointerArea"))
        val pen = PointerInput(PointerInput.Kind.PEN, "default pen")
        val eventProperties = PointerInput.eventProperties()
                .setTiltX(-72)
                .setTiltY(9)
                .setTwist(86)
        val origin = PointerInput.Origin.fromElement(pointerArea)
        
        val actionListPen = Sequence(pen, 0)
                .addAction(pen.createPointerMove(Duration.ZERO, origin, 0, 0))
                .addAction(pen.createPointerDown(0))
                .addAction(pen.createPointerMove(Duration.ZERO, origin, 2, 2, eventProperties))
                .addAction(pen.createPointerUp(0))

        (driver as RemoteWebDriver).perform(listOf(actionListPen))
                    

        val moves = driver.findElements(By.className("pointermove"))
        val moveTo = getPropertyInfo(moves.get(0))
        val down = getPropertyInfo(driver.findElement(By.className("pointerdown")))
        val moveBy = getPropertyInfo(moves.get(1))
        val up = getPropertyInfo(driver.findElement(By.className("pointerup")))
        
        val rect = pointerArea.getRect()

        val centerX = Math.floor(rect.width.toDouble() / 2 + rect.getX()).toInt()
        val centerY = Math.floor(rect.height.toDouble() / 2 + rect.getY()).toInt()
        Assertions.assertEquals("-1", moveTo.get("button"))
        Assertions.assertEquals("pen", moveTo.get("pointerType"))
        Assertions.assertEquals(centerX.toString(), moveTo.get("pageX"))
        Assertions.assertEquals(centerY.toString(), moveTo.get("pageY"))
        Assertions.assertEquals("0", down.get("button"))
        Assertions.assertEquals("pen", down.get("pointerType"))
        Assertions.assertEquals(centerX.toString(), down.get("pageX"))
        Assertions.assertEquals(centerY.toString(), down.get("pageY"))
        Assertions.assertEquals("-1", moveBy.get("button"))
        Assertions.assertEquals("pen", moveBy.get("pointerType"))
        Assertions.assertEquals((centerX + 2).toString(), moveBy.get("pageX"))
        Assertions.assertEquals((centerY + 2).toString(), moveBy.get("pageY"))
        Assertions.assertEquals("0", up.get("button"))
        Assertions.assertEquals("pen", up.get("pointerType"))
        Assertions.assertEquals((centerX + 2).toString(), up.get("pageX"))
        Assertions.assertEquals((centerY + 2).toString(), up.get("pageY")) 
	    
        Assertions.assertEquals("-72", moveBy.get("tiltX"))
        Assertions.assertEquals("9", moveBy.get("tiltY"))
        Assertions.assertEquals("86", moveBy.get("twist"))
    }
    
    fun getPropertyInfo(element: WebElement): Map<String, String> {
        var text = element.getText()  
        text = text.substring(text.indexOf(" ")+1)
        return text.split(", ")
        .map { it.split(": ") }
        .map { it.first() to it.last() }
        .toMap() 
    }
}
Última modificação November 17, 2023: Upgrade to Docsy 0 7 2 (#1529) (48f4361690)