{"version":3,"file":"testing.mjs","sources":["../../../../../../../src/material/tree/testing/node-harness.ts","../../../../../../../src/material/tree/testing/tree-harness.ts","../../../../../../../src/material/tree/testing/tree-harness-filters.ts","../../../../../../../src/material/tree/testing/public-api.ts","../../../../../../../src/material/tree/testing/index.ts"],"sourcesContent":["/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {\n  ComponentHarnessConstructor,\n  ContentContainerComponentHarness,\n  HarnessPredicate,\n} from '@angular/cdk/testing';\nimport {TreeNodeHarnessFilters} from './tree-harness-filters';\nimport {coerceBooleanProperty, coerceNumberProperty} from '@angular/cdk/coercion';\n\n/** Harness for interacting with a standard Angular Material tree node. */\nexport class MatTreeNodeHarness extends ContentContainerComponentHarness<string> {\n  /** The selector of the host element of a `MatTreeNode` instance. */\n  static hostSelector = '.mat-tree-node, .mat-nested-tree-node';\n\n  _toggle = this.locatorForOptional('[matTreeNodeToggle]');\n\n  /**\n   * Gets a `HarnessPredicate` that can be used to search for a tree node with specific attributes.\n   * @param options Options for narrowing the search\n   * @return a `HarnessPredicate` configured with the given options.\n   */\n  static with(options: TreeNodeHarnessFilters = {}): HarnessPredicate<MatTreeNodeHarness> {\n    return getNodePredicate(MatTreeNodeHarness, options);\n  }\n\n  /** Whether the tree node is expanded. */\n  async isExpanded(): Promise<boolean> {\n    return coerceBooleanProperty(await (await this.host()).getAttribute('aria-expanded'));\n  }\n\n  /** Whether the tree node is disabled. */\n  async isDisabled(): Promise<boolean> {\n    return coerceBooleanProperty(await (await this.host()).getProperty('aria-disabled'));\n  }\n\n  /** Gets the level of the tree node. Note that this gets the aria-level and is 1 indexed. */\n  async getLevel(): Promise<number> {\n    return coerceNumberProperty(await (await this.host()).getAttribute('aria-level'));\n  }\n\n  /** Gets the tree node's text. */\n  async getText(): Promise<string> {\n    return (await this.host()).text({exclude: '.mat-tree-node, .mat-nested-tree-node, button'});\n  }\n\n  /** Toggles node between expanded/collapsed. Only works when node is not disabled. */\n  async toggle(): Promise<void> {\n    const toggle = await this._toggle();\n    if (toggle) {\n      return toggle.click();\n    }\n  }\n\n  /** Expands the node if it is collapsed. Only works when node is not disabled. */\n  async expand(): Promise<void> {\n    if (!(await this.isExpanded())) {\n      await this.toggle();\n    }\n  }\n\n  /** Collapses the node if it is expanded. Only works when node is not disabled. */\n  async collapse(): Promise<void> {\n    if (await this.isExpanded()) {\n      await this.toggle();\n    }\n  }\n}\n\nfunction getNodePredicate<T extends MatTreeNodeHarness>(\n  type: ComponentHarnessConstructor<T>,\n  options: TreeNodeHarnessFilters,\n): HarnessPredicate<T> {\n  return new HarnessPredicate(type, options)\n    .addOption('text', options.text, (harness, text) =>\n      HarnessPredicate.stringMatches(harness.getText(), text),\n    )\n    .addOption(\n      'disabled',\n      options.disabled,\n      async (harness, disabled) => (await harness.isDisabled()) === disabled,\n    )\n    .addOption(\n      'expanded',\n      options.expanded,\n      async (harness, expanded) => (await harness.isExpanded()) === expanded,\n    )\n    .addOption(\n      'level',\n      options.level,\n      async (harness, level) => (await harness.getLevel()) === level,\n    );\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {ComponentHarness, HarnessPredicate, parallel} from '@angular/cdk/testing';\nimport {MatTreeNodeHarness} from './node-harness';\nimport {TreeHarnessFilters, TreeNodeHarnessFilters} from './tree-harness-filters';\n\nexport type TextTree = {\n  text?: string;\n  children?: TextTree[];\n};\n\n/** Harness for interacting with a standard mat-tree in tests. */\nexport class MatTreeHarness extends ComponentHarness {\n  /** The selector for the host element of a `MatTableHarness` instance. */\n  static hostSelector = '.mat-tree';\n\n  /**\n   * Gets a `HarnessPredicate` that can be used to search for a tree with specific attributes.\n   * @param options Options for narrowing the search\n   * @return a `HarnessPredicate` configured with the given options.\n   */\n  static with(options: TreeHarnessFilters = {}): HarnessPredicate<MatTreeHarness> {\n    return new HarnessPredicate(MatTreeHarness, options);\n  }\n\n  /** Gets all of the nodes in the tree. */\n  async getNodes(filter: TreeNodeHarnessFilters = {}): Promise<MatTreeNodeHarness[]> {\n    return this.locatorForAll(MatTreeNodeHarness.with(filter))();\n  }\n\n  /**\n   * Gets an object representation for the visible tree structure\n   * If a node is under an unexpanded node it will not be included.\n   * Eg.\n   * Tree (all nodes expanded):\n   * `\n   * <mat-tree>\n   *   <mat-tree-node>Node 1<mat-tree-node>\n   *   <mat-nested-tree-node>\n   *     Node 2\n   *     <mat-nested-tree-node>\n   *       Node 2.1\n   *       <mat-tree-node>\n   *         Node 2.1.1\n   *       <mat-tree-node>\n   *     <mat-nested-tree-node>\n   *     <mat-tree-node>\n   *       Node 2.2\n   *     <mat-tree-node>\n   *   <mat-nested-tree-node>\n   * </mat-tree>`\n   *\n   * Tree structure:\n   * {\n   *  children: [\n   *    {\n   *      text: 'Node 1',\n   *      children: [\n   *        {\n   *          text: 'Node 2',\n   *          children: [\n   *            {\n   *              text: 'Node 2.1',\n   *              children: [{text: 'Node 2.1.1'}]\n   *            },\n   *            {text: 'Node 2.2'}\n   *          ]\n   *        }\n   *      ]\n   *    }\n   *  ]\n   * };\n   */\n  async getTreeStructure(): Promise<TextTree> {\n    const nodes = await this.getNodes();\n    const nodeInformation = await parallel(() =>\n      nodes.map(node => {\n        return parallel(() => [node.getLevel(), node.getText(), node.isExpanded()]);\n      }),\n    );\n    return this._getTreeStructure(nodeInformation, 1, true);\n  }\n\n  /**\n   * Recursively collect the structured text of the tree nodes.\n   * @param nodes A list of tree nodes\n   * @param level The level of nodes that are being accounted for during this iteration\n   * @param parentExpanded Whether the parent of the first node in param nodes is expanded\n   */\n  private _getTreeStructure(\n    nodes: [number, string, boolean][],\n    level: number,\n    parentExpanded: boolean,\n  ): TextTree {\n    const result: TextTree = {};\n    for (let i = 0; i < nodes.length; i++) {\n      const [nodeLevel, text, expanded] = nodes[i];\n      const nextNodeLevel = nodes[i + 1]?.[0] ?? -1;\n\n      // Return the accumulated value for the current level once we reach a shallower level node\n      if (nodeLevel < level) {\n        return result;\n      }\n      // Skip deeper level nodes during this iteration, they will be picked up in a later iteration\n      if (nodeLevel > level) {\n        continue;\n      }\n      // Only add to representation if it is visible (parent is expanded)\n      if (parentExpanded) {\n        // Collect the data under this node according to the following rules:\n        // 1. If the next node in the list is a sibling of the current node add it to the child list\n        // 2. If the next node is a child of the current node, get the sub-tree structure for the\n        //    child and add it under this node\n        // 3. If the next node has a shallower level, we've reached the end of the child nodes for\n        //    the current parent.\n        if (nextNodeLevel === level) {\n          this._addChildToNode(result, {text});\n        } else if (nextNodeLevel > level) {\n          let children = this._getTreeStructure(\n            nodes.slice(i + 1),\n            nextNodeLevel,\n            expanded,\n          )?.children;\n          let child = children ? {text, children} : {text};\n          this._addChildToNode(result, child);\n        } else {\n          this._addChildToNode(result, {text});\n          return result;\n        }\n      }\n    }\n    return result;\n  }\n\n  private _addChildToNode(result: TextTree, child: TextTree) {\n    result.children ? result.children.push(child) : (result.children = [child]);\n  }\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {BaseHarnessFilters} from '@angular/cdk/testing';\n\n/** A set of criteria that can be used to filter a list of tree harness instances */\nexport interface TreeHarnessFilters extends BaseHarnessFilters {}\n\n/** A set of criteria that can be used to filter a list of node harness instances. */\nexport interface TreeNodeHarnessFilters extends BaseHarnessFilters {\n  /** Only find instances whose text matches the given value. */\n  text?: string | RegExp;\n\n  /** Only find instances whose disabled state matches the given value. */\n  disabled?: boolean;\n\n  /** Only find instances whose expansion state matches the given value. */\n  expanded?: boolean;\n\n  /** Only find instances whose level matches the given value. */\n  level?: number;\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nexport * from './node-harness';\nexport * from './tree-harness';\nexport * from './tree-harness-filters';\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}