Skip to content

Commit f80bcf8

Browse files
fix
1 parent 1302418 commit f80bcf8

3 files changed

Lines changed: 113 additions & 12 deletions

File tree

tests/e2e-test/pages/HomePage.py

Lines changed: 26 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import os.path
44

55
from base.base import BasePage
6+
from config.constants import URL
67

78
from playwright.sync_api import expect
89

@@ -48,10 +49,20 @@ class HomePage(BasePage):
4849

4950
# Harmful file validation message
5051
ERROR_MSG_UNABLE_TO_PROCESS = "//span[normalize-space()='Unable to process the file']"
52+
HARMFUL_FILE_2 = "//span[.='harmful_content_2 2.sql']"
53+
5154

5255
def __init__(self, page):
5356
self.page = page
5457

58+
def navigate_to_base_url(self):
59+
"""
60+
Navigate to the base URL and wait for page load.
61+
"""
62+
self.page.goto(URL, wait_until="domcontentloaded")
63+
self.page.wait_for_timeout(2000)
64+
logger.info(f"Navigated to base URL: {URL}")
65+
5566
def validate_home_page(self):
5667
expect(self.page.locator(self.TITLE_TEXT)).to_be_visible()
5768

@@ -62,27 +73,27 @@ def upload_files(self):
6273
self.page.wait_for_load_state("networkidle")
6374
file_chooser = fc_info.value
6475
current_working_dir = os.getcwd()
65-
file_path1 = os.path.join(current_working_dir, "testdata/Valid_files/q1_informix.sql")
66-
file_path2 = os.path.join(current_working_dir, "testdata/Valid_files/f1.sql")
67-
file_path3 = os.path.join(current_working_dir, "testdata/Valid_files/f2.sql")
76+
file_path1 = os.path.join(current_working_dir, "testdata/valid_files/q1_informix.sql")
77+
file_path2 = os.path.join(current_working_dir, "testdata/valid_files/f1.sql")
78+
file_path3 = os.path.join(current_working_dir, "testdata/valid_files/f2.sql")
6879
file_chooser.set_files([file_path1, file_path2, file_path3])
6980
self.page.wait_for_timeout(10000)
7081
self.page.wait_for_load_state("networkidle")
7182
expect(self.page.locator(self.SUCCESS_MSG)).to_be_visible()
7283

7384
def upload_all_files(self):
7485
"""
75-
Upload all files present in the testdata/Valid_files folder.
86+
Upload all files present in the testdata/valid_files folder.
7687
"""
7788
with self.page.expect_file_chooser() as fc_info:
7889
self.page.locator(self.BROWSE_FILES).click()
7990
self.page.wait_for_timeout(5000)
8091
self.page.wait_for_load_state("networkidle")
8192
file_chooser = fc_info.value
8293
current_working_dir = os.getcwd()
83-
testdata_dir = os.path.join(current_working_dir, "testdata/Valid_files")
84-
85-
# Get all files from testdata/Valid_files folder
94+
testdata_dir = os.path.join(current_working_dir, "testdata/valid_files")
95+
96+
# Get all files from testdata/valid_files folder
8697
all_files = []
8798
if os.path.exists(testdata_dir) and os.path.isdir(testdata_dir):
8899
for filename in os.listdir(testdata_dir):
@@ -127,7 +138,7 @@ def remove_first_three_files_and_validate_count(self):
127138
remove_buttons = self.page.locator(self.REMOVE_FILE_BTN)
128139

129140
# Remove first three files
130-
for _i in range(3):
141+
for i in range(3):
131142
remove_buttons.first.click()
132143
self.page.wait_for_timeout(2000)
133144

@@ -253,7 +264,12 @@ def upload_harmful_file_and_validate(self):
253264
self.page.wait_for_timeout(10000)
254265
self.page.wait_for_load_state("networkidle")
255266
logger.info("Translation process started")
256-
267+
268+
# Click on harmful_content_2 2.sql file
269+
self.page.locator(self.HARMFUL_FILE_2).click()
270+
self.page.wait_for_timeout(2000)
271+
logger.info("Clicked on harmful_content_2 2.sql file")
272+
257273
# Validate error message is visible
258274
try:
259275
expect(self.page.locator(self.ERROR_MSG_UNABLE_TO_PROCESS)).to_be_visible(timeout=200000)
@@ -280,7 +296,7 @@ def upload_harmful_file_and_validate(self):
280296
def validate_translate(self):
281297
self.page.locator(self.TRANSLATE_BTN).click()
282298
expect(self.page.locator(self.DOWNLOAD_FILES)).to_be_enabled(timeout=200000)
283-
self.page.locator(self.SUMMARY).click()
299+
self.page.locator(self.SUMMARY).first.click()
284300
expect(self.page.locator(self.FILE_PROCESSED_MSG)).to_be_visible()
285301
self.page.wait_for_timeout(3000)
286302

