-
Notifications
You must be signed in to change notification settings - Fork 6
Expand file tree
/
Copy pathOSIABViewModelTests.swift
More file actions
340 lines (281 loc) · 13.9 KB
/
OSIABViewModelTests.swift
File metadata and controls
340 lines (281 loc) · 13.9 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
import XCTest
import WebKit
@testable import OSInAppBrowserLib
final class OSIABViewModelTests: XCTestCase {
private var url: URL = .init(string: "https://outsystems.com/")!
private var secondURL: URL = .init(string: "https://google.com/")!
// MARK: MediaTypesRequiringUserActionForPlayback Tests
func test_createModel_noMediaTypesRequiringUserActionForPlayback_usesNone() {
XCTAssertEqual(makeSUT(url).webView.configuration.mediaTypesRequiringUserActionForPlayback, [])
}
func test_createModel_withMediaTypesRequiringUserActionForPlayback_usesSpecifiedValue() {
XCTAssertEqual(
makeSUT(url, mediaTypesRequiringUserActionForPlayback: .all).webView.configuration.mediaTypesRequiringUserActionForPlayback,
.all
)
}
// MARK: IgnoresViewportScaleLimits Tests
func test_createModel_noIgnoresViewportScaleLimits_setsToFalse() {
XCTAssertFalse(makeSUT(url).webView.configuration.ignoresViewportScaleLimits)
}
func test_createModel_withIgnoresViewportScaleLimitsEnabled_setsToValueSpecified() {
XCTAssertTrue(makeSUT(url, ignoresViewportScaleLimits: true).webView.configuration.ignoresViewportScaleLimits)
}
// MARK: AllowsInlineMediaPlayback Tests
func test_createModel_noAllowsInlineMediaPlayback_setsToFalse() {
XCTAssertFalse(makeSUT(url).webView.configuration.allowsInlineMediaPlayback)
}
func test_createModel_withAllowsInlineMediaPlaybackEnabled_setsToValueSpecified() {
XCTAssertTrue(makeSUT(url, allowsInlineMediaPlayback: true).webView.configuration.allowsInlineMediaPlayback)
}
// MARK: SurpressesIncrementalRendering Tests
func test_createModel_noSurpressesIncrementalRendering_setsToFalse() {
XCTAssertFalse(makeSUT(url).webView.configuration.suppressesIncrementalRendering)
}
func test_createModel_withSurpressesIncrementalRenderingEnabled_setsToValueSpecified() {
XCTAssertTrue(makeSUT(url, surpressesIncrementalRendering: true).webView.configuration.suppressesIncrementalRendering)
}
// MARK: ScrollViewBounds Tests
func test_createModel_noScrollViewBounds_setsToFalse() {
XCTAssertFalse(makeSUT(url).webView.scrollView.bounces)
}
func test_createModel_withScrollViewBoundsEnabled_setsToValueSpecified() {
XCTAssertTrue(makeSUT(url, scrollViewBounds: true).webView.scrollView.bounces)
}
// MARK: CustomUserAgent Tests
func test_createModel_settingCustomUserAgent_setsToSpecifiedValue() {
let newUserAgent = "New User Agent"
XCTAssertEqual(makeSUT(url, customUserAgent: newUserAgent).webView.customUserAgent, newUserAgent)
}
// MARK: ShowURL Tests
func test_createModel_noShowURL_setsAddressLabel() {
XCTAssertEqual(makeSUT(url).addressLabel, url.absoluteString)
}
func test_createModel_setShowURLToFalse_addressLabelNotSet() {
XCTAssertEqual(makeSUT(url, showURL: false).addressLabel, "")
}
// MARK: ShowToolbar Tests
func test_createModel_noShowToolbar_setsToolbarPositionValue() {
XCTAssertNotNil(makeSUT(url).toolbarPosition)
}
func test_createModel_setsShowToolbarToFalse_toolbarPositionValueShouldBeNil() {
XCTAssertNil(makeSUT(url, showToolbar: false).toolbarPosition)
}
// MARK: ToolbarPosition Tests
func test_createModel_noToolbarPosition_setsToDefault() {
XCTAssertEqual(makeSUT(url).toolbarPosition, OSIABToolbarPosition.defaultValue)
}
func test_createModel_setsToolbarPosition_setsToSpecificValue() {
XCTAssertEqual(makeSUT(url, toolbarPosition: .bottom).toolbarPosition, OSIABToolbarPosition.bottom)
}
// MARK: ShowNavigationButtons Tests
func test_createModel_noShowNavigationButtons_setsToDefault() {
XCTAssertTrue(makeSUT(url).showNavigationButtons)
}
func test_createModel_disablesShowNavigationButtons_setsToFalse() {
XCTAssertFalse(makeSUT(url, showNavigationButtons: false).showNavigationButtons)
}
// MARK: LeftToRight Tests
func test_createModel_noLeftToRighthowNavigationButtons_setsToDefault() {
XCTAssertFalse(makeSUT(url).leftToRight)
}
func test_createModel_enablesLeftToRight_setsToTrue() {
XCTAssertTrue(makeSUT(url, leftToRight: true).leftToRight)
}
// MARK: URL Address Tests
func test_createModel_whenChangingURL_urlAddressIsModified() {
let sut = makeSUT(url)
sut.webView(sut.webView, decidePolicyFor: OSIABNavigationActionStub(secondURL)) { _ in }
XCTAssertEqual(sut.addressLabel, secondURL.absoluteString)
}
func test_createModel_withShowURLSetToFalse_whenChangingURL_urlAddressIsNotSet() {
let sut = makeSUT(url, showURL: false)
sut.webView(sut.webView, decidePolicyFor: OSIABNavigationActionStub(secondURL)) { _ in }
XCTAssertEqual(sut.addressLabel, "")
}
func test_createModel_withShowToolbarSetToFalse_whenChangingURL_urlAddressIsNotSet() {
let sut = makeSUT(url, showToolbar: false)
sut.webView(sut.webView, decidePolicyFor: OSIABNavigationActionStub(secondURL)) { _ in }
XCTAssertEqual(sut.addressLabel, "")
}
// MARK: Load URL Tests
func test_loadURL_webViewShouldUpdate() {
let sut = makeSUT(url)
XCTAssertNil(sut.webView.url)
sut.loadURL()
XCTAssertEqual(sut.webView.url, url)
}
func test_loadURL_withCustomHeaders() {
let mockWebView = MockWKWebView(frame: .zero, configuration: WKWebViewConfiguration())
let sut = makeSUT(url, webView: mockWebView, customHeaders: ["Custom-Header": "Value"])
sut.loadURL()
XCTAssertEqual(mockWebView.lastRequest?.value(forHTTPHeaderField: "Custom-Header"), "Value")
}
// MARK: Close Button Pressed
func test_closeButtonPressed_triggersTheBrowserClosedEvent() {
var closed = false
var isBrowserAlreadyClosed = true
let sut = makeSUT(url, onBrowserClosed: { param in
isBrowserAlreadyClosed = param
closed = true
})
sut.closeButtonPressed()
XCTAssertTrue(closed)
XCTAssertFalse(isBrowserAlreadyClosed)
}
// MARK: Navigation Tests
func test_navigateToNewPage_whenMainDocumentURLDoesNotMatchURL_cancelShouldBeReturned() {
let sut = makeSUT(url)
var resultAction: WKNavigationActionPolicy = .allow
sut.webView(sut.webView, decidePolicyFor: OSIABNavigationActionStub(url, mainDocumentURL: secondURL)) { resultAction = $0 }
XCTAssertEqual(resultAction, .cancel)
}
func test_navigateToMailToScheme_shouldDelegateURL() {
var shouldDelegateURL = false
let mailToURL: URL = .init(string: "mailto://mail@outsystems.com/")!
var resultAction: WKNavigationActionPolicy = .allow
let sut = makeSUT(url, onDelegateURL: { urlToDelegate in
XCTAssertEqual(mailToURL, urlToDelegate)
shouldDelegateURL = true
})
sut.webView(sut.webView, decidePolicyFor: OSIABNavigationActionStub(mailToURL)) { resultAction = $0 }
XCTAssertTrue(shouldDelegateURL)
XCTAssertEqual(resultAction, .cancel)
}
func test_navigateToNewPage_whenTargetFrameIsSet_allowShouldBeReturned() {
var resultAction: WKNavigationActionPolicy = .cancel
let sut = makeSUT(url)
sut.webView(sut.webView, decidePolicyFor: OSIABNavigationActionStub(secondURL, useTargetFrame: true)) { resultAction = $0 }
XCTAssertEqual(resultAction, .allow)
}
func test_navigateToNewPage_onBrowserPageNavigationCompletedEventShouldBeTrigged() {
var result: String? = nil
let expectation = self.expectation(description: "Trigger onBrowserPageNavigationCompleted Event")
let sut = makeSUT(url, onBrowserPageNavigationCompleted: { data in
result = data
expectation.fulfill()
})
sut.webView(sut.webView, didFinish: nil)
sut.webView(sut.webView, didFinish: nil)
waitForExpectations(timeout: 1)
XCTAssertEqual(url.absoluteString, result)
}
// MARK: Browser Page Load Event Tests
func test_navigateToURL_whenFinished_triggerPageLoadEventOnFirstTime() {
var pageLoaded = false
let sut = makeSUT(url, onBrowserPageLoad: { pageLoaded = true })
sut.webView(sut.webView, didFinish: nil)
XCTAssertTrue(pageLoaded)
}
func test_navigateToURLTwice_triggerPageLoadEventIsTriggeredOnlyOnTheFirstTime() {
var pageLoaded = false
let sut = makeSUT(url, onBrowserPageLoad: { pageLoaded = true })
sut.webView(sut.webView, didFinish: nil)
pageLoaded = false
sut.webView(sut.webView, didFinish: nil)
XCTAssertFalse(pageLoaded)
}
// MARK: Failed Navigation Tests
func test_provisionalNavigationToURLFails_errorIsTriggered() {
let sut = makeSUT(url)
sut.webView(sut.webView, didFailProvisionalNavigation: nil, withError: NSError(domain: "testing", code: NSURLErrorUnknown))
XCTAssertNotNil(sut.error)
}
func test_provisionalNavigationToURLFailsDueToCancelling_errorIsNotTriggered() {
let sut = makeSUT(url)
sut.webView(sut.webView, didFailProvisionalNavigation: nil, withError: NSError(domain: "testing", code: NSURLErrorCancelled))
XCTAssertNil(sut.error)
}
func test_navigationToURLFails_errorIsTriggered() {
let sut = makeSUT(url)
sut.webView(sut.webView, didFail: nil, withError: NSError(domain: "testing", code: NSURLErrorUnknown))
XCTAssertNotNil(sut.error)
}
func test_navigationToURLFailsDueToCancelling_errorIsNotTriggered() {
let sut = makeSUT(url)
sut.webView(sut.webView, didFail: nil, withError: NSError(domain: "testing", code: NSURLErrorCancelled))
XCTAssertNil(sut.error)
}
// MARK: Delegate Alert Controller Event Tests
func test_whenOpeningAnAlertPanel_theAlertIsDelegated() {
let alertMessage = "Body"
var alertController: UIAlertController?
let sut = makeSUT(url, onDelegateAlertController: { alertController = $0 })
sut.webView(sut.webView, runJavaScriptAlertPanelWithMessage: alertMessage, initiatedByFrame: .init(), completionHandler: {})
XCTAssertEqual(alertController?.message, alertMessage)
XCTAssertEqual(alertController?.actions.count, 1)
}
func test_whenOpeningAnConfirmPanel_theAlertIsDelegated() {
let alertMessage = "Body"
var alertController: UIAlertController?
let sut = makeSUT(url, onDelegateAlertController: { alertController = $0 })
sut.webView(sut.webView, runJavaScriptConfirmPanelWithMessage: alertMessage, initiatedByFrame: .init()) { _ in }
XCTAssertEqual(alertController?.message, alertMessage)
XCTAssertEqual(alertController?.actions.count, 2)
}
func test_whenOpeningAnTextInputPanel_theAlertIsDelegated() {
let alertMessage = "Body"
let defaultText = "Some random text"
var alertController: UIAlertController?
let sut = makeSUT(url, onDelegateAlertController: { alertController = $0 })
sut.webView(sut.webView, runJavaScriptTextInputPanelWithPrompt: alertMessage, defaultText: defaultText, initiatedByFrame: .init()) { _ in }
XCTAssertEqual(alertController?.message, alertMessage)
XCTAssertEqual(alertController?.actions.count, 2)
XCTAssertEqual(alertController?.textFields?.first?.text, defaultText)
}
}
private extension OSIABViewModelTests {
func makeSUT(
_ url: URL,
webView: WKWebView? = nil,
customHeaders: [String: String]? = nil,
mediaTypesRequiringUserActionForPlayback: WKAudiovisualMediaTypes = [],
ignoresViewportScaleLimits: Bool = false,
allowsInlineMediaPlayback: Bool = false,
surpressesIncrementalRendering: Bool = false,
scrollViewBounds: Bool = false,
customUserAgent: String? = nil,
showURL: Bool = true,
showToolbar: Bool = true,
toolbarPosition: OSIABToolbarPosition = .defaultValue,
showNavigationButtons: Bool = true,
leftToRight: Bool = false,
onDelegateURL: @escaping (URL) -> Void = { _ in },
onDelegateAlertController: @escaping (UIAlertController) -> Void = { _ in },
onBrowserPageLoad: @escaping () -> Void = {},
onBrowserClosed: @escaping (Bool) -> Void = { _ in },
onBrowserPageNavigationCompleted: @escaping (String?) -> Void = { _ in }
) -> OSIABWebViewModel {
let configurationModel = OSIABWebViewConfigurationModel(
mediaTypesRequiringUserActionForPlayback, ignoresViewportScaleLimits, allowsInlineMediaPlayback, surpressesIncrementalRendering
)
return .init(
url: url,
customHeaders: customHeaders,
webView: webView ?? WKWebView(frame: .zero, configuration: configurationModel.toWebViewConfiguration()),
scrollViewBounces: scrollViewBounds,
customUserAgent: customUserAgent,
uiModel: .init(
showURL: showURL,
showToolbar: showToolbar,
toolbarPosition: toolbarPosition,
showNavigationButtons: showNavigationButtons,
leftToRight: leftToRight
),
callbackHandler: .init(
onDelegateURL: onDelegateURL,
onDelegateAlertController: onDelegateAlertController,
onBrowserPageLoad: onBrowserPageLoad,
onBrowserClosed: onBrowserClosed,
onBrowserPageNavigationCompleted: onBrowserPageNavigationCompleted
)
)
}
}
class MockWKWebView: WKWebView {
var lastRequest: URLRequest?
override func load(_ request: URLRequest) -> WKNavigation? {
lastRequest = request
return nil
}
}