test(e2e): add TC-E2E-003/004/005/007/008/009/010 — delete, pagination, errors, profile, theme

- test_post_deletion.py: user delete own, admin delete any, 403 for other's
- test_pagination.py: navigation across pages, boundary on last page
- test_errors.py: 404 nonexistent post, 404 for other user's draft
- test_post_lifecycle.py: draft-to-publish via edit flow
- test_post_ownership.py: user can edit own post
- test_profile_and_theme.py: profile page rendering, theme toggle with localStorage
- fix(web): remove infinite pagination for USER role (routes.py)
- fix(e2e): stabilize all publish() calls with expect_navigation
- fix(e2e): add _unique_title() to avoid slug collisions at scale
- docs: update FEATURE_POST_LIFECYCLE.md and TEST_MODEL.md coverage
This commit is contained in:
2026-05-08 20:25:01 +03:00
parent 714342f5ac
commit cf4982c0e5
10 changed files with 783 additions and 48 deletions

View File

@@ -81,6 +81,53 @@ class HomePage(BasePage):
"""
return self._empty_state.is_visible(self.page)
def count_posts(self) -> int:
"""Count the number of post cards on the page.
Returns:
Number of visible post cards.
"""
return self.page.locator('article[data-testid^="post-card-"]').count()
def get_current_page(self) -> int:
"""Get the current pagination page number.
Returns:
Current page number as integer.
"""
text = self.page.locator('[data-testid="pagination-current"]').text_content()
return int(text) if text else 1
def can_go_next(self) -> bool:
"""Check if the next page link is enabled.
Returns:
True if the next pagination control is a clickable link.
"""
tag = self.page.locator('[data-testid="pagination-next"]').evaluate(
"el => el.tagName.toLowerCase()"
)
return tag == "a"
def can_go_prev(self) -> bool:
"""Check if the previous page link is enabled.
Returns:
True if the previous pagination control is a clickable link.
"""
tag = self.page.locator('[data-testid="pagination-prev"]').evaluate(
"el => el.tagName.toLowerCase()"
)
return tag == "a"
def go_to_next_page(self) -> None:
"""Click the next page pagination link."""
self.page.locator('[data-testid="pagination-next"]').click()
def go_to_prev_page(self) -> None:
"""Click the previous page pagination link."""
self.page.locator('[data-testid="pagination-prev"]').click()
class PostFormPage(BasePage):
"""Page object for the new post / edit post form.
@@ -223,3 +270,8 @@ class PostDetailPage(BasePage):
True if delete button is present.
"""
return self._delete_btn.is_visible(self.page)
def delete(self) -> None:
"""Click the delete button and accept the confirmation dialog."""
self.page.on("dialog", lambda dialog: dialog.accept())
self._delete_btn.click(self.page)