playwright-ui5 1.3.1 → 1.4.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/README.md CHANGED
@@ -28,12 +28,13 @@ test('ui5 example', ({ page }) => {
28
28
 
29
29
  this selector engine uses css selector-like syntax. the main difference is that `.` is not used for class names, rather they are treated as part of the type name (ie. `sap.m.Button`)
30
30
 
31
- | feature | examples | suported | notes |
32
- | ------------------- | ------------------------------------------------------- | -------- | ------------------------------------------------------------------------------------------------- |
31
+ | feature | examples | suported | notes |
32
+ | ------------------- | ------------------------------------------------------- | -------- | ----------------------------------------------------------------------------------------------------------------------------------------- |
33
33
  | type selectors | `sap.m.Button`, `m.Button`, `*` | ✔ |
34
- | class selectors | n/a | n/a | as mentioned above, `.` is treated as part of the control type |
35
- | attribute selectors | `[text]`, `[text='foo']`,`[text*='foo']` | ✔ | some equality mods are useless for ui5 (eg. `\|=`) but are supported for the sake of completeness |
36
- | id selectors | `sap.m.Button#foo` | ✔ | you should not use id selectors if the id is generated (eg. `__button1`) as they can change often |
37
- | nesting | `sap.m.Table sap.m.Button`,`sap.m.Table > sap.m.Button` | ❌ | use playwright selector nesting instead (`ui5=sap.m.Table >> ui5=sap.m.Button`) |
38
- | pseudo-classes | `sap.m.Table:has(sap.m.Button)` | ✔ | only `:has` is supported for now |
34
+ | class selectors | n/a | n/a | as mentioned above, `.` is treated as part of the control type |
35
+ | attribute selectors | `[text]`, `[text='foo']`,`[text*='foo']` | ✔ | some equality mods are useless for ui5 (eg. `\|=`) but are supported for the sake of completeness |
36
+ | id selectors | `sap.m.Button#foo` | ✔ | you should not use id selectors if the id is generated (eg. `__button1`) as they can change often |
37
+ | nesting | `sap.m.Table sap.m.Button`,`sap.m.Table > sap.m.Button` | ❌ | use playwright selector nesting instead (`ui5=sap.m.Table >> ui5=sap.m.Button`) |
38
+ | pseudo-classes | `sap.m.Table:has(sap.m.Button)` | ✔ | only `:has` is supported for now |
39
+ | pseudo-elements | `sap.m.DateTimeField::subclass` | ✔ | `::subclass` will match the specified control type and any subtypes (eg. both `sap.m.DateTimeField` and subtypes like `sap.m.DatePicker`) |
39
40
  | selector lists | `sap.m.Button,sap.m.Table` | ✔ |
@@ -748,7 +748,7 @@ var require_parser = __commonJS({
748
748
  next();
749
749
  }
750
750
  }
751
- function parseSelector(relative) {
751
+ function parseSelector2(relative) {
752
752
  if (relative === void 0) {
753
753
  relative = false;
754
754
  }
@@ -933,7 +933,7 @@ var require_parser = __commonJS({
933
933
  };
934
934
  assert(pseudo.argument.value, "Expected pseudo-class argument value.");
935
935
  } else if (pseudoDefinition.type === "Selector") {
936
- pseudo.argument = parseSelector(true);
936
+ pseudo.argument = parseSelector2(true);
937
937
  } else if (pseudoDefinition.type === "Formula") {
938
938
  var _a2 = parseFormula(), a = _a2[0], b = _a2[1];
939
939
  pseudo.argument = {
@@ -1130,7 +1130,7 @@ var require_parser = __commonJS({
1130
1130
  l = str.length;
1131
1131
  pos = 0;
1132
1132
  chr = str.charAt(0);
1133
- return parseSelector();
1133
+ return parseSelector2();
1134
1134
  };
1135
1135
  }
1136
1136
  exports.createParser = createParser2;
@@ -1360,12 +1360,40 @@ __export(main_exports, {
1360
1360
  module.exports = __toCommonJS(main_exports);
1361
1361
  var import_css_selector_parser = __toESM(require_lib());
1362
1362
  var import_throw_expression = __toESM(require_throw_expression());
1363
+ var getAllParents = (element) => {
1364
+ const getParents = (class_) => {
1365
+ const parent = class_.getParent();
1366
+ if (parent !== void 0) {
1367
+ return [class_, ...getParents(parent)];
1368
+ }
1369
+ return [class_];
1370
+ };
1371
+ return getParents(element.getMetadata()).map((parent) => parent.getName());
1372
+ };
1373
+ var parseSelector = (selector) => {
1374
+ if (selector === "") {
1375
+ throw new Error("ui5 selector is empty");
1376
+ }
1377
+ const parsedSelector = parse(selector);
1378
+ parsedSelector.rules.forEach((rule) => {
1379
+ var _a;
1380
+ if (rule.ids && rule.ids.length > 1) {
1381
+ throw new Error("multiple ids are not supported");
1382
+ }
1383
+ if (rule.pseudoElement === "subclass" && ((_a = rule.tag) == null ? void 0 : _a.type) !== "TagName") {
1384
+ throw new Error(
1385
+ "subclass pseudo-selector cannot be used without specifying a control type"
1386
+ );
1387
+ }
1388
+ });
1389
+ return parsedSelector;
1390
+ };
1363
1391
  var parse = (0, import_css_selector_parser.createParser)({
1364
1392
  syntax: {
1365
1393
  combinators: [],
1366
1394
  namespace: false,
1367
1395
  attributes: { operators: ["=", "^=", "$=", "*=", "~=", "|="] },
1368
- pseudoElements: false,
1396
+ pseudoElements: { definitions: ["subclass"] },
1369
1397
  pseudoClasses: { definitions: { Selector: ["has"] } },
1370
1398
  tag: { wildcard: true },
1371
1399
  ids: true,
@@ -1384,10 +1412,7 @@ var querySelector = (root, selector) => selector.rules.flatMap((rule) => {
1384
1412
  }
1385
1413
  const controls = sap.ui.core.Element.registry.filter((element) => {
1386
1414
  var _a2, _b;
1387
- if (rule.ids && rule.ids.length > 1) {
1388
- throw new Error("multiple ids are not supported");
1389
- }
1390
- if (((_a2 = rule.tag) == null ? void 0 : _a2.type) === "TagName" && rule.tag.name !== element.getMetadata().getName() || rule.ids && rule.ids[0] !== element.getId()) {
1415
+ if (((_a2 = rule.tag) == null ? void 0 : _a2.type) === "TagName" && rule.tag.name !== element.getMetadata().getName() && (rule.pseudoElement !== "subclass" || !getAllParents(element).includes(rule.tag.name)) || rule.ids && rule.ids[0] !== element.getId()) {
1391
1416
  return false;
1392
1417
  }
1393
1418
  return ((_b = rule.attributes) != null ? _b : []).every((attr) => {
@@ -1432,10 +1457,7 @@ var querySelector = (root, selector) => selector.rules.flatMap((rule) => {
1432
1457
  });
1433
1458
  var queryAll = (root, selector) => {
1434
1459
  try {
1435
- const parsedSelector = parse(selector);
1436
- if (selector === "") {
1437
- throw new Error("ui5 selector is empty");
1438
- }
1460
+ const parsedSelector = parseSelector(selector);
1439
1461
  if (typeof sap === "undefined") {
1440
1462
  return [];
1441
1463
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "playwright-ui5",
3
- "version": "1.3.1",
3
+ "version": "1.4.0",
4
4
  "files": [
5
5
  "dist",
6
6
  "src/node"
@@ -30,7 +30,7 @@
30
30
  "devDependencies": {
31
31
  "@detachhead/eslint-config": "^1.2.0",
32
32
  "@detachhead/ts-helpers": "^16.1.0",
33
- "@playwright/test": "^1.35.0",
33
+ "@playwright/test": "^1.38.1",
34
34
  "@sapui5/ts-types": "^1.113.0",
35
35
  "@trivago/prettier-plugin-sort-imports": "^4.1.1",
36
36
  "@types/eslint": "^8.4.6",