Improve sitemaps
All checks were successful
Deploy to Server / deploy (push) Successful in 9s

This commit is contained in:
Joakim Hellsén 2026-02-27 06:02:30 +01:00
commit 415dd12fd9
Signed by: Joakim Hellsén
SSH key fingerprint: SHA256:/9h/CsExpFp+PRhsfA0xznFx2CGfTT5R/kpuFfUgEQk
16 changed files with 843 additions and 379 deletions

View file

@ -2,6 +2,8 @@ from __future__ import annotations
import json
from pathlib import Path
from typing import TYPE_CHECKING
from typing import Any
from unittest import skipIf
from django.db import connection
@ -17,6 +19,9 @@ from twitch.models import Organization
from twitch.models import TimeBasedDrop
from twitch.schemas import DropBenefitSchema
if TYPE_CHECKING:
from pytest_django.asserts import QuerySet
class GetOrUpdateBenefitTests(TestCase):
"""Tests for the _get_or_update_benefit method in better_import_drops.Command."""
@ -24,7 +29,6 @@ class GetOrUpdateBenefitTests(TestCase):
def test_defaults_distribution_type_when_missing(self) -> None:
"""Ensure importer sets distribution_type to empty string when absent."""
command = Command()
command.benefit_cache = {}
benefit_schema: DropBenefitSchema = DropBenefitSchema.model_validate(
{
@ -324,7 +328,7 @@ class CampaignStructureDetectionTests(TestCase):
command = Command()
# Inventory format with null dropCampaignsInProgress - should not detect as inventory_campaigns
response = {
response: dict[str, dict[str, dict[str, str | dict[str, str | None]]]] = {
"data": {
"currentUser": {
"id": "123",
@ -462,15 +466,19 @@ class OperationNameFilteringTests(TestCase):
command.process_responses([inventory_payload], Path("inventory.json"), {})
# Verify we can filter by operation_names with JSON containment
viewer_campaigns = DropCampaign.objects.filter(operation_names__contains=["ViewerDropsDashboard"])
inventory_campaigns = DropCampaign.objects.filter(operation_names__contains=["Inventory"])
viewer_campaigns: QuerySet[DropCampaign, DropCampaign] = DropCampaign.objects.filter(
operation_names__contains=["ViewerDropsDashboard"],
)
inventory_campaigns: QuerySet[DropCampaign, DropCampaign] = DropCampaign.objects.filter(
operation_names__contains=["Inventory"],
)
assert len(viewer_campaigns) >= 1
assert len(inventory_campaigns) >= 1
# Verify the correct campaigns are in each list
viewer_ids = [c.twitch_id for c in viewer_campaigns]
inventory_ids = [c.twitch_id for c in inventory_campaigns]
viewer_ids: list[str] = [c.twitch_id for c in viewer_campaigns]
inventory_ids: list[str] = [c.twitch_id for c in inventory_campaigns]
assert "viewer-campaign-1" in viewer_ids
assert "inventory-campaign-1" in inventory_ids
@ -532,7 +540,7 @@ class GameImportTests(TestCase):
assert success is True
assert broken_dir is None
game = Game.objects.get(twitch_id="497057")
game: Game = Game.objects.get(twitch_id="497057")
assert game.slug == "destiny-2"
assert game.display_name == "Destiny 2"
@ -595,10 +603,8 @@ class ExampleJsonImportTests(TestCase):
assert first_drop.required_minutes_watched == 120
assert DropBenefit.objects.count() == 1
benefit: DropBenefit = DropBenefit.objects.get(twitch_id="ccb3fb7f-e59b-11ef-aef0-0a58a9feac02")
assert (
benefit.image_asset_url
== "https://static-cdn.jtvnw.net/twitch-quests-assets/REWARD/903496ad-de97-41ff-ad97-12f099e20ea8.jpeg"
)
image_url = "https://static-cdn.jtvnw.net/twitch-quests-assets/REWARD/903496ad-de97-41ff-ad97-12f099e20ea8.jpeg"
assert benefit.image_asset_url == image_url
class ImporterRobustnessTests(TestCase):
@ -608,7 +614,7 @@ class ImporterRobustnessTests(TestCase):
"""Ensure tuple payloads from json_repair don't crash the importer."""
command = Command()
parsed = (
parsed: tuple[dict[str, dict[str, dict[str, str | list[Any]]] | dict[str, str]], list[dict[str, str]]] = (
{
"data": {
"currentUser": {
@ -622,7 +628,7 @@ class ImporterRobustnessTests(TestCase):
[{"json_repair": "log"}],
)
normalized = command._normalize_responses(parsed)
normalized: list[dict[str, Any]] = command._normalize_responses(parsed)
assert isinstance(normalized, list)
assert len(normalized) == 1
assert normalized[0]["extensions"]["operationName"] == "ViewerDropsDashboard"
@ -670,7 +676,7 @@ class ImporterRobustnessTests(TestCase):
assert success is True
assert broken_dir is None
campaign = DropCampaign.objects.get(twitch_id="campaign-null-image")
campaign: DropCampaign = DropCampaign.objects.get(twitch_id="campaign-null-image")
assert not campaign.image_url
@ -679,7 +685,7 @@ class ErrorOnlyResponseDetectionTests(TestCase):
def test_detects_error_only_response_with_service_timeout(self) -> None:
"""Ensure error-only response with service timeout is detected."""
parsed_json = {
parsed_json: dict[str, list[dict[str, str | list[str]]]] = {
"errors": [
{
"message": "service timeout",
@ -688,12 +694,13 @@ class ErrorOnlyResponseDetectionTests(TestCase):
],
}
result = detect_error_only_response(parsed_json)
result: str | None = detect_error_only_response(parsed_json)
assert result == "error_only: service timeout"
def test_detects_error_only_response_with_null_data(self) -> None:
"""Ensure error-only response with null data field is detected."""
parsed_json = {
parsed_json: dict[str, list[dict[str, str | list[str]]] | None] = {
"errors": [
{
"message": "internal server error",
@ -703,12 +710,13 @@ class ErrorOnlyResponseDetectionTests(TestCase):
"data": None,
}
result = detect_error_only_response(parsed_json)
result: str | None = detect_error_only_response(parsed_json)
assert result == "error_only: internal server error"
def test_detects_error_only_response_with_empty_data(self) -> None:
"""Ensure error-only response with empty data dict is allowed through."""
parsed_json = {
parsed_json: dict[str, list[dict[str, str]] | dict[str, None]] = {
"errors": [
{
"message": "unauthorized",
@ -717,13 +725,14 @@ class ErrorOnlyResponseDetectionTests(TestCase):
"data": {},
}
result = detect_error_only_response(parsed_json)
result: str | None = detect_error_only_response(parsed_json)
# Empty dict {} is considered "data exists" so this should pass
assert result is None
def test_detects_error_only_response_without_data_key(self) -> None:
"""Ensure error-only response without data key is detected."""
parsed_json = {
parsed_json: dict[str, list[dict[str, str]]] = {
"errors": [
{
"message": "missing data",
@ -731,7 +740,7 @@ class ErrorOnlyResponseDetectionTests(TestCase):
],
}
result = detect_error_only_response(parsed_json)
result: str | None = detect_error_only_response(parsed_json)
assert result == "error_only: missing data"
def test_allows_response_with_both_errors_and_data(self) -> None:
@ -749,12 +758,12 @@ class ErrorOnlyResponseDetectionTests(TestCase):
},
}
result = detect_error_only_response(parsed_json)
result: str | None = detect_error_only_response(parsed_json)
assert result is None
def test_allows_response_with_no_errors(self) -> None:
"""Ensure normal responses without errors are not flagged."""
parsed_json = {
parsed_json: dict[str, dict[str, dict[str, list[None]]]] = {
"data": {
"currentUser": {
"dropCampaigns": [],
@ -762,12 +771,12 @@ class ErrorOnlyResponseDetectionTests(TestCase):
},
}
result = detect_error_only_response(parsed_json)
result: str | None = detect_error_only_response(parsed_json)
assert result is None
def test_detects_error_only_in_list_of_responses(self) -> None:
"""Ensure error-only detection works with list of responses."""
parsed_json = [
parsed_json: list[dict[str, list[dict[str, str]]]] = [
{
"errors": [
{
@ -777,12 +786,12 @@ class ErrorOnlyResponseDetectionTests(TestCase):
},
]
result = detect_error_only_response(parsed_json)
result: str | None = detect_error_only_response(parsed_json)
assert result == "error_only: rate limit exceeded"
def test_handles_json_repair_tuple_format(self) -> None:
"""Ensure error-only detection works with json_repair tuple format."""
parsed_json = (
parsed_json: tuple[dict[str, list[dict[str, str | list[str]]]], list[dict[str, str]]] = (
{
"errors": [
{
@ -794,26 +803,26 @@ class ErrorOnlyResponseDetectionTests(TestCase):
[{"json_repair": "log"}],
)
result = detect_error_only_response(parsed_json)
result: str | None = detect_error_only_response(parsed_json)
assert result == "error_only: service timeout"
def test_returns_none_for_non_dict_input(self) -> None:
"""Ensure non-dict input is handled gracefully."""
result = detect_error_only_response("invalid")
result: str | None = detect_error_only_response("invalid")
assert result is None
def test_returns_none_for_empty_errors_list(self) -> None:
"""Ensure empty errors list is not flagged as error-only."""
parsed_json = {
parsed_json: dict[str, list[None]] = {
"errors": [],
}
result = detect_error_only_response(parsed_json)
result: str | None = detect_error_only_response(parsed_json)
assert result is None
def test_handles_error_without_message_field(self) -> None:
"""Ensure errors without message field use default text."""
parsed_json = {
parsed_json: dict[str, list[dict[str, list[str]]]] = {
"errors": [
{
"path": ["data"],
@ -821,5 +830,5 @@ class ErrorOnlyResponseDetectionTests(TestCase):
],
}
result = detect_error_only_response(parsed_json)
result: str | None = detect_error_only_response(parsed_json)
assert result == "error_only: unknown error"