xmlui 0.11.11 → 0.11.12
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/lib/{index-BNm0RhXG.js → index-C_siLDTF.js} +223 -88
- package/dist/lib/index.css +1 -1
- package/dist/lib/{initMock-DK8FL64P.js → initMock-BYfY6ibT.js} +1 -1
- package/dist/lib/testing.d.ts +5 -403
- package/dist/lib/testing.js +4 -702
- package/dist/lib/xmlui.d.ts +2 -1
- package/dist/lib/xmlui.js +1 -1
- package/dist/metadata/{collectedComponentMetadata-DvV8yJ4N.js → collectedComponentMetadata-CCJh2wtR.js} +221 -86
- package/dist/metadata/{initMock-Bndg9J7D.js → initMock-Dm6pyFPh.js} +1 -1
- package/dist/metadata/xmlui-metadata.css +1 -1
- package/dist/metadata/xmlui-metadata.js +1 -1
- package/dist/metadata/xmlui-metadata.umd.cjs +1 -1
- package/dist/standalone/xmlui-standalone.es.d.ts +2 -1
- package/dist/standalone/xmlui-standalone.umd.js +36 -36
- package/package.json +1 -1
package/dist/lib/testing.js
CHANGED
|
@@ -1,16 +1,6 @@
|
|
|
1
1
|
import { expect as expect$1, test as test$1 } from "@playwright/test";
|
|
2
2
|
import { x as xmlUiMarkupToComponent, P as PART_START_ADORNMENT, a as PART_END_ADORNMENT, b as PART_INPUT } from "./xmlui-parser-CW8YmGjO.js";
|
|
3
|
-
import
|
|
4
|
-
function mapObject(obj, valFn = ((val) => val), keyFn = ((val) => val)) {
|
|
5
|
-
const newObject = {};
|
|
6
|
-
Object.entries(obj).forEach(([key, value]) => {
|
|
7
|
-
newObject[keyFn(key)] = valFn(value);
|
|
8
|
-
});
|
|
9
|
-
return newObject;
|
|
10
|
-
}
|
|
11
|
-
function getComponentTagName(locator) {
|
|
12
|
-
return locator.evaluate((el) => el.tagName.toLowerCase());
|
|
13
|
-
}
|
|
3
|
+
import "chroma-js";
|
|
14
4
|
function parseComponentIfNecessary(rawComponent) {
|
|
15
5
|
if (typeof rawComponent === "string") {
|
|
16
6
|
return xmlUiMarkupToComponent(rawComponent);
|
|
@@ -21,62 +11,7 @@ function parseComponentIfNecessary(rawComponent) {
|
|
|
21
11
|
erroneousCompoundComponentName: void 0
|
|
22
12
|
};
|
|
23
13
|
}
|
|
24
|
-
function
|
|
25
|
-
const parsed = parseAsNumericCss(percentage);
|
|
26
|
-
if (parsed.unit !== "%") {
|
|
27
|
-
throw new Error(`Expected percentage unit (%), got: ${parsed.unit}`);
|
|
28
|
-
}
|
|
29
|
-
return scalarOf100Percent / 100 * parsed.value;
|
|
30
|
-
}
|
|
31
|
-
function getBoundingRect$1(locator) {
|
|
32
|
-
return locator.evaluate((element) => element.getBoundingClientRect());
|
|
33
|
-
}
|
|
34
|
-
function getElementStyle$1(specifier, style) {
|
|
35
|
-
return specifier.evaluate(
|
|
36
|
-
(element, style2) => window.getComputedStyle(element).getPropertyValue(style2),
|
|
37
|
-
style
|
|
38
|
-
);
|
|
39
|
-
}
|
|
40
|
-
function getElementStyles$1(locator, styles = []) {
|
|
41
|
-
return locator.evaluate(
|
|
42
|
-
(element, styles2) => Object.fromEntries(
|
|
43
|
-
styles2.map((styleName) => [
|
|
44
|
-
styleName,
|
|
45
|
-
window.getComputedStyle(element).getPropertyValue(styleName)
|
|
46
|
-
])
|
|
47
|
-
),
|
|
48
|
-
styles
|
|
49
|
-
);
|
|
50
|
-
}
|
|
51
|
-
function isIndeterminate(specifier) {
|
|
52
|
-
if (specifier instanceof ComponentDriver) specifier = specifier.component;
|
|
53
|
-
return specifier.evaluate((el) => el.indeterminate);
|
|
54
|
-
}
|
|
55
|
-
async function overflows(locator, direction = "both") {
|
|
56
|
-
const [width, height, scrollWidth, scrollHeight] = await locator.evaluate((element) => [
|
|
57
|
-
element.clientWidth,
|
|
58
|
-
element.clientHeight,
|
|
59
|
-
element.scrollWidth,
|
|
60
|
-
element.scrollHeight
|
|
61
|
-
]);
|
|
62
|
-
if (direction === "x") return scrollWidth > width;
|
|
63
|
-
if (direction === "y") return scrollHeight > height;
|
|
64
|
-
return scrollWidth > width && scrollHeight > height;
|
|
65
|
-
}
|
|
66
|
-
function getStyles(specifier, style) {
|
|
67
|
-
if (specifier instanceof ComponentDriver) specifier = specifier.component;
|
|
68
|
-
style = Array.isArray(style) ? style : [style];
|
|
69
|
-
return specifier.evaluate(
|
|
70
|
-
(element, styles) => Object.fromEntries(
|
|
71
|
-
styles.map((styleName) => [
|
|
72
|
-
styleName.trim().split("-").map((n, idx) => idx === 0 ? n : n[0].toUpperCase() + n.slice(1)).join(""),
|
|
73
|
-
window.getComputedStyle(element).getPropertyValue(styleName)
|
|
74
|
-
])
|
|
75
|
-
),
|
|
76
|
-
style
|
|
77
|
-
);
|
|
78
|
-
}
|
|
79
|
-
function getPseudoStyles(specifier, pseudoElement, style) {
|
|
14
|
+
function getStyles(specifier, style, pseudoElement) {
|
|
80
15
|
if (specifier instanceof ComponentDriver) specifier = specifier.component;
|
|
81
16
|
style = Array.isArray(style) ? style : [style];
|
|
82
17
|
return specifier.evaluate(
|
|
@@ -89,204 +24,6 @@ function getPseudoStyles(specifier, pseudoElement, style) {
|
|
|
89
24
|
{ style, pseudoElement }
|
|
90
25
|
);
|
|
91
26
|
}
|
|
92
|
-
async function getHtmlAttributes(specifier, attributes) {
|
|
93
|
-
if (specifier instanceof ComponentDriver) specifier = specifier.component;
|
|
94
|
-
attributes = Array.isArray(attributes) ? attributes : [attributes];
|
|
95
|
-
const mapped = await Promise.all(
|
|
96
|
-
attributes.map(async (attr) => {
|
|
97
|
-
return [attr, await specifier.getAttribute(attr)];
|
|
98
|
-
})
|
|
99
|
-
);
|
|
100
|
-
return Object.fromEntries(mapped);
|
|
101
|
-
}
|
|
102
|
-
async function getPaddings(specifier) {
|
|
103
|
-
const paddings = mapObject(
|
|
104
|
-
await getStyles(specifier, ["padding-left", "padding-right", "padding-top", "padding-bottom"]),
|
|
105
|
-
parseAsNumericCss
|
|
106
|
-
);
|
|
107
|
-
return {
|
|
108
|
-
left: paddings.paddingLeft,
|
|
109
|
-
right: paddings.paddingRight,
|
|
110
|
-
top: paddings.paddingTop,
|
|
111
|
-
bottom: paddings.paddingBottom
|
|
112
|
-
};
|
|
113
|
-
}
|
|
114
|
-
async function getBorders(specifier) {
|
|
115
|
-
const borders = mapObject(
|
|
116
|
-
await getStyles(specifier, ["border-left", "border-right", "border-top", "border-bottom"]),
|
|
117
|
-
parseAsCssBorder
|
|
118
|
-
);
|
|
119
|
-
return {
|
|
120
|
-
left: borders.borderLeft,
|
|
121
|
-
right: borders.borderRight,
|
|
122
|
-
top: borders.borderTop,
|
|
123
|
-
bottom: borders.borderBottom
|
|
124
|
-
};
|
|
125
|
-
}
|
|
126
|
-
function getMargins(specifier) {
|
|
127
|
-
return getStyles(specifier, ["margin-left", "margin-right", "margin-top", "margin-bottom"]);
|
|
128
|
-
}
|
|
129
|
-
async function getBounds(specifier) {
|
|
130
|
-
if (specifier instanceof ComponentDriver) specifier = specifier.component;
|
|
131
|
-
const boundingRect = await specifier.evaluate((element) => element.getBoundingClientRect());
|
|
132
|
-
const m = mapObject(await getMargins(specifier), parseFloat);
|
|
133
|
-
const width = boundingRect.width + m.marginLeft + m.marginRight;
|
|
134
|
-
const height = boundingRect.height + m.marginTop + m.marginBottom;
|
|
135
|
-
const left = boundingRect.left - m.marginLeft;
|
|
136
|
-
const right = boundingRect.right + m.marginRight;
|
|
137
|
-
const top = boundingRect.top - m.marginTop;
|
|
138
|
-
const bottom = boundingRect.bottom + m.marginBottom;
|
|
139
|
-
return {
|
|
140
|
-
width,
|
|
141
|
-
height,
|
|
142
|
-
left,
|
|
143
|
-
right,
|
|
144
|
-
top,
|
|
145
|
-
bottom
|
|
146
|
-
};
|
|
147
|
-
}
|
|
148
|
-
class TestSkipReason {
|
|
149
|
-
addAnnotation(type, description) {
|
|
150
|
-
return {
|
|
151
|
-
annotation: {
|
|
152
|
-
type,
|
|
153
|
-
description: description ?? ""
|
|
154
|
-
}
|
|
155
|
-
};
|
|
156
|
-
}
|
|
157
|
-
NOT_IMPLEMENTED_XMLUI(description) {
|
|
158
|
-
return this.addAnnotation("not implemented in xmlui", description);
|
|
159
|
-
}
|
|
160
|
-
TO_BE_IMPLEMENTED(description) {
|
|
161
|
-
return this.addAnnotation("to be implemented", description);
|
|
162
|
-
}
|
|
163
|
-
XMLUI_BUG(description) {
|
|
164
|
-
return this.addAnnotation("xmlui bug", description);
|
|
165
|
-
}
|
|
166
|
-
TEST_INFRA_BUG(description) {
|
|
167
|
-
return this.addAnnotation("test infra bug", description);
|
|
168
|
-
}
|
|
169
|
-
TEST_NOT_WORKING(description) {
|
|
170
|
-
return this.addAnnotation("test not working", description);
|
|
171
|
-
}
|
|
172
|
-
TEST_INFRA_NOT_IMPLEMENTED(description) {
|
|
173
|
-
return this.addAnnotation("test infra not implemented", description);
|
|
174
|
-
}
|
|
175
|
-
REFACTOR(description) {
|
|
176
|
-
return this.addAnnotation("refactor", description);
|
|
177
|
-
}
|
|
178
|
-
// Need to specify a reason here!
|
|
179
|
-
UNSURE(description) {
|
|
180
|
-
return this.addAnnotation("unsure", description);
|
|
181
|
-
}
|
|
182
|
-
}
|
|
183
|
-
const SKIP_REASON = new TestSkipReason();
|
|
184
|
-
function pixelStrToNum$1(pixelStr) {
|
|
185
|
-
return Number(pixelStr.replace("px", ""));
|
|
186
|
-
}
|
|
187
|
-
function parseAsCssBorder(str) {
|
|
188
|
-
const parts = str.split(/\s+(?=[a-z]+|\()/i);
|
|
189
|
-
if (parts.length > 3) {
|
|
190
|
-
throw new Error(`Provided value ${str} cannot be parsed as a CSS border`);
|
|
191
|
-
}
|
|
192
|
-
const style = parts.filter(isCSSBorderStyle);
|
|
193
|
-
if (style.length > 1) {
|
|
194
|
-
throw new Error(`Too many border styles provided in ${str}`);
|
|
195
|
-
}
|
|
196
|
-
const width = parts.filter(isNumericCSS);
|
|
197
|
-
if (width.length > 1) {
|
|
198
|
-
throw new Error(`Too many border widths provided in ${str}`);
|
|
199
|
-
}
|
|
200
|
-
const color = parts.filter((p) => chroma.valid(p));
|
|
201
|
-
if (color.length > 1) {
|
|
202
|
-
throw new Error(`Too many border colors provided in ${str}`);
|
|
203
|
-
}
|
|
204
|
-
const result = {
|
|
205
|
-
width: !!width[0] ? parseAsNumericCss(width[0]) : void 0,
|
|
206
|
-
style: style[0],
|
|
207
|
-
color: chroma(color[0])
|
|
208
|
-
};
|
|
209
|
-
return result;
|
|
210
|
-
}
|
|
211
|
-
const numericCSSRegex = /^([+-]?(?:\d+|\d*\.\d+))([a-z]*|%)$/;
|
|
212
|
-
function isNumericCSS(str) {
|
|
213
|
-
const parts = str.match(numericCSSRegex);
|
|
214
|
-
if (!parts) return false;
|
|
215
|
-
if (parts.length < 3) return false;
|
|
216
|
-
if (isNaN(parseFloat(parts[1]))) return false;
|
|
217
|
-
if (!isCSSUnit(parts[2])) return false;
|
|
218
|
-
return true;
|
|
219
|
-
}
|
|
220
|
-
function parseAsNumericCss(str) {
|
|
221
|
-
const parts = str.match(numericCSSRegex);
|
|
222
|
-
if (!parts) {
|
|
223
|
-
throw new Error(`Provided value ${str} cannot be parsed as a numeric CSS value`);
|
|
224
|
-
}
|
|
225
|
-
if (parts.length < 3) {
|
|
226
|
-
throw new Error(`${parts[0]} is not a correct numeric CSS value`);
|
|
227
|
-
}
|
|
228
|
-
const value = parseFloat(parts[1]);
|
|
229
|
-
if (isNaN(value)) {
|
|
230
|
-
throw new Error(`${value} is not a valid number in ${str}`);
|
|
231
|
-
}
|
|
232
|
-
const unit = parts[2];
|
|
233
|
-
if (!isCSSUnit(unit)) {
|
|
234
|
-
throw new Error(`${unit} is not have a valid CSS unit in ${str}`);
|
|
235
|
-
}
|
|
236
|
-
const result = { value, unit };
|
|
237
|
-
return result;
|
|
238
|
-
}
|
|
239
|
-
function numericCSSToString(cssValue) {
|
|
240
|
-
return `${cssValue.value}${cssValue.unit}`;
|
|
241
|
-
}
|
|
242
|
-
function parseAsCSSColor(str) {
|
|
243
|
-
return chroma(str);
|
|
244
|
-
}
|
|
245
|
-
const CSSUnitValues = [
|
|
246
|
-
"px",
|
|
247
|
-
"em",
|
|
248
|
-
"rem",
|
|
249
|
-
"vh",
|
|
250
|
-
"vw",
|
|
251
|
-
"%",
|
|
252
|
-
"cm",
|
|
253
|
-
"mm",
|
|
254
|
-
"in",
|
|
255
|
-
"pt",
|
|
256
|
-
"pc",
|
|
257
|
-
"ex",
|
|
258
|
-
"ch",
|
|
259
|
-
"vmin",
|
|
260
|
-
"vmax"
|
|
261
|
-
];
|
|
262
|
-
function isCSSUnit(str) {
|
|
263
|
-
return CSSUnitValues.includes(str);
|
|
264
|
-
}
|
|
265
|
-
const CSSBorderStyleValues = [
|
|
266
|
-
"solid",
|
|
267
|
-
"dotted",
|
|
268
|
-
"dashed",
|
|
269
|
-
"double",
|
|
270
|
-
"none",
|
|
271
|
-
"hidden",
|
|
272
|
-
"groove",
|
|
273
|
-
"ridge",
|
|
274
|
-
"inset",
|
|
275
|
-
"outset"
|
|
276
|
-
];
|
|
277
|
-
function isCSSBorderStyle(str) {
|
|
278
|
-
return CSSBorderStyleValues.includes(str);
|
|
279
|
-
}
|
|
280
|
-
function parseAsCSSBorderStyle(str) {
|
|
281
|
-
if (!isCSSBorderStyle(str)) {
|
|
282
|
-
throw new Error(`Provided value ${str} cannot be parsed as a CSS border style`);
|
|
283
|
-
}
|
|
284
|
-
return str;
|
|
285
|
-
}
|
|
286
|
-
const BorderSideValues = ["top", "bottom", "left", "right"];
|
|
287
|
-
function isBorderSide(str) {
|
|
288
|
-
return BorderSideValues.includes(str);
|
|
289
|
-
}
|
|
290
27
|
class ComponentDriver {
|
|
291
28
|
constructor({ locator, page }) {
|
|
292
29
|
this.click = async (options) => {
|
|
@@ -1023,7 +760,7 @@ class CodeBlockDriver extends ComponentDriver {
|
|
|
1023
760
|
class CheckboxDriver extends InputComponentDriver {
|
|
1024
761
|
async getIndicatorColor() {
|
|
1025
762
|
const specifier = this.component.getByRole("checkbox").or(this.component).last();
|
|
1026
|
-
const { boxShadow } = await
|
|
763
|
+
const { boxShadow } = await getStyles(specifier, "box-shadow", "::before");
|
|
1027
764
|
const colorMatch = boxShadow.match(/(rgba?\([^)]+\)|hsla?\([^)]+\)|#[a-fA-F0-9]{3,8})/);
|
|
1028
765
|
return colorMatch ? colorMatch[1] : null;
|
|
1029
766
|
}
|
|
@@ -1485,307 +1222,6 @@ Received: ${this.utils.printReceived(provided)}`;
|
|
|
1485
1222
|
expected,
|
|
1486
1223
|
actual: void 0
|
|
1487
1224
|
};
|
|
1488
|
-
},
|
|
1489
|
-
// ---
|
|
1490
|
-
// --- NOTE: Assertations below this line are experimental and are reserved for future test cases (ex. comparison tests)
|
|
1491
|
-
// ---
|
|
1492
|
-
/**
|
|
1493
|
-
* Asserts whether a component has the correct CSS `border-color` styling.
|
|
1494
|
-
*
|
|
1495
|
-
* @param expected Expected CSS color
|
|
1496
|
-
* @param border Border side(s), Default: **"all"**
|
|
1497
|
-
*
|
|
1498
|
-
* ---
|
|
1499
|
-
* **Usage**
|
|
1500
|
-
*
|
|
1501
|
-
* ```js
|
|
1502
|
-
* await initTestBed(`<Button label="hello" />`, {
|
|
1503
|
-
* testThemeVars: { "borderLeftColor-Button": "rgb(0, 0, 0)" },
|
|
1504
|
-
* });
|
|
1505
|
-
* const driver = await createButtonDriver();
|
|
1506
|
-
* await expect(driver.component).toHaveBorderColor("rgb(0, 0, 0)", "left");
|
|
1507
|
-
* ```
|
|
1508
|
-
*/
|
|
1509
|
-
async toHaveBorderColor(locator, expected, border = "all") {
|
|
1510
|
-
const assertionName = "toHaveBorder";
|
|
1511
|
-
let expectedBorderColor;
|
|
1512
|
-
try {
|
|
1513
|
-
expectedBorderColor = parseAsCSSColor(expected);
|
|
1514
|
-
if (Object.values(expectedBorderColor).length === 0) {
|
|
1515
|
-
throw new Error("Empty color!");
|
|
1516
|
-
}
|
|
1517
|
-
} catch (e) {
|
|
1518
|
-
return {
|
|
1519
|
-
message: () => "In " + this.utils.matcherHint(assertionName, locator, expected, { isNot: this.isNot }) + ":\n" + (e instanceof Error ? e.message : String(e)) + `
|
|
1520
|
-
|
|
1521
|
-
Expected: Correct CSS border color to expect (e.g. "red", "rgb(0, 0, 0)", "#AA0011")
|
|
1522
|
-
Received: ${this.utils.printReceived(expected)}`,
|
|
1523
|
-
pass: false,
|
|
1524
|
-
name: assertionName,
|
|
1525
|
-
expected,
|
|
1526
|
-
actual: void 0
|
|
1527
|
-
};
|
|
1528
|
-
}
|
|
1529
|
-
let _border = [];
|
|
1530
|
-
if (typeof border === "string") {
|
|
1531
|
-
if (border === "all") {
|
|
1532
|
-
_border = ["top", "bottom", "left", "right"];
|
|
1533
|
-
} else {
|
|
1534
|
-
_border = [border];
|
|
1535
|
-
}
|
|
1536
|
-
} else {
|
|
1537
|
-
_border = Array.from(new Set(border)).filter(isBorderSide);
|
|
1538
|
-
}
|
|
1539
|
-
let pass = true;
|
|
1540
|
-
let matcherResult;
|
|
1541
|
-
const colorStr = `rgb(${expectedBorderColor.rgb().join(", ")})`;
|
|
1542
|
-
try {
|
|
1543
|
-
for (let b of _border) {
|
|
1544
|
-
await expect$1(locator).toHaveCSS(`border-${b}-color`, colorStr);
|
|
1545
|
-
}
|
|
1546
|
-
} catch (e) {
|
|
1547
|
-
matcherResult = e.matcherResult;
|
|
1548
|
-
pass = false;
|
|
1549
|
-
}
|
|
1550
|
-
const message = pass ? () => this.utils.matcherHint(assertionName, void 0, void 0, { isNot: this.isNot }) + `
|
|
1551
|
-
|
|
1552
|
-
Expected: not ${this.utils.printExpected(expected)}
|
|
1553
|
-
` + (matcherResult ? `Received: ${this.utils.printReceived(matcherResult.actual)}` : "") : () => this.utils.matcherHint(assertionName, void 0, void 0, { isNot: this.isNot }) + `
|
|
1554
|
-
|
|
1555
|
-
Expected: ${this.utils.printExpected(expected)}
|
|
1556
|
-
` + (matcherResult ? `Received: ${this.utils.printReceived(matcherResult.actual)}` : "");
|
|
1557
|
-
return {
|
|
1558
|
-
message,
|
|
1559
|
-
pass,
|
|
1560
|
-
name: assertionName,
|
|
1561
|
-
expected,
|
|
1562
|
-
actual: matcherResult?.actual
|
|
1563
|
-
};
|
|
1564
|
-
},
|
|
1565
|
-
/**
|
|
1566
|
-
* Asserts whether a component has the correct CSS `border-width` styling.
|
|
1567
|
-
*
|
|
1568
|
-
* @param expected Expected CSS size
|
|
1569
|
-
* @param border Border side(s), Default: **"all"**
|
|
1570
|
-
*
|
|
1571
|
-
* ---
|
|
1572
|
-
* **Usage**
|
|
1573
|
-
*
|
|
1574
|
-
* ```js
|
|
1575
|
-
* await initTestBed(`<Button label="hello" />`, {
|
|
1576
|
-
* testThemeVars: { "borderLeftWidth-Button": "12px" },
|
|
1577
|
-
* });
|
|
1578
|
-
* const driver = await createButtonDriver();
|
|
1579
|
-
* await expect(driver.component).toHaveBorderWidth("12px", "left");
|
|
1580
|
-
* ```
|
|
1581
|
-
*/
|
|
1582
|
-
async toHaveBorderWidth(locator, expected, border = "all") {
|
|
1583
|
-
const assertionName = "toHaveBorder";
|
|
1584
|
-
let expectedBorderWidth;
|
|
1585
|
-
try {
|
|
1586
|
-
expectedBorderWidth = parseAsNumericCss(expected);
|
|
1587
|
-
if (Object.values(expectedBorderWidth).length === 0) {
|
|
1588
|
-
throw new Error("Empty width!");
|
|
1589
|
-
}
|
|
1590
|
-
} catch (e) {
|
|
1591
|
-
return {
|
|
1592
|
-
message: () => "In " + this.utils.matcherHint(assertionName, locator, expected, { isNot: this.isNot }) + ":\n" + (e instanceof Error ? e.message : String(e)) + `
|
|
1593
|
-
|
|
1594
|
-
Expected: Correct CSS border width to expect (e.g. "1px", "2rem")
|
|
1595
|
-
Received: ${this.utils.printReceived(expected)}`,
|
|
1596
|
-
pass: false,
|
|
1597
|
-
name: assertionName,
|
|
1598
|
-
expected,
|
|
1599
|
-
actual: void 0
|
|
1600
|
-
};
|
|
1601
|
-
}
|
|
1602
|
-
let _border = [];
|
|
1603
|
-
if (typeof border === "string") {
|
|
1604
|
-
if (border === "all") {
|
|
1605
|
-
_border = ["top", "bottom", "left", "right"];
|
|
1606
|
-
} else {
|
|
1607
|
-
_border = [border];
|
|
1608
|
-
}
|
|
1609
|
-
} else {
|
|
1610
|
-
_border = Array.from(new Set(border)).filter(isBorderSide);
|
|
1611
|
-
}
|
|
1612
|
-
let pass = true;
|
|
1613
|
-
let matcherResult;
|
|
1614
|
-
const widthStr = numericCSSToString(expectedBorderWidth);
|
|
1615
|
-
try {
|
|
1616
|
-
for (let b of _border) {
|
|
1617
|
-
await expect$1(locator).toHaveCSS(`border-${b}-width`, widthStr);
|
|
1618
|
-
}
|
|
1619
|
-
} catch (e) {
|
|
1620
|
-
matcherResult = e.matcherResult;
|
|
1621
|
-
pass = false;
|
|
1622
|
-
}
|
|
1623
|
-
const message = pass ? () => this.utils.matcherHint(assertionName, void 0, void 0, { isNot: this.isNot }) + `
|
|
1624
|
-
|
|
1625
|
-
Expected: not ${this.utils.printExpected(expected)}
|
|
1626
|
-
` + (matcherResult ? `Received: ${this.utils.printReceived(matcherResult.actual)}` : "") : () => this.utils.matcherHint(assertionName, void 0, void 0, { isNot: this.isNot }) + `
|
|
1627
|
-
|
|
1628
|
-
Expected: ${this.utils.printExpected(expected)}
|
|
1629
|
-
` + (matcherResult ? `Received: ${this.utils.printReceived(matcherResult.actual)}` : "");
|
|
1630
|
-
return {
|
|
1631
|
-
message,
|
|
1632
|
-
pass,
|
|
1633
|
-
name: assertionName,
|
|
1634
|
-
expected,
|
|
1635
|
-
actual: matcherResult?.actual
|
|
1636
|
-
};
|
|
1637
|
-
},
|
|
1638
|
-
/**
|
|
1639
|
-
* Asserts whether a component has the correct CSS `border-style` styling.
|
|
1640
|
-
*
|
|
1641
|
-
* @param expected Expected CSS border style
|
|
1642
|
-
* @param border Border side(s), default: **"all"**
|
|
1643
|
-
*
|
|
1644
|
-
* ---
|
|
1645
|
-
* **Usage**
|
|
1646
|
-
*
|
|
1647
|
-
* ```js
|
|
1648
|
-
* await initTestBed(`<Button label="hello" />`, {
|
|
1649
|
-
* testThemeVars: { "borderLeftStyle-Button": "dotted" },
|
|
1650
|
-
* });
|
|
1651
|
-
* const driver = await createButtonDriver();
|
|
1652
|
-
* await expect(driver.component).toHaveBorderStyle("dotted", "left");
|
|
1653
|
-
* ```
|
|
1654
|
-
*/
|
|
1655
|
-
async toHaveBorderStyle(locator, expected, border = "all") {
|
|
1656
|
-
const assertionName = "toHaveBorder";
|
|
1657
|
-
let expectedBorderStyle;
|
|
1658
|
-
try {
|
|
1659
|
-
expectedBorderStyle = parseAsCSSBorderStyle(expected);
|
|
1660
|
-
if (Object.values(expectedBorderStyle).length === 0) {
|
|
1661
|
-
throw new Error("Empty border style!");
|
|
1662
|
-
}
|
|
1663
|
-
} catch (e) {
|
|
1664
|
-
return {
|
|
1665
|
-
message: () => "In " + this.utils.matcherHint(assertionName, locator, expected, { isNot: this.isNot }) + ":\n" + (e instanceof Error ? e.message : String(e)) + `
|
|
1666
|
-
|
|
1667
|
-
Expected: Correct CSS border style to expect (e.g. "1px solid black")
|
|
1668
|
-
Received: ${this.utils.printReceived(expected)}`,
|
|
1669
|
-
pass: false,
|
|
1670
|
-
name: assertionName,
|
|
1671
|
-
expected,
|
|
1672
|
-
actual: void 0
|
|
1673
|
-
};
|
|
1674
|
-
}
|
|
1675
|
-
let _border = [];
|
|
1676
|
-
if (typeof border === "string") {
|
|
1677
|
-
if (border === "all") {
|
|
1678
|
-
_border = ["top", "bottom", "left", "right"];
|
|
1679
|
-
} else {
|
|
1680
|
-
_border = [border];
|
|
1681
|
-
}
|
|
1682
|
-
} else {
|
|
1683
|
-
_border = Array.from(new Set(border)).filter(isBorderSide);
|
|
1684
|
-
}
|
|
1685
|
-
let pass = true;
|
|
1686
|
-
let matcherResult;
|
|
1687
|
-
try {
|
|
1688
|
-
for (let b of _border) {
|
|
1689
|
-
await expect$1(locator).toHaveCSS(`border-${b}-style`, expectedBorderStyle);
|
|
1690
|
-
}
|
|
1691
|
-
} catch (e) {
|
|
1692
|
-
matcherResult = e.matcherResult;
|
|
1693
|
-
pass = false;
|
|
1694
|
-
}
|
|
1695
|
-
const message = pass ? () => this.utils.matcherHint(assertionName, void 0, void 0, { isNot: this.isNot }) + `
|
|
1696
|
-
|
|
1697
|
-
Expected: not ${this.utils.printExpected(expected)}
|
|
1698
|
-
` + (matcherResult ? `Received: ${this.utils.printReceived(matcherResult.actual)}` : "") : () => this.utils.matcherHint(assertionName, void 0, void 0, { isNot: this.isNot }) + `
|
|
1699
|
-
|
|
1700
|
-
Expected: ${this.utils.printExpected(expected)}
|
|
1701
|
-
` + (matcherResult ? `Received: ${this.utils.printReceived(matcherResult.actual)}` : "");
|
|
1702
|
-
return {
|
|
1703
|
-
message,
|
|
1704
|
-
pass,
|
|
1705
|
-
name: assertionName,
|
|
1706
|
-
expected,
|
|
1707
|
-
actual: matcherResult?.actual
|
|
1708
|
-
};
|
|
1709
|
-
},
|
|
1710
|
-
/**
|
|
1711
|
-
* Asserts whether a component has the correct CSS `border` shorthand set:
|
|
1712
|
-
* `color`, `width`, `style`.
|
|
1713
|
-
*
|
|
1714
|
-
* @param expected Expected string label
|
|
1715
|
-
* @param border Border side(s), Default: **"all"**
|
|
1716
|
-
*
|
|
1717
|
-
* ---
|
|
1718
|
-
* **Usage**
|
|
1719
|
-
*
|
|
1720
|
-
* ```js
|
|
1721
|
-
* await initTestBed(`<Button label="hello" />`, {
|
|
1722
|
-
* testThemeVars: { "borderLeft-Button": "1px solid black" },
|
|
1723
|
-
* });
|
|
1724
|
-
* const driver = await createButtonDriver();
|
|
1725
|
-
* await expect(driver.component).toHaveBorder("1px solid black", "left");
|
|
1726
|
-
* ```
|
|
1727
|
-
*/
|
|
1728
|
-
async toHaveBorder(locator, expected, border = "all") {
|
|
1729
|
-
const assertionName = "toHaveBorder";
|
|
1730
|
-
let expectedBorder;
|
|
1731
|
-
try {
|
|
1732
|
-
expectedBorder = parseAsCssBorder(expected);
|
|
1733
|
-
if (Object.values(expectedBorder).length === 0) {
|
|
1734
|
-
throw new Error("Empty style!");
|
|
1735
|
-
}
|
|
1736
|
-
} catch (e) {
|
|
1737
|
-
return {
|
|
1738
|
-
message: () => "In " + this.utils.matcherHint(assertionName, locator, expected, { isNot: this.isNot }) + ":\n" + (e instanceof Error ? e.message : String(e)) + `
|
|
1739
|
-
|
|
1740
|
-
Expected: Correct CSS border style to expect (e.g. "1px solid black")
|
|
1741
|
-
Received: ${this.utils.printReceived(expected)}`,
|
|
1742
|
-
pass: false,
|
|
1743
|
-
name: assertionName,
|
|
1744
|
-
expected,
|
|
1745
|
-
actual: void 0
|
|
1746
|
-
};
|
|
1747
|
-
}
|
|
1748
|
-
let _border = [];
|
|
1749
|
-
if (typeof border === "string") {
|
|
1750
|
-
if (border === "all") {
|
|
1751
|
-
_border = ["top", "bottom", "left", "right"];
|
|
1752
|
-
} else {
|
|
1753
|
-
_border = [border];
|
|
1754
|
-
}
|
|
1755
|
-
} else {
|
|
1756
|
-
_border = Array.from(new Set(border)).filter(isBorderSide);
|
|
1757
|
-
}
|
|
1758
|
-
let pass = true;
|
|
1759
|
-
let matcherResult;
|
|
1760
|
-
try {
|
|
1761
|
-
if (expectedBorder?.color) {
|
|
1762
|
-
const colorStr = `rgb(${expectedBorder.color.rgb().join(", ")})`;
|
|
1763
|
-
await expect(locator).toHaveBorderColor(colorStr, _border);
|
|
1764
|
-
}
|
|
1765
|
-
if (expectedBorder?.width) {
|
|
1766
|
-
await expect(locator).toHaveBorderWidth(numericCSSToString(expectedBorder.width), _border);
|
|
1767
|
-
}
|
|
1768
|
-
if (expectedBorder?.style) {
|
|
1769
|
-
await expect(locator).toHaveBorderStyle(expectedBorder.style, _border);
|
|
1770
|
-
}
|
|
1771
|
-
} catch (e) {
|
|
1772
|
-
matcherResult = e.matcherResult;
|
|
1773
|
-
pass = false;
|
|
1774
|
-
}
|
|
1775
|
-
const message = pass ? () => this.utils.matcherHint(assertionName, void 0, void 0, { isNot: this.isNot }) + `
|
|
1776
|
-
|
|
1777
|
-
Expected: not ${this.utils.printExpected(expected)}
|
|
1778
|
-
` + (matcherResult ? `Received: ${this.utils.printReceived(matcherResult.actual)}` : "") : () => this.utils.matcherHint(assertionName, void 0, void 0, { isNot: this.isNot }) + `
|
|
1779
|
-
|
|
1780
|
-
Expected: ${this.utils.printExpected(expected)}
|
|
1781
|
-
` + (matcherResult ? `Received: ${this.utils.printReceived(matcherResult.actual)}` : "");
|
|
1782
|
-
return {
|
|
1783
|
-
message,
|
|
1784
|
-
pass,
|
|
1785
|
-
name: assertionName,
|
|
1786
|
-
expected,
|
|
1787
|
-
actual: matcherResult?.actual
|
|
1788
|
-
};
|
|
1789
1225
|
}
|
|
1790
1226
|
});
|
|
1791
1227
|
const isCI = process?.env?.CI === "true";
|
|
@@ -2243,141 +1679,7 @@ const test = test$1.extend({
|
|
|
2243
1679
|
});
|
|
2244
1680
|
}
|
|
2245
1681
|
});
|
|
2246
|
-
function parseComponent(entryPoint) {
|
|
2247
|
-
if (typeof entryPoint === "string") {
|
|
2248
|
-
return xmlUiMarkupToComponent(entryPoint).component;
|
|
2249
|
-
}
|
|
2250
|
-
return entryPoint;
|
|
2251
|
-
}
|
|
2252
|
-
async function initApp(page, appDescription, url = "/", resources = {}) {
|
|
2253
|
-
const { entryPoint, components } = appDescription;
|
|
2254
|
-
const _appDescription = {
|
|
2255
|
-
...appDescription,
|
|
2256
|
-
name: appDescription.name || "Test App",
|
|
2257
|
-
entryPoint: parseComponent(entryPoint),
|
|
2258
|
-
resources,
|
|
2259
|
-
components: !components ? void 0 : Array.isArray(components) ? components.map((comp) => parseComponent(comp)) : [parseComponent(components)]
|
|
2260
|
-
};
|
|
2261
|
-
await page.addInitScript((app) => {
|
|
2262
|
-
window.TEST_ENV = app;
|
|
2263
|
-
}, _appDescription);
|
|
2264
|
-
await page.goto(url);
|
|
2265
|
-
}
|
|
2266
|
-
async function prepPage(co, appDesc, url = "/") {
|
|
2267
|
-
const context = co;
|
|
2268
|
-
const page = await context.newPage();
|
|
2269
|
-
await initApp(page, appDesc, url);
|
|
2270
|
-
return page;
|
|
2271
|
-
}
|
|
2272
|
-
async function initThemedApp(page, entryPoint, theme) {
|
|
2273
|
-
theme.id ?? (theme.id = "testTheme");
|
|
2274
|
-
theme.name ?? (theme.name = "Custom Test theme");
|
|
2275
|
-
await initApp(page, { entryPoint, defaultTheme: theme.id, themes: [theme] });
|
|
2276
|
-
}
|
|
2277
|
-
function scalePercentBy(scalarOf100Percent, percentage) {
|
|
2278
|
-
if (!percentage.endsWith("%")) {
|
|
2279
|
-
throw new Error("argument doesn't end with % sign");
|
|
2280
|
-
}
|
|
2281
|
-
const percentageNum = Number(percentage.slice(0, -1));
|
|
2282
|
-
return scalarOf100Percent / 100 * percentageNum;
|
|
2283
|
-
}
|
|
2284
|
-
function getBoundingRect(locator) {
|
|
2285
|
-
return locator.evaluate((element) => element.getBoundingClientRect());
|
|
2286
|
-
}
|
|
2287
|
-
async function getFullRectangle(locator) {
|
|
2288
|
-
const boundingRect = await locator.evaluate((element) => element.getBoundingClientRect());
|
|
2289
|
-
const margins = await getElementStyles(locator, [
|
|
2290
|
-
"margin-left",
|
|
2291
|
-
"margin-right",
|
|
2292
|
-
"margin-top",
|
|
2293
|
-
"margin-bottom"
|
|
2294
|
-
]);
|
|
2295
|
-
const marginLeft = parseFloat(margins["margin-left"]);
|
|
2296
|
-
const marginRight = parseFloat(margins["margin-right"]);
|
|
2297
|
-
const marginTop = parseFloat(margins["margin-top"]);
|
|
2298
|
-
const marginBottom = parseFloat(margins["margin-bottom"]);
|
|
2299
|
-
const width = boundingRect.width + marginLeft + marginRight;
|
|
2300
|
-
const height = boundingRect.height + marginTop + marginBottom;
|
|
2301
|
-
const left = boundingRect.left - marginLeft;
|
|
2302
|
-
const right = boundingRect.right + marginRight;
|
|
2303
|
-
const top = boundingRect.top - marginTop;
|
|
2304
|
-
const bottom = boundingRect.bottom + marginBottom;
|
|
2305
|
-
return { width, height, left, right, top, bottom };
|
|
2306
|
-
}
|
|
2307
|
-
async function isElementOverflown(locator, direction = "both") {
|
|
2308
|
-
const [width, height, scrollWidth, scrollHeight] = await locator.evaluate((element) => [
|
|
2309
|
-
element.clientWidth,
|
|
2310
|
-
element.clientHeight,
|
|
2311
|
-
element.scrollWidth,
|
|
2312
|
-
element.scrollHeight
|
|
2313
|
-
]);
|
|
2314
|
-
if (direction === "x") return scrollWidth > width;
|
|
2315
|
-
if (direction === "y") return scrollHeight > height;
|
|
2316
|
-
return scrollWidth > width && scrollHeight > height;
|
|
2317
|
-
}
|
|
2318
|
-
function pixelStrToNum(pixelStr) {
|
|
2319
|
-
return Number(pixelStr.replace("px", ""));
|
|
2320
|
-
}
|
|
2321
|
-
function getElementStyle(locator, style) {
|
|
2322
|
-
return locator.evaluate(
|
|
2323
|
-
(element, style2) => window.getComputedStyle(element).getPropertyValue(style2),
|
|
2324
|
-
style
|
|
2325
|
-
);
|
|
2326
|
-
}
|
|
2327
|
-
function getElementStyles(locator, styles = []) {
|
|
2328
|
-
return locator.evaluate(
|
|
2329
|
-
(element, styles2) => Object.fromEntries(
|
|
2330
|
-
styles2.map((styleName) => [
|
|
2331
|
-
styleName,
|
|
2332
|
-
window.getComputedStyle(element).getPropertyValue(styleName)
|
|
2333
|
-
])
|
|
2334
|
-
),
|
|
2335
|
-
styles
|
|
2336
|
-
);
|
|
2337
|
-
}
|
|
2338
|
-
async function getStyle(page, testId, style) {
|
|
2339
|
-
const locator = page.getByTestId(testId);
|
|
2340
|
-
return await getElementStyle(locator, style);
|
|
2341
|
-
}
|
|
2342
1682
|
export {
|
|
2343
|
-
ComponentDriver,
|
|
2344
|
-
DateInputDriver,
|
|
2345
|
-
SKIP_REASON,
|
|
2346
|
-
TimeInputDriver,
|
|
2347
|
-
TimerDriver,
|
|
2348
1683
|
expect,
|
|
2349
|
-
|
|
2350
|
-
getBoundingRect$1 as getBoundingRect,
|
|
2351
|
-
getBounds,
|
|
2352
|
-
getComponentTagName,
|
|
2353
|
-
getElementStyle$1 as getElementStyle,
|
|
2354
|
-
getElementStyles$1 as getElementStyles,
|
|
2355
|
-
getFullRectangle,
|
|
2356
|
-
getHtmlAttributes,
|
|
2357
|
-
getMargins,
|
|
2358
|
-
getPaddings,
|
|
2359
|
-
getPseudoStyles,
|
|
2360
|
-
getStyles,
|
|
2361
|
-
getBoundingRect as getThemedBoundingRect,
|
|
2362
|
-
getElementStyle as getThemedElementStyle,
|
|
2363
|
-
getElementStyles as getThemedElementStyles,
|
|
2364
|
-
getStyle as getThemedStyle,
|
|
2365
|
-
initApp,
|
|
2366
|
-
initThemedApp,
|
|
2367
|
-
isIndeterminate,
|
|
2368
|
-
mapObject,
|
|
2369
|
-
numericCSSToString,
|
|
2370
|
-
overflows,
|
|
2371
|
-
parseAsCSSBorderStyle,
|
|
2372
|
-
parseAsCSSColor,
|
|
2373
|
-
parseAsCssBorder,
|
|
2374
|
-
parseAsNumericCss,
|
|
2375
|
-
parseComponentIfNecessary,
|
|
2376
|
-
pixelStrToNum$1 as pixelStrToNum,
|
|
2377
|
-
prepPage,
|
|
2378
|
-
scaleByPercent,
|
|
2379
|
-
scalePercentBy,
|
|
2380
|
-
test,
|
|
2381
|
-
isElementOverflown as themedOverflows,
|
|
2382
|
-
pixelStrToNum as themedPixelStrToNum
|
|
1684
|
+
test
|
|
2383
1685
|
};
|