Skip to content

Commit aa96485

Browse files
test: Improve corrupted envelope UI test (#5549)
Simplify the UI test by writing the corrupted envelope and then starting the SDK. This removes the need to relaunch the app, which is often problematic in CI. Furthermore, this PR now lets the UI test fail with an error message if the test can't write the corrupted envelope instead of using fatalError. So when this fails, we know clearly what went wrong.
1 parent 2a36c3f commit aa96485

File tree

2 files changed

+73
-53
lines changed

2 files changed

+73
-53
lines changed

TestSamples/SwiftUITestSample/SwiftUITestSample/SwiftUITestSampleApp.swift

Lines changed: 62 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,8 @@
11
import Sentry
22
import SwiftUI
33

4-
struct Options {
5-
static var dsnHash: String?
6-
static var cacheDirPath: String?
7-
}
8-
94
@main
105
struct SwiftUITestSampleApp: App {
11-
init() {
12-
SentrySDK.start { options in
13-
options.debug = true
14-
options.dsn = "https://6cc9bae94def43cab8444a99e0031c28@o447951.ingest.sentry.io/5428557"
15-
Options.dsnHash = options.parsedDsn?.getHash()
16-
Options.cacheDirPath = options.cacheDirectoryPath
17-
}
18-
}
196

207
var body: some Scene {
218
WindowGroup {
@@ -25,38 +12,81 @@ struct SwiftUITestSampleApp: App {
2512
}
2613

2714
struct ContentView: View {
15+
@State private var errorMessage: String?
16+
2817
var body: some View {
2918
VStack {
3019
Text("Welcome!")
31-
Button("Close SDK") {
32-
SentrySDK.close()
20+
Button("Start SDK") {
21+
startSDK()
3322
}
3423
Button("Write Corrupted Envelope") {
35-
guard let dsnHash = Options.dsnHash else {
36-
fatalError("dsnHash can not be nil!")
37-
}
38-
39-
guard let cachePath = Options.cacheDirPath else {
40-
fatalError("cacheDirPath can not be nil!")
41-
}
42-
43-
let envelopePath = "\(cachePath)/io.sentry/\(dsnHash)/envelopes/corrupted-envelope.json"
44-
let corruptedEnvelopeData = Data("""
45-
{"event_id":"1990b5bc31904b7395fd07feb72daf1c","sdk":{"name":"sentry.cocoa","version":"8.33.0"}}
46-
{"type":"test","length":50}
47-
""".utf8)
48-
4924
do {
50-
try corruptedEnvelopeData.write(to: URL(fileURLWithPath: envelopePath))
51-
print("Corrupted envelope saved to: " + envelopePath)
25+
errorMessage = nil // Clear any previous error
26+
try writeCorruptedEnvelope()
27+
} catch let error as WriteCorruptedEnvelopeError {
28+
errorMessage = error.description
5229
} catch {
53-
fatalError("Error while writing corrupted envelope to: " + envelopePath)
30+
errorMessage = "Unknown error: \(error)"
5431
}
5532
}
33+
34+
if let errorMessage = errorMessage {
35+
Text("\(errorMessage)")
36+
.accessibilityIdentifier("errorMessage")
37+
}
5638
}
5739
}
5840
}
5941

42+
private var sentryOptions: Options = {
43+
let options = Options()
44+
options.dsn = "https://6cc9bae94def43cab8444a99e0031c28@o447951.ingest.sentry.io/5428557"
45+
options.debug = true
46+
return options
47+
}()
48+
49+
private func startSDK() {
50+
SentrySDK.start(options: sentryOptions)
51+
}
52+
53+
enum WriteCorruptedEnvelopeError: Error {
54+
case dsn
55+
case write(String)
56+
}
57+
58+
extension WriteCorruptedEnvelopeError: CustomStringConvertible {
59+
var description: String {
60+
switch self {
61+
case .dsn:
62+
return "DSN hash is not available"
63+
case .write(let s):
64+
return s
65+
}
66+
}
67+
}
68+
69+
private func writeCorruptedEnvelope() throws {
70+
guard let dsnHash = sentryOptions.parsedDsn?.getHash() else {
71+
throw WriteCorruptedEnvelopeError.dsn
72+
}
73+
74+
let envelopeFolder = "\(sentryOptions.cacheDirectoryPath)/io.sentry/\(dsnHash)/envelopes"
75+
let envelopePath = "\(envelopeFolder)/corrupted-envelope.json"
76+
let corruptedEnvelopeData = Data("""
77+
{"event_id":"1990b5bc31904b7395fd07feb72daf1c","sdk":{"name":"sentry.cocoa","version":"8.33.0"}}
78+
{"type":"test","length":50}
79+
""".utf8)
80+
81+
do {
82+
let fileManager = FileManager.default
83+
try fileManager.createDirectory(atPath: envelopeFolder, withIntermediateDirectories: true)
84+
try corruptedEnvelopeData.write(to: URL(fileURLWithPath: envelopePath), options: .atomic)
85+
} catch {
86+
throw WriteCorruptedEnvelopeError.write("Error while writing corrupted envelope to: \(envelopePath) error: \(error)")
87+
}
88+
}
89+
6090
struct ContentView_Previews: PreviewProvider {
6191
static var previews: some View {
6292
ContentView()
Lines changed: 11 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,20 @@
11
import XCTest
22

33
final class EnvelopeTest: XCTestCase {
4-
let app = XCUIApplication()
5-
6-
override func setUpWithError() throws {
7-
continueAfterFailure = false
8-
}
94

105
func testCorruptedEnvelope() throws {
11-
launchApp()
12-
13-
app.buttons["Write Corrupted Envelope"].tap()
14-
// The close here ensures the next corrupted envelope
15-
// will be present on the next app launch
16-
app.buttons["Close SDK"].tap()
6+
let app = XCUIApplication()
7+
8+
app.launch()
9+
1710
app.buttons["Write Corrupted Envelope"].tap()
18-
19-
app.terminate()
20-
launchApp()
11+
let errorMessageElement = app.staticTexts["errorMessage"]
12+
if errorMessageElement.exists {
13+
XCTFail("Writing corrupted envelope failed with \(errorMessageElement.label)")
14+
}
15+
16+
app.buttons["Start SDK"].tap()
17+
2118
XCTAssertTrue(app.staticTexts["Welcome!"].exists)
2219
}
23-
24-
private func launchApp() {
25-
app.activate()
26-
// Wait for the app to be ready
27-
sleep(2)
28-
app.launch()
29-
}
3020
}

0 commit comments

Comments
 (0)