tests/e2e-test/tests/conftest.py

Lines changed: 80 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
import io
33
import logging
44
import os
5+
from datetime import datetime
56

67

78
from bs4 import BeautifulSoup
@@ -13,6 +14,11 @@
1314
import pytest
1415

1516

17+
# Create screenshots directory if it doesn't exist
18+
SCREENSHOTS_DIR = os.path.join(os.path.dirname(__file__), "screenshots")
19+
os.makedirs(SCREENSHOTS_DIR, exist_ok=True)
20+
21+
1622
@pytest.fixture(scope="session")
1723
def login_logout():
1824
# perform login and browser close once in a session
@@ -64,9 +70,45 @@ def pytest_runtest_setup(item):
6470

6571
@pytest.hookimpl(hookwrapper=True)
6672
def pytest_runtest_makereport(item, call):
73+
"""Generate test report with logs, subtest details, and screenshots on failure"""
6774
outcome = yield
6875
report = outcome.get_result()
6976

77+
# Capture screenshot on failure
78+
if report.when == "call" and report.failed:
79+
# Get the page fixture if it exists
80+
if "login_logout" in item.fixturenames:
81+
page = item.funcargs.get("login_logout")
82+
if page:
83+
try:
84+
# Generate screenshot filename with timestamp
85+
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
86+
test_name = item.name.replace(" ", "_").replace("/", "_")
87+
screenshot_name = f"screenshot_{test_name}_{timestamp}.png"
88+
screenshot_path = os.path.join(SCREENSHOTS_DIR, screenshot_name)
89+
90+
# Take screenshot
91+
page.screenshot(path=screenshot_path)
92+
93+
# Add screenshot link to report
94+
if not hasattr(report, 'extra'):
95+
report.extra = []
96+
97+
# Add screenshot as a link in the Links column
98+
# Use relative path from report.html location
99+
relative_path = os.path.relpath(
100+
screenshot_path,
101+
os.path.dirname(os.path.abspath("report.html"))
102+
)
103+
104+
# pytest-html expects this format for extras
105+
from pytest_html import extras
106+
report.extra.append(extras.url(relative_path, name='Screenshot'))
107+
108+
logging.info("Screenshot saved: %s", screenshot_path)
109+
except Exception as exc: # pylint: disable=broad-exception-caught
110+
logging.error("Failed to capture screenshot: %s", str(exc))
111+
70112
handler, stream = log_streams.get(item.nodeid, (None, None))
71113

72114
if handler and stream:
@@ -78,8 +120,44 @@ def pytest_runtest_makereport(item, call):
78120
logger = logging.getLogger()
79121
logger.removeHandler(handler)
80122

81-
# Store the log output on the report object for HTML reporting
82-
report.description = f"<pre>{log_output.strip()}</pre>"
123+
# Check if there are subtests
124+
subtests_html = ""
125+
if hasattr(item, 'user_properties'):
126+
item_subtests = [
127+
prop[1] for prop in item.user_properties if prop[0] == "subtest"
128+
]
129+
if item_subtests:
130+
subtests_html = (
131+
"<div style='margin-top: 10px;'>"
132+
"<strong>Step-by-Step Details:</strong>"
133+
"<ul style='list-style: none; padding-left: 0;'>"
134+
)
135+
for idx, subtest in enumerate(item_subtests, 1):
136+
status = "✅ PASSED" if subtest.get('passed') else "❌ FAILED"
137+
status_color = "green" if subtest.get('passed') else "red"
138+
subtests_html += (
139+
f"<li style='margin: 10px 0; padding: 10px; "
140+
f"border-left: 3px solid {status_color}; "
141+
f"background-color: #f9f9f9;'>"
142+
)
143+
subtests_html += (
144+
f"<div style='font-weight: bold; color: {status_color};'>"
145+
f"{status} - {subtest.get('msg', f'Step {idx}')}</div>"
146+
)
147+
if subtest.get('logs'):
148+
subtests_html += (
149+
f"<pre style='margin: 5px 0; padding: 5px; "
150+
f"background-color: #fff; border: 1px solid #ddd; "
151+
f"font-size: 11px;'>{subtest.get('logs').strip()}</pre>"
152+
)
153+
subtests_html += "</li>"
154+
subtests_html += "</ul></div>"
155+
156+
# Combine main log output with subtests
157+
if subtests_html:
158+
report.description = f"<pre>{log_output.strip()}</pre>{subtests_html}"
159+
else:
160+
report.description = f"<pre>{log_output.strip()}</pre>"
83161

