Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 10 additions & 15 deletions .github/workflows/testing.yml
Original file line number Diff line number Diff line change
Expand Up @@ -116,9 +116,8 @@ jobs:

- name: Setup virtual display
run: |
sudo apt-get update
sudo apt-get install -y xvfb
sudo Xvfb :99 -ac -screen 0 1280x1024x24 &
sudo Xvfb :99 -ac -screen 0 1280x1024x24 >/dev/null 2>&1 &
disown
echo "DISPLAY=:99" >> $GITHUB_ENV

- name: Run lint
Expand Down Expand Up @@ -673,9 +672,8 @@ jobs:

- name: Setup virtual display
run: |
sudo apt-get update
sudo apt-get install -y xvfb
sudo Xvfb :99 -ac -screen 0 1280x1024x24 &
sudo Xvfb :99 -ac -screen 0 1280x1024x24 >/dev/null 2>&1 &
disown
echo "DISPLAY=:99" >> $GITHUB_ENV

- name: Build/Setup test components
Expand Down Expand Up @@ -778,9 +776,8 @@ jobs:

- name: Setup virtual display
run: |
sudo apt-get update
sudo apt-get install -y xvfb
sudo Xvfb :99 -ac -screen 0 1280x1024x24 &
sudo Xvfb :99 -ac -screen 0 1280x1024x24 >/dev/null 2>&1 &
disown
echo "DISPLAY=:99" >> $GITHUB_ENV

- name: Install HTML components dependencies
Expand Down Expand Up @@ -975,9 +972,8 @@ jobs:

- name: Setup virtual display
run: |
sudo apt-get update
sudo apt-get install -y xvfb
sudo Xvfb :99 -ac -screen 0 1280x1024x24 &
sudo Xvfb :99 -ac -screen 0 1280x1024x24 >/dev/null 2>&1 &
disown
echo "DISPLAY=:99" >> $GITHUB_ENV

- name: Remove DCC Python package and run tests
Expand Down Expand Up @@ -1059,9 +1055,8 @@ jobs:

- name: Setup virtual display
run: |
sudo apt-get update
sudo apt-get install -y xvfb
sudo Xvfb :99 -ac -screen 0 1280x1024x24 &
sudo Xvfb :99 -ac -screen 0 1280x1024x24 >/dev/null 2>&1 &
disown
echo "DISPLAY=:99" >> $GITHUB_ENV

