Skip to content

Commit

Permalink
revert .filter usage in playwright and add test to check occurences
Browse files Browse the repository at this point in the history
  • Loading branch information
karangattu committed Aug 27, 2024
1 parent a47f062 commit 187089f
Show file tree
Hide file tree
Showing 2 changed files with 96 additions and 6 deletions.
19 changes: 13 additions & 6 deletions shiny/playwright/controller/_controls.py
Original file line number Diff line number Diff line change
Expand Up @@ -263,9 +263,10 @@ def __init__(
loc = loc_container

else:
loc_container = loc_container.filter(
loc_container = loc_container.locator(
# `page.locator(loc)` is executed from within `loc_container`
has=page.locator(loc)
"xpath=.",
has=page.locator(loc),
)

loc = loc_container.locator(loc)
Expand Down Expand Up @@ -1792,7 +1793,8 @@ def expect_locator_contains_values_in_list(
# Find all items in set
for item in arr:
# Given the container, make sure it contains this locator
loc_container = loc_container.filter(
loc_container = loc_container.locator(
"xpath=.",
# Simple approach as position is not needed
has=page.locator(
f"{el_type}[{_attr_match_str(key, item)}]{is_checked_str}",
Expand Down Expand Up @@ -1894,7 +1896,11 @@ def expect_locator_values_in_list(
)

# Given the container, make sure it contains this locator
loc_container = loc_container.filter(has=has_locator)
loc_container = loc_container.locator(
# Return self
"xpath=.",
has=has_locator,
)

# Make sure other items are not in set
# If we know all elements are contained in the container,
Expand Down Expand Up @@ -4908,7 +4914,8 @@ def __init__(self, page: Page, id: str) -> None:
loc="> div.accordion-item",
loc_container=f"div#{id}.accordion.shiny-bound-input",
)
# self.loc_open = self.loc.filter(
# self.loc_open = self.loc.locator(
# "xpath=.",
# # Simple approach as position is not needed
# has=page.locator(
# "> div.accordion-collapse.show",
Expand Down Expand Up @@ -5909,7 +5916,7 @@ def __init__(
self.loc_title = (
self.loc_container.locator("..")
.locator("> span")
.filter(has=self.page.locator(f"+ ul#{self.id}"))
.locator("xpath=.", has=self.page.locator(f"+ ul#{self.id}"))
)


Expand Down
83 changes: 83 additions & 0 deletions tests/pytest/test_playwright_filter.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
from __future__ import annotations

import glob
from pathlib import Path
from typing import Dict, Set

from tests.pytest._utils import skip_on_windows

known_entries: Dict[str, Set[str]] = {
# "tests/pytest/test_poll.py": {
# "my_locator.filter('foo')",
# }
}

# Trim all line values of `known_entries`
for k, v in known_entries.items():
known_entries[k] = {x.strip() for x in v}


@skip_on_windows
def test_named_temporary_file_is_not_used():
"""
Playwright's Locator hangs when we call `.filter(foo)`.
Instead you should use `.locator("xpath=.", has=page.locator(foo))`
"""

root_here = Path(__file__).parent.parent.parent
shiny_files = glob.glob(str(root_here / "shiny" / "**" / "*.py"), recursive=True)
tests_files = glob.glob(str(root_here / "tests" / "**" / "*.py"), recursive=True)

assert len(shiny_files) > 0
assert len(tests_files) > 0

all_files = [*shiny_files, *tests_files]

search_string = ".filter("

bad_entries: list[tuple[Path, int, str]] = []

# For every python file...
for path in all_files:
path = Path(path)
# Skip if dir
if path.is_dir():
continue

# Skip this file
if path.name in {"test_playwright_filter.py"}:
continue

with open(path, "r") as f:
# Read file contents
txt = f.read().replace(".filter()", ".not_playwright_filter()")

# Skip if search string is not in file
if search_string not in txt:
continue

# Split file contents by line
lines = txt.split("\n")
rel_path = path.relative_to(root_here)
known_lines = known_entries.get(str(rel_path), set())
seen_lines: set[str] = set()

# If the search string is in the line
# and the line is not in the known lines,
# add it to the bad entries
for i, line in enumerate(lines):
line = line.strip()
if search_string in line:
seen_lines.add(line)
if line not in known_lines:
bad_entries.append((rel_path, i + 1, line))

if (len(known_lines) > 0) and (len(seen_lines) != len(known_lines)):
raise ValueError(
f"Lines not found in {rel_path}: {known_lines - seen_lines}"
"\nPlease remove them from the known_entries dictionary."
)

assert (
len(bad_entries) == 0
), f"Unexpected files containing `.filter(`: {str(bad_entries)}"

0 comments on commit 187089f

Please sign in to comment.