Skip to content
Open
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
25 changes: 17 additions & 8 deletions MixpanelDemo/MixpanelDemo/TrackingViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ class TrackingViewController: UIViewController, UITableViewDelegate, UITableView
var tableViewItems = [
"Track w/o Properties",
"Track w Properties",
"Time Event 5secs",
"Time Event 5secs with name",
"Time Event 5secs with ID",
"Clear Timed Events",
"Get Current SuperProperties",
"Clear SuperProperties",
Expand Down Expand Up @@ -57,22 +58,30 @@ class TrackingViewController: UIViewController, UITableViewDelegate, UITableView
Mixpanel.mainInstance().track(event: ev, properties: p)
descStr = "Event: \"\(ev)\"\n Properties: \(p)"
case 2:
let ev = "Timed Event"
let ev = "Timed Event with name"
Mixpanel.mainInstance().time(event: ev)
DispatchQueue.main.asyncAfter(deadline: .now() + 5) {
Mixpanel.mainInstance().track(event: ev)
}
descStr = "Timed Event: \"\(ev)\""
case 3:
let evID = UUID()
let ev = "Timed Event with id"
Mixpanel.mainInstance().time(timedEventID: evID)
DispatchQueue.main.asyncAfter(deadline: .now() + 5) {
Mixpanel.mainInstance().track(event: ev, timedEventID: evID)
}
descStr = "Timed Event: \"\(ev)\""
case 4:
Mixpanel.mainInstance().clearTimedEvents()
descStr = "Timed Events Cleared"
case 4:
case 5:
descStr = "Super Properties:\n"
descStr += "\(Mixpanel.mainInstance().currentSuperProperties())"
case 5:
case 6:
Mixpanel.mainInstance().clearSuperProperties()
descStr = "Cleared Super Properties"
case 6:
case 7:
let p: Properties = [
"Super Property 1": 1,
"Super Property 2": "p2",
Expand All @@ -85,15 +94,15 @@ class TrackingViewController: UIViewController, UITableViewDelegate, UITableView
]
Mixpanel.mainInstance().registerSuperProperties(p)
descStr = "Properties: \(p)"
case 7:
case 8:
let p = ["Super Property 1": 2.3]
Mixpanel.mainInstance().registerSuperPropertiesOnce(p)
descStr = "Properties: \(p)"
case 8:
case 9:
let p = ["Super Property 1": 1.2]
Mixpanel.mainInstance().registerSuperPropertiesOnce(p, defaultValue: 2.3)
descStr = "Properties: \(p) with Default Value: 2.3"
case 9:
case 10:
let p = "Super Property 2"
Mixpanel.mainInstance().unregisterSuperProperty(p)
descStr = "Properties: \(p)"
Expand Down
12 changes: 8 additions & 4 deletions MixpanelDemo/MixpanelDemoMacTests/MixpanelBaseTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,10 @@ class MixpanelBaseTests: XCTestCase, MixpanelDelegate {
func randomId() -> String {
return String(format: "%08x%08x", arc4random(), arc4random())
}

func uuid(_ intValue: Int) -> UUID {
return UUID.init(uuidString: "00000000-0000-0000-0000-\(String(format: "%012x", intValue))")!
}

func waitForAsyncTasks() {
var hasCompletedTask = false
Expand All @@ -103,20 +107,20 @@ class MixpanelBaseTests: XCTestCase, MixpanelDelegate {
}

func eventQueue(token: String) -> Queue {
return MixpanelPersistence.init(token: token).loadEntitiesInBatch(type: .events)
return MixpanelPersistence.init(instanceName: token).loadEntitiesInBatch(type: .events)
}

func peopleQueue(token: String) -> Queue {
return MixpanelPersistence.init(token: token).loadEntitiesInBatch(type: .people)
return MixpanelPersistence.init(instanceName: token).loadEntitiesInBatch(type: .people)
}

func unIdentifiedPeopleQueue(token: String) -> Queue {
return MixpanelPersistence.init(token: token).loadEntitiesInBatch(
return MixpanelPersistence.init(instanceName: token).loadEntitiesInBatch(
type: .people, flag: PersistenceConstant.unIdentifiedFlag)
}

func groupQueue(token: String) -> Queue {
return MixpanelPersistence.init(token: token).loadEntitiesInBatch(type: .groups)
return MixpanelPersistence.init(instanceName: token).loadEntitiesInBatch(type: .groups)
}

func flushAndWaitForTrackingQueue(_ mixpanel: MixpanelInstance) {
Expand Down
169 changes: 130 additions & 39 deletions MixpanelDemo/MixpanelDemoMacTests/MixpanelDemoTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -131,37 +131,37 @@ class MixpanelDemoTests: MixpanelBaseTests {
removeDBfile(testMixpanel)
}

func testAddEventContainsInvalidJsonObjectDoubleNaN() {
let testMixpanel = Mixpanel.initialize(token: randomId(), flushInterval: 60)
XCTExpectAssert("unsupported property type was allowed") {
testMixpanel.track(event: "bad event", properties: ["BadProp": Double.nan])
}
removeDBfile(testMixpanel)
}

func testAddEventContainsInvalidJsonObjectFloatNaN() {
let testMixpanel = Mixpanel.initialize(token: randomId(), flushInterval: 60)
XCTExpectAssert("unsupported property type was allowed") {
testMixpanel.track(event: "bad event", properties: ["BadProp": Float.nan])
}
removeDBfile(testMixpanel)
}

func testAddEventContainsInvalidJsonObjectDoubleInfinity() {
let testMixpanel = Mixpanel.initialize(token: randomId(), flushInterval: 60)
XCTExpectAssert("unsupported property type was allowed") {
testMixpanel.track(event: "bad event", properties: ["BadProp": Double.infinity])
}
removeDBfile(testMixpanel)
}

func testAddEventContainsInvalidJsonObjectFloatInfinity() {
let testMixpanel = Mixpanel.initialize(token: randomId(), flushInterval: 60)
XCTExpectAssert("unsupported property type was allowed") {
testMixpanel.track(event: "bad event", properties: ["BadProp": Float.infinity])
}
removeDBfile(testMixpanel)
}
func testAddEventContainsInvalidJsonObjectDoubleNaN() {
let testMixpanel = Mixpanel.initialize(token: randomId(), flushInterval: 60)
XCTExpectAssert("unsupported property type was allowed") {
testMixpanel.track(event: "bad event", properties: ["BadProp": Double.nan])
}
removeDBfile(testMixpanel)
}

func testAddEventContainsInvalidJsonObjectFloatNaN() {
let testMixpanel = Mixpanel.initialize(token: randomId(), flushInterval: 60)
XCTExpectAssert("unsupported property type was allowed") {
testMixpanel.track(event: "bad event", properties: ["BadProp": Float.nan])
}
removeDBfile(testMixpanel)
}

func testAddEventContainsInvalidJsonObjectDoubleInfinity() {
let testMixpanel = Mixpanel.initialize(token: randomId(), flushInterval: 60)
XCTExpectAssert("unsupported property type was allowed") {
testMixpanel.track(event: "bad event", properties: ["BadProp": Double.infinity])
}
removeDBfile(testMixpanel)
}

func testAddEventContainsInvalidJsonObjectFloatInfinity() {
let testMixpanel = Mixpanel.initialize(token: randomId(), flushInterval: 60)
XCTExpectAssert("unsupported property type was allowed") {
testMixpanel.track(event: "bad event", properties: ["BadProp": Float.infinity])
}
removeDBfile(testMixpanel)
}

func testAddingEventsAfterFlush() {
let testMixpanel = Mixpanel.initialize(token: randomId(), flushInterval: 60)
Expand Down Expand Up @@ -349,24 +349,24 @@ class MixpanelDemoTests: MixpanelBaseTests {
waitForTrackingQueue(testMixpanel)
testMixpanel.createAlias(alias, distinctId: testMixpanel.distinctId)
waitForTrackingQueue(testMixpanel)
var mixpanelIdentity = MixpanelPersistence.loadIdentity(apiToken: testMixpanel.apiToken)
var mixpanelIdentity = MixpanelPersistence.loadIdentity(instanceName: testMixpanel.apiToken)
XCTAssertTrue(
distinctId == mixpanelIdentity.distinctID && distinctId == mixpanelIdentity.peopleDistinctID
&& distinctId == mixpanelIdentity.userId && alias == mixpanelIdentity.alias)
testMixpanel.archive()
waitForTrackingQueue(testMixpanel)
testMixpanel.unarchive()
waitForTrackingQueue(testMixpanel)
mixpanelIdentity = MixpanelPersistence.loadIdentity(apiToken: testMixpanel.apiToken)
mixpanelIdentity = MixpanelPersistence.loadIdentity(instanceName: testMixpanel.apiToken)
XCTAssertTrue(
testMixpanel.distinctId == mixpanelIdentity.distinctID
&& testMixpanel.people.distinctId == mixpanelIdentity.peopleDistinctID
&& testMixpanel.anonymousId == mixpanelIdentity.anonymousId
&& testMixpanel.userId == mixpanelIdentity.userId
&& testMixpanel.alias == mixpanelIdentity.alias)
MixpanelPersistence.deleteMPUserDefaultsData(apiToken: testMixpanel.apiToken)
MixpanelPersistence.deleteMPUserDefaultsData(instanceName: testMixpanel.apiToken)
waitForTrackingQueue(testMixpanel)
mixpanelIdentity = MixpanelPersistence.loadIdentity(apiToken: testMixpanel.apiToken)
mixpanelIdentity = MixpanelPersistence.loadIdentity(instanceName: testMixpanel.apiToken)
XCTAssertTrue(
"" == mixpanelIdentity.distinctID && nil == mixpanelIdentity.peopleDistinctID
&& nil == mixpanelIdentity.anonymousId && nil == mixpanelIdentity.userId
Expand Down Expand Up @@ -778,7 +778,7 @@ class MixpanelDemoTests: MixpanelBaseTests {
XCTAssertTrue(
peopleQueue(token: testMixpanel2.apiToken).count == 1, "pending people queue archive failed")
XCTAssertEqual(
testMixpanel2.timedEvents["e2"] as? Int, 5,
testMixpanel2.timedEvents["e2"], 5,
"timedEvents archive failed")
testMixpanel2.mixpanelPersistence.closeDB()
let testMixpanel3 = Mixpanel.initialize(token: testToken, flushInterval: 60)
Expand Down Expand Up @@ -848,20 +848,111 @@ class MixpanelDemoTests: MixpanelBaseTests {
testMixpanel.time(event: "Time Event B")
testMixpanel.time(event: "Time Event C")
waitForTrackingQueue(testMixpanel)
var testTimedEvents = MixpanelPersistence.loadTimedEvents(apiToken: testMixpanel.apiToken)
var testTimedEvents = MixpanelPersistence.loadTimedEvents(instanceName: testMixpanel.apiToken)
XCTAssertTrue(
testTimedEvents.count == 3, "Each call to time() should add an event to timedEvents")
XCTAssertNotNil(testTimedEvents["Time Event A"], "Keys in timedEvents should be event names")
testMixpanel.clearTimedEvent(event: "Time Event A")
waitForTrackingQueue(testMixpanel)
testTimedEvents = MixpanelPersistence.loadTimedEvents(apiToken: testMixpanel.apiToken)
testTimedEvents = MixpanelPersistence.loadTimedEvents(instanceName: testMixpanel.apiToken)
XCTAssertNil(testTimedEvents["Time Event A"], "clearTimedEvent should remove key/value pair")
XCTAssertTrue(
testTimedEvents.count == 2, "clearTimedEvent shoud remove only one key/value pair")
testMixpanel.clearTimedEvents()
waitForTrackingQueue(testMixpanel)
XCTAssertTrue(
MixpanelPersistence.loadTimedEvents(apiToken: testMixpanel.apiToken).count == 0,
MixpanelPersistence.loadTimedEvents(instanceName: testMixpanel.apiToken).count == 0,
"clearTimedEvents should remove all key/value pairs")
removeDBfile(testMixpanel)
}

func testEventTimingWithTimedEventID() {
let testMixpanel = Mixpanel.initialize(token: randomId(), flushInterval: 60)
testMixpanel.track(event: "Something Happened")
waitForTrackingQueue(testMixpanel)
var e: InternalProperties = eventQueue(token: testMixpanel.apiToken).last!
var p = e["properties"] as! InternalProperties
XCTAssertNil(p["$duration"], "New events should not be timed.")
let event1UUID = uuid(1)
let event2UUID = uuid(2)
testMixpanel.time(timedEventID: event1UUID)
testMixpanel.track(event: "Event 1", timedEventID: event2UUID)
waitForTrackingQueue(testMixpanel)
e = eventQueue(token: testMixpanel.apiToken).last!
p = e["properties"] as! InternalProperties
XCTAssertNil(p["$duration"], "The exact same timedEventID is required for timing, regardless of name")
testMixpanel.track(event: "Event 1", timedEventID: event1UUID)
waitForTrackingQueue(testMixpanel)
e = eventQueue(token: testMixpanel.apiToken).last!
p = e["properties"] as! InternalProperties
XCTAssertNotNil(p["$duration"], "This event should be timed.")
testMixpanel.track(event: "Event 1", timedEventID: event1UUID)
waitForTrackingQueue(testMixpanel)
e = eventQueue(token: testMixpanel.apiToken).last!
p = e["properties"] as! InternalProperties
XCTAssertNil(
p["$duration"],
"Tracking the same event should require a second call to timeEvent.")
removeDBfile(testMixpanel)
}

func testClearingTimedEventsWithId() {
let testMixpanel = Mixpanel.initialize(token: randomId(), flushInterval: 60)
let event1UUID = uuid(1)
let event2UUID = uuid(2)
testMixpanel.time(timedEventID: event1UUID)
testMixpanel.time(timedEventID: event2UUID)
waitForTrackingQueue(testMixpanel)
var testTimedEvents = MixpanelPersistence.loadTimedEvents(instanceName: testMixpanel.apiToken)
XCTAssertTrue(
testTimedEvents.count == 2, "Each call to time() should add an event to timedEvents")
XCTAssertNotNil(testTimedEvents[event1UUID.uuidString], "Keys in timedEvents should be timedEventID's uuidString")
XCTAssertNotNil(testTimedEvents[event2UUID.uuidString], "Keys in timedEvents should be timedEventID's uuidString")
testMixpanel.clearTimedEvent(timedEventID: event1UUID)
waitForTrackingQueue(testMixpanel)
testTimedEvents = MixpanelPersistence.loadTimedEvents(instanceName: testMixpanel.apiToken)
XCTAssertNil(testTimedEvents[event1UUID.uuidString], "clearTimedEvent should remove key/value pair")
XCTAssertNotNil(testTimedEvents[event2UUID.uuidString], "clearTimedEvent should only remove the correct timedEventID's uuidString")
XCTAssertTrue(
testTimedEvents.count == 1, "clearTimedEvent shoud remove only one key/value pair")
removeDBfile(testMixpanel)
}

func testEventTimingMultipleTimedEventsWithId() {
let testMixpanel = Mixpanel.initialize(token: randomId(), flushInterval: 60)
let event1UUID = uuid(1)
let event2UUID = uuid(2)
let event3UUID = uuid(3)
let event4UUID = uuid(4)
testMixpanel.time(timedEventID: event1UUID)
testMixpanel.time(timedEventID: event2UUID)
testMixpanel.time(timedEventID: event3UUID)
testMixpanel.time(timedEventID: event4UUID)
waitForTrackingQueue(testMixpanel)
var testTimedEvents = MixpanelPersistence.loadTimedEvents(instanceName: testMixpanel.apiToken)
XCTAssertTrue(
testTimedEvents.count == 4, "Each call to time() should add an event to timedEvents")
testMixpanel.track(event: "Recurring Event", timedEventID: event1UUID)
waitForTrackingQueue(testMixpanel)
let event4 = eventQueue(token: testMixpanel.apiToken).last!
let event4Properties = event4["properties"] as! InternalProperties
XCTAssertNotNil(event4Properties["$duration"], "This event should be timed.")
testTimedEvents = MixpanelPersistence.loadTimedEvents(instanceName: testMixpanel.apiToken)
XCTAssertTrue(
testTimedEvents.count == 3, "tracking and event shoud remove only one key/value pair")
testMixpanel.track(event: "Recurring Event", timedEventID: event2UUID)
waitForTrackingQueue(testMixpanel)
let event5 = eventQueue(token: testMixpanel.apiToken).last!
let event5Properties = event5["properties"] as! InternalProperties
XCTAssertNotNil(
event5Properties["$duration"], "This event should be timed. Event though there was another event with the same name.")
testTimedEvents = MixpanelPersistence.loadTimedEvents(instanceName: testMixpanel.apiToken)
XCTAssertTrue(
testTimedEvents.count == 2, "tracking and event shoud remove only one key/value pair")
testMixpanel.clearTimedEvents()
waitForTrackingQueue(testMixpanel)
testTimedEvents = MixpanelPersistence.loadTimedEvents(instanceName: testMixpanel.apiToken)
XCTAssertTrue(testTimedEvents.count == 0,
"clearTimedEvents should remove all key/value pairs")
removeDBfile(testMixpanel)
}
Expand Down
14 changes: 14 additions & 0 deletions MixpanelDemo/MixpanelDemoMacTests/MixpanelOptOutTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -262,6 +262,20 @@ class MixpanelOptOutTests: MixpanelBaseTests {
"When opted out, this event should not be timed.")
removeDBfile(testMixpanel)
}

func testOptOutWilSkipTimeEventWithId() {
let testMixpanel = Mixpanel.initialize(token: randomId(), optOutTrackingByDefault: true)
testMixpanel.optOutTracking()
waitForTrackingQueue(testMixpanel)
let eventUUID = uuid(1)
testMixpanel.time(timedEventID: eventUUID)
testMixpanel.track(event: "400 Meters", timedEventID: eventUUID)
waitForTrackingQueue(testMixpanel)
XCTAssertNil(
eventQueue(token: testMixpanel.apiToken).last,
"When opted out, this event should not be timed.")
removeDBfile(testMixpanel)
}

func testOptOutWillSkipFlushPeople() {
let testMixpanel = Mixpanel.initialize(token: randomId(), optOutTrackingByDefault: true)
Expand Down
4 changes: 4 additions & 0 deletions MixpanelDemo/MixpanelDemoTests/MixpanelBaseTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,10 @@ class MixpanelBaseTests: XCTestCase, MixpanelDelegate {
func randomId() -> String {
return String(format: "%08x%08x", arc4random(), arc4random())
}

func uuid(_ intValue: Int) -> UUID {
return UUID.init(uuidString: "00000000-0000-0000-0000-\(String(format: "%012x", intValue))")!
}

func waitForAsyncTasks() {
var hasCompletedTask = false
Expand Down
Loading