@redrockswebdevelopment/formstack-form-testing 0.1.33 → 0.1.35
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.d.ts +99 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +384 -24
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -23,8 +23,8 @@ export const liveFormFieldTypeCoverage = {
|
|
|
23
23
|
apiWrite: true,
|
|
24
24
|
domInteraction: true,
|
|
25
25
|
domAssertion: true,
|
|
26
|
-
reason: "Compound address values can be written through Live Form API, while
|
|
27
|
-
recommendedHelpers: ["buildLiveFormAddressValue", "
|
|
26
|
+
reason: "Compound address values can be written through Live Form API, while subfield UX should be asserted for address line, city, state, ZIP, and country controls.",
|
|
27
|
+
recommendedHelpers: ["buildLiveFormAddressValue", "setLiveFormAddressValue", "readLiveFormAddressState", "fillAddress"],
|
|
28
28
|
},
|
|
29
29
|
checkbox: {
|
|
30
30
|
kind: "checkbox",
|
|
@@ -150,8 +150,8 @@ export const liveFormFieldTypeCoverage = {
|
|
|
150
150
|
apiWrite: true,
|
|
151
151
|
domInteraction: true,
|
|
152
152
|
domAssertion: true,
|
|
153
|
-
reason: "Product API state can be set, but visible quantity
|
|
154
|
-
recommendedHelpers: ["buildLiveFormProductValue", "
|
|
153
|
+
reason: "Product API state can be set, but visible quantity, fixed amount, and selected product UI can diverge by product configuration.",
|
|
154
|
+
recommendedHelpers: ["buildLiveFormProductValue", "setLiveFormProductValue", "readLiveFormProductState", "fillProduct"],
|
|
155
155
|
},
|
|
156
156
|
radio: {
|
|
157
157
|
kind: "radio",
|
|
@@ -901,6 +901,16 @@ export function buildLiveFormAddressValue(value, current = {}) {
|
|
|
901
901
|
...value,
|
|
902
902
|
};
|
|
903
903
|
}
|
|
904
|
+
export function normalizeLiveFormAddressValue(value, current = {}) {
|
|
905
|
+
return buildLiveFormAddressValue({
|
|
906
|
+
...(value.address === undefined ? {} : { address: String(value.address) }),
|
|
907
|
+
...(value.address2 === undefined ? {} : { address2: String(value.address2) }),
|
|
908
|
+
...(value.city === undefined ? {} : { city: String(value.city) }),
|
|
909
|
+
...(value.state === undefined ? {} : { state: String(value.state) }),
|
|
910
|
+
...(value.zip === undefined ? {} : { zip: String(value.zip) }),
|
|
911
|
+
...(value.country === undefined ? {} : { country: String(value.country) }),
|
|
912
|
+
}, current);
|
|
913
|
+
}
|
|
904
914
|
export function buildLiveFormChoiceValue(value, otherValue = "") {
|
|
905
915
|
return { value, otherValue };
|
|
906
916
|
}
|
|
@@ -1030,6 +1040,13 @@ export function buildLiveFormProductValue(value, current = {}) {
|
|
|
1030
1040
|
...value,
|
|
1031
1041
|
};
|
|
1032
1042
|
}
|
|
1043
|
+
export function normalizeLiveFormProductValue(value, current = {}) {
|
|
1044
|
+
return buildLiveFormProductValue({
|
|
1045
|
+
...(value.fixedAmount === undefined ? {} : { fixedAmount: String(value.fixedAmount) }),
|
|
1046
|
+
...(value.quantity === undefined ? {} : { quantity: String(value.quantity) }),
|
|
1047
|
+
...("value" in value && value.value !== undefined ? { value: String(value.value) } : {}),
|
|
1048
|
+
}, current);
|
|
1049
|
+
}
|
|
1033
1050
|
export function buildLiveFormRatingValue(value) {
|
|
1034
1051
|
return { value: String(value) };
|
|
1035
1052
|
}
|
|
@@ -1827,6 +1844,217 @@ export async function waitForLiveFormDomFieldState(page, options) {
|
|
|
1827
1844
|
}
|
|
1828
1845
|
return latest;
|
|
1829
1846
|
}
|
|
1847
|
+
export async function readLiveFormProductState(page, options) {
|
|
1848
|
+
if (!hasEvaluate(page)) {
|
|
1849
|
+
throw new Error("readLiveFormProductState requires a Playwright page with evaluate().");
|
|
1850
|
+
}
|
|
1851
|
+
return page.evaluate((stateOptions) => {
|
|
1852
|
+
const normalizeText = (value) => (value ?? "").replace(/\s+/g, " ").trim();
|
|
1853
|
+
const inferPart = (control) => {
|
|
1854
|
+
const label = control.id ? document.querySelector(`label[for="${CSS.escape(control.id)}"]`) : null;
|
|
1855
|
+
const haystack = [
|
|
1856
|
+
control.name,
|
|
1857
|
+
control.id,
|
|
1858
|
+
control.className,
|
|
1859
|
+
control.getAttribute("placeholder"),
|
|
1860
|
+
control.getAttribute("aria-label"),
|
|
1861
|
+
label?.textContent,
|
|
1862
|
+
].map(normalizeText).join(" ").toLowerCase();
|
|
1863
|
+
if (/\b(quantity|qty|\[quantity\]|-quantity$|_quantity$)/i.test(haystack))
|
|
1864
|
+
return "quantity";
|
|
1865
|
+
if (/\b(fixed amount|fixedamount|amount|price|\[fixedamount\]|-fixedamount$|_fixedamount$)/i.test(haystack))
|
|
1866
|
+
return "fixedAmount";
|
|
1867
|
+
if (/\b(product|option|value|\[value\]|-value$|_value$)/i.test(haystack))
|
|
1868
|
+
return "value";
|
|
1869
|
+
return null;
|
|
1870
|
+
};
|
|
1871
|
+
const root = stateOptions.selector != null
|
|
1872
|
+
? document.querySelector(stateOptions.selector)
|
|
1873
|
+
: stateOptions.internalLabel != null
|
|
1874
|
+
? document.querySelector(`[data-internal-label="${CSS.escape(stateOptions.internalLabel)}"]`)
|
|
1875
|
+
: stateOptions.fieldId == null
|
|
1876
|
+
? null
|
|
1877
|
+
: document.querySelector(`#fsCell${CSS.escape(String(stateOptions.fieldId))}, #fsFieldCell${CSS.escape(String(stateOptions.fieldId))}, [data-testid="field-${CSS.escape(String(stateOptions.fieldId))}"]`);
|
|
1878
|
+
const nativeControls = root
|
|
1879
|
+
? Array.from(root.querySelectorAll("input, textarea, select"))
|
|
1880
|
+
: [];
|
|
1881
|
+
const controls = nativeControls.map((control) => {
|
|
1882
|
+
const selected = control instanceof HTMLSelectElement
|
|
1883
|
+
? control.selectedIndex >= 0
|
|
1884
|
+
: control instanceof HTMLInputElement && ["checkbox", "radio"].includes(control.type)
|
|
1885
|
+
? control.checked
|
|
1886
|
+
: null;
|
|
1887
|
+
return {
|
|
1888
|
+
tagName: control.tagName.toLowerCase(),
|
|
1889
|
+
type: control.getAttribute("type"),
|
|
1890
|
+
id: control.getAttribute("id"),
|
|
1891
|
+
name: control.getAttribute("name"),
|
|
1892
|
+
value: control.getAttribute("value"),
|
|
1893
|
+
currentValue: "value" in control ? control.value : "",
|
|
1894
|
+
checked: control instanceof HTMLInputElement && ["checkbox", "radio"].includes(control.type) ? control.checked : null,
|
|
1895
|
+
part: inferPart(control),
|
|
1896
|
+
text: control instanceof HTMLSelectElement
|
|
1897
|
+
? normalizeText(control.selectedOptions.item(0)?.textContent)
|
|
1898
|
+
: normalizeText(control.textContent),
|
|
1899
|
+
selected,
|
|
1900
|
+
disabled: "disabled" in control ? Boolean(control.disabled) : null,
|
|
1901
|
+
};
|
|
1902
|
+
});
|
|
1903
|
+
const activeControls = controls.filter((control) => control.disabled !== true &&
|
|
1904
|
+
((control.tagName === "select" && (control.currentValue ?? "").length > 0) ||
|
|
1905
|
+
(["checkbox", "radio"].includes(control.type ?? "") ? control.checked === true : (control.currentValue ?? "").length > 0)));
|
|
1906
|
+
const findPart = (part) => activeControls.find((control) => control.part === part)?.currentValue ?? null;
|
|
1907
|
+
const selectedValue = findPart("value") ?? activeControls.find((control) => ["checkbox", "radio"].includes(control.type ?? "") && control.checked === true)?.currentValue ?? null;
|
|
1908
|
+
const quantity = findPart("quantity");
|
|
1909
|
+
const fixedAmount = findPart("fixedAmount");
|
|
1910
|
+
const amountText = root
|
|
1911
|
+
? Array.from(root.querySelectorAll("[class*=\"amount\"], [class*=\"price\"], [data-testid*=\"amount\"], [data-testid*=\"price\"]"))
|
|
1912
|
+
.map((element) => normalizeText(element.textContent))
|
|
1913
|
+
.find((text) => text.length > 0 && /[$€£]|\d/.test(text)) ?? null
|
|
1914
|
+
: null;
|
|
1915
|
+
const expected = stateOptions.expectedValue ?? {};
|
|
1916
|
+
const expectedEntries = Object.entries(expected).filter((entry) => typeof entry[1] === "string" && entry[1].length > 0);
|
|
1917
|
+
const selectedParts = {
|
|
1918
|
+
value: selectedValue,
|
|
1919
|
+
quantity,
|
|
1920
|
+
fixedAmount,
|
|
1921
|
+
};
|
|
1922
|
+
const renderedExpectedEntries = expectedEntries.filter(([part]) => selectedParts[part] !== null);
|
|
1923
|
+
const unavailableParts = expectedEntries
|
|
1924
|
+
.filter(([part]) => selectedParts[part] === null)
|
|
1925
|
+
.map(([part]) => part);
|
|
1926
|
+
const missingParts = renderedExpectedEntries
|
|
1927
|
+
.filter(([part]) => selectedParts[part] === "")
|
|
1928
|
+
.map(([part]) => part);
|
|
1929
|
+
const mismatchedParts = renderedExpectedEntries
|
|
1930
|
+
.filter(([part, value]) => selectedParts[part] !== "" && selectedParts[part] !== value)
|
|
1931
|
+
.map(([part]) => part);
|
|
1932
|
+
const renderedValueAvailable = renderedExpectedEntries.length > 0 || activeControls.length > 0 || amountText !== null;
|
|
1933
|
+
return {
|
|
1934
|
+
fieldMatched: Boolean(root),
|
|
1935
|
+
selectedValue,
|
|
1936
|
+
quantity,
|
|
1937
|
+
fixedAmount,
|
|
1938
|
+
amountText,
|
|
1939
|
+
...(stateOptions.expectedValue === undefined ? {} : { expectedValue: stateOptions.expectedValue }),
|
|
1940
|
+
renderedValueAvailable,
|
|
1941
|
+
unavailableParts,
|
|
1942
|
+
missingParts,
|
|
1943
|
+
mismatchedParts,
|
|
1944
|
+
matched: Boolean(root) && missingParts.length === 0 && mismatchedParts.length === 0,
|
|
1945
|
+
controls,
|
|
1946
|
+
};
|
|
1947
|
+
}, options);
|
|
1948
|
+
}
|
|
1949
|
+
export async function waitForLiveFormProductState(page, options) {
|
|
1950
|
+
const timeoutMs = options.timeoutMs ?? 10_000;
|
|
1951
|
+
const intervalMs = options.intervalMs ?? 100;
|
|
1952
|
+
const startedAt = Date.now();
|
|
1953
|
+
let latest = await readLiveFormProductState(page, options);
|
|
1954
|
+
while (!latest.matched && Date.now() - startedAt < timeoutMs) {
|
|
1955
|
+
await delay(intervalMs);
|
|
1956
|
+
latest = await readLiveFormProductState(page, options);
|
|
1957
|
+
}
|
|
1958
|
+
return latest;
|
|
1959
|
+
}
|
|
1960
|
+
export async function readLiveFormAddressState(page, options) {
|
|
1961
|
+
if (!hasEvaluate(page)) {
|
|
1962
|
+
throw new Error("readLiveFormAddressState requires a Playwright page with evaluate().");
|
|
1963
|
+
}
|
|
1964
|
+
return page.evaluate((stateOptions) => {
|
|
1965
|
+
const normalizeText = (value) => (value ?? "").replace(/\s+/g, " ").trim();
|
|
1966
|
+
const inferPart = (control) => {
|
|
1967
|
+
const label = control.id ? document.querySelector(`label[for="${CSS.escape(control.id)}"]`) : null;
|
|
1968
|
+
const haystack = [
|
|
1969
|
+
control.name,
|
|
1970
|
+
control.id,
|
|
1971
|
+
control.className,
|
|
1972
|
+
control.getAttribute("placeholder"),
|
|
1973
|
+
control.getAttribute("aria-label"),
|
|
1974
|
+
label?.textContent,
|
|
1975
|
+
].map(normalizeText).join(" ").toLowerCase();
|
|
1976
|
+
if (/\b(address line 2|address 2|address2|line 2|street 2|\[address2\]|-address2$|_address2$)/i.test(haystack))
|
|
1977
|
+
return "address2";
|
|
1978
|
+
if (/\b(address line 1|address 1|address|street|line 1|\[address\]|-address$|_address$)/i.test(haystack))
|
|
1979
|
+
return "address";
|
|
1980
|
+
if (/\b(city|\[city\]|-city$|_city$)/i.test(haystack))
|
|
1981
|
+
return "city";
|
|
1982
|
+
if (/\b(state|province|region|\[state\]|-state$|_state$)/i.test(haystack))
|
|
1983
|
+
return "state";
|
|
1984
|
+
if (/\b(zip|postal|postcode|post code|\[zip\]|-zip$|_zip$)/i.test(haystack))
|
|
1985
|
+
return "zip";
|
|
1986
|
+
if (/\b(country|\[country\]|-country$|_country$)/i.test(haystack))
|
|
1987
|
+
return "country";
|
|
1988
|
+
return null;
|
|
1989
|
+
};
|
|
1990
|
+
const root = stateOptions.selector != null
|
|
1991
|
+
? document.querySelector(stateOptions.selector)
|
|
1992
|
+
: stateOptions.internalLabel != null
|
|
1993
|
+
? document.querySelector(`[data-internal-label="${CSS.escape(stateOptions.internalLabel)}"]`)
|
|
1994
|
+
: stateOptions.fieldId == null
|
|
1995
|
+
? null
|
|
1996
|
+
: document.querySelector(`#fsCell${CSS.escape(String(stateOptions.fieldId))}, #fsFieldCell${CSS.escape(String(stateOptions.fieldId))}, [data-testid="field-${CSS.escape(String(stateOptions.fieldId))}"]`);
|
|
1997
|
+
const nativeControls = root
|
|
1998
|
+
? Array.from(root.querySelectorAll("input, textarea, select"))
|
|
1999
|
+
: [];
|
|
2000
|
+
const controls = nativeControls.map((control) => ({
|
|
2001
|
+
tagName: control.tagName.toLowerCase(),
|
|
2002
|
+
type: control.getAttribute("type"),
|
|
2003
|
+
id: control.getAttribute("id"),
|
|
2004
|
+
name: control.getAttribute("name"),
|
|
2005
|
+
value: control.getAttribute("value"),
|
|
2006
|
+
currentValue: "value" in control ? control.value : "",
|
|
2007
|
+
checked: control instanceof HTMLInputElement && ["checkbox", "radio"].includes(control.type) ? control.checked : null,
|
|
2008
|
+
part: inferPart(control),
|
|
2009
|
+
text: control instanceof HTMLSelectElement
|
|
2010
|
+
? normalizeText(control.selectedOptions.item(0)?.textContent)
|
|
2011
|
+
: normalizeText(control.textContent),
|
|
2012
|
+
disabled: "disabled" in control ? Boolean(control.disabled) : null,
|
|
2013
|
+
}));
|
|
2014
|
+
const selectedParts = {};
|
|
2015
|
+
for (const control of controls) {
|
|
2016
|
+
if (control.part && control.disabled !== true && typeof control.currentValue === "string" && control.currentValue.length > 0) {
|
|
2017
|
+
selectedParts[control.part] = control.currentValue;
|
|
2018
|
+
}
|
|
2019
|
+
}
|
|
2020
|
+
const expected = stateOptions.expectedValue ?? {};
|
|
2021
|
+
const expectedEntries = Object.entries(expected).filter((entry) => typeof entry[1] === "string" && entry[1].length > 0);
|
|
2022
|
+
const availableParts = new Set(controls.filter((control) => control.part && control.disabled !== true).map((control) => control.part));
|
|
2023
|
+
const renderedExpectedEntries = expectedEntries.filter(([part]) => availableParts.has(part));
|
|
2024
|
+
const unavailableParts = expectedEntries
|
|
2025
|
+
.filter(([part]) => !availableParts.has(part))
|
|
2026
|
+
.map(([part]) => part);
|
|
2027
|
+
const missingParts = renderedExpectedEntries
|
|
2028
|
+
.filter(([part]) => selectedParts[part] === undefined || selectedParts[part] === "")
|
|
2029
|
+
.map(([part]) => part);
|
|
2030
|
+
const mismatchedParts = renderedExpectedEntries
|
|
2031
|
+
.filter(([part, value]) => selectedParts[part] !== undefined && selectedParts[part] !== "" && selectedParts[part] !== value)
|
|
2032
|
+
.map(([part]) => part);
|
|
2033
|
+
const renderedValueAvailable = Object.keys(selectedParts).length > 0;
|
|
2034
|
+
return {
|
|
2035
|
+
fieldMatched: Boolean(root),
|
|
2036
|
+
selectedParts,
|
|
2037
|
+
...(stateOptions.expectedValue === undefined ? {} : { expectedValue: stateOptions.expectedValue }),
|
|
2038
|
+
renderedValueAvailable,
|
|
2039
|
+
unavailableParts,
|
|
2040
|
+
missingParts,
|
|
2041
|
+
mismatchedParts,
|
|
2042
|
+
matched: Boolean(root) && missingParts.length === 0 && mismatchedParts.length === 0,
|
|
2043
|
+
controls,
|
|
2044
|
+
};
|
|
2045
|
+
}, options);
|
|
2046
|
+
}
|
|
2047
|
+
export async function waitForLiveFormAddressState(page, options) {
|
|
2048
|
+
const timeoutMs = options.timeoutMs ?? 10_000;
|
|
2049
|
+
const intervalMs = options.intervalMs ?? 100;
|
|
2050
|
+
const startedAt = Date.now();
|
|
2051
|
+
let latest = await readLiveFormAddressState(page, options);
|
|
2052
|
+
while (!latest.matched && Date.now() - startedAt < timeoutMs) {
|
|
2053
|
+
await delay(intervalMs);
|
|
2054
|
+
latest = await readLiveFormAddressState(page, options);
|
|
2055
|
+
}
|
|
2056
|
+
return latest;
|
|
2057
|
+
}
|
|
1830
2058
|
export async function readLiveFormCheckboxState(page, options) {
|
|
1831
2059
|
if (!hasEvaluate(page)) {
|
|
1832
2060
|
throw new Error("readLiveFormCheckboxState requires a Playwright page with evaluate().");
|
|
@@ -4081,6 +4309,88 @@ export async function setLiveFormMatrixValues(page, options) {
|
|
|
4081
4309
|
(visibility?.matched ?? true),
|
|
4082
4310
|
};
|
|
4083
4311
|
}
|
|
4312
|
+
export async function setLiveFormProductValue(page, options) {
|
|
4313
|
+
const payload = normalizeLiveFormProductValue(options.value, options.current);
|
|
4314
|
+
const transaction = await performLiveFormFieldTransaction(page, {
|
|
4315
|
+
write: {
|
|
4316
|
+
...(options.write ?? {}),
|
|
4317
|
+
target: options.target,
|
|
4318
|
+
value: payload,
|
|
4319
|
+
notify: options.write?.notify ?? true,
|
|
4320
|
+
},
|
|
4321
|
+
fieldKind: "product",
|
|
4322
|
+
waitForEvent: options.waitForEvent ?? true,
|
|
4323
|
+
dispatchDomEvents: options.dispatchDomEvents ?? "auto",
|
|
4324
|
+
afterQuiet: options.afterQuiet ?? { quietMs: 200, timeoutMs: 5_000 },
|
|
4325
|
+
...(options.afterValidation === undefined ? {} : { afterValidation: options.afterValidation }),
|
|
4326
|
+
});
|
|
4327
|
+
const dom = await waitForLiveFormProductState(page, {
|
|
4328
|
+
...options.target,
|
|
4329
|
+
expectedValue: payload,
|
|
4330
|
+
...(options.write?.timeoutMs === undefined ? {} : { timeoutMs: options.write.timeoutMs }),
|
|
4331
|
+
});
|
|
4332
|
+
const visibilityTargets = [
|
|
4333
|
+
...(options.expectVisible ?? []).map((target) => ({ ...target, visible: true })),
|
|
4334
|
+
...(options.expectHidden ?? []).map((target) => ({ ...target, visible: false })),
|
|
4335
|
+
];
|
|
4336
|
+
const visibility = visibilityTargets.length > 0
|
|
4337
|
+
? await waitForLiveFormVisibility(page, { targets: visibilityTargets })
|
|
4338
|
+
: undefined;
|
|
4339
|
+
return {
|
|
4340
|
+
payload,
|
|
4341
|
+
transaction,
|
|
4342
|
+
dom,
|
|
4343
|
+
...(visibility ? { visibility } : {}),
|
|
4344
|
+
ok: transaction.write.valueMatched &&
|
|
4345
|
+
(transaction.event?.matched ?? true) &&
|
|
4346
|
+
(transaction.domDispatch ? transaction.domDispatch.matchedControlCount >= 1 : true) &&
|
|
4347
|
+
(transaction.quiet?.quiet ?? true) &&
|
|
4348
|
+
((transaction.validation?.inlineErrors.length ?? 0) === 0) &&
|
|
4349
|
+
dom.matched &&
|
|
4350
|
+
(visibility?.matched ?? true),
|
|
4351
|
+
};
|
|
4352
|
+
}
|
|
4353
|
+
export async function setLiveFormAddressValue(page, options) {
|
|
4354
|
+
const payload = normalizeLiveFormAddressValue(options.value, options.current);
|
|
4355
|
+
const transaction = await performLiveFormFieldTransaction(page, {
|
|
4356
|
+
write: {
|
|
4357
|
+
...(options.write ?? {}),
|
|
4358
|
+
target: options.target,
|
|
4359
|
+
value: payload,
|
|
4360
|
+
notify: options.write?.notify ?? true,
|
|
4361
|
+
},
|
|
4362
|
+
fieldKind: "address",
|
|
4363
|
+
waitForEvent: options.waitForEvent ?? true,
|
|
4364
|
+
dispatchDomEvents: options.dispatchDomEvents ?? "auto",
|
|
4365
|
+
afterQuiet: options.afterQuiet ?? { quietMs: 200, timeoutMs: 5_000 },
|
|
4366
|
+
...(options.afterValidation === undefined ? {} : { afterValidation: options.afterValidation }),
|
|
4367
|
+
});
|
|
4368
|
+
const dom = await waitForLiveFormAddressState(page, {
|
|
4369
|
+
...options.target,
|
|
4370
|
+
expectedValue: payload,
|
|
4371
|
+
...(options.write?.timeoutMs === undefined ? {} : { timeoutMs: options.write.timeoutMs }),
|
|
4372
|
+
});
|
|
4373
|
+
const visibilityTargets = [
|
|
4374
|
+
...(options.expectVisible ?? []).map((target) => ({ ...target, visible: true })),
|
|
4375
|
+
...(options.expectHidden ?? []).map((target) => ({ ...target, visible: false })),
|
|
4376
|
+
];
|
|
4377
|
+
const visibility = visibilityTargets.length > 0
|
|
4378
|
+
? await waitForLiveFormVisibility(page, { targets: visibilityTargets })
|
|
4379
|
+
: undefined;
|
|
4380
|
+
return {
|
|
4381
|
+
payload,
|
|
4382
|
+
transaction,
|
|
4383
|
+
dom,
|
|
4384
|
+
...(visibility ? { visibility } : {}),
|
|
4385
|
+
ok: transaction.write.valueMatched &&
|
|
4386
|
+
(transaction.event?.matched ?? true) &&
|
|
4387
|
+
(transaction.domDispatch ? transaction.domDispatch.matchedControlCount >= 1 : true) &&
|
|
4388
|
+
(transaction.quiet?.quiet ?? true) &&
|
|
4389
|
+
((transaction.validation?.inlineErrors.length ?? 0) === 0) &&
|
|
4390
|
+
dom.matched &&
|
|
4391
|
+
(visibility?.matched ?? true),
|
|
4392
|
+
};
|
|
4393
|
+
}
|
|
4084
4394
|
export async function setLiveFormRatingValue(page, options) {
|
|
4085
4395
|
const payload = normalizeLiveFormRatingValue(options.value);
|
|
4086
4396
|
const value = payload.value;
|
|
@@ -4211,7 +4521,29 @@ export async function answerProgressiveLiveFormField(page, options) {
|
|
|
4211
4521
|
...(validationOptions ? { afterValidation: validationOptions } : {}),
|
|
4212
4522
|
})
|
|
4213
4523
|
: undefined;
|
|
4214
|
-
const
|
|
4524
|
+
const addressTransaction = !checkboxTransaction && !choiceTransaction && !selectTransaction && !matrixTransaction && options.fieldKind === "address"
|
|
4525
|
+
? await setLiveFormAddressValue(page, {
|
|
4526
|
+
target: options.target,
|
|
4527
|
+
value: options.value,
|
|
4528
|
+
...(options.write === undefined ? {} : { write: options.write }),
|
|
4529
|
+
waitForEvent: options.waitForEvent ?? true,
|
|
4530
|
+
dispatchDomEvents: options.dispatchDomEvents ?? "auto",
|
|
4531
|
+
afterQuiet: options.afterQuiet ?? true,
|
|
4532
|
+
...(validationOptions ? { afterValidation: validationOptions } : {}),
|
|
4533
|
+
})
|
|
4534
|
+
: undefined;
|
|
4535
|
+
const productTransaction = !checkboxTransaction && !choiceTransaction && !selectTransaction && !matrixTransaction && !addressTransaction && options.fieldKind === "product"
|
|
4536
|
+
? await setLiveFormProductValue(page, {
|
|
4537
|
+
target: options.target,
|
|
4538
|
+
value: options.value,
|
|
4539
|
+
...(options.write === undefined ? {} : { write: options.write }),
|
|
4540
|
+
waitForEvent: options.waitForEvent ?? true,
|
|
4541
|
+
dispatchDomEvents: options.dispatchDomEvents ?? "auto",
|
|
4542
|
+
afterQuiet: options.afterQuiet ?? true,
|
|
4543
|
+
...(validationOptions ? { afterValidation: validationOptions } : {}),
|
|
4544
|
+
})
|
|
4545
|
+
: undefined;
|
|
4546
|
+
const ratingTransaction = !checkboxTransaction && !choiceTransaction && !selectTransaction && !matrixTransaction && !addressTransaction && !productTransaction && options.fieldKind === "rating"
|
|
4215
4547
|
? await setLiveFormRatingValue(page, {
|
|
4216
4548
|
target: options.target,
|
|
4217
4549
|
value: options.value,
|
|
@@ -4241,23 +4573,27 @@ export async function answerProgressiveLiveFormField(page, options) {
|
|
|
4241
4573
|
? selectTransaction.transaction
|
|
4242
4574
|
: matrixTransaction
|
|
4243
4575
|
? matrixTransaction.transaction
|
|
4244
|
-
:
|
|
4245
|
-
?
|
|
4246
|
-
:
|
|
4247
|
-
?
|
|
4248
|
-
:
|
|
4249
|
-
|
|
4250
|
-
|
|
4251
|
-
|
|
4252
|
-
|
|
4253
|
-
|
|
4254
|
-
|
|
4255
|
-
|
|
4256
|
-
|
|
4257
|
-
|
|
4258
|
-
|
|
4259
|
-
|
|
4260
|
-
|
|
4576
|
+
: addressTransaction
|
|
4577
|
+
? addressTransaction.transaction
|
|
4578
|
+
: productTransaction
|
|
4579
|
+
? productTransaction.transaction
|
|
4580
|
+
: ratingTransaction
|
|
4581
|
+
? ratingTransaction.transaction
|
|
4582
|
+
: dateTimeTransaction
|
|
4583
|
+
? dateTimeTransaction.transaction
|
|
4584
|
+
: await performLiveFormFieldTransaction(page, {
|
|
4585
|
+
write: {
|
|
4586
|
+
...(options.write ?? {}),
|
|
4587
|
+
target: options.target,
|
|
4588
|
+
value: options.value,
|
|
4589
|
+
notify: options.write?.notify ?? true,
|
|
4590
|
+
},
|
|
4591
|
+
...(options.fieldKind ? { fieldKind: options.fieldKind } : {}),
|
|
4592
|
+
waitForEvent: options.waitForEvent ?? true,
|
|
4593
|
+
dispatchDomEvents: options.dispatchDomEvents ?? "auto",
|
|
4594
|
+
afterQuiet: options.afterQuiet ?? true,
|
|
4595
|
+
...(validationOptions ? { afterValidation: validationOptions } : {}),
|
|
4596
|
+
});
|
|
4261
4597
|
const visibilityTargets = [
|
|
4262
4598
|
...(options.expectVisible ?? []),
|
|
4263
4599
|
...(options.expectHidden ?? []).map((target) => ({ ...target, visible: false })),
|
|
@@ -5962,7 +6298,19 @@ export const liveFormFieldRecipes = {
|
|
|
5962
6298
|
},
|
|
5963
6299
|
}),
|
|
5964
6300
|
setNameApi: (name, internalLabel, value, options) => apiRecipeStep(name, { internalLabel }, buildLiveFormNameValue(value), options),
|
|
5965
|
-
setAddressApi: (name, internalLabel, value, options) =>
|
|
6301
|
+
setAddressApi: (name, internalLabel, value, options = {}) => ({
|
|
6302
|
+
name,
|
|
6303
|
+
run: async (harness) => {
|
|
6304
|
+
await setLiveFormAddressValue(harness.page, {
|
|
6305
|
+
target: { internalLabel },
|
|
6306
|
+
value,
|
|
6307
|
+
write: { notify: options.notify ?? true },
|
|
6308
|
+
waitForEvent: options.waitForEvent ?? (options.notify ?? true),
|
|
6309
|
+
dispatchDomEvents: options.dispatchDomEvents ?? "auto",
|
|
6310
|
+
afterQuiet: options.waitForQuiet ?? true,
|
|
6311
|
+
});
|
|
6312
|
+
},
|
|
6313
|
+
}),
|
|
5966
6314
|
setChoiceApi: (name, internalLabel, value, options = {}) => ({
|
|
5967
6315
|
name,
|
|
5968
6316
|
run: async (harness) => {
|
|
@@ -6041,7 +6389,19 @@ export const liveFormFieldRecipes = {
|
|
|
6041
6389
|
});
|
|
6042
6390
|
},
|
|
6043
6391
|
}),
|
|
6044
|
-
setProductApi: (name, internalLabel, value, options) =>
|
|
6392
|
+
setProductApi: (name, internalLabel, value, options = {}) => ({
|
|
6393
|
+
name,
|
|
6394
|
+
run: async (harness) => {
|
|
6395
|
+
await setLiveFormProductValue(harness.page, {
|
|
6396
|
+
target: { internalLabel },
|
|
6397
|
+
value,
|
|
6398
|
+
write: { notify: options.notify ?? true },
|
|
6399
|
+
waitForEvent: options.waitForEvent ?? (options.notify ?? true),
|
|
6400
|
+
dispatchDomEvents: options.dispatchDomEvents ?? "auto",
|
|
6401
|
+
afterQuiet: options.waitForQuiet ?? true,
|
|
6402
|
+
});
|
|
6403
|
+
},
|
|
6404
|
+
}),
|
|
6045
6405
|
setFieldApiAuto: (name, internalLabel, value, fieldKind, options = {}) => apiRecipeStep(name, { internalLabel }, value, { ...options, fieldKind, dispatchDomEvents: "auto" }),
|
|
6046
6406
|
setNameApiAndDispatch: (name, internalLabel, value, options = {}) => liveFormFieldRecipes.setNameApi(name, internalLabel, value, { ...options, fieldKind: options.fieldKind ?? "name", dispatchDomEvents: "auto" }),
|
|
6047
6407
|
setChoiceApiAndDispatch: (name, internalLabel, value, options = {}) => liveFormFieldRecipes.setChoiceApi(name, internalLabel, value, { ...options, fieldKind: options.fieldKind ?? "radio", dispatchDomEvents: "auto" }),
|