Bin
2025-12-16 9e0b2ba2c317b1a86212f24cbae3195ad1f3dbfa
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
const { centerOfBbox } = require("../tests/helpers");
const { I } = inject();
 
module.exports = {
  _rootSelector: ".lsf-outliner",
  _regionListSelector: ".lsf-outliner-tree",
  _regionListItemSelector: ".lsf-tree__node:not(.lsf-tree__node_type_footer)",
  _regionListItemSelectedSelector: ".lsf-tree-node-selected",
  _regionListItemIndex: ".lsf-outliner-item__index",
  _regionVesibilityActionButton: ".lsf-outliner-item__control_type_visibility button",
  _incompleteStateIcon: ".lsf-outliner-item__incomplete",
  locateOutliner() {
    return locate(this._rootSelector);
  },
  locate(locator) {
    return locator ? locate(locator).inside(this.locateOutliner()) : this.locateOutliner();
  },
  locateRegionList() {
    return this.locate(this._regionListSelector);
  },
  locateRegionItemList(text) {
    if (text) {
      return locate(this._regionListItemSelector).withText(text).inside(this.locateRegionList());
    }
    return locate(this._regionListItemSelector).inside(this.locateRegionList());
  },
  locateRegionItemIndex(idx) {
    return locate(this._regionListItemIndex).withText(`${idx}`).inside(this.locateRegionItemList());
  },
  locateRegionIndex(idx) {
    return this.locateRegionItemList().withDescendant(
      `${locate(this._regionListItemIndex).toXPath()}[text()='${idx}']`,
    );
  },
  locateSelectedItem(locator) {
    const selectedLocator = locate(this._regionListItemSelectedSelector).inside(this.locateRegionList());
 
    return locator ? selectedLocator.find(locator) : selectedLocator;
  },
  locateRegion(idxOrText) {
    return typeof idxOrText === "number" ? this.locateRegionItemIndex(idxOrText) : this.locateRegionItemList(idxOrText);
  },
  locateIncompleteStateIcon(idxOrText) {
    if (idxOrText === undefined) {
      return locate(this._incompleteStateIcon).inside(this.locateRegionList());
    }
    return locate(this._incompleteStateIcon).inside(this.locateRegion(idxOrText));
  },
  see(text) {
    I.see(text, this._regionListSelector);
  },
  dontSee(text) {
    I.dontSee(text, this._regionListSelector);
  },
  seeElement(locator) {
    I.seeElement(this.locate(locator));
  },
  seeRegions(count) {
    // Avoid tries to find a region when there are 0 of them
    count && I.seeElement(this.locateRegionItemIndex(count));
    I.dontSeeElement(this.locateRegionItemIndex(count + 1));
  },
  dontSeeRegions(count) {
    count && I.dontSeeElement(this.locateRegionItemList().at(count));
    count === +count && I.dontSeeElement(this.locateRegionItemIndex(count));
    !count && I.see("Labeled regions will appear here");
  },
  clickRegion(idxOrText) {
    I.click(this.locateRegion(idxOrText));
  },
  hoverRegion(idxOrText) {
    I.moveCursorTo(this.locateRegion(idxOrText));
  },
  toggleRegionVisibility(idxOrText) {
    // Hover to see action button
    this.hoverRegion(idxOrText);
    // This button exist only for hovered list item
    I.click(locate(this._regionVesibilityActionButton));
  },
  seeSelectedRegion(text = undefined) {
    I.seeElement(text ? this.locateSelectedItem().withText(text) : this.locateSelectedItem());
  },
  dontSeeSelectedRegion(text = undefined) {
    I.dontSeeElement(text ? this.locateSelectedItem().withText(text) : this.locateSelectedItem());
  },
  /**
   * Verifies that the incomplete state icon is visible in a region list or for the specific region.
   *
   * @param {number|string} [idxOrText] - The index or text reference used to locate the region that should contain incomplete state icon.
   * Otherwise, it tries to find any.
   * @return {void} This method does not return any value.
   */
  seeIncompleteRegion(idxOrText) {
    I.seeElement(this.locateIncompleteStateIcon(idxOrText));
  },
  /**
   * Verifies that the incomplete state icon is not visible in a region list or for the specific region.
   *
   * @param {number|string} [idxOrText] - The index or text reference used to locate the region that should contain incomplete state icon.
   * Otherwise, it tries to find any.
   * @return {void} This method does not return any value.
   */
  dontSeeIncompleteRegion(idxOrText) {
    I.dontSeeElement(this.locateIncompleteStateIcon(idxOrText));
  },
  /**
   * Drag and drop region through the outliner's regions tree
   * @param {number} dragRegionIdx - Index of the dragged region
   * @param {number} dropRegionIdx - Index of the region that will be a drop zone
   * @param {number} [steps=3] - Sends intermediate mousemove events.
   * @returns {Promise<void>}
   */
  async dragAndDropRegion(dragRegionIdx, dropRegionIdx, steps = 3) {
    const fromBbox = await I.grabElementBoundingRect(this.locateRegionItemIndex(dragRegionIdx));
    const toBbox = await I.grabElementBoundingRect(this.locateRegionItemIndex(dropRegionIdx));
    const fromPoint = centerOfBbox(fromBbox);
    const toPoint = {
      x: toBbox.x + toBbox.width / 2,
      y: toBbox.y + (3 * toBbox.height) / 4,
    };
 
    return await I.dragAndDropMouse(fromPoint, toPoint, "left", steps);
  },
};