Skip to content

Commit ce5331d

Browse files
committed
Repro for apiHost configuration problem
Steps for repro: - Load the ExampleApp project in XCode - Put breakpoints in the HTTPClient file in Segment package where the batch uploads happen - Run the app on simulator (I have tried iPhone 12 Pro) - Login using creds: [email protected], test1234 - Observe the value of uploadURL in the debugger when the batch is uploaded Expected: - Should be analytics-ingestion.kraftful.com since that is passed in the configuration in the SegmentAnalytlics.swift file Actual: - api.segment.io/v1 is used instead.
1 parent ddbe8ef commit ce5331d

File tree

20 files changed

+1293
-0
lines changed

20 files changed

+1293
-0
lines changed

Examples/APIHostConfigurationRepro/ExampleApp.xcodeproj/project.pbxproj

Lines changed: 439 additions & 0 deletions
Large diffs are not rendered by default.

Examples/APIHostConfigurationRepro/ExampleApp.xcodeproj/project.xcworkspace/contents.xcworkspacedata

Lines changed: 7 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3+
<plist version="1.0">
4+
<dict>
5+
<key>IDEDidComputeMac32BitWarning</key>
6+
<true/>
7+
</dict>
8+
</plist>
Lines changed: 181 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,181 @@
1+
//
2+
// AppState.swift
3+
// ExampleApp
4+
//
5+
// Created by Jacob Gable on 6/16/22.
6+
//
7+
8+
import Foundation
9+
10+
var TEST_USER_EMAIL = "[email protected]"
11+
var TEST_USER_PASSWORD = "test1234"
12+
var TEST_USER_ID = "12345"
13+
var TEST_DEVICE_CONNECT_TOKEN = "123abc"
14+
15+
// Serializable version of state data
16+
struct AppStateData: Codable {
17+
var loggedIn: Bool
18+
var loggedInUserId: String
19+
var deviceConnected: Bool
20+
var deviceReady: Bool
21+
var deviceCurrentTemp: Double
22+
var deviceModes = ["Cool", "Heat", "Off"]
23+
var deviceMode: String
24+
var deviceSetpoint: Double
25+
26+
init() {
27+
self.loggedIn = false
28+
self.loggedInUserId = ""
29+
self.deviceConnected = false
30+
self.deviceReady = false
31+
self.deviceCurrentTemp = 75
32+
self.deviceMode = "Cool"
33+
self.deviceSetpoint = 72
34+
}
35+
}
36+
37+
// Observable state data/methods and persistence statics
38+
class AppState: ObservableObject {
39+
@Published var loggedIn: Bool
40+
@Published var loggedInUserId: String
41+
@Published var deviceConnected: Bool
42+
@Published var deviceReady: Bool
43+
@Published var deviceCurrentTemp: Double
44+
@Published var deviceModes = ["Cool", "Heat", "Off"]
45+
@Published var deviceMode: String
46+
@Published var deviceSetpoint: Double
47+
48+
init() {
49+
self.loggedIn = false
50+
self.loggedInUserId = ""
51+
self.deviceConnected = false
52+
self.deviceReady = false
53+
self.deviceCurrentTemp = 75
54+
self.deviceMode = "Cool"
55+
self.deviceSetpoint = 72
56+
}
57+
58+
func signIn(username: String, password: String) -> Bool {
59+
if (username == TEST_USER_EMAIL && password == TEST_USER_PASSWORD) {
60+
self.loggedIn = true
61+
self.loggedInUserId = TEST_USER_ID
62+
} else {
63+
self.loggedIn = false
64+
self.loggedInUserId = ""
65+
}
66+
67+
return self.loggedIn
68+
}
69+
70+
func register(username: String, password: String) -> Bool {
71+
if (username == TEST_USER_EMAIL && password == TEST_USER_PASSWORD) {
72+
self.loggedIn = true
73+
self.loggedInUserId = TEST_USER_ID
74+
} else {
75+
self.loggedIn = false
76+
self.loggedInUserId = ""
77+
}
78+
79+
return self.loggedIn
80+
}
81+
82+
func connectDevice(token: String) -> Bool {
83+
self.deviceConnected = token.lowercased() == TEST_DEVICE_CONNECT_TOKEN
84+
85+
return self.deviceConnected
86+
}
87+
88+
func markDeviceReady() {
89+
self.deviceReady = true
90+
}
91+
92+
func changeSetpoint(increment: Double) {
93+
self.deviceSetpoint += increment
94+
}
95+
96+
func logout() {
97+
self.loggedIn = false
98+
self.loggedInUserId = ""
99+
self.deviceConnected = false
100+
self.deviceReady = false
101+
self.deviceCurrentTemp = 75
102+
self.deviceMode = "Cool"
103+
self.deviceSetpoint = 72
104+
}
105+
106+
// Persistence helpers
107+
108+
func fromData(data: AppStateData) {
109+
self.loggedIn = data.loggedIn
110+
self.loggedInUserId = data.loggedInUserId
111+
self.deviceConnected = data.deviceConnected
112+
self.deviceReady = data.deviceReady
113+
self.deviceCurrentTemp = data.deviceCurrentTemp
114+
self.deviceMode = data.deviceMode
115+
self.deviceSetpoint = data.deviceSetpoint
116+
}
117+
118+
func toData() -> AppStateData {
119+
var data = AppStateData()
120+
data.loggedIn = self.loggedIn
121+
data.loggedInUserId = self.loggedInUserId
122+
data.deviceConnected = self.deviceConnected
123+
data.deviceReady = self.deviceReady
124+
data.deviceCurrentTemp = self.deviceCurrentTemp
125+
data.deviceMode = self.deviceMode
126+
data.deviceSetpoint = self.deviceSetpoint
127+
128+
return data
129+
}
130+
131+
private static func fileURL() throws -> URL {
132+
try FileManager.default.url(
133+
for: .documentDirectory,
134+
in: .userDomainMask,
135+
appropriateFor: nil,
136+
create: false
137+
)
138+
.appendingPathComponent("appstate.data")
139+
}
140+
141+
static func load(completion: @escaping (Result<AppStateData, Error>)->Void) {
142+
let _ = print("Loading state")
143+
DispatchQueue.global(qos: .background).async {
144+
do {
145+
let fileURL = try fileURL()
146+
guard let file = try? FileHandle(forReadingFrom: fileURL) else {
147+
DispatchQueue.main.async {
148+
completion(.success(AppStateData()))
149+
}
150+
return
151+
}
152+
let decodedAppState = try JSONDecoder().decode(AppStateData.self, from: file.availableData)
153+
DispatchQueue.main.async {
154+
completion(.success(decodedAppState))
155+
}
156+
} catch {
157+
DispatchQueue.main.async {
158+
completion(.failure(error))
159+
}
160+
}
161+
}
162+
}
163+
164+
static func save(state: AppStateData, completion: @escaping (Result<Bool, Error>)->Void) {
165+
let _ = print("Saving state")
166+
DispatchQueue.global(qos: .background).async {
167+
do {
168+
let data = try JSONEncoder().encode(state)
169+
let outfile = try fileURL()
170+
try data.write(to: outfile)
171+
DispatchQueue.main.async {
172+
completion(.success(true))
173+
}
174+
} catch {
175+
DispatchQueue.main.async {
176+
completion(.failure(error))
177+
}
178+
}
179+
}
180+
}
181+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
{
2+
"colors" : [
3+
{
4+
"idiom" : "universal"
5+
}
6+
],
7+
"info" : {
8+
"author" : "xcode",
9+
"version" : 1
10+
}
11+
}
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
{
2+
"images" : [
3+
{
4+
"idiom" : "iphone",
5+
"scale" : "2x",
6+
"size" : "20x20"
7+
},
8+
{
9+
"idiom" : "iphone",
10+
"scale" : "3x",
11+
"size" : "20x20"
12+
},
13+
{
14+
"idiom" : "iphone",
15+
"scale" : "2x",
16+
"size" : "29x29"
17+
},
18+
{
19+
"idiom" : "iphone",
20+
"scale" : "3x",
21+
"size" : "29x29"
22+
},
23+
{
24+
"idiom" : "iphone",
25+
"scale" : "2x",
26+
"size" : "40x40"
27+
},
28+
{
29+
"idiom" : "iphone",
30+
"scale" : "3x",
31+
"size" : "40x40"
32+
},
33+
{
34+
"idiom" : "iphone",
35+
"scale" : "2x",
36+
"size" : "60x60"
37+
},
38+
{
39+
"idiom" : "iphone",
40+
"scale" : "3x",
41+
"size" : "60x60"
42+
},
43+
{
44+
"idiom" : "ipad",
45+
"scale" : "1x",
46+
"size" : "20x20"
47+
},
48+
{
49+
"idiom" : "ipad",
50+
"scale" : "2x",
51+
"size" : "20x20"
52+
},
53+
{
54+
"idiom" : "ipad",
55+
"scale" : "1x",
56+
"size" : "29x29"
57+
},
58+
{
59+
"idiom" : "ipad",
60+
"scale" : "2x",
61+
"size" : "29x29"
62+
},
63+
{
64+
"idiom" : "ipad",
65+
"scale" : "1x",
66+
"size" : "40x40"
67+
},
68+
{
69+
"idiom" : "ipad",
70+
"scale" : "2x",
71+
"size" : "40x40"
72+
},
73+
{
74+
"idiom" : "ipad",
75+
"scale" : "1x",
76+
"size" : "76x76"
77+
},
78+
{
79+
"idiom" : "ipad",
80+
"scale" : "2x",
81+
"size" : "76x76"
82+
},
83+
{
84+
"idiom" : "ipad",
85+
"scale" : "2x",
86+
"size" : "83.5x83.5"
87+
},
88+
{
89+
"idiom" : "ios-marketing",
90+
"scale" : "1x",
91+
"size" : "1024x1024"
92+
}
93+
],
94+
"info" : {
95+
"author" : "xcode",
96+
"version" : 1
97+
}
98+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"info" : {
3+
"author" : "xcode",
4+
"version" : 1
5+
}
6+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
//
2+
// AuthenticationView.swift
3+
// ExampleApp
4+
//
5+
// Created by Jacob Gable on 6/16/22.
6+
//
7+
8+
import SwiftUI
9+
10+
struct AuthenticationView: View {
11+
var body: some View {
12+
NavigationView {
13+
SignInView()
14+
}
15+
}
16+
}
17+
18+
struct AuthenticationView_Previews: PreviewProvider {
19+
static var previews: some View {
20+
AuthenticationView()
21+
}
22+
}
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
//
2+
// RegisterView.swift
3+
// ExampleApp
4+
//
5+
// Created by Jacob Gable on 6/16/22.
6+
//
7+
8+
import SwiftUI
9+
10+
struct RegisterView: View {
11+
@EnvironmentObject var appState: AppState
12+
@State var username: String = ""
13+
@State var password: String = ""
14+
@State var registerError: String = ""
15+
let lightGray: Color = Color(red: 0.9, green: 0.9, blue: 0.9)
16+
17+
var body: some View {
18+
ScrollView {
19+
VStack {
20+
Text("Enter account information")
21+
.padding(.bottom, 10)
22+
TextField("Username", text: $username)
23+
.autocapitalization(.none)
24+
.padding()
25+
.background(lightGray)
26+
.cornerRadius(5.0)
27+
.padding(.bottom, 5)
28+
SecureField("Password", text: $password)
29+
.autocapitalization(.none)
30+
.padding()
31+
.background(lightGray)
32+
.cornerRadius(5.0)
33+
.padding(.bottom, 10)
34+
Button(action: {
35+
let success = appState.register(username: username, password: password)
36+
if (!success) {
37+
registerError = "Unable to register with those credentials"
38+
} else {
39+
registerError = ""
40+
}
41+
}) {
42+
Text("Register!")
43+
}
44+
.padding(.bottom, 10)
45+
Text(registerError)
46+
.foregroundColor(Color(.systemRed))
47+
}.padding()
48+
}
49+
.navigationTitle("Register")
50+
}
51+
}
52+
53+
struct RegisterView_Previews: PreviewProvider {
54+
static var previews: some View {
55+
NavigationView {
56+
RegisterView()
57+
}
58+
}
59+
}

0 commit comments

Comments
 (0)