Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion templates/login.html
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ <h1 style="text-align:left">Please Login:</h1>
</div>
<div class="form-group">
<label for="password">Password: </label>
<input type="text" id="password" name="password" required><br>
<input type="password" id="password" name="password" required><br>
</div>
</div>
<button type="submit" class="btn btn-primary btn-block btn-large">Login</button>
Expand Down
4 changes: 2 additions & 2 deletions templates/register.html
Original file line number Diff line number Diff line change
Expand Up @@ -101,11 +101,11 @@ <h1 style="text-align:left">Please Register As A User</h1>
</div>
<div class="form-group">
<label for="password">Password: </label>
<input type="text" id="password" name="password" required><br>
<input type="password" id="password" name="password" required><br>
</div>
<div class="form-group">
<label for="confirmpw">Confirm Password: </label>
<input type="text" id="confirmpw" name="confirmpw" required><br>
<input type="password" id="confirmpw" name="confirmpw" required><br>
</div>
<div class="form-group">
<label for="email">Email Address: </label>
Expand Down
93 changes: 93 additions & 0 deletions tests/test_login.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,96 @@ def test_valid_login(self):
# validate login was successful
self.assert_text("Logged in successfully!")

def test_invalid_username(self):
"""Test login with invalid username"""
# open login page
self.open("http://127.0.0.1:5000/login")

# enter invalid username and valid password
self.type("#username", "invaliduser")
self.type("#password", "TestTest")

# click login button
self.click('button[type="submit"]')

# validate error message is displayed
self.assert_text("Incorrect username/password!")
# ensure we're still on login page
self.assert_element("#username")

def test_invalid_password(self):
"""Test login with valid username but invalid password"""
# open login page
self.open("http://127.0.0.1:5000/login")

# enter valid username and invalid password
self.type("#username", "jefferyepayne")
self.type("#password", "WrongPassword")

# click login button
self.click('button[type="submit"]')

# validate error message is displayed
self.assert_text("Incorrect username/password!")
# ensure we're still on login page
self.assert_element("#username")

def test_empty_credentials(self):
"""Test login with empty username and password"""
# open login page
self.open("http://127.0.0.1:5000/login")

# try to submit form without entering anything
self.click('button[type="submit"]')

# HTML5 validation should prevent submission with required fields empty
# We should still be on the login page
self.assert_element("#username")
self.assert_element("#password")

def test_password_field_is_masked(self):
"""Test that password field properly masks input"""
# open login page
self.open("http://127.0.0.1:5000/login")

# verify password field has correct type attribute
password_field = self.find_element("#password")
field_type = password_field.get_attribute("type")
self.assertEqual(field_type, "password", "Password field should have type='password'")

# type in password field and verify it's masked
self.type("#password", "TestPassword123")

# The actual text content should not be visible in plain text
# We can check that the input type is password which ensures masking
self.assert_attribute("#password", "type", "password")

def test_unauthenticated_redirect_to_login(self):
"""Test that unauthenticated users are redirected to login page"""
# try to access the main wine classification page without logging in
self.open("http://127.0.0.1:5000/")

# should be redirected to login page
self.assert_element("#username")
self.assert_element("#password")
self.assert_text("Please Login:")

def test_login_error_message_visibility(self):
"""Test that error messages are prominently displayed"""
# open login page
self.open("http://127.0.0.1:5000/login")

# enter invalid credentials
self.type("#username", "wronguser")
self.type("#password", "wrongpass")

# click login button
self.click('button[type="submit"]')

# check that error message is visible and prominent
self.assert_text("Incorrect username/password!")

# The error message should be displayed in bold (based on template)
error_element = self.find_element("//b[contains(text(), 'Incorrect username/password!')]")
self.assertTrue(error_element.is_displayed(), "Error message should be prominently displayed")

70 changes: 70 additions & 0 deletions tests/test_login_quick.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
"""
Quick unit tests for login functionality that can run without browser automation.
These tests focus on the critical security and functionality aspects.
"""
import sys
import os
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))

import pytest
from wine import app
import sqlite3

@pytest.fixture
def client():
"""Create a test client for the Flask app"""
app.config['TESTING'] = True
with app.test_client() as client:
yield client

def test_login_page_loads(client):
"""Test that login page loads correctly"""
response = client.get('/login')
assert response.status_code == 200
assert b'Please Login:' in response.data
assert b'type="password"' in response.data # Verify password field is masked

def test_valid_login_redirects_to_wine_page(client):
"""Test that valid login redirects to wine classification page"""
response = client.post('/login', data={'username': 'jefferyepayne', 'password': 'TestTest'})
assert response.status_code == 200
assert b'Logged in successfully!' in response.data
assert b'Predict Your Wine Variety' in response.data

def test_invalid_login_shows_error(client):
"""Test that invalid login shows error message"""
response = client.post('/login', data={'username': 'wronguser', 'password': 'wrongpass'})
assert response.status_code == 200
assert b'Incorrect username/password!' in response.data
assert b'Please Login:' in response.data # Should stay on login page

def test_empty_credentials_shows_login_page(client):
"""Test that empty credentials keep user on login page"""
response = client.post('/login', data={'username': '', 'password': ''})
assert response.status_code == 200
assert b'Please Login:' in response.data

def test_unauthenticated_redirect(client):
"""Test that unauthenticated users are redirected to login"""
response = client.get('/')
assert response.status_code == 200
assert b'Please Login:' in response.data

def test_register_page_has_masked_passwords(client):
"""Test that register page has properly masked password fields"""
response = client.get('/register')
assert response.status_code == 200
assert b'type="password"' in response.data
# Should have at least two password fields (password and confirm)
assert response.data.count(b'type="password"') >= 2

def test_database_has_test_user():
"""Verify test user exists in database"""
conn = sqlite3.connect('wineusers.db')
cursor = conn.cursor()
cursor.execute('SELECT * FROM accounts WHERE username = ?', ('jefferyepayne',))
account = cursor.fetchone()
conn.close()
assert account is not None
assert account[1] == 'jefferyepayne'
assert account[2] == 'TestTest'