Files
devplacepy/tests/e2e/auth/login.py
T

236 lines
7.8 KiB
Python
Raw Normal View History

# retoor <retoor@molodetz.nl>
import hashlib
import time
from datetime import datetime, timedelta, timezone
from playwright.sync_api import expect
from tests.conftest import BASE_URL
from devplacepy.database import get_table
from devplacepy.utils import hash_password, generate_uid
from uuid import uuid4
from datetime import datetime, timezone
import requests
def _seed_news_seo():
from datetime import datetime, timezone
from devplacepy.database import get_table
from devplacepy.utils import generate_uid, make_combined_slug
uid = generate_uid()
title = f"SEO Test News Article {uid.split('-')[-1]}"
slug = make_combined_slug(title, uid)
get_table("news").insert(
{
"deleted_at": None,
"deleted_by": None,
"uid": uid,
"slug": slug,
"title": title,
"description": "A seeded news article for SEO tests.",
"content": "Body content for the seeded article.",
"url": "https://example.com/article",
"source_name": "ExampleSource",
"status": "published",
"synced_at": datetime.now(timezone.utc).isoformat(),
"show_on_landing": 0,
"grade": 8,
}
)
return slug, uid
def _seed_owner():
from datetime import datetime, timezone
from uuid import uuid4
from devplacepy.database import get_table
uid = str(uuid4())
get_table("users").insert(
{
"uid": uid,
"username": f"seo_{uid[:8]}",
"terms_version": "1",
"email": f"{uid[:8]}@seo.test",
"password_hash": "x",
"role": "Member",
"is_active": True,
"created_at": datetime.now(timezone.utc).isoformat(),
}
)
return uid
def _seed_post_seo(image=None):
from datetime import datetime, timezone
from uuid import uuid4
from devplacepy.database import get_table
from devplacepy.utils import make_combined_slug
owner = _seed_owner()
uid = str(uuid4())
slug = make_combined_slug("SEO Detail Post", uid)
get_table("posts").insert(
{
"deleted_at": None,
"deleted_by": None,
"uid": uid,
"user_uid": owner,
"slug": slug,
"title": "SEO Detail Post",
"content": "Body text for the SEO detail post.",
"topic": "general",
"project_uid": None,
"image": image,
"stars": 0,
"created_at": datetime.now(timezone.utc).isoformat(),
}
)
return slug, uid
def _seed_gist():
from datetime import datetime, timezone
from uuid import uuid4
from devplacepy.database import get_table
from devplacepy.utils import make_combined_slug
owner = _seed_owner()
uid = str(uuid4())
slug = make_combined_slug("SEO Detail Gist", uid)
get_table("gists").insert(
{
"deleted_at": None,
"deleted_by": None,
"uid": uid,
"user_uid": owner,
"slug": slug,
"title": "SEO Detail Gist",
"description": "Gist description for SEO tests.",
"source_code": "print('seo')",
"language": "python",
"stars": 0,
"created_at": datetime.now(timezone.utc).isoformat(),
}
)
return slug, uid
def _seed_project():
from datetime import datetime, timezone
from uuid import uuid4
from devplacepy.database import get_table
from devplacepy.utils import make_combined_slug
owner = _seed_owner()
uid = str(uuid4())
slug = make_combined_slug("SEO Detail Project", uid)
get_table("projects").insert(
{
"deleted_at": None,
"deleted_by": None,
"uid": uid,
"user_uid": owner,
"slug": slug,
"title": "SEO Detail Project",
"description": "Project description for SEO tests.",
"project_type": "software",
"platforms": "Linux",
"status": "Released",
"stars": 0,
"created_at": datetime.now(timezone.utc).isoformat(),
}
)
return slug, uid
def _seed_news_image(news_uid):
from devplacepy.database import get_table
get_table("news_images").insert(
{
"deleted_at": None,
"deleted_by": None,
"news_uid": news_uid,
"url": "https://example.com/seo-news-image.jpg",
}
)
def _seed_feed_posts(count):
from datetime import datetime, timezone, timedelta
from uuid import uuid4
from devplacepy.database import get_table
from devplacepy.utils import make_combined_slug
owner = _seed_owner()
topic = f"seopag{owner[:8]}"
base = datetime(2026, 1, 1, tzinfo=timezone.utc)
posts = get_table("posts")
for i in range(count):
uid = str(uuid4())
posts.insert(
{
"deleted_at": None,
"deleted_by": None,
"uid": uid,
"user_uid": owner,
"slug": make_combined_slug(f"seo pag {i}", uid),
"title": None,
"content": f"seo pag post {i}",
"topic": topic,
"project_uid": None,
"image": None,
"stars": 0,
"created_at": (base - timedelta(seconds=i)).isoformat(),
}
)
return topic
def test_login_page_loads(page, app_server):
page.goto(f"{BASE_URL}/auth/login", wait_until="domcontentloaded")
assert page.is_visible("h2:has-text('Welcome Back')")
assert page.is_visible("#email")
assert page.is_visible("#password")
assert page.is_visible("button:has-text('Sign in')")
def test_login_nonexistent_email(page, app_server):
page.goto(f"{BASE_URL}/auth/login", wait_until="domcontentloaded")
page.fill("#email", "nobody@nowhere.devplace")
page.fill("#password", "secret123")
page.click("button:has-text('Sign in')")
expect(page.locator("text=Invalid email or password")).to_be_visible()
def test_signup_link_from_login(page, app_server):
page.goto(f"{BASE_URL}/auth/login", wait_until="domcontentloaded")
page.click("a:has-text('Create new account')")
page.wait_for_url("**/auth/signup", wait_until="domcontentloaded")
def test_login_next_redirects_to_target(page, app_server, seeded_db):
page.goto(f"{BASE_URL}/auth/login?next=/gists", wait_until="domcontentloaded")
page.fill("#email", seeded_db["alice"]["email"])
page.fill("#password", seeded_db["alice"]["password"])
page.click("button:has-text('Sign in')")
page.wait_for_url("**/gists", wait_until="domcontentloaded")
def test_login_next_rejects_external(page, app_server, seeded_db):
page.goto(
f"{BASE_URL}/auth/login?next=https://evil.example.com",
wait_until="domcontentloaded",
)
page.fill("#email", seeded_db["alice"]["email"])
page.fill("#password", seeded_db["alice"]["password"])
page.click("button:has-text('Sign in')")
page.wait_for_url("**/feed", wait_until="domcontentloaded")
def test_landing_nav_to_login(page, app_server):
page.goto(f"{BASE_URL}/", wait_until="domcontentloaded")
page.click("a:has-text('Login')")
page.wait_for_url(f"{BASE_URL}/auth/login", wait_until="domcontentloaded")
assert page.is_visible("h2:has-text('Welcome Back')")
def test_landing_log_in_link(page, app_server):
page.goto(f"{BASE_URL}/", wait_until="domcontentloaded")
page.click("text=Log In")
page.wait_for_url(f"{BASE_URL}/auth/login", wait_until="domcontentloaded")
def test_login_page_is_noindex(page, app_server):
page.goto(f"{BASE_URL}/auth/login", wait_until="domcontentloaded")
meta = page.locator('meta[name="robots"]')
content = meta.get_attribute("content")
assert content and "noindex" in content