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)