Skip to content

//workflow/com.squareup.workflow1.testing/RenderTester

RenderTester

[jvm] abstract class RenderTester<PropsT, StateT, OutputT, RenderingT>

The props must be specified, the initial state may be specified, and then all child workflows and workers that are expected to run, and any outputs from them, must be specified with expectWorkflow and (optionally) expectWorker calls. If one needs to verify all workers explicitly, perhaps to verify that a worker is not run, then use requireExplicitWorkerExpectations. Then call render and perform any assertions on the rendering. An event may also be sent to the rendering if no workflows or workers emitted an output. Lastly, the RenderTestResult returned by render may be used to assert on the WorkflowActions processed to handle events or outputs by calling verifyAction or verifyActionResult.

  • All workflows that are rendered/ran by this workflow must be specified.
  • Workers are optionally specified. Specified workers must run. Unexpected workers on a render pass do not cause a test failure.
  • It is an error if more than one workflow or worker specifies an output.
  • It is a test failure if any workflows or workers that were expected were not ran.
  • It is a test failure if the workflow tried to run any workflows that were not expected.
  • It is a test failure if no workflow or workflow emitted an output, no rendering event was invoked, and any of the action verification methods on [RenderTestResult](../-render-test-result/index.md) is called.

Examples

Worker output

The following example tests a render pass that runs one worker, SubmitLoginWorker, which is configured to have “emitted” an output, and one workflow, ChildWorkflow, which expects a props containing “test@foo.com” and returning a ChildRendering as its rendering.

It checks that the rendering properties are expected and that the output handler for the SubmitLoginWorker returned the CompleteLogin action.

workflow
.testRender(
props = MyProps(…),
initialState = MyState(…)
)
.expectWorker(
workerClass = SubmitLoginWorker::class
key = “signin”,
output = WorkflowOutput(LoginResponse(success = true))
)
.expectWorkflow(
workflowType = ChildWorkflow::class,
key = “child”,
assertProps = { assertThat(it.email).isEqualTo(“test@foo.com”) },
rendering = ChildRendering(“message”)
)
.render { rendering ->
assertThat(rendering.text).isEqualTo(“foo”)
}
.verifyAction { action ->
assertThat(action).isEqualTo(Action.CompleteLogin(success = true))
}

Rendering event

This is similar to the example above, but will test an event sent to the rendering instead.

workflow
.testRender(
props = MyProps(…),
initialState = MyState(…)
)
.expectWorker(
matchesWhen = { it is SubmitLoginWorker },
key = “signin”
)
.expectWorkflow(
workflowType = ChildWorkflow::class,
key = “child”,
assertProps = { assertThat(it.email).isEqualTo(“test@foo.com”) },
rendering = ChildRendering(“message”)
)
.render { rendering ->
rendering.onCancelClicked()
assertThat(rendering.text).isEqualTo(“foo”)
}
.verifyAction { action ->
assertThat(action).isEqualTo(Action.CancelLogin)
}

Verify action result

This test verifies the action result instead of the action itself. This technique is useful if the WorkflowAction is anonymous or inline.

val currentState = …
val previousState = …

workflow
.testRender(
props = MyProps(…),
initialState = currentState
)
.render { rendering ->
rendering.onCancelClicked()
}
.verifyActionResult { newState, output ->
// Check that the workflow navigated back correctly.
assertThat(newState).isEqualTo(previousState)

1
2
// Check that the workflow didn't emit any output from the button click.  
assertThat(output).isNull()

}

Too many outputs

This is an example of what not to do – this test will error out because a worker is emitting and output and a rendering event is sent.

