testing.mjs 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. import { ContentContainerComponentHarness, HarnessPredicate } from '@angular/cdk/testing';
  2. import { coerceBooleanProperty } from '@angular/cdk/coercion';
  3. /** Harness for interacting with a mat-menu in tests. */
  4. class MatMenuHarness extends ContentContainerComponentHarness {
  5. _documentRootLocator = this.documentRootLocatorFactory();
  6. /** The selector for the host element of a `MatMenu` instance. */
  7. static hostSelector = '.mat-mdc-menu-trigger';
  8. /**
  9. * Gets a `HarnessPredicate` that can be used to search for a menu with specific attributes.
  10. * @param options Options for filtering which menu instances are considered a match.
  11. * @return a `HarnessPredicate` configured with the given options.
  12. */
  13. static with(options = {}) {
  14. return new HarnessPredicate(this, options).addOption('triggerText', options.triggerText, (harness, text) => HarnessPredicate.stringMatches(harness.getTriggerText(), text));
  15. }
  16. /** Whether the menu is disabled. */
  17. async isDisabled() {
  18. const disabled = (await this.host()).getAttribute('disabled');
  19. return coerceBooleanProperty(await disabled);
  20. }
  21. /** Whether the menu is open. */
  22. async isOpen() {
  23. return !!(await this._getMenuPanel());
  24. }
  25. /** Gets the text of the menu's trigger element. */
  26. async getTriggerText() {
  27. return (await this.host()).text();
  28. }
  29. /** Focuses the menu. */
  30. async focus() {
  31. return (await this.host()).focus();
  32. }
  33. /** Blurs the menu. */
  34. async blur() {
  35. return (await this.host()).blur();
  36. }
  37. /** Whether the menu is focused. */
  38. async isFocused() {
  39. return (await this.host()).isFocused();
  40. }
  41. /** Opens the menu. */
  42. async open() {
  43. if (!(await this.isOpen())) {
  44. return (await this.host()).click();
  45. }
  46. }
  47. /** Closes the menu. */
  48. async close() {
  49. const panel = await this._getMenuPanel();
  50. if (panel) {
  51. return panel.click();
  52. }
  53. }
  54. /**
  55. * Gets a list of `MatMenuItemHarness` representing the items in the menu.
  56. * @param filters Optionally filters which menu items are included.
  57. */
  58. async getItems(filters) {
  59. const panelId = await this._getPanelId();
  60. if (panelId) {
  61. return this._documentRootLocator.locatorForAll(MatMenuItemHarness.with({
  62. ...(filters || {}),
  63. ancestor: `#${panelId}`,
  64. }))();
  65. }
  66. return [];
  67. }
  68. /**
  69. * Clicks an item in the menu, and optionally continues clicking items in subsequent sub-menus.
  70. * @param itemFilter A filter used to represent which item in the menu should be clicked. The
  71. * first matching menu item will be clicked.
  72. * @param subItemFilters A list of filters representing the items to click in any subsequent
  73. * sub-menus. The first item in the sub-menu matching the corresponding filter in
  74. * `subItemFilters` will be clicked.
  75. */
  76. async clickItem(itemFilter, ...subItemFilters) {
  77. await this.open();
  78. const items = await this.getItems(itemFilter);
  79. if (!items.length) {
  80. throw Error(`Could not find item matching ${JSON.stringify(itemFilter)}`);
  81. }
  82. if (!subItemFilters.length) {
  83. return await items[0].click();
  84. }
  85. const menu = await items[0].getSubmenu();
  86. if (!menu) {
  87. throw Error(`Item matching ${JSON.stringify(itemFilter)} does not have a submenu`);
  88. }
  89. return menu.clickItem(...subItemFilters);
  90. }
  91. async getRootHarnessLoader() {
  92. const panelId = await this._getPanelId();
  93. return this.documentRootLocatorFactory().harnessLoaderFor(`#${panelId}`);
  94. }
  95. /** Gets the menu panel associated with this menu. */
  96. async _getMenuPanel() {
  97. const panelId = await this._getPanelId();
  98. return panelId ? this._documentRootLocator.locatorForOptional(`#${panelId}`)() : null;
  99. }
  100. /** Gets the id of the menu panel associated with this menu. */
  101. async _getPanelId() {
  102. const panelId = await (await this.host()).getAttribute('aria-controls');
  103. return panelId || null;
  104. }
  105. }
  106. class MatMenuItemHarness extends ContentContainerComponentHarness {
  107. /** The selector for the host element of a `MatMenuItem` instance. */
  108. static hostSelector = '.mat-mdc-menu-item';
  109. /**
  110. * Gets a `HarnessPredicate` that can be used to search for a menu item with specific attributes.
  111. * @param options Options for filtering which menu item instances are considered a match.
  112. * @return a `HarnessPredicate` configured with the given options.
  113. */
  114. static with(options = {}) {
  115. return new HarnessPredicate(this, options)
  116. .addOption('text', options.text, (harness, text) => HarnessPredicate.stringMatches(harness.getText(), text))
  117. .addOption('hasSubmenu', options.hasSubmenu, async (harness, hasSubmenu) => (await harness.hasSubmenu()) === hasSubmenu);
  118. }
  119. /** Whether the menu is disabled. */
  120. async isDisabled() {
  121. const disabled = (await this.host()).getAttribute('disabled');
  122. return coerceBooleanProperty(await disabled);
  123. }
  124. /** Gets the text of the menu item. */
  125. async getText() {
  126. return (await this.host()).text();
  127. }
  128. /** Focuses the menu item. */
  129. async focus() {
  130. return (await this.host()).focus();
  131. }
  132. /** Blurs the menu item. */
  133. async blur() {
  134. return (await this.host()).blur();
  135. }
  136. /** Whether the menu item is focused. */
  137. async isFocused() {
  138. return (await this.host()).isFocused();
  139. }
  140. /** Clicks the menu item. */
  141. async click() {
  142. return (await this.host()).click();
  143. }
  144. /** Whether this item has a submenu. */
  145. async hasSubmenu() {
  146. return (await this.host()).matchesSelector(MatMenuHarness.hostSelector);
  147. }
  148. /** Gets the submenu associated with this menu item, or null if none. */
  149. async getSubmenu() {
  150. if (await this.hasSubmenu()) {
  151. return new MatMenuHarness(this.locatorFactory);
  152. }
  153. return null;
  154. }
  155. }
  156. export { MatMenuHarness, MatMenuItemHarness };
  157. //# sourceMappingURL=testing.mjs.map