Skip to content

ZTPConfigTab

Модуль вкладки 'Конфигурация' в модуле Zero Touch Provisioning.

Содержит класс ZTPConfigTab для работы с таблицей конфигурации ZTP. Позволяет проверять состояние и взаимодействовать с элементами вкладки.

ZTPConfigTab

Bases: BasePage

Класс для работы с вкладкой 'Конфигурация' в модуле Zero Touch Provisioning.

Предоставляет методы для взаимодействия с таблицей конфигурации ZTP и проверки состояния элементов интерфейса. Включает функциональность для: - Проверки содержимого и структуры таблицы конфигурации - Прокрутки таблицы и проверки видимости строк - Выделения строк таблицы - Работы с кнопкой синхронизации (Reload) в заголовке таблицы - Проверки видимости и подсказок кнопок синхронизации

Parameters:

Name Type Description Default
page Page

Экземпляр страницы Playwright.

required
Source code in pages\ztp_config_tab.py
 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
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
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
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
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
class ZTPConfigTab(BasePage):
    """Класс для работы с вкладкой 'Конфигурация' в модуле Zero Touch Provisioning.

    Предоставляет методы для взаимодействия с таблицей конфигурации ZTP
    и проверки состояния элементов интерфейса. Включает функциональность для:
    - Проверки содержимого и структуры таблицы конфигурации
    - Прокрутки таблицы и проверки видимости строк
    - Выделения строк таблицы
    - Работы с кнопкой синхронизации (Reload) в заголовке таблицы
    - Проверки видимости и подсказок кнопок синхронизации

    Args:
        page (Page): Экземпляр страницы Playwright.
    """

    def __init__(self, page: Page) -> None:
        """Инициализирует компоненты вкладки 'Конфигурация'.

        Args:
            page: Экземпляр страницы Playwright для взаимодействия с браузером.
        """
        super().__init__(page)

        # Компонент тулбара вкладки конфигурации
        self.toolbar = ToolbarComponent(page, "Конфигурация")

        # Компонент таблицы конфигурации ZTP
        self.ztp_config_table = TableComponent(page)

        # Словарь для хранения кнопок синхронизации по индексам
        self.sync_buttons = {}

    def get_rows_count(self) -> int:
        """Возвращает количество строк в таблице конфигурации (без заголовка).

        Returns:
            int: Количество строк с данными конфигурации ZTP.

        Raises:
            AssertionError: Если таблица пуста или не загружена.
        """
        return self.ztp_config_table.get_rows_count(TableLocators.TABLE_WORK_AREA)

    def scroll_config_table_up(self) -> None:
        """Прокручивает таблицу конфигурации вверх до начала."""
        self.ztp_config_table.scroll_up(TableLocators.TABLE_SCROLL_CONTAINER)

    def scroll_config_table_down(self) -> None:
        """Прокручивает таблицу конфигурации вниз до конца."""
        self.ztp_config_table.scroll_down(TableLocators.TABLE_SCROLL_CONTAINER)

    def check_config_table_content(self) -> None:
        """Проверяет содержимое таблицы конфигурации ZTP.

        Проверяет соответствие заголовков таблицы ожидаемым значениям
        и наличие данных в таблице.

        Raises:
            AssertionError: Если таблица пуста или заголовки не соответствуют ожидаемым.
        """
        # Ожидаемые заголовки столбцов таблицы конфигурации ZTP
        expected_headers = [
            'sync',
            'IDENTIFIER',
            'MAC',
            'DHCPRELAY',
            'ШАБЛОН',
            'IPSETTODEVICE',
            'СТАТУС',
            'ДЕЙСТВИЯ'
        ]

        self.ztp_config_table.check_content(
            TableLocators.TABLE_WORK_AREA,
            expected_headers,
            False
        )

    def should_be_config_table(self) -> None:
        """Проверяет наличие и видимость таблицы конфигурации ZTP.

        Raises:
            AssertionError: Если таблица конфигурации отсутствует на странице.
        """
        self.ztp_config_table.check_visibility(
            TableLocators.TABLE_WORK_AREA, "Configuration table is missing"
        )

    def get_sync_button(self, index: int) -> Locator:
        """Получает кнопку синхронизации (Reload) по индексу ячейки заголовка таблицы.

        Args:
            index: Индекс ячейки в заголовке таблицы (0-based).

        Returns:
            Locator: Локатор кнопки синхронизации (Reload) для взаимодействия.

        Raises:
            AssertionError: Если индекс выходит за пределы диапазона ячеек
                          или кнопка не найдена в указанной ячейке.
        """
        table_locator = TableLocators.TABLE_WORK_AREA

        # Получаем локатор таблицы через компонент таблицы
        table = self.ztp_config_table.get_locator(table_locator)

        # Проверяем количество ячеек в заголовке таблицы
        header_cells_count = table.locator("//thead/tr/th").count()
        assert index in range(header_cells_count), "Header cell index is out of range"

        # Ищем кнопку в указанной ячейке заголовка
        sync_button = table.locator("//thead/tr/th").nth(index).get_by_role("button")
        assert sync_button.is_enabled(), f"Sync button is missing in {index} header cell"

        return sync_button

    def add_sync_button_to_toolbar(self, index: int) -> None:
        """Добавляет кнопку синхронизации (Reload) в тулбар для управления подсказками.

        Регистрирует кнопку в компоненте тулбара, что позволяет использовать
        стандартные методы проверки подсказок.

        Args:
            index: Индекс ячейки в заголовке таблицы.
        """
        sync_button = self.get_sync_button(index)
        button_name = f"sync_button_{index}"

        # Добавляем кнопку в тулбар компонент как кнопку с подсказкой
        self.toolbar.add_tooltip_button(sync_button, button_name)

        # Сохраняем связь между индексом и именем кнопки для последующего доступа
        self.sync_buttons[index] = button_name

        logger.info("Кнопка синхронизации (Reload) добавлена в тулбар как '%s'", button_name)

    def check_sync_button_visibility(self, index: int) -> None:
        """Проверяет видимость кнопки синхронизации (Reload) в указанной ячейке заголовка.

        Args:
            index: Индекс ячейки в заголовке таблицы.

        Raises:
            AssertionError: Если кнопка не видна на странице.
        """
        sync_button = self.get_sync_button(index)

        # Прокручиваем к элементу для гарантии видимости
        sync_button.scroll_into_view_if_needed()

        # Проверяем видимость кнопки
        assert sync_button.is_visible(), f"Sync button in header cell {index} is not visible"

        logger.info("Кнопка синхронизации (Reload) видима")

    def check_sync_button_tooltip(self, index: int, expected_tooltip: str = "reload") -> None:
        """Проверяет текст подсказки кнопки синхронизации (Reload).

        Использует стандартный механизм проверки подсказок из ToolbarComponent.

        Args:
            index: Индекс ячейки в заголовке таблицы.
            expected_tooltip: Ожидаемый текст подсказки (по умолчанию 'reload').

        Raises:
            AssertionError: Если подсказка не соответствует ожидаемой или отсутствует.
        """
        # Убеждаемся, что кнопка зарегистрирована в тулбаре
        if index not in self.sync_buttons:
            self.add_sync_button_to_toolbar(index)

        button_name = self.sync_buttons[index]

        # Проверка подсказки
        self.toolbar.check_button_tooltip(button_name, expected_tooltip)

        logger.info(
            "Подсказка кнопки синхронизации (Reload) в ячейке %d: '%s'",
            index,
            expected_tooltip
        )

    def click_sync_button(self, index: int) -> None:
        """Нажимает кнопку 'Reload' в указанной ячейке заголовка таблицы.

        Перед кликом проверяет видимость кнопки.

        Args:
            index: Индекс ячейки в заголовке таблицы.

        Raises:
            AssertionError: Если индекс выходит за пределы или кнопка не найдена.
        """
        sync_button = self.get_sync_button(index)

        # Проверяем видимость перед кликом
        self.check_sync_button_visibility(index)

        # Выполняем клик по кнопке
        sync_button.click()
        logger.info("Нажата кнопка синхронизации (Reload)")

    def check_config_table_vertical_scrolling(self) -> bool:
        """Проверяет возможность вертикальной прокрутки таблицы конфигурации.

        Returns:
            bool: True если таблица поддерживает вертикальную прокрутку, иначе False.
        """
        return self.ztp_config_table.is_scrollable_vertically(
            TableLocators.TABLE_SCROLL_CONTAINER
        )

    def check_config_table_first_row_visibility(self) -> None:
        """Проверяет видимость первой строки таблицы конфигурации.

        Raises:
            AssertionError: Если первая строка таблицы не видна.
        """
        self.ztp_config_table.check_first_row_visibility(TableLocators.TABLE_WORK_AREA)

    def check_config_table_last_row_visibility(self) -> None:
        """Проверяет видимость последней строки таблицы конфигурации.

        Raises:
            AssertionError: Если последняя строка таблицы не видна.
        """
        self.ztp_config_table.check_last_row_visibility(TableLocators.TABLE_WORK_AREA)

    def check_config_table_row_highlighting(self, row_index: int) -> None:
        """Проверяет выделение указанной строки таблицы конфигурации.

        Args:
            row_index: Индекс проверяемой строки (0-based, без учета заголовка).

        Raises:
            AssertionError: Если строка не выделена после взаимодействия.
        """
        self.ztp_config_table.check_row_highlighting(
            TableLocators.TABLE_WORK_AREA, row_index
        )

    def should_be_toolbar(self) -> None:
        """Проверяет наличие и видимость тулбара на вкладке конфигурации.

        Raises:
            AssertionError: Если тулбар отсутствует на странице.
        """
        self.toolbar.check_toolbar_presence("Toolbar is missing")

    def should_be_config_table(self) -> None:
        """Проверяет наличие и видимость таблицы конфигурации ZTP.

        Raises:
            AssertionError: Если таблица конфигурации отсутствует на странице.
        """
        self.ztp_config_table.check_visibility(
            TableLocators.TABLE_WORK_AREA, "Configuration table is missing"
        )

