automation_model 1.0.0-amdocs

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (75) hide show
  1. package/README.md +130 -0
  2. package/lib/analyze_helper.d.ts +9 -0
  3. package/lib/analyze_helper.js +161 -0
  4. package/lib/analyze_helper.js.map +1 -0
  5. package/lib/api.d.ts +55 -0
  6. package/lib/api.js +349 -0
  7. package/lib/api.js.map +1 -0
  8. package/lib/auto_page.d.ts +7 -0
  9. package/lib/auto_page.js +199 -0
  10. package/lib/auto_page.js.map +1 -0
  11. package/lib/browser_manager.d.ts +32 -0
  12. package/lib/browser_manager.js +257 -0
  13. package/lib/browser_manager.js.map +1 -0
  14. package/lib/command_common.d.ts +6 -0
  15. package/lib/command_common.js +182 -0
  16. package/lib/command_common.js.map +1 -0
  17. package/lib/date_time.d.ts +10 -0
  18. package/lib/date_time.js +45 -0
  19. package/lib/date_time.js.map +1 -0
  20. package/lib/drawRect.d.ts +2 -0
  21. package/lib/drawRect.js +25 -0
  22. package/lib/drawRect.js.map +1 -0
  23. package/lib/environment.d.ts +27 -0
  24. package/lib/environment.js +15 -0
  25. package/lib/environment.js.map +1 -0
  26. package/lib/error-messages.d.ts +6 -0
  27. package/lib/error-messages.js +206 -0
  28. package/lib/error-messages.js.map +1 -0
  29. package/lib/find_function.d.ts +2 -0
  30. package/lib/find_function.js +51 -0
  31. package/lib/find_function.js.map +1 -0
  32. package/lib/generation_scripts.d.ts +4 -0
  33. package/lib/generation_scripts.js +2 -0
  34. package/lib/generation_scripts.js.map +1 -0
  35. package/lib/index.d.ts +10 -0
  36. package/lib/index.js +11 -0
  37. package/lib/index.js.map +1 -0
  38. package/lib/init_browser.d.ts +10 -0
  39. package/lib/init_browser.js +216 -0
  40. package/lib/init_browser.js.map +1 -0
  41. package/lib/locate_element.d.ts +7 -0
  42. package/lib/locate_element.js +215 -0
  43. package/lib/locate_element.js.map +1 -0
  44. package/lib/locator.d.ts +70 -0
  45. package/lib/locator.js +392 -0
  46. package/lib/locator.js.map +1 -0
  47. package/lib/locator_log.d.ts +26 -0
  48. package/lib/locator_log.js +69 -0
  49. package/lib/locator_log.js.map +1 -0
  50. package/lib/network.d.ts +3 -0
  51. package/lib/network.js +183 -0
  52. package/lib/network.js.map +1 -0
  53. package/lib/popups.d.ts +0 -0
  54. package/lib/popups.js +36 -0
  55. package/lib/popups.js.map +1 -0
  56. package/lib/scripts/axe.mini.js +12 -0
  57. package/lib/stable_browser.d.ts +188 -0
  58. package/lib/stable_browser.js +3322 -0
  59. package/lib/stable_browser.js.map +1 -0
  60. package/lib/table.d.ts +13 -0
  61. package/lib/table.js +187 -0
  62. package/lib/table.js.map +1 -0
  63. package/lib/table_analyze.d.ts +4 -0
  64. package/lib/table_analyze.js +95 -0
  65. package/lib/table_analyze.js.map +1 -0
  66. package/lib/table_helper.d.ts +19 -0
  67. package/lib/table_helper.js +101 -0
  68. package/lib/table_helper.js.map +1 -0
  69. package/lib/test_context.d.ts +21 -0
  70. package/lib/test_context.js +17 -0
  71. package/lib/test_context.js.map +1 -0
  72. package/lib/utils.d.ts +21 -0
  73. package/lib/utils.js +601 -0
  74. package/lib/utils.js.map +1 -0
  75. package/package.json +56 -0
