Skip to content

Commit

Permalink
QE-13247 Add Drag and Drop file upload step (#361)
Browse files Browse the repository at this point in the history
Add a drag & drop style file upload step. Tested it in E2E tests:
https://github.com/cerebrotech/domino/pull/36973

Will add functional tests later:
https://dominodatalab.atlassian.net/browse/QE-13261
  • Loading branch information
ddl-xin authored Sep 5, 2023
1 parent 4bb9abc commit 8cd0203
Show file tree
Hide file tree
Showing 5 changed files with 80 additions and 32 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project closely adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## 0.160.0
- Add - drag and drop file upload step

## 0.159.0
- Change - ignore exceptions from sub_headers hook
- Security - update Certifi to remove e-Tugra root certificate
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[tool.poetry]
name = "cucu"
version = "0.159.0"
version = "0.160.0"
license = "MIT"
description = "Easy BDD web testing"
authors = ["Domino Data Lab <[email protected]>"]
Expand Down
1 change: 1 addition & 0 deletions src/cucu/steps/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
import cucu.steps.filesystem_steps
import cucu.steps.image_steps
import cucu.steps.input_steps
import cucu.steps.file_input_steps
import cucu.steps.link_steps
import cucu.steps.flow_control_steps
import cucu.steps.menuitem_steps
Expand Down
31 changes: 0 additions & 31 deletions src/cucu/steps/browser_steps.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import base64
import os

import humanize
from selenium.webdriver.common.keys import Keys

from cucu import config, fuzzy, logger, retry, run_steps, step
Expand Down Expand Up @@ -220,30 +219,6 @@ def wait_to_switch_to_previous_browser_tab(ctx):
retry(switch_to_previous_tab)(ctx)


def find_file_input(ctx, name, index=0):
"""
* <input type="file">
parameters:
ctx(object): behave context object used to share data between steps
name(str): name that identifies the desired button on screen
index(str): the index of the button if there are duplicates
returns:
the WebElement that matches the provided arguments.
"""
ctx.check_browser_initialized()
_input = fuzzy.find(ctx.browser, name, ['input[type="file"]'], index=index)

prefix = "" if index == 0 else f"{humanize.ordinal(index)} "

if _input is None:
raise RuntimeError(f'unable to find the {prefix}file input "{name}"')

return _input


def save_downloaded_file(ctx, filename):
ctx.check_browser_initialized()

Expand Down Expand Up @@ -314,12 +289,6 @@ def wait_up_to_seconds_to_see_downloaded_file(ctx, seconds, filename):
retry(save_downloaded_file, wait_up_to_s=seconds)(ctx, filename)


@step('I upload the file "{filepath}" to the file input "{name}"')
def upload_file_to_input(ctx, filepath, name):
_input = find_file_input(ctx, name)
_input.send_keys(os.path.abspath(filepath))


@step('I download an mht archive of the current page to "{file_path}"')
def download_mht_archive(ctx, file_path):
ctx.browser.download_mht(file_path)
Expand Down
75 changes: 75 additions & 0 deletions src/cucu/steps/file_input_steps.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import os

import humanize

from cucu import fuzzy, logger, step


def find_file_input(ctx, name, index=0):
"""
* <input type="file">
parameters:
ctx(object): behave context object used to share data between steps
name(str): name that identifies the desired button on screen
index(str): the index of the button if there are duplicates
returns:
the WebElement that matches the provided arguments.
"""
ctx.check_browser_initialized()
_input = fuzzy.find(ctx.browser, name, ['input[type="file"]'], index=index)

prefix = "" if index == 0 else f"{humanize.ordinal(index)} "

if _input is None:
raise RuntimeError(f'unable to find the {prefix}file input "{name}"')

return _input


@step('I upload the file "{filepath}" to the file input "{name}"')
def upload_file_to_input(ctx, filepath, name):
_input = find_file_input(ctx, name)
_input.send_keys(os.path.abspath(filepath))


JS_DROP_FILE = """
var target = arguments[0],
offsetX = arguments[1],
offsetY = arguments[2],
document = target.ownerDocument || document,
window = document.defaultView || window;
var input = document.createElement('INPUT');
input.type = 'file';
input.onchange = function () {
var rect = target.getBoundingClientRect(),
x = rect.left + (offsetX || (rect.width >> 1)),
y = rect.top + (offsetY || (rect.height >> 1)),
dataTransfer = { files: this.files };
['dragenter', 'dragover', 'drop'].forEach(function (name) {
var evt = document.createEvent('MouseEvent');
evt.initMouseEvent(name, !0, !0, window, 0, 0, 0, x, y, !1, !1, !1, !1, 0, null);
evt.dataTransfer = dataTransfer;
target.dispatchEvent(evt);
});
setTimeout(function () { document.body.removeChild(input); }, 25);
};
document.body.appendChild(input);
return input;
"""


@step('I drag and drop the file "{filepath}" to "{name}"')
def drag_and_drop_file(ctx, name, filepath):
drop_target = fuzzy.find(ctx.browser, name, ["*"])
drop_target_html = drop_target.get_attribute("outerHTML")
logger.debug(
f'looked for drag & drop target "{name}" and found "{drop_target_html}"'
)
file_input = ctx.browser.execute(JS_DROP_FILE, drop_target, 0, 0)
file_input.send_keys(filepath)

0 comments on commit 8cd0203

Please sign in to comment.