Skip to content

Commit 5c83ffc

Browse files
included more test cases
1 parent bb762a6 commit 5c83ffc

5 files changed

Lines changed: 2953 additions & 40 deletions

File tree

tests/e2e-test/config/constants.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,16 @@
1313
# browse input data
1414
browse_question1 = "What are typical sections in a promissory note?"
1515
browse_question2 = "List the details of two promissory notes governed by the laws of the state of California"
16+
browse_question3 = "List all documents and their value"
17+
browse_question4 = "list each promissory note, the borrower name, the lender name, the amount, and the interest rate in table format where the interest rate is not 5%"
18+
browse_question5 = "list each promissory note, the borrower name, the lender name, the amount, and the interest rate in tabular format where the interest rate is not 5%"
1619

1720
# Generate input data
1821
generate_question1 = "Generate promissory note for Washington State"
1922
add_section = "Add Payment acceleration clause after the payment terms sections"
2023

24+
remove_section = "Remove Borrower Information Promissory note"
25+
2126
# Response Text Data
2227
invalid_response = "I was unable to find content related to your query and could not generate a template. Please try again."
2328
invalid_response1 = "An error occurred. Answers can't be saved at this time. If the problem persists, please contact the site administrator."

tests/e2e-test/pages/browsePage.py

Lines changed: 183 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
from base.base import BasePage
22
from playwright.sync_api import expect
3+
import logging
4+
logger = logging.getLogger(__name__)
35

46

57
class BrowsePage(BasePage):
@@ -10,7 +12,10 @@ class BrowsePage(BasePage):
1012
DRAFT_TAB_CONTAINER = "//div[contains(@class, '_navigationButtonDisabled')]"
1113
RESPONSE_REFERENCE_EXPAND_ICON = "//span[@aria-label='Open references']"
1214
REFERENCE_LINKS_IN_RESPONSE = "//span[@class='_citationContainer_1qm4u_72']"
15+
REFERENCE_POPUP_PANEL = "//div[@role='dialog']"
16+
REFERENCE_POPUP_CONTENT = "//div[@role='dialog']//div[contains(@class, 'fui-DialogSurface')]"
1317
CLOSE_BUTTON = "//button[.='Close']"
18+
CLEAR_CHAT_BROOM_BUTTON = "button[aria-label='clear chat button']"
1419

1520
def __init__(self, page):
1621
self.page = page
@@ -102,3 +107,181 @@ def is_draft_tab_disabled(self):
102107
return False
103108
return True # If not visible, consider it disabled
104109

