diff --git a/README.md b/README.md index 62642ea..1dc085b 100644 --- a/README.md +++ b/README.md @@ -95,7 +95,7 @@ - **步驟三:在遊戲中按貼上組合鍵** - 回到《FINAL FANTASY XIV 繁體中文版》遊戲後,在遊戲內的聊天輸入框按下遊戲中預設的貼上組合鍵(需先於遊戲設定中啟用),貼上剛才複製的文字,最後送出即可。 -**補充說明**:這是一套半自動、手動觸發的聊天輔助流程,重點在於穩定輸入與快速貼上。 +**補充說明**:這是一套手動觸發的文字暫存與剪貼簿中轉流程,重點在於穩定輸入;實際貼上與送出仍由使用者在遊戲中自行操作。 ### 1. 鍵盤操作 ⌨️ diff --git a/docs/engineering/git-commit-safety.md b/docs/engineering/git-commit-safety.md index 1902f35..6ca879f 100644 --- a/docs/engineering/git-commit-safety.md +++ b/docs/engineering/git-commit-safety.md @@ -38,5 +38,6 @@ ## 5. 法律合規工作流 1. 若任務涉及「按鍵處理」、「剪貼簿自動化」或「控制器映射」。 2. 使用對應代理可用的網頁抓取工具訪問上述連結(例如 Copilot:`fetch_webpage`;Gemini:`web_fetch`)。 -3. 比對異動是否符合「非自動化」、「非模擬」原則。 -4. 在計畫書 (/plan) 中聲明合規性分析結果。 +3. 若條款頁面僅回傳 JavaScript shell 或無法直接取得條款本文,必須改用可執行 JavaScript 的瀏覽器工具、官方網站中可抓取的同等條款頁,或明確記錄「未能擷取完整本文」並停止進行高風險核心輸入/輸出異動。 +4. 比對異動是否符合「非自動化」、「非模擬」原則。 +5. 在計畫書 (/plan) 或交付摘要中聲明合規性分析結果。 diff --git a/docs/engineering/testing.md b/docs/engineering/testing.md index 9396e05..268b202 100644 --- a/docs/engineering/testing.md +++ b/docs/engineering/testing.md @@ -11,13 +11,13 @@ ```powershell # 從 repo 根目錄執行 -dotnet test tests/InputBox.Tests/InputBox.Tests.csproj +dotnet test --project tests/InputBox.Tests/InputBox.Tests.csproj # 加入詳細輸出 -dotnet test tests/InputBox.Tests/InputBox.Tests.csproj --logger "console;verbosity=detailed" +dotnet test --project tests/InputBox.Tests/InputBox.Tests.csproj --logger "console;verbosity=detailed" # 收集 Code Coverage(MTP 原生模式,同 CI) -dotnet test tests/InputBox.Tests/InputBox.Tests.csproj -c Release --no-build ` +dotnet test --project tests/InputBox.Tests/InputBox.Tests.csproj -c Release --no-build ` --coverage ` --coverage-output-format cobertura ` --coverage-output coverage.cobertura.xml diff --git a/tests/InputBox.Tests/DialogLabelStabilityTests.cs b/tests/InputBox.Tests/DialogLabelStabilityTests.cs index e442d3b..5668684 100644 --- a/tests/InputBox.Tests/DialogLabelStabilityTests.cs +++ b/tests/InputBox.Tests/DialogLabelStabilityTests.cs @@ -11,6 +11,9 @@ namespace InputBox.Tests; /// public sealed class DialogLabelStabilityTests { + /// + /// 片語編輯對話框的名稱與內容計數標籤應使用固定寬度,避免文字長度變動造成版面抖動。 + /// [Fact] public void PhraseEditDialog_CountLabels_UseFixedWidth() { @@ -25,6 +28,9 @@ public void PhraseEditDialog_CountLabels_UseFixedWidth() Assert.True(contentCount.MinimumSize.Width > 0); } + /// + /// 片語管理對話框的片語數量標籤應使用固定寬度,避免數量變動時推擠其他控制項。 + /// [Fact] public void PhraseManagerDialog_CountLabel_UsesFixedWidth() { diff --git a/tests/InputBox.Tests/GamepadCalibrationVisualizerMapperTests.cs b/tests/InputBox.Tests/GamepadCalibrationVisualizerMapperTests.cs index b5f4057..19006da 100644 --- a/tests/InputBox.Tests/GamepadCalibrationVisualizerMapperTests.cs +++ b/tests/InputBox.Tests/GamepadCalibrationVisualizerMapperTests.cs @@ -23,6 +23,9 @@ public void ClampNormalized_RestrictsToVisibleRange(float input, float expected) Assert.Equal(expected, actual, 3); } + /// + /// 死區半徑應依完整軸向範圍換算成正規化比例,避免校準圖縮放錯誤。 + /// [Fact] public void CalculateDeadzoneRadius_UsesFullScaleRatioAndClamps() { @@ -31,6 +34,9 @@ public void CalculateDeadzoneRadius_UsesFullScaleRatioAndClamps() Assert.InRange(actual, 0.07f, 0.08f); } + /// + /// 死區值超過完整軸向範圍時應夾至最大半徑,避免繪製超出校準圖邊界。 + /// [Fact] public void CalculateDeadzoneRadius_WhenInputExceedsFullScale_ReturnsOne() { @@ -39,6 +45,9 @@ public void CalculateDeadzoneRadius_WhenInputExceedsFullScale_ReturnsOne() Assert.Equal(1.0f, actual, 3); } + /// + /// 控制器已連線的廣播文字應包含裝置名稱,且不應殘留格式化預留位置。 + /// [Fact] public void FormatConnectionAnnouncement_WhenConnected_IncludesDeviceName() { @@ -48,6 +57,9 @@ public void FormatConnectionAnnouncement_WhenConnected_IncludesDeviceName() Assert.DoesNotContain("{0}", actual); } + /// + /// 控制器未連線的廣播文字應使用斷線範本並帶入裝置名稱,避免播報未格式化字串。 + /// [Fact] public void FormatConnectionAnnouncement_WhenDisconnected_UsesDisconnectedTemplate() { @@ -57,6 +69,9 @@ public void FormatConnectionAnnouncement_WhenDisconnected_UsesDisconnectedTempla Assert.DoesNotContain("{0}", actual); } + /// + /// 已連線狀態文字應包含左右搖桿座標與死區數值,讓校準診斷資訊完整可讀。 + /// [Fact] public void FormatStatusText_WhenConnected_IncludesLeftAndRightStickValues() { @@ -83,6 +98,9 @@ public void FormatStatusText_WhenConnected_IncludesLeftAndRightStickValues() Assert.Contains("2500", actual); } + /// + /// 未連線狀態文字應回到資源檔中的斷線訊息,避免顯示空白或過期座標。 + /// [Fact] public void FormatStatusText_WhenDisconnected_UsesDisconnectedMessage() { @@ -91,6 +109,9 @@ public void FormatStatusText_WhenDisconnected_UsesDisconnectedMessage() Assert.Equal(Strings.Dialog_GamepadCalibrationVisualizer_StatusDisconnected, actual); } + /// + /// 左搖桿位於中心區域時應允許 D-Pad 導覽焦點,避免校準對話框失去基本可操作性。 + /// [Fact] public void ShouldHandleDirectionalFocusNavigation_WhenStickIsCentered_ReturnsTrue() { @@ -106,6 +127,9 @@ public void ShouldHandleDirectionalFocusNavigation_WhenStickIsCentered_ReturnsTr Assert.True(actual); } + /// + /// 左搖桿已明顯偏移時應阻止 D-Pad 焦點導覽,避免同一輸入同時觸發兩種移動。 + /// [Fact] public void ShouldHandleDirectionalFocusNavigation_WhenLeftStickIsActive_ReturnsFalse() { @@ -121,6 +145,9 @@ public void ShouldHandleDirectionalFocusNavigation_WhenLeftStickIsActive_Returns Assert.False(actual); } + /// + /// 左搖桿剛跨越進入死區時應阻止焦點導覽,避免 stick-to-DPad 映射後又重複移動焦點。 + /// [Fact] public void ShouldHandleDirectionalFocusNavigation_WhenStickJustCrossesEnterDeadzone_ReturnsFalse() { diff --git a/tests/InputBox.Tests/GamepadShoulderShortcutArbiterTests.cs b/tests/InputBox.Tests/GamepadShoulderShortcutArbiterTests.cs index 35c2619..1a9f339 100644 --- a/tests/InputBox.Tests/GamepadShoulderShortcutArbiterTests.cs +++ b/tests/InputBox.Tests/GamepadShoulderShortcutArbiterTests.cs @@ -8,6 +8,9 @@ namespace InputBox.Tests; /// public sealed class GamepadShoulderShortcutArbiterTests { + /// + /// 已武裝的單次肩鍵點按在放開時應輸出一次翻頁動作。 + /// [Fact] public void TryConsumeTapOnRelease_WhenSingleTapWasArmed_EmitsSinglePageAction() { @@ -18,6 +21,9 @@ public void TryConsumeTapOnRelease_WhenSingleTapWasArmed_EmitsSinglePageAction() Assert.True(arbiter.TryConsumeTapOnRelease(direction: -1, isLeftStillHeld: false, isRightStillHeld: false)); } + /// + /// 肩鍵長按連發已消費動作後,放開時不應再額外輸出單次翻頁。 + /// [Fact] public void TryConsumeTapOnRelease_WhenRepeatAlreadyConsumed_DoesNotEmitExtraTap() { @@ -29,6 +35,9 @@ public void TryConsumeTapOnRelease_WhenRepeatAlreadyConsumed_DoesNotEmitExtraTap Assert.False(arbiter.TryConsumeTapOnRelease(direction: -1, isLeftStillHeld: false, isRightStillHeld: false)); } + /// + /// 肩鍵已被用作修飾鍵時,放開時不應誤觸發單次翻頁。 + /// [Fact] public void TryConsumeTapOnRelease_WhenModifierWasUsed_DoesNotEmitTapOnRelease() { @@ -40,6 +49,9 @@ public void TryConsumeTapOnRelease_WhenModifierWasUsed_DoesNotEmitTapOnRelease() Assert.False(arbiter.TryConsumeTapOnRelease(direction: +1, isLeftStillHeld: false, isRightStillHeld: false)); } + /// + /// 雙肩鍵組合保留期間應抑制翻頁,直到兩側肩鍵都放開後才解除抑制。 + /// [Fact] public void ReserveDualShoulderCombo_SuppressesPagingUntilBothShouldersAreReleased() { diff --git a/tests/InputBox.Tests/README.md b/tests/InputBox.Tests/README.md index 7024931..6bc00db 100644 --- a/tests/InputBox.Tests/README.md +++ b/tests/InputBox.Tests/README.md @@ -48,19 +48,19 @@ ## 二、執行方式 🚀 ```powershell -dotnet test tests/InputBox.Tests/InputBox.Tests.csproj +dotnet test --project tests/InputBox.Tests/InputBox.Tests.csproj ``` 加入詳細輸出(MTP): ```powershell -dotnet test tests/InputBox.Tests/InputBox.Tests.csproj --logger "console;verbosity=detailed" +dotnet test --project tests/InputBox.Tests/InputBox.Tests.csproj --logger "console;verbosity=detailed" ``` 收集 Code Coverage(MTP 原生模式,同 CI): ```powershell -dotnet test tests/InputBox.Tests/InputBox.Tests.csproj -c Release --no-build ` +dotnet test --project tests/InputBox.Tests/InputBox.Tests.csproj -c Release --no-build ` --filter-not-trait "Category=UI" ` --coverage ` --coverage-output-format cobertura ` diff --git a/tests/InputBox.Tests/SystemHelperTests.cs b/tests/InputBox.Tests/SystemHelperTests.cs index 0e62bb1..5889ae5 100644 --- a/tests/InputBox.Tests/SystemHelperTests.cs +++ b/tests/InputBox.Tests/SystemHelperTests.cs @@ -1,4 +1,4 @@ -using InputBox.Core.Utilities; +using InputBox.Core.Utilities; using Xunit; namespace InputBox.Tests;