testing.mjs 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  1. import { HarnessPredicate, parallel } from '@angular/cdk/testing';
  2. import { MatFormFieldControlHarness } from '../form-field/testing/control.mjs';
  3. import { M as MatOptionHarness } from '../option-harness-BFcc-M_4.mjs';
  4. import { MatOptgroupHarness } from '../core/testing.mjs';
  5. /** Harness for interacting with a mat-select in tests. */
  6. class MatSelectHarness extends MatFormFieldControlHarness {
  7. static hostSelector = '.mat-mdc-select';
  8. _prefix = 'mat-mdc';
  9. _optionClass = MatOptionHarness;
  10. _optionGroupClass = MatOptgroupHarness;
  11. _documentRootLocator = this.documentRootLocatorFactory();
  12. _backdrop = this._documentRootLocator.locatorFor('.cdk-overlay-backdrop');
  13. /**
  14. * Gets a `HarnessPredicate` that can be used to search for a select with specific attributes.
  15. * @param options Options for filtering which select instances are considered a match.
  16. * @return a `HarnessPredicate` configured with the given options.
  17. */
  18. static with(options = {}) {
  19. return new HarnessPredicate(this, options).addOption('disabled', options.disabled, async (harness, disabled) => {
  20. return (await harness.isDisabled()) === disabled;
  21. });
  22. }
  23. /** Gets a boolean promise indicating if the select is disabled. */
  24. async isDisabled() {
  25. return (await this.host()).hasClass(`${this._prefix}-select-disabled`);
  26. }
  27. /** Gets a boolean promise indicating if the select is valid. */
  28. async isValid() {
  29. return !(await (await this.host()).hasClass('ng-invalid'));
  30. }
  31. /** Gets a boolean promise indicating if the select is required. */
  32. async isRequired() {
  33. return (await this.host()).hasClass(`${this._prefix}-select-required`);
  34. }
  35. /** Gets a boolean promise indicating if the select is empty (no value is selected). */
  36. async isEmpty() {
  37. return (await this.host()).hasClass(`${this._prefix}-select-empty`);
  38. }
  39. /** Gets a boolean promise indicating if the select is in multi-selection mode. */
  40. async isMultiple() {
  41. return (await this.host()).hasClass(`${this._prefix}-select-multiple`);
  42. }
  43. /** Gets a promise for the select's value text. */
  44. async getValueText() {
  45. const value = await this.locatorFor(`.${this._prefix}-select-value`)();
  46. return value.text();
  47. }
  48. /** Focuses the select and returns a void promise that indicates when the action is complete. */
  49. async focus() {
  50. return (await this.host()).focus();
  51. }
  52. /** Blurs the select and returns a void promise that indicates when the action is complete. */
  53. async blur() {
  54. return (await this.host()).blur();
  55. }
  56. /** Whether the select is focused. */
  57. async isFocused() {
  58. return (await this.host()).isFocused();
  59. }
  60. /** Gets the options inside the select panel. */
  61. async getOptions(filter) {
  62. return this._documentRootLocator.locatorForAll(this._optionClass.with({
  63. ...(filter || {}),
  64. ancestor: await this._getPanelSelector(),
  65. }))();
  66. }
  67. /** Gets the groups of options inside the panel. */
  68. async getOptionGroups(filter) {
  69. return this._documentRootLocator.locatorForAll(this._optionGroupClass.with({
  70. ...(filter || {}),
  71. ancestor: await this._getPanelSelector(),
  72. }))();
  73. }
  74. /** Gets whether the select is open. */
  75. async isOpen() {
  76. return !!(await this._documentRootLocator.locatorForOptional(await this._getPanelSelector())());
  77. }
  78. /** Opens the select's panel. */
  79. async open() {
  80. if (!(await this.isOpen())) {
  81. const trigger = await this.locatorFor(`.${this._prefix}-select-trigger`)();
  82. return trigger.click();
  83. }
  84. }
  85. /**
  86. * Clicks the options that match the passed-in filter. If the select is in multi-selection
  87. * mode all options will be clicked, otherwise the harness will pick the first matching option.
  88. */
  89. async clickOptions(filter) {
  90. await this.open();
  91. const [isMultiple, options] = await parallel(() => [
  92. this.isMultiple(),
  93. this.getOptions(filter),
  94. ]);
  95. if (options.length === 0) {
  96. throw Error('Select does not have options matching the specified filter');
  97. }
  98. if (isMultiple) {
  99. await parallel(() => options.map(option => option.click()));
  100. }
  101. else {
  102. await options[0].click();
  103. }
  104. }
  105. /** Closes the select's panel. */
  106. async close() {
  107. if (await this.isOpen()) {
  108. // This is the most consistent way that works both in both single and multi-select modes,
  109. // but it assumes that only one overlay is open at a time. We should be able to make it
  110. // a bit more precise after #16645 where we can dispatch an ESCAPE press to the host instead.
  111. return (await this._backdrop()).click();
  112. }
  113. }
  114. /** Gets the selector that should be used to find this select's panel. */
  115. async _getPanelSelector() {
  116. const id = await (await this.host()).getAttribute('id');
  117. return `#${id}-panel`;
  118. }
  119. }
  120. export { MatSelectHarness };
  121. //# sourceMappingURL=testing.mjs.map