@tyvm/knowhow 0.0.36 → 0.0.37
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/package.json +1 -1
- package/src/agents/tools/aiClient.ts +36 -0
- package/src/agents/tools/lintFile.ts +1 -1
- package/src/agents/tools/list.ts +34 -0
- package/src/ai.ts +5 -4
- package/src/auth/browserLogin.ts +283 -0
- package/src/auth/errors.ts +6 -0
- package/src/auth/spinner.ts +23 -0
- package/src/chat/CliChatService.ts +25 -6
- package/src/chat/modules/AgentModule.ts +1 -2
- package/src/chat/modules/AskModule.ts +1 -2
- package/src/chat/types.ts +14 -4
- package/src/chat-old.ts +446 -0
- package/src/chat.ts +48 -433
- package/src/cli.ts +5 -12
- package/src/embeddings.ts +1 -1
- package/src/index.ts +0 -8
- package/src/login.ts +14 -1
- package/src/microphone.ts +0 -1
- package/src/plugins/downloader/downloader.ts +4 -2
- package/src/services/KnowhowClient.ts +3 -0
- package/src/services/index.ts +1 -2
- package/tests/manual/browser-login/README.md +189 -0
- package/tests/manual/browser-login/test_browser_login_basic.ts +115 -0
- package/tests/manual/browser-login/test_cli_integration.ts +169 -0
- package/tests/manual/browser-login/test_cross_platform_browser.ts +186 -0
- package/tests/manual/browser-login/test_error_scenarios.ts +223 -0
- package/tests/manual/cli/no-env.sh +256 -0
- package/ts_build/src/agents/tools/aiClient.d.ts +2 -0
- package/ts_build/src/agents/tools/aiClient.js +21 -1
- package/ts_build/src/agents/tools/aiClient.js.map +1 -1
- package/ts_build/src/agents/tools/lintFile.js +1 -1
- package/ts_build/src/agents/tools/lintFile.js.map +1 -1
- package/ts_build/src/agents/tools/list.js +32 -0
- package/ts_build/src/agents/tools/list.js.map +1 -1
- package/ts_build/src/ai.d.ts +1 -1
- package/ts_build/src/ai.js +2 -1
- package/ts_build/src/ai.js.map +1 -1
- package/ts_build/src/auth/browserLogin.d.ts +11 -0
- package/ts_build/src/auth/browserLogin.js +197 -0
- package/ts_build/src/auth/browserLogin.js.map +1 -0
- package/ts_build/src/auth/errors.d.ts +4 -0
- package/ts_build/src/auth/errors.js +13 -0
- package/ts_build/src/auth/errors.js.map +1 -0
- package/ts_build/src/auth/spinner.d.ts +7 -0
- package/ts_build/src/auth/spinner.js +23 -0
- package/ts_build/src/auth/spinner.js.map +1 -0
- package/ts_build/src/chat/CliChatService.d.ts +4 -3
- package/ts_build/src/chat/CliChatService.js +18 -4
- package/ts_build/src/chat/CliChatService.js.map +1 -1
- package/ts_build/src/chat/modules/AgentModule.d.ts +1 -1
- package/ts_build/src/chat/modules/AgentModule.js +1 -2
- package/ts_build/src/chat/modules/AgentModule.js.map +1 -1
- package/ts_build/src/chat/modules/AskModule.js +1 -2
- package/ts_build/src/chat/modules/AskModule.js.map +1 -1
- package/ts_build/src/chat/types.d.ts +5 -3
- package/ts_build/src/chat-old.d.ts +13 -0
- package/ts_build/src/chat-old.js +340 -0
- package/ts_build/src/chat-old.js.map +1 -0
- package/ts_build/src/chat.d.ts +3 -13
- package/ts_build/src/chat.js +38 -331
- package/ts_build/src/chat.js.map +1 -1
- package/ts_build/src/chat2.d.ts +1 -1
- package/ts_build/src/chat2.js +2 -2
- package/ts_build/src/chat2.js.map +1 -1
- package/ts_build/src/cli.js +3 -9
- package/ts_build/src/cli.js.map +1 -1
- package/ts_build/src/embeddings.js.map +1 -1
- package/ts_build/src/index.d.ts +0 -2
- package/ts_build/src/index.js +1 -9
- package/ts_build/src/index.js.map +1 -1
- package/ts_build/src/login.d.ts +1 -1
- package/ts_build/src/login.js +14 -0
- package/ts_build/src/login.js.map +1 -1
- package/ts_build/src/microphone.js.map +1 -1
- package/ts_build/src/plugins/downloader/downloader.d.ts +1 -3
- package/ts_build/src/plugins/downloader/downloader.js +4 -4
- package/ts_build/src/plugins/downloader/downloader.js.map +1 -1
- package/ts_build/src/services/KnowhowClient.js +3 -0
- package/ts_build/src/services/KnowhowClient.js.map +1 -1
- package/ts_build/src/services/index.js +1 -2
- package/ts_build/src/services/index.js.map +1 -1
- package/ts_build/tests/manual/browser-login/test_browser_login_basic.d.ts +2 -0
- package/ts_build/tests/manual/browser-login/test_browser_login_basic.js +108 -0
- package/ts_build/tests/manual/browser-login/test_browser_login_basic.js.map +1 -0
- package/ts_build/tests/manual/browser-login/test_cli_integration.d.ts +2 -0
- package/ts_build/tests/manual/browser-login/test_cli_integration.js +153 -0
- package/ts_build/tests/manual/browser-login/test_cli_integration.js.map +1 -0
- package/ts_build/tests/manual/browser-login/test_cross_platform_browser.d.ts +2 -0
- package/ts_build/tests/manual/browser-login/test_cross_platform_browser.js +159 -0
- package/ts_build/tests/manual/browser-login/test_cross_platform_browser.js.map +1 -0
- package/ts_build/tests/manual/browser-login/test_error_scenarios.d.ts +2 -0
- package/ts_build/tests/manual/browser-login/test_error_scenarios.js +197 -0
- package/ts_build/tests/manual/browser-login/test_error_scenarios.js.map +1 -0
- package/src/agents/vim/vim.ts +0 -152
- package/src/chat2.ts +0 -62
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
# Browser Login Manual Tests
|
|
2
|
+
|
|
3
|
+
This directory contains comprehensive manual tests for the browser-based login functionality in the Knowhow CLI.
|
|
4
|
+
|
|
5
|
+
## Test Overview
|
|
6
|
+
|
|
7
|
+
The browser login implementation includes the following key features:
|
|
8
|
+
- Browser-based authentication as the default login method
|
|
9
|
+
- Cross-platform browser opening (macOS, Windows, Linux)
|
|
10
|
+
- Polling mechanism with exponential backoff
|
|
11
|
+
- JWT token retrieval and secure storage
|
|
12
|
+
- Graceful error handling and user cancellation
|
|
13
|
+
- Backwards compatibility with `--jwt` flag
|
|
14
|
+
|
|
15
|
+
## Test Files
|
|
16
|
+
|
|
17
|
+
### 1. `test_browser_login_basic.ts`
|
|
18
|
+
**Purpose**: Tests the core browser login flow end-to-end
|
|
19
|
+
|
|
20
|
+
**What it tests**:
|
|
21
|
+
- Session creation with the API
|
|
22
|
+
- Browser opening for user authentication
|
|
23
|
+
- Authentication polling and completion
|
|
24
|
+
- JWT retrieval and secure storage
|
|
25
|
+
- File permissions (0o600)
|
|
26
|
+
- JWT format validation
|
|
27
|
+
|
|
28
|
+
**Prerequisites**:
|
|
29
|
+
- Valid `KNOWHOW_API_URL` environment variable
|
|
30
|
+
- Network connection to Knowhow API
|
|
31
|
+
- Default browser available
|
|
32
|
+
|
|
33
|
+
**Usage**:
|
|
34
|
+
```bash
|
|
35
|
+
npx tsx ./tests/manual/browser-login/test_browser_login_basic.ts
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
**Manual steps required**:
|
|
39
|
+
- Complete authentication in the opened browser window
|
|
40
|
+
- Verify browser opened to correct URL
|
|
41
|
+
|
|
42
|
+
### 2. `test_cli_integration.ts`
|
|
43
|
+
**Purpose**: Tests CLI command integration and backwards compatibility
|
|
44
|
+
|
|
45
|
+
**What it tests**:
|
|
46
|
+
- `knowhow login` uses browser login by default
|
|
47
|
+
- `knowhow login --jwt` prompts for manual JWT input
|
|
48
|
+
- Command help shows correct options
|
|
49
|
+
- JWT file creation through CLI
|
|
50
|
+
|
|
51
|
+
**Prerequisites**:
|
|
52
|
+
- Built CLI application (`npm run build`)
|
|
53
|
+
- Valid `KNOWHOW_API_URL` environment variable
|
|
54
|
+
|
|
55
|
+
**Usage**:
|
|
56
|
+
```bash
|
|
57
|
+
npx tsx ./tests/manual/browser-login/test_cli_integration.ts
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
**Manual steps required**:
|
|
61
|
+
- Complete browser authentication when prompted
|
|
62
|
+
- Verify help output is correct
|
|
63
|
+
|
|
64
|
+
### 3. `test_cross_platform_browser.ts`
|
|
65
|
+
**Purpose**: Tests browser opening across different operating systems
|
|
66
|
+
|
|
67
|
+
**What it tests**:
|
|
68
|
+
- Platform detection (macOS, Windows, Linux)
|
|
69
|
+
- Correct browser command selection (`open`, `start`, `xdg-open`)
|
|
70
|
+
- Browser command availability
|
|
71
|
+
- URL handling with special characters
|
|
72
|
+
- Graceful fallback when browser opening fails
|
|
73
|
+
|
|
74
|
+
**Prerequisites**:
|
|
75
|
+
- Default browser installed
|
|
76
|
+
- Platform-specific browser commands available
|
|
77
|
+
|
|
78
|
+
**Usage**:
|
|
79
|
+
```bash
|
|
80
|
+
npx tsx ./tests/manual/browser-login/test_cross_platform_browser.ts
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
**Manual steps required**:
|
|
84
|
+
- Verify browser opens to test URLs
|
|
85
|
+
- Confirm platform-specific behavior
|
|
86
|
+
|
|
87
|
+
### 4. `test_error_scenarios.ts`
|
|
88
|
+
**Purpose**: Tests error handling and edge cases
|
|
89
|
+
|
|
90
|
+
**What it tests**:
|
|
91
|
+
- Invalid API URL handling
|
|
92
|
+
- Missing API URL configuration
|
|
93
|
+
- JWT validation with various inputs
|
|
94
|
+
- File permission handling
|
|
95
|
+
- Error code propagation
|
|
96
|
+
- Graceful cancellation mechanisms
|
|
97
|
+
|
|
98
|
+
**Prerequisites**:
|
|
99
|
+
- Ability to modify environment variables temporarily
|
|
100
|
+
|
|
101
|
+
**Usage**:
|
|
102
|
+
```bash
|
|
103
|
+
npx tsx ./tests/manual/browser-login/test_error_scenarios.ts
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
**Manual steps required**:
|
|
107
|
+
- None (fully automated error scenario testing)
|
|
108
|
+
|
|
109
|
+
## Running All Tests
|
|
110
|
+
|
|
111
|
+
To run all tests in sequence:
|
|
112
|
+
|
|
113
|
+
```bash
|
|
114
|
+
# Run individual tests
|
|
115
|
+
npx tsx ./tests/manual/browser-login/test_error_scenarios.ts
|
|
116
|
+
npx tsx ./tests/manual/browser-login/test_cross_platform_browser.ts
|
|
117
|
+
npx tsx ./tests/manual/browser-login/test_cli_integration.ts
|
|
118
|
+
npx tsx ./tests/manual/browser-login/test_browser_login_basic.ts
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
## Test Results Interpretation
|
|
122
|
+
|
|
123
|
+
### ✅ PASSED
|
|
124
|
+
Test completed successfully with expected behavior.
|
|
125
|
+
|
|
126
|
+
### ⚠️ WARNING
|
|
127
|
+
Test completed but with minor issues or platform-specific concerns that don't prevent functionality.
|
|
128
|
+
|
|
129
|
+
### ❌ FAILED
|
|
130
|
+
Test failed due to errors or unexpected behavior that needs to be addressed.
|
|
131
|
+
|
|
132
|
+
### Manual Verification Required
|
|
133
|
+
Some tests require manual verification (e.g., confirming browser opened correctly) as they test user interaction flows.
|
|
134
|
+
|
|
135
|
+
## Common Issues and Troubleshooting
|
|
136
|
+
|
|
137
|
+
### Browser Not Opening
|
|
138
|
+
- **Symptoms**: Browser opening fails or command not found
|
|
139
|
+
- **Solutions**:
|
|
140
|
+
- Ensure default browser is installed
|
|
141
|
+
- Check platform-specific command availability (`open`, `start`, `xdg-open`)
|
|
142
|
+
- Verify display environment for Linux systems
|
|
143
|
+
|
|
144
|
+
### Network Errors
|
|
145
|
+
- **Symptoms**: API connection failures or timeouts
|
|
146
|
+
- **Solutions**:
|
|
147
|
+
- Verify `KNOWHOW_API_URL` is set correctly
|
|
148
|
+
- Check network connectivity
|
|
149
|
+
- Confirm API endpoints are accessible
|
|
150
|
+
|
|
151
|
+
### Permission Errors
|
|
152
|
+
- **Symptoms**: Cannot create or write JWT files
|
|
153
|
+
- **Solutions**:
|
|
154
|
+
- Check write permissions in project directory
|
|
155
|
+
- Verify `.knowhow` directory can be created
|
|
156
|
+
- Check for filesystem restrictions
|
|
157
|
+
|
|
158
|
+
### Authentication Timeout
|
|
159
|
+
- **Symptoms**: Polling times out before user completes authentication
|
|
160
|
+
- **Solutions**:
|
|
161
|
+
- Complete authentication more quickly
|
|
162
|
+
- Check if browser session is blocked by ad blockers
|
|
163
|
+
- Verify correct authentication URL
|
|
164
|
+
|
|
165
|
+
## Integration with CI/CD
|
|
166
|
+
|
|
167
|
+
These manual tests are designed for human verification and are not suitable for automated CI/CD pipelines. For automated testing, consider:
|
|
168
|
+
|
|
169
|
+
1. Mocking the browser opening functionality
|
|
170
|
+
2. Creating integration tests with test authentication endpoints
|
|
171
|
+
3. Unit testing individual components separately
|
|
172
|
+
|
|
173
|
+
## Security Considerations
|
|
174
|
+
|
|
175
|
+
When running these tests:
|
|
176
|
+
- JWT tokens are stored temporarily and cleaned up
|
|
177
|
+
- File permissions are tested to ensure secure storage (0o600)
|
|
178
|
+
- No sensitive data should be logged or persisted beyond test execution
|
|
179
|
+
- Tests clean up after themselves to avoid leaving test artifacts
|
|
180
|
+
|
|
181
|
+
## Contributing
|
|
182
|
+
|
|
183
|
+
When adding new tests:
|
|
184
|
+
1. Follow the existing test file naming pattern
|
|
185
|
+
2. Include comprehensive error handling
|
|
186
|
+
3. Provide clear manual steps in comments
|
|
187
|
+
4. Clean up any created files or state
|
|
188
|
+
5. Add appropriate timeout handling
|
|
189
|
+
6. Update this README with new test descriptions
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
#!/usr/bin/env npx tsx
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Manual Test: Basic Browser Login Flow
|
|
5
|
+
*
|
|
6
|
+
* This test validates the complete browser-based authentication flow:
|
|
7
|
+
* 1. Creates a login session with the API
|
|
8
|
+
* 2. Opens browser for user authentication
|
|
9
|
+
* 3. Polls for authentication completion
|
|
10
|
+
* 4. Retrieves and stores JWT token
|
|
11
|
+
*
|
|
12
|
+
* Prerequisites:
|
|
13
|
+
* - Valid KNOWHOW_API_URL environment variable
|
|
14
|
+
* - Network connection to Knowhow API
|
|
15
|
+
* - Browser available on the system
|
|
16
|
+
*
|
|
17
|
+
* Usage: npx tsx ./tests/manual/browser-login/test_browser_login_basic.ts
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
import { BrowserLoginService } from '../../../src/auth/browserLogin';
|
|
21
|
+
import * as fs from 'fs';
|
|
22
|
+
import * as path from 'path';
|
|
23
|
+
|
|
24
|
+
async function testBasicBrowserLogin(): Promise<void> {
|
|
25
|
+
console.log('\n=== Basic Browser Login Test ===\n');
|
|
26
|
+
|
|
27
|
+
let success = false;
|
|
28
|
+
const configDir = path.join(process.cwd(), '.knowhow');
|
|
29
|
+
const jwtFile = path.join(configDir, '.jwt');
|
|
30
|
+
|
|
31
|
+
// Clean up any existing JWT file
|
|
32
|
+
if (fs.existsSync(jwtFile)) {
|
|
33
|
+
fs.unlinkSync(jwtFile);
|
|
34
|
+
console.log('🧹 Cleaned up existing JWT file');
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
try {
|
|
38
|
+
console.log('1. Initializing BrowserLoginService...');
|
|
39
|
+
const browserLogin = new BrowserLoginService();
|
|
40
|
+
|
|
41
|
+
console.log('2. Starting browser login flow...');
|
|
42
|
+
console.log(' Note: This will open your browser and require manual authentication');
|
|
43
|
+
console.log(' Please complete the authentication process in your browser');
|
|
44
|
+
|
|
45
|
+
await browserLogin.login();
|
|
46
|
+
|
|
47
|
+
console.log('3. Verifying JWT file was created...');
|
|
48
|
+
if (fs.existsSync(jwtFile)) {
|
|
49
|
+
const jwtContent = fs.readFileSync(jwtFile, 'utf8');
|
|
50
|
+
|
|
51
|
+
// Check file permissions
|
|
52
|
+
const stats = fs.statSync(jwtFile);
|
|
53
|
+
const permissions = stats.mode & parseInt('777', 8);
|
|
54
|
+
|
|
55
|
+
console.log(` ✅ JWT file created: ${jwtFile}`);
|
|
56
|
+
console.log(` ✅ JWT length: ${jwtContent.length} characters`);
|
|
57
|
+
console.log(` ✅ File permissions: ${permissions.toString(8)} (should be 600)`);
|
|
58
|
+
|
|
59
|
+
// Basic JWT validation
|
|
60
|
+
const parts = jwtContent.split('.');
|
|
61
|
+
if (parts.length === 3) {
|
|
62
|
+
console.log(' ✅ JWT has correct structure (3 parts)');
|
|
63
|
+
success = true;
|
|
64
|
+
} else {
|
|
65
|
+
console.log(' ❌ JWT has incorrect structure');
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
if (permissions === parseInt('600', 8)) {
|
|
69
|
+
console.log(' ✅ JWT file has correct permissions (600)');
|
|
70
|
+
} else {
|
|
71
|
+
console.log(` ⚠️ JWT file permissions may be incorrect: ${permissions.toString(8)}`);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
} else {
|
|
75
|
+
console.log(' ❌ JWT file was not created');
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
} catch (error) {
|
|
79
|
+
console.error('❌ Test failed with error:', error.message);
|
|
80
|
+
|
|
81
|
+
if (error.code === 'USER_CANCELLED') {
|
|
82
|
+
console.log(' ℹ️ Authentication was cancelled by user (this is expected for Ctrl+C)');
|
|
83
|
+
} else if (error.code === 'TIMEOUT') {
|
|
84
|
+
console.log(' ⚠️ Authentication timed out (user may not have completed authentication)');
|
|
85
|
+
} else if (error.code === 'NETWORK_ERROR') {
|
|
86
|
+
console.log(' ❌ Network error - check API connectivity');
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
console.log('\n=== Test Results ===');
|
|
91
|
+
if (success) {
|
|
92
|
+
console.log('✅ Browser login test PASSED');
|
|
93
|
+
console.log(' - Session created successfully');
|
|
94
|
+
console.log(' - Browser opened for authentication');
|
|
95
|
+
console.log(' - JWT retrieved and stored securely');
|
|
96
|
+
process.exit(0);
|
|
97
|
+
} else {
|
|
98
|
+
console.log('❌ Browser login test FAILED');
|
|
99
|
+
console.log(' See error details above');
|
|
100
|
+
process.exit(1);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// Handle graceful shutdown
|
|
105
|
+
process.on('SIGINT', () => {
|
|
106
|
+
console.log('\n\n🛑 Test interrupted by user (Ctrl+C)');
|
|
107
|
+
console.log(' This tests the graceful cancellation feature');
|
|
108
|
+
process.exit(0);
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
// Run the test
|
|
112
|
+
testBasicBrowserLogin().catch((error) => {
|
|
113
|
+
console.error('Unhandled error:', error);
|
|
114
|
+
process.exit(1);
|
|
115
|
+
});
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
#!/usr/bin/env npx tsx
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Manual Test: CLI Integration Test
|
|
5
|
+
*
|
|
6
|
+
* This test validates the integration of browser login with the CLI command system:
|
|
7
|
+
* 1. Tests `knowhow login` (browser login as default)
|
|
8
|
+
* 2. Tests `knowhow login --jwt` (legacy JWT input)
|
|
9
|
+
* 3. Verifies backwards compatibility
|
|
10
|
+
* 4. Tests login status verification
|
|
11
|
+
*
|
|
12
|
+
* Prerequisites:
|
|
13
|
+
* - Built CLI application
|
|
14
|
+
* - Valid KNOWHOW_API_URL environment variable
|
|
15
|
+
* - Network connection to Knowhow API
|
|
16
|
+
*
|
|
17
|
+
* Usage: npx tsx ./tests/manual/browser-login/test_cli_integration.ts
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
import { exec } from 'child_process';
|
|
21
|
+
import { promisify } from 'util';
|
|
22
|
+
import * as fs from 'fs';
|
|
23
|
+
import * as path from 'path';
|
|
24
|
+
|
|
25
|
+
const execAsync = promisify(exec);
|
|
26
|
+
|
|
27
|
+
async function testCliIntegration(): Promise<void> {
|
|
28
|
+
console.log('\n=== CLI Integration Test ===\n');
|
|
29
|
+
|
|
30
|
+
const configDir = path.join(process.cwd(), '.knowhow');
|
|
31
|
+
const jwtFile = path.join(configDir, '.jwt');
|
|
32
|
+
let testResults: string[] = [];
|
|
33
|
+
|
|
34
|
+
try {
|
|
35
|
+
// Clean up any existing JWT file
|
|
36
|
+
if (fs.existsSync(jwtFile)) {
|
|
37
|
+
fs.unlinkSync(jwtFile);
|
|
38
|
+
console.log('🧹 Cleaned up existing JWT file\n');
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
console.log('=== Test 1: Browser Login as Default ===');
|
|
42
|
+
console.log('Testing: knowhow login (should use browser login)');
|
|
43
|
+
console.log('Note: This will open your browser - please complete authentication\n');
|
|
44
|
+
|
|
45
|
+
try {
|
|
46
|
+
// This should use browser login by default
|
|
47
|
+
const { stdout, stderr } = await execAsync('npm run build && node dist/cli.js login', {
|
|
48
|
+
timeout: 120000 // 2 minutes timeout
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
console.log('Command output:', stdout);
|
|
52
|
+
if (stderr) console.log('Command stderr:', stderr);
|
|
53
|
+
|
|
54
|
+
// Check if JWT file was created
|
|
55
|
+
if (fs.existsSync(jwtFile)) {
|
|
56
|
+
const jwtContent = fs.readFileSync(jwtFile, 'utf8');
|
|
57
|
+
if (jwtContent.split('.').length === 3) {
|
|
58
|
+
console.log('✅ Test 1 PASSED: Browser login created valid JWT');
|
|
59
|
+
testResults.push('✅ Browser login as default: PASSED');
|
|
60
|
+
} else {
|
|
61
|
+
console.log('❌ Test 1 FAILED: Invalid JWT created');
|
|
62
|
+
testResults.push('❌ Browser login as default: FAILED (invalid JWT)');
|
|
63
|
+
}
|
|
64
|
+
} else {
|
|
65
|
+
console.log('❌ Test 1 FAILED: No JWT file created');
|
|
66
|
+
testResults.push('❌ Browser login as default: FAILED (no JWT file)');
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
} catch (error) {
|
|
70
|
+
if (error.killed && error.signal === 'SIGTERM') {
|
|
71
|
+
console.log('⚠️ Test 1 TIMEOUT: User may not have completed authentication');
|
|
72
|
+
testResults.push('⚠️ Browser login as default: TIMEOUT');
|
|
73
|
+
} else {
|
|
74
|
+
console.log('❌ Test 1 ERROR:', error.message);
|
|
75
|
+
testResults.push('❌ Browser login as default: ERROR');
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// Clean up for next test
|
|
80
|
+
if (fs.existsSync(jwtFile)) {
|
|
81
|
+
fs.unlinkSync(jwtFile);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
console.log('\n=== Test 2: Legacy JWT Input ===');
|
|
85
|
+
console.log('Testing: knowhow login --jwt (should prompt for manual JWT input)');
|
|
86
|
+
|
|
87
|
+
// Create a mock interaction that immediately exits
|
|
88
|
+
try {
|
|
89
|
+
const { stdout, stderr } = await execAsync('echo "" | npm run build && echo "" | node dist/cli.js login --jwt', {
|
|
90
|
+
timeout: 10000
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
console.log('Command output:', stdout);
|
|
94
|
+
if (stderr) console.log('Command stderr:', stderr);
|
|
95
|
+
|
|
96
|
+
// The command should have prompted for JWT input
|
|
97
|
+
if (stdout.includes('JWT') || stdout.includes('token') || stderr.includes('JWT') || stderr.includes('token')) {
|
|
98
|
+
console.log('✅ Test 2 PASSED: --jwt flag triggers manual JWT input');
|
|
99
|
+
testResults.push('✅ Legacy JWT input: PASSED');
|
|
100
|
+
} else {
|
|
101
|
+
console.log('❌ Test 2 FAILED: --jwt flag not working correctly');
|
|
102
|
+
testResults.push('❌ Legacy JWT input: FAILED');
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
} catch (error) {
|
|
106
|
+
// This is expected since we're not providing valid JWT input
|
|
107
|
+
if (error.message.includes('JWT') || error.message.includes('token')) {
|
|
108
|
+
console.log('✅ Test 2 PASSED: --jwt flag triggered JWT input prompt');
|
|
109
|
+
testResults.push('✅ Legacy JWT input: PASSED');
|
|
110
|
+
} else {
|
|
111
|
+
console.log('❌ Test 2 FAILED:', error.message);
|
|
112
|
+
testResults.push('❌ Legacy JWT input: FAILED');
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
console.log('\n=== Test 3: Command Help ===');
|
|
117
|
+
console.log('Testing: knowhow login --help');
|
|
118
|
+
|
|
119
|
+
try {
|
|
120
|
+
const { stdout, stderr } = await execAsync('npm run build && node dist/cli.js login --help');
|
|
121
|
+
|
|
122
|
+
console.log('Help output:', stdout);
|
|
123
|
+
|
|
124
|
+
if (stdout.includes('--jwt') && stdout.includes('browser')) {
|
|
125
|
+
console.log('✅ Test 3 PASSED: Help shows both browser and JWT options');
|
|
126
|
+
testResults.push('✅ Command help: PASSED');
|
|
127
|
+
} else {
|
|
128
|
+
console.log('❌ Test 3 FAILED: Help missing expected options');
|
|
129
|
+
testResults.push('❌ Command help: FAILED');
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
} catch (error) {
|
|
133
|
+
console.log('❌ Test 3 ERROR:', error.message);
|
|
134
|
+
testResults.push('❌ Command help: ERROR');
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
} catch (error) {
|
|
138
|
+
console.error('❌ Test suite failed:', error.message);
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
// Print summary
|
|
142
|
+
console.log('\n=== Test Summary ===');
|
|
143
|
+
testResults.forEach(result => console.log(result));
|
|
144
|
+
|
|
145
|
+
const passedTests = testResults.filter(r => r.includes('PASSED')).length;
|
|
146
|
+
const totalTests = testResults.length;
|
|
147
|
+
|
|
148
|
+
console.log(`\nResults: ${passedTests}/${totalTests} tests passed`);
|
|
149
|
+
|
|
150
|
+
if (passedTests === totalTests) {
|
|
151
|
+
console.log('🎉 All CLI integration tests PASSED!');
|
|
152
|
+
process.exit(0);
|
|
153
|
+
} else {
|
|
154
|
+
console.log('❌ Some CLI integration tests FAILED');
|
|
155
|
+
process.exit(1);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
// Handle graceful shutdown
|
|
160
|
+
process.on('SIGINT', () => {
|
|
161
|
+
console.log('\n\n🛑 Test interrupted by user (Ctrl+C)');
|
|
162
|
+
process.exit(0);
|
|
163
|
+
});
|
|
164
|
+
|
|
165
|
+
// Run the test
|
|
166
|
+
testCliIntegration().catch((error) => {
|
|
167
|
+
console.error('Unhandled error:', error);
|
|
168
|
+
process.exit(1);
|
|
169
|
+
});
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
#!/usr/bin/env npx tsx
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Manual Test: Cross-Platform Browser Opening
|
|
5
|
+
*
|
|
6
|
+
* This test validates that the browser opening functionality works across different platforms:
|
|
7
|
+
* 1. Detects the current platform
|
|
8
|
+
* 2. Tests browser opening with a test URL
|
|
9
|
+
* 3. Validates the correct command is used for each platform
|
|
10
|
+
* 4. Tests fallback behavior when browser opening fails
|
|
11
|
+
*
|
|
12
|
+
* Prerequisites:
|
|
13
|
+
* - Default browser installed on the system
|
|
14
|
+
* - Network connection (for test URL)
|
|
15
|
+
*
|
|
16
|
+
* Usage: npx tsx ./tests/manual/browser-login/test_cross_platform_browser.ts
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
import { openBrowser } from '../../../src/auth/browserLogin';
|
|
20
|
+
import * as os from 'os';
|
|
21
|
+
import { exec } from 'child_process';
|
|
22
|
+
import { promisify } from 'util';
|
|
23
|
+
|
|
24
|
+
const execAsync = promisify(exec);
|
|
25
|
+
|
|
26
|
+
async function testCrossPlatformBrowser(): Promise<void> {
|
|
27
|
+
console.log('\n=== Cross-Platform Browser Opening Test ===\n');
|
|
28
|
+
|
|
29
|
+
const platform = os.platform();
|
|
30
|
+
console.log(`Detected platform: ${platform}`);
|
|
31
|
+
|
|
32
|
+
let testResults: string[] = [];
|
|
33
|
+
|
|
34
|
+
// Test 1: Platform Detection
|
|
35
|
+
console.log('\n=== Test 1: Platform Detection ===');
|
|
36
|
+
|
|
37
|
+
let expectedCommand: string;
|
|
38
|
+
switch (platform) {
|
|
39
|
+
case 'darwin':
|
|
40
|
+
expectedCommand = 'open';
|
|
41
|
+
console.log('✅ Platform: macOS - should use "open" command');
|
|
42
|
+
break;
|
|
43
|
+
case 'win32':
|
|
44
|
+
expectedCommand = 'start';
|
|
45
|
+
console.log('✅ Platform: Windows - should use "start" command');
|
|
46
|
+
break;
|
|
47
|
+
default:
|
|
48
|
+
expectedCommand = 'xdg-open';
|
|
49
|
+
console.log('✅ Platform: Linux/Unix - should use "xdg-open" command');
|
|
50
|
+
break;
|
|
51
|
+
}
|
|
52
|
+
testResults.push('✅ Platform detection: PASSED');
|
|
53
|
+
|
|
54
|
+
// Test 2: Command Availability
|
|
55
|
+
console.log('\n=== Test 2: Browser Command Availability ===');
|
|
56
|
+
|
|
57
|
+
try {
|
|
58
|
+
// Test if the expected command exists
|
|
59
|
+
await execAsync(`which ${expectedCommand} || where ${expectedCommand}`);
|
|
60
|
+
console.log(`✅ Browser command "${expectedCommand}" is available`);
|
|
61
|
+
testResults.push('✅ Browser command availability: PASSED');
|
|
62
|
+
} catch (error) {
|
|
63
|
+
console.log(`⚠️ Browser command "${expectedCommand}" may not be available`);
|
|
64
|
+
console.log(' This could cause browser opening to fail gracefully');
|
|
65
|
+
testResults.push('⚠️ Browser command availability: WARNING');
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// Test 3: Browser Opening with Test URL
|
|
69
|
+
console.log('\n=== Test 3: Browser Opening Test ===');
|
|
70
|
+
console.log('Testing browser opening with a test URL...');
|
|
71
|
+
console.log('Note: This should open https://example.com in your default browser');
|
|
72
|
+
|
|
73
|
+
const testUrl = 'https://example.com';
|
|
74
|
+
|
|
75
|
+
try {
|
|
76
|
+
await openBrowser(testUrl);
|
|
77
|
+
console.log('✅ Browser opening completed without errors');
|
|
78
|
+
|
|
79
|
+
// Give user time to confirm
|
|
80
|
+
console.log('\nDid your browser open to https://example.com? (This test requires manual verification)');
|
|
81
|
+
console.log('The test will continue in 10 seconds...');
|
|
82
|
+
|
|
83
|
+
await new Promise(resolve => setTimeout(resolve, 10000));
|
|
84
|
+
|
|
85
|
+
testResults.push('✅ Browser opening: PASSED (manual verification required)');
|
|
86
|
+
|
|
87
|
+
} catch (error) {
|
|
88
|
+
console.log(`⚠️ Browser opening failed gracefully: ${error.message}`);
|
|
89
|
+
console.log(' This is expected behavior - the application should continue working');
|
|
90
|
+
testResults.push('✅ Browser opening fallback: PASSED');
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// Test 4: Invalid URL Handling
|
|
94
|
+
console.log('\n=== Test 4: Invalid URL Handling ===');
|
|
95
|
+
|
|
96
|
+
try {
|
|
97
|
+
await openBrowser('not-a-valid-url');
|
|
98
|
+
console.log('✅ Invalid URL handled gracefully');
|
|
99
|
+
testResults.push('✅ Invalid URL handling: PASSED');
|
|
100
|
+
} catch (error) {
|
|
101
|
+
console.log(`⚠️ Invalid URL caused error: ${error.message}`);
|
|
102
|
+
console.log(' This is acceptable as long as it doesn\'t crash the application');
|
|
103
|
+
testResults.push('✅ Invalid URL handling: PASSED (graceful failure)');
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// Test 5: URL with Special Characters
|
|
107
|
+
console.log('\n=== Test 5: Special Characters in URL ===');
|
|
108
|
+
|
|
109
|
+
const specialUrl = 'https://example.com/path?param=value&other=test#fragment';
|
|
110
|
+
|
|
111
|
+
try {
|
|
112
|
+
await openBrowser(specialUrl);
|
|
113
|
+
console.log('✅ URL with special characters handled correctly');
|
|
114
|
+
testResults.push('✅ Special characters handling: PASSED');
|
|
115
|
+
} catch (error) {
|
|
116
|
+
console.log(`⚠️ Special characters in URL caused issues: ${error.message}`);
|
|
117
|
+
testResults.push('⚠️ Special characters handling: WARNING');
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
// Platform-specific tests
|
|
121
|
+
console.log('\n=== Test 6: Platform-Specific Command Testing ===');
|
|
122
|
+
|
|
123
|
+
try {
|
|
124
|
+
const testCommand = getTestCommand(platform);
|
|
125
|
+
if (testCommand) {
|
|
126
|
+
console.log(`Testing platform-specific command: ${testCommand}`);
|
|
127
|
+
await execAsync(testCommand);
|
|
128
|
+
console.log('✅ Platform-specific command executed successfully');
|
|
129
|
+
testResults.push('✅ Platform-specific command: PASSED');
|
|
130
|
+
} else {
|
|
131
|
+
console.log('⚠️ No platform-specific test available');
|
|
132
|
+
testResults.push('⚠️ Platform-specific command: SKIPPED');
|
|
133
|
+
}
|
|
134
|
+
} catch (error) {
|
|
135
|
+
console.log(`❌ Platform-specific command failed: ${error.message}`);
|
|
136
|
+
testResults.push('❌ Platform-specific command: FAILED');
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// Print summary
|
|
140
|
+
console.log('\n=== Test Summary ===');
|
|
141
|
+
testResults.forEach(result => console.log(result));
|
|
142
|
+
|
|
143
|
+
const passedTests = testResults.filter(r => r.includes('PASSED')).length;
|
|
144
|
+
const warningTests = testResults.filter(r => r.includes('WARNING')).length;
|
|
145
|
+
const failedTests = testResults.filter(r => r.includes('FAILED')).length;
|
|
146
|
+
const totalTests = testResults.length;
|
|
147
|
+
|
|
148
|
+
console.log(`\nResults: ${passedTests}/${totalTests} passed, ${warningTests} warnings, ${failedTests} failed`);
|
|
149
|
+
|
|
150
|
+
if (failedTests === 0) {
|
|
151
|
+
console.log('🎉 Cross-platform browser tests completed successfully!');
|
|
152
|
+
if (warningTests > 0) {
|
|
153
|
+
console.log(' Some warnings detected - check platform-specific behavior');
|
|
154
|
+
}
|
|
155
|
+
process.exit(0);
|
|
156
|
+
} else {
|
|
157
|
+
console.log('❌ Some cross-platform browser tests failed');
|
|
158
|
+
process.exit(1);
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
function getTestCommand(platform: string): string | null {
|
|
163
|
+
switch (platform) {
|
|
164
|
+
case 'darwin':
|
|
165
|
+
// Test opening a simple file/app that should exist
|
|
166
|
+
return 'open -a "System Preferences" || echo "Could not open System Preferences"';
|
|
167
|
+
case 'win32':
|
|
168
|
+
// Test opening notepad which should be available on all Windows systems
|
|
169
|
+
return 'start notepad && timeout 2 && taskkill /f /im notepad.exe 2>nul || echo "Notepad test completed"';
|
|
170
|
+
default:
|
|
171
|
+
// Test xdg-open with a simple command
|
|
172
|
+
return 'xdg-open --version || echo "xdg-open version check completed"';
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
// Handle graceful shutdown
|
|
177
|
+
process.on('SIGINT', () => {
|
|
178
|
+
console.log('\n\n🛑 Test interrupted by user (Ctrl+C)');
|
|
179
|
+
process.exit(0);
|
|
180
|
+
});
|
|
181
|
+
|
|
182
|
+
// Run the test
|
|
183
|
+
testCrossPlatformBrowser().catch((error) => {
|
|
184
|
+
console.error('Unhandled error:', error);
|
|
185
|
+
process.exit(1);
|
|
186
|
+
});
|