test(storage): migrate StorageTests to Swift Testing, keep Mocker (Phase 3)#1096
Conversation
Coverage Report for CI Build 29818457931Coverage remained the same at 83.583%Details
Uncovered ChangesNo uncovered changes found. Coverage RegressionsNo coverage regressions found. Coverage Stats
💛 - Coveralls |
Converts the largest AuthTests file (87 tests, 81 Mocker Mock() calls, 53 curl-snapshot assertions) to Swift Testing + Replay, per the Phase 0 decision (SDK-1247) and the Phase 4/Phase 3 conversion patterns (PostgRESTTests PR #1095, StorageTests PR #1096). - Curl-snapshot request-shape assertions dropped per the Phase 0 "no shim" decision, replaced by Replay's matcher-based enforcement. - Query strings preserved via exact-URL matching (.method, .url) rather than path-only matching, so query-string regressions are still caught (the gap PR #1095's follow-up commit found and fixed). - Request bodies verified via a custom .custom matcher that decodes both sides as AnyJSON for structural comparison (key order/whitespace insensitive), following the pattern from StorageTests PR #1096's jsonBody(of:) helper -- important here since most of this file's Mocker bodies carry auth-relevant payloads (passwords, tokens, PKCE code verifiers, MFA/passkey credentials). - withMainSerialExecutor wrapping moved from XCTestCase.invokeTest into the handful of @test bodies that actually spawn concurrent authStateChanges-driven Tasks. - HTTPResponse.stub(...) helper (used cross-file by SessionManagerTests) preserved at the bottom of the file. Linear: SDK-1252
Same Phase 3 migration as #1096, but stays on Mocker for HTTP mocking instead of Replay -- Replay isn't proven yet for all our cases, so we stick with Mocker for now. StorageBucketAPITests/StorageFileAPITests gain @suite(.serialized) since Mocker's mock registry is process-global and Swift Testing runs suites in parallel by default. Restores the .snapshotRequest curl-body assertions for move/copy/remove instead of Replay's custom JSON-body matcher, since Mocker already covers that. Linear: SDK-1250
abeffd9 to
7106c74
Compare
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (2)
📝 WalkthroughSummary by CodeRabbit
WalkthroughMigrates the Storage test target from XCTest to Swift Testing using Possibly related PRs
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Pull request overview
Migrates the StorageTests suite (and related FunctionsTests updates) from XCTest to the Swift Testing framework, aligning these test targets with the repo’s Swift 6 test-migration plan and enabling Swift 6 language mode for them via swift6TestTargets.
Changes:
- Converted
Tests/StorageTestsand severalTests/FunctionsTestsfiles fromXCTestCaseto@Suite/@Testwith#expectassertions and Swift Testing idioms. - Updated Mocker-based API tests to use per-test SUT construction and suite serialization traits intended to avoid parallel-execution races.
- Adjusted
Package.swifttest-target dependencies and movedFunctionsTests/StorageTestsinto the Swift 6 test-target set; updated snapshots accordingly.
Reviewed changes
Copilot reviewed 16 out of 21 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| Package.swift | Updates test-target dependencies and enables Swift 6 language mode for FunctionsTests and StorageTests. |
| Tests/StorageTests/ValueTypesTests.swift | Converts value-type unit tests to Swift Testing assertions. |
| Tests/StorageTests/TransformOptionsTests.swift | Converts TransformOptions tests to Swift Testing and adds missing Foundation import. |
| Tests/StorageTests/SupabaseStorageTests.swift | Converts storage client tests to Swift Testing; refactors session mocking to per-test instances. |
| Tests/StorageTests/StorageFileAPITests.swift | Converts Mocker-heavy Storage file API tests to Swift Testing with serialized suite and per-test SUT creation. |
| Tests/StorageTests/StorageErrorTests.swift | Converts StorageError tests to Swift Testing. |
| Tests/StorageTests/StorageBucketAPITests.swift | Converts Mocker-heavy Storage bucket API tests to Swift Testing; replaces looped cases with parameterized tests. |
| Tests/StorageTests/MultipartFormDataTests.swift | Converts multipart form-data tests to Swift Testing, including throws expectations. |
| Tests/StorageTests/FileOptionsTests.swift | Converts FileOptions tests to Swift Testing. |
| Tests/StorageTests/DownloadBehaviorTests.swift | Converts DownloadBehavior URL tests to Swift Testing; moves setup into init(). |
| Tests/StorageTests/BucketOptionsTests.swift | Converts BucketOptions tests to Swift Testing. |
| Tests/StorageTests/Snapshots/StorageBucketAPITests/StorageBucketAPITests-testCreateBucket.1.txt | Removes an orphaned/stale snapshot fixture. |
| Tests/FunctionsTests/RequestTests.swift | Converts to Swift Testing and updates SnapshotTesting call-site metadata arguments. |
| Tests/FunctionsTests/FunctionsErrorTests.swift | Converts Functions error tests to Swift Testing. |
| Tests/FunctionsTests/FunctionsClientTests.swift | Converts Mocker-heavy Functions client tests to Swift Testing with serialized suite and per-test SUT creation. |
| Tests/FunctionsTests/FunctionInvokeOptionsTests.swift | Converts invoke-options tests to Swift Testing. |
| Tests/FunctionsTests/Snapshots/RequestTests/invokeWithDefaultOptions.1.txt | Adds SnapshotTesting fixture for default invoke request. |
| Tests/FunctionsTests/Snapshots/RequestTests/invokeWithCustomRegion.1.txt | Adds SnapshotTesting fixture for custom region invoke request. |
| Tests/FunctionsTests/Snapshots/RequestTests/invokeWithCustomMethod.1.txt | Adds SnapshotTesting fixture for custom method invoke request. |
| Tests/FunctionsTests/Snapshots/RequestTests/invokeWithCustomHeader.1.txt | Adds SnapshotTesting fixture for custom header invoke request. |
| Tests/FunctionsTests/Snapshots/RequestTests/invokeWithBody.1.txt | Adds SnapshotTesting fixture for invoke request with JSON body. |
Same Phase 3 migration as #1096, but stays on Mocker for HTTP mocking instead of Replay -- Replay isn't proven yet for all our cases, so we stick with Mocker for now. StorageBucketAPITests/StorageFileAPITests gain @suite(.serialized) since Mocker's mock registry is process-global and Swift Testing runs suites in parallel by default. Restores the .snapshotRequest curl-body assertions for move/copy/remove instead of Replay's custom JSON-body matcher, since Mocker already covers that. Linear: SDK-1250
7106c74 to
b6c379d
Compare
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 12 out of 12 changed files in this pull request and generated 1 comment.
Comments suppressed due to low confidence (2)
Tests/StorageTests/StorageBucketAPITests.swift:28
Mockregistrations are stored in Mocker’s process-global registry; since this suite no longer callsMocker.removeAll()between tests, stubs can leak across tests and cause unexpected matches (especially for shared URLs like/bucket). Clearing the registry at the start ofmakeSUT()restores per-test isolation.
private func makeSUT() -> SupabaseStorageClient {
let configuration = URLSessionConfiguration.ephemeral
configuration.protocolClasses = [MockingURLProtocol.self]
let session = URLSession(configuration: configuration)
Tests/StorageTests/StorageFileAPITests.swift:30
- This suite registers many Mocker stubs, but there’s no longer a
Mocker.removeAll()between tests. Because Mocker’s registry is process-global, stubs can persist and interfere with later tests (or mask missing stubs). Clearing the registry at the start ofmakeSUT()helps keep tests independent.
private func makeSUT() -> SupabaseStorageClient {
let configuration = URLSessionConfiguration.ephemeral
configuration.protocolClasses = [MockingURLProtocol.self]
let session = URLSession(configuration: configuration)
| let encodedString = String(data: encoded, encoding: .utf8) | ||
| XCTAssertNotNil(encodedString) | ||
| XCTAssertTrue(encodedString!.contains(formData.boundary)) | ||
| #expect(encodedString != nil) | ||
| #expect(encodedString!.contains(formData.boundary)) |
|
The following capabilities are marked
The following capabilities are marked
These may have been renamed, removed, or never registered. Please update the capability matrix. |
Mocker.mock(for:) matches the FIRST registered mock for a request, so a stale stub from an earlier test could shadow a fresh one registered for the same URL in a later test. Clear the registry at the top of makeSUT() in both StorageBucketAPITests and StorageFileAPITests. Since Mocker's registry is process-global, the two suites also can't run concurrently *with each other* anymore (only .serialized within each suite isn't enough) -- otherwise one suite's removeAll() could wipe out mocks the other just registered. Nest both under a shared StorageMockerTests(.serialized) namespace, since Swift Testing applies .serialized recursively to nested suites. Addresses review feedback on #1096.
Same Phase 2 migration as #1094, but stays on Mocker for HTTP mocking instead of Replay -- Replay isn't proven yet for all our cases, so we stick with Mocker for now. FunctionsClientTests gains @suite(.serialized) since Mocker's mock registry is process-global and Swift Testing runs suites in parallel by default. makeSUT() also clears the registry via Mocker.removeAll() up front, since Mocker matches the first registered stub for a request and a stale one could otherwise shadow a fresh one (same fix as landed on #1096 after review). Rebased onto main's x-relay-error-before-status fix (#1112), porting its two new test cases (invoke_relayErrorWithNon2xxStatus_shouldThrowRelayError, invokeWithStreamedResponseRelayErrorWithNon2xxStatus) to Swift Testing. Linear: SDK-1249
Same Phase 2 migration as #1094, but stays on Mocker for HTTP mocking instead of Replay -- Replay isn't proven yet for all our cases, so we stick with Mocker for now. FunctionsClientTests gains @suite(.serialized) since Mocker's mock registry is process-global and Swift Testing runs suites in parallel by default. makeSUT() also clears the registry via Mocker.removeAll() up front, since Mocker matches the first registered stub for a request and a stale one could otherwise shadow a fresh one (same fix as landed on #1096 after review). Rebased onto main's x-relay-error-before-status fix (#1112), porting its two new test cases (invoke_relayErrorWithNon2xxStatus_shouldThrowRelayError, invokeWithStreamedResponseRelayErrorWithNon2xxStatus) to Swift Testing. Linear: SDK-1249
Summary
Migrates
Tests/StorageTests(11 files) from XCTest to Swift Testing (@Suite/@Test), per the repo-wide Swift Testing migration plan (SDK-435) and the conventions decided in Phase 0 (SDK-1247, SDK-1091). Keeps Mocker for HTTP mocking — Replay isn't proven yet for all our cases, so we're sticking with Mocker for now (may revisit later).Changes
StorageTestsout of the blanket.swiftLanguageMode(.v5)pin into theswift6TestTargetsset, so it now compiles under full Swift 6 language mode with the same strict-concurrency settings as production targets. Dropped the unusedCustomDumpdependency; keptMocker/TestHelpers/InlineSnapshotTesting/XCTestDynamicOverlay(all still used). No new package dependency.BucketOptionsTests,FileOptionsTests,TransformOptionsTests,ValueTypesTests,StorageErrorTests,MultipartFormDataTests) are mechanical conversions.DownloadBehaviorTests'setUpbecameinit().StorageBucketAPITests/StorageFileAPITests(the Mocker-heavy files) converted to@Suite(.serialized) structwith a per-testmakeSUT()helper (freshURLSessionConfiguration+MockingURLProtocoleach call), keeping every existingMock(...).snapshotRequest { ... }.register()curl-body assertion as-is — including formove/copy/remove, no new matching mechanism needed..serializedis required: Mocker's mock registry is process-global with no per-test isolation, and Swift Testing runs suites in parallel by default.SupabaseStorageTestskeeps its existing closure-basedStorageHTTPSessionmocking (already framework-agnostic) but dropsXCTestCase.StorageBucketAPITests-testCreateBucket.1.txt, didn't match any current test — that test uses an inline.snapshotRequestinstead). With the directory now empty, dropped the now-danglingexclude: ["__Snapshots__"]from the target too.Root cause note (bug found during migration)
While migrating
SupabaseStorageTests.uploadData/uploadFileURL, found that the original XCTest mocks wired their response-producing closure toStorageHTTPSession.fetch, not.upload— confirmed this is correct because productionStoragecode (StorageApi.swift) only ever callsconfiguration.session.fetch;.uploadis currently dead code for all Storage HTTP calls including multipart uploads. Preserved that wiring in the migrated tests.Test plan
swift test --filter StorageTests: 145/145 tests pass (139 from the original conversion + 6 added tomainsince), run twice to rule out Mocker registry races under parallel execution.swift test(full suite, minusIntegrationTestswhich needs a local Supabase instance perAGENTS.md): 0 failures.import XCTestremaining inTests/StorageTests../scripts/format.shclean.Linear
Closes SDK-1250