__init__(page)

Инициализирует компоненты вкладки 'Конфигурация'.

Parameters:

Name Type Description Default
page Page

Экземпляр страницы Playwright для взаимодействия с браузером.

required
Source code in pages\ztp_config_tab.py
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
def __init__(self, page: Page) -> None:
    """Инициализирует компоненты вкладки 'Конфигурация'.

    Args:
        page: Экземпляр страницы Playwright для взаимодействия с браузером.
    """
    super().__init__(page)

    # Компонент тулбара вкладки конфигурации
    self.toolbar = ToolbarComponent(page, "Конфигурация")

    # Компонент таблицы конфигурации ZTP
    self.ztp_config_table = TableComponent(page)

    # Словарь для хранения кнопок синхронизации по индексам
    self.sync_buttons = {}

add_sync_button_to_toolbar(index)

Добавляет кнопку синхронизации (Reload) в тулбар для управления подсказками.

Регистрирует кнопку в компоненте тулбара, что позволяет использовать стандартные методы проверки подсказок.

Parameters:

Name Type Description Default
index int

Индекс ячейки в заголовке таблицы.

required
Source code in pages\ztp_config_tab.py
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
def add_sync_button_to_toolbar(self, index: int) -> None:
    """Добавляет кнопку синхронизации (Reload) в тулбар для управления подсказками.

    Регистрирует кнопку в компоненте тулбара, что позволяет использовать
    стандартные методы проверки подсказок.

    Args:
        index: Индекс ячейки в заголовке таблицы.
    """
    sync_button = self.get_sync_button(index)
    button_name = f"sync_button_{index}"

    # Добавляем кнопку в тулбар компонент как кнопку с подсказкой
    self.toolbar.add_tooltip_button(sync_button, button_name)

    # Сохраняем связь между индексом и именем кнопки для последующего доступа
    self.sync_buttons[index] = button_name

    logger.info("Кнопка синхронизации (Reload) добавлена в тулбар как '%s'", button_name)

