@hasna/terminal 2.3.0 → 2.3.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/App.js +404 -0
- package/dist/Browse.js +79 -0
- package/dist/FuzzyPicker.js +47 -0
- package/dist/Onboarding.js +51 -0
- package/dist/Spinner.js +12 -0
- package/dist/StatusBar.js +49 -0
- package/dist/ai.js +322 -0
- package/dist/cache.js +41 -0
- package/dist/cli.js +64 -16
- package/dist/command-rewriter.js +64 -0
- package/dist/command-validator.js +86 -0
- package/dist/compression.js +107 -0
- package/dist/context-hints.js +275 -0
- package/dist/diff-cache.js +107 -0
- package/dist/discover.js +212 -0
- package/dist/economy.js +123 -0
- package/dist/expand-store.js +38 -0
- package/dist/file-cache.js +72 -0
- package/dist/file-index.js +62 -0
- package/dist/history.js +62 -0
- package/dist/lazy-executor.js +54 -0
- package/dist/line-dedup.js +59 -0
- package/dist/loop-detector.js +75 -0
- package/dist/mcp/install.js +98 -0
- package/dist/mcp/server.js +569 -0
- package/dist/noise-filter.js +86 -0
- package/dist/output-processor.js +129 -0
- package/dist/output-router.js +41 -0
- package/dist/output-store.js +111 -0
- package/dist/parsers/base.js +2 -0
- package/dist/parsers/build.js +64 -0
- package/dist/parsers/errors.js +101 -0
- package/dist/parsers/files.js +78 -0
- package/dist/parsers/git.js +99 -0
- package/dist/parsers/index.js +48 -0
- package/dist/parsers/tests.js +89 -0
- package/dist/providers/anthropic.js +39 -0
- package/dist/providers/base.js +4 -0
- package/dist/providers/cerebras.js +95 -0
- package/dist/providers/groq.js +95 -0
- package/dist/providers/index.js +73 -0
- package/dist/providers/xai.js +95 -0
- package/dist/recipes/model.js +20 -0
- package/dist/recipes/storage.js +136 -0
- package/dist/search/content-search.js +68 -0
- package/dist/search/file-search.js +61 -0
- package/dist/search/filters.js +34 -0
- package/dist/search/index.js +5 -0
- package/dist/search/semantic.js +320 -0
- package/dist/session-boot.js +59 -0
- package/dist/session-context.js +55 -0
- package/dist/sessions-db.js +173 -0
- package/dist/smart-display.js +286 -0
- package/dist/snapshots.js +51 -0
- package/dist/supervisor.js +112 -0
- package/dist/test-watchlist.js +131 -0
- package/dist/tool-profiles.js +122 -0
- package/dist/tree.js +94 -0
- package/dist/usage-cache.js +65 -0
- package/package.json +8 -1
- package/src/ai.ts +8 -0
- package/src/cli.tsx +57 -18
- package/src/output-processor.ts +6 -1
- package/src/output-store.ts +58 -12
- package/src/tool-profiles.ts +139 -0
- package/.claude/scheduled_tasks.lock +0 -1
- package/.github/ISSUE_TEMPLATE/bug_report.md +0 -20
- package/.github/ISSUE_TEMPLATE/feature_request.md +0 -14
- package/CONTRIBUTING.md +0 -80
- package/benchmarks/benchmark.mjs +0 -115
- package/imported_modules.txt +0 -0
- package/temp/rtk/.claude/agents/code-reviewer.md +0 -221
- package/temp/rtk/.claude/agents/debugger.md +0 -519
- package/temp/rtk/.claude/agents/rtk-testing-specialist.md +0 -461
- package/temp/rtk/.claude/agents/rust-rtk.md +0 -511
- package/temp/rtk/.claude/agents/technical-writer.md +0 -355
- package/temp/rtk/.claude/commands/diagnose.md +0 -352
- package/temp/rtk/.claude/commands/test-routing.md +0 -362
- package/temp/rtk/.claude/hooks/bash/pre-commit-format.sh +0 -16
- package/temp/rtk/.claude/hooks/rtk-rewrite.sh +0 -70
- package/temp/rtk/.claude/hooks/rtk-suggest.sh +0 -152
- package/temp/rtk/.claude/rules/cli-testing.md +0 -526
- package/temp/rtk/.claude/skills/issue-triage/SKILL.md +0 -348
- package/temp/rtk/.claude/skills/issue-triage/templates/issue-comment.md +0 -134
- package/temp/rtk/.claude/skills/performance.md +0 -435
- package/temp/rtk/.claude/skills/pr-triage/SKILL.md +0 -315
- package/temp/rtk/.claude/skills/pr-triage/templates/review-comment.md +0 -71
- package/temp/rtk/.claude/skills/repo-recap.md +0 -206
- package/temp/rtk/.claude/skills/rtk-tdd/SKILL.md +0 -78
- package/temp/rtk/.claude/skills/rtk-tdd/references/testing-patterns.md +0 -124
- package/temp/rtk/.claude/skills/security-guardian.md +0 -503
- package/temp/rtk/.claude/skills/ship.md +0 -404
- package/temp/rtk/.github/workflows/benchmark.yml +0 -34
- package/temp/rtk/.github/workflows/dco-check.yaml +0 -12
- package/temp/rtk/.github/workflows/release-please.yml +0 -51
- package/temp/rtk/.github/workflows/release.yml +0 -343
- package/temp/rtk/.github/workflows/security-check.yml +0 -135
- package/temp/rtk/.github/workflows/validate-docs.yml +0 -78
- package/temp/rtk/.release-please-manifest.json +0 -3
- package/temp/rtk/ARCHITECTURE.md +0 -1491
- package/temp/rtk/CHANGELOG.md +0 -640
- package/temp/rtk/CLAUDE.md +0 -605
- package/temp/rtk/CONTRIBUTING.md +0 -199
- package/temp/rtk/Cargo.lock +0 -1668
- package/temp/rtk/Cargo.toml +0 -64
- package/temp/rtk/Formula/rtk.rb +0 -43
- package/temp/rtk/INSTALL.md +0 -390
- package/temp/rtk/LICENSE +0 -21
- package/temp/rtk/README.md +0 -386
- package/temp/rtk/README_es.md +0 -159
- package/temp/rtk/README_fr.md +0 -197
- package/temp/rtk/README_ja.md +0 -159
- package/temp/rtk/README_ko.md +0 -159
- package/temp/rtk/README_zh.md +0 -167
- package/temp/rtk/ROADMAP.md +0 -15
- package/temp/rtk/SECURITY.md +0 -217
- package/temp/rtk/TEST_EXEC_TIME.md +0 -102
- package/temp/rtk/build.rs +0 -57
- package/temp/rtk/docs/AUDIT_GUIDE.md +0 -432
- package/temp/rtk/docs/FEATURES.md +0 -1410
- package/temp/rtk/docs/TROUBLESHOOTING.md +0 -309
- package/temp/rtk/docs/filter-workflow.md +0 -102
- package/temp/rtk/docs/images/gain-dashboard.jpg +0 -0
- package/temp/rtk/docs/tracking.md +0 -583
- package/temp/rtk/hooks/opencode-rtk.ts +0 -39
- package/temp/rtk/hooks/rtk-awareness.md +0 -29
- package/temp/rtk/hooks/rtk-rewrite.sh +0 -61
- package/temp/rtk/hooks/test-rtk-rewrite.sh +0 -442
- package/temp/rtk/install.sh +0 -124
- package/temp/rtk/release-please-config.json +0 -10
- package/temp/rtk/scripts/benchmark.sh +0 -592
- package/temp/rtk/scripts/check-installation.sh +0 -162
- package/temp/rtk/scripts/install-local.sh +0 -37
- package/temp/rtk/scripts/rtk-economics.sh +0 -137
- package/temp/rtk/scripts/test-all.sh +0 -561
- package/temp/rtk/scripts/test-aristote.sh +0 -227
- package/temp/rtk/scripts/test-tracking.sh +0 -79
- package/temp/rtk/scripts/update-readme-metrics.sh +0 -32
- package/temp/rtk/scripts/validate-docs.sh +0 -73
- package/temp/rtk/src/aws_cmd.rs +0 -880
- package/temp/rtk/src/binlog.rs +0 -1645
- package/temp/rtk/src/cargo_cmd.rs +0 -1727
- package/temp/rtk/src/cc_economics.rs +0 -1157
- package/temp/rtk/src/ccusage.rs +0 -340
- package/temp/rtk/src/config.rs +0 -187
- package/temp/rtk/src/container.rs +0 -855
- package/temp/rtk/src/curl_cmd.rs +0 -134
- package/temp/rtk/src/deps.rs +0 -268
- package/temp/rtk/src/diff_cmd.rs +0 -367
- package/temp/rtk/src/discover/mod.rs +0 -274
- package/temp/rtk/src/discover/provider.rs +0 -388
- package/temp/rtk/src/discover/registry.rs +0 -2022
- package/temp/rtk/src/discover/report.rs +0 -202
- package/temp/rtk/src/discover/rules.rs +0 -667
- package/temp/rtk/src/display_helpers.rs +0 -402
- package/temp/rtk/src/dotnet_cmd.rs +0 -1771
- package/temp/rtk/src/dotnet_format_report.rs +0 -133
- package/temp/rtk/src/dotnet_trx.rs +0 -593
- package/temp/rtk/src/env_cmd.rs +0 -204
- package/temp/rtk/src/filter.rs +0 -462
- package/temp/rtk/src/filters/README.md +0 -52
- package/temp/rtk/src/filters/ansible-playbook.toml +0 -34
- package/temp/rtk/src/filters/basedpyright.toml +0 -47
- package/temp/rtk/src/filters/biome.toml +0 -45
- package/temp/rtk/src/filters/brew-install.toml +0 -37
- package/temp/rtk/src/filters/composer-install.toml +0 -40
- package/temp/rtk/src/filters/df.toml +0 -16
- package/temp/rtk/src/filters/dotnet-build.toml +0 -64
- package/temp/rtk/src/filters/du.toml +0 -16
- package/temp/rtk/src/filters/fail2ban-client.toml +0 -15
- package/temp/rtk/src/filters/gcc.toml +0 -49
- package/temp/rtk/src/filters/gcloud.toml +0 -22
- package/temp/rtk/src/filters/hadolint.toml +0 -24
- package/temp/rtk/src/filters/helm.toml +0 -29
- package/temp/rtk/src/filters/iptables.toml +0 -27
- package/temp/rtk/src/filters/jj.toml +0 -28
- package/temp/rtk/src/filters/jq.toml +0 -24
- package/temp/rtk/src/filters/make.toml +0 -41
- package/temp/rtk/src/filters/markdownlint.toml +0 -24
- package/temp/rtk/src/filters/mix-compile.toml +0 -27
- package/temp/rtk/src/filters/mix-format.toml +0 -15
- package/temp/rtk/src/filters/mvn-build.toml +0 -44
- package/temp/rtk/src/filters/oxlint.toml +0 -43
- package/temp/rtk/src/filters/ping.toml +0 -63
- package/temp/rtk/src/filters/pio-run.toml +0 -40
- package/temp/rtk/src/filters/poetry-install.toml +0 -50
- package/temp/rtk/src/filters/pre-commit.toml +0 -35
- package/temp/rtk/src/filters/ps.toml +0 -16
- package/temp/rtk/src/filters/quarto-render.toml +0 -41
- package/temp/rtk/src/filters/rsync.toml +0 -48
- package/temp/rtk/src/filters/shellcheck.toml +0 -27
- package/temp/rtk/src/filters/shopify-theme.toml +0 -29
- package/temp/rtk/src/filters/skopeo.toml +0 -45
- package/temp/rtk/src/filters/sops.toml +0 -16
- package/temp/rtk/src/filters/ssh.toml +0 -44
- package/temp/rtk/src/filters/stat.toml +0 -34
- package/temp/rtk/src/filters/swift-build.toml +0 -41
- package/temp/rtk/src/filters/systemctl-status.toml +0 -33
- package/temp/rtk/src/filters/terraform-plan.toml +0 -35
- package/temp/rtk/src/filters/tofu-fmt.toml +0 -16
- package/temp/rtk/src/filters/tofu-init.toml +0 -38
- package/temp/rtk/src/filters/tofu-plan.toml +0 -35
- package/temp/rtk/src/filters/tofu-validate.toml +0 -17
- package/temp/rtk/src/filters/trunk-build.toml +0 -39
- package/temp/rtk/src/filters/ty.toml +0 -50
- package/temp/rtk/src/filters/uv-sync.toml +0 -37
- package/temp/rtk/src/filters/xcodebuild.toml +0 -99
- package/temp/rtk/src/filters/yamllint.toml +0 -25
- package/temp/rtk/src/find_cmd.rs +0 -598
- package/temp/rtk/src/format_cmd.rs +0 -386
- package/temp/rtk/src/gain.rs +0 -723
- package/temp/rtk/src/gh_cmd.rs +0 -1651
- package/temp/rtk/src/git.rs +0 -2012
- package/temp/rtk/src/go_cmd.rs +0 -592
- package/temp/rtk/src/golangci_cmd.rs +0 -254
- package/temp/rtk/src/grep_cmd.rs +0 -288
- package/temp/rtk/src/gt_cmd.rs +0 -810
- package/temp/rtk/src/hook_audit_cmd.rs +0 -283
- package/temp/rtk/src/hook_check.rs +0 -171
- package/temp/rtk/src/init.rs +0 -1859
- package/temp/rtk/src/integrity.rs +0 -537
- package/temp/rtk/src/json_cmd.rs +0 -231
- package/temp/rtk/src/learn/detector.rs +0 -628
- package/temp/rtk/src/learn/mod.rs +0 -119
- package/temp/rtk/src/learn/report.rs +0 -184
- package/temp/rtk/src/lint_cmd.rs +0 -694
- package/temp/rtk/src/local_llm.rs +0 -316
- package/temp/rtk/src/log_cmd.rs +0 -248
- package/temp/rtk/src/ls.rs +0 -324
- package/temp/rtk/src/main.rs +0 -2482
- package/temp/rtk/src/mypy_cmd.rs +0 -389
- package/temp/rtk/src/next_cmd.rs +0 -241
- package/temp/rtk/src/npm_cmd.rs +0 -236
- package/temp/rtk/src/parser/README.md +0 -267
- package/temp/rtk/src/parser/error.rs +0 -46
- package/temp/rtk/src/parser/formatter.rs +0 -336
- package/temp/rtk/src/parser/mod.rs +0 -311
- package/temp/rtk/src/parser/types.rs +0 -119
- package/temp/rtk/src/pip_cmd.rs +0 -302
- package/temp/rtk/src/playwright_cmd.rs +0 -479
- package/temp/rtk/src/pnpm_cmd.rs +0 -573
- package/temp/rtk/src/prettier_cmd.rs +0 -221
- package/temp/rtk/src/prisma_cmd.rs +0 -482
- package/temp/rtk/src/psql_cmd.rs +0 -382
- package/temp/rtk/src/pytest_cmd.rs +0 -384
- package/temp/rtk/src/read.rs +0 -217
- package/temp/rtk/src/rewrite_cmd.rs +0 -50
- package/temp/rtk/src/ruff_cmd.rs +0 -402
- package/temp/rtk/src/runner.rs +0 -271
- package/temp/rtk/src/summary.rs +0 -297
- package/temp/rtk/src/tee.rs +0 -405
- package/temp/rtk/src/telemetry.rs +0 -248
- package/temp/rtk/src/toml_filter.rs +0 -1655
- package/temp/rtk/src/tracking.rs +0 -1416
- package/temp/rtk/src/tree.rs +0 -209
- package/temp/rtk/src/tsc_cmd.rs +0 -259
- package/temp/rtk/src/utils.rs +0 -432
- package/temp/rtk/src/verify_cmd.rs +0 -47
- package/temp/rtk/src/vitest_cmd.rs +0 -385
- package/temp/rtk/src/wc_cmd.rs +0 -401
- package/temp/rtk/src/wget_cmd.rs +0 -260
- package/temp/rtk/tests/fixtures/dotnet/build_failed.txt +0 -11
- package/temp/rtk/tests/fixtures/dotnet/format_changes.json +0 -31
- package/temp/rtk/tests/fixtures/dotnet/format_empty.json +0 -1
- package/temp/rtk/tests/fixtures/dotnet/format_success.json +0 -12
- package/temp/rtk/tests/fixtures/dotnet/test_failed.txt +0 -18
- package/tsconfig.json +0 -15
|
@@ -1,526 +0,0 @@
|
|
|
1
|
-
# CLI Testing Strategy
|
|
2
|
-
|
|
3
|
-
Comprehensive testing rules for RTK CLI tool development.
|
|
4
|
-
|
|
5
|
-
## Snapshot Testing (🔴 Critical)
|
|
6
|
-
|
|
7
|
-
**Priority**: 🔴 **Triggers**: All filter changes, output format modifications
|
|
8
|
-
|
|
9
|
-
Use `insta` crate for output validation. This is the **primary testing strategy** for RTK filters.
|
|
10
|
-
|
|
11
|
-
### Basic Snapshot Test
|
|
12
|
-
|
|
13
|
-
```rust
|
|
14
|
-
use insta::assert_snapshot;
|
|
15
|
-
|
|
16
|
-
#[test]
|
|
17
|
-
fn test_git_log_output() {
|
|
18
|
-
let input = include_str!("../tests/fixtures/git_log_raw.txt");
|
|
19
|
-
let output = filter_git_log(input);
|
|
20
|
-
|
|
21
|
-
// Snapshot test - will fail if output changes
|
|
22
|
-
assert_snapshot!(output);
|
|
23
|
-
}
|
|
24
|
-
```
|
|
25
|
-
|
|
26
|
-
### Workflow
|
|
27
|
-
|
|
28
|
-
1. **Write test**: Add `assert_snapshot!(output);` in test
|
|
29
|
-
2. **Run tests**: `cargo test` (creates new snapshots on first run)
|
|
30
|
-
3. **Review snapshots**: `cargo insta review` (interactive review)
|
|
31
|
-
4. **Accept changes**: `cargo insta accept` (if output is correct)
|
|
32
|
-
|
|
33
|
-
### When to Use
|
|
34
|
-
|
|
35
|
-
- **Every new filter**: All filters must have snapshot test
|
|
36
|
-
- **Output format changes**: When modifying filter logic
|
|
37
|
-
- **Regression detection**: Catch unintended changes
|
|
38
|
-
|
|
39
|
-
### Example Workflow
|
|
40
|
-
|
|
41
|
-
```bash
|
|
42
|
-
# 1. Create fixture from real command
|
|
43
|
-
git log -20 > tests/fixtures/git_log_raw.txt
|
|
44
|
-
|
|
45
|
-
# 2. Write test with assert_snapshot!
|
|
46
|
-
cat > src/git.rs <<'EOF'
|
|
47
|
-
#[cfg(test)]
|
|
48
|
-
mod tests {
|
|
49
|
-
use insta::assert_snapshot;
|
|
50
|
-
|
|
51
|
-
#[test]
|
|
52
|
-
fn test_git_log_format() {
|
|
53
|
-
let input = include_str!("../tests/fixtures/git_log_raw.txt");
|
|
54
|
-
let output = filter_git_log(input);
|
|
55
|
-
assert_snapshot!(output);
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
EOF
|
|
59
|
-
|
|
60
|
-
# 3. Run test (creates snapshot)
|
|
61
|
-
cargo test test_git_log_format
|
|
62
|
-
|
|
63
|
-
# 4. Review snapshot
|
|
64
|
-
cargo insta review
|
|
65
|
-
# Press 'a' to accept, 'r' to reject
|
|
66
|
-
|
|
67
|
-
# 5. Snapshot saved in src/snapshots/git.rs.snap
|
|
68
|
-
```
|
|
69
|
-
|
|
70
|
-
## Token Accuracy Testing (🔴 Critical)
|
|
71
|
-
|
|
72
|
-
**Priority**: 🔴 **Triggers**: All filter implementations, token savings claims
|
|
73
|
-
|
|
74
|
-
All filters **MUST** verify 60-90% token savings claims with real fixtures.
|
|
75
|
-
|
|
76
|
-
### Token Count Test
|
|
77
|
-
|
|
78
|
-
```rust
|
|
79
|
-
#[cfg(test)]
|
|
80
|
-
mod tests {
|
|
81
|
-
fn count_tokens(text: &str) -> usize {
|
|
82
|
-
text.split_whitespace().count()
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
#[test]
|
|
86
|
-
fn test_git_log_savings() {
|
|
87
|
-
let input = include_str!("../tests/fixtures/git_log_raw.txt");
|
|
88
|
-
let output = filter_git_log(input);
|
|
89
|
-
|
|
90
|
-
let input_tokens = count_tokens(input);
|
|
91
|
-
let output_tokens = count_tokens(&output);
|
|
92
|
-
|
|
93
|
-
let savings = 100.0 - (output_tokens as f64 / input_tokens as f64 * 100.0);
|
|
94
|
-
|
|
95
|
-
assert!(
|
|
96
|
-
savings >= 60.0,
|
|
97
|
-
"Git log filter: expected ≥60% savings, got {:.1}%",
|
|
98
|
-
savings
|
|
99
|
-
);
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
```
|
|
103
|
-
|
|
104
|
-
### Creating Fixtures
|
|
105
|
-
|
|
106
|
-
**Use real command output**, not synthetic data:
|
|
107
|
-
|
|
108
|
-
```bash
|
|
109
|
-
# Capture real output
|
|
110
|
-
git log -20 > tests/fixtures/git_log_raw.txt
|
|
111
|
-
cargo test 2>&1 > tests/fixtures/cargo_test_raw.txt
|
|
112
|
-
gh pr view 123 > tests/fixtures/gh_pr_view_raw.txt
|
|
113
|
-
pnpm list > tests/fixtures/pnpm_list_raw.txt
|
|
114
|
-
|
|
115
|
-
# Then use in tests:
|
|
116
|
-
# let input = include_str!("../tests/fixtures/git_log_raw.txt");
|
|
117
|
-
```
|
|
118
|
-
|
|
119
|
-
### Savings Targets by Filter
|
|
120
|
-
|
|
121
|
-
| Filter | Expected Savings | Rationale |
|
|
122
|
-
|--------|------------------|-----------|
|
|
123
|
-
| `git log` | 80%+ | Condense commits to hash + message |
|
|
124
|
-
| `cargo test` | 90%+ | Show failures only |
|
|
125
|
-
| `gh pr view` | 87%+ | Remove ASCII art, verbose metadata |
|
|
126
|
-
| `pnpm list` | 70%+ | Compact dependency tree |
|
|
127
|
-
| `docker ps` | 60%+ | Essential fields only |
|
|
128
|
-
|
|
129
|
-
**Release blocker**: If savings drop below 60% for any filter, investigate and fix before merge.
|
|
130
|
-
|
|
131
|
-
## Cross-Platform Testing (🔴 Critical)
|
|
132
|
-
|
|
133
|
-
**Priority**: 🔴 **Triggers**: Shell escaping changes, command execution logic
|
|
134
|
-
|
|
135
|
-
RTK must work on macOS (zsh), Linux (bash), Windows (PowerShell). Shell escaping differs.
|
|
136
|
-
|
|
137
|
-
### Platform-Specific Tests
|
|
138
|
-
|
|
139
|
-
```rust
|
|
140
|
-
#[cfg(target_os = "windows")]
|
|
141
|
-
const EXPECTED_SHELL: &str = "cmd.exe";
|
|
142
|
-
|
|
143
|
-
#[cfg(target_os = "macos")]
|
|
144
|
-
const EXPECTED_SHELL: &str = "zsh";
|
|
145
|
-
|
|
146
|
-
#[cfg(target_os = "linux")]
|
|
147
|
-
const EXPECTED_SHELL: &str = "bash";
|
|
148
|
-
|
|
149
|
-
#[test]
|
|
150
|
-
fn test_shell_escaping() {
|
|
151
|
-
let cmd = r#"git log --format="%H %s""#;
|
|
152
|
-
let escaped = escape_for_shell(cmd);
|
|
153
|
-
|
|
154
|
-
#[cfg(target_os = "windows")]
|
|
155
|
-
assert_eq!(escaped, r#"git log --format=\"%H %s\""#);
|
|
156
|
-
|
|
157
|
-
#[cfg(not(target_os = "windows"))]
|
|
158
|
-
assert_eq!(escaped, r#"git log --format="%H %s""#);
|
|
159
|
-
}
|
|
160
|
-
```
|
|
161
|
-
|
|
162
|
-
### Testing Platforms
|
|
163
|
-
|
|
164
|
-
**macOS (primary)**:
|
|
165
|
-
```bash
|
|
166
|
-
cargo test # Local testing
|
|
167
|
-
```
|
|
168
|
-
|
|
169
|
-
**Linux (via Docker)**:
|
|
170
|
-
```bash
|
|
171
|
-
docker run --rm -v $(pwd):/rtk -w /rtk rust:latest cargo test
|
|
172
|
-
```
|
|
173
|
-
|
|
174
|
-
**Windows (via CI)**:
|
|
175
|
-
Trust GitHub Actions CI/CD pipeline or test manually if Windows machine available.
|
|
176
|
-
|
|
177
|
-
### Shell Differences
|
|
178
|
-
|
|
179
|
-
| Platform | Shell | Quote Escape | Path Sep |
|
|
180
|
-
|----------|-------|--------------|----------|
|
|
181
|
-
| macOS | zsh | `'single'` or `"double"` | `/` |
|
|
182
|
-
| Linux | bash | `'single'` or `"double"` | `/` |
|
|
183
|
-
| Windows | PowerShell | `` `backtick `` or `"double"` | `\` |
|
|
184
|
-
|
|
185
|
-
## Integration Tests (🟡 Important)
|
|
186
|
-
|
|
187
|
-
**Priority**: 🟡 **Triggers**: New filter, command routing changes, release preparation
|
|
188
|
-
|
|
189
|
-
Integration tests execute real commands via RTK to verify end-to-end behavior.
|
|
190
|
-
|
|
191
|
-
### Real Command Execution
|
|
192
|
-
|
|
193
|
-
```rust
|
|
194
|
-
#[test]
|
|
195
|
-
#[ignore] // Run with: cargo test --ignored
|
|
196
|
-
fn test_real_git_log() {
|
|
197
|
-
// Requires:
|
|
198
|
-
// 1. RTK binary installed (cargo install --path .)
|
|
199
|
-
// 2. Git repository available
|
|
200
|
-
|
|
201
|
-
let output = std::process::Command::new("rtk")
|
|
202
|
-
.args(&["git", "log", "-10"])
|
|
203
|
-
.output()
|
|
204
|
-
.expect("Failed to run rtk");
|
|
205
|
-
|
|
206
|
-
assert!(output.status.success());
|
|
207
|
-
assert!(!output.stdout.is_empty());
|
|
208
|
-
|
|
209
|
-
// Verify condensed (not raw git output)
|
|
210
|
-
let stdout = String::from_utf8_lossy(&output.stdout);
|
|
211
|
-
assert!(stdout.len() < 5000, "Output too large, filter not working");
|
|
212
|
-
}
|
|
213
|
-
```
|
|
214
|
-
|
|
215
|
-
### Running Integration Tests
|
|
216
|
-
|
|
217
|
-
```bash
|
|
218
|
-
# 1. Install RTK locally
|
|
219
|
-
cargo install --path .
|
|
220
|
-
|
|
221
|
-
# 2. Run integration tests
|
|
222
|
-
cargo test --ignored
|
|
223
|
-
|
|
224
|
-
# 3. Run specific test
|
|
225
|
-
cargo test --ignored test_real_git_log
|
|
226
|
-
```
|
|
227
|
-
|
|
228
|
-
### When to Run
|
|
229
|
-
|
|
230
|
-
- **Before release**: Always run integration tests
|
|
231
|
-
- **After filter changes**: Verify filter works with real command
|
|
232
|
-
- **After hook changes**: Verify Claude Code integration works
|
|
233
|
-
|
|
234
|
-
## Performance Testing (🟡 Important)
|
|
235
|
-
|
|
236
|
-
**Priority**: 🟡 **Triggers**: Performance-related changes, release preparation
|
|
237
|
-
|
|
238
|
-
RTK targets <10ms startup time and <5MB memory usage.
|
|
239
|
-
|
|
240
|
-
### Benchmark Startup Time
|
|
241
|
-
|
|
242
|
-
```bash
|
|
243
|
-
# Install hyperfine
|
|
244
|
-
brew install hyperfine # macOS
|
|
245
|
-
cargo install hyperfine # or via cargo
|
|
246
|
-
|
|
247
|
-
# Benchmark RTK vs raw command
|
|
248
|
-
hyperfine 'rtk git status' 'git status' --warmup 3
|
|
249
|
-
|
|
250
|
-
# Should show RTK startup <10ms
|
|
251
|
-
# Example output:
|
|
252
|
-
# rtk git status 6.2 ms ± 0.3 ms
|
|
253
|
-
# git status 8.1 ms ± 0.4 ms
|
|
254
|
-
```
|
|
255
|
-
|
|
256
|
-
### Memory Usage
|
|
257
|
-
|
|
258
|
-
```bash
|
|
259
|
-
# macOS
|
|
260
|
-
/usr/bin/time -l rtk git status
|
|
261
|
-
# Look for "maximum resident set size" - should be <5MB
|
|
262
|
-
|
|
263
|
-
# Linux
|
|
264
|
-
/usr/bin/time -v rtk git status
|
|
265
|
-
# Look for "Maximum resident set size" - should be <5000 kbytes
|
|
266
|
-
```
|
|
267
|
-
|
|
268
|
-
### Regression Detection
|
|
269
|
-
|
|
270
|
-
**Before changes**:
|
|
271
|
-
```bash
|
|
272
|
-
hyperfine 'rtk git log -10' --warmup 3 > /tmp/before.txt
|
|
273
|
-
```
|
|
274
|
-
|
|
275
|
-
**After changes**:
|
|
276
|
-
```bash
|
|
277
|
-
cargo build --release
|
|
278
|
-
hyperfine 'target/release/rtk git log -10' --warmup 3 > /tmp/after.txt
|
|
279
|
-
```
|
|
280
|
-
|
|
281
|
-
**Compare**:
|
|
282
|
-
```bash
|
|
283
|
-
diff /tmp/before.txt /tmp/after.txt
|
|
284
|
-
# If startup time increased >2ms, investigate
|
|
285
|
-
```
|
|
286
|
-
|
|
287
|
-
### Performance Targets
|
|
288
|
-
|
|
289
|
-
| Metric | Target | Verification |
|
|
290
|
-
|--------|--------|--------------|
|
|
291
|
-
| Startup time | <10ms | `hyperfine 'rtk <cmd>'` |
|
|
292
|
-
| Memory usage | <5MB | `time -l rtk <cmd>` |
|
|
293
|
-
| Binary size | <5MB | `ls -lh target/release/rtk` |
|
|
294
|
-
|
|
295
|
-
## Test Organization
|
|
296
|
-
|
|
297
|
-
**Directory structure**:
|
|
298
|
-
|
|
299
|
-
```
|
|
300
|
-
rtk/
|
|
301
|
-
├── src/
|
|
302
|
-
│ ├── git.rs # Filter implementation
|
|
303
|
-
│ │ └── #[cfg(test)] mod tests { ... } # Unit tests
|
|
304
|
-
│ ├── snapshots/ # Insta snapshots
|
|
305
|
-
│ │ └── git.rs.snap # Snapshot for git tests
|
|
306
|
-
├── tests/
|
|
307
|
-
│ ├── common/
|
|
308
|
-
│ │ └── mod.rs # Shared test utilities (count_tokens)
|
|
309
|
-
│ ├── fixtures/ # Real command output
|
|
310
|
-
│ │ ├── git_log_raw.txt
|
|
311
|
-
│ │ ├── cargo_test_raw.txt
|
|
312
|
-
│ │ └── gh_pr_view_raw.txt
|
|
313
|
-
│ └── integration_test.rs # Integration tests (#[ignore])
|
|
314
|
-
```
|
|
315
|
-
|
|
316
|
-
**Best practices**:
|
|
317
|
-
- **Unit tests**: Embedded in module (`#[cfg(test)] mod tests`)
|
|
318
|
-
- **Fixtures**: Real command output in `tests/fixtures/`
|
|
319
|
-
- **Snapshots**: Auto-generated in `src/snapshots/` (by insta)
|
|
320
|
-
- **Shared utils**: `tests/common/mod.rs` (count_tokens, helpers)
|
|
321
|
-
- **Integration**: `tests/` with `#[ignore]` attribute
|
|
322
|
-
|
|
323
|
-
## Testing Checklist
|
|
324
|
-
|
|
325
|
-
When adding/modifying a filter:
|
|
326
|
-
|
|
327
|
-
### Implementation Phase
|
|
328
|
-
- [ ] Create fixture from real command output
|
|
329
|
-
- [ ] Add snapshot test with `assert_snapshot!()`
|
|
330
|
-
- [ ] Add token accuracy test (verify ≥60% savings)
|
|
331
|
-
- [ ] Test cross-platform shell escaping (if applicable)
|
|
332
|
-
|
|
333
|
-
### Quality Checks
|
|
334
|
-
- [ ] Run `cargo test --all` (all tests pass)
|
|
335
|
-
- [ ] Run `cargo insta review` (review snapshots)
|
|
336
|
-
- [ ] Run `cargo test --ignored` (integration tests pass)
|
|
337
|
-
- [ ] Benchmark startup time with `hyperfine` (<10ms)
|
|
338
|
-
|
|
339
|
-
### Before Merge
|
|
340
|
-
- [ ] All tests passing (`cargo test --all`)
|
|
341
|
-
- [ ] Snapshots reviewed and accepted (`cargo insta accept`)
|
|
342
|
-
- [ ] Token savings ≥60% verified
|
|
343
|
-
- [ ] Cross-platform tests passed (macOS + Linux)
|
|
344
|
-
- [ ] Performance benchmarks passed (<10ms startup)
|
|
345
|
-
|
|
346
|
-
### Before Release
|
|
347
|
-
- [ ] Integration tests passed (`cargo test --ignored`)
|
|
348
|
-
- [ ] Performance regression check (hyperfine comparison)
|
|
349
|
-
- [ ] Memory usage verified (<5MB with `time -l`)
|
|
350
|
-
- [ ] Cross-platform CI passed (macOS + Linux + Windows)
|
|
351
|
-
|
|
352
|
-
## Common Testing Patterns
|
|
353
|
-
|
|
354
|
-
### Pattern: Snapshot + Token Accuracy
|
|
355
|
-
|
|
356
|
-
**Use case**: Testing filter output format and savings
|
|
357
|
-
|
|
358
|
-
```rust
|
|
359
|
-
#[cfg(test)]
|
|
360
|
-
mod tests {
|
|
361
|
-
use super::*;
|
|
362
|
-
use insta::assert_snapshot;
|
|
363
|
-
|
|
364
|
-
fn count_tokens(text: &str) -> usize {
|
|
365
|
-
text.split_whitespace().count()
|
|
366
|
-
}
|
|
367
|
-
|
|
368
|
-
#[test]
|
|
369
|
-
fn test_output_format() {
|
|
370
|
-
let input = include_str!("../tests/fixtures/cmd_raw.txt");
|
|
371
|
-
let output = filter_cmd(input);
|
|
372
|
-
assert_snapshot!(output);
|
|
373
|
-
}
|
|
374
|
-
|
|
375
|
-
#[test]
|
|
376
|
-
fn test_token_savings() {
|
|
377
|
-
let input = include_str!("../tests/fixtures/cmd_raw.txt");
|
|
378
|
-
let output = filter_cmd(input);
|
|
379
|
-
|
|
380
|
-
let savings = 100.0 - (count_tokens(&output) as f64 / count_tokens(input) as f64 * 100.0);
|
|
381
|
-
assert!(savings >= 60.0, "Expected ≥60% savings, got {:.1}%", savings);
|
|
382
|
-
}
|
|
383
|
-
}
|
|
384
|
-
```
|
|
385
|
-
|
|
386
|
-
### Pattern: Edge Case Testing
|
|
387
|
-
|
|
388
|
-
**Use case**: Testing filter robustness
|
|
389
|
-
|
|
390
|
-
```rust
|
|
391
|
-
#[test]
|
|
392
|
-
fn test_empty_input() {
|
|
393
|
-
let output = filter_cmd("");
|
|
394
|
-
assert_eq!(output, "");
|
|
395
|
-
}
|
|
396
|
-
|
|
397
|
-
#[test]
|
|
398
|
-
fn test_malformed_input() {
|
|
399
|
-
let malformed = "not valid command output";
|
|
400
|
-
let output = filter_cmd(malformed);
|
|
401
|
-
// Should either:
|
|
402
|
-
// 1. Return best-effort filtered output, OR
|
|
403
|
-
// 2. Return original input unchanged (fallback)
|
|
404
|
-
// Both acceptable - just don't panic!
|
|
405
|
-
assert!(!output.is_empty());
|
|
406
|
-
}
|
|
407
|
-
|
|
408
|
-
#[test]
|
|
409
|
-
fn test_unicode_input() {
|
|
410
|
-
let unicode = "commit 日本語メッセージ";
|
|
411
|
-
let output = filter_cmd(unicode);
|
|
412
|
-
assert!(output.contains("commit"));
|
|
413
|
-
}
|
|
414
|
-
|
|
415
|
-
#[test]
|
|
416
|
-
fn test_ansi_codes() {
|
|
417
|
-
let ansi = "\x1b[32mSuccess\x1b[0m";
|
|
418
|
-
let output = filter_cmd(ansi);
|
|
419
|
-
// Should strip ANSI or preserve, but not break
|
|
420
|
-
assert!(output.contains("Success") || output.contains("\x1b[32m"));
|
|
421
|
-
}
|
|
422
|
-
```
|
|
423
|
-
|
|
424
|
-
### Pattern: Integration Test
|
|
425
|
-
|
|
426
|
-
**Use case**: Verify end-to-end behavior
|
|
427
|
-
|
|
428
|
-
```rust
|
|
429
|
-
#[test]
|
|
430
|
-
#[ignore]
|
|
431
|
-
fn test_real_command_execution() {
|
|
432
|
-
let output = std::process::Command::new("rtk")
|
|
433
|
-
.args(&["cmd", "args"])
|
|
434
|
-
.output()
|
|
435
|
-
.expect("Failed to run rtk");
|
|
436
|
-
|
|
437
|
-
assert!(output.status.success());
|
|
438
|
-
assert!(!output.stdout.is_empty());
|
|
439
|
-
|
|
440
|
-
let stdout = String::from_utf8_lossy(&output.stdout);
|
|
441
|
-
assert!(stdout.len() < 5000, "Output too large");
|
|
442
|
-
}
|
|
443
|
-
```
|
|
444
|
-
|
|
445
|
-
## Anti-Patterns
|
|
446
|
-
|
|
447
|
-
❌ **DON'T** test with hardcoded synthetic data
|
|
448
|
-
```rust
|
|
449
|
-
// ❌ WRONG
|
|
450
|
-
let input = "commit abc123\nAuthor: John";
|
|
451
|
-
let output = filter_git_log(input);
|
|
452
|
-
// Synthetic data doesn't reflect real command output
|
|
453
|
-
```
|
|
454
|
-
|
|
455
|
-
✅ **DO** use real command fixtures
|
|
456
|
-
```rust
|
|
457
|
-
// ✅ RIGHT
|
|
458
|
-
let input = include_str!("../tests/fixtures/git_log_raw.txt");
|
|
459
|
-
let output = filter_git_log(input);
|
|
460
|
-
// Real output from `git log -20`
|
|
461
|
-
```
|
|
462
|
-
|
|
463
|
-
❌ **DON'T** skip cross-platform tests
|
|
464
|
-
```rust
|
|
465
|
-
// ❌ WRONG - only tests current platform
|
|
466
|
-
#[test]
|
|
467
|
-
fn test_shell_escaping() {
|
|
468
|
-
let escaped = escape("test");
|
|
469
|
-
assert_eq!(escaped, "test");
|
|
470
|
-
}
|
|
471
|
-
```
|
|
472
|
-
|
|
473
|
-
✅ **DO** test all platforms with cfg
|
|
474
|
-
```rust
|
|
475
|
-
// ✅ RIGHT - tests all platforms
|
|
476
|
-
#[test]
|
|
477
|
-
fn test_shell_escaping() {
|
|
478
|
-
let escaped = escape("test");
|
|
479
|
-
|
|
480
|
-
#[cfg(target_os = "windows")]
|
|
481
|
-
assert_eq!(escaped, "\"test\"");
|
|
482
|
-
|
|
483
|
-
#[cfg(not(target_os = "windows"))]
|
|
484
|
-
assert_eq!(escaped, "test");
|
|
485
|
-
}
|
|
486
|
-
```
|
|
487
|
-
|
|
488
|
-
❌ **DON'T** ignore performance regressions
|
|
489
|
-
```rust
|
|
490
|
-
// ❌ WRONG - no performance tracking
|
|
491
|
-
#[test]
|
|
492
|
-
fn test_filter() {
|
|
493
|
-
let output = filter_cmd(input);
|
|
494
|
-
assert!(!output.is_empty());
|
|
495
|
-
}
|
|
496
|
-
```
|
|
497
|
-
|
|
498
|
-
✅ **DO** benchmark and track performance
|
|
499
|
-
```bash
|
|
500
|
-
# ✅ RIGHT - benchmark before/after
|
|
501
|
-
hyperfine 'rtk cmd' --warmup 3 > /tmp/before.txt
|
|
502
|
-
# Make changes
|
|
503
|
-
cargo build --release
|
|
504
|
-
hyperfine 'target/release/rtk cmd' --warmup 3 > /tmp/after.txt
|
|
505
|
-
diff /tmp/before.txt /tmp/after.txt
|
|
506
|
-
```
|
|
507
|
-
|
|
508
|
-
❌ **DON'T** accept <60% token savings
|
|
509
|
-
```rust
|
|
510
|
-
// ❌ WRONG - no savings verification
|
|
511
|
-
#[test]
|
|
512
|
-
fn test_filter() {
|
|
513
|
-
let output = filter_cmd(input);
|
|
514
|
-
assert!(!output.is_empty());
|
|
515
|
-
}
|
|
516
|
-
```
|
|
517
|
-
|
|
518
|
-
✅ **DO** verify savings claims
|
|
519
|
-
```rust
|
|
520
|
-
// ✅ RIGHT - verify ≥60% savings
|
|
521
|
-
#[test]
|
|
522
|
-
fn test_token_savings() {
|
|
523
|
-
let savings = calculate_savings(input, output);
|
|
524
|
-
assert!(savings >= 60.0, "Expected ≥60%, got {:.1}%", savings);
|
|
525
|
-
}
|
|
526
|
-
```
|