@aiready/consistency 0.3.3 → 0.3.4
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/chunk-Q5XMWG33.mjs +661 -0
- package/dist/chunk-TLVLM3M5.mjs +771 -0
- package/dist/cli.js +277 -14
- package/dist/cli.mjs +1 -1
- package/dist/index.js +277 -14
- package/dist/index.mjs +1 -1
- package/package.json +13 -12
- package/src/__tests__/analyzer.test.ts +14 -1
- package/src/analyzers/naming.ts +137 -23
- package/.turbo/turbo-build.log +0 -24
- package/.turbo/turbo-test.log +0 -76
package/src/analyzers/naming.ts
CHANGED
|
@@ -1,35 +1,69 @@
|
|
|
1
1
|
import { readFileContent } from '@aiready/core';
|
|
2
2
|
import type { NamingIssue } from '../types';
|
|
3
3
|
|
|
4
|
+
// Common short English words that are NOT abbreviations (full, valid words)
|
|
5
|
+
const COMMON_SHORT_WORDS = new Set([
|
|
6
|
+
// Full English words (1-3 letters)
|
|
7
|
+
'day', 'key', 'net', 'to', 'go', 'for', 'not', 'new', 'old', 'top', 'end',
|
|
8
|
+
'run', 'try', 'use', 'get', 'set', 'add', 'put', 'map', 'log', 'row', 'col',
|
|
9
|
+
'tab', 'box', 'div', 'nav', 'tag', 'any', 'all', 'one', 'two', 'out', 'off',
|
|
10
|
+
'on', 'yes', 'no', 'now', 'max', 'min', 'sum', 'avg', 'ref', 'src', 'dst',
|
|
11
|
+
'raw', 'def', 'sub', 'pub', 'pre', 'mid', 'alt', 'opt', 'tmp', 'ext', 'sep',
|
|
12
|
+
// Additional full words commonly flagged
|
|
13
|
+
'tax', 'cat', 'dog', 'car', 'bus', 'web', 'app', 'war', 'law', 'pay', 'buy',
|
|
14
|
+
'win', 'cut', 'hit', 'hot', 'pop', 'job', 'age', 'act', 'let', 'lot', 'bad',
|
|
15
|
+
'big', 'far', 'few', 'own', 'per', 'red', 'low', 'see', 'six', 'ten', 'way',
|
|
16
|
+
'who', 'why', 'yet', 'via', 'due', 'fee', 'fun', 'gas', 'gay', 'god', 'gun',
|
|
17
|
+
'guy', 'ice', 'ill', 'kid', 'mad', 'man', 'mix', 'mom', 'mrs', 'nor', 'odd',
|
|
18
|
+
'oil', 'pan', 'pet', 'pit', 'pot', 'pow', 'pro', 'raw', 'rep', 'rid', 'sad',
|
|
19
|
+
'sea', 'sit', 'sky', 'son', 'tea', 'tie', 'tip', 'van', 'war', 'win', 'won'
|
|
20
|
+
]);
|
|
21
|
+
|
|
4
22
|
// Comprehensive list of acceptable abbreviations and acronyms
|
|
5
23
|
const ACCEPTABLE_ABBREVIATIONS = new Set([
|
|
6
24
|
// Standard identifiers
|
|
7
25
|
'id', 'uid', 'gid', 'pid',
|
|
26
|
+
// Loop counters and iterators
|
|
27
|
+
'i', 'j', 'k', 'n', 'm',
|
|
8
28
|
// Web/Network
|
|
9
29
|
'url', 'uri', 'api', 'cdn', 'dns', 'ip', 'tcp', 'udp', 'http', 'ssl', 'tls',
|
|
10
|
-
'utm', 'seo', 'rss', 'xhr', 'ajax',
|
|
30
|
+
'utm', 'seo', 'rss', 'xhr', 'ajax', 'cors', 'ws', 'wss',
|
|
11
31
|
// Data formats
|
|
12
32
|
'json', 'xml', 'yaml', 'csv', 'html', 'css', 'svg', 'pdf',
|
|
33
|
+
// File types & extensions
|
|
34
|
+
'img', 'txt', 'doc', 'docx', 'xlsx', 'ppt', 'md', 'rst', 'jpg', 'png', 'gif',
|
|
13
35
|
// Databases
|
|
14
|
-
'db', 'sql', 'orm', 'dao', 'dto',
|
|
36
|
+
'db', 'sql', 'orm', 'dao', 'dto', 'ddb', 'rds', 'nosql',
|
|
15
37
|
// File system
|
|
16
38
|
'fs', 'dir', 'tmp', 'src', 'dst', 'bin', 'lib', 'pkg',
|
|
17
39
|
// Operating system
|
|
18
|
-
'os', 'env', 'arg', 'cli', 'cmd', 'exe',
|
|
40
|
+
'os', 'env', 'arg', 'cli', 'cmd', 'exe', 'cwd', 'pwd',
|
|
19
41
|
// UI/UX
|
|
20
42
|
'ui', 'ux', 'gui', 'dom', 'ref',
|
|
21
43
|
// Request/Response
|
|
22
|
-
'req', 'res', 'ctx', 'err', 'msg',
|
|
44
|
+
'req', 'res', 'ctx', 'err', 'msg', 'auth',
|
|
23
45
|
// Mathematics/Computing
|
|
24
46
|
'max', 'min', 'avg', 'sum', 'abs', 'cos', 'sin', 'tan', 'log', 'exp',
|
|
25
|
-
'pow', 'sqrt', 'std', 'var', 'int', 'num',
|
|
47
|
+
'pow', 'sqrt', 'std', 'var', 'int', 'num', 'idx',
|
|
26
48
|
// Time
|
|
27
|
-
'now', 'utc', 'tz', 'ms', 'sec',
|
|
49
|
+
'now', 'utc', 'tz', 'ms', 'sec', 'hr', 'min', 'yr', 'mo',
|
|
28
50
|
// Common patterns
|
|
29
51
|
'app', 'cfg', 'config', 'init', 'len', 'val', 'str', 'obj', 'arr',
|
|
30
52
|
'gen', 'def', 'raw', 'new', 'old', 'pre', 'post', 'sub', 'pub',
|
|
53
|
+
// Programming/Framework specific
|
|
54
|
+
'ts', 'js', 'jsx', 'tsx', 'py', 'rb', 'vue', 're', 'fn', 'fns', 'mod', 'opts', 'dev',
|
|
55
|
+
// Cloud/Infrastructure
|
|
56
|
+
's3', 'ec2', 'sqs', 'sns', 'vpc', 'ami', 'iam', 'acl', 'elb', 'alb', 'nlb', 'aws',
|
|
57
|
+
// Metrics/Performance
|
|
58
|
+
'fcp', 'lcp', 'cls', 'ttfb', 'tti', 'fid', 'fps', 'qps', 'rps', 'tps',
|
|
59
|
+
// Testing & i18n
|
|
60
|
+
'po', 'e2e', 'a11y', 'i18n', 'l10n',
|
|
61
|
+
// Domain-specific abbreviations (context-aware)
|
|
62
|
+
'sk', 'fy', 'faq', 'og', 'seo', 'cta', 'roi', 'kpi',
|
|
31
63
|
// Boolean helpers (these are intentional short names)
|
|
32
|
-
'is', 'has', 'can', 'did', 'was', 'are'
|
|
64
|
+
'is', 'has', 'can', 'did', 'was', 'are',
|
|
65
|
+
// Date/Time context (when in date contexts)
|
|
66
|
+
'd', 't', 'dt'
|
|
33
67
|
]);
|
|
34
68
|
|
|
35
69
|
/**
|
|
@@ -50,6 +84,9 @@ export async function analyzeNaming(files: string[]): Promise<NamingIssue[]> {
|
|
|
50
84
|
function analyzeFileNaming(file: string, content: string): NamingIssue[] {
|
|
51
85
|
const issues: NamingIssue[] = [];
|
|
52
86
|
|
|
87
|
+
// Check if this is a test file (more lenient rules)
|
|
88
|
+
const isTestFile = file.match(/\.(test|spec)\.(ts|tsx|js|jsx)$/);
|
|
89
|
+
|
|
53
90
|
// Split into lines for line number tracking
|
|
54
91
|
const lines = content.split('\n');
|
|
55
92
|
|
|
@@ -61,11 +98,31 @@ function analyzeFileNaming(file: string, content: string): NamingIssue[] {
|
|
|
61
98
|
const singleLetterMatches = line.matchAll(/\b(?:const|let|var)\s+([a-hm-z])\s*=/gi);
|
|
62
99
|
for (const match of singleLetterMatches) {
|
|
63
100
|
const letter = match[1].toLowerCase();
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
101
|
+
|
|
102
|
+
// Enhanced loop/iterator context detection
|
|
103
|
+
const isInLoopContext =
|
|
104
|
+
line.includes('for') ||
|
|
105
|
+
/\.(map|filter|forEach|reduce|find|some|every)\s*\(/.test(line) ||
|
|
106
|
+
line.includes('=>') || // Arrow function
|
|
107
|
+
/\w+\s*=>\s*/.test(line); // Callback pattern
|
|
108
|
+
|
|
109
|
+
// Check for i18n/translation context
|
|
110
|
+
const isI18nContext =
|
|
111
|
+
line.includes('useTranslation') ||
|
|
112
|
+
line.includes('i18n.t') ||
|
|
113
|
+
/\bt\s*\(['"]/.test(line); // t('key') pattern
|
|
114
|
+
|
|
115
|
+
// Check for arrow function parameter (improved detection)
|
|
116
|
+
const isArrowFunctionParam =
|
|
117
|
+
/\(\s*[a-z]\s*(?:,\s*[a-z]\s*)*\)\s*=>/.test(line) || // (s) => or (a, b) =>
|
|
118
|
+
/[a-z]\s*=>/.test(line); // s =>
|
|
119
|
+
|
|
120
|
+
if (!isInLoopContext && !isI18nContext && !isArrowFunctionParam && !['x', 'y', 'z', 'i', 'j', 'k', 'l', 'n', 'm'].includes(letter)) {
|
|
121
|
+
// Skip in test files unless it's really unclear
|
|
122
|
+
if (isTestFile && ['a', 'b', 'c', 'd', 'e', 'f', 's'].includes(letter)) {
|
|
123
|
+
continue;
|
|
124
|
+
}
|
|
125
|
+
|
|
69
126
|
issues.push({
|
|
70
127
|
file,
|
|
71
128
|
line: lineNumber,
|
|
@@ -81,17 +138,48 @@ function analyzeFileNaming(file: string, content: string): NamingIssue[] {
|
|
|
81
138
|
const abbreviationMatches = line.matchAll(/\b(?:const|let|var)\s+([a-z]{1,3})(?=[A-Z]|_|\s*=)/g);
|
|
82
139
|
for (const match of abbreviationMatches) {
|
|
83
140
|
const abbrev = match[1].toLowerCase();
|
|
141
|
+
|
|
142
|
+
// Skip if it's a common short English word (full word, not abbreviation)
|
|
143
|
+
if (COMMON_SHORT_WORDS.has(abbrev)) {
|
|
144
|
+
continue;
|
|
145
|
+
}
|
|
146
|
+
|
|
84
147
|
// Skip acceptable abbreviations
|
|
85
|
-
if (
|
|
86
|
-
|
|
87
|
-
file,
|
|
88
|
-
line: lineNumber,
|
|
89
|
-
type: 'abbreviation',
|
|
90
|
-
identifier: match[1],
|
|
91
|
-
severity: 'info',
|
|
92
|
-
suggestion: `Consider using full word instead of abbreviation '${match[1]}'`
|
|
93
|
-
});
|
|
148
|
+
if (ACCEPTABLE_ABBREVIATIONS.has(abbrev)) {
|
|
149
|
+
continue;
|
|
94
150
|
}
|
|
151
|
+
|
|
152
|
+
// Check for arrow function parameter context
|
|
153
|
+
const isArrowFunctionParam =
|
|
154
|
+
/\(\s*[a-z]\s*(?:,\s*[a-z]\s*)*\)\s*=>/.test(line) || // (s) => or (a, b) =>
|
|
155
|
+
new RegExp(`\\b${abbrev}\\s*=>`).test(line); // s =>
|
|
156
|
+
|
|
157
|
+
if (isArrowFunctionParam) {
|
|
158
|
+
continue;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
// For very short names (1-2 letters), check for date/time context
|
|
162
|
+
if (abbrev.length <= 2) {
|
|
163
|
+
const isDateTimeContext = /date|time|day|hour|minute|second|timestamp/i.test(line);
|
|
164
|
+
if (isDateTimeContext && ['d', 't', 'dt'].includes(abbrev)) {
|
|
165
|
+
continue;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
// Check for user/auth context
|
|
169
|
+
const isUserContext = /user|auth|account/i.test(line);
|
|
170
|
+
if (isUserContext && abbrev === 'u') {
|
|
171
|
+
continue;
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
issues.push({
|
|
176
|
+
file,
|
|
177
|
+
line: lineNumber,
|
|
178
|
+
type: 'abbreviation',
|
|
179
|
+
identifier: match[1],
|
|
180
|
+
severity: 'info',
|
|
181
|
+
suggestion: `Consider using full word instead of abbreviation '${match[1]}'`
|
|
182
|
+
});
|
|
95
183
|
}
|
|
96
184
|
|
|
97
185
|
// Check for snake_case vs camelCase mixing in TypeScript/JavaScript
|
|
@@ -131,16 +219,42 @@ function analyzeFileNaming(file: string, content: string): NamingIssue[] {
|
|
|
131
219
|
const functionMatches = line.matchAll(/function\s+([a-z][a-zA-Z0-9]*)/g);
|
|
132
220
|
for (const match of functionMatches) {
|
|
133
221
|
const name = match[1];
|
|
222
|
+
|
|
223
|
+
// Skip JavaScript/TypeScript keywords that shouldn't be function names
|
|
224
|
+
const isKeyword = ['for', 'if', 'else', 'while', 'do', 'switch', 'case', 'break', 'continue', 'return', 'throw', 'try', 'catch', 'finally', 'with', 'yield', 'await'].includes(name);
|
|
225
|
+
if (isKeyword) {
|
|
226
|
+
continue;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
// Skip common entry point names
|
|
230
|
+
const isEntryPoint = ['main', 'init', 'setup', 'bootstrap'].includes(name);
|
|
231
|
+
if (isEntryPoint) {
|
|
232
|
+
continue;
|
|
233
|
+
}
|
|
234
|
+
|
|
134
235
|
// Functions should typically start with verbs, but allow:
|
|
135
236
|
// 1. Factory/builder patterns (ends with Factory, Builder, etc.)
|
|
136
237
|
// 2. Descriptive compound names that explain what they return
|
|
137
238
|
// 3. Event handlers (onClick, onSubmit, etc.)
|
|
239
|
+
// 4. Descriptive aggregate/collection patterns
|
|
240
|
+
// 5. Very long descriptive names (>15 chars)
|
|
241
|
+
// 6. Compound words with 3+ capitals
|
|
242
|
+
|
|
138
243
|
const isFactoryPattern = name.match(/(Factory|Builder|Creator|Generator)$/);
|
|
139
244
|
const isEventHandler = name.match(/^on[A-Z]/);
|
|
140
|
-
const isDescriptiveLong = name.length >
|
|
245
|
+
const isDescriptiveLong = name.length > 15; // Reduced from 20 to 15
|
|
246
|
+
|
|
247
|
+
// Check for descriptive patterns
|
|
248
|
+
const isDescriptivePattern = name.match(/^(default|total|count|sum|avg|max|min|initial|current|previous|next)\w+/) ||
|
|
249
|
+
name.match(/\w+(Count|Total|Sum|Average|List|Map|Set|Config|Settings|Options|Props)$/);
|
|
250
|
+
|
|
251
|
+
// Count capital letters for compound detection
|
|
252
|
+
const capitalCount = (name.match(/[A-Z]/g) || []).length;
|
|
253
|
+
const isCompoundWord = capitalCount >= 3; // daysSinceLastCommit has 4 capitals
|
|
254
|
+
|
|
141
255
|
const hasActionVerb = name.match(/^(get|set|is|has|can|should|create|update|delete|fetch|load|save|process|handle|validate|check|find|search|filter|map|reduce|make|do|run|start|stop|build|parse|format|render|calculate|compute|generate|transform|convert|normalize|sanitize|encode|decode|compress|extract|merge|split|join|sort|compare|test|verify|ensure|apply|execute|invoke|call|emit|dispatch|trigger|listen|subscribe|unsubscribe|add|remove|clear|reset|toggle|enable|disable|open|close|connect|disconnect|send|receive|read|write|import|export|register|unregister|mount|unmount)/);
|
|
142
256
|
|
|
143
|
-
if (!hasActionVerb && !isFactoryPattern && !isEventHandler && !isDescriptiveLong) {
|
|
257
|
+
if (!hasActionVerb && !isFactoryPattern && !isEventHandler && !isDescriptiveLong && !isDescriptivePattern && !isCompoundWord) {
|
|
144
258
|
issues.push({
|
|
145
259
|
file,
|
|
146
260
|
line: lineNumber,
|
package/.turbo/turbo-build.log
DELETED
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
> @aiready/consistency@0.3.3 build /Users/pengcao/projects/aiready/packages/consistency
|
|
4
|
-
> tsup src/index.ts src/cli.ts --format cjs,esm --dts
|
|
5
|
-
|
|
6
|
-
[34mCLI[39m Building entry: src/cli.ts, src/index.ts
|
|
7
|
-
[34mCLI[39m Using tsconfig: tsconfig.json
|
|
8
|
-
[34mCLI[39m tsup v8.5.1
|
|
9
|
-
[34mCLI[39m Target: es2020
|
|
10
|
-
[34mCJS[39m Build start
|
|
11
|
-
[34mESM[39m Build start
|
|
12
|
-
[32mCJS[39m [1mdist/cli.js [22m[32m25.23 KB[39m
|
|
13
|
-
[32mCJS[39m [1mdist/index.js [22m[32m16.34 KB[39m
|
|
14
|
-
[32mCJS[39m ⚡️ Build success in 79ms
|
|
15
|
-
[32mESM[39m [1mdist/chunk-LUAREV6A.mjs [22m[32m15.11 KB[39m
|
|
16
|
-
[32mESM[39m [1mdist/cli.mjs [22m[32m8.54 KB[39m
|
|
17
|
-
[32mESM[39m [1mdist/index.mjs [22m[32m220.00 B[39m
|
|
18
|
-
[32mESM[39m ⚡️ Build success in 79ms
|
|
19
|
-
DTS Build start
|
|
20
|
-
DTS ⚡️ Build success in 587ms
|
|
21
|
-
DTS dist/cli.d.ts 20.00 B
|
|
22
|
-
DTS dist/index.d.ts 2.60 KB
|
|
23
|
-
DTS dist/cli.d.mts 20.00 B
|
|
24
|
-
DTS dist/index.d.mts 2.60 KB
|
package/.turbo/turbo-test.log
DELETED
|
@@ -1,76 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
> @aiready/consistency@0.3.3 test /Users/pengcao/projects/aiready/packages/consistency
|
|
4
|
-
> vitest run
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
[1m[7m[36m RUN [39m[27m[22m [36mv2.1.9 [39m[90m/Users/pengcao/projects/aiready/packages/consistency[39m
|
|
8
|
-
|
|
9
|
-
[?25l [33m❯[39m analyzeConsistency[2m (2)[22m
|
|
10
|
-
[33m⠙[39m should analyze naming issues
|
|
11
|
-
[90m·[39m should detect minimum severity filtering
|
|
12
|
-
[90m·[39m analyzeNaming[2m (5)[22m
|
|
13
|
-
[90m·[39m should detect single letter variables
|
|
14
|
-
[90m·[39m should NOT flag acceptable abbreviations
|
|
15
|
-
[90m·[39m should detect snake_case in TypeScript files
|
|
16
|
-
[90m·[39m should detect unclear boolean names
|
|
17
|
-
[90m·[39m should allow common abbreviations
|
|
18
|
-
[90m·[39m analyzePatterns[2m (3)[22m
|
|
19
|
-
[90m·[39m should detect mixed error handling
|
|
20
|
-
[90m·[39m should detect mixed async patterns
|
|
21
|
-
[90m·[39m should detect mixed import styles
|
|
22
|
-
[90m·[39m consistency scoring[2m (2)[22m
|
|
23
|
-
[90m·[39m should calculate consistency score correctly
|
|
24
|
-
[90m·[39m should weight critical issues more than info
|
|
25
|
-
[90m·[39m recommendations[2m (3)[22m
|
|
26
|
-
[90m·[39m should generate relevant recommendations
|
|
27
|
-
[90m·[39m should suggest standardizing error handling
|
|
28
|
-
[90m·[39m should suggest using async/await consistently
|
|
29
|
-
[?25l[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[G [32m✓[39m analyzeConsistency[2m (2)[22m
|
|
30
|
-
[32m✓[39m should analyze naming issues
|
|
31
|
-
[32m✓[39m should detect minimum severity filtering
|
|
32
|
-
[32m✓[39m analyzeNaming[2m (5)[22m
|
|
33
|
-
[32m✓[39m should detect single letter variables
|
|
34
|
-
[32m✓[39m should NOT flag acceptable abbreviations
|
|
35
|
-
[32m✓[39m should detect snake_case in TypeScript files
|
|
36
|
-
[32m✓[39m should detect unclear boolean names
|
|
37
|
-
[32m✓[39m should allow common abbreviations
|
|
38
|
-
[32m✓[39m analyzePatterns[2m (3)[22m
|
|
39
|
-
[32m✓[39m should detect mixed error handling
|
|
40
|
-
[32m✓[39m should detect mixed async patterns
|
|
41
|
-
[32m✓[39m should detect mixed import styles
|
|
42
|
-
[32m✓[39m consistency scoring[2m (2)[22m
|
|
43
|
-
[32m✓[39m should calculate consistency score correctly
|
|
44
|
-
[32m✓[39m should weight critical issues more than info
|
|
45
|
-
[32m✓[39m recommendations[2m (3)[22m
|
|
46
|
-
[32m✓[39m should generate relevant recommendations
|
|
47
|
-
[32m✓[39m should suggest standardizing error handling
|
|
48
|
-
[32m✓[39m should suggest using async/await consistently
|
|
49
|
-
[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[G [32m✓[39m [2msrc/__tests__/[22manalyzer[2m.test.ts[22m[2m (15)[22m
|
|
50
|
-
[32m✓[39m analyzeConsistency[2m (2)[22m
|
|
51
|
-
[32m✓[39m should analyze naming issues
|
|
52
|
-
[32m✓[39m should detect minimum severity filtering
|
|
53
|
-
[32m✓[39m analyzeNaming[2m (5)[22m
|
|
54
|
-
[32m✓[39m should detect single letter variables
|
|
55
|
-
[32m✓[39m should NOT flag acceptable abbreviations
|
|
56
|
-
[32m✓[39m should detect snake_case in TypeScript files
|
|
57
|
-
[32m✓[39m should detect unclear boolean names
|
|
58
|
-
[32m✓[39m should allow common abbreviations
|
|
59
|
-
[32m✓[39m analyzePatterns[2m (3)[22m
|
|
60
|
-
[32m✓[39m should detect mixed error handling
|
|
61
|
-
[32m✓[39m should detect mixed async patterns
|
|
62
|
-
[32m✓[39m should detect mixed import styles
|
|
63
|
-
[32m✓[39m consistency scoring[2m (2)[22m
|
|
64
|
-
[32m✓[39m should calculate consistency score correctly
|
|
65
|
-
[32m✓[39m should weight critical issues more than info
|
|
66
|
-
[32m✓[39m recommendations[2m (3)[22m
|
|
67
|
-
[32m✓[39m should generate relevant recommendations
|
|
68
|
-
[32m✓[39m should suggest standardizing error handling
|
|
69
|
-
[32m✓[39m should suggest using async/await consistently
|
|
70
|
-
|
|
71
|
-
[2m Test Files [22m [1m[32m1 passed[39m[22m[90m (1)[39m
|
|
72
|
-
[2m Tests [22m [1m[32m15 passed[39m[22m[90m (15)[39m
|
|
73
|
-
[2m Start at [22m 15:32:25
|
|
74
|
-
[2m Duration [22m 519ms[2m (transform 74ms, setup 0ms, collect 251ms, tests 24ms, environment 0ms, prepare 54ms)[22m
|
|
75
|
-
|
|
76
|
-
[?25h[?25h
|