check_config_table_content()

Проверяет содержимое таблицы конфигурации ZTP.

Проверяет соответствие заголовков таблицы ожидаемым значениям и наличие данных в таблице.

Raises:

Type Description
AssertionError

Если таблица пуста или заголовки не соответствуют ожидаемым.

Source code in pages\ztp_config_tab.py
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
def check_config_table_content(self) -> None:
    """Проверяет содержимое таблицы конфигурации ZTP.

    Проверяет соответствие заголовков таблицы ожидаемым значениям
    и наличие данных в таблице.

    Raises:
        AssertionError: Если таблица пуста или заголовки не соответствуют ожидаемым.
    """
    # Ожидаемые заголовки столбцов таблицы конфигурации ZTP
    expected_headers = [
        'sync',
        'IDENTIFIER',
        'MAC',
        'DHCPRELAY',
        'ШАБЛОН',
        'IPSETTODEVICE',
        'СТАТУС',
        'ДЕЙСТВИЯ'
    ]

    self.ztp_config_table.check_content(
        TableLocators.TABLE_WORK_AREA,
        expected_headers,
        False
    )

check_config_table_first_row_visibility()

Проверяет видимость первой строки таблицы конфигурации.

Raises:

Type Description
AssertionError

Если первая строка таблицы не видна.