110+
def click_broom_icon(self):
111+
broom = self.page.locator(self.CLEAR_CHAT_BROOM_BUTTON)
112+
assert broom.is_visible(), "Broom (clear chat) icon is not visible"
113+
broom.click()
114+
logger.info("Clicked broom icon to clear the chat")
115+
116+
def is_chat_cleared(self):
117+
"""
118+
Verify that the chat has been cleared and a new session has started.
119+
Checks if the chat area is empty (no previous messages visible).
120+
121+
:return: True if chat is cleared, False otherwise
122+
"""
123+
self.page.wait_for_timeout(1000)
124+
125+
# Check if any response paragraphs exist (indicating old messages)
126+
response_paragraphs = self.page.locator("//div[contains(@class, 'answerContainer')]//p")
127+
has_old_messages = response_paragraphs.count() > 0
128+
129+
if has_old_messages:
130+
logger.warning("Chat still contains old messages after clearing")
131+
return False
132+
133+
# Verify the input field is visible and empty (ready for new input)
134+
input_field = self.page.locator(self.TYPE_QUESTION)
135+
if not input_field.is_visible():
136+
logger.warning("Chat input field is not visible")
137+
return False
138+
139+
# Check if input field is empty or has placeholder text
140+
input_value = input_field.input_value()
141+
if input_value.strip():
142+
logger.warning("Chat input field still contains text: '%s'", input_value)
143+
return False
144+
145+
logger.info("Chat cleared successfully - no old messages, input field is empty")
146+
return True
147+
148+
def get_citation_count(self):
149+
"""
150+
Get the number of citations/references in the last response.
151+
152+
Returns:
153+
int: Number of citation links found
154+
"""
155+
logger.info("🔹 Counting citations in response")
156+
157+
self.page.wait_for_timeout(2000)
158+
159+
# Get citation links in the last response
160+
citation_links = self.page.locator(self.REFERENCE_LINKS_IN_RESPONSE)
161+
count = citation_links.count()
162+
163+
logger.info(f"Found {count} citations in response")
164+
return count
165+
166+
def get_citations_and_documents(self):
167+
"""
168+
Get all citations and their corresponding document names from the last response.
169+
Expands the references section and extracts document information.
170+
171+
Returns:
172+
tuple: (citation_count, document_list)
173+
"""
174+
logger.info("🔹 Extracting citations and documents from response")
175+
176+
self.page.wait_for_timeout(3000)
177+
178+
# Count citations first
179+
citation_count = self.get_citation_count()
180+
181+
if citation_count == 0:
182+
logger.warning("No citations found in response")
183+
return 0, []
184+
185+
# Click to expand references
186+
try:
187+
expand_icon = self.page.locator(self.RESPONSE_REFERENCE_EXPAND_ICON)
188+
if expand_icon.count() > 0:
189+
expand_icon.nth(expand_icon.count() - 1).click()
190+
logger.info("Expanded references section")
191+
self.page.wait_for_timeout(2000)
192+
else:
193+
logger.warning("References expand icon not found")
194+
return citation_count, []
195+
except Exception as e:
196+
logger.error(f"Failed to expand references: {e}")
197+
return citation_count, []
198+
199+
# Extract document names from expanded references
200+
documents = []
201+
202+
try:
203+
# Look for reference items in the expanded section
204+
# This selector may need adjustment based on actual DOM structure
205+
reference_items = self.page.locator("//div[contains(@class, 'citationPanel')]//div[contains(@class, 'citationItem')]")
206+
207+
if reference_items.count() == 0:
208+
# Try alternative selector
209+
reference_items = self.page.locator("//div[@role='complementary']//div[contains(@class, 'citation')]")
210+
211+
ref_count = reference_items.count()
212+
logger.info(f"Found {ref_count} reference items in expanded section")
213+
214+
for i in range(ref_count):
215+
try:
216+
ref_text = reference_items.nth(i).inner_text()
217+
documents.append(ref_text.strip())
218+
logger.info(f" Reference {i + 1}: {ref_text[:100]}...")
219+
except Exception as e:
220+
logger.warning(f"Could not extract reference {i + 1}: {e}")
221+
222+
except Exception as e:
223+
logger.error(f"Failed to extract reference documents: {e}")
224+
225+
logger.info(f"✅ Extracted {len(documents)} document references")
226+
return citation_count, documents
227+
228+
def verify_response_has_citations(self, min_citations=1):
229+
"""
230+
Verify that the response has at least the minimum number of citations.
231+
232+
Args:
233+
min_citations: Minimum expected number of citations (default: 1)
234+
235+
Returns:
236+
bool: True if citation count >= min_citations
237+
"""
238+
logger.info(f"🔹 Verifying response has at least {min_citations} citation(s)")
239+
240+
citation_count = self.get_citation_count()
241+
242+
if citation_count >= min_citations:
243+
logger.info(f"✅ Response has {citation_count} citations (>= {min_citations})")
244+
return True
245+
else:
246+
logger.error(f"❌ Response has only {citation_count} citations (expected >= {min_citations})")
247+
return False
248+
249+
def verify_response_generated_with_citations(self, timeout=60000):
250+
"""
251+
Verify that a response is generated with citations/references.
252+
253+
Args:
254+
timeout: Maximum wait time in milliseconds
255+
256+
Returns:
257+
tuple: (response_text, citation_count)
258+
"""
259+
logger.info("🔹 Verifying response generated with citations")
260+
261+
# Wait for response container
262+
self.page.wait_for_timeout(5000)
263+
264+
answer_container = self.page.locator("//div[contains(@class, 'answerContainer')]").last
265+
266+
try:
267+
# Wait for answer to be visible
268+
expect(answer_container).to_be_visible(timeout=timeout)
269+
270+
# Get response text
271+
response_text = answer_container.inner_text()
272+
logger.info(f"Response length: {len(response_text)} characters")
273+
274+
# Verify response is not empty
275+
assert response_text.strip(), "Response text is empty"
276+
277+
# Count citations
278+
citation_count = self.get_citation_count()
279+
logger.info(f"Response has {citation_count} citations")
280+
281+
logger.info("✅ Response generated successfully with citations")
282+
return response_text, citation_count
283+
284+
except Exception as e:
285+
logger.error(f"❌ Failed to verify response with citations: {e}")
286+
raise
287+

0 commit comments

Comments
 (0)