mirror of
https://github.com/yattee/yattee.git
synced 2026-02-19 09:19:46 +00:00
Fix URL scheme UI tests for YouTube deep links and content loading
Route HTTPS YouTube URLs through yattee://open?url= scheme since simctl can't trigger Universal Links. Improve wait strategies: use player expansion check for video tests, tree length threshold for channel/ playlist content loading. Add retry logic to cleanup_after_video.
This commit is contained in:
@@ -1,5 +1,6 @@
|
|||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require 'cgi'
|
||||||
require_relative '../spec_helper'
|
require_relative '../spec_helper'
|
||||||
|
|
||||||
RSpec.describe 'URL Schemes', :smoke do
|
RSpec.describe 'URL Schemes', :smoke do
|
||||||
@@ -231,7 +232,7 @@ RSpec.describe 'URL Schemes with Backend', :url_backend do
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# Open a URL and dismiss the iOS "Open in Yattee?" system confirmation dialog
|
# Open a yattee:// URL and dismiss the iOS "Open in Yattee?" system confirmation dialog
|
||||||
def open_url(url)
|
def open_url(url)
|
||||||
UITest::Simulator.open_url(@udid, url)
|
UITest::Simulator.open_url(@udid, url)
|
||||||
sleep 0.8
|
sleep 0.8
|
||||||
@@ -253,6 +254,13 @@ RSpec.describe 'URL Schemes with Backend', :url_backend do
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Wrap an HTTPS URL in yattee://open?url= scheme so simctl routes it to the app
|
||||||
|
# instead of Safari. This tests the app's YouTube URL parsing via URLRouter.
|
||||||
|
def open_youtube_url(url)
|
||||||
|
encoded = CGI.escape(url)
|
||||||
|
open_url("yattee://open?url=#{encoded}")
|
||||||
|
end
|
||||||
|
|
||||||
# Navigate back to Home tab
|
# Navigate back to Home tab
|
||||||
def navigate_to_home
|
def navigate_to_home
|
||||||
5.times do
|
5.times do
|
||||||
@@ -288,25 +296,21 @@ RSpec.describe 'URL Schemes with Backend', :url_backend do
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# Wait for any content to load (not an empty state)
|
# Wait for content to load (channel/playlist views with actual data)
|
||||||
def wait_for_content_loaded(timeout: 20)
|
def wait_for_content_loaded(timeout: 20)
|
||||||
start_time = Time.now
|
start_time = Time.now
|
||||||
|
|
||||||
loop do
|
loop do
|
||||||
# Content loaded if we see video titles, channel names, etc.
|
|
||||||
# Check that we're not just on an empty/loading screen
|
|
||||||
tree = @axe.describe_ui
|
tree = @axe.describe_ui
|
||||||
tree_str = tree.to_s
|
tree_str = tree.to_s
|
||||||
|
|
||||||
# Look for signs of loaded content (not just nav titles)
|
# A loaded channel/playlist view has a large tree (video thumbnails, titles, etc.)
|
||||||
has_content = tree_str.include?('AXImage') ||
|
# Skeleton/loading views are much smaller (< 2000 chars)
|
||||||
tree_str.include?('AXStaticText') && tree_str.length > 2000
|
return true if tree_str.length > 2000
|
||||||
|
|
||||||
return true if has_content
|
|
||||||
|
|
||||||
if Time.now - start_time > timeout
|
if Time.now - start_time > timeout
|
||||||
@axe.screenshot('debug-content-load-timeout')
|
@axe.screenshot('debug-content-load-timeout')
|
||||||
raise "Content did not load after #{timeout} seconds"
|
raise "Content did not load after #{timeout} seconds (tree length: #{tree_str.length})"
|
||||||
end
|
end
|
||||||
|
|
||||||
sleep 1
|
sleep 1
|
||||||
@@ -315,10 +319,25 @@ RSpec.describe 'URL Schemes with Backend', :url_backend do
|
|||||||
|
|
||||||
# Close player if open, then navigate home
|
# Close player if open, then navigate home
|
||||||
def cleanup_after_video
|
def cleanup_after_video
|
||||||
|
# Try closing expanded player
|
||||||
if @player.player_expanded?
|
if @player.player_expanded?
|
||||||
@player.close_player
|
@player.close_player
|
||||||
sleep 0.5
|
sleep 1
|
||||||
|
# Verify it actually closed, retry if needed
|
||||||
|
if @player.player_expanded?
|
||||||
|
@player.close_player
|
||||||
|
sleep 1
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# Dismiss any remaining sheets/modals (e.g. video info overlays)
|
||||||
|
begin
|
||||||
|
@axe.swipe(start_x: 200, start_y: 200, end_x: 200, end_y: 800, duration: 0.3)
|
||||||
|
sleep 0.5
|
||||||
|
rescue UITest::Axe::AxeError
|
||||||
|
# Ignore if swipe fails
|
||||||
|
end
|
||||||
|
|
||||||
navigate_to_home
|
navigate_to_home
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -329,63 +348,55 @@ RSpec.describe 'URL Schemes with Backend', :url_backend do
|
|||||||
|
|
||||||
it 'opens video via yattee://video/{id}' do
|
it 'opens video via yattee://video/{id}' do
|
||||||
open_url('yattee://video/dQw4w9WgXcQ')
|
open_url('yattee://video/dQw4w9WgXcQ')
|
||||||
sleep 3
|
@player.wait_for_player_expanded(timeout: 20)
|
||||||
wait_for_content_loaded
|
|
||||||
@axe.screenshot('url-scheme-video')
|
@axe.screenshot('url-scheme-video')
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'opens channel via yattee://channel/{id}' do
|
it 'opens channel via yattee://channel/{id}' do
|
||||||
open_url('yattee://channel/UC_x5XG1OV2P6uZZ5FSM9Ttw')
|
open_url('yattee://channel/UC_x5XG1OV2P6uZZ5FSM9Ttw')
|
||||||
sleep 3
|
wait_for_content_loaded(timeout: 20)
|
||||||
wait_for_content_loaded
|
|
||||||
@axe.screenshot('url-scheme-channel')
|
@axe.screenshot('url-scheme-channel')
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'opens playlist via yattee://playlist/{id}' do
|
it 'opens playlist via yattee://playlist/{id}' do
|
||||||
open_url('yattee://playlist/PLrAXtmErZgOeiKm4sgNOknGvNjby9efdf')
|
open_url('yattee://playlist/PLrAXtmErZgOeiKm4sgNOknGvNjby9efdf')
|
||||||
sleep 3
|
wait_for_content_loaded(timeout: 20)
|
||||||
wait_for_content_loaded
|
|
||||||
@axe.screenshot('url-scheme-playlist')
|
@axe.screenshot('url-scheme-playlist')
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe 'YouTube URL parsing' do
|
describe 'YouTube URL parsing via yattee://open?url=' do
|
||||||
after(:each) do
|
after(:each) do
|
||||||
cleanup_after_video
|
cleanup_after_video
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'opens video via youtube.com/watch URL' do
|
it 'parses youtube.com/watch URL and opens video' do
|
||||||
open_url('https://www.youtube.com/watch?v=dQw4w9WgXcQ')
|
open_youtube_url('https://www.youtube.com/watch?v=dQw4w9WgXcQ')
|
||||||
sleep 3
|
@player.wait_for_player_expanded(timeout: 20)
|
||||||
wait_for_content_loaded
|
|
||||||
@axe.screenshot('url-scheme-youtube-watch')
|
@axe.screenshot('url-scheme-youtube-watch')
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'opens video via youtu.be short URL' do
|
it 'parses youtu.be short URL and opens video' do
|
||||||
open_url('https://youtu.be/dQw4w9WgXcQ')
|
open_youtube_url('https://youtu.be/dQw4w9WgXcQ')
|
||||||
sleep 3
|
@player.wait_for_player_expanded(timeout: 20)
|
||||||
wait_for_content_loaded
|
|
||||||
@axe.screenshot('url-scheme-youtube-short')
|
@axe.screenshot('url-scheme-youtube-short')
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'opens video via youtube.com/shorts URL' do
|
it 'parses youtube.com/shorts URL and opens video' do
|
||||||
open_url('https://www.youtube.com/shorts/dQw4w9WgXcQ')
|
open_youtube_url('https://www.youtube.com/shorts/dQw4w9WgXcQ')
|
||||||
sleep 3
|
@player.wait_for_player_expanded(timeout: 20)
|
||||||
wait_for_content_loaded
|
|
||||||
@axe.screenshot('url-scheme-youtube-shorts')
|
@axe.screenshot('url-scheme-youtube-shorts')
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'opens playlist via youtube.com/playlist URL' do
|
it 'parses youtube.com/playlist URL and opens playlist' do
|
||||||
open_url('https://www.youtube.com/playlist?list=PLrAXtmErZgOeiKm4sgNOknGvNjby9efdf')
|
open_youtube_url('https://www.youtube.com/playlist?list=PLrAXtmErZgOeiKm4sgNOknGvNjby9efdf')
|
||||||
sleep 3
|
wait_for_content_loaded(timeout: 20)
|
||||||
wait_for_content_loaded
|
|
||||||
@axe.screenshot('url-scheme-youtube-playlist')
|
@axe.screenshot('url-scheme-youtube-playlist')
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'opens channel via youtube.com/@handle URL' do
|
it 'parses youtube.com/@handle URL and opens channel' do
|
||||||
open_url('https://www.youtube.com/@Google')
|
open_youtube_url('https://www.youtube.com/@Google')
|
||||||
sleep 3
|
wait_for_content_loaded(timeout: 20)
|
||||||
wait_for_content_loaded
|
|
||||||
@axe.screenshot('url-scheme-youtube-handle')
|
@axe.screenshot('url-scheme-youtube-handle')
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
Reference in New Issue
Block a user