Skip to content
Merged
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
1 change: 0 additions & 1 deletion app/routes/admin_panel_comments.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@


@admin_panel_comments_blueprint.route("/admin/comments", methods=["GET", "POST"])
@admin_panel_comments_blueprint.route("/admin-panel/comments", methods=["GET", "POST"])
def admin_panel_comments():
if "username" in session:
Log.info(f"Admin: {session['username']} reached to comments admin panel")
Expand Down
1 change: 0 additions & 1 deletion app/routes/admin_panel_posts.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@


@admin_panel_posts_blueprint.route("/admin/posts", methods=["GET", "POST"])
@admin_panel_posts_blueprint.route("/admin-panel/posts", methods=["GET", "POST"])
def admin_panel_posts():
if "username" in session:
Log.info(f"Admin: {session['username']} reached to posts admin panel")
Expand Down
1 change: 0 additions & 1 deletion app/routes/admin_panel_users.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@


@admin_panel_users_blueprint.route("/admin/users", methods=["GET", "POST"])
@admin_panel_users_blueprint.route("/admin-panel/users", methods=["GET", "POST"])
def admin_panel_users():
if "username" in session:
Log.info(f"Admin: {session['username']} reached to users admin panel")
Expand Down
3 changes: 0 additions & 3 deletions app/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@ class Settings:
LOG_FOLDER_ROOT (str): Root path of the log folder.
LOG_FILE_ROOT (str): Root path of the log file.
LOG_JSON_ROOT (str): Root path of the log JSON file.
BREAKER_TEXT (str): Separator text used in log files.
APP_SECRET_KEY (str): Secret key for Flask sessions.
SESSION_PERMANENT (bool): Toggle permanent sessions for the Flask application.
DB_FOLDER_ROOT (str): Root path of the database folder.
Expand Down Expand Up @@ -120,8 +119,6 @@ class Settings:
LOG_FOLDER_ROOT = os.environ.get("LOG_FOLDER_ROOT", "log/")
LOG_FILE_ROOT = LOG_FOLDER_ROOT + "log.log"
LOG_JSON_ROOT = LOG_FOLDER_ROOT + "log.json"
BREAKER_TEXT = "\n"

# Session Configuration
APP_SECRET_KEY = os.environ.get("APP_SECRET_KEY", secrets.token_urlsafe(32))
SESSION_PERMANENT = _bool(os.environ.get("SESSION_PERMANENT", "True"))
Expand Down
2 changes: 0 additions & 2 deletions app/static/js/post_config.js

This file was deleted.

4 changes: 2 additions & 2 deletions app/utils/context_processor/return_post_url_id.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@


def return_post_url_id():
def url_id(title, content):
return get_post_url_id_from_post(title, content)
def url_id(post_id):
return get_post_url_id_from_post(post_id)

return dict(url_id=url_id)
28 changes: 0 additions & 28 deletions app/utils/time.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,34 +3,6 @@
"""

from datetime import datetime
from time import tzname


def current_time_zone():
"""
Returns the current system time zone as a string.
"""
return tzname[0]


def current_date():
"""
Returns the current date as a string in the format "dd.mm.yy".
"""
return datetime.now().strftime("%d.%m.%y")


def current_time(seconds=False, micro_seconds=False):
"""
Returns the current time as a string in the format "HH:MM" or "HH:MM:SS" depending on the value of the seconds parameter. If the micro_seconds parameter is set to True, the time will include microseconds as well.
"""
if not seconds:
return datetime.now().strftime("%H:%M")
else:
if micro_seconds:
return datetime.now().strftime("%H:%M:%S.%f")
else:
return datetime.now().strftime("%H:%M:%S")


def current_time_stamp():
Expand Down
3 changes: 1 addition & 2 deletions tests/e2e/helpers/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,11 @@
create_test_user,
get_user_by_username,
)
from tests.e2e.helpers.test_data import UserData, PostData
from tests.e2e.helpers.test_data import UserData

__all__ = [
"reset_database",
"create_test_user",
"get_user_by_username",
"UserData",
"PostData",
]
40 changes: 0 additions & 40 deletions tests/e2e/helpers/database_helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -105,41 +105,6 @@ def get_user_by_username(db_path: str, username: str) -> dict | None:
conn.close()


def delete_user(db_path: str, username: str) -> bool:
"""
Delete a user by username.
Returns True if user was deleted, False if not found.
"""
conn = get_db_connection(db_path)
cursor = conn.cursor()

try:
cursor.execute(
"DELETE FROM users WHERE LOWER(username) = LOWER(?)", (username,)
)
conn.commit()
return cursor.rowcount > 0
finally:
conn.close()


def user_exists(db_path: str, username: str) -> bool:
"""Check if a user exists by username."""
return get_user_by_username(db_path, username) is not None


def get_user_count(db_path: str) -> int:
"""Get the total number of users in the database."""
conn = get_db_connection(db_path)
cursor = conn.cursor()

try:
cursor.execute("SELECT COUNT(*) FROM users")
return cursor.fetchone()[0]
finally:
conn.close()


def get_user_by_email(db_path: str, email: str) -> dict | None:
"""
Get user data by email.
Expand Down Expand Up @@ -172,8 +137,3 @@ def get_user_points(db_path: str, username: str) -> int | None:
if user:
return user.get("points", 0)
return None


