All checks were successful
ci/woodpecker/pr/pipeline Pipeline was successful
- Write 3 e2e tests (TC-E2E-106-108): like/unlike flow, multi-user like, guest redirect - Add get_like_count() and click_like() to PostDetailPage object - Fix _map_to_dto in 5 use cases (create, get, list, publish, update) to include like_count - Fix pre-existing mypy issues in page object (evaluate returns Any) - Update FEATURE_LIKES.md with verified E2E status
184 lines
5.8 KiB
Python
184 lines
5.8 KiB
Python
"""End-to-end tests for post likes via web UI.
|
|
|
|
Tests the like/unlike toggle flow, multi-user like isolation,
|
|
and guest authentication redirect.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import uuid
|
|
|
|
import pytest
|
|
from playwright.sync_api import Page, expect
|
|
from pytfm.generators import PostDataGenerator
|
|
|
|
from tests.e2e.pages import HomePage, PostDetailPage, PostFormPage
|
|
|
|
|
|
def _unique_title(base: str) -> str:
|
|
"""Append a short UUID to a title to avoid slug collisions."""
|
|
return f"{base} {uuid.uuid4().hex[:8]}"
|
|
|
|
|
|
@pytest.mark.e2e
|
|
def test_like_unlike_flow(
|
|
user_page: Page,
|
|
base_url: str,
|
|
) -> None:
|
|
"""Test like/unlike toggle through the web UI.
|
|
|
|
Steps:
|
|
1. Create and publish a post.
|
|
2. Verify initial like count is 0.
|
|
3. Click the like button.
|
|
4. Verify like count becomes 1.
|
|
5. Click the like button again.
|
|
6. Verify like count returns to 0.
|
|
|
|
Args:
|
|
user_page: Playwright page authenticated as regular user.
|
|
base_url: Application base URL.
|
|
"""
|
|
generator = PostDataGenerator()
|
|
post_data = generator.generate_post()
|
|
title = _unique_title(str(post_data["title"]))
|
|
content = str(post_data["content"])
|
|
tags = ", ".join(post_data["tags"])
|
|
|
|
home = HomePage(user_page, base_url)
|
|
home.open()
|
|
home.create_post()
|
|
|
|
form = PostFormPage(user_page, base_url)
|
|
form.fill_form(title, content, tags)
|
|
with user_page.expect_navigation(wait_until="networkidle"):
|
|
form.publish()
|
|
current_url = user_page.url
|
|
assert "new" not in current_url, f"Still on form page: {current_url}"
|
|
slug = current_url.rstrip("/").split("/")[-1]
|
|
|
|
user_page.wait_for_selector('[data-testid="post-detail-title"]')
|
|
detail = PostDetailPage(user_page, base_url, slug)
|
|
assert detail.get_title() == title
|
|
|
|
# Initial like count should be 0 for a new post
|
|
assert detail.get_like_count() == 0
|
|
|
|
# Like the post
|
|
detail.click_like()
|
|
expect(user_page.locator("#like-count")).to_have_text("1", timeout=15000)
|
|
|
|
# Unlike the post
|
|
detail.click_like()
|
|
expect(user_page.locator("#like-count")).to_have_text("0", timeout=15000)
|
|
|
|
|
|
@pytest.mark.e2e
|
|
def test_multiple_users_can_like(
|
|
user_page: Page,
|
|
user2_page: Page,
|
|
base_url: str,
|
|
) -> None:
|
|
"""Test that two users can independently like the same post.
|
|
|
|
Steps:
|
|
1. User creates and publishes a post.
|
|
2. User likes the post (count becomes 1).
|
|
3. User2 opens the same post (sees count=1).
|
|
4. User2 clicks like (count becomes 2).
|
|
|
|
Args:
|
|
user_page: Playwright page authenticated as first regular user.
|
|
user2_page: Playwright page authenticated as second regular user.
|
|
base_url: Application base URL.
|
|
"""
|
|
generator = PostDataGenerator()
|
|
post_data = generator.generate_post()
|
|
title = _unique_title(str(post_data["title"]))
|
|
content = str(post_data["content"])
|
|
tags = ", ".join(post_data["tags"])
|
|
|
|
home = HomePage(user_page, base_url)
|
|
home.open()
|
|
home.create_post()
|
|
|
|
form = PostFormPage(user_page, base_url)
|
|
form.fill_form(title, content, tags)
|
|
with user_page.expect_navigation(wait_until="networkidle"):
|
|
form.publish()
|
|
current_url = user_page.url
|
|
assert "new" not in current_url, f"Still on form page: {current_url}"
|
|
slug = current_url.rstrip("/").split("/")[-1]
|
|
|
|
user_page.wait_for_selector('[data-testid="post-detail-title"]')
|
|
detail = PostDetailPage(user_page, base_url, slug)
|
|
assert detail.get_title() == title
|
|
|
|
# User likes the post
|
|
assert detail.get_like_count() == 0
|
|
detail.click_like()
|
|
expect(user_page.locator("#like-count")).to_have_text("1", timeout=15000)
|
|
|
|
# Verify like_count persists after page reload
|
|
user_page.reload(wait_until="networkidle")
|
|
user_page.wait_for_selector('[data-testid="post-detail-title"]')
|
|
assert detail.get_like_count() == 1
|
|
|
|
# User2 opens same post and likes
|
|
user2_detail = PostDetailPage(user2_page, base_url, slug)
|
|
user2_detail.open()
|
|
user2_page.wait_for_selector('[data-testid="post-detail-title"]')
|
|
assert user2_detail.get_like_count() == 1
|
|
|
|
user2_detail.click_like()
|
|
expect(user2_page.locator("#like-count")).to_have_text("2", timeout=15000)
|
|
|
|
|
|
@pytest.mark.e2e
|
|
def test_guest_redirect_on_like(
|
|
user_page: Page,
|
|
guest_page: Page,
|
|
base_url: str,
|
|
) -> None:
|
|
"""Test that unauthenticated guests are redirected to login when liking.
|
|
|
|
Steps:
|
|
1. User creates and publishes a post.
|
|
2. Guest opens the post detail page.
|
|
3. Guest clicks the like button.
|
|
4. Guest is redirected to the development login page.
|
|
|
|
Args:
|
|
user_page: Playwright page authenticated as regular user.
|
|
guest_page: Unauthenticated Playwright page.
|
|
base_url: Application base URL.
|
|
"""
|
|
generator = PostDataGenerator()
|
|
post_data = generator.generate_post()
|
|
title = _unique_title(str(post_data["title"]))
|
|
content = str(post_data["content"])
|
|
tags = ", ".join(post_data["tags"])
|
|
|
|
home = HomePage(user_page, base_url)
|
|
home.open()
|
|
home.create_post()
|
|
|
|
form = PostFormPage(user_page, base_url)
|
|
form.fill_form(title, content, tags)
|
|
with user_page.expect_navigation(wait_until="networkidle"):
|
|
form.publish()
|
|
current_url = user_page.url
|
|
assert "new" not in current_url, f"Still on form page: {current_url}"
|
|
slug = current_url.rstrip("/").split("/")[-1]
|
|
|
|
# Guest opens the published post
|
|
guest_detail = PostDetailPage(guest_page, base_url, slug)
|
|
guest_detail.open()
|
|
guest_page.wait_for_selector('[data-testid="post-detail-title"]')
|
|
|
|
# Guest clicks like -> should be redirected to dev login page
|
|
with guest_page.expect_navigation(wait_until="networkidle", timeout=15000):
|
|
guest_detail.click_like()
|
|
|
|
assert "dev-login" in guest_page.url
|