@@ -0,0 +1,215 @@
1
+ import axios from "axios";
2
+ import * as path from "path";
3
+ import { fileURLToPath } from "url";
4
+ import { _getServerUrl } from "./utils.js";
5
+ // Get __filename and __dirname in ESM
6
+ const __filename = fileURLToPath(import.meta.url);
7
+ const __dirname = path.dirname(__filename);
8
+ export async function locate_element(context, elementDescription, operation = "click", value = null) {
9
+ // load the axe-core library to all of the frames in the page
10
+ // read the axe-core library from the file system placed in the same folder as the script file, name axe.mini.js
11
+ // Construct the path to axe.min.js relative to the current file
12
+ // let axeMinJsPath = path.join(__dirname, "..", "scripts", "axe.mini.js");
13
+ // // Check if the file exists
14
+ // if (!fs.existsSync(axeMinJsPath)) {
15
+ // axeMinJsPath = path.join(__dirname, "scripts", "axe.mini.js");
16
+ // }
17
+ // // Read the content of axe.min.js synchronously
18
+ // const axeMinJsContent = fs.readFileSync(axeMinJsPath, "utf-8");
19
+ // await Promise.all(context.stable.page.frames().map((frame: any) => frame.evaluate(axeMinJsContent)));
20
+ const frames = await context.stable.page.frames();
21
+ // for each frame create a tree of the accessibility nodes
22
+ const frameDump = [];
23
+ let iframeIndex = 0;
24
+ let nextFrameIndex = 1;
25
+ let actionableElementIndex = 0;
26
+ const randomToken = Math.random().toString(36).substring(7);
27
+ const actionableElements = [];
28
+ for (let frame of frames) {
29
+ // @ts-ignore
30
+ let result = null;
31
+ try {
32
+ result = await frame.evaluate(
33
+ // @ts-ignore
34
+ ([iframeIndex, nextFrameIndex, actionableElementIndex, randomToken]) => {
35
+ let iframeCount = 1;
36
+ const actionableElements = [];
37
+ const actionableRoles = [
38
+ "link",
39
+ "button",
40
+ "tab",
41
+ "menuitem",
42
+ "menuitemcheckbox",
43
+ "menuitemradio",
44
+ "checkbox",
45
+ "textbox",
46
+ "combobox",
47
+ "listitem",
48
+ "radio",
49
+ "searchbox",
50
+ "option",
51
+ "Date",
52
+ "row",
53
+ "DateTime",
54
+ "InputTime",
55
+ "treeitem",
56
+ ];
57
+ function isAccessibilityElement(element) {
58
+ if (!element) {
59
+ return false;
60
+ }
61
+ // @ts-ignore
62
+ let hidden = axe.commons.dom.isHiddenForEveryone(element);
63
+ if (hidden) {
64
+ return false;
65
+ }
66
+ if (element.tagName === "IFRAME") {
67
+ return true;
68
+ }
69
+ // @ts-ignore
70
+ let roles = axe.commons.aria.getRole(element);
71
+ if (!roles) {
72
+ return false;
73
+ }
74
+ return true;
75
+ }
76
+ function getAttributes(element) {
77
+ const attrs = element.attributes;
78
+ const result = {};
79
+ for (let i = 0; i < attrs.length; i++) {
80
+ result[attrs[i].name] = attrs[i].value;
81
+ if (attrs[i].name === "class") {
82
+ // clean the spaces
83
+ result[attrs[i].name] = attrs[i].value.replace(/\s+/g, " ").trim();
84
+ }
85
+ }
86
+ return result;
87
+ }
88
+ function createAccessibilityNode(element, actionableElements) {
89
+ // check if the element is an iframe
90
+ const result = {
91
+ tag: element.tagName,
92
+ // @ts-ignore
93
+ role: axe.commons.aria.getRole(element),
94
+ // @ts-ignore
95
+ visible: axe.commons.dom.isVisible(element),
96
+ // @ts-ignore
97
+ name: axe.commons.text.accessibleText(element),
98
+ attributes: getAttributes(element),
99
+ // @ts-ignore
100
+ frameIndex: iframeIndex,
101
+ };
102
+ if (actionableRoles.includes(result.role)) {
103
+ // @ts-ignore
104
+ result.elementNumber = actionableElementIndex;
105
+ element.setAttribute("data-blinq-id", "blinq-id-" + randomToken + "-" + actionableElementIndex);
106
+ //console.log("attribute set to " + "blinq-id-" + randomToken + "-" + actionableElementIndex);
107
+ actionableElementIndex++;
108
+ actionableElements.push(result);
109
+ }
110
+ if (element.tagName === "IFRAME") {
111
+ // @ts-ignore
112
+ result.targetFrameIndex = nextFrameIndex;
113
+ nextFrameIndex++;
114
+ }
115
+ return result;
116
+ }
117
+ // a function that traverses the DOM tree and builds a tree of accessibility nodes
118
+ function buildAccessibilityTree(node, treeRoot) {
119
+ //const foundAccessibilityNodes = [];
120
+ if (!treeRoot.children) {
121
+ treeRoot.children = [];
122
+ }
123
+ //console.log(node.tagName + " " + node.children.length);
124
+ for (let child of node.children) {
125
+ if (isAccessibilityElement(child)) {
126
+ const accessibilityNode = createAccessibilityNode(child, actionableElements);
127
+ // @ts-ignore
128
+ // accessibilityNode.children = buildAccessibilityTree(child, accessibilityNode),
129
+ // foundAccessibilityNodes.push(accessibilityNode);
130
+ treeRoot.children.push(accessibilityNode);
131
+ buildAccessibilityTree(child, accessibilityNode);
132
+ }
133
+ else {
134
+ buildAccessibilityTree(child, treeRoot);
135
+ }
136
+ }
137
+ }
138
+ // @ts-ignore
139
+ axe.utils.getFlattenedTree(document);
140
+ const root = createAccessibilityNode(document.body, actionableElements);
141
+ buildAccessibilityTree(document.body, root);
142
+ return JSON.stringify({ root, nextFrameIndex, actionableElementIndex, actionableElements }, null, 2);
143
+ }, [iframeIndex, nextFrameIndex, actionableElementIndex, randomToken]);
144
+ const resultData = JSON.parse(result);
145
+ nextFrameIndex = resultData.nextFrameIndex;
146
+ actionableElementIndex = resultData.actionableElementIndex;
147
+ frameDump.push(resultData.root);
148
+ actionableElements.push(...resultData.actionableElements);
149
+ iframeIndex++;
150
+ }
151
+ catch (e) {
152
+ // ignore
153
+ }
154
+ }
155
+ function traverseDFS(node) {
156
+ // Recursively traverse each child node
157
+ if (node.children && node.children.length > 0) {
158
+ node.children.forEach((child) => {
159
+ if (child.tag === "IFRAME") {
160
+ if (child.targetFrameIndex && frameDump.length >= child.targetFrameIndex) {
161
+ child.children = [frameDump[child.targetFrameIndex]];
162
+ }
163
+ }
164
+ if (child.shadowRoot) {
165
+ traverseDFS(child.shadowRoot);
166
+ }
167
+ else {
168
+ traverseDFS(child);
169
+ }
170
+ });
171
+ }
172
+ }
173
+ traverseDFS(frameDump[0]);
174
+ let serviceUrl = _getServerUrl();
175
+ const config = {
176
+ method: "post",
177
+ url: `${serviceUrl}/api/runs/locate-element/locate`,
178
+ headers: {
179
+ "x-source": "true",
180
+ "Content-Type": "application/json",
181
+ Authorization: `Bearer ${process.env.TOKEN}`,
182
+ },
183
+ data: JSON.stringify({
184
+ elementDescription: elementDescription,
185
+ operation: operation,
186
+ dump: frameDump[0],
187
+ value: value,
188
+ }),
189
+ };
190
+ let result = await axios.request(config);
191
+ //console.log(JSON.stringify(frameDump[0]));
192
+ if (result.status !== 200 || !result.data || result.data.status !== true || !result.data.result) {
193
+ console.error("Failed to locate element");
194
+ return null;
195
+ }
196
+ const returnData = {
197
+ reason: result.data.result.reason,
198
+ elementNumber: result.data.result.elementNumber,
199
+ frameIndex: -1,
200
+ frame: null,
201
+ css: "",
202
+ };
203
+ if (result.data.result.elementNumber !== -1) {
204
+ // find the iframe index, the element is in, by identifying the actionable element
205
+ const actionableElement = actionableElements.find((element) => element.elementNumber === result.data.result.elementNumber);
206
+ if (actionableElement) {
207
+ returnData.frameIndex = actionableElement.frameIndex;
208
+ returnData.frame = frames[returnData.frameIndex];
209
+ returnData.css = `[data-blinq-id="blinq-id-${randomToken}-${returnData.elementNumber}"]`;
210
+ }
211
+ }
212
+ //console.log(dumpToHtml(frameDump[0]));
213
+ return returnData;
214
+ }
215
+ //# sourceMappingURL=locate_element.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"locate_element.js","sourceRoot":"","sources":["../../src/locate_element.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,70 @@
1
+ type Change = {
2
+ css: string;
3
+ changes: {
4
+ role: string;
5
+ };
6
+ };
7
+ declare const document: Document & {
8
+ selectors: Change[] | null;
9
+ tableSelector: string | null;
10
+ processTableQuery: TprocessTableQuery;
11
+ };
12
+ declare const selectors: null;
13
+ declare const tableSelector: null;
14
+ declare function getTableData(table: Element): {
15
+ rowsCount: number;
16
+ columnsCount: number;
17
+ columnNames: never[];
18
+ rows: never[];
19
+ };
20
+ declare function getTableData2(table: any): {
21
+ rowsCount: number;
22
+ columnsCount: number;
23
+ nodes: never[];
24
+ rows: never[];
25
+ columnHeaders: never[];
26
+ };
27
+ declare function getVisibleText(thElement: any): any;
28
+ declare const Roles: {
29
+ LINK: string;
30
+ BUTTON: string;
31
+ CHECKBOX: string;
32
+ RADIO: string;
33
+ SLIDER: string;
34
+ TEXTBOX: string;
35
+ PRESENTATION: string;
36
+ IMG: string;
37
+ LIST: string;
38
+ LISTITEM: string;
39
+ TABLE: string;
40
+ COLUMNHEADER: string;
41
+ ROWHEADER: string;
42
+ CELL: string;
43
+ ROW: string;
44
+ NAVIGATION: string;
45
+ BANNER: string;
46
+ CONTENTINFO: string;
47
+ MAIN: string;
48
+ ARTICLE: string;
49
+ REGION: string;
50
+ COMPLEMENTARY: string;
51
+ FORM: string;
52
+ LISTBOX: string;
53
+ COMBOBOX: string;
54
+ };
55
+ declare function getRole(element: any): any;
56
+ declare function processTableQuery(table: Element, query: string): {
57
+ cells: any[];
58
+ error?: undefined;
59
+ rect?: undefined;
60
+ } | {
61
+ error: string;
62
+ cells?: undefined;
63
+ rect?: undefined;
64
+ } | {
65
+ cells: any[];
66
+ rect: DOMRect | null;
67
+ error?: undefined;
68
+ };
69
+ declare const merge: (rec1: DOMRect, rec2: DOMRect) => DOMRect;
70
+ type TprocessTableQuery = typeof processTableQuery;
package/lib/locator.js ADDED
@@ -0,0 +1,392 @@
1
+ "use strict";
2
+ const selectors = null;
3
+ document.selectors = selectors;
4
+ const tableSelector = null;
5
+ document.tableSelector = tableSelector;
6
+ function getTableData(table) {
7
+ const tableData = {
8
+ rowsCount: 0,
9
+ columnsCount: 0,
10
+ columnNames: [],
11
+ rows: [],
12
+ };
13
+ let columnheader = [];
14
+ //const rowheader = rows[0];
15
+ columnheader = Array.from(table.querySelectorAll("th, [data-blinq-role='columnheader'], [role='columnheader']"));
16
+ console.log("columnheader length", columnheader.length);
17
+ let columnsCount = columnheader.length;
18
+ const columnNames = [];
19
+ for (let i = 0; i < columnheader.length; i++) {
20
+ const cell = columnheader[i];
21
+ const cellText = cell.innerText;
22
+ columnNames.push(cellText);
23
+ }
24
+ tableData.columnNames = columnNames;
25
+ tableData.columnsCount = columnsCount;
26
+ const rows = Array.from(table.querySelectorAll("tr, [data-blinq-role='row'], [role='row']"));
27
+ const rowsCount = rows.length;
28
+ for (let i = 0; i < rows.length; i++) {
29
+ const row = rows[i];
30
+ const cells = Array.from(row.querySelectorAll("td, [data-blinq-role='cell'], [role='cell']"));
31
+ const cellsTexts = [];
32
+ console.log("cells count", cells.length);
33
+ if (cells.length === 0) {
34
+ continue;
35
+ }
36
+ for (let j = 0; j < cells.length; j++) {
37
+ const cell = cells[j];
38
+ const cellText = cell.innerText;
39
+ cellsTexts.push(cellText);
40
+ }
41
+ tableData.rows.push(cellsTexts);
42
+ }
43
+ tableData.rowsCount = rowsCount;
44
+ return tableData;
45
+ }
46
+ // @ts-ignore
47
+ document.getTableData = getTableData;
48
+ function getTableData2(table) {
49
+ // Scan the table and build a tree
50
+ function scanTable(root, nodeArray, tableData) {
51
+ const role = document.getRole(root);
52
+ if (role &&
53
+ (role === Roles.CELL || role === Roles.ROW || role === Roles.COLUMNHEADER || role === Roles.ROWHEADER)) {
54
+ const rec = root.getBoundingClientRect();
55
+ const node = {
56
+ tag: root.tagName,
57
+ role,
58
+ rec: rec ? [rec.x, rec.y, rec.width, rec.height] : null,
59
+ children: [],
60
+ };
61
+ if (role === Roles.CELL || role === Roles.COLUMNHEADER || role === Roles.ROWHEADER) {
62
+ node.text = document.getVisibleText(root);
63
+ }
64
+ if (role === Roles.COLUMNHEADER) {
65
+ tableData.columnsCount++;
66
+ tableData.columnHeaders.push(node);
67
+ }
68
+ if (role === Roles.ROW) {
69
+ tableData.rowsCount++;
70
+ tableData.rows.push(node);
71
+ }
72
+ nodeArray.push(node);
73
+ nodeArray = node.children;
74
+ }
75
+ const children = Array.from(root.children);
76
+ for (let i = 0; i < children.length; i++) {
77
+ scanTable(children[i], nodeArray, tableData);
78
+ }
79
+ }
80
+ const tableData = {
81
+ rowsCount: 0,
82
+ columnsCount: 0,
83
+ nodes: [],
84
+ rows: [],
85
+ columnHeaders: [],
86
+ };
87
+ // Pass the root table element and initialize the tree
88
+ scanTable(table, tableData.nodes, tableData);
89
+ return tableData;
90
+ }
91
+ function getVisibleText(thElement) {
92
+ // if (!(thElement instanceof HTMLTableCellElement && thElement.tagName === 'TH')) {
93
+ // throw new Error('Provided element is not a valid TH element.');
94
+ // }
95
+ // Helper function to recursively collect visible text
96
+ function getText(node) {
97
+ if (node.nodeType === Node.TEXT_NODE) {
98
+ return node.textContent.trim(); // Return text content of text nodes
99
+ }
100
+ if (node.nodeType === Node.ELEMENT_NODE) {
101
+ const tagName = node.tagName.toUpperCase();
102
+ if (tagName === "BR") {
103
+ return "\n"; // Treat <br> as a newline
104
+ }
105
+ if (getComputedStyle(node).display === "none") {
106
+ return ""; // Ignore invisible elements
107
+ }
108
+ // Recursively process child nodes
109
+ return Array.from(node.childNodes).map(getText).join("");
110
+ }
111
+ return ""; // Ignore other node types
112
+ }
113
+ return getText(thElement)
114
+ .replace(/\n\s*\n/g, "\n")
115
+ .trim(); // Clean up multiple newlines
116
+ }
117
+ document.getVisibleText = getVisibleText;
118
+ // @ts-ignore
119
+ document.getTableData2 = getTableData2;
120
+ const Roles = {
121
+ LINK: "link",
122
+ BUTTON: "button",
123
+ CHECKBOX: "checkbox",
124
+ RADIO: "radio",
125
+ SLIDER: "slider",
126
+ TEXTBOX: "textbox",
127
+ PRESENTATION: "presentation",
128
+ IMG: "img",
129
+ LIST: "list",
130
+ LISTITEM: "listitem",
131
+ TABLE: "table",
132
+ COLUMNHEADER: "columnheader",
133
+ ROWHEADER: "rowheader",
134
+ CELL: "cell",
135
+ ROW: "row",
136
+ NAVIGATION: "navigation",
137
+ BANNER: "banner",
138
+ CONTENTINFO: "contentinfo",
139
+ MAIN: "main",
140
+ ARTICLE: "article",
141
+ REGION: "region",
142
+ COMPLEMENTARY: "complementary",
143
+ FORM: "form",
144
+ LISTBOX: "listbox",
145
+ COMBOBOX: "combobox",
146
+ };
147
+ function getRole(element) {
148
+ if (!element || typeof element.getAttribute !== "function") {
149
+ return null;
150
+ }
151
+ const tagName = element.tagName.toLowerCase();
152
+ function getInputRole(el) {
153
+ const type = el.type;
154
+ if (["button", "submit", "reset", "image"].includes(type)) {
155
+ return Roles.BUTTON;
156
+ }
157
+ if (type === "checkbox")
158
+ return Roles.CHECKBOX;
159
+ if (type === "radio")
160
+ return Roles.RADIO;
161
+ if (type === "range")
162
+ return Roles.SLIDER;
163
+ if (["email", "tel", "text", "search", "url", "password"].includes(type)) {
164
+ return Roles.TEXTBOX;
165
+ }
166
+ return null;
167
+ }
168
+ function getImageRole(el) {
169
+ return el.getAttribute("alt") === "" ? Roles.PRESENTATION : Roles.IMG;
170
+ }
171
+ const implicitRoles = {
172
+ a: (el) => (el.hasAttribute("href") ? Roles.LINK : null),
173
+ button: Roles.BUTTON,
174
+ input: getInputRole,
175
+ select: (el) => (el.hasAttribute("multiple") || el.size > 1 ? Roles.LISTBOX : Roles.COMBOBOX),
176
+ textarea: Roles.TEXTBOX,
177
+ img: getImageRole,
178
+ ul: Roles.LIST,
179
+ ol: Roles.LIST,
180
+ li: Roles.LISTITEM,
181
+ table: Roles.TABLE,
182
+ th: (el) => {
183
+ const scope = el.getAttribute("scope");
184
+ if (scope === "col" || el.closest("thead")) {
185
+ return Roles.COLUMNHEADER;
186
+ }
187
+ if (scope === "row") {
188
+ return Roles.ROWHEADER;
189
+ }
190
+ // Fallback: infer based on context
191
+ const parentRow = el.closest("tr");
192
+ return parentRow && parentRow.parentNode.tagName.toLowerCase() === "thead" ? Roles.COLUMNHEADER : Roles.ROWHEADER;
193
+ },
194
+ td: Roles.CELL,
195
+ tr: Roles.ROW,
196
+ nav: Roles.NAVIGATION,
197
+ header: Roles.BANNER,
198
+ footer: Roles.CONTENTINFO,
199
+ form: (el) => (el.hasAttribute("name") ? Roles.FORM : null),
200
+ main: Roles.MAIN,
201
+ article: Roles.ARTICLE,
202
+ section: Roles.REGION,
203
+ aside: Roles.COMPLEMENTARY,
204
+ };
205
+ const role = element.getAttribute("role");
206
+ if (role) {
207
+ return role;
208
+ }
209
+ const implicitRole = implicitRoles[tagName];
210
+ return typeof implicitRole === "function" ? implicitRole(element) : implicitRole || null;
211
+ }
212
+ document.getRole = getRole;
213
+ // locator | operator | value
214
+ // table.rows | >= | 1
215
+ // table[1]["Availability"].text | equals | 100%
216
+ // table[*][2].text |not_equals| error
217
+ function processTableQuery(table, query) {
218
+ if (document.selectors && document.selectors.length > 0) {
219
+ for (let i = 0; i < document.selectors.length; i++) {
220
+ const selector = document.selectors[i];
221
+ const allElementsList = document.querySelectorAll(selector.css);
222
+ const allElements = Array.from(allElementsList);
223
+ for (let j = 0; j < allElements.length; j++) {
224
+ const element = allElements[j];
225
+ element.setAttribute("data-blinq-role", selector.changes.role);
226
+ }
227
+ }
228
+ }
229
+ const rows = Array.from(table.querySelectorAll("tr, [data-blinq-role='row'], [role='row']"));
230
+ const _rows = rows.length;
231
+ const _columnNames = [];
232
+ let _columns = 0;
233
+ let columnheader = [];
234
+ if (rows.length > 0) {
235
+ //const rowheader = rows[0];
236
+ columnheader = Array.from(table.querySelectorAll("th, [data-blinq-role='columnheader'], [role='columnheader']"));
237
+ console.log("columnheader length", columnheader.length);
238
+ _columns = columnheader.length;
239
+ for (let i = 0; i < columnheader.length; i++) {
240
+ const cell = columnheader[i];
241
+ const cellText = cell.innerText;
242
+ _columnNames.push(cellText);
243
+ }
244
+ }
245
+ let _rowStartIndex = 0;
246
+ // if (columnheader.length > 0) {
247
+ // tableData.rowStartIndex = 1;
248
+ // }
249
+ const tableData = {
250
+ rows: _rows,
251
+ columns: _columns,
252
+ columnNames: _columnNames,
253
+ rowStartIndex: _rowStartIndex,
254
+ };
255
+ if (query.startsWith("table.")) {
256
+ const result = [];
257
+ const property = query.substring(6);
258
+ //console.log("property", property);
259
+ // @ts-ignore
260
+ const value = tableData[property];
261
+ //console.log("value", value);
262
+ result.push(value);
263
+ return { cells: result };
264
+ }
265
+ const pattern = /^table\[(.+)\]\[(.+)\]\.(.+)$/;
266
+ const match = query.match(pattern);
267
+ if (!match) {
268
+ return { error: "Invalid quary" };
269
+ }
270
+ const rowSelector = match[1];
271
+ let columnSelector = match[2];
272
+ const property = match[3];
273
+ let selectedRows = [];
274
+ if (rowSelector === "*") {
275
+ selectedRows = rows;
276
+ }
277
+ else {
278
+ // @ts-ignore
279
+ if (isNaN(rowSelector)) {
280
+ return { error: "Invalid row selector" };
281
+ }
282
+ const rowIndex = parseInt(rowSelector);
283
+ if (rowIndex < 0 || rowIndex >= rows.length) {
284
+ return { error: "Invalid row selector" };
285
+ }
286
+ selectedRows.push(rows[rowIndex]);
287
+ }
288
+ console.log("selectedRows count", selectedRows.length);
289
+ const selectedCells = [];
290
+ // @ts-ignore
291
+ if (isNaN(columnSelector)) {
292
+ if (columnSelector.startsWith('"') && columnSelector.endsWith('"')) {
293
+ columnSelector = columnSelector.substring(1, columnSelector.length - 1);
294
+ }
295
+ else if (columnSelector.startsWith("'") && columnSelector.endsWith("'")) {
296
+ columnSelector = columnSelector.substring(1, columnSelector.length - 1);
297
+ }
298
+ if (columnheader.length === 0) {
299
+ return { error: "No column header available" };
300
+ }
301
+ let foundHeader = null;
302
+ for (let i = 0; i < columnheader.length; i++) {
303
+ const cell = columnheader[i];
304
+ const cellText = cell.innerText;
305
+ console.log("cellText", cellText);
306
+ if (cellText === columnSelector) {
307
+ foundHeader = cell;
308
+ break;
309
+ }
310
+ }
311
+ if (!foundHeader) {
312
+ for (let i = 0; i < columnheader.length; i++) {
313
+ const cell = columnheader[i];
314
+ const cellText = cell.innerText;
315
+ console.log("cellText", cellText);
316
+ if (cellText.includes(columnSelector)) {
317
+ foundHeader = cell;
318
+ break;
319
+ }
320
+ }
321
+ if (!foundHeader) {
322
+ return { error: "No column header found" };
323
+ }
324
+ }
325
+ const foundHeaderRec = foundHeader.getBoundingClientRect();
326
+ for (let i = 0; i < selectedRows.length; i++) {
327
+ const row = selectedRows[i];
328
+ const cells = Array.from(row.querySelectorAll("td, [data-blinq-role='cell'], [role='cell']"));
329
+ console.log("cells count", cells.length);
330
+ for (let j = 0; j < cells.length; j++) {
331
+ const cell = cells[j];
332
+ const rec = cell.getBoundingClientRect();
333
+ const xCenter = rec.left + rec.width / 2;
334
+ if (foundHeaderRec.left <= xCenter && xCenter <= foundHeaderRec.right) {
335
+ selectedCells.push(cell);
336
+ }
337
+ }
338
+ }
339
+ }
340
+ else {
341
+ const columnIndex = parseInt(columnSelector);
342
+ if (columnIndex < 0 || columnIndex >= columnheader.length) {
343
+ return { error: "Column index out of bounds" };
344
+ }
345
+ for (let i = 0; i < selectedRows.length; i++) {
346
+ const row = selectedRows[i];
347
+ const cells = Array.from(row.querySelectorAll("td, [data-blinq-role='cell'], [role='cell']"));
348
+ selectedCells.push(cells[columnIndex]);
349
+ }
350
+ }
351
+ let rect = null;
352
+ const result = [];
353
+ for (let i = 0; i < selectedCells.length; i++) {
354
+ let added = false;
355
+ if (property === "element") {
356
+ added = true;
357
+ result.push(selectedCells[i]);
358
+ }
359
+ else {
360
+ if (property === "text" || property === "innerText") {
361
+ added = true;
362
+ result.push(selectedCells[i].innerText);
363
+ }
364
+ else {
365
+ if (selectedCells[i].hasAttribute(property)) {
366
+ added = true;
367
+ result.push(selectedCells[i].getAttribute(property));
368
+ }
369
+ else {
370
+ added = true;
371
+ // @ts-ignore
372
+ result.push(selectedCells[i][property]);
373
+ }
374
+ }
375
+ if (added) {
376
+ rect = rect ? merge(rect, selectedCells[i].getBoundingClientRect()) : selectedCells[i].getBoundingClientRect();
377
+ }
378
+ }
379
+ }
380
+ return { cells: result, rect };
381
+ }
382
+ const merge = (rec1, rec2) => {
383
+ const x = Math.min(rec1.left, rec2.left);
384
+ const y = Math.min(rec1.top, rec2.top);
385
+ const width = Math.max(rec1.right, rec2.right) - x;
386
+ const height = Math.max(rec1.bottom, rec2.bottom) - y;
387
+ return { x, y, width, height };
388
+ };
389
+ // @ts-ignore
390
+ document.processTableQuery = processTableQuery;
391
+ // export type {TprocessTableQuery}
392
+ //# sourceMappingURL=locator.js.map