Skip to content

Commit

Permalink
Remove various IUOs, force unwraps, and force casts (#89)
Browse files Browse the repository at this point in the history
  • Loading branch information
mokagio authored Aug 17, 2023
2 parents e4dcfa8 + f6876d0 commit b1db4b0
Show file tree
Hide file tree
Showing 11 changed files with 111 additions and 64 deletions.
4 changes: 4 additions & 0 deletions Demo/ParselyDemo.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

/* Begin PBXBuildFile section */
2A1F02DDE91E502E3B49AFAB /* StorageTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2A1F03819E4FAF1F979D5926 /* StorageTests.swift */; };
3F0B192F2A8DD03B0012C731 /* ParselyTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3F0B192D2A8DCFBC0012C731 /* ParselyTests.swift */; };
3F147F8F29EF8CA100752DFB /* Nimble in Frameworks */ = {isa = PBXBuildFile; productRef = 3F147F8E29EF8CA100752DFB /* Nimble */; };
3F147F9529EF965500752DFB /* ParselyAnalytics in Frameworks */ = {isa = PBXBuildFile; productRef = 3F147F9429EF965500752DFB /* ParselyAnalytics */; };
3F147F9729EF96EE00752DFB /* ParselyAnalytics in Frameworks */ = {isa = PBXBuildFile; productRef = 3F147F9629EF96EE00752DFB /* ParselyAnalytics */; };
Expand Down Expand Up @@ -57,6 +58,7 @@

