# 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 datetime import re import pytest from playwright.sync_api import Browser, Error, Page, expect from tests.server import Server def test_assertions_page_to_have_title(page: Page, server: Server) -> None: page.goto(server.EMPTY_PAGE) page.set_content("new title") expect(page).to_have_title("new title") expect(page).to_have_title(re.compile("new title")) with pytest.raises(AssertionError): expect(page).to_have_title("not the current title", timeout=750) with pytest.raises(AssertionError): expect(page).to_have_title(re.compile("not the current title"), timeout=750) with pytest.raises(AssertionError): expect(page).not_to_have_title(re.compile("new title"), timeout=750) with pytest.raises(AssertionError): expect(page).not_to_have_title("new title", timeout=750) expect(page).not_to_have_title("great title", timeout=750) page.evaluate( """ setTimeout(() => { document.title = 'great title'; }, 2000); """ ) expect(page).to_have_title("great title") expect(page).to_have_title(re.compile("great title")) def test_assertions_page_to_have_url(page: Page, server: Server) -> None: page.goto(server.EMPTY_PAGE) expect(page).to_have_url(server.EMPTY_PAGE) expect(page).to_have_url(re.compile(r".*/empty\.html")) with pytest.raises(AssertionError): expect(page).to_have_url("nooooo", timeout=750) with pytest.raises(AssertionError): expect(page).to_have_url(re.compile("not-the-url"), timeout=750) page.evaluate( """ setTimeout(() => { window.location = window.location.origin + '/grid.html'; }, 2000); """ ) expect(page).to_have_url(server.PREFIX + "/grid.html") expect(page).not_to_have_url(server.EMPTY_PAGE, timeout=750) with pytest.raises(AssertionError): expect(page).not_to_have_url(re.compile(r".*/grid\.html"), timeout=750) with pytest.raises(AssertionError): expect(page).not_to_have_url(server.PREFIX + "/grid.html", timeout=750) expect(page).to_have_url(re.compile(r".*/grid\.html")) expect(page).not_to_have_url("**/empty.html", timeout=750) def test_assertions_page_to_have_url_with_base_url( browser: Browser, server: Server ) -> None: page = browser.new_page(base_url=server.PREFIX) page.goto("/empty.html") expect(page).to_have_url("/empty.html") expect(page).to_have_url(re.compile(r".*/empty\.html")) page.close() def test_assertions_locator_to_contain_text(page: Page, server: Server) -> None: page.goto(server.EMPTY_PAGE) page.set_content("
kek
") expect(page.locator("div#foobar")).to_contain_text("kek") expect(page.locator("div#foobar")).not_to_contain_text("bar", timeout=100) with pytest.raises(AssertionError): expect(page.locator("div#foobar")).to_contain_text("bar", timeout=100) page.set_content("
Text \n1
Text2
Text3
") expect(page.locator("div")).to_contain_text(["ext 1", re.compile("ext3")]) def test_assertions_locator_to_have_attribute(page: Page, server: Server) -> None: page.goto(server.EMPTY_PAGE) page.set_content("
kek
") expect(page.locator("div#foobar")).to_have_attribute("id", "foobar") expect(page.locator("div#foobar")).to_have_attribute("id", re.compile("foobar")) expect(page.locator("div#foobar")).not_to_have_attribute("id", "kek", timeout=100) with pytest.raises(AssertionError): expect(page.locator("div#foobar")).to_have_attribute("id", "koko", timeout=100) def test_assertions_locator_to_have_attribute_ignore_case( page: Page, server: Page ) -> None: page.set_content("
Text content
") locator = page.locator("#NoDe") expect(locator).to_have_attribute("id", "node", ignore_case=True) expect(locator).not_to_have_attribute("id", "node") def test_assertions_locator_to_have_class(page: Page, server: Server) -> None: page.goto(server.EMPTY_PAGE) page.set_content("
kek
") expect(page.locator("div.foobar")).to_have_class("foobar") expect(page.locator("div.foobar")).to_have_class(["foobar"]) expect(page.locator("div.foobar")).to_have_class(re.compile("foobar")) expect(page.locator("div.foobar")).to_have_class([re.compile("foobar")]) expect(page.locator("div.foobar")).not_to_have_class("kekstar", timeout=100) with pytest.raises(AssertionError): expect(page.locator("div.foobar")).to_have_class("oh-no", timeout=100) def test_assertions_locator_to_contain_class(page: Page, server: Server) -> None: page.goto(server.EMPTY_PAGE) page.set_content("
") locator = page.locator("div") expect(locator).to_contain_class("") expect(locator).to_contain_class("bar") expect(locator).to_contain_class("baz bar") expect(locator).to_contain_class(" bar foo ") expect(locator).not_to_contain_class( " baz not-matching " ) # Strip whitespace and match individual classes with pytest.raises(AssertionError) as excinfo: expect(locator).to_contain_class("does-not-exist", timeout=100) assert excinfo.match("Locator expected to contain class 'does-not-exist'") assert excinfo.match("Actual value: foo bar baz") assert excinfo.match('Expect "to_contain_class" with timeout 100ms') page.set_content( '
' ) expect(locator).to_contain_class(["foo", "hello", "baz"]) expect(locator).not_to_contain_class(["not-there", "hello", "baz"]) expect(locator).not_to_contain_class(["foo", "hello"]) def test_assertions_locator_to_have_count(page: Page, server: Server) -> None: page.goto(server.EMPTY_PAGE) page.set_content("
kek
kek
") expect(page.locator("div.foobar")).to_have_count(2) expect(page.locator("div.foobar")).not_to_have_count(42, timeout=100) with pytest.raises(AssertionError): expect(page.locator("div.foobar")).to_have_count(42, timeout=100) def test_assertions_locator_to_have_css(page: Page, server: Server) -> None: page.goto(server.EMPTY_PAGE) page.set_content("
kek
") expect(page.locator("div.foobar")).to_have_css("color", "rgb(234, 74, 90)") expect(page.locator("div.foobar")).not_to_have_css( "color", "rgb(42, 42, 42)", timeout=100 ) with pytest.raises(AssertionError): expect(page.locator("div.foobar")).to_have_css( "color", "rgb(42, 42, 42)", timeout=100 ) def test_assertions_locator_to_have_id(page: Page, server: Server) -> None: page.goto(server.EMPTY_PAGE) page.set_content("
kek
") expect(page.locator("div.foobar")).to_have_id("kek") expect(page.locator("div.foobar")).not_to_have_id("top", timeout=100) with pytest.raises(AssertionError): expect(page.locator("div.foobar")).to_have_id("top", timeout=100) def test_assertions_locator_to_have_js_property(page: Page, server: Server) -> None: page.goto(server.EMPTY_PAGE) page.set_content("
") page.eval_on_selector( "div", "e => e.foo = { a: 1, b: 'string', c: new Date(1627503992000) }" ) expect(page.locator("div")).to_have_js_property( "foo", { "a": 1, "b": "string", "c": datetime.datetime.fromtimestamp(1627503992000 / 1000), }, ) def test_to_have_js_property_pass_string(page: Page) -> None: page.set_content("
") page.eval_on_selector("div", "e => e.foo = 'string'") locator = page.locator("div") expect(locator).to_have_js_property("foo", "string") def test_to_have_js_property_fail_string(page: Page) -> None: page.set_content("
") page.eval_on_selector("div", "e => e.foo = 'string'") locator = page.locator("div") with pytest.raises(AssertionError): expect(locator).to_have_js_property("foo", "error", timeout=500) def test_to_have_js_property_pass_number(page: Page) -> None: page.set_content("
") page.eval_on_selector("div", "e => e.foo = 2021") locator = page.locator("div") expect(locator).to_have_js_property("foo", 2021) def test_to_have_js_property_fail_number(page: Page) -> None: page.set_content("
") page.eval_on_selector("div", "e => e.foo = 2021") locator = page.locator("div") with pytest.raises(AssertionError): expect(locator).to_have_js_property("foo", 1, timeout=500) def test_to_have_js_property_pass_boolean(page: Page) -> None: page.set_content("
") page.eval_on_selector("div", "e => e.foo = true") locator = page.locator("div") expect(locator).to_have_js_property("foo", True) def test_to_have_js_property_fail_boolean(page: Page) -> None: page.set_content("
") page.eval_on_selector("div", "e => e.foo = false") locator = page.locator("div") with pytest.raises(AssertionError): expect(locator).to_have_js_property("foo", True, timeout=500) def test_to_have_js_property_pass_boolean_2(page: Page) -> None: page.set_content("
") page.eval_on_selector("div", "e => e.foo = false") locator = page.locator("div") expect(locator).to_have_js_property("foo", False) def test_to_have_js_property_fail_boolean_2(page: Page) -> None: page.set_content("
") page.eval_on_selector("div", "e => e.foo = false") locator = page.locator("div") with pytest.raises(AssertionError): expect(locator).to_have_js_property("foo", True, timeout=500) def test_to_have_js_property_pass_null(page: Page) -> None: page.set_content("
") page.eval_on_selector("div", "e => e.foo = null") locator = page.locator("div") expect(locator).to_have_js_property("foo", None) def test_assertions_locator_to_have_text(page: Page, server: Server) -> None: page.goto(server.EMPTY_PAGE) page.set_content("
kek
") expect(page.locator("div#foobar")).to_have_text("kek") expect(page.locator("div#foobar")).not_to_have_text("top", timeout=100) page.set_content("
Text \n1
Text 2a
") # Should only normalize whitespace in the first item. 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"], ) def test_ignore_case(page: Page, server: Server, method: str) -> None: page.goto(server.EMPTY_PAGE) page.set_content("
apple BANANA
orange
") getattr(expect(page.locator("div#target")), method)("apple BANANA") getattr(expect(page.locator("div#target")), method)( "apple banana", ignore_case=True ) # defaults false with pytest.raises(AssertionError) as excinfo: 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 getattr(expect(page.locator("div")), method)(["apple BANANA", "orange"]) getattr(expect(page.locator("div")), method)( ["apple banana", "ORANGE"], ignore_case=True ) # defaults false with pytest.raises(AssertionError) as excinfo: getattr(expect(page.locator("div")), method)( ["apple banana", "ORANGE"], timeout=300, ) assert expected_error_msg in str(excinfo.value) # not variant getattr(expect(page.locator("div#target")), f"not_{method}")("apple banana") with pytest.raises(AssertionError) as excinfo: 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"], ) def test_ignore_case_regex(page: Page, server: Server, method: str) -> None: page.goto(server.EMPTY_PAGE) page.set_content("
apple BANANA
orange
") getattr(expect(page.locator("div#target")), method)(re.compile("apple BANANA")) getattr(expect(page.locator("div#target")), method)( re.compile("apple banana"), ignore_case=True ) # defaults to regex flag with pytest.raises(AssertionError) as excinfo: 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: 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 getattr(expect(page.locator("div")), method)( [re.compile("apple BANANA"), re.compile("orange")] ) 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: 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: 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 getattr(expect(page.locator("div#target")), f"not_{method}")( re.compile("apple banana") ) with pytest.raises(AssertionError) as excinfo: 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) def test_assertions_locator_to_have_value(page: Page, server: Server) -> None: page.goto(server.EMPTY_PAGE) page.set_content("") my_input = page.locator("#foo") expect(my_input).to_have_value("") expect(my_input).not_to_have_value("bar", timeout=100) my_input.fill("kektus") expect(my_input).to_have_value("kektus") def test_to_have_values_works_with_text(page: Page, server: Server) -> None: page.set_content( """ """ ) locator = page.locator("select") locator.select_option(["R", "G"]) expect(locator).to_have_values(["R", "G"]) def test_to_have_values_follows_labels(page: Page, server: Server) -> None: page.set_content( """ """ ) locator = page.locator("text=Pick a Color") locator.select_option(["R", "G"]) expect(locator).to_have_values(["R", "G"]) def test_to_have_values_exact_match_with_text(page: Page, server: Server) -> None: page.set_content( """ """ ) locator = page.locator("select") locator.select_option(["RR", "GG"]) with pytest.raises(AssertionError) as excinfo: 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) def test_to_have_values_works_with_regex(page: Page, server: Server) -> None: page.set_content( """ """ ) locator = page.locator("select") locator.select_option(["R", "G"]) expect(locator).to_have_values([re.compile("R"), re.compile("G")]) def test_to_have_values_fails_when_items_not_selected( page: Page, server: Server ) -> None: page.set_content( """ """ ) locator = page.locator("select") locator.select_option(["B"]) with pytest.raises(AssertionError) as excinfo: 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) def test_to_have_values_fails_when_multiple_not_specified( page: Page, server: Server ) -> None: page.set_content( """ """ ) locator = page.locator("select") locator.select_option(["B"]) with pytest.raises(AssertionError) as excinfo: expect(locator).to_have_values(["R", "G"], timeout=500) assert "Error: Not a select element with a multiple attribute" in str(excinfo.value) def test_to_have_values_fails_when_not_a_select_element( page: Page, server: Server ) -> None: page.set_content( """ """ ) locator = page.locator("input") with pytest.raises(AssertionError) as excinfo: expect(locator).to_have_values(["R", "G"], timeout=500) assert "Error: Not a select element with a multiple attribute" in str(excinfo.value) def test_assertions_locator_to_be_checked(page: Page, server: Server) -> None: page.goto(server.EMPTY_PAGE) page.set_content("") my_checkbox = page.locator("input") expect(my_checkbox).not_to_be_checked() 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, match="Locator expected to be unchecked"): expect(my_checkbox).to_be_checked(timeout=100, checked=False) expect(my_checkbox).to_be_checked() def test_assertions_boolean_checked_with_intermediate_true(page: Page) -> None: page.set_content("") page.locator("input").evaluate("e => e.indeterminate = true") expect(page.locator("input")).to_be_checked(indeterminate=True) def test_assertions_boolean_checked_with_intermediate_true_and_checked( page: Page, ) -> None: page.set_content("") page.locator("input").evaluate("e => e.indeterminate = true") with pytest.raises( AssertionError, match="Can't assert indeterminate and checked at the same time" ): expect(page.locator("input")).to_be_checked(checked=False, indeterminate=True) def test_assertions_boolean_fail_with_indeterminate_true(page: Page) -> None: page.set_content("") with pytest.raises( AssertionError, match='Expect "to_be_checked" with timeout 1000ms' ): expect(page.locator("input")).to_be_checked(indeterminate=True, timeout=1000) def test_assertions_locator_to_be_disabled_enabled(page: Page, server: Server) -> None: page.goto(server.EMPTY_PAGE) page.set_content("") my_checkbox = page.locator("input") expect(my_checkbox).not_to_be_disabled() expect(my_checkbox).to_be_enabled() with pytest.raises(AssertionError): 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, match="Locator expected to be enabled"): expect(my_checkbox).to_be_enabled(timeout=100) def test_assertions_locator_to_be_enabled_with_true(page: Page) -> None: page.set_content("") 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("") 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("") expect(page.locator("button")).to_be_enabled(enabled=False) def test_assertions_locator_to_be_enabled_with_not_and_false(page: Page) -> None: page.set_content("") expect(page.locator("button")).not_to_be_enabled(enabled=False) def test_assertions_locator_to_be_enabled_eventually(page: Page) -> None: page.set_content("") page.eval_on_selector( "button", """ button => setTimeout(() => { button.removeAttribute('disabled'); }, 700); """, ) expect(page.locator("button")).to_be_enabled() def test_assertions_locator_to_be_enabled_eventually_with_not(page: Page) -> None: page.set_content("") page.eval_on_selector( "button", """ button => setTimeout(() => { button.setAttribute('disabled', ''); }, 700); """, ) expect(page.locator("button")).not_to_be_enabled() def test_assertions_locator_to_be_editable(page: Page, server: Server) -> None: page.goto(server.EMPTY_PAGE) page.set_content("") expect(page.locator("input")).to_be_editable() def test_assertions_locator_to_be_editable_throws(page: Page, server: Server) -> None: page.goto(server.EMPTY_PAGE) page.set_content("") with pytest.raises( AssertionError, match=r"Element is not an ,