@sapudex/web-components 2.40.0 → 2.42.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.
Files changed (163) hide show
  1. package/config/wdio.conf.cjs +18 -2
  2. package/cypress/specs/Dropdown.cy.tsx +90 -0
  3. package/cypress/specs/MessageStrip.cy.tsx +77 -0
  4. package/cypress/specs/PasswordField.cy.tsx +37 -0
  5. package/cypress/specs/Search.cy.tsx +244 -138
  6. package/cypress/specs/SelectBox.cy.tsx +184 -5
  7. package/cypress/support/component-imports.instrumented.ts +2 -0
  8. package/cypress/support/component-imports.src.ts +2 -0
  9. package/cypress.config.ts +10 -0
  10. package/dist/Dropdown.d.ts +5 -0
  11. package/dist/Dropdown.js +56 -0
  12. package/dist/Dropdown.js.map +1 -1
  13. package/dist/List.d.ts +1 -6
  14. package/dist/List.js +2 -10
  15. package/dist/List.js.map +1 -1
  16. package/dist/MastheadCountrySelector.d.ts +7 -0
  17. package/dist/MastheadCountrySelector.js +3 -0
  18. package/dist/MastheadCountrySelector.js.map +1 -1
  19. package/dist/MessageStrip.d.ts +25 -0
  20. package/dist/MessageStrip.js +16 -4
  21. package/dist/MessageStrip.js.map +1 -1
  22. package/dist/PasswordField.d.ts +10 -0
  23. package/dist/PasswordField.js +17 -2
  24. package/dist/PasswordField.js.map +1 -1
  25. package/dist/PasswordFieldTemplate.js +1 -1
  26. package/dist/PasswordFieldTemplate.js.map +1 -1
  27. package/dist/Search.d.ts +1 -1
  28. package/dist/Search.js +13 -9
  29. package/dist/Search.js.map +1 -1
  30. package/dist/SearchTemplate.js +3 -3
  31. package/dist/SearchTemplate.js.map +1 -1
  32. package/dist/SearchableListBase.d.ts +1 -6
  33. package/dist/SearchableListBase.js.map +1 -1
  34. package/dist/SearchableListBaseTemplate.js +1 -1
  35. package/dist/SearchableListBaseTemplate.js.map +1 -1
  36. package/dist/SelectBase.d.ts +7 -1
  37. package/dist/SelectBase.js +114 -17
  38. package/dist/SelectBase.js.map +1 -1
  39. package/dist/TextField.d.ts +1 -1
  40. package/dist/TextField.js +2 -2
  41. package/dist/TextField.js.map +1 -1
  42. package/dist/TextFieldTemplate.js +1 -1
  43. package/dist/TextFieldTemplate.js.map +1 -1
  44. package/dist/assets/{InputSuggestions-DAElWNvY.js → InputSuggestions-DVRXb_CJ.js} +1 -1
  45. package/dist/assets/{ListItemStandardExpandableTextTemplate-B2fGcGW7.js → ListItemStandardExpandableTextTemplate-DhmGlKzk.js} +1 -1
  46. package/dist/assets/{bundle.esm-DPVxY8xv.js → bundle.esm-CjF11YUZ.js} +233 -233
  47. package/dist/assets/messagebundle_en-BZqDcZHN.js +1 -0
  48. package/dist/assets/messagebundle_hu-CBV3ISbF.js +1 -0
  49. package/dist/assets/messagebundle_tr-DOeCmUdx.js +1 -0
  50. package/dist/assets/messagebundle_uk-GmdhsMsP.js +1 -0
  51. package/dist/assets/messagebundle_zh_CN-CHwH3F3-.js +1 -0
  52. package/dist/assets/messagebundle_zh_TW-FO0BCkub.js +1 -0
  53. package/dist/css/themes/MastheadCountrySelector.css +1 -1
  54. package/dist/css/themes/MastheadMenuItem.css +1 -1
  55. package/dist/css/themes/MastheadProfileMenu.css +1 -1
  56. package/dist/css/themes/StatusMessage.css +1 -1
  57. package/dist/css/themes/TextField.css +1 -1
  58. package/dist/css/themes/Toast.css +1 -1
  59. package/dist/css/themes/Wizard.css +1 -1
  60. package/dist/css/themes/WizardTab.css +1 -1
  61. package/dist/custom-elements-internal.json +114 -146
  62. package/dist/custom-elements.json +114 -114
  63. package/dist/features/SearchSuggestionsPopover.d.ts +6 -9
  64. package/dist/features/SearchSuggestionsPopover.js +47 -163
  65. package/dist/features/SearchSuggestionsPopover.js.map +1 -1
  66. package/dist/generated/assets/i18n/messagebundle_en.json +1 -1
  67. package/dist/generated/assets/i18n/messagebundle_hu.json +1 -1
  68. package/dist/generated/assets/i18n/messagebundle_tr.json +1 -1
  69. package/dist/generated/assets/i18n/messagebundle_uk.json +1 -1
  70. package/dist/generated/assets/i18n/messagebundle_zh_CN.json +1 -1
  71. package/dist/generated/assets/i18n/messagebundle_zh_TW.json +1 -1
  72. package/dist/generated/i18n/i18n-defaults.d.ts +3 -2
  73. package/dist/generated/i18n/i18n-defaults.js +3 -2
  74. package/dist/generated/i18n/i18n-defaults.js.map +1 -1
  75. package/dist/generated/templates/MastheadCountrySelectorTemplate.lit.js +6 -5
  76. package/dist/generated/templates/MastheadCountrySelectorTemplate.lit.js.map +1 -1
  77. package/dist/generated/templates/MastheadMobileMenuTemplate.lit.js +1 -1
  78. package/dist/generated/templates/MastheadMobileMenuTemplate.lit.js.map +1 -1
  79. package/dist/generated/themes/MastheadCountrySelector.css.d.ts +1 -1
  80. package/dist/generated/themes/MastheadCountrySelector.css.js +1 -1
  81. package/dist/generated/themes/MastheadCountrySelector.css.js.map +1 -1
  82. package/dist/generated/themes/MastheadMenuItem.css.d.ts +1 -1
  83. package/dist/generated/themes/MastheadMenuItem.css.js +1 -1
  84. package/dist/generated/themes/MastheadMenuItem.css.js.map +1 -1
  85. package/dist/generated/themes/MastheadProfileMenu.css.d.ts +1 -1
  86. package/dist/generated/themes/MastheadProfileMenu.css.js +1 -1
  87. package/dist/generated/themes/MastheadProfileMenu.css.js.map +1 -1
  88. package/dist/generated/themes/StatusMessage.css.d.ts +1 -1
  89. package/dist/generated/themes/StatusMessage.css.js +1 -1
  90. package/dist/generated/themes/StatusMessage.css.js.map +1 -1
  91. package/dist/generated/themes/TextField.css.d.ts +1 -1
  92. package/dist/generated/themes/TextField.css.js +1 -1
  93. package/dist/generated/themes/TextField.css.js.map +1 -1
  94. package/dist/generated/themes/Toast.css.d.ts +1 -1
  95. package/dist/generated/themes/Toast.css.js +1 -1
  96. package/dist/generated/themes/Toast.css.js.map +1 -1
  97. package/dist/generated/themes/Wizard.css.d.ts +1 -1
  98. package/dist/generated/themes/Wizard.css.js +1 -1
  99. package/dist/generated/themes/Wizard.css.js.map +1 -1
  100. package/dist/generated/themes/WizardTab.css.d.ts +1 -1
  101. package/dist/generated/themes/WizardTab.css.js +1 -1
  102. package/dist/generated/themes/WizardTab.css.js.map +1 -1
  103. package/dist/messagebundle.properties +2 -1
  104. package/dist/messagebundle_en.properties +2 -1
  105. package/dist/messagebundle_hu.properties +125 -0
  106. package/dist/messagebundle_tr.properties +126 -0
  107. package/dist/messagebundle_uk.properties +128 -0
  108. package/dist/messagebundle_zh_CN.properties +126 -0
  109. package/dist/messagebundle_zh_TW.properties +126 -0
  110. package/dist/utils/sanitizeString.js +1 -4
  111. package/dist/utils/sanitizeString.js.map +1 -1
  112. package/dist/vscode.html-custom-data.json +30 -25
  113. package/dist/web-types.json +61 -41
  114. package/package.json +2 -2
  115. package/src/Dropdown.ts +62 -0
  116. package/src/List.ts +3 -18
  117. package/src/MastheadCountrySelector.hbs +2 -0
  118. package/src/MastheadCountrySelector.ts +9 -0
  119. package/src/MastheadMobileMenu.hbs +1 -0
  120. package/src/MessageStrip.ts +37 -4
  121. package/src/PasswordField.ts +24 -0
  122. package/src/PasswordFieldTemplate.tsx +2 -2
  123. package/src/Search.ts +13 -9
  124. package/src/SearchTemplate.tsx +0 -3
  125. package/src/SearchableListBase.ts +1 -6
  126. package/src/SearchableListBaseTemplate.tsx +0 -1
  127. package/src/SelectBase.ts +114 -19
  128. package/src/TextField.ts +1 -1
  129. package/src/TextFieldTemplate.tsx +1 -1
  130. package/src/features/SearchSuggestionsPopover.ts +55 -177
  131. package/src/generated/i18n/i18n-defaults.ts +2 -2
  132. package/src/generated/templates/MastheadCountrySelectorTemplate.lit.ts +6 -5
  133. package/src/generated/templates/MastheadMobileMenuTemplate.lit.ts +1 -1
  134. package/src/generated/themes/MastheadCountrySelector.css.ts +1 -1
  135. package/src/generated/themes/MastheadMenuItem.css.ts +1 -1
  136. package/src/generated/themes/MastheadProfileMenu.css.ts +1 -1
  137. package/src/generated/themes/StatusMessage.css.ts +1 -1
  138. package/src/generated/themes/TextField.css.ts +1 -1
  139. package/src/generated/themes/Toast.css.ts +1 -1
  140. package/src/generated/themes/Wizard.css.ts +1 -1
  141. package/src/generated/themes/WizardTab.css.ts +1 -1
  142. package/src/i18n/messagebundle.properties +2 -1
  143. package/src/i18n/messagebundle_en.properties +2 -1
  144. package/src/i18n/messagebundle_hu.properties +125 -0
  145. package/src/i18n/messagebundle_tr.properties +126 -0
  146. package/src/i18n/messagebundle_uk.properties +128 -0
  147. package/src/i18n/messagebundle_zh_CN.properties +126 -0
  148. package/src/i18n/messagebundle_zh_TW.properties +126 -0
  149. package/src/themes/MastheadCountrySelector.css +5 -2
  150. package/src/themes/MastheadMenuItem.css +12 -4
  151. package/src/themes/MastheadProfileMenu.css +0 -5
  152. package/src/themes/StatusMessage.css +4 -4
  153. package/src/themes/TextField.css +3 -0
  154. package/src/themes/Toast.css +14 -2
  155. package/src/themes/Wizard.css +7 -0
  156. package/src/themes/WizardTab.css +23 -0
  157. package/src/utils/sanitizeString.ts +1 -4
  158. package/dist/assets/messagebundle_en-BxjFAY2S.js +0 -1
  159. package/dist/assets/messagebundle_hu-BEMbu-EE.js +0 -1
  160. package/dist/assets/messagebundle_tr-9FvYSV7d.js +0 -1
  161. package/dist/assets/messagebundle_uk-BgTRxken.js +0 -1
  162. package/dist/assets/messagebundle_zh_CN-BsCxQ-NE.js +0 -1
  163. package/dist/assets/messagebundle_zh_TW-Li9m-Dgo.js +0 -1
