agentic-qe 3.8.4 → 3.8.6
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/.claude/skills/skills-manifest.json +1 -1
- package/CHANGELOG.md +12 -0
- package/dist/cli/bundle.js +694 -694
- package/dist/cli/commands/hooks-handlers/command-hooks.d.ts +12 -0
- package/dist/cli/commands/hooks-handlers/command-hooks.js +253 -0
- package/dist/cli/commands/hooks-handlers/editing-hooks.d.ts +12 -0
- package/dist/cli/commands/hooks-handlers/editing-hooks.js +161 -0
- package/dist/cli/commands/hooks-handlers/hooks-dream-learning.d.ts +57 -0
- package/dist/cli/commands/hooks-handlers/hooks-dream-learning.js +263 -0
- package/dist/cli/commands/hooks-handlers/hooks-shared.d.ts +52 -0
- package/dist/cli/commands/hooks-handlers/hooks-shared.js +223 -0
- package/dist/cli/commands/hooks-handlers/routing-hooks.d.ts +12 -0
- package/dist/cli/commands/hooks-handlers/routing-hooks.js +107 -0
- package/dist/cli/commands/hooks-handlers/session-hooks.d.ts +12 -0
- package/dist/cli/commands/hooks-handlers/session-hooks.js +171 -0
- package/dist/cli/commands/hooks-handlers/stats-hooks.d.ts +12 -0
- package/dist/cli/commands/hooks-handlers/stats-hooks.js +248 -0
- package/dist/cli/commands/hooks-handlers/task-hooks.d.ts +12 -0
- package/dist/cli/commands/hooks-handlers/task-hooks.js +152 -0
- package/dist/cli/commands/hooks.d.ts +3 -23
- package/dist/cli/commands/hooks.js +16 -1459
- package/dist/coordination/mincut/phase-executor.d.ts +27 -0
- package/dist/coordination/mincut/phase-executor.js +70 -0
- package/dist/coordination/mincut/time-crystal-analysis.d.ts +35 -0
- package/dist/coordination/mincut/time-crystal-analysis.js +237 -0
- package/dist/coordination/mincut/time-crystal-persistence.d.ts +35 -0
- package/dist/coordination/mincut/time-crystal-persistence.js +81 -0
- package/dist/coordination/mincut/time-crystal-scheduling.d.ts +34 -0
- package/dist/coordination/mincut/time-crystal-scheduling.js +213 -0
- package/dist/coordination/mincut/time-crystal-types.d.ts +278 -0
- package/dist/coordination/mincut/time-crystal-types.js +67 -0
- package/dist/coordination/mincut/time-crystal.d.ts +8 -438
- package/dist/coordination/mincut/time-crystal.js +87 -905
- package/dist/domains/base-domain-coordinator.d.ts +0 -15
- package/dist/domains/base-domain-coordinator.js +7 -5
- package/dist/domains/chaos-resilience/coordinator.d.ts +0 -4
- package/dist/domains/chaos-resilience/coordinator.js +24 -22
- package/dist/domains/chaos-resilience/services/chaos-engineer.d.ts +0 -4
- package/dist/domains/chaos-resilience/services/chaos-engineer.js +47 -45
- package/dist/domains/chaos-resilience/services/performance-profiler.d.ts +0 -4
- package/dist/domains/chaos-resilience/services/performance-profiler.js +10 -8
- package/dist/domains/code-intelligence/coordinator-consensus.d.ts +0 -3
- package/dist/domains/code-intelligence/coordinator-consensus.js +8 -6
- package/dist/domains/code-intelligence/coordinator-gnn.d.ts +0 -3
- package/dist/domains/code-intelligence/coordinator-gnn.js +8 -6
- package/dist/domains/code-intelligence/coordinator-hypergraph.d.ts +0 -3
- package/dist/domains/code-intelligence/coordinator-hypergraph.js +13 -11
- package/dist/domains/code-intelligence/coordinator.d.ts +0 -3
- package/dist/domains/code-intelligence/coordinator.js +21 -19
- package/dist/domains/code-intelligence/services/c4-model/index.d.ts +0 -3
- package/dist/domains/code-intelligence/services/c4-model/index.js +5 -3
- package/dist/domains/code-intelligence/services/knowledge-graph.d.ts +0 -6
- package/dist/domains/code-intelligence/services/knowledge-graph.js +4 -2
- package/dist/domains/code-intelligence/services/product-factors-bridge.d.ts +0 -5
- package/dist/domains/code-intelligence/services/product-factors-bridge.js +9 -7
- package/dist/domains/contract-testing/coordinator.d.ts +0 -6
- package/dist/domains/contract-testing/coordinator.js +25 -23
- package/dist/domains/contract-testing/services/contract-validator.d.ts +0 -4
- package/dist/domains/contract-testing/services/contract-validator.js +4 -2
- package/dist/domains/contract-testing/services/schema-validator.js +1 -1
- package/dist/domains/coverage-analysis/coordinator.js +13 -11
- package/dist/domains/coverage-analysis/services/coverage-analyzer.js +4 -2
- package/dist/domains/coverage-analysis/services/gap-detector.js +3 -1
- package/dist/domains/coverage-analysis/services/hnsw-index.d.ts +0 -15
- package/dist/domains/coverage-analysis/services/hnsw-index.js +3 -1
- package/dist/domains/coverage-analysis/services/sublinear-analyzer.d.ts +0 -26
- package/dist/domains/coverage-analysis/services/sublinear-analyzer.js +3 -1
- package/dist/domains/defect-intelligence/coordinator.d.ts +1 -10
- package/dist/domains/defect-intelligence/coordinator.js +5 -3
- package/dist/domains/defect-intelligence/services/causal-root-cause-analyzer.d.ts +0 -6
- package/dist/domains/defect-intelligence/services/causal-root-cause-analyzer.js +3 -1
- package/dist/domains/defect-intelligence/services/defect-predictor.d.ts +0 -6
- package/dist/domains/defect-intelligence/services/defect-predictor.js +5 -3
- package/dist/domains/defect-intelligence/services/pattern-learner.d.ts +0 -4
- package/dist/domains/defect-intelligence/services/pattern-learner.js +3 -1
- package/dist/domains/defect-intelligence/services/root-cause-analyzer.d.ts +0 -6
- package/dist/domains/defect-intelligence/services/root-cause-analyzer.js +3 -1
- package/dist/domains/enterprise-integration/coordinator.js +6 -4
- package/dist/domains/learning-optimization/coordinator-consensus.d.ts +0 -3
- package/dist/domains/learning-optimization/coordinator-consensus.js +8 -6
- package/dist/domains/learning-optimization/coordinator.d.ts +0 -3
- package/dist/domains/learning-optimization/coordinator.js +15 -13
- package/dist/domains/learning-optimization/services/learning-coordinator.d.ts +0 -4
- package/dist/domains/learning-optimization/services/learning-coordinator.js +4 -2
- package/dist/domains/quality-assessment/coordinator-claim-verifier.d.ts +0 -3
- package/dist/domains/quality-assessment/coordinator-claim-verifier.js +6 -4
- package/dist/domains/quality-assessment/coordinator-gate-evaluation.d.ts +0 -4
- package/dist/domains/quality-assessment/coordinator-gate-evaluation.js +9 -7
- package/dist/domains/quality-assessment/coordinator-rl-integration.d.ts +0 -3
- package/dist/domains/quality-assessment/coordinator-rl-integration.js +10 -8
- package/dist/domains/quality-assessment/coordinator.d.ts +0 -15
- package/dist/domains/quality-assessment/coordinator.js +14 -12
- package/dist/domains/quality-assessment/services/deployment-advisor.d.ts +0 -10
- package/dist/domains/quality-assessment/services/deployment-advisor.js +4 -2
- package/dist/domains/quality-assessment/services/quality-analyzer.d.ts +0 -6
- package/dist/domains/quality-assessment/services/quality-analyzer.js +4 -2
- package/dist/domains/requirements-validation/coordinator.d.ts +0 -3
- package/dist/domains/requirements-validation/coordinator.js +15 -13
- package/dist/domains/requirements-validation/services/product-factors-assessment/code-intelligence/codebase-analyzer.d.ts +0 -5
- package/dist/domains/requirements-validation/services/product-factors-assessment/code-intelligence/codebase-analyzer.js +15 -13
- package/dist/domains/requirements-validation/services/product-factors-assessment/product-factors-service.d.ts +0 -6
- package/dist/domains/requirements-validation/services/product-factors-assessment/product-factors-service.js +9 -7
- package/dist/domains/requirements-validation/services/requirements-validator.d.ts +0 -6
- package/dist/domains/requirements-validation/services/requirements-validator.js +4 -2
- package/dist/domains/security-compliance/coordinator.js +24 -22
- package/dist/domains/security-compliance/services/scanners/dast-scanner.d.ts +0 -21
- package/dist/domains/security-compliance/services/scanners/dast-scanner.js +4 -2
- package/dist/domains/security-compliance/services/scanners/sast-scanner.d.ts +0 -4
- package/dist/domains/security-compliance/services/scanners/sast-scanner.js +3 -1
- package/dist/domains/security-compliance/services/security-auditor-dast.d.ts +0 -4
- package/dist/domains/security-compliance/services/security-auditor-dast.js +3 -1
- package/dist/domains/security-compliance/services/security-auditor-sast.d.ts +0 -3
- package/dist/domains/security-compliance/services/security-auditor-sast.js +3 -1
- package/dist/domains/security-compliance/services/security-auditor-secrets.d.ts +0 -3
- package/dist/domains/security-compliance/services/security-auditor-secrets.js +3 -1
- package/dist/domains/security-compliance/services/security-auditor.js +11 -9
- package/dist/domains/test-execution/coordinator.js +11 -9
- package/dist/domains/test-execution/services/auth-state-manager.d.ts +0 -3
- package/dist/domains/test-execution/services/auth-state-manager.js +4 -2
- package/dist/domains/test-execution/services/e2e/e2e-coordinator.d.ts +0 -14
- package/dist/domains/test-execution/services/e2e/e2e-coordinator.js +3 -1
- package/dist/domains/test-execution/services/flaky-detector.js +4 -2
- package/dist/domains/test-execution/services/retry-handler.js +3 -1
- package/dist/domains/test-execution/services/test-executor.js +3 -1
- package/dist/domains/test-generation/coordinator.d.ts +0 -17
- package/dist/domains/test-generation/coordinator.js +33 -31
- package/dist/domains/test-generation/pattern-injection/edge-case-injector.d.ts +0 -5
- package/dist/domains/test-generation/pattern-injection/edge-case-injector.js +3 -1
- package/dist/domains/test-generation/services/code-transform-integration.d.ts +0 -7
- package/dist/domains/test-generation/services/code-transform-integration.js +3 -1
- package/dist/domains/test-generation/services/coherence-gate-service.d.ts +0 -3
- package/dist/domains/test-generation/services/coherence-gate-service.js +3 -1
- package/dist/domains/test-generation/services/test-generator.d.ts +0 -8
- package/dist/domains/test-generation/services/test-generator.js +5 -3
- package/dist/domains/visual-accessibility/coordinator.d.ts +0 -3
- package/dist/domains/visual-accessibility/coordinator.js +14 -12
- package/dist/domains/visual-accessibility/services/accessibility-tester-browser.d.ts +0 -3
- package/dist/domains/visual-accessibility/services/accessibility-tester-browser.js +52 -50
- package/dist/domains/visual-accessibility/services/accessibility-tester.d.ts +0 -4
- package/dist/domains/visual-accessibility/services/accessibility-tester.js +8 -6
- package/dist/domains/visual-accessibility/services/axe-core-integration.d.ts +0 -3
- package/dist/domains/visual-accessibility/services/axe-core-integration.js +20 -18
- package/dist/domains/visual-accessibility/services/browser-security-scanner.d.ts +0 -4
- package/dist/domains/visual-accessibility/services/browser-security-scanner.js +6 -4
- package/dist/domains/visual-accessibility/services/browser-swarm-coordinator.d.ts +0 -30
- package/dist/domains/visual-accessibility/services/browser-swarm-coordinator.js +5 -3
- package/dist/domains/visual-accessibility/services/viewport-capture.d.ts +0 -27
- package/dist/domains/visual-accessibility/services/viewport-capture.js +6 -4
- package/dist/domains/visual-accessibility/services/visual-regression.d.ts +0 -26
- package/dist/domains/visual-accessibility/services/visual-regression.js +4 -2
- package/dist/domains/visual-accessibility/services/visual-tester.d.ts +0 -4
- package/dist/domains/visual-accessibility/services/visual-tester.js +4 -2
- package/dist/governance/deterministic-gateway-integration.js +1 -1
- package/dist/learning/agent-routing.d.ts +53 -0
- package/dist/learning/agent-routing.js +142 -0
- package/dist/learning/embedding-utils.d.ts +34 -0
- package/dist/learning/embedding-utils.js +95 -0
- package/dist/learning/pattern-promotion.d.ts +63 -0
- package/dist/learning/pattern-promotion.js +187 -0
- package/dist/learning/pretrained-patterns.d.ts +14 -0
- package/dist/learning/pretrained-patterns.js +726 -0
- package/dist/learning/qe-reasoning-bank-types.d.ts +174 -0
- package/dist/learning/qe-reasoning-bank-types.js +24 -0
- package/dist/learning/qe-reasoning-bank.d.ts +9 -192
- package/dist/learning/qe-reasoning-bank.js +48 -1093
- package/dist/mcp/bundle.js +335 -335
- package/dist/mcp/security/validators/command-validator.d.ts +1 -40
- package/dist/mcp/security/validators/command-validator.js +2 -122
- package/dist/mcp/security/validators/crypto-validator.d.ts +1 -39
- package/dist/mcp/security/validators/crypto-validator.js +2 -71
- package/dist/mcp/security/validators/input-sanitizer.d.ts +1 -55
- package/dist/mcp/security/validators/input-sanitizer.js +2 -156
- package/dist/mcp/security/validators/interfaces.d.ts +1 -163
- package/dist/mcp/security/validators/interfaces.js +2 -5
- package/dist/mcp/security/validators/path-traversal-validator.d.ts +1 -49
- package/dist/mcp/security/validators/path-traversal-validator.js +2 -241
- package/dist/mcp/security/validators/regex-safety-validator.d.ts +1 -49
- package/dist/mcp/security/validators/regex-safety-validator.js +2 -182
- package/dist/mcp/security/validators/validation-orchestrator.d.ts +1 -65
- package/dist/mcp/security/validators/validation-orchestrator.js +2 -145
- package/dist/shared/io/file-reader.js +1 -1
- package/dist/shared/security/command-validator.d.ts +44 -0
- package/dist/shared/security/command-validator.js +126 -0
- package/dist/shared/security/crypto-validator.d.ts +43 -0
- package/dist/shared/security/crypto-validator.js +75 -0
- package/dist/shared/security/index.d.ts +7 -0
- package/dist/shared/security/index.js +15 -0
- package/dist/shared/security/input-sanitizer.d.ts +59 -0
- package/dist/shared/security/input-sanitizer.js +160 -0
- package/dist/shared/security/path-traversal-validator.d.ts +53 -0
- package/dist/shared/security/path-traversal-validator.js +245 -0
- package/dist/shared/security/regex-safety-validator.d.ts +53 -0
- package/dist/shared/security/regex-safety-validator.js +186 -0
- package/dist/shared/security/validation-orchestrator.d.ts +69 -0
- package/dist/shared/security/validation-orchestrator.js +149 -0
- package/dist/shared/security/validators-interfaces.d.ts +167 -0
- package/dist/shared/security/validators-interfaces.js +9 -0
- package/package.json +1 -1
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
* Agentic QE v3 - Visual & Accessibility Coordinator
|
|
3
3
|
* Orchestrates the visual and accessibility testing workflows
|
|
4
4
|
*/
|
|
5
|
+
import { LoggerFactory } from '../../logging/index.js';
|
|
5
6
|
import { v4 as uuidv4 } from 'uuid';
|
|
6
7
|
import { toError, toErrorMessage } from '../../shared/error-utils.js';
|
|
7
8
|
import { ok, err, } from '../../shared/types/index.js';
|
|
@@ -35,6 +36,7 @@ const DEFAULT_CONFIG = {
|
|
|
35
36
|
/**
|
|
36
37
|
* CQ-002: Extends BaseDomainCoordinator
|
|
37
38
|
*/
|
|
39
|
+
const logger = LoggerFactory.create('visual-accessibility');
|
|
38
40
|
export class VisualAccessibilityCoordinator extends BaseDomainCoordinator {
|
|
39
41
|
memory;
|
|
40
42
|
agentCoordinator;
|
|
@@ -80,10 +82,10 @@ export class VisualAccessibilityCoordinator extends BaseDomainCoordinator {
|
|
|
80
82
|
numWorkers: 4,
|
|
81
83
|
});
|
|
82
84
|
// First call to predict will initialize the algorithm
|
|
83
|
-
|
|
85
|
+
logger.info('A2C algorithm created successfully');
|
|
84
86
|
}
|
|
85
87
|
catch (error) {
|
|
86
|
-
|
|
88
|
+
logger.error('Failed to create A2C:', error instanceof Error ? error : undefined);
|
|
87
89
|
throw new Error(`A2C creation failed: ${toErrorMessage(error)}`);
|
|
88
90
|
}
|
|
89
91
|
}
|
|
@@ -91,10 +93,10 @@ export class VisualAccessibilityCoordinator extends BaseDomainCoordinator {
|
|
|
91
93
|
if (this.config.enableFlashAttention) {
|
|
92
94
|
try {
|
|
93
95
|
this.flashAttention = await createQEFlashAttention('test-similarity');
|
|
94
|
-
|
|
96
|
+
logger.info('QEFlashAttention initialized successfully');
|
|
95
97
|
}
|
|
96
98
|
catch (error) {
|
|
97
|
-
|
|
99
|
+
logger.error('Failed to initialize Flash Attention:', error instanceof Error ? error : undefined);
|
|
98
100
|
throw new Error(`Flash Attention initialization failed: ${toErrorMessage(error)}`);
|
|
99
101
|
}
|
|
100
102
|
}
|
|
@@ -133,7 +135,7 @@ export class VisualAccessibilityCoordinator extends BaseDomainCoordinator {
|
|
|
133
135
|
this.startWorkflow(workflowId, 'visual');
|
|
134
136
|
// V3: Check topology health before proceeding (ADR-047)
|
|
135
137
|
if (this.config.enableMinCutAwareness && !this.isTopologyHealthy()) {
|
|
136
|
-
|
|
138
|
+
logger.warn('Topology degraded, using conservative strategy');
|
|
137
139
|
}
|
|
138
140
|
// V3: Pause operations if topology is critical and configured to pause
|
|
139
141
|
if (this.minCutMixin.shouldPauseOperations()) {
|
|
@@ -176,7 +178,7 @@ export class VisualAccessibilityCoordinator extends BaseDomainCoordinator {
|
|
|
176
178
|
url: t.url,
|
|
177
179
|
viewport: t.viewport,
|
|
178
180
|
}));
|
|
179
|
-
|
|
181
|
+
logger.info(`[visual-accessibility] Using ${prioritizationResult.value.strategy} strategy for visual test order (confidence: ${prioritizationResult.value.confidence.toFixed(2)})`);
|
|
180
182
|
}
|
|
181
183
|
}
|
|
182
184
|
const totalTests = testList.length;
|
|
@@ -281,7 +283,7 @@ export class VisualAccessibilityCoordinator extends BaseDomainCoordinator {
|
|
|
281
283
|
this.startWorkflow(workflowId, 'accessibility');
|
|
282
284
|
// V3: Check topology health before proceeding (ADR-047)
|
|
283
285
|
if (this.config.enableMinCutAwareness && !this.isTopologyHealthy()) {
|
|
284
|
-
|
|
286
|
+
logger.warn('Topology degraded, using conservative strategy');
|
|
285
287
|
}
|
|
286
288
|
// V3: Pause operations if topology is critical and configured to pause
|
|
287
289
|
if (this.minCutMixin.shouldPauseOperations()) {
|
|
@@ -925,7 +927,7 @@ export class VisualAccessibilityCoordinator extends BaseDomainCoordinator {
|
|
|
925
927
|
nextState: state,
|
|
926
928
|
done: true,
|
|
927
929
|
});
|
|
928
|
-
|
|
930
|
+
logger.info(`[visual-accessibility] A2C prioritized ${tests.length} visual tests using ${strategy} strategy (confidence: ${prediction.confidence.toFixed(2)})`);
|
|
929
931
|
return ok({
|
|
930
932
|
orderedTests: prioritized,
|
|
931
933
|
strategy,
|
|
@@ -933,7 +935,7 @@ export class VisualAccessibilityCoordinator extends BaseDomainCoordinator {
|
|
|
933
935
|
});
|
|
934
936
|
}
|
|
935
937
|
catch (error) {
|
|
936
|
-
|
|
938
|
+
logger.error('A2C prioritization failed:', error instanceof Error ? error : undefined);
|
|
937
939
|
// Return original tests on error (graceful degradation)
|
|
938
940
|
return ok({
|
|
939
941
|
orderedTests: tests.map((t) => ({ ...t, priority: t.priority ?? 5, reason: 'fallback' })),
|
|
@@ -981,7 +983,7 @@ export class VisualAccessibilityCoordinator extends BaseDomainCoordinator {
|
|
|
981
983
|
}));
|
|
982
984
|
}
|
|
983
985
|
catch (error) {
|
|
984
|
-
|
|
986
|
+
logger.error('Flash Attention similarity search failed:', error instanceof Error ? error : undefined);
|
|
985
987
|
return this.cosineSimilarityFallback(targetImageEmbedding, imageEmbeddings, topK);
|
|
986
988
|
}
|
|
987
989
|
}
|
|
@@ -1012,10 +1014,10 @@ export class VisualAccessibilityCoordinator extends BaseDomainCoordinator {
|
|
|
1012
1014
|
const embedding = this.createVisualEmbedding(url, viewport, diffScore, passed);
|
|
1013
1015
|
// Store in memory for future similarity searches
|
|
1014
1016
|
await this.memory.set(`visual-accessibility:embedding:${url}:${viewport.width}x${viewport.height}`, { embedding, url, viewport, diffScore, passed, timestamp: new Date() }, { namespace: 'visual-accessibility', persist: true });
|
|
1015
|
-
|
|
1017
|
+
logger.info(`Stored visual pattern for ${url} at ${viewport.width}x${viewport.height}`);
|
|
1016
1018
|
}
|
|
1017
1019
|
catch (error) {
|
|
1018
|
-
|
|
1020
|
+
logger.error('Failed to store visual pattern:', error instanceof Error ? error : undefined);
|
|
1019
1021
|
}
|
|
1020
1022
|
}
|
|
1021
1023
|
/**
|
|
@@ -32,9 +32,6 @@ export interface AxeCoreResult {
|
|
|
32
32
|
* WCAG 2.2 criteria definitions (shared reference)
|
|
33
33
|
*/
|
|
34
34
|
export declare const WCAG_CRITERIA: Record<string, WCAGCriterion>;
|
|
35
|
-
/**
|
|
36
|
-
* Check if client is an IAgentBrowserClient (has getSnapshot method)
|
|
37
|
-
*/
|
|
38
35
|
export declare function isAgentBrowserClient(client: IBrowserClient): client is IAgentBrowserClient;
|
|
39
36
|
/**
|
|
40
37
|
* Get axe-core tags for a WCAG conformance level
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
* Agentic QE v3 - Accessibility Tester Browser Mode
|
|
3
3
|
* Extracted from accessibility-tester.ts - Browser-based auditing via agent-browser and Vibium
|
|
4
4
|
*/
|
|
5
|
+
import { LoggerFactory } from '../../../logging/index.js';
|
|
5
6
|
import { ok, err } from '../../../shared/types/index.js';
|
|
6
7
|
import { toError } from '../../../shared/error-utils.js';
|
|
7
8
|
import { safeJsonParse } from '../../../shared/safe-json.js';
|
|
@@ -30,6 +31,7 @@ export const WCAG_CRITERIA = {
|
|
|
30
31
|
/**
|
|
31
32
|
* Check if client is an IAgentBrowserClient (has getSnapshot method)
|
|
32
33
|
*/
|
|
34
|
+
const logger = LoggerFactory.create('visual-accessibility/accessibility-tester-browser');
|
|
33
35
|
export function isAgentBrowserClient(client) {
|
|
34
36
|
return client.tool === 'agent-browser' && 'getSnapshot' in client;
|
|
35
37
|
}
|
|
@@ -79,55 +81,55 @@ export function getErrorMessage(result) {
|
|
|
79
81
|
export async function runAxeCore(client, wcagLevel, options) {
|
|
80
82
|
const tags = getAxeTagsForWcagLevel(wcagLevel);
|
|
81
83
|
const excludeSelectors = options?.excludeSelectors ?? [];
|
|
82
|
-
const axeScript = `
|
|
83
|
-
(async function() {
|
|
84
|
-
// Check if axe is already loaded
|
|
85
|
-
if (typeof axe === 'undefined') {
|
|
86
|
-
// Inject axe-core from CDN
|
|
87
|
-
const script = document.createElement('script');
|
|
88
|
-
script.src = 'https://cdnjs.cloudflare.com/ajax/libs/axe-core/4.8.4/axe.min.js';
|
|
89
|
-
script.crossOrigin = 'anonymous';
|
|
90
|
-
document.head.appendChild(script);
|
|
91
|
-
|
|
92
|
-
// Wait for script to load
|
|
93
|
-
await new Promise((resolve, reject) => {
|
|
94
|
-
script.onload = resolve;
|
|
95
|
-
script.onerror = () => reject(new Error('Failed to load axe-core'));
|
|
96
|
-
setTimeout(() => reject(new Error('Timeout loading axe-core')), 10000);
|
|
97
|
-
});
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
// Configure and run axe
|
|
101
|
-
const config = {
|
|
102
|
-
runOnly: {
|
|
103
|
-
type: 'tag',
|
|
104
|
-
values: ${JSON.stringify(tags)}
|
|
105
|
-
},
|
|
106
|
-
exclude: ${JSON.stringify(excludeSelectors.map(s => [s]))}
|
|
107
|
-
};
|
|
108
|
-
|
|
109
|
-
const results = await axe.run(document, config);
|
|
110
|
-
|
|
111
|
-
return JSON.stringify({
|
|
112
|
-
violations: results.violations.map(v => ({
|
|
113
|
-
id: v.id,
|
|
114
|
-
impact: v.impact,
|
|
115
|
-
description: v.description,
|
|
116
|
-
help: v.help,
|
|
117
|
-
helpUrl: v.helpUrl,
|
|
118
|
-
tags: v.tags,
|
|
119
|
-
nodes: v.nodes.map(n => ({
|
|
120
|
-
selector: n.target.join(' > '),
|
|
121
|
-
html: n.html,
|
|
122
|
-
target: n.target,
|
|
123
|
-
failureSummary: n.failureSummary
|
|
124
|
-
}))
|
|
125
|
-
})),
|
|
126
|
-
passes: results.passes.map(p => p.id),
|
|
127
|
-
incomplete: results.incomplete.map(i => i.id),
|
|
128
|
-
inapplicable: results.inapplicable.map(i => i.id)
|
|
129
|
-
});
|
|
130
|
-
})();
|
|
84
|
+
const axeScript = `
|
|
85
|
+
(async function() {
|
|
86
|
+
// Check if axe is already loaded
|
|
87
|
+
if (typeof axe === 'undefined') {
|
|
88
|
+
// Inject axe-core from CDN
|
|
89
|
+
const script = document.createElement('script');
|
|
90
|
+
script.src = 'https://cdnjs.cloudflare.com/ajax/libs/axe-core/4.8.4/axe.min.js';
|
|
91
|
+
script.crossOrigin = 'anonymous';
|
|
92
|
+
document.head.appendChild(script);
|
|
93
|
+
|
|
94
|
+
// Wait for script to load
|
|
95
|
+
await new Promise((resolve, reject) => {
|
|
96
|
+
script.onload = resolve;
|
|
97
|
+
script.onerror = () => reject(new Error('Failed to load axe-core'));
|
|
98
|
+
setTimeout(() => reject(new Error('Timeout loading axe-core')), 10000);
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// Configure and run axe
|
|
103
|
+
const config = {
|
|
104
|
+
runOnly: {
|
|
105
|
+
type: 'tag',
|
|
106
|
+
values: ${JSON.stringify(tags)}
|
|
107
|
+
},
|
|
108
|
+
exclude: ${JSON.stringify(excludeSelectors.map(s => [s]))}
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
const results = await axe.run(document, config);
|
|
112
|
+
|
|
113
|
+
return JSON.stringify({
|
|
114
|
+
violations: results.violations.map(v => ({
|
|
115
|
+
id: v.id,
|
|
116
|
+
impact: v.impact,
|
|
117
|
+
description: v.description,
|
|
118
|
+
help: v.help,
|
|
119
|
+
helpUrl: v.helpUrl,
|
|
120
|
+
tags: v.tags,
|
|
121
|
+
nodes: v.nodes.map(n => ({
|
|
122
|
+
selector: n.target.join(' > '),
|
|
123
|
+
html: n.html,
|
|
124
|
+
target: n.target,
|
|
125
|
+
failureSummary: n.failureSummary
|
|
126
|
+
}))
|
|
127
|
+
})),
|
|
128
|
+
passes: results.passes.map(p => p.id),
|
|
129
|
+
incomplete: results.incomplete.map(i => i.id),
|
|
130
|
+
inapplicable: results.inapplicable.map(i => i.id)
|
|
131
|
+
});
|
|
132
|
+
})();
|
|
131
133
|
`;
|
|
132
134
|
const evalResult = await client.evaluate(axeScript);
|
|
133
135
|
if (!evalResult.success) {
|
|
@@ -329,7 +331,7 @@ export async function auditWithBrowserClient(client, url, wcagLevel, browserConf
|
|
|
329
331
|
const snapshotResult = await client.getSnapshot({ interactive: true });
|
|
330
332
|
if (snapshotResult.success) {
|
|
331
333
|
const elementCount = snapshotResult.value.interactiveElements.length;
|
|
332
|
-
|
|
334
|
+
logger.debug(`Found ${elementCount} interactive elements`);
|
|
333
335
|
}
|
|
334
336
|
}
|
|
335
337
|
const axeResult = await runAxeCore(client, wcagLevel, options);
|
|
@@ -42,10 +42,6 @@ export interface AccessibilityTesterConfig {
|
|
|
42
42
|
browserClient?: IBrowserClient;
|
|
43
43
|
preferAgentBrowser: boolean;
|
|
44
44
|
}
|
|
45
|
-
/**
|
|
46
|
-
* Accessibility Auditing Service Implementation
|
|
47
|
-
* Provides WCAG 2.2 compliance checking with optional browser mode via Vibium
|
|
48
|
-
*/
|
|
49
45
|
export declare class AccessibilityTesterService implements IAccessibilityAuditingService {
|
|
50
46
|
private readonly memory;
|
|
51
47
|
private readonly config;
|
|
@@ -19,6 +19,7 @@
|
|
|
19
19
|
*
|
|
20
20
|
* @module domains/visual-accessibility/services/accessibility-tester
|
|
21
21
|
*/
|
|
22
|
+
import { LoggerFactory } from '../../../logging/index.js';
|
|
22
23
|
import { v4 as uuidv4 } from 'uuid';
|
|
23
24
|
import { ok, err } from '../../../shared/types/index.js';
|
|
24
25
|
import { EUComplianceService } from './eu-compliance.js';
|
|
@@ -47,6 +48,7 @@ const DEFAULT_CONFIG = {
|
|
|
47
48
|
* Accessibility Auditing Service Implementation
|
|
48
49
|
* Provides WCAG 2.2 compliance checking with optional browser mode via Vibium
|
|
49
50
|
*/
|
|
51
|
+
const logger = LoggerFactory.create('visual-accessibility/accessibility-tester');
|
|
50
52
|
export class AccessibilityTesterService {
|
|
51
53
|
memory;
|
|
52
54
|
config;
|
|
@@ -96,7 +98,7 @@ export class AccessibilityTesterService {
|
|
|
96
98
|
}
|
|
97
99
|
}
|
|
98
100
|
catch (error) {
|
|
99
|
-
|
|
101
|
+
logger.debug('Browser client error:');
|
|
100
102
|
}
|
|
101
103
|
}
|
|
102
104
|
return null;
|
|
@@ -116,7 +118,7 @@ export class AccessibilityTesterService {
|
|
|
116
118
|
return browserResult;
|
|
117
119
|
}
|
|
118
120
|
const errorMsg = getErrorMessage(browserResult);
|
|
119
|
-
|
|
121
|
+
logger.warn(`Browser client audit failed: ${errorMsg}`);
|
|
120
122
|
}
|
|
121
123
|
if (this.vibiumClient && isBrowserModeEnabled() && isAxeCoreEnabled()) {
|
|
122
124
|
const vibiumResult = await auditWithVibium(this.vibiumClient, url, wcagLevel, this.config.browserConfig, options);
|
|
@@ -125,7 +127,7 @@ export class AccessibilityTesterService {
|
|
|
125
127
|
return vibiumResult;
|
|
126
128
|
}
|
|
127
129
|
const errorMsg = getErrorMessage(vibiumResult);
|
|
128
|
-
|
|
130
|
+
logger.warn(`Vibium audit failed, falling back to heuristic mode: ${errorMsg}`);
|
|
129
131
|
}
|
|
130
132
|
}
|
|
131
133
|
return this.auditWithHeuristics(url, wcagLevel, options);
|
|
@@ -142,7 +144,7 @@ export class AccessibilityTesterService {
|
|
|
142
144
|
return browserResult;
|
|
143
145
|
}
|
|
144
146
|
const errorMsg = getErrorMessage(browserResult);
|
|
145
|
-
|
|
147
|
+
logger.warn(`Browser mode element audit failed, falling back to heuristic mode: ${errorMsg}`);
|
|
146
148
|
}
|
|
147
149
|
return this.audit(url, {
|
|
148
150
|
excludeSelectors: [],
|
|
@@ -226,7 +228,7 @@ export class AccessibilityTesterService {
|
|
|
226
228
|
}
|
|
227
229
|
else {
|
|
228
230
|
const errorMsg = getErrorMessage(browserResult);
|
|
229
|
-
|
|
231
|
+
logger.warn(`Browser mode contrast check failed, falling back to heuristic mode: ${errorMsg}`);
|
|
230
232
|
analyses = analyzeContrastForElements(url);
|
|
231
233
|
}
|
|
232
234
|
}
|
|
@@ -286,7 +288,7 @@ export class AccessibilityTesterService {
|
|
|
286
288
|
}
|
|
287
289
|
else {
|
|
288
290
|
const errorMsg = getErrorMessage(browserResult);
|
|
289
|
-
|
|
291
|
+
logger.warn(`Browser mode keyboard check failed, falling back to heuristic mode: ${errorMsg}`);
|
|
290
292
|
report = generateKeyboardReportWithHeuristics(url);
|
|
291
293
|
}
|
|
292
294
|
}
|
|
@@ -245,9 +245,6 @@ export declare const FIX_SUGGESTIONS: Record<string, string>;
|
|
|
245
245
|
* Using the official axe-core CDN
|
|
246
246
|
*/
|
|
247
247
|
export declare const AXE_CORE_CDN_URL = "https://cdnjs.cloudflare.com/ajax/libs/axe-core/4.8.4/axe.min.js";
|
|
248
|
-
/**
|
|
249
|
-
* Error thrown when axe-core injection fails
|
|
250
|
-
*/
|
|
251
248
|
export declare class AxeCoreInjectionError extends Error {
|
|
252
249
|
readonly cause?: Error | undefined;
|
|
253
250
|
constructor(message: string, cause?: Error | undefined);
|
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
*
|
|
11
11
|
* @module domains/visual-accessibility/services/axe-core-integration
|
|
12
12
|
*/
|
|
13
|
+
import { LoggerFactory } from '../../../logging/index.js';
|
|
13
14
|
import { ok, err } from '../../../shared/types/index.js';
|
|
14
15
|
import { toError } from '../../../shared/error-utils.js';
|
|
15
16
|
// ============================================================================
|
|
@@ -175,10 +176,10 @@ export const AXE_CORE_CDN_URL = 'https://cdnjs.cloudflare.com/ajax/libs/axe-core
|
|
|
175
176
|
* Minified axe-core script for injection
|
|
176
177
|
* This is a placeholder - in production, use the CDN or bundle axe-core
|
|
177
178
|
*/
|
|
178
|
-
const AXE_CORE_INJECTION_CHECK = `
|
|
179
|
-
if (typeof axe === 'undefined') {
|
|
180
|
-
throw new Error('axe-core not loaded');
|
|
181
|
-
}
|
|
179
|
+
const AXE_CORE_INJECTION_CHECK = `
|
|
180
|
+
if (typeof axe === 'undefined') {
|
|
181
|
+
throw new Error('axe-core not loaded');
|
|
182
|
+
}
|
|
182
183
|
`;
|
|
183
184
|
// ============================================================================
|
|
184
185
|
// Integration Functions
|
|
@@ -186,6 +187,7 @@ const AXE_CORE_INJECTION_CHECK = `
|
|
|
186
187
|
/**
|
|
187
188
|
* Error thrown when axe-core injection fails
|
|
188
189
|
*/
|
|
190
|
+
const logger = LoggerFactory.create('visual-accessibility/axe-core');
|
|
189
191
|
export class AxeCoreInjectionError extends Error {
|
|
190
192
|
cause;
|
|
191
193
|
constructor(message, cause) {
|
|
@@ -231,8 +233,8 @@ export async function injectAxeCore(client, options = {}) {
|
|
|
231
233
|
const { useCDN = true, timeout = 10000 } = options;
|
|
232
234
|
try {
|
|
233
235
|
// Check if axe-core is already loaded
|
|
234
|
-
const checkResult = await executeInBrowser(client, `
|
|
235
|
-
return typeof axe !== 'undefined';
|
|
236
|
+
const checkResult = await executeInBrowser(client, `
|
|
237
|
+
return typeof axe !== 'undefined';
|
|
236
238
|
`, timeout);
|
|
237
239
|
if (checkResult.success && checkResult.value === true) {
|
|
238
240
|
// axe-core already loaded
|
|
@@ -240,21 +242,21 @@ export async function injectAxeCore(client, options = {}) {
|
|
|
240
242
|
}
|
|
241
243
|
if (useCDN) {
|
|
242
244
|
// Try to load from CDN
|
|
243
|
-
const cdnResult = await executeInBrowser(client, `
|
|
244
|
-
return new Promise((resolve, reject) => {
|
|
245
|
-
const script = document.createElement('script');
|
|
246
|
-
script.src = '${AXE_CORE_CDN_URL}';
|
|
247
|
-
script.onload = () => resolve(true);
|
|
248
|
-
script.onerror = () => reject(new Error('Failed to load axe-core from CDN'));
|
|
249
|
-
document.head.appendChild(script);
|
|
250
|
-
setTimeout(() => reject(new Error('axe-core CDN load timeout')), ${timeout});
|
|
251
|
-
});
|
|
245
|
+
const cdnResult = await executeInBrowser(client, `
|
|
246
|
+
return new Promise((resolve, reject) => {
|
|
247
|
+
const script = document.createElement('script');
|
|
248
|
+
script.src = '${AXE_CORE_CDN_URL}';
|
|
249
|
+
script.onload = () => resolve(true);
|
|
250
|
+
script.onerror = () => reject(new Error('Failed to load axe-core from CDN'));
|
|
251
|
+
document.head.appendChild(script);
|
|
252
|
+
setTimeout(() => reject(new Error('axe-core CDN load timeout')), ${timeout});
|
|
253
|
+
});
|
|
252
254
|
`, timeout + 1000);
|
|
253
255
|
if (cdnResult.success) {
|
|
254
256
|
return ok(undefined);
|
|
255
257
|
}
|
|
256
258
|
// CDN failed, log and continue to fallback
|
|
257
|
-
|
|
259
|
+
logger.warn('Failed to load axe-core from CDN, attempting inline injection');
|
|
258
260
|
}
|
|
259
261
|
// Fallback: Check if we have inline axe-core (would need to be bundled)
|
|
260
262
|
// For now, return error if CDN fails
|
|
@@ -304,8 +306,8 @@ export async function runAxeAudit(client, options = {}) {
|
|
|
304
306
|
}
|
|
305
307
|
// Build the axe.run() call with options
|
|
306
308
|
const axeOptionsJson = JSON.stringify(options);
|
|
307
|
-
const auditScript = `
|
|
308
|
-
return await axe.run(document, ${axeOptionsJson});
|
|
309
|
+
const auditScript = `
|
|
310
|
+
return await axe.run(document, ${axeOptionsJson});
|
|
309
311
|
`;
|
|
310
312
|
const auditResult = await executeInBrowser(client, auditScript, 60000);
|
|
311
313
|
if (!auditResult.success) {
|
|
@@ -56,10 +56,6 @@ export interface BrowserSecurityScannerConfig {
|
|
|
56
56
|
/** Enable detailed logging */
|
|
57
57
|
verbose?: boolean;
|
|
58
58
|
}
|
|
59
|
-
/**
|
|
60
|
-
* Browser Security Scanner Service
|
|
61
|
-
* Wraps @claude-flow/browser MCP security features with graceful fallback
|
|
62
|
-
*/
|
|
63
59
|
export declare class BrowserSecurityScanner {
|
|
64
60
|
private initialized;
|
|
65
61
|
private browserAvailable;
|
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
*
|
|
10
10
|
* @module domains/visual-accessibility/services/browser-security-scanner
|
|
11
11
|
*/
|
|
12
|
+
import { LoggerFactory } from '../../../logging/index.js';
|
|
12
13
|
import { ok, err } from '../../../shared/types/index.js';
|
|
13
14
|
import { toErrorMessage } from '../../../shared/error-utils.js';
|
|
14
15
|
// ============================================================================
|
|
@@ -37,6 +38,7 @@ function hasMcpTools() {
|
|
|
37
38
|
* Browser Security Scanner Service
|
|
38
39
|
* Wraps @claude-flow/browser MCP security features with graceful fallback
|
|
39
40
|
*/
|
|
41
|
+
const logger = LoggerFactory.create('visual-accessibility/browser-security-scanner');
|
|
40
42
|
export class BrowserSecurityScanner {
|
|
41
43
|
initialized = false;
|
|
42
44
|
browserAvailable = false;
|
|
@@ -61,7 +63,7 @@ export class BrowserSecurityScanner {
|
|
|
61
63
|
// Check if MCP tools are available
|
|
62
64
|
this.browserAvailable = hasMcpTools();
|
|
63
65
|
if (this.config.verbose) {
|
|
64
|
-
|
|
66
|
+
logger.info(`MCP tools available: ${this.browserAvailable}`);
|
|
65
67
|
}
|
|
66
68
|
this.initialized = true;
|
|
67
69
|
}
|
|
@@ -112,7 +114,7 @@ export class BrowserSecurityScanner {
|
|
|
112
114
|
}
|
|
113
115
|
catch (error) {
|
|
114
116
|
if (this.config.verbose) {
|
|
115
|
-
|
|
117
|
+
logger.error('validateUrl error:', error instanceof Error ? error : undefined);
|
|
116
118
|
}
|
|
117
119
|
return this.fallbackValidateUrl(url);
|
|
118
120
|
}
|
|
@@ -154,7 +156,7 @@ export class BrowserSecurityScanner {
|
|
|
154
156
|
}
|
|
155
157
|
catch (error) {
|
|
156
158
|
if (this.config.verbose) {
|
|
157
|
-
|
|
159
|
+
logger.error('detectPhishing error:', error instanceof Error ? error : undefined);
|
|
158
160
|
}
|
|
159
161
|
return this.fallbackDetectPhishing(url);
|
|
160
162
|
}
|
|
@@ -189,7 +191,7 @@ export class BrowserSecurityScanner {
|
|
|
189
191
|
}
|
|
190
192
|
catch (error) {
|
|
191
193
|
if (this.config.verbose) {
|
|
192
|
-
|
|
194
|
+
logger.error('scanForPII error:', error instanceof Error ? error : undefined);
|
|
193
195
|
}
|
|
194
196
|
return this.fallbackScanForPII(content);
|
|
195
197
|
}
|
|
@@ -137,36 +137,6 @@ export interface BrowserSwarmConfig {
|
|
|
137
137
|
* Standard viewport configurations for common devices
|
|
138
138
|
*/
|
|
139
139
|
export declare const STANDARD_VIEWPORTS: Viewport[];
|
|
140
|
-
/**
|
|
141
|
-
* Multi-session browser coordinator for parallel viewport testing
|
|
142
|
-
*
|
|
143
|
-
* Manages a pool of browser sessions across different viewports,
|
|
144
|
-
* enabling efficient parallel testing with resource management.
|
|
145
|
-
*
|
|
146
|
-
* Features:
|
|
147
|
-
* - Parallel session management across multiple viewports
|
|
148
|
-
* - Resource monitoring and memory management
|
|
149
|
-
* - Graceful degradation to sequential execution
|
|
150
|
-
* - Automatic session cleanup and recovery
|
|
151
|
-
* - Support for screenshots and accessibility audits
|
|
152
|
-
*
|
|
153
|
-
* @example
|
|
154
|
-
* ```typescript
|
|
155
|
-
* const coordinator = new BrowserSwarmCoordinator(memory);
|
|
156
|
-
*
|
|
157
|
-
* // Initialize with standard viewports
|
|
158
|
-
* await coordinator.initialize(STANDARD_VIEWPORTS);
|
|
159
|
-
*
|
|
160
|
-
* // Capture screenshots across all viewports in parallel
|
|
161
|
-
* const screenshots = await coordinator.captureAllViewports('https://example.com');
|
|
162
|
-
*
|
|
163
|
-
* // Run accessibility audits
|
|
164
|
-
* const audits = await coordinator.auditAllViewports('https://example.com');
|
|
165
|
-
*
|
|
166
|
-
* // Cleanup
|
|
167
|
-
* await coordinator.shutdown();
|
|
168
|
-
* ```
|
|
169
|
-
*/
|
|
170
140
|
export declare class BrowserSwarmCoordinator {
|
|
171
141
|
private readonly memory;
|
|
172
142
|
private readonly config;
|
|
@@ -19,6 +19,7 @@
|
|
|
19
19
|
*
|
|
20
20
|
* @module domains/visual-accessibility/services/browser-swarm-coordinator
|
|
21
21
|
*/
|
|
22
|
+
import { LoggerFactory } from '../../../logging/index.js';
|
|
22
23
|
import { v4 as uuidv4 } from 'uuid';
|
|
23
24
|
import { ok, err } from '../../../shared/types/index.js';
|
|
24
25
|
import { FilePath } from '../../../shared/value-objects/index.js';
|
|
@@ -111,6 +112,7 @@ const DEFAULT_CONFIG = {
|
|
|
111
112
|
* await coordinator.shutdown();
|
|
112
113
|
* ```
|
|
113
114
|
*/
|
|
115
|
+
const logger = LoggerFactory.create('visual-accessibility/browser-swarm');
|
|
114
116
|
export class BrowserSwarmCoordinator {
|
|
115
117
|
memory;
|
|
116
118
|
config;
|
|
@@ -408,7 +410,7 @@ export class BrowserSwarmCoordinator {
|
|
|
408
410
|
}
|
|
409
411
|
catch (error) {
|
|
410
412
|
// Log but don't fail shutdown
|
|
411
|
-
|
|
413
|
+
logger.error(`[BrowserSwarm] Failed to close session ${session.id}`, error instanceof Error ? error : undefined);
|
|
412
414
|
}
|
|
413
415
|
});
|
|
414
416
|
await Promise.all(closePromises);
|
|
@@ -512,7 +514,7 @@ export class BrowserSwarmCoordinator {
|
|
|
512
514
|
this.memoryCheckInterval = setInterval(() => {
|
|
513
515
|
const memoryUsage = this.estimateMemoryUsage();
|
|
514
516
|
if (memoryUsage > this.config.memoryThresholdMB) {
|
|
515
|
-
|
|
517
|
+
logger.warn(`[BrowserSwarm] Memory usage ${memoryUsage.toFixed(2)}MB exceeds threshold ${this.config.memoryThresholdMB}MB. Degrading to sequential execution.`);
|
|
516
518
|
}
|
|
517
519
|
// Store metrics
|
|
518
520
|
this.memory
|
|
@@ -522,7 +524,7 @@ export class BrowserSwarmCoordinator {
|
|
|
522
524
|
timestamp: new Date(),
|
|
523
525
|
}, { namespace: 'visual-accessibility', ttl: 3600 })
|
|
524
526
|
.catch((err) => {
|
|
525
|
-
|
|
527
|
+
logger.error('Failed to store memory metrics:', err instanceof Error ? err : undefined);
|
|
526
528
|
});
|
|
527
529
|
}, 30000);
|
|
528
530
|
}
|
|
@@ -247,33 +247,6 @@ export interface SingleCaptureOptions {
|
|
|
247
247
|
/** Hide selectors */
|
|
248
248
|
hideSelectors?: string[];
|
|
249
249
|
}
|
|
250
|
-
/**
|
|
251
|
-
* Multi-viewport screenshot capture service implementation
|
|
252
|
-
*
|
|
253
|
-
* Provides comprehensive screenshot capture capabilities:
|
|
254
|
-
* - Capture at multiple viewports in parallel
|
|
255
|
-
* - Capture at CSS breakpoints for responsive testing
|
|
256
|
-
* - Screenshot comparison utilities
|
|
257
|
-
* - Performance metrics tracking
|
|
258
|
-
*
|
|
259
|
-
* @example
|
|
260
|
-
* ```typescript
|
|
261
|
-
* const service = new ViewportCaptureService(memory, vibiumClient);
|
|
262
|
-
*
|
|
263
|
-
* // Capture at standard presets
|
|
264
|
-
* const result = await service.captureWithPresets(
|
|
265
|
-
* 'https://example.com',
|
|
266
|
-
* ['mobile-m', 'tablet', 'desktop']
|
|
267
|
-
* );
|
|
268
|
-
*
|
|
269
|
-
* // Capture at responsive breakpoints
|
|
270
|
-
* const analysis = await service.captureResponsiveBreakpoints(
|
|
271
|
-
* 'https://example.com',
|
|
272
|
-
* 320,
|
|
273
|
-
* 1920
|
|
274
|
-
* );
|
|
275
|
-
* ```
|
|
276
|
-
*/
|
|
277
250
|
export declare class ViewportCaptureService implements IViewportCaptureService {
|
|
278
251
|
private readonly memory;
|
|
279
252
|
private readonly vibiumClient?;
|
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
*
|
|
12
12
|
* @module domains/visual-accessibility/services/viewport-capture
|
|
13
13
|
*/
|
|
14
|
+
import { LoggerFactory } from '../../../logging/index.js';
|
|
14
15
|
import { v4 as uuidv4 } from 'uuid';
|
|
15
16
|
import { ok, err } from '../../../shared/types/index.js';
|
|
16
17
|
import { FilePath } from '../../../shared/value-objects/index.js';
|
|
@@ -140,6 +141,7 @@ const DEFAULT_CONFIG = {
|
|
|
140
141
|
* );
|
|
141
142
|
* ```
|
|
142
143
|
*/
|
|
144
|
+
const logger = LoggerFactory.create('visual-accessibility/viewport-capture');
|
|
143
145
|
export class ViewportCaptureService {
|
|
144
146
|
memory;
|
|
145
147
|
vibiumClient;
|
|
@@ -179,7 +181,7 @@ export class ViewportCaptureService {
|
|
|
179
181
|
}
|
|
180
182
|
catch (error) {
|
|
181
183
|
// Non-critical: browser client acquisition failed
|
|
182
|
-
|
|
184
|
+
logger.debug('Browser client error:');
|
|
183
185
|
}
|
|
184
186
|
}
|
|
185
187
|
return null;
|
|
@@ -343,7 +345,7 @@ export class ViewportCaptureService {
|
|
|
343
345
|
return result;
|
|
344
346
|
}
|
|
345
347
|
// Log failure and try next option
|
|
346
|
-
|
|
348
|
+
logger.warn(`Browser client capture failed, trying Vibium`);
|
|
347
349
|
}
|
|
348
350
|
// If Vibium client is available and has active session, use real browser capture
|
|
349
351
|
if (this.vibiumClient) {
|
|
@@ -385,7 +387,7 @@ export class ViewportCaptureService {
|
|
|
385
387
|
}
|
|
386
388
|
else {
|
|
387
389
|
// Log warning but continue with valid presets
|
|
388
|
-
|
|
390
|
+
logger.warn(`Unknown preset: ${name}`);
|
|
389
391
|
}
|
|
390
392
|
}
|
|
391
393
|
if (viewports.length === 0) {
|
|
@@ -453,7 +455,7 @@ export class ViewportCaptureService {
|
|
|
453
455
|
// Set viewport for device emulation
|
|
454
456
|
const viewportResult = await client.setViewport(viewport.width, viewport.height);
|
|
455
457
|
if (!viewportResult.success) {
|
|
456
|
-
|
|
458
|
+
logger.warn(`setViewport failed: ${viewportResult.error?.message}`);
|
|
457
459
|
}
|
|
458
460
|
// Optionally set device preset for mobile viewports
|
|
459
461
|
if (viewport.isMobile) {
|