mirror of
https://github.com/DRYTRIX/TimeTracker.git
synced 2026-05-17 18:38:46 -05:00
766 lines
29 KiB
Python
766 lines
29 KiB
Python
"""
|
|
Comprehensive tests for user settings routes and functionality.
|
|
Tests settings page rendering, form validation, preference updates, and API endpoints.
|
|
"""
|
|
|
|
import pytest
|
|
from flask import url_for
|
|
from app.models import User
|
|
from app import db
|
|
import pytz
|
|
|
|
|
|
class TestUserSettingsPage:
|
|
"""Tests for the user settings page GET endpoint"""
|
|
|
|
def test_settings_page_requires_login(self, client):
|
|
"""Test that settings page redirects to login if not authenticated"""
|
|
response = client.get("/settings", follow_redirects=False)
|
|
assert response.status_code == 302
|
|
assert "/login" in response.location
|
|
|
|
def test_settings_page_loads_for_authenticated_user(self, client, user):
|
|
"""Test that settings page loads successfully for authenticated users"""
|
|
# Log in the user
|
|
with client.session_transaction() as sess:
|
|
sess["_user_id"] = str(user.id)
|
|
|
|
response = client.get("/settings")
|
|
assert response.status_code == 200
|
|
assert b"Settings" in response.data
|
|
assert b"Notification Preferences" in response.data
|
|
assert b"Display Preferences" in response.data
|
|
assert b"Regional Settings" in response.data
|
|
|
|
def test_settings_page_displays_current_values(self, client, user):
|
|
"""Test that settings page displays user's current settings"""
|
|
# Set some specific settings
|
|
user.theme_preference = "dark"
|
|
user.timezone = "America/New_York"
|
|
user.date_format = "MM/DD/YYYY"
|
|
user.email_notifications = True
|
|
db.session.commit()
|
|
|
|
with client.session_transaction() as sess:
|
|
sess["_user_id"] = str(user.id)
|
|
|
|
response = client.get("/settings")
|
|
assert response.status_code == 200
|
|
data = response.data.decode("utf-8")
|
|
|
|
# Check that current values are selected
|
|
assert 'value="dark" selected' in data or 'value="dark"' in data
|
|
assert "America/New_York" in data
|
|
assert "email_notifications" in data
|
|
|
|
def test_settings_page_includes_all_sections(self, client, user):
|
|
"""Test that all settings sections are present on the page"""
|
|
with client.session_transaction() as sess:
|
|
sess["_user_id"] = str(user.id)
|
|
|
|
response = client.get("/settings")
|
|
data = response.data.decode("utf-8")
|
|
|
|
# Check for all major sections
|
|
assert "Profile Information" in data
|
|
assert "Notification Preferences" in data
|
|
assert "Display Preferences" in data
|
|
assert "Time Rounding Preferences" in data
|
|
assert "Overtime Settings" in data
|
|
assert "UI Customization" in data
|
|
assert "Regional Settings" in data
|
|
|
|
|
|
class TestUserSettingsUpdate:
|
|
"""Tests for updating user settings via POST"""
|
|
|
|
def test_update_profile_information(self, client, user):
|
|
"""Test updating profile information (full name and email)"""
|
|
with client.session_transaction() as sess:
|
|
sess["_user_id"] = str(user.id)
|
|
|
|
response = client.post(
|
|
"/settings", data={"full_name": "John Doe", "email": "john.doe@example.com"}, follow_redirects=True
|
|
)
|
|
|
|
assert response.status_code == 200
|
|
assert b"Settings saved successfully" in response.data
|
|
|
|
# Verify changes in database
|
|
db.session.refresh(user)
|
|
assert user.full_name == "John Doe"
|
|
assert user.email == "john.doe@example.com"
|
|
|
|
def test_update_notification_preferences(self, client, user):
|
|
"""Test updating email notification preferences"""
|
|
with client.session_transaction() as sess:
|
|
sess["_user_id"] = str(user.id)
|
|
|
|
response = client.post(
|
|
"/settings",
|
|
data={
|
|
"email_notifications": "on",
|
|
"notification_overdue_invoices": "on",
|
|
"notification_task_assigned": "on",
|
|
"notification_task_comments": "on",
|
|
"notification_weekly_summary": "on",
|
|
},
|
|
follow_redirects=True,
|
|
)
|
|
|
|
assert response.status_code == 200
|
|
|
|
# Verify changes
|
|
db.session.refresh(user)
|
|
assert user.email_notifications is True
|
|
assert user.notification_overdue_invoices is True
|
|
assert user.notification_task_assigned is True
|
|
assert user.notification_task_comments is True
|
|
assert user.notification_weekly_summary is True
|
|
|
|
def test_update_notification_preferences_all_disabled(self, client, user):
|
|
"""Test disabling all notification preferences"""
|
|
# First enable them
|
|
user.email_notifications = True
|
|
user.notification_overdue_invoices = True
|
|
db.session.commit()
|
|
|
|
with client.session_transaction() as sess:
|
|
sess["_user_id"] = str(user.id)
|
|
|
|
# POST without checkbox values (unchecked checkboxes don't send values)
|
|
response = client.post("/settings", data={"full_name": user.full_name or ""}, follow_redirects=True)
|
|
|
|
assert response.status_code == 200
|
|
|
|
# Verify all notifications are disabled
|
|
db.session.refresh(user)
|
|
assert user.email_notifications is False
|
|
assert user.notification_overdue_invoices is False
|
|
assert user.notification_task_assigned is False
|
|
assert user.notification_task_comments is False
|
|
assert user.notification_weekly_summary is False
|
|
|
|
def test_update_theme_preference(self, client, user):
|
|
"""Test updating theme preference"""
|
|
with client.session_transaction() as sess:
|
|
sess["_user_id"] = str(user.id)
|
|
|
|
# Test setting dark theme
|
|
response = client.post("/settings", data={"theme_preference": "dark"}, follow_redirects=True)
|
|
|
|
assert response.status_code == 200
|
|
db.session.refresh(user)
|
|
assert user.theme_preference == "dark"
|
|
|
|
# Test setting light theme
|
|
response = client.post("/settings", data={"theme_preference": "light"}, follow_redirects=True)
|
|
|
|
assert response.status_code == 200
|
|
db.session.refresh(user)
|
|
assert user.theme_preference == "light"
|
|
|
|
# Test setting system default (empty string)
|
|
response = client.post("/settings", data={"theme_preference": ""}, follow_redirects=True)
|
|
|
|
assert response.status_code == 200
|
|
db.session.refresh(user)
|
|
assert user.theme_preference is None
|
|
|
|
def test_update_timezone(self, client, user):
|
|
"""Test updating timezone preference"""
|
|
with client.session_transaction() as sess:
|
|
sess["_user_id"] = str(user.id)
|
|
|
|
response = client.post("/settings", data={"timezone": "America/New_York"}, follow_redirects=True)
|
|
|
|
assert response.status_code == 200
|
|
db.session.refresh(user)
|
|
assert user.timezone == "America/New_York"
|
|
|
|
def test_update_timezone_with_invalid_value(self, client, user):
|
|
"""Test that invalid timezone is rejected"""
|
|
with client.session_transaction() as sess:
|
|
sess["_user_id"] = str(user.id)
|
|
|
|
response = client.post("/settings", data={"timezone": "Invalid/Timezone"}, follow_redirects=True)
|
|
|
|
assert response.status_code == 200
|
|
assert b"Invalid timezone selected" in response.data
|
|
|
|
def test_update_calendar_default_view_via_settings_form(self, client, user):
|
|
"""Test saving calendar default view via settings form POST."""
|
|
with client.session_transaction() as sess:
|
|
sess["_user_id"] = str(user.id)
|
|
|
|
response = client.post(
|
|
"/settings",
|
|
data={"calendar_default_view": "week"},
|
|
follow_redirects=True,
|
|
)
|
|
assert response.status_code == 200
|
|
assert b"Settings saved successfully" in response.data
|
|
db.session.refresh(user)
|
|
assert user.calendar_default_view == "week"
|
|
|
|
# Save "Remember last view" (empty)
|
|
response2 = client.post(
|
|
"/settings",
|
|
data={"calendar_default_view": ""},
|
|
follow_redirects=True,
|
|
)
|
|
assert response2.status_code == 200
|
|
db.session.refresh(user)
|
|
assert user.calendar_default_view is None
|
|
|
|
def test_update_date_format(self, client, user):
|
|
"""Test updating date format preference"""
|
|
with client.session_transaction() as sess:
|
|
sess["_user_id"] = str(user.id)
|
|
|
|
for date_format in ["YYYY-MM-DD", "MM/DD/YYYY", "DD/MM/YYYY", "DD.MM.YYYY"]:
|
|
response = client.post("/settings", data={"date_format": date_format}, follow_redirects=True)
|
|
|
|
assert response.status_code == 200
|
|
db.session.refresh(user)
|
|
assert user.date_format == date_format
|
|
|
|
def test_update_time_format(self, client, user):
|
|
"""Test updating time format preference (12h/24h)"""
|
|
with client.session_transaction() as sess:
|
|
sess["_user_id"] = str(user.id)
|
|
|
|
# Test 24-hour format
|
|
response = client.post("/settings", data={"time_format": "24h"}, follow_redirects=True)
|
|
|
|
assert response.status_code == 200
|
|
db.session.refresh(user)
|
|
assert user.time_format == "24h"
|
|
|
|
# Test 12-hour format
|
|
response = client.post("/settings", data={"time_format": "12h"}, follow_redirects=True)
|
|
|
|
assert response.status_code == 200
|
|
db.session.refresh(user)
|
|
assert user.time_format == "12h"
|
|
|
|
def test_update_week_start_day(self, client, user):
|
|
"""Test updating week start day preference"""
|
|
with client.session_transaction() as sess:
|
|
sess["_user_id"] = str(user.id)
|
|
|
|
# Test Monday (1)
|
|
response = client.post("/settings", data={"week_start_day": "1"}, follow_redirects=True)
|
|
|
|
assert response.status_code == 200
|
|
db.session.refresh(user)
|
|
assert user.week_start_day == 1
|
|
|
|
# Test Sunday (0)
|
|
response = client.post("/settings", data={"week_start_day": "0"}, follow_redirects=True)
|
|
|
|
assert response.status_code == 200
|
|
db.session.refresh(user)
|
|
assert user.week_start_day == 0
|
|
|
|
def test_update_time_rounding_preferences(self, client, user):
|
|
"""Test updating time rounding preferences"""
|
|
with client.session_transaction() as sess:
|
|
sess["_user_id"] = str(user.id)
|
|
|
|
response = client.post(
|
|
"/settings",
|
|
data={"time_rounding_enabled": "on", "time_rounding_minutes": "15", "time_rounding_method": "up"},
|
|
follow_redirects=True,
|
|
)
|
|
|
|
assert response.status_code == 200
|
|
db.session.refresh(user)
|
|
assert user.time_rounding_enabled is True
|
|
assert user.time_rounding_minutes == 15
|
|
assert user.time_rounding_method == "up"
|
|
|
|
def test_update_time_rounding_intervals(self, client, user):
|
|
"""Test all valid time rounding intervals"""
|
|
with client.session_transaction() as sess:
|
|
sess["_user_id"] = str(user.id)
|
|
|
|
valid_intervals = [1, 5, 10, 15, 30, 60]
|
|
|
|
for interval in valid_intervals:
|
|
response = client.post(
|
|
"/settings",
|
|
data={"time_rounding_enabled": "on", "time_rounding_minutes": str(interval)},
|
|
follow_redirects=True,
|
|
)
|
|
|
|
assert response.status_code == 200
|
|
db.session.refresh(user)
|
|
assert user.time_rounding_minutes == interval
|
|
|
|
def test_update_time_rounding_methods(self, client, user):
|
|
"""Test all valid time rounding methods"""
|
|
with client.session_transaction() as sess:
|
|
sess["_user_id"] = str(user.id)
|
|
|
|
valid_methods = ["nearest", "up", "down"]
|
|
|
|
for method in valid_methods:
|
|
response = client.post(
|
|
"/settings", data={"time_rounding_enabled": "on", "time_rounding_method": method}, follow_redirects=True
|
|
)
|
|
|
|
assert response.status_code == 200
|
|
db.session.refresh(user)
|
|
assert user.time_rounding_method == method
|
|
|
|
def test_update_standard_hours_per_day(self, client, user):
|
|
"""Test updating standard hours per day for overtime calculation"""
|
|
with client.session_transaction() as sess:
|
|
sess["_user_id"] = str(user.id)
|
|
|
|
response = client.post("/settings", data={"standard_hours_per_day": "7.5"}, follow_redirects=True)
|
|
|
|
assert response.status_code == 200
|
|
db.session.refresh(user)
|
|
assert user.standard_hours_per_day == 7.5
|
|
|
|
def test_update_standard_hours_validation(self, client, user):
|
|
"""Test validation of standard hours per day (must be between 0.5 and 24)"""
|
|
with client.session_transaction() as sess:
|
|
sess["_user_id"] = str(user.id)
|
|
|
|
# Test too low
|
|
response = client.post("/settings", data={"standard_hours_per_day": "0.2"}, follow_redirects=True)
|
|
|
|
assert response.status_code == 200
|
|
assert b"Standard hours per day must be between 0.5 and 24" in response.data
|
|
|
|
# Test too high
|
|
response = client.post("/settings", data={"standard_hours_per_day": "25"}, follow_redirects=True)
|
|
|
|
assert response.status_code == 200
|
|
assert b"Standard hours per day must be between 0.5 and 24" in response.data
|
|
|
|
def test_update_overtime_calculation_mode_and_weekly_hours(self, client, user):
|
|
"""Test updating overtime calculation mode to weekly and standard hours per week."""
|
|
with client.session_transaction() as sess:
|
|
sess["_user_id"] = str(user.id)
|
|
|
|
response = client.post(
|
|
"/settings",
|
|
data={
|
|
"overtime_calculation_mode": "weekly",
|
|
"standard_hours_per_week": "20",
|
|
},
|
|
follow_redirects=True,
|
|
)
|
|
assert response.status_code == 200
|
|
db.session.refresh(user)
|
|
assert getattr(user, "overtime_calculation_mode", "daily") == "weekly"
|
|
assert getattr(user, "standard_hours_per_week", None) == 20.0
|
|
|
|
def test_update_standard_hours_per_week_validation(self, client, user):
|
|
"""Test validation of standard hours per week (must be between 1 and 168)."""
|
|
with client.session_transaction() as sess:
|
|
sess["_user_id"] = str(user.id)
|
|
|
|
response = client.post(
|
|
"/settings",
|
|
data={"overtime_calculation_mode": "weekly", "standard_hours_per_week": "0.5"},
|
|
follow_redirects=True,
|
|
)
|
|
assert response.status_code == 200
|
|
assert b"Standard hours per week must be between 1 and 168" in response.data
|
|
|
|
response = client.post(
|
|
"/settings",
|
|
data={"overtime_calculation_mode": "weekly", "standard_hours_per_week": "200"},
|
|
follow_redirects=True,
|
|
)
|
|
assert response.status_code == 200
|
|
assert b"Standard hours per week must be between 1 and 168" in response.data
|
|
|
|
def test_update_language_preference(self, client, user):
|
|
"""Test updating language preference"""
|
|
with client.session_transaction() as sess:
|
|
sess["_user_id"] = str(user.id)
|
|
|
|
response = client.post("/settings", data={"preferred_language": "de"}, follow_redirects=True)
|
|
|
|
assert response.status_code == 200
|
|
db.session.refresh(user)
|
|
assert user.preferred_language == "de"
|
|
|
|
def test_update_multiple_settings_at_once(self, client, user):
|
|
"""Test updating multiple settings in a single request"""
|
|
with client.session_transaction() as sess:
|
|
sess["_user_id"] = str(user.id)
|
|
|
|
response = client.post(
|
|
"/settings",
|
|
data={
|
|
"full_name": "Jane Smith",
|
|
"email": "jane@example.com",
|
|
"theme_preference": "dark",
|
|
"timezone": "Europe/London",
|
|
"date_format": "DD/MM/YYYY",
|
|
"time_format": "24h",
|
|
"email_notifications": "on",
|
|
"time_rounding_enabled": "on",
|
|
"time_rounding_minutes": "15",
|
|
"standard_hours_per_day": "8",
|
|
},
|
|
follow_redirects=True,
|
|
)
|
|
|
|
assert response.status_code == 200
|
|
assert b"Settings saved successfully" in response.data
|
|
|
|
# Verify all changes
|
|
db.session.refresh(user)
|
|
assert user.full_name == "Jane Smith"
|
|
assert user.email == "jane@example.com"
|
|
assert user.theme_preference == "dark"
|
|
assert user.timezone == "Europe/London"
|
|
assert user.date_format == "DD/MM/YYYY"
|
|
assert user.time_format == "24h"
|
|
assert user.email_notifications is True
|
|
assert user.time_rounding_enabled is True
|
|
assert user.time_rounding_minutes == 15
|
|
assert user.standard_hours_per_day == 8.0
|
|
|
|
|
|
class TestUserSettingsAPIEndpoints:
|
|
"""Tests for API endpoints for updating preferences"""
|
|
|
|
def test_update_preferences_api_requires_login(self, client):
|
|
"""Test that API endpoint requires authentication"""
|
|
response = client.patch("/api/preferences", json={"theme_preference": "dark"})
|
|
assert response.status_code == 302 # Redirect to login
|
|
|
|
def test_update_theme_via_api(self, client, user):
|
|
"""Test updating theme via AJAX API"""
|
|
with client.session_transaction() as sess:
|
|
sess["_user_id"] = str(user.id)
|
|
|
|
response = client.patch("/api/preferences", json={"theme_preference": "dark"})
|
|
|
|
assert response.status_code == 200
|
|
data = response.get_json()
|
|
assert data["success"] is True
|
|
|
|
db.session.refresh(user)
|
|
assert user.theme_preference == "dark"
|
|
|
|
def test_update_email_notifications_via_api(self, client, user):
|
|
"""Test updating email notifications via API"""
|
|
with client.session_transaction() as sess:
|
|
sess["_user_id"] = str(user.id)
|
|
|
|
response = client.patch("/api/preferences", json={"email_notifications": False})
|
|
|
|
assert response.status_code == 200
|
|
data = response.get_json()
|
|
assert data["success"] is True
|
|
|
|
db.session.refresh(user)
|
|
assert user.email_notifications is False
|
|
|
|
def test_update_timezone_via_api(self, client, user):
|
|
"""Test updating timezone via API"""
|
|
with client.session_transaction() as sess:
|
|
sess["_user_id"] = str(user.id)
|
|
|
|
response = client.patch("/api/preferences", json={"timezone": "Asia/Tokyo"})
|
|
|
|
assert response.status_code == 200
|
|
data = response.get_json()
|
|
assert data["success"] is True
|
|
|
|
db.session.refresh(user)
|
|
assert user.timezone == "Asia/Tokyo"
|
|
|
|
def test_update_invalid_timezone_via_api(self, client, user):
|
|
"""Test that API rejects invalid timezone"""
|
|
with client.session_transaction() as sess:
|
|
sess["_user_id"] = str(user.id)
|
|
|
|
response = client.patch("/api/preferences", json={"timezone": "Invalid/Zone"})
|
|
|
|
assert response.status_code == 400
|
|
data = response.get_json()
|
|
assert "error" in data
|
|
|
|
def test_update_calendar_default_view_via_api(self, client, user):
|
|
"""Test updating calendar default view via PATCH /api/preferences."""
|
|
with client.session_transaction() as sess:
|
|
sess["_user_id"] = str(user.id)
|
|
|
|
response = client.patch("/api/preferences", json={"calendar_default_view": "week"})
|
|
assert response.status_code == 200
|
|
data = response.get_json()
|
|
assert data.get("success") is True
|
|
db.session.refresh(user)
|
|
assert user.calendar_default_view == "week"
|
|
|
|
# Clear to "remember last view"
|
|
response2 = client.patch("/api/preferences", json={"calendar_default_view": ""})
|
|
assert response2.status_code == 200
|
|
db.session.refresh(user)
|
|
assert user.calendar_default_view is None
|
|
|
|
def test_update_calendar_default_view_invalid_via_api(self, client, user):
|
|
"""Test that invalid calendar_default_view is rejected."""
|
|
with client.session_transaction() as sess:
|
|
sess["_user_id"] = str(user.id)
|
|
|
|
response = client.patch("/api/preferences", json={"calendar_default_view": "year"})
|
|
assert response.status_code == 400
|
|
data = response.get_json()
|
|
assert "error" in data
|
|
|
|
def test_update_ui_feature_flags(self, client, user):
|
|
"""Test updating UI feature flags"""
|
|
with client.session_transaction() as sess:
|
|
sess["_user_id"] = str(user.id)
|
|
|
|
response = client.post(
|
|
"/settings",
|
|
data={
|
|
"ui_show_inventory": "on",
|
|
"ui_show_mileage": "on",
|
|
# ui_show_per_diem and ui_show_kanban_board not checked (should be False)
|
|
},
|
|
follow_redirects=True,
|
|
)
|
|
|
|
assert response.status_code == 200
|
|
assert b"Settings saved successfully" in response.data
|
|
|
|
# Verify changes
|
|
db.session.refresh(user)
|
|
assert user.ui_show_inventory is True
|
|
assert user.ui_show_mileage is True
|
|
assert user.ui_show_per_diem is False
|
|
assert user.ui_show_kanban_board is False
|
|
|
|
def test_ui_feature_flags_default_to_true(self, client, user):
|
|
"""Test that UI feature flags default to True for new users"""
|
|
# Create a new user
|
|
new_user = User(username="newuser", email="newuser@example.com")
|
|
new_user.set_password("password")
|
|
db.session.add(new_user)
|
|
db.session.commit()
|
|
|
|
# Check defaults
|
|
assert new_user.ui_show_inventory is True
|
|
assert new_user.ui_show_mileage is True
|
|
assert new_user.ui_show_per_diem is True
|
|
assert new_user.ui_show_kanban_board is True
|
|
|
|
def test_settings_page_includes_ui_customization_section(self, client, user):
|
|
"""Test that settings page includes UI customization section"""
|
|
with client.session_transaction() as sess:
|
|
sess["_user_id"] = str(user.id)
|
|
|
|
response = client.get("/settings")
|
|
data = response.data.decode("utf-8")
|
|
|
|
# Check for UI customization section and key flags
|
|
assert "UI Customization" in data
|
|
assert "ui_show_inventory" in data
|
|
assert "ui_show_mileage" in data
|
|
assert "ui_show_per_diem" in data
|
|
assert "ui_show_kanban_board" in data
|
|
assert "ui_show_calendar" in data
|
|
assert "ui_show_quotes" in data
|
|
assert "ui_show_reports" in data
|
|
assert "ui_show_analytics" in data
|
|
assert "ui_show_tools" in data
|
|
|
|
def test_update_ui_feature_flags(self, client, user):
|
|
"""Test updating UI feature flags"""
|
|
with client.session_transaction() as sess:
|
|
sess["_user_id"] = str(user.id)
|
|
|
|
response = client.post(
|
|
"/settings",
|
|
data={
|
|
"ui_show_inventory": "on",
|
|
"ui_show_mileage": "on",
|
|
"ui_show_calendar": "on",
|
|
"ui_show_quotes": "on",
|
|
# Other flags not checked (should be False)
|
|
},
|
|
follow_redirects=True,
|
|
)
|
|
|
|
assert response.status_code == 200
|
|
assert b"Settings saved successfully" in response.data
|
|
|
|
# Verify changes
|
|
db.session.refresh(user)
|
|
assert user.ui_show_inventory is True
|
|
assert user.ui_show_mileage is True
|
|
assert user.ui_show_calendar is True
|
|
assert user.ui_show_quotes is True
|
|
assert user.ui_show_per_diem is False
|
|
assert user.ui_show_kanban_board is False
|
|
assert user.ui_show_reports is False
|
|
|
|
def test_ui_feature_flags_default_to_true(self, client, user):
|
|
"""Test that UI feature flags default to True for new users"""
|
|
# Create a new user
|
|
new_user = User(username="newuser", email="newuser@example.com")
|
|
new_user.set_password("password")
|
|
db.session.add(new_user)
|
|
db.session.commit()
|
|
|
|
# Check defaults - all should be True
|
|
assert new_user.ui_show_inventory is True
|
|
assert new_user.ui_show_mileage is True
|
|
assert new_user.ui_show_per_diem is True
|
|
assert new_user.ui_show_kanban_board is True
|
|
assert new_user.ui_show_calendar is True
|
|
assert new_user.ui_show_project_templates is True
|
|
assert new_user.ui_show_gantt_chart is True
|
|
assert new_user.ui_show_weekly_goals is True
|
|
assert new_user.ui_show_quotes is True
|
|
assert new_user.ui_show_reports is True
|
|
assert new_user.ui_show_analytics is True
|
|
assert new_user.ui_show_tools is True
|
|
|
|
def test_settings_page_includes_ui_customization_section(self, client, user):
|
|
"""Test that settings page includes UI customization section"""
|
|
with client.session_transaction() as sess:
|
|
sess["_user_id"] = str(user.id)
|
|
|
|
response = client.get("/settings")
|
|
data = response.data.decode("utf-8")
|
|
|
|
# Check for UI customization section and key flags
|
|
assert "UI Customization" in data
|
|
assert "ui_show_inventory" in data
|
|
assert "ui_show_mileage" in data
|
|
assert "ui_show_per_diem" in data
|
|
assert "ui_show_kanban_board" in data
|
|
assert "ui_show_calendar" in data
|
|
assert "ui_show_quotes" in data
|
|
assert "ui_show_reports" in data
|
|
assert "ui_show_analytics" in data
|
|
assert "ui_show_tools" in data
|
|
|
|
def test_set_theme_api_endpoint(self, client, user):
|
|
"""Test the dedicated theme switcher API endpoint"""
|
|
with client.session_transaction() as sess:
|
|
sess["_user_id"] = str(user.id)
|
|
|
|
# Test setting dark theme
|
|
response = client.post("/api/theme", json={"theme": "dark"})
|
|
|
|
assert response.status_code == 200
|
|
data = response.get_json()
|
|
assert data["success"] is True
|
|
assert data["theme"] == "dark"
|
|
|
|
db.session.refresh(user)
|
|
assert user.theme_preference == "dark"
|
|
|
|
# Test setting system default
|
|
response = client.post("/api/theme", json={"theme": ""})
|
|
|
|
assert response.status_code == 200
|
|
data = response.get_json()
|
|
assert data["success"] is True
|
|
assert data["theme"] == "system"
|
|
|
|
db.session.refresh(user)
|
|
assert user.theme_preference is None
|
|
|
|
def test_set_invalid_theme_via_api(self, client, user):
|
|
"""Test that API rejects invalid theme values"""
|
|
with client.session_transaction() as sess:
|
|
sess["_user_id"] = str(user.id)
|
|
|
|
response = client.post("/api/theme", json={"theme": "invalid"})
|
|
|
|
assert response.status_code == 400
|
|
data = response.get_json()
|
|
assert "error" in data
|
|
|
|
|
|
class TestUserSettingsIntegration:
|
|
"""Integration tests for user settings feature"""
|
|
|
|
def test_settings_persist_across_sessions(self, client, user):
|
|
"""Test that settings persist after saving and reloading"""
|
|
# Save settings
|
|
with client.session_transaction() as sess:
|
|
sess["_user_id"] = str(user.id)
|
|
|
|
client.post(
|
|
"/settings",
|
|
data={
|
|
"full_name": "Test User",
|
|
"email": "test@example.com",
|
|
"theme_preference": "dark",
|
|
"timezone": "America/Los_Angeles",
|
|
"date_format": "MM/DD/YYYY",
|
|
"email_notifications": "on",
|
|
"time_rounding_enabled": "on",
|
|
"time_rounding_minutes": "15",
|
|
"standard_hours_per_day": "8",
|
|
},
|
|
follow_redirects=True,
|
|
)
|
|
|
|
# Reload page and verify settings are still there
|
|
response = client.get("/settings")
|
|
data = response.data.decode("utf-8")
|
|
|
|
assert "Test User" in data
|
|
assert "test@example.com" in data
|
|
assert "America/Los_Angeles" in data
|
|
|
|
def test_default_settings_for_new_user(self, app):
|
|
"""Test that new users get appropriate default settings"""
|
|
with app.app_context():
|
|
new_user = User(username="newuser", role="user")
|
|
db.session.add(new_user)
|
|
db.session.commit()
|
|
|
|
# Check defaults
|
|
assert new_user.email_notifications is True
|
|
assert new_user.notification_overdue_invoices is True
|
|
assert new_user.notification_task_assigned is True
|
|
assert new_user.notification_task_comments is True
|
|
assert new_user.notification_weekly_summary is False
|
|
assert new_user.date_format == "YYYY-MM-DD"
|
|
assert new_user.time_format == "24h"
|
|
assert new_user.week_start_day == 1
|
|
assert new_user.time_rounding_enabled is True
|
|
assert new_user.time_rounding_minutes == 1
|
|
assert new_user.time_rounding_method == "nearest"
|
|
assert new_user.standard_hours_per_day == 8.0
|
|
|
|
def test_settings_form_csrf_protection(self, app):
|
|
"""Test that settings form is protected with CSRF token"""
|
|
# Create app with CSRF enabled
|
|
app.config["WTF_CSRF_ENABLED"] = True
|
|
client = app.test_client()
|
|
|
|
# Create a test user
|
|
with app.app_context():
|
|
user = User(username="testuser", role="user")
|
|
db.session.add(user)
|
|
db.session.commit()
|
|
user_id = user.id
|
|
|
|
with client.session_transaction() as sess:
|
|
sess["_user_id"] = str(user_id)
|
|
|
|
# Verify CSRF token is present in the form
|
|
response = client.get("/settings")
|
|
assert b"csrf_token" in response.data or b"CSRF" in response.data
|