Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add actions support #103

Closed
igrishaev opened this issue Feb 1, 2018 · 15 comments
Closed

add actions support #103

igrishaev opened this issue Feb 1, 2018 · 15 comments
Assignees
Labels
huge It's a huge task

Comments

@igrishaev
Copy link
Collaborator Author

Разобраться с actions:

  • для чего они нужны
  • что они делают такого, чего нельзя сделать без них
  • насколько браузеры их поддерживают
  • продумать удобные апи для людей
  • написать реализацию
  • добавить тесты
  • добавить примеры в readme

@igrishaev igrishaev added the huge It's a huge task label Jul 30, 2020
@igrishaev
Copy link
Collaborator Author

начать с w3c-спеки https://www.w3.org/TR/webdriver/#actions

@Uunnamed
Copy link
Contributor

пока ответ на первые 3 пункта

  1. Для управления вводом с устройств на низком уровне
  2. например с их помощью можно выполнить связку удержание control + нажатие F или нажатие стилуса на экран и перемещение курсора
  3. из нашего списка только фантом не поддерживает

@igrishaev
Copy link
Collaborator Author

Предположу, что можно будет сделать макросы (with-ctrl-key ...), (with-mouse-left-btn ...) и другие, чтобы выполнять код с нажатой кнопкой или другим эффектом.

@igrishaev
Copy link
Collaborator Author

Общий подход такой: сперва делаем низкоуровневое апи, которое буквально принимает все параметры. Затем на базе их колбасим наиболее нужные обертки и макросы.

@Uunnamed
Copy link
Contributor

Экшены в результате это массив, каждый элемент которого описывает виртуальный источник ввода.
Источники есть следующих типов none, key, pointer, wheel:

  • none имеет только один тип действия pause, длина паузы задается свойством duration
  • key это клавиатура, в дополнение к none имеет типы действия keyDown, keyUp
  • pointer имеет подтипы mouse, pen, touch. в дополнение к none имеет типы действий:
    pointerDown, ponterUp, pointerMove, pointerCancel.
  • wheel в дополнение к none имеет тип действия scroll

В стандарте есть понятие tick, отрезок времени в течении которого источник выполняет действие. Например зажатие клавиши, клик мышью, перемещение курсора.
У каждого источника ввода (элемента массива actions) есть ассоциированый с ним набор действий, так же actions, в котором указана последовательность действий.

Пример единичного действия:
{:type "keyDown" :value cmd} для key, {:type "pointerMove" :origin "pointer" :x 396 :y 323} для pointer и тп.

Насколько я понял, перечисленные источники, начинают выполнять действия одновременно.
Т.е. в первый тик (см. пример карты ниже), одновременно выполнятся действия
{:type "keyDown" :value cmd}
{:type "pointerMove" :origin "pointer" :x 396 :y 323}

во второй:
{:type "keyDown" :value "a"}
{:type "pointerDown" :duration 0 :button 0}

Длина тика определяется временем, которое занимает самое долгое действие.
Чтобы синхронизировать действия источников, в Тики где один источник ничего не должен делать вставляют pause. На примере зума по экрану
1-й палец: pointerDown -> pause 5 -> pointerUp
2-й палец: pointerDown -> pointerMove -> pointerUp

Пример карты:

{:actions [{:type    "key"
            :id      "UUID or some name"
            :actions [{:type "keyDown" :value cmd}
                      {:type "keyDown" :value "a"}
                      {:type "keyUp" :value "a"}
                      {:type "keyUp" :value cmd}
                      {:type "pause" :duration 100}]}
           {:type       "pointer"
            :id         "UUID or some name"
            :parameters {:pointerType "mouse"}
            :actions    [{:type "pointerMove" :origin "pointer" :x 396 :y 323}
                         ;; double click
                         {:type "pointerDown" :duration 0 :button 0}
                         {:type "pointerUp" :duration 0 :button 0}
                         {:type "pointerDown" :duration 0 :button 0}
                         {:type "pointerUp" :duration 0 :button 0}]}]}

