Repository navigation
Web loading lifecycle progress transition refactor #895
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
ikostan
merged 41 commits into
main
from
web-loading-lifecycle-progress-transition-refactor
Aug 17, 2026
Merged
Changes from 4 commits
Commits
Show all changes
41 commits
Select commit
Hold shift + click to select a range
87695df
Add telemetry hook and normalize handlers
ikostan 11e2936
Create splash_transition_flow_test.py
ikostan cafa396
Add canvas geometry assertions to splash test
ikostan 815c46e
Enhance splash transition telemetry checks
ikostan cbcc5ff
style: format code with Black and isort
deepsource-autofix[bot] 4b737d9
Cleanup & minor fixes in splash_transition_flow_test
ikostan 08b0354
CodeRabbit Generated Unit Tests: Add Generated Unit Tests for PR Changes
coderabbitai[bot] c3015ff
Merge branch 'web-loading-lifecycle-progress-transition-refactor' of …
ikostan 2207cf9
style: format code with Black and isort
deepsource-autofix[bot] ea8467f
style: format code with Black and isort
deepsource-autofix[bot] 7d70c5b
Merge branch 'web-loading-lifecycle-progress-transition-refactor' int…
ikostan 2e21602
style: format code with Black and isort
deepsource-autofix[bot] e3302a2
Merge pull request #897 from ikostan/coderabbitai/utg/96e3a12
ikostan d419aa4
Use test_utils for coverage and artifacts in splash test
ikostan d370602
style: format code with Black and isort
deepsource-autofix[bot] 32c1ba2
Refactor splash test: extract validation helpers
ikostan 9ccc9b1
style: format code with Black and isort
deepsource-autofix[bot] 5c3d18a
Update splash_transition_flow_test.py
ikostan d3335fb
style: format code with Black and isort
deepsource-autofix[bot] bca00be
Update test_utils.py
ikostan b49bd2a
Improve loading accessibility and focus handling
ikostan 2faa85e
Update tests/splash_transition_flow_test.py
ikostan 93ff096
Use regex to extract onProgress function
ikostan 2cb1779
Capture screenshot in test failure artifacts
ikostan 94aacdd
style: format code with Black and isort
deepsource-autofix[bot] 193ee20
Update custom_shell.html
ikostan 4f9cdc6
style: format code with Black and isort
deepsource-autofix[bot] 9396dbe
Update custom_shell.html
ikostan fc04b07
Merge branch 'web-loading-lifecycle-progress-transition-refactor' of …
ikostan c43bb43
Update splash_transition_flow_test.py
ikostan 0e0a5cc
style: format code with Black and isort
deepsource-autofix[bot] feb1e4b
Update splash_transition_flow_test.py
ikostan ae294e7
Merge branch 'web-loading-lifecycle-progress-transition-refactor' of …
ikostan 70f4a4a
style: format code with Black and isort
deepsource-autofix[bot] e1eaa3e
Refactor formatting in splash_transition tests
ikostan a5002db
Merge branch 'web-loading-lifecycle-progress-transition-refactor' of …
ikostan 644cf4b
style: format code with Black and isort
deepsource-autofix[bot] 0c0c101
Clamp transfer progress telemetry
ikostan f47ffd1
Create Part_1_Web_loading_lifecycle_progress_transition_refactor.md
ikostan 2bd1add
Update Part_1_Web_loading_lifecycle_progress_transition_refactor.md
ikostan 0221bf7
Update test_utils.py
ikostan File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Some comments aren't visible on the classic Files Changed page.
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,189 @@ | ||
| # Copyright (C) 2025-2026 Egor Kostan | ||
| # SPDX-License-Identifier: GPL-3.0-or-later | ||
| # tests/splash_transition_flow_test.py | ||
| """ | ||
| Splash Screen Transition & Telemetry Test Suite (Playwright + UI Automation) | ||
| ============================================================================= | ||
|
|
||
| Overview | ||
| -------- | ||
| Verifies the asynchronous web loading workflow, custom shell initialization pipeline, | ||
| progressive assembly telemetry, and in-game progress transition mechanics. Eliminates | ||
| race conditions by validating orderly handshakes between the DOM layout engine and the | ||
| WebAssembly runtime graphics context. | ||
|
|
||
| Prerequisites | ||
| ------------- | ||
| - http://localhost:8080/index.html (HTML5 export with preloader & overlays) | ||
| - pytest, playwright | ||
|
|
||
| Running | ||
| ------- | ||
| pytest -k splash_transition_flow -q | ||
|
|
||
| Artifacts | ||
| --------- | ||
| v8_coverage_splash_transition_flow_test.json, artifacts/test_splash_failure_*.png/txt/html | ||
|
ikostan marked this conversation as resolved.
Resolved
|
||
| """ | ||
|
|
||
| import json | ||
| import os | ||
| import re | ||
| import time | ||
| from typing import Any | ||
|
|
||
| from playwright.sync_api import Page, expect | ||
|
|
||
| from tests.test_utils import DEFAULT_TIMEOUT, TEST_TIMEOUT | ||
|
|
||
|
|
||
| # DO NOT REFACTOR: Must consume function-scoped `page` to capture preloader & startup telemetry. | ||
|
ikostan marked this conversation as resolved.
Resolved
|
||
| def test_splash_transition_flow(page: Page) -> None: | ||
|
ikostan marked this conversation as resolved.
Resolved
|
||
| """ | ||
| Validates assembly stream metrics, progressive telemetry monotonicity, | ||
| WebGL frame canvas presentation, and orderly removal of preloader DOM layers. | ||
| """ | ||
| logs: list[dict[str, str]] = [] | ||
| page_errors: list[str] = [] | ||
| cdp_session = None | ||
|
|
||
| def on_console(msg: Any) -> None: | ||
| """Capture all console logs to track runtime lifecycle telemetry.""" | ||
| logs.append({"type": msg.type, "text": msg.text}) | ||
|
|
||
| def on_page_error(exc: Any) -> None: | ||
| """Capture uncaught runtime errors during engine boot.""" | ||
| page_errors.append(f"Uncaught Exception: {exc.message}\n{exc.stack}") | ||
|
|
||
| # Register listeners BEFORE navigation to capture early boot telemetry & errors | ||
| page.on("console", on_console) | ||
| page.on("pageerror", on_page_error) | ||
|
|
||
| try: | ||
| # 1. INITIALIZE V8 PRECISE COVERAGE VIA CDP | ||
| cdp_session = page.context.new_cdp_session(page) | ||
| cdp_session.send("Profiler.enable") | ||
| cdp_session.send( | ||
| "Profiler.startPreciseCoverage", {"callCount": True, "detailed": True} | ||
| ) | ||
|
|
||
| # 2. MONITOR INITIAL BROWSER LOADING LAYER | ||
| page.goto( | ||
| "http://localhost:8080/index.html", | ||
| wait_until="domcontentloaded", | ||
| timeout=DEFAULT_TIMEOUT, | ||
| ) | ||
|
|
||
| # Verify custom HTML layout preloader maps instantly to the viewport | ||
| loading_overlay = page.locator("#loading") | ||
| expect(loading_overlay).to_be_visible(timeout=TEST_TIMEOUT) | ||
|
|
||
| # 3. VERIFY ENGINE INITIALIZATION & RUNTIME TELEMETRY | ||
| page.wait_for_function( | ||
| "() => window.godotInitialized === true", timeout=DEFAULT_TIMEOUT | ||
| ) | ||
|
|
||
| # Parse progressive assembly transfer marks ("Telemetry - Assembly Transfer: X%") | ||
|
ikostan marked this conversation as resolved.
Resolved
|
||
| progress_values: list[int] = [] | ||
| for log in logs: | ||
| match = re.search(r"Telemetry - Assembly Transfer:\s*(\d+)%", log["text"]) | ||
| if match: | ||
| progress_values.append(int(match.group(1))) | ||
|
|
||
| # Assert telemetry presence, range bounds, and monotonic forward progression | ||
| assert ( | ||
| len(progress_values) > 0 | ||
| ), "No 'Telemetry - Assembly Transfer:' marks captured during engine boot." | ||
| assert all( | ||
| 0 <= val <= 100 for val in progress_values | ||
| ), f"Telemetry percentage out of bounds [0, 100]: {progress_values}" | ||
| assert ( | ||
| progress_values == sorted(progress_values) | ||
| ), f"Assembly transfer telemetry did not progress monotonically: {progress_values}" | ||
|
ikostan marked this conversation as resolved.
Resolved
|
||
|
|
||
| # 4. ASSIGN RENDERING CANVAS HANDSHAKE & STRUCTURAL GEOMETRY | ||
| canvas_element = page.locator("#canvas") | ||
| expect(canvas_element).to_be_visible(timeout=TEST_TIMEOUT) | ||
|
|
||
| canvas_box = canvas_element.bounding_box() | ||
| assert canvas_box is not None, "Canvas element has no rendered bounding box" | ||
| assert canvas_box["width"] > 0, "Canvas rendered width is zero (viewport layout failure)" | ||
| assert canvas_box["height"] > 0, "Canvas rendered height is zero (viewport layout failure)" | ||
|
|
||
| assert ( | ||
| "SkyLockAssault" in page.title() | ||
| ), f"Target application title mismatch: '{page.title()}'" | ||
|
|
||
| # 5. VERIFY DOM TEARDOWN & LIFECYCLE INVARIANTS | ||
| expect(loading_overlay).to_be_hidden(timeout=TEST_TIMEOUT) | ||
| assert page.evaluate( | ||
| "() => document.getElementById('loading').getAttribute('aria-hidden') === 'true'" | ||
|
ikostan marked this conversation as resolved.
Resolved
|
||
| ), "Loading container missing aria-hidden='true' post-initialization" | ||
|
|
||
| # Invariant: engine initialization state must remain true after overlay teardown | ||
| assert page.evaluate( | ||
| "() => window.godotInitialized === true" | ||
| ), "window.godotInitialized lost its truthy state after splash transition completed" | ||
|
ikostan marked this conversation as resolved.
Resolved
|
||
|
|
||
| # 6. AUDIT FATAL PARSING & SCRIPT COMPILATION EXCEPTIONS | ||
| critical_faults = [ | ||
| log["text"] | ||
| for log in logs | ||
| if log["type"] == "error" | ||
| and not any( | ||
| phrase in log["text"].lower() | ||
| for phrase in ["encryption aborted", "salt is empty"] | ||
| ) | ||
| ] + page_errors | ||
|
|
||
| assert ( | ||
| len(critical_faults) == 0 | ||
| ), f"Critical exceptions found during web handshake:\n" + "\n".join(critical_faults) | ||
|
|
||
| except Exception as e: | ||
| print(f"Test: 'test_splash_transition_flow' failed: {e!s}") | ||
| os.makedirs("artifacts", exist_ok=True) | ||
| timestamp: int = int(time.time()) | ||
|
|
||
| # Isolate diagnostic files on execution crashes | ||
| page.screenshot(path=f"artifacts/test_splash_failure_screenshot_{timestamp}.png") | ||
|
|
||
| with open( | ||
| f"artifacts/test_splash_failure_console_logs_{timestamp}.txt", | ||
| "w", | ||
| encoding="utf-8", | ||
| ) as f: | ||
| f.write("--- CONSOLE LOGS ---\n") | ||
| for log in logs: | ||
| f.write(f"[{log['type']}] {log['text']}\n") | ||
| f.write("\n--- PAGE ERRORS ---\n") | ||
| for p_err in page_errors: | ||
| f.write(f"{p_err}\n") | ||
|
|
||
| with open( | ||
| f"artifacts/test_splash_failure_html_{timestamp}.html", | ||
| "w", | ||
| encoding="utf-8", | ||
| ) as f: | ||
| f.write(page.content()) | ||
| raise | ||
|
|
||
| finally: | ||
| try: | ||
| page.remove_listener("console", on_console) | ||
| page.remove_listener("pageerror", on_page_error) | ||
| except Exception: | ||
| pass | ||
|
|
||
| if cdp_session: | ||
| try: | ||
| coverage = cdp_session.send("Profiler.takePreciseCoverage")["result"] | ||
| cdp_session.send("Profiler.stopPreciseCoverage") | ||
| cdp_session.send("Profiler.disable") | ||
| cdp_session.detach() | ||
| with open( | ||
| "v8_coverage_splash_transition_flow_test.json", "w", encoding="utf-8" | ||
| ) as f: | ||
| json.dump(coverage, f) | ||
| except Exception as cov_err: | ||
| print(f"Warning: Failed to harvest V8 coverage data: {cov_err}") | ||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.