Fix UI tests for onboarding flow and AddRemoteServer redesign

- Skip onboarding in tests by setting UserDefaults before launch
- Update all addSource.* identifiers to addRemoteServer.* for new flow
- Switch from identifier-based to text-based element lookups (iOS 26 AXe limitation)
- Add Yattee Server credential support in instance setup
- Update baseline screenshots for Home tab and settings
This commit is contained in:
Arkadiusz Fal
2026-02-10 00:05:39 +01:00
parent 3905fd8b18
commit 9cd9506dcf
17 changed files with 350 additions and 150 deletions

View File

@@ -32,39 +32,33 @@ RSpec.describe 'App Launch', :smoke do
UITest::Simulator.shutdown(@udid) if @udid && !UITest::Config.keep_simulator?
end
describe 'Library tab' do
it 'displays the Library navigation bar' do
# With toolbarTitleDisplayMode(.inlineLarge), the title is an AXHeading with AXLabel "Library"
# but no AXUniqueId, so we check for the text instead
expect(@axe).to have_text('Library')
describe 'Home tab' do
it 'displays the Home navigation bar' do
expect(@axe).to have_text('Home')
end
it 'displays the Tab Bar' do
expect(@axe).to have_text('Tab Bar')
end
it 'displays the Playlists card' do
expect(@axe).to have_element('library.card.playlists')
it 'displays the Open Link shortcut' do
expect(@axe).to have_element('home.shortcut.openURL')
end
it 'displays the Bookmarks card' do
expect(@axe).to have_element('library.card.bookmarks')
it 'displays the Bookmarks shortcut' do
expect(@axe).to have_element('home.shortcut.bookmarks')
end
it 'displays the History card' do
expect(@axe).to have_element('library.card.history')
it 'displays the History shortcut' do
expect(@axe).to have_element('home.shortcut.history')
end
it 'displays the Downloads card' do
expect(@axe).to have_element('library.card.downloads')
end
it 'displays the Channels card' do
expect(@axe).to have_element('library.card.channels')
it 'displays the Settings button' do
expect(@axe).to have_element('home.settingsButton')
end
it 'matches the baseline screenshot', :visual do
screenshot = @axe.screenshot('app-launch-library')
screenshot = @axe.screenshot('app-launch-home')
expect(screenshot).to match_baseline
end
end

View File

@@ -43,7 +43,7 @@ RSpec.describe 'Import Playlists from Piped', :smoke do
@instance_setup.send(:navigate_to_sources)
# Tap the Piped row (using helper due to iOS 26 multiple-match issue)
@instance_setup.send(:tap_first_element_with_id, "sources.row.piped.#{UITest::Config.piped_host}")
@instance_setup.send(:tap_element_containing_text, UITest::Config.piped_host)
sleep 0.8
# Wait for EditSourceView
@@ -71,7 +71,7 @@ RSpec.describe 'Import Playlists from Piped', :smoke do
@instance_setup.send(:navigate_to_sources)
# Tap the Piped row (using helper due to iOS 26 multiple-match issue)
@instance_setup.send(:tap_first_element_with_id, "sources.row.piped.#{UITest::Config.piped_host}")
@instance_setup.send(:tap_element_containing_text, UITest::Config.piped_host)
sleep 0.8
# Wait for EditSourceView

View File

@@ -43,7 +43,7 @@ RSpec.describe 'Import Playlists from Invidious', :smoke do
@instance_setup.send(:navigate_to_sources)
# Tap the Invidious row (using helper due to iOS 26 multiple-match issue)
@instance_setup.send(:tap_first_element_with_id, "sources.row.invidious.#{UITest::Config.invidious_host}")
@instance_setup.send(:tap_element_containing_text, UITest::Config.invidious_host)
sleep 0.8
# Wait for EditSourceView
@@ -71,7 +71,7 @@ RSpec.describe 'Import Playlists from Invidious', :smoke do
@instance_setup.send(:navigate_to_sources)
# Tap the Invidious row (using helper due to iOS 26 multiple-match issue)
@instance_setup.send(:tap_first_element_with_id, "sources.row.invidious.#{UITest::Config.invidious_host}")
@instance_setup.send(:tap_element_containing_text, UITest::Config.invidious_host)
sleep 0.8
# Wait for EditSourceView