@@ -1,3 +1,19 @@
1
- const config = require("@ui5/webcomponents-tools/components-package/wdio.js");
1
+ const baseConfig = require("@ui5/webcomponents-tools/components-package/wdio.js");
2
+ const fs = require("fs");
2
3
 
3
- module.exports = config;
4
+ // When CHROMEDRIVER_SKIP_DOWNLOAD=true the npm package binary is not downloaded,
5
+ // so the wdio-chromedriver-service fallback resolves 'chromedriver' via PATH and
6
+ // finds node_modules/.bin/chromedriver (a Node wrapper) before /usr/local/bin.
7
+ // That wrapper then fails to find the binary and exits, so the port never binds.
8
+ // Explicitly point at the system binary installed by setup-node to bypass this.
9
+ const ciChromedriverPath = "/usr/local/bin/chromedriver";
10
+ if (fs.existsSync(ciChromedriverPath)) {
11
+ baseConfig.config.services = baseConfig.config.services.map((service) => {
12
+ if (service === "chromedriver") {
13
+ return ["chromedriver", { chromedriverCustomPath: ciChromedriverPath }];
14
+ }
15
+ return service;
16
+ });
17
+ }
18
+
19
+ module.exports = baseConfig;
@@ -0,0 +1,90 @@
1
+ import {
2
+ UDExDropdown,
3
+ UDExButton,
4
+ UDExList,
5
+ UDExListItem,
6
+ UDExSearch,
7
+ } from "../support/component-imports.js";
8
+
9
+ const dropdownFixture = (
10
+ <div style="position:relative; padding: 24px;">
11
+ <a id="prev-link" href="#">Previous focusable element</a>
12
+ {" "}
13
+ <UDExButton id="opener">Open dropdown</UDExButton>
14
+ {" "}
15
+ <a id="next-link" href="#">Next focusable element</a>
16
+ <UDExDropdown id="dropdown" opener="opener">
17
+ <div slot="header">
18
+ <UDExSearch id="dropdown-search"></UDExSearch>
19
+ </div>
20
+ <UDExList id="dropdown-list">
21
+ <UDExListItem id="item-1">List Item 1</UDExListItem>
22
+ <UDExListItem id="item-2">List Item 2</UDExListItem>
23
+ <UDExListItem id="item-3">List Item 3</UDExListItem>
24
+ </UDExList>
25
+ <div slot="footer">
26
+ <UDExButton id="footer-button" design="Tertiary">Apply</UDExButton>
27
+ </div>
28
+ </UDExDropdown>
29
+ </div>
30
+ );
31
+
32
+ const openDropdown = () => {
33
+ cy.get("#dropdown").then($el => {
34
+ ($el[0] as any).open = true;
35
+ });
36
+ cy.get("[udex-dropdown]").should("have.attr", "open");
37
+ };
38
+
39
+ describe("UDExDropdown", () => {
40
+ describe("Rendering", () => {
41
+ it("registers the udex-dropdown custom element", () => {
42
+ cy.mount(dropdownFixture);
43
+ cy.get("[udex-dropdown]").should("exist");
44
+ });
45
+ });
46
+
47
+ describe("Dropdown keyboard navigation", () => {
48
+ it("Shift+Tab from first focusable element closes dropdown and returns focus to opener", () => {
49
+ cy.mount(dropdownFixture);
50
+ openDropdown();
51
+
52
+ // Opening the dropdown auto-focuses the search input in the header.
53
+ // forwardToLast() (Shift+Tab from the first focusable element) calls
54
+ // closePopup() which resets focus back to the opener.
55
+ cy.realPress(["Shift", "Tab"]);
56
+
57
+ cy.get("[udex-dropdown]").should("not.have.attr", "open");
58
+ cy.get("#opener").should("be.focused");
59
+ });
60
+
61
+ it("Tab from last focusable element closes dropdown and moves focus past opener", () => {
62
+ cy.mount(dropdownFixture);
63
+ openDropdown();
64
+
65
+ // Directly focus the last-fe sentinel — this is exactly what the browser
66
+ // does when Tab is pressed from the last focusable element inside the
67
+ // popover. The sentinel's onFocusIn calls forwardToFirst(), which closes
68
+ // the dropdown and moves focus to the next element after the opener.
69
+ cy.get("[udex-dropdown]").shadow().find(".last-fe").then($el => {
70
+ $el[0].focus();
71
+ });
72
+
73
+ cy.get("[udex-dropdown]").should("not.have.attr", "open");
74
+ cy.get("#next-link").should("be.focused");
75
+ });
76
+
77
+ it("Tab navigates forward through focusable elements without closing the dropdown", () => {
78
+ cy.mount(dropdownFixture);
79
+ openDropdown();
80
+
81
+ // The search input is auto-focused on open. A single forward Tab should
82
+ // move focus to the next focusable element inside the popover (list /
83
+ // footer) — the dropdown should remain open because we have not yet
84
+ // crossed the last-fe sentinel.
85
+ cy.realPress("Tab");
86
+
87
+ cy.get("[udex-dropdown]").should("have.attr", "open");
88
+ });
89
+ });
90
+ });
@@ -0,0 +1,77 @@
1
+ import { UDExMessageStrip } from "../support/component-imports.js";
2
+ import { UDExMessageStripDesign, UDExMessageStripStatusType } from "../../src/types/MessageStrip.js";
3
+
4
+ describe("MessageStrip — custom status text", () => {
5
+ it("renders custom information status text", () => {
6
+ cy.mount(
7
+ <UDExMessageStrip
8
+ design={UDExMessageStripDesign.Information}
9
+ statusType={UDExMessageStripStatusType.Text}
10
+ statusInformationText="Custom Info"
11
+ >
12
+ Message
13
+ </UDExMessageStrip>
14
+ );
15
+ cy.get("[udex-message-strip]").shadow().find(".message-strip__text-status").should("have.text", "Custom Info:");
16
+ });
17
+
18
+ it("renders custom success status text", () => {
19
+ cy.mount(
20
+ <UDExMessageStrip
21
+ design={UDExMessageStripDesign.Positive}
22
+ statusType={UDExMessageStripStatusType.Text}
23
+ statusSuccessText="Custom Success"
24
+ >
25
+ Message
26
+ </UDExMessageStrip>
27
+ );
28
+ cy.get("[udex-message-strip]").shadow().find(".message-strip__text-status").should("have.text", "Custom Success:");
29
+ });
30
+
31
+ it("renders custom error status text", () => {
32
+ cy.mount(
33
+ <UDExMessageStrip
34
+ design={UDExMessageStripDesign.Negative}
35
+ statusType={UDExMessageStripStatusType.Text}
36
+ statusErrorText="Custom Error"
37
+ >
38
+ Message
39
+ </UDExMessageStrip>
40
+ );
41
+ cy.get("[udex-message-strip]").shadow().find(".message-strip__text-status").should("have.text", "Custom Error:");
42
+ });
43
+
44
+ it("renders custom warning status text", () => {
45
+ cy.mount(
46
+ <UDExMessageStrip
47
+ design={UDExMessageStripDesign.Warning}
48
+ statusType={UDExMessageStripStatusType.Text}
49
+ statusWarningText="Custom Warning"
50
+ >
51
+ Message
52
+ </UDExMessageStrip>
53
+ );
54
+ cy.get("[udex-message-strip]").shadow().find(".message-strip__text-status").should("have.text", "Custom Warning:");
55
+ });
56
+
57
+ it("falls back to default text when custom status text is not provided", () => {
58
+ cy.mount(
59
+ <UDExMessageStrip
60
+ design={UDExMessageStripDesign.Information}
61
+ statusType={UDExMessageStripStatusType.Text}
62
+ >
63
+ Message
64
+ </UDExMessageStrip>
65
+ );
66
+ cy.get("[udex-message-strip]").shadow().find(".message-strip__text-status").should("not.have.text", "Custom Info:");
67
+ });
68
+
69
+ it("does not render status text for Action design", () => {
70
+ cy.mount(
71
+ <UDExMessageStrip design={UDExMessageStripDesign.Action} statusType={UDExMessageStripStatusType.Text}>
72
+ Message
73
+ </UDExMessageStrip>
74
+ );
75
+ cy.get("[udex-message-strip]").shadow().find(".message-strip__text-status").should("not.exist");
76
+ });
77
+ });
@@ -237,6 +237,43 @@ describe("passwordVisible property", () => {
237
237
  });