def email_exists(db_path: str, email: str) -> bool:
"""Check if an email exists in the database."""
return get_user_by_email(db_path, email) is not None
55 changes: 0 additions & 55 deletions tests/e2e/helpers/test_data.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,62 +21,7 @@ def generate(cls, **overrides) -> "UserData":
"""Generate test user data with optional overrides."""
return cls(**overrides)

@classmethod
def admin(cls) -> "UserData":
"""Generate admin user data."""
return cls(
username=f"testadmin_{uuid.uuid4().hex[:8]}",
email=f"admin_{uuid.uuid4().hex[:8]}@test.com",
role="admin",
)

@classmethod
def unverified(cls) -> "UserData":
"""Generate unverified user data."""
return cls(is_verified="False")


@dataclass
class PostData:
"""Test post data with default values."""

title: str = field(default_factory=lambda: f"Test Post {uuid.uuid4().hex[:8]}")
content: str = "This is test content for the post."
category: str = "test"
tags: str = "test,automation"
abstract: str = "Test post abstract"
url_id: str = field(default_factory=lambda: f"test-post-{uuid.uuid4().hex[:8]}")
author: str = "admin"

@classmethod
def generate(cls, **overrides) -> "PostData":
"""Generate test post data with optional overrides."""
return cls(**overrides)


# Invalid username test cases
INVALID_USERNAMES = [
"", # Empty
" ", # Whitespace only
"a" * 256, # Too long
"user@name", # Invalid character
"user<script>", # XSS attempt
]

# Invalid password test cases
INVALID_PASSWORDS = [
"", # Empty
" ", # Whitespace only
"a", # Too short (single char)
]

# Default admin credentials (from Settings)
DEFAULT_ADMIN_CREDENTIALS = {
"username": "admin",
"password": "admin",
"email": "admin@flaskblog.com",
}

# Test constants
TEST_TIMEOUT = 5000 # Default timeout in milliseconds
SLOW_TEST_TIMEOUT = 15000 # Timeout for slow tests
49 changes: 0 additions & 49 deletions tests/e2e/pages/base_page.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,6 @@ def __init__(self, page: Page, base_url: str):
self.base_url = base_url

# Common selectors
self.flash_toast = ".toast"
self.flash_alert = ".alert"
self.flash_success = ".alert-success"
self.flash_error = ".alert-error"

Expand All @@ -24,23 +22,6 @@ def navigate(self, path: str = "/"):
self.page.goto(url, wait_until="domcontentloaded")
return self

def get_flash_message(self) -> str | None:
"""Get the text content of the flash message if present."""
alert = self.page.locator(self.flash_alert).first
if alert.count() > 0:
return alert.text_content()
return None

def get_flash_messages(self) -> list[str]:
"""Get all flash message texts."""
alerts = self.page.locator(self.flash_alert)
messages = []
for i in range(alerts.count()):
text = alerts.nth(i).text_content()
if text:
messages.append(text.strip())
return messages

