296 lines
10 KiB
Python
296 lines
10 KiB
Python
|
|
#!/usr/bin/env python3
|
||
|
|
"""
|
||
|
|
Test suite for EP Inspection Tool
|
||
|
|
"""
|
||
|
|
import unittest
|
||
|
|
import tempfile
|
||
|
|
import os
|
||
|
|
from app import create_app
|
||
|
|
from app.models import db, User, Inspection, InspectionInspector, Photo
|
||
|
|
from config import Config
|
||
|
|
from werkzeug.security import generate_password_hash
|
||
|
|
|
||
|
|
class TestConfig(Config):
|
||
|
|
"""Test configuration"""
|
||
|
|
TESTING = True
|
||
|
|
SQLALCHEMY_DATABASE_URI = 'sqlite:///:memory:'
|
||
|
|
SECRET_KEY = 'test-secret-key'
|
||
|
|
WTF_CSRF_ENABLED = False # Disable CSRF for testing
|
||
|
|
|
||
|
|
class EPInspectionTestCase(unittest.TestCase):
|
||
|
|
def setUp(self):
|
||
|
|
"""Set up test environment"""
|
||
|
|
self.app = create_app(TestConfig)
|
||
|
|
self.app_context = self.app.app_context()
|
||
|
|
self.app_context.push()
|
||
|
|
db.create_all()
|
||
|
|
|
||
|
|
# Create a test user
|
||
|
|
self.test_user = User(
|
||
|
|
username='testuser',
|
||
|
|
full_name='Test User',
|
||
|
|
email='test@example.com',
|
||
|
|
is_admin=False
|
||
|
|
)
|
||
|
|
self.test_user.set_password('password')
|
||
|
|
db.session.add(self.test_user)
|
||
|
|
db.session.commit()
|
||
|
|
|
||
|
|
# Create an admin user
|
||
|
|
self.admin_user = User(
|
||
|
|
username='admin',
|
||
|
|
full_name='Admin User',
|
||
|
|
email='admin@example.com',
|
||
|
|
is_admin=True
|
||
|
|
)
|
||
|
|
self.admin_user.set_password('adminpassword')
|
||
|
|
db.session.add(self.admin_user)
|
||
|
|
db.session.commit()
|
||
|
|
|
||
|
|
self.client = self.app.test_client()
|
||
|
|
|
||
|
|
def tearDown(self):
|
||
|
|
"""Clean up after tests"""
|
||
|
|
db.session.remove()
|
||
|
|
db.drop_all()
|
||
|
|
self.app_context.pop()
|
||
|
|
|
||
|
|
def test_user_creation(self):
|
||
|
|
"""Test user creation and password hashing"""
|
||
|
|
user = User.query.filter_by(username='testuser').first()
|
||
|
|
self.assertIsNotNone(user)
|
||
|
|
self.assertTrue(user.check_password('password'))
|
||
|
|
self.assertFalse(user.check_password('wrongpassword'))
|
||
|
|
|
||
|
|
def test_user_creation_with_admin(self):
|
||
|
|
"""Test admin user creation"""
|
||
|
|
admin = User.query.filter_by(username='admin').first()
|
||
|
|
self.assertIsNotNone(admin)
|
||
|
|
self.assertTrue(admin.is_admin)
|
||
|
|
self.assertTrue(admin.check_password('adminpassword'))
|
||
|
|
|
||
|
|
def test_inspection_creation(self):
|
||
|
|
"""Test inspection creation"""
|
||
|
|
from datetime import date
|
||
|
|
inspection = Inspection(
|
||
|
|
installation_name='Test Installation',
|
||
|
|
location='Test Location',
|
||
|
|
inspection_date=date(2023, 1, 1),
|
||
|
|
reference_number=1,
|
||
|
|
conclusion_status='ok',
|
||
|
|
created_by_id=self.test_user.id
|
||
|
|
)
|
||
|
|
db.session.add(inspection)
|
||
|
|
db.session.commit()
|
||
|
|
|
||
|
|
# Verify inspection was created
|
||
|
|
inspection = Inspection.query.first()
|
||
|
|
self.assertIsNotNone(inspection)
|
||
|
|
self.assertEqual(inspection.installation_name, 'Test Installation')
|
||
|
|
|
||
|
|
def test_inspection_creation_with_inspectors(self):
|
||
|
|
"""Test inspection creation with inspectors"""
|
||
|
|
from datetime import date
|
||
|
|
inspection = Inspection(
|
||
|
|
installation_name='Test Installation',
|
||
|
|
location='Test Location',
|
||
|
|
inspection_date=date(2023, 1, 1),
|
||
|
|
reference_number=1,
|
||
|
|
conclusion_status='ok',
|
||
|
|
created_by_id=self.test_user.id
|
||
|
|
)
|
||
|
|
db.session.add(inspection)
|
||
|
|
db.session.flush()
|
||
|
|
|
||
|
|
# Add inspector
|
||
|
|
inspector = InspectionInspector(
|
||
|
|
inspection_id=inspection.id,
|
||
|
|
user_id=self.test_user.id
|
||
|
|
)
|
||
|
|
db.session.add(inspector)
|
||
|
|
db.session.commit()
|
||
|
|
|
||
|
|
# Verify inspector was added
|
||
|
|
inspector = InspectionInspector.query.first()
|
||
|
|
self.assertIsNotNone(inspector)
|
||
|
|
self.assertEqual(inspector.user_id, self.test_user.id)
|
||
|
|
|
||
|
|
def test_database_connection(self):
|
||
|
|
"""Test that database is accessible"""
|
||
|
|
self.assertIsNotNone(db.engine)
|
||
|
|
|
||
|
|
def test_user_authentication(self):
|
||
|
|
"""Test user authentication"""
|
||
|
|
response = self.client.post('/login', data={
|
||
|
|
'username': 'testuser',
|
||
|
|
'password': 'password'
|
||
|
|
})
|
||
|
|
self.assertEqual(response.status_code, 302) # Redirect after login
|
||
|
|
|
||
|
|
def test_user_authentication_failed(self):
|
||
|
|
"""Test failed user authentication"""
|
||
|
|
response = self.client.post('/login', data={
|
||
|
|
'username': 'testuser',
|
||
|
|
'password': 'wrongpassword'
|
||
|
|
})
|
||
|
|
self.assertEqual(response.status_code, 200) # Stay on login page
|
||
|
|
|
||
|
|
def test_user_login_with_invalid_credentials(self):
|
||
|
|
"""Test login with invalid credentials"""
|
||
|
|
response = self.client.post('/login', data={
|
||
|
|
'username': 'nonexistent',
|
||
|
|
'password': 'password'
|
||
|
|
})
|
||
|
|
self.assertEqual(response.status_code, 200) # Stay on login page
|
||
|
|
|
||
|
|
def test_admin_user_can_access_admin_panel(self):
|
||
|
|
"""Test that admin user can access admin panel"""
|
||
|
|
# Login as admin
|
||
|
|
self.client.post('/login', data={
|
||
|
|
'username': 'admin',
|
||
|
|
'password': 'adminpassword'
|
||
|
|
})
|
||
|
|
|
||
|
|
# Access admin panel (should be accessible)
|
||
|
|
response = self.client.get('/admin')
|
||
|
|
# Should either redirect to login or return 200 (depending on implementation)
|
||
|
|
|
||
|
|
def test_inspection_creation_with_photo(self):
|
||
|
|
"""Test inspection creation with photo"""
|
||
|
|
from datetime import date
|
||
|
|
inspection = Inspection(
|
||
|
|
installation_name='Test Installation',
|
||
|
|
location='Test Location',
|
||
|
|
inspection_date=date(2023, 1, 1),
|
||
|
|
reference_number=1,
|
||
|
|
conclusion_status='ok',
|
||
|
|
created_by_id=self.test_user.id
|
||
|
|
)
|
||
|
|
db.session.add(inspection)
|
||
|
|
db.session.commit()
|
||
|
|
|
||
|
|
# Create a photo
|
||
|
|
photo = Photo(
|
||
|
|
inspection_id=inspection.id,
|
||
|
|
filename='test_photo.jpg',
|
||
|
|
action_required='none'
|
||
|
|
)
|
||
|
|
db.session.add(photo)
|
||
|
|
db.session.commit()
|
||
|
|
|
||
|
|
# Verify photo was added
|
||
|
|
photo = Photo.query.first()
|
||
|
|
self.assertIsNotNone(photo)
|
||
|
|
self.assertEqual(photo.filename, 'test_photo.jpg')
|
||
|
|
|
||
|
|
def test_inspection_validation(self):
|
||
|
|
"""Test inspection data validation"""
|
||
|
|
from datetime import date
|
||
|
|
# Test with valid data
|
||
|
|
inspection = Inspection(
|
||
|
|
installation_name='Test Installation',
|
||
|
|
location='Test Location',
|
||
|
|
inspection_date=date(2023, 1, 1),
|
||
|
|
reference_number=1,
|
||
|
|
conclusion_status='ok',
|
||
|
|
created_by_id=self.test_user.id
|
||
|
|
)
|
||
|
|
db.session.add(inspection)
|
||
|
|
db.session.commit()
|
||
|
|
|
||
|
|
# Test with invalid data (should be prevented by constraints)
|
||
|
|
# This test verifies that constraints are properly applied
|
||
|
|
inspection2 = Inspection(
|
||
|
|
installation_name='T', # Too short
|
||
|
|
location='Test Location',
|
||
|
|
inspection_date=date(2023, 1, 1),
|
||
|
|
reference_number=1,
|
||
|
|
conclusion_status='ok',
|
||
|
|
created_by_id=self.test_user.id
|
||
|
|
)
|
||
|
|
db.session.add(inspection2)
|
||
|
|
|
||
|
|
# This should raise an exception due to validation constraints
|
||
|
|
with self.assertRaises(Exception):
|
||
|
|
db.session.commit()
|
||
|
|
|
||
|
|
def test_user_validation(self):
|
||
|
|
"""Test user data validation"""
|
||
|
|
# Test with valid data
|
||
|
|
user = User(
|
||
|
|
username='testuser2',
|
||
|
|
full_name='Test User 2',
|
||
|
|
email='test2@example.com',
|
||
|
|
is_admin=False
|
||
|
|
)
|
||
|
|
user.set_password('password')
|
||
|
|
db.session.add(user)
|
||
|
|
db.session.commit()
|
||
|
|
|
||
|
|
# Verify user was created
|
||
|
|
user = User.query.filter_by(username='testuser2').first()
|
||
|
|
self.assertIsNotNone(user)
|
||
|
|
|
||
|
|
# Test with invalid data (should be prevented by constraints)
|
||
|
|
invalid_user = User(
|
||
|
|
username='ab', # Too short
|
||
|
|
full_name='Test User',
|
||
|
|
email='test@example.com',
|
||
|
|
is_admin=False
|
||
|
|
)
|
||
|
|
invalid_user.set_password('password')
|
||
|
|
db.session.add(invalid_user)
|
||
|
|
|
||
|
|
# This should raise an exception due to validation constraints
|
||
|
|
with self.assertRaises(Exception):
|
||
|
|
db.session.commit()
|
||
|
|
|
||
|
|
def test_inspection_workflow(self):
|
||
|
|
"""Test complete inspection workflow"""
|
||
|
|
# Login
|
||
|
|
response = self.client.post('/login', data={
|
||
|
|
'username': 'testuser',
|
||
|
|
'password': 'password'
|
||
|
|
})
|
||
|
|
self.assertEqual(response.status_code, 302)
|
||
|
|
|
||
|
|
# Create inspection
|
||
|
|
response = self.client.post('/inspection/new', data={
|
||
|
|
'installation_name': 'Workshop Inspection',
|
||
|
|
'location': 'Building A',
|
||
|
|
'inspection_date': '2023-01-15',
|
||
|
|
'reference_number': 1001,
|
||
|
|
'conclusion_status': 'ok',
|
||
|
|
'observations': 'All systems normal',
|
||
|
|
'conclusion_text': 'No issues found'
|
||
|
|
}, follow_redirects=True)
|
||
|
|
|
||
|
|
self.assertEqual(response.status_code, 200)
|
||
|
|
|
||
|
|
# Verify inspection was created
|
||
|
|
inspection = Inspection.query.first()
|
||
|
|
self.assertIsNotNone(inspection)
|
||
|
|
self.assertEqual(inspection.installation_name, 'Workshop Inspection')
|
||
|
|
|
||
|
|
def test_admin_access(self):
|
||
|
|
"""Test admin user access to restricted areas"""
|
||
|
|
# Login as admin
|
||
|
|
response = self.client.post('/login', data={
|
||
|
|
'username': 'admin',
|
||
|
|
'password': 'adminpassword'
|
||
|
|
})
|
||
|
|
self.assertEqual(response.status_code, 302)
|
||
|
|
|
||
|
|
# Access admin panel
|
||
|
|
response = self.client.get('/admin')
|
||
|
|
# This should either redirect or give access
|
||
|
|
|
||
|
|
def test_unauthorized_access(self):
|
||
|
|
"""Test unauthorized access prevention"""
|
||
|
|
# Try to access dashboard without login
|
||
|
|
response = self.client.get('/dashboard')
|
||
|
|
# Should redirect to login
|
||
|
|
self.assertEqual(response.status_code, 302)
|
||
|
|
|
||
|
|
if __name__ == '__main__':
|
||
|
|
unittest.main()
|