|
| 1 | +import datetime |
1 | 2 | from typing import TYPE_CHECKING |
2 | 3 |
|
3 | 4 | import pytest |
| 5 | +import sqlalchemy as sa |
4 | 6 | from fastapi import status |
5 | 7 |
|
| 8 | +from app import models |
6 | 9 | from tests import factories |
7 | 10 |
|
8 | 11 |
|
9 | 12 | if TYPE_CHECKING: |
10 | 13 | from httpx import AsyncClient |
| 14 | + from sqlalchemy.ext.asyncio import AsyncSession |
11 | 15 |
|
12 | 16 |
|
13 | 17 | pytestmark = [pytest.mark.usefixtures("set_async_session_in_base_sqlalchemy_factory")] |
@@ -137,6 +141,47 @@ async def test_cards_ordered_by_id_after_update(client: AsyncClient) -> None: |
137 | 141 | assert [x["id"] for x in response.json()["items"]] == [card1.id, card2.id] |
138 | 142 |
|
139 | 143 |
|
| 144 | +async def test_update_cards_sends_one_statement(client: AsyncClient, statements: list[str]) -> None: |
| 145 | + deck = await factories.DeckModelFactory.create_async() |
| 146 | + card1, card2 = await factories.CardModelFactory.create_batch_async(size=2, deck_id=deck.id) |
| 147 | + statements.clear() |
| 148 | + |
| 149 | + response = await client.put( |
| 150 | + f"/api/decks/{deck.id}/cards/", |
| 151 | + json=[{"id": card1.id, "front": "card1 updated"}, {"id": card2.id, "front": "card2 updated"}], |
| 152 | + ) |
| 153 | + assert response.status_code == status.HTTP_200_OK |
| 154 | + assert [x["front"] for x in response.json()["items"]] == ["card1 updated", "card2 updated"] |
| 155 | + assert len(statements) == 1 |
| 156 | + |
| 157 | + |
| 158 | +async def test_update_cards_moves_updated_at(client: AsyncClient, db_session: AsyncSession) -> None: |
| 159 | + long_ago = datetime.datetime(2000, 1, 1, tzinfo=datetime.UTC) |
| 160 | + deck = await factories.DeckModelFactory.create_async() |
| 161 | + card = await factories.CardModelFactory.create_async(deck_id=deck.id, updated_at=long_ago) |
| 162 | + |
| 163 | + response = await client.put(f"/api/decks/{deck.id}/cards/", json=[{"id": card.id, "front": "updated"}]) |
| 164 | + assert response.status_code == status.HTTP_200_OK |
| 165 | + updated_at = (await db_session.scalars(sa.select(models.Card.updated_at).where(models.Card.id == card.id))).one() |
| 166 | + assert updated_at > long_ago |
| 167 | + |
| 168 | + |
| 169 | +async def test_update_cards_with_no_cards(client: AsyncClient) -> None: |
| 170 | + deck = await factories.DeckModelFactory.create_async() |
| 171 | + |
| 172 | + response = await client.put(f"/api/decks/{deck.id}/cards/", json=[]) |
| 173 | + assert response.status_code == status.HTTP_200_OK |
| 174 | + assert response.json() == {"items": []} |
| 175 | + |
| 176 | + |
| 177 | +async def test_update_cards_to_a_duplicate_front(client: AsyncClient) -> None: |
| 178 | + deck = await factories.DeckModelFactory.create_async() |
| 179 | + card1, card2 = await factories.CardModelFactory.create_batch_async(size=2, deck_id=deck.id) |
| 180 | + |
| 181 | + response = await client.put(f"/api/decks/{deck.id}/cards/", json=[{"id": card2.id, "front": card1.front}]) |
| 182 | + assert response.status_code == status.HTTP_422_UNPROCESSABLE_CONTENT |
| 183 | + |
| 184 | + |
140 | 185 | async def test_openapi_card_deck_id_required(client: AsyncClient) -> None: |
141 | 186 | response = await client.get("/openapi.json") |
142 | 187 | assert response.status_code == status.HTTP_200_OK |
|
0 commit comments