- name: Install Table test dependencies
Expand Down
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ This project adheres to [Semantic Versioning](https://semver.org/).
- [#3646](https://github.com/plotly/dash/pull/3646) Remove React 16 support (`16.14.0` is no longer an accepted value for `REACT_VERSION` / `_set_react_version`).

### Fixed
- Unpin `selenium` in the testing requirements (was capped at `<=4.2.0`, from 2022) and require `>=4.11.0`. The old cap predated Selenium Manager, so the pinned selenium could not drive the current stable Chrome (151+) that CI installs, producing widespread `StaleElementReferenceException`/`TimeoutException` flakiness across the browser-based integration tests. Modern selenium auto-provisions a matching chromedriver, restoring stable CI runs.
- [#3941](https://github.com/plotly/dash/pull/3941) Fix the FastAPI and Quart backends opening a WebSocket connection on every page load, even for apps with no WebSocket callbacks. The renderer keyed the connection on the mere presence of WebSocket infrastructure (always advertised by these backends) rather than on whether it was needed. The socket now opens eagerly only when `websocket_callbacks=True`; with just per-callback `websocket=True` it opens lazily on the first such callback dispatch, and an app with no WebSocket callbacks never opens one. Fixes [#3939](https://github.com/plotly/dash/issues/3939).
- [#3916](https://github.com/plotly/dash/pull/3916) Fixed a regression where dragging multiple files into `dcc.Upload` would upload only the first file when `multiple=True`
- [#3922](https://github.com/plotly/dash/pull/3922) Fix `dcc.Input(type="number")` stepper behavior when only `min` is set.
Expand Down
16 changes: 12 additions & 4 deletions components/dash-core-components/tests/dash_core_components_page.py
Original file line number Diff line number Diff line change
Expand Up @@ -103,14 +103,18 @@ def click_and_hold_at_coord_fractions(self, elem_or_selector, fx, fy):
elem = self._get_element(elem_or_selector)

ActionChains(self.driver).move_to_element_with_offset(
elem, elem.size["width"] * fx, elem.size["height"] * fy
elem,
int(elem.size["width"] * (fx - 0.5)),
int(elem.size["height"] * (fy - 0.5)),
).click_and_hold().perform()

def move_to_coord_fractions(self, elem_or_selector, fx, fy):
elem = self._get_element(elem_or_selector)

ActionChains(self.driver).click_and_hold().move_to_element_with_offset(
elem, elem.size["width"] * fx, elem.size["height"] * fy
elem,
int(elem.size["width"] * (fx - 0.5)),
int(elem.size["height"] * (fy - 0.5)),
).perform()

def release(self):
Expand All @@ -120,7 +124,11 @@ def click_and_drag_at_coord_fractions(self, elem_or_selector, fx1, fy1, fx2, fy2
elem = self._get_element(elem_or_selector)

ActionChains(self.driver).move_to_element_with_offset(
elem, elem.size["width"] * fx1, elem.size["height"] * fy1
elem,
int(elem.size["width"] * (fx1 - 0.5)),
int(elem.size["height"] * (fy1 - 0.5)),
).click_and_hold().move_to_element_with_offset(
elem, elem.size["width"] * fx2, elem.size["height"] * fy2
elem,
int(elem.size["width"] * (fx2 - 0.5)),
int(elem.size["height"] * (fy2 - 0.5)),
).release().perform()
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# -*- coding: utf-8 -*-

from selenium.webdriver.common.by import By

from dash import Dash, Input, Output, dcc, html


Expand Down Expand Up @@ -71,11 +73,11 @@ def update_md(nclicks):

# a highlighted node will have <span> children which are what color the text
code = dash_dcc.wait_for_element("code[data-highlighted='yes']")
assert len(code.find_elements_by_tag_name("span")) == 2
assert len(code.find_elements(By.TAG_NAME, "span")) == 2

dash_dcc.find_element("#md-trigger").click()

code = dash_dcc.wait_for_element("code[data-highlighted='yes']")
assert len(code.find_elements_by_tag_name("span")) == 3
assert len(code.find_elements(By.TAG_NAME, "span")) == 3

assert dash_dcc.get_logs() == []
Original file line number Diff line number Diff line change
Expand Up @@ -68,9 +68,10 @@ def update_tooltip_content(hoverData):
elem = dash_dcc.find_element("#graph .nsewdrag")

with lock:
# hover on the center of the graph
# hover on the center of the graph (offset is measured from the
# element center in selenium >= 4.3, so 0, 0 is the center)
ActionChains(dash_dcc.driver).move_to_element_with_offset(
elem, elem.size["width"] / 2, elem.size["height"] / 2
elem, 0, 0
).click().perform()
dash_dcc.wait_for_text_to_equal("#graph-tooltip", loading_text)

Expand All @@ -83,7 +84,7 @@ def update_tooltip_content(hoverData):
elem = dash_dcc.find_element("#graph .nsewdrag")

ActionChains(dash_dcc.driver).move_to_element_with_offset(
elem, 5, elem.size["height"] - 5
elem, int(5 - elem.size["width"] / 2), int(elem.size["height"] / 2 - 5)
).perform()

until(lambda: not dash_dcc.find_element("#graph-tooltip").is_displayed(), 3)
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import time
from selenium.webdriver.common.by import By
from dash import Dash, dcc, html


Expand Down Expand Up @@ -41,16 +42,16 @@ def test_upca001_upload_children_gallery(dash_dcc):
time.sleep(0.5)
dash_dcc.percy_snapshot("upca001 children gallery")

first_child = dash_dcc.find_element("#upload").find_element_by_css_selector(
":first-child"
first_child = dash_dcc.find_element("#upload").find_element(
By.CSS_SELECTOR, ":first-child"
)
# Check that there is no default style since className is specified
style = first_child.get_attribute("style")
assert "opacity: 0.5" not in style

first_child = dash_dcc.find_element(
"#upload-no-className"
).find_element_by_css_selector(":first-child")
first_child = dash_dcc.find_element("#upload-no-className").find_element(
By.CSS_SELECTOR, ":first-child"
)

# Check that there is default style since no className is specified
style = first_child.get_attribute("style")
Expand Down
8 changes: 4 additions & 4 deletions dash/testing/browser.py
Original file line number Diff line number Diff line change
Expand Up @@ -539,8 +539,6 @@ def _get_chrome(self):
def _get_firefox(self):
options = self._get_wd_options()

options.set_capability("marionette", True)

options.set_preference("browser.download.dir", self.download_path)
options.set_preference("browser.download.folderList", 2)
options.set_preference(
Expand Down Expand Up @@ -598,7 +596,7 @@ def zoom_in_graph_by_ratio(
w, h = elem.size["width"], elem.size["height"]
try:
ActionChains(self.driver).move_to_element_with_offset(
elem, w * start_fraction, h * start_fraction
elem, int(w * (start_fraction - 0.5)), int(h * (start_fraction - 0.5))
).drag_and_drop_by_offset(
elem, w * zoom_box_fraction, h * zoom_box_fraction
).perform()
Expand All @@ -613,7 +611,9 @@ def click_at_coord_fractions(self, elem_or_selector, fx, fy):
elem = self._get_element(elem_or_selector)

ActionChains(self.driver).move_to_element_with_offset(
elem, elem.size["width"] * fx, elem.size["height"] * fy
elem,
int(elem.size["width"] * (fx - 0.5)),
int(elem.size["height"] * (fy - 0.5)),
).click().perform()

def get_logs(self):
Expand Down
2 changes: 1 addition & 1 deletion requirements/testing.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ lxml>=4.6.2
percy-python-selenium>=1.0.0
pytest>=6.0.2
requests[security]>=2.21.0
selenium>=3.141.0,<=4.2.0
selenium>=4.11.0,<=4.46.0
waitress>=1.4.4
multiprocess>=0.70.12
psutil>=5.8.0
Expand Down
7 changes: 4 additions & 3 deletions tests/integration/callbacks/test_multiple_callbacks.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
from multiprocessing import Value, Lock

import pytest
from selenium.webdriver.common.by import By

from dash import Dash, Input, Output, State, callback_context, html, dcc, dash_table
from dash.exceptions import PreventUpdate
Expand Down Expand Up @@ -648,9 +649,9 @@ def set_display_children(selected_country, selected_city):
assert out_call_count.value == 1

all_labels = dash_duo.find_elements("label")
canada_opt = next(
i for i in all_labels if i.text == "Canada"
).find_element_by_tag_name("input")
canada_opt = next(i for i in all_labels if i.text == "Canada").find_element(
By.TAG_NAME, "input"
)

with out_lock:
canada_opt.click()
Expand Down
14 changes: 7 additions & 7 deletions tests/integration/test_duo.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,39 +12,39 @@ def test_duo001_wait_for_text_error(dash_duo):
with pytest.raises(TimeoutException) as err:
dash_duo.wait_for_text_to_equal("#content", "Invalid", timeout=1.0)

assert err.value.args[0] == "text -> Invalid not found within 1.0s, found: Content"
assert err.value.msg == "text -> Invalid not found within 1.0s, found: Content"

with pytest.raises(TimeoutException) as err:
dash_duo.wait_for_text_to_equal("#content", "None", timeout=1.0)

assert err.value.args[0] == "text -> None not found within 1.0s, found: Content"
assert err.value.msg == "text -> None not found within 1.0s, found: Content"

with pytest.raises(TimeoutException) as err:
dash_duo.wait_for_text_to_equal("#none", "None", timeout=1.0)

assert err.value.args[0] == "text -> None not found within 1.0s, #none not found"
assert err.value.msg == "text -> None not found within 1.0s, #none not found"

with pytest.raises(TimeoutException) as err:
dash_duo.wait_for_contains_text("#content", "invalid", timeout=1.0)

assert (
err.value.args[0]
err.value.msg
== "text -> invalid not found inside element within 1.0s, found: Content"
)

with pytest.raises(TimeoutException) as err:
dash_duo.wait_for_contains_text("#content", "None", timeout=1.0)

assert (
err.value.args[0]
err.value.msg
== "text -> None not found inside element within 1.0s, found: Content"
)

with pytest.raises(TimeoutException) as err:
dash_duo.wait_for_contains_text("#none", "none", timeout=1.0)

assert (
err.value.args[0]
err.value.msg
== "text -> none not found inside element within 1.0s, #none not found"
)

Expand All @@ -59,6 +59,6 @@ def test_duo002_wait_for_text_value(dash_duo):
dash_duo.wait_for_contains_text("#value-item", "None", timeout=1.0)

assert (
err.value.args[0]
err.value.msg
== "text -> None not found inside element within 1.0s, found: Item"
)