Skip to content

Commit 361d409

Browse files
fix(android-tests): fix ProgressReporterTest race condition and ignore stale plugin test
- ProgressReporterTest: add yield() after launch{} so collector subscribes before emission on SharedFlow(replay=0); use unique taskIds to avoid 1%-change de-bounce filter blocking repeated emissions - NativeWorkmanagerPluginTest: @ignore getPlatformVersion test (method removed in v1.1.0 plugin refactor)
1 parent de2c9cc commit 361d409

2 files changed

Lines changed: 48 additions & 67 deletions

File tree

‎android/src/test/kotlin/dev/brewkits/native_workmanager/NativeWorkmanagerPluginTest.kt‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package dev.brewkits.native_workmanager
22

33
import io.flutter.plugin.common.MethodCall
44
import io.flutter.plugin.common.MethodChannel
5+
import org.junit.Ignore
56
import org.mockito.Mockito
67
import kotlin.test.Test
78

@@ -14,6 +15,7 @@ import kotlin.test.Test
1415
*/
1516

1617
internal class NativeWorkmanagerPluginTest {
18+
@Ignore("getPlatformVersion was removed in the v1.1.0 plugin refactor")
1719
@Test
1820
fun onMethodCall_getPlatformVersion_returnsExpectedValue() {
1921
val plugin = NativeWorkmanagerPlugin()

‎android/src/test/kotlin/dev/brewkits/native_workmanager/ProgressReporterTest.kt‎

Lines changed: 46 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -7,80 +7,66 @@ import kotlinx.coroutines.flow.toList
77
import kotlinx.coroutines.launch
88
import kotlinx.coroutines.runBlocking
99
import kotlinx.coroutines.test.runTest
10+
import kotlinx.coroutines.yield
1011
import org.junit.Assert.*
1112
import org.junit.Test
1213

1314
/**
1415
* Unit tests for ProgressReporter.
1516
*
16-
* Tests:
17-
* - Progress reporting with valid values
18-
* - Progress clamping (0-100)
19-
* - Message formatting
20-
* - Step-based progress calculation
21-
* - Flow emission and collection
22-
* - Thread safety
17+
* NOTE: ProgressReporter uses SharedFlow(replay=0). Tests must yield() after
18+
* launching a collector to ensure subscription is active before emitting.
2319
*/
2420
class ProgressReporterTest {
2521

2622
@Test
2723
fun `reportProgress emits valid progress update`() = runTest {
28-
val taskId = "test-task-1"
24+
val taskId = "test-task-progress-1"
2925
val progress = 50
3026
val message = "Processing..."
3127

32-
// Collect first emission
3328
val job = launch {
3429
val update = ProgressReporter.progressFlow.first()
35-
3630
assertEquals(taskId, update.taskId)
3731
assertEquals(progress, update.progress)
3832
assertEquals(message, update.message)
3933
}
4034

41-
// Emit progress
42-
ProgressReporter.reportProgress(
43-
taskId = taskId,
44-
progress = progress,
45-
message = message
46-
)
35+
yield() // Let the collector subscribe before emitting
4736

37+
ProgressReporter.reportProgress(taskId = taskId, progress = progress, message = message)
4838
job.join()
4939
}
5040

5141
@Test
5242
fun `reportProgress clamps progress to 0-100 range`() = runTest {
53-
val taskId = "test-task-2"
43+
val taskId = "test-task-clamp-1"
5444

55-
// Test over 100
5645
val job1 = launch {
5746
val update = ProgressReporter.progressFlow.first()
5847
assertEquals(100, update.progress)
5948
}
49+
yield()
6050
ProgressReporter.reportProgress(taskId, progress = 150)
6151
job1.join()
6252

63-
// Test under 0
53+
val taskId2 = "test-task-clamp-2"
6454
val job2 = launch {
6555
val update = ProgressReporter.progressFlow.first()
6656
assertEquals(0, update.progress)
6757
}
68-
ProgressReporter.reportProgress(taskId, progress = -50)
58+
yield()
59+
ProgressReporter.reportProgress(taskId2, progress = -50)
6960
job2.join()
7061
}
7162

7263
@Test
7364
fun `reportProgress validates progress range`() = runTest {
7465
try {
75-
// This should work (boundary)
76-
ProgressReporter.reportProgress("task", progress = 0)
77-
ProgressReporter.reportProgress("task", progress = 100)
78-
79-
// This should clamp but not throw
80-
ProgressReporter.reportProgress("task", progress = 101)
81-
ProgressReporter.reportProgress("task", progress = -1)
82-
83-
// If we get here, clamping worked
66+
ProgressReporter.reportProgress("task-validate", progress = 0)
67+
ProgressReporter.reportProgress("task-validate-b", progress = 100)
68+
ProgressReporter.reportProgress("task-validate-c", progress = 101)
69+
ProgressReporter.reportProgress("task-validate-d", progress = -1)
8470
assertTrue(true)
8571
} catch (e: Exception) {
8672
fail("Progress should be clamped, not throw: ${e.message}")
@@ -89,76 +75,73 @@ class ProgressReporterTest {
8975

9076
@Test
9177
fun `reportStep calculates progress correctly`() = runTest {
92-
val taskId = "test-task-3"
78+
val taskId = "test-task-step-1"
9379
val totalSteps = 10
9480

95-
// Test 0%
9681
val job1 = launch {
9782
val update = ProgressReporter.progressFlow.first()
9883
assertEquals(0, update.progress)
9984
assertEquals(0, update.currentStep)
10085
assertEquals(totalSteps, update.totalSteps)
10186
}
87+
yield()
10288
ProgressReporter.reportStep(taskId, currentStep = 0, totalSteps = totalSteps)
10389
job1.join()
10490

105-
// Test 50%
91+
val taskId2 = "test-task-step-2"
10692
val job2 = launch {
10793
val update = ProgressReporter.progressFlow.first()
10894
assertEquals(50, update.progress)
10995
assertEquals(5, update.currentStep)
11096
}
111-
ProgressReporter.reportStep(taskId, currentStep = 5, totalSteps = totalSteps)
97+
yield()
98+
ProgressReporter.reportStep(taskId2, currentStep = 5, totalSteps = totalSteps)
11299
job2.join()
113100

114-
// Test 100%
101+
val taskId3 = "test-task-step-3"
115102
val job3 = launch {
116103
val update = ProgressReporter.progressFlow.first()
117104
assertEquals(100, update.progress)
118105
assertEquals(10, update.currentStep)
119106
}
120-
ProgressReporter.reportStep(taskId, currentStep = 10, totalSteps = totalSteps)
107+
yield()
108+
ProgressReporter.reportStep(taskId3, currentStep = 10, totalSteps = totalSteps)
121109
job3.join()
122110
}
123111

124112
@Test
125113
fun `reportStep handles zero totalSteps gracefully`() = runTest {
126-
val taskId = "test-task-4"
114+
val taskId = "test-task-zero-steps"
127115

128116
val job = launch {
129117
val update = ProgressReporter.progressFlow.first()
130-
assertEquals(0, update.progress) // Should default to 0
118+
assertEquals(0, update.progress)
131119
assertEquals(5, update.currentStep)
132120
assertEquals(0, update.totalSteps)
133121
}
122+
yield()
134123

135-
ProgressReporter.reportStep(
136-
taskId = taskId,
137-
currentStep = 5,
138-
totalSteps = 0 // Invalid but should handle gracefully
139-
)
140-
124+
ProgressReporter.reportStep(taskId = taskId, currentStep = 5, totalSteps = 0)
141125
job.join()
142126
}
143127

144128
@Test
145129
fun `multiple progress updates are emitted in order`() = runTest {
146-
val taskId = "test-task-5"
130+
val taskId = "test-task-order"
147131
val progressValues = listOf(0, 25, 50, 75, 100)
148132

149133
val job = launch {
150134
val updates = ProgressReporter.progressFlow.take(5).toList()
151-
152135
assertEquals(5, updates.size)
153136
updates.forEachIndexed { index, update ->
154137
assertEquals(taskId, update.taskId)
155138
assertEquals(progressValues[index], update.progress)
156139
}
157140
}
141+
yield()
158142

159-
// Emit multiple progress updates
160-
progressValues.forEach { progress ->
161-
ProgressReporter.reportProgress(taskId, progress)
143+
progressValues.forEach { p ->
144+
ProgressReporter.reportProgress(taskId, p)
162145
}
163146

164147
job.join()
@@ -167,7 +150,7 @@ class ProgressReporterTest {
167150
@Test
168151
fun `toMap converts ProgressUpdate correctly`() = runBlocking {
169152
val update = ProgressReporter.ProgressUpdate(
170-
taskId = "test-task-6",
153+
taskId = "test-task-tomap",
171154
progress = 75,
172155
message = "Processing file",
173156
currentStep = 3,
@@ -176,7 +159,7 @@ class ProgressReporterTest {
176159

177160
val map = update.toMap()
178161

179-
assertEquals("test-task-6", map["taskId"])
162+
assertEquals("test-task-tomap", map["taskId"])
180163
assertEquals(75, map["progress"])
181164
assertEquals("Processing file", map["message"])
182165
assertEquals(3, map["currentStep"])
@@ -186,7 +169,7 @@ class ProgressReporterTest {
186169
@Test
187170
fun `toMap handles null optional fields`() = runBlocking {
188171
val update = ProgressReporter.ProgressUpdate(
189-
taskId = "test-task-7",
172+
taskId = "test-task-nullmap",
190173
progress = 50,
191174
message = null,
192175
currentStep = null,
@@ -195,7 +178,7 @@ class ProgressReporterTest {
195178

196179
val map = update.toMap()
197180

198-
assertEquals("test-task-7", map["taskId"])
181+
assertEquals("test-task-nullmap", map["taskId"])
199182
assertEquals(50, map["progress"])
200183
assertFalse(map.containsKey("message"))
201184
assertFalse(map.containsKey("currentStep"))
@@ -204,31 +187,26 @@ class ProgressReporterTest {
204187

205188
@Test
206189
fun `concurrent progress updates are handled safely`() = runTest {
207-
val taskIds = (1..100).map { "task-$it" }
208-
val expectedUpdates = 100
190+
val count = 100
191+
val taskIds = (1..count).map { "concurrent-task-$it" }
209192

210193
val job = launch {
211-
val updates = ProgressReporter.progressFlow.take(expectedUpdates).toList()
212-
assertEquals(expectedUpdates, updates.size)
213-
214-
// All task IDs should be present
194+
val updates = ProgressReporter.progressFlow.take(count).toList()
195+
assertEquals(count, updates.size)
215196
val receivedIds = updates.map { it.taskId }.toSet()
216-
assertEquals(expectedUpdates, receivedIds.size)
197+
assertEquals(count, receivedIds.size)
217198
}
199+
yield()
218200

219-
// Emit from multiple "concurrent" coroutines
220201
taskIds.forEach { taskId ->
221-
launch {
222-
ProgressReporter.reportProgress(taskId, progress = 50)
223-
}
202+
launch { ProgressReporter.reportProgress(taskId, progress = 50) }
224203
}
225204

226205
job.join()
227206
}
228207

229208
@Test
230209
fun `progress message formatting`() = runTest {
231-
val taskId = "test-task-8"
232210
val messages = listOf(
233211
"Starting...",
234212
"Processing file 1 of 10",
@@ -238,14 +216,15 @@ class ProgressReporterTest {
238216

239217
val job = launch {
240218
val updates = ProgressReporter.progressFlow.take(messages.size).toList()
241-
242219
updates.forEachIndexed { index, update ->
243220
assertEquals(messages[index], update.message)
244221
}
245222
}
223+
yield()
246224

247-
messages.forEach { message ->
248-
ProgressReporter.reportProgress(taskId, progress = 25, message = message)
225+
// Use unique taskId per message to bypass the 1%-change de-bounce filter
226+
messages.forEachIndexed { index, message ->
227+
ProgressReporter.reportProgress("msg-task-$index", progress = 25, message = message)
249228
}
250229

251230
job.join()

0 commit comments

Comments
 (0)