Source code in pages\ztp_config_tab.py
229
230
231
232
233
234
235
def check_config_table_first_row_visibility(self) -> None:
    """Проверяет видимость первой строки таблицы конфигурации.

    Raises:
        AssertionError: Если первая строка таблицы не видна.
    """
    self.ztp_config_table.check_first_row_visibility(TableLocators.TABLE_WORK_AREA)

check_config_table_last_row_visibility()

Проверяет видимость последней строки таблицы конфигурации.

Raises:

Type Description
AssertionError

Если последняя строка таблицы не видна.

Source code in pages\ztp_config_tab.py
237
238
239
240
241
242
243
def check_config_table_last_row_visibility(self) -> None:
    """Проверяет видимость последней строки таблицы конфигурации.

    Raises:
        AssertionError: Если последняя строка таблицы не видна.
    """
    self.ztp_config_table.check_last_row_visibility(TableLocators.TABLE_WORK_AREA)

check_config_table_row_highlighting(row_index)

Проверяет выделение указанной строки таблицы конфигурации.

Parameters:

Name Type Description Default
row_index int

Индекс проверяемой строки (0-based, без учета заголовка).

required

Raises:

Type Description
AssertionError

Если строка не выделена после взаимодействия.

Source code in pages\ztp_config_tab.py
245
246
247
248
249
250
251
252
253
254
255
256
def check_config_table_row_highlighting(self, row_index: int) -> None:
    """Проверяет выделение указанной строки таблицы конфигурации.

    Args:
        row_index: Индекс проверяемой строки (0-based, без учета заголовка).

    Raises:
        AssertionError: Если строка не выделена после взаимодействия.
    """
    self.ztp_config_table.check_row_highlighting(
        TableLocators.TABLE_WORK_AREA, row_index
    )

check_config_table_vertical_scrolling()

Проверяет возможность вертикальной прокрутки таблицы конфигурации.

Returns:

Name Type Description
bool bool

True если таблица поддерживает вертикальную прокрутку, иначе False.

Source code in pages\ztp_config_tab.py
219
220
221
222
223
224
225
226
227
def check_config_table_vertical_scrolling(self) -> bool:
    """Проверяет возможность вертикальной прокрутки таблицы конфигурации.

    Returns:
        bool: True если таблица поддерживает вертикальную прокрутку, иначе False.
    """
    return self.ztp_config_table.is_scrollable_vertically(
        TableLocators.TABLE_SCROLL_CONTAINER
    )

