@testsmith/perfornium 0.6.4 → 0.6.5
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/cli/commands/distributed.js +2 -2
- package/dist/cli/commands/report.js +2 -2
- package/dist/cli/commands/run.js +2 -0
- package/dist/config/parser.js +2 -2
- package/dist/config/types/global-config.d.ts +82 -2
- package/dist/config/types/scenario-config.d.ts +2 -2
- package/dist/core/data/data-manager.d.ts +70 -0
- package/dist/core/data/data-manager.js +186 -0
- package/dist/core/data/data-provider.d.ts +85 -0
- package/dist/core/data/data-provider.js +468 -0
- package/dist/core/data/index.d.ts +8 -0
- package/dist/core/data/index.js +13 -0
- package/dist/core/execution/check-evaluator.d.ts +10 -0
- package/dist/core/execution/check-evaluator.js +79 -0
- package/dist/core/execution/data-extractor.d.ts +6 -0
- package/dist/core/execution/data-extractor.js +70 -0
- package/dist/core/execution/index.d.ts +3 -0
- package/dist/core/execution/index.js +9 -0
- package/dist/core/execution/json-payload-processor.d.ts +7 -0
- package/dist/core/execution/json-payload-processor.js +140 -0
- package/dist/core/factories/index.d.ts +2 -0
- package/dist/core/factories/index.js +7 -0
- package/dist/core/factories/output-handler-factory.d.ts +10 -0
- package/dist/core/factories/output-handler-factory.js +91 -0
- package/dist/core/factories/protocol-handler-factory.d.ts +12 -0
- package/dist/core/factories/protocol-handler-factory.js +96 -0
- package/dist/core/index.d.ts +3 -2
- package/dist/core/index.js +8 -3
- package/dist/core/reporting/dashboard-reporter.d.ts +17 -0
- package/dist/core/reporting/dashboard-reporter.js +127 -0
- package/dist/core/reporting/index.d.ts +1 -0
- package/dist/core/reporting/index.js +5 -0
- package/dist/core/step-executor.d.ts +6 -20
- package/dist/core/step-executor.js +72 -366
- package/dist/core/strategies/index.d.ts +2 -0
- package/dist/core/strategies/index.js +7 -0
- package/dist/core/strategies/scenario-selector.d.ts +13 -0
- package/dist/core/strategies/scenario-selector.js +37 -0
- package/dist/core/strategies/think-time-strategy.d.ts +15 -0
- package/dist/core/strategies/think-time-strategy.js +71 -0
- package/dist/core/test-runner.d.ts +4 -11
- package/dist/core/test-runner.js +105 -312
- package/dist/core/virtual-user.d.ts +7 -37
- package/dist/core/virtual-user.js +29 -269
- package/dist/dashboard/routes/api.d.ts +64 -0
- package/dist/dashboard/routes/api.js +569 -0
- package/dist/dashboard/routes/index.d.ts +2 -0
- package/dist/dashboard/routes/index.js +7 -0
- package/dist/dashboard/routes/static.d.ts +6 -0
- package/dist/dashboard/routes/static.js +76 -0
- package/dist/dashboard/server.d.ts +8 -84
- package/dist/dashboard/server.js +76 -2007
- package/dist/dashboard/services/file-scanner.d.ts +7 -0
- package/dist/dashboard/services/file-scanner.js +114 -0
- package/dist/dashboard/services/index.d.ts +5 -0
- package/dist/dashboard/services/index.js +13 -0
- package/dist/dashboard/services/influxdb-service.d.ts +41 -0
- package/dist/dashboard/services/influxdb-service.js +329 -0
- package/dist/dashboard/services/metrics-parser.d.ts +12 -0
- package/dist/dashboard/services/metrics-parser.js +209 -0
- package/dist/dashboard/services/results-manager.d.ts +17 -0
- package/dist/dashboard/services/results-manager.js +311 -0
- package/dist/dashboard/services/test-executor.d.ts +41 -0
- package/dist/dashboard/services/test-executor.js +250 -0
- package/dist/dashboard/services/workers-manager.d.ts +13 -0
- package/dist/dashboard/services/workers-manager.js +81 -0
- package/dist/dashboard/templates/index.html +122 -0
- package/dist/dashboard/templates/scripts/main.js +3280 -0
- package/dist/dashboard/templates/styles.css +402 -0
- package/dist/dashboard/types.d.ts +168 -0
- package/dist/dashboard/types.js +2 -0
- package/dist/distributed/result-aggregator.js +1 -3
- package/dist/metrics/batch/batch-processor.d.ts +27 -0
- package/dist/metrics/batch/batch-processor.js +85 -0
- package/dist/metrics/batch/index.d.ts +1 -0
- package/dist/metrics/batch/index.js +5 -0
- package/dist/metrics/collector.d.ts +46 -45
- package/dist/metrics/collector.js +179 -640
- package/dist/metrics/core/error-tracker.d.ts +9 -0
- package/dist/metrics/core/error-tracker.js +52 -0
- package/dist/metrics/core/index.d.ts +3 -0
- package/dist/metrics/core/index.js +9 -0
- package/dist/metrics/core/result-storage.d.ts +19 -0
- package/dist/metrics/core/result-storage.js +56 -0
- package/dist/metrics/core/statistics-engine.d.ts +27 -0
- package/dist/metrics/core/statistics-engine.js +91 -0
- package/dist/metrics/output/file-writer.d.ts +19 -0
- package/dist/metrics/output/file-writer.js +129 -0
- package/dist/metrics/output/index.d.ts +2 -0
- package/dist/metrics/output/index.js +10 -0
- package/dist/metrics/output/influxdb-writer.d.ts +89 -0
- package/dist/metrics/output/influxdb-writer.js +404 -0
- package/dist/metrics/realtime/dispatcher.d.ts +18 -0
- package/dist/metrics/realtime/dispatcher.js +45 -0
- package/dist/metrics/realtime/endpoints/graphite.d.ts +3 -0
- package/dist/metrics/realtime/endpoints/graphite.js +61 -0
- package/dist/metrics/realtime/endpoints/influxdb.d.ts +3 -0
- package/dist/metrics/realtime/endpoints/influxdb.js +35 -0
- package/dist/metrics/realtime/endpoints/webhook.d.ts +3 -0
- package/dist/metrics/realtime/endpoints/webhook.js +22 -0
- package/dist/metrics/realtime/endpoints/websocket.d.ts +3 -0
- package/dist/metrics/realtime/endpoints/websocket.js +25 -0
- package/dist/metrics/realtime/index.d.ts +5 -0
- package/dist/metrics/realtime/index.js +13 -0
- package/dist/metrics/reporting/index.d.ts +3 -0
- package/dist/metrics/reporting/index.js +9 -0
- package/dist/metrics/reporting/step-statistics.d.ts +6 -0
- package/dist/metrics/reporting/step-statistics.js +59 -0
- package/dist/metrics/reporting/summary-generator.d.ts +16 -0
- package/dist/metrics/reporting/summary-generator.js +46 -0
- package/dist/metrics/reporting/timeline-calculator.d.ts +7 -0
- package/dist/metrics/reporting/timeline-calculator.js +86 -0
- package/dist/metrics/types.d.ts +58 -0
- package/dist/outputs/csv.d.ts +2 -0
- package/dist/outputs/csv.js +21 -2
- package/dist/outputs/json.js +6 -2
- package/dist/protocols/rest/handler.d.ts +4 -53
- package/dist/protocols/rest/handler.js +73 -454
- package/dist/protocols/rest/request/auth-handler.d.ts +4 -0
- package/dist/protocols/rest/request/auth-handler.js +30 -0
- package/dist/protocols/rest/request/body-processor.d.ts +11 -0
- package/dist/protocols/rest/request/body-processor.js +62 -0
- package/dist/protocols/rest/request/index.d.ts +2 -0
- package/dist/protocols/rest/request/index.js +7 -0
- package/dist/protocols/rest/response/checks.d.ts +6 -0
- package/dist/protocols/rest/response/checks.js +71 -0
- package/dist/protocols/rest/response/index.d.ts +2 -0
- package/dist/protocols/rest/response/index.js +7 -0
- package/dist/protocols/rest/response/size-calculator.d.ts +12 -0
- package/dist/protocols/rest/response/size-calculator.js +64 -0
- package/dist/protocols/web/browser/highlight.d.ts +7 -0
- package/dist/protocols/web/browser/highlight.js +47 -0
- package/dist/protocols/web/browser/index.d.ts +4 -0
- package/dist/protocols/web/browser/index.js +11 -0
- package/dist/protocols/web/browser/manager.d.ts +20 -0
- package/dist/protocols/web/browser/manager.js +189 -0
- package/dist/protocols/web/browser/screenshot.d.ts +8 -0
- package/dist/protocols/web/browser/screenshot.js +69 -0
- package/dist/protocols/web/browser/storage.d.ts +5 -0
- package/dist/protocols/web/browser/storage.js +45 -0
- package/dist/protocols/web/commands/index.d.ts +5 -0
- package/dist/protocols/web/commands/index.js +11 -0
- package/dist/protocols/web/commands/interaction.d.ts +13 -0
- package/dist/protocols/web/commands/interaction.js +68 -0
- package/dist/protocols/web/commands/measurement.d.ts +16 -0
- package/dist/protocols/web/commands/measurement.js +33 -0
- package/dist/protocols/web/commands/navigation.d.ts +11 -0
- package/dist/protocols/web/commands/navigation.js +43 -0
- package/dist/protocols/web/commands/types.d.ts +12 -0
- package/dist/protocols/web/commands/types.js +2 -0
- package/dist/protocols/web/commands/verification.d.ts +11 -0
- package/dist/protocols/web/commands/verification.js +98 -0
- package/dist/protocols/web/handler.d.ts +19 -30
- package/dist/protocols/web/handler.js +160 -650
- package/dist/protocols/web/network/capture.d.ts +19 -0
- package/dist/protocols/web/network/capture.js +225 -0
- package/dist/protocols/web/network/filters.d.ts +5 -0
- package/dist/protocols/web/network/filters.js +49 -0
- package/dist/protocols/web/network/index.d.ts +4 -0
- package/dist/protocols/web/network/index.js +9 -0
- package/dist/protocols/web/network/types.d.ts +13 -0
- package/dist/protocols/web/network/types.js +2 -0
- package/dist/protocols/web/network/utils.d.ts +8 -0
- package/dist/protocols/web/network/utils.js +29 -0
- package/dist/reporting/chart-data/index.d.ts +5 -0
- package/dist/reporting/chart-data/index.js +13 -0
- package/dist/reporting/chart-data/network.d.ts +25 -0
- package/dist/reporting/chart-data/network.js +78 -0
- package/dist/reporting/chart-data/scenario.d.ts +37 -0
- package/dist/reporting/chart-data/scenario.js +76 -0
- package/dist/reporting/chart-data/step-statistics.d.ts +24 -0
- package/dist/reporting/chart-data/step-statistics.js +94 -0
- package/dist/reporting/chart-data/throughput.d.ts +16 -0
- package/dist/reporting/chart-data/throughput.js +24 -0
- package/dist/reporting/chart-data/timeline.d.ts +17 -0
- package/dist/reporting/chart-data/timeline.js +46 -0
- package/dist/reporting/handlebars-helpers.d.ts +1 -0
- package/dist/reporting/handlebars-helpers.js +63 -0
- package/dist/reporting/{enhanced-html-generator.d.ts → html-generator.d.ts} +1 -1
- package/dist/reporting/{enhanced-html-generator.js → html-generator.js} +10 -7
- package/dist/reporting/templates/{enhanced-report.hbs → report.hbs} +9 -9
- package/dist/utils/data-utils.d.ts +17 -0
- package/dist/utils/data-utils.js +129 -0
- package/dist/utils/template.js +2 -2
- package/package.json +5 -2
- package/dist/core/csv-data-provider.d.ts +0 -47
- package/dist/core/csv-data-provider.js +0 -265
- package/dist/reporting/generator.d.ts +0 -42
- package/dist/reporting/generator.js +0 -1217
- package/dist/reporting/templates/html.hbs +0 -2453
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
export interface CSVDataConfig {
|
|
2
|
-
file: string;
|
|
3
|
-
delimiter?: string;
|
|
4
|
-
encoding?: BufferEncoding;
|
|
5
|
-
skipEmptyLines?: boolean;
|
|
6
|
-
skipFirstLine?: boolean;
|
|
7
|
-
columns?: string[];
|
|
8
|
-
filter?: string;
|
|
9
|
-
randomize?: boolean;
|
|
10
|
-
cycleOnExhaustion?: boolean;
|
|
11
|
-
/** Map CSV column names to custom variable names: { "csv_column": "variable_name" } */
|
|
12
|
-
variables?: Record<string, string>;
|
|
13
|
-
}
|
|
14
|
-
export interface CSVDataRow {
|
|
15
|
-
[key: string]: string | number | boolean;
|
|
16
|
-
}
|
|
17
|
-
export declare class CSVDataProvider {
|
|
18
|
-
private static instances;
|
|
19
|
-
private static baseDir;
|
|
20
|
-
private filePath;
|
|
21
|
-
private data;
|
|
22
|
-
private originalData;
|
|
23
|
-
private currentIndex;
|
|
24
|
-
private config;
|
|
25
|
-
private isLoaded;
|
|
26
|
-
private isExhausted;
|
|
27
|
-
private globalIndex;
|
|
28
|
-
private accessCount;
|
|
29
|
-
private constructor();
|
|
30
|
-
static getInstance(config: CSVDataConfig): CSVDataProvider;
|
|
31
|
-
static setBaseDir(dir: string): void;
|
|
32
|
-
loadData(): Promise<void>;
|
|
33
|
-
/**
|
|
34
|
-
* Enhanced getNextRow - returns null when exhausted if cycleOnExhaustion is false
|
|
35
|
-
*/
|
|
36
|
-
getNextRow(vuId: number): Promise<CSVDataRow | null>;
|
|
37
|
-
/**
|
|
38
|
-
* Enhanced getUniqueRow - returns null when exhausted if cycleOnExhaustion is false
|
|
39
|
-
*/
|
|
40
|
-
getUniqueRow(vuId: number): Promise<CSVDataRow | null>;
|
|
41
|
-
/**
|
|
42
|
-
* Enhanced getRandomRow - returns null when exhausted if cycleOnExhaustion is false
|
|
43
|
-
*/
|
|
44
|
-
getRandomRow(vuId?: number): Promise<CSVDataRow | null>;
|
|
45
|
-
private filterData;
|
|
46
|
-
private shuffleArray;
|
|
47
|
-
}
|
|
@@ -1,265 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
-
if (k2 === undefined) k2 = k;
|
|
4
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
-
}
|
|
8
|
-
Object.defineProperty(o, k2, desc);
|
|
9
|
-
}) : (function(o, m, k, k2) {
|
|
10
|
-
if (k2 === undefined) k2 = k;
|
|
11
|
-
o[k2] = m[k];
|
|
12
|
-
}));
|
|
13
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
-
}) : function(o, v) {
|
|
16
|
-
o["default"] = v;
|
|
17
|
-
});
|
|
18
|
-
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
-
var ownKeys = function(o) {
|
|
20
|
-
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
-
var ar = [];
|
|
22
|
-
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
-
return ar;
|
|
24
|
-
};
|
|
25
|
-
return ownKeys(o);
|
|
26
|
-
};
|
|
27
|
-
return function (mod) {
|
|
28
|
-
if (mod && mod.__esModule) return mod;
|
|
29
|
-
var result = {};
|
|
30
|
-
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
-
__setModuleDefault(result, mod);
|
|
32
|
-
return result;
|
|
33
|
-
};
|
|
34
|
-
})();
|
|
35
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
|
-
};
|
|
38
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
-
exports.CSVDataProvider = void 0;
|
|
40
|
-
const fs = __importStar(require("fs"));
|
|
41
|
-
const path = __importStar(require("path"));
|
|
42
|
-
const papaparse_1 = __importDefault(require("papaparse"));
|
|
43
|
-
const logger_1 = require("../utils/logger");
|
|
44
|
-
/** Apply variable name mapping to a row */
|
|
45
|
-
function applyVariableMapping(row, mapping) {
|
|
46
|
-
if (!mapping || Object.keys(mapping).length === 0) {
|
|
47
|
-
return row;
|
|
48
|
-
}
|
|
49
|
-
const mappedRow = {};
|
|
50
|
-
for (const [csvColumn, value] of Object.entries(row)) {
|
|
51
|
-
// Use mapped name if defined, otherwise keep original column name
|
|
52
|
-
const variableName = mapping[csvColumn] || csvColumn;
|
|
53
|
-
mappedRow[variableName] = value;
|
|
54
|
-
}
|
|
55
|
-
return mappedRow;
|
|
56
|
-
}
|
|
57
|
-
class CSVDataProvider {
|
|
58
|
-
// Remove test termination callback - we don't need it anymore
|
|
59
|
-
constructor(filePath, config) {
|
|
60
|
-
this.data = [];
|
|
61
|
-
this.originalData = [];
|
|
62
|
-
this.currentIndex = 0;
|
|
63
|
-
this.isLoaded = false;
|
|
64
|
-
this.isExhausted = false;
|
|
65
|
-
this.globalIndex = 0; // For sequential tracking across all modes
|
|
66
|
-
this.accessCount = 0; // For random mode tracking
|
|
67
|
-
this.filePath = filePath;
|
|
68
|
-
this.config = config;
|
|
69
|
-
}
|
|
70
|
-
static getInstance(config) {
|
|
71
|
-
const fullPath = path.resolve(CSVDataProvider.baseDir, config.file);
|
|
72
|
-
const key = `${fullPath}-${JSON.stringify(config)}`;
|
|
73
|
-
if (!CSVDataProvider.instances.has(key)) {
|
|
74
|
-
CSVDataProvider.instances.set(key, new CSVDataProvider(fullPath, config));
|
|
75
|
-
}
|
|
76
|
-
return CSVDataProvider.instances.get(key);
|
|
77
|
-
}
|
|
78
|
-
static setBaseDir(dir) {
|
|
79
|
-
CSVDataProvider.baseDir = dir;
|
|
80
|
-
}
|
|
81
|
-
// ... existing loadData method stays the same ...
|
|
82
|
-
async loadData() {
|
|
83
|
-
if (this.isLoaded) {
|
|
84
|
-
return;
|
|
85
|
-
}
|
|
86
|
-
const fullPath = path.resolve(CSVDataProvider.baseDir, this.config.file);
|
|
87
|
-
if (!fs.existsSync(fullPath)) {
|
|
88
|
-
throw new Error(`CSV file not found: ${fullPath}`);
|
|
89
|
-
}
|
|
90
|
-
logger_1.logger.info(`📊 Loading CSV data from: ${this.config.file}`);
|
|
91
|
-
const encoding = this.config.encoding || 'utf8';
|
|
92
|
-
const csvContent = fs.readFileSync(fullPath, encoding);
|
|
93
|
-
const parseConfig = {
|
|
94
|
-
header: true,
|
|
95
|
-
delimiter: this.config.delimiter || ',',
|
|
96
|
-
skipEmptyLines: this.config.skipEmptyLines !== false,
|
|
97
|
-
dynamicTyping: true,
|
|
98
|
-
delimitersToGuess: [',', '\t', '|', ';']
|
|
99
|
-
};
|
|
100
|
-
const parseResult = papaparse_1.default.parse(csvContent, parseConfig);
|
|
101
|
-
if (parseResult.errors.length > 0) {
|
|
102
|
-
logger_1.logger.warn('CSV parsing warnings:', parseResult.errors);
|
|
103
|
-
}
|
|
104
|
-
this.originalData = parseResult.data;
|
|
105
|
-
if (this.config.skipFirstLine) {
|
|
106
|
-
this.originalData = this.originalData.slice(1);
|
|
107
|
-
}
|
|
108
|
-
if (this.config.columns && this.config.columns.length > 0) {
|
|
109
|
-
this.originalData = this.originalData.map(row => {
|
|
110
|
-
const filteredRow = {};
|
|
111
|
-
for (const col of this.config.columns) {
|
|
112
|
-
if (row.hasOwnProperty(col)) {
|
|
113
|
-
filteredRow[col] = row[col];
|
|
114
|
-
}
|
|
115
|
-
}
|
|
116
|
-
return filteredRow;
|
|
117
|
-
});
|
|
118
|
-
}
|
|
119
|
-
if (this.config.filter) {
|
|
120
|
-
this.originalData = this.filterData(this.originalData, this.config.filter);
|
|
121
|
-
}
|
|
122
|
-
if (this.config.randomize) {
|
|
123
|
-
this.originalData = this.shuffleArray([...this.originalData]);
|
|
124
|
-
}
|
|
125
|
-
this.data = [...this.originalData];
|
|
126
|
-
this.isLoaded = true;
|
|
127
|
-
logger_1.logger.info(`📊 Loaded ${this.data.length} rows from CSV: ${this.config.file}`);
|
|
128
|
-
}
|
|
129
|
-
/**
|
|
130
|
-
* Enhanced getNextRow - returns null when exhausted if cycleOnExhaustion is false
|
|
131
|
-
*/
|
|
132
|
-
async getNextRow(vuId) {
|
|
133
|
-
await this.loadData();
|
|
134
|
-
if (this.originalData.length === 0) {
|
|
135
|
-
logger_1.logger.warn(`📊 No data available in CSV: ${this.config.file}`);
|
|
136
|
-
return null;
|
|
137
|
-
}
|
|
138
|
-
// If cycling is disabled, use sequential exhaustible access
|
|
139
|
-
if (this.config.cycleOnExhaustion === false) {
|
|
140
|
-
if (this.globalIndex >= this.originalData.length) {
|
|
141
|
-
logger_1.logger.warn(`📊 VU${vuId}: CSV data exhausted in file: ${this.config.file} (next mode, cycling disabled)`);
|
|
142
|
-
return null; // Just return null, don't terminate test
|
|
143
|
-
}
|
|
144
|
-
const row = this.originalData[this.globalIndex];
|
|
145
|
-
this.globalIndex++;
|
|
146
|
-
logger_1.logger.info(`📊 VU${vuId} using sequential CSV row ${this.globalIndex}/${this.originalData.length}:`, Object.keys(row));
|
|
147
|
-
return applyVariableMapping({ ...row }, this.config.variables);
|
|
148
|
-
}
|
|
149
|
-
else {
|
|
150
|
-
// Normal round-robin behavior
|
|
151
|
-
const index = (vuId - 1) % this.originalData.length;
|
|
152
|
-
const row = this.originalData[index];
|
|
153
|
-
logger_1.logger.debug(`📊 VU${vuId} using CSV row ${index + 1}/${this.originalData.length}:`, Object.keys(row));
|
|
154
|
-
return applyVariableMapping({ ...row }, this.config.variables);
|
|
155
|
-
}
|
|
156
|
-
}
|
|
157
|
-
/**
|
|
158
|
-
* Enhanced getUniqueRow - returns null when exhausted if cycleOnExhaustion is false
|
|
159
|
-
*/
|
|
160
|
-
async getUniqueRow(vuId) {
|
|
161
|
-
await this.loadData();
|
|
162
|
-
if (this.data.length === 0) {
|
|
163
|
-
if (this.isExhausted && this.config.cycleOnExhaustion === false) {
|
|
164
|
-
logger_1.logger.warn(`📊 VU${vuId}: CSV data exhausted and cycling disabled: ${this.config.file}`);
|
|
165
|
-
return null; // Just return null, don't terminate test
|
|
166
|
-
}
|
|
167
|
-
logger_1.logger.warn(`📊 VU${vuId}: No more data available in CSV: ${this.config.file}`);
|
|
168
|
-
return null;
|
|
169
|
-
}
|
|
170
|
-
const row = this.data.shift();
|
|
171
|
-
logger_1.logger.info(`📊 VU${vuId} using unique CSV row (${this.data.length} remaining):`, Object.keys(row));
|
|
172
|
-
if (this.data.length === 0) {
|
|
173
|
-
this.isExhausted = true;
|
|
174
|
-
if (this.config.cycleOnExhaustion !== false) {
|
|
175
|
-
logger_1.logger.info(`📊 CSV data exhausted, reloading: ${this.config.file}`);
|
|
176
|
-
this.data = [...this.originalData];
|
|
177
|
-
if (this.config.randomize) {
|
|
178
|
-
this.data = this.shuffleArray(this.data);
|
|
179
|
-
}
|
|
180
|
-
this.isExhausted = false;
|
|
181
|
-
logger_1.logger.info(`📊 CSV data reloaded: ${this.data.length} rows available`);
|
|
182
|
-
}
|
|
183
|
-
else {
|
|
184
|
-
logger_1.logger.warn(`📊 CSV data exhausted, cycling disabled: ${this.config.file} - future requests will return null`);
|
|
185
|
-
}
|
|
186
|
-
}
|
|
187
|
-
return applyVariableMapping({ ...row }, this.config.variables);
|
|
188
|
-
}
|
|
189
|
-
/**
|
|
190
|
-
* Enhanced getRandomRow - returns null when exhausted if cycleOnExhaustion is false
|
|
191
|
-
*/
|
|
192
|
-
async getRandomRow(vuId = 0) {
|
|
193
|
-
await this.loadData();
|
|
194
|
-
if (this.originalData.length === 0) {
|
|
195
|
-
logger_1.logger.warn(`📊 No data available for random selection in CSV: ${this.config.file}`);
|
|
196
|
-
return null;
|
|
197
|
-
}
|
|
198
|
-
// If cycling is disabled, track accesses and stop after using all data once
|
|
199
|
-
if (this.config.cycleOnExhaustion === false) {
|
|
200
|
-
this.accessCount++;
|
|
201
|
-
if (this.accessCount > this.originalData.length) {
|
|
202
|
-
logger_1.logger.warn(`📊 VU${vuId}: CSV data exhausted in file: ${this.config.file} (random mode, cycling disabled, ${this.accessCount} accesses)`);
|
|
203
|
-
return null; // Just return null, don't terminate test
|
|
204
|
-
}
|
|
205
|
-
}
|
|
206
|
-
const randomIndex = Math.floor(Math.random() * this.originalData.length);
|
|
207
|
-
const row = this.originalData[randomIndex];
|
|
208
|
-
logger_1.logger.debug(`📊 VU${vuId} using random CSV row ${randomIndex + 1}/${this.originalData.length} (access ${this.accessCount}):`, Object.keys(row));
|
|
209
|
-
return applyVariableMapping({ ...row }, this.config.variables);
|
|
210
|
-
}
|
|
211
|
-
filterData(data, filterExpression) {
|
|
212
|
-
try {
|
|
213
|
-
const operators = ['!=', '>=', '<=', '=', '>', '<'];
|
|
214
|
-
let operator = '';
|
|
215
|
-
let parts = [];
|
|
216
|
-
for (const op of operators) {
|
|
217
|
-
if (filterExpression.includes(op)) {
|
|
218
|
-
operator = op;
|
|
219
|
-
parts = filterExpression.split(op).map(p => p.trim());
|
|
220
|
-
break;
|
|
221
|
-
}
|
|
222
|
-
}
|
|
223
|
-
if (parts.length !== 2) {
|
|
224
|
-
logger_1.logger.warn(`Invalid filter expression: ${filterExpression}`);
|
|
225
|
-
return data;
|
|
226
|
-
}
|
|
227
|
-
const [column, value] = parts;
|
|
228
|
-
const filterValue = isNaN(Number(value)) ? value.replace(/['"]/g, '') : Number(value);
|
|
229
|
-
return data.filter(row => {
|
|
230
|
-
const rowValue = row[column];
|
|
231
|
-
switch (operator) {
|
|
232
|
-
case '=':
|
|
233
|
-
return rowValue == filterValue;
|
|
234
|
-
case '!=':
|
|
235
|
-
return rowValue != filterValue;
|
|
236
|
-
case '>':
|
|
237
|
-
return Number(rowValue) > Number(filterValue);
|
|
238
|
-
case '<':
|
|
239
|
-
return Number(rowValue) < Number(filterValue);
|
|
240
|
-
case '>=':
|
|
241
|
-
return Number(rowValue) >= Number(filterValue);
|
|
242
|
-
case '<=':
|
|
243
|
-
return Number(rowValue) <= Number(filterValue);
|
|
244
|
-
default:
|
|
245
|
-
return true;
|
|
246
|
-
}
|
|
247
|
-
});
|
|
248
|
-
}
|
|
249
|
-
catch (error) {
|
|
250
|
-
logger_1.logger.warn(`Error applying filter "${filterExpression}":`, error);
|
|
251
|
-
return data;
|
|
252
|
-
}
|
|
253
|
-
}
|
|
254
|
-
shuffleArray(array) {
|
|
255
|
-
const shuffled = [...array];
|
|
256
|
-
for (let i = shuffled.length - 1; i > 0; i--) {
|
|
257
|
-
const j = Math.floor(Math.random() * (i + 1));
|
|
258
|
-
[shuffled[i], shuffled[j]] = [shuffled[j], shuffled[i]];
|
|
259
|
-
}
|
|
260
|
-
return shuffled;
|
|
261
|
-
}
|
|
262
|
-
}
|
|
263
|
-
exports.CSVDataProvider = CSVDataProvider;
|
|
264
|
-
CSVDataProvider.instances = new Map();
|
|
265
|
-
CSVDataProvider.baseDir = process.cwd();
|
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
import { TestResult, MetricsSummary } from '../metrics/types';
|
|
2
|
-
import { ReportConfig } from '../config/types';
|
|
3
|
-
export interface ReportData {
|
|
4
|
-
testName: string;
|
|
5
|
-
summary: MetricsSummary;
|
|
6
|
-
results: TestResult[];
|
|
7
|
-
}
|
|
8
|
-
export declare class HTMLReportGenerator {
|
|
9
|
-
constructor();
|
|
10
|
-
private registerHelpers;
|
|
11
|
-
generate(data: ReportData, config: ReportConfig, outputPath: string): Promise<void>;
|
|
12
|
-
/**
|
|
13
|
-
* Enhanced step statistics with min, max, and additional percentiles
|
|
14
|
-
* Only includes measurable results (verifications, not actions like click/fill)
|
|
15
|
-
*/
|
|
16
|
-
private calculateStepStatistics;
|
|
17
|
-
/**
|
|
18
|
-
* Calculate requests per second over time
|
|
19
|
-
*/
|
|
20
|
-
private calculateRequestsPerSecondData;
|
|
21
|
-
/**
|
|
22
|
-
* Calculate responses per second over time (successful responses)
|
|
23
|
-
*/
|
|
24
|
-
private calculateResponsesPerSecondData;
|
|
25
|
-
/**
|
|
26
|
-
* Generate proper filename with timestamp and test name from config
|
|
27
|
-
*/
|
|
28
|
-
generateFilename(testName: string, type: 'html' | 'csv' | 'json' | 'summary', configPath?: string): string;
|
|
29
|
-
/**
|
|
30
|
-
* Extract test name from YAML config file
|
|
31
|
-
*/
|
|
32
|
-
private extractTestNameFromConfig;
|
|
33
|
-
private calculateVURampupData;
|
|
34
|
-
private calculateTimelineData;
|
|
35
|
-
private prepareChartData;
|
|
36
|
-
private groupByScenario;
|
|
37
|
-
private calculateStepResponseTimes;
|
|
38
|
-
private calculateScenarioStatistics;
|
|
39
|
-
private getDefaultTemplatePath;
|
|
40
|
-
private getBuiltInTemplate;
|
|
41
|
-
private getEnhancedTemplate;
|
|
42
|
-
}
|