diff --git a/Workflow/Sources/AnyWorkflow+Rendering.swift b/Workflow/Sources/AnyWorkflow+Rendering.swift new file mode 100644 index 000000000..ba72ce416 --- /dev/null +++ b/Workflow/Sources/AnyWorkflow+Rendering.swift @@ -0,0 +1,34 @@ +/* + * Copyright 2020 Square Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +extension AnyWorkflow where Output == Never { + /// Creates an AnyWorkflow that does nothing but echo the given `rendering`. + /// + /// - Note: To use with `RenderTester`, use `expectRenderingWorkflow` + public init(rendering: Rendering) { + self = RenderingWorkflow(rendering: rendering).asAnyWorkflow() + } +} + +struct RenderingWorkflow: Workflow { + var rendering: Rendering + typealias Output = Never + typealias State = Void + + func render(state: State, context: RenderContext) -> Rendering { + return rendering + } +} diff --git a/Workflow/Tests/AnyWorkflowRenderingTests.swift b/Workflow/Tests/AnyWorkflowRenderingTests.swift new file mode 100644 index 000000000..54b34b431 --- /dev/null +++ b/Workflow/Tests/AnyWorkflowRenderingTests.swift @@ -0,0 +1,45 @@ +/* + * Copyright 2020 Square Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import XCTest +@testable import Workflow + +public class AnyWorkflowRenderingTests: XCTestCase { + func testRenderingString() { + let workflow = AnyWorkflow(rendering: "Hello") + let node = WorkflowNode(workflow: PassthroughWorkflow(workflow)) + + XCTAssertEqual(node.render(), "Hello") + } + + func testRenderingInt() { + let workflow = AnyWorkflow(rendering: 160) + let node = WorkflowNode(workflow: PassthroughWorkflow(workflow)) + + XCTAssertEqual(node.render(), 160) + } +} + +private struct PassthroughWorkflow: Workflow { + var child: AnyWorkflow + init(_ child: AnyWorkflow) { + self.child = child + } + + func render(state: Void, context: RenderContext) -> Rendering { + child.rendered(in: context) + } +} diff --git a/WorkflowTesting/Sources/WorkflowRenderTester.swift b/WorkflowTesting/Sources/WorkflowRenderTester.swift index 41a2ac6d6..eb5249755 100644 --- a/WorkflowTesting/Sources/WorkflowRenderTester.swift +++ b/WorkflowTesting/Sources/WorkflowRenderTester.swift @@ -253,6 +253,25 @@ } } + extension RenderTester { + /// Expect a constant rendering workflow as created with `AnyWorkflow(rendering:)` + /// + /// - Parameters: + /// - key: The key of the expected workflow (if specified). + /// - rendering: The rendering result that should be returned when this workflow is rendered. + public func expectRenderingWorkflow( + key: String = "", + producingRendering rendering: Rendering, + file: StaticString = #file, line: UInt = #line + ) -> RenderTester { + return expectWorkflow( + type: RenderingWorkflow.self, + producingRendering: rendering, + file: file, line: line + ) + } + } + extension Collection { fileprivate func appending(_ element: Element) -> [Element] { return self + [element] diff --git a/WorkflowTesting/Tests/WorkflowRenderTesterTests.swift b/WorkflowTesting/Tests/WorkflowRenderTesterTests.swift index fcd792b3a..8b82235f9 100644 --- a/WorkflowTesting/Tests/WorkflowRenderTesterTests.swift +++ b/WorkflowTesting/Tests/WorkflowRenderTesterTests.swift @@ -115,6 +115,16 @@ final class WorkflowRenderTesterTests: XCTestCase { XCTAssertEqual("Failed", state.text) } } + + func test_renderingWorkflow() { + WrappingWorkflow(child: AnyWorkflow(rendering: "not-called")) + .renderTester() + .expectRenderingWorkflow(producingRendering: "real") + .render { rendering in + XCTAssertEqual("->real<-", rendering) + } + .assertNoOutput() + } } private struct TestWorkflow: Workflow { @@ -320,3 +330,13 @@ private struct ChildWorkflow: Workflow { String(text.reversed()) } } + +private struct WrappingWorkflow: Workflow { + var child: AnyWorkflow + + typealias State = Void + + func render(state: State, context: RenderContext) -> String { + "->" + child.rendered(in: context) + "<-" + } +}