check_sync_button_tooltip(index, expected_tooltip='reload')

Проверяет текст подсказки кнопки синхронизации (Reload).

Использует стандартный механизм проверки подсказок из ToolbarComponent.

Parameters:

Name Type Description Default
index int

Индекс ячейки в заголовке таблицы.

required
expected_tooltip str

Ожидаемый текст подсказки (по умолчанию 'reload').

'reload'

Raises:

Type Description
AssertionError

Если подсказка не соответствует ожидаемой или отсутствует.

Source code in pages\ztp_config_tab.py
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
def check_sync_button_tooltip(self, index: int, expected_tooltip: str = "reload") -> None:
    """Проверяет текст подсказки кнопки синхронизации (Reload).

    Использует стандартный механизм проверки подсказок из ToolbarComponent.

    Args:
        index: Индекс ячейки в заголовке таблицы.
        expected_tooltip: Ожидаемый текст подсказки (по умолчанию 'reload').

    Raises:
        AssertionError: Если подсказка не соответствует ожидаемой или отсутствует.
    """
    # Убеждаемся, что кнопка зарегистрирована в тулбаре
    if index not in self.sync_buttons:
        self.add_sync_button_to_toolbar(index)

    button_name = self.sync_buttons[index]

    # Проверка подсказки
    self.toolbar.check_button_tooltip(button_name, expected_tooltip)

    logger.info(
        "Подсказка кнопки синхронизации (Reload) в ячейке %d: '%s'",
        index,
        expected_tooltip
    )

check_sync_button_visibility(index)

Проверяет видимость кнопки синхронизации (Reload) в указанной ячейке заголовка.

Parameters:

Name Type Description Default
index int

Индекс ячейки в заголовке таблицы.

required

Raises:

Type Description
AssertionError

Если кнопка не видна на странице.

Source code in pages\ztp_config_tab.py
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
def check_sync_button_visibility(self, index: int) -> None:
    """Проверяет видимость кнопки синхронизации (Reload) в указанной ячейке заголовка.

    Args:
        index: Индекс ячейки в заголовке таблицы.

    Raises:
        AssertionError: Если кнопка не видна на странице.
    """
    sync_button = self.get_sync_button(index)

    # Прокручиваем к элементу для гарантии видимости
    sync_button.scroll_into_view_if_needed()

    # Проверяем видимость кнопки
    assert sync_button.is_visible(), f"Sync button in header cell {index} is not visible"

    logger.info("Кнопка синхронизации (Reload) видима")

click_sync_button(index)

Нажимает кнопку 'Reload' в указанной ячейке заголовка таблицы.

Перед кликом проверяет видимость кнопки.

Parameters:

Name Type Description Default
index int

Индекс ячейки в заголовке таблицы.

required

Raises:

Type Description
AssertionError

Если индекс выходит за пределы или кнопка не найдена.

Source code in pages\ztp_config_tab.py
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
def click_sync_button(self, index: int) -> None:
    """Нажимает кнопку 'Reload' в указанной ячейке заголовка таблицы.

    Перед кликом проверяет видимость кнопки.

    Args:
        index: Индекс ячейки в заголовке таблицы.

    Raises:
        AssertionError: Если индекс выходит за пределы или кнопка не найдена.
    """
    sync_button = self.get_sync_button(index)

    # Проверяем видимость перед кликом
    self.check_sync_button_visibility(index)

    # Выполняем клик по кнопке
    sync_button.click()
    logger.info("Нажата кнопка синхронизации (Reload)")

get_rows_count()

Возвращает количество строк в таблице конфигурации (без заголовка).

Returns:

Name Type Description
int int

Количество строк с данными конфигурации ZTP.

Raises:

Type Description
AssertionError

