@loadstrike/loadstrike-sdk 1.0.27101 → 1.0.29201
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/README.md +3 -3
- package/dist/cjs/index.js +27 -2
- package/dist/cjs/local.js +71 -1
- package/dist/cjs/runtime.js +314 -2
- package/dist/cjs/sinks.js +262 -1
- package/dist/cjs/transports.js +326 -13
- package/dist/esm/index.js +3 -3
- package/dist/esm/local.js +71 -1
- package/dist/esm/runtime.js +308 -1
- package/dist/esm/sinks.js +249 -0
- package/dist/esm/transports.js +319 -12
- package/dist/types/contracts.d.ts +12 -0
- package/dist/types/index.d.ts +5 -5
- package/dist/types/runtime.d.ts +67 -0
- package/dist/types/sinks.d.ts +136 -0
- package/dist/types/transports.d.ts +114 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -9,9 +9,9 @@ LoadStrike is a developer-first load testing SDK for Node.js applications, servi
|
|
|
9
9
|
- Exercise HTTP and event-driven workflows across multiple steps.
|
|
10
10
|
- Apply load simulations, thresholds, and custom metrics to real transactions.
|
|
11
11
|
- Split a single load profile across weighted scenario mixes.
|
|
12
|
-
- Generate local reports and, on
|
|
12
|
+
- Generate local reports and, on Enterprise, publish observability data to supported sinks.
|
|
13
13
|
|
|
14
|
-
Built-in transport coverage includes HTTP, Kafka, RabbitMQ, NATS, Redis Streams, Azure Event Hubs, Push Diffusion, and delegate-based custom streams. Local report output supports HTML, Markdown, TXT, and CSV, and
|
|
14
|
+
Built-in transport coverage includes HTTP, Kafka, RabbitMQ, NATS, Redis Streams, Azure Event Hubs, Push Diffusion, and delegate-based custom streams. Local report output supports HTML, Markdown, TXT, and CSV, and Enterprise can publish to InfluxDB, TimescaleDB, Grafana Loki, Datadog, Splunk HEC, OpenTelemetry Collector, and the expanded built-in sink family.
|
|
15
15
|
|
|
16
16
|
## Requirements
|
|
17
17
|
|
|
@@ -56,7 +56,7 @@ const result = await LoadStrikeRunner
|
|
|
56
56
|
|
|
57
57
|
## Traffic Mixes
|
|
58
58
|
|
|
59
|
-
Use `LoadStrikeTrafficMix` on
|
|
59
|
+
Use `LoadStrikeTrafficMix` on Pro and Enterprise plans when one total load profile should be distributed across multiple scenario lanes. For example, a 1000 requests-per-second profile with scenario weights of 60, 30, and 10 sends roughly 600 requests per second to the first scenario, 300 to the second, and 100 to the third.
|
|
60
60
|
|
|
61
61
|
Each lane is still a normal scenario with its own named steps, thresholds, reports, and portal results. Register the mix with `LoadStrikeRunner.registerTrafficMix(...)` or add it to a runner with `.addTrafficMix(...)`.
|
|
62
62
|
|
package/dist/cjs/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
4
|
-
exports.TimescaleDbReportingSinkOptions = exports.TimescaleDbReportingSink = exports.SplunkReportingSinkOptions = exports.SplunkReportingSink = exports.PortalReportingSink = exports.OtelCollectorReportingSinkOptions = exports.OtelCollectorReportingSink = exports.InfluxDbReportingSinkOptions = exports.InfluxDbReportingSink = exports.GrafanaLokiReportingSinkOptions = exports.GrafanaLokiReportingSink = exports.DatadogReportingSinkOptions = exports.DatadogReportingSink = exports.HttpAuthOptions = void 0;
|
|
3
|
+
exports.SqsEndpointDefinition = exports.AzureEventHubsEndpointDefinition = exports.RedisStreamsEndpointDefinition = exports.NatsEndpointDefinition = exports.RabbitMqEndpointDefinition = exports.KafkaSaslOptions = exports.KafkaEndpointDefinition = exports.HttpEndpointDefinition = exports.TrafficEndpointDefinition = exports.LOADSTRIKE_TRACE_ID_TRACKING_FIELD = exports.LOADSTRIKE_TRACE_ID_HEADER = exports.TrackingFieldSelector = exports.TrackingPayloadBuilder = exports.RedisCorrelationStore = exports.RedisCorrelationStoreOptions = exports.InMemoryCorrelationStore = exports.CrossPlatformTrackingRuntime = exports.CorrelationStoreConfiguration = exports.LoadStrikeThreshold = exports.LoadStrikeStep = exports.LoadStrikeGauge = exports.LoadStrikeCounter = exports.LoadStrikeMetric = exports.CrossPlatformTrackingConfiguration = exports.LoadStrikeTrafficMix = exports.LoadStrikeSimulation = exports.LoadStrikeScenarioShare = exports.LoadStrikeScenario = exports.LoadStrikeRunner = exports.LoadStrikeOperationType = exports.LoadStrikeScenarioOperation = exports.LoadStrikeLogLevel = exports.LoadStrikeResponse = exports.LoadStrikeReportFormat = exports.LoadStrikeNodeType = exports.LoadStrikePluginDataTable = exports.LoadStrikePluginData = exports.LoadStrikeBrowserWebVitalsCollector = exports.LoadStrikeBrowserWebVitals = exports.LoadStrikeAccessibilityScanner = exports.LoadStrikeAccessibilityCiGate = exports.LoadStrikeAccessibilityBaseline = exports.LoadStrikeAccessibilityAdapters = exports.LoadStrikeAccessibility = exports.LoadStrikeContext = exports.ScenarioTrackingExtensions = exports.CrossPlatformScenarioConfigurator = exports.LoadStrikeAutopilotReadiness = exports.LoadStrikeAutopilotResult = exports.LoadStrikeAutopilot = void 0;
|
|
4
|
+
exports.TimescaleDbReportingSinkOptions = exports.TimescaleDbReportingSink = exports.StatsDReportingSink = exports.SplunkReportingSinkOptions = exports.SplunkReportingSink = exports.PrometheusRemoteWriteReportingSink = exports.PortalReportingSink = exports.OpenSearchReportingSink = exports.OtelCollectorReportingSinkOptions = exports.OtelCollectorReportingSink = exports.NewRelicReportingSink = exports.NetdataStatsDReportingSink = exports.KafkaReportingSink = exports.JsonlFileReportingSink = exports.InfluxDbReportingSinkOptions = exports.InfluxDbReportingSink = exports.GenericWebhookReportingSink = exports.GrafanaLokiReportingSinkOptions = exports.GrafanaLokiReportingSink = exports.ElasticsearchReportingSink = exports.DynatraceReportingSink = exports.CloudWatchReportingSink = exports.DogStatsDReportingSink = exports.DatadogReportingSinkOptions = exports.DatadogReportingSink = exports.HttpAuthOptions = exports.HttpOAuth2ClientCredentialsOptions = exports.WebSocketReconnectPolicy = exports.WebSocketNativeClientOptions = exports.WebSocketMessageSpec = exports.WebSocketExpectedMessage = exports.WebSocketEndpointDefinition = exports.ProtocolMetricSnapshot = exports.GrpcStatusMapper = exports.GrpcNativeClientOptions = exports.GrpcMethodTypes = exports.GrpcEndpointDefinition = exports.PushDiffusionEndpointDefinition = exports.DelegateStreamEndpointDefinition = void 0;
|
|
5
5
|
var autopilot_js_1 = require("./autopilot.js");
|
|
6
6
|
Object.defineProperty(exports, "LoadStrikeAutopilot", { enumerable: true, get: function () { return autopilot_js_1.LoadStrikeAutopilot; } });
|
|
7
7
|
Object.defineProperty(exports, "LoadStrikeAutopilotResult", { enumerable: true, get: function () { return autopilot_js_1.LoadStrikeAutopilotResult; } });
|
|
@@ -12,7 +12,12 @@ Object.defineProperty(exports, "CrossPlatformScenarioConfigurator", { enumerable
|
|
|
12
12
|
Object.defineProperty(exports, "ScenarioTrackingExtensions", { enumerable: true, get: function () { return runtime_js_1.ScenarioTrackingExtensions; } });
|
|
13
13
|
Object.defineProperty(exports, "LoadStrikeContext", { enumerable: true, get: function () { return runtime_js_1.LoadStrikeContext; } });
|
|
14
14
|
Object.defineProperty(exports, "LoadStrikeAccessibility", { enumerable: true, get: function () { return runtime_js_1.LoadStrikeAccessibility; } });
|
|
15
|
+
Object.defineProperty(exports, "LoadStrikeAccessibilityAdapters", { enumerable: true, get: function () { return runtime_js_1.LoadStrikeAccessibilityAdapters; } });
|
|
16
|
+
Object.defineProperty(exports, "LoadStrikeAccessibilityBaseline", { enumerable: true, get: function () { return runtime_js_1.LoadStrikeAccessibilityBaseline; } });
|
|
17
|
+
Object.defineProperty(exports, "LoadStrikeAccessibilityCiGate", { enumerable: true, get: function () { return runtime_js_1.LoadStrikeAccessibilityCiGate; } });
|
|
18
|
+
Object.defineProperty(exports, "LoadStrikeAccessibilityScanner", { enumerable: true, get: function () { return runtime_js_1.LoadStrikeAccessibilityScanner; } });
|
|
15
19
|
Object.defineProperty(exports, "LoadStrikeBrowserWebVitals", { enumerable: true, get: function () { return runtime_js_1.LoadStrikeBrowserWebVitals; } });
|
|
20
|
+
Object.defineProperty(exports, "LoadStrikeBrowserWebVitalsCollector", { enumerable: true, get: function () { return runtime_js_1.LoadStrikeBrowserWebVitalsCollector; } });
|
|
16
21
|
Object.defineProperty(exports, "LoadStrikePluginData", { enumerable: true, get: function () { return runtime_js_1.LoadStrikePluginData; } });
|
|
17
22
|
Object.defineProperty(exports, "LoadStrikePluginDataTable", { enumerable: true, get: function () { return runtime_js_1.LoadStrikePluginDataTable; } });
|
|
18
23
|
Object.defineProperty(exports, "LoadStrikeNodeType", { enumerable: true, get: function () { return runtime_js_1.LoadStrikeNodeType; } });
|
|
@@ -55,20 +60,40 @@ Object.defineProperty(exports, "SqsEndpointDefinition", { enumerable: true, get:
|
|
|
55
60
|
Object.defineProperty(exports, "DelegateStreamEndpointDefinition", { enumerable: true, get: function () { return transports_js_1.DelegateStreamEndpointDefinition; } });
|
|
56
61
|
Object.defineProperty(exports, "PushDiffusionEndpointDefinition", { enumerable: true, get: function () { return transports_js_1.PushDiffusionEndpointDefinition; } });
|
|
57
62
|
Object.defineProperty(exports, "GrpcEndpointDefinition", { enumerable: true, get: function () { return transports_js_1.GrpcEndpointDefinition; } });
|
|
63
|
+
Object.defineProperty(exports, "GrpcMethodTypes", { enumerable: true, get: function () { return transports_js_1.GrpcMethodTypes; } });
|
|
64
|
+
Object.defineProperty(exports, "GrpcNativeClientOptions", { enumerable: true, get: function () { return transports_js_1.GrpcNativeClientOptions; } });
|
|
65
|
+
Object.defineProperty(exports, "GrpcStatusMapper", { enumerable: true, get: function () { return transports_js_1.GrpcStatusMapper; } });
|
|
66
|
+
Object.defineProperty(exports, "ProtocolMetricSnapshot", { enumerable: true, get: function () { return transports_js_1.ProtocolMetricSnapshot; } });
|
|
58
67
|
Object.defineProperty(exports, "WebSocketEndpointDefinition", { enumerable: true, get: function () { return transports_js_1.WebSocketEndpointDefinition; } });
|
|
68
|
+
Object.defineProperty(exports, "WebSocketExpectedMessage", { enumerable: true, get: function () { return transports_js_1.WebSocketExpectedMessage; } });
|
|
69
|
+
Object.defineProperty(exports, "WebSocketMessageSpec", { enumerable: true, get: function () { return transports_js_1.WebSocketMessageSpec; } });
|
|
70
|
+
Object.defineProperty(exports, "WebSocketNativeClientOptions", { enumerable: true, get: function () { return transports_js_1.WebSocketNativeClientOptions; } });
|
|
71
|
+
Object.defineProperty(exports, "WebSocketReconnectPolicy", { enumerable: true, get: function () { return transports_js_1.WebSocketReconnectPolicy; } });
|
|
59
72
|
Object.defineProperty(exports, "HttpOAuth2ClientCredentialsOptions", { enumerable: true, get: function () { return transports_js_1.HttpOAuth2ClientCredentialsOptions; } });
|
|
60
73
|
Object.defineProperty(exports, "HttpAuthOptions", { enumerable: true, get: function () { return transports_js_1.HttpAuthOptions; } });
|
|
61
74
|
var sinks_js_1 = require("./sinks.js");
|
|
62
75
|
Object.defineProperty(exports, "DatadogReportingSink", { enumerable: true, get: function () { return sinks_js_1.DatadogReportingSink; } });
|
|
63
76
|
Object.defineProperty(exports, "DatadogReportingSinkOptions", { enumerable: true, get: function () { return sinks_js_1.DatadogReportingSinkOptions; } });
|
|
77
|
+
Object.defineProperty(exports, "DogStatsDReportingSink", { enumerable: true, get: function () { return sinks_js_1.DogStatsDReportingSink; } });
|
|
78
|
+
Object.defineProperty(exports, "CloudWatchReportingSink", { enumerable: true, get: function () { return sinks_js_1.CloudWatchReportingSink; } });
|
|
79
|
+
Object.defineProperty(exports, "DynatraceReportingSink", { enumerable: true, get: function () { return sinks_js_1.DynatraceReportingSink; } });
|
|
80
|
+
Object.defineProperty(exports, "ElasticsearchReportingSink", { enumerable: true, get: function () { return sinks_js_1.ElasticsearchReportingSink; } });
|
|
64
81
|
Object.defineProperty(exports, "GrafanaLokiReportingSink", { enumerable: true, get: function () { return sinks_js_1.GrafanaLokiReportingSink; } });
|
|
65
82
|
Object.defineProperty(exports, "GrafanaLokiReportingSinkOptions", { enumerable: true, get: function () { return sinks_js_1.GrafanaLokiReportingSinkOptions; } });
|
|
83
|
+
Object.defineProperty(exports, "GenericWebhookReportingSink", { enumerable: true, get: function () { return sinks_js_1.GenericWebhookReportingSink; } });
|
|
66
84
|
Object.defineProperty(exports, "InfluxDbReportingSink", { enumerable: true, get: function () { return sinks_js_1.InfluxDbReportingSink; } });
|
|
67
85
|
Object.defineProperty(exports, "InfluxDbReportingSinkOptions", { enumerable: true, get: function () { return sinks_js_1.InfluxDbReportingSinkOptions; } });
|
|
86
|
+
Object.defineProperty(exports, "JsonlFileReportingSink", { enumerable: true, get: function () { return sinks_js_1.JsonlFileReportingSink; } });
|
|
87
|
+
Object.defineProperty(exports, "KafkaReportingSink", { enumerable: true, get: function () { return sinks_js_1.KafkaReportingSink; } });
|
|
88
|
+
Object.defineProperty(exports, "NetdataStatsDReportingSink", { enumerable: true, get: function () { return sinks_js_1.NetdataStatsDReportingSink; } });
|
|
89
|
+
Object.defineProperty(exports, "NewRelicReportingSink", { enumerable: true, get: function () { return sinks_js_1.NewRelicReportingSink; } });
|
|
68
90
|
Object.defineProperty(exports, "OtelCollectorReportingSink", { enumerable: true, get: function () { return sinks_js_1.OtelCollectorReportingSink; } });
|
|
69
91
|
Object.defineProperty(exports, "OtelCollectorReportingSinkOptions", { enumerable: true, get: function () { return sinks_js_1.OtelCollectorReportingSinkOptions; } });
|
|
92
|
+
Object.defineProperty(exports, "OpenSearchReportingSink", { enumerable: true, get: function () { return sinks_js_1.OpenSearchReportingSink; } });
|
|
70
93
|
Object.defineProperty(exports, "PortalReportingSink", { enumerable: true, get: function () { return sinks_js_1.PortalReportingSink; } });
|
|
94
|
+
Object.defineProperty(exports, "PrometheusRemoteWriteReportingSink", { enumerable: true, get: function () { return sinks_js_1.PrometheusRemoteWriteReportingSink; } });
|
|
71
95
|
Object.defineProperty(exports, "SplunkReportingSink", { enumerable: true, get: function () { return sinks_js_1.SplunkReportingSink; } });
|
|
72
96
|
Object.defineProperty(exports, "SplunkReportingSinkOptions", { enumerable: true, get: function () { return sinks_js_1.SplunkReportingSinkOptions; } });
|
|
97
|
+
Object.defineProperty(exports, "StatsDReportingSink", { enumerable: true, get: function () { return sinks_js_1.StatsDReportingSink; } });
|
|
73
98
|
Object.defineProperty(exports, "TimescaleDbReportingSink", { enumerable: true, get: function () { return sinks_js_1.TimescaleDbReportingSink; } });
|
|
74
99
|
Object.defineProperty(exports, "TimescaleDbReportingSinkOptions", { enumerable: true, get: function () { return sinks_js_1.TimescaleDbReportingSinkOptions; } });
|
package/dist/cjs/local.js
CHANGED
|
@@ -207,7 +207,9 @@ class LoadStrikeLocalClient {
|
|
|
207
207
|
NodeType: stringOrDefault(context.NodeType, nodeType),
|
|
208
208
|
MachineName: machineName,
|
|
209
209
|
EnvironmentClassification: environmentClassification,
|
|
210
|
-
DeviceHash: computedDeviceHash
|
|
210
|
+
DeviceHash: computedDeviceHash,
|
|
211
|
+
Scenarios: buildLicenseScenarioMetadata(request),
|
|
212
|
+
ScenarioSourceAnalysis: buildScenarioSourceAnalysisMetadata(request)
|
|
211
213
|
};
|
|
212
214
|
const controller = new AbortController();
|
|
213
215
|
const timer = setTimeout(() => controller.abort(), this.licenseValidationTimeoutMs);
|
|
@@ -1578,6 +1580,74 @@ function computeScenarioRequestCount(scenario) {
|
|
|
1578
1580
|
}
|
|
1579
1581
|
return Math.max(total, 0);
|
|
1580
1582
|
}
|
|
1583
|
+
function buildLicenseScenarioMetadata(request) {
|
|
1584
|
+
const scenarios = Array.isArray(request.Scenarios) ? request.Scenarios : [];
|
|
1585
|
+
return scenarios.map((item) => {
|
|
1586
|
+
const scenario = asRecord(item);
|
|
1587
|
+
const scenarioName = stringOrDefault(scenario.ScenarioName ?? scenario.scenarioName ?? scenario.Name ?? scenario.name, "");
|
|
1588
|
+
return {
|
|
1589
|
+
Name: scenarioName,
|
|
1590
|
+
ScenarioName: scenarioName,
|
|
1591
|
+
Simulations: normalizeLicenseSimulations(scenario.LoadSimulations)
|
|
1592
|
+
};
|
|
1593
|
+
});
|
|
1594
|
+
}
|
|
1595
|
+
function normalizeLicenseSimulations(value) {
|
|
1596
|
+
const simulations = Array.isArray(value) ? value : [];
|
|
1597
|
+
return simulations.map((item) => {
|
|
1598
|
+
const simulation = asRecord(item);
|
|
1599
|
+
return {
|
|
1600
|
+
Kind: stringOrDefault(simulation.Kind ?? simulation.kind, ""),
|
|
1601
|
+
Rate: positiveOrUndefined(simulation.Rate ?? simulation.rate),
|
|
1602
|
+
MinRate: positiveOrUndefined(simulation.MinRate ?? simulation.minRate),
|
|
1603
|
+
MaxRate: positiveOrUndefined(simulation.MaxRate ?? simulation.maxRate),
|
|
1604
|
+
Copies: positiveOrUndefined(simulation.Copies ?? simulation.copies),
|
|
1605
|
+
Iterations: positiveOrUndefined(simulation.Iterations ?? simulation.iterations),
|
|
1606
|
+
IntervalSeconds: positiveNumberOrUndefined(simulation.IntervalSeconds ?? simulation.intervalSeconds),
|
|
1607
|
+
DurationSeconds: positiveNumberOrUndefined(simulation.DurationSeconds ?? simulation.durationSeconds ?? simulation.DuringSeconds ?? simulation.duringSeconds),
|
|
1608
|
+
Children: normalizeLicenseSimulations(simulation.Children ?? simulation.children)
|
|
1609
|
+
};
|
|
1610
|
+
});
|
|
1611
|
+
}
|
|
1612
|
+
function buildScenarioSourceAnalysisMetadata(request) {
|
|
1613
|
+
const scenarios = Array.isArray(request.Scenarios) ? request.Scenarios : [];
|
|
1614
|
+
return scenarios.map((item) => {
|
|
1615
|
+
const scenario = asRecord(item);
|
|
1616
|
+
const source = asRecord(scenario.ScenarioSourceAnalysis ?? scenario.scenarioSourceAnalysis ?? scenario.SourceAnalysis);
|
|
1617
|
+
const scenarioName = stringOrDefault(source.ScenarioName ?? source.scenarioName ?? scenario.Name ?? scenario.name, "");
|
|
1618
|
+
const scenarioBlockLineCount = Math.max(asInt(source.ScenarioBlockLineCount ?? source.scenarioBlockLineCount), 1);
|
|
1619
|
+
const localMethodLineCount = Math.max(asInt(source.LocalMethodLineCount
|
|
1620
|
+
?? source.localMethodLineCount
|
|
1621
|
+
?? source.TransitiveLocalMethodLineCount
|
|
1622
|
+
?? source.transitiveLocalMethodLineCount), 0);
|
|
1623
|
+
const totalCountedLineCount = Math.max(asInt(source.TotalCountedLineCount ?? source.totalCountedLineCount), scenarioBlockLineCount + localMethodLineCount);
|
|
1624
|
+
const warningsValue = source.Warnings ?? source.warnings;
|
|
1625
|
+
const warnings = Array.isArray(warningsValue)
|
|
1626
|
+
? warningsValue.map((warning) => stringOrDefault(warning, "")).filter((warning) => warning.length > 0)
|
|
1627
|
+
: ["Scenario source analysis was synthesized from scenario metadata."];
|
|
1628
|
+
return {
|
|
1629
|
+
ScenarioName: scenarioName,
|
|
1630
|
+
Language: stringOrDefault(source.Language ?? source.language, "TypeScript/JavaScript"),
|
|
1631
|
+
AnalyzerVersion: stringOrDefault(source.AnalyzerVersion ?? source.analyzerVersion, "function-source-v1"),
|
|
1632
|
+
ScenarioBlockLineCount: scenarioBlockLineCount,
|
|
1633
|
+
LocalMethodLineCount: localMethodLineCount,
|
|
1634
|
+
TotalCountedLineCount: totalCountedLineCount,
|
|
1635
|
+
IgnoredExternalCallCount: Math.max(asInt(source.IgnoredExternalCallCount
|
|
1636
|
+
?? source.ignoredExternalCallCount
|
|
1637
|
+
?? source.IgnoredLibraryCallCount
|
|
1638
|
+
?? source.ignoredLibraryCallCount), 0),
|
|
1639
|
+
Warnings: warnings
|
|
1640
|
+
};
|
|
1641
|
+
});
|
|
1642
|
+
}
|
|
1643
|
+
function positiveOrUndefined(value) {
|
|
1644
|
+
const normalized = asInt(value);
|
|
1645
|
+
return normalized > 0 ? normalized : undefined;
|
|
1646
|
+
}
|
|
1647
|
+
function positiveNumberOrUndefined(value) {
|
|
1648
|
+
const normalized = asNumber(value);
|
|
1649
|
+
return normalized > 0 ? normalized : undefined;
|
|
1650
|
+
}
|
|
1581
1651
|
function buildNodeStatsContract(context, createdUtc, completedUtc, values) {
|
|
1582
1652
|
const durationMs = Math.max(completedUtc.getTime() - createdUtc.getTime(), 0);
|
|
1583
1653
|
return {
|
package/dist/cjs/runtime.js
CHANGED
|
@@ -3,7 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.__loadstrikeTestExports = exports.LoadStrikeRunner = exports.LoadStrikeTrafficMix = exports.LoadStrikeScenarioShare = exports.LoadStrikeScenario = exports.LoadStrikeBrowserWebVitals = exports.LoadStrikeAccessibility = exports.LoadStrikeContext = exports.ScenarioTrackingExtensions = exports.CrossPlatformScenarioConfigurator = exports.LoadStrikeThreshold = exports.LoadStrikeMetric = exports.LoadStrikeGauge = exports.LoadStrikeCounter = exports.LoadStrikeSimulation = exports.LoadStrikeStep = exports.LoadStrikeResponse = exports.LoadStrikePluginData = exports.LoadStrikePluginDataTable = exports.CrossPlatformTrackingConfiguration = exports.LoadStrikeOperationType = exports.LoadStrikeScenarioOperation = exports.LoadStrikeLogLevel = exports.LoadStrikeReportFormat = exports.LoadStrikeNodeType = void 0;
|
|
6
|
+
exports.__loadstrikeTestExports = exports.LoadStrikeRunner = exports.LoadStrikeTrafficMix = exports.LoadStrikeScenarioShare = exports.LoadStrikeScenario = exports.LoadStrikeBrowserWebVitals = exports.LoadStrikeAccessibility = exports.LoadStrikeBrowserWebVitalsCollector = exports.LoadStrikeAccessibilityAdapters = exports.LoadStrikeAccessibilityScanner = exports.LoadStrikeAccessibilityCiGate = exports.LoadStrikeAccessibilityBaseline = exports.LoadStrikeContext = exports.ScenarioTrackingExtensions = exports.CrossPlatformScenarioConfigurator = exports.LoadStrikeThreshold = exports.LoadStrikeMetric = exports.LoadStrikeGauge = exports.LoadStrikeCounter = exports.LoadStrikeSimulation = exports.LoadStrikeStep = exports.LoadStrikeResponse = exports.LoadStrikePluginData = exports.LoadStrikePluginDataTable = exports.CrossPlatformTrackingConfiguration = exports.LoadStrikeOperationType = exports.LoadStrikeScenarioOperation = exports.LoadStrikeLogLevel = exports.LoadStrikeReportFormat = exports.LoadStrikeNodeType = void 0;
|
|
7
7
|
const node_fs_1 = require("node:fs");
|
|
8
8
|
const node_crypto_1 = require("node:crypto");
|
|
9
9
|
const node_os_1 = __importDefault(require("node:os"));
|
|
@@ -1624,6 +1624,174 @@ class LoadStrikeContext {
|
|
|
1624
1624
|
exports.LoadStrikeContext = LoadStrikeContext;
|
|
1625
1625
|
const ACCESSIBILITY_TESTING_FEATURE = "testing.accessibility";
|
|
1626
1626
|
const BROWSER_WEB_VITALS_FEATURE = "testing.browser_web_vitals";
|
|
1627
|
+
class LoadStrikeAccessibilityBaseline {
|
|
1628
|
+
constructor(initial = {}) {
|
|
1629
|
+
const source = qualityRecord(initial);
|
|
1630
|
+
this.allowedRuleIds = qualityStringArray(qualityValue(source, "allowedRuleIds", "AllowedRuleIds"));
|
|
1631
|
+
this.AllowedRuleIds = this.allowedRuleIds;
|
|
1632
|
+
this.maxNewViolations = Math.max(0, qualityNumber(source, 0, "maxNewViolations", "MaxNewViolations"));
|
|
1633
|
+
this.MaxNewViolations = this.maxNewViolations;
|
|
1634
|
+
}
|
|
1635
|
+
compare(result) {
|
|
1636
|
+
const violations = Array.isArray(result?.violations) ? result.violations : [];
|
|
1637
|
+
const allowed = new Set(this.allowedRuleIds.map((value) => value.toLowerCase()));
|
|
1638
|
+
const newViolations = violations.filter((violation) => !allowed.has(String(violation.ruleId ?? "").toLowerCase()));
|
|
1639
|
+
const newRuleIds = Array.from(new Set(newViolations
|
|
1640
|
+
.map((violation) => String(violation.ruleId ?? "").trim())
|
|
1641
|
+
.filter(Boolean)));
|
|
1642
|
+
return {
|
|
1643
|
+
passed: newViolations.length <= this.maxNewViolations,
|
|
1644
|
+
Passed: newViolations.length <= this.maxNewViolations,
|
|
1645
|
+
newViolationCount: newViolations.length,
|
|
1646
|
+
NewViolationCount: newViolations.length,
|
|
1647
|
+
newRuleIds,
|
|
1648
|
+
NewRuleIds: newRuleIds
|
|
1649
|
+
};
|
|
1650
|
+
}
|
|
1651
|
+
Compare(result) {
|
|
1652
|
+
return this.compare(result);
|
|
1653
|
+
}
|
|
1654
|
+
}
|
|
1655
|
+
exports.LoadStrikeAccessibilityBaseline = LoadStrikeAccessibilityBaseline;
|
|
1656
|
+
class LoadStrikeAccessibilityCiGate {
|
|
1657
|
+
constructor(initial = {}) {
|
|
1658
|
+
const source = qualityRecord(initial);
|
|
1659
|
+
this.maxViolations = qualityOptionalNumber(source, "maxViolations", "MaxViolations");
|
|
1660
|
+
this.MaxViolations = this.maxViolations;
|
|
1661
|
+
this.maxCriticalViolations = qualityOptionalNumber(source, "maxCriticalViolations", "MaxCriticalViolations");
|
|
1662
|
+
this.MaxCriticalViolations = this.maxCriticalViolations;
|
|
1663
|
+
this.maxSeriousViolations = qualityOptionalNumber(source, "maxSeriousViolations", "MaxSeriousViolations");
|
|
1664
|
+
this.MaxSeriousViolations = this.maxSeriousViolations;
|
|
1665
|
+
const baseline = qualityValue(source, "baseline", "Baseline");
|
|
1666
|
+
this.baseline = baseline instanceof LoadStrikeAccessibilityBaseline
|
|
1667
|
+
? baseline
|
|
1668
|
+
: (baseline && typeof baseline === "object" ? new LoadStrikeAccessibilityBaseline(baseline) : undefined);
|
|
1669
|
+
this.Baseline = this.baseline;
|
|
1670
|
+
}
|
|
1671
|
+
evaluate(result) {
|
|
1672
|
+
const normalized = attachAccessibilityCounts(result);
|
|
1673
|
+
const reasons = [];
|
|
1674
|
+
if (this.maxViolations != null && (normalized.totalViolations ?? 0) > this.maxViolations) {
|
|
1675
|
+
reasons.push(`total accessibility violations ${normalized.totalViolations} exceeded ${this.maxViolations}.`);
|
|
1676
|
+
}
|
|
1677
|
+
if (this.maxCriticalViolations != null && (normalized.criticalViolations ?? 0) > this.maxCriticalViolations) {
|
|
1678
|
+
reasons.push(`critical accessibility violations ${normalized.criticalViolations} exceeded ${this.maxCriticalViolations}.`);
|
|
1679
|
+
}
|
|
1680
|
+
if (this.maxSeriousViolations != null && (normalized.seriousViolations ?? 0) > this.maxSeriousViolations) {
|
|
1681
|
+
reasons.push(`serious accessibility violations ${normalized.seriousViolations} exceeded ${this.maxSeriousViolations}.`);
|
|
1682
|
+
}
|
|
1683
|
+
if (this.baseline) {
|
|
1684
|
+
const baseline = this.baseline.compare(normalized);
|
|
1685
|
+
if (!baseline.passed) {
|
|
1686
|
+
reasons.push(`baseline found ${baseline.newViolationCount} new accessibility violation(s).`);
|
|
1687
|
+
}
|
|
1688
|
+
}
|
|
1689
|
+
return {
|
|
1690
|
+
passed: reasons.length === 0,
|
|
1691
|
+
Passed: reasons.length === 0,
|
|
1692
|
+
reasons,
|
|
1693
|
+
Reasons: reasons
|
|
1694
|
+
};
|
|
1695
|
+
}
|
|
1696
|
+
Evaluate(result) {
|
|
1697
|
+
return this.evaluate(result);
|
|
1698
|
+
}
|
|
1699
|
+
}
|
|
1700
|
+
exports.LoadStrikeAccessibilityCiGate = LoadStrikeAccessibilityCiGate;
|
|
1701
|
+
class LoadStrikeAccessibilityScanner {
|
|
1702
|
+
static scanHtml(options, html) {
|
|
1703
|
+
validateAbsoluteUrl(options?.url, "Accessibility check URL");
|
|
1704
|
+
const source = String(html ?? "");
|
|
1705
|
+
const violations = [];
|
|
1706
|
+
if (!/<html\b[^>]*\blang\s*=\s*["'][^"']+["']/i.test(source)) {
|
|
1707
|
+
violations.push(createAccessibilityViolation("html-has-lang", "serious", "The html element should declare a non-empty language."));
|
|
1708
|
+
}
|
|
1709
|
+
if (/<title\b[^>]*>\s*<\/title>/i.test(source) || !/<title\b/i.test(source)) {
|
|
1710
|
+
violations.push(createAccessibilityViolation("document-title", "serious", "The page should provide a useful title."));
|
|
1711
|
+
}
|
|
1712
|
+
for (const match of source.matchAll(/<img\b(?![^>]*\balt\s*=)[^>]*>/gi)) {
|
|
1713
|
+
violations.push(createAccessibilityViolation("image-alt", "serious", "Images should provide alternate text.", match[0]));
|
|
1714
|
+
}
|
|
1715
|
+
for (const match of source.matchAll(/<button\b(?![^>]*\baria-label\s*=)[^>]*>\s*<\/button>/gi)) {
|
|
1716
|
+
violations.push(createAccessibilityViolation("button-name", "critical", "Buttons should have an accessible name.", match[0]));
|
|
1717
|
+
}
|
|
1718
|
+
for (const match of source.matchAll(/<input\b(?![^>]*\baria-label\s*=)[^>]*\bid\s*=\s*["']?([a-zA-Z0-9_-]+)["']?[^>]*>/gi)) {
|
|
1719
|
+
const id = match[1] ?? "";
|
|
1720
|
+
const labelRegex = new RegExp(`<label\\b[^>]*\\bfor\\s*=\\s*["']?${escapeRegExp(id)}["']?[^>]*>`, "i");
|
|
1721
|
+
if (!labelRegex.test(source)) {
|
|
1722
|
+
violations.push(createAccessibilityViolation("label", "critical", "Form fields should have labels.", match[0]));
|
|
1723
|
+
}
|
|
1724
|
+
}
|
|
1725
|
+
const focusOrder = [...source.matchAll(/<(a|button|input|select|textarea)\b[^>]*>/gi)]
|
|
1726
|
+
.map((match) => match[0]);
|
|
1727
|
+
const visibleFocusFailures = focusOrder.filter((element) => /outline\s*:\s*(none|0)\b/i.test(element)).length;
|
|
1728
|
+
const missingSkipLinkCount = /href\s*=\s*["']#(main|content)["']/i.test(source) ? 0 : 1;
|
|
1729
|
+
if (visibleFocusFailures > 0) {
|
|
1730
|
+
violations.push(createAccessibilityViolation("focus-visible", "serious", "Keyboard focus indicators should remain visible."));
|
|
1731
|
+
}
|
|
1732
|
+
if (missingSkipLinkCount > 0) {
|
|
1733
|
+
violations.push(createAccessibilityViolation("skip-link", "moderate", "Pages should provide a skip link to the main content."));
|
|
1734
|
+
}
|
|
1735
|
+
return attachAccessibilityCounts({
|
|
1736
|
+
url: options.url,
|
|
1737
|
+
violations,
|
|
1738
|
+
keyboardFocus: {
|
|
1739
|
+
tabbableElementCount: focusOrder.length,
|
|
1740
|
+
visibleFocusFailures,
|
|
1741
|
+
missingSkipLinkCount,
|
|
1742
|
+
focusOrder
|
|
1743
|
+
}
|
|
1744
|
+
});
|
|
1745
|
+
}
|
|
1746
|
+
static ScanHtml(options, html) {
|
|
1747
|
+
return LoadStrikeAccessibilityScanner.scanHtml(options, html);
|
|
1748
|
+
}
|
|
1749
|
+
}
|
|
1750
|
+
exports.LoadStrikeAccessibilityScanner = LoadStrikeAccessibilityScanner;
|
|
1751
|
+
class LoadStrikeAccessibilityAdapters {
|
|
1752
|
+
static async fromPlaywrightPageAsync(options, page) {
|
|
1753
|
+
const html = await readBrowserContent(page, ["ContentAsync", "contentAsync", "content"]);
|
|
1754
|
+
return LoadStrikeAccessibilityScanner.scanHtml(options, html);
|
|
1755
|
+
}
|
|
1756
|
+
static FromPlaywrightPageAsync(options, page) {
|
|
1757
|
+
return LoadStrikeAccessibilityAdapters.fromPlaywrightPageAsync(options, page);
|
|
1758
|
+
}
|
|
1759
|
+
static fromSeleniumDriver(options, driver) {
|
|
1760
|
+
const record = qualityRecord(driver);
|
|
1761
|
+
const html = String(qualityValue(record, "PageSource", "pageSource") ?? "");
|
|
1762
|
+
return LoadStrikeAccessibilityScanner.scanHtml(options, html);
|
|
1763
|
+
}
|
|
1764
|
+
static FromSeleniumDriver(options, driver) {
|
|
1765
|
+
return LoadStrikeAccessibilityAdapters.fromSeleniumDriver(options, driver);
|
|
1766
|
+
}
|
|
1767
|
+
}
|
|
1768
|
+
exports.LoadStrikeAccessibilityAdapters = LoadStrikeAccessibilityAdapters;
|
|
1769
|
+
class LoadStrikeBrowserWebVitalsCollector {
|
|
1770
|
+
static fromPerformanceSnapshot(options, snapshot) {
|
|
1771
|
+
validateAbsoluteUrl(options?.url, "Browser Web Vitals URL");
|
|
1772
|
+
return normalizeWebVitalsSnapshot(options.url, snapshot);
|
|
1773
|
+
}
|
|
1774
|
+
static FromPerformanceSnapshot(options, snapshot) {
|
|
1775
|
+
return LoadStrikeBrowserWebVitalsCollector.fromPerformanceSnapshot(options, snapshot);
|
|
1776
|
+
}
|
|
1777
|
+
static async fromPlaywrightPageAsync(options, page) {
|
|
1778
|
+
validateAbsoluteUrl(options?.url, "Browser Web Vitals URL");
|
|
1779
|
+
const snapshot = await invokeBrowserMethod(page, ["EvaluateAsync", "evaluate"], WEB_VITALS_SCRIPT);
|
|
1780
|
+
return normalizeWebVitalsSnapshot(options.url, snapshot);
|
|
1781
|
+
}
|
|
1782
|
+
static FromPlaywrightPageAsync(options, page) {
|
|
1783
|
+
return LoadStrikeBrowserWebVitalsCollector.fromPlaywrightPageAsync(options, page);
|
|
1784
|
+
}
|
|
1785
|
+
static fromSeleniumDriver(options, driver) {
|
|
1786
|
+
validateAbsoluteUrl(options?.url, "Browser Web Vitals URL");
|
|
1787
|
+
const snapshot = invokeBrowserMethodSync(driver, ["ExecuteScript", "executeScript"], WEB_VITALS_SCRIPT);
|
|
1788
|
+
return normalizeWebVitalsSnapshot(options.url, snapshot);
|
|
1789
|
+
}
|
|
1790
|
+
static FromSeleniumDriver(options, driver) {
|
|
1791
|
+
return LoadStrikeBrowserWebVitalsCollector.fromSeleniumDriver(options, driver);
|
|
1792
|
+
}
|
|
1793
|
+
}
|
|
1794
|
+
exports.LoadStrikeBrowserWebVitalsCollector = LoadStrikeBrowserWebVitalsCollector;
|
|
1627
1795
|
class LoadStrikeAccessibility {
|
|
1628
1796
|
static createScenario(name, options, check) {
|
|
1629
1797
|
if (typeof name !== "string" || !name.trim()) {
|
|
@@ -1674,6 +1842,129 @@ class LoadStrikeBrowserWebVitals {
|
|
|
1674
1842
|
}
|
|
1675
1843
|
}
|
|
1676
1844
|
exports.LoadStrikeBrowserWebVitals = LoadStrikeBrowserWebVitals;
|
|
1845
|
+
const WEB_VITALS_SCRIPT = `
|
|
1846
|
+
(() => {
|
|
1847
|
+
const navigation = performance.getEntriesByType("navigation")[0];
|
|
1848
|
+
const paint = performance.getEntriesByType("paint");
|
|
1849
|
+
const fcp = paint.find((entry) => entry.name === "first-contentful-paint");
|
|
1850
|
+
return {
|
|
1851
|
+
largestContentfulPaintMs: globalThis.__loadstrikeLcp ?? 0,
|
|
1852
|
+
interactionToNextPaintMs: globalThis.__loadstrikeInp ?? 0,
|
|
1853
|
+
cumulativeLayoutShift: globalThis.__loadstrikeCls ?? 0,
|
|
1854
|
+
firstContentfulPaintMs: fcp ? fcp.startTime : 0,
|
|
1855
|
+
timeToFirstByteMs: navigation ? navigation.responseStart : 0
|
|
1856
|
+
};
|
|
1857
|
+
})()
|
|
1858
|
+
`;
|
|
1859
|
+
function createAccessibilityViolation(ruleId, impact, description, target) {
|
|
1860
|
+
return {
|
|
1861
|
+
ruleId,
|
|
1862
|
+
impact,
|
|
1863
|
+
description,
|
|
1864
|
+
helpUrl: `https://www.w3.org/WAI/WCAG22/quickref/?versions=2.2#${ruleId}`,
|
|
1865
|
+
targets: target ? [target] : []
|
|
1866
|
+
};
|
|
1867
|
+
}
|
|
1868
|
+
function attachAccessibilityCounts(result) {
|
|
1869
|
+
const violations = Array.isArray(result?.violations) ? result.violations : [];
|
|
1870
|
+
return {
|
|
1871
|
+
...result,
|
|
1872
|
+
violations,
|
|
1873
|
+
totalViolations: violations.length,
|
|
1874
|
+
criticalViolations: countAccessibilityImpact(violations, "critical"),
|
|
1875
|
+
seriousViolations: countAccessibilityImpact(violations, "serious"),
|
|
1876
|
+
moderateViolations: countAccessibilityImpact(violations, "moderate"),
|
|
1877
|
+
minorViolations: countAccessibilityImpact(violations, "minor")
|
|
1878
|
+
};
|
|
1879
|
+
}
|
|
1880
|
+
function qualityRecord(value) {
|
|
1881
|
+
return value && typeof value === "object" && !Array.isArray(value)
|
|
1882
|
+
? value
|
|
1883
|
+
: {};
|
|
1884
|
+
}
|
|
1885
|
+
function qualityValue(record, ...keys) {
|
|
1886
|
+
for (const key of keys) {
|
|
1887
|
+
if (key in record) {
|
|
1888
|
+
return record[key];
|
|
1889
|
+
}
|
|
1890
|
+
const normalized = key.toLowerCase();
|
|
1891
|
+
const match = Object.entries(record).find(([entryKey]) => entryKey.toLowerCase() === normalized);
|
|
1892
|
+
if (match) {
|
|
1893
|
+
return match[1];
|
|
1894
|
+
}
|
|
1895
|
+
}
|
|
1896
|
+
return undefined;
|
|
1897
|
+
}
|
|
1898
|
+
function qualityStringArray(value) {
|
|
1899
|
+
if (!Array.isArray(value)) {
|
|
1900
|
+
return [];
|
|
1901
|
+
}
|
|
1902
|
+
return value.map((entry) => String(entry ?? "").trim()).filter(Boolean);
|
|
1903
|
+
}
|
|
1904
|
+
function qualityNumber(record, fallback, ...keys) {
|
|
1905
|
+
const value = qualityValue(record, ...keys);
|
|
1906
|
+
if (typeof value === "number" && Number.isFinite(value)) {
|
|
1907
|
+
return value;
|
|
1908
|
+
}
|
|
1909
|
+
if (typeof value === "string" && value.trim()) {
|
|
1910
|
+
const parsed = Number(value);
|
|
1911
|
+
if (Number.isFinite(parsed)) {
|
|
1912
|
+
return parsed;
|
|
1913
|
+
}
|
|
1914
|
+
}
|
|
1915
|
+
return fallback;
|
|
1916
|
+
}
|
|
1917
|
+
function qualityOptionalNumber(record, ...keys) {
|
|
1918
|
+
const value = qualityValue(record, ...keys);
|
|
1919
|
+
if (typeof value === "number" && Number.isFinite(value)) {
|
|
1920
|
+
return value;
|
|
1921
|
+
}
|
|
1922
|
+
if (typeof value === "string" && value.trim()) {
|
|
1923
|
+
const parsed = Number(value);
|
|
1924
|
+
if (Number.isFinite(parsed)) {
|
|
1925
|
+
return parsed;
|
|
1926
|
+
}
|
|
1927
|
+
}
|
|
1928
|
+
return undefined;
|
|
1929
|
+
}
|
|
1930
|
+
function escapeRegExp(value) {
|
|
1931
|
+
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
1932
|
+
}
|
|
1933
|
+
async function readBrowserContent(target, methodNames) {
|
|
1934
|
+
const value = await invokeBrowserMethod(target, methodNames);
|
|
1935
|
+
return String(value ?? "");
|
|
1936
|
+
}
|
|
1937
|
+
async function invokeBrowserMethod(target, methodNames, ...args) {
|
|
1938
|
+
const record = qualityRecord(target);
|
|
1939
|
+
for (const name of methodNames) {
|
|
1940
|
+
const method = record[name];
|
|
1941
|
+
if (typeof method === "function") {
|
|
1942
|
+
return await method.apply(target, args);
|
|
1943
|
+
}
|
|
1944
|
+
}
|
|
1945
|
+
throw new Error(`Browser object does not expose ${methodNames.join(" or ")}.`);
|
|
1946
|
+
}
|
|
1947
|
+
function invokeBrowserMethodSync(target, methodNames, ...args) {
|
|
1948
|
+
const record = qualityRecord(target);
|
|
1949
|
+
for (const name of methodNames) {
|
|
1950
|
+
const method = record[name];
|
|
1951
|
+
if (typeof method === "function") {
|
|
1952
|
+
return method.apply(target, args);
|
|
1953
|
+
}
|
|
1954
|
+
}
|
|
1955
|
+
throw new Error(`Browser object does not expose ${methodNames.join(" or ")}.`);
|
|
1956
|
+
}
|
|
1957
|
+
function normalizeWebVitalsSnapshot(url, snapshot) {
|
|
1958
|
+
const source = qualityRecord(snapshot);
|
|
1959
|
+
return {
|
|
1960
|
+
url,
|
|
1961
|
+
largestContentfulPaintMs: qualityNumber(source, 0, "largestContentfulPaintMs", "LargestContentfulPaintMs", "LCP", "lcp"),
|
|
1962
|
+
interactionToNextPaintMs: qualityNumber(source, 0, "interactionToNextPaintMs", "InteractionToNextPaintMs", "INP", "inp"),
|
|
1963
|
+
cumulativeLayoutShift: qualityNumber(source, 0, "cumulativeLayoutShift", "CumulativeLayoutShift", "CLS", "cls"),
|
|
1964
|
+
firstContentfulPaintMs: qualityNumber(source, 0, "firstContentfulPaintMs", "FirstContentfulPaintMs", "FCP", "fcp"),
|
|
1965
|
+
timeToFirstByteMs: qualityNumber(source, 0, "timeToFirstByteMs", "TimeToFirstByteMs", "TTFB", "ttfb")
|
|
1966
|
+
};
|
|
1967
|
+
}
|
|
1677
1968
|
function validateAbsoluteUrl(value, label) {
|
|
1678
1969
|
if (typeof value !== "string" || !value.trim()) {
|
|
1679
1970
|
throw new Error(`${label} must be provided.`);
|
|
@@ -1964,6 +2255,26 @@ class LoadStrikeScenario {
|
|
|
1964
2255
|
__loadStrikeInternalLicenseFeatures() {
|
|
1965
2256
|
return [...this.internalLicenseFeatures];
|
|
1966
2257
|
}
|
|
2258
|
+
__loadStrikeScenarioSourceAnalysis() {
|
|
2259
|
+
const source = this.runHandler.toString();
|
|
2260
|
+
const lines = source
|
|
2261
|
+
.split(/\r?\n/)
|
|
2262
|
+
.map((line) => line.trim())
|
|
2263
|
+
.filter((line) => line.length > 0 && !line.startsWith("//"));
|
|
2264
|
+
const lineCount = Math.max(lines.length, 1);
|
|
2265
|
+
return {
|
|
2266
|
+
ScenarioName: this.name,
|
|
2267
|
+
Language: "TypeScript/JavaScript",
|
|
2268
|
+
AnalyzerVersion: "function-source-v1",
|
|
2269
|
+
ScenarioBlockLineCount: lineCount,
|
|
2270
|
+
LocalMethodLineCount: 0,
|
|
2271
|
+
TotalCountedLineCount: lineCount,
|
|
2272
|
+
IgnoredExternalCallCount: 0,
|
|
2273
|
+
Warnings: [
|
|
2274
|
+
"Function-source analysis counts the scenario handler source available at runtime; imported library implementation lines are ignored."
|
|
2275
|
+
]
|
|
2276
|
+
};
|
|
2277
|
+
}
|
|
1967
2278
|
__loadStrikeWithInternalLicenseFeatures(...features) {
|
|
1968
2279
|
const merged = Array.from(new Set([...this.internalLicenseFeatures, ...normalizeStringArray(features)]));
|
|
1969
2280
|
return new LoadStrikeScenario(this.name, this.runHandler, this.initHandler, this.cleanHandler, this.loadSimulations, this.thresholds, this.trackingConfiguration, this.maxFailCount, this.withoutWarmUpValue, this.warmUpDurationSeconds, this.weight, this.restartIterationOnFail, merged);
|
|
@@ -8061,7 +8372,8 @@ function buildLicenseValidationPayload(options, scenarios) {
|
|
|
8061
8372
|
Weight: scenario.getWeight(),
|
|
8062
8373
|
LoadSimulations: [...scenario.getSimulations()],
|
|
8063
8374
|
Thresholds: [...scenario.getThresholds()],
|
|
8064
|
-
Tracking: scenario.getTrackingConfiguration() ?? {}
|
|
8375
|
+
Tracking: scenario.getTrackingConfiguration() ?? {},
|
|
8376
|
+
ScenarioSourceAnalysis: scenario.__loadStrikeScenarioSourceAnalysis()
|
|
8065
8377
|
};
|
|
8066
8378
|
const internalLicenseFeatures = scenario.__loadStrikeInternalLicenseFeatures();
|
|
8067
8379
|
if (internalLicenseFeatures.length > 0) {
|