@modelnex/sdk 0.5.39 → 0.5.40
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +98 -4
- package/dist/index.mjs +98 -4
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -3742,6 +3742,20 @@ function isValueBearingElement(element) {
|
|
|
3742
3742
|
element && (element instanceof HTMLInputElement || element instanceof HTMLTextAreaElement || element instanceof HTMLSelectElement)
|
|
3743
3743
|
);
|
|
3744
3744
|
}
|
|
3745
|
+
var DEFAULT_TEXT_INPUT_IDLE_COMMIT_MS = 700;
|
|
3746
|
+
var DEFAULT_SELECTION_INPUT_IDLE_COMMIT_MS = 250;
|
|
3747
|
+
function getManualInputCommitPolicy(target) {
|
|
3748
|
+
const tagName = String(target.tagName || "").toLowerCase();
|
|
3749
|
+
const role = String(target.role || "").toLowerCase();
|
|
3750
|
+
const inputType = String(target.type || "").toLowerCase();
|
|
3751
|
+
const isContentEditable = Boolean(target.isContentEditable);
|
|
3752
|
+
const isSelectionLike = tagName === "select" || role === "combobox" || ["checkbox", "radio", "range", "color", "date", "datetime-local", "month", "time", "week"].includes(inputType);
|
|
3753
|
+
return {
|
|
3754
|
+
idleCommitMs: isSelectionLike ? DEFAULT_SELECTION_INPUT_IDLE_COMMIT_MS : DEFAULT_TEXT_INPUT_IDLE_COMMIT_MS,
|
|
3755
|
+
commitOnBlur: !isSelectionLike || tagName === "select" || role === "combobox" || isContentEditable,
|
|
3756
|
+
commitOnChange: true
|
|
3757
|
+
};
|
|
3758
|
+
}
|
|
3745
3759
|
function resolveWaitTargetElement(element) {
|
|
3746
3760
|
if (isValueBearingElement(element) || element.isContentEditable) {
|
|
3747
3761
|
return element;
|
|
@@ -3761,9 +3775,40 @@ function readWaitTargetValue(element) {
|
|
|
3761
3775
|
if (isValueBearingElement(element)) {
|
|
3762
3776
|
return element.value.trim();
|
|
3763
3777
|
}
|
|
3778
|
+
const genericValue = element.value;
|
|
3779
|
+
if (typeof genericValue === "string") {
|
|
3780
|
+
return genericValue.trim();
|
|
3781
|
+
}
|
|
3782
|
+
if (typeof genericValue === "number" && Number.isFinite(genericValue)) {
|
|
3783
|
+
return String(genericValue).trim();
|
|
3784
|
+
}
|
|
3764
3785
|
if (element.isContentEditable) {
|
|
3765
3786
|
return (element.textContent || "").trim();
|
|
3766
3787
|
}
|
|
3788
|
+
const ariaValueText = element.getAttribute("aria-valuetext");
|
|
3789
|
+
if (typeof ariaValueText === "string" && ariaValueText.trim()) {
|
|
3790
|
+
return ariaValueText.trim();
|
|
3791
|
+
}
|
|
3792
|
+
const ariaValueNow = element.getAttribute("aria-valuenow");
|
|
3793
|
+
if (typeof ariaValueNow === "string" && ariaValueNow.trim()) {
|
|
3794
|
+
return ariaValueNow.trim();
|
|
3795
|
+
}
|
|
3796
|
+
if (element.getAttribute("role") === "textbox" || element.getAttribute("role") === "combobox") {
|
|
3797
|
+
const nestedControl = element.querySelector(
|
|
3798
|
+
'input:not([type="hidden"]):not([disabled]), textarea:not([disabled]), select:not([disabled]), [contenteditable="true"], [role="textbox"], [role="combobox"]'
|
|
3799
|
+
);
|
|
3800
|
+
if (nestedControl && nestedControl !== element) {
|
|
3801
|
+
const nestedValue = readWaitTargetValue(nestedControl);
|
|
3802
|
+
if (nestedValue) {
|
|
3803
|
+
return nestedValue;
|
|
3804
|
+
}
|
|
3805
|
+
}
|
|
3806
|
+
return (element.textContent || "").trim();
|
|
3807
|
+
}
|
|
3808
|
+
const shadowInput = findInputInShadowRoot(element);
|
|
3809
|
+
if (shadowInput) {
|
|
3810
|
+
return shadowInput.value.trim();
|
|
3811
|
+
}
|
|
3767
3812
|
return "";
|
|
3768
3813
|
}
|
|
3769
3814
|
function buildManualCompletionTranscript(step, eventName) {
|
|
@@ -3785,6 +3830,12 @@ function createManualWaitForTarget(rawTarget, eventName, step) {
|
|
|
3785
3830
|
const target = resolveWaitTargetElement(rawTarget);
|
|
3786
3831
|
const completionTranscript = buildManualCompletionTranscript(step, eventName);
|
|
3787
3832
|
const isInputLikeEvent = isInputLikeWait(eventName, step);
|
|
3833
|
+
const commitPolicy = getManualInputCommitPolicy({
|
|
3834
|
+
tagName: target.tagName,
|
|
3835
|
+
role: target.getAttribute("role"),
|
|
3836
|
+
type: target.type ?? null,
|
|
3837
|
+
isContentEditable: target.isContentEditable
|
|
3838
|
+
});
|
|
3788
3839
|
if (isInputLikeEvent && readWaitTargetValue(target)) {
|
|
3789
3840
|
const initialValue = readWaitTargetValue(target);
|
|
3790
3841
|
return {
|
|
@@ -3796,6 +3847,8 @@ function createManualWaitForTarget(rawTarget, eventName, step) {
|
|
|
3796
3847
|
let cleanup = () => void 0;
|
|
3797
3848
|
const promise = new Promise((resolve) => {
|
|
3798
3849
|
const listeners2 = [];
|
|
3850
|
+
let observer = null;
|
|
3851
|
+
let idleTimer = null;
|
|
3799
3852
|
let settled = false;
|
|
3800
3853
|
const finish = () => {
|
|
3801
3854
|
if (settled) return;
|
|
@@ -3808,20 +3861,61 @@ function createManualWaitForTarget(rawTarget, eventName, step) {
|
|
|
3808
3861
|
listeners2.push({ node, type, handler });
|
|
3809
3862
|
};
|
|
3810
3863
|
if (isInputLikeEvent) {
|
|
3811
|
-
const
|
|
3864
|
+
const clearIdleCommit = () => {
|
|
3865
|
+
if (idleTimer) {
|
|
3866
|
+
clearTimeout(idleTimer);
|
|
3867
|
+
idleTimer = null;
|
|
3868
|
+
}
|
|
3869
|
+
};
|
|
3870
|
+
const scheduleIdleCommit = () => {
|
|
3871
|
+
const currentValue = readWaitTargetValue(target);
|
|
3872
|
+
if (!currentValue) {
|
|
3873
|
+
clearIdleCommit();
|
|
3874
|
+
return;
|
|
3875
|
+
}
|
|
3876
|
+
clearIdleCommit();
|
|
3877
|
+
idleTimer = setTimeout(() => {
|
|
3878
|
+
idleTimer = null;
|
|
3879
|
+
finish();
|
|
3880
|
+
}, commitPolicy.idleCommitMs);
|
|
3881
|
+
};
|
|
3882
|
+
const handleImmediateCommitEvent = () => {
|
|
3812
3883
|
const currentValue = readWaitTargetValue(target);
|
|
3813
3884
|
if (currentValue) {
|
|
3885
|
+
clearIdleCommit();
|
|
3814
3886
|
finish();
|
|
3815
3887
|
}
|
|
3816
3888
|
};
|
|
3817
|
-
addListener(target, "input",
|
|
3818
|
-
|
|
3819
|
-
|
|
3889
|
+
addListener(target, "input", scheduleIdleCommit);
|
|
3890
|
+
if (commitPolicy.commitOnChange) {
|
|
3891
|
+
addListener(target, "change", handleImmediateCommitEvent);
|
|
3892
|
+
}
|
|
3893
|
+
if (commitPolicy.commitOnBlur) {
|
|
3894
|
+
addListener(target, "blur", handleImmediateCommitEvent);
|
|
3895
|
+
}
|
|
3896
|
+
if (typeof MutationObserver !== "undefined") {
|
|
3897
|
+
observer = new MutationObserver(() => {
|
|
3898
|
+
scheduleIdleCommit();
|
|
3899
|
+
});
|
|
3900
|
+
observer.observe(target, {
|
|
3901
|
+
subtree: true,
|
|
3902
|
+
childList: true,
|
|
3903
|
+
characterData: true,
|
|
3904
|
+
attributes: true,
|
|
3905
|
+
attributeFilter: ["value", "aria-valuetext", "aria-valuenow", "aria-activedescendant"]
|
|
3906
|
+
});
|
|
3907
|
+
}
|
|
3820
3908
|
} else {
|
|
3821
3909
|
const handleActionEvent = () => finish();
|
|
3822
3910
|
addListener(target, eventName, handleActionEvent);
|
|
3823
3911
|
}
|
|
3824
3912
|
cleanup = () => {
|
|
3913
|
+
if (idleTimer) {
|
|
3914
|
+
clearTimeout(idleTimer);
|
|
3915
|
+
idleTimer = null;
|
|
3916
|
+
}
|
|
3917
|
+
observer?.disconnect();
|
|
3918
|
+
observer = null;
|
|
3825
3919
|
listeners2.forEach(({ node, type, handler }) => node.removeEventListener(type, handler));
|
|
3826
3920
|
listeners2.length = 0;
|
|
3827
3921
|
};
|
package/dist/index.mjs
CHANGED
|
@@ -3531,6 +3531,20 @@ function isValueBearingElement(element) {
|
|
|
3531
3531
|
element && (element instanceof HTMLInputElement || element instanceof HTMLTextAreaElement || element instanceof HTMLSelectElement)
|
|
3532
3532
|
);
|
|
3533
3533
|
}
|
|
3534
|
+
var DEFAULT_TEXT_INPUT_IDLE_COMMIT_MS = 700;
|
|
3535
|
+
var DEFAULT_SELECTION_INPUT_IDLE_COMMIT_MS = 250;
|
|
3536
|
+
function getManualInputCommitPolicy(target) {
|
|
3537
|
+
const tagName = String(target.tagName || "").toLowerCase();
|
|
3538
|
+
const role = String(target.role || "").toLowerCase();
|
|
3539
|
+
const inputType = String(target.type || "").toLowerCase();
|
|
3540
|
+
const isContentEditable = Boolean(target.isContentEditable);
|
|
3541
|
+
const isSelectionLike = tagName === "select" || role === "combobox" || ["checkbox", "radio", "range", "color", "date", "datetime-local", "month", "time", "week"].includes(inputType);
|
|
3542
|
+
return {
|
|
3543
|
+
idleCommitMs: isSelectionLike ? DEFAULT_SELECTION_INPUT_IDLE_COMMIT_MS : DEFAULT_TEXT_INPUT_IDLE_COMMIT_MS,
|
|
3544
|
+
commitOnBlur: !isSelectionLike || tagName === "select" || role === "combobox" || isContentEditable,
|
|
3545
|
+
commitOnChange: true
|
|
3546
|
+
};
|
|
3547
|
+
}
|
|
3534
3548
|
function resolveWaitTargetElement(element) {
|
|
3535
3549
|
if (isValueBearingElement(element) || element.isContentEditable) {
|
|
3536
3550
|
return element;
|
|
@@ -3550,9 +3564,40 @@ function readWaitTargetValue(element) {
|
|
|
3550
3564
|
if (isValueBearingElement(element)) {
|
|
3551
3565
|
return element.value.trim();
|
|
3552
3566
|
}
|
|
3567
|
+
const genericValue = element.value;
|
|
3568
|
+
if (typeof genericValue === "string") {
|
|
3569
|
+
return genericValue.trim();
|
|
3570
|
+
}
|
|
3571
|
+
if (typeof genericValue === "number" && Number.isFinite(genericValue)) {
|
|
3572
|
+
return String(genericValue).trim();
|
|
3573
|
+
}
|
|
3553
3574
|
if (element.isContentEditable) {
|
|
3554
3575
|
return (element.textContent || "").trim();
|
|
3555
3576
|
}
|
|
3577
|
+
const ariaValueText = element.getAttribute("aria-valuetext");
|
|
3578
|
+
if (typeof ariaValueText === "string" && ariaValueText.trim()) {
|
|
3579
|
+
return ariaValueText.trim();
|
|
3580
|
+
}
|
|
3581
|
+
const ariaValueNow = element.getAttribute("aria-valuenow");
|
|
3582
|
+
if (typeof ariaValueNow === "string" && ariaValueNow.trim()) {
|
|
3583
|
+
return ariaValueNow.trim();
|
|
3584
|
+
}
|
|
3585
|
+
if (element.getAttribute("role") === "textbox" || element.getAttribute("role") === "combobox") {
|
|
3586
|
+
const nestedControl = element.querySelector(
|
|
3587
|
+
'input:not([type="hidden"]):not([disabled]), textarea:not([disabled]), select:not([disabled]), [contenteditable="true"], [role="textbox"], [role="combobox"]'
|
|
3588
|
+
);
|
|
3589
|
+
if (nestedControl && nestedControl !== element) {
|
|
3590
|
+
const nestedValue = readWaitTargetValue(nestedControl);
|
|
3591
|
+
if (nestedValue) {
|
|
3592
|
+
return nestedValue;
|
|
3593
|
+
}
|
|
3594
|
+
}
|
|
3595
|
+
return (element.textContent || "").trim();
|
|
3596
|
+
}
|
|
3597
|
+
const shadowInput = findInputInShadowRoot(element);
|
|
3598
|
+
if (shadowInput) {
|
|
3599
|
+
return shadowInput.value.trim();
|
|
3600
|
+
}
|
|
3556
3601
|
return "";
|
|
3557
3602
|
}
|
|
3558
3603
|
function buildManualCompletionTranscript(step, eventName) {
|
|
@@ -3574,6 +3619,12 @@ function createManualWaitForTarget(rawTarget, eventName, step) {
|
|
|
3574
3619
|
const target = resolveWaitTargetElement(rawTarget);
|
|
3575
3620
|
const completionTranscript = buildManualCompletionTranscript(step, eventName);
|
|
3576
3621
|
const isInputLikeEvent = isInputLikeWait(eventName, step);
|
|
3622
|
+
const commitPolicy = getManualInputCommitPolicy({
|
|
3623
|
+
tagName: target.tagName,
|
|
3624
|
+
role: target.getAttribute("role"),
|
|
3625
|
+
type: target.type ?? null,
|
|
3626
|
+
isContentEditable: target.isContentEditable
|
|
3627
|
+
});
|
|
3577
3628
|
if (isInputLikeEvent && readWaitTargetValue(target)) {
|
|
3578
3629
|
const initialValue = readWaitTargetValue(target);
|
|
3579
3630
|
return {
|
|
@@ -3585,6 +3636,8 @@ function createManualWaitForTarget(rawTarget, eventName, step) {
|
|
|
3585
3636
|
let cleanup = () => void 0;
|
|
3586
3637
|
const promise = new Promise((resolve) => {
|
|
3587
3638
|
const listeners2 = [];
|
|
3639
|
+
let observer = null;
|
|
3640
|
+
let idleTimer = null;
|
|
3588
3641
|
let settled = false;
|
|
3589
3642
|
const finish = () => {
|
|
3590
3643
|
if (settled) return;
|
|
@@ -3597,20 +3650,61 @@ function createManualWaitForTarget(rawTarget, eventName, step) {
|
|
|
3597
3650
|
listeners2.push({ node, type, handler });
|
|
3598
3651
|
};
|
|
3599
3652
|
if (isInputLikeEvent) {
|
|
3600
|
-
const
|
|
3653
|
+
const clearIdleCommit = () => {
|
|
3654
|
+
if (idleTimer) {
|
|
3655
|
+
clearTimeout(idleTimer);
|
|
3656
|
+
idleTimer = null;
|
|
3657
|
+
}
|
|
3658
|
+
};
|
|
3659
|
+
const scheduleIdleCommit = () => {
|
|
3660
|
+
const currentValue = readWaitTargetValue(target);
|
|
3661
|
+
if (!currentValue) {
|
|
3662
|
+
clearIdleCommit();
|
|
3663
|
+
return;
|
|
3664
|
+
}
|
|
3665
|
+
clearIdleCommit();
|
|
3666
|
+
idleTimer = setTimeout(() => {
|
|
3667
|
+
idleTimer = null;
|
|
3668
|
+
finish();
|
|
3669
|
+
}, commitPolicy.idleCommitMs);
|
|
3670
|
+
};
|
|
3671
|
+
const handleImmediateCommitEvent = () => {
|
|
3601
3672
|
const currentValue = readWaitTargetValue(target);
|
|
3602
3673
|
if (currentValue) {
|
|
3674
|
+
clearIdleCommit();
|
|
3603
3675
|
finish();
|
|
3604
3676
|
}
|
|
3605
3677
|
};
|
|
3606
|
-
addListener(target, "input",
|
|
3607
|
-
|
|
3608
|
-
|
|
3678
|
+
addListener(target, "input", scheduleIdleCommit);
|
|
3679
|
+
if (commitPolicy.commitOnChange) {
|
|
3680
|
+
addListener(target, "change", handleImmediateCommitEvent);
|
|
3681
|
+
}
|
|
3682
|
+
if (commitPolicy.commitOnBlur) {
|
|
3683
|
+
addListener(target, "blur", handleImmediateCommitEvent);
|
|
3684
|
+
}
|
|
3685
|
+
if (typeof MutationObserver !== "undefined") {
|
|
3686
|
+
observer = new MutationObserver(() => {
|
|
3687
|
+
scheduleIdleCommit();
|
|
3688
|
+
});
|
|
3689
|
+
observer.observe(target, {
|
|
3690
|
+
subtree: true,
|
|
3691
|
+
childList: true,
|
|
3692
|
+
characterData: true,
|
|
3693
|
+
attributes: true,
|
|
3694
|
+
attributeFilter: ["value", "aria-valuetext", "aria-valuenow", "aria-activedescendant"]
|
|
3695
|
+
});
|
|
3696
|
+
}
|
|
3609
3697
|
} else {
|
|
3610
3698
|
const handleActionEvent = () => finish();
|
|
3611
3699
|
addListener(target, eventName, handleActionEvent);
|
|
3612
3700
|
}
|
|
3613
3701
|
cleanup = () => {
|
|
3702
|
+
if (idleTimer) {
|
|
3703
|
+
clearTimeout(idleTimer);
|
|
3704
|
+
idleTimer = null;
|
|
3705
|
+
}
|
|
3706
|
+
observer?.disconnect();
|
|
3707
|
+
observer = null;
|
|
3614
3708
|
listeners2.forEach(({ node, type, handler }) => node.removeEventListener(type, handler));
|
|
3615
3709
|
listeners2.length = 0;
|
|
3616
3710
|
};
|