@git.zone/tstest 1.1.0 → 1.2.0
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_ts/00_commitinfo_data.js +1 -1
- package/dist_ts/index.js +43 -4
- package/dist_ts/tstest.classes.tap.combinator.d.ts +3 -0
- package/dist_ts/tstest.classes.tap.combinator.js +14 -40
- package/dist_ts/tstest.classes.tap.parser.d.ts +3 -1
- package/dist_ts/tstest.classes.tap.parser.js +42 -18
- package/dist_ts/tstest.classes.tstest.d.ts +6 -3
- package/dist_ts/tstest.classes.tstest.js +32 -33
- package/dist_ts/tstest.logging.d.ts +48 -0
- package/dist_ts/tstest.logging.js +228 -0
- package/package.json +1 -1
- package/readme.plan.md +196 -48
- package/ts/00_commitinfo_data.ts +1 -1
- package/ts/index.ts +46 -3
- package/ts/tstest.classes.tap.combinator.ts +19 -41
- package/ts/tstest.classes.tap.parser.ts +44 -47
- package/ts/tstest.classes.tstest.ts +38 -35
- package/ts/tstest.logging.ts +285 -0
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
import { coloredString as cs } from '@push.rocks/consolecolor';
|
|
2
|
+
import * as plugins from './tstest.plugins.js';
|
|
3
|
+
export class TsTestLogger {
|
|
4
|
+
constructor(options = {}) {
|
|
5
|
+
this.fileResults = [];
|
|
6
|
+
this.currentFileResult = null;
|
|
7
|
+
this.options = options;
|
|
8
|
+
this.startTime = Date.now();
|
|
9
|
+
}
|
|
10
|
+
format(text, color) {
|
|
11
|
+
if (this.options.noColor || !color) {
|
|
12
|
+
return text;
|
|
13
|
+
}
|
|
14
|
+
return cs(text, color);
|
|
15
|
+
}
|
|
16
|
+
log(message) {
|
|
17
|
+
if (this.options.json)
|
|
18
|
+
return;
|
|
19
|
+
console.log(message);
|
|
20
|
+
if (this.options.logFile) {
|
|
21
|
+
// TODO: Implement file logging
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
// Section separators
|
|
25
|
+
sectionStart(title) {
|
|
26
|
+
if (this.options.quiet || this.options.json)
|
|
27
|
+
return;
|
|
28
|
+
this.log(this.format(`\n━━━ ${title} ━━━`, 'cyan'));
|
|
29
|
+
}
|
|
30
|
+
sectionEnd() {
|
|
31
|
+
if (this.options.quiet || this.options.json)
|
|
32
|
+
return;
|
|
33
|
+
this.log(this.format('─'.repeat(50), 'dim'));
|
|
34
|
+
}
|
|
35
|
+
// Progress indication
|
|
36
|
+
progress(current, total, message) {
|
|
37
|
+
if (this.options.quiet || this.options.json)
|
|
38
|
+
return;
|
|
39
|
+
const percentage = Math.round((current / total) * 100);
|
|
40
|
+
const filled = Math.round((current / total) * 20);
|
|
41
|
+
const empty = 20 - filled;
|
|
42
|
+
this.log(this.format(`\n📊 Progress: ${current}/${total} (${percentage}%)`, 'cyan'));
|
|
43
|
+
this.log(this.format(`[${'█'.repeat(filled)}${'░'.repeat(empty)}] ${message}`, 'dim'));
|
|
44
|
+
}
|
|
45
|
+
// Test discovery
|
|
46
|
+
testDiscovery(count, pattern, executionMode) {
|
|
47
|
+
if (this.options.json) {
|
|
48
|
+
console.log(JSON.stringify({ event: 'discovery', count, pattern, executionMode }));
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
if (this.options.quiet) {
|
|
52
|
+
this.log(`Found ${count} tests`);
|
|
53
|
+
}
|
|
54
|
+
else {
|
|
55
|
+
this.log(this.format(`\n🔍 Test Discovery`, 'bold'));
|
|
56
|
+
this.log(this.format(` Mode: ${executionMode}`, 'dim'));
|
|
57
|
+
this.log(this.format(` Pattern: ${pattern}`, 'dim'));
|
|
58
|
+
this.log(this.format(` Found: ${count} test file(s)`, 'green'));
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
// Test execution
|
|
62
|
+
testFileStart(filename, runtime, index, total) {
|
|
63
|
+
this.currentFileResult = {
|
|
64
|
+
file: filename,
|
|
65
|
+
passed: 0,
|
|
66
|
+
failed: 0,
|
|
67
|
+
total: 0,
|
|
68
|
+
duration: 0,
|
|
69
|
+
tests: []
|
|
70
|
+
};
|
|
71
|
+
if (this.options.json) {
|
|
72
|
+
console.log(JSON.stringify({ event: 'fileStart', filename, runtime, index, total }));
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
if (this.options.quiet)
|
|
76
|
+
return;
|
|
77
|
+
this.log(this.format(`\n▶️ ${filename} (${index}/${total})`, 'blue'));
|
|
78
|
+
this.log(this.format(` Runtime: ${runtime}`, 'dim'));
|
|
79
|
+
}
|
|
80
|
+
testResult(testName, passed, duration, error) {
|
|
81
|
+
if (this.currentFileResult) {
|
|
82
|
+
this.currentFileResult.tests.push({ name: testName, passed, duration, error });
|
|
83
|
+
this.currentFileResult.total++;
|
|
84
|
+
if (passed) {
|
|
85
|
+
this.currentFileResult.passed++;
|
|
86
|
+
}
|
|
87
|
+
else {
|
|
88
|
+
this.currentFileResult.failed++;
|
|
89
|
+
}
|
|
90
|
+
this.currentFileResult.duration += duration;
|
|
91
|
+
}
|
|
92
|
+
if (this.options.json) {
|
|
93
|
+
console.log(JSON.stringify({ event: 'testResult', testName, passed, duration, error }));
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
const icon = passed ? '✅' : '❌';
|
|
97
|
+
const color = passed ? 'green' : 'red';
|
|
98
|
+
if (this.options.quiet) {
|
|
99
|
+
this.log(`${icon} ${testName}`);
|
|
100
|
+
}
|
|
101
|
+
else {
|
|
102
|
+
this.log(this.format(` ${icon} ${testName} (${duration}ms)`, color));
|
|
103
|
+
if (error && !passed) {
|
|
104
|
+
this.log(this.format(` ${error}`, 'red'));
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
testFileEnd(passed, failed, duration) {
|
|
109
|
+
if (this.currentFileResult) {
|
|
110
|
+
this.fileResults.push(this.currentFileResult);
|
|
111
|
+
this.currentFileResult = null;
|
|
112
|
+
}
|
|
113
|
+
if (this.options.json) {
|
|
114
|
+
console.log(JSON.stringify({ event: 'fileEnd', passed, failed, duration }));
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
117
|
+
if (!this.options.quiet) {
|
|
118
|
+
const total = passed + failed;
|
|
119
|
+
const status = failed === 0 ? 'PASSED' : 'FAILED';
|
|
120
|
+
const color = failed === 0 ? 'green' : 'red';
|
|
121
|
+
this.log(this.format(` Summary: ${passed}/${total} ${status}`, color));
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
// TAP output forwarding
|
|
125
|
+
tapOutput(message, isError = false) {
|
|
126
|
+
if (this.options.json)
|
|
127
|
+
return;
|
|
128
|
+
if (this.options.verbose || isError) {
|
|
129
|
+
const prefix = isError ? ' ⚠️ ' : ' ';
|
|
130
|
+
const color = isError ? 'red' : 'dim';
|
|
131
|
+
this.log(this.format(`${prefix}${message}`, color));
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
// Browser console
|
|
135
|
+
browserConsole(message, level = 'log') {
|
|
136
|
+
if (this.options.json) {
|
|
137
|
+
console.log(JSON.stringify({ event: 'browserConsole', message, level }));
|
|
138
|
+
return;
|
|
139
|
+
}
|
|
140
|
+
if (!this.options.quiet) {
|
|
141
|
+
const prefix = level === 'error' ? '🌐❌' : '🌐';
|
|
142
|
+
const color = level === 'error' ? 'red' : 'magenta';
|
|
143
|
+
this.log(this.format(` ${prefix} ${message}`, color));
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
// Final summary
|
|
147
|
+
summary() {
|
|
148
|
+
const totalDuration = Date.now() - this.startTime;
|
|
149
|
+
const summary = {
|
|
150
|
+
totalFiles: this.fileResults.length,
|
|
151
|
+
totalTests: this.fileResults.reduce((sum, r) => sum + r.total, 0),
|
|
152
|
+
totalPassed: this.fileResults.reduce((sum, r) => sum + r.passed, 0),
|
|
153
|
+
totalFailed: this.fileResults.reduce((sum, r) => sum + r.failed, 0),
|
|
154
|
+
totalDuration,
|
|
155
|
+
fileResults: this.fileResults
|
|
156
|
+
};
|
|
157
|
+
if (this.options.json) {
|
|
158
|
+
console.log(JSON.stringify({ event: 'summary', summary }));
|
|
159
|
+
return;
|
|
160
|
+
}
|
|
161
|
+
if (this.options.quiet) {
|
|
162
|
+
const status = summary.totalFailed === 0 ? 'PASSED' : 'FAILED';
|
|
163
|
+
this.log(`\nSummary: ${summary.totalPassed}/${summary.totalTests} | ${totalDuration}ms | ${status}`);
|
|
164
|
+
return;
|
|
165
|
+
}
|
|
166
|
+
// Detailed summary
|
|
167
|
+
this.log(this.format('\n📊 Test Summary', 'bold'));
|
|
168
|
+
this.log(this.format('┌────────────────────────────────┐', 'dim'));
|
|
169
|
+
this.log(this.format(`│ Total Files: ${summary.totalFiles.toString().padStart(14)} │`, 'white'));
|
|
170
|
+
this.log(this.format(`│ Total Tests: ${summary.totalTests.toString().padStart(14)} │`, 'white'));
|
|
171
|
+
this.log(this.format(`│ Passed: ${summary.totalPassed.toString().padStart(14)} │`, 'green'));
|
|
172
|
+
this.log(this.format(`│ Failed: ${summary.totalFailed.toString().padStart(14)} │`, summary.totalFailed > 0 ? 'red' : 'green'));
|
|
173
|
+
this.log(this.format(`│ Duration: ${totalDuration.toString().padStart(14)}ms │`, 'white'));
|
|
174
|
+
this.log(this.format('└────────────────────────────────┘', 'dim'));
|
|
175
|
+
// File results
|
|
176
|
+
if (summary.totalFailed > 0) {
|
|
177
|
+
this.log(this.format('\n❌ Failed Tests:', 'red'));
|
|
178
|
+
this.fileResults.forEach(fileResult => {
|
|
179
|
+
if (fileResult.failed > 0) {
|
|
180
|
+
this.log(this.format(`\n ${fileResult.file}`, 'yellow'));
|
|
181
|
+
fileResult.tests.filter(t => !t.passed).forEach(test => {
|
|
182
|
+
this.log(this.format(` ❌ ${test.name}`, 'red'));
|
|
183
|
+
if (test.error) {
|
|
184
|
+
this.log(this.format(` ${test.error}`, 'dim'));
|
|
185
|
+
}
|
|
186
|
+
});
|
|
187
|
+
}
|
|
188
|
+
});
|
|
189
|
+
}
|
|
190
|
+
// Performance metrics
|
|
191
|
+
if (this.options.verbose) {
|
|
192
|
+
const avgDuration = Math.round(totalDuration / summary.totalTests);
|
|
193
|
+
const slowestTest = this.fileResults
|
|
194
|
+
.flatMap(r => r.tests)
|
|
195
|
+
.sort((a, b) => b.duration - a.duration)[0];
|
|
196
|
+
this.log(this.format('\n⏱️ Performance Metrics:', 'cyan'));
|
|
197
|
+
this.log(this.format(` Average per test: ${avgDuration}ms`, 'white'));
|
|
198
|
+
if (slowestTest) {
|
|
199
|
+
this.log(this.format(` Slowest test: ${slowestTest.name} (${slowestTest.duration}ms)`, 'yellow'));
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
// Final status
|
|
203
|
+
const status = summary.totalFailed === 0 ? 'ALL TESTS PASSED! 🎉' : 'SOME TESTS FAILED! ❌';
|
|
204
|
+
const statusColor = summary.totalFailed === 0 ? 'green' : 'red';
|
|
205
|
+
this.log(this.format(`\n${status}`, statusColor));
|
|
206
|
+
}
|
|
207
|
+
// Error display
|
|
208
|
+
error(message, file, stack) {
|
|
209
|
+
if (this.options.json) {
|
|
210
|
+
console.log(JSON.stringify({ event: 'error', message, file, stack }));
|
|
211
|
+
return;
|
|
212
|
+
}
|
|
213
|
+
if (this.options.quiet) {
|
|
214
|
+
console.error(`ERROR: ${message}`);
|
|
215
|
+
}
|
|
216
|
+
else {
|
|
217
|
+
this.log(this.format('\n⚠️ Error', 'red'));
|
|
218
|
+
if (file)
|
|
219
|
+
this.log(this.format(` File: ${file}`, 'yellow'));
|
|
220
|
+
this.log(this.format(` ${message}`, 'red'));
|
|
221
|
+
if (stack && this.options.verbose) {
|
|
222
|
+
this.log(this.format(` Stack:`, 'dim'));
|
|
223
|
+
this.log(this.format(stack.split('\n').map(line => ` ${line}`).join('\n'), 'dim'));
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHN0ZXN0LmxvZ2dpbmcuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi90cy90c3Rlc3QubG9nZ2luZy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsYUFBYSxJQUFJLEVBQUUsRUFBRSxNQUFNLDBCQUEwQixDQUFDO0FBQy9ELE9BQU8sS0FBSyxPQUFPLE1BQU0scUJBQXFCLENBQUM7QUFpQy9DLE1BQU0sT0FBTyxZQUFZO0lBTXZCLFlBQVksVUFBc0IsRUFBRTtRQUg1QixnQkFBVyxHQUFxQixFQUFFLENBQUM7UUFDbkMsc0JBQWlCLEdBQTBCLElBQUksQ0FBQztRQUd0RCxJQUFJLENBQUMsT0FBTyxHQUFHLE9BQU8sQ0FBQztRQUN2QixJQUFJLENBQUMsU0FBUyxHQUFHLElBQUksQ0FBQyxHQUFHLEVBQUUsQ0FBQztJQUM5QixDQUFDO0lBRU8sTUFBTSxDQUFDLElBQVksRUFBRSxLQUFjO1FBQ3pDLElBQUksSUFBSSxDQUFDLE9BQU8sQ0FBQyxPQUFPLElBQUksQ0FBQyxLQUFLLEVBQUUsQ0FBQztZQUNuQyxPQUFPLElBQUksQ0FBQztRQUNkLENBQUM7UUFDRCxPQUFPLEVBQUUsQ0FBQyxJQUFJLEVBQUUsS0FBWSxDQUFDLENBQUM7SUFDaEMsQ0FBQztJQUVPLEdBQUcsQ0FBQyxPQUFlO1FBQ3pCLElBQUksSUFBSSxDQUFDLE9BQU8sQ0FBQyxJQUFJO1lBQUUsT0FBTztRQUM5QixPQUFPLENBQUMsR0FBRyxDQUFDLE9BQU8sQ0FBQyxDQUFDO1FBRXJCLElBQUksSUFBSSxDQUFDLE9BQU8sQ0FBQyxPQUFPLEVBQUUsQ0FBQztZQUN6QiwrQkFBK0I7UUFDakMsQ0FBQztJQUNILENBQUM7SUFFRCxxQkFBcUI7SUFDckIsWUFBWSxDQUFDLEtBQWE7UUFDeEIsSUFBSSxJQUFJLENBQUMsT0FBTyxDQUFDLEtBQUssSUFBSSxJQUFJLENBQUMsT0FBTyxDQUFDLElBQUk7WUFBRSxPQUFPO1FBQ3BELElBQUksQ0FBQyxHQUFH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
|
package/package.json
CHANGED
package/readme.plan.md
CHANGED
|
@@ -1,51 +1,199 @@
|
|
|
1
|
-
# Plan for
|
|
1
|
+
# Plan for improving logging and output in tstest
|
|
2
2
|
|
|
3
3
|
!! FIRST: Reread /home/philkunz/.claude/CLAUDE.md to ensure following all guidelines !!
|
|
4
4
|
|
|
5
|
-
## Goal - ✅ COMPLETED
|
|
6
|
-
- ✅ Make
|
|
7
|
-
- ✅
|
|
8
|
-
- ✅
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
- ✅
|
|
14
|
-
- ✅
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
- ✅
|
|
26
|
-
- ✅
|
|
27
|
-
- ✅
|
|
28
|
-
|
|
29
|
-
###
|
|
30
|
-
- ✅
|
|
31
|
-
- ✅ Used
|
|
32
|
-
- ✅
|
|
33
|
-
- ✅
|
|
34
|
-
- ✅
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
- ✅
|
|
40
|
-
- ✅
|
|
41
|
-
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
5
|
+
## Goal - ✅ MOSTLY COMPLETED
|
|
6
|
+
- ✅ Make test output cleaner and more visually appealing
|
|
7
|
+
- ✅ Add structured logging capabilities
|
|
8
|
+
- ✅ Support different verbosity levels
|
|
9
|
+
- ✅ Improve CI/CD compatibility
|
|
10
|
+
- ✅ Add progress indicators and timing summaries
|
|
11
|
+
|
|
12
|
+
## Current State - UPDATED
|
|
13
|
+
- ✅ Clean, modern visual design with Unicode characters
|
|
14
|
+
- ✅ Structured output format (JSON support)
|
|
15
|
+
- ✅ Multiple verbosity levels (quiet, normal, verbose)
|
|
16
|
+
- ✅ Real-time output with cleaner formatting
|
|
17
|
+
- ✅ Better error aggregation and display
|
|
18
|
+
- ✅ TAP protocol support integrated with new logger
|
|
19
|
+
|
|
20
|
+
## Completed Improvements
|
|
21
|
+
|
|
22
|
+
### 1. ✅ Created new TsTestLogger class
|
|
23
|
+
- ✅ Centralized logging with consistent formatting
|
|
24
|
+
- ✅ Support for different output modes (normal, quiet, verbose)
|
|
25
|
+
- ✅ Better visual hierarchy with modern Unicode characters
|
|
26
|
+
- ✅ Progress indicators for multiple test files
|
|
27
|
+
- ✅ Structured error collection and display
|
|
28
|
+
|
|
29
|
+
### 2. ✅ Updated visual design
|
|
30
|
+
- ✅ Replaced heavy separators with cleaner alternatives
|
|
31
|
+
- ✅ Used better emoji and Unicode characters
|
|
32
|
+
- ✅ Added indentation for hierarchical display
|
|
33
|
+
- ✅ Grouped related information visually
|
|
34
|
+
- ✅ Added color coding consistently
|
|
35
|
+
|
|
36
|
+
### 3. ✅ Added command-line options
|
|
37
|
+
- ✅ `--quiet` for minimal CI-friendly output
|
|
38
|
+
- ✅ `--verbose` for detailed debugging information
|
|
39
|
+
- ✅ `--no-color` for environments without color support
|
|
40
|
+
- ✅ `--json` for structured JSON output
|
|
41
|
+
- ⏳ `--log-file <path>` for persistent logging (TODO)
|
|
42
|
+
|
|
43
|
+
### 4. ✅ Improved progress feedback
|
|
44
|
+
- ⏳ Show progress bar for multiple files (TODO)
|
|
45
|
+
- ✅ Display current file being executed
|
|
46
|
+
- ✅ Show real-time test counts
|
|
47
|
+
- ⏳ Add ETA for long test suites (TODO)
|
|
48
|
+
|
|
49
|
+
### 5. ✅ Better error and summary display
|
|
50
|
+
- ✅ Collect all errors and display at end
|
|
51
|
+
- ✅ Show timing metrics and performance summary (in verbose mode)
|
|
52
|
+
- ✅ Highlight slowest tests (in verbose mode)
|
|
53
|
+
- ✅ Add test failure context
|
|
54
|
+
|
|
55
|
+
### 6. ✅ Browser console integration
|
|
56
|
+
- ✅ Clearly separate browser logs from test output
|
|
57
|
+
- ⏳ Add browser log filtering options (TODO)
|
|
58
|
+
- ✅ Format browser errors specially
|
|
59
|
+
|
|
60
|
+
## Implementation Steps - COMPLETED
|
|
61
|
+
|
|
62
|
+
### Phase 1: ✅ Core Logger Implementation
|
|
63
|
+
1. ✅ Created `tstest.logging.ts` with TsTestLogger class
|
|
64
|
+
2. ✅ Added LogOptions interface for configuration
|
|
65
|
+
3. ✅ Implemented basic formatting methods
|
|
66
|
+
4. ✅ Added progress and summary methods
|
|
67
|
+
|
|
68
|
+
### Phase 2: ✅ Integration
|
|
69
|
+
1. ✅ Updated CLI to accept new command-line options
|
|
70
|
+
2. ✅ Modified TsTest class to use new logger
|
|
71
|
+
3. ✅ Updated TapParser to use structured logging
|
|
72
|
+
4. ✅ Updated TapCombinator for better summaries
|
|
73
|
+
|
|
74
|
+
### Phase 3: ✅ Visual Improvements
|
|
75
|
+
1. ✅ Replaced all existing separators
|
|
76
|
+
2. ✅ Updated color scheme
|
|
77
|
+
3. ✅ Added emoji and Unicode characters
|
|
78
|
+
4. ✅ Implemented hierarchical output
|
|
79
|
+
|
|
80
|
+
### Phase 4: ✅ Advanced Features
|
|
81
|
+
1. ✅ Add JSON output format
|
|
82
|
+
2. ⏳ Implement file-based logging (TODO)
|
|
83
|
+
3. ✅ Add performance metrics collection
|
|
84
|
+
4. ✅ Create error aggregation system
|
|
85
|
+
|
|
86
|
+
### Phase 5: ✅ Browser Integration
|
|
87
|
+
1. ✅ Update browser console forwarding
|
|
88
|
+
2. ✅ Add browser log formatting
|
|
89
|
+
3. ✅ Implement browser-specific indicators
|
|
90
|
+
|
|
91
|
+
## Files modified
|
|
92
|
+
- ✅ `ts/tstest.logging.ts` - New logger implementation (created)
|
|
93
|
+
- ✅ `ts/index.ts` - Added CLI options parsing
|
|
94
|
+
- ✅ `ts/tstest.classes.tstest.ts` - Integrated new logger
|
|
95
|
+
- ✅ `ts/tstest.classes.tap.parser.ts` - Updated output formatting
|
|
96
|
+
- ✅ `ts/tstest.classes.tap.combinator.ts` - Improved summary display
|
|
97
|
+
- ❌ `ts/tstest.logprefixes.ts` - Still in use, can be deprecated later
|
|
98
|
+
- ❌ `package.json` - No new dependencies needed
|
|
99
|
+
|
|
100
|
+
## Success Criteria - ACHIEVED
|
|
101
|
+
- ✅ Cleaner, more readable test output
|
|
102
|
+
- ✅ Configurable verbosity levels
|
|
103
|
+
- ✅ Better CI/CD integration
|
|
104
|
+
- ✅ Improved error visibility
|
|
105
|
+
- ✅ Performance metrics available
|
|
106
|
+
- ✅ Consistent visual design
|
|
107
|
+
- ✅ Maintained backward compatibility
|
|
108
|
+
|
|
109
|
+
## Example Output Comparison
|
|
110
|
+
|
|
111
|
+
### Current Output
|
|
112
|
+
```
|
|
113
|
+
☰☰☰☰☰☰☰☰☰☰☰☰☰☰☰☰☰☰☰☰☰☰☰☰☰☰☰☰☰☰☰☰☰☰☰☰☰☰☰☰
|
|
114
|
+
**TSTEST** FOUND 4 TESTFILE(S):
|
|
115
|
+
**TSTEST** test/test.ts
|
|
116
|
+
------------------------------------------------
|
|
117
|
+
=> Running test/test.ts in node.js runtime.
|
|
118
|
+
= = = = = = = = = = = = = = = = = = = = = = = =
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
### Actual Output (IMPLEMENTED)
|
|
122
|
+
```
|
|
123
|
+
🔍 Test Discovery
|
|
124
|
+
Mode: directory
|
|
125
|
+
Pattern: test
|
|
126
|
+
Found: 4 test file(s)
|
|
127
|
+
|
|
128
|
+
▶️ test/test.ts (1/4)
|
|
129
|
+
Runtime: node.js
|
|
130
|
+
✅ prepare test (0ms)
|
|
131
|
+
Summary: 1/1 PASSED
|
|
132
|
+
|
|
133
|
+
▶️ test/test.single.ts (2/4)
|
|
134
|
+
Runtime: node.js
|
|
135
|
+
✅ single file test execution (1ms)
|
|
136
|
+
Summary: 1/1 PASSED
|
|
137
|
+
|
|
138
|
+
📊 Test Summary
|
|
139
|
+
┌────────────────────────────────┐
|
|
140
|
+
│ Total Files: 4 │
|
|
141
|
+
│ Total Tests: 4 │
|
|
142
|
+
│ Passed: 4 │
|
|
143
|
+
│ Failed: 0 │
|
|
144
|
+
│ Duration: 5739ms │
|
|
145
|
+
└────────────────────────────────┘
|
|
146
|
+
|
|
147
|
+
ALL TESTS PASSED! 🎉
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
### Additional Features Implemented
|
|
151
|
+
|
|
152
|
+
1. **Quiet Mode**:
|
|
153
|
+
```
|
|
154
|
+
Found 1 tests
|
|
155
|
+
✅ single file test execution
|
|
156
|
+
|
|
157
|
+
Summary: 1/1 | 1210ms | PASSED
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
2. **JSON Mode**:
|
|
161
|
+
```json
|
|
162
|
+
{"event":"discovery","count":1,"pattern":"test/test.single.ts","executionMode":"file"}
|
|
163
|
+
{"event":"fileStart","filename":"test/test.single.ts","runtime":"node.js","index":1,"total":1}
|
|
164
|
+
{"event":"testResult","testName":"single file test execution","passed":true,"duration":0}
|
|
165
|
+
{"event":"summary","summary":{"totalFiles":1,"totalTests":1,"totalPassed":1,"totalFailed":0,"totalDuration":1223,"fileResults":[...]}}
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
3. **Error Display**:
|
|
169
|
+
```
|
|
170
|
+
❌ Failed Tests:
|
|
171
|
+
|
|
172
|
+
test/test.fail.ts
|
|
173
|
+
❌ This test should fail
|
|
174
|
+
|
|
175
|
+
SOME TESTS FAILED! ❌
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
## Summary of Implementation
|
|
179
|
+
|
|
180
|
+
The logging improvement plan has been successfully implemented with the following achievements:
|
|
181
|
+
|
|
182
|
+
1. **Created a new centralized TsTestLogger class** that handles all output formatting
|
|
183
|
+
2. **Added multiple output modes**: quiet, normal, verbose, and JSON
|
|
184
|
+
3. **Improved visual design** with modern Unicode characters and emojis
|
|
185
|
+
4. **Added CLI argument parsing** for all new options
|
|
186
|
+
5. **Integrated the logger throughout the codebase** (TsTest, TapParser, TapCombinator)
|
|
187
|
+
6. **Better error aggregation and display** with failed tests shown at the end
|
|
188
|
+
7. **Performance metrics** available in verbose mode
|
|
189
|
+
8. **Clean, hierarchical output** that's much more readable
|
|
190
|
+
|
|
191
|
+
### Remaining TODOs
|
|
192
|
+
|
|
193
|
+
Only a few minor features remain unimplemented:
|
|
194
|
+
- File-based logging (--log-file option)
|
|
195
|
+
- Progress bar visualization
|
|
196
|
+
- ETA for long test suites
|
|
197
|
+
- Browser log filtering options
|
|
198
|
+
|
|
199
|
+
The core logging improvements are complete and provide a much better user experience!
|
package/ts/00_commitinfo_data.ts
CHANGED
package/ts/index.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { TsTest } from './tstest.classes.tstest.js';
|
|
2
|
+
import type { LogOptions } from './tstest.logging.js';
|
|
2
3
|
|
|
3
4
|
export enum TestExecutionMode {
|
|
4
5
|
DIRECTORY = 'directory',
|
|
@@ -7,12 +8,54 @@ export enum TestExecutionMode {
|
|
|
7
8
|
}
|
|
8
9
|
|
|
9
10
|
export const runCli = async () => {
|
|
10
|
-
|
|
11
|
+
// Parse command line arguments
|
|
12
|
+
const args = process.argv.slice(2);
|
|
13
|
+
const logOptions: LogOptions = {};
|
|
14
|
+
let testPath: string | null = null;
|
|
15
|
+
|
|
16
|
+
// Parse options
|
|
17
|
+
for (let i = 0; i < args.length; i++) {
|
|
18
|
+
const arg = args[i];
|
|
19
|
+
|
|
20
|
+
switch (arg) {
|
|
21
|
+
case '--quiet':
|
|
22
|
+
case '-q':
|
|
23
|
+
logOptions.quiet = true;
|
|
24
|
+
break;
|
|
25
|
+
case '--verbose':
|
|
26
|
+
case '-v':
|
|
27
|
+
logOptions.verbose = true;
|
|
28
|
+
break;
|
|
29
|
+
case '--no-color':
|
|
30
|
+
logOptions.noColor = true;
|
|
31
|
+
break;
|
|
32
|
+
case '--json':
|
|
33
|
+
logOptions.json = true;
|
|
34
|
+
break;
|
|
35
|
+
case '--log-file':
|
|
36
|
+
if (i + 1 < args.length) {
|
|
37
|
+
logOptions.logFile = args[++i];
|
|
38
|
+
}
|
|
39
|
+
break;
|
|
40
|
+
default:
|
|
41
|
+
if (!arg.startsWith('-')) {
|
|
42
|
+
testPath = arg;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
if (!testPath) {
|
|
11
48
|
console.error('You must specify a test directory/file/pattern as argument. Please try again.');
|
|
49
|
+
console.error('\nUsage: tstest <path> [options]');
|
|
50
|
+
console.error('\nOptions:');
|
|
51
|
+
console.error(' --quiet, -q Minimal output');
|
|
52
|
+
console.error(' --verbose, -v Verbose output');
|
|
53
|
+
console.error(' --no-color Disable colored output');
|
|
54
|
+
console.error(' --json Output results as JSON');
|
|
55
|
+
console.error(' --log-file Write logs to file');
|
|
12
56
|
process.exit(1);
|
|
13
57
|
}
|
|
14
58
|
|
|
15
|
-
const testPath = process.argv[2];
|
|
16
59
|
let executionMode: TestExecutionMode;
|
|
17
60
|
|
|
18
61
|
// Detect execution mode based on the argument
|
|
@@ -24,6 +67,6 @@ export const runCli = async () => {
|
|
|
24
67
|
executionMode = TestExecutionMode.DIRECTORY;
|
|
25
68
|
}
|
|
26
69
|
|
|
27
|
-
const tsTestInstance = new TsTest(process.cwd(), testPath, executionMode);
|
|
70
|
+
const tsTestInstance = new TsTest(process.cwd(), testPath, executionMode, logOptions);
|
|
28
71
|
await tsTestInstance.run();
|
|
29
72
|
};
|