From 6d78a6ebf19ef98545a7dbe09390e6dd63815e87 Mon Sep 17 00:00:00 2001 From: GErP83 Date: Tue, 3 Feb 2026 17:10:06 +0100 Subject: [PATCH 01/11] texts fixes, package fix --- .github/workflows/deployment.yml | 1 + .github/workflows/testing.yml | 4 ++-- Package.swift | 20 ++++++++++++++------ README.md | 20 ++++++++++---------- 4 files changed, 27 insertions(+), 18 deletions(-) diff --git a/.github/workflows/deployment.yml b/.github/workflows/deployment.yml index 680623b..672e272 100644 --- a/.github/workflows/deployment.yml +++ b/.github/workflows/deployment.yml @@ -5,6 +5,7 @@ on: tags: - 'v*' - '[0-9]*' + workflow_dispatch: jobs: diff --git a/.github/workflows/testing.yml b/.github/workflows/testing.yml index ebfae0b..68dadfa 100644 --- a/.github/workflows/testing.yml +++ b/.github/workflows/testing.yml @@ -15,7 +15,7 @@ jobs: format_check_enabled : true broken_symlink_check_enabled : true unacceptable_language_check_enabled : true - shell_check_enabled : true + shell_check_enabled : false docs_check_enabled : false api_breakage_check_enabled : false license_header_check_enabled : false @@ -27,7 +27,7 @@ jobs: uses: BinaryBirds/github-workflows/.github/workflows/extra_soundness.yml@main with: local_swift_dependencies_check_enabled : true - headers_check_enabled : true + headers_check_enabled : false docc_warnings_check_enabled : true swiftlang_tests: diff --git a/Package.swift b/Package.swift index 806eec0..6e4f77d 100644 --- a/Package.swift +++ b/Package.swift @@ -34,14 +34,22 @@ let package = Package( .library(name: "FeatherSpec", targets: ["FeatherSpec"]), ], dependencies: [ + // [docc-plugin-placeholder] .package(url: "https://github.com/apple/swift-openapi-runtime", from: "1.0.0"), ], targets: [ - .target(name: "FeatherSpec", dependencies: [ - .product(name: "OpenAPIRuntime", package: "swift-openapi-runtime"), - ]), - .testTarget(name: "FeatherSpecTests", dependencies: [ - .target(name: "FeatherSpec"), - ]), + .target(name: "FeatherSpec", + dependencies: [ + .product(name: "OpenAPIRuntime", package: "swift-openapi-runtime" + ) + ], + swiftSettings: defaultSwiftSettings + ), + .testTarget(name: "FeatherSpecTests", + dependencies: [ + .target(name: "FeatherSpec"), + ], + swiftSettings: defaultSwiftSettings + ), ] ) diff --git a/README.md b/README.md index 84b7cf0..1064ed0 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ Declarative HTTP specification testing for Swift, providing a shared API surface for runners and executors. -![Release: 1.0.0-beta.1](https://img.shields.io/badge/Release-1%2E0%2E0--beta%2E1-F05138) +[![Release: 1.0.0-beta.2](https://img.shields.io/badge/Release-1.0.0--beta.2-F05138)]( https://github.com/feather-framework/feather-spec/releases/tag/1.0.0-beta.2) ## Features @@ -18,11 +18,11 @@ Declarative HTTP specification testing for Swift, providing a shared API surface - Swift 6.1+ - Platforms: - - macOS 15+ - - iOS 18+ - - tvOS 18+ - - watchOS 11+ - - visionOS 2+ + - macOS 15+ + - iOS 18+ + - tvOS 18+ + - watchOS 11+ + - visionOS 2+ ## Installation @@ -40,9 +40,9 @@ Then add `FeatherSpec` to your target dependencies: ## Usage -![DocC API documentation](https://img.shields.io/badge/DocC-API_documentation-F05138) +[![DocC API documentation](https://img.shields.io/badge/DocC-API_documentation-F05138)](https://feather-framework.github.io/feather-spec/) -API documentation is available at the following [link](https://feather-framework.github.io/feather-spec/). Refer to the mock objects in the Tests directory if you want to build a custom runner or executor implementation. +API documentation is available at the following link. Refer to the mock objects in the Tests directory if you want to build a custom runner or executor implementation. > [!WARNING] > This repository is a work in progress, things can break until it reaches v1.0.0. @@ -58,8 +58,8 @@ The following Swift server-side runtime integrations are available: - Build: `swift build` - Test: - - local: `make test` - - using Docker: `make docker-test` + - local: `make test` + - using Docker: `make docker-test` - Format: `make format` - Check: `make check` From 060516c3de5cec888460ae07104efcfdf2c03d94 Mon Sep 17 00:00:00 2001 From: GErP83 Date: Tue, 3 Feb 2026 17:12:34 +0100 Subject: [PATCH 02/11] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 1064ed0..f8ec123 100644 --- a/README.md +++ b/README.md @@ -29,7 +29,7 @@ Declarative HTTP specification testing for Swift, providing a shared API surface Use Swift Package Manager; add the dependency to your `Package.swift` file: ```swift -.package(url: "https://github.com/feather-framework/feather-spec", exact: "1.0.0-beta.1"), +.package(url: "https://github.com/feather-framework/feather-spec", exact: "1.0.0-beta.2"), ``` Then add `FeatherSpec` to your target dependencies: From ff01575c3d0b5450f6c8fd5f008c97be68cafb80 Mon Sep 17 00:00:00 2001 From: GErP83 Date: Tue, 3 Feb 2026 18:00:50 +0100 Subject: [PATCH 03/11] add missing Sendable's after package.swift fix --- Sources/FeatherSpec/Models/Expectation.swift | 8 ++++---- Sources/FeatherSpec/Models/Spec.swift | 12 +++++++----- Sources/FeatherSpec/Protocols/SpecExecutor.swift | 2 +- Sources/FeatherSpec/Protocols/SpecRunner.swift | 5 ++--- .../Expectations/ExpectBuilderParam.swift | 4 ++-- Tests/FeatherSpecTests/FeatherSpecTests.swift | 11 +++++++---- Tests/FeatherSpecTests/MockRunner/Custom.swift | 2 +- 7 files changed, 24 insertions(+), 20 deletions(-) diff --git a/Sources/FeatherSpec/Models/Expectation.swift b/Sources/FeatherSpec/Models/Expectation.swift index c8ab764..edac10c 100644 --- a/Sources/FeatherSpec/Models/Expectation.swift +++ b/Sources/FeatherSpec/Models/Expectation.swift @@ -10,12 +10,12 @@ import OpenAPIRuntime /// A structure representing an expectation to be used in building specifications. /// /// Expectations encapsulate async validation logic for responses. -public struct Expectation { +public struct Expectation: Sendable { /// A closure representing the expectation block. /// /// The block receives the response and body produced by the executor. - public let block: ((HTTPResponse, HTTPBody) async throws -> Void) + public let block: (@Sendable (HTTPResponse, HTTPBody) async throws -> Void) /// Initializes an `Expectation` instance with the specified parameters. /// @@ -23,7 +23,7 @@ public struct Expectation { /// /// - Parameter block: The closure representing the expectation block. public init( - block: @escaping ((HTTPResponse, HTTPBody) async throws -> Void) + block: @escaping @Sendable (HTTPResponse, HTTPBody) async throws -> Void ) { self.block = block } @@ -62,7 +62,7 @@ extension Expectation { /// - Returns: An `Expectation` instance for verifying the presence of a specific HTTP header. public static func header( name: HTTPField.Name, - block: ((String) async throws -> Void)? = nil + block: (@Sendable (String) async throws -> Void)? = nil ) -> Self { .init( block: { response, _ in diff --git a/Sources/FeatherSpec/Models/Spec.swift b/Sources/FeatherSpec/Models/Spec.swift index b8e3acf..68babc9 100644 --- a/Sources/FeatherSpec/Models/Spec.swift +++ b/Sources/FeatherSpec/Models/Spec.swift @@ -10,7 +10,7 @@ import OpenAPIRuntime /// A structure representing an HTTP request specification. /// /// This holds request data and expectations to be evaluated after execution. -public struct Spec { +public struct Spec: Sendable { /// The HTTP request. /// @@ -75,7 +75,8 @@ public struct Spec { /// /// The expectation runs after the request completes. public mutating func addExpectation( - _ block: @escaping ((HTTPResponse, HTTPBody) async throws -> Void) + _ block: + @escaping @Sendable (HTTPResponse, HTTPBody) async throws -> Void ) { expectations.append(.init(block: block)) } @@ -180,7 +181,8 @@ public struct Spec { /// /// Returns a new spec with the expectation appended. public func expect( - _ block: @escaping ((HTTPResponse, HTTPBody) async throws -> Void) + _ block: + @escaping @Sendable (HTTPResponse, HTTPBody) async throws -> Void ) -> Self { modify { $0.addExpectation(block) } } @@ -222,7 +224,7 @@ extension Spec { /// An optional block can further validate the header value. public mutating func addExpectation( _ name: HTTPField.Name, - _ block: ((String) async throws -> Void)? = nil + _ block: (@Sendable (String) async throws -> Void)? = nil ) { expectations.append( .header(name: name, block: block) @@ -245,7 +247,7 @@ extension Spec { /// Returns a new spec with the expectation appended. public func expect( _ name: HTTPField.Name, - _ block: ((String) async throws -> Void)? = nil + _ block: (@Sendable (String) async throws -> Void)? = nil ) -> Self { modify { $0.addExpectation(name, block) } } diff --git a/Sources/FeatherSpec/Protocols/SpecExecutor.swift b/Sources/FeatherSpec/Protocols/SpecExecutor.swift index 8857907..748cad3 100644 --- a/Sources/FeatherSpec/Protocols/SpecExecutor.swift +++ b/Sources/FeatherSpec/Protocols/SpecExecutor.swift @@ -10,7 +10,7 @@ import OpenAPIRuntime /// A protocol defining the interface for running HTTP request specifications. /// /// Executors turn a `Spec` into a concrete HTTP request and return a response. -public protocol SpecExecutor { +public protocol SpecExecutor: Sendable { /// Executes an HTTP request specification asynchronously. /// diff --git a/Sources/FeatherSpec/Protocols/SpecRunner.swift b/Sources/FeatherSpec/Protocols/SpecRunner.swift index b1c27b8..58a38bc 100644 --- a/Sources/FeatherSpec/Protocols/SpecRunner.swift +++ b/Sources/FeatherSpec/Protocols/SpecRunner.swift @@ -15,9 +15,8 @@ public protocol SpecRunner { /// /// - Parameter block: A closure that takes a `SpecExecutor` and performs asynchronous operations. /// - Throws: error - func test( - block: @escaping (SpecExecutor) async throws -> Void - ) async throws + func test(block: @escaping @Sendable (SpecExecutor) async throws -> Void) + async throws } // NOTE: result type? diff --git a/Sources/FeatherSpec/SpecBuilderParameters/Expectations/ExpectBuilderParam.swift b/Sources/FeatherSpec/SpecBuilderParameters/Expectations/ExpectBuilderParam.swift index 9b118cc..f2e818e 100644 --- a/Sources/FeatherSpec/SpecBuilderParameters/Expectations/ExpectBuilderParam.swift +++ b/Sources/FeatherSpec/SpecBuilderParameters/Expectations/ExpectBuilderParam.swift @@ -20,7 +20,7 @@ public struct Expect: SpecBuilderParameter { /// /// - Parameter block: A closure that takes an `HTTPResponse` and `HTTPBody` and performs an asynchronous operation. public init( - block: @escaping ((HTTPResponse, HTTPBody) async throws -> Void) + block: @escaping @Sendable (HTTPResponse, HTTPBody) async throws -> Void ) { self.expectation = .init(block: block) } @@ -60,7 +60,7 @@ extension Expect { /// - block: An optional closure that takes a `String` and performs an asynchronous operation. public init( _ name: HTTPField.Name, - _ block: ((String) async throws -> Void)? = nil + _ block: (@Sendable (String) async throws -> Void)? = nil ) { self.expectation = .header(name: name, block: block) } diff --git a/Tests/FeatherSpecTests/FeatherSpecTests.swift b/Tests/FeatherSpecTests/FeatherSpecTests.swift index 09824d4..49e8913 100644 --- a/Tests/FeatherSpecTests/FeatherSpecTests.swift +++ b/Tests/FeatherSpecTests/FeatherSpecTests.swift @@ -62,6 +62,7 @@ struct FeatherSpecTests { /// Verifies the mutating `Spec` API. @Test func testMutatingFuncSpec() async throws { + let expectedTitle = todo.title var spec = Spec() spec.setMethod(.post) spec.setPath(path) @@ -73,7 +74,7 @@ struct FeatherSpecTests { } spec.addExpectation { response, body in let todo = try await body.decode(Todo.self, with: response) - #expect(todo.title == self.todo.title) + #expect(todo.title == expectedTitle) } #expect(spec.request.method == .post) @@ -88,6 +89,7 @@ struct FeatherSpecTests { /// Verifies the fluent `Spec` API. @Test func testBuilderFuncSpec() async throws { + let expectedTitle = todo.title let spec = Spec() .method(.post) .path(path) @@ -99,7 +101,7 @@ struct FeatherSpecTests { } .expect { response, body in let todo = try await body.decode(Todo.self, with: response) - #expect(todo.title == self.todo.title) + #expect(todo.title == expectedTitle) } #expect(spec.request.method == .post) @@ -114,6 +116,7 @@ struct FeatherSpecTests { /// Verifies the DSL builder API. @Test func testDslSpec() async throws { + let expectedTitle = todo.title let spec = SpecBuilder { Method(.post) Path(path) @@ -125,11 +128,11 @@ struct FeatherSpecTests { } Expect { response, body in let todo = try await body.decode(Todo.self, with: response) - #expect(todo.title == self.todo.title) + #expect(todo.title == expectedTitle) } Custom { response, body in let todo = try await body.decode(Todo.self, with: response) - #expect(todo.title == self.todo.title) + #expect(todo.title == expectedTitle) } } .build() diff --git a/Tests/FeatherSpecTests/MockRunner/Custom.swift b/Tests/FeatherSpecTests/MockRunner/Custom.swift index 1d079c9..1680bde 100644 --- a/Tests/FeatherSpecTests/MockRunner/Custom.swift +++ b/Tests/FeatherSpecTests/MockRunner/Custom.swift @@ -22,7 +22,7 @@ struct Custom: SpecBuilderParameter { /// /// The block is wrapped into an `Expectation`. init( - block: @escaping ((HTTPResponse, HTTPBody) async throws -> Void) + block: @escaping @Sendable (HTTPResponse, HTTPBody) async throws -> Void ) { self.expectation = .init(block: block) } From d665ea6dd1cc411c3622be61d764602a6676d881 Mon Sep 17 00:00:00 2001 From: GErP83 Date: Thu, 5 Feb 2026 10:02:37 +0100 Subject: [PATCH 04/11] Update SpecRunner.swift --- Sources/FeatherSpec/Protocols/SpecRunner.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Sources/FeatherSpec/Protocols/SpecRunner.swift b/Sources/FeatherSpec/Protocols/SpecRunner.swift index 58a38bc..8bad4fb 100644 --- a/Sources/FeatherSpec/Protocols/SpecRunner.swift +++ b/Sources/FeatherSpec/Protocols/SpecRunner.swift @@ -7,7 +7,7 @@ /// SpecRunner. /// /// Conforming types provide the execution environment for one or more specs. -public protocol SpecRunner { +public protocol SpecRunner: Sendable { /// Asynchronously tests a specification. /// From 355e56b20f1bfd00f7fe9945e2dc381a8119470a Mon Sep 17 00:00:00 2001 From: GErP83 Date: Mon, 9 Feb 2026 14:28:09 +0100 Subject: [PATCH 05/11] update readme --- Package.swift | 2 +- README.md | 1 + .../{FeatherSpecTests.swift => FeatherSpecTestSuite.swift} | 4 ++-- 3 files changed, 4 insertions(+), 3 deletions(-) rename Tests/FeatherSpecTests/{FeatherSpecTests.swift => FeatherSpecTestSuite.swift} (99%) diff --git a/Package.swift b/Package.swift index 6e4f77d..160107d 100644 --- a/Package.swift +++ b/Package.swift @@ -11,7 +11,7 @@ var defaultSwiftSettings: [SwiftSetting] = // https://forums.swift.org/t/experimental-support-for-lifetime-dependencies-in-swift-6-2-and-beyond/78638 .enableExperimentalFeature("Lifetimes"), // https://github.com/swiftlang/swift/pull/65218 - .enableExperimentalFeature("AvailabilityMacro=featherDatabase 1.0:macOS 15.0, iOS 18.0, tvOS 18.0, watchOS 11.0, visionOS 2.0"), + .enableExperimentalFeature("AvailabilityMacro=featherSpec 1.0:macOS 15.0, iOS 18.0, tvOS 18.0, watchOS 11.0, visionOS 2.0"), ] #if compiler(>=6.2) diff --git a/README.md b/README.md index f8ec123..823d7d2 100644 --- a/README.md +++ b/README.md @@ -18,6 +18,7 @@ Declarative HTTP specification testing for Swift, providing a shared API surface - Swift 6.1+ - Platforms: + - Linux - macOS 15+ - iOS 18+ - tvOS 18+ diff --git a/Tests/FeatherSpecTests/FeatherSpecTests.swift b/Tests/FeatherSpecTests/FeatherSpecTestSuite.swift similarity index 99% rename from Tests/FeatherSpecTests/FeatherSpecTests.swift rename to Tests/FeatherSpecTests/FeatherSpecTestSuite.swift index 49e8913..16bd73e 100644 --- a/Tests/FeatherSpecTests/FeatherSpecTests.swift +++ b/Tests/FeatherSpecTests/FeatherSpecTestSuite.swift @@ -1,5 +1,5 @@ // -// FeatherSpecTests.swift +// FeatherSpecTestSuite.swift // feather-spec // // Created by Binary Birds on 2026. 01. 20.. @@ -14,7 +14,7 @@ import Testing /// /// Covers the fluent API, DSL builder, and executor integrations. @Suite -struct FeatherSpecTests { +struct FeatherSpecTestSuite { /// Shared request path used across tests. /// From 6dbb2b83173e2cb4b9a1d7f1f0646c5c09a4f0ef Mon Sep 17 00:00:00 2001 From: GErP83 Date: Mon, 9 Feb 2026 14:39:59 +0100 Subject: [PATCH 06/11] add new workflow --- .github/workflows/testing.yml | 4 ++++ Makefile | 8 +++++++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/.github/workflows/testing.yml b/.github/workflows/testing.yml index 68dadfa..a927259 100644 --- a/.github/workflows/testing.yml +++ b/.github/workflows/testing.yml @@ -7,6 +7,10 @@ on: jobs: + api_breakage: + name: Check API breakage + uses: BinaryBirds/github-workflows/.github/workflows/api_breakage.yml@feature/breakage-workflow + swiftlang_checks: name: Swiftlang Checks uses: swiftlang/github-workflows/.github/workflows/soundness.yml@main diff --git a/Makefile b/Makefile index 11bd428..53b8568 100644 --- a/Makefile +++ b/Makefile @@ -2,7 +2,13 @@ SHELL=/bin/bash baseUrl = https://raw.githubusercontent.com/BinaryBirds/github-workflows/refs/heads/main/scripts -check: symlinks language deps lint docc-warnings headers +check: symlinks language deps lint docc-warnings headers package + +package: + curl -s $(baseUrl)/check-swift-package.sh | bash + +breakage: + curl -s $(baseUrl)/check-api-breakage.sh | bash symlinks: curl -s $(baseUrl)/check-broken-symlinks.sh | bash From 8b8fdeee07215c8d27adc986d87d50734d7f1a3b Mon Sep 17 00:00:00 2001 From: GErP83 Date: Mon, 9 Feb 2026 14:42:32 +0100 Subject: [PATCH 07/11] Update testing.yml --- .github/workflows/testing.yml | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/.github/workflows/testing.yml b/.github/workflows/testing.yml index a927259..f51b603 100644 --- a/.github/workflows/testing.yml +++ b/.github/workflows/testing.yml @@ -31,13 +31,7 @@ jobs: uses: BinaryBirds/github-workflows/.github/workflows/extra_soundness.yml@main with: local_swift_dependencies_check_enabled : true + run_tests_with_cache_enabled : true headers_check_enabled : false docc_warnings_check_enabled : true - - swiftlang_tests: - name: Swiftlang Tests - uses: swiftlang/github-workflows/.github/workflows/swift_package_test.yml@main - with: - enable_windows_checks : false - linux_build_command: "swift test --parallel --enable-code-coverage" - linux_exclude_swift_versions: "[{\"swift_version\": \"5.8\"}, {\"swift_version\": \"5.9\"}, {\"swift_version\": \"5.10\"}, {\"swift_version\": \"nightly\"}, {\"swift_version\": \"nightly-main\"}, {\"swift_version\": \"6.0\"}, {\"swift_version\": \"nightly-6.0\"}, {\"swift_version\": \"nightly-6.1\"}, {\"swift_version\": \"nightly-6.3\"}]" \ No newline at end of file + run_tests_swift_versions: '["6.1","6.2"]' \ No newline at end of file From 8d609181690af84b8b3f7599cb32e95e73430457 Mon Sep 17 00:00:00 2001 From: GErP83 Date: Mon, 9 Feb 2026 15:26:19 +0100 Subject: [PATCH 08/11] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 823d7d2..6b39363 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ Declarative HTTP specification testing for Swift, providing a shared API surface ## Requirements ![Swift 6.1+](https://img.shields.io/badge/Swift-6%2E1%2B-F05138) -![Platforms: macOS, iOS, tvOS, watchOS, visionOS](https://img.shields.io/badge/Platforms-macOS_%7C_iOS_%7C_tvOS_%7C_watchOS_%7C_visionOS-F05138) +![Platforms: Linux, macOS, iOS, tvOS, watchOS, visionOS](https://img.shields.io/badge/Platforms-Linux_%7C_macOS_%7C_iOS_%7C_tvOS_%7C_watchOS_%7C_visionOS-F05138) - Swift 6.1+ - Platforms: From 7be8bd476e9e66d9424eaad7eba2147faef56847 Mon Sep 17 00:00:00 2001 From: GErP83 Date: Mon, 9 Feb 2026 15:40:45 +0100 Subject: [PATCH 09/11] Update testing.yml --- .github/workflows/testing.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/testing.yml b/.github/workflows/testing.yml index f51b603..fe7fad0 100644 --- a/.github/workflows/testing.yml +++ b/.github/workflows/testing.yml @@ -9,7 +9,7 @@ jobs: api_breakage: name: Check API breakage - uses: BinaryBirds/github-workflows/.github/workflows/api_breakage.yml@feature/breakage-workflow + uses: BinaryBirds/github-workflows/.github/workflows/api_breakage.yml@main swiftlang_checks: name: Swiftlang Checks From fd52a33d29478e204428d703da25e3a8602f1bc4 Mon Sep 17 00:00:00 2001 From: GErP83 Date: Tue, 10 Feb 2026 10:54:23 +0100 Subject: [PATCH 10/11] Update SpecRunner.swift --- Sources/FeatherSpec/Protocols/SpecRunner.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Sources/FeatherSpec/Protocols/SpecRunner.swift b/Sources/FeatherSpec/Protocols/SpecRunner.swift index 8bad4fb..58a38bc 100644 --- a/Sources/FeatherSpec/Protocols/SpecRunner.swift +++ b/Sources/FeatherSpec/Protocols/SpecRunner.swift @@ -7,7 +7,7 @@ /// SpecRunner. /// /// Conforming types provide the execution environment for one or more specs. -public protocol SpecRunner: Sendable { +public protocol SpecRunner { /// Asynchronously tests a specification. /// From a636d5bf56951a81d58c243ab832cdc815b6aa24 Mon Sep 17 00:00:00 2001 From: GErP83 Date: Tue, 10 Feb 2026 20:42:34 +0100 Subject: [PATCH 11/11] Update SpecRunner.swift --- Sources/FeatherSpec/Protocols/SpecRunner.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Sources/FeatherSpec/Protocols/SpecRunner.swift b/Sources/FeatherSpec/Protocols/SpecRunner.swift index 58a38bc..8bad4fb 100644 --- a/Sources/FeatherSpec/Protocols/SpecRunner.swift +++ b/Sources/FeatherSpec/Protocols/SpecRunner.swift @@ -7,7 +7,7 @@ /// SpecRunner. /// /// Conforming types provide the execution environment for one or more specs. -public protocol SpecRunner { +public protocol SpecRunner: Sendable { /// Asynchronously tests a specification. ///