Improve import command
This commit is contained in:
parent
b11cfa03ea
commit
1d6c52325c
30 changed files with 2628 additions and 554 deletions
230
twitch/tests/test_views.py
Normal file
230
twitch/tests/test_views.py
Normal file
|
|
@ -0,0 +1,230 @@
|
|||
from __future__ import annotations
|
||||
|
||||
from typing import TYPE_CHECKING
|
||||
from typing import Any
|
||||
from typing import Literal
|
||||
|
||||
import pytest
|
||||
from django.test.client import _MonkeyPatchedWSGIResponse
|
||||
from django.test.utils import ContextList
|
||||
|
||||
from twitch.models import DropBenefit
|
||||
from twitch.models import DropCampaign
|
||||
from twitch.models import Game
|
||||
from twitch.models import Organization
|
||||
from twitch.models import TimeBasedDrop
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from django.test import Client
|
||||
from django.test.client import _MonkeyPatchedWSGIResponse
|
||||
from django.test.utils import ContextList
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
class TestSearchView:
|
||||
"""Tests for the search_view function."""
|
||||
|
||||
@pytest.fixture
|
||||
def sample_data(self) -> dict[str, Organization | Game | DropCampaign | TimeBasedDrop | DropBenefit]:
|
||||
"""Create sample data for testing.
|
||||
|
||||
Returns:
|
||||
A dictionary containing the created sample data.
|
||||
"""
|
||||
org: Organization = Organization.objects.create(twitch_id="123", name="Test Organization")
|
||||
game: Game = Game.objects.create(
|
||||
twitch_id="456",
|
||||
name="test_game",
|
||||
display_name="Test Game",
|
||||
owner=org,
|
||||
)
|
||||
campaign: DropCampaign = DropCampaign.objects.create(
|
||||
twitch_id="789",
|
||||
name="Test Campaign",
|
||||
description="A test campaign",
|
||||
game=game,
|
||||
)
|
||||
drop: TimeBasedDrop = TimeBasedDrop.objects.create(
|
||||
twitch_id="1011",
|
||||
name="Test Drop",
|
||||
campaign=campaign,
|
||||
)
|
||||
benefit: DropBenefit = DropBenefit.objects.create(
|
||||
twitch_id="1213",
|
||||
name="Test Benefit",
|
||||
)
|
||||
return {
|
||||
"org": org,
|
||||
"game": game,
|
||||
"campaign": campaign,
|
||||
"drop": drop,
|
||||
"benefit": benefit,
|
||||
}
|
||||
|
||||
@staticmethod
|
||||
def _get_context(response: _MonkeyPatchedWSGIResponse) -> ContextList | dict[str, Any]:
|
||||
"""Normalize Django test response context to a plain dict.
|
||||
|
||||
Args:
|
||||
response: The Django test response.
|
||||
|
||||
Returns:
|
||||
The context as a plain dictionary.
|
||||
"""
|
||||
context: ContextList | dict[str, Any] = response.context
|
||||
if isinstance(context, list): # Django can return a list of contexts
|
||||
context = context[-1]
|
||||
return context
|
||||
|
||||
def test_empty_query(
|
||||
self,
|
||||
client: Client,
|
||||
sample_data: dict[str, Organization | Game | DropCampaign | TimeBasedDrop | DropBenefit],
|
||||
) -> None:
|
||||
"""Test search with empty query returns no results."""
|
||||
response: _MonkeyPatchedWSGIResponse = client.get("/search/?q=")
|
||||
context: ContextList | dict[str, Any] = self._get_context(response)
|
||||
|
||||
assert response.status_code == 200
|
||||
assert "results" in context
|
||||
assert context["results"] == {}
|
||||
|
||||
def test_no_query_parameter(
|
||||
self,
|
||||
client: Client,
|
||||
sample_data: dict[str, Organization | Game | DropCampaign | TimeBasedDrop | DropBenefit],
|
||||
) -> None:
|
||||
"""Test search with no query parameter returns no results."""
|
||||
response: _MonkeyPatchedWSGIResponse = client.get("/search/")
|
||||
context: ContextList | dict[str, Any] = self._get_context(response)
|
||||
|
||||
assert response.status_code == 200
|
||||
assert context["results"] == {}
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"model_key",
|
||||
["org", "game", "campaign", "drop", "benefit"],
|
||||
)
|
||||
def test_short_query_istartswith(
|
||||
self,
|
||||
client: Client,
|
||||
sample_data: dict[str, Organization | Game | DropCampaign | TimeBasedDrop | DropBenefit],
|
||||
model_key: Literal["org", "game", "campaign", "drop", "benefit"],
|
||||
) -> None:
|
||||
"""Test short query (< 3 chars) uses istartswith for all models."""
|
||||
response: _MonkeyPatchedWSGIResponse = client.get("/search/?q=Te")
|
||||
context: ContextList | dict[str, Any] = self._get_context(response)
|
||||
|
||||
assert response.status_code == 200
|
||||
|
||||
# Map model keys to result keys
|
||||
result_key_map = {
|
||||
"org": "organizations",
|
||||
"game": "games",
|
||||
"campaign": "campaigns",
|
||||
"drop": "drops",
|
||||
"benefit": "benefits",
|
||||
}
|
||||
result_key = result_key_map[model_key]
|
||||
assert sample_data[model_key] in context["results"][result_key]
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"model_key",
|
||||
["org", "game", "campaign", "drop", "benefit"],
|
||||
)
|
||||
def test_long_query_icontains(
|
||||
self,
|
||||
client: Client,
|
||||
sample_data: dict[str, Organization | Game | DropCampaign | TimeBasedDrop | DropBenefit],
|
||||
model_key: Literal["org", "game", "campaign", "drop", "benefit"],
|
||||
) -> None:
|
||||
"""Test long query (>= 3 chars) uses icontains for all models."""
|
||||
response: _MonkeyPatchedWSGIResponse = client.get("/search/?q=Test")
|
||||
context: ContextList | dict[str, Any] = self._get_context(response)
|
||||
|
||||
assert response.status_code == 200
|
||||
|
||||
# Map model keys to result keys
|
||||
result_key_map = {
|
||||
"org": "organizations",
|
||||
"game": "games",
|
||||
"campaign": "campaigns",
|
||||
"drop": "drops",
|
||||
"benefit": "benefits",
|
||||
}
|
||||
result_key = result_key_map[model_key]
|
||||
assert sample_data[model_key] in context["results"][result_key]
|
||||
|
||||
def test_campaign_description_search(
|
||||
self,
|
||||
client: Client,
|
||||
sample_data: dict[str, Organization | Game | DropCampaign | TimeBasedDrop | DropBenefit],
|
||||
) -> None:
|
||||
"""Test that campaign description is searchable."""
|
||||
response: _MonkeyPatchedWSGIResponse = client.get("/search/?q=campaign")
|
||||
context: ContextList | dict[str, Any] = self._get_context(response)
|
||||
|
||||
assert response.status_code == 200
|
||||
assert sample_data["campaign"] in context["results"]["campaigns"]
|
||||
|
||||
def test_game_display_name_search(
|
||||
self,
|
||||
client: Client,
|
||||
sample_data: dict[str, Organization | Game | DropCampaign | TimeBasedDrop | DropBenefit],
|
||||
) -> None:
|
||||
"""Test that game display_name is searchable."""
|
||||
response: _MonkeyPatchedWSGIResponse = client.get("/search/?q=Game")
|
||||
context: ContextList | dict[str, Any] = self._get_context(response)
|
||||
|
||||
assert response.status_code == 200
|
||||
assert sample_data["game"] in context["results"]["games"]
|
||||
|
||||
def test_query_no_matches(
|
||||
self,
|
||||
client: Client,
|
||||
sample_data: dict[str, Organization | Game | DropCampaign | TimeBasedDrop | DropBenefit],
|
||||
) -> None:
|
||||
"""Test search with query that has no matches."""
|
||||
response: _MonkeyPatchedWSGIResponse = client.get("/search/?q=xyz")
|
||||
context: ContextList | dict[str, Any] = self._get_context(response)
|
||||
|
||||
assert response.status_code == 200
|
||||
for result_list in context["results"].values():
|
||||
assert len(result_list) == 0
|
||||
|
||||
def test_context_contains_query(
|
||||
self,
|
||||
client: Client,
|
||||
sample_data: dict[str, Organization | Game | DropCampaign | TimeBasedDrop | DropBenefit],
|
||||
) -> None:
|
||||
"""Test that context contains the search query."""
|
||||
query = "Test"
|
||||
response: _MonkeyPatchedWSGIResponse = client.get(f"/search/?q={query}")
|
||||
context: ContextList | dict[str, Any] = self._get_context(response)
|
||||
|
||||
assert context["query"] == query
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("model_key", "related_field"),
|
||||
[
|
||||
("campaigns", "game"),
|
||||
("drops", "campaign"),
|
||||
],
|
||||
)
|
||||
def test_select_related_optimization(
|
||||
self,
|
||||
client: Client,
|
||||
sample_data: dict[str, Organization | Game | DropCampaign | TimeBasedDrop | DropBenefit],
|
||||
model_key: str,
|
||||
related_field: str,
|
||||
) -> None:
|
||||
"""Test that queries use select_related for performance optimization."""
|
||||
response: _MonkeyPatchedWSGIResponse = client.get("/search/?q=Test")
|
||||
context: ContextList | dict[str, Any] = self._get_context(response)
|
||||
|
||||
results = context["results"][model_key]
|
||||
assert len(results) > 0
|
||||
|
||||
# Verify the related object is accessible without additional query
|
||||
first_result = results[0]
|
||||
assert hasattr(first_result, related_field)
|
||||
Loading…
Add table
Add a link
Reference in a new issue