Changelog¶
Changelog¶
All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
[1.0.0] - 2026-08-27¶
Added¶
- Project skeleton with CI, linting, and build infrastructure
- Regression tests for all bug fixes listed below
CONTRIBUTING.mdwith development setup, testing guidelines, and architecture overviewSECURITY.mdwith vulnerability reporting policyCODE_OF_CONDUCT.mdbased on Contributor Covenant 2.1- GitHub issue templates for bug reports and feature requests
- Automated release workflow (
.github/workflows/release.yml) with PyPI trusted publishing and GitHub Releases expect.configure()example and Features section to README- Ruff badge to README header
- Comprehensive MkDocs documentation with Material theme
- Auto-retry polling with configurable timeout and backoff schedules
- Fluent assertion API for
WebElement,WebDriver,list[WebElement],Alert,Select,ShadowRoot, iframes, cookies, JavaScript, and windows - Locator-based expect to avoid
StaleElementReferenceException - Soft assertions with
SoftAssertionCollectorandassert_all() - Custom matchers via
@extenddecorator andmerge_expects() expect.poll()for retry-based assertions on arbitrary functionsExpectConfigdataclass for global and per-assertion configuration- Screenshot capture on assertion failure
- Debug mode with per-poll logging
- Descriptive error messages with timelines and actual vs expected values
- Composition assertions:
to_satisfy_all,to_satisfy_any,to_satisfy_none - Negation via
.not_on all assertions
Fixed¶
_retry.py: Emptypolling_intervalslist causedIndexErroron first poll_retry.py:timeout=0skipped the first poll, never evaluating the condition_config.py:ExpectConfigdid not validate emptypolling_intervalslists_config.py:set_default_timeout()did not normalize milliseconds (int >= 1000 treated as seconds instead of ms)_poll.py:PollAssertion.to_contain()crashed on falsy non-string values (0,False,[])_poll.py:PollAssertiondid not normalize timeout consistently withexpect()_poll.py: Missing validation for empty per-assertionpollinglists_expect.py:expect(timeout=5000)stored 5000 seconds instead of 5 seconds (timeout not normalized before config overrides)_locator.py:LocatorExpect.__getattr__did not fall back toCustomMatcherRegistry, breaking custom matchers on locator-based assertionslist.py:to_have_texts_containsandto_have_texts_containingcrashed onNoneelement textjs.py:to_have_js_result_containscrashed on falsy non-string values (0,False,[])js.py: JavaScript injection vulnerability inlocalStorage,sessionStorage, andto_have_js_variablemethods (f-string interpolation replaced witharguments[0]parameter passing)driver.py:to_have_capability_containscrashed on falsy non-string capability values (False,0)element.py:to_have_property_containscrashed on falsy non-string property values (False,0)
Changed¶
_expect.py: Replacedexpectfunction with monkeypatched.poll/.configureattributes with a properExpectcallable class — eliminatestype: ignore, improves type safety and API discoverability_base.py: Replacedos/os.pathwithpathlib.Pathfor screenshot path handling_base.py: Screenshot timestamps now use timezone-awaredatetime.now(tz=UTC)instead of naivedatetime.now()_config.py: Centralizednormalize_timeoutfunction imported by all modules that need timeout normalization