Skip to content

Commit

Permalink
fix(assertions): error messages from negated matchers
Browse files Browse the repository at this point in the history
  • Loading branch information
mxschmitt committed Oct 28, 2024
1 parent 3352d85 commit f45fbcd
Show file tree
Hide file tree
Showing 3 changed files with 195 additions and 27 deletions.
31 changes: 16 additions & 15 deletions playwright/_impl/_assertions.py
Original file line number Diff line number Diff line change
Expand Up @@ -511,15 +511,14 @@ async def to_be_attached(
timeout: float = None,
) -> None:
__tracebackhide__ = True
if attached is None:
attached = True
attached_string = "attached" if attached else "detached"
await self._expect_impl(
(
"to.be.attached"
if (attached is None or attached is True)
else "to.be.detached"
),
("to.be.attached" if attached else "to.be.detached"),
FrameExpectOptions(timeout=timeout),
None,
"Locator expected to be attached",
f"Locator expected to be {attached_string}",
)

async def to_be_checked(
Expand All @@ -528,15 +527,14 @@ async def to_be_checked(
checked: bool = None,
) -> None:
__tracebackhide__ = True
if checked is None:
checked = True
checked_string = "checked" if checked else "unchecked"
await self._expect_impl(
(
"to.be.checked"
if checked is None or checked is True
else "to.be.unchecked"
),
("to.be.checked" if checked else "to.be.unchecked"),
FrameExpectOptions(timeout=timeout),
None,
"Locator expected to be checked",
f"Locator expected to be {checked_string}",
)

async def not_to_be_attached(
Expand Down Expand Up @@ -581,11 +579,12 @@ async def to_be_editable(
__tracebackhide__ = True
if editable is None:
editable = True
editable_string = "editable" if editable else "readonly"
await self._expect_impl(
"to.be.editable" if editable else "to.be.readonly",
FrameExpectOptions(timeout=timeout),
None,
"Locator expected to be editable",
f"Locator expected to be {editable_string}",
)

async def not_to_be_editable(
Expand Down Expand Up @@ -623,11 +622,12 @@ async def to_be_enabled(
__tracebackhide__ = True
if enabled is None:
enabled = True
enabled_string = "enabled" if enabled else "disabled"
await self._expect_impl(
"to.be.enabled" if enabled else "to.be.disabled",
FrameExpectOptions(timeout=timeout),
None,
"Locator expected to be enabled",
f"Locator expected to be {enabled_string}",
)

async def not_to_be_enabled(
Expand Down Expand Up @@ -665,11 +665,12 @@ async def to_be_visible(
__tracebackhide__ = True
if visible is None:
visible = True
visible_string = "visible" if visible else "hidden"
await self._expect_impl(
"to.be.visible" if visible else "to.be.hidden",
FrameExpectOptions(timeout=timeout),
None,
"Locator expected to be visible",
f"Locator expected to be {visible_string}",
)

async def not_to_be_visible(
Expand Down
144 changes: 138 additions & 6 deletions tests/async/test_assertions.py
Original file line number Diff line number Diff line change
Expand Up @@ -510,14 +510,14 @@ async def test_assertions_locator_to_be_checked(page: Page, server: Server) -> N
await page.set_content("<input type=checkbox>")
my_checkbox = page.locator("input")
await expect(my_checkbox).not_to_be_checked()
with pytest.raises(AssertionError):
with pytest.raises(AssertionError, match="Locator expected to be checked"):
await expect(my_checkbox).to_be_checked(timeout=100)
await expect(my_checkbox).to_be_checked(timeout=100, checked=False)
with pytest.raises(AssertionError):
await expect(my_checkbox).to_be_checked(timeout=100, checked=True)
await my_checkbox.check()
await expect(my_checkbox).to_be_checked(timeout=100, checked=True)
with pytest.raises(AssertionError):
with pytest.raises(AssertionError, match="Locator expected to be unchecked"):
await expect(my_checkbox).to_be_checked(timeout=100, checked=False)
await expect(my_checkbox).to_be_checked()

Expand All @@ -534,19 +534,91 @@ async def test_assertions_locator_to_be_disabled_enabled(
await expect(my_checkbox).to_be_disabled(timeout=100)
await my_checkbox.evaluate("e => e.disabled = true")
await expect(my_checkbox).to_be_disabled()
with pytest.raises(AssertionError):
with pytest.raises(AssertionError, match="Locator expected to be enabled"):
await expect(my_checkbox).to_be_enabled(timeout=100)


async def test_assertions_locator_to_be_enabled_with_true(page: Page) -> None:
await page.set_content("<button>Text</button>")
await expect(page.locator("button")).to_be_enabled(enabled=True)


async def test_assertions_locator_to_be_enabled_with_false_throws_good_exception(
page: Page,
) -> None:
await page.set_content("<button>Text</button>")
with pytest.raises(AssertionError, match="Locator expected to be disabled"):
await expect(page.locator("button")).to_be_enabled(enabled=False)


async def test_assertions_locator_to_be_enabled_with_false(page: Page) -> None:
await page.set_content("<button disabled>Text</button>")
await expect(page.locator("button")).to_be_enabled(enabled=False)


async def test_assertions_locator_to_be_enabled_with_not_and_false(page: Page) -> None:
await page.set_content("<button>Text</button>")
await expect(page.locator("button")).not_to_be_enabled(enabled=False)


async def test_assertions_locator_to_be_enabled_eventually(page: Page) -> None:
await page.set_content("<button disabled>Text</button>")
await page.eval_on_selector(
"button",
"""
button => setTimeout(() => {
button.removeAttribute('disabled');
}, 700);
""",
)
await expect(page.locator("button")).to_be_enabled()


async def test_assertions_locator_to_be_enabled_eventually_with_not(page: Page) -> None:
await page.set_content("<button>Text</button>")
await page.eval_on_selector(
"button",
"""
button => setTimeout(() => {
button.setAttribute('disabled', '');
}, 700);
""",
)
await expect(page.locator("button")).not_to_be_enabled()


async def test_assertions_locator_to_be_editable(page: Page, server: Server) -> None:
await page.goto(server.EMPTY_PAGE)
await page.set_content("<input></input><button disabled>Text</button>")
await expect(page.locator("button")).not_to_be_editable()
await expect(page.locator("input")).to_be_editable()
with pytest.raises(AssertionError):
with pytest.raises(AssertionError, match="Locator expected to be editable"):
await expect(page.locator("button")).to_be_editable(timeout=100)


async def test_assertions_locator_to_be_editable_with_true(page: Page) -> None:
await page.set_content("<input></input>")
await expect(page.locator("input")).to_be_editable(editable=True)


async def test_assertions_locator_to_be_editable_with_false(page: Page) -> None:
await page.set_content("<input readonly></input>")
await expect(page.locator("input")).to_be_editable(editable=False)


async def test_assertions_locator_to_be_editable_with_false_and_throw_good_exception(
page: Page,
) -> None:
await page.set_content("<input></input>")
with pytest.raises(AssertionError, match="Locator expected to be readonly"):
await expect(page.locator("input")).to_be_editable(editable=False)


async def test_assertions_locator_to_be_editable_with_not_and_false(page: Page) -> None:
await page.set_content("<input></input>")
await expect(page.locator("input")).not_to_be_editable(editable=False)


async def test_assertions_locator_to_be_empty(page: Page, server: Server) -> None:
await page.goto(server.EMPTY_PAGE)
await page.set_content(
Expand Down Expand Up @@ -579,10 +651,59 @@ async def test_assertions_locator_to_be_hidden_visible(
await expect(my_checkbox).to_be_hidden(timeout=100)
await my_checkbox.evaluate("e => e.style.display = 'none'")
await expect(my_checkbox).to_be_hidden()
with pytest.raises(AssertionError):
with pytest.raises(AssertionError, match="Locator expected to be visible"):
await expect(my_checkbox).to_be_visible(timeout=100)


async def test_assertions_locator_to_be_visible_with_true(page: Page) -> None:
await page.set_content("<button>hello</button>")
await expect(page.locator("button")).to_be_visible(visible=True)


async def test_assertions_locator_to_be_visible_with_false(page: Page) -> None:
await page.set_content("<button hidden>hello</button>")
await expect(page.locator("button")).to_be_visible(visible=False)


async def test_assertions_locator_to_be_visible_with_false_throws_good_exception(
page: Page,
) -> None:
await page.set_content("<button>hello</button>")
with pytest.raises(AssertionError, match="Locator expected to be hidden"):
await expect(page.locator("button")).to_be_visible(visible=False)


async def test_assertions_locator_to_be_visible_with_not_and_false(page: Page) -> None:
await page.set_content("<button>hello</button>")
await expect(page.locator("button")).not_to_be_visible(visible=False)


async def test_assertions_locator_to_be_visible_eventually(page: Page) -> None:
await page.set_content("<div></div>")
await page.eval_on_selector(
"div",
"""
div => setTimeout(() => {
div.innerHTML = '<span>Hello</span>';
}, 700);
""",
)
await expect(page.locator("span")).to_be_visible()


async def test_assertions_locator_to_be_visible_eventually_with_not(page: Page) -> None:
await page.set_content("<div><span>Hello</span></div>")
await page.eval_on_selector(
"span",
"""
span => setTimeout(() => {
span.textContent = '';
}, 700);
""",
)
await expect(page.locator("span")).not_to_be_visible()


async def test_assertions_should_serialize_regexp_correctly(
page: Page, server: Server
) -> None:
Expand Down Expand Up @@ -746,6 +867,15 @@ async def test_should_be_attached_with_attached_false(page: Page) -> None:
await expect(locator).to_be_attached(attached=False)


async def test_should_be_attached_with_attached_false_and_throw_good_error(
page: Page,
) -> None:
await page.set_content("<button>hello</button>")
locator = page.locator("button")
with pytest.raises(AssertionError, match="Locator expected to be detached"):
await expect(locator).to_be_attached(attached=False, timeout=1)


async def test_should_be_attached_with_not_and_attached_false(page: Page) -> None:
await page.set_content("<button>hello</button>")
locator = page.locator("button")
Expand Down Expand Up @@ -773,7 +903,9 @@ async def test_should_be_attached_eventually_with_not(page: Page) -> None:
async def test_should_be_attached_fail(page: Page) -> None:
await page.set_content("<button>Hello</button>")
locator = page.locator("input")
with pytest.raises(AssertionError) as exc_info:
with pytest.raises(
AssertionError, match="Locator expected to be attached"
) as exc_info:
await expect(locator).to_be_attached(timeout=1000)
assert "locator resolved to" not in exc_info.value.args[0]

Expand Down
47 changes: 41 additions & 6 deletions tests/sync/test_assertions.py
Original file line number Diff line number Diff line change
Expand Up @@ -490,14 +490,14 @@ def test_assertions_locator_to_be_checked(page: Page, server: Server) -> None:
page.set_content("<input type=checkbox>")
my_checkbox = page.locator("input")
expect(my_checkbox).not_to_be_checked()
with pytest.raises(AssertionError):
with pytest.raises(AssertionError, match="Locator expected to be checked"):
expect(my_checkbox).to_be_checked(timeout=100)
expect(my_checkbox).to_be_checked(timeout=100, checked=False)
with pytest.raises(AssertionError):
expect(my_checkbox).to_be_checked(timeout=100, checked=True)
my_checkbox.check()
expect(my_checkbox).to_be_checked(timeout=100, checked=True)
with pytest.raises(AssertionError):
with pytest.raises(AssertionError, match="Locator expected to be unchecked"):
expect(my_checkbox).to_be_checked(timeout=100, checked=False)
expect(my_checkbox).to_be_checked()

Expand All @@ -512,7 +512,7 @@ def test_assertions_locator_to_be_disabled_enabled(page: Page, server: Server) -
expect(my_checkbox).to_be_disabled(timeout=100)
my_checkbox.evaluate("e => e.disabled = true")
expect(my_checkbox).to_be_disabled()
with pytest.raises(AssertionError):
with pytest.raises(AssertionError, match="Locator expected to be enabled"):
expect(my_checkbox).to_be_enabled(timeout=100)


Expand All @@ -521,6 +521,14 @@ def test_assertions_locator_to_be_enabled_with_true(page: Page) -> None:
expect(page.locator("button")).to_be_enabled(enabled=True)


def test_assertions_locator_to_be_enabled_with_false_throws_good_exception(
page: Page,
) -> None:
page.set_content("<button>Text</button>")
with pytest.raises(AssertionError, match="Locator expected to be disabled"):
expect(page.locator("button")).to_be_enabled(enabled=False)


def test_assertions_locator_to_be_enabled_with_false(page: Page) -> None:
page.set_content("<button disabled>Text</button>")
expect(page.locator("button")).to_be_enabled(enabled=False)
Expand Down Expand Up @@ -562,7 +570,7 @@ def test_assertions_locator_to_be_editable(page: Page, server: Server) -> None:
page.set_content("<input></input><button disabled>Text</button>")
expect(page.locator("button")).not_to_be_editable()
expect(page.locator("input")).to_be_editable()
with pytest.raises(AssertionError):
with pytest.raises(AssertionError, match="Locator expected to be editable"):
expect(page.locator("button")).to_be_editable(timeout=100)


Expand All @@ -576,6 +584,14 @@ def test_assertions_locator_to_be_editable_with_false(page: Page) -> None:
expect(page.locator("input")).to_be_editable(editable=False)


def test_assertions_locator_to_be_editable_with_false_and_throw_good_exception(
page: Page,
) -> None:
page.set_content("<input></input>")
with pytest.raises(AssertionError, match="Locator expected to be readonly"):
expect(page.locator("input")).to_be_editable(editable=False)


def test_assertions_locator_to_be_editable_with_not_and_false(page: Page) -> None:
page.set_content("<input></input>")
expect(page.locator("input")).not_to_be_editable(editable=False)
Expand Down Expand Up @@ -611,7 +627,7 @@ def test_assertions_locator_to_be_hidden_visible(page: Page, server: Server) ->
expect(my_checkbox).to_be_hidden(timeout=100)
my_checkbox.evaluate("e => e.style.display = 'none'")
expect(my_checkbox).to_be_hidden()
with pytest.raises(AssertionError):
with pytest.raises(AssertionError, match="Locator expected to be visible"):
expect(my_checkbox).to_be_visible(timeout=100)


Expand All @@ -625,6 +641,14 @@ def test_assertions_locator_to_be_visible_with_false(page: Page) -> None:
expect(page.locator("button")).to_be_visible(visible=False)


def test_assertions_locator_to_be_visible_with_false_throws_good_exception(
page: Page,
) -> None:
page.set_content("<button>hello</button>")
with pytest.raises(AssertionError, match="Locator expected to be hidden"):
expect(page.locator("button")).to_be_visible(visible=False)


def test_assertions_locator_to_be_visible_with_not_and_false(page: Page) -> None:
page.set_content("<button>hello</button>")
expect(page.locator("button")).not_to_be_visible(visible=False)
Expand Down Expand Up @@ -813,6 +837,15 @@ def test_should_be_attached_with_attached_false(page: Page) -> None:
expect(locator).to_be_attached(attached=False)


def test_should_be_attached_with_attached_false_and_throw_good_error(
page: Page,
) -> None:
page.set_content("<button>hello</button>")
locator = page.locator("button")
with pytest.raises(AssertionError, match="Locator expected to be detached"):
expect(locator).to_be_attached(attached=False, timeout=1)


def test_should_be_attached_with_not_and_attached_false(page: Page) -> None:
page.set_content("<button>hello</button>")
locator = page.locator("button")
Expand All @@ -838,7 +871,9 @@ def test_should_be_attached_eventually_with_not(page: Page) -> None:
def test_should_be_attached_fail(page: Page) -> None:
page.set_content("<button>Hello</button>")
locator = page.locator("input")
with pytest.raises(AssertionError) as exc_info:
with pytest.raises(
AssertionError, match="Locator expected to be attached"
) as exc_info:
expect(locator).to_be_attached(timeout=1000)
assert "locator resolved to" not in exc_info.value.args[0]

Expand Down

0 comments on commit f45fbcd

Please sign in to comment.