diff --git a/Package.swift b/Package.swift index 1d980d92b..e60b66235 100644 --- a/Package.swift +++ b/Package.swift @@ -31,7 +31,7 @@ var package = Package( ] ), .testTarget( - name: "ComposableLoadableXCTests", + name: "ComposableLoadableTests", dependencies: [ "CommonTestHelpers", "ComposableLoadable", diff --git a/Package@swift-5.10.swift b/Package@swift-5.10.swift deleted file mode 100644 index 7a75f831c..000000000 --- a/Package@swift-5.10.swift +++ /dev/null @@ -1,52 +0,0 @@ -// swift-tools-version: 5.10 -import PackageDescription - -var package = Package( - name: "swift-composable-loadable", - platforms: [ - .macOS(.v13), - .iOS(.v16), - .tvOS(.v16), - .watchOS(.v9), - ], - products: [ - .library(name: "ComposableLoadable", targets: ["ComposableLoadable"]) - ], - dependencies: [ - .package(url: "https://github.com/apple/swift-docc-plugin", from: "1.3.0"), - .package(url: "https://github.com/apple/swift-testing", from: "0.7.0"), - .package(url: "https://github.com/pointfreeco/swift-composable-architecture", from: "1.10.0"), - ], - targets: [ - .target( - name: "ComposableLoadable", - dependencies: [ - .composableArchitecture - ] - ), - .target( - name: "CommonTestHelpers", - dependencies: [ - "ComposableLoadable", - .composableArchitecture, - ] - ), - .testTarget( - name: "ComposableLoadableTests", - dependencies: [ - "CommonTestHelpers", - "ComposableLoadable", - .swiftTesting, - ] - ), - ] -) - -extension Target.Dependency { - static let composableArchitecture: Target.Dependency = .product( - name: "ComposableArchitecture", package: "swift-composable-architecture" - ) - static let swiftTesting: Target.Dependency = .product( - name: "Testing", package: "swift-testing" - ) -} diff --git a/README.md b/README.md index 1e3aad39a..24230ec71 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # swift-composable-loadable -[![CI/CD](https://github.com/danthorpe/swift-composable-loadable/actions/workflows/main.yml/badge.svg)](https://github.com/danthorpe/swift-composable-loadable/actions/workflows/main.yml) +[![CI/CD](https://github.com/danthorpe/swift-composable-loadable/actions/workflows/main.yml/badge.svg)](https://github.com/danthorpe/swift-composable-loadable/actions/workflows/main.yml) [![codecov](https://codecov.io/github/danthorpe/swift-composable-loadable/graph/badge.svg?token=4RI5GTSZ4F)](https://codecov.io/github/danthorpe/swift-composable-loadable) A Swift Composable Architecture component for loadable features. diff --git a/Tests/ComposableLoadableTests/LoadableActionTests.swift b/Tests/ComposableLoadableTests/LoadableActionTests.swift index 5c58910e4..b976fcc3b 100644 --- a/Tests/ComposableLoadableTests/LoadableActionTests.swift +++ b/Tests/ComposableLoadableTests/LoadableActionTests.swift @@ -1,34 +1,32 @@ import ComposableArchitecture -import Testing +import XCTest @testable import CommonTestHelpers @testable import ComposableLoadable -@Suite("LoadableAction Tests") -struct LoadableActionTests { +final class LoadableActionTests: XCTestCase { - @Test("Equatable Conformance") - func equatableConformance() { + func test__equatable_conformances() { typealias Action = LoadingActionWith - #expect(Action.cancel == Action.cancel) - #expect(Action.refresh == Action.refresh) - #expect(Action.cancel != Action.refresh) - #expect(Action.load("Hello") == Action.load("Hello")) - #expect(Action.load("Hello") != Action.load("Goodbye")) - #expect(Action.finished("Hello", .success(100)) == Action.finished("Hello", .success(100))) - #expect(Action.finished("Hello", .success(100)) != Action.finished("Hello", .success(200))) - #expect(Action.finished("Hello", .success(100)) != Action.finished("Goodbye", .success(100))) - #expect( + XCTAssertEqual(Action.cancel, Action.cancel) + XCTAssertEqual(Action.refresh, Action.refresh) + XCTAssertNotEqual(Action.cancel, Action.refresh) + XCTAssertEqual(Action.load("Hello"), Action.load("Hello")) + XCTAssertNotEqual(Action.load("Hello"), Action.load("Goodbye")) + XCTAssertEqual(Action.finished("Hello", .success(100)), Action.finished("Hello", .success(100))) + XCTAssertNotEqual(Action.finished("Hello", .success(100)), Action.finished("Hello", .success(200))) + XCTAssertNotEqual(Action.finished("Hello", .success(100)), Action.finished("Goodbye", .success(100))) + XCTAssertEqual( + Action.finished("Hello", .failure(EquatableErrorA())), Action.finished("Hello", .failure(EquatableErrorA())) - == Action.finished("Hello", .failure(EquatableErrorA())) ) - #expect( - Action.finished("Hello", .failure(EquatableErrorA())) - != Action.finished("Goodbye", .failure(EquatableErrorA())) + XCTAssertNotEqual( + Action.finished("Hello", .failure(EquatableErrorA())), + Action.finished("Goodbye", .failure(EquatableErrorA())) ) - #expect( - Action.finished("Hello", .failure(EquatableErrorA())) - != Action.finished("Hello", .failure(EquatableErrorB())) + XCTAssertNotEqual( + Action.finished("Hello", .failure(EquatableErrorA())), + Action.finished("Hello", .failure(EquatableErrorB())) ) } } diff --git a/Tests/ComposableLoadableTests/LoadableReducerTests.swift b/Tests/ComposableLoadableTests/LoadableReducerTests.swift index 33d900082..79587e564 100644 --- a/Tests/ComposableLoadableTests/LoadableReducerTests.swift +++ b/Tests/ComposableLoadableTests/LoadableReducerTests.swift @@ -1,24 +1,21 @@ import ComposableArchitecture -import Testing +import XCTest @testable import CommonTestHelpers @testable import ComposableLoadable -@Suite("Reducer Basics") -@MainActor struct ReducerBasicTests { - - let request = "Hello" - fileprivate let store = TestStore(initialState: ParentFeature.State()) { - ParentFeature() - } withDependencies: { - $0.testClient.getValue = { input in - #expect(input == "Hello") - return 100 +final class ReducerBasicTests: XCTestCase { + + @MainActor func test__happy_path() async throws { + let request = "Hello" + let store = TestStore(initialState: ParentFeature.State()) { + ParentFeature() + } withDependencies: { + $0.testClient.getValue = { input in + XCTAssertEqual(input, "Hello") + return 100 + } } - } - - @Test("Happy Path Journey") - func happyPath() async throws { await store.send(.counter(.load(request))) { $0.$counter.previous = .pending @@ -31,7 +28,7 @@ import Testing } store.dependencies.testClient.getValue = { input in - #expect(input == request) + XCTAssertEqual(input, request) return 200 } @@ -47,7 +44,7 @@ import Testing let expectedError = TestFeatureClientError() store.dependencies.testClient.getValue = { input in - #expect(input == request) + XCTAssertEqual(input, request) throw expectedError } @@ -62,8 +59,16 @@ import Testing } } - @Test("Child Reducer") - func childReducer() async throws { + @MainActor func test__child_reducer() async throws { + let request = "Hello" + let store = TestStore(initialState: ParentFeature.State()) { + ParentFeature() + } withDependencies: { + $0.testClient.getValue = { input in + XCTAssertEqual(input, "Hello") + return 100 + } + } await store.send(.counter(.load(request))) { $0.$counter.previous = .pending diff --git a/Tests/ComposableLoadableTests/LoadableStateTests.swift b/Tests/ComposableLoadableTests/LoadableStateTests.swift index 17b45f3a6..00de272fc 100644 --- a/Tests/ComposableLoadableTests/LoadableStateTests.swift +++ b/Tests/ComposableLoadableTests/LoadableStateTests.swift @@ -1,120 +1,93 @@ -import Testing +import Foundation +import XCTest @testable import CommonTestHelpers @testable import ComposableLoadable -@Suite("LoadableState Tests") -struct LoadableStateTests { +final class LoadableStateTests: XCTest { - @Test("isPending") - func isPending() { + func test__isPending() { let state = LoadableState.pending - #expect(state.isPending) - #expect(false == state.isActive) - #expect(false == state.isFailure) - #expect(false == state.isSuccess) - #expect(nil == state.request) - #expect(nil == state.value) + XCTAssertTrue(state.isPending) + XCTAssertFalse(state.isActive) + XCTAssertFalse(state.isFailure) + XCTAssertFalse(state.isSuccess) + XCTAssertNil(state.request) + XCTAssertNil(state.value) } - @Test("isActive") - func isActive() { + func test__isActive() { let state = LoadableState(current: .active) - #expect(state.isActive) - #expect(false == state.isPending) - #expect(false == state.isFailure) - #expect(false == state.isSuccess) - #expect(state.request == EmptyLoadRequest()) + XCTAssertTrue(state.isActive) + XCTAssertFalse(state.isPending) + XCTAssertFalse(state.isFailure) + XCTAssertFalse(state.isSuccess) + XCTAssertEqual(state.request, EmptyLoadRequest()) } - @Test("isLoaded Success") - func isLoadedSuccess() { + func test__isLoadedSuccess() { let state = LoadableState(success: TestState(value: 100)) - #expect(state.isSuccess) - #expect(false == state.isActive) - #expect(false == state.isPending) - #expect(false == state.isFailure) - #expect(state.request == EmptyLoadRequest()) - #expect(state.wrappedValue == TestState(value: 100)) + XCTAssertTrue(state.isSuccess) + XCTAssertFalse(state.isActive) + XCTAssertFalse(state.isPending) + XCTAssertFalse(state.isFailure) + XCTAssertEqual(state.request, EmptyLoadRequest()) + XCTAssertEqual(state.wrappedValue, TestState(value: 100)) } - @Test("isLoaded Failure") - func isLoadedFailure() { + func test__isLoadedFailure() { var state = LoadableState(current: .active, previous: .pending) state.finish(EmptyLoadRequest(), result: .failure(EquatableErrorA())) - #expect(state.isFailure) - #expect(false == state.isSuccess) - #expect(false == state.isActive) - #expect(false == state.isPending) - #expect(state.request == EmptyLoadRequest()) + XCTAssertTrue(state.isFailure) + XCTAssertFalse(state.isSuccess) + XCTAssertFalse(state.isActive) + XCTAssertFalse(state.isPending) + XCTAssertEqual(state.request, EmptyLoadRequest()) } - @Test("Set loadedValue to nil") - func setLoadedValueToNil() { + func test__setLoadedValueToNil() { var state = LoadableState.pending state.loadedValue = nil - #expect(state.isPending) - #expect(false == state.isActive) - #expect(false == state.isFailure) - #expect(false == state.isSuccess) - #expect(nil == state.request) + XCTAssertTrue(state.isPending) + XCTAssertFalse(state.isActive) + XCTAssertFalse(state.isFailure) + XCTAssertFalse(state.isSuccess) + XCTAssertNil(state.request) state.loadedFailure = nil - #expect(state.isPending) - #expect(false == state.isActive) - #expect(false == state.isFailure) - #expect(false == state.isSuccess) - #expect(nil == state.request) + XCTAssertTrue(state.isPending) + XCTAssertFalse(state.isActive) + XCTAssertFalse(state.isFailure) + XCTAssertFalse(state.isSuccess) + XCTAssertNil(state.request) } - @Test("Basic happy path") - func basicHappyPath() { + func test__basicHappyPath() { var state = LoadableState.pending - #expect(nil == state.wrappedValue) - #expect(nil == state.loadedValue) - #expect(nil == state.loadedFailure) + XCTAssertNil(state.wrappedValue) + XCTAssertNil(state.loadedValue) + XCTAssertNil(state.loadedFailure) state.wrappedValue = nil - #expect(nil == state.wrappedValue) - #expect(nil == state.loadedValue) - #expect(nil == state.loadedFailure) + XCTAssertNil(state.wrappedValue) + XCTAssertNil(state.loadedValue) + XCTAssertNil(state.loadedFailure) state.becomeActive() - #expect(state.isActive) - #expect(false == state.isPending) - #expect(false == state.isFailure) - #expect(false == state.isSuccess) - #expect(state.request == EmptyLoadRequest()) + XCTAssertTrue(state.isActive) + XCTAssertNil(state.isPending) + XCTAssertNil(state.isFailure) + XCTAssertNil(state.isSuccess) + XCTAssertEqual(state.request, EmptyLoadRequest()) state.wrappedValue = TestState(value: 100) - #expect(state.isSuccess) - #expect(false == state.isActive) - #expect(false == state.isPending) - #expect(false == state.isFailure) - #expect(state.request == EmptyLoadRequest()) - #expect(state.wrappedValue == TestState(value: 100)) - - #expect(state.value == 100) - } - - @Test("Property Wrapper basics") - func propertyWrapperBasics() throws { - @LoadableState var state - #expect(state == nil) - - $state = .active - #expect(state == nil) - - $state.finish(.success(TestState(value: 42))) - #expect(state?.value == 42) - - $state.becomeActive() - #expect(state?.value == 42) - - $state.finish(.failure(EquatableErrorA())) - #expect(state == nil) - #expect($state.isFailure) - let error = try #require($state.error) - #expect(_isEqual(error, EquatableErrorA())) + XCTAssertTrue(state.isSuccess) + XCTAssertNil(state.isActive) + XCTAssertNil(state.isPending) + XCTAssertNil(state.isFailure) + XCTAssertEqual(state.request, EmptyLoadRequest()) + XCTAssertEqual(state.wrappedValue, TestState(value: 100)) + + XCTAssertEqual(state.value, 100) } } diff --git a/Tests/ComposableLoadableTests/Scaffold.swift b/Tests/ComposableLoadableTests/Scaffold.swift deleted file mode 100644 index 0db91a0cf..000000000 --- a/Tests/ComposableLoadableTests/Scaffold.swift +++ /dev/null @@ -1,8 +0,0 @@ -import Testing -import XCTest - -final class AllTests: XCTestCase { - func testAll() async { - await XCTestScaffold.runAllTests(hostedBy: self) - } -} diff --git a/Tests/ComposableLoadableXCTests/LoadableActionTests.swift b/Tests/ComposableLoadableXCTests/LoadableActionTests.swift deleted file mode 100644 index b976fcc3b..000000000 --- a/Tests/ComposableLoadableXCTests/LoadableActionTests.swift +++ /dev/null @@ -1,32 +0,0 @@ -import ComposableArchitecture -import XCTest - -@testable import CommonTestHelpers -@testable import ComposableLoadable - -final class LoadableActionTests: XCTestCase { - - func test__equatable_conformances() { - typealias Action = LoadingActionWith - XCTAssertEqual(Action.cancel, Action.cancel) - XCTAssertEqual(Action.refresh, Action.refresh) - XCTAssertNotEqual(Action.cancel, Action.refresh) - XCTAssertEqual(Action.load("Hello"), Action.load("Hello")) - XCTAssertNotEqual(Action.load("Hello"), Action.load("Goodbye")) - XCTAssertEqual(Action.finished("Hello", .success(100)), Action.finished("Hello", .success(100))) - XCTAssertNotEqual(Action.finished("Hello", .success(100)), Action.finished("Hello", .success(200))) - XCTAssertNotEqual(Action.finished("Hello", .success(100)), Action.finished("Goodbye", .success(100))) - XCTAssertEqual( - Action.finished("Hello", .failure(EquatableErrorA())), - Action.finished("Hello", .failure(EquatableErrorA())) - ) - XCTAssertNotEqual( - Action.finished("Hello", .failure(EquatableErrorA())), - Action.finished("Goodbye", .failure(EquatableErrorA())) - ) - XCTAssertNotEqual( - Action.finished("Hello", .failure(EquatableErrorA())), - Action.finished("Hello", .failure(EquatableErrorB())) - ) - } -} diff --git a/Tests/ComposableLoadableXCTests/LoadableReducerTests.swift b/Tests/ComposableLoadableXCTests/LoadableReducerTests.swift deleted file mode 100644 index 79587e564..000000000 --- a/Tests/ComposableLoadableXCTests/LoadableReducerTests.swift +++ /dev/null @@ -1,101 +0,0 @@ -import ComposableArchitecture -import XCTest - -@testable import CommonTestHelpers -@testable import ComposableLoadable - -final class ReducerBasicTests: XCTestCase { - - @MainActor func test__happy_path() async throws { - let request = "Hello" - let store = TestStore(initialState: ParentFeature.State()) { - ParentFeature() - } withDependencies: { - $0.testClient.getValue = { input in - XCTAssertEqual(input, "Hello") - return 100 - } - } - - await store.send(.counter(.load(request))) { - $0.$counter.previous = .pending - $0.$counter.current = .active(request) - } - - await store.receive(.counter(.finished(request, .success(100)))) { - $0.$counter.previous = .active(request) - $0.$counter.current = .success(.init(request: request, value: 100)) - } - - store.dependencies.testClient.getValue = { input in - XCTAssertEqual(input, request) - return 200 - } - - await store.send(.counter(.refresh)) { - $0.$counter.previous = .success(.init(request: request, value: 100)) - $0.$counter.current = .active(request) - } - - await store.receive(.counter(.finished(request, .success(200)))) { - $0.$counter.previous = .active(request) - $0.$counter.current = .success(.init(request: request, value: 200)) - } - - let expectedError = TestFeatureClientError() - store.dependencies.testClient.getValue = { input in - XCTAssertEqual(input, request) - throw expectedError - } - - await store.send(.counter(.refresh)) { - $0.$counter.previous = .success(.init(request: request, value: 200)) - $0.$counter.current = .active(request) - } - - await store.receive(.counter(.finished(request, .failure(expectedError)))) { - $0.$counter.previous = .active(request) - $0.$counter.current = .failure(.init(request: request, error: expectedError)) - } - } - - @MainActor func test__child_reducer() async throws { - let request = "Hello" - let store = TestStore(initialState: ParentFeature.State()) { - ParentFeature() - } withDependencies: { - $0.testClient.getValue = { input in - XCTAssertEqual(input, "Hello") - return 100 - } - } - - await store.send(.counter(.load(request))) { - $0.$counter.previous = .pending - $0.$counter.current = .active(request) - } - - await store.receive(.counter(.finished(request, .success(100)))) { - $0.$counter.previous = .active(request) - $0.$counter.current = .success(.init(request: request, value: 100)) - } - - await store.send(.counter(.loaded(.incrementButtonTapped))) { - $0.$counter.wrappedValue?.count = 101 - } - - await store.send(.counter(.refresh)) { - $0.$counter.previous = .success(.init(request: request, value: 101)) - $0.$counter.current = .active(request) - } - - await store.receive(.counter(.finished(request, .success(100)))) { - $0.$counter.previous = .active(request) - $0.$counter.current = .success(.init(request: request, value: 100)) - } - - await store.send(.counter(.loaded(.decrementButtonTapped))) { - $0.$counter.wrappedValue?.count = 99 - } - } -} diff --git a/Tests/ComposableLoadableXCTests/LoadableStateTests.swift b/Tests/ComposableLoadableXCTests/LoadableStateTests.swift deleted file mode 100644 index 00de272fc..000000000 --- a/Tests/ComposableLoadableXCTests/LoadableStateTests.swift +++ /dev/null @@ -1,93 +0,0 @@ -import Foundation -import XCTest - -@testable import CommonTestHelpers -@testable import ComposableLoadable - -final class LoadableStateTests: XCTest { - - func test__isPending() { - let state = LoadableState.pending - XCTAssertTrue(state.isPending) - XCTAssertFalse(state.isActive) - XCTAssertFalse(state.isFailure) - XCTAssertFalse(state.isSuccess) - XCTAssertNil(state.request) - XCTAssertNil(state.value) - } - - func test__isActive() { - let state = LoadableState(current: .active) - XCTAssertTrue(state.isActive) - XCTAssertFalse(state.isPending) - XCTAssertFalse(state.isFailure) - XCTAssertFalse(state.isSuccess) - XCTAssertEqual(state.request, EmptyLoadRequest()) - } - - func test__isLoadedSuccess() { - let state = LoadableState(success: TestState(value: 100)) - XCTAssertTrue(state.isSuccess) - XCTAssertFalse(state.isActive) - XCTAssertFalse(state.isPending) - XCTAssertFalse(state.isFailure) - XCTAssertEqual(state.request, EmptyLoadRequest()) - XCTAssertEqual(state.wrappedValue, TestState(value: 100)) - } - - func test__isLoadedFailure() { - var state = LoadableState(current: .active, previous: .pending) - state.finish(EmptyLoadRequest(), result: .failure(EquatableErrorA())) - XCTAssertTrue(state.isFailure) - XCTAssertFalse(state.isSuccess) - XCTAssertFalse(state.isActive) - XCTAssertFalse(state.isPending) - XCTAssertEqual(state.request, EmptyLoadRequest()) - } - - func test__setLoadedValueToNil() { - var state = LoadableState.pending - state.loadedValue = nil - XCTAssertTrue(state.isPending) - XCTAssertFalse(state.isActive) - XCTAssertFalse(state.isFailure) - XCTAssertFalse(state.isSuccess) - XCTAssertNil(state.request) - - state.loadedFailure = nil - XCTAssertTrue(state.isPending) - XCTAssertFalse(state.isActive) - XCTAssertFalse(state.isFailure) - XCTAssertFalse(state.isSuccess) - XCTAssertNil(state.request) - } - - func test__basicHappyPath() { - var state = LoadableState.pending - XCTAssertNil(state.wrappedValue) - XCTAssertNil(state.loadedValue) - XCTAssertNil(state.loadedFailure) - - state.wrappedValue = nil - XCTAssertNil(state.wrappedValue) - XCTAssertNil(state.loadedValue) - XCTAssertNil(state.loadedFailure) - - state.becomeActive() - XCTAssertTrue(state.isActive) - XCTAssertNil(state.isPending) - XCTAssertNil(state.isFailure) - XCTAssertNil(state.isSuccess) - XCTAssertEqual(state.request, EmptyLoadRequest()) - - state.wrappedValue = TestState(value: 100) - XCTAssertTrue(state.isSuccess) - XCTAssertNil(state.isActive) - XCTAssertNil(state.isPending) - XCTAssertNil(state.isFailure) - XCTAssertEqual(state.request, EmptyLoadRequest()) - XCTAssertEqual(state.wrappedValue, TestState(value: 100)) - - XCTAssertEqual(state.value, 100) - } -}