diff --git a/qa327/backend.py b/qa327/backend.py
index 482aa39..ca75911 100644
--- a/qa327/backend.py
+++ b/qa327/backend.py
@@ -48,7 +48,7 @@ def register_user(email, name, password, password2):
db.session.commit()
except:
return False
-
+
return True
@@ -78,11 +78,10 @@ def update_ticket(name, quantity, price, date):
ticket.quantity = quantity
ticket.price = price
ticket.date = date
- db.session.update(ticket)
db.session.commit()
return 1
-
+
# Backend functionality for ticket buying
def buy_ticket(name, user, quantity):
# Make sure ticket exists
@@ -92,12 +91,12 @@ def buy_ticket(name, user, quantity):
# Make sure enough quantity of tickets exist and user has enough balance
if ticket.quantity < quantity:
return 0
- elif user.balance < (ticket.price*quantity + (ticket.price*quantity*0.4)):
+ elif user.balance < (ticket.price * quantity + (ticket.price * quantity * 0.4)):
return 0
else:
# Subtracts the ticket amount plus services and tax from the buyers account
- user.balance -= quantity*ticket.price + (quantity*ticket.price*0.4)
+ user.balance -= quantity * ticket.price + (quantity * ticket.price * 0.4)
# Gets the seller's user data
seller = get_user(ticket.email)
@@ -106,7 +105,7 @@ def buy_ticket(name, user, quantity):
if not seller.balance:
seller.balance = 0
# Add the ticket sale revenue to the sellers balance
- seller.balance += quantity*ticket.price
+ seller.balance += quantity * ticket.price
# Check if there are still tickets left after the order is complete
if ticket.quantity > quantity:
@@ -118,5 +117,5 @@ def buy_ticket(name, user, quantity):
# Commit all changes to the database
db.session.commit()
else:
- return 0
- return 1
+ return 0
+ return 1
diff --git a/qa327/frontend.py b/qa327/frontend.py
index 5ada6a8..49b7ffa 100644
--- a/qa327/frontend.py
+++ b/qa327/frontend.py
@@ -12,6 +12,7 @@
The html templates are stored in the 'templates' folder.
"""
+
@app.route('/register', methods=['GET'])
def register_get():
if 'logged_in' in session:
@@ -21,7 +22,6 @@ def register_get():
@app.route('/register', methods=['POST'])
def register_post():
-
patternEmail = re.compile(r"(^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$)")
patternPass = re.compile("^(?=.*?[A-Z])(?=.*?[a-z])(?=.*?[^A-Za-z0-9]).{6,}$")
@@ -38,17 +38,17 @@ def register_post():
session['error'] = error_message
return redirect('/login')
elif not patternEmail.fullmatch(email):
- error_message = '{} format is incorrect.'.format("Email")
+ error_message = '{} format is incorrect.'.format("Email")
session['error'] = error_message
return redirect('/login')
elif not patternPass.fullmatch(password):
- error_message = '{} format is incorrect.'.format("Password")
+ error_message = '{} format is incorrect.'.format("Password")
session['error'] = error_message
return redirect('/login')
elif not patternName.fullmatch(name) or len(name) < 2 or len(name) > 20:
- error_message = '{} format is incorrect.'.format("Name")
+ error_message = '{} format is incorrect.'.format("Name")
session['error'] = error_message
return redirect('/login')
@@ -82,10 +82,10 @@ def login_get():
def login_post():
email = request.form.get('email')
password = request.form.get('password')
- #regex for email obtained from https://emailregex.com/
+ # regex for email obtained from https://emailregex.com/
EMAIL_REGEX = re.compile(r"(^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$)")
PASSWORD_REGEX = re.compile(r"^(?=.*?[A-Z])(?=.*?[a-z])(?=.*?[^A-Za-z0-9]).{6,}$")
- if not EMAIL_REGEX.match(email) or not PASSWORD_REGEX.match(password):
+ if not EMAIL_REGEX.match(email) or not PASSWORD_REGEX.match(password):
return render_template('login.html', message='email/password format invalid')
user = bn.login_user(email, password)
if user:
@@ -159,6 +159,7 @@ def profile(user):
tickets = bn.get_all_tickets()
return render_template('index.html', user=user, tickets=tickets)
+
@app.errorhandler(404)
def page_not_found(e):
return render_template('404.html'), 404
@@ -198,9 +199,9 @@ def check_ticket_form(name=None, quantity=None, price=None, date=None):
@app.route('/sell', methods=['POST'])
def sell():
"""
- Route to sell a new ticket.
+ Route to sell a new ticket.
This route will validate the ticket form, if valid it will use a backend function
- to commit to the database
+ to commit to the database
"""
if 'logged_in' not in session:
return redirect('/login')
@@ -230,32 +231,30 @@ def buy():
if 'logged_in' not in session:
return redirect('/login')
email = session['logged_in']
- #Get user information
+ # Get user information
user = bn.get_user(email)
- #Sets the error message to blank initially
- error_message=""
- #Get information from the form
+ # Sets the error message to blank initially
+ error_message = ""
+ # Get information from the form
name = request.form.get('name')
quantity = request.form.get('quantity')
- #Get all tickets to pass to backend function
+ # Get all tickets to pass to backend function
tickets = bn.get_all_tickets()
error_message = check_ticket_form(name, quantity)
if not error_message:
- if bn.buy_ticket(name,user,int(quantity)):
+ if bn.buy_ticket(name, user, int(quantity)):
message = "Tickets bought succesfully"
else:
error_message = "Ticket could not be bought"
- #Checks if there is an error, and if there is set the error message
+ # Checks if there is an error, and if there is set the error message
if len(error_message) > 0:
session['error'] = error_message
message = session["error"]
del session["error"]
return render_template('index.html', buy_message=message, user=user, tickets=tickets)
-def displayUpdateMessage(message):
- return render_template('index.html', update_message=message)
-
+
@app.route('/update', methods=['POST'])
def update():
"""
@@ -266,7 +265,10 @@ def update():
if 'logged_in' not in session:
return redirect('/login')
- #Grab necessary information from update form
+ # Grab necessary information from update form
+ user = bn.get_user(session['logged_in'])
+ tickets = bn.get_all_tickets()
+
name = request.form.get('name')
quantity = request.form.get('quantity')
price = request.form.get('price')
@@ -274,15 +276,15 @@ def update():
error_message = check_ticket_form(name, quantity, price, date)
if error_message:
- return displayUpdateMessage(error_message)
+ return render_template('index.html', update_message=error_message, user=user, tickets=tickets)
- #Check if ticket exists in database
+ # Check if ticket exists in database
ticket = bn.get_ticket(name)
- if (ticket is None):
- return displayUpdateMessage('Ticket does not exist')
+ if ticket is None:
+ return render_template('index.html', update_message='Ticket does not exist', user=user, tickets=tickets)
- #Update tickets to database
+ # Update tickets to database
bn.update_ticket(name, quantity, price, date)
- return displayUpdateMessage('Successfully updated tickets')
+ return render_template('index.html', update_message='Successfully updated tickets', user=user, tickets=tickets)
diff --git a/qa327/templates/index.html b/qa327/templates/index.html
index 3230217..80031f8 100644
--- a/qa327/templates/index.html
+++ b/qa327/templates/index.html
@@ -53,18 +53,18 @@
{{buy_message}}
Update a Ticket
-{{update_message}}
+{{update_message}}
diff --git a/qa327_test/frontend/test_home.py b/qa327_test/frontend/test_home.py
index 7804f06..aa9eceb 100644
--- a/qa327_test/frontend/test_home.py
+++ b/qa327_test/frontend/test_home.py
@@ -171,10 +171,10 @@ def test_home_update_form_exists(self, *_):
self.open(base_url)
# make sure each field exists under a form with the action to update
- self.assert_element_present('form[action*="/update"] #name')
- self.assert_element_present('form[action*="/update"] #quantity')
- self.assert_element_present('form[action*="/update"] #price')
- self.assert_element_present('form[action*="/update"] #date')
+ self.assert_element_present('form[action*="/update"] #update-name')
+ self.assert_element_present('form[action*="/update"] #update-quantity')
+ self.assert_element_present('form[action*="/update"] #update-price')
+ self.assert_element_present('form[action*="/update"] #update-date')
@patch('qa327.backend.get_user', return_value=test_user)
@patch('qa327.backend.get_all_tickets', return_value=test_tickets)
diff --git a/qa327_test/frontend/test_update.py b/qa327_test/frontend/test_update.py
new file mode 100644
index 0000000..2c3867a
--- /dev/null
+++ b/qa327_test/frontend/test_update.py
@@ -0,0 +1,198 @@
+from time import sleep
+
+import pytest
+from seleniumbase import BaseCase
+
+from qa327_test.conftest import base_url
+from unittest.mock import patch
+from qa327.models import db, User
+from werkzeug.security import generate_password_hash, check_password_hash
+
+# Mock a sample user
+test_user = User(
+ email='test_frontend@test.com',
+ name='test_frontend',
+ password=generate_password_hash('Test_frontend', method='sha256')
+)
+
+
+class UpdatePageTest(BaseCase):
+
+ @patch('qa327.backend.get_user', return_value=test_user)
+ def login(self, *_):
+ self.open(base_url + '/login')
+ # fill in form
+ self.type("#email", "test_frontend@test.com")
+ self.type("#password", 'Test_frontend')
+ # submit
+ self.click('input[type="submit"]')
+
+ @patch('qa327.backend.get_user', return_value=test_user)
+ def test_update_invalid_name(self, *_):
+ """
+ R5.1.1
+ """
+ # invalidate any logged in sessions
+ self.open(base_url + '/logout')
+ # open login page
+ self.login()
+ # open home page
+ self.open(base_url)
+
+ # enter in update form information
+ self.type("#update-name","*hi^xd!")
+ self.type("#update-quantity", 1)
+ self.type("#update-price", 15)
+ self.execute_script("document.querySelector('#update-date').setAttribute('value', '{}')".format('2020-12-10'))
+
+ self.click('input[value="Update Ticket"]')
+
+ self.assert_text("Name can only contain alphanumeric characters", '#update-message')
+
+ @patch('qa327.backend.get_user', return_value=test_user)
+ def test_update_invalid_name_space(self, *_):
+ """
+ R5.1.2
+ """
+ # invalidate any logged in sessions
+ self.open(base_url + '/logout')
+ # open login page
+ self.login()
+ # open home page
+ self.open(base_url)
+ # enter in update form information
+ self.type("#update-name"," ohno")
+ self.type("#update-quantity", 1)
+ self.type("#update-price", 15)
+ self.execute_script("document.querySelector('#update-date').setAttribute('value', '{}')".format('2020-12-10'))
+
+ self.click('input[value="Update Ticket"]')
+
+ self.assert_text("Name has space at beginning or end", '#update-message')
+
+ @patch('qa327.backend.get_user', return_value=test_user)
+ def test_update_name_length(self, *_):
+ """
+ R5.2.1
+ """
+ # invalidate any logged in sessions
+ self.open(base_url + '/logout')
+ # open login page
+ self.login()
+ # open home page
+ self.open(base_url)
+ # enter in update form information
+ self.type("#update-name","imtoolong"*7)
+ self.type("#update-quantity", 1)
+ self.type("#update-price", 15)
+ self.execute_script("document.querySelector('#update-date').setAttribute('value', '{}')".format('2020-12-10'))
+
+ self.click('input[value="Update Ticket"]')
+
+ self.assert_text("Name is too long, it must be shorter than 60 characters", "#update-message")
+
+ @patch('qa327.backend.get_user', return_value=test_user)
+ def test_update_quantity_range_high(self, *_):
+ """
+ R5.3.1
+ """
+ # invalidate any logged in sessions
+ self.open(base_url + '/logout')
+ # open login page
+ self.login()
+ # open home page
+ self.open(base_url)
+ # enter in update form information
+ self.type("#update-name","Test123")
+ self.type("#update-quantity", 101)
+ self.type("#update-price", 15)
+ self.execute_script("document.querySelector('#update-date').setAttribute('value', '{}')".format('2020-12-10'))
+
+ self.click('input[value="Update Ticket"]')
+
+ self.assert_text("Quantity must be greater than 0 and less than or equal to 100", "#update-message")
+
+ @patch('qa327.backend.get_user', return_value=test_user)
+ def test_update_quantity_range_low(self, *_):
+ """
+ R5.3.2
+ """
+ # invalidate any logged in sessions
+ self.open(base_url + '/logout')
+ # open login page
+ self.login()
+ # open home page
+ self.open(base_url)
+ # enter in update form information
+ self.type("#update-name","Test123")
+ self.type("#update-quantity", 0)
+ self.type("#update-price", 15)
+ self.execute_script("document.querySelector('#update-date').setAttribute('value', '{}')".format('2020-12-10'))
+
+ self.click('input[value="Update Ticket"]')
+
+ self.assert_text("Quantity must be greater than 0 and less than or equal to 100", "#update-message")
+
+ @patch('qa327.backend.get_user', return_value=test_user)
+ def test_update_price_range_low(self, *_):
+ """
+ R5.4.1
+ """
+ # invalidate any logged in sessions
+ self.open(base_url + '/logout')
+ # open login page
+ self.login()
+ # open home page
+ self.open(base_url)
+ # enter in update form information
+ self.type("#update-name","Test123")
+ self.type("#update-quantity", 2)
+ self.type("#update-price", 5)
+ self.execute_script("document.querySelector('#update-date').setAttribute('value', '{}')".format('2020-12-10'))
+
+ self.click('input[value="Update Ticket"]')
+
+ self.assert_text("Price must be greater than or equal to 10 and less than or equal to 100", "#update-message")
+
+ @patch('qa327.backend.get_user', return_value=test_user)
+ def test_update_price_range_high(self, *_):
+ """
+ R5.4.2
+ """
+ # invalidate any logged in sessions
+ self.open(base_url + '/logout')
+ # open login page
+ self.login()
+ # open home page
+ self.open(base_url)
+ # enter in update form information
+ self.type("#update-name","Test123")
+ self.type("#update-quantity", 2)
+ self.type("#update-price", 105)
+ self.execute_script("document.querySelector('#update-date').setAttribute('value', '{}')".format('2020-12-10'))
+
+ self.click('input[value="Update Ticket"]')
+
+ self.assert_text("Price must be greater than or equal to 10 and less than or equal to 100", "#update-message")
+
+ @patch('qa327.backend.get_user', return_value=test_user)
+ def test_update_user_profile(self, *_):
+ """
+ R5.5.1
+ """
+ # invalidate any logged in sessions
+ self.open(base_url + '/logout')
+ # open login page
+ self.login()
+ # open home page
+ self.open(base_url)
+ # enter in update form information
+ self.type("#update-name","Test123")
+ self.type("#update-quantity", 2)
+ self.type("#update-price", 15)
+ # valid date format
+ self.execute_script("document.querySelector('#update-date').setAttribute('value', '{}')".format('2020-12-10'))
+
+ # successfully update ticket
+ self.click('input[value="Update Ticket"]')
+
diff --git a/qa327_test/test_failures/R5_failures.md b/qa327_test/test_failures/R5_failures.md
new file mode 100644
index 0000000..17bb397
--- /dev/null
+++ b/qa327_test/test_failures/R5_failures.md
@@ -0,0 +1,8 @@
+# R5 Requirement Failures
+These are the failures found and fixed on a specific branch for the R@ requirement.
+
+Branch: **52_test**
+- Issue with return statements from /update post function, it does not render the html correctly, resulting in server error
+ - Fixed by rendering html correctly through passing all required arguments
+- Issue with backend function to update a ticket, the code runs unnecessary db.session.update function
+ - Fixed by removing that line of code so it'll update a ticket without error.
\ No newline at end of file