Skip to content

Commit 48374e2

Browse files
rjrjrsteve-the-edwards
authored andcommitted
Revert "Update expectRemember to provide result"
- This change forced us to provide an `expectRemember` call for every `remember` call - Under `STABLE_EVENT_HANDLERS` that means every `eventHandler` call, clearly impractical - So we could change it to allow providing an option of returning alternative value from the remember call, but default to run the real calculation; but we have found no use cases for that - So were just going back to the original implementation This reverts commit fa75ef8.
1 parent 1a40760 commit 48374e2

File tree

4 files changed

+52
-121
lines changed

4 files changed

+52
-121
lines changed

workflow-testing/api/workflow-testing.api

Lines changed: 3 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ public abstract class com/squareup/workflow1/testing/RenderTester {
3434
public static synthetic fun expectSideEffect$default (Lcom/squareup/workflow1/testing/RenderTester;Ljava/lang/String;ZLkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lcom/squareup/workflow1/testing/RenderTester;
3535
public abstract fun render (Lkotlin/jvm/functions/Function1;)Lcom/squareup/workflow1/testing/RenderTestResult;
3636
public static synthetic fun render$default (Lcom/squareup/workflow1/testing/RenderTester;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lcom/squareup/workflow1/testing/RenderTestResult;
37+
public abstract fun requireExplicitRememberExpectations ()Lcom/squareup/workflow1/testing/RenderTester;
3738
public abstract fun requireExplicitSideEffectExpectations ()Lcom/squareup/workflow1/testing/RenderTester;
3839
public abstract fun requireExplicitWorkerExpectations ()Lcom/squareup/workflow1/testing/RenderTester;
3940
}
@@ -62,18 +63,6 @@ public final class com/squareup/workflow1/testing/RenderTester$RememberInvocatio
6263
public final fun getResultType ()Lkotlin/reflect/KType;
6364
}
6465

65-
public abstract class com/squareup/workflow1/testing/RenderTester$RememberMatch {
66-
}
67-
68-
public final class com/squareup/workflow1/testing/RenderTester$RememberMatch$Matched : com/squareup/workflow1/testing/RenderTester$RememberMatch {
69-
public fun <init> (Ljava/lang/Object;)V
70-
public final fun getResult ()Ljava/lang/Object;
71-
}
72-
73-
public final class com/squareup/workflow1/testing/RenderTester$RememberMatch$NotMatched : com/squareup/workflow1/testing/RenderTester$RememberMatch {
74-
public static final field INSTANCE Lcom/squareup/workflow1/testing/RenderTester$RememberMatch$NotMatched;
75-
}
76-
7766
public final class com/squareup/workflow1/testing/RenderTester$RenderChildInvocation {
7867
public fun <init> (Lcom/squareup/workflow1/Workflow;Ljava/lang/Object;Lkotlin/reflect/KTypeProjection;Lkotlin/reflect/KTypeProjection;Ljava/lang/String;)V
7968
public final fun getOutputType ()Lkotlin/reflect/KTypeProjection;
@@ -86,8 +75,8 @@ public final class com/squareup/workflow1/testing/RenderTester$RenderChildInvoca
8675
public final class com/squareup/workflow1/testing/RenderTesterKt {
8776
public static final fun expectCovariantWorkflow (Lcom/squareup/workflow1/testing/RenderTester;Lkotlin/reflect/KClass;Lkotlin/reflect/KType;ILkotlin/reflect/KType;ILjava/lang/Object;Lcom/squareup/workflow1/WorkflowOutput;Ljava/lang/String;Ljava/lang/String;Lkotlin/jvm/functions/Function1;)Lcom/squareup/workflow1/testing/RenderTester;
8877
public static synthetic fun expectCovariantWorkflow$default (Lcom/squareup/workflow1/testing/RenderTester;Lkotlin/reflect/KClass;Lkotlin/reflect/KType;ILkotlin/reflect/KType;ILjava/lang/Object;Lcom/squareup/workflow1/WorkflowOutput;Ljava/lang/String;Ljava/lang/String;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lcom/squareup/workflow1/testing/RenderTester;
89-
public static final fun expectRemember (Lcom/squareup/workflow1/testing/RenderTester;Ljava/lang/String;Lkotlin/reflect/KType;Ljava/lang/Object;[Ljava/lang/Object;Ljava/lang/String;Lkotlin/jvm/functions/Function1;)Lcom/squareup/workflow1/testing/RenderTester;
90-
public static synthetic fun expectRemember$default (Lcom/squareup/workflow1/testing/RenderTester;Ljava/lang/String;Lkotlin/reflect/KType;Ljava/lang/Object;[Ljava/lang/Object;Ljava/lang/String;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lcom/squareup/workflow1/testing/RenderTester;
78+
public static final fun expectRemember (Lcom/squareup/workflow1/testing/RenderTester;Ljava/lang/String;Lkotlin/reflect/KType;[Ljava/lang/Object;Ljava/lang/String;Lkotlin/jvm/functions/Function1;)Lcom/squareup/workflow1/testing/RenderTester;
79+
public static synthetic fun expectRemember$default (Lcom/squareup/workflow1/testing/RenderTester;Ljava/lang/String;Lkotlin/reflect/KType;[Ljava/lang/Object;Ljava/lang/String;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lcom/squareup/workflow1/testing/RenderTester;
9180
public static final fun expectSideEffect (Lcom/squareup/workflow1/testing/RenderTester;Ljava/lang/String;)Lcom/squareup/workflow1/testing/RenderTester;
9281
public static final fun expectWorkflow (Lcom/squareup/workflow1/testing/RenderTester;Lcom/squareup/workflow1/WorkflowIdentifier;Ljava/lang/Object;Lcom/squareup/workflow1/WorkflowOutput;Ljava/lang/String;Ljava/lang/String;Lkotlin/jvm/functions/Function1;)Lcom/squareup/workflow1/testing/RenderTester;
9382
public static final fun expectWorkflow (Lcom/squareup/workflow1/testing/RenderTester;Lcom/squareup/workflow1/WorkflowIdentifier;Ljava/lang/Object;Ljava/lang/String;Ljava/lang/String;Lkotlin/jvm/functions/Function1;)Lcom/squareup/workflow1/testing/RenderTester;

workflow-testing/src/main/java/com/squareup/workflow1/testing/RealRenderTester.kt

Lines changed: 27 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ internal class RealRenderTester<PropsT, StateT, OutputT, RenderingT>(
9494
}
9595

9696
data class ExpectedRemember(
97-
val matcher: (RememberInvocation) -> RememberMatch,
97+
val matcher: (RememberInvocation) -> Boolean,
9898
val exactMatch: Boolean,
9999
val description: String,
100100
) : Expectation<Nothing>() {
@@ -106,6 +106,7 @@ internal class RealRenderTester<PropsT, StateT, OutputT, RenderingT>(
106106

107107
private var explicitWorkerExpectationsRequired: Boolean = false
108108
private var explicitSideEffectExpectationsRequired: Boolean = false
109+
private var explicitRememberExpectationsRequired: Boolean = false
109110
private val stateAndOutput: Pair<StateT, WorkflowOutput<OutputT>?> by lazy {
110111
val action = processedAction ?: noAction()
111112
val (state, actionApplied) = action.applyTo(props, state)
@@ -152,7 +153,7 @@ internal class RealRenderTester<PropsT, StateT, OutputT, RenderingT>(
152153
override fun expectRemember(
153154
description: String,
154155
exactMatch: Boolean,
155-
matcher: (RememberInvocation) -> RememberMatch
156+
matcher: (RememberInvocation) -> Boolean
156157
): RenderTester<PropsT, StateT, OutputT, RenderingT> = apply {
157158
expectations += ExpectedRemember(matcher, exactMatch, description)
158159
}
@@ -170,6 +171,11 @@ internal class RealRenderTester<PropsT, StateT, OutputT, RenderingT>(
170171
expectSideEffect(description = "unexpected side effect", exactMatch = false) { true }
171172
}
172173

174+
if (!explicitRememberExpectationsRequired) {
175+
// Allow unexpected remember calls.
176+
expectRemember(description = "unexpected remembered value", exactMatch = false) { true }
177+
}
178+
173179
frozen = false
174180
// Clone the expectations to run a "dry" render pass.
175181
val noopContext = deepCloneForRender()
@@ -311,36 +317,27 @@ internal class RealRenderTester<PropsT, StateT, OutputT, RenderingT>(
311317
val description = "remember with key \"$key\""
312318

313319
val matches = expectations.filterIsInstance<ExpectedRemember>()
314-
.mapNotNull {
315-
val matchResult = it.matcher(invocation)
316-
if (matchResult is RememberMatch.Matched) Pair(it, matchResult) else null
317-
}
320+
.mapNotNull { if (it.matcher(invocation)) it else null }
318321
if (matches.isEmpty()) {
319322
throw AssertionError("Unexpected $description")
320323
}
321324

322-
val exactMatches = matches.filter { it.first.exactMatch }
323-
val (_, match) = when {
324-
exactMatches.size == 1 -> {
325-
exactMatches.single()
326-
.also { (expected, _) ->
327-
expectations -= expected
328-
consumedExpectations += expected
329-
}
330-
}
325+
val exactMatches = matches.filter { it.exactMatch }
326+
if (exactMatches.size > 1) {
327+
throw AssertionError(
328+
"Multiple expectations matched $description: \n" +
329+
exactMatches.joinToString(separator = "\n") { " ${it.describe()}" }
330+
)
331+
}
331332

332-
exactMatches.size > 1 -> {
333-
throw AssertionError(
334-
"Multiple expectations matched $description:\n" +
335-
exactMatches.joinToString(separator = "\n") { " ${it.first.describe()}" }
336-
)
333+
// Inexact matches are not consumable.
334+
exactMatches.singleOrNull()
335+
?.let { expected ->
336+
expectations -= expected
337+
consumedExpectations += expected
337338
}
338-
// Inexact matches are not consumable.
339-
else -> matches.first()
340-
}
341339

342-
@Suppress("UNCHECKED_CAST")
343-
return match.result as ResultT
340+
return calculation()
344341
}
345342

346343
override fun requireExplicitWorkerExpectations():
@@ -353,6 +350,11 @@ internal class RealRenderTester<PropsT, StateT, OutputT, RenderingT>(
353350
explicitSideEffectExpectationsRequired = true
354351
}
355352

353+
override fun requireExplicitRememberExpectations():
354+
RenderTester<PropsT, StateT, OutputT, RenderingT> = this.apply {
355+
explicitRememberExpectationsRequired = true
356+
}
357+
356358
override fun send(value: WorkflowAction<PropsT, StateT, OutputT>) {
357359
if (!frozen) {
358360
throw UnsupportedOperationException(

workflow-testing/src/main/java/com/squareup/workflow1/testing/RenderTester.kt

Lines changed: 8 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ import com.squareup.workflow1.config.JvmTestRuntimeConfigTools
1515
import com.squareup.workflow1.identifier
1616
import com.squareup.workflow1.testing.RenderTester.ChildWorkflowMatch
1717
import com.squareup.workflow1.testing.RenderTester.Companion
18-
import com.squareup.workflow1.testing.RenderTester.RememberMatch
1918
import com.squareup.workflow1.workflowIdentifier
2019
import kotlinx.coroutines.CoroutineScope
2120
import kotlin.reflect.KClass
@@ -285,14 +284,13 @@ public abstract class RenderTester<PropsT, StateT, OutputT, RenderingT> {
285284
* which case the first match will be used), and the expectation may match multiple side effects.
286285
*
287286
* @param matcher A function that is passed the parameters from
288-
* [RenderContext.remember][com.squareup.workflow1.BaseRenderContext.remember] and determines if
289-
* they match what the workflow specified. If they do match, this includes the result that should
290-
* be provided to the workflow.
287+
* [RenderContext.remember][com.squareup.workflow1.BaseRenderContext.remember] and return
288+
* true if such a call expected.
291289
*/
292290
public abstract fun expectRemember(
293291
description: String,
294292
exactMatch: Boolean = true,
295-
matcher: (RememberInvocation) -> RememberMatch
293+
matcher: (RememberInvocation) -> Boolean
296294
): RenderTester<PropsT, StateT, OutputT, RenderingT>
297295

298296
/**
@@ -320,6 +318,9 @@ public abstract class RenderTester<PropsT, StateT, OutputT, RenderingT> {
320318
public abstract fun requireExplicitSideEffectExpectations():
321319
RenderTester<PropsT, StateT, OutputT, RenderingT>
322320

321+
public abstract fun requireExplicitRememberExpectations():
322+
RenderTester<PropsT, StateT, OutputT, RenderingT>
323+
323324
/**
324325
* Describes a call to
325326
* [RenderContext.renderChild][com.squareup.workflow1.BaseRenderContext.renderChild].
@@ -357,22 +358,6 @@ public abstract class RenderTester<PropsT, StateT, OutputT, RenderingT> {
357358
public val inputs: List<Any?>,
358359
)
359360

360-
public sealed class RememberMatch {
361-
/**
362-
* Indicates that the remember specifications did not match what was used by the Workflow.
363-
*/
364-
public object NotMatched : RememberMatch()
365-
366-
/**
367-
* Indicates that the remember specifications were matched.
368-
*
369-
* @param result the result to return from the remember call.
370-
*/
371-
public class Matched(
372-
public val result: Any?,
373-
) : RememberMatch()
374-
}
375-
376361
public sealed class ChildWorkflowMatch {
377362
/**
378363
* Indicates that the child workflow did not match the predicate and must match a different
@@ -789,9 +774,6 @@ public fun <PropsT, StateT, OutputT, RenderingT>
789774
* @param resultType The type of the value returned by the `calculation` function passed
790775
* to [remember][com.squareup.workflow1.BaseRenderContext.remember].
791776
*
792-
* @param result The result to be provided from
793-
* [remember][com.squareup.workflow1.BaseRenderContext.remember] if the invocation is matched.
794-
*
795777
* @param inputs The `inputs` values passed to
796778
* [remember][com.squareup.workflow1.BaseRenderContext.remember], if any
797779
*
@@ -805,7 +787,6 @@ public fun <PropsT, StateT, OutputT, RenderingT>
805787
RenderTester<PropsT, StateT, OutputT, RenderingT>.expectRemember(
806788
key: String,
807789
resultType: KType,
808-
result: Any?,
809790
vararg inputs: Any?,
810791
description: String = "",
811792
assertInputs: (inputs: List<Any?>) -> Unit = {},
@@ -826,9 +807,9 @@ public fun <PropsT, StateT, OutputT, RenderingT>
826807
key == invocation.key
827808
) {
828809
assertInputs(invocation.inputs)
829-
RememberMatch.Matched(result)
810+
true
830811
} else {
831-
RememberMatch.NotMatched
812+
false
832813
}
833814
}
834815
}

workflow-testing/src/test/java/com/squareup/workflow1/testing/RealRenderTesterTest.kt

Lines changed: 14 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -157,40 +157,31 @@ internal class RealRenderTesterTest {
157157
)
158158
}
159159

160-
@Test fun `remember throws when not expected`() {
160+
@Test fun `remember runs and returns calculations`() {
161161
val workflow = Workflow.stateless<Unit, Nothing, String> {
162162
val numOutput = remember("the key") { 36 }
163-
"$numOutput"
163+
val stringInputs = remember("the key", "the", "inputs") { "string with string inputs" }
164+
val noInputs = remember("the key", 1, 2, 3) { "string with number inputs" }
165+
"$numOutput-$stringInputs-$noInputs"
164166
}
165-
val failure = assertFailsWith<AssertionError> {
166-
workflow.testRender(Unit).render()
167+
workflow.testRender(Unit).render {
168+
assertEquals("36-string with string inputs-string with number inputs", it)
167169
}
168-
assertEquals(
169-
"Unexpected remember with key \"the key\"",
170-
failure.message
171-
)
172170
}
173171

174172
@Test fun `expectRemember throws when already expecting remember with same key`() {
175173
val workflow = Workflow.stateless<Unit, Nothing, String> {
176174
remember("the key", "the", "inputs") { "theOutput" }
177175
}
178176
val tester = workflow.testRender(Unit)
179-
.expectRemember("the key", typeOf<String>(), result = "theOutput", "the", "inputs")
180-
.expectRemember(
181-
"the key",
182-
typeOf<String>(),
183-
result = "theOutput",
184-
"the",
185-
"inputs",
186-
description = "duplicate match"
187-
)
177+
.expectRemember("the key", typeOf<String>(), "the", "inputs")
178+
.expectRemember("the key", typeOf<String>(), "the", "inputs", description = "duplicate match")
188179

189180
val error = assertFailsWith<AssertionError> {
190181
tester.render()
191182
}
192183
assertEquals(
193-
"Multiple expectations matched remember with key \"the key\":\n" +
184+
"Multiple expectations matched remember with key \"the key\": \n" +
194185
" remember key=the key, inputs=[the, inputs], resultType=kotlin.String\n" +
195186
" duplicate match",
196187
error.message
@@ -206,48 +197,16 @@ internal class RealRenderTesterTest {
206197
}
207198

208199
workflow.testRender(Unit)
209-
.expectRemember("the key", typeOf<Int>(), result = 36)
210-
.expectRemember(
211-
"the key",
212-
typeOf<String>(),
213-
result = "string with string inputs",
214-
"the",
215-
"inputs"
216-
)
217-
.expectRemember("the key", typeOf<String>(), result = "string with number inputs", 1, 2, 3)
200+
.expectRemember("the key", typeOf<Int>())
201+
.expectRemember("the key", typeOf<String>(), "the", "inputs")
202+
.expectRemember("the key", typeOf<String>(), 1, 2, 3)
218203
.render()
219204
}
220205

221-
@Test fun `expectRemember uses the result provided`() {
222-
val workflow = Workflow.stateless<Unit, Nothing, String> {
223-
val numOutput = remember("the key") { 42 }
224-
val stringInputs = remember("the key", "the", "inputs") { "a different string" }
225-
val noInputs = remember("the key", 1, 2, 3) { "yet another string not used." }
226-
"$numOutput-$stringInputs-$noInputs"
227-
}
228-
229-
workflow.testRender(Unit)
230-
.expectRemember("the key", typeOf<Int>(), result = 36)
231-
.expectRemember(
232-
"the key",
233-
typeOf<String>(),
234-
result = "string with string inputs",
235-
"the",
236-
"inputs"
237-
)
238-
.expectRemember("the key", typeOf<String>(), result = "string with number inputs", 1, 2, 3)
239-
.render {
240-
assertEquals(
241-
"36-string with string inputs-string with number inputs",
242-
it
243-
)
244-
}
245-
}
246-
247206
@Test fun `expectRemember doesn't match key`() {
248207
val workflow = Workflow.stateless<Unit, Nothing, Unit> {}
249208
val tester = workflow.testRender(Unit)
250-
.expectRemember("the key", typeOf<String>(), result = "test", "the", "inputs")
209+
.expectRemember("the key", typeOf<String>(), "the", "inputs")
251210

252211
val error = assertFailsWith<AssertionError> {
253212
tester.render {}
@@ -266,6 +225,7 @@ internal class RealRenderTesterTest {
266225
remember("the key", "the", "inputs") { "theOutput" }
267226
}
268227
val tester = workflow.testRender(Unit)
228+
.requireExplicitRememberExpectations()
269229

270230
val error = assertFailsWith<AssertionError> {
271231
tester.render {}
@@ -281,7 +241,6 @@ internal class RealRenderTesterTest {
281241
.expectRemember(
282242
key = "the key",
283243
resultType = typeOf<String>(),
284-
result = "theOutput",
285244
"the",
286245
"inputs",
287246
assertInputs = { inputs ->

0 commit comments

Comments
 (0)