Skip to content

Commit bbbd812

Browse files
test: Implemented Smoke test cases automation - Test Automation - Automate UI Smoke test cases
2 parents 1f5a12e + dca4186 commit bbbd812

3 files changed

Lines changed: 2005 additions & 6 deletions

File tree

tests/e2e-test/pages/dkmPage.py

Lines changed: 98 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,7 @@ class DkmPage(BasePage):
1111
NEWTOPIC = "//button[normalize-space()='New Topic']"
1212
Suggested_follow_up_questions = "body > div:nth-child(3) > div:nth-child(1) > main:nth-child(2) > div:nth-child(1) > div:nth-child(4) > div:nth-child(1) > div:nth-child(1) > div:nth-child(1) > div:nth-child(1) > div:nth-child(3) > div:nth-child(1) > div:nth-child(6) > div:nth-child(3) > button:nth-child(2)"
1313
SCROLL_DOWN = "//div[10]//div[2]//div[2]//i[1]//img[1]"
14-
ASK_QUESTION = (
15-
"//textarea[@placeholder='Ask a question or request (ctrl + enter to submit)']"
16-
)
14+
ASK_QUESTION = "(//textarea[@placeholder='Ask a question or request (ctrl + enter to submit)'])[1]"
1715
SEARCH_BOX = "//input[@type='search']"
1816
HOUSING_2022 = "//body[1]/div[2]/div[1]/main[1]/div[1]/div[2]/div[4]/div[1]/div[1]/div[2]/div[2]/div[2]/span[1]"
1917
HOUSING_2023 = "//body[1]/div[2]/div[1]/main[1]/div[1]/div[2]/div[4]/div[1]/div[1]/div[1]/div[2]/div[2]/span[1]"
@@ -25,11 +23,16 @@ class DkmPage(BasePage):
2523
HANDWRITTEN_DOC1 = "//body[1]/div[2]/div[1]/main[1]/div[1]/div[2]/div[4]/div[1]/div[1]/div[1]/div[2]/div[2]/span[1]"
2624
HANDWRITTEN_DOC2 = "//body[1]/div[2]/div[1]/main[1]/div[1]/div[2]/div[4]/div[1]/div[1]/div[2]/div[2]/div[2]/span[1]"
2725
HANDWRITTEN_DOC3 = "//body[1]/div[2]/div[1]/main[1]/div[1]/div[2]/div[4]/div[1]/div[1]/div[6]/div[2]/div[2]/span[1]"
28-
SEND_BUTTON = "//button[@aria-label='Send']"
26+
SEND_BUTTON = "(//button[@aria-label='Send'])[1]"
2927
POP_UP_CHAT_SEARCH = "(//textarea[@placeholder='Ask a question or request (ctrl + enter to submit)'])[2]"
3028
POP_UP_CHAT_SEND = "(//button[@type='submit'])[2]"
3129
DOCUMENT_FILTER = "//button[normalize-space()='Accessibility Features']"
3230
HEADING_TITLE = "//div[.='Document Knowledge Mining']"
31+
UPLOAD_BUTTON = "//button[contains(text(), 'Upload')]"
32+
FILE_INPUT = "input[type='file']"
33+
CLEAR_ALL_BUTTON = "//button[normalize-space()='Clear all']"
34+
SEARCH_CLEAR = "//button[@aria-label='Clear']"
35+
TIME_FILTER = "//button[contains(text(), 'Anytime')]"
3336

3437
def __init__(self, page):
3538
self.page = page
@@ -41,7 +44,10 @@ def validate_home_page(self):
4144
self.page.wait_for_timeout(2000)
4245

4346
def enter_a_question(self, text):
44-
self.page.locator(self.ASK_QUESTION).fill(text)
47+
# Close any blocking dialogs first
48+
self.close_dialog_if_open()
49+
# Target the main page textarea
50+
self.page.locator(self.ASK_QUESTION).first.fill(text)
4551
self.page.wait_for_timeout(5000)
4652

4753
def enter_in_search(self, text):
@@ -55,6 +61,8 @@ def enter_in_popup_search(self, text):
5561
# self.page.wait_for_load_state('networkidle')
5662

