ssh-keyman 2.0.0 → 2.0.1
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/.github/TEST-REPORTING.md +335 -0
- package/.github/workflows/test-report.yml +24 -8
- package/package.json +36 -3
- package/readme.md +6 -7
- package/src/commands.js +1 -1
- package/src/extendFs.js +2 -9
- package/src/__tests__/testUtils.js +0 -113
|
@@ -0,0 +1,335 @@
|
|
|
1
|
+
# Test Reporting Configuration
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
This document explains how test reporting works in the ssh-keyman project.
|
|
6
|
+
|
|
7
|
+
## Test Report Formats
|
|
8
|
+
|
|
9
|
+
### 1. **Console Output** (Default)
|
|
10
|
+
```bash
|
|
11
|
+
npm test
|
|
12
|
+
```
|
|
13
|
+
Shows test results in terminal with coverage table.
|
|
14
|
+
|
|
15
|
+
### 2. **JUnit XML Report** (CI/CD)
|
|
16
|
+
```bash
|
|
17
|
+
npm run test:ci
|
|
18
|
+
```
|
|
19
|
+
Generates `coverage/junit.xml` for GitHub Actions integration.
|
|
20
|
+
|
|
21
|
+
### 3. **HTML Coverage Report**
|
|
22
|
+
```bash
|
|
23
|
+
npm test
|
|
24
|
+
open coverage/lcov-report/index.html
|
|
25
|
+
```
|
|
26
|
+
Visual coverage report in browser.
|
|
27
|
+
|
|
28
|
+
---
|
|
29
|
+
|
|
30
|
+
## GitHub Actions Integration
|
|
31
|
+
|
|
32
|
+
### Workflows Using Test Reports
|
|
33
|
+
|
|
34
|
+
#### 1. **CI Workflow** (`ci.yml`)
|
|
35
|
+
- Runs tests on every push/PR
|
|
36
|
+
- Uploads coverage to Codecov
|
|
37
|
+
- Validates across multiple platforms
|
|
38
|
+
|
|
39
|
+
#### 2. **Test Report Workflow** (`test-report.yml`)
|
|
40
|
+
- Generates detailed test reports
|
|
41
|
+
- Creates check runs with test results
|
|
42
|
+
- Comments on PRs with coverage details
|
|
43
|
+
- Uploads test artifacts
|
|
44
|
+
|
|
45
|
+
---
|
|
46
|
+
|
|
47
|
+
## JUnit Report Configuration
|
|
48
|
+
|
|
49
|
+
### Package: `jest-junit`
|
|
50
|
+
Installed as dev dependency to generate JUnit XML format.
|
|
51
|
+
|
|
52
|
+
### Jest Configuration
|
|
53
|
+
```json
|
|
54
|
+
{
|
|
55
|
+
"reporters": [
|
|
56
|
+
"default",
|
|
57
|
+
[
|
|
58
|
+
"jest-junit",
|
|
59
|
+
{
|
|
60
|
+
"outputDirectory": "coverage",
|
|
61
|
+
"outputName": "junit.xml",
|
|
62
|
+
"classNameTemplate": "{classname}",
|
|
63
|
+
"titleTemplate": "{title}",
|
|
64
|
+
"ancestorSeparator": " › ",
|
|
65
|
+
"usePathForSuiteName": "true"
|
|
66
|
+
}
|
|
67
|
+
]
|
|
68
|
+
]
|
|
69
|
+
}
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
### Generated File
|
|
73
|
+
- **Location**: `coverage/junit.xml`
|
|
74
|
+
- **Size**: ~5KB
|
|
75
|
+
- **Format**: Standard JUnit XML
|
|
76
|
+
- **Contents**: Test results, timings, failures
|
|
77
|
+
|
|
78
|
+
---
|
|
79
|
+
|
|
80
|
+
## Test Report Workflow Breakdown
|
|
81
|
+
|
|
82
|
+
### Triggers
|
|
83
|
+
- Push to `main`, `master`, or `develop`
|
|
84
|
+
- Pull requests to above branches
|
|
85
|
+
|
|
86
|
+
### Steps
|
|
87
|
+
|
|
88
|
+
#### 1. **Run Tests**
|
|
89
|
+
```yaml
|
|
90
|
+
- name: Run tests with coverage
|
|
91
|
+
run: npm run test:ci
|
|
92
|
+
continue-on-error: true
|
|
93
|
+
```
|
|
94
|
+
Runs tests and generates JUnit report.
|
|
95
|
+
|
|
96
|
+
#### 2. **Upload Artifacts**
|
|
97
|
+
```yaml
|
|
98
|
+
- name: Upload test results
|
|
99
|
+
uses: actions/upload-artifact@v4
|
|
100
|
+
with:
|
|
101
|
+
name: test-results
|
|
102
|
+
path: coverage/junit.xml
|
|
103
|
+
retention-days: 30
|
|
104
|
+
```
|
|
105
|
+
Stores test results for 30 days.
|
|
106
|
+
|
|
107
|
+
#### 3. **Generate Report**
|
|
108
|
+
```yaml
|
|
109
|
+
- name: Test Report
|
|
110
|
+
uses: dorny/test-reporter@v1
|
|
111
|
+
with:
|
|
112
|
+
name: Jest Tests
|
|
113
|
+
path: coverage/junit.xml
|
|
114
|
+
reporter: jest-junit
|
|
115
|
+
```
|
|
116
|
+
Creates GitHub check runs with test details.
|
|
117
|
+
|
|
118
|
+
#### 4. **PR Comments**
|
|
119
|
+
```yaml
|
|
120
|
+
- name: Comment PR with Coverage
|
|
121
|
+
if: github.event_name == 'pull_request'
|
|
122
|
+
uses: ArtiomTr/jest-coverage-report-action@v2
|
|
123
|
+
```
|
|
124
|
+
Adds coverage comment to pull requests.
|
|
125
|
+
|
|
126
|
+
---
|
|
127
|
+
|
|
128
|
+
## Viewing Test Reports
|
|
129
|
+
|
|
130
|
+
### In GitHub Actions
|
|
131
|
+
|
|
132
|
+
1. **Go to Actions tab**
|
|
133
|
+
2. **Select workflow run**
|
|
134
|
+
3. **View "Test Report" job**
|
|
135
|
+
4. **Check "Artifacts" section** for downloadable reports
|
|
136
|
+
|
|
137
|
+
### Check Runs
|
|
138
|
+
|
|
139
|
+
GitHub automatically creates check runs showing:
|
|
140
|
+
- ✅ Tests passed/failed
|
|
141
|
+
- 📊 Test count by suite
|
|
142
|
+
- ⏱️ Execution time
|
|
143
|
+
- 📋 Individual test results
|
|
144
|
+
|
|
145
|
+
### PR Comments
|
|
146
|
+
|
|
147
|
+
On pull requests, you'll see:
|
|
148
|
+
- Coverage percentage change
|
|
149
|
+
- Lines added/removed
|
|
150
|
+
- Coverage by file
|
|
151
|
+
- Detailed coverage report link
|
|
152
|
+
|
|
153
|
+
---
|
|
154
|
+
|
|
155
|
+
## Report Contents
|
|
156
|
+
|
|
157
|
+
### JUnit XML Structure
|
|
158
|
+
|
|
159
|
+
```xml
|
|
160
|
+
<testsuites name="jest tests" tests="35" failures="0">
|
|
161
|
+
<testsuite name="src/__tests__/cliOptions.test.js">
|
|
162
|
+
<testcase classname="cliOptions › prepareArgs"
|
|
163
|
+
name="should extract arguments"
|
|
164
|
+
time="0.007">
|
|
165
|
+
</testcase>
|
|
166
|
+
<!-- More test cases -->
|
|
167
|
+
</testsuite>
|
|
168
|
+
</testsuites>
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
### Report Includes
|
|
172
|
+
|
|
173
|
+
- ✅ Test suite names
|
|
174
|
+
- ✅ Individual test names
|
|
175
|
+
- ✅ Execution time per test
|
|
176
|
+
- ✅ Failure details (if any)
|
|
177
|
+
- ✅ Error messages
|
|
178
|
+
- ✅ Stack traces (on failure)
|
|
179
|
+
|
|
180
|
+
---
|
|
181
|
+
|
|
182
|
+
## Artifacts
|
|
183
|
+
|
|
184
|
+
### Test Results Artifact
|
|
185
|
+
- **Name**: `test-results`
|
|
186
|
+
- **Contents**: `junit.xml`
|
|
187
|
+
- **Retention**: 30 days
|
|
188
|
+
- **Use**: Download to view detailed test data
|
|
189
|
+
|
|
190
|
+
### Coverage Results Artifact
|
|
191
|
+
- **Name**: `coverage-results`
|
|
192
|
+
- **Contents**: Full coverage directory
|
|
193
|
+
- **Includes**:
|
|
194
|
+
- `coverage-final.json`
|
|
195
|
+
- `lcov.info`
|
|
196
|
+
- `junit.xml`
|
|
197
|
+
- HTML reports
|
|
198
|
+
- **Retention**: 30 days
|
|
199
|
+
|
|
200
|
+
---
|
|
201
|
+
|
|
202
|
+
## Troubleshooting
|
|
203
|
+
|
|
204
|
+
### "No test report files were found"
|
|
205
|
+
|
|
206
|
+
**Cause**: JUnit XML not generated
|
|
207
|
+
**Solution**:
|
|
208
|
+
- Ensure `jest-junit` is installed
|
|
209
|
+
- Check Jest reporter configuration
|
|
210
|
+
- Verify tests ran successfully
|
|
211
|
+
|
|
212
|
+
### "Reporter not found"
|
|
213
|
+
|
|
214
|
+
**Cause**: Incorrect reporter name
|
|
215
|
+
**Solution**: Use `jest-junit` (not `jest`)
|
|
216
|
+
|
|
217
|
+
### "Permission denied"
|
|
218
|
+
|
|
219
|
+
**Cause**: Missing workflow permissions
|
|
220
|
+
**Solution**: Add to workflow:
|
|
221
|
+
```yaml
|
|
222
|
+
permissions:
|
|
223
|
+
contents: read
|
|
224
|
+
checks: write
|
|
225
|
+
pull-requests: write
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
### Tests Pass but Report Fails
|
|
229
|
+
|
|
230
|
+
**Cause**: Report generation error
|
|
231
|
+
**Solution**:
|
|
232
|
+
- Check artifact upload logs
|
|
233
|
+
- Verify file path is correct
|
|
234
|
+
- Ensure XML is valid
|
|
235
|
+
|
|
236
|
+
---
|
|
237
|
+
|
|
238
|
+
## Best Practices
|
|
239
|
+
|
|
240
|
+
### ✅ Do
|
|
241
|
+
- Run tests before pushing
|
|
242
|
+
- Check test reports on PRs
|
|
243
|
+
- Review coverage changes
|
|
244
|
+
- Keep artifacts for debugging
|
|
245
|
+
- Use `continue-on-error` for report steps
|
|
246
|
+
|
|
247
|
+
### ❌ Don't
|
|
248
|
+
- Commit `junit.xml` to git
|
|
249
|
+
- Ignore test report failures
|
|
250
|
+
- Skip coverage checks
|
|
251
|
+
- Delete artifacts prematurely
|
|
252
|
+
|
|
253
|
+
---
|
|
254
|
+
|
|
255
|
+
## Local Testing
|
|
256
|
+
|
|
257
|
+
### Generate Report Locally
|
|
258
|
+
```bash
|
|
259
|
+
# Run tests with JUnit output
|
|
260
|
+
npm run test:ci
|
|
261
|
+
|
|
262
|
+
# View JUnit XML
|
|
263
|
+
cat coverage/junit.xml
|
|
264
|
+
|
|
265
|
+
# View HTML coverage
|
|
266
|
+
open coverage/lcov-report/index.html
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
### Validate XML
|
|
270
|
+
```bash
|
|
271
|
+
# Check if XML is well-formed
|
|
272
|
+
xmllint --noout coverage/junit.xml
|
|
273
|
+
|
|
274
|
+
# Pretty print
|
|
275
|
+
xmllint --format coverage/junit.xml
|
|
276
|
+
```
|
|
277
|
+
|
|
278
|
+
---
|
|
279
|
+
|
|
280
|
+
## CI/CD Flow Diagram
|
|
281
|
+
|
|
282
|
+
```
|
|
283
|
+
Push/PR → CI Workflow
|
|
284
|
+
├─ Install Dependencies
|
|
285
|
+
├─ Run Tests
|
|
286
|
+
├─ Generate Coverage
|
|
287
|
+
└─ Upload to Codecov
|
|
288
|
+
|
|
289
|
+
→ Test Report Workflow
|
|
290
|
+
├─ Run Tests
|
|
291
|
+
├─ Generate JUnit XML
|
|
292
|
+
├─ Upload Artifacts
|
|
293
|
+
├─ Create Check Run
|
|
294
|
+
└─ Comment on PR (if PR)
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
---
|
|
298
|
+
|
|
299
|
+
## Coverage Report Features
|
|
300
|
+
|
|
301
|
+
### In PR Comments
|
|
302
|
+
|
|
303
|
+
**Coverage Summary:**
|
|
304
|
+
```
|
|
305
|
+
Coverage: 75.59% (+1.2%)
|
|
306
|
+
Files: 5
|
|
307
|
+
Lines: 163/215 (+5)
|
|
308
|
+
```
|
|
309
|
+
|
|
310
|
+
**By File:**
|
|
311
|
+
```
|
|
312
|
+
commands.js 78.91% (+2.1%)
|
|
313
|
+
cliOptions.js 60.00% (no change)
|
|
314
|
+
```
|
|
315
|
+
|
|
316
|
+
**Annotations:**
|
|
317
|
+
- Uncovered lines highlighted
|
|
318
|
+
- Coverage decrease warnings
|
|
319
|
+
- New uncovered code markers
|
|
320
|
+
|
|
321
|
+
---
|
|
322
|
+
|
|
323
|
+
## References
|
|
324
|
+
|
|
325
|
+
- [jest-junit Documentation](https://github.com/jest-community/jest-junit)
|
|
326
|
+
- [dorny/test-reporter](https://github.com/dorny/test-reporter)
|
|
327
|
+
- [ArtiomTr/jest-coverage-report-action](https://github.com/ArtiomTr/jest-coverage-report-action)
|
|
328
|
+
- [JUnit XML Format](https://llg.cubic.org/docs/junit/)
|
|
329
|
+
|
|
330
|
+
---
|
|
331
|
+
|
|
332
|
+
**Status**: ✅ Fully Configured
|
|
333
|
+
**Last Updated**: 2026-01-15
|
|
334
|
+
**Maintained By**: ssh-keyman team
|
|
335
|
+
|
|
@@ -5,14 +5,15 @@ on:
|
|
|
5
5
|
branches: [ main, master, develop ]
|
|
6
6
|
pull_request:
|
|
7
7
|
branches: [ main, master, develop ]
|
|
8
|
-
schedule:
|
|
9
|
-
# Run tests daily at 2 AM UTC
|
|
10
|
-
- cron: '0 2 * * *'
|
|
11
8
|
|
|
12
9
|
jobs:
|
|
13
10
|
test-report:
|
|
14
11
|
name: Generate Test Report
|
|
15
12
|
runs-on: ubuntu-latest
|
|
13
|
+
permissions:
|
|
14
|
+
contents: read
|
|
15
|
+
checks: write
|
|
16
|
+
pull-requests: write
|
|
16
17
|
|
|
17
18
|
steps:
|
|
18
19
|
- name: Checkout code
|
|
@@ -29,22 +30,37 @@ jobs:
|
|
|
29
30
|
|
|
30
31
|
- name: Run tests with coverage
|
|
31
32
|
run: npm run test:ci
|
|
33
|
+
continue-on-error: true
|
|
32
34
|
|
|
33
|
-
- name:
|
|
35
|
+
- name: Upload test results
|
|
34
36
|
if: always()
|
|
37
|
+
uses: actions/upload-artifact@v4
|
|
38
|
+
with:
|
|
39
|
+
name: test-results
|
|
40
|
+
path: coverage/junit.xml
|
|
41
|
+
retention-days: 30
|
|
42
|
+
|
|
43
|
+
- name: Upload coverage results
|
|
44
|
+
if: always()
|
|
45
|
+
uses: actions/upload-artifact@v4
|
|
46
|
+
with:
|
|
47
|
+
name: coverage-results
|
|
48
|
+
path: coverage/
|
|
49
|
+
retention-days: 30
|
|
50
|
+
|
|
51
|
+
- name: Test Report
|
|
35
52
|
uses: dorny/test-reporter@v1
|
|
53
|
+
if: always()
|
|
36
54
|
with:
|
|
37
55
|
name: Jest Tests
|
|
38
56
|
path: coverage/junit.xml
|
|
39
57
|
reporter: jest-junit
|
|
40
58
|
fail-on-error: false
|
|
41
59
|
|
|
42
|
-
- name: Comment PR with
|
|
60
|
+
- name: Comment PR with Coverage
|
|
43
61
|
if: github.event_name == 'pull_request'
|
|
44
62
|
uses: ArtiomTr/jest-coverage-report-action@v2
|
|
45
63
|
with:
|
|
46
|
-
|
|
47
|
-
base-coverage-file: ./coverage/coverage-summary.json
|
|
48
|
-
annotations: failed-tests
|
|
64
|
+
annotations: coverage
|
|
49
65
|
package-manager: npm
|
|
50
66
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ssh-keyman",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.1",
|
|
4
4
|
"description": "A cli tool to manage multiple ssh keys and switch between different ssh keys with ease & grace.",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"bin": "index.js",
|
|
@@ -35,6 +35,10 @@
|
|
|
35
35
|
"url": "https://github.com/shahidullahkhankhattak/ssh-keyman/issues"
|
|
36
36
|
},
|
|
37
37
|
"homepage": "https://github.com/shahidullahkhankhattak/ssh-keyman#readme",
|
|
38
|
+
"engines": {
|
|
39
|
+
"node": ">=16.0.0",
|
|
40
|
+
"npm": ">=7.0.0"
|
|
41
|
+
},
|
|
38
42
|
"dependencies": {
|
|
39
43
|
"chalk": "^4.1.2",
|
|
40
44
|
"fs-extra": "^10.0.0",
|
|
@@ -43,6 +47,7 @@
|
|
|
43
47
|
},
|
|
44
48
|
"devDependencies": {
|
|
45
49
|
"jest": "^29.7.0",
|
|
50
|
+
"jest-junit": "^16.0.0",
|
|
46
51
|
"@types/jest": "^29.5.11"
|
|
47
52
|
},
|
|
48
53
|
"jest": {
|
|
@@ -51,13 +56,27 @@
|
|
|
51
56
|
"collectCoverageFrom": [
|
|
52
57
|
"src/**/*.js",
|
|
53
58
|
"!src/**/*.test.js",
|
|
59
|
+
"!src/**/*.spec.js",
|
|
54
60
|
"!src/__tests__/helpers.js",
|
|
55
|
-
"
|
|
61
|
+
"!src/__tests__/testUtils.js",
|
|
62
|
+
"!**/node_modules/**",
|
|
63
|
+
"!**/coverage/**"
|
|
56
64
|
],
|
|
57
65
|
"testMatch": [
|
|
58
66
|
"**/__tests__/**/*.test.js",
|
|
59
67
|
"**/?(*.)+(spec|test).js"
|
|
60
68
|
],
|
|
69
|
+
"testPathIgnorePatterns": [
|
|
70
|
+
"/node_modules/",
|
|
71
|
+
"helpers.js",
|
|
72
|
+
"testUtils.js"
|
|
73
|
+
],
|
|
74
|
+
"coveragePathIgnorePatterns": [
|
|
75
|
+
"/node_modules/",
|
|
76
|
+
"/coverage/",
|
|
77
|
+
"/__tests__/helpers.js",
|
|
78
|
+
"/__tests__/testUtils.js"
|
|
79
|
+
],
|
|
61
80
|
"coverageThreshold": {
|
|
62
81
|
"global": {
|
|
63
82
|
"branches": 50,
|
|
@@ -65,6 +84,20 @@
|
|
|
65
84
|
"lines": 55,
|
|
66
85
|
"statements": 55
|
|
67
86
|
}
|
|
68
|
-
}
|
|
87
|
+
},
|
|
88
|
+
"reporters": [
|
|
89
|
+
"default",
|
|
90
|
+
[
|
|
91
|
+
"jest-junit",
|
|
92
|
+
{
|
|
93
|
+
"outputDirectory": "coverage",
|
|
94
|
+
"outputName": "junit.xml",
|
|
95
|
+
"classNameTemplate": "{classname}",
|
|
96
|
+
"titleTemplate": "{title}",
|
|
97
|
+
"ancestorSeparator": " › ",
|
|
98
|
+
"usePathForSuiteName": "true"
|
|
99
|
+
}
|
|
100
|
+
]
|
|
101
|
+
]
|
|
69
102
|
}
|
|
70
103
|
}
|
package/readme.md
CHANGED
|
@@ -4,21 +4,20 @@ ssh-keyman
|
|
|
4
4
|
<!-- Build & Test Status -->
|
|
5
5
|
[](https://github.com/shahidullahkhankhattak/ssh-keyman/actions/workflows/ci.yml)
|
|
6
6
|
[](https://github.com/shahidullahkhankhattak/ssh-keyman/actions/workflows/ci.yml)
|
|
7
|
-
|
|
8
|
-
|
|
7
|
+

|
|
8
|
+

|
|
9
9
|
|
|
10
10
|
<!-- Package Info -->
|
|
11
11
|
[](https://www.npmjs.com/package/ssh-keyman)
|
|
12
12
|
[](https://www.npmjs.com/package/ssh-keyman)
|
|
13
|
-
|
|
13
|
+

|
|
14
14
|
|
|
15
15
|
<!-- Platform & Standards -->
|
|
16
|
-
[](https://nodejs.org/)
|
|
17
16
|
[](https://opensource.org/licenses/ISC)
|
|
18
17
|
[](https://github.com/shahidullahkhankhattak/ssh-keyman/graphs/commit-activity)
|
|
19
18
|
[](CONTRIBUTING.md)
|
|
20
19
|
|
|
21
|
-
<!-- Repository Stats -->
|
|
20
|
+
<!-- Repository Stats (activate after first push) -->
|
|
22
21
|
[](https://github.com/shahidullahkhankhattak/ssh-keyman/commits)
|
|
23
22
|
[](https://github.com/shahidullahkhankhattak/ssh-keyman/issues)
|
|
24
23
|
[](https://github.com/shahidullahkhankhattak/ssh-keyman/pulls)
|
|
@@ -31,8 +30,8 @@ A sophisticated key manager cli tool to manage multiple ssh keys and switch betw
|
|
|
31
30
|
| Workflow | Status |
|
|
32
31
|
|----------|--------|
|
|
33
32
|
| **Build & Test** | [](https://github.com/shahidullahkhankhattak/ssh-keyman/actions/workflows/ci.yml) |
|
|
34
|
-
| **
|
|
35
|
-
| **
|
|
33
|
+
| **Test Coverage** |  |
|
|
34
|
+
| **NPM Publish** |  |
|
|
36
35
|
|
|
37
36
|
> 📊 **[View Detailed Status Report →](STATUS.md)**
|
|
38
37
|
|
package/src/commands.js
CHANGED
|
@@ -282,7 +282,7 @@ const deleteEnv = async function (name) {
|
|
|
282
282
|
}
|
|
283
283
|
if (exist && available.find((env) => env === name)) {
|
|
284
284
|
available.splice(available.indexOf(name), 1);
|
|
285
|
-
fs.
|
|
285
|
+
fs.rmSync(path.join(KEYMAN_DIR_PATH, name), { recursive: true, force: true });
|
|
286
286
|
fs.writeFileSync(
|
|
287
287
|
KEYMAN_PATH,
|
|
288
288
|
JSON.stringify({ active, available: available })
|
package/src/extendFs.js
CHANGED
|
@@ -2,16 +2,9 @@ const fs = require("fs-extra");
|
|
|
2
2
|
const path = require("path");
|
|
3
3
|
|
|
4
4
|
const delDirSync = (pathName) => {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
return fs.rmdirSync(pathName);
|
|
5
|
+
if (fs.existsSync(pathName)) {
|
|
6
|
+
fs.rmSync(pathName, { recursive: true, force: true });
|
|
8
7
|
}
|
|
9
|
-
content.forEach((contentPath) => {
|
|
10
|
-
const isDir = fs.lstatSync(path.join(pathName, contentPath)).isDirectory();
|
|
11
|
-
if (isDir) delDirSync(path.join(pathName, contentPath));
|
|
12
|
-
else fs.rmSync(path.join(pathName, contentPath));
|
|
13
|
-
});
|
|
14
|
-
fs.rmdirSync(pathName);
|
|
15
8
|
};
|
|
16
9
|
|
|
17
10
|
const delAndCopySync = (fromPath, toPath) => {
|
|
@@ -1,113 +0,0 @@
|
|
|
1
|
-
const fs = require("fs-extra");
|
|
2
|
-
const path = require("path");
|
|
3
|
-
const os = require("os");
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* Create a mock file system structure for testing
|
|
7
|
-
*/
|
|
8
|
-
function createMockFileSystem(baseDir) {
|
|
9
|
-
const sshPath = path.join(baseDir, ".ssh");
|
|
10
|
-
const keymanPath = path.join(baseDir, ".sshkeyman");
|
|
11
|
-
const keymanFile = path.join(keymanPath, ".sshkeyman");
|
|
12
|
-
const defaultEnvPath = path.join(keymanPath, "default");
|
|
13
|
-
|
|
14
|
-
return {
|
|
15
|
-
sshPath,
|
|
16
|
-
keymanPath,
|
|
17
|
-
keymanFile,
|
|
18
|
-
defaultEnvPath,
|
|
19
|
-
setup: () => {
|
|
20
|
-
if (!fs.existsSync(baseDir)) {
|
|
21
|
-
fs.mkdirSync(baseDir, { recursive: true });
|
|
22
|
-
}
|
|
23
|
-
if (!fs.existsSync(sshPath)) {
|
|
24
|
-
fs.mkdirSync(sshPath, { recursive: true });
|
|
25
|
-
fs.writeFileSync(path.join(sshPath, "id_rsa"), "mock private key");
|
|
26
|
-
fs.writeFileSync(path.join(sshPath, "id_rsa.pub"), "mock public key");
|
|
27
|
-
}
|
|
28
|
-
},
|
|
29
|
-
cleanup: () => {
|
|
30
|
-
if (fs.existsSync(baseDir)) {
|
|
31
|
-
fs.rmSync(baseDir, { recursive: true, force: true });
|
|
32
|
-
}
|
|
33
|
-
},
|
|
34
|
-
initializeKeyman: () => {
|
|
35
|
-
if (!fs.existsSync(keymanPath)) {
|
|
36
|
-
fs.mkdirSync(keymanPath, { recursive: true });
|
|
37
|
-
}
|
|
38
|
-
if (!fs.existsSync(defaultEnvPath)) {
|
|
39
|
-
fs.mkdirSync(defaultEnvPath, { recursive: true });
|
|
40
|
-
fs.copySync(sshPath, defaultEnvPath);
|
|
41
|
-
}
|
|
42
|
-
fs.writeFileSync(
|
|
43
|
-
keymanFile,
|
|
44
|
-
JSON.stringify({ active: "default", available: ["default"] })
|
|
45
|
-
);
|
|
46
|
-
},
|
|
47
|
-
};
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
/**
|
|
51
|
-
* Mock console methods
|
|
52
|
-
*/
|
|
53
|
-
function mockConsole() {
|
|
54
|
-
const originalLog = console.log;
|
|
55
|
-
const originalError = console.error;
|
|
56
|
-
const logs = [];
|
|
57
|
-
const errors = [];
|
|
58
|
-
|
|
59
|
-
console.log = (...args) => {
|
|
60
|
-
logs.push(args.join(" "));
|
|
61
|
-
};
|
|
62
|
-
console.error = (...args) => {
|
|
63
|
-
errors.push(args.join(" "));
|
|
64
|
-
};
|
|
65
|
-
|
|
66
|
-
return {
|
|
67
|
-
logs,
|
|
68
|
-
errors,
|
|
69
|
-
restore: () => {
|
|
70
|
-
console.log = originalLog;
|
|
71
|
-
console.error = originalError;
|
|
72
|
-
},
|
|
73
|
-
getLogs: () => logs,
|
|
74
|
-
getErrors: () => errors,
|
|
75
|
-
clear: () => {
|
|
76
|
-
logs.length = 0;
|
|
77
|
-
errors.length = 0;
|
|
78
|
-
},
|
|
79
|
-
};
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
/**
|
|
83
|
-
* Mock inquirer prompts
|
|
84
|
-
*/
|
|
85
|
-
function mockInquirer(answers = {}) {
|
|
86
|
-
const inquirer = require("inquirer");
|
|
87
|
-
const originalPrompt = inquirer.prompt;
|
|
88
|
-
|
|
89
|
-
inquirer.prompt = jest.fn((questions) => {
|
|
90
|
-
const responses = {};
|
|
91
|
-
questions.forEach((q) => {
|
|
92
|
-
if (answers[q.name] !== undefined) {
|
|
93
|
-
responses[q.name] = answers[q.name];
|
|
94
|
-
} else if (q.default !== undefined) {
|
|
95
|
-
responses[q.name] = q.default;
|
|
96
|
-
}
|
|
97
|
-
});
|
|
98
|
-
return Promise.resolve(responses);
|
|
99
|
-
});
|
|
100
|
-
|
|
101
|
-
return {
|
|
102
|
-
restore: () => {
|
|
103
|
-
inquirer.prompt = originalPrompt;
|
|
104
|
-
},
|
|
105
|
-
};
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
module.exports = {
|
|
109
|
-
createMockFileSystem,
|
|
110
|
-
mockConsole,
|
|
111
|
-
mockInquirer,
|
|
112
|
-
};
|
|
113
|
-
|