|
1 | 1 | from typing import Generator |
2 | 2 |
|
3 | 3 | import pytest |
4 | | -from sqlalchemy import Column, Integer |
| 4 | +from sqlalchemy import Column, ForeignKey, Integer, String |
5 | 5 | from sqlalchemy.ext.asyncio import AsyncSession, async_sessionmaker |
6 | | -from sqlalchemy.orm import declarative_base |
| 6 | +from sqlalchemy.orm import declarative_base, relationship |
7 | 7 | from starlette.applications import Starlette |
8 | 8 | from starlette.requests import Request |
9 | 9 | from starlette.responses import JSONResponse, RedirectResponse |
@@ -118,3 +118,82 @@ def test_action_access_login_required_views(client: TestClient) -> None: |
118 | 118 |
|
119 | 119 | response = client.get("/admin/movie/action/test") |
120 | 120 | assert {"status": "ok"} == response.json() |
| 121 | + |
| 122 | + |
| 123 | +class Artist(Base): |
| 124 | + __tablename__ = "artists_auth" |
| 125 | + |
| 126 | + id = Column(Integer, primary_key=True) |
| 127 | + name = Column(String(50)) |
| 128 | + |
| 129 | + songs = relationship("SongAuth", back_populates="artist") |
| 130 | + |
| 131 | + def __str__(self) -> str: |
| 132 | + return f"Artist {self.id}" |
| 133 | + |
| 134 | + |
| 135 | +class SongAuth(Base): |
| 136 | + __tablename__ = "songs_auth" |
| 137 | + |
| 138 | + id = Column(Integer, primary_key=True) |
| 139 | + artist_id = Column(Integer, ForeignKey("artists_auth.id")) |
| 140 | + |
| 141 | + artist = relationship("Artist", back_populates="songs") |
| 142 | + |
| 143 | + |
| 144 | +class ArtistAdmin(ModelView, model=Artist): |
| 145 | + pass |
| 146 | + |
| 147 | + |
| 148 | +class SongAuthAdmin(ModelView, model=SongAuth): |
| 149 | + form_ajax_refs = { |
| 150 | + "artist": { |
| 151 | + "fields": ("name",), |
| 152 | + "order_by": "name", |
| 153 | + } |
| 154 | + } |
| 155 | + |
| 156 | + |
| 157 | +admin.add_view(ArtistAdmin) |
| 158 | +admin.add_view(SongAuthAdmin) |
| 159 | + |
| 160 | + |
| 161 | +@pytest.fixture(autouse=False) |
| 162 | +def prepare_ajax_tables() -> Generator[None, None, None]: |
| 163 | + Base.metadata.create_all(engine) |
| 164 | + yield |
| 165 | + Base.metadata.drop_all(engine) |
| 166 | + |
| 167 | + |
| 168 | +def test_ajax_lookup_unauthenticated_redirects_to_login( |
| 169 | + client: TestClient, |
| 170 | +) -> None: |
| 171 | + response = client.get("/admin/song-auth/ajax/lookup?name=artist&term=test") |
| 172 | + assert response.url == "http://testserver/admin/login" |
| 173 | + |
| 174 | + |
| 175 | +def test_ajax_lookup_authenticated_returns_200( |
| 176 | + client: TestClient, |
| 177 | + prepare_ajax_tables: None, |
| 178 | +) -> None: |
| 179 | + client.post( |
| 180 | + "/admin/login", |
| 181 | + data={"username": "a", "password": "b"}, |
| 182 | + ) |
| 183 | + |
| 184 | + response = client.get("/admin/song-auth/ajax/lookup?name=artist&term=test") |
| 185 | + assert response.status_code == 200 |
| 186 | + assert "results" in response.json() |
| 187 | + |
| 188 | + |
| 189 | +def test_ajax_lookup_after_logout_redirects_to_login( |
| 190 | + client: TestClient, |
| 191 | +) -> None: |
| 192 | + client.post( |
| 193 | + "/admin/login", |
| 194 | + data={"username": "a", "password": "b"}, |
| 195 | + ) |
| 196 | + client.get("/admin/logout") |
| 197 | + |
| 198 | + response = client.get("/admin/song-auth/ajax/lookup?name=artist&term=test") |
| 199 | + assert response.url == "http://testserver/admin/login" |
0 commit comments