5763
def select_housing_checkbox(self):
64+
# Close any blocking dialogs first
65+
self.close_dialog_if_open()
5866
self.page.locator(self.HOUSING_2022).click()
5967
self.page.locator(self.HOUSING_2023).click()
6068
self.page.wait_for_timeout(5000)
@@ -81,8 +89,10 @@ def select_handwritten_doc(self):
8189
self.page.wait_for_timeout(2000)
8290

8391
def click_send_button(self):
92+
# Close any blocking dialogs first
93+
self.close_dialog_if_open()
8494
# Click on send button in question area
85-
self.page.locator(self.SEND_BUTTON).click()
95+
self.page.locator(self.SEND_BUTTON).first.click()
8696
self.page.wait_for_timeout(5000)
8797

8898
# self.page.wait_for_load_state('networkidle')
@@ -143,3 +153,85 @@ def click_suggested_question(self):
143153
def click_on_contract_details(self):
144154
self.page.locator(self.CONTRACTS_DETAILS_PAGE).click()
145155
self.page.wait_for_timeout(12000)
156+
157+
def click_upload_button(self):
158+
"""Click the upload documents button"""
159+
self.page.locator(self.UPLOAD_BUTTON).click()
160+
self.page.wait_for_timeout(2000)
161+
162+
def upload_file(self, file_path):
163+
"""Upload a file using file input"""
164+
with self.page.expect_file_chooser() as fc_info:
165+
self.page.locator(self.FILE_INPUT).click()
166+
file_chooser = fc_info.value
167+
file_chooser.set_files(file_path)
168+
self.page.wait_for_timeout(3000)
169+
170+
def upload_multiple_files(self, file_paths):
171+
"""Upload multiple files"""
172+
with self.page.expect_file_chooser() as fc_info:
173+
self.page.locator(self.FILE_INPUT).click()
174+
file_chooser = fc_info.value
175+
file_chooser.set_files(file_paths)
176+
self.page.wait_for_timeout(5000)
177+
178+
def click_clear_all(self):
179+
"""Click the Clear All button"""
180+
self.page.locator(self.CLEAR_ALL_BUTTON).click()
181+
self.page.wait_for_timeout(2000)
182+
183+
def clear_search_box(self):
184+
"""Clear the search box"""
185+
self.page.locator(self.SEARCH_BOX).fill("")
186+
self.page.wait_for_timeout(2000)
187+
188+
def close_dialog_if_open(self):
189+
"""Close any open dialog/modal popup"""
190+
try:
191+
# Check if dialog exists and is visible
192+
dialog = self.page.locator("div[role='dialog'][aria-modal='true']")
193+
if dialog.is_visible(timeout=2000):
194+
# Try to close via close button
195+
close_button = dialog.locator("button[aria-label='close'], button[aria-label='Close']")
196+
if close_button.is_visible(timeout=1000):
197+
close_button.click()
198+
self.page.wait_for_timeout(1000)
199+
else:
200+
# Try pressing Escape key
201+
self.page.keyboard.press("Escape")
202+
self.page.wait_for_timeout(1000)
203+
except:
204+
# No dialog open, continue
205+
pass
206+
207+
def verify_send_button_disabled(self):
208+
"""Verify send button is disabled (checking main page button, not popup)"""
209+
# Close any dialogs first
210+
self.close_dialog_if_open()
211+
# Target the main page send button specifically
212+
send_button = self.page.locator(self.SEND_BUTTON).first
213+
# The send button might not have disabled attribute, check if it's clickable
214+
# In some apps, the button stays enabled but backend validation prevents submission
215+
try:
216+
# Check if button has disabled attribute
217+
is_disabled = send_button.get_attribute("disabled") is not None
218+
if is_disabled:
219+
return True
220+
# If no disabled attribute, check aria-disabled
221+
aria_disabled = send_button.get_attribute("aria-disabled")
222+
if aria_disabled == "true":
223+
return True
224+
# If neither, the button is enabled in UI - return False
225+
return False
226+
except:
227+
return False
228+
229+
def verify_send_button_enabled(self):
230+
"""Verify send button is enabled (checking main page button, not popup)"""
231+
# Close any dialogs first
232+
self.close_dialog_if_open()
233+
# Target the main page send button specifically
234+
send_button = self.page.locator(self.SEND_BUTTON).first
235+
# Check the disabled attribute
236+
is_disabled = send_button.get_attribute("disabled") is not None
237+
return not is_disabled

