mirror of
https://github.com/User0332/rewards-farmer.git
synced 2026-09-18 01:51:37 +00:00
tell absence and a slow render apart when a task fails
Every failed task printed the same reason, because the blanket catch in complete_all_tasks treated NoSuchElementException and TimeoutException as one finding. A wait that expires says nothing about whether the section was there, since wait_for_element swallowed whatever the getter raised and returned False. A market that does not ship visual search and a points panel that was on screen and slow both arrived as TimeoutException wait_for_element now keeps the last reason the getter gave and raises ElementNeverAppeared when nothing was in the DOM for the whole wait. _container_by_id raises ElementNotReady when the id is present but no visible copy has content yet, which is the hydrating case it used to report as missing. Both subclass what they refine, so claim_bonus_points and complete_bing_daily_set keep working untouched A task that was reached and then ran out of time is now a [FAIL] rather than a [SKIP], because it may have left points behind. Absence stays a [SKIP] 56 tests pass, 20 of them new. A mutation check backs them, forcing every expired wait to count as absence fails 2, and collapsing the two branches back into one [SKIP] fails 4 Refs #52
This commit is contained in:
@@ -6,6 +6,20 @@ from selenium.common.exceptions import NoSuchElementException, StaleElementRefer
|
||||
from selenium import webdriver
|
||||
|
||||
|
||||
class ElementNotReady(NoSuchElementException):
|
||||
"""The element is in the page but not usable yet.
|
||||
|
||||
A section this market does not ship and a section that has not finished
|
||||
hydrating both reach the caller as NoSuchElementException, which is why a
|
||||
run could report "not available in this UI variant" for something that was
|
||||
on screen. They need different messages and different next steps, so the
|
||||
second case gets its own type.
|
||||
|
||||
Subclassed rather than separate, so every existing `except
|
||||
NoSuchElementException` keeps catching it.
|
||||
"""
|
||||
|
||||
|
||||
class Labels:
|
||||
"""Visible labels the selectors match on.
|
||||
|
||||
@@ -45,7 +59,9 @@ class ElementSelectionUtils:
|
||||
pick the copy that is visible and actually has content.
|
||||
|
||||
Anything the current variant does not ship raises NoSuchElementException so
|
||||
the caller can skip that task instead of aborting the whole run.
|
||||
the caller can skip that task instead of aborting the whole run. Something
|
||||
that is present but not usable yet raises ElementNotReady instead, because
|
||||
skipping it is the wrong answer and so is the message that goes with it.
|
||||
"""
|
||||
|
||||
def __init__(self, driver: webdriver.Edge):
|
||||
@@ -66,6 +82,11 @@ class ElementSelectionUtils:
|
||||
their `.text` is empty, so returning one produces silent no-ops further
|
||||
up. Raising instead lets the caller's WebDriverWait retry while the page
|
||||
finishes hydrating.
|
||||
|
||||
The two failures are not the same finding. No element with the id means
|
||||
this variant does not ship the section. An id that is there but has no
|
||||
usable copy means it is still rendering, so that one raises
|
||||
ElementNotReady.
|
||||
"""
|
||||
matches = self.driver.find_elements(By.ID, element_id)
|
||||
|
||||
@@ -79,7 +100,7 @@ class ElementSelectionUtils:
|
||||
except StaleElementReferenceException:
|
||||
continue
|
||||
|
||||
raise NoSuchElementException(
|
||||
raise ElementNotReady(
|
||||
f"{element_id!r} is present but no visible copy has content yet"
|
||||
)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user