Files
owniverse/tests/test_achievements.gd
T

130 lines
7.4 KiB
GDScript

extends SceneTree
const E = preload("res://world/owniverse/math/exact.gd")
const Controller = preload("res://ui/achievements/achievement_controller.gd")
var failures := 0
class MockWorld extends RefCounted:
var state := {"time": {"year": 0}, "stats": {"total_amount": {}}}
var presentation := {"revision": 0}
class MockStage extends Control:
const PAGE_WIDTH = 1080
var owniverse = MockWorld.new()
var screens: Dictionary
var stage_page_scroller: ScrollContainer
func _initialize() -> void:
call_deferred("run")
func check(value: bool, message: String) -> void:
if not value:
failures += 1
push_error(message)
func node(parent: Node, child: Node, label: String) -> Node:
child.name = label
parent.add_child(child)
return child
func run() -> void:
check(load("res://stage/stage.gd") != null, "Stage integration compiles")
var scene: PackedScene = load("res://world/world.tscn")
var scene_state: SceneState = scene.get_state()
for language in ["English", "Russian"]:
var connected := false
for i in scene_state.get_connection_count():
if str(scene_state.get_connection_source(i)) == "Stage/MainMenu/Language/" + language:
connected = scene_state.get_connection_signal(i) == &"pressed" and str(scene_state.get_connection_target(i)) == "Stage/MainMenu" and scene_state.get_connection_method(i) == &"_on_change_locale_pressed" and scene_state.get_connection_binds(i) == ["en" if language == "English" else "ru"]
check(connected, language + " button connects to locale handler")
var stage := MockStage.new()
root.add_child(stage)
var world = node(stage, Control.new(), "World")
stage.screens = {"World": world}
stage.stage_page_scroller = node(world, ScrollContainer.new(), "PageScroller")
var pages = node(stage.stage_page_scroller, HBoxContainer.new(), "HBoxContainer")
for names in [["ForcePage", "ForceHeader"], ["ResourcePage", "ResourceHeader"], ["StarPage", "StarHeader"], ["StructurePage", "StructureHeader"], ["LifePage", "LifeHeader"]]:
node(node(pages, VBoxContainer.new(), names[0]), HBoxContainer.new(), names[1])
var screen = node(stage, Control.new(), "Achievements")
var title = node(node(screen, Control.new(), "Header"), TextureRect.new(), "Title")
node(node(screen, ScrollContainer.new(), "AchievementList"), VBoxContainer.new(), "AchievementItems")
var controller = Controller.new()
controller.progress_path = "/tmp/owniverse-achievements-test-%s.cfg" % OS.get_process_id()
stage.add_child(controller)
controller.initialize(stage)
check(controller.definitions.size() == 72, "All 72 enabled achievements loaded")
check(not controller.definitions.has("a95"), "Ignored achievement excluded")
controller.update(0.0)
check(controller.queue.is_empty() and controller.current.is_empty(), "Initially visible achievements do not notify")
stage.owniverse.state.stats.total_amount.H = E.of("5E4")
stage.owniverse.presentation.revision += 1
controller.update(0.0)
check(controller.progress.a13.unlocked, "Cumulative hydrogen threshold unlocks")
check(controller.progress.a14.visible and not controller.progress.a14.unlocked, "Opening threshold reveals next achievement")
controller.queue.clear()
controller._enqueue("a14", "g")
controller._enqueue("a14", "c")
check(controller.queue.size() == 1 and controller.queue[0].type == "c", "Pending reveal upgrades to completion")
controller.queue.clear()
controller.current = {}
stage.owniverse.state.time.year = E.of("1E12")
stage.owniverse.state.stats.total_amount.H = E.of("1E24")
stage.owniverse.state.stats.total_amount.Star = E.of("9E16")
stage.owniverse.presentation.revision += 1
controller.update(0.0)
check(controller.progress.a4.unlocked and controller.progress.a20.unlocked and controller.progress.a71.unlocked, "Exact large thresholds unlock")
check(controller.current.type == "c", "Immediate completion emits only completed notification")
var count: int = controller.queue.size()
controller.update(0.0)
check(controller.queue.size() == count, "Repeated update does not duplicate events")
world.hide()
var time: float = controller.elapsed
controller.update(5.0)
check(controller.elapsed == time, "Menu pauses notification")
world.show()
controller.update(3.4)
check(controller.current.is_empty() and not controller.panel.visible, "Notification expires")
for header in controller.headers: check(header.modulate.a == 1.0, "Indicators restored")
controller.update(0.0)
var remaining: int = controller.queue.size()
var click := InputEventMouseButton.new()
click.button_index = MOUSE_BUTTON_LEFT
click.pressed = true
controller._on_notification_input(click)
check(controller.current.is_empty() and not controller.panel.visible, "Click dismisses notification")
check(controller.queue.size() == remaining, "Click preserves pending notifications")
for header in controller.headers: check(header.modulate.a == 1.0, "Click restores indicators")
stage.owniverse = MockWorld.new()
controller.update(0.0)
check(controller.progress.a71.unlocked, "New universe preserves unlocked achievements")
controller.progress.clear()
controller._load_progress()
check(controller.progress.a71.unlocked, "Progress survives reload")
# Every enabled definition must be reachable through its actual compiled rule.
for id in controller.definitions:
var rule: Dictionary = controller.conditions[id].achieve
var source := {"time": {"year": 0}, "stats": {"total_amount": {}}}
if rule.type == "age": source.time.year = E.subtract(rule.amount, 1)
else: source.stats.total_amount[rule.id] = E.subtract(rule.amount, 1)
check(not controller._matches(rule, source), id + " stays locked below threshold")
if rule.type == "age": source.time.year = rule.amount
else: source.stats.total_amount[rule.id] = rule.amount
check(controller._matches(rule, source), id + " completes at exact threshold")
var global: Node = root.get_node("Global")
var previous_locale: String = global.Locale
global.Locale = "ru"
controller.update(0.0)
check(controller.status.text.begins_with("Открыто"), "Status localizes")
check(title.texture == Controller.TITLES.ru, "Russian title selected")
check(controller.items.a71.event_label.text.contains("90 квадриллионов"), "Russian achievement text selected")
global.Locale = "en"
controller.update(0.0)
check(controller.status.text.begins_with("Unlocked"), "English status selected")
check(title.texture == Controller.TITLES.en, "English title selected")
check(controller.items.a71.event_label.text.contains("90 quadrillion"), "English achievement text selected")
controller.current = {"id": "a71", "type": "c"}
controller._display_event(controller.current)
check(controller.notification_item.event_label.text.contains("90 quadrillion"), "English notification text selected")
global.Locale = "ru"
controller.update(0.0)
check(controller.notification_item.event_label.text.contains("90 квадриллионов"), "Active notification changes language")
global.Locale = previous_locale
var path: String = controller.progress_path
stage.free()
DirAccess.remove_absolute(path)
print("Achievement checks: ", "PASS" if failures == 0 else "FAIL")
quit(1 if failures else 0)