Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 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
6 changes: 6 additions & 0 deletions Sources/Segment/Configuration.swift
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,12 @@ public extension Configuration {
return self
}

@discardableResult
func defaultSettings(_ settings: Settings) -> Configuration {
values.defaultSettings = settings
return self
}

@discardableResult
func autoAddSegmentDestination(_ value: Bool) -> Configuration {
values.autoAddSegmentDestination = value
Expand Down
9 changes: 9 additions & 0 deletions Sources/Segment/Settings.swift
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,15 @@ public struct Settings: Codable {
])
}

public init(writeKey: String) {
integrations = try! JSON([
SegmentDestination.Constants.integrationName.rawValue: [
SegmentDestination.Constants.apiKey.rawValue: writeKey,
SegmentDestination.Constants.apiHost.rawValue: HTTPClient.getDefaultAPIHost()
]
])
}

public init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: CodingKeys.self)
self.integrations = try? values.decode(JSON.self, forKey: CodingKeys.integrations)
Expand Down
55 changes: 29 additions & 26 deletions Sources/Segment/Timeline.swift
Original file line number Diff line number Diff line change
Expand Up @@ -209,37 +209,40 @@ extension DestinationPlugin {
// This will process plugins (think destination middleware) that are tied
// to this destination.

var result: E? = incomingEvent

// For destination plugins, we will always have some kind of `settings`,
// and if we don't, it means this destination hasn't been setup on app.segment.com,
// which in turn ALSO means that we shouldn't be sending events to it.


// apply .before and .enrichment types first ...
let beforeResult = timeline.applyPlugins(type: .before, event: incomingEvent)
let enrichmentResult = timeline.applyPlugins(type: .enrichment, event: beforeResult)

// now we execute any overrides we may have made. basically, the idea is to take an
// incoming event, like identify, and map it to whatever is appropriate for this destination.
var destinationResult: E? = nil
switch enrichmentResult {
case let e as IdentifyEvent:
destinationResult = identify(event: e) as? E
case let e as TrackEvent:
destinationResult = track(event: e) as? E
case let e as ScreenEvent:
destinationResult = screen(event: e) as? E
case let e as GroupEvent:
destinationResult = group(event: e) as? E
case let e as AliasEvent:
destinationResult = alias(event: e) as? E
default:
break

if let enabled = analytics?.settings()?.isDestinationEnabled(key: self.key), enabled == true {
// apply .before and .enrichment types first ...
let beforeResult = timeline.applyPlugins(type: .before, event: incomingEvent)
let enrichmentResult = timeline.applyPlugins(type: .enrichment, event: beforeResult)

// now we execute any overrides we may have made. basically, the idea is to take an
// incoming event, like identify, and map it to whatever is appropriate for this destination.
var destinationResult: E? = nil
switch enrichmentResult {
case let e as IdentifyEvent:
destinationResult = identify(event: e) as? E
case let e as TrackEvent:
destinationResult = track(event: e) as? E
case let e as ScreenEvent:
destinationResult = screen(event: e) as? E
case let e as GroupEvent:
destinationResult = group(event: e) as? E
case let e as AliasEvent:
destinationResult = alias(event: e) as? E
default:
break
}

// apply .after plugins ...
result = timeline.applyPlugins(type: .after, event: destinationResult)
}

// apply .after plugins ...
let afterResult = timeline.applyPlugins(type: .after, event: destinationResult)

return afterResult
return result
}
}

53 changes: 53 additions & 0 deletions Tests/Segment-Tests/Analytics_Tests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,59 @@ final class Analytics_Tests: XCTestCase {

wait(for: [expectation], timeout: 1.0)
}

func testDestinationEnabled() {
// need to clear settings for this one.
UserDefaults.standard.removePersistentDomain(forName: "com.segment.storage.test")

let expectation = XCTestExpectation(description: "MyDestination Expectation")
let myDestination = MyDestination {
expectation.fulfill()
}

var settings = Settings(writeKey: "test")
if let existing = settings.integrations?.dictionaryValue {
var newIntegrations = existing
newIntegrations[myDestination.key] = true
settings.integrations = try! JSON(newIntegrations)
}
let configuration = Configuration(writeKey: "test")
configuration.defaultSettings(settings)
let analytics = Analytics(configuration: configuration)

analytics.add(plugin: myDestination)

waitUntilStarted(analytics: analytics)

analytics.track(name: "testDestinationEnabled")

wait(for: [expectation], timeout: 1.0)
}

// Linux doesn't support XCTExpectFailure
#if !os(Linux)
func testDestinationNotEnabled() {
// need to clear settings for this one.
UserDefaults.standard.removePersistentDomain(forName: "com.segment.storage.test")

let expectation = XCTestExpectation(description: "MyDestination Expectation")
let myDestination = MyDestination {
expectation.fulfill()
}

let configuration = Configuration(writeKey: "test")
let analytics = Analytics(configuration: configuration)

analytics.add(plugin: myDestination)

waitUntilStarted(analytics: analytics)

analytics.track(name: "testDestinationEnabled")

XCTExpectFailure()
wait(for: [expectation], timeout: 1.0)
}
#endif

func testAnonymousId() {
let analytics = Analytics(configuration: Configuration(writeKey: "test"))
Expand Down
10 changes: 9 additions & 1 deletion Tests/Segment-Tests/Support/TestUtilities.swift
Original file line number Diff line number Diff line change
Expand Up @@ -73,17 +73,25 @@ class MyDestination: DestinationPlugin {
let type: PluginType
let key: String
var analytics: Analytics?
let trackCompletion: (() -> Void)?

init() {
init(trackCompletion: (() -> Void)? = nil) {
self.key = "MyDestination"
self.type = .destination
self.timeline = Timeline()
self.trackCompletion = trackCompletion
}

func update(settings: Settings) {
//
}

func track(event: TrackEvent) -> TrackEvent? {
if let completion = trackCompletion {
completion()
}
return event
}
}

class OutputReaderPlugin: Plugin {
Expand Down