# Copyright (c) Microsoft Corporation.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import asyncio
import datetime
import re
import pytest
from playwright.async_api import Browser, Error, Page, expect
from tests.server import Server
async def test_assertions_page_to_have_title(page: Page, server: Server) -> None:
await page.goto(server.EMPTY_PAGE)
await page.set_content("
new title ")
await expect(page).to_have_title("new title")
await expect(page).to_have_title(re.compile("new title"))
with pytest.raises(AssertionError):
await expect(page).to_have_title("not the current title", timeout=750)
with pytest.raises(AssertionError):
await expect(page).to_have_title(re.compile("not the current title"), timeout=750)
with pytest.raises(AssertionError):
await expect(page).not_to_have_title(re.compile("new title"), timeout=750)
with pytest.raises(AssertionError):
await expect(page).not_to_have_title("new title", timeout=750)
await expect(page).not_to_have_title("great title", timeout=750)
await page.evaluate(
"""
setTimeout(() => {
document.title = 'great title';
}, 2000);
"""
)
await expect(page).to_have_title("great title")
await expect(page).to_have_title(re.compile("great title"))
async def test_assertions_page_to_have_url(page: Page, server: Server) -> None:
await page.goto(server.EMPTY_PAGE)
await expect(page).to_have_url(server.EMPTY_PAGE)
await expect(page).to_have_url(re.compile(r".*/empty\.html"))
with pytest.raises(AssertionError):
await expect(page).to_have_url("nooooo", timeout=750)
with pytest.raises(AssertionError):
await expect(page).to_have_url(re.compile("not-the-url"), timeout=750)
await page.evaluate(
"""
setTimeout(() => {
window.location = window.location.origin + '/grid.html';
}, 2000);
"""
)
await expect(page).to_have_url(server.PREFIX + "/grid.html")
await expect(page).not_to_have_url(server.EMPTY_PAGE, timeout=750)
with pytest.raises(AssertionError):
await expect(page).not_to_have_url(re.compile(r".*/grid\.html"), timeout=750)
with pytest.raises(AssertionError):
await expect(page).not_to_have_url(server.PREFIX + "/grid.html", timeout=750)
await expect(page).to_have_url(re.compile(r".*/grid\.html"))
await expect(page).not_to_have_url("**/empty.html", timeout=750)
async def test_assertions_page_to_have_url_with_base_url(browser: Browser, server: Server) -> None:
page = await browser.new_page(base_url=server.PREFIX)
await page.goto("/empty.html")
await expect(page).to_have_url("/empty.html")
await expect(page).to_have_url(re.compile(r".*/empty\.html"))
await page.close()
async def test_assertions_page_to_have_url_support_ignore_case(page: Page) -> None:
await page.goto("data:text/html,A
")
await expect(page).to_have_url("DATA:teXT/HTml,a
", ignore_case=True)
async def test_assertions_locator_to_contain_text(page: Page, server: Server) -> None:
await page.goto(server.EMPTY_PAGE)
await page.set_content("kek
")
await expect(page.locator("div#foobar")).to_contain_text("kek")
await expect(page.locator("div#foobar")).not_to_contain_text("bar", timeout=100)
with pytest.raises(AssertionError):
await expect(page.locator("div#foobar")).to_contain_text("bar", timeout=100)
await page.set_content("Text \n1
Text2
Text3
")
await expect(page.locator("div")).to_contain_text(["ext 1", re.compile("ext3")])
async def test_assertions_locator_to_contain_text_should_throw_if_arg_is_unsupported_type(
page: Page,
) -> None:
with pytest.raises(Error, match="value must be a string or regular expression"):
await expect(page.locator("div")).to_contain_text(1) # type: ignore
async def test_assertions_locator_to_have_attribute(page: Page, server: Server) -> None:
await page.goto(server.EMPTY_PAGE)
await page.set_content("kek
")
await expect(page.locator("div#foobar")).to_have_attribute("id", "foobar")
await expect(page.locator("div#foobar")).to_have_attribute("id", re.compile("foobar"))
await expect(page.locator("div#foobar")).not_to_have_attribute("id", "kek", timeout=100)
with pytest.raises(AssertionError):
await expect(page.locator("div#foobar")).to_have_attribute("id", "koko", timeout=100)
async def test_assertions_locator_to_have_attribute_ignore_case(page: Page, server: Page) -> None:
await page.set_content("Text content
")
locator = page.locator("#NoDe")
await expect(locator).to_have_attribute("id", "node", ignore_case=True)
await expect(locator).not_to_have_attribute("id", "node")
async def test_assertions_locator_to_have_class(page: Page, server: Server) -> None:
await page.goto(server.EMPTY_PAGE)
await page.set_content("kek
")
await expect(page.locator("div.foobar")).to_have_class("foobar")
await expect(page.locator("div.foobar")).to_have_class(["foobar"])
await expect(page.locator("div.foobar")).to_have_class(re.compile("foobar"))
await expect(page.locator("div.foobar")).to_have_class([re.compile("foobar")])
await expect(page.locator("div.foobar")).not_to_have_class("kekstar", timeout=100)
with pytest.raises(AssertionError):
await expect(page.locator("div.foobar")).to_have_class("oh-no", timeout=100)
async def test_assertions_locator_to_have_count(page: Page, server: Server) -> None:
await page.goto(server.EMPTY_PAGE)
await page.set_content("kek
kek
")
await expect(page.locator("div.foobar")).to_have_count(2)
await expect(page.locator("div.foobar")).not_to_have_count(42, timeout=100)
with pytest.raises(AssertionError):
await expect(page.locator("div.foobar")).to_have_count(42, timeout=100)
async def test_assertions_locator_to_have_css(page: Page, server: Server) -> None:
await page.goto(server.EMPTY_PAGE)
await page.set_content("kek
")
await expect(page.locator("div.foobar")).to_have_css("color", "rgb(234, 74, 90)")
await expect(page.locator("div.foobar")).not_to_have_css(
"color", "rgb(42, 42, 42)", timeout=100
)
with pytest.raises(AssertionError):
await expect(page.locator("div.foobar")).to_have_css(
"color", "rgb(42, 42, 42)", timeout=100
)
async def test_assertions_locator_to_have_id(page: Page, server: Server) -> None:
await page.goto(server.EMPTY_PAGE)
await page.set_content("kek
")
await expect(page.locator("div.foobar")).to_have_id("kek")
await expect(page.locator("div.foobar")).not_to_have_id("top", timeout=100)
with pytest.raises(AssertionError):
await expect(page.locator("div.foobar")).to_have_id("top", timeout=100)
async def test_assertions_locator_to_have_js_property(page: Page, server: Server) -> None:
await page.goto(server.EMPTY_PAGE)
await page.set_content("
")
await page.eval_on_selector(
"div", "e => e.foo = { a: 1, b: 'string', c: new Date(1627503992000) }"
)
await expect(page.locator("div")).to_have_js_property(
"foo",
{
"a": 1,
"b": "string",
"c": datetime.datetime.fromtimestamp(1627503992000 / 1000),
},
)
async def test_to_have_js_property_pass_string(page: Page) -> None:
await page.set_content("
")
await page.eval_on_selector("div", "e => e.foo = 'string'")
locator = page.locator("div")
await expect(locator).to_have_js_property("foo", "string")
async def test_to_have_js_property_fail_string(page: Page) -> None:
await page.set_content("
")
await page.eval_on_selector("div", "e => e.foo = 'string'")
locator = page.locator("div")
with pytest.raises(AssertionError):
await expect(locator).to_have_js_property("foo", "error", timeout=500)
async def test_to_have_js_property_pass_number(page: Page) -> None:
await page.set_content("
")
await page.eval_on_selector("div", "e => e.foo = 2021")
locator = page.locator("div")
await expect(locator).to_have_js_property("foo", 2021)
async def test_to_have_js_property_fail_number(page: Page) -> None:
await page.set_content("
")
await page.eval_on_selector("div", "e => e.foo = 2021")
locator = page.locator("div")
with pytest.raises(AssertionError):
await expect(locator).to_have_js_property("foo", 1, timeout=500)
async def test_to_have_js_property_pass_boolean(page: Page) -> None:
await page.set_content("
")
await page.eval_on_selector("div", "e => e.foo = true")
locator = page.locator("div")
await expect(locator).to_have_js_property("foo", True)
async def test_to_have_js_property_fail_boolean(page: Page) -> None:
await page.set_content("
")
await page.eval_on_selector("div", "e => e.foo = false")
locator = page.locator("div")
with pytest.raises(AssertionError):
await expect(locator).to_have_js_property("foo", True, timeout=500)
async def test_to_have_js_property_pass_boolean_2(page: Page) -> None:
await page.set_content("
")
await page.eval_on_selector("div", "e => e.foo = false")
locator = page.locator("div")
await expect(locator).to_have_js_property("foo", False)
async def test_to_have_js_property_fail_boolean_2(page: Page) -> None:
await page.set_content("
")
await page.eval_on_selector("div", "e => e.foo = false")
locator = page.locator("div")
with pytest.raises(AssertionError):
await expect(locator).to_have_js_property("foo", True, timeout=500)
async def test_to_have_js_property_pass_null(page: Page) -> None:
await page.set_content("
")
await page.eval_on_selector("div", "e => e.foo = null")
locator = page.locator("div")
await expect(locator).to_have_js_property("foo", None)
async def test_assertions_locator_to_have_text(page: Page, server: Server) -> None:
await page.goto(server.EMPTY_PAGE)
await page.set_content("kek
")
await expect(page.locator("div#foobar")).to_have_text("kek")
await expect(page.locator("div#foobar")).not_to_have_text("top", timeout=100)
await page.set_content("Text \n1
Text 2a
")
# Should only normalize whitespace in the first item.
await expect(page.locator("div")).to_have_text(["Text 1", re.compile(r"Text \d+a")])
@pytest.mark.parametrize(
"method",
["to_have_text", "to_contain_text"],
)
async def test_ignore_case(page: Page, server: Server, method: str) -> None:
await page.goto(server.EMPTY_PAGE)
await page.set_content("apple BANANA
orange
")
await getattr(expect(page.locator("div#target")), method)("apple BANANA")
await getattr(expect(page.locator("div#target")), method)("apple banana", ignore_case=True)
# defaults false
with pytest.raises(AssertionError) as excinfo:
await getattr(expect(page.locator("div#target")), method)("apple banana", timeout=300)
expected_error_msg = method.replace("_", " ")
assert expected_error_msg in str(excinfo.value)
# Array Variants
await getattr(expect(page.locator("div")), method)(["apple BANANA", "orange"])
await getattr(expect(page.locator("div")), method)(["apple banana", "ORANGE"], ignore_case=True)
# defaults false
with pytest.raises(AssertionError) as excinfo:
await getattr(expect(page.locator("div")), method)(["apple banana", "ORANGE"], timeout=300)
assert expected_error_msg in str(excinfo.value)
# not variant
await getattr(expect(page.locator("div#target")), f"not_{method}")("apple banana")
with pytest.raises(AssertionError) as excinfo:
await getattr(expect(page.locator("div#target")), f"not_{method}")(
"apple banana", ignore_case=True, timeout=300
)
assert f"not {expected_error_msg}" in str(excinfo)
@pytest.mark.parametrize(
"method",
["to_have_text", "to_contain_text"],
)
async def test_ignore_case_regex(page: Page, server: Server, method: str) -> None:
await page.goto(server.EMPTY_PAGE)
await page.set_content("apple BANANA
orange
")
await getattr(expect(page.locator("div#target")), method)(re.compile("apple BANANA"))
await getattr(expect(page.locator("div#target")), method)(
re.compile("apple banana"), ignore_case=True
)
# defaults to regex flag
with pytest.raises(AssertionError) as excinfo:
await getattr(expect(page.locator("div#target")), method)(
re.compile("apple banana"), timeout=300
)
expected_error_msg = method.replace("_", " ")
assert expected_error_msg in str(excinfo.value)
# overrides regex flag
with pytest.raises(AssertionError) as excinfo:
await getattr(expect(page.locator("div#target")), method)(
re.compile("apple banana", re.IGNORECASE), ignore_case=False, timeout=300
)
assert expected_error_msg in str(excinfo.value)
# Array Variants
await getattr(expect(page.locator("div")), method)(
[re.compile("apple BANANA"), re.compile("orange")]
)
await getattr(expect(page.locator("div")), method)(
[re.compile("apple banana"), re.compile("ORANGE")], ignore_case=True
)
# defaults regex flag
with pytest.raises(AssertionError) as excinfo:
await getattr(expect(page.locator("div")), method)(
[re.compile("apple banana"), re.compile("ORANGE")], timeout=300
)
assert expected_error_msg in str(excinfo.value)
# overrides regex flag
with pytest.raises(AssertionError) as excinfo:
await getattr(expect(page.locator("div")), method)(
[
re.compile("apple banana", re.IGNORECASE),
re.compile("ORANGE", re.IGNORECASE),
],
ignore_case=False,
timeout=300,
)
assert expected_error_msg in str(excinfo.value)
# not variant
await getattr(expect(page.locator("div#target")), f"not_{method}")(re.compile("apple banana"))
with pytest.raises(AssertionError) as excinfo:
await getattr(expect(page.locator("div#target")), f"not_{method}")(
re.compile("apple banana"), ignore_case=True, timeout=300
)
assert f"not {expected_error_msg}" in str(excinfo)
async def test_assertions_locator_to_have_value(page: Page, server: Server) -> None:
await page.goto(server.EMPTY_PAGE)
await page.set_content(" ")
my_input = page.locator("#foo")
await expect(my_input).to_have_value("")
await expect(my_input).not_to_have_value("bar", timeout=100)
await my_input.fill("kektus")
await expect(my_input).to_have_value("kektus")
async def test_to_have_values_works_with_text(page: Page, server: Server) -> None:
await page.set_content(
"""
Red
Green
Blue
"""
)
locator = page.locator("select")
await locator.select_option(["R", "G"])
await expect(locator).to_have_values(["R", "G"])
async def test_to_have_values_follows_labels(page: Page, server: Server) -> None:
await page.set_content(
"""
Pick a Color
Red
Green
Blue
"""
)
locator = page.locator("text=Pick a Color")
await locator.select_option(["R", "G"])
await expect(locator).to_have_values(["R", "G"])
async def test_to_have_values_exact_match_with_text(page: Page, server: Server) -> None:
await page.set_content(
"""
Red
Green
"""
)
locator = page.locator("select")
await locator.select_option(["RR", "GG"])
with pytest.raises(AssertionError) as excinfo:
await expect(locator).to_have_values(["R", "G"], timeout=500)
assert "Locator expected to have Values '['R', 'G']'" in str(excinfo.value)
assert "Actual value: ['RR', 'GG']" in str(excinfo.value)
async def test_to_have_values_works_with_regex(page: Page, server: Server) -> None:
await page.set_content(
"""
Red
Green
Blue
"""
)
locator = page.locator("select")
await locator.select_option(["R", "G"])
await expect(locator).to_have_values([re.compile("R"), re.compile("G")])
async def test_to_have_values_fails_when_items_not_selected(page: Page, server: Server) -> None:
await page.set_content(
"""
Red
Green
Blue
"""
)
locator = page.locator("select")
await locator.select_option(["B"])
with pytest.raises(AssertionError) as excinfo:
await expect(locator).to_have_values(["R", "G"], timeout=500)
assert "Locator expected to have Values '['R', 'G']'" in str(excinfo.value)
assert "Actual value: ['B']" in str(excinfo.value)
async def test_to_have_values_fails_when_multiple_not_specified(page: Page, server: Server) -> None:
await page.set_content(
"""
Red
Green
Blue
"""
)
locator = page.locator("select")
await locator.select_option(["B"])
# Assertion failures surface as AssertionError now, not playwright.Error.
with pytest.raises(AssertionError) as excinfo:
await expect(locator).to_have_values(["R", "G"], timeout=500)
assert "Error: Not a select element with a multiple attribute" in str(excinfo.value)
async def test_to_have_values_fails_when_not_a_select_element(page: Page, server: Server) -> None:
await page.set_content(
"""
"""
)
locator = page.locator("input")
with pytest.raises(AssertionError) as excinfo:
await expect(locator).to_have_values(["R", "G"], timeout=500)
assert "Error: Not a select element with a multiple attribute" in str(excinfo.value)
async def test_assertions_locator_to_be_checked(page: Page, server: Server) -> None:
await page.goto(server.EMPTY_PAGE)
await page.set_content(" ")
my_checkbox = page.locator("input")
await expect(my_checkbox).not_to_be_checked()
with pytest.raises(AssertionError):
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):
await expect(my_checkbox).to_be_checked(timeout=100, checked=False)
await expect(my_checkbox).to_be_checked()
async def test_assertions_locator_to_be_disabled_enabled(page: Page, server: Server) -> None:
await page.goto(server.EMPTY_PAGE)
await page.set_content(" ")
my_checkbox = page.locator("input")
await expect(my_checkbox).not_to_be_disabled()
await expect(my_checkbox).to_be_enabled()
with pytest.raises(AssertionError):
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):
await expect(my_checkbox).to_be_enabled(timeout=100)
async def test_assertions_locator_to_be_editable(page: Page, server: Server) -> None:
await page.goto(server.EMPTY_PAGE)
# A is no longer merely "not editable": editability is only
# defined for /