mirror of
https://github.com/vector-im/element-ios.git
synced 2024-09-28 15:22:39 +00:00
Analytics | Add support for super properties and appPlatform
This commit is contained in:
parent
fddd6e20a4
commit
a4a73b1a92
9 changed files with 380 additions and 17 deletions
|
@ -41,8 +41,8 @@
|
|||
"kind" : "remoteSourceControl",
|
||||
"location" : "https://github.com/matrix-org/matrix-analytics-events",
|
||||
"state" : {
|
||||
"revision" : "44d5a0e898a71f8abbbe12afe9d73e82d370a9a1",
|
||||
"version" : "0.15.0"
|
||||
"revision" : "de0cac487e5e7f607ee17045882204c91585461f",
|
||||
"version" : "0.23.1"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
|
|
@ -94,6 +94,13 @@ import AnalyticsEvents
|
|||
|
||||
guard let session = session else { return }
|
||||
useAnalyticsSettings(from: session)
|
||||
self.client.updateSuperProperties(
|
||||
AnalyticsEvent.SuperProperties(
|
||||
appPlatform: .EI,
|
||||
cryptoSDK: .Rust,
|
||||
cryptoSDKVersion: session.crypto.version
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
/// Stops analytics tracking and calls `reset` to clear any IDs and event queues.
|
||||
|
@ -148,6 +155,13 @@ import AnalyticsEvents
|
|||
switch result {
|
||||
case .success(let settings):
|
||||
self.identify(with: settings)
|
||||
self.client.updateSuperProperties(
|
||||
AnalyticsEvent.SuperProperties(
|
||||
appPlatform: .EI,
|
||||
cryptoSDK: .Rust,
|
||||
cryptoSDKVersion: session.crypto.version
|
||||
)
|
||||
)
|
||||
self.service = nil
|
||||
case .failure:
|
||||
MXLog.error("[Analytics] Failed to use analytics settings. Will continue to run without analytics ID.")
|
||||
|
@ -242,7 +256,8 @@ extension Analytics {
|
|||
let userProperties = AnalyticsEvent.UserProperties(allChatsActiveFilter: allChatsActiveFilter?.analyticsName,
|
||||
ftueUseCaseSelection: ftueUseCase?.analyticsName,
|
||||
numFavouriteRooms: numFavouriteRooms,
|
||||
numSpaces: numSpaces)
|
||||
numSpaces: numSpaces,
|
||||
recoveryState: nil, verificationState: nil)
|
||||
client.updateUserProperties(userProperties)
|
||||
}
|
||||
|
||||
|
|
|
@ -53,4 +53,11 @@ protocol AnalyticsClientProtocol {
|
|||
/// be a delay when updating user properties as these are cached to be included
|
||||
/// as part of the next event that gets captured.
|
||||
func updateUserProperties(_ userProperties: AnalyticsEvent.UserProperties)
|
||||
|
||||
|
||||
/// Updates the user properties.
|
||||
/// Super properties added to all captured events and screen.
|
||||
/// - Parameter superProperties: The properties event to capture.
|
||||
func updateSuperProperties(_ event: AnalyticsEvent.SuperProperties)
|
||||
|
||||
}
|
||||
|
|
|
@ -19,23 +19,39 @@ import AnalyticsEvents
|
|||
|
||||
/// An analytics client that reports events to a PostHog server.
|
||||
class PostHogAnalyticsClient: AnalyticsClientProtocol {
|
||||
|
||||
private var posthogFactory: PostHogFactory = DefaultPostHogFactory()
|
||||
|
||||
init(posthogFactory: PostHogFactory? = nil) {
|
||||
if let factory = posthogFactory {
|
||||
self.posthogFactory = factory
|
||||
}
|
||||
}
|
||||
|
||||
/// The PHGPostHog object used to report events.
|
||||
private var postHog: PostHogSDK?
|
||||
private var postHog: PostHogProtocol?
|
||||
|
||||
/// Any user properties to be included with the next captured event.
|
||||
private(set) var pendingUserProperties: AnalyticsEvent.UserProperties?
|
||||
|
||||
/// Super Properties are properties associated with events that are set once and then sent with every capture call, be it a $screen, an autocaptured button click, or anything else.
|
||||
/// It is different from user properties that will be attached to the user and not events.
|
||||
/// Not persisted for now, should be set on start.
|
||||
private var superProperties: AnalyticsEvent.SuperProperties?
|
||||
|
||||
static let shared = PostHogAnalyticsClient()
|
||||
|
||||
var isRunning: Bool { postHog != nil && !postHog!.isOptOut() }
|
||||
var isRunning: Bool {
|
||||
guard let postHog else { return false }
|
||||
return !postHog.isOptOut()
|
||||
}
|
||||
|
||||
func start() {
|
||||
// Only start if analytics have been configured in BuildSettings
|
||||
guard let configuration = PostHogConfig.standard else { return }
|
||||
|
||||
if postHog == nil {
|
||||
PostHogSDK.shared.setup(configuration)
|
||||
postHog = PostHogSDK.shared
|
||||
postHog = posthogFactory.createPostHog(config: configuration)
|
||||
}
|
||||
|
||||
postHog?.optIn()
|
||||
|
@ -67,13 +83,13 @@ class PostHogAnalyticsClient: AnalyticsClientProtocol {
|
|||
}
|
||||
|
||||
func capture(_ event: AnalyticsEventProtocol) {
|
||||
postHog?.capture(event.eventName, properties: event.properties, userProperties: pendingUserProperties?.properties.compactMapValues { $0 })
|
||||
postHog?.capture(event.eventName, properties: attachSuperProperties(to: event.properties), userProperties: pendingUserProperties?.properties.compactMapValues { $0 })
|
||||
// Pending user properties have been added
|
||||
self.pendingUserProperties = nil
|
||||
}
|
||||
|
||||
func screen(_ event: AnalyticsScreenProtocol) {
|
||||
postHog?.screen(event.screenName.rawValue, properties: event.properties)
|
||||
postHog?.screen(event.screenName.rawValue, properties: attachSuperProperties(to: event.properties))
|
||||
}
|
||||
|
||||
func updateUserProperties(_ userProperties: AnalyticsEvent.UserProperties) {
|
||||
|
@ -86,9 +102,35 @@ class PostHogAnalyticsClient: AnalyticsClientProtocol {
|
|||
self.pendingUserProperties = AnalyticsEvent.UserProperties(allChatsActiveFilter: userProperties.allChatsActiveFilter ?? pendingUserProperties.allChatsActiveFilter,
|
||||
ftueUseCaseSelection: userProperties.ftueUseCaseSelection ?? pendingUserProperties.ftueUseCaseSelection,
|
||||
numFavouriteRooms: userProperties.numFavouriteRooms ?? pendingUserProperties.numFavouriteRooms,
|
||||
numSpaces: userProperties.numSpaces ?? pendingUserProperties.numSpaces)
|
||||
numSpaces: userProperties.numSpaces ?? pendingUserProperties.numSpaces,
|
||||
// Not yet supported
|
||||
recoveryState: nil, verificationState: nil)
|
||||
}
|
||||
|
||||
func updateSuperProperties(_ updatedProperties: AnalyticsEvent.SuperProperties) {
|
||||
self.superProperties = AnalyticsEvent.SuperProperties(
|
||||
appPlatform: updatedProperties.appPlatform ?? superProperties?.appPlatform,
|
||||
cryptoSDK: updatedProperties.cryptoSDK ?? superProperties?.cryptoSDK,
|
||||
cryptoSDKVersion: updatedProperties.cryptoSDKVersion ?? superProperties?.cryptoSDKVersion
|
||||
)
|
||||
}
|
||||
|
||||
/// Attach super properties to events.
|
||||
/// If the property is already set on the event, the already set value will be kept.
|
||||
private func attachSuperProperties(to properties: [String: Any]) -> [String: Any] {
|
||||
guard isRunning, let superProperties else { return properties }
|
||||
|
||||
var properties = properties
|
||||
|
||||
superProperties.properties.forEach { (key: String, value: Any) in
|
||||
if properties[key] == nil {
|
||||
properties[key] = value
|
||||
}
|
||||
}
|
||||
return properties
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
extension PostHogAnalyticsClient: RemoteFeaturesClientProtocol {
|
||||
|
|
53
Riot/Modules/Analytics/PosthogProtocol.swift
Normal file
53
Riot/Modules/Analytics/PosthogProtocol.swift
Normal file
|
@ -0,0 +1,53 @@
|
|||
//
|
||||
// Copyright 2024 New Vector Ltd
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import PostHog
|
||||
|
||||
protocol PostHogProtocol {
|
||||
func optIn()
|
||||
|
||||
func optOut()
|
||||
|
||||
func reset()
|
||||
|
||||
func flush()
|
||||
|
||||
func capture(_ event: String, properties: [String: Any]?, userProperties: [String: Any]?)
|
||||
|
||||
func screen(_ screenTitle: String, properties: [String: Any]?)
|
||||
|
||||
func isFeatureEnabled(_ feature: String) -> Bool
|
||||
|
||||
func identify(_ distinctId: String)
|
||||
|
||||
func identify(_ distinctId: String, userProperties: [String: Any]?)
|
||||
|
||||
func isOptOut() -> Bool
|
||||
}
|
||||
|
||||
protocol PostHogFactory {
|
||||
func createPostHog(config: PostHogConfig) -> PostHogProtocol
|
||||
}
|
||||
|
||||
class DefaultPostHogFactory: PostHogFactory {
|
||||
func createPostHog(config: PostHogConfig) -> PostHogProtocol {
|
||||
PostHogSDK.shared.setup(config)
|
||||
return PostHogSDK.shared
|
||||
}
|
||||
}
|
||||
|
||||
extension PostHogSDK: PostHogProtocol { }
|
|
@ -78,7 +78,7 @@ class AnalyticsTests: XCTestCase {
|
|||
XCTAssertNil(client.pendingUserProperties, "No user properties should have been set yet.")
|
||||
|
||||
// When updating the user properties
|
||||
client.updateUserProperties(AnalyticsEvent.UserProperties(allChatsActiveFilter: nil, ftueUseCaseSelection: .PersonalMessaging, numFavouriteRooms: 4, numSpaces: 5))
|
||||
client.updateUserProperties(AnalyticsEvent.UserProperties(allChatsActiveFilter: nil, ftueUseCaseSelection: .PersonalMessaging, numFavouriteRooms: 4, numSpaces: 5, recoveryState: nil, verificationState: nil))
|
||||
|
||||
// Then the properties should be cached
|
||||
XCTAssertNotNil(client.pendingUserProperties, "The user properties should be cached.")
|
||||
|
@ -90,7 +90,7 @@ class AnalyticsTests: XCTestCase {
|
|||
func testMergingUserProperties() {
|
||||
// Given a client with a cached use case user properties
|
||||
let client = PostHogAnalyticsClient()
|
||||
client.updateUserProperties(AnalyticsEvent.UserProperties(allChatsActiveFilter: nil, ftueUseCaseSelection: .PersonalMessaging, numFavouriteRooms: nil, numSpaces: nil))
|
||||
client.updateUserProperties(AnalyticsEvent.UserProperties(allChatsActiveFilter: nil, ftueUseCaseSelection: .PersonalMessaging, numFavouriteRooms: nil, numSpaces: nil, recoveryState: nil, verificationState: nil))
|
||||
|
||||
XCTAssertNotNil(client.pendingUserProperties, "The user properties should be cached.")
|
||||
XCTAssertEqual(client.pendingUserProperties?.ftueUseCaseSelection, .PersonalMessaging, "The use case selection should match.")
|
||||
|
@ -98,7 +98,7 @@ class AnalyticsTests: XCTestCase {
|
|||
XCTAssertNil(client.pendingUserProperties?.numSpaces, "The number of spaces should not be set.")
|
||||
|
||||
// When updating the number of spaces
|
||||
client.updateUserProperties(AnalyticsEvent.UserProperties(allChatsActiveFilter: nil, ftueUseCaseSelection: nil, numFavouriteRooms: 4, numSpaces: 5))
|
||||
client.updateUserProperties(AnalyticsEvent.UserProperties(allChatsActiveFilter: nil, ftueUseCaseSelection: nil, numFavouriteRooms: 4, numSpaces: 5, recoveryState: nil, verificationState: nil))
|
||||
|
||||
// Then the new properties should be updated and the existing properties should remain unchanged
|
||||
XCTAssertNotNil(client.pendingUserProperties, "The user properties should be cached.")
|
||||
|
@ -107,7 +107,7 @@ class AnalyticsTests: XCTestCase {
|
|||
XCTAssertEqual(client.pendingUserProperties?.numSpaces, 5, "The number of spaces should have been updated.")
|
||||
|
||||
// When updating the number of spaces
|
||||
client.updateUserProperties(AnalyticsEvent.UserProperties(allChatsActiveFilter: .Favourites, ftueUseCaseSelection: nil, numFavouriteRooms: nil, numSpaces: nil))
|
||||
client.updateUserProperties(AnalyticsEvent.UserProperties(allChatsActiveFilter: .Favourites, ftueUseCaseSelection: nil, numFavouriteRooms: nil, numSpaces: nil, recoveryState: nil, verificationState: nil))
|
||||
|
||||
// Then the new properties should be updated and the existing properties should remain unchanged
|
||||
XCTAssertNotNil(client.pendingUserProperties, "The user properties should be cached.")
|
||||
|
@ -120,7 +120,7 @@ class AnalyticsTests: XCTestCase {
|
|||
func testSendingUserProperties() {
|
||||
// Given a client with user properties set
|
||||
let client = PostHogAnalyticsClient()
|
||||
client.updateUserProperties(AnalyticsEvent.UserProperties(allChatsActiveFilter: nil, ftueUseCaseSelection: .PersonalMessaging, numFavouriteRooms: nil, numSpaces: nil))
|
||||
client.updateUserProperties(AnalyticsEvent.UserProperties(allChatsActiveFilter: nil, ftueUseCaseSelection: .PersonalMessaging, numFavouriteRooms: nil, numSpaces: nil, recoveryState: nil, verificationState: nil))
|
||||
client.start()
|
||||
|
||||
XCTAssertNotNil(client.pendingUserProperties, "The user properties should be cached.")
|
||||
|
@ -137,7 +137,7 @@ class AnalyticsTests: XCTestCase {
|
|||
func testSendingUserPropertiesWithIdentify() {
|
||||
// Given a client with user properties set
|
||||
let client = PostHogAnalyticsClient()
|
||||
client.updateUserProperties(AnalyticsEvent.UserProperties(allChatsActiveFilter: nil, ftueUseCaseSelection: .PersonalMessaging, numFavouriteRooms: nil, numSpaces: nil))
|
||||
client.updateUserProperties(AnalyticsEvent.UserProperties(allChatsActiveFilter: nil, ftueUseCaseSelection: .PersonalMessaging, numFavouriteRooms: nil, numSpaces: nil, recoveryState: nil, verificationState: nil))
|
||||
client.start()
|
||||
|
||||
XCTAssertNotNil(client.pendingUserProperties, "The user properties should be cached.")
|
||||
|
|
|
@ -15,6 +15,8 @@
|
|||
//
|
||||
|
||||
import Foundation
|
||||
import PostHog
|
||||
@testable import Element
|
||||
|
||||
|
||||
class FakeEvent: MXEvent {
|
||||
|
@ -346,3 +348,134 @@ class FakeKeyVerificationManager: NSObject, MXKeyVerificationManager {
|
|||
}
|
||||
|
||||
}
|
||||
|
||||
class MockPostHog: PostHogProtocol {
|
||||
|
||||
private var enabled = false
|
||||
|
||||
func optIn() {
|
||||
enabled = true
|
||||
}
|
||||
|
||||
func optOut() {
|
||||
enabled = false
|
||||
}
|
||||
|
||||
func reset() {
|
||||
|
||||
}
|
||||
|
||||
func flush() {
|
||||
|
||||
}
|
||||
|
||||
var capturePropertiesUserPropertiesUnderlyingCallsCount = 0
|
||||
var capturePropertiesUserPropertiesCallsCount: Int {
|
||||
get {
|
||||
if Thread.isMainThread {
|
||||
return capturePropertiesUserPropertiesUnderlyingCallsCount
|
||||
} else {
|
||||
var returnValue: Int? = nil
|
||||
DispatchQueue.main.sync {
|
||||
returnValue = capturePropertiesUserPropertiesUnderlyingCallsCount
|
||||
}
|
||||
|
||||
return returnValue!
|
||||
}
|
||||
}
|
||||
set {
|
||||
if Thread.isMainThread {
|
||||
capturePropertiesUserPropertiesUnderlyingCallsCount = newValue
|
||||
} else {
|
||||
DispatchQueue.main.sync {
|
||||
capturePropertiesUserPropertiesUnderlyingCallsCount = newValue
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
var capturePropertiesUserPropertiesCalled: Bool {
|
||||
return capturePropertiesUserPropertiesCallsCount > 0
|
||||
}
|
||||
var capturePropertiesUserPropertiesReceivedArguments: (event: String, properties: [String: Any]?, userProperties: [String: Any]?)?
|
||||
var capturePropertiesUserPropertiesReceivedInvocations: [(event: String, properties: [String: Any]?, userProperties: [String: Any]?)] = []
|
||||
var capturePropertiesUserPropertiesClosure: ((String, [String: Any]?, [String: Any]?) -> Void)?
|
||||
|
||||
func capture(_ event: String, properties: [String: Any]?, userProperties: [String: Any]?) {
|
||||
if !enabled { return }
|
||||
capturePropertiesUserPropertiesCallsCount += 1
|
||||
capturePropertiesUserPropertiesReceivedArguments = (event: event, properties: properties, userProperties: userProperties)
|
||||
capturePropertiesUserPropertiesReceivedInvocations.append((event: event, properties: properties, userProperties: userProperties))
|
||||
capturePropertiesUserPropertiesClosure?(event, properties, userProperties)
|
||||
}
|
||||
|
||||
var screenPropertiesUnderlyingCallsCount = 0
|
||||
var screenPropertiesCallsCount: Int {
|
||||
get {
|
||||
if Thread.isMainThread {
|
||||
return screenPropertiesUnderlyingCallsCount
|
||||
} else {
|
||||
var returnValue: Int? = nil
|
||||
DispatchQueue.main.sync {
|
||||
returnValue = screenPropertiesUnderlyingCallsCount
|
||||
}
|
||||
|
||||
return returnValue!
|
||||
}
|
||||
}
|
||||
set {
|
||||
if Thread.isMainThread {
|
||||
screenPropertiesUnderlyingCallsCount = newValue
|
||||
} else {
|
||||
DispatchQueue.main.sync {
|
||||
screenPropertiesUnderlyingCallsCount = newValue
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var screenPropertiesCalled: Bool {
|
||||
return screenPropertiesCallsCount > 0
|
||||
}
|
||||
var screenPropertiesReceivedArguments: (screenTitle: String, properties: [String: Any]?)?
|
||||
var screenPropertiesReceivedInvocations: [(screenTitle: String, properties: [String: Any]?)] = []
|
||||
var screenPropertiesClosure: ((String, [String: Any]?) -> Void)?
|
||||
|
||||
func screen(_ screenTitle: String, properties: [String: Any]?) {
|
||||
if !enabled { return }
|
||||
screenPropertiesCallsCount += 1
|
||||
screenPropertiesReceivedArguments = (screenTitle: screenTitle, properties: properties)
|
||||
screenPropertiesReceivedInvocations.append((screenTitle: screenTitle, properties: properties))
|
||||
screenPropertiesClosure?(screenTitle, properties)
|
||||
}
|
||||
|
||||
func isFeatureEnabled(_ feature: String) -> Bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func identify(_ distinctId: String) {
|
||||
|
||||
}
|
||||
|
||||
func identify(_ distinctId: String, userProperties: [String : Any]?) {
|
||||
|
||||
}
|
||||
|
||||
func isOptOut() -> Bool {
|
||||
!enabled
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
class MockPostHogFactory: PostHogFactory {
|
||||
var mock: PostHogProtocol!
|
||||
|
||||
init(mock: PostHogProtocol) {
|
||||
self.mock = mock
|
||||
}
|
||||
|
||||
func createPostHog(config: PostHogConfig) -> PostHogProtocol {
|
||||
mock
|
||||
}
|
||||
}
|
||||
|
||||
|
|
113
RiotTests/PostHogAnalyticsClientTests.swift
Normal file
113
RiotTests/PostHogAnalyticsClientTests.swift
Normal file
|
@ -0,0 +1,113 @@
|
|||
//
|
||||
// Copyright 2024 New Vector Ltd
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
import XCTest
|
||||
@testable import Element
|
||||
import AnalyticsEvents
|
||||
|
||||
class PostHogAnalyticsClientTests: XCTestCase {
|
||||
|
||||
private var posthogMock: MockPostHog!
|
||||
|
||||
override func setUp() {
|
||||
posthogMock = MockPostHog()
|
||||
}
|
||||
|
||||
func testSuperPropertiesAddedToAllCaptured() {
|
||||
let analyticsClient = PostHogAnalyticsClient(posthogFactory: MockPostHogFactory(mock: posthogMock))
|
||||
analyticsClient.start()
|
||||
|
||||
let superProperties = AnalyticsEvent.SuperProperties(appPlatform: .EI, cryptoSDK: .Rust, cryptoSDKVersion: "0.0")
|
||||
|
||||
analyticsClient.updateSuperProperties(superProperties)
|
||||
// It should be the same for any event
|
||||
let someEvent = AnalyticsEvent.CallEnded(durationMs: 0, isVideo: false, numParticipants: 1, placed: true)
|
||||
analyticsClient.capture(someEvent)
|
||||
|
||||
let capturedEvent = posthogMock.capturePropertiesUserPropertiesReceivedArguments
|
||||
|
||||
// All the super properties should have been added
|
||||
XCTAssertEqual(capturedEvent?.properties?["cryptoSDK"] as? String, AnalyticsEvent.SuperProperties.CryptoSDK.Rust.rawValue)
|
||||
XCTAssertEqual(capturedEvent?.properties?["appPlatform"] as? String, AnalyticsEvent.SuperProperties.AppPlatform.EI.rawValue)
|
||||
XCTAssertEqual(capturedEvent?.properties?["cryptoSDKVersion"] as? String, "0.0")
|
||||
|
||||
// Other properties should be there
|
||||
XCTAssertEqual(capturedEvent?.properties?["isVideo"] as? Bool, false)
|
||||
|
||||
// Should also work for screens
|
||||
|
||||
analyticsClient.screen(AnalyticsEvent.MobileScreen.init(durationMs: 0, screenName: .Home))
|
||||
|
||||
|
||||
let capturedScreen = posthogMock.screenPropertiesReceivedArguments
|
||||
|
||||
|
||||
XCTAssertEqual(capturedScreen?.properties?["cryptoSDK"] as? String, AnalyticsEvent.SuperProperties.CryptoSDK.Rust.rawValue)
|
||||
XCTAssertEqual(capturedScreen?.properties?["appPlatform"] as? String, AnalyticsEvent.SuperProperties.AppPlatform.EI.rawValue)
|
||||
XCTAssertEqual(capturedScreen?.properties?["cryptoSDKVersion"] as? String, "0.0")
|
||||
|
||||
|
||||
XCTAssertEqual(capturedScreen?.screenTitle, AnalyticsEvent.MobileScreen.ScreenName.Home.rawValue)
|
||||
|
||||
|
||||
}
|
||||
|
||||
func testSuperPropertiesCanBeUdpated() {
|
||||
let analyticsClient = PostHogAnalyticsClient(posthogFactory: MockPostHogFactory(mock: posthogMock))
|
||||
analyticsClient.start()
|
||||
|
||||
let superProperties = AnalyticsEvent.SuperProperties(appPlatform: .EI, cryptoSDK: .Rust, cryptoSDKVersion: "0.0")
|
||||
|
||||
analyticsClient.updateSuperProperties(superProperties)
|
||||
// It should be the same for any event
|
||||
let someEvent = AnalyticsEvent.CallEnded(durationMs: 0, isVideo: false, numParticipants: 1, placed: true)
|
||||
analyticsClient.capture(someEvent)
|
||||
|
||||
let capturedEvent = posthogMock.capturePropertiesUserPropertiesReceivedArguments
|
||||
|
||||
//
|
||||
XCTAssertEqual(capturedEvent?.properties?["cryptoSDKVersion"] as? String, "0.0")
|
||||
|
||||
analyticsClient.updateSuperProperties(AnalyticsEvent.SuperProperties(appPlatform: .EI, cryptoSDK: .Rust, cryptoSDKVersion: "1.0"))
|
||||
|
||||
|
||||
analyticsClient.capture(someEvent)
|
||||
|
||||
let secondCapturedEvent = posthogMock.capturePropertiesUserPropertiesReceivedArguments
|
||||
|
||||
XCTAssertEqual(secondCapturedEvent?.properties?["cryptoSDKVersion"] as? String, "1.0")
|
||||
}
|
||||
|
||||
func testSuperPropertiesDontOverrideEventProperties() {
|
||||
let analyticsClient = PostHogAnalyticsClient(posthogFactory: MockPostHogFactory(mock: posthogMock))
|
||||
analyticsClient.start()
|
||||
|
||||
// Super property for cryptoSDK is rust
|
||||
let superProperties = AnalyticsEvent.SuperProperties(appPlatform: nil, cryptoSDK: .Rust, cryptoSDKVersion: nil)
|
||||
|
||||
analyticsClient.updateSuperProperties(superProperties)
|
||||
|
||||
// This event as a similar named property `cryptoSDK` with Legacy value
|
||||
let someEvent = AnalyticsEvent.Error(context: nil, cryptoModule: nil, cryptoSDK: .Legacy, domain: .E2EE, eventLocalAgeMillis: nil, isFederated: nil, isMatrixDotOrg: nil, name: .OlmKeysNotSentError, timeToDecryptMillis: nil, userTrustsOwnIdentity: nil, wasVisibleToUser: nil)
|
||||
|
||||
analyticsClient.capture(someEvent)
|
||||
|
||||
let capturedEvent = posthogMock.capturePropertiesUserPropertiesReceivedArguments
|
||||
|
||||
XCTAssertEqual(capturedEvent?.properties?["cryptoSDK"] as? String, AnalyticsEvent.Error.CryptoSDK.Legacy.rawValue)
|
||||
}
|
||||
|
||||
}
|
|
@ -45,7 +45,7 @@ include:
|
|||
packages:
|
||||
AnalyticsEvents:
|
||||
url: https://github.com/matrix-org/matrix-analytics-events
|
||||
exactVersion: 0.15.0
|
||||
exactVersion: 0.23.1
|
||||
Mapbox:
|
||||
url: https://github.com/maplibre/maplibre-gl-native-distribution
|
||||
minVersion: 5.12.2
|
||||
|
|
Loading…
Reference in a new issue