Fable will fix it! Pt 2
This commit is contained in:
@@ -3,7 +3,7 @@ import json
|
||||
from sqlmodel import SQLModel, create_engine, Session
|
||||
from pirats import cards
|
||||
from pirats import crud
|
||||
from pirats.models import Game, Player, Obstacle
|
||||
from pirats.models import Obstacle
|
||||
|
||||
# In-memory database for testing
|
||||
@pytest.fixture(name="session")
|
||||
@@ -201,7 +201,6 @@ def test_assistant_does_not_draw(session):
|
||||
ok, msg = crud.create_challenge(session, game.id, deep.id, p2.id, [obs.id])
|
||||
assert ok
|
||||
session.refresh(game)
|
||||
challenge = game.challenges[0]
|
||||
|
||||
# p3 assists: plays a color-matching card but must NOT draw back
|
||||
ok, msg, res = crud.play_challenge_card(session, p3.id, obs.id, helper_card)
|
||||
@@ -409,7 +408,6 @@ def test_create_game_endpoint():
|
||||
from sqlalchemy.pool import StaticPool
|
||||
from sqlmodel import SQLModel, create_engine, Session, select
|
||||
from pirats.main import app
|
||||
from pirats import crud
|
||||
|
||||
# Setup in-memory DB
|
||||
engine = create_engine(
|
||||
@@ -963,7 +961,7 @@ def test_submit_techniques_rejects_collisions(session):
|
||||
def test_roll_new_character_smell_name_normalization(session):
|
||||
game = crud.create_game(session)
|
||||
p1 = crud.add_player(session, game.id, "P1")
|
||||
p2 = crud.add_player(session, game.id, "P2")
|
||||
crud.add_player(session, game.id, "P2")
|
||||
p1.is_dead = True
|
||||
session.add(p1)
|
||||
session.commit()
|
||||
@@ -1009,3 +1007,115 @@ def test_roll_new_character_avoids_technique_collisions(session):
|
||||
session.refresh(p1)
|
||||
recruit_techs = {p1.tech_jack, p1.tech_queen, p1.tech_king}
|
||||
assert recruit_techs == set(original[3:6])
|
||||
|
||||
def test_reshuffle_keeps_open_pvp_temp_card_out_of_deck(session):
|
||||
game, deep, (p2, p3) = make_scene_game(session, num_pirats=2)
|
||||
p2.hand_cards = json.dumps(["7C"])
|
||||
session.add(p2)
|
||||
session.commit()
|
||||
|
||||
ok, msg = crud.create_pvp_challenge(session, game.id, p2.id, p3.id, "7C")
|
||||
assert ok, msg
|
||||
|
||||
# A mid-duel reshuffle must not pull the temporary Obstacle back into the deck
|
||||
session.refresh(game)
|
||||
crud.reshuffle_discard_pile(session, game)
|
||||
assert "7C" not in crud.get_game_deck(game)
|
||||
|
||||
# Once the duel resolves, the card is discarded and reshuffles normally
|
||||
duel = [c for c in game.challenges if c.challenge_type == "pvp"][0]
|
||||
p3.hand_cards = json.dumps(["9C"])
|
||||
session.add(p3)
|
||||
session.commit()
|
||||
ok, _, _ = crud.play_pvp_defense(session, duel.id, p3.id, "9C")
|
||||
assert ok
|
||||
crud.reshuffle_discard_pile(session, game)
|
||||
assert "7C" in crud.get_game_deck(game)
|
||||
|
||||
def test_late_joiner_is_dealt_a_hand(session):
|
||||
game, deep, (p2,) = make_scene_game(session)
|
||||
assert game.phase == "scene"
|
||||
|
||||
newbie = crud.add_player(session, game.id, "Stowaway")
|
||||
assert newbie.role == "pirat"
|
||||
session.refresh(game)
|
||||
expected = crud.calculate_max_hand_size(newbie, game.players, game.captain_player_id)
|
||||
assert expected > 0
|
||||
assert len(crud.get_player_hand(newbie)) == expected
|
||||
|
||||
def test_technique_suggestions_endpoint():
|
||||
from fastapi.testclient import TestClient
|
||||
from pirats.main import app
|
||||
|
||||
client = TestClient(app, base_url="http://testserver")
|
||||
response = client.get("/api/suggestions/techniques")
|
||||
assert response.status_code == 200
|
||||
techs = response.json()["techniques"]
|
||||
assert techs == cards.TECHNIQUE_SUGGESTIONS
|
||||
assert len(techs) >= 100
|
||||
|
||||
def test_admin_key_returned_at_create_but_hidden_from_state():
|
||||
from fastapi.testclient import TestClient
|
||||
from sqlalchemy.pool import StaticPool
|
||||
from sqlmodel import SQLModel, create_engine, Session
|
||||
from pirats.main import app
|
||||
|
||||
engine = create_engine(
|
||||
"sqlite://",
|
||||
connect_args={"check_same_thread": False},
|
||||
poolclass=StaticPool,
|
||||
)
|
||||
SQLModel.metadata.create_all(engine)
|
||||
session = Session(engine)
|
||||
|
||||
def get_session_override():
|
||||
yield session
|
||||
|
||||
from pirats.database import get_session
|
||||
app.dependency_overrides[get_session] = get_session_override
|
||||
client = TestClient(app, base_url="http://testserver")
|
||||
|
||||
try:
|
||||
created = client.post("/api/game", data={"crew_name": "Leak Test"}).json()
|
||||
assert created["admin_key"]
|
||||
|
||||
game_id = created["id"]
|
||||
player_id = client.post(f"/api/game/{game_id}/join", data={"name": "Carlos"}).json()["id"]
|
||||
state = client.get(f"/api/game/{game_id}/player/{player_id}/state").json()
|
||||
assert "admin_key" not in state["game"]
|
||||
finally:
|
||||
app.dependency_overrides.clear()
|
||||
|
||||
def test_event_log_pagination(session):
|
||||
from pirats.models import GameEvent
|
||||
|
||||
game = crud.create_game(session)
|
||||
for i in range(120):
|
||||
# Explicit timestamps keep ordering deterministic
|
||||
session.add(GameEvent(game_id=game.id, timestamp=1000.0 + i, message=f"event {i}", kind="info"))
|
||||
session.commit()
|
||||
|
||||
# Newest page
|
||||
events, have_more = crud.get_events_page(session, game.id, limit=50)
|
||||
assert have_more
|
||||
assert len(events) == 50
|
||||
assert events[0].message == "event 70"
|
||||
assert events[-1].message == "event 119"
|
||||
|
||||
# Page back from the oldest loaded event
|
||||
older, have_more = crud.get_events_page(session, game.id, before=events[0].timestamp, limit=50)
|
||||
assert have_more
|
||||
assert older[0].message == "event 20"
|
||||
assert older[-1].message == "event 69"
|
||||
|
||||
# Final page is short and reports no more history
|
||||
oldest, have_more = crud.get_events_page(session, game.id, before=older[0].timestamp, limit=50)
|
||||
assert not have_more
|
||||
assert len(oldest) == 20
|
||||
assert oldest[0].message == "event 0"
|
||||
assert oldest[-1].message == "event 19"
|
||||
|
||||
# Exact page boundary still reports no remaining history
|
||||
exact, have_more = crud.get_events_page(session, game.id, before=1020.0, limit=20)
|
||||
assert not have_more
|
||||
assert [e.message for e in exact] == [f"event {i}" for i in range(20)]
|
||||
|
||||
Reference in New Issue
Block a user