@@ -103,6 +103,8 @@ internal class RealRenderTester<PropsT, StateT, OutputT, RenderingT>(
103
103
}
104
104
}
105
105
106
+ private var frozen = false
107
+
106
108
private var explicitWorkerExpectationsRequired: Boolean = false
107
109
private var explicitSideEffectExpectationsRequired: Boolean = false
108
110
private val stateAndOutput: Pair <StateT , WorkflowOutput <OutputT >? > by lazy {
@@ -151,12 +153,13 @@ internal class RealRenderTester<PropsT, StateT, OutputT, RenderingT>(
151
153
expectSideEffect(description = " unexpected side effect" , exactMatch = false ) { true }
152
154
}
153
155
156
+ frozen = false
154
157
// Clone the expectations to run a "dry" render pass.
155
158
val noopContext = deepCloneForRender()
156
159
workflow.render(props, state, RenderContext (noopContext, workflow))
157
-
158
- workflow.render(props, state, RenderContext ( this , workflow))
159
- . also ( block)
160
+ val rendering = workflow.render(props, state, RenderContext ( this , workflow))
161
+ frozen = true
162
+ block(rendering )
160
163
161
164
// Ensure all exact matches were consumed.
162
165
val unconsumedExactMatches = expectations.filter {
@@ -184,6 +187,7 @@ internal class RealRenderTester<PropsT, StateT, OutputT, RenderingT>(
184
187
key : String ,
185
188
handler : (ChildOutputT ) -> WorkflowAction <PropsT , StateT , OutputT >
186
189
): ChildRenderingT {
190
+ checkNotFrozen { " renderChild(${child.identifier} )" }
187
191
val identifierPair = Pair (child.identifier, key)
188
192
require(identifierPair !in renderedChildren) {
189
193
" Expected keys to be unique for ${child.identifier} : key=\" $key \" "
@@ -244,6 +248,7 @@ internal class RealRenderTester<PropsT, StateT, OutputT, RenderingT>(
244
248
key : String ,
245
249
sideEffect : suspend CoroutineScope .() -> Unit
246
250
) {
251
+ checkNotFrozen { " runningSideEffect($key )" }
247
252
require(key !in ranSideEffects) { " Expected side effect keys to be unique: \" $key \" " }
248
253
ranSideEffects + = key
249
254
@@ -279,6 +284,7 @@ internal class RealRenderTester<PropsT, StateT, OutputT, RenderingT>(
279
284
vararg inputs : Any? ,
280
285
calculation : () -> ResultT
281
286
): ResultT {
287
+ checkNotFrozen { " remember($key )" }
282
288
val mapKey = TestRememberKey (key, resultType, inputs.asList())
283
289
check(rememberSet.add(mapKey)) {
284
290
" Expected combination of key, inputs and result type to be unique: \" $key \" "
@@ -297,6 +303,12 @@ internal class RealRenderTester<PropsT, StateT, OutputT, RenderingT>(
297
303
}
298
304
299
305
override fun send (value : WorkflowAction <PropsT , StateT , OutputT >) {
306
+ if (! frozen) {
307
+ throw UnsupportedOperationException (
308
+ " Expected sink to not be sent to until after the render pass. " +
309
+ " Received action: ${value.debuggingName} "
310
+ )
311
+ }
300
312
checkNoOutputs()
301
313
check(processedAction == null ) {
302
314
" Tried to send action to sink after another action was already processed:\n " +
@@ -363,6 +375,11 @@ internal class RealRenderTester<PropsT, StateT, OutputT, RenderingT>(
363
375
expectationsWithOutputs.joinToString(separator = " \n " ) { " $it " }
364
376
}
365
377
}
378
+
379
+ private fun checkNotFrozen (reason : () -> String = { "" }) = check(! frozen) {
380
+ " RenderContext cannot be used after render method returns" +
381
+ " ${reason().takeUnless { it.isBlank() }?.let { " ($it )" }} "
382
+ }
366
383
}
367
384
368
385
internal fun createRenderChildInvocation (
0 commit comments