mindheal 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.env.example +48 -0
- package/CHANGELOG.md +27 -0
- package/LICENSE +21 -0
- package/README.md +481 -0
- package/dist/cjs/ai/ai-provider.js +46 -0
- package/dist/cjs/ai/ai-provider.js.map +1 -0
- package/dist/cjs/ai/anthropic-provider.js +106 -0
- package/dist/cjs/ai/anthropic-provider.js.map +1 -0
- package/dist/cjs/ai/azure-openai-provider.js +130 -0
- package/dist/cjs/ai/azure-openai-provider.js.map +1 -0
- package/dist/cjs/ai/bedrock-provider.js +183 -0
- package/dist/cjs/ai/bedrock-provider.js.map +1 -0
- package/dist/cjs/ai/deepseek-provider.js +118 -0
- package/dist/cjs/ai/deepseek-provider.js.map +1 -0
- package/dist/cjs/ai/gemini-provider.js +129 -0
- package/dist/cjs/ai/gemini-provider.js.map +1 -0
- package/dist/cjs/ai/groq-provider.js +118 -0
- package/dist/cjs/ai/groq-provider.js.map +1 -0
- package/dist/cjs/ai/meta-provider.js +118 -0
- package/dist/cjs/ai/meta-provider.js.map +1 -0
- package/dist/cjs/ai/ollama-provider.js +127 -0
- package/dist/cjs/ai/ollama-provider.js.map +1 -0
- package/dist/cjs/ai/openai-provider.js +117 -0
- package/dist/cjs/ai/openai-provider.js.map +1 -0
- package/dist/cjs/ai/perplexity-provider.js +118 -0
- package/dist/cjs/ai/perplexity-provider.js.map +1 -0
- package/dist/cjs/ai/prompt-templates.js +174 -0
- package/dist/cjs/ai/prompt-templates.js.map +1 -0
- package/dist/cjs/ai/qwen-provider.js +118 -0
- package/dist/cjs/ai/qwen-provider.js.map +1 -0
- package/dist/cjs/analytics/healing-analytics.js +263 -0
- package/dist/cjs/analytics/healing-analytics.js.map +1 -0
- package/dist/cjs/cli/init.js +517 -0
- package/dist/cjs/cli/init.js.map +1 -0
- package/dist/cjs/config/config-loader.js +135 -0
- package/dist/cjs/config/config-loader.js.map +1 -0
- package/dist/cjs/config/defaults.js +109 -0
- package/dist/cjs/config/defaults.js.map +1 -0
- package/dist/cjs/core/dom-snapshot.js +280 -0
- package/dist/cjs/core/dom-snapshot.js.map +1 -0
- package/dist/cjs/core/enterprise-strategy.js +702 -0
- package/dist/cjs/core/enterprise-strategy.js.map +1 -0
- package/dist/cjs/core/healer.js +283 -0
- package/dist/cjs/core/healer.js.map +1 -0
- package/dist/cjs/core/interceptor.js +945 -0
- package/dist/cjs/core/interceptor.js.map +1 -0
- package/dist/cjs/core/locator-analyzer.js +172 -0
- package/dist/cjs/core/locator-analyzer.js.map +1 -0
- package/dist/cjs/core/locator-strategies.js +891 -0
- package/dist/cjs/core/locator-strategies.js.map +1 -0
- package/dist/cjs/core/self-heal-cache.js +178 -0
- package/dist/cjs/core/self-heal-cache.js.map +1 -0
- package/dist/cjs/core/smart-retry.js +248 -0
- package/dist/cjs/core/smart-retry.js.map +1 -0
- package/dist/cjs/core/visual-verification.js +262 -0
- package/dist/cjs/core/visual-verification.js.map +1 -0
- package/dist/cjs/git/code-modifier.js +184 -0
- package/dist/cjs/git/code-modifier.js.map +1 -0
- package/dist/cjs/git/git-operations.js +145 -0
- package/dist/cjs/git/git-operations.js.map +1 -0
- package/dist/cjs/git/pr-creator.js +190 -0
- package/dist/cjs/git/pr-creator.js.map +1 -0
- package/dist/cjs/index.js +97 -0
- package/dist/cjs/index.js.map +1 -0
- package/dist/cjs/rag/context-retriever.js +289 -0
- package/dist/cjs/rag/context-retriever.js.map +1 -0
- package/dist/cjs/rag/embeddings.js +82 -0
- package/dist/cjs/rag/embeddings.js.map +1 -0
- package/dist/cjs/rag/knowledge-store.js +159 -0
- package/dist/cjs/rag/knowledge-store.js.map +1 -0
- package/dist/cjs/reporters/heal-report.js +279 -0
- package/dist/cjs/reporters/heal-report.js.map +1 -0
- package/dist/cjs/reporters/heal-reporter.js +294 -0
- package/dist/cjs/reporters/heal-reporter.js.map +1 -0
- package/dist/cjs/server/review-server.js +166 -0
- package/dist/cjs/server/review-server.js.map +1 -0
- package/dist/cjs/server/routes.js +92 -0
- package/dist/cjs/server/routes.js.map +1 -0
- package/dist/cjs/utils/environment.js +57 -0
- package/dist/cjs/utils/environment.js.map +1 -0
- package/dist/cjs/utils/file-lock.js +136 -0
- package/dist/cjs/utils/file-lock.js.map +1 -0
- package/dist/cjs/utils/file-utils.js +49 -0
- package/dist/cjs/utils/file-utils.js.map +1 -0
- package/dist/cjs/utils/logger.js +78 -0
- package/dist/cjs/utils/logger.js.map +1 -0
- package/dist/esm/ai/ai-provider.js +44 -0
- package/dist/esm/ai/ai-provider.js.map +1 -0
- package/dist/esm/ai/anthropic-provider.js +104 -0
- package/dist/esm/ai/anthropic-provider.js.map +1 -0
- package/dist/esm/ai/azure-openai-provider.js +128 -0
- package/dist/esm/ai/azure-openai-provider.js.map +1 -0
- package/dist/esm/ai/bedrock-provider.js +181 -0
- package/dist/esm/ai/bedrock-provider.js.map +1 -0
- package/dist/esm/ai/deepseek-provider.js +116 -0
- package/dist/esm/ai/deepseek-provider.js.map +1 -0
- package/dist/esm/ai/gemini-provider.js +127 -0
- package/dist/esm/ai/gemini-provider.js.map +1 -0
- package/dist/esm/ai/groq-provider.js +116 -0
- package/dist/esm/ai/groq-provider.js.map +1 -0
- package/dist/esm/ai/meta-provider.js +116 -0
- package/dist/esm/ai/meta-provider.js.map +1 -0
- package/dist/esm/ai/ollama-provider.js +125 -0
- package/dist/esm/ai/ollama-provider.js.map +1 -0
- package/dist/esm/ai/openai-provider.js +115 -0
- package/dist/esm/ai/openai-provider.js.map +1 -0
- package/dist/esm/ai/perplexity-provider.js +116 -0
- package/dist/esm/ai/perplexity-provider.js.map +1 -0
- package/dist/esm/ai/prompt-templates.js +171 -0
- package/dist/esm/ai/prompt-templates.js.map +1 -0
- package/dist/esm/ai/qwen-provider.js +116 -0
- package/dist/esm/ai/qwen-provider.js.map +1 -0
- package/dist/esm/analytics/healing-analytics.js +261 -0
- package/dist/esm/analytics/healing-analytics.js.map +1 -0
- package/dist/esm/cli/init.js +495 -0
- package/dist/esm/cli/init.js.map +1 -0
- package/dist/esm/config/config-loader.js +132 -0
- package/dist/esm/config/config-loader.js.map +1 -0
- package/dist/esm/config/defaults.js +107 -0
- package/dist/esm/config/defaults.js.map +1 -0
- package/dist/esm/core/dom-snapshot.js +278 -0
- package/dist/esm/core/dom-snapshot.js.map +1 -0
- package/dist/esm/core/enterprise-strategy.js +695 -0
- package/dist/esm/core/enterprise-strategy.js.map +1 -0
- package/dist/esm/core/healer.js +281 -0
- package/dist/esm/core/healer.js.map +1 -0
- package/dist/esm/core/interceptor.js +940 -0
- package/dist/esm/core/interceptor.js.map +1 -0
- package/dist/esm/core/locator-analyzer.js +169 -0
- package/dist/esm/core/locator-analyzer.js.map +1 -0
- package/dist/esm/core/locator-strategies.js +882 -0
- package/dist/esm/core/locator-strategies.js.map +1 -0
- package/dist/esm/core/self-heal-cache.js +176 -0
- package/dist/esm/core/self-heal-cache.js.map +1 -0
- package/dist/esm/core/smart-retry.js +246 -0
- package/dist/esm/core/smart-retry.js.map +1 -0
- package/dist/esm/core/visual-verification.js +260 -0
- package/dist/esm/core/visual-verification.js.map +1 -0
- package/dist/esm/git/code-modifier.js +182 -0
- package/dist/esm/git/code-modifier.js.map +1 -0
- package/dist/esm/git/git-operations.js +143 -0
- package/dist/esm/git/git-operations.js.map +1 -0
- package/dist/esm/git/pr-creator.js +188 -0
- package/dist/esm/git/pr-creator.js.map +1 -0
- package/dist/esm/index.js +37 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/rag/context-retriever.js +287 -0
- package/dist/esm/rag/context-retriever.js.map +1 -0
- package/dist/esm/rag/embeddings.js +77 -0
- package/dist/esm/rag/embeddings.js.map +1 -0
- package/dist/esm/rag/knowledge-store.js +157 -0
- package/dist/esm/rag/knowledge-store.js.map +1 -0
- package/dist/esm/reporters/heal-report.js +277 -0
- package/dist/esm/reporters/heal-report.js.map +1 -0
- package/dist/esm/reporters/heal-reporter.js +290 -0
- package/dist/esm/reporters/heal-reporter.js.map +1 -0
- package/dist/esm/server/review-server.js +164 -0
- package/dist/esm/server/review-server.js.map +1 -0
- package/dist/esm/server/routes.js +90 -0
- package/dist/esm/server/routes.js.map +1 -0
- package/dist/esm/utils/environment.js +53 -0
- package/dist/esm/utils/environment.js.map +1 -0
- package/dist/esm/utils/file-lock.js +134 -0
- package/dist/esm/utils/file-lock.js.map +1 -0
- package/dist/esm/utils/file-utils.js +43 -0
- package/dist/esm/utils/file-utils.js.map +1 -0
- package/dist/esm/utils/logger.js +75 -0
- package/dist/esm/utils/logger.js.map +1 -0
- package/dist/types/ai/ai-provider.d.ts +4 -0
- package/dist/types/ai/ai-provider.d.ts.map +1 -0
- package/dist/types/ai/anthropic-provider.d.ts +11 -0
- package/dist/types/ai/anthropic-provider.d.ts.map +1 -0
- package/dist/types/ai/azure-openai-provider.d.ts +13 -0
- package/dist/types/ai/azure-openai-provider.d.ts.map +1 -0
- package/dist/types/ai/bedrock-provider.d.ts +14 -0
- package/dist/types/ai/bedrock-provider.d.ts.map +1 -0
- package/dist/types/ai/deepseek-provider.d.ts +12 -0
- package/dist/types/ai/deepseek-provider.d.ts.map +1 -0
- package/dist/types/ai/gemini-provider.d.ts +12 -0
- package/dist/types/ai/gemini-provider.d.ts.map +1 -0
- package/dist/types/ai/groq-provider.d.ts +12 -0
- package/dist/types/ai/groq-provider.d.ts.map +1 -0
- package/dist/types/ai/meta-provider.d.ts +12 -0
- package/dist/types/ai/meta-provider.d.ts.map +1 -0
- package/dist/types/ai/ollama-provider.d.ts +10 -0
- package/dist/types/ai/ollama-provider.d.ts.map +1 -0
- package/dist/types/ai/openai-provider.d.ts +11 -0
- package/dist/types/ai/openai-provider.d.ts.map +1 -0
- package/dist/types/ai/perplexity-provider.d.ts +12 -0
- package/dist/types/ai/perplexity-provider.d.ts.map +1 -0
- package/dist/types/ai/prompt-templates.d.ts +11 -0
- package/dist/types/ai/prompt-templates.d.ts.map +1 -0
- package/dist/types/ai/qwen-provider.d.ts +12 -0
- package/dist/types/ai/qwen-provider.d.ts.map +1 -0
- package/dist/types/analytics/healing-analytics.d.ts +36 -0
- package/dist/types/analytics/healing-analytics.d.ts.map +1 -0
- package/dist/types/cli/init.d.ts +15 -0
- package/dist/types/cli/init.d.ts.map +1 -0
- package/dist/types/config/config-loader.d.ts +4 -0
- package/dist/types/config/config-loader.d.ts.map +1 -0
- package/dist/types/config/defaults.d.ts +3 -0
- package/dist/types/config/defaults.d.ts.map +1 -0
- package/dist/types/core/dom-snapshot.d.ts +12 -0
- package/dist/types/core/dom-snapshot.d.ts.map +1 -0
- package/dist/types/core/enterprise-strategy.d.ts +56 -0
- package/dist/types/core/enterprise-strategy.d.ts.map +1 -0
- package/dist/types/core/healer.d.ts +52 -0
- package/dist/types/core/healer.d.ts.map +1 -0
- package/dist/types/core/interceptor.d.ts +64 -0
- package/dist/types/core/interceptor.d.ts.map +1 -0
- package/dist/types/core/locator-analyzer.d.ts +31 -0
- package/dist/types/core/locator-analyzer.d.ts.map +1 -0
- package/dist/types/core/locator-strategies.d.ts +45 -0
- package/dist/types/core/locator-strategies.d.ts.map +1 -0
- package/dist/types/core/self-heal-cache.d.ts +51 -0
- package/dist/types/core/self-heal-cache.d.ts.map +1 -0
- package/dist/types/core/smart-retry.d.ts +64 -0
- package/dist/types/core/smart-retry.d.ts.map +1 -0
- package/dist/types/core/visual-verification.d.ts +46 -0
- package/dist/types/core/visual-verification.d.ts.map +1 -0
- package/dist/types/git/code-modifier.d.ts +51 -0
- package/dist/types/git/code-modifier.d.ts.map +1 -0
- package/dist/types/git/git-operations.d.ts +40 -0
- package/dist/types/git/git-operations.d.ts.map +1 -0
- package/dist/types/git/pr-creator.d.ts +27 -0
- package/dist/types/git/pr-creator.d.ts.map +1 -0
- package/dist/types/index.d.ts +40 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/rag/context-retriever.d.ts +69 -0
- package/dist/types/rag/context-retriever.d.ts.map +1 -0
- package/dist/types/rag/embeddings.d.ts +32 -0
- package/dist/types/rag/embeddings.d.ts.map +1 -0
- package/dist/types/rag/index.d.ts +12 -0
- package/dist/types/rag/index.d.ts.map +1 -0
- package/dist/types/rag/knowledge-store.d.ts +38 -0
- package/dist/types/rag/knowledge-store.d.ts.map +1 -0
- package/dist/types/reporters/heal-report.d.ts +29 -0
- package/dist/types/reporters/heal-report.d.ts.map +1 -0
- package/dist/types/reporters/heal-reporter.d.ts +49 -0
- package/dist/types/reporters/heal-reporter.d.ts.map +1 -0
- package/dist/types/server/review-server.d.ts +20 -0
- package/dist/types/server/review-server.d.ts.map +1 -0
- package/dist/types/server/routes.d.ts +4 -0
- package/dist/types/server/routes.d.ts.map +1 -0
- package/dist/types/types/index.d.ts +433 -0
- package/dist/types/types/index.d.ts.map +1 -0
- package/dist/types/utils/environment.d.ts +10 -0
- package/dist/types/utils/environment.d.ts.map +1 -0
- package/dist/types/utils/file-lock.d.ts +37 -0
- package/dist/types/utils/file-lock.d.ts.map +1 -0
- package/dist/types/utils/file-utils.d.ts +7 -0
- package/dist/types/utils/file-utils.d.ts.map +1 -0
- package/dist/types/utils/logger.d.ts +9 -0
- package/dist/types/utils/logger.d.ts.map +1 -0
- package/package.json +106 -0
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Enterprise Application Healing Strategy
|
|
3
|
+
*
|
|
4
|
+
* Specialized healing for complex enterprise web applications:
|
|
5
|
+
* - SAP Fiori / SAP GUI for HTML / UI5
|
|
6
|
+
* - Salesforce Lightning / Classic / LWC
|
|
7
|
+
* - Oracle ERP / NetSuite
|
|
8
|
+
* - Workday
|
|
9
|
+
* - ServiceNow
|
|
10
|
+
* - Microsoft Dynamics 365
|
|
11
|
+
*
|
|
12
|
+
* These platforms share common challenges:
|
|
13
|
+
* 1. Dynamically generated IDs that change on every render
|
|
14
|
+
* 2. Deep Shadow DOM nesting (Lightning Web Components)
|
|
15
|
+
* 3. Deeply nested iframes (SAP GUI, Classic Salesforce)
|
|
16
|
+
* 4. Custom web components with proprietary tag names
|
|
17
|
+
* 5. Virtual scrolling / lazy-loaded grids with thousands of rows
|
|
18
|
+
* 6. Complex multi-level menus and navigation trees
|
|
19
|
+
* 7. Hashed/obfuscated CSS class names
|
|
20
|
+
* 8. Heavy async data loading with skeleton/shimmer screens
|
|
21
|
+
*/
|
|
22
|
+
import type { Page } from '@playwright/test';
|
|
23
|
+
import type { LocatorInfo, DOMSnapshot, StrategyAttempt } from '../types/index';
|
|
24
|
+
/**
|
|
25
|
+
* Detects if an ID appears to be dynamically generated.
|
|
26
|
+
*/
|
|
27
|
+
export declare function isDynamicId(id: string): boolean;
|
|
28
|
+
/**
|
|
29
|
+
* Detects the enterprise platform from page URL, DOM content, or element tags.
|
|
30
|
+
*/
|
|
31
|
+
export declare function detectPlatform(url: string, html: string): string | null;
|
|
32
|
+
/**
|
|
33
|
+
* Strips dynamic ID prefixes/suffixes to extract the stable portion.
|
|
34
|
+
* Example: "__xmlview0--loginButton" → "loginButton"
|
|
35
|
+
*/
|
|
36
|
+
export declare function extractStableIdPart(id: string): string | null;
|
|
37
|
+
/**
|
|
38
|
+
* Enterprise healing strategy.
|
|
39
|
+
*
|
|
40
|
+
* Handles dynamic IDs, custom web components, enterprise-specific stable
|
|
41
|
+
* attributes, and Shadow DOM / iframe piercing for SAP, Salesforce,
|
|
42
|
+
* Oracle, Workday, ServiceNow, Dynamics 365, and similar platforms.
|
|
43
|
+
*/
|
|
44
|
+
export declare function enterpriseStrategy(page: Page, originalLocator: LocatorInfo, domSnapshot: DOMSnapshot): Promise<StrategyAttempt>;
|
|
45
|
+
/**
|
|
46
|
+
* Enterprise applications often have extended loading times with skeleton
|
|
47
|
+
* screens, spinners, and async data fetches. This helper waits for
|
|
48
|
+
* enterprise-specific loading indicators to disappear.
|
|
49
|
+
*/
|
|
50
|
+
export declare function waitForEnterpriseLoad(page: Page, timeout?: number): Promise<void>;
|
|
51
|
+
/**
|
|
52
|
+
* Scrolls a virtual scroll container to try to bring more elements into view.
|
|
53
|
+
* Enterprise grids (SAP ALV, Salesforce report tables) often virtualize rows.
|
|
54
|
+
*/
|
|
55
|
+
export declare function scrollVirtualContainer(page: Page, containerSelector?: string): Promise<void>;
|
|
56
|
+
//# sourceMappingURL=enterprise-strategy.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"enterprise-strategy.d.ts","sourceRoot":"","sources":["../../../src/core/enterprise-strategy.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAC7C,OAAO,KAAK,EACV,WAAW,EAEX,WAAW,EACX,eAAe,EAEhB,MAAM,gBAAgB,CAAC;AA+HxB;;GAEG;AACH,wBAAgB,WAAW,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAE/C;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAuCvE;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAW7D;AAoaD;;;;;;GAMG;AACH,wBAAsB,kBAAkB,CACtC,IAAI,EAAE,IAAI,EACV,eAAe,EAAE,WAAW,EAC5B,WAAW,EAAE,WAAW,GACvB,OAAO,CAAC,eAAe,CAAC,CAkF1B;AAID;;;;GAIG;AACH,wBAAsB,qBAAqB,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,SAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,CAwCtF;AAED;;;GAGG;AACH,wBAAsB,sBAAsB,CAC1C,IAAI,EAAE,IAAI,EACV,iBAAiB,CAAC,EAAE,MAAM,GACzB,OAAO,CAAC,IAAI,CAAC,CA+Bf"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import type { Page } from '@playwright/test';
|
|
2
|
+
import type { MindHealConfig, AIProvider, LocatorInfo, HealingResult } from '../types/index';
|
|
3
|
+
import { SelfHealCache } from './self-heal-cache';
|
|
4
|
+
import { ContextRetriever } from '../rag/context-retriever';
|
|
5
|
+
import { SmartRetry } from './smart-retry';
|
|
6
|
+
import { VisualVerifier } from './visual-verification';
|
|
7
|
+
import { HealingAnalytics } from '../analytics/healing-analytics';
|
|
8
|
+
/**
|
|
9
|
+
* The healing engine that orchestrates locator recovery.
|
|
10
|
+
*
|
|
11
|
+
* Executes strategies in the order defined by the configuration and stops
|
|
12
|
+
* on the first result whose confidence meets or exceeds the configured threshold.
|
|
13
|
+
*
|
|
14
|
+
* Pipeline order: cache -> attribute -> text -> role -> css -> xpath -> ai
|
|
15
|
+
*/
|
|
16
|
+
export declare class Healer {
|
|
17
|
+
private readonly config;
|
|
18
|
+
private readonly aiProvider;
|
|
19
|
+
private readonly cache;
|
|
20
|
+
private readonly contextRetriever;
|
|
21
|
+
private readonly smartRetry;
|
|
22
|
+
private readonly visualVerifier;
|
|
23
|
+
private readonly analytics;
|
|
24
|
+
constructor(config: MindHealConfig, aiProvider: AIProvider | null, cache: SelfHealCache, contextRetriever?: ContextRetriever | null, smartRetry?: SmartRetry | null, visualVerifier?: VisualVerifier | null, analytics?: HealingAnalytics | null);
|
|
25
|
+
/**
|
|
26
|
+
* Attempts to heal a broken locator by running configured strategies in order.
|
|
27
|
+
*
|
|
28
|
+
* @param page - Playwright Page instance for DOM inspection.
|
|
29
|
+
* @param originalLocator - The locator that failed to resolve.
|
|
30
|
+
* @param action - The Playwright action that was attempted (e.g. "click", "fill").
|
|
31
|
+
* @param error - The original error that triggered healing.
|
|
32
|
+
* @returns A HealingResult describing what happened, including all attempts.
|
|
33
|
+
*/
|
|
34
|
+
heal(page: Page, originalLocator: LocatorInfo, action: string, error: Error): Promise<HealingResult>;
|
|
35
|
+
/**
|
|
36
|
+
* Executes a single named strategy and returns the attempt result.
|
|
37
|
+
* The "cache" and "ai" strategies are handled specially; everything else
|
|
38
|
+
* delegates to the shared `runStrategy` dispatcher.
|
|
39
|
+
*/
|
|
40
|
+
private executeStrategy;
|
|
41
|
+
private cacheStrategy;
|
|
42
|
+
private aiStrategy;
|
|
43
|
+
/**
|
|
44
|
+
* Verifies that a proposed healed locator actually resolves to at least one
|
|
45
|
+
* element on the page. Uses a short timeout to avoid blocking.
|
|
46
|
+
*/
|
|
47
|
+
private verifyLocator;
|
|
48
|
+
private cacheResult;
|
|
49
|
+
private buildReasoning;
|
|
50
|
+
private buildFailureResult;
|
|
51
|
+
}
|
|
52
|
+
//# sourceMappingURL=healer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"healer.d.ts","sourceRoot":"","sources":["../../../src/core/healer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAC7C,OAAO,KAAK,EACV,cAAc,EACd,UAAU,EACV,WAAW,EACX,aAAa,EAKd,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAKlD,OAAO,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAC5D,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAC3C,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,gBAAgB,EAAE,MAAM,gCAAgC,CAAC;AAWlE;;;;;;;GAOG;AACH,qBAAa,MAAM;IACjB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAiB;IACxC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAoB;IAC/C,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAgB;IACtC,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAA0B;IAC3D,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAoB;IAC/C,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAwB;IACvD,OAAO,CAAC,QAAQ,CAAC,SAAS,CAA0B;gBAGlD,MAAM,EAAE,cAAc,EACtB,UAAU,EAAE,UAAU,GAAG,IAAI,EAC7B,KAAK,EAAE,aAAa,EACpB,gBAAgB,CAAC,EAAE,gBAAgB,GAAG,IAAI,EAC1C,UAAU,CAAC,EAAE,UAAU,GAAG,IAAI,EAC9B,cAAc,CAAC,EAAE,cAAc,GAAG,IAAI,EACtC,SAAS,CAAC,EAAE,gBAAgB,GAAG,IAAI;IAWrC;;;;;;;;OAQG;IACG,IAAI,CACR,IAAI,EAAE,IAAI,EACV,eAAe,EAAE,WAAW,EAC5B,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,KAAK,GACX,OAAO,CAAC,aAAa,CAAC;IAqHzB;;;;OAIG;YACW,eAAe;IAwB7B,OAAO,CAAC,aAAa;YAgCP,UAAU;IAiExB;;;OAGG;YACW,aAAa;IAqB3B,OAAO,CAAC,WAAW;IAoCnB,OAAO,CAAC,cAAc;IActB,OAAO,CAAC,kBAAkB;CAgB3B"}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import type { MindHealConfig, HealingSession, MindHealFixtures, MindHealWorkerFixtures } from '../types/index';
|
|
2
|
+
export declare function getHealingSession(sessionId: string): HealingSession | undefined;
|
|
3
|
+
export declare function getAllHealingSessions(): HealingSession[];
|
|
4
|
+
/**
|
|
5
|
+
* Creates a Playwright fixture that wraps the built-in `page` fixture with the
|
|
6
|
+
* MindHeal healing proxy. Tests require zero changes; failures are healed
|
|
7
|
+
* transparently.
|
|
8
|
+
*
|
|
9
|
+
* Usage:
|
|
10
|
+
* ```ts
|
|
11
|
+
* import { createMindHealFixture } from 'mindheal';
|
|
12
|
+
* const test = createMindHealFixture(myConfig);
|
|
13
|
+
* ```
|
|
14
|
+
*/
|
|
15
|
+
export declare function createMindHealFixture(config: MindHealConfig): import("playwright/test").TestType<import("playwright/test").PlaywrightTestArgs & import("playwright/test").PlaywrightTestOptions & MindHealFixtures, import("playwright/test").PlaywrightWorkerArgs & import("playwright/test").PlaywrightWorkerOptions & MindHealWorkerFixtures>;
|
|
16
|
+
/**
|
|
17
|
+
* Convenience function that returns a partial Playwright config object
|
|
18
|
+
* pre-configured with the MindHeal fixture and reporter.
|
|
19
|
+
*
|
|
20
|
+
* Usage in `playwright.config.ts`:
|
|
21
|
+
* ```ts
|
|
22
|
+
* import { mindHealConfig } from 'mindheal';
|
|
23
|
+
* import { defineConfig } from '@playwright/test';
|
|
24
|
+
*
|
|
25
|
+
* export default defineConfig({
|
|
26
|
+
* ...mindHealConfig({ ai: { provider: 'anthropic', apiKey: '...' } }),
|
|
27
|
+
* });
|
|
28
|
+
* ```
|
|
29
|
+
*/
|
|
30
|
+
export declare function mindHealConfig(userConfig?: Partial<MindHealConfig>): {
|
|
31
|
+
test: import("playwright/test").TestType<import("playwright/test").PlaywrightTestArgs & import("playwright/test").PlaywrightTestOptions & MindHealFixtures, import("playwright/test").PlaywrightWorkerArgs & import("playwright/test").PlaywrightWorkerOptions & MindHealWorkerFixtures>;
|
|
32
|
+
use: {};
|
|
33
|
+
reporter: ("list"[] | ("json" | {
|
|
34
|
+
outputFile: string;
|
|
35
|
+
})[])[];
|
|
36
|
+
metadata: {
|
|
37
|
+
mindHealConfig: MindHealConfig;
|
|
38
|
+
};
|
|
39
|
+
};
|
|
40
|
+
/**
|
|
41
|
+
* Returns the resolved config set by `mindHealConfig()`. Used internally by
|
|
42
|
+
* the auto-fixture export so that `import { test } from 'mindheal'` works
|
|
43
|
+
* without consumers having to thread the config themselves.
|
|
44
|
+
*/
|
|
45
|
+
export declare function getGlobalConfig(): MindHealConfig | null;
|
|
46
|
+
/**
|
|
47
|
+
* Pre-built `test` fixture that reads config from `mindHealConfig()` call in
|
|
48
|
+
* `playwright.config.ts`. This enables zero-change imports:
|
|
49
|
+
*
|
|
50
|
+
* ```ts
|
|
51
|
+
* // playwright.config.ts
|
|
52
|
+
* import { mindHealConfig } from 'mindheal';
|
|
53
|
+
* export default defineConfig({ ...mindHealConfig({ ai: { ... } }) });
|
|
54
|
+
*
|
|
55
|
+
* // Any test file — no changes needed if you use this import:
|
|
56
|
+
* import { test, expect } from 'mindheal';
|
|
57
|
+
* ```
|
|
58
|
+
*
|
|
59
|
+
* If `mindHealConfig()` has not been called yet (e.g. the config file hasn't
|
|
60
|
+
* loaded), this falls back to the standard `@playwright/test` `test` with no
|
|
61
|
+
* healing — tests still run, they just won't self-heal.
|
|
62
|
+
*/
|
|
63
|
+
export declare const autoTest: import("playwright/test").TestType<import("playwright/test").PlaywrightTestArgs & import("playwright/test").PlaywrightTestOptions & MindHealFixtures, import("playwright/test").PlaywrightWorkerArgs & import("playwright/test").PlaywrightWorkerOptions & MindHealWorkerFixtures>;
|
|
64
|
+
//# sourceMappingURL=interceptor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"interceptor.d.ts","sourceRoot":"","sources":["../../../src/core/interceptor.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,cAAc,EACd,cAAc,EAOd,gBAAgB,EAChB,sBAAsB,EACvB,MAAM,gBAAgB,CAAC;AAuBxB,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,MAAM,GAAG,cAAc,GAAG,SAAS,CAE/E;AAED,wBAAgB,qBAAqB,IAAI,cAAc,EAAE,CAExD;AA+rBD;;;;;;;;;;GAUG;AACH,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,cAAc,sRA4J3D;AAID;;;;;;;;;;;;;GAaG;AACH,wBAAgB,cAAc,CAAC,UAAU,GAAE,OAAO,CAAC,cAAc,CAAM;;;;;;;;;EAgCtE;AAMD;;;;GAIG;AACH,wBAAgB,eAAe,IAAI,cAAc,GAAG,IAAI,CAEvD;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,QAAQ,oRAqKjB,CAAC"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type { LocatorInfo } from '../types/index';
|
|
2
|
+
/**
|
|
3
|
+
* Analyzes a Playwright locator expression and extracts structured information.
|
|
4
|
+
*
|
|
5
|
+
* Handles both full Playwright expressions (e.g., `page.getByRole('button', { name: 'Submit' })`)
|
|
6
|
+
* and raw selectors (e.g., `#submit-btn`, `//button[@type="submit"]`).
|
|
7
|
+
*
|
|
8
|
+
* @param expression - The locator expression string to analyze.
|
|
9
|
+
* @returns Structured LocatorInfo with type, selector, options, and the original expression.
|
|
10
|
+
*/
|
|
11
|
+
export declare function analyzeLocator(expression: string): LocatorInfo;
|
|
12
|
+
/**
|
|
13
|
+
* Parses a Playwright expression into a method name and its arguments.
|
|
14
|
+
*
|
|
15
|
+
* @param expression - Full Playwright expression (e.g., `page.getByRole('button', { name: 'OK' })`)
|
|
16
|
+
* @returns An object with the method name and parsed arguments array.
|
|
17
|
+
*/
|
|
18
|
+
export declare function parsePlaywrightExpression(expression: string): {
|
|
19
|
+
method: string;
|
|
20
|
+
args: unknown[];
|
|
21
|
+
};
|
|
22
|
+
/**
|
|
23
|
+
* Generates a stable hash key for a locator + page URL combination.
|
|
24
|
+
* Used as the cache key in the self-heal cache.
|
|
25
|
+
*
|
|
26
|
+
* @param locator - The parsed locator information.
|
|
27
|
+
* @param pageUrl - The page URL (the path portion is used, query params stripped).
|
|
28
|
+
* @returns A hex string hash.
|
|
29
|
+
*/
|
|
30
|
+
export declare function getLocatorHash(locator: LocatorInfo, pageUrl: string): string;
|
|
31
|
+
//# sourceMappingURL=locator-analyzer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"locator-analyzer.d.ts","sourceRoot":"","sources":["../../../src/core/locator-analyzer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAe,MAAM,gBAAgB,CAAC;AA4E/D;;;;;;;;GAQG;AACH,wBAAgB,cAAc,CAAC,UAAU,EAAE,MAAM,GAAG,WAAW,CAiE9D;AAED;;;;;GAKG;AACH,wBAAgB,yBAAyB,CAAC,UAAU,EAAE,MAAM,GAAG;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,OAAO,EAAE,CAAA;CAAE,CAgDjG;AAED;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAkB5E"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import type { Page } from '@playwright/test';
|
|
2
|
+
import type { LocatorInfo, DOMSnapshot, StrategyAttempt } from '../types/index';
|
|
3
|
+
/**
|
|
4
|
+
* Finds elements with similar attributes (id, name, class, data-testid, aria-label).
|
|
5
|
+
* Uses Levenshtein-based similarity on attribute values.
|
|
6
|
+
*/
|
|
7
|
+
declare function attributeStrategy(page: Page, originalLocator: LocatorInfo, _domSnapshot: DOMSnapshot): Promise<StrategyAttempt>;
|
|
8
|
+
/**
|
|
9
|
+
* Matches elements by visible text content or placeholder text.
|
|
10
|
+
*/
|
|
11
|
+
declare function textStrategy(page: Page, originalLocator: LocatorInfo, _domSnapshot: DOMSnapshot): Promise<StrategyAttempt>;
|
|
12
|
+
/**
|
|
13
|
+
* Matches elements by ARIA role and accessible name.
|
|
14
|
+
*/
|
|
15
|
+
declare function roleStrategy(page: Page, originalLocator: LocatorInfo, _domSnapshot: DOMSnapshot): Promise<StrategyAttempt>;
|
|
16
|
+
/**
|
|
17
|
+
* Finds elements with similar CSS selectors using edit distance comparison.
|
|
18
|
+
*/
|
|
19
|
+
declare function cssProximityStrategy(page: Page, originalLocator: LocatorInfo, _domSnapshot: DOMSnapshot): Promise<StrategyAttempt>;
|
|
20
|
+
/**
|
|
21
|
+
* Generates XPath-based locators using element context from the DOM snapshot.
|
|
22
|
+
*/
|
|
23
|
+
declare function xpathStrategy(page: Page, originalLocator: LocatorInfo, _domSnapshot: DOMSnapshot): Promise<StrategyAttempt>;
|
|
24
|
+
/**
|
|
25
|
+
* Finds elements within HTML tables using row/column indexing,
|
|
26
|
+
* header-to-cell correlation, and structural matching.
|
|
27
|
+
*/
|
|
28
|
+
declare function tableStrategy(page: Page, originalLocator: LocatorInfo, _domSnapshot: DOMSnapshot): Promise<StrategyAttempt>;
|
|
29
|
+
/**
|
|
30
|
+
* Finds elements within modal dialogs, popups, and overlays.
|
|
31
|
+
* Prioritises candidates that are inside currently visible modals/dialogs.
|
|
32
|
+
*/
|
|
33
|
+
declare function modalStrategy(page: Page, originalLocator: LocatorInfo, _domSnapshot: DOMSnapshot): Promise<StrategyAttempt>;
|
|
34
|
+
/**
|
|
35
|
+
* Dispatches a named healing strategy and returns the result.
|
|
36
|
+
*
|
|
37
|
+
* @param name - The strategy name (attribute, text, role, css, xpath).
|
|
38
|
+
* @param page - Playwright Page object.
|
|
39
|
+
* @param originalLocator - The original failed locator information.
|
|
40
|
+
* @param domSnapshot - A DOM snapshot of the page.
|
|
41
|
+
* @returns The strategy attempt result.
|
|
42
|
+
*/
|
|
43
|
+
export declare function runStrategy(name: string, page: Page, originalLocator: LocatorInfo, domSnapshot: DOMSnapshot): Promise<StrategyAttempt>;
|
|
44
|
+
export { attributeStrategy, textStrategy, roleStrategy, cssProximityStrategy, xpathStrategy, tableStrategy, modalStrategy, };
|
|
45
|
+
//# sourceMappingURL=locator-strategies.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"locator-strategies.d.ts","sourceRoot":"","sources":["../../../src/core/locator-strategies.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAC7C,OAAO,KAAK,EACV,WAAW,EAEX,WAAW,EAEX,eAAe,EAChB,MAAM,gBAAgB,CAAC;AA0cxB;;;GAGG;AACH,iBAAe,iBAAiB,CAC9B,IAAI,EAAE,IAAI,EACV,eAAe,EAAE,WAAW,EAC5B,YAAY,EAAE,WAAW,GACxB,OAAO,CAAC,eAAe,CAAC,CAwD1B;AAED;;GAEG;AACH,iBAAe,YAAY,CACzB,IAAI,EAAE,IAAI,EACV,eAAe,EAAE,WAAW,EAC5B,YAAY,EAAE,WAAW,GACxB,OAAO,CAAC,eAAe,CAAC,CAmD1B;AAED;;GAEG;AACH,iBAAe,YAAY,CACzB,IAAI,EAAE,IAAI,EACV,eAAe,EAAE,WAAW,EAC5B,YAAY,EAAE,WAAW,GACxB,OAAO,CAAC,eAAe,CAAC,CAiE1B;AAED;;GAEG;AACH,iBAAe,oBAAoB,CACjC,IAAI,EAAE,IAAI,EACV,eAAe,EAAE,WAAW,EAC5B,YAAY,EAAE,WAAW,GACxB,OAAO,CAAC,eAAe,CAAC,CAgD1B;AAED;;GAEG;AACH,iBAAe,aAAa,CAC1B,IAAI,EAAE,IAAI,EACV,eAAe,EAAE,WAAW,EAC5B,YAAY,EAAE,WAAW,GACxB,OAAO,CAAC,eAAe,CAAC,CAkD1B;AAID;;;GAGG;AACH,iBAAe,aAAa,CAC1B,IAAI,EAAE,IAAI,EACV,eAAe,EAAE,WAAW,EAC5B,YAAY,EAAE,WAAW,GACxB,OAAO,CAAC,eAAe,CAAC,CAqE1B;AAqCD;;;GAGG;AACH,iBAAe,aAAa,CAC1B,IAAI,EAAE,IAAI,EACV,eAAe,EAAE,WAAW,EAC5B,YAAY,EAAE,WAAW,GACxB,OAAO,CAAC,eAAe,CAAC,CAyE1B;AA2ED;;;;;;;;GAQG;AACH,wBAAsB,WAAW,CAC/B,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,IAAI,EACV,eAAe,EAAE,WAAW,EAC5B,WAAW,EAAE,WAAW,GACvB,OAAO,CAAC,eAAe,CAAC,CAqB1B;AAED,OAAO,EACL,iBAAiB,EACjB,YAAY,EACZ,YAAY,EACZ,oBAAoB,EACpB,aAAa,EACb,aAAa,EACb,aAAa,GACd,CAAC"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import type { CacheEntry } from '../types/index';
|
|
2
|
+
/**
|
|
3
|
+
* In-memory + file-backed cache for healed locator mappings.
|
|
4
|
+
*
|
|
5
|
+
* Keys are hashes of (original selector + page URL pattern), generated
|
|
6
|
+
* by `getLocatorHash` from the locator-analyzer module.
|
|
7
|
+
*
|
|
8
|
+
* The cache is loaded from disk on initialization and saved after every mutation.
|
|
9
|
+
* Entries older than 30 days are pruned during load.
|
|
10
|
+
*/
|
|
11
|
+
export declare class SelfHealCache {
|
|
12
|
+
private readonly cachePath;
|
|
13
|
+
private entries;
|
|
14
|
+
private loaded;
|
|
15
|
+
constructor(cachePath?: string);
|
|
16
|
+
/**
|
|
17
|
+
* Loads the cache from disk. Prunes expired entries.
|
|
18
|
+
* Safe to call multiple times; subsequent calls reload from disk.
|
|
19
|
+
*/
|
|
20
|
+
load(): void;
|
|
21
|
+
/**
|
|
22
|
+
* Persists the current in-memory cache to disk.
|
|
23
|
+
*/
|
|
24
|
+
save(): void;
|
|
25
|
+
/**
|
|
26
|
+
* Ensures the cache is loaded before any read/write operation.
|
|
27
|
+
*/
|
|
28
|
+
private ensureLoaded;
|
|
29
|
+
/**
|
|
30
|
+
* Retrieves a cache entry by hash. Updates usage count and timestamp on hit.
|
|
31
|
+
* Returns `undefined` if not found.
|
|
32
|
+
*/
|
|
33
|
+
get(hash: string): CacheEntry | undefined;
|
|
34
|
+
/**
|
|
35
|
+
* Stores or updates a cache entry.
|
|
36
|
+
*/
|
|
37
|
+
set(hash: string, entry: CacheEntry): void;
|
|
38
|
+
/**
|
|
39
|
+
* Checks if a non-expired entry exists for the given hash.
|
|
40
|
+
*/
|
|
41
|
+
has(hash: string): boolean;
|
|
42
|
+
/**
|
|
43
|
+
* Removes all entries from the cache and saves the empty state to disk.
|
|
44
|
+
*/
|
|
45
|
+
clear(): void;
|
|
46
|
+
/**
|
|
47
|
+
* Returns the number of entries currently in the cache.
|
|
48
|
+
*/
|
|
49
|
+
get size(): number;
|
|
50
|
+
}
|
|
51
|
+
//# sourceMappingURL=self-heal-cache.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"self-heal-cache.d.ts","sourceRoot":"","sources":["../../../src/core/self-heal-cache.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAa,MAAM,gBAAgB,CAAC;AAoB5D;;;;;;;;GAQG;AACH,qBAAa,aAAa;IACxB,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IACnC,OAAO,CAAC,OAAO,CAA0B;IACzC,OAAO,CAAC,MAAM,CAAU;gBAEZ,SAAS,CAAC,EAAE,MAAM;IAM9B;;;OAGG;IACH,IAAI,IAAI,IAAI;IA2DZ;;OAEG;IACH,IAAI,IAAI,IAAI;IAiBZ;;OAEG;IACH,OAAO,CAAC,YAAY;IAMpB;;;OAGG;IACH,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,UAAU,GAAG,SAAS;IAuBzC;;OAEG;IACH,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,UAAU,GAAG,IAAI;IAS1C;;OAEG;IACH,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;IAe1B;;OAEG;IACH,KAAK,IAAI,IAAI;IAOb;;OAEG;IACH,IAAI,IAAI,IAAI,MAAM,CAGjB;CACF"}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Smart Retry Intelligence
|
|
3
|
+
*
|
|
4
|
+
* Provides:
|
|
5
|
+
* 1. Network idle wait — waits for all pending requests to settle before healing
|
|
6
|
+
* 2. Exponential backoff — progressive delays between retry attempts
|
|
7
|
+
* 3. Flaky test detection — tracks intermittent failures vs genuine breakage
|
|
8
|
+
* 4. Test stability scoring — scores each locator by failure frequency
|
|
9
|
+
*/
|
|
10
|
+
import type { Page } from '@playwright/test';
|
|
11
|
+
import type { SmartRetryConfig, FlakyTestEntry, LocatorInfo } from '../types/index';
|
|
12
|
+
export declare class SmartRetry {
|
|
13
|
+
private readonly config;
|
|
14
|
+
private flakyStore;
|
|
15
|
+
private loaded;
|
|
16
|
+
constructor(config: SmartRetryConfig);
|
|
17
|
+
load(): void;
|
|
18
|
+
save(): void;
|
|
19
|
+
/**
|
|
20
|
+
* Waits for network to become idle before attempting healing.
|
|
21
|
+
* Prevents healing from running while the page is still loading data.
|
|
22
|
+
*/
|
|
23
|
+
waitForNetworkIdle(page: Page): Promise<void>;
|
|
24
|
+
/**
|
|
25
|
+
* Additionally waits for DOM to stabilize (no mutations for 500ms).
|
|
26
|
+
* Useful for SPAs that render asynchronously.
|
|
27
|
+
*/
|
|
28
|
+
waitForDOMStable(page: Page, stabilityMs?: number): Promise<void>;
|
|
29
|
+
/**
|
|
30
|
+
* Computes the delay for the given retry attempt using exponential backoff.
|
|
31
|
+
* Includes jitter to prevent thundering herd in parallel execution.
|
|
32
|
+
*
|
|
33
|
+
* @param attempt - Zero-based attempt index (0 = first retry)
|
|
34
|
+
* @returns Delay in milliseconds
|
|
35
|
+
*/
|
|
36
|
+
getBackoffDelay(attempt: number): number;
|
|
37
|
+
/**
|
|
38
|
+
* Sleeps for the computed backoff delay.
|
|
39
|
+
*/
|
|
40
|
+
backoff(attempt: number): Promise<void>;
|
|
41
|
+
/**
|
|
42
|
+
* Records a healing attempt result for flaky detection.
|
|
43
|
+
*/
|
|
44
|
+
recordAttempt(testFile: string, testTitle: string, locator: LocatorInfo, success: boolean): void;
|
|
45
|
+
/**
|
|
46
|
+
* Check if a locator in a test file is known to be flaky.
|
|
47
|
+
*/
|
|
48
|
+
isFlaky(testFile: string, locator: LocatorInfo): boolean;
|
|
49
|
+
/**
|
|
50
|
+
* Returns all known flaky test entries.
|
|
51
|
+
*/
|
|
52
|
+
getFlakyTests(): FlakyTestEntry[];
|
|
53
|
+
/**
|
|
54
|
+
* Returns all consistently broken entries (not flaky, just broken).
|
|
55
|
+
*/
|
|
56
|
+
getBrokenLocators(): FlakyTestEntry[];
|
|
57
|
+
/**
|
|
58
|
+
* Determines whether to skip healing for a known flaky locator and just retry.
|
|
59
|
+
* If the locator is flaky (intermittent), a simple retry may be sufficient
|
|
60
|
+
* without running the full healing pipeline.
|
|
61
|
+
*/
|
|
62
|
+
shouldSkipHealing(testFile: string, locator: LocatorInfo): boolean;
|
|
63
|
+
}
|
|
64
|
+
//# sourceMappingURL=smart-retry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"smart-retry.d.ts","sourceRoot":"","sources":["../../../src/core/smart-retry.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAC7C,OAAO,KAAK,EACV,gBAAgB,EAChB,cAAc,EAEd,WAAW,EACZ,MAAM,gBAAgB,CAAC;AAOxB,qBAAa,UAAU;IACrB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAmB;IAC1C,OAAO,CAAC,UAAU,CAAiB;IACnC,OAAO,CAAC,MAAM,CAAS;gBAEX,MAAM,EAAE,gBAAgB;IAOpC,IAAI,IAAI,IAAI;IA4BZ,IAAI,IAAI,IAAI;IAcZ;;;OAGG;IACG,kBAAkB,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;IAcnD;;;OAGG;IACG,gBAAgB,CAAC,IAAI,EAAE,IAAI,EAAE,WAAW,SAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAoCpE;;;;;;OAMG;IACH,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM;IAUxC;;OAEG;IACG,OAAO,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAU7C;;OAEG;IACH,aAAa,CACX,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,WAAW,EACpB,OAAO,EAAE,OAAO,GACf,IAAI;IAwDP;;OAEG;IACH,OAAO,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,WAAW,GAAG,OAAO;IASxD;;OAEG;IACH,aAAa,IAAI,cAAc,EAAE;IAOjC;;OAEG;IACH,iBAAiB,IAAI,cAAc,EAAE;IAOrC;;;;OAIG;IACH,iBAAiB,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,WAAW,GAAG,OAAO;CAInE"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Visual Verification
|
|
3
|
+
*
|
|
4
|
+
* After healing a locator, captures a screenshot of the healed element and
|
|
5
|
+
* verifies it's visually the correct element. This prevents "wrong element"
|
|
6
|
+
* heals where the selector matches something in a different part of the page.
|
|
7
|
+
*
|
|
8
|
+
* Checks:
|
|
9
|
+
* 1. Element is visible on the page
|
|
10
|
+
* 2. Element is within the viewport (not scrolled off-screen)
|
|
11
|
+
* 3. Element has a reasonable bounding box (not 0x0)
|
|
12
|
+
* 4. Screenshot capture succeeds (element is rendered)
|
|
13
|
+
*/
|
|
14
|
+
import type { Page } from '@playwright/test';
|
|
15
|
+
import type { VisualVerificationConfig, VisualVerificationResult, LocatorInfo } from '../types/index';
|
|
16
|
+
/**
|
|
17
|
+
* Visual Verification engine for healed locators.
|
|
18
|
+
*/
|
|
19
|
+
export declare class VisualVerifier {
|
|
20
|
+
private readonly config;
|
|
21
|
+
constructor(config: VisualVerificationConfig);
|
|
22
|
+
/**
|
|
23
|
+
* Verify that a healed locator points to a visually valid element.
|
|
24
|
+
*
|
|
25
|
+
* Returns a VisualVerificationResult with:
|
|
26
|
+
* - `verified`: true if the element passes all visual checks
|
|
27
|
+
* - `elementScreenshotPath`: path to element screenshot (if captured)
|
|
28
|
+
* - `boundingBox`: element's position and size on page
|
|
29
|
+
* - `elementVisible`: whether the element is visible
|
|
30
|
+
* - `elementInViewport`: whether the element is within the viewport
|
|
31
|
+
*/
|
|
32
|
+
verify(page: Page, healedLocator: LocatorInfo, eventId: string): Promise<VisualVerificationResult>;
|
|
33
|
+
/**
|
|
34
|
+
* Compare two screenshots at the pixel level.
|
|
35
|
+
* Returns a similarity score (0-1).
|
|
36
|
+
*
|
|
37
|
+
* This is a lightweight comparison using a sampling approach
|
|
38
|
+
* (no external image processing libraries required).
|
|
39
|
+
*/
|
|
40
|
+
compareScreenshots(page: Page, screenshotA: Buffer, screenshotB: Buffer): Promise<number>;
|
|
41
|
+
/**
|
|
42
|
+
* Cleanup old screenshots if keepScreenshots is false.
|
|
43
|
+
*/
|
|
44
|
+
cleanup(): void;
|
|
45
|
+
}
|
|
46
|
+
//# sourceMappingURL=visual-verification.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"visual-verification.d.ts","sourceRoot":"","sources":["../../../src/core/visual-verification.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAC7C,OAAO,KAAK,EACV,wBAAwB,EACxB,wBAAwB,EACxB,WAAW,EACZ,MAAM,gBAAgB,CAAC;AAIxB;;GAEG;AACH,qBAAa,cAAc;IACzB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAA2B;gBAEtC,MAAM,EAAE,wBAAwB;IAI5C;;;;;;;;;OASG;IACG,MAAM,CACV,IAAI,EAAE,IAAI,EACV,aAAa,EAAE,WAAW,EAC1B,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,wBAAwB,CAAC;IAmJpC;;;;;;OAMG;IACG,kBAAkB,CACtB,IAAI,EAAE,IAAI,EACV,WAAW,EAAE,MAAM,EACnB,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,MAAM,CAAC;IAsElB;;OAEG;IACH,OAAO,IAAI,IAAI;CAyBhB"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import type { CodeModification } from '../types/index';
|
|
2
|
+
/**
|
|
3
|
+
* AST-based source code modifier that updates Playwright locators in test files.
|
|
4
|
+
* Uses ts-morph to parse and manipulate TypeScript ASTs so that only the target
|
|
5
|
+
* locator expression is replaced while surrounding code is fully preserved.
|
|
6
|
+
*/
|
|
7
|
+
export declare class CodeModifier {
|
|
8
|
+
private readonly project;
|
|
9
|
+
constructor();
|
|
10
|
+
/**
|
|
11
|
+
* Modify a single locator in the source file described by `modification`.
|
|
12
|
+
*/
|
|
13
|
+
modifyLocator(modification: CodeModification): Promise<void>;
|
|
14
|
+
/**
|
|
15
|
+
* Generate a human-readable unified-diff-style string for a single modification.
|
|
16
|
+
*/
|
|
17
|
+
generateDiff(modification: CodeModification): string;
|
|
18
|
+
/**
|
|
19
|
+
* Apply multiple modifications, grouping them by file to minimize I/O.
|
|
20
|
+
* Modifications within the same file are applied from bottom to top
|
|
21
|
+
* (descending line number) so that earlier line numbers stay valid.
|
|
22
|
+
*/
|
|
23
|
+
applyAllModifications(modifications: CodeModification[]): Promise<void>;
|
|
24
|
+
/**
|
|
25
|
+
* Add (or retrieve) a ts-morph SourceFile for the given path.
|
|
26
|
+
*/
|
|
27
|
+
private getOrAddSourceFile;
|
|
28
|
+
/**
|
|
29
|
+
* Attempt to locate the original locator expression in the AST at the given
|
|
30
|
+
* line and replace it. Returns the new full text on success or `null` if the
|
|
31
|
+
* expression could not be found via AST traversal.
|
|
32
|
+
*
|
|
33
|
+
* Supports Playwright patterns:
|
|
34
|
+
* page.locator('selector')
|
|
35
|
+
* page.getByRole('role', { name: 'value' })
|
|
36
|
+
* page.getByText('text')
|
|
37
|
+
* page.getByTestId('id')
|
|
38
|
+
* Chained: page.locator('parent').locator('child')
|
|
39
|
+
*/
|
|
40
|
+
private tryASTReplace;
|
|
41
|
+
/**
|
|
42
|
+
* Fallback: perform a direct string replacement on the specific line of `fullText`.
|
|
43
|
+
* Only the first occurrence on the target line is replaced to avoid unintended changes.
|
|
44
|
+
*/
|
|
45
|
+
private replaceAtLine;
|
|
46
|
+
/**
|
|
47
|
+
* Collapse all whitespace to single spaces for comparison purposes.
|
|
48
|
+
*/
|
|
49
|
+
private normalizeWhitespace;
|
|
50
|
+
}
|
|
51
|
+
//# sourceMappingURL=code-modifier.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"code-modifier.d.ts","sourceRoot":"","sources":["../../../src/git/code-modifier.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,gBAAgB,EAAgB,MAAM,gBAAgB,CAAC;AAGrE;;;;GAIG;AACH,qBAAa,YAAY;IACvB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAU;;IAWlC;;OAEG;IACU,aAAa,CAAC,YAAY,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC;IA+BzE;;OAEG;IACI,YAAY,CAAC,YAAY,EAAE,gBAAgB,GAAG,MAAM;IAU3D;;;;OAIG;IACU,qBAAqB,CAAC,aAAa,EAAE,gBAAgB,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAwCpF;;OAEG;IACH,OAAO,CAAC,kBAAkB;IAU1B;;;;;;;;;;;OAWG;IACH,OAAO,CAAC,aAAa;IAkDrB;;;OAGG;IACH,OAAO,CAAC,aAAa;IA2BrB;;OAEG;IACH,OAAO,CAAC,mBAAmB;CAG5B"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import type { GitConfig } from '../types/index';
|
|
2
|
+
export declare class GitOperations {
|
|
3
|
+
private readonly git;
|
|
4
|
+
private readonly config;
|
|
5
|
+
constructor(config: GitConfig);
|
|
6
|
+
/**
|
|
7
|
+
* Generate a branch name using the configured prefix and current timestamp.
|
|
8
|
+
* Format: {prefix}-{YYYYMMDD}-{HHmmss}
|
|
9
|
+
*/
|
|
10
|
+
generateBranchName(): string;
|
|
11
|
+
/**
|
|
12
|
+
* Create a new branch and check it out.
|
|
13
|
+
*/
|
|
14
|
+
createBranch(branchName: string): Promise<void>;
|
|
15
|
+
/**
|
|
16
|
+
* Stage specified files and create a commit.
|
|
17
|
+
*/
|
|
18
|
+
commitChanges(files: string[], message: string): Promise<void>;
|
|
19
|
+
/**
|
|
20
|
+
* Push a branch to the remote origin.
|
|
21
|
+
*/
|
|
22
|
+
pushBranch(branchName: string): Promise<void>;
|
|
23
|
+
/**
|
|
24
|
+
* Get the name of the currently checked-out branch.
|
|
25
|
+
*/
|
|
26
|
+
getCurrentBranch(): Promise<string>;
|
|
27
|
+
/**
|
|
28
|
+
* Switch to an existing branch.
|
|
29
|
+
*/
|
|
30
|
+
switchBranch(branchName: string): Promise<void>;
|
|
31
|
+
/**
|
|
32
|
+
* Stash all uncommitted changes (tracked and untracked).
|
|
33
|
+
*/
|
|
34
|
+
stashChanges(): Promise<void>;
|
|
35
|
+
/**
|
|
36
|
+
* Pop the most recent stash entry.
|
|
37
|
+
*/
|
|
38
|
+
popStash(): Promise<void>;
|
|
39
|
+
}
|
|
40
|
+
//# sourceMappingURL=git-operations.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"git-operations.d.ts","sourceRoot":"","sources":["../../../src/git/git-operations.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAGhD,qBAAa,aAAa;IACxB,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAY;IAChC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAY;gBAEvB,MAAM,EAAE,SAAS;IAK7B;;;OAGG;IACI,kBAAkB,IAAI,MAAM;IAiBnC;;OAEG;IACU,YAAY,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAY5D;;OAEG;IACU,aAAa,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAuB3E;;OAEG;IACU,UAAU,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAY1D;;OAEG;IACU,gBAAgB,IAAI,OAAO,CAAC,MAAM,CAAC;IAWhD;;OAEG;IACU,YAAY,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAY5D;;OAEG;IACU,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC;IAY1C;;OAEG;IACU,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;CAWvC"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { GitConfig, PRDetails, PRResult } from '../types/index';
|
|
2
|
+
export declare class PRCreator {
|
|
3
|
+
private readonly config;
|
|
4
|
+
constructor(config: GitConfig);
|
|
5
|
+
/**
|
|
6
|
+
* Create a pull/merge request on the configured provider.
|
|
7
|
+
*/
|
|
8
|
+
createPR(details: PRDetails): Promise<PRResult>;
|
|
9
|
+
/**
|
|
10
|
+
* Resolve the repository owner/name from config or by auto-detecting from
|
|
11
|
+
* the git remote URL.
|
|
12
|
+
*/
|
|
13
|
+
private resolveRepo;
|
|
14
|
+
/**
|
|
15
|
+
* Format the PR body with a healing summary markdown table.
|
|
16
|
+
*/
|
|
17
|
+
private formatBody;
|
|
18
|
+
private createGitHubPR;
|
|
19
|
+
/**
|
|
20
|
+
* Add labels and request reviewers on a GitHub PR (non-critical).
|
|
21
|
+
*/
|
|
22
|
+
private addGitHubExtras;
|
|
23
|
+
private createGitLabMR;
|
|
24
|
+
private createBitbucketPR;
|
|
25
|
+
private request;
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=pr-creator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pr-creator.d.ts","sourceRoot":"","sources":["../../../src/git/pr-creator.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AASrE,qBAAa,SAAS;IACpB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAY;gBAEvB,MAAM,EAAE,SAAS;IAI7B;;OAEG;IACU,QAAQ,CAAC,OAAO,EAAE,SAAS,GAAG,OAAO,CAAC,QAAQ,CAAC;IAqB5D;;;OAGG;IACH,OAAO,CAAC,WAAW;IAiBnB;;OAEG;IACH,OAAO,CAAC,UAAU;YAaJ,cAAc;IAmC5B;;OAEG;YACW,eAAe;YAoCf,cAAc;YAoCd,iBAAiB;YAwCjB,OAAO;CAmBtB"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
export { mindHealConfig, createMindHealFixture, getAllHealingSessions } from './core/interceptor';
|
|
2
|
+
export { autoTest as test } from './core/interceptor';
|
|
3
|
+
export { expect } from '@playwright/test';
|
|
4
|
+
export { Healer } from './core/healer';
|
|
5
|
+
export { loadConfig, createConfig } from './config/config-loader';
|
|
6
|
+
export { DEFAULT_CONFIG } from './config/defaults';
|
|
7
|
+
export { createAIProvider } from './ai/ai-provider';
|
|
8
|
+
export type { AIProvider } from './ai/ai-provider';
|
|
9
|
+
export { AnthropicProvider } from './ai/anthropic-provider';
|
|
10
|
+
export { OpenAIProvider } from './ai/openai-provider';
|
|
11
|
+
export { AzureOpenAIProvider } from './ai/azure-openai-provider';
|
|
12
|
+
export { GeminiProvider } from './ai/gemini-provider';
|
|
13
|
+
export { OllamaProvider } from './ai/ollama-provider';
|
|
14
|
+
export { BedrockProvider } from './ai/bedrock-provider';
|
|
15
|
+
export { DeepSeekProvider } from './ai/deepseek-provider';
|
|
16
|
+
export { GroqProvider } from './ai/groq-provider';
|
|
17
|
+
export { QwenProvider } from './ai/qwen-provider';
|
|
18
|
+
export { MetaProvider } from './ai/meta-provider';
|
|
19
|
+
export { PerplexityProvider } from './ai/perplexity-provider';
|
|
20
|
+
export { GitOperations } from './git/git-operations';
|
|
21
|
+
export { PRCreator } from './git/pr-creator';
|
|
22
|
+
export { CodeModifier } from './git/code-modifier';
|
|
23
|
+
export { ReviewServer } from './server/review-server';
|
|
24
|
+
export { HealReportGenerator } from './reporters/heal-report';
|
|
25
|
+
export { SelfHealCache } from './core/self-heal-cache';
|
|
26
|
+
export { KnowledgeStore } from './rag/knowledge-store';
|
|
27
|
+
export { ContextRetriever } from './rag/context-retriever';
|
|
28
|
+
export { textSimilarity, tokenize, buildTermVector, cosineSimilarity } from './rag/embeddings';
|
|
29
|
+
export { HealingAnalytics } from './analytics/healing-analytics';
|
|
30
|
+
export { SmartRetry } from './core/smart-retry';
|
|
31
|
+
export { VisualVerifier } from './core/visual-verification';
|
|
32
|
+
export { FileLock } from './utils/file-lock';
|
|
33
|
+
export { logger, configureLogger } from './utils/logger';
|
|
34
|
+
export { isCI, detectGitProvider, getRepoInfo } from './utils/environment';
|
|
35
|
+
export { enterpriseStrategy, isDynamicId, detectPlatform, extractStableIdPart, waitForEnterpriseLoad, scrollVirtualContainer, } from './core/enterprise-strategy';
|
|
36
|
+
export { captureDOMSnapshot } from './core/dom-snapshot';
|
|
37
|
+
export { analyzeLocator, getLocatorHash } from './core/locator-analyzer';
|
|
38
|
+
export { runStrategy } from './core/locator-strategies';
|
|
39
|
+
export type { MindHealConfig, AIConfig, AIProviderName, HealingConfig, GitConfig, ReviewServerConfig, ReportingConfig, LoggingConfig, HealingStrategyName, HealingResult, StrategyAttempt, LocatorInfo, LocatorType, HealingEvent, SourceLocation, DOMSnapshot, DOMElement, AIHealingRequest, AIHealingResponse, PRDetails, PRResult, CodeModification, ReviewAction, ReviewSummary, CacheEntry, HealCache, HealReport, HealingSession, MindHealFixtures, MindHealWorkerFixtures, EnterpriseConfig, EnterprisePlatform, RAGConfig, RAGSourceName, RAGContextChunk, RAGKnowledgeEntry, RAGKnowledgeStore, AnalyticsConfig, AnalyticsEntry, AnalyticsSnapshot, StrategyStats, LocatorStats, TestStabilityRecord, SmartRetryConfig, FlakyTestEntry, FlakyTestStore, ParallelConfig, VisualVerificationConfig, VisualVerificationResult, } from './types/index';
|
|
40
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"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"}
|