"""Tests for /player refractor_tier view. Tests cover _build_refractor_response, a module-level helper that processes raw API refractor data and returns structured response data for the slash command. The function is pure (no network calls) so tests run without mocks for the happy path cases, keeping tests readable and fast. """ import sys import os import pytest # Make the repo root importable sys.path.insert(0, os.path.join(os.path.dirname(__file__), "..")) from cogs.players import _build_refractor_response REFRACTOR_CARDS_RESPONSE = { "count": 3, "items": [ { "player_id": 100, "player_name": "Mike Trout", "current_tier": 3, "current_value": 160, "variant": 7, "track": {"card_type": "batter"}, "image_url": "https://s3.example.com/cards/cardset-027/player-100/v7/battingcard.png", }, { "player_id": 200, "player_name": "Barry Bonds", "current_tier": 2, "current_value": 110, "variant": 3, "track": {"card_type": "batter"}, "image_url": "https://s3.example.com/cards/cardset-027/player-200/v3/battingcard.png", }, { "player_id": 300, "player_name": "Ken Griffey Jr.", "current_tier": 1, "current_value": 55, "variant": 1, "track": {"card_type": "batter"}, "image_url": None, }, ], } class TestBuildRefractorResponse: """Build embed content for /player refractor_tier views.""" @pytest.mark.asyncio async def test_happy_path_returns_embed_with_image(self): """When user has the refractor at requested tier, embed includes S3 image. Verifies that when a player_id match is found at or above the requested tier, the result is marked as found and the image_url is passed through. """ result = await _build_refractor_response( player_name="Mike Trout", player_id=100, refractor_tier=3, refractor_data=REFRACTOR_CARDS_RESPONSE, ) assert result["found"] is True assert "s3.example.com" in result["image_url"] @pytest.mark.asyncio async def test_not_found_returns_top_5(self): """When user doesn't have the refractor, show top 5 cards. Verifies that when no match is found for the given player_id + tier, the response includes the top cards sorted by tier descending, and the highest-tier card appears first. """ result = await _build_refractor_response( player_name="Nobody", player_id=999, refractor_tier=2, refractor_data=REFRACTOR_CARDS_RESPONSE, ) assert result["found"] is False assert len(result["top_cards"]) <= 5 assert result["top_cards"][0]["player_name"] == "Mike Trout" @pytest.mark.asyncio async def test_image_url_none_triggers_render(self): """When refractor exists but image_url is None, result signals render needed. A card may exist at the requested tier without a cached S3 image URL if it has never been rendered. The response should set needs_render=True so the caller can construct a render endpoint URL and show a placeholder. """ result = await _build_refractor_response( player_name="Ken Griffey Jr.", player_id=300, refractor_tier=1, refractor_data=REFRACTOR_CARDS_RESPONSE, ) assert result["found"] is True assert result["image_url"] is None assert result["needs_render"] is True assert result["variant"] == 1 @pytest.mark.asyncio async def test_no_refractors_at_all(self): """When user has zero refractor cards, clean message. An empty items list should produce found=False with an empty top_cards list, allowing the caller to show a "no refractors yet" message. """ empty_data = {"count": 0, "items": []} result = await _build_refractor_response( player_name="Someone", player_id=500, refractor_tier=1, refractor_data=empty_data, ) assert result["found"] is False assert result["top_cards"] == [] @pytest.mark.asyncio async def test_tier_higher_than_current_not_found(self): """Requesting T4 when player is at T3 returns not found. The match condition requires current_tier >= refractor_tier. Requesting a tier the player hasn't reached should return found=False so the caller can show what tier they do have. """ result = await _build_refractor_response( player_name="Mike Trout", player_id=100, refractor_tier=4, refractor_data=REFRACTOR_CARDS_RESPONSE, ) assert result["found"] is False