The quiz (song, playlist, players, music player and the popups opened from it) moves into Quiz.tscn and the top panel into TopBar.tscn. The main window keeps only the top bar, the quiz and the popups opened from the top bar, so other views can be added next to the quiz later. Every node keeps its place on screen. Screenshots of every UI state before and after are pixel-identical, and a layout test checks each node against a baseline taken before the split.
99 lines
4.0 KiB
GDScript
99 lines
4.0 KiB
GDScript
extends GdUnitTestSuite
|
|
## Checks that every node of the main window is where it was before the window was
|
|
## split into scenes.
|
|
##
|
|
## [code]tests/data/layout_baseline.json[/code] was written by
|
|
## [code]tools/take_screenshots.gd[/code] before the split. It holds the position, size
|
|
## and visibility of every node in each UiTour state, keyed by the node's old path. This
|
|
## test runs the same tour and compares, after moving each old path to where the node
|
|
## lives now.
|
|
|
|
const BASELINE_PATH: String = "res://tests/data/layout_baseline.json"
|
|
|
|
## Nodes that moved from the main window into the Quiz scene, by their old name.
|
|
const QUIZ_NODES: Array[String] = [
|
|
"Open", "FileDialog", "MusicListPanel", "ScrollContainer", "VBoxContainer",
|
|
"MusicPlayer", "Players", "ResetPlaylistButton", "ResetPointsButton", "SettingsButton",
|
|
"SoundTestButton", "ShowAnswerButton", "NextButton", "RepeatSongCheckButton",
|
|
"DebugLabel", "SettingsWindow", "NewCharacterSelect", "WinnerWindow", "Log",
|
|
]
|
|
|
|
## Nodes that moved from the main window into the TopBar scene, by their old name.
|
|
const TOP_BAR_NODES: Array[String] = [
|
|
"TopPanelContainer", "Title", "SearchButton", "SyncButton", "StatisticsButton",
|
|
"ShortcutsButton", "AboutButton", "QRButton",
|
|
]
|
|
|
|
## How far a node may be from its old place, in pixels.
|
|
const TOLERANCE: float = 0.5
|
|
|
|
var _snapshot: AutoloadSnapshot
|
|
var _server: FakeHttpTransport
|
|
var _main: Control
|
|
var _layout: Dictionary = {}
|
|
|
|
|
|
func before() -> void:
|
|
_snapshot = AutoloadSnapshot.take([Settings, Playlist])
|
|
UiTour.prepare_autoloads()
|
|
_server = UiTour.make_server().install()
|
|
# Laid out at the size the baseline was taken at, like the screenshots
|
|
var viewport: SubViewport = auto_free(SubViewport.new())
|
|
viewport.size = Vector2i(1920, 1080)
|
|
viewport.gui_embed_subwindows = true
|
|
Engine.get_main_loop().root.add_child(viewport)
|
|
_main = load("res://MainWindow.tscn").instantiate()
|
|
viewport.add_child(_main)
|
|
await UiTour.new(_main).run(func(state: String, popup: Node) -> void:
|
|
_layout[state] = UiTour.dump_layout(_main, _main if popup == null else popup))
|
|
|
|
|
|
func after() -> void:
|
|
_main.free()
|
|
await Engine.get_main_loop().process_frame
|
|
_server.uninstall()
|
|
_snapshot.restore()
|
|
|
|
|
|
## Where the node that used to be at [param old_path] in the main window is now.
|
|
static func new_path(old_path: String) -> String:
|
|
var first: String = old_path.get_slice("/", 0)
|
|
if first in QUIZ_NODES:
|
|
return "Quiz/" + old_path
|
|
if first in TOP_BAR_NODES:
|
|
return "TopBar/" + old_path
|
|
return old_path
|
|
|
|
|
|
func _baseline() -> Dictionary:
|
|
return JSON.parse_string(FileAccess.get_file_as_string(BASELINE_PATH))
|
|
|
|
|
|
func test_tour_has_the_same_states_as_the_baseline() -> void:
|
|
assert_array(_layout.keys()).contains_exactly_in_any_order(_baseline().keys())
|
|
|
|
|
|
func test_every_node_is_where_it_was() -> void:
|
|
var problems: Array[String] = []
|
|
var baseline: Dictionary = _baseline()
|
|
for state: String in baseline:
|
|
var actual: Dictionary = _layout.get(state, {})
|
|
for old_path: String in baseline[state]:
|
|
var path: String = new_path(old_path)
|
|
var expected: Dictionary = baseline[state][old_path]
|
|
if !actual.has(path):
|
|
problems.append("%s: %s is missing (was %s)" % [state, path, old_path])
|
|
continue
|
|
var rect: Array = actual[path].rect
|
|
for i: int in 4:
|
|
if absf(rect[i] - expected.rect[i]) > TOLERANCE:
|
|
problems.append("%s: %s is at %s, was %s"
|
|
% [state, path, rect, expected.rect])
|
|
break
|
|
if actual[path].visible != expected.visible:
|
|
problems.append("%s: %s visible is %s, was %s"
|
|
% [state, path, actual[path].visible, expected.visible])
|
|
assert_array(problems).override_failure_message(
|
|
"%d nodes moved:\n%s" % [problems.size(), "\n".join(problems.slice(0, 30))]) \
|
|
.is_empty()
|