From 461db915469c063666c989feac470b649781080c Mon Sep 17 00:00:00 2001 From: Alexander Kauer Date: Mon, 29 Sep 2025 12:07:34 +0200 Subject: [PATCH 1/6] Expanded generics items on Equatable protocol --- Sources/AsyncLoad/AsyncLoad/AsyncAction.swift | 15 +++++++++++++++ Sources/AsyncLoad/AsyncLoad/AsyncLoad.swift | 15 +++++++++++++++ .../CachedAsyncLoad/CachedAsyncAction.swift | 15 +++++++++++++++ .../CachedAsyncLoad/CachedAsyncLoad.swift | 15 +++++++++++++++ 4 files changed, 60 insertions(+) diff --git a/Sources/AsyncLoad/AsyncLoad/AsyncAction.swift b/Sources/AsyncLoad/AsyncLoad/AsyncAction.swift index 3da666f..7932a8e 100644 --- a/Sources/AsyncLoad/AsyncLoad/AsyncAction.swift +++ b/Sources/AsyncLoad/AsyncLoad/AsyncAction.swift @@ -45,4 +45,19 @@ public enum AsyncAction: Equatable { false } } + + public static func == (lhs: AsyncAction, rhs: AsyncAction) -> Bool where T : Equatable { + switch (lhs, rhs) { + case (.none, .none): + true + case (.loading, .loading): + true + case (.error, .error): + true + case (.success, .success): + rhs.item == lhs.item + default: + false + } + } } diff --git a/Sources/AsyncLoad/AsyncLoad/AsyncLoad.swift b/Sources/AsyncLoad/AsyncLoad/AsyncLoad.swift index 0297b92..d6a9136 100644 --- a/Sources/AsyncLoad/AsyncLoad/AsyncLoad.swift +++ b/Sources/AsyncLoad/AsyncLoad/AsyncLoad.swift @@ -45,4 +45,19 @@ public enum AsyncLoad: Equatable { false } } + + public static func == (lhs: AsyncLoad, rhs: AsyncLoad) -> Bool where T : Equatable { + switch (lhs, rhs) { + case (.none, .none): + true + case (.loading, .loading): + true + case (.error, .error): + true + case (.loaded, .loaded): + lhs == rhs + default: + false + } + } } diff --git a/Sources/AsyncLoad/CachedAsyncLoad/CachedAsyncAction.swift b/Sources/AsyncLoad/CachedAsyncLoad/CachedAsyncAction.swift index c4488c7..cd02549 100644 --- a/Sources/AsyncLoad/CachedAsyncLoad/CachedAsyncAction.swift +++ b/Sources/AsyncLoad/CachedAsyncLoad/CachedAsyncAction.swift @@ -45,4 +45,19 @@ public enum CachedAsyncAction: Equatable { false } } + + public static func == (lhs: CachedAsyncAction, rhs: CachedAsyncAction) -> Bool where T : Equatable { + switch (lhs, rhs) { + case (.none, .none): + true + case (.loading, .loading): + lhs.item == rhs.item + case (.error, .error): + true + case (.success, .success): + lhs.item == rhs.item + default: + false + } + } } diff --git a/Sources/AsyncLoad/CachedAsyncLoad/CachedAsyncLoad.swift b/Sources/AsyncLoad/CachedAsyncLoad/CachedAsyncLoad.swift index 92cfa9a..ba97a8a 100644 --- a/Sources/AsyncLoad/CachedAsyncLoad/CachedAsyncLoad.swift +++ b/Sources/AsyncLoad/CachedAsyncLoad/CachedAsyncLoad.swift @@ -45,4 +45,19 @@ public enum CachedAsyncLoad: Equatable { false } } + + public static func == (lhs: CachedAsyncLoad, rhs: CachedAsyncLoad) -> Bool where T : Equatable { + switch (lhs, rhs) { + case (.none, .none): + true + case (.loading, .loading): + lhs.item == rhs.item + case (.error, .error): + true + case (.loaded, .loaded): + lhs.item == rhs.item + default: + false + } + } } From 927bcc379344e14870aff1e0312afd71ea04a3aa Mon Sep 17 00:00:00 2001 From: Alexander Kauer Date: Mon, 29 Sep 2025 13:37:22 +0200 Subject: [PATCH 2/6] Fixed equatable where T: Equatable, added tests --- Sources/AsyncLoad/AsyncLoad/AsyncAction.swift | 17 +++- Sources/AsyncLoad/AsyncLoad/AsyncLoad.swift | 21 ++++- .../CachedAsyncLoad/CachedAsyncAction.swift | 23 ++++- .../CachedAsyncLoad/CachedAsyncLoad.swift | 25 ++++-- .../AsyncLoadEquatableItemTests.swift | 75 ++++++++++++++++ .../AsyncLoadNonEquatableItemTests.swift | 70 +++++++++++++++ Tests/AsyncLoadTests/AsyncLoadTests.swift | 56 ------------ .../CachedAsyncLoadEquatableItemTests.swift | 85 +++++++++++++++++++ ...CachedAsyncLoadNonEquatableItemTests.swift | 70 +++++++++++++++ Tests/AsyncLoadTests/Utils.swift | 18 ++++ 10 files changed, 391 insertions(+), 69 deletions(-) create mode 100644 Tests/AsyncLoadTests/AsyncLoadEquatableItemTests.swift create mode 100644 Tests/AsyncLoadTests/AsyncLoadNonEquatableItemTests.swift delete mode 100644 Tests/AsyncLoadTests/AsyncLoadTests.swift create mode 100644 Tests/AsyncLoadTests/CachedAsyncLoadEquatableItemTests.swift create mode 100644 Tests/AsyncLoadTests/CachedAsyncLoadNonEquatableItemTests.swift create mode 100644 Tests/AsyncLoadTests/Utils.swift diff --git a/Sources/AsyncLoad/AsyncLoad/AsyncAction.swift b/Sources/AsyncLoad/AsyncLoad/AsyncAction.swift index 7932a8e..466940d 100644 --- a/Sources/AsyncLoad/AsyncLoad/AsyncAction.swift +++ b/Sources/AsyncLoad/AsyncLoad/AsyncAction.swift @@ -55,7 +55,22 @@ public enum AsyncAction: Equatable { case (.error, .error): true case (.success, .success): - rhs.item == lhs.item + lhs.item == rhs.item + default: + false + } + } + + public static func != (lhs: AsyncAction, rhs: AsyncAction) -> Bool where T : Equatable { + switch (lhs, rhs) { + case (.none, .none): + true + case (.loading, .loading): + true + case (.error, .error): + true + case let (.success(lhsItem), .success(rhsItem)): + lhsItem != rhsItem default: false } diff --git a/Sources/AsyncLoad/AsyncLoad/AsyncLoad.swift b/Sources/AsyncLoad/AsyncLoad/AsyncLoad.swift index d6a9136..00242d8 100644 --- a/Sources/AsyncLoad/AsyncLoad/AsyncLoad.swift +++ b/Sources/AsyncLoad/AsyncLoad/AsyncLoad.swift @@ -1,6 +1,6 @@ import Foundation -public enum AsyncLoad: Equatable { +public enum AsyncLoad : Equatable { case none case loading case error(Error) @@ -54,10 +54,25 @@ public enum AsyncLoad: Equatable { true case (.error, .error): true - case (.loaded, .loaded): - lhs == rhs + case let (.loaded(lhsItem), .loaded(rhsItem)): + lhsItem == rhsItem default: false } } + + public static func != (lhs: AsyncLoad, rhs: AsyncLoad) -> Bool where T : Equatable { + switch (lhs, rhs) { + case (.none, .none): + false + case (.loading, .loading): + false + case (.error, .error): + false + case let (.loaded(rhsItem), .loaded(lhsItem)): + lhsItem != rhsItem + default: + true + } + } } diff --git a/Sources/AsyncLoad/CachedAsyncLoad/CachedAsyncAction.swift b/Sources/AsyncLoad/CachedAsyncLoad/CachedAsyncAction.swift index cd02549..ebac0c9 100644 --- a/Sources/AsyncLoad/CachedAsyncLoad/CachedAsyncAction.swift +++ b/Sources/AsyncLoad/CachedAsyncLoad/CachedAsyncAction.swift @@ -50,12 +50,27 @@ public enum CachedAsyncAction: Equatable { switch (lhs, rhs) { case (.none, .none): true - case (.loading, .loading): - lhs.item == rhs.item + case let (.loading(lhsItem), .loading(rhsItem)): + lhsItem == rhsItem case (.error, .error): true - case (.success, .success): - lhs.item == rhs.item + case let (.success(lhsItem), .success(rhsItem)): + lhsItem == rhsItem + default: + false + } + } + + public static func != (lhs: CachedAsyncAction, rhs: CachedAsyncAction) -> Bool where T : Equatable { + switch (lhs, rhs) { + case (.none, .none): + false + case let (.loading(lhsItem), .loading(rhsItem)): + lhsItem != rhsItem + case (.error, .error): + false + case let (.success(lhsItem), .success(rhsItem)): + lhsItem != rhsItem default: false } diff --git a/Sources/AsyncLoad/CachedAsyncLoad/CachedAsyncLoad.swift b/Sources/AsyncLoad/CachedAsyncLoad/CachedAsyncLoad.swift index ba97a8a..75b9b65 100644 --- a/Sources/AsyncLoad/CachedAsyncLoad/CachedAsyncLoad.swift +++ b/Sources/AsyncLoad/CachedAsyncLoad/CachedAsyncLoad.swift @@ -50,12 +50,27 @@ public enum CachedAsyncLoad: Equatable { switch (lhs, rhs) { case (.none, .none): true - case (.loading, .loading): - lhs.item == rhs.item - case (.error, .error): + case let (.loading(lhsItem), .loading(rhsItem)): + lhsItem == rhsItem + case let (.error(lhsItem, _), .error(rhsItem, _)): + lhsItem == rhsItem + case let (.loaded( lhsItem), .loaded(rhsItem)): + lhsItem == rhsItem + default: + false + } + } + + public static func != (lhs: CachedAsyncLoad, rhs: CachedAsyncLoad) -> Bool where T : Equatable { + switch (lhs, rhs) { + case (.none, .none): true - case (.loaded, .loaded): - lhs.item == rhs.item + case let (.loading(lhsItem), .loading(rhsItem)): + lhsItem != rhsItem + case let (.error(lhsItem, _), .error(rhsItem, _)): + lhsItem != rhsItem + case let (.loaded( lhsItem), .loaded(rhsItem)): + lhsItem != rhsItem default: false } diff --git a/Tests/AsyncLoadTests/AsyncLoadEquatableItemTests.swift b/Tests/AsyncLoadTests/AsyncLoadEquatableItemTests.swift new file mode 100644 index 0000000..51bc3b8 --- /dev/null +++ b/Tests/AsyncLoadTests/AsyncLoadEquatableItemTests.swift @@ -0,0 +1,75 @@ +import Testing +@testable import AsyncLoad + +@Suite("Test equatable AsyncLoad") +struct AsyncLoadEquatableItemTests { + @Test func testNone() async throws { + let load1: AsyncLoad = .none + let load2: AsyncLoad = .none + + #expect(load1 == load2) + } + + @Test func testLoadedString() async throws { + var load1: AsyncLoad = .loaded("Some") + var load2: AsyncLoad = .loaded("Some") + + #expect(load1 == load2) + + load1 = .loaded("Other") + load2 = .loaded("Other1") + + #expect(load1 != load2) + } + + @Test func testLoadedUser() async throws { + var load1: AsyncLoad = .loaded(User(name: "Some")) + var load2: AsyncLoad = .loaded(User(name: "Some")) + + #expect(load1 == load2) + + load1 = .loaded(User(name: "Alex")) + load2 = .loaded(User(name: "Daniel")) + + #expect(load1 != load2) + } + + @Test func testError() async throws { + var load1: AsyncLoad = .error(TestingError.some) + var load2: AsyncLoad = .error(TestingError.some) + + #expect(load1 == load2) + + load1 = .error(TestingError.some) + load2 = .error(TestingError.other) + + #expect(load1 == load2) + } + + @Test func testMultiple() async throws { + var load1: AsyncLoad = .none + var load2: AsyncLoad = .none + + #expect(load1 == load2) + + load1 = .loading + load2 = .loading + + #expect(load1 == load2) + + load1 = .loaded("Some") + load2 = .loaded("Other") + + #expect(load1 != load2) + + load1 = .loaded("some") + load2 = .loaded("some") + + #expect(load1 == load2) + + load1 = .error(TestingError.some) + load2 = .error(TestingError.some) + + #expect(load1 == load2) + } +} diff --git a/Tests/AsyncLoadTests/AsyncLoadNonEquatableItemTests.swift b/Tests/AsyncLoadTests/AsyncLoadNonEquatableItemTests.swift new file mode 100644 index 0000000..d2a1098 --- /dev/null +++ b/Tests/AsyncLoadTests/AsyncLoadNonEquatableItemTests.swift @@ -0,0 +1,70 @@ +import Testing +@testable import AsyncLoad + +@Suite("Test non-equatable AsyncLoad") +struct AsyncLoadNonEquatableItemTests { + @Test func testNone() async throws { + let load1: AsyncLoad = .none + let load2: AsyncLoad = .none + + #expect(load1 == load2) + } + + @Test func testLoadedString() async throws { + var load1: AsyncLoad = .loaded(NonEquatableItem(name: "Hello")) + var load2: AsyncLoad = .loaded(NonEquatableItem(name: "Hello")) + + #expect(load1 == load2) + + load1 = .loaded(NonEquatableItem(name: "Some")) + load2 = .loaded(NonEquatableItem(name: "Other")) + + #expect(load1 == load2) + } + + @Test func testLoading() async throws { + let load1: AsyncLoad = .loading + let load2: AsyncLoad = .loading + + #expect(load1 == load2) + } + + @Test func testError() async throws { + var load1: AsyncLoad = .error(TestingError.some) + var load2: AsyncLoad = .error(TestingError.some) + + #expect(load1 == load2) + + load1 = .error(TestingError.some) + load2 = .error(TestingError.other) + + #expect(load1 == load2) + } + + @Test func testMultiple() async throws { + var load1: AsyncLoad = .none + var load2: AsyncLoad = .none + + #expect(load1 == load2) + + load1 = .loading + load2 = .loading + + #expect(load1 == load2) + + load1 = .loaded(NonEquatableItem(name: "Some")) + load2 = .loaded(NonEquatableItem(name: "Some")) + + #expect(load1 == load2) + + load1 = .loaded(NonEquatableItem(name: "Some")) + load2 = .loaded(NonEquatableItem(name: "Other")) + + #expect(load1 == load2) + + load1 = .error(TestingError.some) + load2 = .error(TestingError.some) + + #expect(load1 == load2) + } +} diff --git a/Tests/AsyncLoadTests/AsyncLoadTests.swift b/Tests/AsyncLoadTests/AsyncLoadTests.swift deleted file mode 100644 index 1cbecb5..0000000 --- a/Tests/AsyncLoadTests/AsyncLoadTests.swift +++ /dev/null @@ -1,56 +0,0 @@ -import Testing -@testable import AsyncLoad - -enum TestingError: Error { - case some -} - -@Test func testAsyncLoadEquatable() async throws { - var load1: AsyncLoad = .none - var load2: AsyncLoad = .none - - #expect(load1 == load2) - - load1 = .loading - load2 = .loading - - #expect(load1 == load2) - - load1 = .loaded("some") - load2 = .loaded("other") - - #expect(load1 == load2) - - load1 = .error(TestingError.some) - load2 = .error(TestingError.some) - - #expect(load1 == load2) -} - - -@Test func testCachedAsyncLoadEquatable() async throws { - var load1: CachedAsyncLoad = .none - var load2: CachedAsyncLoad = .none - - #expect(load1 == load2) - - load1 = .loading() - load2 = .loading() - - #expect(load1 == load2) - - load1 = .loaded("some") - load2 = .loaded("other") - - #expect(load1 == load2) - - load1 = .loading("some") - load2 = .loading("other") - - #expect(load1 == load2) - - load1 = .error("some", TestingError.some) - load2 = .error(nil, TestingError.some) - - #expect(load1 == load2) -} diff --git a/Tests/AsyncLoadTests/CachedAsyncLoadEquatableItemTests.swift b/Tests/AsyncLoadTests/CachedAsyncLoadEquatableItemTests.swift new file mode 100644 index 0000000..2f56afa --- /dev/null +++ b/Tests/AsyncLoadTests/CachedAsyncLoadEquatableItemTests.swift @@ -0,0 +1,85 @@ +import Testing +@testable import AsyncLoad + +@Suite("Test equatable CachedAsyncLoad") +struct CachedAsyncLoadEquatableItemTests { + @Test func testNone() async throws { + let load1: CachedAsyncLoad = .none + let load2: CachedAsyncLoad = .none + + #expect(load1 == load2) + } + + @Test func testLoadedString() async throws { + var load1: CachedAsyncLoad = .loaded("Some") + var load2: CachedAsyncLoad = .loaded("Some") + + #expect(load1 == load2) + + load1 = .loaded("Other") + load2 = .loaded("Other1") + + #expect(load1 != load2) + } + + @Test func testLoadedUser() async throws { + var load1: CachedAsyncLoad = .loaded(User(name: "Some")) + var load2: CachedAsyncLoad = .loaded(User(name: "Some")) + + #expect(load1 == load2) + + load1 = .loaded(User(name: "Alex")) + load2 = .loaded(User(name: "Daniel")) + + #expect(load1 != load2) + } + + @Test func testError() async throws { + var load1: CachedAsyncLoad = .error("some", TestingError.some) + var load2: CachedAsyncLoad = .error("some", TestingError.some) + + #expect(load1 == load2) + + load1 = .error(nil, TestingError.some) + load2 = .error("some", TestingError.some) + + #expect(load1 != load2) + + load1 = .error(nil, TestingError.some) + load2 = .error("some", TestingError.other) + + #expect(load1 != load2) + } + + @Test func testMultiple() async throws { + var load1: CachedAsyncLoad = .none + var load2: CachedAsyncLoad = .none + + #expect(load1 == load2) + + load1 = .loading() + load2 = .loading() + + #expect(load1 == load2) + + load1 = .loaded("some") + load2 = .loaded("some") + + #expect(load1 == load2) + + load1 = .loading("some") + load2 = .loading("other") + + #expect(load1 != load2) + + load1 = .loading() + load2 = .loading() + + #expect(load1 == load2) + + load1 = .error("some", TestingError.some) + load2 = .error(nil, TestingError.some) + + #expect(load1 != load2) + } +} diff --git a/Tests/AsyncLoadTests/CachedAsyncLoadNonEquatableItemTests.swift b/Tests/AsyncLoadTests/CachedAsyncLoadNonEquatableItemTests.swift new file mode 100644 index 0000000..3f50d36 --- /dev/null +++ b/Tests/AsyncLoadTests/CachedAsyncLoadNonEquatableItemTests.swift @@ -0,0 +1,70 @@ +import Testing +@testable import AsyncLoad + +@Suite("Test non-equatable CachedAsyncLoad") +struct CachedAsyncLoadNonEquatableItemTests { + @Test func testNone() async throws { + let load1: CachedAsyncLoad = .none + let load2: CachedAsyncLoad = .none + + #expect(load1 == load2) + } + + @Test func testLoadedString() async throws { + var load1: CachedAsyncLoad = .loaded(NonEquatableItem(name: "Hello")) + var load2: CachedAsyncLoad = .loaded(NonEquatableItem(name: "Hello")) + + #expect(load1 == load2) + + load1 = .loaded(NonEquatableItem(name: "Some")) + load2 = .loaded(NonEquatableItem(name: "Other")) + + #expect(load1 == load2) + } + + @Test func testLoading() async throws { + let load1: CachedAsyncLoad = .loading() + let load2: CachedAsyncLoad = .loading() + + #expect(load1 == load2) + } + + @Test func testError() async throws { + var load1: CachedAsyncLoad = .error(nil, TestingError.some) + var load2: CachedAsyncLoad = .error(nil, TestingError.some) + + #expect(load1 == load2) + + load1 = .error(nil, TestingError.some) + load2 = .error(NonEquatableItem(name: "Hello"), TestingError.other) + + #expect(load1 == load2) + } + + @Test func testMultiple() async throws { + var load1: CachedAsyncLoad = .none + var load2: CachedAsyncLoad = .none + + #expect(load1 == load2) + + load1 = .loading() + load2 = .loading() + + #expect(load1 == load2) + + load1 = .loaded(NonEquatableItem(name: "Some")) + load2 = .loaded(NonEquatableItem(name: "Some")) + + #expect(load1 == load2) + + load1 = .loaded(NonEquatableItem(name: "Some")) + load2 = .loaded(NonEquatableItem(name: "Other")) + + #expect(load1 == load2) + + load1 = .error(NonEquatableItem(name: "Hello"), TestingError.some) + load2 = .error(NonEquatableItem(name: "Hello"), TestingError.some) + + #expect(load1 == load2) + } +} diff --git a/Tests/AsyncLoadTests/Utils.swift b/Tests/AsyncLoadTests/Utils.swift new file mode 100644 index 0000000..80dc623 --- /dev/null +++ b/Tests/AsyncLoadTests/Utils.swift @@ -0,0 +1,18 @@ +import Foundation + +enum TestingError: Error { + case some + case other +} + +class NonEquatableItem { + let name: String + + init(name: String) { + self.name = name + } +} + +struct User: Equatable { + let name: String +} From 62248b8961720142844427dab801792464974dba Mon Sep 17 00:00:00 2001 From: Alexander Kauer Date: Mon, 29 Sep 2025 13:55:20 +0200 Subject: [PATCH 3/6] Added AsyncAction and CachedAsyncAction tests --- .../CachedAsyncLoad/CachedAsyncAction.swift | 8 +- .../AsyncActionEquatableItemTests.swift | 75 ++++++++++++++++ .../AsyncActionNonEquatableItemTests.swift | 70 +++++++++++++++ .../CachedAsyncActionEquatableItemTests.swift | 85 +++++++++++++++++++ ...chedAsyncActionNonEquatableItemTests.swift | 70 +++++++++++++++ 5 files changed, 304 insertions(+), 4 deletions(-) create mode 100644 Tests/AsyncLoadTests/AsyncActionEquatableItemTests.swift create mode 100644 Tests/AsyncLoadTests/AsyncActionNonEquatableItemTests.swift create mode 100644 Tests/AsyncLoadTests/CachedAsyncActionEquatableItemTests.swift create mode 100644 Tests/AsyncLoadTests/CachedAsyncActionNonEquatableItemTests.swift diff --git a/Sources/AsyncLoad/CachedAsyncLoad/CachedAsyncAction.swift b/Sources/AsyncLoad/CachedAsyncLoad/CachedAsyncAction.swift index ebac0c9..6f4ff1c 100644 --- a/Sources/AsyncLoad/CachedAsyncLoad/CachedAsyncAction.swift +++ b/Sources/AsyncLoad/CachedAsyncLoad/CachedAsyncAction.swift @@ -52,8 +52,8 @@ public enum CachedAsyncAction: Equatable { true case let (.loading(lhsItem), .loading(rhsItem)): lhsItem == rhsItem - case (.error, .error): - true + case let (.error(lhsItem, _), .error(rhsItem, _)): + lhsItem == rhsItem case let (.success(lhsItem), .success(rhsItem)): lhsItem == rhsItem default: @@ -67,8 +67,8 @@ public enum CachedAsyncAction: Equatable { false case let (.loading(lhsItem), .loading(rhsItem)): lhsItem != rhsItem - case (.error, .error): - false + case let (.error(lhsItem, _), .error(rhsItem, _)): + lhsItem != rhsItem case let (.success(lhsItem), .success(rhsItem)): lhsItem != rhsItem default: diff --git a/Tests/AsyncLoadTests/AsyncActionEquatableItemTests.swift b/Tests/AsyncLoadTests/AsyncActionEquatableItemTests.swift new file mode 100644 index 0000000..28b8d50 --- /dev/null +++ b/Tests/AsyncLoadTests/AsyncActionEquatableItemTests.swift @@ -0,0 +1,75 @@ +import Testing +@testable import AsyncLoad + +@Suite("Test equatable AsyncAction") +struct AsyncActionEquatableItemTests { + @Test func testNone() async throws { + let action1: AsyncAction = .none + let action2: AsyncAction = .none + + #expect(action1 == action2) + } + + @Test func testLoadedString() async throws { + var action1: AsyncAction = .success("Some") + var action2: AsyncAction = .success("Some") + + #expect(action1 == action2) + + action1 = .success("Other") + action2 = .success("Other1") + + #expect(action1 != action2) + } + + @Test func testLoadedUser() async throws { + var action1: AsyncAction = .success(User(name: "Some")) + var action2: AsyncAction = .success(User(name: "Some")) + + #expect(action1 == action2) + + action1 = .success(User(name: "Alex")) + action2 = .success(User(name: "Daniel")) + + #expect(action1 != action2) + } + + @Test func testError() async throws { + var action1: AsyncAction = .error(TestingError.some) + var action2: AsyncAction = .error(TestingError.some) + + #expect(action1 == action2) + + action1 = .error(TestingError.some) + action2 = .error(TestingError.other) + + #expect(action1 == action2) + } + + @Test func testMultiple() async throws { + var action1: AsyncAction = .none + var action2: AsyncAction = .none + + #expect(action1 == action2) + + action1 = .loading + action2 = .loading + + #expect(action1 == action2) + + action1 = .success("Some") + action2 = .success("Other") + + #expect(action1 != action2) + + action1 = .success("some") + action2 = .success("some") + + #expect(action1 == action2) + + action1 = .error(TestingError.some) + action2 = .error(TestingError.some) + + #expect(action1 == action2) + } +} \ No newline at end of file diff --git a/Tests/AsyncLoadTests/AsyncActionNonEquatableItemTests.swift b/Tests/AsyncLoadTests/AsyncActionNonEquatableItemTests.swift new file mode 100644 index 0000000..1695eab --- /dev/null +++ b/Tests/AsyncLoadTests/AsyncActionNonEquatableItemTests.swift @@ -0,0 +1,70 @@ +import Testing +@testable import AsyncLoad + +@Suite("Test non-equatable AsyncAction") +struct AsyncActionNonEquatableItemTests { + @Test func testNone() async throws { + let action1: AsyncAction = .none + let action2: AsyncAction = .none + + #expect(action1 == action2) + } + + @Test func testLoadedString() async throws { + var action1: AsyncAction = .success(NonEquatableItem(name: "Hello")) + var action2: AsyncAction = .success(NonEquatableItem(name: "Hello")) + + #expect(action1 == action2) + + action1 = .success(NonEquatableItem(name: "Some")) + action2 = .success(NonEquatableItem(name: "Other")) + + #expect(action1 == action2) + } + + @Test func testLoading() async throws { + let action1: AsyncAction = .loading + let action2: AsyncAction = .loading + + #expect(action1 == action2) + } + + @Test func testError() async throws { + var action1: AsyncAction = .error(TestingError.some) + var action2: AsyncAction = .error(TestingError.some) + + #expect(action1 == action2) + + action1 = .error(TestingError.some) + action2 = .error(TestingError.other) + + #expect(action1 == action2) + } + + @Test func testMultiple() async throws { + var action1: AsyncAction = .none + var action2: AsyncAction = .none + + #expect(action1 == action2) + + action1 = .loading + action2 = .loading + + #expect(action1 == action2) + + action1 = .success(NonEquatableItem(name: "Some")) + action2 = .success(NonEquatableItem(name: "Some")) + + #expect(action1 == action2) + + action1 = .success(NonEquatableItem(name: "Some")) + action2 = .success(NonEquatableItem(name: "Other")) + + #expect(action1 == action2) + + action1 = .error(TestingError.some) + action2 = .error(TestingError.some) + + #expect(action1 == action2) + } +} \ No newline at end of file diff --git a/Tests/AsyncLoadTests/CachedAsyncActionEquatableItemTests.swift b/Tests/AsyncLoadTests/CachedAsyncActionEquatableItemTests.swift new file mode 100644 index 0000000..dafdda2 --- /dev/null +++ b/Tests/AsyncLoadTests/CachedAsyncActionEquatableItemTests.swift @@ -0,0 +1,85 @@ +import Testing +@testable import AsyncLoad + +@Suite("Test equatable CachedAsyncAction") +struct CachedAsyncActionEquatableItemTests { + @Test func testNone() async throws { + let action1: CachedAsyncAction = .none + let action2: CachedAsyncAction = .none + + #expect(action1 == action2) + } + + @Test func testLoadedString() async throws { + var action1: CachedAsyncAction = .success("Some") + var action2: CachedAsyncAction = .success("Some") + + #expect(action1 == action2) + + action1 = .success("Other") + action2 = .success("Other1") + + #expect(action1 != action2) + } + + @Test func testLoadedUser() async throws { + var action1: CachedAsyncAction = .success(User(name: "Some")) + var action2: CachedAsyncAction = .success(User(name: "Some")) + + #expect(action1 == action2) + + action1 = .success(User(name: "Alex")) + action2 = .success(User(name: "Daniel")) + + #expect(action1 != action2) + } + + @Test func testError() async throws { + var action1: CachedAsyncAction = .error("some", TestingError.some) + var action2: CachedAsyncAction = .error("some", TestingError.some) + + #expect(action1 == action2) + + action1 = .error(nil, TestingError.some) + action2 = .error("some", TestingError.some) + + #expect(action1 != action2) + + action1 = .error(nil, TestingError.some) + action2 = .error("some", TestingError.other) + + #expect(action1 != action2) + } + + @Test func testMultiple() async throws { + var action1: CachedAsyncAction = .none + var action2: CachedAsyncAction = .none + + #expect(action1 == action2) + + action1 = .loading() + action2 = .loading() + + #expect(action1 == action2) + + action1 = .success("some") + action2 = .success("some") + + #expect(action1 == action2) + + action1 = .loading("some") + action2 = .loading("other") + + #expect(action1 != action2) + + action1 = .loading() + action2 = .loading() + + #expect(action1 == action2) + + action1 = .error("some", TestingError.some) + action2 = .error(nil, TestingError.some) + + #expect(action1 != action2) + } +} diff --git a/Tests/AsyncLoadTests/CachedAsyncActionNonEquatableItemTests.swift b/Tests/AsyncLoadTests/CachedAsyncActionNonEquatableItemTests.swift new file mode 100644 index 0000000..7646cfa --- /dev/null +++ b/Tests/AsyncLoadTests/CachedAsyncActionNonEquatableItemTests.swift @@ -0,0 +1,70 @@ +import Testing +@testable import AsyncLoad + +@Suite("Test non-equatable CachedAsyncAction") +struct CachedAsyncActionNonEquatableItemTests { + @Test func testNone() async throws { + let action1: CachedAsyncAction = .none + let action2: CachedAsyncAction = .none + + #expect(action1 == action2) + } + + @Test func testLoadedString() async throws { + var action1: CachedAsyncAction = .success(NonEquatableItem(name: "Hello")) + var action2: CachedAsyncAction = .success(NonEquatableItem(name: "Hello")) + + #expect(action1 == action2) + + action1 = .success(NonEquatableItem(name: "Some")) + action2 = .success(NonEquatableItem(name: "Other")) + + #expect(action1 == action2) + } + + @Test func testLoading() async throws { + let action1: CachedAsyncAction = .loading() + let action2: CachedAsyncAction = .loading() + + #expect(action1 == action2) + } + + @Test func testError() async throws { + var action1: CachedAsyncAction = .error(nil, TestingError.some) + var action2: CachedAsyncAction = .error(nil, TestingError.some) + + #expect(action1 == action2) + + action1 = .error(nil, TestingError.some) + action2 = .error(NonEquatableItem(name: "Hello"), TestingError.other) + + #expect(action1 == action2) + } + + @Test func testMultiple() async throws { + var action1: CachedAsyncAction = .none + var action2: CachedAsyncAction = .none + + #expect(action1 == action2) + + action1 = .loading() + action2 = .loading() + + #expect(action1 == action2) + + action1 = .success(NonEquatableItem(name: "Some")) + action2 = .success(NonEquatableItem(name: "Some")) + + #expect(action1 == action2) + + action1 = .success(NonEquatableItem(name: "Some")) + action2 = .success(NonEquatableItem(name: "Other")) + + #expect(action1 == action2) + + action1 = .error(NonEquatableItem(name: "Hello"), TestingError.some) + action2 = .error(NonEquatableItem(name: "Hello"), TestingError.some) + + #expect(action1 == action2) + } +} \ No newline at end of file From 299d2db6f0cf797f91f86226480dde25d3c870c5 Mon Sep 17 00:00:00 2001 From: Alexander Kauer Date: Mon, 29 Sep 2025 14:38:17 +0200 Subject: [PATCH 4/6] Review feedback --- README.md | 117 ++++++++++++++++-- Sources/AsyncLoad/AsyncLoad/AsyncAction.swift | 4 +- Sources/AsyncLoad/AsyncLoad/AsyncLoad.swift | 2 +- 3 files changed, 112 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index f50f92f..acb424b 100644 --- a/README.md +++ b/README.md @@ -4,10 +4,13 @@ A Swift package that provides elegant state management for asynchronous operatio ## Overview -AsyncLoad provides two main components for handling asynchronous operations: +AsyncLoad provides components for handling asynchronous operations: - `AsyncLoad`: For loading data operations -- `AsyncAction`: For action-based operations +- `AsyncAction`: For action-based operations +- `CachedAsyncLoad`: For loading operations that preserve cached data during refreshes +- `CachedAsyncAction`: For actions that preserve cached data during retries - `AsyncLoadView`: A SwiftUI view component for displaying async states +- `CachedAsyncLoadView`: A SwiftUI view component for cached async states ## Requirements @@ -25,7 +28,7 @@ Add AsyncLoad to your project by adding the following to your `Package.swift`: ```swift dependencies: [ - .package(url: "https://github.com/yourusername/AsyncLoad", from: "1.0.0") + .package(url: "https://github.com/diamirio/AsyncLoad", from: "1.0.0") ] ``` @@ -118,6 +121,101 @@ class FormViewModel { } ``` +### CachedAsyncLoad + +An enhanced version of AsyncLoad that preserves cached data during loading and error states. + +```swift +public enum CachedAsyncLoad: Equatable { + case none // Initial state + case loading(T? = nil) // Loading with optional cached data + case error(T? = nil, Error) // Error with optional cached data + case loaded(T) // Successfully loaded with data +} +``` + +#### Properties + +- `isLoading: Bool` - Returns true if the state is `.loading` +- `item: T?` - Returns the loaded item if state is `.loaded`, nil otherwise +- `error: Error?` - Returns the error if state is `.error`, nil otherwise + +#### Example Usage + +```swift +import AsyncLoad + +@Observable +class CachedDataViewModel { + var userProfile: CachedAsyncLoad = .none + + func loadUserProfile(id: String) async { + // Start loading while preserving any existing data + if case .loaded(let existingUser) = userProfile { + userProfile = .loading(existingUser) + } else { + userProfile = .loading() + } + + do { + let user = try await userService.fetchUser(id: id) + userProfile = .loaded(user) + } catch { + // Preserve existing data even during error + let existingUser = userProfile.item + userProfile = .error(existingUser, error) + } + } +} +``` + +### CachedAsyncAction + +Similar to AsyncAction but preserves cached data during loading and error states. + +```swift +public enum CachedAsyncAction: Equatable { + case none // Initial state + case loading(T? = nil) // Action in progress with optional cached data + case error(T? = nil, Error) // Action failed with optional cached data + case success(T) // Action completed successfully +} +``` + +#### Properties + +- `isLoading: Bool` - Returns true if the state is `.loading` +- `item: T?` - Returns the success result if state is `.success`, nil otherwise +- `error: Error?` - Returns the error if state is `.error`, nil otherwise + +#### Example Usage + +```swift +import AsyncLoad + +@Observable +class CachedFormViewModel { + var submitAction: CachedAsyncAction = .none + + func submitForm(data: FormData) async { + // Preserve previous successful response during retry + if case .success(let previousResponse) = submitAction { + submitAction = .loading(previousResponse) + } else { + submitAction = .loading() + } + + do { + let response = try await apiService.submit(data) + submitAction = .success(response) + } catch { + let previousResponse = submitAction.item + submitAction = .error(previousResponse, error) + } + } +} +``` + ### AsyncLoadView A SwiftUI view component that automatically handles the display of different async states. @@ -182,16 +280,19 @@ struct UserProfileView: View { ## Features - **Type-safe**: Generic enums ensure type safety for your data -- **Equatable**: Both AsyncLoad and AsyncAction conform to Equatable for easy state comparison -- **SwiftUI Integration**: AsyncLoadView provides seamless integration with SwiftUI +- **Equatable**: All async state enums conform to Equatable for easy state comparison +- **SwiftUI Integration**: AsyncLoadView and CachedAsyncLoadView provide seamless integration with SwiftUI - **Error Handling**: Built-in error state management - **Loading States**: Automatic loading state handling with progress indicators +- **Cached Data**: CachedAsyncLoad and CachedAsyncAction preserve data during refreshes and errors - **Flexible UI**: Customizable content and error views ## Best Practices 1. **Use AsyncLoad for data fetching** operations (GET requests, loading content) 2. **Use AsyncAction for user actions** (POST/PUT/DELETE requests, form submissions) -3. **Always handle all states** in your UI to provide good user experience -4. **Use AsyncLoadView** for simple cases to reduce boilerplate code -5. **Reset states** appropriately (e.g., set to `.none` when appropriate) +3. **Use CachedAsyncLoad** when you want to preserve data during refreshes or show stale data during errors +4. **Use CachedAsyncAction** when you want to preserve previous results during action retries +5. **Always handle all states** in your UI to provide good user experience +6. **Use AsyncLoadView and CachedAsyncLoadView** for simple cases to reduce boilerplate code +7. **Reset states** appropriately (e.g., set to `.none` when appropriate) diff --git a/Sources/AsyncLoad/AsyncLoad/AsyncAction.swift b/Sources/AsyncLoad/AsyncLoad/AsyncAction.swift index 466940d..593ca7c 100644 --- a/Sources/AsyncLoad/AsyncLoad/AsyncAction.swift +++ b/Sources/AsyncLoad/AsyncLoad/AsyncAction.swift @@ -54,8 +54,8 @@ public enum AsyncAction: Equatable { true case (.error, .error): true - case (.success, .success): - lhs.item == rhs.item + case let (.success(lhsItem), .success(rhsItem)): + lhsItem == rhsItem default: false } diff --git a/Sources/AsyncLoad/AsyncLoad/AsyncLoad.swift b/Sources/AsyncLoad/AsyncLoad/AsyncLoad.swift index 00242d8..f5f3313 100644 --- a/Sources/AsyncLoad/AsyncLoad/AsyncLoad.swift +++ b/Sources/AsyncLoad/AsyncLoad/AsyncLoad.swift @@ -1,6 +1,6 @@ import Foundation -public enum AsyncLoad : Equatable { +public enum AsyncLoad: Equatable { case none case loading case error(Error) From 638c1073984b709023c2c99f782faafb656db7d8 Mon Sep 17 00:00:00 2001 From: Alexander Kauer Date: Mon, 29 Sep 2025 15:52:56 +0200 Subject: [PATCH 5/6] Sendable conformance, Cleanup tests, Use Xcode 26.0 for tests --- .github/workflows/swift-tests.yaml | 4 +- Sources/AsyncLoad/AsyncLoad/AsyncAction.swift | 10 +- Sources/AsyncLoad/AsyncLoad/AsyncLoad.swift | 2 +- .../AsyncLoad/AsyncLoad/AsyncLoadView.swift | 6 +- .../CachedAsyncLoad/CachedAsyncAction.swift | 2 +- .../CachedAsyncLoad/CachedAsyncLoad.swift | 2 +- .../CachedAsyncLoad/CachedAsyncLoadView.swift | 2 +- .../AsyncActionEquatableItemTests.swift | 100 ++++++---------- .../AsyncActionNonEquatableItemTests.swift | 80 +++---------- .../AsyncLoadEquatableItemTests.swift | 98 ++++++---------- .../AsyncLoadNonEquatableItemTests.swift | 80 +++---------- .../CachedAsyncActionEquatableItemTests.swift | 107 ++++++----------- ...chedAsyncActionNonEquatableItemTests.swift | 77 ++---------- .../CachedAsyncLoadEquatableItemTests.swift | 111 ++++++------------ ...CachedAsyncLoadNonEquatableItemTests.swift | 75 ++---------- Tests/AsyncLoadTests/Utils.swift | 43 ++++++- 16 files changed, 258 insertions(+), 541 deletions(-) diff --git a/.github/workflows/swift-tests.yaml b/.github/workflows/swift-tests.yaml index d322710..8e1d00d 100644 --- a/.github/workflows/swift-tests.yaml +++ b/.github/workflows/swift-tests.yaml @@ -9,8 +9,8 @@ jobs: steps: - uses: actions/checkout@v4 - - name: Select Xcode 16.4 - run: sudo xcode-select -s /Applications/Xcode_16.4.app/Contents/Developer + - name: Select Xcode 26.0 + run: sudo xcode-select -s /Applications/Xcode_26.app/Contents/Developer - name: Build run: swift build -v - name: Run tests diff --git a/Sources/AsyncLoad/AsyncLoad/AsyncAction.swift b/Sources/AsyncLoad/AsyncLoad/AsyncAction.swift index 593ca7c..215b3d8 100644 --- a/Sources/AsyncLoad/AsyncLoad/AsyncAction.swift +++ b/Sources/AsyncLoad/AsyncLoad/AsyncAction.swift @@ -1,6 +1,6 @@ import Foundation -public enum AsyncAction: Equatable { +public enum AsyncAction: Equatable, Sendable { case none case loading case error(Error) @@ -64,15 +64,15 @@ public enum AsyncAction: Equatable { public static func != (lhs: AsyncAction, rhs: AsyncAction) -> Bool where T : Equatable { switch (lhs, rhs) { case (.none, .none): - true + false case (.loading, .loading): - true + false case (.error, .error): - true + false case let (.success(lhsItem), .success(rhsItem)): lhsItem != rhsItem default: - false + true } } } diff --git a/Sources/AsyncLoad/AsyncLoad/AsyncLoad.swift b/Sources/AsyncLoad/AsyncLoad/AsyncLoad.swift index f5f3313..2fb48f9 100644 --- a/Sources/AsyncLoad/AsyncLoad/AsyncLoad.swift +++ b/Sources/AsyncLoad/AsyncLoad/AsyncLoad.swift @@ -1,6 +1,6 @@ import Foundation -public enum AsyncLoad: Equatable { +public enum AsyncLoad: Equatable, Sendable { case none case loading case error(Error) diff --git a/Sources/AsyncLoad/AsyncLoad/AsyncLoadView.swift b/Sources/AsyncLoad/AsyncLoad/AsyncLoadView.swift index bf2d30a..c57ef83 100644 --- a/Sources/AsyncLoad/AsyncLoad/AsyncLoadView.swift +++ b/Sources/AsyncLoad/AsyncLoad/AsyncLoadView.swift @@ -2,7 +2,11 @@ import Foundation #if canImport(SwiftUI) import SwiftUI -public struct AsyncLoadView: View { +public struct AsyncLoadView< + Item: Sendable, + Content: View, + ErrorContent: View +>: View { let state: AsyncLoad @ViewBuilder diff --git a/Sources/AsyncLoad/CachedAsyncLoad/CachedAsyncAction.swift b/Sources/AsyncLoad/CachedAsyncLoad/CachedAsyncAction.swift index 6f4ff1c..162cc58 100644 --- a/Sources/AsyncLoad/CachedAsyncLoad/CachedAsyncAction.swift +++ b/Sources/AsyncLoad/CachedAsyncLoad/CachedAsyncAction.swift @@ -1,6 +1,6 @@ import Foundation -public enum CachedAsyncAction: Equatable { +public enum CachedAsyncAction: Equatable, Sendable { case none case loading(T? = nil) case error(T? = nil, Error) diff --git a/Sources/AsyncLoad/CachedAsyncLoad/CachedAsyncLoad.swift b/Sources/AsyncLoad/CachedAsyncLoad/CachedAsyncLoad.swift index 75b9b65..6e79f1c 100644 --- a/Sources/AsyncLoad/CachedAsyncLoad/CachedAsyncLoad.swift +++ b/Sources/AsyncLoad/CachedAsyncLoad/CachedAsyncLoad.swift @@ -1,6 +1,6 @@ import Foundation -public enum CachedAsyncLoad: Equatable { +public enum CachedAsyncLoad: Equatable, Sendable { case none case loading(T? = nil) case error(T? = nil, Error) diff --git a/Sources/AsyncLoad/CachedAsyncLoad/CachedAsyncLoadView.swift b/Sources/AsyncLoad/CachedAsyncLoad/CachedAsyncLoadView.swift index e1803ca..03c6e9b 100644 --- a/Sources/AsyncLoad/CachedAsyncLoad/CachedAsyncLoadView.swift +++ b/Sources/AsyncLoad/CachedAsyncLoad/CachedAsyncLoadView.swift @@ -3,7 +3,7 @@ import Foundation import SwiftUI public struct CachedAsyncLoadView< - Item, + Item: Sendable, Content: View, ErrorContent: View, LoadingContent: View diff --git a/Tests/AsyncLoadTests/AsyncActionEquatableItemTests.swift b/Tests/AsyncLoadTests/AsyncActionEquatableItemTests.swift index 28b8d50..602e927 100644 --- a/Tests/AsyncLoadTests/AsyncActionEquatableItemTests.swift +++ b/Tests/AsyncLoadTests/AsyncActionEquatableItemTests.swift @@ -3,73 +3,41 @@ import Testing @Suite("Test equatable AsyncAction") struct AsyncActionEquatableItemTests { - @Test func testNone() async throws { - let action1: AsyncAction = .none - let action2: AsyncAction = .none - - #expect(action1 == action2) - } - - @Test func testLoadedString() async throws { - var action1: AsyncAction = .success("Some") - var action2: AsyncAction = .success("Some") - - #expect(action1 == action2) - - action1 = .success("Other") - action2 = .success("Other1") - - #expect(action1 != action2) + @Test<[AsyncActionParameter]>("Should be equal ", arguments: [ + .init(.none, .none), + .init(.loading, .loading), + .init(.error(TestingError.some), .error(TestingError.some)), + .init(.error(TestingError.some), .error(TestingError.other)), + .init(.success("some"), .success("some")), + ]) + func equalString(param: AsyncActionParameter) async throws { + #expect(param.action1 == param.action2) } - - @Test func testLoadedUser() async throws { - var action1: AsyncAction = .success(User(name: "Some")) - var action2: AsyncAction = .success(User(name: "Some")) - - #expect(action1 == action2) - - action1 = .success(User(name: "Alex")) - action2 = .success(User(name: "Daniel")) - - #expect(action1 != action2) + + @Test<[AsyncActionParameter]>("Should not be equal ", arguments: [ + .init(.success("some"), .success("other")), + .init(.error(TestingError.some), .success("other")), + ]) + func nonEqualString(param: AsyncActionParameter) async throws { + #expect(param.action1 != param.action2) } - - @Test func testError() async throws { - var action1: AsyncAction = .error(TestingError.some) - var action2: AsyncAction = .error(TestingError.some) - - #expect(action1 == action2) - - action1 = .error(TestingError.some) - action2 = .error(TestingError.other) - - #expect(action1 == action2) + + @Test<[AsyncActionParameter]>("Should be equal ", arguments: [ + .init(.none, .none), + .init(.loading, .loading), + .init(.error(TestingError.some), .error(TestingError.some)), + .init(.error(TestingError.some), .error(TestingError.other)), + .init(.success(User(name: "some")), .success(User(name: "some"))), + ]) + func equalUser(param: AsyncActionParameter) async throws { + #expect(param.action1 == param.action2) } - - @Test func testMultiple() async throws { - var action1: AsyncAction = .none - var action2: AsyncAction = .none - - #expect(action1 == action2) - - action1 = .loading - action2 = .loading - - #expect(action1 == action2) - - action1 = .success("Some") - action2 = .success("Other") - - #expect(action1 != action2) - - action1 = .success("some") - action2 = .success("some") - - #expect(action1 == action2) - - action1 = .error(TestingError.some) - action2 = .error(TestingError.some) - - #expect(action1 == action2) + + @Test<[AsyncActionParameter]>("Should not be equal ", arguments: [ + .init(.success(User(name: "some")), .success(User(name: "other"))), + .init(.error(TestingError.some), .success(User(name: "some"))), + ]) + func nonEqualuser(param: AsyncActionParameter) async throws { + #expect(param.action1 != param.action2) } -} \ No newline at end of file +} diff --git a/Tests/AsyncLoadTests/AsyncActionNonEquatableItemTests.swift b/Tests/AsyncLoadTests/AsyncActionNonEquatableItemTests.swift index 1695eab..c5b45dd 100644 --- a/Tests/AsyncLoadTests/AsyncActionNonEquatableItemTests.swift +++ b/Tests/AsyncLoadTests/AsyncActionNonEquatableItemTests.swift @@ -3,68 +3,24 @@ import Testing @Suite("Test non-equatable AsyncAction") struct AsyncActionNonEquatableItemTests { - @Test func testNone() async throws { - let action1: AsyncAction = .none - let action2: AsyncAction = .none - - #expect(action1 == action2) - } - - @Test func testLoadedString() async throws { - var action1: AsyncAction = .success(NonEquatableItem(name: "Hello")) - var action2: AsyncAction = .success(NonEquatableItem(name: "Hello")) - - #expect(action1 == action2) - - action1 = .success(NonEquatableItem(name: "Some")) - action2 = .success(NonEquatableItem(name: "Other")) - - #expect(action1 == action2) + @Test<[AsyncActionParameter]>("Should be equal (structural)", arguments: [ + .init(.none, .none), + .init(.loading, .loading), + .init(.success(NonEquatableItem(name: "Hello")), .success(NonEquatableItem(name: "Different"))), + .init(.success(NonEquatableItem(name: "Some")), .success(NonEquatableItem(name: "Other"))), + .init(.error(TestingError.some), .error(TestingError.some)), + .init(.error(TestingError.some), .error(TestingError.other)), + ]) + func structuralEquality(param: AsyncActionParameter) async throws { + #expect(param.action1 == param.action2) } - @Test func testLoading() async throws { - let action1: AsyncAction = .loading - let action2: AsyncAction = .loading - - #expect(action1 == action2) - } - - @Test func testError() async throws { - var action1: AsyncAction = .error(TestingError.some) - var action2: AsyncAction = .error(TestingError.some) - - #expect(action1 == action2) - - action1 = .error(TestingError.some) - action2 = .error(TestingError.other) - - #expect(action1 == action2) - } - - @Test func testMultiple() async throws { - var action1: AsyncAction = .none - var action2: AsyncAction = .none - - #expect(action1 == action2) - - action1 = .loading - action2 = .loading - - #expect(action1 == action2) - - action1 = .success(NonEquatableItem(name: "Some")) - action2 = .success(NonEquatableItem(name: "Some")) - - #expect(action1 == action2) - - action1 = .success(NonEquatableItem(name: "Some")) - action2 = .success(NonEquatableItem(name: "Other")) - - #expect(action1 == action2) - - action1 = .error(TestingError.some) - action2 = .error(TestingError.some) - - #expect(action1 == action2) + @Test<[AsyncActionParameter]>("Should be equal (mixed types)", arguments: [ + .init(.loading, .loading), + .init(.error(TestingError.some), .error(TestingError.some)), + .init(.error(TestingError.some), .error(TestingError.other)), + ]) + func mixedTypeEquality(param: AsyncActionParameter) async throws { + #expect(param.action1 == param.action2) } -} \ No newline at end of file +} diff --git a/Tests/AsyncLoadTests/AsyncLoadEquatableItemTests.swift b/Tests/AsyncLoadTests/AsyncLoadEquatableItemTests.swift index 51bc3b8..d0a44fa 100644 --- a/Tests/AsyncLoadTests/AsyncLoadEquatableItemTests.swift +++ b/Tests/AsyncLoadTests/AsyncLoadEquatableItemTests.swift @@ -3,73 +3,41 @@ import Testing @Suite("Test equatable AsyncLoad") struct AsyncLoadEquatableItemTests { - @Test func testNone() async throws { - let load1: AsyncLoad = .none - let load2: AsyncLoad = .none - - #expect(load1 == load2) + @Test<[AsyncLoadParameter]>("Should be equal ", arguments: [ + .init(.none, .none), + .init(.loading, .loading), + .init(.error(TestingError.some), .error(TestingError.some)), + .init(.error(TestingError.some), .error(TestingError.other)), + .init(.loaded("some"), .loaded("some")), + ]) + func equalString(param: AsyncLoadParameter) async throws { + #expect(param.load1 == param.load2) } - - @Test func testLoadedString() async throws { - var load1: AsyncLoad = .loaded("Some") - var load2: AsyncLoad = .loaded("Some") - - #expect(load1 == load2) - - load1 = .loaded("Other") - load2 = .loaded("Other1") - - #expect(load1 != load2) - } - - @Test func testLoadedUser() async throws { - var load1: AsyncLoad = .loaded(User(name: "Some")) - var load2: AsyncLoad = .loaded(User(name: "Some")) - - #expect(load1 == load2) - - load1 = .loaded(User(name: "Alex")) - load2 = .loaded(User(name: "Daniel")) - - #expect(load1 != load2) + + @Test<[AsyncLoadParameter]>("Should not be equal ", arguments: [ + .init(.loaded("Some"), .loaded("Other")), + .init(.error(TestingError.some), .loaded("some")), + ]) + func nonEqualString(param: AsyncLoadParameter) async throws { + #expect(param.load1 != param.load2) } - - @Test func testError() async throws { - var load1: AsyncLoad = .error(TestingError.some) - var load2: AsyncLoad = .error(TestingError.some) - - #expect(load1 == load2) - - load1 = .error(TestingError.some) - load2 = .error(TestingError.other) - - #expect(load1 == load2) + + @Test<[AsyncLoadParameter]>("Should be equal ", arguments: [ + .init(.none, .none), + .init(.loading, .loading), + .init(.error(TestingError.some), .error(TestingError.some)), + .init(.error(TestingError.some), .error(TestingError.other)), + .init(.loaded(User(name: "some")), .loaded(User(name: "some"))), + ]) + func equalUser(param: AsyncLoadParameter) async throws { + #expect(param.load1 == param.load2) } - - @Test func testMultiple() async throws { - var load1: AsyncLoad = .none - var load2: AsyncLoad = .none - - #expect(load1 == load2) - - load1 = .loading - load2 = .loading - - #expect(load1 == load2) - - load1 = .loaded("Some") - load2 = .loaded("Other") - - #expect(load1 != load2) - - load1 = .loaded("some") - load2 = .loaded("some") - - #expect(load1 == load2) - - load1 = .error(TestingError.some) - load2 = .error(TestingError.some) - - #expect(load1 == load2) + + @Test<[AsyncLoadParameter]>("Should not be equal ", arguments: [ + .init(.loaded(User(name: "Alex")), .loaded(User(name: "Daniel"))), + .init(.error(TestingError.some), .loaded(User(name: "some"))), + ]) + func nonEqualUser(param: AsyncLoadParameter) async throws { + #expect(param.load1 != param.load2) } } diff --git a/Tests/AsyncLoadTests/AsyncLoadNonEquatableItemTests.swift b/Tests/AsyncLoadTests/AsyncLoadNonEquatableItemTests.swift index d2a1098..9281991 100644 --- a/Tests/AsyncLoadTests/AsyncLoadNonEquatableItemTests.swift +++ b/Tests/AsyncLoadTests/AsyncLoadNonEquatableItemTests.swift @@ -3,68 +3,24 @@ import Testing @Suite("Test non-equatable AsyncLoad") struct AsyncLoadNonEquatableItemTests { - @Test func testNone() async throws { - let load1: AsyncLoad = .none - let load2: AsyncLoad = .none - - #expect(load1 == load2) + @Test<[AsyncLoadParameter]>("Should be equal (structural)", arguments: [ + .init(.none, .none), + .init(.loading, .loading), + .init(.loaded(NonEquatableItem(name: "Hello")), .loaded(NonEquatableItem(name: "Different"))), + .init(.loaded(NonEquatableItem(name: "Some")), .loaded(NonEquatableItem(name: "Other"))), + .init(.error(TestingError.some), .error(TestingError.some)), + .init(.error(TestingError.some), .error(TestingError.other)), + ]) + func structuralEquality(param: AsyncLoadParameter) async throws { + #expect(param.load1 == param.load2) } - - @Test func testLoadedString() async throws { - var load1: AsyncLoad = .loaded(NonEquatableItem(name: "Hello")) - var load2: AsyncLoad = .loaded(NonEquatableItem(name: "Hello")) - - #expect(load1 == load2) - - load1 = .loaded(NonEquatableItem(name: "Some")) - load2 = .loaded(NonEquatableItem(name: "Other")) - - #expect(load1 == load2) - } - - @Test func testLoading() async throws { - let load1: AsyncLoad = .loading - let load2: AsyncLoad = .loading - - #expect(load1 == load2) - } - - @Test func testError() async throws { - var load1: AsyncLoad = .error(TestingError.some) - var load2: AsyncLoad = .error(TestingError.some) - - #expect(load1 == load2) - - load1 = .error(TestingError.some) - load2 = .error(TestingError.other) - - #expect(load1 == load2) - } - - @Test func testMultiple() async throws { - var load1: AsyncLoad = .none - var load2: AsyncLoad = .none - - #expect(load1 == load2) - - load1 = .loading - load2 = .loading - - #expect(load1 == load2) - - load1 = .loaded(NonEquatableItem(name: "Some")) - load2 = .loaded(NonEquatableItem(name: "Some")) - - #expect(load1 == load2) - - load1 = .loaded(NonEquatableItem(name: "Some")) - load2 = .loaded(NonEquatableItem(name: "Other")) - - #expect(load1 == load2) - - load1 = .error(TestingError.some) - load2 = .error(TestingError.some) - - #expect(load1 == load2) + + @Test<[AsyncLoadParameter]>("Should be equal (mixed types)", arguments: [ + .init(.loading, .loading), + .init(.error(TestingError.some), .error(TestingError.some)), + .init(.error(TestingError.some), .error(TestingError.other)), + ]) + func mixedTypeEquality(param: AsyncLoadParameter) async throws { + #expect(param.load1 == param.load2) } } diff --git a/Tests/AsyncLoadTests/CachedAsyncActionEquatableItemTests.swift b/Tests/AsyncLoadTests/CachedAsyncActionEquatableItemTests.swift index dafdda2..25fb8a9 100644 --- a/Tests/AsyncLoadTests/CachedAsyncActionEquatableItemTests.swift +++ b/Tests/AsyncLoadTests/CachedAsyncActionEquatableItemTests.swift @@ -3,83 +3,46 @@ import Testing @Suite("Test equatable CachedAsyncAction") struct CachedAsyncActionEquatableItemTests { - @Test func testNone() async throws { - let action1: CachedAsyncAction = .none - let action2: CachedAsyncAction = .none - - #expect(action1 == action2) + @Test<[CachedAsyncActionParameter]>("Should be equal ", arguments: [ + .init(.none, .none), + .init(.loading(), .loading()), + .init(.success("some"), .success("some")), + .init(.loading("some"), .loading("some")), + .init(.error("some", TestingError.some), .error("some", TestingError.some)), + ]) + func equalString(param: CachedAsyncActionParameter) async throws { + #expect(param.action1 == param.action2) } - @Test func testLoadedString() async throws { - var action1: CachedAsyncAction = .success("Some") - var action2: CachedAsyncAction = .success("Some") - - #expect(action1 == action2) - - action1 = .success("Other") - action2 = .success("Other1") - - #expect(action1 != action2) + @Test<[CachedAsyncActionParameter]>("Should not be equal ", arguments: [ + .init(.success("Other"), .success("Other1")), + .init(.loading("some"), .loading("other")), + .init(.error(nil, TestingError.some), .error("some", TestingError.some)), + .init(.error(nil, TestingError.some), .error("some", TestingError.other)), + .init(.error("some", TestingError.some), .error(nil, TestingError.some)), + ]) + func nonEqualString(param: CachedAsyncActionParameter) async throws { + #expect(param.action1 != param.action2) } - @Test func testLoadedUser() async throws { - var action1: CachedAsyncAction = .success(User(name: "Some")) - var action2: CachedAsyncAction = .success(User(name: "Some")) - - #expect(action1 == action2) - - action1 = .success(User(name: "Alex")) - action2 = .success(User(name: "Daniel")) - - #expect(action1 != action2) + @Test<[CachedAsyncActionParameter]>("Should be equal ", arguments: [ + .init(.none, .none), + .init(.loading(), .loading()), + .init(.success(User(name: "some")), .success(User(name: "some"))), + .init(.loading(User(name: "some")), .loading(User(name: "some"))), + .init(.error(User(name: "some"), TestingError.some), .error(User(name: "some"), TestingError.some)), + ]) + func equalUser(param: CachedAsyncActionParameter) async throws { + #expect(param.action1 == param.action2) } - @Test func testError() async throws { - var action1: CachedAsyncAction = .error("some", TestingError.some) - var action2: CachedAsyncAction = .error("some", TestingError.some) - - #expect(action1 == action2) - - action1 = .error(nil, TestingError.some) - action2 = .error("some", TestingError.some) - - #expect(action1 != action2) - - action1 = .error(nil, TestingError.some) - action2 = .error("some", TestingError.other) - - #expect(action1 != action2) - } - - @Test func testMultiple() async throws { - var action1: CachedAsyncAction = .none - var action2: CachedAsyncAction = .none - - #expect(action1 == action2) - - action1 = .loading() - action2 = .loading() - - #expect(action1 == action2) - - action1 = .success("some") - action2 = .success("some") - - #expect(action1 == action2) - - action1 = .loading("some") - action2 = .loading("other") - - #expect(action1 != action2) - - action1 = .loading() - action2 = .loading() - - #expect(action1 == action2) - - action1 = .error("some", TestingError.some) - action2 = .error(nil, TestingError.some) - - #expect(action1 != action2) + @Test<[CachedAsyncActionParameter]>("Should not be equal ", arguments: [ + .init(.success(User(name: "Alex")), .success(User(name: "Daniel"))), + .init(.loading(User(name: "Alex")), .loading(User(name: "Daniel"))), + .init(.error(nil, TestingError.some), .error(User(name: "some"), TestingError.some)), + .init(.error(User(name: "Alex"), TestingError.some), .error(User(name: "Daniel"), TestingError.some)), + ]) + func nonEqualUser(param: CachedAsyncActionParameter) async throws { + #expect(param.action1 != param.action2) } } diff --git a/Tests/AsyncLoadTests/CachedAsyncActionNonEquatableItemTests.swift b/Tests/AsyncLoadTests/CachedAsyncActionNonEquatableItemTests.swift index 7646cfa..e369b89 100644 --- a/Tests/AsyncLoadTests/CachedAsyncActionNonEquatableItemTests.swift +++ b/Tests/AsyncLoadTests/CachedAsyncActionNonEquatableItemTests.swift @@ -3,68 +3,17 @@ import Testing @Suite("Test non-equatable CachedAsyncAction") struct CachedAsyncActionNonEquatableItemTests { - @Test func testNone() async throws { - let action1: CachedAsyncAction = .none - let action2: CachedAsyncAction = .none - - #expect(action1 == action2) - } - - @Test func testLoadedString() async throws { - var action1: CachedAsyncAction = .success(NonEquatableItem(name: "Hello")) - var action2: CachedAsyncAction = .success(NonEquatableItem(name: "Hello")) - - #expect(action1 == action2) - - action1 = .success(NonEquatableItem(name: "Some")) - action2 = .success(NonEquatableItem(name: "Other")) - - #expect(action1 == action2) - } - - @Test func testLoading() async throws { - let action1: CachedAsyncAction = .loading() - let action2: CachedAsyncAction = .loading() - - #expect(action1 == action2) - } - - @Test func testError() async throws { - var action1: CachedAsyncAction = .error(nil, TestingError.some) - var action2: CachedAsyncAction = .error(nil, TestingError.some) - - #expect(action1 == action2) - - action1 = .error(nil, TestingError.some) - action2 = .error(NonEquatableItem(name: "Hello"), TestingError.other) - - #expect(action1 == action2) - } - - @Test func testMultiple() async throws { - var action1: CachedAsyncAction = .none - var action2: CachedAsyncAction = .none - - #expect(action1 == action2) - - action1 = .loading() - action2 = .loading() - - #expect(action1 == action2) - - action1 = .success(NonEquatableItem(name: "Some")) - action2 = .success(NonEquatableItem(name: "Some")) - - #expect(action1 == action2) - - action1 = .success(NonEquatableItem(name: "Some")) - action2 = .success(NonEquatableItem(name: "Other")) - - #expect(action1 == action2) - - action1 = .error(NonEquatableItem(name: "Hello"), TestingError.some) - action2 = .error(NonEquatableItem(name: "Hello"), TestingError.some) - - #expect(action1 == action2) + @Test<[CachedAsyncActionParameter]>("Should be equal (structural)", arguments: [ + .init(.none, .none), + .init(.loading(), .loading()), + .init(.success(NonEquatableItem(name: "Hello")), .success(NonEquatableItem(name: "Different"))), + .init(.success(NonEquatableItem(name: "Some")), .success(NonEquatableItem(name: "Other"))), + .init(.loading(NonEquatableItem(name: "Some")), .loading(NonEquatableItem(name: "Other"))), + .init(.error(nil, TestingError.some), .error(nil, TestingError.some)), + .init(.error(nil, TestingError.some), .error(NonEquatableItem(name: "Hello"), TestingError.other)), + .init(.error(NonEquatableItem(name: "Hello"), TestingError.some), .error(NonEquatableItem(name: "World"), TestingError.some)), + ]) + func structuralEquality(param: CachedAsyncActionParameter) async throws { + #expect(param.action1 == param.action2) } -} \ No newline at end of file +} diff --git a/Tests/AsyncLoadTests/CachedAsyncLoadEquatableItemTests.swift b/Tests/AsyncLoadTests/CachedAsyncLoadEquatableItemTests.swift index 2f56afa..e554e38 100644 --- a/Tests/AsyncLoadTests/CachedAsyncLoadEquatableItemTests.swift +++ b/Tests/AsyncLoadTests/CachedAsyncLoadEquatableItemTests.swift @@ -3,83 +3,46 @@ import Testing @Suite("Test equatable CachedAsyncLoad") struct CachedAsyncLoadEquatableItemTests { - @Test func testNone() async throws { - let load1: CachedAsyncLoad = .none - let load2: CachedAsyncLoad = .none - - #expect(load1 == load2) + @Test<[CachedAsyncLoadParameter]>("Should be equal ", arguments: [ + .init(.none, .none), + .init(.loading(), .loading()), + .init(.loaded("some"), .loaded("some")), + .init(.loading("some"), .loading("some")), + .init(.error("some", TestingError.some), .error("some", TestingError.some)), + ]) + func equalString(param: CachedAsyncLoadParameter) async throws { + #expect(param.load1 == param.load2) } - - @Test func testLoadedString() async throws { - var load1: CachedAsyncLoad = .loaded("Some") - var load2: CachedAsyncLoad = .loaded("Some") - - #expect(load1 == load2) - - load1 = .loaded("Other") - load2 = .loaded("Other1") - - #expect(load1 != load2) - } - - @Test func testLoadedUser() async throws { - var load1: CachedAsyncLoad = .loaded(User(name: "Some")) - var load2: CachedAsyncLoad = .loaded(User(name: "Some")) - - #expect(load1 == load2) - - load1 = .loaded(User(name: "Alex")) - load2 = .loaded(User(name: "Daniel")) - - #expect(load1 != load2) + + @Test<[CachedAsyncLoadParameter]>("Should not be equal ", arguments: [ + .init(.loaded("Other"), .loaded("Other1")), + .init(.loading("some"), .loading("other")), + .init(.error(nil, TestingError.some), .error("some", TestingError.some)), + .init(.error(nil, TestingError.some), .error("some", TestingError.other)), + .init(.error("some", TestingError.some), .error(nil, TestingError.some)), + ]) + func nonEqualString(param: CachedAsyncLoadParameter) async throws { + #expect(param.load1 != param.load2) } - - @Test func testError() async throws { - var load1: CachedAsyncLoad = .error("some", TestingError.some) - var load2: CachedAsyncLoad = .error("some", TestingError.some) - - #expect(load1 == load2) - - load1 = .error(nil, TestingError.some) - load2 = .error("some", TestingError.some) - - #expect(load1 != load2) - - load1 = .error(nil, TestingError.some) - load2 = .error("some", TestingError.other) - - #expect(load1 != load2) + + @Test<[CachedAsyncLoadParameter]>("Should be equal ", arguments: [ + .init(.none, .none), + .init(.loading(), .loading()), + .init(.loaded(User(name: "some")), .loaded(User(name: "some"))), + .init(.loading(User(name: "some")), .loading(User(name: "some"))), + .init(.error(User(name: "some"), TestingError.some), .error(User(name: "some"), TestingError.some)), + ]) + func equalUser(param: CachedAsyncLoadParameter) async throws { + #expect(param.load1 == param.load2) } - - @Test func testMultiple() async throws { - var load1: CachedAsyncLoad = .none - var load2: CachedAsyncLoad = .none - - #expect(load1 == load2) - - load1 = .loading() - load2 = .loading() - - #expect(load1 == load2) - - load1 = .loaded("some") - load2 = .loaded("some") - - #expect(load1 == load2) - load1 = .loading("some") - load2 = .loading("other") - - #expect(load1 != load2) - - load1 = .loading() - load2 = .loading() - - #expect(load1 == load2) - - load1 = .error("some", TestingError.some) - load2 = .error(nil, TestingError.some) - - #expect(load1 != load2) + @Test<[CachedAsyncLoadParameter]>("Should not be equal ", arguments: [ + .init(.loaded(User(name: "Alex")), .loaded(User(name: "Daniel"))), + .init(.loading(User(name: "Alex")), .loading(User(name: "Daniel"))), + .init(.error(nil, TestingError.some), .error(User(name: "some"), TestingError.some)), + .init(.error(User(name: "Alex"), TestingError.some), .error(User(name: "Daniel"), TestingError.some)), + ]) + func nonEqualUser(param: CachedAsyncLoadParameter) async throws { + #expect(param.load1 != param.load2) } } diff --git a/Tests/AsyncLoadTests/CachedAsyncLoadNonEquatableItemTests.swift b/Tests/AsyncLoadTests/CachedAsyncLoadNonEquatableItemTests.swift index 3f50d36..a16da59 100644 --- a/Tests/AsyncLoadTests/CachedAsyncLoadNonEquatableItemTests.swift +++ b/Tests/AsyncLoadTests/CachedAsyncLoadNonEquatableItemTests.swift @@ -3,68 +3,17 @@ import Testing @Suite("Test non-equatable CachedAsyncLoad") struct CachedAsyncLoadNonEquatableItemTests { - @Test func testNone() async throws { - let load1: CachedAsyncLoad = .none - let load2: CachedAsyncLoad = .none - - #expect(load1 == load2) - } - - @Test func testLoadedString() async throws { - var load1: CachedAsyncLoad = .loaded(NonEquatableItem(name: "Hello")) - var load2: CachedAsyncLoad = .loaded(NonEquatableItem(name: "Hello")) - - #expect(load1 == load2) - - load1 = .loaded(NonEquatableItem(name: "Some")) - load2 = .loaded(NonEquatableItem(name: "Other")) - - #expect(load1 == load2) - } - - @Test func testLoading() async throws { - let load1: CachedAsyncLoad = .loading() - let load2: CachedAsyncLoad = .loading() - - #expect(load1 == load2) - } - - @Test func testError() async throws { - var load1: CachedAsyncLoad = .error(nil, TestingError.some) - var load2: CachedAsyncLoad = .error(nil, TestingError.some) - - #expect(load1 == load2) - - load1 = .error(nil, TestingError.some) - load2 = .error(NonEquatableItem(name: "Hello"), TestingError.other) - - #expect(load1 == load2) - } - - @Test func testMultiple() async throws { - var load1: CachedAsyncLoad = .none - var load2: CachedAsyncLoad = .none - - #expect(load1 == load2) - - load1 = .loading() - load2 = .loading() - - #expect(load1 == load2) - - load1 = .loaded(NonEquatableItem(name: "Some")) - load2 = .loaded(NonEquatableItem(name: "Some")) - - #expect(load1 == load2) - - load1 = .loaded(NonEquatableItem(name: "Some")) - load2 = .loaded(NonEquatableItem(name: "Other")) - - #expect(load1 == load2) - - load1 = .error(NonEquatableItem(name: "Hello"), TestingError.some) - load2 = .error(NonEquatableItem(name: "Hello"), TestingError.some) - - #expect(load1 == load2) + @Test<[CachedAsyncLoadParameter]>("Should be equal (structural)", arguments: [ + .init(.none, .none), + .init(.loading(), .loading()), + .init(.loaded(NonEquatableItem(name: "Hello")), .loaded(NonEquatableItem(name: "Different"))), + .init(.loaded(NonEquatableItem(name: "Some")), .loaded(NonEquatableItem(name: "Other"))), +// .init(.loading(NonEquatableItem(name: "Some")), .loading(NonEquatableItem(name: "Other"))), +// .init(.error(nil, TestingError.some), .error(nil, TestingError.some)), +// .init(.error(nil, TestingError.some), .error(NonEquatableItem(name: "Hello"), TestingError.other)), +// .init(.error(NonEquatableItem(name: "Hello"), TestingError.some), .error(NonEquatableItem(name: "World"), TestingError.some)), + ]) + func structuralEquality(param: CachedAsyncLoadParameter) async throws { + #expect(param.load1 == param.load2) } } diff --git a/Tests/AsyncLoadTests/Utils.swift b/Tests/AsyncLoadTests/Utils.swift index 80dc623..b3cdbb0 100644 --- a/Tests/AsyncLoadTests/Utils.swift +++ b/Tests/AsyncLoadTests/Utils.swift @@ -1,11 +1,12 @@ import Foundation +@testable import AsyncLoad enum TestingError: Error { case some case other } -class NonEquatableItem { +final class NonEquatableItem: Sendable { let name: String init(name: String) { @@ -16,3 +17,43 @@ class NonEquatableItem { struct User: Equatable { let name: String } + +struct AsyncActionParameter { + let action1: AsyncAction + let action2: AsyncAction + + init(_ action1: AsyncAction, _ action2: AsyncAction) { + self.action1 = action1 + self.action2 = action2 + } +} + +struct AsyncLoadParameter { + let load1: AsyncLoad + let load2: AsyncLoad + + init(_ load1: AsyncLoad, _ load2: AsyncLoad) { + self.load1 = load1 + self.load2 = load2 + } +} + +struct CachedAsyncActionParameter { + let action1: CachedAsyncAction + let action2: CachedAsyncAction + + init(_ action1: CachedAsyncAction, _ action2: CachedAsyncAction) { + self.action1 = action1 + self.action2 = action2 + } +} + +struct CachedAsyncLoadParameter { + let load1: CachedAsyncLoad + let load2: CachedAsyncLoad + + init(_ load1: CachedAsyncLoad, _ load2: CachedAsyncLoad) { + self.load1 = load1 + self.load2 = load2 + } +} From f22986ed0ede0c15774317e20a99e2ef82299367 Mon Sep 17 00:00:00 2001 From: Alexander Kauer Date: Mon, 29 Sep 2025 16:50:15 +0200 Subject: [PATCH 6/6] added commented test cases --- .../CachedAsyncLoadNonEquatableItemTests.swift | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Tests/AsyncLoadTests/CachedAsyncLoadNonEquatableItemTests.swift b/Tests/AsyncLoadTests/CachedAsyncLoadNonEquatableItemTests.swift index a16da59..c55af85 100644 --- a/Tests/AsyncLoadTests/CachedAsyncLoadNonEquatableItemTests.swift +++ b/Tests/AsyncLoadTests/CachedAsyncLoadNonEquatableItemTests.swift @@ -8,10 +8,10 @@ struct CachedAsyncLoadNonEquatableItemTests { .init(.loading(), .loading()), .init(.loaded(NonEquatableItem(name: "Hello")), .loaded(NonEquatableItem(name: "Different"))), .init(.loaded(NonEquatableItem(name: "Some")), .loaded(NonEquatableItem(name: "Other"))), -// .init(.loading(NonEquatableItem(name: "Some")), .loading(NonEquatableItem(name: "Other"))), -// .init(.error(nil, TestingError.some), .error(nil, TestingError.some)), -// .init(.error(nil, TestingError.some), .error(NonEquatableItem(name: "Hello"), TestingError.other)), -// .init(.error(NonEquatableItem(name: "Hello"), TestingError.some), .error(NonEquatableItem(name: "World"), TestingError.some)), + .init(.loading(NonEquatableItem(name: "Some")), .loading(NonEquatableItem(name: "Other"))), + .init(.error(nil, TestingError.some), .error(nil, TestingError.some)), + .init(.error(nil, TestingError.some), .error(NonEquatableItem(name: "Hello"), TestingError.other)), + .init(.error(NonEquatableItem(name: "Hello"), TestingError.some), .error(NonEquatableItem(name: "World"), TestingError.some)), ]) func structuralEquality(param: CachedAsyncLoadParameter) async throws { #expect(param.load1 == param.load2)