Skip to content

Commit 45ad51e

Browse files
committed
add e2e tests for the quiz app
1 parent 8a665b3 commit 45ad51e

File tree

2 files changed

+254
-0
lines changed

2 files changed

+254
-0
lines changed

tests/e2e/requirements.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
pytest
2+
playwright
3+
boto3
4+
pytest-playwright

tests/e2e/test_quiz_flow.py

Lines changed: 250 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,250 @@
1+
import os
2+
import pytest
3+
import boto3
4+
from playwright.sync_api import sync_playwright, expect
5+
import time
6+
import random
7+
import string
8+
9+
@pytest.fixture(scope="session")
10+
def browser():
11+
with sync_playwright() as p:
12+
# Launch browser in headed mode for debugging
13+
browser = p.chromium.launch(headless=False, slow_mo=1000)
14+
yield browser
15+
browser.close()
16+
17+
@pytest.fixture(scope="session")
18+
def page(browser):
19+
context = browser.new_context()
20+
page = context.new_page()
21+
yield page
22+
context.close()
23+
24+
@pytest.fixture(scope="session")
25+
def app_url():
26+
# Use boto3 to get the CloudFront distribution ID
27+
cloudfront = boto3.client('cloudfront', endpoint_url='http://localhost:4566')
28+
response = cloudfront.list_distributions()
29+
distribution_id = response['DistributionList']['Items'][0]['Id']
30+
return f"https://{distribution_id}.cloudfront.localhost.localstack.cloud"
31+
32+
def test_quiz_flow(page, app_url):
33+
# Enable verbose logging
34+
page.set_viewport_size({"width": 1280, "height": 720})
35+
36+
# Navigate to the home page
37+
print("\nNavigating to home page...")
38+
page.goto(app_url)
39+
40+
# Verify the home page loaded
41+
print("Verifying home page...")
42+
expect(page.get_by_text("Welcome")).to_be_visible()
43+
44+
# Select AWS Quiz from public quizzes
45+
print("Selecting AWS Quiz...")
46+
quiz_select = page.get_by_label("Select a Public Quiz")
47+
quiz_select.click()
48+
page.get_by_text("AWS Quiz").click()
49+
50+
# Fill in user details
51+
username = ''.join(random.choices(string.ascii_letters + string.digits, k=8))
52+
print(f"Username: {username}")
53+
email = f"{username}@example.com"
54+
print(f"Email: {email}")
55+
print("Filling in user details...")
56+
username_input = page.get_by_label("Username")
57+
username_input.fill(username)
58+
59+
# Optional: Fill in email
60+
email_input = page.get_by_label("Email (Optional)")
61+
email_input.fill(email)
62+
63+
# Start the quiz
64+
print("Starting quiz...")
65+
start_button = page.get_by_text("Start Playing")
66+
expect(start_button).to_be_enabled()
67+
start_button.click()
68+
69+
# Wait for first question to load
70+
print("Waiting for first question...")
71+
expect(page.get_by_text("Question 1 / 5")).to_be_visible()
72+
73+
# Answer all questions
74+
answers = [
75+
"B. Amazon EC2", # What is the primary compute service in AWS?
76+
"A. Simple Storage Service", # What does S3 stand for in AWS?
77+
"A. Amazon DynamoDB", # Which AWS service is a NoSQL database?
78+
"B. AWS Lambda", # Which AWS service lets you run code without provisioning servers?
79+
"B. Identity and Access Management" # What is IAM used for?
80+
]
81+
82+
for i, answer in enumerate(answers):
83+
print(f"Answering question {i + 1}...")
84+
# Wait for question to be visible
85+
expect(page.get_by_text(f"Question {i + 1} / 5")).to_be_visible()
86+
87+
# Select answer
88+
answer_radio = page.get_by_label(answer)
89+
expect(answer_radio).to_be_visible()
90+
answer_radio.click()
91+
92+
# Wait for next question or submit button
93+
time.sleep(2) # Increased delay to ensure state updates
94+
95+
# After last question, verify we're on the results page
96+
print("Waiting for results page...")
97+
98+
# Take a screenshot for debugging
99+
page.screenshot(path="results-page.png")
100+
101+
# Print current page content for debugging
102+
print("\nPage content after quiz completion:")
103+
print(page.content())
104+
105+
# Try different selectors for the results
106+
selectors = [
107+
"text=Processing your submission...",
108+
"text=Your Score",
109+
"text=Quiz Results",
110+
".main-quiz-container", # Try container class
111+
"[data-testid=results-page]" # Try test ID if available
112+
]
113+
114+
for selector in selectors:
115+
try:
116+
print(f"\nTrying to find: {selector}")
117+
element = page.wait_for_selector(selector, timeout=5000)
118+
if element:
119+
print(f"Found element with selector: {selector}")
120+
break
121+
except Exception as e:
122+
print(f"Selector {selector} not found: {str(e)}")
123+
124+
# Wait longer for results processing
125+
print("Waiting for results to process...")
126+
time.sleep(5) # Give more time for backend processing
127+
128+
# Try to find score text with a more flexible approach
129+
score_element = page.get_by_text("Score", exact=False)
130+
if score_element:
131+
print(f"Found score element: {score_element.text_content()}")
132+
133+
# Click View Leaderboard if available
134+
try:
135+
leaderboard_button = page.get_by_text("View Leaderboard")
136+
if leaderboard_button.is_visible():
137+
print("Clicking leaderboard button...")
138+
leaderboard_button.click()
139+
140+
# Verify leaderboard loaded
141+
expect(page.get_by_text("Leaderboard")).to_be_visible()
142+
143+
# Verify our user appears in the leaderboard
144+
print("Checking leaderboard entries...")
145+
leaderboard_entries = page.get_by_role("row")
146+
found_user = False
147+
for entry in leaderboard_entries.all():
148+
content = entry.text_content()
149+
print(f"Leaderboard entry: {content}")
150+
if username in content.lower():
151+
found_user = True
152+
break
153+
154+
assert found_user, "User not found in leaderboard"
155+
except Exception as e:
156+
print(f"Error accessing leaderboard: {str(e)}")
157+
page.screenshot(path="leaderboard-error.png")
158+
159+
def test_quiz_creation(page, app_url):
160+
print("\nStarting quiz creation test...")
161+
# Navigate to home page
162+
print("Navigating to home page...")
163+
page.goto(app_url)
164+
165+
# Click Create a New Quiz
166+
print("Clicking Create a New Quiz...")
167+
page.get_by_text("Create a New Quiz").click()
168+
169+
# Fill in quiz details
170+
print("Filling quiz title...")
171+
page.get_by_label("Quiz Title").fill("Test Quiz")
172+
173+
# Add a question
174+
print("Adding question text...")
175+
question_input = page.get_by_role("textbox", name="Question Text")
176+
question_input.fill("What is LocalStack?")
177+
178+
# Fill options
179+
options = [
180+
"A. A cloud service emulator",
181+
"B. A database system",
182+
"C. A web framework",
183+
"D. A programming language"
184+
]
185+
186+
print("Filling options...")
187+
for i, option in enumerate(options):
188+
# Use role selector for textbox with specific name
189+
option_input = page.get_by_role("textbox", name=f"Option {i + 1}")
190+
option_input.fill(option)
191+
192+
# Add trivia (if required)
193+
print("Adding trivia...")
194+
trivia_input = page.get_by_role("textbox", name="Trivia")
195+
trivia_input.fill("LocalStack is a cloud service emulator that runs in a single container on your laptop.")
196+
197+
# Select correct answer using radio group
198+
print("Selecting correct answer...")
199+
radio_group = page.get_by_role("radiogroup")
200+
expect(radio_group).to_be_visible()
201+
202+
# Select the first option (A) as correct answer
203+
correct_answer = page.locator('input[type="radio"]').first
204+
expect(correct_answer).to_be_visible()
205+
correct_answer.check()
206+
207+
# Add question
208+
print("Adding question...")
209+
add_question_button = page.get_by_role("button", name="Add Question")
210+
expect(add_question_button).to_be_enabled()
211+
add_question_button.click()
212+
213+
# Submit quiz
214+
print("Submitting quiz...")
215+
submit_button = page.get_by_role("button", name="Submit Quiz")
216+
expect(submit_button).to_be_enabled()
217+
submit_button.click()
218+
219+
# Verify quiz was created
220+
print("Verifying quiz creation...")
221+
success_message = page.get_by_text("Quiz created successfully!")
222+
expect(success_message).to_be_visible()
223+
224+
# Get Quiz ID from success message
225+
success_text = success_message.text_content()
226+
quiz_id = success_text.split("Quiz ID: ")[1]
227+
print(f"Quiz created with ID: {quiz_id}")
228+
229+
# Go back to home
230+
print("Going back to home...")
231+
page.get_by_text("Go to Home").click()
232+
233+
# Verify we can find and start the new quiz
234+
print("Starting the created quiz...")
235+
quiz_id_input = page.get_by_label("Quiz ID")
236+
quiz_id_input.fill(quiz_id)
237+
238+
username = ''.join(random.choices(string.ascii_letters + string.digits, k=8))
239+
print(f"Using username: {username}")
240+
username_input = page.get_by_label("Username")
241+
username_input.fill(username)
242+
243+
start_button = page.get_by_text("Start Playing")
244+
expect(start_button).to_be_enabled()
245+
start_button.click()
246+
247+
# Verify question appears
248+
print("Verifying question appears...")
249+
expect(page.get_by_text("What is LocalStack?")).to_be_visible()
250+
print("Quiz creation test completed successfully!")

0 commit comments

Comments
 (0)