-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathtest_undo_state.gd
More file actions
155 lines (127 loc) · 5.85 KB
/
Copy pathtest_undo_state.gd
File metadata and controls
155 lines (127 loc) · 5.85 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
## Verifies the undo/redo state round-trip: the snapshot the dock stores per edit
## (_bound_state) must restore EVERY dock control, not just the parts - preset
## dropdowns, body shape, species and colors included. Run headless:
## godot --headless -s tests/test_undo_state.gd
extends SceneTree
var _failures := 0
var _dock: Control
var _character: SidekickCharacter
func _init() -> void:
ProjectSettings.set_setting("kickdot/build/combine_meshes", false)
ProjectSettings.set_setting(SKResourceCache.SETTING_CACHE_DIR, "user://test_kickdot_cache")
call_deferred("_run")
func _run() -> void:
_dock = load("res://addons/kickdot/editor/sidekick_dock.gd").new()
root.add_child(_dock)
_character = SidekickCharacter.new()
_character.build_on_load = false
root.add_child(_character)
_dock._bind(_character)
_test_preset_round_trip()
_test_body_shape_and_colors_round_trip()
_test_species_round_trip()
print("UNDO STATE: %s" % ("ALL PASSED" if _failures == 0 else "%d FAILURES" % _failures))
quit(0 if _failures == 0 else 1)
## The reported bug: picking preset A, then B, then undoing back to A left the preset
## dropdown showing B.
func _test_preset_round_trip() -> void:
print("[part preset round-trip]")
var group := SKEnums.PartGroup.HEAD
var picker: OptionButton = _dock._preset_pickers[group]
_check(picker.item_count > 2, "head presets available (got %d)" % (picker.item_count - 1))
if picker.item_count <= 2:
return
# Edit 1: pick the first preset and commit it, capturing the "before undo" state.
_pick(picker, 1, group)
var state_a: Dictionary = _dock._bound_state()
var preset_a := picker.get_item_text(1)
var parts_a := _selected_parts()
# Edit 2: pick a different preset.
_pick(picker, 2, group)
var preset_b := picker.get_item_text(2)
_check(picker.get_item_text(picker.selected) == preset_b, "preset B selected after second edit")
_check(_selected_parts() != parts_a, "parts changed between presets")
# Undo: restore snapshot A.
_dock._restore_bound_state(_character, state_a)
_check(picker.get_item_text(picker.selected) == preset_a,
"preset dropdown shows A after undo (got '%s', expected '%s')"
% [picker.get_item_text(picker.selected), preset_a])
_check(_selected_parts() == parts_a, "part dropdowns match A after undo")
_check(_dock._stored_id(_character.part_preset_ids, group) == picker.get_item_id(1),
"node stores the restored part preset id")
func _test_body_shape_and_colors_round_trip() -> void:
print("[body shape + color round-trip]")
var body: OptionButton = _dock._body_shape_picker
var colors: OptionButton = _dock._color_pickers[SKEnums.ColorGroup.SPECIES]
if body.item_count <= 2 or colors.item_count <= 2:
_check(false, "body shape and color presets available")
return
body.select(1)
body.item_selected.emit(1)
colors.select(1)
colors.item_selected.emit(1)
_dock._apply_now()
var state_a: Dictionary = _dock._bound_state()
var body_a := body.get_item_text(1)
var color_a := colors.get_item_text(1)
var sliders_a := [_dock._body_type_slider.value, _dock._body_size_slider.value,
_dock._muscle_slider.value]
body.select(2)
body.item_selected.emit(2)
colors.select(2)
colors.item_selected.emit(2)
_dock._apply_now()
_check(body.get_item_text(body.selected) != body_a, "body shape changed for the second edit")
_dock._restore_bound_state(_character, state_a)
_check(body.get_item_text(body.selected) == body_a,
"body shape dropdown restored (got '%s', expected '%s')"
% [body.get_item_text(body.selected), body_a])
_check(colors.get_item_text(colors.selected) == color_a,
"color preset dropdown restored (got '%s', expected '%s')"
% [colors.get_item_text(colors.selected), color_a])
_check([_dock._body_type_slider.value, _dock._body_size_slider.value,
_dock._muscle_slider.value] == sliders_a, "body sliders restored")
## A species change repopulates the dropdowns, so undoing one has to restore both the
## species and the part lists that belong to it.
func _test_species_round_trip() -> void:
print("[species round-trip]")
var species: OptionButton = _dock._species_options
var zombie_index := -1
for i in species.item_count:
if species.get_item_id(i) == 6: # Zombie
zombie_index = i
if zombie_index < 0:
print(" skip: Zombie species not installed")
return
var human_id: int = _dock._selected_species_id()
_dock._apply_now()
var state_a: Dictionary = _dock._bound_state()
var head_picker: OptionButton = _dock._part_pickers[SKEnums.PartType.HEAD]
var head_a := head_picker.get_item_text(head_picker.selected) if head_picker.selected > 0 else ""
species.select(zombie_index)
_dock._on_species_selected(zombie_index)
_dock._apply_now()
_check(_dock._selected_species_id() == 6, "species switched to Zombie")
_dock._restore_bound_state(_character, state_a)
_check(_dock._selected_species_id() == human_id,
"species restored after undo (got %d, expected %d)" % [_dock._selected_species_id(), human_id])
_check(_dock._species_options_parts.selected == species.selected, "Parts-tab species mirror restored")
var head_now := head_picker.get_item_text(head_picker.selected) if head_picker.selected > 0 else ""
_check(head_now == head_a, "head part restored after undo (got '%s', expected '%s')" % [head_now, head_a])
## Picks a preset the way the UI does (signal-driven), then commits the edit.
func _pick(picker: OptionButton, index: int, group: int) -> void:
picker.select(index)
picker.item_selected.emit(index)
_dock._on_preset_picked(index, group)
_dock._apply_now()
## Current selection of every part dropdown, as a comparable dictionary.
func _selected_parts() -> Dictionary:
var parts := {}
for type: int in _dock._part_pickers:
var picker: OptionButton = _dock._part_pickers[type]
parts[type] = picker.get_item_text(picker.selected) if picker.selected > 0 else ""
return parts
func _check(ok: bool, what: String) -> void:
if not ok:
_failures += 1
print(" %s %s" % ["ok " if ok else "FAIL", what])