diff --git a/Sources/SwiftCurrent_SwiftUI/Models/ExtendedFlowRepresentableMetadata.swift b/Sources/SwiftCurrent_SwiftUI/Models/ExtendedFlowRepresentableMetadata.swift index 0397780c7..53d217cff 100644 --- a/Sources/SwiftCurrent_SwiftUI/Models/ExtendedFlowRepresentableMetadata.swift +++ b/Sources/SwiftCurrent_SwiftUI/Models/ExtendedFlowRepresentableMetadata.swift @@ -17,9 +17,13 @@ class ExtendedFlowRepresentableMetadata: FlowRepresentableMetadata { launchStyle: LaunchStyle = .default, flowPersistence: @escaping (AnyWorkflow.PassedArgs) -> FlowPersistence = { _ in .default }, flowRepresentableFactory: @escaping (AnyWorkflow.PassedArgs) -> AnyFlowRepresentable) { + func createWorkflowItem() -> WorkflowItem { + WorkflowItem(FR.self).presentationType(.init(rawValue: launchStyle) ?? .default) + } + workflowItemFactory = { - guard let wrappedWorkflowItem = $0 else { return AnyWorkflowItem(view: WorkflowItem(FR.self)) } - return AnyWorkflowItem(view: WorkflowItemWrapper(content: WorkflowItem(FR.self)) { wrappedWorkflowItem }) + guard let wrappedWorkflowItem = $0 else { return AnyWorkflowItem(view: WorkflowItemWrapper(content: createWorkflowItem())) } + return AnyWorkflowItem(view: WorkflowItemWrapper(content: createWorkflowItem()) { wrappedWorkflowItem }) } super.init(flowRepresentableType, launchStyle: launchStyle, flowPersistence: flowPersistence, flowRepresentableFactory: flowRepresentableFactory) @@ -28,9 +32,13 @@ class ExtendedFlowRepresentableMetadata: FlowRepresentableMetadata { init(flowRepresentableType: FR.Type, launchStyle: LaunchStyle = .default, flowPersistence: @escaping (AnyWorkflow.PassedArgs) -> FlowPersistence = { _ in .default }) { + func createWorkflowItem() -> WorkflowItem { + WorkflowItem(FR.self).presentationType(.init(rawValue: launchStyle) ?? .default) + } + workflowItemFactory = { - guard let wrappedWorkflowItem = $0 else { return AnyWorkflowItem(view: WorkflowItem(FR.self)) } - return AnyWorkflowItem(view: WorkflowItemWrapper(content: WorkflowItem(FR.self)) { wrappedWorkflowItem }) + guard let wrappedWorkflowItem = $0 else { return AnyWorkflowItem(view: WorkflowItemWrapper(content: createWorkflowItem())) } + return AnyWorkflowItem(view: WorkflowItemWrapper(content: createWorkflowItem()) { wrappedWorkflowItem }) } super.init(flowRepresentableType, launchStyle: launchStyle, flowPersistence: flowPersistence) { args in diff --git a/SwiftCurrent.xcworkspace/xcshareddata/xcschemes/SwiftCurrentMultiPlatformTests.xcscheme b/SwiftCurrent.xcworkspace/xcshareddata/xcschemes/SwiftCurrentMultiPlatformTests.xcscheme index da4ca12c2..e709a5674 100644 --- a/SwiftCurrent.xcworkspace/xcshareddata/xcschemes/SwiftCurrentMultiPlatformTests.xcscheme +++ b/SwiftCurrent.xcworkspace/xcshareddata/xcschemes/SwiftCurrentMultiPlatformTests.xcscheme @@ -49,4 +49,4 @@ buildConfiguration = "Release" revealArchiveInOrganizer = "YES"> - \ No newline at end of file + diff --git a/Tests/SwiftCurrent_SwiftUITests/SwiftCurrent_SwiftUITests.swift b/Tests/SwiftCurrent_SwiftUITests/SwiftCurrent_SwiftUITests.swift index b914faf9b..9a0181130 100644 --- a/Tests/SwiftCurrent_SwiftUITests/SwiftCurrent_SwiftUITests.swift +++ b/Tests/SwiftCurrent_SwiftUITests/SwiftCurrent_SwiftUITests.swift @@ -794,7 +794,7 @@ final class SwiftCurrent_SwiftUIConsumerTests: XCTestCase, App { XCTAssertNoThrow(try launcher.view(WorkflowItemWrapper, Never>.self)) } - func testLaunchingAWorkflowWithOneItemFromAnAnyWorkflow() throws { + func testLaunchingAWorkflowWithOneItemFromAnAnyWorkflow() async throws { struct FR1: View, FlowRepresentable, Inspectable, WorkflowDecodable { weak var _workflowPointer: AnyFlowRepresentable? @@ -805,15 +805,67 @@ final class SwiftCurrent_SwiftUIConsumerTests: XCTestCase, App { let wf = try decodeAnyWorkflow(with: FR1.self) - let launcher = WorkflowView(workflow: wf) + let launcher = try await MainActor.run { + WorkflowView(workflow: wf) + }.hostAndInspect(with: \.inspection) + + XCTAssertNoThrow(try launcher.find(FR1.self), "Unable to find FR1") + } + + func testLaunchingAWorkflowFromAnAnyWorkflow_UsesCorrectLaunchStyle() async throws { + struct FR1: View, FlowRepresentable, Inspectable, WorkflowDecodable { + weak var _workflowPointer: AnyFlowRepresentable? + + var body: some View { + Button("Proceed") { proceedInWorkflow() } + } + } + + let firstWorkflowJSON = try XCTUnwrap(""" + { + "schemaVersion": "\(AnyWorkflow.jsonSchemaVersion.rawValue)", + "sequence" : [ + { + "flowRepresentableName" : "FR1", + "launchStyle" : "modal" + } + ] + } + """.data(using: .utf8)) + + let firstWF = try JSONDecoder().decodeWorkflow(withAggregator: TestRegistry(types: [FR1.self]), from: firstWorkflowJSON) + + let firstLauncher = try await MainActor.run { + WorkflowView(workflow: firstWF) + }.hostAndInspect(with: \.inspection) - let exp = launcher.inspection.inspect { view in - XCTAssertNoThrow(try view.find(FR1.self)) + XCTAssertNoThrow(try firstLauncher.find(FR1.self), "Unable to find FR1") + let fr1Wrapper = try await firstLauncher.extractWorkflowLauncher().view(AnyWorkflowItem.self).anyView().view(WorkflowItemWrapper, Never>.self) + let fr1LaunchStyle = try await fr1Wrapper.actualView().workflowLaunchStyle + XCTAssertEqual(fr1LaunchStyle, .modal) + + let secondWorkflowJSON = try XCTUnwrap(""" + { + "schemaVersion": "\(AnyWorkflow.jsonSchemaVersion.rawValue)", + "sequence" : [ + { + "flowRepresentableName" : "FR1", + "launchStyle" : "navigationLink" + } + ] } + """.data(using: .utf8)) - ViewHosting.host(view: launcher) + let secondWF = try JSONDecoder().decodeWorkflow(withAggregator: TestRegistry(types: [FR1.self]), from: secondWorkflowJSON) - wait(for: [exp], timeout: TestConstant.timeout) + let secondLauncher = try await MainActor.run { + WorkflowView(workflow: secondWF) + }.hostAndInspect(with: \.inspection) + + XCTAssertNoThrow(try secondLauncher.find(FR1.self), "Unable to find FR1") + let secondFr1Wrapper = try await secondLauncher.extractWorkflowLauncher().view(AnyWorkflowItem.self).anyView().view(WorkflowItemWrapper, Never>.self) + let secondFr1LaunchStyle = try await secondFr1Wrapper.actualView().workflowLaunchStyle + XCTAssertEqual(secondFr1LaunchStyle, .navigationLink) } func testLaunchingAMultiTypeLongWorkflowFromAnAnyWorkflow() async throws { @@ -1008,7 +1060,7 @@ final class SwiftCurrent_SwiftUIConsumerTests: XCTestCase, App { wait(for: [expectOnFinish], timeout: TestConstant.timeout) } - func testLaunchingAWorkflowUsingNonPassedArgsStartingArgs() throws { + func testLaunchingAWorkflowUsingNonPassedArgsStartingArgs() async throws { struct FR1: View, FlowRepresentable, Inspectable, WorkflowDecodable { weak var _workflowPointer: AnyFlowRepresentable? var body: some View { Text("FR1 type") } @@ -1019,15 +1071,11 @@ final class SwiftCurrent_SwiftUIConsumerTests: XCTestCase, App { let wf = try decodeAnyWorkflow(with: FR1.self) let expectedData = UUID().uuidString - let launcher = WorkflowView(launchingWith: expectedData, workflow: wf) - - let expectViewLoaded = launcher.inspection.inspect { viewUnderTest in - XCTAssertEqual(try viewUnderTest.find(FR1.self).actualView().data, expectedData) - } - - ViewHosting.host(view: launcher) + let launcher = try await MainActor.run { + WorkflowView(launchingWith: expectedData, workflow: wf) + }.hostAndInspect(with: \.inspection) - wait(for: [expectViewLoaded], timeout: TestConstant.timeout) + XCTAssertEqual(try launcher.find(FR1.self).actualView().data, expectedData) } func testIfNoWorkflowItemsThenFatalError() throws {