@@ -38,27 +38,46 @@ struct LinkOpenerTests {
3838 func presentsSafariViewController( ) {
3939 let settings = StubSettingsUseCase ( safariReaderMode: true , openInDefaultBrowser: false )
4040 var capturedPresented : ( UIViewController , SFSafariViewController ) ?
41+ var capturedFactoryInput : ( URL , SFSafariViewController . Configuration ) ?
42+ var stubSafari : StubSafariViewController ?
4143
4244 LinkOpener . setEnvironmentForTesting (
4345 settings: { settings } ,
4446 openURL: { _ in Issue . record ( " Should not open system browser when presenter exists " ) } ,
4547 presenter: { StubPresenter ( ) } ,
4648 presentSafari: { presenter, safari in
4749 capturedPresented = ( presenter, safari)
50+ } ,
51+ safariControllerFactory: { url, configuration in
52+ capturedFactoryInput = ( url, configuration)
53+ let controller = StubSafariViewController ( url: url, configuration: configuration)
54+ stubSafari = controller
55+ return controller
4856 }
4957 )
5058
59+ defer { LinkOpener . resetEnvironment ( ) }
60+
5161 let url = URL ( string: " https://news.ycombinator.com " ) !
5262 LinkOpener . openURL ( url)
5363
54- guard let ( _, safariController) = capturedPresented else {
64+ guard let factoryInput = capturedFactoryInput else {
65+ Issue . record ( " Expected safariControllerFactory to be invoked " )
66+ return
67+ }
68+
69+ #expect( factoryInput. 0 == url)
70+ #expect( factoryInput. 1 . entersReaderIfAvailable)
71+
72+ guard let ( presenter, safariController) = capturedPresented else {
5573 Issue . record ( " Expected Safari to be presented " )
5674 return
5775 }
5876
59- #expect( safariController. initialURL == url)
60- #expect( safariController. resolvedConfiguration. entersReaderIfAvailable)
61- LinkOpener . resetEnvironment ( )
77+ #expect( presenter is StubPresenter )
78+ #expect( safariController === stubSafari)
79+ #expect( stubSafari? . capturedURL == url)
80+ #expect( stubSafari? . capturedConfiguration. entersReaderIfAvailable == true )
6281 }
6382
6483 @MainActor
@@ -121,15 +140,18 @@ private final class StubSettingsUseCase: SettingsUseCase, @unchecked Sendable {
121140
122141private final class StubPresenter : UIViewController { }
123142
124- private extension SFSafariViewController {
125- var initialURL : URL {
126- // SFSafariViewController exposes the initial URL through private API, but we can rely on the
127- // view controller's `value(forKey:)` for testing purposes in the test bundle.
128- value ( forKey: " URL " ) as? URL ?? URL ( string: " about:blank " ) !
143+ private final class StubSafariViewController : SFSafariViewController {
144+ let capturedURL : URL
145+ let capturedConfiguration : SFSafariViewController . Configuration
146+
147+ override init ( url: URL , configuration: SFSafariViewController . Configuration ) {
148+ capturedURL = url
149+ capturedConfiguration = configuration
150+ super. init ( url: url, configuration: configuration)
129151 }
130152
131- var resolvedConfiguration : SFSafariViewController . Configuration {
132- ( value ( forKey : " configuration " ) as? SFSafariViewController . Configuration )
133- ?? SFSafariViewController . Configuration ( )
153+ @ available ( * , unavailable )
154+ override required init ( coder : NSCoder ) {
155+ fatalError ( " init(coder:) has not been implemented " )
134156 }
135157}
0 commit comments