diff --git a/app/src/androidTest/java/com/m57/hermescontrol/ui/chat/components/ContextUsageComponentsTest.kt b/app/src/androidTest/java/com/m57/hermescontrol/ui/chat/components/ContextUsageComponentsTest.kt new file mode 100644 index 00000000..e1ec3178 --- /dev/null +++ b/app/src/androidTest/java/com/m57/hermescontrol/ui/chat/components/ContextUsageComponentsTest.kt @@ -0,0 +1,108 @@ +package com.m57.hermescontrol.ui.chat.components + +import androidx.compose.ui.test.assertIsDisplayed +import androidx.compose.ui.test.junit4.createComposeRule +import androidx.compose.ui.test.onNodeWithText +import androidx.test.ext.junit.runners.AndroidJUnit4 +import androidx.test.filters.MediumTest +import com.m57.hermescontrol.theme.HermesControlTheme +import com.m57.hermescontrol.ui.chat.ContextBreakdown +import org.junit.Rule +import org.junit.Test +import org.junit.runner.RunWith + +/** + * Regression coverage for backend-reported context occupancy. + * + * Cumulative REST input-token accounting must never masquerade as the live + * context-window numerator when the backend has not reported context_used. + */ +@RunWith(AndroidJUnit4::class) +@MediumTest +class ContextUsageComponentsTest { + @get:Rule + val composeTestRule = createComposeRule() + + @Test + fun chip_missingBackendOccupancy_doesNotShowFakeZeroPercent() { + composeTestRule.setContent { + HermesControlTheme { + ContextUsageChip( + usedTokens = null, + fullTokens = 128_000L, + ) + } + } + + composeTestRule + .onNodeWithText("— / 128k context") + .assertIsDisplayed() + + composeTestRule + .onNodeWithText("0%") + .assertDoesNotExist() + } + + @Test + fun chip_backendOccupancyAvailable_showsDeterminateUsage() { + composeTestRule.setContent { + HermesControlTheme { + ContextUsageChip( + usedTokens = 64_000L, + fullTokens = 128_000L, + ) + } + } + + composeTestRule + .onNodeWithText("64k / 128k context") + .assertIsDisplayed() + + composeTestRule + .onNodeWithText("50%") + .assertIsDisplayed() + } + + @Test + fun detailSheet_missingBackendOccupancy_doesNotUseCumulativeInputTokensAsNumerator() { + composeTestRule.setContent { + HermesControlTheme { + ContextDetailSheet( + breakdown = + ContextBreakdown( + inputTokens = 12_300L, + outputTokens = 2_000L, + cacheReadTokens = 500L, + cacheWriteTokens = 250L, + reasoningTokens = 100L, + messageCount = 4, + ), + usedTokens = null, + fullTokens = 128_000L, + onDismiss = {}, + ) + } + } + + // The live numerator is unavailable, even though cumulative REST + // input-token accounting exists below in the detail breakdown. + composeTestRule + .onNodeWithText("—") + .assertIsDisplayed() + + composeTestRule + .onNodeWithText("Context window usage unavailable") + .assertIsDisplayed() + + // Cumulative accounting is still preserved as informational detail. + composeTestRule + .onNodeWithText("12.3k") + .assertIsDisplayed() + + // Most important regression guard: null occupancy is not rendered as + // a determinate zero-percent context state. + composeTestRule + .onNodeWithText("0% of context window used") + .assertDoesNotExist() + } +} diff --git a/app/src/main/res/values-ar/strings.xml b/app/src/main/res/values-ar/strings.xml index c0e458e6..83265e23 100644 --- a/app/src/main/res/values-ar/strings.xml +++ b/app/src/main/res/values-ar/strings.xml @@ -1308,7 +1308,7 @@ الإكمال (المخرجات) مضغوط ×%1$s المطالبة (المدخلات) -تعكس رموز المطالبة إجمالي السياق المستخدم في هذه الجلسة حتى الآن. +أعداد الرموز أدناه تراكمية للجلسة ولا تمثل الاستخدام الحالي لنافذة السياق. نافذة السياق استخدام نافذة السياق غير متوفر تشغيل GIF diff --git a/app/src/main/res/values-zh/strings.xml b/app/src/main/res/values-zh/strings.xml index 8fd352db..0c36aea0 100644 --- a/app/src/main/res/values-zh/strings.xml +++ b/app/src/main/res/values-zh/strings.xml @@ -1275,7 +1275,7 @@ 补全(输出) 已压缩 ×%1$s 提示词(输入) - 提示词 token 反映此会话迄今使用的总上下文。 + 下方 token 数为会话累计用量,不代表当前上下文窗口占用。 上下文窗口 上下文窗口使用量不可用 播放 GIF diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 16e3cc74..c5f01c34 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -1435,7 +1435,7 @@ Completion (output) compressed ×%1$s Prompt (input) - Prompt tokens reflect total context used by this session so far. + Token counts below are cumulative session accounting and do not represent current context-window occupancy. Context window Context window usage unavailable Play GIF