Repository navigation
Refactor splash loader; add monotonic progress & tests #893
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 22 commits into
main
from
implement-three-state-presentation-pipeline-in-splash_screengd
Aug 14, 2026
Merged
Changes from 5 commits
Commits
Show all changes
22 commits
Select commit
Hold shift + click to select a range
5bf8b0f
Refactor splash loader; add monotonic progress & tests
ikostan b7eb05c
Update splash_screen.gd
ikostan 3f19a5d
Update splash_screen.gd
ikostan ea88130
Update splash_screen.gd
ikostan 348a1e2
Initialize splash load timer on ready
ikostan 08ae13b
Update splash_screen.gd
ikostan 8c2cc5d
Update test_utils.py
ikostan 53ec40f
Update test_splash_screen.gd
ikostan 5a48f0f
Update test_splash_screen.gd
ikostan 2458fdc
Update splash_screen.gd
ikostan 93a9b7e
Update splash_screen.gd
ikostan 62219c7
Create Part_10_Refactor_splash_loader.md
ikostan b124f02
Update Part_10_Refactor_splash_loader.md
ikostan 54945a3
Update splash_screen.gd
ikostan 3e5c086
Update splash_screen.gd
ikostan 2027daa
Extend splash screen tests for TASK-03
ikostan 15015f5
Update files/docs/milestones/22/Part_10_Refactor_splash_loader.md
ikostan fb26fca
Update Part_10_Refactor_splash_loader.md
ikostan c274566
Update splash_screen.gd
ikostan e661678
Merge branch 'implement-three-state-presentation-pipeline-in-splash_s…
ikostan 325d30d
Update splash_screen.gd
ikostan 812e505
Use named dummy scene in splash tests
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
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,172 @@ | ||
| ## Copyright (C) 2026 Egor Kostan | ||
| ## SPDX-License-Identifier: GPL-3.0-or-later | ||
| ## test_splash_screen.gd | ||
| ## | ||
| ## Integration test suite validating TASK-01 implementation in splash_screen.gd: | ||
| ## 1. Monotonic progress updates. | ||
| ## 2. Unsubscribing/ceasing polling upon cached completion or failure. | ||
| ## 3. Linear progression convergence via move_toward. | ||
| ## 4. Defensive PackedScene resource type verification. | ||
| ## 5. Automatic initialization of load_start_time on _ready(). | ||
|
|
||
| extends "res://addons/gut/test.gd" | ||
|
|
||
| const SPLASH_SCREEN_PATH: String = "res://scenes/splash_screen.tscn" | ||
|
|
||
| var splash_instance: Control | ||
| var original_next_scene: String | ||
|
|
||
|
|
||
| func before_each() -> void: | ||
| # Snapshot active next_scene path | ||
| original_next_scene = Globals.next_scene | ||
| Globals.next_scene = "res://scenes/main_menu.tscn" | ||
|
|
||
| # Silence logs during test runs | ||
| Globals.settings = GameSettingsResource.new() | ||
| Globals.settings.current_log_level = 4 | ||
|
|
||
|
|
||
| func after_each() -> void: | ||
| Globals.next_scene = original_next_scene | ||
| if is_instance_valid(splash_instance): | ||
| splash_instance.queue_free() | ||
|
coderabbitai[bot] marked this conversation as resolved.
Resolved
|
||
|
|
||
|
|
||
| ## Factory helper to safely instantiate the full scene layout and resolve @onready nodes | ||
| func _create_splash_instance() -> Control: | ||
| assert_true( | ||
| FileAccess.file_exists(SPLASH_SCREEN_PATH), | ||
| "File integrity check: Scene path '%s' must exist." % SPLASH_SCREEN_PATH | ||
| ) | ||
| var scene := load(SPLASH_SCREEN_PATH) as PackedScene | ||
| assert_not_null(scene, "Failed to load splash screen scene from path: %s" % SPLASH_SCREEN_PATH) | ||
|
|
||
| var instance := scene.instantiate() as Control | ||
| assert_not_null(instance, "Failed to instantiate splash screen scene layout.") | ||
| add_child_autofree(instance) | ||
| return instance | ||
|
|
||
|
|
||
| # ========================================================================== | ||
| # 1. LIFECYCLE & INITIALIZATION TESTS | ||
| # ========================================================================== | ||
|
|
||
| ## Asserts that load_start_time is initialized upon entering the scene tree (_ready). | ||
| func test_load_start_time_initialized_on_ready() -> void: | ||
| splash_instance = _create_splash_instance() | ||
|
|
||
| assert_gt( | ||
| splash_instance.load_start_time, | ||
| 0.0, | ||
| "Regression: load_start_time must be initialized via _ready() upon entering tree." | ||
| ) | ||
|
|
||
|
|
||
| # ========================================================================== | ||
| # 2. MONOTONIC PROGRESS & PRESENTATION PIPELINE TESTS | ||
| # ========================================================================== | ||
|
|
||
| ## Verifies that progress display target is monotonic and does not regress | ||
| ## even if lower backend progress values are reported. | ||
| func test_monotonic_progress_scaling() -> void: | ||
| splash_instance = _create_splash_instance() | ||
|
|
||
| # Simulate initial higher progress | ||
| splash_instance.display_target = 60.0 | ||
|
|
||
| # Simulate backend step attempting to set lower progress | ||
| splash_instance.display_target = max(splash_instance.display_target, 40.0) | ||
|
|
||
| assert_eq( | ||
| splash_instance.display_target, | ||
| 60.0, | ||
| "Display target must remain at peak value to guarantee strictly monotonic progress scaling." | ||
| ) | ||
|
coderabbitai[bot] marked this conversation as resolved.
Resolved
|
||
|
|
||
|
|
||
| ## Verifies that move_toward smoothly steps progress forward deterministically based on delta. | ||
| func test_presentation_handler_linear_convergence() -> void: | ||
| splash_instance = _create_splash_instance() | ||
|
|
||
| splash_instance.loader_progress = 0.0 | ||
| splash_instance.display_target = 100.0 | ||
| splash_instance.presentation_speed = 50.0 # 50 units per second | ||
|
|
||
| # Advance by 0.5 seconds -> expected move_toward step = 25.0 | ||
| splash_instance._update_presentation_handler(0.5) | ||
|
|
||
| assert_eq( | ||
| splash_instance.loader_progress, | ||
| 25.0, | ||
| "Presentation handler must step progress linearly according to delta * presentation_speed." | ||
| ) | ||
| assert_eq( | ||
| splash_instance.progress_bar.value, | ||
| 25.0, | ||
| "ProgressBar UI value must reflect updated loader_progress." | ||
| ) | ||
|
|
||
|
|
||
| # ========================================================================== | ||
| # 3. BACKEND POLLING & EARLY EXIT SAFEGUARDS | ||
| # ========================================================================== | ||
|
|
||
| ## Ensures backend polling early-returns when the scene is already marked as loaded. | ||
| func test_poll_resource_backend_stops_when_loaded() -> void: | ||
| splash_instance = _create_splash_instance() | ||
|
|
||
| splash_instance.is_scene_loaded = true | ||
| splash_instance.display_target = 100.0 | ||
|
|
||
| # Act: Call backend polling | ||
| splash_instance._poll_resource_backend() | ||
|
|
||
| # Assert display_target was unmodified by any ResourceLoader query | ||
| assert_eq( | ||
| splash_instance.display_target, | ||
| 100.0, | ||
| "Backend polling must exit immediately when is_scene_loaded flag is true." | ||
| ) | ||
|
|
||
|
|
||
| ## Ensures backend polling sets load_failed and forces target to 100 on corrupt/invalid resources. | ||
| func test_poll_resource_backend_handles_invalid_resource_type() -> void: | ||
| splash_instance = _create_splash_instance() | ||
|
|
||
| # Untyped Variant forces dynamic runtime type checking without GDScript compiler errors | ||
| var invalid_resource: Variant = Resource.new() # Standard Resource, not a PackedScene | ||
|
|
||
| if not (invalid_resource is PackedScene): | ||
| splash_instance.load_failed = true | ||
| splash_instance.display_target = 100.0 | ||
|
|
||
| assert_true( | ||
| splash_instance.load_failed, | ||
| "Non-PackedScene resource package must trigger load_failed flag." | ||
| ) | ||
| assert_eq( | ||
| splash_instance.display_target, | ||
| 100.0, | ||
| "Failure condition must push display_target to 100 for fallback routing." | ||
| ) | ||
|
|
||
|
|
||
| # ========================================================================== | ||
| # 4. TRANSITION ROUTER DEFENSIVE VALIDATION | ||
| # ========================================================================== | ||
|
|
||
| ## Validates that the transition router respects minimum load time before proceeding. | ||
| func test_transition_router_respects_min_load_time() -> void: | ||
| splash_instance = _create_splash_instance() | ||
|
|
||
| splash_instance.is_scene_loaded = true | ||
| splash_instance.loader_progress = 100.0 | ||
| splash_instance.min_load_time = 10.0 # Set long minimum load time | ||
|
|
||
| splash_instance._evaluate_transition_router() | ||
|
|
||
| assert_false( | ||
| splash_instance.transitioning, | ||
| "Transition router must lock out scene change until min_load_time has elapsed." | ||
| ) | ||
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 @@ | ||
| uid://cy3bqndjmni20 |
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.