View File

@@ -43,7 +43,7 @@ RSpec.describe 'Import Subscriptions from Piped', :smoke do
@instance_setup.send(:navigate_to_sources)
# Tap the Piped row (using helper due to iOS 26 multiple-match issue)
@instance_setup.send(:tap_first_element_with_id, "sources.row.piped.#{UITest::Config.piped_host}")
@instance_setup.send(:tap_element_containing_text, UITest::Config.piped_host)
sleep 0.8
# Wait for EditSourceView
@@ -71,7 +71,7 @@ RSpec.describe 'Import Subscriptions from Piped', :smoke do
@instance_setup.send(:navigate_to_sources)
# Tap the Piped row (using helper due to iOS 26 multiple-match issue)
@instance_setup.send(:tap_first_element_with_id, "sources.row.piped.#{UITest::Config.piped_host}")
@instance_setup.send(:tap_element_containing_text, UITest::Config.piped_host)
sleep 0.8
# Wait for EditSourceView

View File

@@ -43,7 +43,7 @@ RSpec.describe 'Import Subscriptions from Invidious', :smoke do
@instance_setup.send(:navigate_to_sources)
# Tap the Invidious row (using helper due to iOS 26 multiple-match issue)
@instance_setup.send(:tap_first_element_with_id, "sources.row.invidious.#{UITest::Config.invidious_host}")
@instance_setup.send(:tap_element_containing_text, UITest::Config.invidious_host)
sleep 0.8
# Wait for EditSourceView
@@ -71,7 +71,7 @@ RSpec.describe 'Import Subscriptions from Invidious', :smoke do
@instance_setup.send(:navigate_to_sources)
# Tap the Invidious row (using helper due to iOS 26 multiple-match issue)
@instance_setup.send(:tap_first_element_with_id, "sources.row.invidious.#{UITest::Config.invidious_host}")
@instance_setup.send(:tap_element_containing_text, UITest::Config.invidious_host)
sleep 0.8
# Wait for EditSourceView

View File

@@ -38,15 +38,15 @@ RSpec.describe 'Invidious Instance', :smoke do
invidious_url = UITest::Config.invidious_url
invidious_host = UITest::Config.invidious_host
# Ensure we start from Library (check for text since inlineLarge title has no AXUniqueId)
expect(@axe).to have_text('Library')
# Ensure we start from Home
expect(@axe).to have_text('Home')
# Remove existing instance (if any) and add fresh - always tests the add flow
@instance_setup.remove_and_add_invidious(invidious_url)
# Navigate to Sources to verify the instance was added
# Open Settings using accessibility identifier
@axe.tap_id('library.settingsButton')
@axe.tap_id('home.settingsButton')
sleep 1
expect(@axe).to have_element('settings.view')
@@ -55,15 +55,13 @@ RSpec.describe 'Invidious Instance', :smoke do
@axe.tap_id('settings.row.sources')
sleep 0.5
# Verify we're on Sources list
expect(@axe).to have_element('sources.view')
# Verify instance appears in Sources list
expect(@axe).to have_element("sources.row.invidious.#{invidious_host}")
# Verify instance appears in Sources list (check by host text since
# SwiftUI accessibilityIdentifier doesn't expose as AXUniqueId)
expect(@axe).to have_text(invidious_host)
# Close settings
begin
@axe.tap_label('Done')
@axe.tap_id('settings.doneButton')
rescue StandardError
nil
end

View File

@@ -38,15 +38,15 @@ RSpec.describe 'Piped Instance', :smoke do
piped_url = UITest::Config.piped_url
piped_host = UITest::Config.piped_host
# Ensure we start from Library (check for text since inlineLarge title has no AXUniqueId)
expect(@axe).to have_text('Library')
# Ensure we start from Home
expect(@axe).to have_text('Home')
# Remove existing instance (if any) and add fresh - always tests the add flow
@instance_setup.remove_and_add_piped(piped_url)
# Navigate to Sources to verify the instance was added
# Open Settings using accessibility identifier
@axe.tap_id('library.settingsButton')
@axe.tap_id('home.settingsButton')
sleep 1
expect(@axe).to have_element('settings.view')
@@ -55,15 +55,12 @@ RSpec.describe 'Piped Instance', :smoke do
@axe.tap_id('settings.row.sources')
sleep 0.5
# Verify we're on Sources list
expect(@axe).to have_element('sources.view')
# Verify instance appears in Sources list
expect(@axe).to have_element("sources.row.piped.#{piped_host}")
expect(@axe).to have_text(piped_host)
# Close settings
begin
@axe.tap_label('Done')
@axe.tap_id('settings.doneButton')
rescue StandardError
nil
end

