@testsmith/perfornium 0.6.3 → 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/recorder/native-recorder.js +2 -1
- 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
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.StorageManager = void 0;
|
|
4
|
+
const logger_1 = require("../../../utils/logger");
|
|
5
|
+
class StorageManager {
|
|
6
|
+
async clearStorageIfConfigured(page, context, clearConfig) {
|
|
7
|
+
if (!clearConfig)
|
|
8
|
+
return;
|
|
9
|
+
const config = typeof clearConfig === 'boolean'
|
|
10
|
+
? { local_storage: true, session_storage: true, cookies: true, cache: false }
|
|
11
|
+
: clearConfig;
|
|
12
|
+
try {
|
|
13
|
+
await page.goto('about:blank');
|
|
14
|
+
if (config.cookies !== false) {
|
|
15
|
+
await context.clearCookies();
|
|
16
|
+
logger_1.logger.debug('Cleared cookies');
|
|
17
|
+
}
|
|
18
|
+
if (config.local_storage !== false || config.session_storage !== false) {
|
|
19
|
+
await page.evaluate((opts) => {
|
|
20
|
+
if (opts.local_storage !== false) {
|
|
21
|
+
try {
|
|
22
|
+
localStorage.clear();
|
|
23
|
+
}
|
|
24
|
+
catch (e) { /* ignore */ }
|
|
25
|
+
}
|
|
26
|
+
if (opts.session_storage !== false) {
|
|
27
|
+
try {
|
|
28
|
+
sessionStorage.clear();
|
|
29
|
+
}
|
|
30
|
+
catch (e) { /* ignore */ }
|
|
31
|
+
}
|
|
32
|
+
}, { local_storage: config.local_storage, session_storage: config.session_storage });
|
|
33
|
+
if (config.local_storage !== false)
|
|
34
|
+
logger_1.logger.debug('Cleared localStorage');
|
|
35
|
+
if (config.session_storage !== false)
|
|
36
|
+
logger_1.logger.debug('Cleared sessionStorage');
|
|
37
|
+
}
|
|
38
|
+
logger_1.logger.debug('Browser storage cleared');
|
|
39
|
+
}
|
|
40
|
+
catch (error) {
|
|
41
|
+
logger_1.logger.warn('Failed to clear storage:', error);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
exports.StorageManager = StorageManager;
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { NavigationCommands } from './navigation';
|
|
2
|
+
export { InteractionCommands } from './interaction';
|
|
3
|
+
export { VerificationCommands } from './verification';
|
|
4
|
+
export { MeasurementCommands } from './measurement';
|
|
5
|
+
export { CommandResult, CommandHandler, HighlightFunction } from './types';
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.MeasurementCommands = exports.VerificationCommands = exports.InteractionCommands = exports.NavigationCommands = void 0;
|
|
4
|
+
var navigation_1 = require("./navigation");
|
|
5
|
+
Object.defineProperty(exports, "NavigationCommands", { enumerable: true, get: function () { return navigation_1.NavigationCommands; } });
|
|
6
|
+
var interaction_1 = require("./interaction");
|
|
7
|
+
Object.defineProperty(exports, "InteractionCommands", { enumerable: true, get: function () { return interaction_1.InteractionCommands; } });
|
|
8
|
+
var verification_1 = require("./verification");
|
|
9
|
+
Object.defineProperty(exports, "VerificationCommands", { enumerable: true, get: function () { return verification_1.VerificationCommands; } });
|
|
10
|
+
var measurement_1 = require("./measurement");
|
|
11
|
+
Object.defineProperty(exports, "MeasurementCommands", { enumerable: true, get: function () { return measurement_1.MeasurementCommands; } });
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { Page } from 'playwright';
|
|
2
|
+
import { WebAction } from '../../../config';
|
|
3
|
+
import { CommandResult, HighlightFunction } from './types';
|
|
4
|
+
export declare class InteractionCommands {
|
|
5
|
+
private highlightElement;
|
|
6
|
+
constructor(highlightElement: HighlightFunction);
|
|
7
|
+
handleClick(page: Page, action: WebAction): Promise<CommandResult>;
|
|
8
|
+
handleFill(page: Page, action: WebAction): Promise<CommandResult>;
|
|
9
|
+
handleSelect(page: Page, action: WebAction): Promise<CommandResult>;
|
|
10
|
+
handlePress(page: Page, action: WebAction): Promise<CommandResult>;
|
|
11
|
+
handleHover(page: Page, action: WebAction): Promise<CommandResult>;
|
|
12
|
+
handleEvaluate(page: Page, action: WebAction): Promise<CommandResult>;
|
|
13
|
+
}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.InteractionCommands = void 0;
|
|
4
|
+
class InteractionCommands {
|
|
5
|
+
constructor(highlightElement) {
|
|
6
|
+
this.highlightElement = highlightElement;
|
|
7
|
+
}
|
|
8
|
+
async handleClick(page, action) {
|
|
9
|
+
const timeout = action.timeout || 30000;
|
|
10
|
+
const selector = action.selector;
|
|
11
|
+
await page.waitForSelector(selector, {
|
|
12
|
+
state: 'visible',
|
|
13
|
+
timeout
|
|
14
|
+
});
|
|
15
|
+
await this.highlightElement(page, selector);
|
|
16
|
+
await page.locator(selector).click({ timeout });
|
|
17
|
+
return { clicked: selector };
|
|
18
|
+
}
|
|
19
|
+
async handleFill(page, action) {
|
|
20
|
+
const timeout = action.timeout || 30000;
|
|
21
|
+
await page.waitForSelector(action.selector, {
|
|
22
|
+
state: 'visible',
|
|
23
|
+
timeout
|
|
24
|
+
});
|
|
25
|
+
await this.highlightElement(page, action.selector);
|
|
26
|
+
await page.locator(action.selector).fill(action.value, { timeout });
|
|
27
|
+
return { filled: action.selector, value: action.value };
|
|
28
|
+
}
|
|
29
|
+
async handleSelect(page, action) {
|
|
30
|
+
const timeout = action.timeout || 30000;
|
|
31
|
+
await page.waitForSelector(action.selector, {
|
|
32
|
+
state: 'visible',
|
|
33
|
+
timeout
|
|
34
|
+
});
|
|
35
|
+
await this.highlightElement(page, action.selector);
|
|
36
|
+
await page.locator(action.selector).selectOption(action.value, { timeout });
|
|
37
|
+
return { selected: action.selector, value: action.value };
|
|
38
|
+
}
|
|
39
|
+
async handlePress(page, action) {
|
|
40
|
+
const timeout = action.timeout || 30000;
|
|
41
|
+
const key = action.key;
|
|
42
|
+
if (action.selector) {
|
|
43
|
+
await page.waitForSelector(action.selector, {
|
|
44
|
+
state: 'visible',
|
|
45
|
+
timeout
|
|
46
|
+
});
|
|
47
|
+
await this.highlightElement(page, action.selector);
|
|
48
|
+
await page.locator(action.selector).press(key, { timeout });
|
|
49
|
+
return { pressed: key, selector: action.selector };
|
|
50
|
+
}
|
|
51
|
+
else {
|
|
52
|
+
await page.keyboard.press(key);
|
|
53
|
+
return { pressed: key };
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
async handleHover(page, action) {
|
|
57
|
+
await page.hover(action.selector);
|
|
58
|
+
return { hovered: action.selector };
|
|
59
|
+
}
|
|
60
|
+
async handleEvaluate(page, action) {
|
|
61
|
+
if (action.script) {
|
|
62
|
+
const result = await page.evaluate(action.script);
|
|
63
|
+
return { evaluation_result: result };
|
|
64
|
+
}
|
|
65
|
+
throw new Error('No script provided for evaluate command');
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
exports.InteractionCommands = InteractionCommands;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { Page } from 'playwright';
|
|
2
|
+
import { WebAction } from '../../../config';
|
|
3
|
+
import { CommandResult } from './types';
|
|
4
|
+
import { CoreWebVitals, VerificationStepMetrics } from '../core-web-vitals';
|
|
5
|
+
export declare class MeasurementCommands {
|
|
6
|
+
handleMeasureWebVitals(page: Page, action: WebAction): Promise<CommandResult & {
|
|
7
|
+
web_vitals: CoreWebVitals;
|
|
8
|
+
}>;
|
|
9
|
+
handlePerformanceAudit(page: Page, action: WebAction, verificationMetrics?: VerificationStepMetrics): Promise<CommandResult>;
|
|
10
|
+
handleScreenshot(page: Page, action: WebAction): Promise<CommandResult>;
|
|
11
|
+
collectWebVitalsIfNeeded(page: Page, action: WebAction, shouldCollect: boolean): Promise<CoreWebVitals | undefined>;
|
|
12
|
+
evaluateVitals(webVitals: CoreWebVitals, thresholds?: any): {
|
|
13
|
+
score: 'good' | 'needs-improvement' | 'poor';
|
|
14
|
+
details: any;
|
|
15
|
+
};
|
|
16
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.MeasurementCommands = void 0;
|
|
4
|
+
const core_web_vitals_1 = require("../core-web-vitals");
|
|
5
|
+
class MeasurementCommands {
|
|
6
|
+
async handleMeasureWebVitals(page, action) {
|
|
7
|
+
const webVitals = await core_web_vitals_1.CoreWebVitalsCollector.collectVitals(page, action.webVitalsWaitTime || 3000);
|
|
8
|
+
return { web_vitals: webVitals };
|
|
9
|
+
}
|
|
10
|
+
async handlePerformanceAudit(page, action, verificationMetrics) {
|
|
11
|
+
const performanceMetrics = await core_web_vitals_1.WebPerformanceCollector.collectAllMetrics(page, verificationMetrics);
|
|
12
|
+
return { performance_audit: performanceMetrics };
|
|
13
|
+
}
|
|
14
|
+
async handleScreenshot(page, action) {
|
|
15
|
+
const screenshot = await page.screenshot({
|
|
16
|
+
type: 'png',
|
|
17
|
+
fullPage: action.options?.fullPage || false
|
|
18
|
+
});
|
|
19
|
+
return {
|
|
20
|
+
screenshot: screenshot.length,
|
|
21
|
+
screenshot_data: action.options?.includeData ? screenshot.toString('base64') : undefined
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
async collectWebVitalsIfNeeded(page, action, shouldCollect) {
|
|
25
|
+
if (!shouldCollect)
|
|
26
|
+
return undefined;
|
|
27
|
+
return core_web_vitals_1.CoreWebVitalsCollector.collectVitals(page, action.webVitalsWaitTime || 1000);
|
|
28
|
+
}
|
|
29
|
+
evaluateVitals(webVitals, thresholds) {
|
|
30
|
+
return core_web_vitals_1.CoreWebVitalsCollector.evaluateVitals(webVitals, thresholds);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
exports.MeasurementCommands = MeasurementCommands;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { Page } from 'playwright';
|
|
2
|
+
import { WebAction, BrowserConfig } from '../../../config';
|
|
3
|
+
import { CommandResult } from './types';
|
|
4
|
+
export declare class NavigationCommands {
|
|
5
|
+
private config;
|
|
6
|
+
constructor(config: BrowserConfig);
|
|
7
|
+
handleGoto(page: Page, action: WebAction): Promise<CommandResult>;
|
|
8
|
+
handleWaitForLoadState(page: Page, action: WebAction): Promise<CommandResult>;
|
|
9
|
+
handleNetworkIdle(page: Page, action: WebAction): Promise<CommandResult>;
|
|
10
|
+
handleDomReady(page: Page, action: WebAction): Promise<CommandResult>;
|
|
11
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.NavigationCommands = void 0;
|
|
4
|
+
class NavigationCommands {
|
|
5
|
+
constructor(config) {
|
|
6
|
+
this.config = config;
|
|
7
|
+
}
|
|
8
|
+
async handleGoto(page, action) {
|
|
9
|
+
const fullUrl = action.url?.startsWith('http')
|
|
10
|
+
? action.url
|
|
11
|
+
: `${this.config.base_url}${action.url || ''}`;
|
|
12
|
+
const response = await page.goto(fullUrl, {
|
|
13
|
+
timeout: action.timeout || 30000,
|
|
14
|
+
waitUntil: action.waitUntil || 'domcontentloaded'
|
|
15
|
+
});
|
|
16
|
+
return {
|
|
17
|
+
url: page.url(),
|
|
18
|
+
status: response?.status(),
|
|
19
|
+
headers: await response?.allHeaders(),
|
|
20
|
+
loading_time: Date.now() - performance.now()
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
async handleWaitForLoadState(page, action) {
|
|
24
|
+
const waitUntil = action.waitUntil === 'commit' ? 'load' : (action.waitUntil || 'load');
|
|
25
|
+
await page.waitForLoadState(waitUntil, {
|
|
26
|
+
timeout: action.timeout || 30000
|
|
27
|
+
});
|
|
28
|
+
return { load_state: waitUntil };
|
|
29
|
+
}
|
|
30
|
+
async handleNetworkIdle(page, action) {
|
|
31
|
+
await page.waitForLoadState('networkidle', {
|
|
32
|
+
timeout: action.networkIdleTimeout || 30000
|
|
33
|
+
});
|
|
34
|
+
return { network_idle: true };
|
|
35
|
+
}
|
|
36
|
+
async handleDomReady(page, action) {
|
|
37
|
+
await page.waitForLoadState('domcontentloaded', {
|
|
38
|
+
timeout: action.timeout || 30000
|
|
39
|
+
});
|
|
40
|
+
return { dom_ready: true };
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
exports.NavigationCommands = NavigationCommands;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { Page } from 'playwright';
|
|
2
|
+
import { WebAction } from '../../../config';
|
|
3
|
+
export interface CommandResult {
|
|
4
|
+
[key: string]: any;
|
|
5
|
+
action_time?: number;
|
|
6
|
+
}
|
|
7
|
+
export interface CommandHandler {
|
|
8
|
+
execute(page: Page, action: WebAction): Promise<CommandResult>;
|
|
9
|
+
}
|
|
10
|
+
export interface HighlightFunction {
|
|
11
|
+
(page: Page, selector: string): Promise<void>;
|
|
12
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { Page } from 'playwright';
|
|
2
|
+
import { WebAction } from '../../../config';
|
|
3
|
+
import { CommandResult } from './types';
|
|
4
|
+
export declare class VerificationCommands {
|
|
5
|
+
handleWaitForSelector(page: Page, action: WebAction): Promise<CommandResult>;
|
|
6
|
+
handleVerifyExists(page: Page, action: WebAction): Promise<CommandResult>;
|
|
7
|
+
handleVerifyVisible(page: Page, action: WebAction): Promise<CommandResult>;
|
|
8
|
+
handleVerifyText(page: Page, action: WebAction): Promise<CommandResult>;
|
|
9
|
+
handleVerifyContains(page: Page, action: WebAction): Promise<CommandResult>;
|
|
10
|
+
handleVerifyNotExists(page: Page, action: WebAction): Promise<CommandResult>;
|
|
11
|
+
}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.VerificationCommands = void 0;
|
|
4
|
+
class VerificationCommands {
|
|
5
|
+
async handleWaitForSelector(page, action) {
|
|
6
|
+
await page.waitForSelector(action.selector, {
|
|
7
|
+
timeout: action.timeout || 30000
|
|
8
|
+
});
|
|
9
|
+
return { waited_for: action.selector };
|
|
10
|
+
}
|
|
11
|
+
async handleVerifyExists(page, action) {
|
|
12
|
+
await page.waitForSelector(action.selector, {
|
|
13
|
+
state: 'attached',
|
|
14
|
+
timeout: action.timeout || 30000
|
|
15
|
+
});
|
|
16
|
+
const elementCount = await page.locator(action.selector).count();
|
|
17
|
+
return {
|
|
18
|
+
verified: 'exists',
|
|
19
|
+
selector: action.selector,
|
|
20
|
+
name: action.name,
|
|
21
|
+
found_elements: elementCount,
|
|
22
|
+
element_count: elementCount
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
async handleVerifyVisible(page, action) {
|
|
26
|
+
await page.waitForSelector(action.selector, {
|
|
27
|
+
state: 'visible',
|
|
28
|
+
timeout: action.timeout || 30000
|
|
29
|
+
});
|
|
30
|
+
return {
|
|
31
|
+
verified: 'visible',
|
|
32
|
+
selector: action.selector,
|
|
33
|
+
name: action.name,
|
|
34
|
+
is_visible: true
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
async handleVerifyText(page, action) {
|
|
38
|
+
await page.waitForSelector(action.selector, {
|
|
39
|
+
state: 'attached',
|
|
40
|
+
timeout: action.timeout || 30000
|
|
41
|
+
});
|
|
42
|
+
const textLocator = page.locator(action.selector);
|
|
43
|
+
const actualText = await textLocator.textContent();
|
|
44
|
+
const expectedText = action.expected_text;
|
|
45
|
+
if (!actualText || !actualText.includes(expectedText)) {
|
|
46
|
+
throw new Error(`Verification failed: Element "${action.selector}" text "${actualText}" does not contain expected text "${expectedText}"${action.name ? ` (${action.name})` : ''}`);
|
|
47
|
+
}
|
|
48
|
+
return {
|
|
49
|
+
verified: 'text',
|
|
50
|
+
selector: action.selector,
|
|
51
|
+
name: action.name,
|
|
52
|
+
expected_text: expectedText,
|
|
53
|
+
actual_text: actualText,
|
|
54
|
+
text_match: true
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
async handleVerifyContains(page, action) {
|
|
58
|
+
await page.waitForSelector(action.selector, {
|
|
59
|
+
state: 'attached',
|
|
60
|
+
timeout: action.timeout || 30000
|
|
61
|
+
});
|
|
62
|
+
const textLocator = page.locator(action.selector);
|
|
63
|
+
const actualText = await textLocator.textContent();
|
|
64
|
+
const expectedText = action.value;
|
|
65
|
+
if (!actualText || !actualText.includes(expectedText)) {
|
|
66
|
+
throw new Error(`Verification failed: Element "${action.selector}" text "${actualText}" does not contain "${expectedText}"${action.name ? ` (${action.name})` : ''}`);
|
|
67
|
+
}
|
|
68
|
+
return {
|
|
69
|
+
verified: 'contains',
|
|
70
|
+
selector: action.selector,
|
|
71
|
+
name: action.name,
|
|
72
|
+
expected_text: expectedText,
|
|
73
|
+
actual_text: actualText,
|
|
74
|
+
text_match: true
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
async handleVerifyNotExists(page, action) {
|
|
78
|
+
try {
|
|
79
|
+
await page.waitForSelector(action.selector, {
|
|
80
|
+
state: 'detached',
|
|
81
|
+
timeout: action.timeout || 5000
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
catch (error) {
|
|
85
|
+
const count = await page.locator(action.selector).count();
|
|
86
|
+
if (count > 0) {
|
|
87
|
+
throw new Error(`Verification failed: Element "${action.selector}" exists but should not exist${action.name ? ` (${action.name})` : ''}`);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
return {
|
|
91
|
+
verified: 'not_exists',
|
|
92
|
+
selector: action.selector,
|
|
93
|
+
name: action.name,
|
|
94
|
+
found_elements: 0
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
exports.VerificationCommands = VerificationCommands;
|
|
@@ -1,30 +1,31 @@
|
|
|
1
1
|
import { ProtocolHandler, ProtocolResult } from '../base';
|
|
2
2
|
import { VUContext, WebAction, BrowserConfig } from '../../config';
|
|
3
3
|
import { VerificationStepMetrics } from './core-web-vitals';
|
|
4
|
+
import { CapturedNetworkCall } from '../../metrics/types';
|
|
5
|
+
import { NetworkCallCallback } from './network';
|
|
4
6
|
export declare class WebHandler implements ProtocolHandler {
|
|
5
|
-
private browsers;
|
|
6
|
-
private contexts;
|
|
7
|
-
private pages;
|
|
8
|
-
private verificationMetrics;
|
|
9
7
|
private config;
|
|
10
|
-
|
|
8
|
+
private verificationMetrics;
|
|
9
|
+
private browserManager;
|
|
10
|
+
private networkManager;
|
|
11
|
+
private storageManager;
|
|
12
|
+
private highlighter;
|
|
13
|
+
private screenshotCapture;
|
|
14
|
+
private navigationCommands;
|
|
15
|
+
private interactionCommands;
|
|
16
|
+
private verificationCommands;
|
|
17
|
+
private measurementCommands;
|
|
18
|
+
constructor(config: BrowserConfig, onNetworkCall?: NetworkCallCallback);
|
|
11
19
|
initialize(): Promise<void>;
|
|
12
20
|
execute(action: WebAction, context: VUContext): Promise<ProtocolResult>;
|
|
13
|
-
private
|
|
14
|
-
private
|
|
15
|
-
private
|
|
16
|
-
private
|
|
17
|
-
private
|
|
18
|
-
private handleWaitForSelector;
|
|
19
|
-
private handleVerifyExists;
|
|
20
|
-
private handleVerifyVisible;
|
|
21
|
-
private handleVerifyText;
|
|
22
|
-
private handleVerifyContains;
|
|
23
|
-
private handleVerifyNotExists;
|
|
24
|
-
private handleLegacyAction;
|
|
21
|
+
private executeWithTiming;
|
|
22
|
+
private executeInteractionWithMeasurement;
|
|
23
|
+
private executeVerificationWithMeasurement;
|
|
24
|
+
private executeVerification;
|
|
25
|
+
private handleExecutionError;
|
|
25
26
|
private getPage;
|
|
26
|
-
private createBrowserForVU;
|
|
27
27
|
getVerificationMetrics(vuId: number): VerificationStepMetrics[];
|
|
28
|
+
getNetworkCalls(vuId: number): CapturedNetworkCall[];
|
|
28
29
|
getAggregatedVerificationMetrics(): {
|
|
29
30
|
total_verifications: number;
|
|
30
31
|
success_rate: number;
|
|
@@ -39,16 +40,4 @@ export declare class WebHandler implements ProtocolHandler {
|
|
|
39
40
|
connected: boolean;
|
|
40
41
|
} | null;
|
|
41
42
|
getActiveVUCount(): number;
|
|
42
|
-
/**
|
|
43
|
-
* Clear browser storage (localStorage, sessionStorage, cookies) if configured
|
|
44
|
-
*/
|
|
45
|
-
private clearStorageIfConfigured;
|
|
46
|
-
/**
|
|
47
|
-
* Highlight an element before interacting with it (for debugging)
|
|
48
|
-
*/
|
|
49
|
-
private highlightElement;
|
|
50
|
-
/**
|
|
51
|
-
* Capture a screenshot when a test step fails
|
|
52
|
-
*/
|
|
53
|
-
private captureFailureScreenshot;
|
|
54
43
|
}
|