@loopcheck/qa-sdk 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/ARCHITECTURE.md +59 -0
- package/README.md +131 -0
- package/dist/config/normalize.d.ts +6 -0
- package/dist/config/normalize.d.ts.map +1 -0
- package/dist/config/normalize.js +88 -0
- package/dist/config/normalize.js.map +1 -0
- package/dist/core/QAClient.d.ts +53 -0
- package/dist/core/QAClient.d.ts.map +1 -0
- package/dist/core/QAClient.js +318 -0
- package/dist/core/QAClient.js.map +1 -0
- package/dist/core/QAEventBus.d.ts +10 -0
- package/dist/core/QAEventBus.d.ts.map +1 -0
- package/dist/core/QAEventBus.js +27 -0
- package/dist/core/QAEventBus.js.map +1 -0
- package/dist/debug/Debugger.d.ts +4 -0
- package/dist/debug/Debugger.d.ts.map +1 -0
- package/dist/debug/Debugger.js +57 -0
- package/dist/debug/Debugger.js.map +1 -0
- package/dist/identity/AccessibilityResolver.d.ts +3 -0
- package/dist/identity/AccessibilityResolver.d.ts.map +1 -0
- package/dist/identity/AccessibilityResolver.js +76 -0
- package/dist/identity/AccessibilityResolver.js.map +1 -0
- package/dist/identity/DuplicateDetector.d.ts +9 -0
- package/dist/identity/DuplicateDetector.d.ts.map +1 -0
- package/dist/identity/DuplicateDetector.js +41 -0
- package/dist/identity/DuplicateDetector.js.map +1 -0
- package/dist/identity/ElementResolver.d.ts +5 -0
- package/dist/identity/ElementResolver.d.ts.map +1 -0
- package/dist/identity/ElementResolver.js +123 -0
- package/dist/identity/ElementResolver.js.map +1 -0
- package/dist/identity/FingerprintGenerator.d.ts +19 -0
- package/dist/identity/FingerprintGenerator.d.ts.map +1 -0
- package/dist/identity/FingerprintGenerator.js +49 -0
- package/dist/identity/FingerprintGenerator.js.map +1 -0
- package/dist/identity/IdentityValidator.d.ts +6 -0
- package/dist/identity/IdentityValidator.d.ts.map +1 -0
- package/dist/identity/IdentityValidator.js +28 -0
- package/dist/identity/IdentityValidator.js.map +1 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +9 -0
- package/dist/index.js.map +1 -0
- package/dist/instrumentation/DOMObserver.d.ts +13 -0
- package/dist/instrumentation/DOMObserver.d.ts.map +1 -0
- package/dist/instrumentation/DOMObserver.js +45 -0
- package/dist/instrumentation/DOMObserver.js.map +1 -0
- package/dist/instrumentation/ElementRegistry.d.ts +15 -0
- package/dist/instrumentation/ElementRegistry.d.ts.map +1 -0
- package/dist/instrumentation/ElementRegistry.js +53 -0
- package/dist/instrumentation/ElementRegistry.js.map +1 -0
- package/dist/instrumentation/EventDelegator.d.ts +31 -0
- package/dist/instrumentation/EventDelegator.d.ts.map +1 -0
- package/dist/instrumentation/EventDelegator.js +238 -0
- package/dist/instrumentation/EventDelegator.js.map +1 -0
- package/dist/instrumentation/FormHarvest.d.ts +33 -0
- package/dist/instrumentation/FormHarvest.d.ts.map +1 -0
- package/dist/instrumentation/FormHarvest.js +179 -0
- package/dist/instrumentation/FormHarvest.js.map +1 -0
- package/dist/instrumentation/NavigationObserver.d.ts +11 -0
- package/dist/instrumentation/NavigationObserver.d.ts.map +1 -0
- package/dist/instrumentation/NavigationObserver.js +52 -0
- package/dist/instrumentation/NavigationObserver.js.map +1 -0
- package/dist/instrumentation/compiler-contract.d.ts +11 -0
- package/dist/instrumentation/compiler-contract.d.ts.map +1 -0
- package/dist/instrumentation/compiler-contract.js +11 -0
- package/dist/instrumentation/compiler-contract.js.map +1 -0
- package/dist/privacy/Redactor.d.ts +4 -0
- package/dist/privacy/Redactor.d.ts.map +1 -0
- package/dist/privacy/Redactor.js +50 -0
- package/dist/privacy/Redactor.js.map +1 -0
- package/dist/react/QAButton.d.ts +595 -0
- package/dist/react/QAButton.d.ts.map +1 -0
- package/dist/react/QAButton.js +22 -0
- package/dist/react/QAButton.js.map +1 -0
- package/dist/react/QAProvider.d.ts +23 -0
- package/dist/react/QAProvider.d.ts.map +1 -0
- package/dist/react/QAProvider.js +41 -0
- package/dist/react/QAProvider.js.map +1 -0
- package/dist/react/index.d.ts +4 -0
- package/dist/react/index.d.ts.map +1 -0
- package/dist/react/index.js +5 -0
- package/dist/react/index.js.map +1 -0
- package/dist/react/useQAElement.d.ts +3 -0
- package/dist/react/useQAElement.d.ts.map +1 -0
- package/dist/react/useQAElement.js +23 -0
- package/dist/react/useQAElement.js.map +1 -0
- package/dist/recorder/EventNormalizer.d.ts +32 -0
- package/dist/recorder/EventNormalizer.d.ts.map +1 -0
- package/dist/recorder/EventNormalizer.js +113 -0
- package/dist/recorder/EventNormalizer.js.map +1 -0
- package/dist/recorder.iife.js +14 -0
- package/dist/transport/BatchQueue.d.ts +26 -0
- package/dist/transport/BatchQueue.d.ts.map +1 -0
- package/dist/transport/BatchQueue.js +110 -0
- package/dist/transport/BatchQueue.js.map +1 -0
- package/dist/transport/HTTPTransport.d.ts +36 -0
- package/dist/transport/HTTPTransport.d.ts.map +1 -0
- package/dist/transport/HTTPTransport.js +121 -0
- package/dist/transport/HTTPTransport.js.map +1 -0
- package/dist/transport/RetryQueue.d.ts +10 -0
- package/dist/transport/RetryQueue.d.ts.map +1 -0
- package/dist/transport/RetryQueue.js +60 -0
- package/dist/transport/RetryQueue.js.map +1 -0
- package/dist/types/index.d.ts +147 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +24 -0
- package/dist/types/index.js.map +1 -0
- package/dist/utils/dom.d.ts +24 -0
- package/dist/utils/dom.d.ts.map +1 -0
- package/dist/utils/dom.js +152 -0
- package/dist/utils/dom.js.map +1 -0
- package/dist/utils/env.d.ts +2 -0
- package/dist/utils/env.d.ts.map +1 -0
- package/dist/utils/env.js +6 -0
- package/dist/utils/env.js.map +1 -0
- package/dist/utils/id.d.ts +13 -0
- package/dist/utils/id.d.ts.map +1 -0
- package/dist/utils/id.js +74 -0
- package/dist/utils/id.js.map +1 -0
- package/dist/utils/safe.d.ts +5 -0
- package/dist/utils/safe.d.ts.map +1 -0
- package/dist/utils/safe.js +28 -0
- package/dist/utils/safe.js.map +1 -0
- package/package.json +79 -0
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
export class DOMObserver {
|
|
2
|
+
config;
|
|
3
|
+
registry;
|
|
4
|
+
observer;
|
|
5
|
+
timer;
|
|
6
|
+
constructor(config, registry) {
|
|
7
|
+
this.config = config;
|
|
8
|
+
this.registry = registry;
|
|
9
|
+
}
|
|
10
|
+
start(root = document) {
|
|
11
|
+
if (typeof MutationObserver === 'undefined') {
|
|
12
|
+
return;
|
|
13
|
+
}
|
|
14
|
+
this.observer = new MutationObserver(() => {
|
|
15
|
+
this.schedule(root);
|
|
16
|
+
});
|
|
17
|
+
if (root instanceof Node) {
|
|
18
|
+
this.observer.observe(root, {
|
|
19
|
+
subtree: true,
|
|
20
|
+
childList: true,
|
|
21
|
+
attributes: true,
|
|
22
|
+
attributeFilter: ['data-qa-id', 'data-qa-source', 'role', 'name', 'type'],
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
this.registry.scheduleScan(root);
|
|
26
|
+
}
|
|
27
|
+
stop() {
|
|
28
|
+
this.observer?.disconnect();
|
|
29
|
+
this.observer = undefined;
|
|
30
|
+
if (this.timer) {
|
|
31
|
+
clearTimeout(this.timer);
|
|
32
|
+
this.timer = undefined;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
schedule(root) {
|
|
36
|
+
if (this.timer) {
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
this.timer = setTimeout(() => {
|
|
40
|
+
this.timer = undefined;
|
|
41
|
+
this.registry.scheduleScan(root);
|
|
42
|
+
}, 100);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
//# sourceMappingURL=DOMObserver.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DOMObserver.js","sourceRoot":"","sources":["../../src/instrumentation/DOMObserver.ts"],"names":[],"mappings":"AAGA,MAAM,OAAO,WAAW;IAKH;IACA;IALX,QAAQ,CAA+B;IACvC,KAAK,CAA4C;IAEzD,YACmB,MAAwB,EACxB,QAAyB;QADzB,WAAM,GAAN,MAAM,CAAkB;QACxB,aAAQ,GAAR,QAAQ,CAAiB;IACzC,CAAC;IAEJ,KAAK,CAAC,OAAmB,QAAQ;QAC/B,IAAI,OAAO,gBAAgB,KAAK,WAAW,EAAE,CAAC;YAC5C,OAAO;QACT,CAAC;QACD,IAAI,CAAC,QAAQ,GAAG,IAAI,gBAAgB,CAAC,GAAG,EAAE;YACxC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;QACtB,CAAC,CAAC,CAAC;QACH,IAAI,IAAI,YAAY,IAAI,EAAE,CAAC;YACzB,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,EAAE;gBAC1B,OAAO,EAAE,IAAI;gBACb,SAAS,EAAE,IAAI;gBACf,UAAU,EAAE,IAAI;gBAChB,eAAe,EAAE,CAAC,YAAY,EAAE,gBAAgB,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC;aAC1E,CAAC,CAAC;QACL,CAAC;QACD,IAAI,CAAC,QAAQ,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC;IACnC,CAAC;IAED,IAAI;QACF,IAAI,CAAC,QAAQ,EAAE,UAAU,EAAE,CAAC;QAC5B,IAAI,CAAC,QAAQ,GAAG,SAAS,CAAC;QAC1B,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;YACf,YAAY,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YACzB,IAAI,CAAC,KAAK,GAAG,SAAS,CAAC;QACzB,CAAC;IACH,CAAC;IAEO,QAAQ,CAAC,IAAgB;QAC/B,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;YACf,OAAO;QACT,CAAC;QACD,IAAI,CAAC,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE;YAC3B,IAAI,CAAC,KAAK,GAAG,SAAS,CAAC;YACvB,IAAI,CAAC,QAAQ,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC;QACnC,CAAC,EAAE,GAAG,CAAC,CAAC;IACV,CAAC;CACF"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { QAElementResolution, ResolvedQAConfig } from '../types';
|
|
2
|
+
import { type DuplicateHit } from '../identity/DuplicateDetector';
|
|
3
|
+
export declare class ElementRegistry {
|
|
4
|
+
private readonly config;
|
|
5
|
+
private readonly onDuplicates;
|
|
6
|
+
private readonly onResolved?;
|
|
7
|
+
private readonly duplicates;
|
|
8
|
+
private lastScan;
|
|
9
|
+
private scheduled;
|
|
10
|
+
constructor(config: ResolvedQAConfig, onDuplicates: (hits: DuplicateHit[]) => void, onResolved?: ((resolution: QAElementResolution) => void) | undefined);
|
|
11
|
+
resolve(element: Element): QAElementResolution;
|
|
12
|
+
scheduleScan(root?: ParentNode): void;
|
|
13
|
+
scan(root?: ParentNode): DuplicateHit[];
|
|
14
|
+
}
|
|
15
|
+
//# sourceMappingURL=ElementRegistry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ElementRegistry.d.ts","sourceRoot":"","sources":["../../src/instrumentation/ElementRegistry.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAGtE,OAAO,EAAqB,KAAK,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAErF,qBAAa,eAAe;IAMxB,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,YAAY;IAC7B,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAC;IAP9B,OAAO,CAAC,QAAQ,CAAC,UAAU,CAA2B;IACtD,OAAO,CAAC,QAAQ,CAAK;IACrB,OAAO,CAAC,SAAS,CAAS;gBAGP,MAAM,EAAE,gBAAgB,EACxB,YAAY,EAAE,CAAC,IAAI,EAAE,YAAY,EAAE,KAAK,IAAI,EAC5C,UAAU,CAAC,GAAE,CAAC,UAAU,EAAE,mBAAmB,KAAK,IAAI,aAAA;IAGzE,OAAO,CAAC,OAAO,EAAE,OAAO,GAAG,mBAAmB;IAU9C,YAAY,CAAC,IAAI,GAAE,UAAqB,GAAG,IAAI;IAgB/C,IAAI,CAAC,IAAI,GAAE,UAAqB,GAAG,YAAY,EAAE;CAYlD"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { closestInteractive } from '../utils/dom';
|
|
2
|
+
import { resolveElement } from '../identity/ElementResolver';
|
|
3
|
+
import { DuplicateDetector } from '../identity/DuplicateDetector';
|
|
4
|
+
export class ElementRegistry {
|
|
5
|
+
config;
|
|
6
|
+
onDuplicates;
|
|
7
|
+
onResolved;
|
|
8
|
+
duplicates = new DuplicateDetector();
|
|
9
|
+
lastScan = 0;
|
|
10
|
+
scheduled = false;
|
|
11
|
+
constructor(config, onDuplicates, onResolved) {
|
|
12
|
+
this.config = config;
|
|
13
|
+
this.onDuplicates = onDuplicates;
|
|
14
|
+
this.onResolved = onResolved;
|
|
15
|
+
}
|
|
16
|
+
resolve(element) {
|
|
17
|
+
const target = closestInteractive(element, this.config.interactiveSelectors) ?? element;
|
|
18
|
+
const resolution = resolveElement(target, {
|
|
19
|
+
allowUnstableIds: this.config.allowUnstableIds,
|
|
20
|
+
});
|
|
21
|
+
this.onResolved?.(resolution);
|
|
22
|
+
return resolution;
|
|
23
|
+
}
|
|
24
|
+
scheduleScan(root = document) {
|
|
25
|
+
if (this.scheduled) {
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
this.scheduled = true;
|
|
29
|
+
const run = () => {
|
|
30
|
+
this.scheduled = false;
|
|
31
|
+
this.scan(root);
|
|
32
|
+
};
|
|
33
|
+
if (typeof requestAnimationFrame === 'function') {
|
|
34
|
+
requestAnimationFrame(run);
|
|
35
|
+
}
|
|
36
|
+
else {
|
|
37
|
+
setTimeout(run, 32);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
scan(root = document) {
|
|
41
|
+
const now = Date.now();
|
|
42
|
+
if (now - this.lastScan < 80) {
|
|
43
|
+
return [];
|
|
44
|
+
}
|
|
45
|
+
this.lastScan = now;
|
|
46
|
+
const hits = this.duplicates.scan(root);
|
|
47
|
+
if (hits.length > 0) {
|
|
48
|
+
this.onDuplicates(hits);
|
|
49
|
+
}
|
|
50
|
+
return hits;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
//# sourceMappingURL=ElementRegistry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ElementRegistry.js","sourceRoot":"","sources":["../../src/instrumentation/ElementRegistry.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAClD,OAAO,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAC7D,OAAO,EAAE,iBAAiB,EAAqB,MAAM,+BAA+B,CAAC;AAErF,MAAM,OAAO,eAAe;IAMP;IACA;IACA;IAPF,UAAU,GAAG,IAAI,iBAAiB,EAAE,CAAC;IAC9C,QAAQ,GAAG,CAAC,CAAC;IACb,SAAS,GAAG,KAAK,CAAC;IAE1B,YACmB,MAAwB,EACxB,YAA4C,EAC5C,UAAsD;QAFtD,WAAM,GAAN,MAAM,CAAkB;QACxB,iBAAY,GAAZ,YAAY,CAAgC;QAC5C,eAAU,GAAV,UAAU,CAA4C;IACtE,CAAC;IAEJ,OAAO,CAAC,OAAgB;QACtB,MAAM,MAAM,GACV,kBAAkB,CAAC,OAAO,EAAE,IAAI,CAAC,MAAM,CAAC,oBAAoB,CAAC,IAAI,OAAO,CAAC;QAC3E,MAAM,UAAU,GAAG,cAAc,CAAC,MAAM,EAAE;YACxC,gBAAgB,EAAE,IAAI,CAAC,MAAM,CAAC,gBAAgB;SAC/C,CAAC,CAAC;QACH,IAAI,CAAC,UAAU,EAAE,CAAC,UAAU,CAAC,CAAC;QAC9B,OAAO,UAAU,CAAC;IACpB,CAAC;IAED,YAAY,CAAC,OAAmB,QAAQ;QACtC,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;YACnB,OAAO;QACT,CAAC;QACD,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC;QACtB,MAAM,GAAG,GAAG,GAAS,EAAE;YACrB,IAAI,CAAC,SAAS,GAAG,KAAK,CAAC;YACvB,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAClB,CAAC,CAAC;QACF,IAAI,OAAO,qBAAqB,KAAK,UAAU,EAAE,CAAC;YAChD,qBAAqB,CAAC,GAAG,CAAC,CAAC;QAC7B,CAAC;aAAM,CAAC;YACN,UAAU,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;QACtB,CAAC;IACH,CAAC;IAED,IAAI,CAAC,OAAmB,QAAQ;QAC9B,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QACvB,IAAI,GAAG,GAAG,IAAI,CAAC,QAAQ,GAAG,EAAE,EAAE,CAAC;YAC7B,OAAO,EAAE,CAAC;QACZ,CAAC;QACD,IAAI,CAAC,QAAQ,GAAG,GAAG,CAAC;QACpB,MAAM,IAAI,GAAG,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACxC,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACpB,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC;QAC1B,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;CACF"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type { ResolvedQAConfig } from '../types';
|
|
2
|
+
import { ElementRegistry } from './ElementRegistry';
|
|
3
|
+
import { EventNormalizer } from '../recorder/EventNormalizer';
|
|
4
|
+
import { type FillSource } from './FormHarvest';
|
|
5
|
+
export declare class EventDelegator {
|
|
6
|
+
private readonly config;
|
|
7
|
+
private readonly registry;
|
|
8
|
+
private readonly normalizer;
|
|
9
|
+
private readonly shouldRecord;
|
|
10
|
+
private attached;
|
|
11
|
+
private readonly onEvent;
|
|
12
|
+
private readonly recordedFields;
|
|
13
|
+
private lastClickedFingerprint;
|
|
14
|
+
private harvest;
|
|
15
|
+
constructor(config: ResolvedQAConfig, registry: ElementRegistry, normalizer: EventNormalizer, shouldRecord: () => boolean);
|
|
16
|
+
start(): void;
|
|
17
|
+
stop(): void;
|
|
18
|
+
harvestPrefills(source?: FillSource, root?: ParentNode): void;
|
|
19
|
+
private frameMeta;
|
|
20
|
+
private withFrame;
|
|
21
|
+
private emitHarvested;
|
|
22
|
+
private handle;
|
|
23
|
+
private emitFileChange;
|
|
24
|
+
private handleSubmit;
|
|
25
|
+
private emitControlChange;
|
|
26
|
+
private handleKey;
|
|
27
|
+
private readonly onScroll;
|
|
28
|
+
private scrollTimer;
|
|
29
|
+
private throttledScroll;
|
|
30
|
+
}
|
|
31
|
+
//# sourceMappingURL=EventDelegator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"EventDelegator.d.ts","sourceRoot":"","sources":["../../src/instrumentation/EventDelegator.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAkC,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAOjF,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAC;AAC9D,OAAO,EAKL,KAAK,UAAU,EAEhB,MAAM,eAAe,CAAC;AAkBvB,qBAAa,cAAc;IAQvB,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,QAAQ;IACzB,OAAO,CAAC,QAAQ,CAAC,UAAU;IAC3B,OAAO,CAAC,QAAQ,CAAC,YAAY;IAV/B,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAyB;IACjD,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAqB;IACpD,OAAO,CAAC,sBAAsB,CAAqB;IACnD,OAAO,CAAC,OAAO,CAA4B;gBAGxB,MAAM,EAAE,gBAAgB,EACxB,QAAQ,EAAE,eAAe,EACzB,UAAU,EAAE,eAAe,EAC3B,YAAY,EAAE,MAAM,OAAO;IAK9C,KAAK,IAAI,IAAI;IAeb,IAAI,IAAI,IAAI;IAaZ,eAAe,CAAC,MAAM,GAAE,UAAwB,EAAE,IAAI,CAAC,EAAE,UAAU,GAAG,IAAI;IAO1E,OAAO,CAAC,SAAS;IAYjB,OAAO,CAAC,SAAS;IAUjB,OAAO,CAAC,aAAa;IAcrB,OAAO,CAAC,MAAM;IA6Ed,OAAO,CAAC,cAAc;IAiBtB,OAAO,CAAC,YAAY;IAmBpB,OAAO,CAAC,iBAAiB;IAYzB,OAAO,CAAC,SAAS;IAYjB,OAAO,CAAC,QAAQ,CAAC,QAAQ,CASvB;IAEF,OAAO,CAAC,WAAW,CAA4C;IAC/D,OAAO,CAAC,eAAe,CAQrB;CACH"}
|
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
import { closestInteractive, eventTargetElement, frameContext, isRecorderUi, } from '../utils/dom';
|
|
2
|
+
import { FormHarvest, controlState, isCheckableControl, shouldHarvestBeforeClick, } from './FormHarvest';
|
|
3
|
+
const DELEGATED_EVENTS = [
|
|
4
|
+
'click',
|
|
5
|
+
'dblclick',
|
|
6
|
+
'input',
|
|
7
|
+
'change',
|
|
8
|
+
'focus',
|
|
9
|
+
'blur',
|
|
10
|
+
'submit',
|
|
11
|
+
'keydown',
|
|
12
|
+
'dragstart',
|
|
13
|
+
'drop',
|
|
14
|
+
'mouseover',
|
|
15
|
+
];
|
|
16
|
+
const RECORDED_KEYS = new Set(['Enter', 'Escape']);
|
|
17
|
+
export class EventDelegator {
|
|
18
|
+
config;
|
|
19
|
+
registry;
|
|
20
|
+
normalizer;
|
|
21
|
+
shouldRecord;
|
|
22
|
+
attached = false;
|
|
23
|
+
onEvent;
|
|
24
|
+
recordedFields = new Set();
|
|
25
|
+
lastClickedFingerprint;
|
|
26
|
+
harvest = null;
|
|
27
|
+
constructor(config, registry, normalizer, shouldRecord) {
|
|
28
|
+
this.config = config;
|
|
29
|
+
this.registry = registry;
|
|
30
|
+
this.normalizer = normalizer;
|
|
31
|
+
this.shouldRecord = shouldRecord;
|
|
32
|
+
this.onEvent = (event) => this.handle(event);
|
|
33
|
+
}
|
|
34
|
+
start() {
|
|
35
|
+
if (this.attached || typeof document === 'undefined') {
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
this.harvest = new FormHarvest(this.config, this.registry, (field, source) => {
|
|
39
|
+
this.emitHarvested(field, source);
|
|
40
|
+
});
|
|
41
|
+
this.harvest.start();
|
|
42
|
+
for (const type of DELEGATED_EVENTS) {
|
|
43
|
+
document.addEventListener(type, this.onEvent, true);
|
|
44
|
+
}
|
|
45
|
+
window.addEventListener('scroll', this.onScroll, true);
|
|
46
|
+
this.attached = true;
|
|
47
|
+
}
|
|
48
|
+
stop() {
|
|
49
|
+
if (!this.attached || typeof document === 'undefined') {
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
for (const type of DELEGATED_EVENTS) {
|
|
53
|
+
document.removeEventListener(type, this.onEvent, true);
|
|
54
|
+
}
|
|
55
|
+
window.removeEventListener('scroll', this.onScroll, true);
|
|
56
|
+
this.harvest?.stop();
|
|
57
|
+
this.harvest = null;
|
|
58
|
+
this.attached = false;
|
|
59
|
+
}
|
|
60
|
+
harvestPrefills(source = 'prefilled', root) {
|
|
61
|
+
if (!this.shouldRecord() || typeof document === 'undefined') {
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
this.harvest?.collect(root ?? document, this.recordedFields, source);
|
|
65
|
+
}
|
|
66
|
+
frameMeta() {
|
|
67
|
+
const ctx = frameContext();
|
|
68
|
+
if (!ctx) {
|
|
69
|
+
return undefined;
|
|
70
|
+
}
|
|
71
|
+
return {
|
|
72
|
+
inIframe: true,
|
|
73
|
+
...(ctx.frame ? { frame: ctx.frame } : {}),
|
|
74
|
+
...(ctx.crossOriginFrame ? { crossOriginFrame: true } : {}),
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
withFrame(extra) {
|
|
78
|
+
const frame = this.frameMeta();
|
|
79
|
+
if (!frame && !extra) {
|
|
80
|
+
return undefined;
|
|
81
|
+
}
|
|
82
|
+
return { ...frame, ...extra };
|
|
83
|
+
}
|
|
84
|
+
emitHarvested(field, source) {
|
|
85
|
+
if (!this.shouldRecord()) {
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
if (this.recordedFields.has(field.identity.fingerprint)) {
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
this.recordedFields.add(field.identity.fingerprint);
|
|
92
|
+
this.normalizer.change(field.identity, field.value, field.eventType, this.withFrame({
|
|
93
|
+
source,
|
|
94
|
+
...(field.checked !== undefined ? { checked: field.checked } : {}),
|
|
95
|
+
}));
|
|
96
|
+
}
|
|
97
|
+
handle(event) {
|
|
98
|
+
if (!this.shouldRecord()) {
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
const element = eventTargetElement(event);
|
|
102
|
+
if (!element || isRecorderUi(element)) {
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
const interactive = closestInteractive(element, this.config.interactiveSelectors);
|
|
106
|
+
if (!interactive && event.type !== 'submit' && event.type !== 'keydown') {
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
const targetEl = interactive ?? element;
|
|
110
|
+
const identity = this.registry.resolve(targetEl).identity;
|
|
111
|
+
switch (event.type) {
|
|
112
|
+
case 'click':
|
|
113
|
+
if (shouldHarvestBeforeClick(targetEl)) {
|
|
114
|
+
this.harvestPrefills('prefilled', targetEl.closest('form') ?? document);
|
|
115
|
+
}
|
|
116
|
+
this.lastClickedFingerprint = identity.fingerprint;
|
|
117
|
+
this.normalizer.click(identity, 'click', this.frameMeta());
|
|
118
|
+
break;
|
|
119
|
+
case 'dblclick':
|
|
120
|
+
this.normalizer.click(identity, 'dblclick', this.frameMeta());
|
|
121
|
+
break;
|
|
122
|
+
case 'input':
|
|
123
|
+
if (isCheckableControl(targetEl)) {
|
|
124
|
+
break;
|
|
125
|
+
}
|
|
126
|
+
if (targetEl instanceof HTMLInputElement && targetEl.type === 'file') {
|
|
127
|
+
break;
|
|
128
|
+
}
|
|
129
|
+
this.recordedFields.add(identity.fingerprint);
|
|
130
|
+
this.normalizer.input(identity, controlState(targetEl, this.config).value, this.withFrame({ source: 'typed' }));
|
|
131
|
+
break;
|
|
132
|
+
case 'change':
|
|
133
|
+
this.recordedFields.add(identity.fingerprint);
|
|
134
|
+
if (targetEl instanceof HTMLInputElement && targetEl.type === 'file') {
|
|
135
|
+
this.emitFileChange(targetEl, identity);
|
|
136
|
+
break;
|
|
137
|
+
}
|
|
138
|
+
this.emitControlChange(targetEl, identity, 'typed');
|
|
139
|
+
break;
|
|
140
|
+
case 'focus':
|
|
141
|
+
this.normalizer.simple('focus', identity, this.frameMeta());
|
|
142
|
+
break;
|
|
143
|
+
case 'blur':
|
|
144
|
+
this.normalizer.flushInput();
|
|
145
|
+
this.normalizer.simple('blur', identity, this.frameMeta());
|
|
146
|
+
break;
|
|
147
|
+
case 'submit':
|
|
148
|
+
this.handleSubmit(event, targetEl, identity);
|
|
149
|
+
break;
|
|
150
|
+
case 'keydown':
|
|
151
|
+
this.handleKey(event, identity);
|
|
152
|
+
break;
|
|
153
|
+
case 'dragstart':
|
|
154
|
+
this.normalizer.simple('drag', identity, this.frameMeta());
|
|
155
|
+
break;
|
|
156
|
+
case 'drop':
|
|
157
|
+
this.normalizer.simple('drop', identity, this.frameMeta());
|
|
158
|
+
break;
|
|
159
|
+
case 'mouseover':
|
|
160
|
+
if (this.config.recordHover) {
|
|
161
|
+
this.normalizer.simple('hover', identity, this.frameMeta());
|
|
162
|
+
}
|
|
163
|
+
break;
|
|
164
|
+
default:
|
|
165
|
+
break;
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
emitFileChange(element, identity) {
|
|
169
|
+
const files = Array.from(element.files ?? []).map((file) => file.name);
|
|
170
|
+
this.normalizer.change(identity, undefined, 'change', this.withFrame({
|
|
171
|
+
source: 'typed',
|
|
172
|
+
files: files.length > 0 ? files : ['upload.bin'],
|
|
173
|
+
fileName: files[0] ?? 'upload.bin',
|
|
174
|
+
}));
|
|
175
|
+
}
|
|
176
|
+
handleSubmit(event, targetEl, identity) {
|
|
177
|
+
const form = targetEl.closest('form') ?? targetEl;
|
|
178
|
+
this.harvestPrefills('prefilled', form);
|
|
179
|
+
const submitter = submitterOf(event, form);
|
|
180
|
+
if (submitter) {
|
|
181
|
+
const submitterIdentity = this.registry.resolve(submitter).identity;
|
|
182
|
+
if (submitterIdentity.fingerprint !== this.lastClickedFingerprint) {
|
|
183
|
+
this.lastClickedFingerprint = submitterIdentity.fingerprint;
|
|
184
|
+
this.normalizer.click(submitterIdentity, 'click', this.frameMeta());
|
|
185
|
+
}
|
|
186
|
+
return;
|
|
187
|
+
}
|
|
188
|
+
this.normalizer.simple('submit', identity, this.frameMeta());
|
|
189
|
+
}
|
|
190
|
+
emitControlChange(element, identity, source) {
|
|
191
|
+
const state = controlState(element, this.config);
|
|
192
|
+
this.normalizer.change(identity, state.value, changeType(element), this.withFrame({
|
|
193
|
+
source,
|
|
194
|
+
...(state.checked !== undefined ? { checked: state.checked } : {}),
|
|
195
|
+
}));
|
|
196
|
+
}
|
|
197
|
+
handleKey(event, identity) {
|
|
198
|
+
if (!RECORDED_KEYS.has(event.key)) {
|
|
199
|
+
return;
|
|
200
|
+
}
|
|
201
|
+
this.normalizer.flushInput();
|
|
202
|
+
this.normalizer.simple('keydown', identity, this.withFrame({ key: event.key }));
|
|
203
|
+
}
|
|
204
|
+
onScroll = (event) => {
|
|
205
|
+
if (!this.shouldRecord()) {
|
|
206
|
+
return;
|
|
207
|
+
}
|
|
208
|
+
const element = eventTargetElement(event);
|
|
209
|
+
if (element && isRecorderUi(element)) {
|
|
210
|
+
return;
|
|
211
|
+
}
|
|
212
|
+
this.throttledScroll();
|
|
213
|
+
};
|
|
214
|
+
scrollTimer;
|
|
215
|
+
throttledScroll = () => {
|
|
216
|
+
if (this.scrollTimer) {
|
|
217
|
+
return;
|
|
218
|
+
}
|
|
219
|
+
this.scrollTimer = setTimeout(() => {
|
|
220
|
+
this.scrollTimer = undefined;
|
|
221
|
+
this.normalizer.simple('scroll', undefined, this.frameMeta());
|
|
222
|
+
}, 400);
|
|
223
|
+
};
|
|
224
|
+
}
|
|
225
|
+
function submitterOf(event, form) {
|
|
226
|
+
const submitter = 'submitter' in event ? event.submitter : null;
|
|
227
|
+
if (submitter instanceof Element) {
|
|
228
|
+
return submitter;
|
|
229
|
+
}
|
|
230
|
+
return form.querySelector('button[type="submit"], input[type="submit"], button:not([type]), input[type="image"]');
|
|
231
|
+
}
|
|
232
|
+
function changeType(element) {
|
|
233
|
+
if (element instanceof HTMLSelectElement) {
|
|
234
|
+
return 'select';
|
|
235
|
+
}
|
|
236
|
+
return 'change';
|
|
237
|
+
}
|
|
238
|
+
//# sourceMappingURL=EventDelegator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"EventDelegator.js","sourceRoot":"","sources":["../../src/instrumentation/EventDelegator.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type { QAElementIdentity, QAEventType, ResolvedQAConfig } from '../types';
|
|
2
|
+
import { ElementRegistry } from './ElementRegistry';
|
|
3
|
+
export type FillSource = 'typed' | 'autofill' | 'prefilled';
|
|
4
|
+
export declare const PREFILL_HARVEST_MS = 300;
|
|
5
|
+
export declare const AUTOFILL_ANIMATION = "lc-on-autofill";
|
|
6
|
+
export declare const AUTOFILL_STYLE_ID = "loopcheck-autofill-detect";
|
|
7
|
+
export type HarvestedField = {
|
|
8
|
+
element: Element;
|
|
9
|
+
identity: QAElementIdentity;
|
|
10
|
+
value: string | undefined;
|
|
11
|
+
checked?: boolean;
|
|
12
|
+
eventType: QAEventType;
|
|
13
|
+
};
|
|
14
|
+
export declare function isFormControl(element: Element): element is HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement;
|
|
15
|
+
export declare function isCheckableControl(element: Element): boolean;
|
|
16
|
+
export declare function isSubmitControl(element: Element): boolean;
|
|
17
|
+
export declare function shouldHarvestBeforeClick(element: Element): boolean;
|
|
18
|
+
export declare function controlState(element: Element, config: ResolvedQAConfig): {
|
|
19
|
+
value: string | undefined;
|
|
20
|
+
checked?: boolean;
|
|
21
|
+
};
|
|
22
|
+
export declare function collectFilledFields(root: ParentNode, registry: ElementRegistry, config: ResolvedQAConfig, skip: Set<string>): HarvestedField[];
|
|
23
|
+
export declare class FormHarvest {
|
|
24
|
+
private readonly config;
|
|
25
|
+
private readonly registry;
|
|
26
|
+
private readonly onField;
|
|
27
|
+
constructor(config: ResolvedQAConfig, registry: ElementRegistry, onField: (field: HarvestedField, source: FillSource) => void);
|
|
28
|
+
start(): void;
|
|
29
|
+
stop(): void;
|
|
30
|
+
collect(root: ParentNode, skip: Set<string>, source: FillSource): void;
|
|
31
|
+
private readonly onAnimationStart;
|
|
32
|
+
}
|
|
33
|
+
//# sourceMappingURL=FormHarvest.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FormHarvest.d.ts","sourceRoot":"","sources":["../../src/instrumentation/FormHarvest.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,iBAAiB,EACjB,WAAW,EACX,gBAAgB,EACjB,MAAM,UAAU,CAAC;AAGlB,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAEpD,MAAM,MAAM,UAAU,GAAG,OAAO,GAAG,UAAU,GAAG,WAAW,CAAC;AAE5D,eAAO,MAAM,kBAAkB,MAAM,CAAC;AACtC,eAAO,MAAM,kBAAkB,mBAAmB,CAAC;AACnD,eAAO,MAAM,iBAAiB,8BAA8B,CAAC;AAW7D,MAAM,MAAM,cAAc,GAAG;IAC3B,OAAO,EAAE,OAAO,CAAC;IACjB,QAAQ,EAAE,iBAAiB,CAAC;IAC5B,KAAK,EAAE,MAAM,GAAG,SAAS,CAAC;IAC1B,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,SAAS,EAAE,WAAW,CAAC;CACxB,CAAC;AAEF,wBAAgB,aAAa,CAC3B,OAAO,EAAE,OAAO,GACf,OAAO,IAAI,gBAAgB,GAAG,mBAAmB,GAAG,iBAAiB,CAMvE;AAED,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAM5D;AAED,wBAAgB,eAAe,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CASzD;AAED,wBAAgB,wBAAwB,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAQlE;AAED,wBAAgB,YAAY,CAC1B,OAAO,EAAE,OAAO,EAChB,MAAM,EAAE,gBAAgB,GACvB;IAAE,KAAK,EAAE,MAAM,GAAG,SAAS,CAAC;IAAC,OAAO,CAAC,EAAE,OAAO,CAAA;CAAE,CAclD;AAED,wBAAgB,mBAAmB,CACjC,IAAI,EAAE,UAAU,EAChB,QAAQ,EAAE,eAAe,EACzB,MAAM,EAAE,gBAAgB,EACxB,IAAI,EAAE,GAAG,CAAC,MAAM,CAAC,GAChB,cAAc,EAAE,CA0ClB;AA4BD,qBAAa,WAAW;IAEpB,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,QAAQ;IACzB,OAAO,CAAC,QAAQ,CAAC,OAAO;gBAFP,MAAM,EAAE,gBAAgB,EACxB,QAAQ,EAAE,eAAe,EACzB,OAAO,EAAE,CAAC,KAAK,EAAE,cAAc,EAAE,MAAM,EAAE,UAAU,KAAK,IAAI;IAG/E,KAAK,IAAI,IAAI;IAQb,IAAI,IAAI,IAAI;IAQZ,OAAO,CAAC,IAAI,EAAE,UAAU,EAAE,IAAI,EAAE,GAAG,CAAC,MAAM,CAAC,EAAE,MAAM,EAAE,UAAU,GAAG,IAAI;IAMtE,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CA0B/B;CACH"}
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
import { redactValue } from '../privacy/Redactor';
|
|
2
|
+
import { isRecorderUi } from '../utils/dom';
|
|
3
|
+
export const PREFILL_HARVEST_MS = 300;
|
|
4
|
+
export const AUTOFILL_ANIMATION = 'lc-on-autofill';
|
|
5
|
+
export const AUTOFILL_STYLE_ID = 'loopcheck-autofill-detect';
|
|
6
|
+
const SKIP_INPUT_TYPES = new Set([
|
|
7
|
+
'hidden',
|
|
8
|
+
'file',
|
|
9
|
+
'button',
|
|
10
|
+
'submit',
|
|
11
|
+
'reset',
|
|
12
|
+
'image',
|
|
13
|
+
]);
|
|
14
|
+
export function isFormControl(element) {
|
|
15
|
+
return (element instanceof HTMLInputElement ||
|
|
16
|
+
element instanceof HTMLTextAreaElement ||
|
|
17
|
+
element instanceof HTMLSelectElement);
|
|
18
|
+
}
|
|
19
|
+
export function isCheckableControl(element) {
|
|
20
|
+
if (!(element instanceof HTMLInputElement)) {
|
|
21
|
+
return false;
|
|
22
|
+
}
|
|
23
|
+
const type = element.type.toLowerCase();
|
|
24
|
+
return type === 'checkbox' || type === 'radio';
|
|
25
|
+
}
|
|
26
|
+
export function isSubmitControl(element) {
|
|
27
|
+
if (element instanceof HTMLInputElement) {
|
|
28
|
+
const type = element.type.toLowerCase();
|
|
29
|
+
return type === 'submit' || type === 'image';
|
|
30
|
+
}
|
|
31
|
+
if (element instanceof HTMLButtonElement) {
|
|
32
|
+
return element.type === 'submit';
|
|
33
|
+
}
|
|
34
|
+
return false;
|
|
35
|
+
}
|
|
36
|
+
export function shouldHarvestBeforeClick(element) {
|
|
37
|
+
if (isSubmitControl(element)) {
|
|
38
|
+
return true;
|
|
39
|
+
}
|
|
40
|
+
if (!element.closest('form')) {
|
|
41
|
+
return false;
|
|
42
|
+
}
|
|
43
|
+
return element.matches('button, [role="button"], input[type="submit"], input[type="image"]');
|
|
44
|
+
}
|
|
45
|
+
export function controlState(element, config) {
|
|
46
|
+
if (element instanceof HTMLInputElement && isCheckableControl(element)) {
|
|
47
|
+
return {
|
|
48
|
+
value: redactValue(element, element.value, config),
|
|
49
|
+
checked: element.checked,
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
const raw = element instanceof HTMLInputElement ||
|
|
53
|
+
element instanceof HTMLTextAreaElement ||
|
|
54
|
+
element instanceof HTMLSelectElement
|
|
55
|
+
? element.value
|
|
56
|
+
: undefined;
|
|
57
|
+
return { value: redactValue(element, raw, config) };
|
|
58
|
+
}
|
|
59
|
+
export function collectFilledFields(root, registry, config, skip) {
|
|
60
|
+
const out = [];
|
|
61
|
+
if (typeof document === 'undefined') {
|
|
62
|
+
return out;
|
|
63
|
+
}
|
|
64
|
+
const nodes = root.querySelectorAll('input, textarea, select');
|
|
65
|
+
for (const node of nodes) {
|
|
66
|
+
if (!isFormControl(node) || isRecorderUi(node)) {
|
|
67
|
+
continue;
|
|
68
|
+
}
|
|
69
|
+
if (node instanceof HTMLInputElement && SKIP_INPUT_TYPES.has(node.type.toLowerCase())) {
|
|
70
|
+
continue;
|
|
71
|
+
}
|
|
72
|
+
if ('disabled' in node && node.disabled) {
|
|
73
|
+
continue;
|
|
74
|
+
}
|
|
75
|
+
if (isCheckableControl(node)) {
|
|
76
|
+
if (!(node instanceof HTMLInputElement) || !node.checked) {
|
|
77
|
+
continue;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
else if (!node.value.trim()) {
|
|
81
|
+
continue;
|
|
82
|
+
}
|
|
83
|
+
const identity = registry.resolve(node).identity;
|
|
84
|
+
if (skip.has(identity.fingerprint)) {
|
|
85
|
+
continue;
|
|
86
|
+
}
|
|
87
|
+
const state = controlState(node, config);
|
|
88
|
+
out.push({
|
|
89
|
+
element: node,
|
|
90
|
+
identity,
|
|
91
|
+
value: state.value,
|
|
92
|
+
checked: state.checked,
|
|
93
|
+
eventType: node instanceof HTMLSelectElement
|
|
94
|
+
? 'select'
|
|
95
|
+
: isCheckableControl(node)
|
|
96
|
+
? 'change'
|
|
97
|
+
: 'input',
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
return out;
|
|
101
|
+
}
|
|
102
|
+
function injectAutofillStyle() {
|
|
103
|
+
if (typeof document === 'undefined' || document.getElementById(AUTOFILL_STYLE_ID)) {
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
const style = document.createElement('style');
|
|
107
|
+
style.id = AUTOFILL_STYLE_ID;
|
|
108
|
+
style.setAttribute('data-loopcheck-recorder', '1');
|
|
109
|
+
style.textContent = `@keyframes ${AUTOFILL_ANIMATION} {
|
|
110
|
+
from { opacity: 0.99; }
|
|
111
|
+
to { opacity: 1; }
|
|
112
|
+
}
|
|
113
|
+
input:-webkit-autofill,
|
|
114
|
+
textarea:-webkit-autofill,
|
|
115
|
+
select:-webkit-autofill {
|
|
116
|
+
animation-name: ${AUTOFILL_ANIMATION};
|
|
117
|
+
}`;
|
|
118
|
+
document.documentElement.appendChild(style);
|
|
119
|
+
}
|
|
120
|
+
function removeAutofillStyle() {
|
|
121
|
+
if (typeof document === 'undefined') {
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
124
|
+
document.getElementById(AUTOFILL_STYLE_ID)?.remove();
|
|
125
|
+
}
|
|
126
|
+
export class FormHarvest {
|
|
127
|
+
config;
|
|
128
|
+
registry;
|
|
129
|
+
onField;
|
|
130
|
+
constructor(config, registry, onField) {
|
|
131
|
+
this.config = config;
|
|
132
|
+
this.registry = registry;
|
|
133
|
+
this.onField = onField;
|
|
134
|
+
}
|
|
135
|
+
start() {
|
|
136
|
+
if (typeof document === 'undefined') {
|
|
137
|
+
return;
|
|
138
|
+
}
|
|
139
|
+
injectAutofillStyle();
|
|
140
|
+
document.addEventListener('animationstart', this.onAnimationStart, true);
|
|
141
|
+
}
|
|
142
|
+
stop() {
|
|
143
|
+
if (typeof document === 'undefined') {
|
|
144
|
+
return;
|
|
145
|
+
}
|
|
146
|
+
document.removeEventListener('animationstart', this.onAnimationStart, true);
|
|
147
|
+
removeAutofillStyle();
|
|
148
|
+
}
|
|
149
|
+
collect(root, skip, source) {
|
|
150
|
+
for (const field of collectFilledFields(root, this.registry, this.config, skip)) {
|
|
151
|
+
this.onField(field, source);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
onAnimationStart = (event) => {
|
|
155
|
+
if (event.animationName !== AUTOFILL_ANIMATION) {
|
|
156
|
+
return;
|
|
157
|
+
}
|
|
158
|
+
const element = event.target;
|
|
159
|
+
if (!(element instanceof Element) || !isFormControl(element) || isRecorderUi(element)) {
|
|
160
|
+
return;
|
|
161
|
+
}
|
|
162
|
+
if (isCheckableControl(element)) {
|
|
163
|
+
return;
|
|
164
|
+
}
|
|
165
|
+
if (!element.value.trim()) {
|
|
166
|
+
return;
|
|
167
|
+
}
|
|
168
|
+
const identity = this.registry.resolve(element).identity;
|
|
169
|
+
const state = controlState(element, this.config);
|
|
170
|
+
this.onField({
|
|
171
|
+
element,
|
|
172
|
+
identity,
|
|
173
|
+
value: state.value,
|
|
174
|
+
checked: state.checked,
|
|
175
|
+
eventType: element instanceof HTMLSelectElement ? 'select' : 'input',
|
|
176
|
+
}, 'autofill');
|
|
177
|
+
};
|
|
178
|
+
}
|
|
179
|
+
//# sourceMappingURL=FormHarvest.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FormHarvest.js","sourceRoot":"","sources":["../../src/instrumentation/FormHarvest.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export declare class NavigationObserver {
|
|
2
|
+
private readonly onNavigate;
|
|
3
|
+
private originalPush?;
|
|
4
|
+
private originalReplace?;
|
|
5
|
+
private lastUrl;
|
|
6
|
+
constructor(onNavigate: (url: string, pathname: string) => void);
|
|
7
|
+
start(): void;
|
|
8
|
+
stop(): void;
|
|
9
|
+
private readonly check;
|
|
10
|
+
}
|
|
11
|
+
//# sourceMappingURL=NavigationObserver.d.ts.map
|