ViewInspectorでWebViewのテストを書こうとしてハマったので備忘録。
作成したサンプルコード
どの辺でハマったか。
UIViewControllerに処理を書かないと始まらない。
UIViewController
のviewDidLoad
を実行するには、view.loadViewIfNeeded()
を実行しないと処理が始まらない。
当然ViewInspectorもUIViewControllerを取り出さないと処理が始まらない。
sut.on(\.didAppear) { view in
let uiView = try view.view(WebUIViewControllerRepresentable.self).actualView().viewController()
uiView.loadViewIfNeeded()
}
Viewに書いたdidAppearが機能しなくなる
ContentViewにenvironmentObjectを設定するとdidAppearでエラーが出るようになりました。
struct ContentView: View {
var didAppear: ((Self) -> Void)?
var body: some View {
VStack {
WebUIViewControllerRepresentable()
}
.padding()
}
}
// こう書くとdidAppearが機能しない
var sut = ContentView().environmentObject(param)
// 正しくはこうする
var sut = ContentView()
ViewHosting.host(view: sut.environmentObject(param))
処理の完了通知を受け取りたい
もう少しいい方法あるだろうけど簡易なもので。
// ObservableObjectでVoidを作成
class Param: ObservableObject {
@Published var exception: (String) -> Void = { _ in }
}
// テスト完了通知のクロージャーを作成
let exp = XCTestExpectation(description: "didAppear")
let param = Param()
param.exception = { message in
XCTAssertEqual(message, "complete")
exp.fulfill()
}
// HTMLを読み込んだら完了通知
func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
if isRunningTests() {
parent.param.exception("complete")
}
}
おわりに
以上です。
ViewInspectorでWebViewのサンプルコードを見かけなかったので書いて見ました。
無駄に時間を使う人が減れば幸いです。
追記
UIViewController
をUIViewControllerRepresentable
に統合して最適化したところ、loadViewIfNeeded
を呼ばなくても動作するようになった。
それでいいのか?
コード
ファイル数が少ないので掲載。
小さいコードに構造まとめるの大事ですね。