Если таблица пуста или не загружена.

Source code in pages\ztp_config_tab.py
49
50
51
52
53
54
55
56
57
58
def get_rows_count(self) -> int:
    """Возвращает количество строк в таблице конфигурации (без заголовка).

    Returns:
        int: Количество строк с данными конфигурации ZTP.

    Raises:
        AssertionError: Если таблица пуста или не загружена.
    """
    return self.ztp_config_table.get_rows_count(TableLocators.TABLE_WORK_AREA)

get_sync_button(index)

Получает кнопку синхронизации (Reload) по индексу ячейки заголовка таблицы.

Parameters:

Name Type Description Default
index int

Индекс ячейки в заголовке таблицы (0-based).

required

Returns:

Name Type Description
Locator Locator

Локатор кнопки синхронизации (Reload) для взаимодействия.

Raises:

Type Description
AssertionError

Если индекс выходит за пределы диапазона ячеек или кнопка не найдена в указанной ячейке.

Source code in pages\ztp_config_tab.py
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
def get_sync_button(self, index: int) -> Locator:
    """Получает кнопку синхронизации (Reload) по индексу ячейки заголовка таблицы.

    Args:
        index: Индекс ячейки в заголовке таблицы (0-based).

    Returns:
        Locator: Локатор кнопки синхронизации (Reload) для взаимодействия.

    Raises:
        AssertionError: Если индекс выходит за пределы диапазона ячеек
                      или кнопка не найдена в указанной ячейке.
    """
    table_locator = TableLocators.TABLE_WORK_AREA

    # Получаем локатор таблицы через компонент таблицы
    table = self.ztp_config_table.get_locator(table_locator)

    # Проверяем количество ячеек в заголовке таблицы
    header_cells_count = table.locator("//thead/tr/th").count()
    assert index in range(header_cells_count), "Header cell index is out of range"

    # Ищем кнопку в указанной ячейке заголовка
    sync_button = table.locator("//thead/tr/th").nth(index).get_by_role("button")
    assert sync_button.is_enabled(), f"Sync button is missing in {index} header cell"

    return sync_button

scroll_config_table_down()

Прокручивает таблицу конфигурации вниз до конца.

Source code in pages\ztp_config_tab.py
64
65
66
def scroll_config_table_down(self) -> None:
    """Прокручивает таблицу конфигурации вниз до конца."""
    self.ztp_config_table.scroll_down(TableLocators.TABLE_SCROLL_CONTAINER)

scroll_config_table_up()

Прокручивает таблицу конфигурации вверх до начала.

Source code in pages\ztp_config_tab.py
60
61
62
def scroll_config_table_up(self) -> None:
    """Прокручивает таблицу конфигурации вверх до начала."""
    self.ztp_config_table.scroll_up(TableLocators.TABLE_SCROLL_CONTAINER)

should_be_config_table()

Проверяет наличие и видимость таблицы конфигурации ZTP.

Raises:

Type Description
AssertionError

Если таблица конфигурации отсутствует на странице.

Source code in pages\ztp_config_tab.py
266
267
268
269
270
271
272
273
274
def should_be_config_table(self) -> None:
    """Проверяет наличие и видимость таблицы конфигурации ZTP.

    Raises:
        AssertionError: Если таблица конфигурации отсутствует на странице.
    """
    self.ztp_config_table.check_visibility(
        TableLocators.TABLE_WORK_AREA, "Configuration table is missing"
    )

should_be_toolbar()

Проверяет наличие и видимость тулбара на вкладке конфигурации.

Raises:

Type Description
AssertionError

Если тулбар отсутствует на странице.

Source code in pages\ztp_config_tab.py
258
259
260
261
262
263
264
def should_be_toolbar(self) -> None:
    """Проверяет наличие и видимость тулбара на вкладке конфигурации.

    Raises:
        AssertionError: Если тулбар отсутствует на странице.
    """
    self.toolbar.check_toolbar_presence("Toolbar is missing")