testing.mjs 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  1. import { ContentContainerComponentHarness, HarnessPredicate, ComponentHarness } from '@angular/cdk/testing';
  2. /** Harness for interacting with a standard Angular Material step in tests. */
  3. class MatStepHarness extends ContentContainerComponentHarness {
  4. /** The selector for the host element of a `MatStep` instance. */
  5. static hostSelector = '.mat-step-header';
  6. /**
  7. * Gets a `HarnessPredicate` that can be used to search for a `MatStepHarness` that meets
  8. * certain criteria.
  9. * @param options Options for filtering which steps are considered a match.
  10. * @return a `HarnessPredicate` configured with the given options.
  11. */
  12. static with(options = {}) {
  13. return new HarnessPredicate(MatStepHarness, options)
  14. .addOption('label', options.label, (harness, label) => HarnessPredicate.stringMatches(harness.getLabel(), label))
  15. .addOption('selected', options.selected, async (harness, selected) => (await harness.isSelected()) === selected)
  16. .addOption('completed', options.completed, async (harness, completed) => (await harness.isCompleted()) === completed)
  17. .addOption('invalid', options.invalid, async (harness, invalid) => (await harness.hasErrors()) === invalid);
  18. }
  19. /** Gets the label of the step. */
  20. async getLabel() {
  21. return (await this.locatorFor('.mat-step-text-label')()).text();
  22. }
  23. /** Gets the `aria-label` of the step. */
  24. async getAriaLabel() {
  25. return (await this.host()).getAttribute('aria-label');
  26. }
  27. /** Gets the value of the `aria-labelledby` attribute. */
  28. async getAriaLabelledby() {
  29. return (await this.host()).getAttribute('aria-labelledby');
  30. }
  31. /** Whether the step is selected. */
  32. async isSelected() {
  33. const host = await this.host();
  34. return (await host.getAttribute('aria-selected')) === 'true';
  35. }
  36. /** Whether the step has been filled out. */
  37. async isCompleted() {
  38. const state = await this._getIconState();
  39. return state === 'done' || (state === 'edit' && !(await this.isSelected()));
  40. }
  41. /**
  42. * Whether the step is currently showing its error state. Note that this doesn't mean that there
  43. * are or aren't any invalid form controls inside the step, but that the step is showing its
  44. * error-specific styling which depends on there being invalid controls, as well as the
  45. * `ErrorStateMatcher` determining that an error should be shown and that the `showErrors`
  46. * option was enabled through the `STEPPER_GLOBAL_OPTIONS` injection token.
  47. */
  48. async hasErrors() {
  49. return (await this._getIconState()) === 'error';
  50. }
  51. /** Whether the step is optional. */
  52. async isOptional() {
  53. // If the node with the optional text is present, it means that the step is optional.
  54. const optionalNode = await this.locatorForOptional('.mat-step-optional')();
  55. return !!optionalNode;
  56. }
  57. /**
  58. * Selects the given step by clicking on the label. The step may not be selected
  59. * if the stepper doesn't allow it (e.g. if there are validation errors).
  60. */
  61. async select() {
  62. await (await this.host()).click();
  63. }
  64. async getRootHarnessLoader() {
  65. const contentId = await (await this.host()).getAttribute('aria-controls');
  66. return this.documentRootLocatorFactory().harnessLoaderFor(`#${contentId}`);
  67. }
  68. /**
  69. * Gets the state of the step. Note that we have a `StepState` which we could use to type the
  70. * return value, but it's basically the same as `string`, because the type has `| string`.
  71. */
  72. async _getIconState() {
  73. // The state is exposed on the icon with a class that looks like `mat-step-icon-state-{{state}}`
  74. const icon = await this.locatorFor('.mat-step-icon')();
  75. const classes = (await icon.getAttribute('class'));
  76. const match = classes.match(/mat-step-icon-state-([a-z]+)/);
  77. if (!match) {
  78. throw Error(`Could not determine step state from "${classes}".`);
  79. }
  80. return match[1];
  81. }
  82. }
  83. /** Possible orientations for a stepper. */
  84. var StepperOrientation;
  85. (function (StepperOrientation) {
  86. StepperOrientation[StepperOrientation["HORIZONTAL"] = 0] = "HORIZONTAL";
  87. StepperOrientation[StepperOrientation["VERTICAL"] = 1] = "VERTICAL";
  88. })(StepperOrientation || (StepperOrientation = {}));
  89. /** Harness for interacting with a standard Material stepper in tests. */
  90. class MatStepperHarness extends ComponentHarness {
  91. /** The selector for the host element of a `MatStepper` instance. */
  92. static hostSelector = '.mat-stepper-horizontal, .mat-stepper-vertical';
  93. /**
  94. * Gets a `HarnessPredicate` that can be used to search for a `MatStepperHarness` that meets
  95. * certain criteria.
  96. * @param options Options for filtering which stepper instances are considered a match.
  97. * @return a `HarnessPredicate` configured with the given options.
  98. */
  99. static with(options = {}) {
  100. return new HarnessPredicate(MatStepperHarness, options).addOption('orientation', options.orientation, async (harness, orientation) => (await harness.getOrientation()) === orientation);
  101. }
  102. /**
  103. * Gets the list of steps in the stepper.
  104. * @param filter Optionally filters which steps are included.
  105. */
  106. async getSteps(filter = {}) {
  107. return this.locatorForAll(MatStepHarness.with(filter))();
  108. }
  109. /** Gets the orientation of the stepper. */
  110. async getOrientation() {
  111. const host = await this.host();
  112. return (await host.hasClass('mat-stepper-horizontal'))
  113. ? StepperOrientation.HORIZONTAL
  114. : StepperOrientation.VERTICAL;
  115. }
  116. /**
  117. * Selects a step in this stepper.
  118. * @param filter An optional filter to apply to the child steps. The first step matching the
  119. * filter will be selected.
  120. */
  121. async selectStep(filter = {}) {
  122. const steps = await this.getSteps(filter);
  123. if (!steps.length) {
  124. throw Error(`Cannot find mat-step matching filter ${JSON.stringify(filter)}`);
  125. }
  126. await steps[0].select();
  127. }
  128. }
  129. /** Base class for stepper button harnesses. */
  130. class StepperButtonHarness extends ComponentHarness {
  131. /** Gets the text of the button. */
  132. async getText() {
  133. return (await this.host()).text();
  134. }
  135. /** Clicks the button. */
  136. async click() {
  137. return (await this.host()).click();
  138. }
  139. }
  140. /** Harness for interacting with a standard Angular Material stepper next button in tests. */
  141. class MatStepperNextHarness extends StepperButtonHarness {
  142. /** The selector for the host element of a `MatStep` instance. */
  143. static hostSelector = '.mat-stepper-next';
  144. /**
  145. * Gets a `HarnessPredicate` that can be used to search for a `MatStepperNextHarness` that meets
  146. * certain criteria.
  147. * @param options Options for filtering which steps are considered a match.
  148. * @return a `HarnessPredicate` configured with the given options.
  149. */
  150. static with(options = {}) {
  151. return new HarnessPredicate(MatStepperNextHarness, options).addOption('text', options.text, (harness, text) => HarnessPredicate.stringMatches(harness.getText(), text));
  152. }
  153. }
  154. /** Harness for interacting with a standard Angular Material stepper previous button in tests. */
  155. class MatStepperPreviousHarness extends StepperButtonHarness {
  156. /** The selector for the host element of a `MatStep` instance. */
  157. static hostSelector = '.mat-stepper-previous';
  158. /**
  159. * Gets a `HarnessPredicate` that can be used to search for a `MatStepperPreviousHarness`
  160. * that meets certain criteria.
  161. * @param options Options for filtering which steps are considered a match.
  162. * @return a `HarnessPredicate` configured with the given options.
  163. */
  164. static with(options = {}) {
  165. return new HarnessPredicate(MatStepperPreviousHarness, options).addOption('text', options.text, (harness, text) => HarnessPredicate.stringMatches(harness.getText(), text));
  166. }
  167. }
  168. export { MatStepHarness, MatStepperHarness, MatStepperNextHarness, MatStepperPreviousHarness, StepperOrientation };
  169. //# sourceMappingURL=testing.mjs.map