iUpdate
DevPlace CI / test (push) Successful in 6m46s

This commit is contained in:
2026-05-30 20:16:39 +02:00
parent 3f900b4002
commit c3a8347cc0
57 changed files with 1310 additions and 674 deletions
+18
View File
@@ -1,6 +1,24 @@
import re
from playwright.sync_api import expect
from tests.conftest import BASE_URL, assert_share_copies
def test_feed_vote_voted_state_persists(alice):
page, _ = alice
page.goto(f"{BASE_URL}/feed", wait_until="domcontentloaded")
page.locator(".feed-fab").first.click()
page.fill("#post-content", "Feed vote persistence test content")
page.locator("#create-post-modal button.btn-primary:has-text('Post')").click()
page.wait_for_url(f"{BASE_URL}/posts/*", wait_until="domcontentloaded")
page.goto(f"{BASE_URL}/feed", wait_until="domcontentloaded")
page.locator(".post-action-btn.vote-up").first.click()
expect(page.locator(".post-vote-count").first).to_have_text("1")
page.goto(f"{BASE_URL}/feed", wait_until="domcontentloaded")
expect(page.locator(".post-action-btn.vote-up").first).to_have_class(re.compile(r"\bvoted\b"))
def test_feed_card_share_button(alice):
page, _ = alice
page.goto(f"{BASE_URL}/feed", wait_until="domcontentloaded")
+14
View File
@@ -1,4 +1,8 @@
import re
import time
from playwright.sync_api import expect
from tests.conftest import BASE_URL, assert_share_copies
@@ -195,3 +199,13 @@ def test_gist_listing_shows_created_gist(alice, app_server):
_create_gist(page, title=title, source_code="show_in_list = True")
page.goto(f"{BASE_URL}/gists", wait_until="domcontentloaded")
assert page.is_visible(f"text={title}")
def test_gist_voted_state_persists(alice):
page, _ = alice
_create_gist(page, title="Voted State Gist")
star = "form[action*='/votes/gist/'] button"
page.locator(star).first.click()
page.wait_for_timeout(500)
page.reload(wait_until="domcontentloaded")
expect(page.locator(star).first).to_have_class(re.compile(r"\bvoted\b"))
+62
View File
@@ -0,0 +1,62 @@
from tests.conftest import BASE_URL
def test_leaderboard_page_loads(alice):
page, _ = alice
page.goto(f"{BASE_URL}/leaderboard", wait_until="domcontentloaded")
assert page.locator(".leaderboard-header h1").is_visible()
assert page.is_visible("text=Ranked by total stars")
def test_leaderboard_nav_link(alice):
page, _ = alice
page.goto(f"{BASE_URL}/feed", wait_until="domcontentloaded")
assert page.is_visible("a.topnav-link:has-text('Leaderboard')")
def test_leaderboard_no_pagination(alice):
page, _ = alice
page.goto(f"{BASE_URL}/leaderboard", wait_until="domcontentloaded")
assert page.locator(".pagination").count() == 0
def test_profile_rank_stat(alice):
page, user = alice
page.goto(f"{BASE_URL}/profile/{user['username']}", wait_until="domcontentloaded")
assert page.is_visible("text=Rank")
def test_leaderboard_ranks_after_upvote(app_server, browser, seeded_db):
from tests.conftest import login_user
ctx_a = browser.new_context(viewport={"width": 1400, "height": 900})
ctx_b = browser.new_context(viewport={"width": 1400, "height": 900})
pa = ctx_a.new_page()
pb = ctx_b.new_page()
pa.set_default_timeout(15000)
pb.set_default_timeout(15000)
login_user(pa, seeded_db["alice"])
login_user(pb, seeded_db["bob"])
pb.goto(f"{BASE_URL}/feed", wait_until="domcontentloaded")
pb.locator(".feed-fab").first.wait_for(state="visible", timeout=10000)
pb.locator(".feed-fab").first.click()
pb.fill("#post-content", "Post for leaderboard ranking test")
pb.locator("#create-post-modal button.btn-primary:has-text('Post')").click()
pb.wait_for_url("**/posts/*", timeout=10000, wait_until="domcontentloaded")
post_url = pb.url
pa.goto(post_url, wait_until="domcontentloaded")
pa.wait_for_timeout(1000)
vote_btn = pa.locator("button.post-action-btn").filter(has_text="+").first
vote_btn.wait_for(state="visible", timeout=10000)
vote_btn.click()
pa.wait_for_timeout(1500)
pa.goto(f"{BASE_URL}/leaderboard", wait_until="domcontentloaded")
body = pa.locator("body").text_content()
assert "Internal Server Error" not in body, f"Got 500 on leaderboard: {body[:300]}"
assert pa.is_visible("a.leaderboard-name:has-text('bob_test')")
ctx_a.close()
ctx_b.close()
+35
View File
@@ -1,3 +1,5 @@
import re
from playwright.sync_api import expect
from tests.conftest import BASE_URL, assert_share_copies
@@ -49,6 +51,39 @@ def test_post_vote_increment(alice):
expect(page.locator(".post-vote-count").first).to_have_text("1")
def test_post_upvote_voted_state_persists(alice):
page, _ = alice
create_post(page, "showcase", "Upvote persistence test")
page.locator(".post-action-btn.vote-up").first.click()
expect(page.locator(".post-vote-count").first).to_have_text("1")
page.reload(wait_until="domcontentloaded")
expect(page.locator(".post-action-btn.vote-up").first).to_have_class(re.compile(r"\bvoted\b"))
assert "voted" not in (page.locator(".post-action-btn.vote-down").first.get_attribute("class") or "")
def test_post_downvote_voted_state_persists(alice):
page, _ = alice
create_post(page, "showcase", "Downvote persistence test")
page.locator(".post-action-btn.vote-down").first.click()
expect(page.locator(".post-vote-count").first).to_have_text("-1")
page.reload(wait_until="domcontentloaded")
expect(page.locator(".post-action-btn.vote-down").first).to_have_class(re.compile(r"\bvoted\b"))
assert "voted" not in (page.locator(".post-action-btn.vote-up").first.get_attribute("class") or "")
def test_comment_voted_state_persists(alice):
page, _ = alice
create_post(page, "devlog", "Post for comment vote persistence")
textarea = page.locator(".comment-form textarea[name='content']")
textarea.fill("Comment whose vote should persist")
page.locator(".comment-form button:has-text('Post')").click()
page.wait_for_timeout(500)
page.locator(".comment-vote-btn").first.click()
page.wait_for_timeout(500)
page.reload(wait_until="domcontentloaded")
expect(page.locator(".comment-vote-btn").first).to_have_class(re.compile(r"\bvoted\b"))
def _profile_stars(page, username):
page.goto(f"{BASE_URL}/profile/{username}", wait_until="domcontentloaded")
value = page.locator(".profile-stat:has(.profile-stat-label:has-text('Stars')) .profile-stat-value").first
+12
View File
@@ -1,3 +1,5 @@
import re
from playwright.sync_api import expect
from tests.conftest import BASE_URL, assert_share_copies
@@ -28,6 +30,16 @@ def test_project_vote(alice):
assert after == before + 1
def test_project_voted_state_persists(alice):
page, _ = alice
_create_project(page, "Voted State Project")
star = "form[action*='/votes/project/'] button"
page.locator(star).first.click()
page.wait_for_timeout(500)
page.reload(wait_until="domcontentloaded")
expect(page.locator(star).first).to_have_class(re.compile(r"\bvoted\b"))
def test_delete_own_project(alice):
page, _ = alice
_create_project(page, "Deletable Project XYZ")
+25 -1
View File
@@ -1,4 +1,4 @@
from devplacepy.utils import hash_password, verify_password, generate_uid, slugify, time_ago
from devplacepy.utils import hash_password, verify_password, generate_uid, slugify, time_ago, level_for_xp, badge_info
from datetime import datetime, timedelta, timezone
@@ -80,3 +80,27 @@ def test_time_ago_years():
dt = (datetime.now(timezone.utc) - timedelta(days=400)).isoformat()
result = time_ago(dt)
assert "/" in result
def test_level_for_xp_boundaries():
assert level_for_xp(0) == 1
assert level_for_xp(99) == 1
assert level_for_xp(100) == 2
assert level_for_xp(250) == 3
assert level_for_xp(450) == 5
def test_level_for_xp_negative():
assert level_for_xp(-50) == 1
def test_badge_info_known():
meta = badge_info("Star Author")
assert meta["icon"]
assert meta["description"] == "Earned 100 stars"
def test_badge_info_unknown_fallback():
meta = badge_info("Nonexistent Badge")
assert meta["icon"]
assert meta["description"] == "Nonexistent Badge"