chore: 代码清理(debug日志+孤立文件+未用字段+测试修复)
1. 去掉 fetchStatistics/renderDots 中的 debug Timber.d 2. 删除孤立文件: bg_new_task_hint.xml, bg_btn_primary.xml, bg_btn_secondary.xml 3. 删除未用字段: onPendingCountChanged 4. 单元测试修复: - 添加 Dispatchers.setMain/resetMain (JVM无Main线程) - 新增: 数字id解析、acknowledgeCard减pendingCount、ack清除、preNotificationStats - 总计 22 条测试 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -71,9 +71,6 @@ class NotificationManager @Inject constructor(
|
|||||||
/** 协程作用域 */
|
/** 协程作用域 */
|
||||||
private val scope = CoroutineScope(Dispatchers.Main + SupervisorJob())
|
private val scope = CoroutineScope(Dispatchers.Main + SupervisorJob())
|
||||||
|
|
||||||
/** 去抖合并后的回调(通知 UI 更新横幅数字) */
|
|
||||||
var onPendingCountChanged: ((Int) -> Unit)? = null
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 处理 MQTT type=1 新任务消息
|
* 处理 MQTT type=1 新任务消息
|
||||||
* 去抖策略:1s 窗口内的消息暂存,窗口结束后合并处理(不丢弃)
|
* 去抖策略:1s 窗口内的消息暂存,窗口结束后合并处理(不丢弃)
|
||||||
|
|||||||
@@ -366,14 +366,11 @@ class HomeFragment : BaseFragment<FragmentHomeBinding>() {
|
|||||||
|
|
||||||
if (checkDots && notificationManager.pendingCount > 0) {
|
if (checkDots && notificationManager.pendingCount > 0) {
|
||||||
val baseline = notificationManager.preNotificationStats
|
val baseline = notificationManager.preNotificationStats
|
||||||
Timber.d("首页: checkDots baseline=$baseline, newData=$data, pendingCount=${notificationManager.pendingCount}")
|
|
||||||
if (baseline != null) {
|
if (baseline != null) {
|
||||||
val changed = notificationManager.diffStats(baseline, data)
|
val changed = notificationManager.diffStats(baseline, data)
|
||||||
val ack = notificationManager.acknowledgedCards
|
val ack = notificationManager.acknowledgedCards
|
||||||
Timber.d("首页: diffStats changed=$changed, ack=$ack, activeDots=$activeDotCards")
|
|
||||||
for (status in changed) {
|
for (status in changed) {
|
||||||
if (status !in ack) activeDotCards.add(status)
|
if (status !in ack) activeDotCards.add(status)
|
||||||
// 记录每个分类的增量(供 acknowledgeCard 扣减 pendingCount 用)
|
|
||||||
val increment = when (status) {
|
val increment = when (status) {
|
||||||
2 -> data.waitForTask - baseline.waitForTask
|
2 -> data.waitForTask - baseline.waitForTask
|
||||||
3 -> data.treatTask - baseline.treatTask
|
3 -> data.treatTask - baseline.treatTask
|
||||||
@@ -383,17 +380,15 @@ class HomeFragment : BaseFragment<FragmentHomeBinding>() {
|
|||||||
notificationManager.recordCardIncrement(status, increment)
|
notificationManager.recordCardIncrement(status, increment)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Timber.d("首页: baseline为null,兜底显示所有有值的红点")
|
// 无快照(极端情况)→ 所有有值的加红点
|
||||||
val ack = notificationManager.acknowledgedCards
|
val ack = notificationManager.acknowledgedCards
|
||||||
if (data.waitForTask > 0 && 2 !in ack) activeDotCards.add(2)
|
if (data.waitForTask > 0 && 2 !in ack) activeDotCards.add(2)
|
||||||
if (data.treatTask > 0 && 3 !in ack) activeDotCards.add(3)
|
if (data.treatTask > 0 && 3 !in ack) activeDotCards.add(3)
|
||||||
if (data.incompleteTask > 0 && 4 !in ack) activeDotCards.add(4)
|
if (data.incompleteTask > 0 && 4 !in ack) activeDotCards.add(4)
|
||||||
}
|
}
|
||||||
Timber.d("首页: renderDots activeDotCards=$activeDotCards")
|
|
||||||
renderDots()
|
renderDots()
|
||||||
} else {
|
} else {
|
||||||
notificationManager.lastStats = data
|
notificationManager.lastStats = data
|
||||||
Timber.d("首页: lastStats 更新为 $data (无通知刷新)")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 更新数字
|
// 更新数字
|
||||||
@@ -582,7 +577,6 @@ class HomeFragment : BaseFragment<FragmentHomeBinding>() {
|
|||||||
dotPool.visibility = if (2 in activeDotCards) View.VISIBLE else View.GONE
|
dotPool.visibility = if (2 in activeDotCards) View.VISIBLE else View.GONE
|
||||||
dotPunch.visibility = if (3 in activeDotCards) View.VISIBLE else View.GONE
|
dotPunch.visibility = if (3 in activeDotCards) View.VISIBLE else View.GONE
|
||||||
dotComplete.visibility = if (4 in activeDotCards) View.VISIBLE else View.GONE
|
dotComplete.visibility = if (4 in activeDotCards) View.VISIBLE else View.GONE
|
||||||
Timber.d("首页: renderDots 完成 pool=${dotPool.visibility==View.VISIBLE} punch=${dotPunch.visibility==View.VISIBLE} complete=${dotComplete.visibility==View.VISIBLE}")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 标记某个分类已查看:从 activeDotCards 移除 + 通知管理器记录 */
|
/** 标记某个分类已查看:从 activeDotCards 移除 + 通知管理器记录 */
|
||||||
|
|||||||
@@ -1,16 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<!-- 主按钮背景(深蓝色圆角) -->
|
|
||||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
|
||||||
<item android:state_pressed="true">
|
|
||||||
<shape android:shape="rectangle">
|
|
||||||
<solid android:color="#FF1565C0" />
|
|
||||||
<corners android:radius="12dp" />
|
|
||||||
</shape>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<shape android:shape="rectangle">
|
|
||||||
<solid android:color="#FF1E88E5" />
|
|
||||||
<corners android:radius="12dp" />
|
|
||||||
</shape>
|
|
||||||
</item>
|
|
||||||
</selector>
|
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<!-- 次按钮背景(深灰色圆角) -->
|
|
||||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
|
||||||
<item android:state_pressed="true">
|
|
||||||
<shape android:shape="rectangle">
|
|
||||||
<solid android:color="#FF424242" />
|
|
||||||
<corners android:radius="12dp" />
|
|
||||||
</shape>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<shape android:shape="rectangle">
|
|
||||||
<solid android:color="#FF333333" />
|
|
||||||
<corners android:radius="12dp" />
|
|
||||||
</shape>
|
|
||||||
</item>
|
|
||||||
</selector>
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<!-- 新任务提示条背景(蓝色半透明圆角) -->
|
|
||||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:shape="rectangle">
|
|
||||||
<solid android:color="#1A3B9EFF" />
|
|
||||||
<corners android:radius="12dp" />
|
|
||||||
</shape>
|
|
||||||
@@ -5,50 +5,59 @@ import com.xiaoqu.watch.device.screen.ScreenController
|
|||||||
import com.xiaoqu.watch.device.sensor.VibrationController
|
import com.xiaoqu.watch.device.sensor.VibrationController
|
||||||
import com.xiaoqu.watch.event.EventBus
|
import com.xiaoqu.watch.event.EventBus
|
||||||
import io.mockk.*
|
import io.mockk.*
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||||
|
import kotlinx.coroutines.test.StandardTestDispatcher
|
||||||
|
import kotlinx.coroutines.test.setMain
|
||||||
|
import kotlinx.coroutines.test.resetMain
|
||||||
|
import org.junit.After
|
||||||
import org.junit.Assert.*
|
import org.junit.Assert.*
|
||||||
import org.junit.Before
|
import org.junit.Before
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* NotificationManager 单元测试
|
* NotificationManager 单元测试
|
||||||
* 测试:去抖逻辑、任务 ID 解析、消息消费、红点对比
|
* 测试:去抖、任务 ID 解析、消息消费、红点对比、ack 清除
|
||||||
*/
|
*/
|
||||||
|
@OptIn(ExperimentalCoroutinesApi::class)
|
||||||
class NotificationManagerTest {
|
class NotificationManagerTest {
|
||||||
|
|
||||||
private lateinit var manager: NotificationManager
|
private lateinit var manager: NotificationManager
|
||||||
private val vibrationController = mockk<VibrationController>(relaxed = true)
|
private val vibrationController = mockk<VibrationController>(relaxed = true)
|
||||||
private val screenController = mockk<ScreenController>(relaxed = true)
|
private val screenController = mockk<ScreenController>(relaxed = true)
|
||||||
private val eventBus = mockk<EventBus>(relaxed = true)
|
private val eventBus = mockk<EventBus>(relaxed = true)
|
||||||
|
private val testDispatcher = StandardTestDispatcher()
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
fun setup() {
|
fun setup() {
|
||||||
|
Dispatchers.setMain(testDispatcher)
|
||||||
manager = NotificationManager(vibrationController, screenController, eventBus)
|
manager = NotificationManager(vibrationController, screenController, eventBus)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ===== 去抖逻辑 =====
|
@After
|
||||||
|
fun tearDown() {
|
||||||
|
Dispatchers.resetMain()
|
||||||
|
}
|
||||||
|
|
||||||
|
// ===== 去抖 =====
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `onNewTaskMessage - first message should be handled`() {
|
fun `first message should be handled`() {
|
||||||
val json = """{"id":"100"}"""
|
manager.onNewTaskMessage("""{"id":"100"}""")
|
||||||
manager.onNewTaskMessage(json)
|
assertEquals(1, manager.pendingTaskIds.size)
|
||||||
assertEquals(1, manager.pendingCount)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `onNewTaskMessage - duplicate within 1s should be buffered not dropped`() {
|
fun `duplicate within 1s should be buffered not dropped`() {
|
||||||
val json1 = """{"id":"100"}"""
|
manager.onNewTaskMessage("""{"id":"100"}""")
|
||||||
val json2 = """{"id":"200"}"""
|
manager.onNewTaskMessage("""{"id":"200"}""")
|
||||||
manager.onNewTaskMessage(json1)
|
// 第一条立即处理,第二条暂存
|
||||||
// 立即再发一条(间隔 <1s)→ 暂存,不丢弃
|
assertEquals(1, manager.pendingTaskIds.size)
|
||||||
manager.onNewTaskMessage(json2)
|
|
||||||
// 第一条立即处理,第二条暂存等延迟处理
|
|
||||||
assertEquals(1, manager.pendingCount) // 暂存的还没处理
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `onNewTaskMessage - should trigger vibration and screen`() {
|
fun `should trigger vibration and screen on first message`() {
|
||||||
val json = """{"id":"100"}"""
|
manager.onNewTaskMessage("""{"id":"100"}""")
|
||||||
manager.onNewTaskMessage(json)
|
|
||||||
verify { vibrationController.executePattern(any()) }
|
verify { vibrationController.executePattern(any()) }
|
||||||
verify { screenController.turnOn() }
|
verify { screenController.turnOn() }
|
||||||
}
|
}
|
||||||
@@ -56,119 +65,163 @@ class NotificationManagerTest {
|
|||||||
// ===== 任务 ID 解析 =====
|
// ===== 任务 ID 解析 =====
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `parseTaskIds - message with direct id field`() {
|
fun `parse message with direct id field`() {
|
||||||
val json = """{"messageType":1,"id":"200"}"""
|
manager.onNewTaskMessage("""{"messageType":1,"id":"200"}""")
|
||||||
manager.onNewTaskMessage(json)
|
|
||||||
assertEquals(listOf("200"), manager.pendingTaskIds)
|
assertEquals(listOf("200"), manager.pendingTaskIds)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `parseTaskIds - message with taskArr array`() {
|
fun `parse message with numeric id field`() {
|
||||||
val json = """{"messageType":1,"taskArr":[{"id":"301"},{"id":"302"}]}"""
|
// 实际 MQTT 消息 id 是数字
|
||||||
manager.onNewTaskMessage(json)
|
manager.onNewTaskMessage("""{"messageType":1,"id":6093091}""")
|
||||||
|
assertEquals(listOf("6093091"), manager.pendingTaskIds)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `parse message with taskArr array`() {
|
||||||
|
manager.onNewTaskMessage("""{"messageType":1,"taskArr":[{"id":"301"},{"id":"302"}]}""")
|
||||||
assertEquals(listOf("301", "302"), manager.pendingTaskIds)
|
assertEquals(listOf("301", "302"), manager.pendingTaskIds)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `parseTaskIds - message with data array`() {
|
fun `parse message with data array`() {
|
||||||
val json = """{"messageType":1,"data":[{"id":"401"}]}"""
|
manager.onNewTaskMessage("""{"messageType":1,"data":[{"id":"401"}]}""")
|
||||||
manager.onNewTaskMessage(json)
|
|
||||||
assertEquals(listOf("401"), manager.pendingTaskIds)
|
assertEquals(listOf("401"), manager.pendingTaskIds)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `parseTaskIds - message without id should not be handled`() {
|
fun `message without id should not add to pending`() {
|
||||||
val json = """{"messageType":1,"name":"test"}"""
|
manager.onNewTaskMessage("""{"messageType":1,"name":"test"}""")
|
||||||
val result = manager.onNewTaskMessage(json)
|
assertEquals(0, manager.pendingTaskIds.size)
|
||||||
assertFalse(result)
|
|
||||||
assertEquals(0, manager.pendingCount)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `parseTaskIds - malformed json should not crash`() {
|
fun `malformed json should not crash`() {
|
||||||
val json = "not a json"
|
manager.onNewTaskMessage("not a json")
|
||||||
val result = manager.onNewTaskMessage(json)
|
assertEquals(0, manager.pendingTaskIds.size)
|
||||||
assertFalse(result)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ===== 去重 =====
|
// ===== 去重 =====
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `onNewTaskMessage - duplicate taskId should not be added twice`() {
|
fun `same taskId should not be added twice`() {
|
||||||
// 需要间隔 >1s 绕过去抖,这里直接测内部状态
|
manager.onNewTaskMessage("""{"id":"500"}""")
|
||||||
val json1 = """{"id":"500"}"""
|
assertEquals(1, manager.pendingTaskIds.size)
|
||||||
manager.onNewTaskMessage(json1)
|
|
||||||
// 模拟第二条消息(通过不同 json 但相同 id,且间隔足够)
|
|
||||||
// 由于去抖限制,这里只验证单次消息中的去重
|
|
||||||
assertEquals(1, manager.pendingCount)
|
|
||||||
assertTrue(manager.pendingTaskIds.contains("500"))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ===== 消息消费 =====
|
// ===== 消费 =====
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `consumeAll - should clear all pending tasks`() {
|
fun `consumeAll clears everything`() {
|
||||||
manager.onNewTaskMessage("""{"taskArr":[{"id":"1"},{"id":"2"},{"id":"3"}]}""")
|
manager.onNewTaskMessage("""{"taskArr":[{"id":"1"},{"id":"2"},{"id":"3"}]}""")
|
||||||
assertEquals(3, manager.pendingCount)
|
|
||||||
manager.consumeAll()
|
manager.consumeAll()
|
||||||
assertEquals(0, manager.pendingCount)
|
assertEquals(0, manager.pendingTaskIds.size)
|
||||||
|
assertTrue(manager.acknowledgedCards.isEmpty())
|
||||||
|
assertNull(manager.preNotificationStats)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `consumeByTaskId - should remove specific task`() {
|
fun `consumeByTaskId removes specific task`() {
|
||||||
manager.onNewTaskMessage("""{"taskArr":[{"id":"10"},{"id":"20"},{"id":"30"}]}""")
|
manager.onNewTaskMessage("""{"taskArr":[{"id":"10"},{"id":"20"},{"id":"30"}]}""")
|
||||||
manager.consumeByTaskId("20")
|
manager.consumeByTaskId("20")
|
||||||
assertEquals(2, manager.pendingCount)
|
assertEquals(2, manager.pendingTaskIds.size)
|
||||||
assertFalse(manager.pendingTaskIds.contains("20"))
|
assertFalse(manager.pendingTaskIds.contains("20"))
|
||||||
assertTrue(manager.pendingTaskIds.contains("10"))
|
|
||||||
assertTrue(manager.pendingTaskIds.contains("30"))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `consumeByTaskId - non-existent id should not crash`() {
|
fun `consumeByTaskId with non-existent id does not crash`() {
|
||||||
manager.onNewTaskMessage("""{"id":"1"}""")
|
manager.onNewTaskMessage("""{"id":"1"}""")
|
||||||
manager.consumeByTaskId("999")
|
manager.consumeByTaskId("999")
|
||||||
assertEquals(1, manager.pendingCount)
|
assertEquals(1, manager.pendingTaskIds.size)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ===== 红点对比 =====
|
// ===== 红点对比 =====
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `diffStats - all increased should return all cards`() {
|
fun `diffStats all increased returns all cards`() {
|
||||||
val old = TaskStatistics(waitForTask = 3, treatTask = 2, incompleteTask = 1)
|
val old = TaskStatistics(waitForTask = 3, treatTask = 2, incompleteTask = 1)
|
||||||
val new = TaskStatistics(waitForTask = 4, treatTask = 3, incompleteTask = 2)
|
val new = TaskStatistics(waitForTask = 4, treatTask = 3, incompleteTask = 2)
|
||||||
val result = manager.diffStats(old, new)
|
assertEquals(setOf(2, 3, 4), manager.diffStats(old, new))
|
||||||
assertEquals(setOf(2, 3, 4), result)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `diffStats - only waitForTask increased`() {
|
fun `diffStats only waitForTask increased`() {
|
||||||
val old = TaskStatistics(waitForTask = 3, treatTask = 2, incompleteTask = 1)
|
val old = TaskStatistics(waitForTask = 3, treatTask = 2, incompleteTask = 1)
|
||||||
val new = TaskStatistics(waitForTask = 5, treatTask = 2, incompleteTask = 1)
|
val new = TaskStatistics(waitForTask = 5, treatTask = 2, incompleteTask = 1)
|
||||||
val result = manager.diffStats(old, new)
|
assertEquals(setOf(2), manager.diffStats(old, new))
|
||||||
assertEquals(setOf(2), result)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `diffStats - no change should return empty`() {
|
fun `diffStats no change returns empty`() {
|
||||||
val old = TaskStatistics(waitForTask = 3, treatTask = 2, incompleteTask = 1)
|
val old = TaskStatistics(waitForTask = 3, treatTask = 2, incompleteTask = 1)
|
||||||
val new = TaskStatistics(waitForTask = 3, treatTask = 2, incompleteTask = 1)
|
assertEquals(emptySet<Int>(), manager.diffStats(old, old))
|
||||||
val result = manager.diffStats(old, new)
|
|
||||||
assertTrue(result.isEmpty())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `diffStats - decreased should not return card`() {
|
fun `diffStats decreased returns empty`() {
|
||||||
val old = TaskStatistics(waitForTask = 3, treatTask = 2, incompleteTask = 1)
|
val old = TaskStatistics(waitForTask = 3, treatTask = 2, incompleteTask = 1)
|
||||||
val new = TaskStatistics(waitForTask = 2, treatTask = 2, incompleteTask = 1)
|
val new = TaskStatistics(waitForTask = 2, treatTask = 2, incompleteTask = 1)
|
||||||
val result = manager.diffStats(old, new)
|
assertTrue(manager.diffStats(old, new).isEmpty())
|
||||||
assertTrue(result.isEmpty())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `diffStats - null old stats should return empty`() {
|
fun `diffStats null old returns empty`() {
|
||||||
val new = TaskStatistics(waitForTask = 5, treatTask = 3, incompleteTask = 2)
|
val new = TaskStatistics(waitForTask = 5, treatTask = 3, incompleteTask = 2)
|
||||||
val result = manager.diffStats(null, new)
|
assertTrue(manager.diffStats(null, new).isEmpty())
|
||||||
assertTrue(result.isEmpty())
|
}
|
||||||
|
|
||||||
|
// ===== acknowledgeCard + pendingCount =====
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `acknowledgeCard reduces pendingCount`() {
|
||||||
|
manager.onNewTaskMessage("""{"id":"1"}""")
|
||||||
|
manager.recordCardIncrement(3, 1)
|
||||||
|
manager.acknowledgeCard(3)
|
||||||
|
assertEquals(0, manager.pendingCount)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `acknowledgeCard partial reduces pendingCount`() {
|
||||||
|
manager.onNewTaskMessage("""{"taskArr":[{"id":"1"},{"id":"2"}]}""")
|
||||||
|
manager.recordCardIncrement(2, 1)
|
||||||
|
manager.recordCardIncrement(3, 1)
|
||||||
|
manager.acknowledgeCard(2)
|
||||||
|
assertEquals(1, manager.pendingCount)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ===== ack 清除 =====
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `new notification clears acknowledgedCards`() {
|
||||||
|
manager.onNewTaskMessage("""{"id":"1"}""")
|
||||||
|
manager.acknowledgeCard(3)
|
||||||
|
assertTrue(manager.acknowledgedCards.contains(3))
|
||||||
|
// 模拟新通知(需间隔 >1s,这里用新 manager 绕过去抖)
|
||||||
|
val manager2 = NotificationManager(vibrationController, screenController, eventBus)
|
||||||
|
manager2.acknowledgeCard(3)
|
||||||
|
assertTrue(manager2.acknowledgedCards.contains(3))
|
||||||
|
manager2.onNewTaskMessage("""{"id":"2"}""")
|
||||||
|
assertTrue(manager2.acknowledgedCards.isEmpty())
|
||||||
|
}
|
||||||
|
|
||||||
|
// ===== preNotificationStats =====
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `preNotificationStats saved on first notification`() {
|
||||||
|
val stats = TaskStatistics(waitForTask = 3, treatTask = 2, incompleteTask = 1)
|
||||||
|
manager.lastStats = stats
|
||||||
|
manager.onNewTaskMessage("""{"id":"1"}""")
|
||||||
|
assertEquals(stats, manager.preNotificationStats)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `preNotificationStats not overwritten on subsequent notification`() {
|
||||||
|
val stats1 = TaskStatistics(waitForTask = 3, treatTask = 2, incompleteTask = 1)
|
||||||
|
manager.lastStats = stats1
|
||||||
|
manager.onNewTaskMessage("""{"id":"1"}""")
|
||||||
|
// 模拟 lastStats 被更新
|
||||||
|
manager.lastStats = TaskStatistics(waitForTask = 4, treatTask = 2, incompleteTask = 1)
|
||||||
|
// preNotificationStats 不应该因为后续处理而变化(但去抖会阻止第二次 processMessage)
|
||||||
|
assertEquals(stats1, manager.preNotificationStats)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user