Skip to content

table

Table(browser, container, mapping=dict(), wait_for_seconds=10)

Bases: BaseComponent

Component: Table

Base class of Input & Configuration table

Parameters:

Name Type Description Default
browser

The selenium webdriver

required
container

Container in which the table is located. Of type dictionary: {“by”:…, “select”:…}

required
mapping

If the table headers are different from it’s html-label, provide the mapping as dictionary. For ex, {“Status”: “disabled”}

dict()
Source code in pytest_splunk_addon_ui_smartx/components/table.py
 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
def __init__(self, browser, container, mapping=dict(), wait_for_seconds=10):
    """
    :param browser: The selenium webdriver
    :param container: Container in which the table is located. Of type dictionary: {"by":..., "select":...}
    :param mapping: If the table headers are different from it's html-label, provide the mapping as dictionary. For ex, {"Status": "disabled"}
    """

    super().__init__(browser, container)
    self.header_mapping = mapping
    self.browser = browser

    self.elements.update(
        {
            "rows": Selector(
                select=container.select
                + ' tbody[data-test="body"] tr[data-test="row"]'
            ),
            "header": Selector(
                select=container.select + ' th[data-test="head-cell"]'
            ),
            "app_listings": Selector(
                select=container.select + ' tbody[data-test="body"]'
            ),
            "action_values": Selector(
                select=container.select + ' [data-test="toggle"]'
            ),
            "col": Selector(
                select=container.select
                + ' [data-test="cell"][data-column="{column}"]'
            ),
            "col-number": Selector(
                select=container.select + " td:nth-child({col_number})"
            ),
            "edit": Selector(select=".editBtn"),
            "clone": Selector(select=".cloneBtn"),
            "search": Selector(select=".searchBtn"),
            "delete": Selector(select=".deleteBtn"),
            "delete_prompt": Selector(select=".deletePrompt"),  # [data-test="body"]
            "delete_btn": Selector(select='[data-test="button"][label="Delete"]'),
            "delete_cancel": Selector(
                select='[data-test="button"][label="Cancel"]'
            ),
            "delete_close": Selector(select='[data-test="close"]'),
            "delete_loading": Selector(select='button[data-test="wait-spinner"]'),
            "waitspinner": Selector(
                select=container.select + ' [data-test="wait-spinner"]'
            ),
            "count": Selector(select=container.select + " .inputNumber"),
            "filter": Selector(select=container.select + ' [data-test="textbox"]'),
            "filter_clear": Selector(
                select=container.select + ' [data-test="clear"]'
            ),
            "more_info": Selector(
                select=container.select + ' [data-test="expand"]'
            ),
            "more_info_row": Selector(
                select=container.select + ' [data-expansion-row="true"]'
            ),
            "more_info_key": Selector(select='[data-test="term"]'),
            "more_info_value": Selector(select='[data-test="description"]'),
            "switch_to_page": Selector(
                select=container.select + " button[data-test-page]"
            ),
            "alert_sign": Selector(
                select=container.select + ' [data-test="alert-icon"]'
            ),
            "status_cell": Selector(select='[data-test="status"]'),
        }
    )
    self.wait_for_seconds = wait_for_seconds

__getattr__(key)

