Serialized the capturing service calls for the RecordingViewModel view model in the Recording package target.

This commit is contained in:
2026-07-04 14:55:49 +02:00
parent 702333038c
commit ed9d1e86fa
2 changed files with 70 additions and 40 deletions
@@ -258,8 +258,7 @@ struct RecordingViewModelTests {
try await Task.sleep(for: .seconds(0.1))
#expect(capturer.countStart == 1)
#expect(capturer.countResume == 0)
#expect(capturer.calls == ["start"])
model.pressedMain()
}
@@ -273,7 +272,7 @@ struct RecordingViewModelTests {
try await Task.sleep(for: .seconds(0.1))
#expect(capturer.countPause == 1)
#expect(capturer.calls == ["start", "pause"])
}
@Test func `resumes the capture after a pause`() async throws {
@@ -286,8 +285,7 @@ struct RecordingViewModelTests {
try await Task.sleep(for: .seconds(0.1))
#expect(capturer.countStart == 1)
#expect(capturer.countResume == 1)
#expect(capturer.calls == ["start", "pause", "resume"])
model.pressedMain()
}
@@ -303,7 +301,29 @@ struct RecordingViewModelTests {
try await Task.sleep(for: .seconds(0.5))
#expect(capturer.countStop == 1)
#expect(capturer.calls == ["start", "pause", "stop"])
}
@Test func `serializes the calls when states change rapidly`() async throws {
let capturer = CapturingMock()
capturer.delay = .seconds(0.2)
let model = Model(capturer: capturer)
model.pressedMain()
model.pressedMain()
model.pressedMain()
try await Task.sleep(for: .seconds(0.1))
#expect(capturer.calls == ["start"])
try await Task.sleep(for: .seconds(0.6))
#expect(capturer.calls == ["start", "pause", "resume"])
model.pressedMain()
}
@Test func `falls back to not recording when the capture fails`() async throws {
@@ -419,52 +439,45 @@ private extension RecordingView.Model {
// MARK: - Mocks
/// A recording service that counts its invocations and can be configured to fail.
/// A recording service that records its invocations in call order, each one taking a configurable amount of time, and can be
/// configured to fail.
@MainActor
private final class CapturingMock: Capturing {
/// The duration every method takes before returning, simulating slow capture work.
var delay: Duration = .zero
/// The error the service throws from every method, or `nil` when it should succeed.
var error: Error?
/// The number of times ``start()`` has been called.
private(set) var countStart = 0
/// The number of times ``pause()`` has been called.
private(set) var countPause = 0
/// The number of times ``resume()`` has been called.
private(set) var countResume = 0
/// The number of times ``stop()`` has been called.
private(set) var countStop = 0
/// The names of the methods called on the service, in call order.
private(set) var calls: [String] = []
func start() async throws {
countStart += 1
try throwConfiguredError()
try await called("start")
}
func pause() async throws {
countPause += 1
try throwConfiguredError()
try await called("pause")
}
func resume() async throws {
countResume += 1
try throwConfiguredError()
try await called("resume")
}
func stop() async throws -> Data {
countStop += 1
try throwConfiguredError()
try await called("stop")
return .init()
}
private func throwConfiguredError() throws {
private func called(
_ name: String
) async throws {
calls.append(name)
try await Task.sleep(for: delay)
if let error {
throw error
}