tests/e2e-test/tests/conftest.py

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,22 @@
22
import io
33
import logging
44
import os
5+
import time
56

67
import pytest
78
from bs4 import BeautifulSoup
89
from playwright.sync_api import sync_playwright
10+
from datetime import datetime
11+
from pytest_html import extras
912

1013
from config.constants import URL
1114

1215

16+
# Create screenshots directory if it doesn't exist
17+
SCREENSHOTS_DIR = os.path.join(os.path.dirname(__file__), "..", "screenshots")
18+
os.makedirs(SCREENSHOTS_DIR, exist_ok=True)
19+
20+
1321
@pytest.fixture(scope="session")
1422
def login_logout():
1523
# perform login and browser close once in a session
@@ -64,6 +72,73 @@ def pytest_runtest_makereport(item, call):
6472
log_streams.pop(item.nodeid, None)
6573
else:
6674
report.description = ""
75+
76+
# Capture screenshot on failure or error - MUST BE AFTER log processing
77+
if report.failed:
78+
page = None
79+
80+
# Try to get page from funcargs (works for call phase failures)
81+
if "login_logout" in item.fixturenames:
82+
page = item.funcargs.get("login_logout")
83+
84+
# If page not in funcargs, try alternative methods for setup phase errors
85+
if not page:
86+
try:
87+
# Try to get from fixture manager
88+
fixturemanager = item.session._fixturemanager
89+
if hasattr(fixturemanager, '_arg2fixturedefs') and "login_logout" in fixturemanager._arg2fixturedefs:
90+
fixdefs = fixturemanager._arg2fixturedefs["login_logout"]
91+
for fixdef in fixdefs:
92+
if hasattr(fixdef, 'cached_result') and fixdef.cached_result:
93+
# cached_result is (result, None, (exc, tb)) for failures
94+
# or (result, cache_key, None) for successes
95+
if len(fixdef.cached_result) >= 3 and fixdef.cached_result[2]:
96+
# Fixture failed, try to extract page from traceback frame locals
97+
exc, tb = fixdef.cached_result[2]
98+
# Walk through traceback frames looking for 'page' variable
99+
current_tb = tb
100+
while current_tb:
101+
frame_locals = current_tb.tb_frame.f_locals
102+
if 'page' in frame_locals:
103+
page = frame_locals['page']
104+
break
105+
current_tb = current_tb.tb_next
106+
else:
107+
# Normal success case
108+
page = fixdef.cached_result[0]
109+
if page:
110+
break
111+
except Exception as e:
112+
# If we can't access the fixture, continue without screenshot
113+
pass
114+
115+
if page:
116+
try:
117+
# Generate screenshot filename with timestamp
118+
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
119+
test_name = item.name.replace(" ", "_").replace("/", "_")
120+
screenshot_name = f"screenshot_{test_name}_{timestamp}.png"
121+
screenshot_path = os.path.join(SCREENSHOTS_DIR, screenshot_name)
122+
123+
# Take screenshot
124+
page.screenshot(path=screenshot_path)
125+
126+
# Add screenshot link to report
127+
if not hasattr(report, 'extra'):
128+
report.extra = []
129+
130+
# Use relative path for screenshots (relative to HTML report location)
131+
relative_screenshot_path = f"screenshots/{screenshot_name}"
132+
133+
# pytest-html expects this format for extras
134+
report.extra.append(extras.url(relative_screenshot_path, name='Screenshot'))
135+
136+
print(f"\n📸 Screenshot saved: {screenshot_path}")
137+
print(f"🔗 Link added to report: {relative_screenshot_path}")
138+
except Exception as exc:
139+
# Browser/page might be closed for setup phase errors
140+
# This is expected when fixture fails before yielding
141+
pass
67142

68143

69144
def pytest_collection_modifyitems(items):

0 commit comments

Comments
 (0)