Skip to content

Commit

Permalink
RUMM-1649 PR comments addressed
Browse files Browse the repository at this point in the history
WebViewScenarioTest uses an actual website to test WebView Tracking feature
  • Loading branch information
buranmert committed Jan 14, 2022
1 parent 347ea1a commit 1d95970
Show file tree
Hide file tree
Showing 4 changed files with 38 additions and 123 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -9,111 +9,13 @@ import WebKit
import Datadog

class WebViewTrackingFixtureViewController: UIViewController, WKNavigationDelegate {
let html = """
<head>
<meta charset="utf-8">
<title>Mobile SDK Detection test page</title>
<link rel="icon" type="image/x-icon" href="./favicon.ico">
<script type="text/javascript">
function show(message) {
const p = document.createElement("p");
p.innerHTML = message;
if (document.body) {
document.body.appendChild(p);
} else {
window.addEventListener("DOMContentLoaded", () =>
document.body.appendChild(p)
);
}
}
function isEventBridgePresent() {
const isPresent = window.DatadogEventBridge;
if (!isPresent) {
show(`window.DatadogEventBridge absent!`);
return false;
}
if (!isViewHostAllowed()) {
show(
`This page does not respect window.DatadogEventBridge.getAllowedWebViewHosts: <br>${window.DatadogEventBridge.getAllowedWebViewHosts()}`
);
return false;
}
return true;
}
function getEventBridge() {
const datadogEventBridge = window.DatadogEventBridge;
return {
getAllowedWebViewHosts() {
try {
return JSON.parse(
window.DatadogEventBridge.getAllowedWebViewHosts()
);
} catch (e) {
show(
`allowWebViewHosts is not a valid json ${window.DatadogEventBridge.getAllowedWebViewHosts()}`
);
}
return [];
},
send(eventType, event) {
const eventStr = JSON.stringify({
eventType,
event,
tags: ["browser_sdk_version:3.6.13"],
});
datadogEventBridge.send(eventStr);
show(
`window.DatadogEventBridge: ${eventType} sent! <br><br>${eventStr}`
);
},
};
}
function sendLog() {
if (!isEventBridgePresent()) {
return;
}
try {
const log = {
date: 1635932927012,
error: { origin: "console" },
message: "console error: error",
session_id: "0110cab4-7471-480e-aa4e-7ce039ced355",
status: "error",
view: {
referrer: "",
url: "https://datadoghq.dev/browser-sdk-test-playground",
},
};
getEventBridge().send("log", log);
} catch (err) {
show(`window.DatadogEventBridge: Could not send ${err}`);
}
}
function isViewHostAllowed() {
return getEventBridge()
.getAllowedWebViewHosts()
.some((o) => o.includes(window.location.hostname));
}
show(
`window.DatadogEventBridge: <br>${JSON.stringify(
window.DatadogEventBridge
)}`
);
</script>
</head>
<body>
<button onclick="sendLog()">Send dummy log</button>
<p>window.DatadogEventBridge: <br>undefined</p></body>
"""

private var webView: WKWebView!

override func viewDidLoad() {
super.viewDidLoad()

let controller = WKUserContentController()
controller.addDatadogMessageHandler(allowedWebViewHosts: ["datadoghq.dev"])
controller.addDatadogMessageHandler(allowedWebViewHosts: ["shopist.io"])
let config = WKWebViewConfiguration()
config.userContentController = controller

Expand All @@ -124,15 +26,9 @@ class WebViewTrackingFixtureViewController: UIViewController, WKNavigationDelega

override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
webView.loadHTMLString(html, baseURL: nil)
}

func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
let js = """
window.sendLog()
"""
webView.evaluateJavaScript(js) { res, err in
assert(err == nil, "JS execution shouldn't return an error")
}
// swiftlint:disable:next force_unwrapping
let request = URLRequest(url: URL(string: "https://shopist.io")!)
webView.load(request)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,28 +8,36 @@ import Foundation
import HTTPServerMock
import XCTest

class WebViewScenarioTest: IntegrationTests, LoggingCommonAsserts {
func testWebViewLoggingScenario() throws {
let loggingServerSession = server.obtainUniqueRecordingSession()
class WebViewScenarioTest: IntegrationTests, RUMCommonAsserts {
func testWebViewRUMEventsScenario() throws {
// Server session recording RUM events send to `HTTPServerMock`.
let rumServerSession = server.obtainUniqueRecordingSession()

let app = ExampleApplication()
app.launchWith(
testScenarioClassName: "WebViewTrackingScenario",
serverConfiguration: HTTPServerMockConfiguration(
logsEndpoint: loggingServerSession.recordingURL
rumEndpoint: rumServerSession.recordingURL
)
)

// Get expected number of `LogMatchers`
let recordedRequests = try loggingServerSession.pullRecordedRequests(timeout: dataDeliveryTimeout) { requests in
try LogMatcher.from(requests: requests).count >= 1
// Get RUM Sessions with expected number of View visits
let recordedRUMRequests = try rumServerSession.pullRecordedRequests(timeout: dataDeliveryTimeout) { requests in
try RUMSessionMatcher.singleSession(from: requests)?.viewVisits.count == 2
}
let logMatchers = try LogMatcher.from(requests: recordedRequests)

// Assert common things
assertLogging(requests: recordedRequests)
assertRUM(requests: recordedRUMRequests)

logMatchers[0].assertStatus(equals: "error")
logMatchers[0].assertMessage(equals: "console error: error")
let session = try XCTUnwrap(RUMSessionMatcher.singleSession(from: recordedRUMRequests))

XCTAssertEqual(session.viewVisits.count, 2)
session.viewVisits[0].viewEvents.forEach { nativeView in
XCTAssertEqual(nativeView.source, .ios)
}
session.viewVisits[1].viewEvents.forEach { browserView in
// ideally `source` should be `.browser`
// but it's not implemented in `browser-sdk` yet
XCTAssertNotEqual(browserView.source, .ios)
}
}
}
15 changes: 13 additions & 2 deletions Tests/DatadogTests/Matchers/RUMEventMatcher.swift
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,19 @@ internal class RUMEventMatcher {
private let jsonDataDecoder = JSONDecoder()

private init(with jsonData: Data) throws {
self.jsonMatcher = JSONDataMatcher(from: try jsonData.toJSONObject())
self.jsonData = jsonData
var json = try jsonData.toJSONObject()

// NOTE: RUMM-1649 WebViewScenarioTest receives lowercase `method` values
if let eventType = json["type"] as? String,
eventType == "resource",
var resource = json["resource"] as? [String: Any],
let method = resource["method"] as? String {
resource["method"] = method.uppercased()
json["resource"] = resource
}

self.jsonMatcher = JSONDataMatcher(from: json)
self.jsonData = try JSONSerialization.data(withJSONObject: json, options: [])
}

// MARK: - Full match
Expand Down
2 changes: 1 addition & 1 deletion Tests/DatadogTests/Matchers/RUMSessionMatcher.swift
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ internal class RUMSessionMatcher {
visit.viewEvents.append(rumEvent)
visit.viewEventMatchers.append(matcher)
if visit.name.isEmpty {
visit.name = rumEvent.view.name!
visit.name = rumEvent.view.name ?? ""
} else if visit.name != rumEvent.view.name {
throw RUMSessionConsistencyException(
description: "The RUM View name: \(rumEvent) is different than other RUM View names for the same `view.id`."
Expand Down

0 comments on commit 1d95970

Please sign in to comment.