Skip to content

Commit 7fecf9a

Browse files
Update the tests and Demo app to test timed analytics events using UUID event ID's
1 parent 2cc286c commit 7fecf9a

File tree

7 files changed

+280
-52
lines changed

7 files changed

+280
-52
lines changed

MixpanelDemo/MixpanelDemo/TrackingViewController.swift

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,8 @@ class TrackingViewController: UIViewController, UITableViewDelegate, UITableView
1515
var tableViewItems = [
1616
"Track w/o Properties",
1717
"Track w Properties",
18-
"Time Event 5secs",
18+
"Time Event 5secs with name",
19+
"Time Event 5secs with ID",
1920
"Clear Timed Events",
2021
"Get Current SuperProperties",
2122
"Clear SuperProperties",
@@ -57,22 +58,30 @@ class TrackingViewController: UIViewController, UITableViewDelegate, UITableView
5758
Mixpanel.mainInstance().track(event: ev, properties: p)
5859
descStr = "Event: \"\(ev)\"\n Properties: \(p)"
5960
case 2:
60-
let ev = "Timed Event"
61+
let ev = "Timed Event with name"
6162
Mixpanel.mainInstance().time(event: ev)
6263
DispatchQueue.main.asyncAfter(deadline: .now() + 5) {
6364
Mixpanel.mainInstance().track(event: ev)
6465
}
6566
descStr = "Timed Event: \"\(ev)\""
6667
case 3:
68+
let evID = UUID()
69+
let ev = "Timed Event with id"
70+
Mixpanel.mainInstance().time(timedEventID: evID)
71+
DispatchQueue.main.asyncAfter(deadline: .now() + 5) {
72+
Mixpanel.mainInstance().track(event: ev, timedEventID: evID)
73+
}
74+
descStr = "Timed Event: \"\(ev)\""
75+
case 4:
6776
Mixpanel.mainInstance().clearTimedEvents()
6877
descStr = "Timed Events Cleared"
69-
case 4:
78+
case 5:
7079
descStr = "Super Properties:\n"
7180
descStr += "\(Mixpanel.mainInstance().currentSuperProperties())"
72-
case 5:
81+
case 6:
7382
Mixpanel.mainInstance().clearSuperProperties()
7483
descStr = "Cleared Super Properties"
75-
case 6:
84+
case 7:
7685
let p: Properties = [
7786
"Super Property 1": 1,
7887
"Super Property 2": "p2",
@@ -85,15 +94,15 @@ class TrackingViewController: UIViewController, UITableViewDelegate, UITableView
8594
]
8695
Mixpanel.mainInstance().registerSuperProperties(p)
8796
descStr = "Properties: \(p)"
88-
case 7:
97+
case 8:
8998
let p = ["Super Property 1": 2.3]
9099
Mixpanel.mainInstance().registerSuperPropertiesOnce(p)
91100
descStr = "Properties: \(p)"
92-
case 8:
101+
case 9:
93102
let p = ["Super Property 1": 1.2]
94103
Mixpanel.mainInstance().registerSuperPropertiesOnce(p, defaultValue: 2.3)
95104
descStr = "Properties: \(p) with Default Value: 2.3"
96-
case 9:
105+
case 10:
97106
let p = "Super Property 2"
98107
Mixpanel.mainInstance().unregisterSuperProperty(p)
99108
descStr = "Properties: \(p)"

MixpanelDemo/MixpanelDemoMacTests/MixpanelBaseTests.swift

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,10 @@ class MixpanelBaseTests: XCTestCase, MixpanelDelegate {
8989
func randomId() -> String {
9090
return String(format: "%08x%08x", arc4random(), arc4random())
9191
}
92+
93+
func uuid(_ intValue: Int) -> UUID {
94+
return UUID.init(uuidString: "00000000-0000-0000-0000-\(String(format: "%012x", intValue))")!
95+
}
9296

9397
func waitForAsyncTasks() {
9498
var hasCompletedTask = false
@@ -103,20 +107,20 @@ class MixpanelBaseTests: XCTestCase, MixpanelDelegate {
103107
}
104108

105109
func eventQueue(token: String) -> Queue {
106-
return MixpanelPersistence.init(token: token).loadEntitiesInBatch(type: .events)
110+
return MixpanelPersistence.init(instanceName: token).loadEntitiesInBatch(type: .events)
107111
}
108112

109113
func peopleQueue(token: String) -> Queue {
110-
return MixpanelPersistence.init(token: token).loadEntitiesInBatch(type: .people)
114+
return MixpanelPersistence.init(instanceName: token).loadEntitiesInBatch(type: .people)
111115
}
112116

113117
func unIdentifiedPeopleQueue(token: String) -> Queue {
114-
return MixpanelPersistence.init(token: token).loadEntitiesInBatch(
118+
return MixpanelPersistence.init(instanceName: token).loadEntitiesInBatch(
115119
type: .people, flag: PersistenceConstant.unIdentifiedFlag)
116120
}
117121

118122
func groupQueue(token: String) -> Queue {
119-
return MixpanelPersistence.init(token: token).loadEntitiesInBatch(type: .groups)
123+
return MixpanelPersistence.init(instanceName: token).loadEntitiesInBatch(type: .groups)
120124
}
121125

122126
func flushAndWaitForTrackingQueue(_ mixpanel: MixpanelInstance) {

MixpanelDemo/MixpanelDemoMacTests/MixpanelDemoTests.swift

Lines changed: 130 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -131,37 +131,37 @@ class MixpanelDemoTests: MixpanelBaseTests {
131131
removeDBfile(testMixpanel)
132132
}
133133

134-
func testAddEventContainsInvalidJsonObjectDoubleNaN() {
135-
let testMixpanel = Mixpanel.initialize(token: randomId(), flushInterval: 60)
136-
XCTExpectAssert("unsupported property type was allowed") {
137-
testMixpanel.track(event: "bad event", properties: ["BadProp": Double.nan])
138-
}
139-
removeDBfile(testMixpanel)
140-
}
141-
142-
func testAddEventContainsInvalidJsonObjectFloatNaN() {
143-
let testMixpanel = Mixpanel.initialize(token: randomId(), flushInterval: 60)
144-
XCTExpectAssert("unsupported property type was allowed") {
145-
testMixpanel.track(event: "bad event", properties: ["BadProp": Float.nan])
146-
}
147-
removeDBfile(testMixpanel)
148-
}
149-
150-
func testAddEventContainsInvalidJsonObjectDoubleInfinity() {
151-
let testMixpanel = Mixpanel.initialize(token: randomId(), flushInterval: 60)
152-
XCTExpectAssert("unsupported property type was allowed") {
153-
testMixpanel.track(event: "bad event", properties: ["BadProp": Double.infinity])
154-
}
155-
removeDBfile(testMixpanel)
156-
}
157-
158-
func testAddEventContainsInvalidJsonObjectFloatInfinity() {
159-
let testMixpanel = Mixpanel.initialize(token: randomId(), flushInterval: 60)
160-
XCTExpectAssert("unsupported property type was allowed") {
161-
testMixpanel.track(event: "bad event", properties: ["BadProp": Float.infinity])
162-
}
163-
removeDBfile(testMixpanel)
164-
}
134+
func testAddEventContainsInvalidJsonObjectDoubleNaN() {
135+
let testMixpanel = Mixpanel.initialize(token: randomId(), flushInterval: 60)
136+
XCTExpectAssert("unsupported property type was allowed") {
137+
testMixpanel.track(event: "bad event", properties: ["BadProp": Double.nan])
138+
}
139+
removeDBfile(testMixpanel)
140+
}
141+
142+
func testAddEventContainsInvalidJsonObjectFloatNaN() {
143+
let testMixpanel = Mixpanel.initialize(token: randomId(), flushInterval: 60)
144+
XCTExpectAssert("unsupported property type was allowed") {
145+
testMixpanel.track(event: "bad event", properties: ["BadProp": Float.nan])
146+
}
147+
removeDBfile(testMixpanel)
148+
}
149+
150+
func testAddEventContainsInvalidJsonObjectDoubleInfinity() {
151+
let testMixpanel = Mixpanel.initialize(token: randomId(), flushInterval: 60)
152+
XCTExpectAssert("unsupported property type was allowed") {
153+
testMixpanel.track(event: "bad event", properties: ["BadProp": Double.infinity])
154+
}
155+
removeDBfile(testMixpanel)
156+
}
157+
158+
func testAddEventContainsInvalidJsonObjectFloatInfinity() {
159+
let testMixpanel = Mixpanel.initialize(token: randomId(), flushInterval: 60)
160+
XCTExpectAssert("unsupported property type was allowed") {
161+
testMixpanel.track(event: "bad event", properties: ["BadProp": Float.infinity])
162+
}
163+
removeDBfile(testMixpanel)
164+
}
165165

166166
func testAddingEventsAfterFlush() {
167167
let testMixpanel = Mixpanel.initialize(token: randomId(), flushInterval: 60)
@@ -349,24 +349,24 @@ class MixpanelDemoTests: MixpanelBaseTests {
349349
waitForTrackingQueue(testMixpanel)
350350
testMixpanel.createAlias(alias, distinctId: testMixpanel.distinctId)
351351
waitForTrackingQueue(testMixpanel)
352-
var mixpanelIdentity = MixpanelPersistence.loadIdentity(apiToken: testMixpanel.apiToken)
352+
var mixpanelIdentity = MixpanelPersistence.loadIdentity(instanceName: testMixpanel.apiToken)
353353
XCTAssertTrue(
354354
distinctId == mixpanelIdentity.distinctID && distinctId == mixpanelIdentity.peopleDistinctID
355355
&& distinctId == mixpanelIdentity.userId && alias == mixpanelIdentity.alias)
356356
testMixpanel.archive()
357357
waitForTrackingQueue(testMixpanel)
358358
testMixpanel.unarchive()
359359
waitForTrackingQueue(testMixpanel)
360-
mixpanelIdentity = MixpanelPersistence.loadIdentity(apiToken: testMixpanel.apiToken)
360+
mixpanelIdentity = MixpanelPersistence.loadIdentity(instanceName: testMixpanel.apiToken)
361361
XCTAssertTrue(
362362
testMixpanel.distinctId == mixpanelIdentity.distinctID
363363
&& testMixpanel.people.distinctId == mixpanelIdentity.peopleDistinctID
364364
&& testMixpanel.anonymousId == mixpanelIdentity.anonymousId
365365
&& testMixpanel.userId == mixpanelIdentity.userId
366366
&& testMixpanel.alias == mixpanelIdentity.alias)
367-
MixpanelPersistence.deleteMPUserDefaultsData(apiToken: testMixpanel.apiToken)
367+
MixpanelPersistence.deleteMPUserDefaultsData(instanceName: testMixpanel.apiToken)
368368
waitForTrackingQueue(testMixpanel)
369-
mixpanelIdentity = MixpanelPersistence.loadIdentity(apiToken: testMixpanel.apiToken)
369+
mixpanelIdentity = MixpanelPersistence.loadIdentity(instanceName: testMixpanel.apiToken)
370370
XCTAssertTrue(
371371
"" == mixpanelIdentity.distinctID && nil == mixpanelIdentity.peopleDistinctID
372372
&& nil == mixpanelIdentity.anonymousId && nil == mixpanelIdentity.userId
@@ -778,7 +778,7 @@ class MixpanelDemoTests: MixpanelBaseTests {
778778
XCTAssertTrue(
779779
peopleQueue(token: testMixpanel2.apiToken).count == 1, "pending people queue archive failed")
780780
XCTAssertEqual(
781-
testMixpanel2.timedEvents["e2"] as? Int, 5,
781+
testMixpanel2.timedEvents["e2"], 5,
782782
"timedEvents archive failed")
783783
testMixpanel2.mixpanelPersistence.closeDB()
784784
let testMixpanel3 = Mixpanel.initialize(token: testToken, flushInterval: 60)
@@ -848,20 +848,111 @@ class MixpanelDemoTests: MixpanelBaseTests {
848848
testMixpanel.time(event: "Time Event B")
849849
testMixpanel.time(event: "Time Event C")
850850
waitForTrackingQueue(testMixpanel)
851-
var testTimedEvents = MixpanelPersistence.loadTimedEvents(apiToken: testMixpanel.apiToken)
851+
var testTimedEvents = MixpanelPersistence.loadTimedEvents(instanceName: testMixpanel.apiToken)
852852
XCTAssertTrue(
853853
testTimedEvents.count == 3, "Each call to time() should add an event to timedEvents")
854854
XCTAssertNotNil(testTimedEvents["Time Event A"], "Keys in timedEvents should be event names")
855855
testMixpanel.clearTimedEvent(event: "Time Event A")
856856
waitForTrackingQueue(testMixpanel)
857-
testTimedEvents = MixpanelPersistence.loadTimedEvents(apiToken: testMixpanel.apiToken)
857+
testTimedEvents = MixpanelPersistence.loadTimedEvents(instanceName: testMixpanel.apiToken)
858858
XCTAssertNil(testTimedEvents["Time Event A"], "clearTimedEvent should remove key/value pair")
859859
XCTAssertTrue(
860860
testTimedEvents.count == 2, "clearTimedEvent shoud remove only one key/value pair")
861861
testMixpanel.clearTimedEvents()
862862
waitForTrackingQueue(testMixpanel)
863863
XCTAssertTrue(
864-
MixpanelPersistence.loadTimedEvents(apiToken: testMixpanel.apiToken).count == 0,
864+
MixpanelPersistence.loadTimedEvents(instanceName: testMixpanel.apiToken).count == 0,
865+
"clearTimedEvents should remove all key/value pairs")
866+
removeDBfile(testMixpanel)
867+
}
868+
869+
func testEventTimingWithTimedEventID() {
870+
let testMixpanel = Mixpanel.initialize(token: randomId(), flushInterval: 60)
871+
testMixpanel.track(event: "Something Happened")
872+
waitForTrackingQueue(testMixpanel)
873+
var e: InternalProperties = eventQueue(token: testMixpanel.apiToken).last!
874+
var p = e["properties"] as! InternalProperties
875+
XCTAssertNil(p["$duration"], "New events should not be timed.")
876+
let event1UUID = uuid(1)
877+
let event2UUID = uuid(2)
878+
testMixpanel.time(timedEventID: event1UUID)
879+
testMixpanel.track(event: "Event 1", timedEventID: event2UUID)
880+
waitForTrackingQueue(testMixpanel)
881+
e = eventQueue(token: testMixpanel.apiToken).last!
882+
p = e["properties"] as! InternalProperties
883+
XCTAssertNil(p["$duration"], "The exact same timedEventID is required for timing, regardless of name")
884+
testMixpanel.track(event: "Event 1", timedEventID: event1UUID)
885+
waitForTrackingQueue(testMixpanel)
886+
e = eventQueue(token: testMixpanel.apiToken).last!
887+
p = e["properties"] as! InternalProperties
888+
XCTAssertNotNil(p["$duration"], "This event should be timed.")
889+
testMixpanel.track(event: "Event 1", timedEventID: event1UUID)
890+
waitForTrackingQueue(testMixpanel)
891+
e = eventQueue(token: testMixpanel.apiToken).last!
892+
p = e["properties"] as! InternalProperties
893+
XCTAssertNil(
894+
p["$duration"],
895+
"Tracking the same event should require a second call to timeEvent.")
896+
removeDBfile(testMixpanel)
897+
}
898+
899+
func testClearingTimedEventsWithId() {
900+
let testMixpanel = Mixpanel.initialize(token: randomId(), flushInterval: 60)
901+
let event1UUID = uuid(1)
902+
let event2UUID = uuid(2)
903+
testMixpanel.time(timedEventID: event1UUID)
904+
testMixpanel.time(timedEventID: event2UUID)
905+
waitForTrackingQueue(testMixpanel)
906+
var testTimedEvents = MixpanelPersistence.loadTimedEvents(instanceName: testMixpanel.apiToken)
907+
XCTAssertTrue(
908+
testTimedEvents.count == 2, "Each call to time() should add an event to timedEvents")
909+
XCTAssertNotNil(testTimedEvents[event1UUID.uuidString], "Keys in timedEvents should be timedEventID's uuidString")
910+
XCTAssertNotNil(testTimedEvents[event2UUID.uuidString], "Keys in timedEvents should be timedEventID's uuidString")
911+
testMixpanel.clearTimedEvent(timedEventID: event1UUID)
912+
waitForTrackingQueue(testMixpanel)
913+
testTimedEvents = MixpanelPersistence.loadTimedEvents(instanceName: testMixpanel.apiToken)
914+
XCTAssertNil(testTimedEvents[event1UUID.uuidString], "clearTimedEvent should remove key/value pair")
915+
XCTAssertNotNil(testTimedEvents[event2UUID.uuidString], "clearTimedEvent should only remove the correct timedEventID's uuidString")
916+
XCTAssertTrue(
917+
testTimedEvents.count == 1, "clearTimedEvent shoud remove only one key/value pair")
918+
removeDBfile(testMixpanel)
919+
}
920+
921+
func testEventTimingMultipleTimedEventsWithId() {
922+
let testMixpanel = Mixpanel.initialize(token: randomId(), flushInterval: 60)
923+
let event1UUID = uuid(1)
924+
let event2UUID = uuid(2)
925+
let event3UUID = uuid(3)
926+
let event4UUID = uuid(4)
927+
testMixpanel.time(timedEventID: event1UUID)
928+
testMixpanel.time(timedEventID: event2UUID)
929+
testMixpanel.time(timedEventID: event3UUID)
930+
testMixpanel.time(timedEventID: event4UUID)
931+
waitForTrackingQueue(testMixpanel)
932+
var testTimedEvents = MixpanelPersistence.loadTimedEvents(instanceName: testMixpanel.apiToken)
933+
XCTAssertTrue(
934+
testTimedEvents.count == 4, "Each call to time() should add an event to timedEvents")
935+
testMixpanel.track(event: "Recurring Event", timedEventID: event1UUID)
936+
waitForTrackingQueue(testMixpanel)
937+
let event4 = eventQueue(token: testMixpanel.apiToken).last!
938+
let event4Properties = event4["properties"] as! InternalProperties
939+
XCTAssertNotNil(event4Properties["$duration"], "This event should be timed.")
940+
testTimedEvents = MixpanelPersistence.loadTimedEvents(instanceName: testMixpanel.apiToken)
941+
XCTAssertTrue(
942+
testTimedEvents.count == 3, "tracking and event shoud remove only one key/value pair")
943+
testMixpanel.track(event: "Recurring Event", timedEventID: event2UUID)
944+
waitForTrackingQueue(testMixpanel)
945+
let event5 = eventQueue(token: testMixpanel.apiToken).last!
946+
let event5Properties = event5["properties"] as! InternalProperties
947+
XCTAssertNotNil(
948+
event5Properties["$duration"], "This event should be timed. Event though there was another event with the same name.")
949+
testTimedEvents = MixpanelPersistence.loadTimedEvents(instanceName: testMixpanel.apiToken)
950+
XCTAssertTrue(
951+
testTimedEvents.count == 2, "tracking and event shoud remove only one key/value pair")
952+
testMixpanel.clearTimedEvents()
953+
waitForTrackingQueue(testMixpanel)
954+
testTimedEvents = MixpanelPersistence.loadTimedEvents(instanceName: testMixpanel.apiToken)
955+
XCTAssertTrue(testTimedEvents.count == 0,
865956
"clearTimedEvents should remove all key/value pairs")
866957
removeDBfile(testMixpanel)
867958
}

MixpanelDemo/MixpanelDemoMacTests/MixpanelOptOutTests.swift

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -262,6 +262,20 @@ class MixpanelOptOutTests: MixpanelBaseTests {
262262
"When opted out, this event should not be timed.")
263263
removeDBfile(testMixpanel)
264264
}
265+
266+
func testOptOutWilSkipTimeEventWithId() {
267+
let testMixpanel = Mixpanel.initialize(token: randomId(), optOutTrackingByDefault: true)
268+
testMixpanel.optOutTracking()
269+
waitForTrackingQueue(testMixpanel)
270+
let eventUUID = uuid(1)
271+
testMixpanel.time(timedEventID: eventUUID)
272+
testMixpanel.track(event: "400 Meters", timedEventID: eventUUID)
273+
waitForTrackingQueue(testMixpanel)
274+
XCTAssertNil(
275+
eventQueue(token: testMixpanel.apiToken).last,
276+
"When opted out, this event should not be timed.")
277+
removeDBfile(testMixpanel)
278+
}
265279

266280
func testOptOutWillSkipFlushPeople() {
267281
let testMixpanel = Mixpanel.initialize(token: randomId(), optOutTrackingByDefault: true)

MixpanelDemo/MixpanelDemoTests/MixpanelBaseTests.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,10 @@ class MixpanelBaseTests: XCTestCase, MixpanelDelegate {
8484
func randomId() -> String {
8585
return String(format: "%08x%08x", arc4random(), arc4random())
8686
}
87+
88+
func uuid(_ intValue: Int) -> UUID {
89+
return UUID.init(uuidString: "00000000-0000-0000-0000-\(String(format: "%012x", intValue))")!
90+
}
8791

8892
func waitForAsyncTasks() {
8993
var hasCompletedTask = false

0 commit comments

Comments
 (0)