Add UI smoke test for Piped authenticated endpoints

Adds a Piped instance, logs in, and exercises the two settings flows that
hit the regressed endpoints directly — Import Subscriptions (/subscriptions)
and Import Playlists (/user/playlists). Asserts that "session is a required
parameter" never appears in the AX tree, catching the recent header-vs-query
auth regression end to end.

Promotes three tree-walking helpers (id_in_tree?, id_with_prefix_in_tree?,
label_in_tree?) onto UITest::Axe so the spec can fetch the AX tree once per
poll iteration and run all checks against it locally — roughly 6× fewer
`axe` subprocess spawns than calling element_exists? / text_visible? per
check, and a primitive other specs can reuse.
This commit is contained in:
Arkadiusz Fal
2026-05-06 20:17:28 +02:00
parent 6f8aa9a1b3
commit e3f4d764cc
2 changed files with 278 additions and 0 deletions

View File

@@ -54,6 +54,60 @@ module UITest
false
end
# Whether any element in the given tree has an AXUniqueId starting with the
# given prefix. Pass an already-fetched tree to avoid re-spawning `axe`.
def self.id_with_prefix_in_tree?(node, prefix)
case node
when Hash
return true if node['AXUniqueId']&.start_with?(prefix)
node.each_value do |value|
return true if id_with_prefix_in_tree?(value, prefix)
end
when Array
node.each do |item|
return true if id_with_prefix_in_tree?(item, prefix)
end
end
false
end
# Whether any element in the given tree has an AXLabel containing `text`.
# Pass an already-fetched tree to avoid re-spawning `axe`.
def self.label_in_tree?(node, text)
case node
when Hash
return true if node['AXLabel']&.include?(text)
node.each_value do |value|
return true if label_in_tree?(value, text)
end
when Array
node.each do |item|
return true if label_in_tree?(item, text)
end
end
false
end
# Whether any element in the given tree has the given AXUniqueId. Pass an
# already-fetched tree to avoid re-spawning `axe`.
def self.id_in_tree?(node, identifier)
case node
when Hash
return true if node['AXUniqueId'] == identifier
node.each_value do |value|
return true if id_in_tree?(value, identifier)
end
when Array
node.each do |item|
return true if id_in_tree?(item, identifier)
end
end
false
end
# Tap on an element by accessibility identifier
# @param identifier [String] Accessibility identifier
def tap_id(identifier)