@igrishaev
Copy link
Collaborator Author

Теперь основная задача в том, как выразить это в коде. Для начала будет низкоуровневая функция, которая принимает уже готовый словарь. Так мы предоставим доступ для прошаренных пользователей и сложных случаев.

Кроме того, должны быть функции или макросы, чтобы выразить эту структуру в коде. Многие действия работают по принципу вкл\выкл, поэтому они могут быть обертками вокруг чего-то еще. Например, условная (wrap-key-press ... key) оборачивает переданный ей массив так, что в начала и в конце добавляются (keyDown key) и (keyUp key).

Или это может быть макрос, который работает на динамической переменной. В момент байдинга в нее что-то аккумулируется как в список или вектор.

Я предлагаю следующее: начать не с функций, а представить, как будто у нас все готово, и нужно только описать структуру. Дальше будем смотеть: если ложится на синтаксис кложи, сделаем функции, а если нет -- макрос.

@igrishaev
Copy link
Collaborator Author

Получается, у нас два уровня: источник ввода и действия к нему. Напрашивается что-то такое, например чтобы с нажатым ctrl нажать А, или сдвинуть мышку с зажатой кнопкой

(with-key
  (with-key-down Ctrl
    (key-press A)))

(with-pointer
  (with-pointer-down
    (pointer-move ...)))

@igrishaev
Copy link
Collaborator Author

У макросов должны быть динамические переменные, куда они будут сваливать все добро. Рассмотреть вариант с функцией и стрелочными оператором:

(-> (make-pointer)
    (add-key-down ...)
    (add-key-up ...))

(-> (make-pointer)
    (add-key-down A)
    (add-key-up A)
    (wrap-key-press Ctrl))

@igrishaev
Copy link
Collaborator Author

Функция make-pointer строит новый инпут. add-key-down добавляет в конец поля :actions инпута нужное действие. wrap-key-press и аналоги добавляют пару действий в начало и хвост :actions.

@igrishaev
Copy link
Collaborator Author

igrishaev commented Aug 28, 2020

Стрелочный вариант хорош тем, что без состояния. По аналогии, сначала делаем общую функцию, например make-action-input, а потом помогаторы make-pointer, make-pen и так далее. То же самое для добавления действий.

@igrishaev
Copy link
Collaborator Author

И подчеркну: перед тем, как писать код, было бы неплохо составить воображаемую версию и скинуть ее сюда или в гист.

@Uunnamed Uunnamed mentioned this issue Aug 28, 2020
@igrishaev
Copy link
Collaborator Author

Еще уточню что может быть параметром origin?

If origin is not equal to "viewport" or "pointer" and origin is not an Object that represents a web element, return error with error code invalid argument.

Из доки ниже я не понял, что такое "Object that represents a web element". Как-то можно передать элемент?

@Uunnamed
Copy link
Contributor

Еще уточню что может быть параметром origin?

If origin is not equal to "viewport" or "pointer" and origin is not an Object that represents a web element, return error with error code invalid argument.

Из доки ниже я не понял, что такое "Object that represents a web element". Как-то можно передать элемент?

да, можно добавить id-шник элемента
у нас есть функа для перевода el->ref

@igrishaev
Copy link
Collaborator Author

Текущий PR хороший, можно смерджить. Разве что тесты упали, но я не смотрел почему. Осталось сделать:

  • написать юнит-тесты, которые проверяют чистые функции для построения actions. То есть просто навешать экшенов, макросов и убедиться, что выходит правильная структура.

  • написать интреграционные тесты для драйвера, когда заходим на страничку и что-то делаем мышкой и т.д. Желательно завести по это дело отдельную HTML-страницу. Если получится сделать локальный drag-n-drop, будет вообще хорошо. Можно скопипастить чей-то код.

  • Добавить новую секцию в readme с примерами. Основные положения: теперь мы поддерживаем actions, ссылка на спеку. Примеры наших функций. Низкоуровневый пример (когда чел сам строит коллекцию).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
huge It's a huge task
Projects
None yet
Development

No branches or pull requests

2 participants