workflow
.testRender(
props = MyProps(…),
initialState = MyState(…)
)
.expectWorker(
matchesWhen = { it is SubmitLoginWorker },
key = “signin”,
output = WorkflowOutput(LoginResponse(success = true))
)
.expectWorkflow(
workflowType = ChildWorkflow::class,
key = “child”,
assertProps = { assertThat(it.email).isEqualTo(“test@foo.com”) },
rendering = ChildRendering(“message”)
)
.render { rendering ->
// This will throw and fail the test because the SubmitLoginWorker is also configured to emit
// an output.
rendering.onCancelClicked()

Constructors

RenderTester [jvm] fun RenderTester()

Types

Name Summary
ChildWorkflowMatch [jvm]
Content
sealed class ChildWorkflowMatch


RenderChildInvocation [jvm]
Content
class RenderChildInvocation(workflow: Workflow<, *, *>, **props*: Any?, outputType: KTypeProjection, renderingType: KTypeProjection, renderKey: String)
More info
Describes a call to RenderContext.renderChild.


Functions

Name Summary
expectSideEffect [jvm]
Content
abstract fun expectSideEffect(description: String, exactMatch: Boolean = true, matcher: (key: String) -> Boolean): RenderTester<PropsT, StateT, OutputT, RenderingT>
More info
Specifies that this render pass is expected to run a side effect with a key that satisfies matcher.


render [jvm]
Content
abstract fun render(block: (RenderingT) -> Unit = {}): RenderTestResult<PropsT, StateT, OutputT>
More info
Execute the workflow’s render method and run block to perform assertions on and send events to the resulting rendering.


requireExplicitWorkerExpectations [jvm]
Content
abstract fun requireExplicitWorkerExpectations(): RenderTester<PropsT, StateT, OutputT, RenderingT>


Extensions

Name Summary
expectSideEffect [jvm]
Content
fun <PropsT, StateT, OutputT, RenderingT> RenderTester<PropsT, StateT, OutputT, RenderingT>.expectSideEffect(key: String): RenderTester<PropsT, StateT, OutputT, RenderingT>
More info
Specifies that this render pass is expected to run a particular side effect.


expectWorker [jvm]
Content
inline fun <PropsT, StateT, OutputT, RenderingT, WorkerOutputT, WorkerT : Worker<WorkerOutputT>> RenderTester<PropsT, StateT, OutputT, RenderingT>.expectWorker(expected: WorkerT, key: String = “”, output: WorkflowOutput<WorkerOutputT>? = null, description: String = “”): RenderTester<PropsT, StateT, OutputT, RenderingT>
More info
Specifies that this render pass is expected to run a Worker that has the same type of the given worker and for which the actual worker’s doesSameWorkAs method returns true.


[jvm]
Content
inline fun <PropsT, StateT, OutputT, RenderingT, WorkerOutputT, WorkerT : Worker<WorkerOutputT>> RenderTester<PropsT, StateT, OutputT, RenderingT>.expectWorker(workerClass: KClassWorkerT>, key: String = “”, crossinline assertWorker: (WorkerT) -> Unit = {}, output: WorkflowOutput<WorkerOutputT>? = null, description: String = “”): RenderTester<PropsT, StateT, OutputT, RenderingT>
More info
Specifies that this render pass is expected to run a Worker with the given workerClass.


[jvm]
Content
fun <PropsT, StateT, OutputT, RenderingT> RenderTester<PropsT, StateT, OutputT, RenderingT>.expectWorker(workerType: KType, key: String = “”, assertWorker: (Worker<>) -> Unit = {}, output: WorkflowOutput<>? = null, description: String = “”): RenderTester<PropsT, StateT, OutputT, RenderingT>
More info
Specifies that this render pass is expected to run a Worker whose KType matches workerType.


expectWorkerOutputting [jvm]
Content
inline fun <PropsT, StateT, OutputT, RenderingT> RenderTester<PropsT, StateT, OutputT, RenderingT>.expectWorkerOutputting(outputType: KType, key: String = “”, crossinline assertWorker: (Worker<>) -> Unit = {}, output: WorkflowOutput<>? = null, description: String = “”): RenderTester<PropsT, StateT, OutputT, RenderingT>
More info
Specifies that this render pass is expected to run a Worker with the given outputType.


expectWorkflow [jvm]
Content
inline fun <ChildRenderingT, PropsT, StateT, OutputT, RenderingT> RenderTester<PropsT, StateT, OutputT, RenderingT>.expectWorkflow(identifier: WorkflowIdentifier, rendering: ChildRenderingT, key: String = “”, description: String = “”, noinline assertProps: (props: Any?) -> Unit = {}): RenderTester<PropsT, StateT, OutputT, RenderingT>
fun <ChildOutputT, ChildRenderingT, PropsT, StateT, OutputT, RenderingT> RenderTester<PropsT, StateT, OutputT, RenderingT>.expectWorkflow(identifier: WorkflowIdentifier, rendering: ChildRenderingT, output: WorkflowOutput<ChildOutputT>?, key: String = “”, description: String = “”, assertProps: (props: Any?) -> Unit = {}): RenderTester<PropsT, StateT, OutputT, RenderingT>
inline fun <ChildPropsT, ChildOutputT, ChildRenderingT, PropsT, StateT, OutputT, RenderingT> RenderTester<PropsT, StateT, OutputT, RenderingT>.expectWorkflow(workflowType: KClass<out Workflow<ChildPropsT, ChildOutputT, ChildRenderingT>>, rendering: ChildRenderingT, key: String = “”, crossinline assertProps: (ChildPropsT) -> Unit = {}, output: WorkflowOutput<ChildOutputT>? = null, description: String = “”): RenderTester<PropsT, StateT, OutputT, RenderingT>
More info
Specifies that this render pass is expected to render a particular child workflow.