Nodes a script uses through a path of several nodes are marked unique in their scene and found with %Name. The search list is renamed SearchResults, and the player row's nodes get their real types.
142 lines
5.2 KiB
GDScript
142 lines
5.2 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"
|
|
|
|
## Where each node of the old main window lives now: its old name, and the path that
|
|
## replaces it. Nodes that are not listed are still where they were.
|
|
const MOVED: Dictionary = {
|
|
# The top bar
|
|
"TopPanelContainer": "TopBar/TopPanelContainer",
|
|
"Title": "TopBar/Title",
|
|
"SearchButton": "TopBar/SearchButton",
|
|
"SyncButton": "TopBar/SyncButton",
|
|
"StatisticsButton": "TopBar/StatisticsButton",
|
|
"ShortcutsButton": "TopBar/ShortcutsButton",
|
|
"AboutButton": "TopBar/AboutButton",
|
|
"QRButton": "TopBar/QRButton",
|
|
# The popups of the main window, renamed from *Window to *Popup
|
|
"Search": "SearchPopup",
|
|
"SyncWindow": "SyncPopup",
|
|
"QRWindow": "QRPopup",
|
|
"ShortcutsWindow": "ShortcutsPopup",
|
|
"AboutWindow": "AboutPopup",
|
|
"Log": "LogPopup",
|
|
# The quiz and its parts
|
|
"Open": "Quiz/Open",
|
|
"FileDialog": "Quiz/FileDialog",
|
|
"DebugLabel": "Quiz/DebugLabel",
|
|
"MusicListPanel": "Quiz/MusicListPanel",
|
|
"Players": "Quiz/PlayersPanel",
|
|
"ScrollContainer": "Quiz/InspirationList",
|
|
"VBoxContainer": "Quiz/NowPlaying",
|
|
"MusicPlayer": "Quiz/MusicPlayer/PlayerBar",
|
|
"RepeatSongCheckButton": "Quiz/MusicPlayer/RepeatSongCheckButton",
|
|
"ResetPlaylistButton": "Quiz/QuizToolbar/ResetPlaylistButton",
|
|
"ResetPointsButton": "Quiz/QuizToolbar/ResetPointsButton",
|
|
"SettingsButton": "Quiz/QuizToolbar/SettingsButton",
|
|
"SoundTestButton": "Quiz/QuizToolbar/SoundTestButton",
|
|
"ShowAnswerButton": "Quiz/SongControls/ShowAnswerButton",
|
|
"NextButton": "Quiz/SongControls/NextButton",
|
|
"SettingsWindow": "Quiz/SettingsPopup",
|
|
"NewCharacterSelect": "Quiz/CharacterSelectPopup",
|
|
"WinnerWindow": "Quiz/WinnerPopup",
|
|
}
|
|
|
|
## Scenes that were renamed, by their old and new root name. A row added to a list is
|
|
## named after its scene's root when the name is still free, so these show up deeper in a
|
|
## path.
|
|
const RENAMED_SCENES: Dictionary = {
|
|
"SongListObject": "SongRow",
|
|
"Player": "PlayerRow",
|
|
}
|
|
|
|
## Nodes renamed inside a popup: old path from the main window, and new path.
|
|
const RENAMED_PATHS: Dictionary = {
|
|
"SearchPopup/ScrollContainer/VBoxContainer": "SearchPopup/ScrollContainer/SearchResults",
|
|
}
|
|
|
|
## 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 parts: PackedStringArray = old_path.split("/")
|
|
for i: int in parts.size():
|
|
parts[i] = RENAMED_SCENES.get(parts[i], parts[i])
|
|
var first: String = parts[0]
|
|
parts[0] = MOVED.get(first, first)
|
|
var path: String = "/".join(parts)
|
|
for renamed: String in RENAMED_PATHS:
|
|
if path == renamed || path.begins_with(renamed + "/"):
|
|
return RENAMED_PATHS[renamed] + path.trim_prefix(renamed)
|
|
return 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()
|