238
238
  });
239
239
 
240
+ describe("activeButtonTooltip", () => {
241
+ const controlBtn = () =>
242
+ cy.get("[udex-password-field]")
243
+ .shadow().find("[udex-text-field]")
244
+ .shadow().find("[udex-control-button]");
245
+
246
+ it("uses showButtonTooltip when password is hidden", () => {
247
+ cy.mount(<UDExPasswordField show-button-enabled show-button-tooltip="Show it" hide-button-tooltip="Hide it"></UDExPasswordField>);
248
+ controlBtn().should("have.attr", "accessible-name", "Show it");
249
+ controlBtn().shadow().find("[data-sap-focus-ref]").should("have.attr", "title", "Show it");
250
+ });
251
+
252
+ it("uses hideButtonTooltip when password is visible", () => {
253
+ cy.mount(<UDExPasswordField show-button-enabled show-button-tooltip="Show it" hide-button-tooltip="Hide it"></UDExPasswordField>);
254
+ controlBtn().click();
255
+ controlBtn().should("have.attr", "accessible-name", "Hide it");
256
+ controlBtn().shadow().find("[data-sap-focus-ref]").should("have.attr", "title", "Hide it");
257
+ });
258
+
259
+ it("falls back to showButtonTooltip when hideButtonTooltip is not set", () => {
260
+ cy.mount(<UDExPasswordField show-button-enabled show-button-tooltip="Show it"></UDExPasswordField>);
261
+ controlBtn().click();
262
+ controlBtn().should("have.attr", "accessible-name", "Hide password");
263
+ });
264
+
265
+ it("falls back to i18n default 'Show password' when no tooltips are set and password is hidden", () => {
266
+ cy.mount(<UDExPasswordField show-button-enabled></UDExPasswordField>);
267
+ controlBtn().should("have.attr", "accessible-name", "Show password");
268
+ });
269
+
270
+ it("falls back to i18n default 'Hide password' when no tooltips are set and password is visible", () => {
271
+ cy.mount(<UDExPasswordField show-button-enabled></UDExPasswordField>);
272
+ controlBtn().click();
273
+ controlBtn().should("have.attr", "accessible-name", "Hide password");
274
+ });
275
+ });
276
+
240
277
  describe("Events", () => {
241
278
  it("fires input event on typing", () => {
242
279
  const inputHandler = cy.stub().as("inputHandler");