@hyperfixi/testing-framework 2.0.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/assertions-BImuwZsB.d.mts +458 -0
- package/dist/assertions-BImuwZsB.d.ts +458 -0
- package/dist/assertions.d.mts +1 -0
- package/dist/assertions.d.ts +1 -0
- package/dist/assertions.js +625 -0
- package/dist/assertions.js.map +1 -0
- package/dist/assertions.mjs +621 -0
- package/dist/assertions.mjs.map +1 -0
- package/dist/index.d.mts +246 -0
- package/dist/index.d.ts +246 -0
- package/dist/index.js +1465 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +1435 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +121 -0
- package/src/assertions.test.ts +490 -0
- package/src/assertions.ts +779 -0
- package/src/index.test.ts +490 -0
- package/src/index.ts +601 -0
- package/src/jsdom.d.ts +7 -0
- package/src/multilingual/README.md +295 -0
- package/src/multilingual/bundle-builder.ts +345 -0
- package/src/multilingual/cli.ts +224 -0
- package/src/multilingual/index.ts +68 -0
- package/src/multilingual/orchestrator.ts +275 -0
- package/src/multilingual/pattern-loader.ts +176 -0
- package/src/multilingual/reporters/console-reporter.ts +294 -0
- package/src/multilingual/reporters/json-reporter.ts +99 -0
- package/src/multilingual/reporters/regression-reporter.ts +263 -0
- package/src/multilingual/tools/analyze-failures.ts +326 -0
- package/src/multilingual/types.ts +268 -0
- package/src/multilingual/validators/parse-diagnostics.ts +337 -0
- package/src/multilingual/validators/parse-validator.ts +193 -0
- package/src/multilingual/validators/size-validator.ts +187 -0
- package/src/runner.test.ts +813 -0
- package/src/runner.ts +639 -0
- package/src/types.ts +505 -0
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Multilingual Testing CLI
|
|
4
|
+
*
|
|
5
|
+
* Command-line interface for running multilingual tests.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { TestOrchestrator } from './orchestrator';
|
|
9
|
+
import { RegressionReporter } from './reporters/regression-reporter';
|
|
10
|
+
import type { TestConfig, LanguageCode } from './types';
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Parse command-line arguments
|
|
14
|
+
*/
|
|
15
|
+
function parseArgs(): TestConfig {
|
|
16
|
+
const args = process.argv.slice(2);
|
|
17
|
+
const config: TestConfig = {
|
|
18
|
+
mode: 'quick',
|
|
19
|
+
quickModeLimit: 10,
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
for (let i = 0; i < args.length; i++) {
|
|
23
|
+
const arg = args[i];
|
|
24
|
+
|
|
25
|
+
switch (arg) {
|
|
26
|
+
case '--language':
|
|
27
|
+
case '-l': {
|
|
28
|
+
const lang = args[++i];
|
|
29
|
+
if (lang) config.languages = [lang as LanguageCode];
|
|
30
|
+
break;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
case '--languages': {
|
|
34
|
+
const langs = args[++i];
|
|
35
|
+
if (langs) config.languages = langs.split(',') as LanguageCode[];
|
|
36
|
+
break;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
case '--bundle':
|
|
40
|
+
case '-b': {
|
|
41
|
+
const bundle = args[++i];
|
|
42
|
+
if (bundle) config.bundle = bundle;
|
|
43
|
+
break;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
case '--build':
|
|
47
|
+
config.build = true;
|
|
48
|
+
break;
|
|
49
|
+
|
|
50
|
+
case '--mode':
|
|
51
|
+
case '-m':
|
|
52
|
+
config.mode = args[++i] as 'quick' | 'full';
|
|
53
|
+
break;
|
|
54
|
+
|
|
55
|
+
case '--quick':
|
|
56
|
+
config.mode = 'quick';
|
|
57
|
+
break;
|
|
58
|
+
|
|
59
|
+
case '--full':
|
|
60
|
+
config.mode = 'full';
|
|
61
|
+
break;
|
|
62
|
+
|
|
63
|
+
case '--verbose':
|
|
64
|
+
case '-v':
|
|
65
|
+
config.verbose = true;
|
|
66
|
+
break;
|
|
67
|
+
|
|
68
|
+
case '--regression':
|
|
69
|
+
case '-r':
|
|
70
|
+
config.regression = true;
|
|
71
|
+
break;
|
|
72
|
+
|
|
73
|
+
case '--confidence':
|
|
74
|
+
case '-c': {
|
|
75
|
+
const conf = args[++i];
|
|
76
|
+
if (conf) config.confidenceThreshold = parseFloat(conf);
|
|
77
|
+
break;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
case '--verified-only':
|
|
81
|
+
config.verifiedOnly = true;
|
|
82
|
+
break;
|
|
83
|
+
|
|
84
|
+
case '--categories': {
|
|
85
|
+
const cats = args[++i];
|
|
86
|
+
if (cats) config.categories = cats.split(',');
|
|
87
|
+
break;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
case '--limit': {
|
|
91
|
+
const lim = args[++i];
|
|
92
|
+
if (lim) config.quickModeLimit = parseInt(lim, 10);
|
|
93
|
+
break;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
case '--help':
|
|
97
|
+
case '-h':
|
|
98
|
+
showHelp();
|
|
99
|
+
process.exit(0);
|
|
100
|
+
break;
|
|
101
|
+
|
|
102
|
+
case '--save-baseline':
|
|
103
|
+
// Special flag to save results as baseline
|
|
104
|
+
runAndSaveBaseline();
|
|
105
|
+
return config; // Early return to avoid running tests below
|
|
106
|
+
|
|
107
|
+
default:
|
|
108
|
+
if (arg && arg.startsWith('-')) {
|
|
109
|
+
console.error(`Unknown option: ${arg}`);
|
|
110
|
+
process.exit(1);
|
|
111
|
+
}
|
|
112
|
+
break;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
return config;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Show help message
|
|
121
|
+
*/
|
|
122
|
+
function showHelp(): void {
|
|
123
|
+
console.log(`
|
|
124
|
+
Multilingual Test Runner
|
|
125
|
+
|
|
126
|
+
USAGE:
|
|
127
|
+
npm run test:multilingual [OPTIONS]
|
|
128
|
+
|
|
129
|
+
OPTIONS:
|
|
130
|
+
-l, --language <code> Test specific language (en, ja, es, etc.)
|
|
131
|
+
--languages <codes> Test multiple languages (comma-separated)
|
|
132
|
+
-b, --bundle <name> Use specific bundle
|
|
133
|
+
--build Build bundle before testing
|
|
134
|
+
-m, --mode <mode> Test mode: 'quick' or 'full' (default: quick)
|
|
135
|
+
--quick Quick mode (10 patterns per language)
|
|
136
|
+
--full Full mode (all patterns)
|
|
137
|
+
-v, --verbose Enable verbose output
|
|
138
|
+
-r, --regression Compare to baseline and report regressions
|
|
139
|
+
-c, --confidence <n> Minimum confidence threshold (0-1)
|
|
140
|
+
--verified-only Only test verified translations
|
|
141
|
+
--categories <cats> Filter by categories (comma-separated)
|
|
142
|
+
--limit <n> Patterns per language in quick mode (default: 10)
|
|
143
|
+
--save-baseline Save current results as new baseline
|
|
144
|
+
-h, --help Show this help message
|
|
145
|
+
|
|
146
|
+
EXAMPLES:
|
|
147
|
+
# Test all languages in quick mode
|
|
148
|
+
npm run test:multilingual
|
|
149
|
+
|
|
150
|
+
# Test specific language with verbose output
|
|
151
|
+
npm run test:multilingual -- --language ja --verbose
|
|
152
|
+
|
|
153
|
+
# Test multiple languages in full mode
|
|
154
|
+
npm run test:multilingual -- --languages ja,ko,es --full
|
|
155
|
+
|
|
156
|
+
# Build bundle and test with regression comparison
|
|
157
|
+
npm run test:multilingual -- --build --regression
|
|
158
|
+
|
|
159
|
+
# Save current results as baseline
|
|
160
|
+
npm run test:multilingual -- --save-baseline
|
|
161
|
+
`);
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* Run tests and save as baseline
|
|
166
|
+
*/
|
|
167
|
+
async function runAndSaveBaseline(): Promise<void> {
|
|
168
|
+
try {
|
|
169
|
+
// Parse config without --save-baseline
|
|
170
|
+
const args = process.argv.slice(2).filter(arg => arg !== '--save-baseline');
|
|
171
|
+
process.argv = [...process.argv.slice(0, 2), ...args];
|
|
172
|
+
|
|
173
|
+
const config = parseArgs();
|
|
174
|
+
config.regression = true; // Enable regression reporter
|
|
175
|
+
|
|
176
|
+
const orchestrator = new TestOrchestrator(config);
|
|
177
|
+
const results = await orchestrator.run();
|
|
178
|
+
|
|
179
|
+
// Save as baseline
|
|
180
|
+
const regressionReporter = orchestrator.getRegressionReporter();
|
|
181
|
+
if (regressionReporter) {
|
|
182
|
+
regressionReporter.saveAsBaseline(results);
|
|
183
|
+
} else {
|
|
184
|
+
// Create reporter and save
|
|
185
|
+
const reporter = new RegressionReporter();
|
|
186
|
+
reporter.saveAsBaseline(results);
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
process.exit(0);
|
|
190
|
+
} catch (error) {
|
|
191
|
+
console.error('Error:', error instanceof Error ? error.message : String(error));
|
|
192
|
+
process.exit(1);
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
/**
|
|
197
|
+
* Main CLI entry point
|
|
198
|
+
*/
|
|
199
|
+
async function main(): Promise<void> {
|
|
200
|
+
try {
|
|
201
|
+
const config = parseArgs();
|
|
202
|
+
|
|
203
|
+
const orchestrator = new TestOrchestrator(config);
|
|
204
|
+
const results = await orchestrator.run();
|
|
205
|
+
|
|
206
|
+
// Exit with appropriate code
|
|
207
|
+
const exitCode = results.summary.overallStatus === 'pass' ? 0 : 1;
|
|
208
|
+
process.exit(exitCode);
|
|
209
|
+
} catch (error) {
|
|
210
|
+
console.error('Error:', error instanceof Error ? error.message : String(error));
|
|
211
|
+
if (error instanceof Error && error.stack) {
|
|
212
|
+
console.error(error.stack);
|
|
213
|
+
}
|
|
214
|
+
process.exit(1);
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
// Check if running as CLI
|
|
219
|
+
if (import.meta.url === `file://${process.argv[1]}`) {
|
|
220
|
+
main();
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
// Export for programmatic use
|
|
224
|
+
export { main, parseArgs, showHelp };
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Multilingual Testing Framework
|
|
3
|
+
*
|
|
4
|
+
* Automated validation of HyperFixi's multilingual system.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
// Main orchestrator
|
|
8
|
+
export { TestOrchestrator, runMultilingualTests } from './orchestrator';
|
|
9
|
+
|
|
10
|
+
// Types
|
|
11
|
+
export type {
|
|
12
|
+
LanguageCode,
|
|
13
|
+
WordOrder,
|
|
14
|
+
Pattern,
|
|
15
|
+
PatternTranslation,
|
|
16
|
+
TestConfig,
|
|
17
|
+
ParseResult,
|
|
18
|
+
SizeResult,
|
|
19
|
+
LanguageResults,
|
|
20
|
+
TestResults,
|
|
21
|
+
Baseline,
|
|
22
|
+
RegressionResult,
|
|
23
|
+
BundleInfo,
|
|
24
|
+
BundleBuildOptions,
|
|
25
|
+
Reporter,
|
|
26
|
+
Validator,
|
|
27
|
+
SamplingStrategy,
|
|
28
|
+
} from './types';
|
|
29
|
+
|
|
30
|
+
// Pattern loading
|
|
31
|
+
export {
|
|
32
|
+
loadPatterns,
|
|
33
|
+
getPatternStatistics,
|
|
34
|
+
loadPatternsByCategory,
|
|
35
|
+
countPatternsByLanguage,
|
|
36
|
+
} from './pattern-loader';
|
|
37
|
+
|
|
38
|
+
// Bundle building
|
|
39
|
+
export {
|
|
40
|
+
findBundleForLanguages,
|
|
41
|
+
getBundleInfo,
|
|
42
|
+
buildBundle,
|
|
43
|
+
selectBundle,
|
|
44
|
+
listAvailableBundles,
|
|
45
|
+
bundleExists,
|
|
46
|
+
getBundleSize,
|
|
47
|
+
estimateBundleSize,
|
|
48
|
+
} from './bundle-builder';
|
|
49
|
+
|
|
50
|
+
// Validators
|
|
51
|
+
export {
|
|
52
|
+
ParseValidator,
|
|
53
|
+
validatePatterns,
|
|
54
|
+
validateAndSummarize,
|
|
55
|
+
} from './validators/parse-validator';
|
|
56
|
+
export {
|
|
57
|
+
SizeValidator,
|
|
58
|
+
validateBundleSize,
|
|
59
|
+
validateAndSummarizeSizes,
|
|
60
|
+
} from './validators/size-validator';
|
|
61
|
+
|
|
62
|
+
// Reporters
|
|
63
|
+
export { ConsoleReporter, createConsoleReporter } from './reporters/console-reporter';
|
|
64
|
+
export { JSONReporter, createJSONReporter } from './reporters/json-reporter';
|
|
65
|
+
export { RegressionReporter, createRegressionReporter } from './reporters/regression-reporter';
|
|
66
|
+
|
|
67
|
+
// CLI
|
|
68
|
+
export { main as runCLI, parseArgs, showHelp } from './cli';
|
|
@@ -0,0 +1,275 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Orchestrator - Main test runner that coordinates all components
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { exec } from 'node:child_process';
|
|
6
|
+
import { promisify } from 'node:util';
|
|
7
|
+
import { loadPatterns } from './pattern-loader';
|
|
8
|
+
import { selectBundle, getBundleInfo } from './bundle-builder';
|
|
9
|
+
import { ParseValidator } from './validators/parse-validator';
|
|
10
|
+
import { SizeValidator } from './validators/size-validator';
|
|
11
|
+
import { ConsoleReporter } from './reporters/console-reporter';
|
|
12
|
+
import { JSONReporter } from './reporters/json-reporter';
|
|
13
|
+
import { RegressionReporter } from './reporters/regression-reporter';
|
|
14
|
+
import type { TestConfig, TestResults, LanguageResults, LanguageCode, Reporter } from './types';
|
|
15
|
+
|
|
16
|
+
const execAsync = promisify(exec);
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Test Orchestrator
|
|
20
|
+
*
|
|
21
|
+
* Coordinates the entire multilingual test workflow:
|
|
22
|
+
* 1. Load patterns from database
|
|
23
|
+
* 2. Select/build bundles
|
|
24
|
+
* 3. Run validators
|
|
25
|
+
* 4. Report results
|
|
26
|
+
*/
|
|
27
|
+
export class TestOrchestrator {
|
|
28
|
+
private config: TestConfig;
|
|
29
|
+
private reporters: Reporter[] = [];
|
|
30
|
+
|
|
31
|
+
constructor(config: TestConfig) {
|
|
32
|
+
this.config = config;
|
|
33
|
+
this.setupReporters();
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Setup default reporters
|
|
38
|
+
*/
|
|
39
|
+
private setupReporters(): void {
|
|
40
|
+
// Always add console reporter
|
|
41
|
+
this.reporters.push(
|
|
42
|
+
new ConsoleReporter({
|
|
43
|
+
verbose: this.config.verbose || false,
|
|
44
|
+
useColors: true,
|
|
45
|
+
})
|
|
46
|
+
);
|
|
47
|
+
|
|
48
|
+
// Add JSON reporter for structured output
|
|
49
|
+
this.reporters.push(new JSONReporter('./test-results/results.json'));
|
|
50
|
+
|
|
51
|
+
// Add regression reporter if requested
|
|
52
|
+
if (this.config.regression) {
|
|
53
|
+
this.reporters.push(new RegressionReporter('./test-results/baseline.json'));
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Add custom reporter
|
|
59
|
+
*/
|
|
60
|
+
addReporter(reporter: Reporter): void {
|
|
61
|
+
this.reporters.push(reporter);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Run the test suite
|
|
66
|
+
*/
|
|
67
|
+
async run(): Promise<TestResults> {
|
|
68
|
+
// Notify reporters of test start
|
|
69
|
+
for (const reporter of this.reporters) {
|
|
70
|
+
reporter.reportStart(this.config);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
try {
|
|
74
|
+
// Get git commit for tracking
|
|
75
|
+
const commit = await this.getGitCommit();
|
|
76
|
+
|
|
77
|
+
// Load patterns
|
|
78
|
+
const patterns = await loadPatterns(this.config);
|
|
79
|
+
|
|
80
|
+
// Group patterns by language
|
|
81
|
+
const patternsByLanguage = this.groupByLanguage(patterns);
|
|
82
|
+
|
|
83
|
+
// Test each language
|
|
84
|
+
const languageResults: LanguageResults[] = [];
|
|
85
|
+
|
|
86
|
+
for (const [language, langPatterns] of patternsByLanguage.entries()) {
|
|
87
|
+
const result = await this.testLanguage(language as LanguageCode, langPatterns);
|
|
88
|
+
languageResults.push(result);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// Collect bundle information
|
|
92
|
+
const bundles: TestResults['bundles'] = {};
|
|
93
|
+
for (const langResult of languageResults) {
|
|
94
|
+
if (!bundles[langResult.bundle]) {
|
|
95
|
+
const bundleInfo = await getBundleInfo(langResult.bundle);
|
|
96
|
+
if (bundleInfo && bundleInfo.exists) {
|
|
97
|
+
bundles[langResult.bundle] = {
|
|
98
|
+
size: bundleInfo.size,
|
|
99
|
+
languages: bundleInfo.languages,
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
// Calculate summary
|
|
106
|
+
const summary = {
|
|
107
|
+
totalPatterns: patterns.length,
|
|
108
|
+
totalSuccess: languageResults.reduce((sum, r) => sum + r.parseSuccess, 0),
|
|
109
|
+
totalFailure: languageResults.reduce((sum, r) => sum + r.parseFailure, 0),
|
|
110
|
+
totalDuration: languageResults.reduce((sum, r) => sum + r.duration, 0),
|
|
111
|
+
overallStatus: this.calculateOverallStatus(languageResults),
|
|
112
|
+
};
|
|
113
|
+
|
|
114
|
+
const results: TestResults = {
|
|
115
|
+
timestamp: new Date().toISOString(),
|
|
116
|
+
commit,
|
|
117
|
+
config: this.config,
|
|
118
|
+
languageResults,
|
|
119
|
+
bundles,
|
|
120
|
+
summary,
|
|
121
|
+
};
|
|
122
|
+
|
|
123
|
+
// Report completion
|
|
124
|
+
for (const reporter of this.reporters) {
|
|
125
|
+
reporter.reportComplete(results);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
// Report regression if enabled
|
|
129
|
+
if (this.config.regression) {
|
|
130
|
+
const regressionReporter = this.reporters.find(r => r instanceof RegressionReporter) as
|
|
131
|
+
| RegressionReporter
|
|
132
|
+
| undefined;
|
|
133
|
+
|
|
134
|
+
if (regressionReporter?.hasBaseline()) {
|
|
135
|
+
const regressionResults = regressionReporter.getRegressionResults();
|
|
136
|
+
for (const reporter of this.reporters) {
|
|
137
|
+
if (reporter.reportRegression) {
|
|
138
|
+
reporter.reportRegression(regressionResults);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
return results;
|
|
145
|
+
} catch (error) {
|
|
146
|
+
// Report error
|
|
147
|
+
const err = error instanceof Error ? error : new Error(String(error));
|
|
148
|
+
for (const reporter of this.reporters) {
|
|
149
|
+
reporter.reportError(err);
|
|
150
|
+
}
|
|
151
|
+
throw err;
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
/**
|
|
156
|
+
* Test a single language
|
|
157
|
+
*/
|
|
158
|
+
private async testLanguage(language: LanguageCode, patterns: any[]): Promise<LanguageResults> {
|
|
159
|
+
const startTime = performance.now();
|
|
160
|
+
|
|
161
|
+
// Select bundle for this language
|
|
162
|
+
const bundle = this.config.bundle
|
|
163
|
+
? await getBundleInfo(this.config.bundle)
|
|
164
|
+
: await selectBundle([language], this.config.build || false);
|
|
165
|
+
|
|
166
|
+
if (!bundle || !bundle.exists) {
|
|
167
|
+
throw new Error(`Bundle not found for language: ${language}`);
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
// Notify reporters
|
|
171
|
+
for (const reporter of this.reporters) {
|
|
172
|
+
reporter.reportLanguageStart(language, bundle.name);
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
// Run parse validation
|
|
176
|
+
const parseValidator = new ParseValidator();
|
|
177
|
+
const parseResults = await parseValidator.validate(patterns);
|
|
178
|
+
|
|
179
|
+
// Calculate statistics
|
|
180
|
+
const parseSuccess = parseResults.filter(r => r.success).length;
|
|
181
|
+
const parseFailure = parseResults.length - parseSuccess;
|
|
182
|
+
const parseRate = parseResults.length > 0 ? parseSuccess / parseResults.length : 0;
|
|
183
|
+
const avgConfidence =
|
|
184
|
+
parseResults
|
|
185
|
+
.filter(r => r.success && r.confidence !== undefined)
|
|
186
|
+
.reduce((sum, r) => sum + (r.confidence || 0), 0) / (parseSuccess || 1);
|
|
187
|
+
|
|
188
|
+
// Determine status
|
|
189
|
+
const status = parseRate >= 0.95 ? 'pass' : parseRate >= 0.8 ? 'warning' : 'fail';
|
|
190
|
+
|
|
191
|
+
const result: LanguageResults = {
|
|
192
|
+
language,
|
|
193
|
+
bundle: bundle.name,
|
|
194
|
+
bundleSize: bundle.size,
|
|
195
|
+
parseResults,
|
|
196
|
+
parseSuccess,
|
|
197
|
+
parseFailure,
|
|
198
|
+
parseRate,
|
|
199
|
+
avgConfidence,
|
|
200
|
+
duration: performance.now() - startTime,
|
|
201
|
+
status,
|
|
202
|
+
};
|
|
203
|
+
|
|
204
|
+
// Notify reporters
|
|
205
|
+
for (const reporter of this.reporters) {
|
|
206
|
+
reporter.reportLanguageComplete(result);
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
return result;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
/**
|
|
213
|
+
* Group patterns by language
|
|
214
|
+
*/
|
|
215
|
+
private groupByLanguage(patterns: any[]): Map<string, any[]> {
|
|
216
|
+
const grouped = new Map<string, any[]>();
|
|
217
|
+
|
|
218
|
+
for (const pattern of patterns) {
|
|
219
|
+
const lang = pattern.language;
|
|
220
|
+
if (!grouped.has(lang)) {
|
|
221
|
+
grouped.set(lang, []);
|
|
222
|
+
}
|
|
223
|
+
grouped.get(lang)!.push(pattern);
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
return grouped;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
/**
|
|
230
|
+
* Calculate overall test status
|
|
231
|
+
*/
|
|
232
|
+
private calculateOverallStatus(results: LanguageResults[]): 'pass' | 'warning' | 'fail' {
|
|
233
|
+
const hasFail = results.some(r => r.status === 'fail');
|
|
234
|
+
const hasWarning = results.some(r => r.status === 'warning');
|
|
235
|
+
|
|
236
|
+
if (hasFail) return 'fail';
|
|
237
|
+
if (hasWarning) return 'warning';
|
|
238
|
+
return 'pass';
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
/**
|
|
242
|
+
* Get current git commit
|
|
243
|
+
*/
|
|
244
|
+
private async getGitCommit(): Promise<string | undefined> {
|
|
245
|
+
try {
|
|
246
|
+
const { stdout } = await execAsync('git rev-parse --short HEAD');
|
|
247
|
+
return stdout.trim();
|
|
248
|
+
} catch {
|
|
249
|
+
return undefined;
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
/**
|
|
254
|
+
* Get regression reporter
|
|
255
|
+
*/
|
|
256
|
+
getRegressionReporter(): RegressionReporter | undefined {
|
|
257
|
+
return this.reporters.find(r => r instanceof RegressionReporter) as
|
|
258
|
+
| RegressionReporter
|
|
259
|
+
| undefined;
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
/**
|
|
264
|
+
* Quick run helper
|
|
265
|
+
*/
|
|
266
|
+
export async function runMultilingualTests(config: Partial<TestConfig>): Promise<TestResults> {
|
|
267
|
+
const fullConfig: TestConfig = {
|
|
268
|
+
mode: 'quick',
|
|
269
|
+
quickModeLimit: 10,
|
|
270
|
+
...config,
|
|
271
|
+
};
|
|
272
|
+
|
|
273
|
+
const orchestrator = new TestOrchestrator(fullConfig);
|
|
274
|
+
return await orchestrator.run();
|
|
275
|
+
}
|