Skip to content

Commit 1310a0c

Browse files
committed
Add E2E test for managed robot upload (ZIP and tar.gz)
Validates the full create/verify/delete flow for managed robots through the browser, covering both archive formats. CMK-31234 Change-Id: Ia7d61bbc57c9e71bebc0ea3984291b5ac610bd47
1 parent 209a01f commit 1310a0c

File tree

2 files changed

+175
-1
lines changed

2 files changed

+175
-1
lines changed

tests/gui_e2e/testlib/playwright/pom/page.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -220,7 +220,12 @@ def _sub_menu(
220220
_loc.click()
221221

222222
if show_more:
223-
self.locator().get_by_role(role="link", name="show more", exact=True)
223+
show_more_locator = self.locator().get_by_role(
224+
role="link", name="show more", exact=True
225+
)
226+
# only try to press if it hasn't already been pressed before
227+
if show_more_locator.count():
228+
show_more_locator.click()
224229
_loc = self.locator().get_by_role(role="link", name=sub_menu, exact=exact)
225230
self._unique_web_element(_loc)
226231
return _loc
Lines changed: 169 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,169 @@
1+
#!/usr/bin/env python3
2+
# Copyright (C) 2026 Checkmk GmbH - License: GNU General Public License v2
3+
# This file is part of Checkmk (https://checkmk.com). It is subject to the terms and
4+
# conditions defined in the file COPYING, which is part of this source code package.
5+
6+
import logging
7+
import re
8+
from pathlib import Path
9+
from typing import override
10+
from urllib.parse import quote_plus
11+
12+
from playwright.sync_api import expect, Locator, Page
13+
14+
from tests.gui_e2e.testlib.playwright.helpers import DropdownListNameToID
15+
from tests.gui_e2e.testlib.playwright.pom.page import CmkPage
16+
17+
logger = logging.getLogger(__name__)
18+
19+
20+
class ManagedRobotsOverview(CmkPage):
21+
"""Represent the page `Setup -> Managed robots`."""
22+
23+
def __init__(
24+
self,
25+
page: Page,
26+
navigate_to_page: bool = True,
27+
) -> None:
28+
self.page_title = "Managed robots"
29+
super().__init__(page, navigate_to_page)
30+
31+
@override
32+
def navigate(self) -> None:
33+
logger.info("Navigate to '%s' page", self.page_title)
34+
self.main_menu.setup_menu("Managed robots", show_more=True).click()
35+
self.page.wait_for_url(
36+
url=re.compile(quote_plus("wato.py?mode=robotmk_managed_robots_overview")),
37+
wait_until="load",
38+
)
39+
self.validate_page()
40+
41+
@override
42+
def validate_page(self) -> None:
43+
logger.info("Validate that current page is '%s' page", self.page_title)
44+
expect(self.create_robot_button).to_be_visible()
45+
46+
@override
47+
def _dropdown_list_name_to_id(self) -> DropdownListNameToID:
48+
return DropdownListNameToID()
49+
50+
@property
51+
def create_robot_button(self) -> Locator:
52+
return self.main_area.get_suggestion("Create robot")
53+
54+
def robot_row(self, name: str) -> Locator:
55+
return self.main_area.locator(f"tr:has(td:has-text('{name}'))")
56+
57+
def delete_robot_button(self, name: str) -> Locator:
58+
return self.robot_row(name).get_by_role("link", name="Delete")
59+
60+
@property
61+
def delete_confirmation_button(self) -> Locator:
62+
return self.main_area.get_confirmation_popup_button("Delete")
63+
64+
def delete_robot(self, name: str) -> None:
65+
logger.info("Deleting robot '%s'", name)
66+
self.delete_robot_button(name).click()
67+
self.delete_confirmation_button.click()
68+
69+
70+
class CreateManagedRobot(CmkPage):
71+
"""Represent the page for creating a new managed robot."""
72+
73+
def __init__(
74+
self,
75+
page: Page,
76+
navigate_to_page: bool = True,
77+
) -> None:
78+
self.page_title = "Create managed robot"
79+
super().__init__(page, navigate_to_page)
80+
81+
@override
82+
def navigate(self) -> None:
83+
logger.info("Navigate to '%s' page", self.page_title)
84+
ManagedRobotsOverview(self.page).create_robot_button.click(timeout=5000)
85+
self.validate_page()
86+
87+
@override
88+
def validate_page(self) -> None:
89+
logger.info("Validate that current page is '%s' page", self.page_title)
90+
expect(self.name_input).to_be_visible()
91+
92+
@override
93+
def _dropdown_list_name_to_id(self) -> DropdownListNameToID:
94+
return DropdownListNameToID()
95+
96+
@property
97+
def name_input(self) -> Locator:
98+
return self.main_area.locator().get_by_role("textbox", name="Name", exact=True)
99+
100+
@property
101+
def version_label_input(self) -> Locator:
102+
return self.main_area.locator().get_by_role("textbox", name="Version label")
103+
104+
@property
105+
def file_upload_input(self) -> Locator:
106+
return self.main_area.locator("input[type='file']")
107+
108+
@property
109+
def application_name_input(self) -> Locator:
110+
return self.main_area.locator().get_by_role("textbox", name="Application name")
111+
112+
@property
113+
def suite_path_input(self) -> Locator:
114+
return self.main_area.locator().get_by_role("textbox", name="Relative path to test suite")
115+
116+
@property
117+
def conda_manifest_path_input(self) -> Locator:
118+
return self.main_area.locator().get_by_role("textbox", name="Relative manifest path")
119+
120+
@property
121+
def robotmk_manifest_checkbox(self) -> Locator:
122+
return self.main_area.locator().get_by_role(
123+
"checkbox", name="Relative path to Robotmk environment manifest"
124+
)
125+
126+
@property
127+
def robotmk_manifest_path_input(self) -> Locator:
128+
return self.main_area.locator().get_by_role(
129+
"textbox", name="Relative path to Robotmk environment manifest"
130+
)
131+
132+
def enable_robotmk_manifest(self) -> None:
133+
self.robotmk_manifest_checkbox.check()
134+
135+
def save(self) -> None:
136+
logger.info("Saving form")
137+
self.main_area.get_suggestion("Save").click()
138+
139+
def fill_and_save(
140+
self,
141+
*,
142+
name: str,
143+
version_label: str,
144+
archive_path: Path,
145+
app_name: str,
146+
suite_path: str,
147+
conda_path: str,
148+
robotmk_path: str,
149+
) -> None:
150+
logger.info("Filling properties: name='%s', version_label='%s'", name, version_label)
151+
self.name_input.fill(name)
152+
self.version_label_input.fill(version_label)
153+
154+
logger.info("Uploading archive '%s'", archive_path.name)
155+
self.file_upload_input.set_input_files(archive_path)
156+
157+
logger.info("Filling plan settings: app='%s', suite='%s'", app_name, suite_path)
158+
self.application_name_input.fill(app_name)
159+
self.suite_path_input.fill(suite_path)
160+
161+
logger.info("Filling conda manifest path")
162+
self.conda_manifest_path_input.fill(conda_path)
163+
164+
logger.info("Enabling and filling robotmk manifest path")
165+
self.enable_robotmk_manifest()
166+
self.robotmk_manifest_path_input.fill(robotmk_path)
167+
168+
logger.info("Saving the new managed robot")
169+
self.save()

0 commit comments

Comments
 (0)