def expect_success_flash(self, timeout: int = 5000):
"""Assert that a success flash message is displayed."""
expect(self.page.locator(self.flash_success).first).to_be_visible(
Expand All @@ -50,33 +31,3 @@ def expect_success_flash(self, timeout: int = 5000):
def expect_error_flash(self, timeout: int = 5000):
"""Assert that an error flash message is displayed."""
expect(self.page.locator(self.flash_error).first).to_be_visible(timeout=timeout)

def expect_flash_contains(self, text: str, timeout: int = 5000):
"""Assert that a flash message contains specific text."""
expect(self.page.locator(self.flash_alert).first).to_contain_text(
text, timeout=timeout
)

def wait_for_navigation(self, url_pattern: str = None, timeout: int = 5000):
"""Wait for page navigation to complete."""
if url_pattern:
self.page.wait_for_url(url_pattern, timeout=timeout)
else:
self.page.wait_for_load_state("networkidle", timeout=timeout)

def is_logged_in(self) -> bool:
"""Check if user is logged in by looking for logout link in navbar."""
logout_link = self.page.locator('a[href="/logout"]')
return logout_link.count() > 0

def get_page_title(self) -> str:
"""Get the page title."""
return self.page.title()

def get_current_url(self) -> str:
"""Get the current page URL."""
return self.page.url

def take_screenshot(self, name: str):
"""Take a screenshot for debugging."""
self.page.screenshot(path=f"screenshots/{name}.png")
21 changes: 0 additions & 21 deletions tests/e2e/pages/login_page.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,6 @@ def __init__(self, page: Page, base_url: str):
self.submit_button = 'button[type="submit"]'
self.csrf_token = 'input[name="csrf_token"]'
self.forgot_password_link = 'a[href*="password_reset"]'
self.login_card = ".card"
self.card_title = ".card-title"

def navigate(self, path: str = "/login/redirect=&"):
"""Navigate to the login page."""
Expand Down Expand Up @@ -51,20 +49,6 @@ def login(self, username: str, password: str):
self.click_submit()
return self

def login_and_expect_success(
self, username: str, password: str, timeout: int = 5000
):
"""Login and verify successful login with flash message."""
self.login(username, password)
self.expect_success_flash(timeout=timeout)
return self

def login_and_expect_error(self, username: str, password: str, timeout: int = 5000):
"""Login and verify failed login with error flash message."""
self.login(username, password)
self.expect_error_flash(timeout=timeout)
return self

def expect_page_loaded(self):
"""Verify that all login page elements are present."""
expect(self.page.locator(self.username_input)).to_be_visible()
Expand All @@ -86,11 +70,6 @@ def expect_has_forgot_password_link(self):
expect(self.page.locator(self.forgot_password_link)).to_be_visible()
return self

def click_forgot_password(self):
"""Click the forgot password link."""
self.page.click(self.forgot_password_link)
return self

def get_username_validation_message(self) -> str:
"""Get HTML5 validation message for username field."""
return self.page.locator(self.username_input).evaluate(
Expand Down
40 changes: 0 additions & 40 deletions tests/e2e/pages/navbar_component.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,22 +15,13 @@ def __init__(self, page: Page):
self.navbar = ".navbar"
self.logout_link = 'a[href="/logout"]'
self.login_link = 'a[href*="/login"]'
self.signup_link = 'a[href="/signup"]'
self.profile_avatar = ".navbar .avatar"
self.create_post_link = 'a[href="/create-post"]'
self.search_input = "#search-input"
self.search_button = 'button[onclick="search()"]'
self.theme_button = 'button[onclick="theme_modal.showModal()"]'
self.home_link = 'a[href="/"]'

def is_logged_in(self) -> bool:
"""Check if user is logged in by looking for logout link."""
return self.page.locator(self.logout_link).count() > 0

def is_logged_out(self) -> bool:
"""Check if user is logged out by looking for login link."""
return self.page.locator(self.login_link).count() > 0

def expect_logged_in(self, timeout: int = 5000):
"""Assert that user is logged in (logout link visible)."""
expect(self.page.locator(self.logout_link)).to_be_visible(timeout=timeout)
Expand All @@ -51,34 +42,3 @@ def logout(self):
"""Click the logout link."""
self.page.click(self.logout_link)
return self

def click_login(self):
"""Click the login link."""
self.page.click(self.login_link)
return self

def click_signup(self):
"""Click the signup link."""
self.page.click(self.signup_link)
return self

def click_home(self):
"""Click the home link."""
self.page.click(self.home_link)
return self

def click_create_post(self):
"""Click the create post link."""
self.page.click(self.create_post_link)
return self

def search(self, query: str):
"""Perform a search."""
self.page.fill(self.search_input, query)
self.page.click(self.search_button)
return self

def click_theme_button(self):
"""Click the theme picker button."""
self.page.click(self.theme_button)
return self
Loading