Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[NT-1599] Survey Response Bugfix #1346

Merged
merged 1 commit into from
Dec 4, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions Library/ViewModels/SurveyResponseViewModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ public final class SurveyResponseViewModel: SurveyResponseViewModelType {
self.title = self.viewDidLoadProperty.signal
.mapConst(Strings.Survey())

// Required for `WKWebView` bug prior to iOS 14
self.extractFormDataWithJavaScript = surveyResponse
.takeWhen(surveyPostRequest.filter { $0.httpBody == nil })
.map { surveyResponse in
Expand All @@ -123,6 +124,7 @@ public final class SurveyResponseViewModel: SurveyResponseViewModelType {

self.webViewLoadRequest = Signal.merge(
initialRequest,
surveyPostRequest.filter { $0.httpBody != nil }, // iOS 14 and up uses this path
newRequest
)
.map { request in AppEnvironment.current.apiService.preparedRequest(forRequest: request) }
Expand All @@ -141,6 +143,7 @@ public final class SurveyResponseViewModel: SurveyResponseViewModelType {
return self.policyDecisionProperty.value
}

// Required for `WKWebView` bug prior to iOS 14
private let didEvaluateJavaScriptWithResultProperty = MutableProperty<Any?>(nil)
public func didEvaluateJavaScriptWithResult(_ result: Any?) {
self.didEvaluateJavaScriptWithResultProperty.value = result
Expand Down
90 changes: 87 additions & 3 deletions Library/ViewModels/SurveyResponseViewModelTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,91 @@ final class SurveyResponseViewModelTests: TestCase {

XCTAssertEqual(WKNavigationActionPolicy.allow.rawValue, surveyPreparedGetRequestPolicy.rawValue)

// 2. Submit unprepared survey.
// 2. Submit unprepared survey with non-nil body.
var surveyUnpreparedPostRequest = surveyRequest(project: project, prepared: false, method: .POST)
surveyUnpreparedPostRequest.httpBody = "data=data".data(using: .utf8)

let surveyUnpreparedPostRequestNavigationAction = WKNavigationActionData(
navigationType: .formSubmitted,
request: surveyUnpreparedPostRequest,
sourceFrame: WKFrameInfoData(mainFrame: true, request: surveyUnpreparedPostRequest),
targetFrame: WKFrameInfoData(mainFrame: true, request: surveyUnpreparedPostRequest)
)

let surveyUnpreparedPostRequestPolicy = self.vm.inputs.decidePolicyFor(
navigationAction: surveyUnpreparedPostRequestNavigationAction
)

XCTAssertEqual(
WKNavigationActionPolicy.cancel.rawValue, surveyUnpreparedPostRequestPolicy.rawValue,
"Not prepared"
)

self.extractFormDataWithJavaScript.assertDidNotEmitValue()
XCTAssertEqual(self.webViewLoadRequest.values.last?.httpBody, "data=data".data(using: .utf8))

self.webViewLoadRequestIsPrepared.assertValues([true, true])
self.webViewLoadRequest.assertValueCount(2)

// 3. Display success alert.
self.showAlert.assertDidNotEmitValue()

let surveyRedirectGetRequest = surveyRequest(project: project, prepared: false, method: .GET)

let surveyRedirectGetRequestNavigationAction = WKNavigationActionData(
navigationType: .other,
request: surveyRedirectGetRequest,
sourceFrame: WKFrameInfoData(mainFrame: true, request: surveyRedirectGetRequest),
targetFrame: WKFrameInfoData(mainFrame: true, request: surveyRedirectGetRequest)
)

let surveyRedirectGetRequestPolicy = self.vm.inputs.decidePolicyFor(
navigationAction: surveyRedirectGetRequestNavigationAction
)

XCTAssertEqual(
WKNavigationActionPolicy.cancel.rawValue, surveyRedirectGetRequestPolicy.rawValue,
"Intercept redirect to survey"
)

self.showAlert.assertValues([Strings.Got_it_your_survey_response_has_been_submitted()])

// 4. Tap OK on alert, dismiss view controller.
self.dismissViewController.assertDidNotEmitValue()

self.vm.inputs.alertButtonTapped()
self.dismissViewController.assertValueCount(1)
}

func testRespondToSurvey_JavaScript_Workaround_Prior_To_iOS_14() {
let project = Project.template
let surveyResponse = .template
|> SurveyResponse.lens.id .~ 123
|> SurveyResponse.lens.project .~ project

self.vm.inputs.configureWith(surveyResponse: surveyResponse)
self.vm.inputs.viewDidLoad()

// 1. Load survey.
self.webViewLoadRequestIsPrepared.assertValues([true])
self.webViewLoadRequest.assertValueCount(1)

let surveyPreparedGetRequest = surveyRequest(project: project, prepared: true, method: .GET)

let surveyPreparedGetRequestNavigationAction = WKNavigationActionData(
navigationType: .other,
request: surveyPreparedGetRequest,
sourceFrame: WKFrameInfoData(mainFrame: true, request: surveyPreparedGetRequest),
targetFrame: WKFrameInfoData(mainFrame: true, request: surveyPreparedGetRequest)
)

let surveyPreparedGetRequestPolicy = self.vm.inputs.decidePolicyFor(
navigationAction: surveyPreparedGetRequestNavigationAction
)

XCTAssertEqual(WKNavigationActionPolicy.allow.rawValue, surveyPreparedGetRequestPolicy.rawValue)

// 2. Submit unprepared survey with nil body.
let surveyUnpreparedPostRequest = surveyRequest(project: project, prepared: false, method: .POST)

let surveyUnpreparedPostRequestNavigationAction = WKNavigationActionData(
Expand Down Expand Up @@ -137,7 +221,7 @@ final class SurveyResponseViewModelTests: TestCase {

XCTAssertEqual(WKNavigationActionPolicy.allow.rawValue, surveyPreparedPostRequestPolicy.rawValue)

// 3. Display success alert.
// 4. Display success alert.
self.showAlert.assertDidNotEmitValue()

let surveyRedirectGetRequest = surveyRequest(project: project, prepared: false, method: .GET)
Expand All @@ -160,7 +244,7 @@ final class SurveyResponseViewModelTests: TestCase {

self.showAlert.assertValues([Strings.Got_it_your_survey_response_has_been_submitted()])

// 4. Tap OK on alert, dismiss view controller.
// 5. Tap OK on alert, dismiss view controller.
self.dismissViewController.assertDidNotEmitValue()

self.vm.inputs.alertButtonTapped()
Expand Down