/* Begin PBXFileReference section */
2A1F03819E4FAF1F979D5926 /* StorageTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StorageTests.swift; sourceTree = "<group>"; };
3F0B192D2A8DCFBC0012C731 /* ParselyTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ParselyTests.swift; sourceTree = "<group>"; };
3F147F9129EF962200752DFB /* AnalyticsSDK-iOS */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = "AnalyticsSDK-iOS"; path = ..; sourceTree = "<group>"; };
3FCAFC8B29E9775A00BC9360 /* UnitTests.xctestplan */ = {isa = PBXFileReference; lastKnownFileType = text; path = UnitTests.xctestplan; sourceTree = "<group>"; };
AA73AAAE2242C1F10089BF1D /* ParselyTestCase.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ParselyTestCase.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -176,6 +178,7 @@
B205889E220CB72A00476E27 /* RequestBuilderTests.swift */,
B2FC40BF221CC43200C70806 /* MetadataTests.swift */,
AA73AAAE2242C1F10089BF1D /* ParselyTestCase.swift */,
3F0B192D2A8DCFBC0012C731 /* ParselyTests.swift */,
3FCAFC8B29E9775A00BC9360 /* UnitTests.xctestplan */,
);
name = Tests;
Expand Down Expand Up @@ -314,6 +317,7 @@
files = (
B2FC40C0221CC43200C70806 /* MetadataTests.swift in Sources */,
F410D63121061D7800DB3EBE /* PixelTests.swift in Sources */,
3F0B192F2A8DD03B0012C731 /* ParselyTests.swift in Sources */,
F4BF866E2190DB4A00BD3867 /* VideoTests.swift in Sources */,
AA73AAAF2242C1F10089BF1D /* ParselyTestCase.swift in Sources */,
F441A55C20F3B8BF009B556E /* EventQueueTests.swift in Sources */,
Expand Down
6 changes: 3 additions & 3 deletions Sources/EngagedTime.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,17 +17,17 @@ class EngagedTime: Sampler {
}
let roundedSecs: Int = Int(data.accumulatedTime)
let totalMs: Int = Int(data.totalTime.milliseconds())
let eventArgs = data.eventArgs!
let eventArgs = data.eventArgs

let event = Heartbeat(
"heartbeat",
url: eventArgs["url"] as! String,
url: eventArgs["url"] as? String ?? "URL_MISSING",
urlref: eventArgs["urlref"] as? String,
inc: roundedSecs,
tt: totalMs,
metadata: eventArgs["metadata"] as? ParselyMetadata,
extra_data: eventArgs["extra_data"] as? Dictionary<String, Any>,
idsite: (eventArgs["idsite"] as! String)
idsite: eventArgs["idsite"] as? String
)

parselyTracker.track.event(event: event)
Expand Down
22 changes: 20 additions & 2 deletions Sources/Event.swift
Original file line number Diff line number Diff line change
Expand Up @@ -105,10 +105,28 @@ class Heartbeat: Event {
var tt: Int
var inc: Int

init(_ action: String, url: String, urlref: String?, inc: Int, tt: Int, metadata: ParselyMetadata?, extra_data: Dictionary<String, Any>?, idsite: String = "") {
init(
_ action: String,
url: String,
urlref: String?,
inc: Int,
tt: Int,
metadata: ParselyMetadata?,
extra_data: Dictionary<String, Any>?,
idsite: String?
) {
self.tt = tt
self.inc = inc
super.init(action, url: url, urlref: urlref, metadata: metadata, extra_data: extra_data, idsite: idsite)

super.init(
action,
url: url,
urlref: urlref,
metadata: metadata,
extra_data: extra_data,
// empty string seems a weird default, but is what we had in the code before this comment was written
idsite: idsite ?? ""
)
}

override func toDict() -> Dictionary<String, Any> {
Expand Down
32 changes: 16 additions & 16 deletions Sources/Metadata.swift
Original file line number Diff line number Diff line change
Expand Up @@ -44,29 +44,29 @@ public class ParselyMetadata {
func toDict() -> Dictionary<String, Any> {
var metas: Dictionary<String, Any> = [:]

if canonical_url != nil {
metas["link"] = canonical_url!
if let canonical_url {
metas["link"] = canonical_url
}
if pub_date != nil {
metas["pub_date"] = String(format:"%i", pub_date!.millisecondsSince1970)
if let pub_date {
metas["pub_date"] = String(format:"%i", pub_date.millisecondsSince1970)
}
if title != nil {
metas["title"] = title!
if let title {
metas["title"] = title
}
if authors != nil {
metas["authors"] = authors!
if let authors {
metas["authors"] = authors
}
if image_url != nil {
metas["image_url"] = image_url!
if let image_url {
metas["image_url"] = image_url
}
if section != nil {
metas["section"] = section!
if let section {
metas["section"] = section
}
if tags != nil {
metas["tags"] = tags!
if let tags {
metas["tags"] = tags
}
if duration != nil {
metas["duration"] = duration!
if let duration {
metas["duration"] = duration
}

return metas
Expand Down
7 changes: 2 additions & 5 deletions Sources/ParselyTracker.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,7 @@ public class Parsely {
public var apikey = ""
public var secondsBetweenHeartbeats: TimeInterval? {
get {
if let secondsBtwnHeartbeats = config["secondsBetweenHeartbeats"] as! TimeInterval? {
return secondsBtwnHeartbeats
}
return nil
config["secondsBetweenHeartbeats"] as? TimeInterval
}
}
public static let sharedInstance = Parsely()
Expand Down Expand Up @@ -232,7 +229,7 @@ public class Parsely {
let events = eventQueue.get()
os_log("Got %s events", log: OSLog.tracker, type:.debug, String(describing: events.count))
let request = RequestBuilder.buildRequest(events: events)
HttpClient.sendRequest(request: request!, queue: eventProcessor) { error in
HttpClient.sendRequest(request: request, queue: eventProcessor) { error in
if let error = error as? URLError, error.code == .notConnectedToInternet {
// When offline, return the events to the queue for the next flush().
self.eventQueue.push(contentsOf: events)
Expand Down
26 changes: 14 additions & 12 deletions Sources/RequestBuilder.swift
Original file line number Diff line number Diff line change
Expand Up @@ -24,25 +24,26 @@ class RequestBuilder {
return platform
}

internal static func getUserAgent() -> String {
if userAgent == nil {
static func getUserAgent() -> String {
guard let userAgent else {
var appDescriptor: String = ""
if let appName = Bundle.main.infoDictionary?["CFBundleName"] as? String {
if let appVersion = Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String {
appDescriptor = String(format: "%@/%@", appName, appVersion)
}
if let appName = Bundle.main.infoDictionary?["CFBundleName"] as? String,
let appVersion = Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String {
appDescriptor = String(format: "%@/%@", appName, appVersion)
}
let osDescriptor = String(format: "iOS/%@", UIDevice.current.systemVersion)
let hardwareString = getHardwareString()
let userAgentString = String(format: "%@ %@ (%@)", appDescriptor, osDescriptor, hardwareString)
// encode the user agent into latin1 in case there are utf8 characters
let userAgentData = Data(userAgentString.utf8)
userAgent = String(data: userAgentData, encoding: .isoLatin1)

return String(data: userAgentData, encoding: .isoLatin1) ?? "invalid user agent"
}
return userAgent!

return userAgent
}

internal static func buildRequest(events: Array<Event>) -> ParselyRequest? {
static func buildRequest(events: Array<Event>) -> ParselyRequest {
let request = ParselyRequest.init(
url: buildPixelEndpoint(),
headers: buildHeadersDict(events: events),
Expand All @@ -52,9 +53,10 @@ class RequestBuilder {
return request
}

internal static func buildPixelEndpoint() -> String {
self._baseURL = "https://p1.parsely.com/mobileproxy"
return self._baseURL!
static func buildPixelEndpoint() -> String {
let endpoint = "https://p1.parsely.com/mobileproxy"
_baseURL = endpoint
return endpoint
}

internal static func buildHeadersDict(events: Array<Event>) -> Dictionary<String, String> {
Expand Down
4 changes: 2 additions & 2 deletions Sources/Sampler.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ struct Accumulator {
var heartbeatTimeout: TimeInterval?
var contentDuration: TimeInterval?
var isEngaged: Bool
var eventArgs: Dictionary<String, Any>?
var eventArgs: Dictionary<String, Any>
}

extension TimeInterval {
Expand Down Expand Up @@ -58,7 +58,7 @@ class Sampler {
func trackKey(
key: String,
contentDuration: TimeInterval?,
eventArgs: Dictionary<String, Any>?,
eventArgs: Dictionary<String, Any> = [:],
resetOnExisting: Bool = false
) -> Void {
os_log("Sampler tracked key: %s in class %@", log: OSLog.tracker, type: .debug, key, String(describing: self))
Expand Down
5 changes: 4 additions & 1 deletion Sources/Session.swift
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,10 @@ class SessionManager {

if session.isEmpty {
var visitorInfo = visitorManager.getVisitorInfo()
visitorInfo["session_count"] = visitorInfo["session_count"] as! Int + 1

if let previousCount = visitorInfo["session_count"] as? Int {
visitorInfo["session_count"] = previousCount + 1
}

session = [:]
session["session_id"] = visitorInfo["session_count"]
Expand Down
7 changes: 2 additions & 5 deletions Sources/Video.swift
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,7 @@ class VideoManager: Sampler {
var trackedVideos: Dictionary<String, TrackedVideo> = [:]

override func sampleFn(key: String) -> Bool {
if trackedVideos[key] == nil {
return false
}
return (trackedVideos[key]?.isPlaying)!
trackedVideos[key]?.isPlaying ?? false
}

override func heartbeatFn(data: Accumulator, enableHeartbeats: Bool) -> Void {
Expand All @@ -42,7 +39,7 @@ class VideoManager: Sampler {
tt: totalMs,
metadata: curVideo.eventArgs["metadata"] as? ParselyMetadata,
extra_data: curVideo.eventArgs["extra_data"] as? Dictionary<String, Any>,
idsite: curVideo.eventArgs["idsite"] as! String
idsite: curVideo.eventArgs["idsite"] as? String
)
parselyTracker.track.event(event: event)
os_log("Sent vheartbeat for video %s", log: OSLog.tracker, type:.debug, data.key)
Expand Down
37 changes: 37 additions & 0 deletions Tests/ParselyTests.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import Nimble
@testable import ParselyAnalytics
import XCTest

class ParselyTests: ParselyTestCase {

func testSecondsBetweenHeartbeatsNilByDefault() {
XCTAssertNil(makePareslyTracker().secondsBetweenHeartbeats)
}

func testSecondsBetweenHeartbeatsNilWhenNotInConfigDict() {
let parsely = makePareslyTracker()
parsely.config = ["key": "value"]

XCTAssertNil(parsely.secondsBetweenHeartbeats)
}

func testSecondsBetweenHeartbeatsNilWhenInConfigDictButNotTimeInterval() {
let parsely = makePareslyTracker()
parsely.config = ["secondsBetweenHeartbeats": "not seconds"]

XCTAssertNil(parsely.secondsBetweenHeartbeats)

// Notice that Int doesn't cast to TimeInterval
let parsely2 = makePareslyTracker()
parsely2.config = ["secondsBetweenHeartbeats": 123]

XCTAssertNil(parsely2.secondsBetweenHeartbeats)
}

func testSecondsBetweenHeartbeatsParsesValueFromConfigDict() {
let parsely = makePareslyTracker()
parsely.config = ["secondsBetweenHeartbeats": 123.0]

XCTAssertEqual(parsely.secondsBetweenHeartbeats, TimeInterval(123))
}
}
25 changes: 7 additions & 18 deletions Tests/RequestBuilderTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -24,18 +24,8 @@ class RequestBuilderTests: XCTestCase {
)]
}

func testEndpoint() {
let endpoint = RequestBuilder.buildPixelEndpoint()
XCTAssert(endpoint != "", "buildPixelEndpoint should return a non-empty string")
}

func testBuildPixelEndpoint() {
var expected: String = "https://p1.parsely.com/mobileproxy"
var actual = RequestBuilder.buildPixelEndpoint()
XCTAssert(actual == expected, "buildPixelEndpoint should return the correct URL for the given date")
expected = "https://p1.parsely.com/mobileproxy"
actual = RequestBuilder.buildPixelEndpoint()
XCTAssert(actual == expected, "buildPixelEndpoint should return the correct URL for the given date")
XCTAssertEqual(RequestBuilder.buildPixelEndpoint(), "https://p1.parsely.com/mobileproxy")
}

func testHeaders() {
Expand All @@ -48,16 +38,15 @@ class RequestBuilderTests: XCTestCase {
func testBuildRequest() {
let events = makeEvents()
let request = RequestBuilder.buildRequest(events: events)
XCTAssertNotNil(request, "buildRequest should return a non-nil value")
XCTAssert(request!.url.contains("https://p1"),
XCTAssert(request.url.contains("https://p1"),
"RequestBuilder.buildRequest should return a request with a valid-looking url attribute")
XCTAssertNotNil(request!.headers,
XCTAssertNotNil(request.headers,
"RequestBuilder.buildRequest should return a request with a non-nil headers attribute")
XCTAssertNotNil(request!.headers["User-Agent"],
XCTAssertNotNil(request.headers["User-Agent"],
"RequestBuilder.buildRequest should return a request with a non-nil User-Agent header")
XCTAssertNotNil(request!.params,
XCTAssertNotNil(request.params,
"RequestBuilder.buildRequest should return a request with a non-nil params attribute")
let actualEvents: Array<Dictionary<String, Any>> = request!.params["events"] as! Array<Dictionary<String, Any>>
let actualEvents: Array<Dictionary<String, Any>> = request.params["events"] as! Array<Dictionary<String, Any>>
XCTAssertEqual(actualEvents.count, events.count,
"RequestBuilder.buildRequest should return a request with an events array containing all " +
"relevant revents")
Expand All @@ -68,7 +57,7 @@ class RequestBuilderTests: XCTestCase {
let request = RequestBuilder.buildRequest(events: events)
var jsonData: Data? = nil
do {
jsonData = try JSONSerialization.data(withJSONObject: request!.params)
jsonData = try JSONSerialization.data(withJSONObject: request.params)
} catch { }
XCTAssertNotNil(jsonData, "Request params should serialize to JSON")
}
Expand Down

0 comments on commit b1db4b0

Please sign in to comment.