From 69ae65ab0361fe4d348d8a1b9fad3c7ce947ea92 Mon Sep 17 00:00:00 2001 From: Neetesh Gupta Date: Tue, 18 Jun 2024 22:43:08 +0100 Subject: [PATCH 1/2] Add `.task(id: ...)` inspection --- .../Modifiers/EventsModifiers.swift | 11 ++++ .../ViewModifiers/EventsModifiersTests.swift | 63 +++++++++++++++++++ 2 files changed, 74 insertions(+) diff --git a/Sources/ViewInspector/Modifiers/EventsModifiers.swift b/Sources/ViewInspector/Modifiers/EventsModifiers.swift index 80ec3a43..047848ee 100644 --- a/Sources/ViewInspector/Modifiers/EventsModifiers.swift +++ b/Sources/ViewInspector/Modifiers/EventsModifiers.swift @@ -62,4 +62,15 @@ public extension InspectableView { type: (@Sendable () async -> Void).self, call: "task") await callback() } + + func callTask(id: some Equatable, index: Int = 0) async throws { + let typeName = Inspector.typeName(type: type(of: id)) + let callback = try modifierAttribute( + modifierName: "_TaskValueModifier<\(typeName)>", + path: "modifier|action", + type: (@Sendable () async -> Void).self, + call: "task", + index: index) + await callback() + } } diff --git a/Tests/ViewInspectorTests/ViewModifiers/EventsModifiersTests.swift b/Tests/ViewInspectorTests/ViewModifiers/EventsModifiersTests.swift index b33aed70..b873e5df 100644 --- a/Tests/ViewInspectorTests/ViewModifiers/EventsModifiersTests.swift +++ b/Tests/ViewInspectorTests/ViewModifiers/EventsModifiersTests.swift @@ -157,6 +157,69 @@ final class ViewEventsTests: XCTestCase { try await sut.inspect().emptyView().callTask() await fulfillment(of: [exp], timeout: 0.1) } + + func testTaskIdInspection() async throws { + guard #available(iOS 15, macOS 12, tvOS 15, watchOS 8, *) else { throw XCTSkip() } + let exp = XCTestExpectation(description: #function) + let sut = EmptyView().padding() + .task(id: "id") { + exp.fulfill() + } + try await sut.inspect().emptyView().callTask(id: "id") + await fulfillment(of: [exp], timeout: 0.1) + } + + func testTaskIdInspectionWithIndex() async throws { + guard #available(iOS 15, macOS 12, tvOS 15, watchOS 8, *) else { throw XCTSkip() } + let exp1 = XCTestExpectation(description: "task1") + let exp2 = XCTestExpectation(description: "task2") + exp1.assertForOverFulfill = true + exp2.assertForOverFulfill = true + + let sut = EmptyView().padding() + .task(id: "id1") { + exp1.fulfill() + } + .task(id: "id2") { + exp2.fulfill() + } + + try await sut.inspect().emptyView().callTask(id: "id1", index: 0) + await fulfillment(of: [exp1], timeout: 0.1) + + try await sut.inspect().emptyView().callTask(id: "id2", index: 1) + await fulfillment(of: [exp2], timeout: 0.1) + } + + func testTaskIdInspectionMultipleDifferentTypes() async throws { + guard #available(iOS 15, macOS 12, tvOS 15, watchOS 8, *) else { throw XCTSkip() } + struct CustomEquatableStruct: Equatable { + let value: Int + } + let exp1 = XCTestExpectation(description: "task1") + let exp2 = XCTestExpectation(description: "task2") + let exp3 = XCTestExpectation(description: "task3") + exp1.assertForOverFulfill = true + exp2.assertForOverFulfill = true + exp3.assertForOverFulfill = true + + let sut = EmptyView().padding() + .task(id: "id") { + exp1.fulfill() + } + .task(id: 2) { + exp2.fulfill() + } + .task(id: CustomEquatableStruct(value: 1)) { + exp3.fulfill() + } + + async let _ = try sut.inspect().emptyView().callTask(id: 2) + async let _ = try sut.inspect().emptyView().callTask(id: "id") + async let _ = try sut.inspect().emptyView().callTask(id: CustomEquatableStruct(value: 1)) + + await fulfillment(of: [exp1, exp2, exp3], timeout: 0.1) + } } // MARK: - ViewPublisherEventsTests From 34e1db7253e7678760b1d2cfb6800b866f0ff6b9 Mon Sep 17 00:00:00 2001 From: Neetesh Gupta Date: Sat, 22 Jun 2024 23:58:43 +0100 Subject: [PATCH 2/2] Update readiness with `.task(id: ...)` inspection support --- readiness.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/readiness.md b/readiness.md index 572c15b6..d596eed3 100644 --- a/readiness.md +++ b/readiness.md @@ -350,7 +350,8 @@ This document reflects the current status of the [ViewInspector](https://github. |:---:|---| |:white_check_mark:| `func onReceive

(P, perform: (P.Output) -> Void) -> some View` | |:white_check_mark:| `func onChange(of: V, perform: (V) -> Void) -> some View` | -|:white_check_mark:| `func task(...) -> some View` | +|:white_check_mark:| `func task(priority: TaskPriority, () async -> Void) -> some View` | +|:white_check_mark:| `func task(id: T, priority: TaskPriority, () async -> Void) -> some View` | ### Handling View Hover and Focus