import pytest from app.models import User, Folder import uuid from bs4 import BeautifulSoup def test_index_route(client, app, mock_user): """Test the index route requires authentication.""" response = client.get('/') # Should redirect to login page assert response.status_code == 302 assert '/login' in response.location def test_index_route_authenticated(authenticated_client, app, mock_user): """Test the index route works for authenticated users.""" response = authenticated_client.get('/') assert response.status_code == 200 # Check if the page contains expected elements assert b'Email Organizer' in response.data assert b'Folders' in response.data assert b'Test User' in response.data # Should show user's name def test_add_folder_route(authenticated_client, mock_user): """Test the add folder API endpoint.""" # Get initial count of folders for the user initial_folder_count = Folder.query.count() # Send form data (URL encoded) instead of JSON response = authenticated_client.post('/api/folders', data={'name': 'Test Folder', 'rule_text': 'Test rule something ok yes'}, content_type='application/x-www-form-urlencoded') # Verify the response status is 201 Created assert response.status_code == 201 # Verify that the number of folders has increased final_folder_count = Folder.query.count() assert final_folder_count > initial_folder_count # Verify the folder belongs to the authenticated user created_folder = Folder.query.filter_by(name='Test Folder').first() assert created_folder.user_id == mock_user.id # Validation failure tests def test_add_folder_validation_failure_empty_name(authenticated_client, mock_user): """Test validation failure when folder name is empty.""" response = authenticated_client.post('/api/folders', data={'name': '', 'rule_text': 'Test rule something ok yes'}, content_type='application/x-www-form-urlencoded') assert response.status_code == 200 soup = BeautifulSoup(response.data, 'html.parser') # Check that the specific error message is present error_text = soup.find(string='Folder name is required') assert error_text is not None # Check that the input field has the error class name_input = soup.find('input', {'name': 'name'}) assert name_input is not None assert 'input-error' in name_input.get('class', []) def test_add_folder_validation_failure_short_name(authenticated_client, mock_user): """Test validation failure when folder name is too short.""" response = authenticated_client.post('/api/folders', data={'name': 'ab', 'rule_text': 'Test rule something ok yes'}, content_type='application/x-www-form-urlencoded') assert response.status_code == 200 soup = BeautifulSoup(response.data, 'html.parser') error_text = soup.find(string='Folder name must be at least 3 characters') assert error_text is not None def test_add_folder_validation_failure_long_name(authenticated_client, mock_user): """Test validation failure when folder name is too long.""" long_name = 'a' * 51 response = authenticated_client.post('/api/folders', data={'name': long_name, 'rule_text': 'Test rule something ok yes'}, content_type='application/x-www-form-urlencoded') assert response.status_code == 200 soup = BeautifulSoup(response.data, 'html.parser') error_text = soup.find(string='Folder name must be less than 50 characters') assert error_text is not None def test_add_folder_validation_failure_empty_rule(authenticated_client, mock_user): """Test validation failure when rule text is empty.""" response = authenticated_client.post('/api/folders', data={'name': 'Test Folder', 'rule_text': ''}, content_type='application/x-www-form-urlencoded') assert response.status_code == 200 soup = BeautifulSoup(response.data, 'html.parser') error_text = soup.find(string='Rule text is required') assert error_text is not None def test_add_folder_validation_failure_short_rule(authenticated_client, mock_user): """Test validation failure when rule text is too short.""" response = authenticated_client.post('/api/folders', data={'name': 'Test Folder', 'rule_text': 'short'}, content_type='application/x-www-form-urlencoded') assert response.status_code == 200 soup = BeautifulSoup(response.data, 'html.parser') error_text = soup.find(string='Rule text must be at least 10 characters') assert error_text is not None def test_add_folder_validation_failure_long_rule(authenticated_client, mock_user): """Test validation failure when rule text is too long.""" long_rule = 'a' * 201 response = authenticated_client.post('/api/folders', data={'name': 'Test Folder', 'rule_text': long_rule}, content_type='application/x-www-form-urlencoded') assert response.status_code == 200 soup = BeautifulSoup(response.data, 'html.parser') error_text = soup.find(string='Rule text must be less than 200 characters') assert error_text is not None def test_add_folder_validation_multiple_errors(authenticated_client, mock_user): """Test validation failure with multiple errors.""" response = authenticated_client.post('/api/folders', data={'name': 'ab', 'rule_text': 'short'}, content_type='application/x-www-form-urlencoded') assert response.status_code == 200 soup = BeautifulSoup(response.data, 'html.parser') error_text1 = soup.find(string='Folder name must be at least 3 characters') error_text2 = soup.find(string='Rule text must be at least 10 characters') assert error_text1 is not None assert error_text2 is not None # Edit folder validation failure tests def test_edit_folder_validation_failure_empty_name(authenticated_client, mock_folder): """Test validation failure when folder name is empty during edit.""" response = authenticated_client.put(f'/api/folders/{mock_folder.id}', data={'name': '', 'rule_text': 'Test rule something ok yes'}, content_type='application/x-www-form-urlencoded') assert response.status_code == 200 soup = BeautifulSoup(response.data, 'html.parser') error_text = soup.find(string='Folder name is required') assert error_text is not None def test_edit_folder_validation_failure_short_name(authenticated_client, mock_folder): """Test validation failure when folder name is too short during edit.""" response = authenticated_client.put(f'/api/folders/{mock_folder.id}', data={'name': 'ab', 'rule_text': 'Test rule something ok yes'}, content_type='application/x-www-form-urlencoded') assert response.status_code == 200 soup = BeautifulSoup(response.data, 'html.parser') error_text = soup.find(string='Folder name must be at least 3 characters') assert error_text is not None def test_edit_folder_validation_failure_long_name(authenticated_client, mock_folder): """Test validation failure when folder name is too long during edit.""" long_name = 'a' * 51 response = authenticated_client.put(f'/api/folders/{mock_folder.id}', data={'name': long_name, 'rule_text': 'Test rule something ok yes'}, content_type='application/x-www-form-urlencoded') assert response.status_code == 200 soup = BeautifulSoup(response.data, 'html.parser') error_text = soup.find(string='Folder name must be less than 50 characters') assert error_text is not None def test_edit_folder_validation_failure_empty_rule(authenticated_client, mock_folder): """Test validation failure when rule text is empty during edit.""" response = authenticated_client.put(f'/api/folders/{mock_folder.id}', data={'name': 'Test Folder', 'rule_text': ''}, content_type='application/x-www-form-urlencoded') assert response.status_code == 200 soup = BeautifulSoup(response.data, 'html.parser') error_text = soup.find(string='Rule text is required') assert error_text is not None def test_edit_folder_validation_failure_short_rule(authenticated_client, mock_folder): """Test validation failure when rule text is too short during edit.""" response = authenticated_client.put(f'/api/folders/{mock_folder.id}', data={'name': 'Test Folder', 'rule_text': 'short'}, content_type='application/x-www-form-urlencoded') assert response.status_code == 200 soup = BeautifulSoup(response.data, 'html.parser') error_text = soup.find(string='Rule text must be at least 10 characters') assert error_text is not None def test_edit_folder_validation_failure_long_rule(authenticated_client, mock_folder): """Test validation failure when rule text is too long during edit.""" long_rule = 'a' * 201 response = authenticated_client.put(f'/api/folders/{mock_folder.id}', data={'name': 'Test Folder', 'rule_text': long_rule}, content_type='application/x-www-form-urlencoded') assert response.status_code == 200 soup = BeautifulSoup(response.data, 'html.parser') error_text = soup.find(string='Rule text must be less than 200 characters') assert error_text is not None def test_edit_folder_validation_multiple_errors(authenticated_client, mock_folder): """Test validation failure with multiple errors during edit.""" response = authenticated_client.put(f'/api/folders/{mock_folder.id}', data={'name': 'ab', 'rule_text': 'short'}, content_type='application/x-www-form-urlencoded') assert response.status_code == 200 soup = BeautifulSoup(response.data, 'html.parser') error_text1 = soup.find(string='Folder name must be at least 3 characters') error_text2 = soup.find(string='Rule text must be at least 10 characters') assert error_text1 is not None assert error_text2 is not None # Dialog close tests def test_add_folder_success_closes_dialog(authenticated_client, mock_user): """Test that successful folder creation triggers dialog close.""" response = authenticated_client.post('/api/folders', data={'name': 'Test Folder', 'rule_text': 'Test rule something ok yes'}, content_type='application/x-www-form-urlencoded') assert response.status_code == 201 # Check for close-modal trigger in response headers assert 'HX-Trigger' in response.headers assert 'close-modal' in response.headers['HX-Trigger'] def test_edit_folder_success_closes_dialog(authenticated_client, mock_folder): """Test that successful folder update triggers dialog close.""" response = authenticated_client.put(f'/api/folders/{mock_folder.id}', data={'name': 'Updated Folder', 'rule_text': 'Updated rule text'}, content_type='application/x-www-form-urlencoded') assert response.status_code == 200 # Check for close-modal trigger in response headers assert 'HX-Trigger' in response.headers assert 'close-modal' in response.headers['HX-Trigger'] # Content matching tests def test_add_folder_content_matches_submission(authenticated_client, mock_user): """Test that submitted folder content matches what was sent.""" test_name = 'Test Folder Content' test_rule = 'Test rule content matching submission' test_priority = '1' response = authenticated_client.post('/api/folders', data={'name': test_name, 'rule_text': test_rule, 'priority': test_priority}, content_type='application/x-www-form-urlencoded') assert response.status_code == 201 # Verify the folder was created with correct content created_folder = Folder.query.filter_by(name=test_name).first() assert created_folder is not None assert created_folder.name == test_name.strip() assert created_folder.rule_text == test_rule.strip() assert created_folder.priority == int(test_priority) assert created_folder.user_id == mock_user.id def test_edit_folder_content_matches_submission(authenticated_client, mock_folder): """Test that updated folder content matches what was sent.""" test_name = 'Updated Folder Content' test_rule = 'Updated rule content matching submission' test_priority = '-1' response = authenticated_client.put(f'/api/folders/{mock_folder.id}', data={'name': test_name, 'rule_text': test_rule, 'priority': test_priority}, content_type='application/x-www-form-urlencoded') assert response.status_code == 200 # Verify the folder was updated with correct content updated_folder = Folder.query.filter_by(id=mock_folder.id).first() assert updated_folder is not None assert updated_folder.name == test_name.strip() assert updated_folder.rule_text == test_rule.strip() assert updated_folder.priority == int(test_priority) def test_add_folder_content_whitespace_handling(authenticated_client, mock_user): """Test that whitespace is properly handled in submitted content.""" test_name = ' Test Folder With Whitespace ' test_rule = ' Test rule with whitespace around it ' test_priority = '0' response = authenticated_client.post('/api/folders', data={'name': test_name, 'rule_text': test_rule, 'priority': test_priority}, content_type='application/x-www-form-urlencoded') assert response.status_code == 201 # Verify the folder was created with properly trimmed content created_folder = Folder.query.filter_by(name='Test Folder With Whitespace').first() assert created_folder is not None assert created_folder.name == 'Test Folder With Whitespace' # Should be trimmed assert created_folder.rule_text == 'Test rule with whitespace around it' # Should be trimmed assert created_folder.priority == int(test_priority) def test_edit_folder_content_whitespace_handling(authenticated_client, mock_folder): """Test that whitespace is properly handled in updated content.""" test_name = ' Updated Folder With Whitespace ' test_rule = ' Updated rule with whitespace around it ' test_priority = '1' response = authenticated_client.put(f'/api/folders/{mock_folder.id}', data={'name': test_name, 'rule_text': test_rule, 'priority': test_priority}, content_type='application/x-www-form-urlencoded') assert response.status_code == 200 # Verify the folder was updated with properly trimmed content updated_folder = Folder.query.filter_by(id=mock_folder.id).first() assert updated_folder is not None assert updated_folder.name == 'Updated Folder With Whitespace' # Should be trimmed assert updated_folder.rule_text == 'Updated rule with whitespace around it' # Should be trimmed assert updated_folder.priority == int(test_priority)