Skip to content

Commit

Permalink
feat(session): add session stop implementation
Browse files Browse the repository at this point in the history
SUITEDEV-35464

Co-authored-by: davidSchuppa <[email protected]>
Co-authored-by: megamegax <[email protected]>
  • Loading branch information
3 people committed Apr 3, 2024
1 parent 23cded8 commit dfb1b96
Show file tree
Hide file tree
Showing 3 changed files with 84 additions and 14 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,14 @@ import mimic
@SdkActor
final class MobileEngageSessionTests: EmarsysTestCase {
let testUuid = "testUuid"
let testDate = Date()
var testDate: Date!
var testEndDate: Date!

@Inject(\.sessionContext)
var fakeSessionContext: SessionContext
var sessionContext: SessionContext

@Inject(\.sdkContext)
var fakeSdkContext: SdkContext
var sdkContext: SdkContext

@Inject(\.timestampProvider)
var fakeTimestampProvider: FakeTimestampProvider
Expand All @@ -38,16 +39,19 @@ final class MobileEngageSessionTests: EmarsysTestCase {


override func setUpWithError() throws {
testDate = Date()
testEndDate = testDate.addingTimeInterval(TimeInterval(300))

fakeEventClient.when(\.fnSendEvents).thenReturn(EventResponse(message: nil, onEventAction: nil, deviceEventState: nil))
fakeUuidProvider.when(\.fnProvide).thenReturn(testUuid)
fakeTimestampProvider.when(\.fnProvide).thenReturn(testDate)

self.fakeSessionContext.contactToken = "testContactToken"
self.sessionContext.contactToken = "testContactToken"
let testConfig = EmarsysConfig(applicationCode: "testApplicationCode")
self.fakeSdkContext.config = testConfig
self.sdkContext.config = testConfig

self.session = MobileEngageSession(sessionContext: self.fakeSessionContext,
sdkContext: self.fakeSdkContext,
self.session = MobileEngageSession(sessionContext: self.sessionContext,
sdkContext: self.sdkContext,
timestampProvider: self.fakeTimestampProvider,
uuidProvider: self.fakeUuidProvider,
eventClient: self.fakeEventClient,
Expand All @@ -67,21 +71,21 @@ final class MobileEngageSessionTests: EmarsysTestCase {

await self.session.start()

XCTAssertNil(self.fakeSessionContext.sessionId)
XCTAssertNil(self.sessionContext.sessionId)
XCTAssertNil(self.session.sessionStartTime)
}

func testStart_shouldNotSendEvent_whenApplicationCode_isNil() async throws {
let testConfig = EmarsysConfig()
self.fakeSdkContext.config = testConfig
self.sdkContext.config = testConfig

await self.session.start()

_ = try fakeEventClient.verify(\.fnSendEvents).times(times: .eq(0))
}

func testStart_shouldNotSendEvent_contactToken_isNil() async throws {
self.fakeSessionContext.contactToken = nil
self.sessionContext.contactToken = nil

await self.session.start()

Expand All @@ -91,7 +95,7 @@ final class MobileEngageSessionTests: EmarsysTestCase {
func testStart_shouldSet_sessionId_onSessionContext() async {
await self.session.start()

XCTAssertEqual(self.fakeSessionContext.sessionId, testUuid)
XCTAssertEqual(self.sessionContext.sessionId, testUuid)
}

func testStart_shouldSet_sessionStartTime() async {
Expand All @@ -100,4 +104,49 @@ final class MobileEngageSessionTests: EmarsysTestCase {
XCTAssertEqual(self.session.sessionStartTime, self.testDate)
}

func testStop_shouldSendInternalCustomEvent_andResetSessionId() async throws {
self.session.sessionStartTime = testDate
self.sessionContext.sessionId = testUuid
let expectedAttribute = ["duration":"300000"]

fakeTimestampProvider.when(\.fnProvide).thenReturn(testEndDate)

await self.session.stop()

_ = try fakeEventClient.verify(\.fnSendEvents).wasCalled(Arg.eq("session:stop"), Arg.eq(expectedAttribute), Arg.eq(EventType.internalEvent))
XCTAssertNil(self.sessionContext.sessionId)
}

func testStop_shouldNotSendInternalCustomEvent_whenSessionWasNotStartedBefore() async throws {
self.session.sessionStartTime = nil

fakeTimestampProvider.when(\.fnProvide).thenReturn(testEndDate)

await self.session.stop()

_ = try fakeEventClient.verify(\.fnSendEvents).times(times: .zero)
}

func testStop_shouldNotSendInternalCustomEvent_whenSessionId_isMissing() async throws {
self.session.sessionStartTime = testDate
sessionContext.sessionId = nil

fakeTimestampProvider.when(\.fnProvide).thenReturn(testEndDate)

await self.session.stop()

_ = try fakeEventClient.verify(\.fnSendEvents).times(times: .zero)
}

func testStop_should_reset_when_eventClient_throws() async throws {
self.session.sessionStartTime = testDate
self.sessionContext.sessionId = testUuid
let error = Errors.NetworkingError.failedRequest(response: HTTPURLResponse())
fakeEventClient.when(\.fnSendEvents).thenThrow(error: error)

await self.session.stop()

XCTAssertNil(self.sessionContext.sessionId)
XCTAssertNil(self.session.sessionStartTime)
}
}
4 changes: 4 additions & 0 deletions Sources/EmarsysSDK/Core/Extensions/Date.swift
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,8 @@ extension Date {
return Date.utcFormatter.string(from: self)
}

func timeElapsedInMillis(fromDate: Date) -> Int {
return Int(self.timeIntervalSince(fromDate) * 1000)
}

}
23 changes: 20 additions & 3 deletions Sources/EmarsysSDK/Session/MobileEngageSession.swift
Original file line number Diff line number Diff line change
Expand Up @@ -39,15 +39,32 @@ class MobileEngageSession: SessionApi {
do {
_ = try await eventClient.sendEvents(name: Constants.Session.sessionStart, attributes: nil, eventType: EventType.internalEvent)
} catch {
self.sessionStartTime = nil
self.sessionContext.sessionId = nil
logger.log(logEntry: LogEntry(topic: "mobile-engage-session", data: ["error": error.localizedDescription]), level: .error)
resetSession()
logger.log(logEntry: LogEntry(topic: "mobile-engage-session-start", data: ["error": error.localizedDescription]), level: .error)
}
}
}

func stop() async {
let endTime = timestampProvider.provide()
guard let sessionStartTime, let _ = self.sessionContext.sessionId else {
return
}

let attributes = ["duration":"\(endTime.timeElapsedInMillis(fromDate: sessionStartTime))"]
do {
defer {
resetSession()
}
_ = try await eventClient.sendEvents(name: Constants.Session.sessionStop, attributes: attributes, eventType: EventType.internalEvent)
} catch {
logger.log(logEntry: LogEntry(topic: "mobile-engage-session-stop", data: ["error": error.localizedDescription]), level: .error)
}
}

private func resetSession() {
self.sessionStartTime = nil
self.sessionContext.sessionId = nil
}


Expand Down

0 comments on commit dfb1b96

Please sign in to comment.