84162
# Clean up references
85163
log_streams.pop(item.nodeid, None)

tests/e2e-test/tests/test_codegen_gp_tc.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ def test_codegen_golden_path(login_logout, request):
2929

3030
# Define step-wise test actions for Golden Path
3131
golden_path_steps = [
32+
("00. Navigate to base URL", lambda: home.navigate_to_base_url()),
3233
("01. Validate home page is loaded", lambda: home.validate_home_page()),
3334
("02. Validate Upload of other than SQL files", lambda: home.upload_unsupported_files()),
3435
("03. Validate Upload input files for SQL only", lambda: home.upload_files()),
@@ -63,6 +64,7 @@ def test_upload_all_files_and_navigate_home(login_logout, request):
6364

6465
# Define test steps
6566
test_steps = [
67+
("00. Navigate to base URL", lambda: home.navigate_to_base_url()),
6668
("01. Validate home page is loaded", lambda: home.validate_home_page()),
6769
("02. Upload all files from testdata folder", lambda: home.upload_all_files()),
6870
("03. Validate uploaded files count equals 20", lambda: home.validate_uploaded_files_count()),
@@ -94,6 +96,7 @@ def test_translate_and_download_files(login_logout, request):
9496

9597
# Define step-wise test actions for translation and download workflow
9698
test_steps = [
99+
("00. Navigate to base URL", lambda: home.navigate_to_base_url()),
97100
("01. Validate home page is loaded", lambda: home.validate_home_page()),
98101
("02. Validate Upload of other than SQL files", lambda: home.upload_unsupported_files()),
99102
("03. Validate Upload input files for SQL only", lambda: home.upload_files()),
@@ -128,6 +131,7 @@ def test_upload_remove_files_and_cancel(login_logout, request):
128131

129132
# Define test steps
130133
test_steps = [
134+
("00. Navigate to base URL", lambda: home.navigate_to_base_url()),
131135
("01. Validate home page is loaded", lambda: home.validate_home_page()),
132136
("02. Upload all files from testdata folder (20 files max)", lambda: home.upload_all_files()),
133137
("03. Validate uploaded files count equals 20", lambda: home.validate_uploaded_files_count()),
@@ -160,6 +164,7 @@ def test_delete_batch_history(login_logout, request):
160164

161165
# Define test steps (golden path without return home + delete batch history)
162166
test_steps = [
167+
("00. Navigate to base URL", lambda: home.navigate_to_base_url()),
163168
("01. Validate home page is loaded", lambda: home.validate_home_page()),
164169
("02. Validate Upload of other than SQL files", lambda: home.upload_unsupported_files()),
165170
("03. Validate Upload input files for SQL only", lambda: home.upload_files()),
@@ -194,6 +199,7 @@ def test_upload_unsupported_files_validation(login_logout, request):
194199

195200
# Define test steps
196201
test_steps = [
202+
("00. Navigate to base URL", lambda: home.navigate_to_base_url()),
197203
("01. Validate home page is loaded", lambda: home.validate_home_page()),
198204
("02. Upload all unsupported files and validate translate button is disabled", lambda: home.upload_all_unsupported_files_and_validate()),
199205
]
@@ -223,6 +229,7 @@ def test_upload_harmful_file_validation(login_logout, request):
223229

224230
# Define test steps
225231
test_steps = [
232+
("00. Navigate to base URL", lambda: home.navigate_to_base_url()),
226233
("01. Validate home page is loaded", lambda: home.validate_home_page()),
227234
("02. Upload harmful file, translate, and validate error handling", lambda: home.upload_harmful_file_and_validate()),
228235
("03. Return to home page", lambda: home.return_to_home_page()),

0 commit comments

Comments
 (0)