diff --git a/pyproject.toml b/pyproject.toml index 7c83f5f..b9a76a3 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -38,6 +38,7 @@ tests = [ "pytest>=9.0.3", "pytest-asyncio>=1.3.0", "pytest-cov>=7.1.0", + "pytfm", ] lints = [ "black>=23.7.0", @@ -47,11 +48,15 @@ lints = [ types = [ "mimesis>=19.1.0", "mypy>=1.20.1", + "pytfm", ] [project.scripts] blog = "app.main:main" +[tool.uv.sources] +pytfm = { workspace = true } + [tool.pytest.ini_options] asyncio_mode = "auto" asyncio_default_fixture_loop_scope = "function" diff --git a/tests/e2e/test_example.py b/tests/e2e/test_example.py new file mode 100644 index 0000000..18bc75f --- /dev/null +++ b/tests/e2e/test_example.py @@ -0,0 +1,57 @@ +"""Example E2E test using pytfm framework. + +This module demonstrates how to use pytfm for testing +the blog application. +""" + +from __future__ import annotations + +import pytest +from playwright.async_api import async_playwright +from pytfm.api import APIClient +from pytfm.web import BasePage + + +class BlogHomePage(BasePage): + """Page object for the blog home page.""" + + path = "/" + + async def get_posts(self) -> list[str]: + """Get list of post titles on the page.""" + posts = await self.page.query_selector_all('[data-testid="post-title"]') + return [await post.text_content() or "" for post in posts] + + +class TestBlogE2E: + """End-to-end tests for the blog application.""" + + @pytest.mark.asyncio + async def test_homepage_loads(self) -> None: + """Test that homepage loads successfully.""" + async with async_playwright() as p: + browser = await p.chromium.launch() + page = await browser.new_page() + + home_page = BlogHomePage(page, "http://localhost:8000") + await home_page.open() + + assert await home_page.is_visible('data-testid="nav-logo"') + + await browser.close() + + +class TestBlogAPI: + """API tests for the blog application.""" + + @pytest.mark.asyncio + async def test_get_posts(self) -> None: + """Test GET /api/v1/posts endpoint.""" + async with APIClient("http://localhost:8000") as client: + response = await client.get("/api/v1/posts") + + assert response.status_code == 200 + assert response.is_success + + data = response.json() + assert isinstance(data, list)