Makes the web-elements to be accessible directly. - For example self.elements = {“textbox”: Selector(by=…, select=…), Access the element by doing self.textbox directly. - It also has implicit wait while finding the element. :param key: The key of the element mentioned in self.elements :returns: The webelement we are accessing

Source code in pytest_splunk_addon_ui_smartx/components/table.py
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
def __getattr__(self, key):
    """
    Makes the web-elements to be accessible directly.
    - For example self.elements = {"textbox": Selector(by=..., select=...),
        Access the element by doing self.textbox directly.
    - It also has implicit wait while finding the element.
        :param key: The key of the element mentioned in self.elements
        :returns: The webelement we are accessing
    """
    # NOTE: Overriding the implementation for only table component.
    try:
        return self.get_element(key)
    except KeyError:
        raise
    except exceptions.TimeoutException:
        # in case when the element isn't found, return None
        # so that checks based on this class's properties are in sync.
        return None

check_alert_sign(row_name, column_name='account')

This function check account warning present in the table while account is not configured in input :param row_name: the name of the row :param column_name: the header name of the column

Source code in pytest_splunk_addon_ui_smartx/components/table.py
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
def check_alert_sign(self, row_name, column_name="account"):
    """
    This function check account warning present in the table while account is not configured in input
        :param row_name: the name of the row
        :param column_name: the header name of the column
    """
    column_selector = column_name.lower().replace(" ", "_")
    column_selector = self.header_mapping.get(column_selector, column_name)

    col = copy.deepcopy(self.elements["alert_sign"])
    col = col._replace(select=col.select.format(column=column_selector))

    _row = self._get_row(row_name)
    try:
        _row.find_element(*list(col._asdict().values()))
        return True
    except exceptions.NoSuchElementException:
        return False

clean_filter()

Clean the filter textbox

Source code in pytest_splunk_addon_ui_smartx/components/table.py
419
420
421
422
423
424
def clean_filter(self):
    """
    Clean the filter textbox
    """
    self.filter.clear()
    self._wait_for_loadspinner()

clone_row(name)

Clone the specified row. It will open the edit form(entity). The opened entity should be interacted with instance of entity-class only. :param name: row_name of the table

Source code in pytest_splunk_addon_ui_smartx/components/table.py
348
349
350
351
352
353
354
def clone_row(self, name):
    """
    Clone the specified row. It will open the edit form(entity). The opened entity should be interacted with instance of entity-class only.
        :param name: row_name of the table
    """
    _row = self._get_row(name)
    _row.find_element(*list(self.elements["clone"]._asdict().values())).click()

delete_row(name, cancel=False, close=False, prompt_msg=False)

Delete the specified row. Clicking on delete will open a pop-up. Delete the row if neither of (cancel, close) specified. :param name: row_name of the table :param cancel: if provided, after the popup is opened, click on cancel button and Do Not delete the row :param close: if provided, after the popup is opened, click on close button and Do Not delete the row :return: Bool Returns true if successful or returns the string of the delete prompt if looking for prompt message

Source code in pytest_splunk_addon_ui_smartx/components/table.py
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
def delete_row(self, name, cancel=False, close=False, prompt_msg=False):
    """
    Delete the specified row. Clicking on delete will open a pop-up. Delete the row if neither of (cancel, close) specified.
        :param name: row_name of the table
        :param cancel: if provided, after the popup is opened, click on cancel button and Do Not delete the row
        :param close:  if provided, after the popup is opened, click on close button and Do Not delete the row
        :return: Bool Returns true if successful or returns the string of the delete prompt if looking for prompt message
    """

    # Click on action
    with self.wait_stale():
        _row = self._get_row(name)
        time.sleep(0.5)
        _row.find_element(*list(self.elements["delete"]._asdict().values())).click()

        self.wait_for("delete_prompt")
        if cancel:
            self.wait_to_be_clickable("delete_cancel")
            self.delete_cancel.click()
            self.wait_until("delete_cancel")
            return True
        elif close:
            self.delete_close.click()
            self.wait_until("delete_close")
            return True
        elif prompt_msg:
            self.wait_for_text("delete_prompt")
            return self.get_clear_text(self.delete_prompt)
        else:
            self.wait_to_be_clickable("delete_btn")
            self.delete_btn.click()
            self.wait_until("waitspinner")

edit_row(name)

Edit the specified row. It will open the edit form(entity). The opened entity should be interacted with instance of entity-class only. :param name: row_name of the table

Source code in pytest_splunk_addon_ui_smartx/components/table.py
340
341
342
343
344
345
346
def edit_row(self, name):
    """
    Edit the specified row. It will open the edit form(entity). The opened entity should be interacted with instance of entity-class only.
        :param name: row_name of the table
    """
    _row = self._get_row(name)
    _row.find_element(*list(self.elements["edit"]._asdict().values())).click()

get_action_values(name)

Get the specified rows action values :param name: row name :return: List Gets the action values of the row specified within the table

Source code in pytest_splunk_addon_ui_smartx/components/table.py
471
472
473
474
475
476
477
478
479
480
def get_action_values(self, name):
    """
    Get the specified rows action values
        :param name: row name
        :return: List Gets the action values of the row specified within the table
    """
    _row = self._get_row(name)
    return [
        self.get_clear_text(each) for each in self.get_elements("action_values")
    ]

get_cell_value(name, column)

Get a specific cell value. :param name: row_name of the table :param column: column header of the table :return: str The value within the cell that we are looking for

Source code in pytest_splunk_addon_ui_smartx/components/table.py
284
285
286
287
288
289
290
291
292
293
294
def get_cell_value(self, name, column):
    """
    Get a specific cell value.
        :param name: row_name of the table
        :param column: column header of the table
        :return: str The value within the cell that we are looking for
    """
    _row = self._get_row(name)
    if column.lower() == "status":
        return _row.find_element_by_css_selector('[data-test="status"]').text
    return self._get_column_value(_row, column)

get_column_values(column)

Get list of values of column :param column: column header of the table :return: List The values within the certain column

Source code in pytest_splunk_addon_ui_smartx/components/table.py
296
297
298
299
300
301
302
303
304
305
def get_column_values(self, column):
    """
    Get list of values of  column
        :param column: column header of the table
        :return: List The values within the certain column
    """
    value_list = []
    for each_row in self._get_rows():
        value_list.append(self._get_column_value(each_row, column))
    return value_list

get_count_number()

Returns the count from the title of the table. :return: Int The title count of the table.

Source code in pytest_splunk_addon_ui_smartx/components/table.py
482
483
484
485
486
487
488
def get_count_number(self):
    """
    Returns the count from the title of the table.
        :return: Int The title count of the table.
    """
    row_count = self.get_count_title()
    return int(re.search(r"\d+", row_count).group())

get_count_title()

Get the count mentioned in the table title :return: Str The count of the table title

Source code in pytest_splunk_addon_ui_smartx/components/table.py
109
110
111
112
113
114
def get_count_title(self):
    """
    Get the count mentioned in the table title
        :return: Str The count of the table title
    """
    return self.get_clear_text(self.count)

get_headers()

Get list of headers from the table :return: Generator for Str list The headers in the table

Source code in pytest_splunk_addon_ui_smartx/components/table.py
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
def get_headers(self):
    """
    Get list of headers from the table
        :return: Generator for Str list The headers in the table
    """
    headers = []
    GET_PARENT_ELEMENT = (
        "var parent = arguments[0].firstChild.firstChild;if(parent.hasChildNodes()){var r='';var C=parent.childNodes;"
        "for(var n=0;n<C.length;n++){if(C[n].nodeType==Node.TEXT_NODE){r+=' '+C[n].nodeValue}}"
        "return r.trim()}else{return parent.innerText}"
    )
    for each in self.get_elements("header"):
        parent_text = self.browser.execute_script(GET_PARENT_ELEMENT, each)
        headers.append(parent_text)

    return headers

get_list_of_actions(name)

Get list of possible actions for a specific row :param name: The name of the row :return: Generator List The list of actions available within a certain row of the table

Source code in pytest_splunk_addon_ui_smartx/components/table.py
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
def get_list_of_actions(self, name):
    """
    Get list of possible actions for a specific row
        :param name: The name of the row
        :return: Generator List The list of actions available within a certain row of the table
    """
    value_list = []
    _row = self._get_row(name)
    # use `find_elements` over `find_element` to avoid NoSuchElementException exception when
    # the action isn't present + to verify only 1 icon of the action is present
    if (
        len(_row.find_elements(*list(self.elements["edit"]._asdict().values())))
        == 1
    ):
        value_list.append("Edit")
    if (
        len(_row.find_elements(*list(self.elements["clone"]._asdict().values())))
        == 1
    ):
        value_list.append("Clone")
    if (
        len(_row.find_elements(*list(self.elements["search"]._asdict().values())))
        == 1
    ):
        value_list.append("Search")
    if (
        len(_row.find_elements(*list(self.elements["delete"]._asdict().values())))
        == 1
    ):
        value_list.append("Delete")

    return value_list

get_more_info(name, cancel=True)

Returns the text from the more info field within a tables row :param name: Str row name :param cancel: Bool Whether or not to click cancel after getting the info :return: Dict The information found when opening the info table on a row in the table

Source code in pytest_splunk_addon_ui_smartx/components/table.py
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
def get_more_info(self, name, cancel=True):
    """
    Returns the text from the more info field within a tables row
        :param name: Str row name
        :param cancel: Bool Whether or not to click cancel after getting the info
        :return: Dict The information found when opening the info table on a row in the table
    """
    _row = self._get_row(name)
    _row.find_element(*list(self.elements["more_info"]._asdict().values())).click()
    keys = self.more_info_row.find_elements(
        *list(self.elements["more_info_key"]._asdict().values())
    )
    values = self.more_info_row.find_elements(
        *list(self.elements["more_info_value"]._asdict().values())
    )
    more_info = {
        self.get_clear_text(key): self.get_clear_text(value)
        for key, value in zip(keys, values)
    }

    if cancel:
        _row = self._get_row(name)
        _row.find_element(
            *list(self.elements["more_info"]._asdict().values())
        ).click()

    return more_info

get_row_count()

Count the number of rows in the page. :return: Int The count of the table rows

Source code in pytest_splunk_addon_ui_smartx/components/table.py
116
117
118
119
120
121
def get_row_count(self):
    """
    Count the number of rows in the page.
        :return: Int The count of the table rows
    """
    return len(list(self._get_rows()))

get_sort_order()

Get the column-header which is sorted rn. Warning: It depends on the class of the headers and due to it, the returned result might give wrong answer.

:returns: a dictionary with the "header" & "ascending" order
Source code in pytest_splunk_addon_ui_smartx/components/table.py
140
141
142
143
144
145
146
147
148
149
150
151
def get_sort_order(self):
    """
    Get the column-header which is sorted rn.
        Warning: It depends on the class of the headers and due to it, the returned result might give wrong answer.

        :returns: a dictionary with the "header" & "ascending" order
    """
    for each_header in self.get_elements("header"):
        if each_header.get_attribute("data-test-sort-dir") == "asc":
            return {"header": self.get_clear_text(each_header), "ascending": True}
        elif each_header.get_attribute("data-test-sort-dir") == "desc":
            return {"header": self.get_clear_text(each_header), "ascending": False}

get_table()

Get whole table in dictionary form. The row_name will will be the key and all header:values will be it’s value. {row_1 : {header_1: value_1, . . .}, . . .} :return: dict The data within the table

Source code in pytest_splunk_addon_ui_smartx/components/table.py
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
def get_table(self):
    """
    Get whole table in dictionary form. The row_name will will be the key and all header:values will be it's value. {row_1 : {header_1: value_1, . . .}, . . .}
        :return: dict The data within the table
    """

    table = dict()
    headers = list(self.get_headers())

    for each_row in self._get_rows():
        row_name = self._get_column_value(each_row, "name")
        table[row_name] = dict()
        for each_col in headers:
            each_col = each_col.lower()
            if each_col == "actions":
                table[row_name][each_col] = ""
                if self.edit != None:
                    table[row_name][each_col] = "Edit"
                if self.clone != None:
                    table[row_name][each_col] += " | Clone"
                if self.search != None:
                    table[row_name][each_col] += " | Search"
                if self.delete != None:
                    table[row_name][each_col] += " | Delete"
                continue
            if each_col == "status":
                table[row_name][each_col] = each_row.find_element_by_css_selector(
                    '[data-test="status"]'
                ).text
                continue
            if each_col:
                table[row_name][each_col] = self._get_column_value(
                    each_row, each_col
                )
    return table

search_row_results(name)

Search the results of the selected input. It will open the search and its results in a new tab. :param name: row_name of the table

Source code in pytest_splunk_addon_ui_smartx/components/table.py
356
357
358
359
360
361
362
def search_row_results(self, name):
    """
    Search the results of the selected input. It will open the search and its results in a new tab.
        :param name: row_name of the table
    """
    _row = self._get_row(name)
    _row.find_element(*list(self.elements["search"]._asdict().values())).click()

set_filter(filter_query)

Provide a string in table filter. :param filter_query: query of the filter :returns: resultant list of filtered row_names

Source code in pytest_splunk_addon_ui_smartx/components/table.py
397
398
399
400
401
402
403
404
405
406
407
def set_filter(self, filter_query):
    """
    Provide a string in table filter.
        :param filter_query: query of the filter
        :returns: resultant list of filtered row_names
    """
    with self.wait_stale():
        self.filter.clear()
        self.filter.send_keys(filter_query)
        self._wait_for_loadspinner()
    return self.get_column_values("name")

sort_column(column, ascending=True)

Sort a column in ascending or descending order :param column: The header of the column which should be sorted :param ascending: True if the column should be sorted in ascending order, False otherwise

Source code in pytest_splunk_addon_ui_smartx/components/table.py
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
def sort_column(self, column, ascending=True):
    """
    Sort a column in ascending or descending order
        :param column: The header of the column which should be sorted
        :param ascending: True if the column should be sorted in ascending order, False otherwise
    """
    for each_header in self.get_elements("header"):
        if self.get_clear_text(each_header).lower() == column.lower():
            if (
                "asc" in each_header.get_attribute("data-test-sort-dir")
                and ascending
            ):
                # If the column is already in ascending order, do nothing
                return
            elif (
                "asc" in each_header.get_attribute("data-test-sort-dir")
                and not ascending
            ):
                # If the column is in ascending order order and we want to have descending order, click on the column-header once
                each_header.click()
                self._wait_for_loadspinner()
                return
            elif (
                "desc" in each_header.get_attribute("data-test-sort-dir")
                and not ascending
            ):
                # If the column is already in descending order, do nothing
                return
            elif (
                "desc" in each_header.get_attribute("data-test-sort-dir")
                and ascending
            ):
                # If the column is in descending order order and we want to have ascending order, click on the column-header once
                each_header.click()
                self._wait_for_loadspinner()
                return
            else:
                # The column was not sorted before
                if ascending:
                    # Click to sort ascending order
                    each_header.click()
                    self._wait_for_loadspinner()
                    return
                else:
                    # Click 2 times to sort in descending order

                    # Ascending
                    each_header.click()
                    self._wait_for_loadspinner()
                    # Decending
                    # The existing element changes (class will be changed), hence, it can not be referenced again.
                    # So we need to get the headers again and do the same process.
                    self.sort_column(column, ascending=False)
                    return

switch_to_next()

Switches the table’s page forward by 1 :return: Bool whether or not switching to the next page was successful

Source code in pytest_splunk_addon_ui_smartx/components/table.py
547
548
549
550
551
552
553
554
555
556
557
def switch_to_next(self):
    """
    Switches the table's page forward by 1
        :return: Bool whether or not switching to the next page was successful
    """
    for page_next in self.get_elements("switch_to_page"):
        if self.get_clear_text(page_next).lower() == "next":
            page_next.click()
            return True
    else:
        raise ValueError("{} not found".format(page_next))

switch_to_page(value)

Switches the table to specified page :param value: Int The page to switch the table to :return: Bool whether or not switching to the page was successful

Source code in pytest_splunk_addon_ui_smartx/components/table.py
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
def switch_to_page(self, value):
    """
    Switches the table to specified page
        :param value: Int The page to switch the table to
        :return: Bool whether or not switching to the page was successful

    """
    for each in self.get_elements("switch_to_page"):
        if self.get_clear_text(each).lower() not in [
            "prev",
            "next",
        ] and self.get_clear_text(each) == str(value):
            each.click()
            return True
    else:
        raise ValueError("{} not found".format(value))

switch_to_prev()

Switches the table’s page back by 1 :return: Bool whether or not switching to the previous page was successful

Source code in pytest_splunk_addon_ui_smartx/components/table.py
535
536
537
538
539
540
541
542
543
544
545
def switch_to_prev(self):
    """
    Switches the table's page back by 1
        :return: Bool whether or not switching to the previous page was successful
    """
    for page_prev in self.get_elements("switch_to_page"):
        if self.get_clear_text(page_prev).lower() == "prev":
            page_prev.click()
            return True
    else:
        raise ValueError("{} not found".format(page_prev))

wait_for_column_to_appear(column_name)

Wait for the table to load the column with the given column name. :param column_name: Name of the column to wait for.

Source code in pytest_splunk_addon_ui_smartx/components/table.py
234
235
236
237
238
239
240
241
242
243
244
245
246
def wait_for_column_to_appear(self, column_name):
    """
    Wait for the table to load the column with the given column name.
        :param column_name: Name of the column to wait for.
    """

    def _wait_for_column_to_appear(driver):
        return column_name in self.get_headers()

    self.wait_for(
        _wait_for_column_to_appear,
        msg="Column {} not found in the table".format(column_name),
    )

wait_for_rows_to_appear(row_count=1)

Wait for the table to load row_count rows :param row_count: number of row_count to wait for.

Source code in pytest_splunk_addon_ui_smartx/components/table.py
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
def wait_for_rows_to_appear(self, row_count=1):
    """
    Wait for the table to load row_count rows
        :param row_count: number of row_count to wait for.
    """

    def _wait_for_rows_to_appear(driver):
        return self.get_row_count() >= row_count

    self.wait_for(
        _wait_for_rows_to_appear,
        msg="Expected rows : {} to be greater or equal to {}".format(
            row_count, self.get_row_count()
        ),
    )