diff --git a/atest/test/01_Browser_Management/tracing_groups.py b/atest/library/tracing_groups.py similarity index 54% rename from atest/test/01_Browser_Management/tracing_groups.py rename to atest/library/tracing_groups.py index 593a3896b..a9968350b 100644 --- a/atest/test/01_Browser_Management/tracing_groups.py +++ b/atest/library/tracing_groups.py @@ -1,9 +1,9 @@ import json from pathlib import Path -from typing import Union def get_trace_lines(path: Path) -> list[dict]: + """Returns the ``before`` entries of a Playwright trace file.""" with path.open(encoding="utf-8") as file: return [ json.loads(line) for line in file.readlines() if '"type":"before"' in line @@ -11,6 +11,7 @@ def get_trace_lines(path: Path) -> list[dict]: def get_trace_group_titles(path: Path) -> list[str]: + """Returns the titles of the trace groups in a Playwright trace file, in order.""" return [ line["title"] for line in get_trace_lines(path) @@ -18,8 +19,9 @@ def get_trace_group_titles(path: Path) -> list[str]: ] -def get_file_line(file: Union[Path, None], line: int, column: int) -> str: +def get_file_line(file: Path | None, line: int, column: int) -> str | None: + """Returns line ``line`` of ``file``, or ``None`` without a file.""" if file is None: return None - with file.open(encoding="utf-8") as file: - return file.readlines()[line - 1] + with file.open(encoding="utf-8") as source: + return source.readlines()[line - 1] diff --git a/atest/test/01_Browser_Management/tracing_groups.robot b/atest/test/01_Browser_Management/tracing_groups.robot index 98914f3a0..22563127c 100644 --- a/atest/test/01_Browser_Management/tracing_groups.robot +++ b/atest/test/01_Browser_Management/tracing_groups.robot @@ -3,7 +3,7 @@ Resource ../variables.resource Library Browser auto_delete_passed_tracing=True tracing_group_mode=Full Library OperatingSystem Library ArchiveLibrary -Library tracing_groups.py +Library ../../library/tracing_groups.py Library Collections *** Variables *** diff --git a/atest/test/05_JS_Tests/adopted_context_recording.robot b/atest/test/05_JS_Tests/adopted_context_recording.robot index be2adb035..6cd574575 100644 --- a/atest/test/05_JS_Tests/adopted_context_recording.robot +++ b/atest/test/05_JS_Tests/adopted_context_recording.robot @@ -3,7 +3,7 @@ Library ../../library/AdoptingLibrary.py jsextension=${CURDIR}/adopt.js Library ArchiveLibrary Library Collections Library OperatingSystem -Library ../01_Browser_Management/tracing_groups.py +Library ../../library/tracing_groups.py Resource ../variables.resource Test Tags no-iframe diff --git a/utest/test_adopted_context.py b/utest/test_adopted_context.py index b240283e7..7dc1706e4 100644 --- a/utest/test_adopted_context.py +++ b/utest/test_adopted_context.py @@ -25,7 +25,8 @@ def grpc_channel(self): yield self.stub -def library(tmpdir, monkeypatch) -> Browser: +@pytest.fixture +def browser(tmpdir, monkeypatch) -> Browser: monkeypatch.setattr(Browser, "_output_dir", tmpdir) monkeypatch.setattr(Browser, "_context_cache", ContextCache()) monkeypatch.delenv("ROBOT_FRAMEWORK_BROWSER_TRACING", raising=False) @@ -34,17 +35,26 @@ def library(tmpdir, monkeypatch) -> Browser: return browser +VIEWPORT = {"width": 800, "height": 600} +VIDEO_SIZES = [ + ({}, {"width": 800, "height": 600}), + ({"size": {"width": 640, "height": 480}}, {"width": 640, "height": 480}), +] + + def keyword_call(name: str) -> KeywordCallStackEntry: return {"name": name, "file": "", "line": 0, "kwname": name, "args": []} -def sent_options(request) -> dict: - return json.loads(request.call_args.args[0].rawOptions) +def sent_request(stub_method): + return stub_method.call_args.args[0] -def test_no_tracing_and_no_recording_by_default(tmpdir, monkeypatch): - browser = library(tmpdir, monkeypatch) +def sent_options(stub_method) -> dict: + return json.loads(sent_request(stub_method).rawOptions) + +def test_no_tracing_and_no_recording_by_default(browser: Browser): options = browser.adopted_context_options() assert options["tracing"] is None @@ -53,10 +63,8 @@ def test_no_tracing_and_no_recording_by_default(tmpdir, monkeypatch): def test_traces_dir_is_a_new_folder_in_browsers_temporary_trace_folder( - tmpdir, monkeypatch + browser: Browser, ): - browser = library(tmpdir, monkeypatch) - first = browser.adopted_context_options()["tracesDir"] second = browser.adopted_context_options()["tracesDir"] @@ -64,9 +72,7 @@ def test_traces_dir_is_a_new_folder_in_browsers_temporary_trace_folder( assert first != second -def test_tracing_follows_new_context(tmpdir, monkeypatch): - browser = library(tmpdir, monkeypatch) - +def test_tracing_follows_new_context(browser: Browser, tmpdir): assert browser.adopted_context_options(tracing=True)["tracing"] == str( browser.traces_output ) @@ -75,23 +81,19 @@ def test_tracing_follows_new_context(tmpdir, monkeypatch): ) -def test_relative_trace_folder_is_in_browsers_trace_folder(tmpdir, monkeypatch): - browser = library(tmpdir, monkeypatch) - +def test_relative_trace_folder_is_in_browsers_trace_folder(browser: Browser): options = browser.adopted_context_options(tracing=Path("adopted")) assert options["tracing"] == str((browser.traces_output / "adopted").resolve()) -def test_tracing_follows_the_global_setting(tmpdir, monkeypatch): - browser = library(tmpdir, monkeypatch) +def test_tracing_follows_the_global_setting(browser: Browser, monkeypatch): monkeypatch.setenv("ROBOT_FRAMEWORK_BROWSER_TRACING", "True") assert browser.adopted_context_options()["tracing"] == str(browser.traces_output) -def test_tracing_follows_the_robot_framework_variable(tmpdir, monkeypatch): - browser = library(tmpdir, monkeypatch) +def test_tracing_follows_the_robot_framework_variable(browser: Browser, monkeypatch): variables = {"${ROBOT_FRAMEWORK_BROWSER_TRACING}": "True"} monkeypatch.setattr( "Browser.keywords.playwright_state.EXECUTION_CONTEXTS", @@ -105,9 +107,7 @@ def test_tracing_follows_the_robot_framework_variable(tmpdir, monkeypatch): assert browser.adopted_context_options()["tracing"] == str(browser.traces_output) -def test_empty_video_options_record_with_the_defaults(tmpdir, monkeypatch): - browser = library(tmpdir, monkeypatch) - +def test_empty_video_options_record_with_the_defaults(browser: Browser): options = browser.adopted_context_options(recordVideo={}) assert options["recordVideo"] == { @@ -116,9 +116,7 @@ def test_empty_video_options_record_with_the_defaults(tmpdir, monkeypatch): } -def test_video_keeps_its_other_keys(tmpdir, monkeypatch): - browser = library(tmpdir, monkeypatch) - +def test_video_keeps_its_other_keys(browser: Browser): options = browser.adopted_context_options( recordVideo={"showActions": {"duration": 500}} ) @@ -126,9 +124,7 @@ def test_video_keeps_its_other_keys(tmpdir, monkeypatch): assert options["recordVideo"]["showActions"] == {"duration": 500} -def test_video_options_are_converted_like_new_context(tmpdir, monkeypatch): - browser = library(tmpdir, monkeypatch) - +def test_video_options_are_converted_like_new_context(browser: Browser): options = browser.adopted_context_options( recordVideo={"fps": "10", "showActions": {"duration": "300"}} ) @@ -137,16 +133,12 @@ def test_video_options_are_converted_like_new_context(tmpdir, monkeypatch): assert options["recordVideo"]["showActions"] == {"duration": 300} -def test_deprecated_font_size_fails_like_new_context(tmpdir, monkeypatch): - browser = library(tmpdir, monkeypatch) - +def test_deprecated_font_size_fails_like_new_context(browser: Browser): with pytest.raises(ValueError, match="RecordVideo"): browser.adopted_context_options(recordVideo={"showActions": {"fontSize": 20}}) -def test_video_folder_and_size_follow_new_context(tmpdir, monkeypatch): - browser = library(tmpdir, monkeypatch) - +def test_video_folder_and_size_follow_new_context(browser: Browser): options = browser.adopted_context_options( recordVideo={"dir": "demo", "size": {"width": "800", "height": "600"}} ) @@ -157,8 +149,7 @@ def test_video_folder_and_size_follow_new_context(tmpdir, monkeypatch): } -def test_absolute_video_folder_is_kept(tmpdir, monkeypatch): - browser = library(tmpdir, monkeypatch) +def test_absolute_video_folder_is_kept(browser: Browser, tmpdir): videos = str(Path(tmpdir, "elsewhere", "videos").resolve()) options = browser.adopted_context_options(recordVideo={"dir": videos}) @@ -166,9 +157,7 @@ def test_absolute_video_folder_is_kept(tmpdir, monkeypatch): assert options["recordVideo"]["dir"] == videos -def test_video_without_size_has_the_size_of_the_viewport(tmpdir, monkeypatch): - browser = library(tmpdir, monkeypatch) - +def test_video_without_size_has_the_size_of_the_viewport(browser: Browser): options = browser.adopted_context_options( recordVideo={}, viewport={"width": 1024, "height": 768} ) @@ -176,8 +165,7 @@ def test_video_without_size_has_the_size_of_the_viewport(tmpdir, monkeypatch): assert options["recordVideo"]["size"] == {"width": 1024, "height": 768} -def test_registered_context_gets_the_keyword_calls_as_trace_groups(tmpdir, monkeypatch): - browser = library(tmpdir, monkeypatch) +def test_registered_context_gets_the_keyword_calls_as_trace_groups(browser: Browser): browser.keyword_call_stack.append(keyword_call("Open Application")) options = browser.adopted_context_options(tracing=True) @@ -188,8 +176,7 @@ def test_registered_context_gets_the_keyword_calls_as_trace_groups(tmpdir, monke assert browser.tracing_contexts == ["context=1"] -def test_registered_context_without_tracing_gets_no_trace_groups(tmpdir, monkeypatch): - browser = library(tmpdir, monkeypatch) +def test_registered_context_without_tracing_gets_no_trace_groups(browser: Browser): browser.keyword_call_stack.append(keyword_call("Open Application")) browser.register_adopted_context("context=1", browser.adopted_context_options()) @@ -198,8 +185,7 @@ def test_registered_context_without_tracing_gets_no_trace_groups(tmpdir, monkeyp assert browser.tracing_contexts == [] -def test_playwright_tracing_group_mode_adds_no_trace_groups(tmpdir, monkeypatch): - browser = library(tmpdir, monkeypatch) +def test_playwright_tracing_group_mode_adds_no_trace_groups(browser: Browser): browser.tracing_group_mode = TracingGroupMode.Playwright browser.keyword_call_stack.append(keyword_call("Open Application")) options = browser.adopted_context_options(tracing=True) @@ -211,9 +197,8 @@ def test_playwright_tracing_group_mode_adds_no_trace_groups(tmpdir, monkeypatch) def test_registered_context_outside_a_keyword_is_traced_without_trace_groups( - tmpdir, monkeypatch + browser: Browser, ): - browser = library(tmpdir, monkeypatch) browser.tracing_group_mode = TracingGroupMode.Browser options = browser.adopted_context_options(tracing=True) @@ -223,22 +208,21 @@ def test_registered_context_outside_a_keyword_is_traced_without_trace_groups( assert browser.tracing_contexts == ["context=1"] -def test_registered_context_embeds_its_video(tmpdir, monkeypatch): - browser = library(tmpdir, monkeypatch) - options = browser.adopted_context_options(recordVideo={}) +def test_registered_context_embeds_its_video(browser: Browser, caplog): + caplog.set_level("INFO") + options = browser.adopted_context_options(recordVideo={}, viewport=VIEWPORT) video = str(Path(options["recordVideo"]["dir"], "page.webm")) video_path = browser.register_adopted_context("context=1", options, video) assert video_path == video - assert browser._playwright_state.context_cache.get("context=1") == { - "width": 1280, - "height": 720, - } + assert ( + '' + ) in caplog.text -def test_video_path_without_record_video_is_ignored(tmpdir, monkeypatch): - browser = library(tmpdir, monkeypatch) +def test_video_path_without_record_video_is_ignored(browser: Browser): options = browser.adopted_context_options() video_path = browser.register_adopted_context("context=1", options, "page.webm") @@ -246,9 +230,9 @@ def test_video_path_without_record_video_is_ignored(tmpdir, monkeypatch): assert video_path == "" -def test_relative_har_path_is_relative_to_the_output_directory(tmpdir, monkeypatch): - browser = library(tmpdir, monkeypatch) - +def test_relative_har_path_is_relative_to_the_output_directory( + browser: Browser, tmpdir +): options = browser.adopted_context_options( recordHar={"path": "har/app.har", "omitContent": True} ) @@ -259,8 +243,7 @@ def test_relative_har_path_is_relative_to_the_output_directory(tmpdir, monkeypat } -def test_absolute_har_path_is_kept(tmpdir, monkeypatch): - browser = library(tmpdir, monkeypatch) +def test_absolute_har_path_is_kept(browser: Browser, tmpdir): har = str(Path(tmpdir, "elsewhere", "app.har").resolve()) options = browser.adopted_context_options(recordHar={"path": har}) @@ -268,18 +251,14 @@ def test_absolute_har_path_is_kept(tmpdir, monkeypatch): assert options["recordHar"] == {"path": har} -def test_new_context_resolves_a_relative_har_path(tmpdir, monkeypatch): - browser = library(tmpdir, monkeypatch) - +def test_new_context_resolves_a_relative_har_path(browser: Browser, tmpdir): browser.new_context(recordHar={"path": "context.har"}) options = sent_options(browser._playwright.stub.NewContext) assert options["recordHar"] == {"path": str(Path(tmpdir, "context.har").resolve())} -def test_new_persistent_context_resolves_a_relative_har_path(tmpdir, monkeypatch): - browser = library(tmpdir, monkeypatch) - +def test_new_persistent_context_resolves_a_relative_har_path(browser: Browser, tmpdir): browser.new_persistent_context(recordHar={"path": "persistent.har"}) options = sent_options(browser._playwright.stub.NewPersistentContext) @@ -288,8 +267,7 @@ def test_new_persistent_context_resolves_a_relative_har_path(tmpdir, monkeypatch } -def test_new_context_sends_frame_rate_and_action_annotations(tmpdir, monkeypatch): - browser = library(tmpdir, monkeypatch) +def test_new_context_sends_frame_rate_and_action_annotations(browser: Browser): show_actions = { "duration": 300, "position": "bottom-left", @@ -304,9 +282,7 @@ def test_new_context_sends_frame_rate_and_action_annotations(tmpdir, monkeypatch assert options["recordVideo"]["showActions"] == show_actions -def test_new_persistent_context_sends_action_annotations(tmpdir, monkeypatch): - browser = library(tmpdir, monkeypatch) - +def test_new_persistent_context_sends_action_annotations(browser: Browser): browser.new_persistent_context(recordVideo={"showActions": {"position": "top"}}) options = sent_options(browser._playwright.stub.NewPersistentContext) @@ -325,10 +301,9 @@ def persistent_context_with_video(browser: Browser) -> MagicMock: def test_new_persistent_context_caches_and_embeds_its_video_once_its_url_opened( - tmpdir, monkeypatch, caplog + browser: Browser, caplog ): caplog.set_level("INFO") - browser = library(tmpdir, monkeypatch) persistent_context_with_video(browser) browser.new_persistent_context(url="http://localhost:1", recordVideo={}) @@ -340,8 +315,7 @@ def test_new_persistent_context_caches_and_embeds_its_video_once_its_url_opened( assert "