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;