Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
12 changes: 0 additions & 12 deletions StreamChatUITestsAppUITests/Robots/UserRobot.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,6 @@ final class UserRobot: Robot {
let composer = MessageListPage.Composer.self
let contextMenu = MessageListPage.ContextMenu.self
let debugAlert = MessageListPage.Alert.Debug.self
private var server: StreamMockServer

init(_ server: StreamMockServer) {
self.server = server
}

@discardableResult
func login() -> Self {
Expand Down Expand Up @@ -56,13 +51,6 @@ final class UserRobot: Robot {
ChannelListPage.cells.allElementsBoundByIndex[channelCellIndex].waitForHitPoint().safeTap()
return self
}

@discardableResult
public func waitForJwtToExpire() -> Self {
let sleepTime = UInt32((StreamMockServer.jwtTimeout + 2) * 1_000_000)
usleep(sleepTime)
return self
}

@discardableResult
public func sleep(_ seconds: Double) -> Self {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ final class Authentication_Tests: StreamTestCase {
.assertConnectionStatus(.connected)
}
WHEN("token expires") {
userRobot.waitForJwtToExpire()
backendRobot.waitForJwtToExpire()
}
THEN("app requests a token refresh") {
userRobot.assertConnectionStatus(.connected)
Expand All @@ -142,7 +142,7 @@ final class Authentication_Tests: StreamTestCase {
deviceRobot.moveApplication(to: .background)
}
AND("token expires") {
userRobot.waitForJwtToExpire()
backendRobot.waitForJwtToExpire()
}
WHEN("user comes back to foreground") {
deviceRobot.moveApplication(to: .foreground)
Expand All @@ -164,7 +164,7 @@ final class Authentication_Tests: StreamTestCase {
userRobot.setConnectivity(to: .off)
}
WHEN("token expires") {
userRobot.waitForJwtToExpire()
backendRobot.waitForJwtToExpire()
}
WHEN("user comes back online") {
userRobot.setConnectivity(to: .on)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ let app = XCUIApplication()

class StreamTestCase: XCTestCase {
let deviceRobot = DeviceRobot(app)
var userRobot: UserRobot!
let userRobot = UserRobot()
var backendRobot: BackendRobot!
var participantRobot: ParticipantRobot!
var mockServer: StreamMockServer!
Expand All @@ -19,10 +19,6 @@ class StreamTestCase: XCTestCase {
continueAfterFailure = false

try super.setUpWithError()
mockServer = StreamMockServer(driverPort: "4566", testName: testName)
backendRobot = BackendRobot(mockServer)
participantRobot = ParticipantRobot(mockServer)
userRobot = UserRobot(mockServer)
alertHandler()
backendHandler()
app.launch()
Expand All @@ -31,7 +27,9 @@ class StreamTestCase: XCTestCase {
override func tearDownWithError() throws {
attachElementTree()
app.terminate()
mockServer.stop()
if useMockServer {
mockServer.stop()
}

try super.tearDownWithError()
app.launchArguments.removeAll()
Expand All @@ -41,13 +39,15 @@ class StreamTestCase: XCTestCase {

extension StreamTestCase {
private func backendHandler() {
app.setEnvironmentVariables([
.websocketHost: "ws://localhost",
.httpHost: "http://localhost",
.port: StreamMockServer.port!
])

if useMockServer {
mockServer = StreamMockServer(driverPort: "4566", testName: testName)
backendRobot = BackendRobot(mockServer)
participantRobot = ParticipantRobot(mockServer)
app.setEnvironmentVariables([
.websocketHost: "ws://localhost",
.httpHost: "http://localhost",
.port: StreamMockServer.port!
])
app.setLaunchArguments(.useMockServer)
} else if let switchApiKey {
app.setEnvironmentVariables([.customApiKey: switchApiKey])
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,25 @@ import XCTest

@available(iOS 15.0, *)
class MessageListScrollTime: StreamTestCase {
override func setUpWithError() throws {
useMockServer = false
switchApiKey = "zcgvnykxsfm8"
try super.setUpWithError()
}
Comment on lines +9 to +13
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Hardcoded API key should be externalized.

The switchApiKey value on line 11 contains a hardcoded API key "zcgvnykxsfm8". As per coding guidelines, API keys should not be committed to the repository. Even for test/sandbox keys, consider externalizing this to an environment variable or a CI-injected secret to avoid accidental exposure and align with security best practices.

🔧 Suggested approach
 override func setUpWithError() throws {
     useMockServer = false
-    switchApiKey = "zcgvnykxsfm8"
+    switchApiKey = ProcessInfo.processInfo.environment["STREAM_PERFORMANCE_TEST_API_KEY"] ?? ""
     try super.setUpWithError()
 }

Then configure STREAM_PERFORMANCE_TEST_API_KEY as a CI secret in your GitHub Actions workflow.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
override func setUpWithError() throws {
useMockServer = false
switchApiKey = "zcgvnykxsfm8"
try super.setUpWithError()
}
override func setUpWithError() throws {
useMockServer = false
switchApiKey = ProcessInfo.processInfo.environment["STREAM_PERFORMANCE_TEST_API_KEY"] ?? ""
try super.setUpWithError()
}
🧰 Tools
🪛 Gitleaks (8.30.0)

[high] 11-11: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.

(generic-api-key)

🤖 Prompt for AI Agents
In `@StreamChatUITestsAppUITests/Tests/Performance/MessageListScrollTime.swift`
around lines 9 - 13, Replace the hardcoded API key in setUpWithError by reading
it from an environment variable: in the override func setUpWithError() used
symbols are useMockServer and switchApiKey — retrieve
ProcessInfo.processInfo.environment["STREAM_PERFORMANCE_TEST_API_KEY"] (or a
CI-injected secret) and assign it to switchApiKey, and if missing either throw
an error or skip the test with XCTSkip to prevent committing secrets; ensure you
update setUpWithError to validate the fetched value before calling try
super.setUpWithError().


func testMessageListScrollTime() {
WHEN("user opens the message list") {
backendRobot.generateChannels(channelsCount: 1, messagesCount: 100, attachments: true)
participantRobot.addReaction(type: .like)
userRobot.login().openChannel()
WHEN("user logs in") {
userRobot.login()
}
AND("user opens a channel with many messages") {
let minMessageCount = 20
for channelIndex in 0..<minMessageCount {
userRobot.openChannel(channelCellIndex: channelIndex)
if MessageListPage.cells.count >= minMessageCount {
break
}
userRobot.tapOnBackButton()
}
}
THEN("user scrolls the message list") {
let measureOptions = XCTMeasureOptions()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,13 @@ public class BackendRobot {
_ = mockServer.postRequest(endpoint: "delay_messages?delay=\(seconds)")
return self
}

@discardableResult
public func waitForJwtToExpire() -> Self {
let sleepTime = UInt32((StreamMockServer.jwtTimeout + 2) * 1_000_000)
usleep(sleepTime)
return self
}

public func revokeToken(duration: Int = 5) {
waitForMockServerToStart()
Expand Down
Loading