View File

@@ -32,20 +32,20 @@ RSpec.describe 'Settings', :smoke do
UITest::Simulator.shutdown(@udid) if @udid && !UITest::Config.keep_simulator?
end
describe 'opening Settings from Library' do
describe 'opening Settings from Home' do
before(:all) do
# Ensure we're on Library tab first (check for text since inlineLarge title has no AXUniqueId)
expect(@axe).to have_text('Library')
# Ensure we're on Home tab first
expect(@axe).to have_text('Home')
# Tap Settings button using accessibility identifier
@axe.tap_id('library.settingsButton')
@axe.tap_id('home.settingsButton')
sleep 1
end
after(:all) do
# Close Settings to return to Library
# Close Settings to return to Home
begin
@axe.tap_label('Done')
@axe.tap_id('settings.doneButton')
rescue StandardError
nil
end
@@ -60,7 +60,7 @@ RSpec.describe 'Settings', :smoke do
expect(@axe).to have_text('Settings')
end
it 'displays the Done button' do
it 'displays the Close button' do
expect(@axe).to have_element('settings.doneButton')
end
@@ -83,24 +83,33 @@ RSpec.describe 'Settings', :smoke do
end
describe 'closing Settings' do
before(:all) do
# Open settings if not already open
unless @axe.element_exists?('settings.view')
@axe.tap_id('library.settingsButton')
sleep 1
it 'closes Settings when tapping Close' do
# Ensure we're on Home first
sleep 0.5
unless @axe.text_visible?('Home') || @axe.element_exists?('home.settingsButton')
# Try to dismiss any open sheets
begin
@axe.tap_id('settings.doneButton')
sleep 0.5
rescue StandardError
nil
end
end
end
it 'closes Settings when tapping Done' do
# Open Settings fresh
@axe.tap_id('home.settingsButton')
sleep 1
# Verify we're in Settings
expect(@axe).to have_element('settings.view')
expect(@axe).to have_element('settings.doneButton')
# Tap Done
@axe.tap_label('Done')
sleep 0.5
# Tap Close
@axe.tap_id('settings.doneButton')
sleep 1.5
# Verify we're back on Library (check for text since inlineLarge title has no AXUniqueId)
expect(@axe).to have_text('Library')
# Verify we're back on Home
expect(@axe).to have_text('Home')
expect(@axe).not_to have_element('settings.view')
end
end

View File

@@ -38,15 +38,15 @@ RSpec.describe 'Yattee Server Instance', :smoke do
server_url = UITest::Config.yattee_server_url
server_host = UITest::Config.yattee_server_host
# Ensure we start from Library (check for text since inlineLarge title has no AXUniqueId)
expect(@axe).to have_text('Library')
# Ensure we start from Home
expect(@axe).to have_text('Home')
# Remove existing instance (if any) and add fresh - always tests the add flow
@instance_setup.remove_and_add_yattee_server(server_url)
# Navigate to Sources to verify the instance was added
# Open Settings using accessibility identifier
@axe.tap_id('library.settingsButton')
@axe.tap_id('home.settingsButton')
sleep 1
expect(@axe).to have_element('settings.view')
@@ -55,15 +55,12 @@ RSpec.describe 'Yattee Server Instance', :smoke do
@axe.tap_id('settings.row.sources')
sleep 0.5
# Verify we're on Sources list
expect(@axe).to have_element('sources.view')
# Verify instance appears in Sources list
expect(@axe).to have_element("sources.row.yatteeServer.#{server_host}")
expect(@axe).to have_text(server_host)
# Close settings
begin
@axe.tap_label('Done')
@axe.tap_id('settings.doneButton')
rescue StandardError
nil
end