Files
MusicPlayer/tests/integration/test_search_popup.gd
T
Sansan 845d08c260 Rework the Search popup and highlight what matched
- The search field is a single-line field, so Enter no longer adds a
  line break that made every search come up empty.
- The field, button and list use real font sizes from the theme instead
  of being drawn at half size and scaled up, so the text is sharp, and
  everything fits inside the panel.
- Results have alternating row backgrounds like the other lists, a count
  ("3 of 1045 soundtracks") and a message when nothing matches.
- The letters that matched are highlighted.
- Searches shorter than Settings.LETTERS_FOR_LOOSE_SEARCH (3) only find
  names that contain the text, instead of names with the letters far
  apart, which matched most of the library. The Statistics tab uses the
  same search.
2026-10-07 14:53:51 +02:00

144 lines
4.3 KiB
GDScript

extends MainWindowTestSuite
## The Search popup: typing, the result list, the count, the highlighted letters and
## the layout.
const SOUNDTRACKS: Array[String] = [
"Chrono Trigger", "Final Fantasy VI", "Mario & Luigi: Superstar Saga", "Super Mario 64",
"The Legend of Zelda: A Link to the Past",
]
var _popup: SearchPopup
func _before_window_starts() -> void:
_server.respond_json("/music/all/order", SOUNDTRACKS)
func before_test() -> void:
super()
_popup = _window.get_node("SearchPopup")
func _open() -> void:
await _click_at(_window.get_node("TopBar/SearchButton").get_global_rect().get_center())
await _runner.simulate_frames(1)
func _type(text: String) -> void:
for letter: String in text:
_popup.search_field.insert_text_at_caret(letter)
_popup.search_field.text_changed.emit(_popup.search_field.text)
func _row_texts() -> Array[String]:
var texts: Array[String] = []
for row: PanelContainer in _popup.search_results.get_children():
if row.visible:
texts.append((row.get_child(0) as RichTextLabel).text)
return texts
func test_shows_every_soundtrack_with_a_count() -> void:
await _open()
assert_array(_popup.shown_names()).contains_exactly(SOUNDTRACKS)
assert_str(_popup.count_label.text).is_equal("5 soundtracks")
assert_bool(_popup.empty_label.visible).is_false()
assert_bool(_popup.search_field.has_focus()).is_true()
func test_typing_filters_and_counts() -> void:
await _open()
_type("mario")
assert_array(_popup.shown_names()) \
.contains_exactly(["Mario & Luigi: Superstar Saga", "Super Mario 64"])
assert_str(_popup.count_label.text).is_equal("2 of 5 soundtracks")
func test_enter_does_not_break_the_search() -> void:
await _open()
_type("chrono")
_runner.simulate_key_pressed(KEY_ENTER)
await _runner.await_input_processed()
assert_str(_popup.search_field.text).is_equal("chrono")
assert_array(_popup.shown_names()).contains_exactly(["Chrono Trigger"])
func test_no_match_says_so() -> void:
await _open()
_type("metroid")
assert_array(_popup.shown_names()).is_empty()
assert_bool(_popup.empty_label.visible).is_true()
assert_str(_popup.count_label.text).is_equal("0 of 5 soundtracks")
func test_short_search_does_not_match_letters_far_apart() -> void:
await _open()
_type("sm")
assert_array(_popup.shown_names()).is_empty()
_type("r")
assert_array(_popup.shown_names()).contains_exactly(["Super Mario 64"])
func test_matched_letters_are_highlighted() -> void:
await _open()
var color: String = _popup.get_theme_color(&"font_color", &"HighlightLarge").to_html(false)
_type("trig")
assert_array(_row_texts()).contains_exactly(["Chrono [color=#%s]Trig[/color]ger" % color])
func test_letters_in_order_are_highlighted_one_by_one() -> void:
var color: Color = Color.ORANGE
var text: String = SearchPopup.highlighted_name("Super Mario 64", "smr", color)
var c: String = color.to_html(false)
assert_str(text).is_equal(
"[color=#%s]S[/color]uper [color=#%s]M[/color]a[color=#%s]r[/color]io 64" % [c, c, c])
func test_square_brackets_in_names_are_shown_as_text() -> void:
assert_str(SearchPopup.highlighted_name("Disc [1]", "", Color.ORANGE)) \
.is_equal("Disc [lb]1]")
func test_clear_shows_everything_again_without_highlights() -> void:
await _open()
_type("mario")
await _click_at(_popup.clear_button.get_global_rect().get_center())
assert_str(_popup.search_field.text).is_empty()
assert_array(_row_texts()).contains_exactly(SOUNDTRACKS)
func test_rows_alternate_like_the_other_lists() -> void:
await _open()
_type("mario")
var rows: Array[Node] = _popup.search_results.get_children().filter(
func(row: Control) -> bool: return row.visible)
assert_str(String(rows[0].theme_type_variation)).is_equal("ListRowEven")
assert_str(String(rows[1].theme_type_variation)).is_equal("ListRowOdd")
func test_everything_fits_inside_the_panel_at_its_real_size() -> void:
await _open()
var panel: Rect2 = _popup.search_panel.get_global_rect()
for node: Control in [_popup.search_field, _popup.clear_button, _popup.count_label,
_popup.search_results.get_parent()]:
assert_bool(panel.encloses(node.get_global_rect())) \
.override_failure_message(node.name + " is outside the panel").is_true()
assert_vector(node.scale).is_equal(Vector2.ONE)
assert_bool(Rect2(Vector2.ZERO, Vector2(1920, 1080)).encloses(panel)).is_true()