mirror of
https://github.com/prosolis/gogobee.git
synced 2026-07-15 08:32:41 +00:00
Adv 2.0 Phase L2 step 8: arena test cleanup + bossflow win assertion
Two cleanup edits to adventure_arena_test.go: - TestRenderArenaStreakEntry_ShowsMultipliers: Level 50 → 20 (D&D cap). - TestRenderArenaStreakEntry_HighLevel_AllEligible: stale "Level 70" comment retargeted to Level 20. - TestArenaStreakSimulation_FullRun: rename combatLevel → skillBonus (the value flows into arenaRoundReward as the battleSkill arg, not a character level — naming was a CombatLevel-era leftover). New test in adventure_arena_bossflow_test.go: TestArenaBossOutcome_WinSurfacesStagedLogAndBossDeath drives renderBossOutcome directly with a forced-win CombatResult so the assertion is RNG-free, then checks the win path emits a TwinBee BossDeath line before the victory headline plus the trailing d20 roll summary. RenderCombatLog is exercised on the same result to confirm the staged-log phases caller in resolveArenaBoss returns content. go vet ./... + go test ./... clean. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -135,6 +135,67 @@ func TestBossFlowPhaseMessages(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// Phase L2 step 8 — assert that an arena win surfaces both the staged
|
||||
// combat log (RenderCombatLog phases prepended by the arena intro) and a
|
||||
// TwinBee BossDeath flavor line in the outcome block. Drives
|
||||
// renderBossOutcome directly with a forced-win CombatResult so the
|
||||
// assertion is RNG-free; the resolveArenaBoss smoke test above already
|
||||
// exercises the live combat path end-to-end.
|
||||
func TestArenaBossOutcome_WinSurfacesStagedLogAndBossDeath(t *testing.T) {
|
||||
monster := arenaBosses[arenaBossID(1, 1)]
|
||||
result := CombatResult{
|
||||
PlayerWon: true,
|
||||
PlayerStartHP: 60, PlayerEndHP: 42,
|
||||
EnemyStartHP: monster.HP, EnemyEndHP: 0,
|
||||
Events: []CombatEvent{
|
||||
{Round: 1, Phase: "attack", Actor: "player", Action: "hit", Roll: 14, RollAgainst: monster.AC, Damage: 10, EnemyHP: monster.HP - 10, PlayerHP: 60},
|
||||
{Round: 2, Phase: "attack", Actor: "player", Action: "crit", Roll: 20, RollAgainst: monster.AC, Damage: monster.HP - 10, EnemyHP: 0, PlayerHP: 42},
|
||||
},
|
||||
TotalRounds: 2,
|
||||
}
|
||||
|
||||
// Staged combat log — same call resolveArenaBoss makes for `phases`.
|
||||
phases := RenderCombatLog(result, "Champion", monster.Name)
|
||||
if len(phases) == 0 {
|
||||
t.Fatal("RenderCombatLog returned no phases for a winning result")
|
||||
}
|
||||
|
||||
victoryHeadline := "🏆 **" + monster.Name + "** falls (HP " + "60" + "→" + "42" + " / 60)."
|
||||
outcome := renderBossOutcome(BossOutcomeInputs{
|
||||
ZoneID: ZoneArena,
|
||||
RunID: "arena-stagedlog-test",
|
||||
RoomIdx: 11,
|
||||
Monster: monster,
|
||||
Result: result,
|
||||
PreHP: 60, PostHP: 42, MaxHP: 60,
|
||||
PhaseTwoAt: arenaBossPhaseTwoAt(1),
|
||||
Nat20s: 1,
|
||||
Nat1s: 0,
|
||||
DefeatHeadline: "unused",
|
||||
VictoryHeadline: victoryHeadline,
|
||||
})
|
||||
|
||||
if !strings.Contains(outcome, "🎭 **TwinBee:**") {
|
||||
t.Errorf("outcome missing TwinBee narration line: %q", outcome)
|
||||
}
|
||||
if !strings.Contains(outcome, victoryHeadline) {
|
||||
t.Errorf("outcome missing victory headline: %q", outcome)
|
||||
}
|
||||
if !strings.Contains(outcome, "🎲 d20 —") {
|
||||
t.Errorf("outcome missing dice-roll summary: %q", outcome)
|
||||
}
|
||||
// BossDeath line must be present — the TwinBee line preceding the
|
||||
// victory headline is sourced from flavor.BossDeath via twinBeeLine.
|
||||
headlineIdx := strings.Index(outcome, victoryHeadline)
|
||||
if headlineIdx <= 0 {
|
||||
t.Fatalf("victory headline not after a TwinBee line: %q", outcome)
|
||||
}
|
||||
prefix := outcome[:headlineIdx]
|
||||
if !strings.Contains(prefix, "🎭 **TwinBee:**") {
|
||||
t.Errorf("BossDeath TwinBee line should precede victory headline; prefix=%q", prefix)
|
||||
}
|
||||
}
|
||||
|
||||
func TestArenaBosses_AllTiersPopulated(t *testing.T) {
|
||||
for tier := 1; tier <= 5; tier++ {
|
||||
for round := 1; round <= 4; round++ {
|
||||
|
||||
@@ -458,7 +458,7 @@ func TestArenaGearDropRates_Decreasing(t *testing.T) {
|
||||
// ── Render Tests (New/Updated) ─────────────────────────────────────────────
|
||||
|
||||
func TestRenderArenaStreakEntry_ShowsMultipliers(t *testing.T) {
|
||||
char := &DnDCharacter{Level: 50}
|
||||
char := &DnDCharacter{Level: 20}
|
||||
tier := arenaGetTier(1)
|
||||
monster := arenaGetMonster(1, 1)
|
||||
|
||||
@@ -491,9 +491,9 @@ func TestRenderArenaStreakEntry_HighLevel_AllEligible(t *testing.T) {
|
||||
monster := arenaGetMonster(1, 1)
|
||||
|
||||
text := renderArenaStreakEntry(char, nil, tier, monster)
|
||||
// Level 70 should make all tiers eligible (no 🔒)
|
||||
// Level 20 (D&D cap) should make all tiers eligible (no 🔒)
|
||||
if strings.Contains(text, "🔒") {
|
||||
t.Error("level 70 should have all tiers eligible (no locked icons)")
|
||||
t.Error("level 20 should have all tiers eligible (no locked icons)")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -753,7 +753,7 @@ func TestArenaStreakSimulation_FullRun(t *testing.T) {
|
||||
TierEarnings: 0,
|
||||
XPAccumulated: 0,
|
||||
}
|
||||
combatLevel := 30
|
||||
skillBonus := 20
|
||||
|
||||
for tierNum := 1; tierNum <= 5; tierNum++ {
|
||||
tier := arenaGetTier(tierNum)
|
||||
@@ -761,7 +761,7 @@ func TestArenaStreakSimulation_FullRun(t *testing.T) {
|
||||
|
||||
for round := 1; round <= 4; round++ {
|
||||
run.Round = round
|
||||
reward := arenaRoundReward(tier, round, combatLevel)
|
||||
reward := arenaRoundReward(tier, round, skillBonus)
|
||||
run.TierEarnings += reward
|
||||
run.XPAccumulated += tier.BattleXP
|
||||
run.RoundsSurvived++
|
||||
@@ -791,7 +791,7 @@ func TestArenaStreakSimulation_FullRun(t *testing.T) {
|
||||
for tierNum := 1; tierNum <= 5; tierNum++ {
|
||||
tier := arenaGetTier(tierNum)
|
||||
for round := 1; round <= 4; round++ {
|
||||
rawTotal += arenaRoundReward(tier, round, combatLevel)
|
||||
rawTotal += arenaRoundReward(tier, round, skillBonus)
|
||||
}
|
||||
rawTotal += tier.CompletionBonus
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user