Command Zone Tests

Overview

This document outlines test cases for the Command Zone in the Commander format. These tests ensure correct implementation of all Commander-specific rules related to the Command Zone, commander casting, commander tax, and zone transitions.

Test Case: Commander Casting

Test: Initial Commander Cast from Command Zone

#![allow(unused)]
fn main() {
#[test]
fn test_initial_commander_cast() {
    // Test setup
    let mut app = App::new();
    app.add_plugins(MinimalPlugins)
       .add_systems(Update, (check_commander_cast, update_command_zone));
       
    // Create player and their commander
    let player = app.world.spawn((
        Player {},
        Mana::default(),
        ActivePlayer,
    )).id();
    
    let commander = app.world.spawn((
        Card { 
            name: "Test Commander".to_string(),
            cost: ManaCost::from_string("{2}{G}{G}").unwrap(),
        },
        Commander { owner: player, cast_count: 0 },
        Zone::CommandZone,
    )).id();
    
    // Player has enough mana to cast
    let mut player_mana = app.world.get_mut::<Mana>(player).unwrap();
    player_mana.add(ManaType::Green, 2);
    player_mana.add(ManaType::Colorless, 2);
    
    // Attempt to cast commander
    app.world.send_event(CastSpellEvent {
        caster: player,
        card: commander,
    });
    app.update();
    
    // Verify commander moved to stack
    assert_eq!(app.world.get::<Zone>(commander).unwrap(), &Zone::Stack);
    
    // Verify no additional tax was applied (first cast)
    assert_eq!(app.world.get::<Commander>(commander).unwrap().cast_count, 1);
}
}

Test: Recasting Commander with Commander Tax

#![allow(unused)]
fn main() {
#[test]
fn test_commander_tax() {
    // Test setup
    let mut app = App::new();
    app.add_plugins(MinimalPlugins)
       .add_systems(Update, (check_commander_cast, update_command_zone, apply_commander_tax));
       
    // Create player and their commander
    let player = app.world.spawn((
        Player {},
        Mana::default(),
        ActivePlayer,
    )).id();
    
    let commander = app.world.spawn((
        Card { 
            name: "Test Commander".to_string(),
            cost: ManaCost::from_string("{2}{G}{G}").unwrap(),
        },
        Commander { owner: player, cast_count: 1 }, // Already cast once before
        Zone::CommandZone,
    )).id();
    
    // Player has enough mana to cast with tax
    let mut player_mana = app.world.get_mut::<Mana>(player).unwrap();
    player_mana.add(ManaType::Green, 2);
    player_mana.add(ManaType::Colorless, 4);  // 2 original + 2 tax
    
    // Attempt to cast commander
    app.world.send_event(CastSpellEvent {
        caster: player,
        card: commander,
    });
    app.update();
    
    // Verify commander moved to stack
    assert_eq!(app.world.get::<Zone>(commander).unwrap(), &Zone::Stack);
    
    // Verify cast count was incremented
    assert_eq!(app.world.get::<Commander>(commander).unwrap().cast_count, 2);
    
    // Verify mana was properly deducted including tax
    let player_mana = app.world.get::<Mana>(player).unwrap();
    assert_eq!(player_mana.get(ManaType::Green), 0);
    assert_eq!(player_mana.get(ManaType::Colorless), 0);
}
}

Test: Insufficient Mana for Commander Tax

#![allow(unused)]
fn main() {
#[test]
fn test_insufficient_mana_for_commander_tax() {
    // Test setup
    let mut app = App::new();
    app.add_plugins(MinimalPlugins)
       .add_systems(Update, (check_commander_cast, update_command_zone, apply_commander_tax));
       
    // Create player and their commander
    let player = app.world.spawn((
        Player {},
        Mana::default(),
        ActivePlayer,
    )).id();
    
    let commander = app.world.spawn((
        Card { 
            name: "Test Commander".to_string(),
            cost: ManaCost::from_string("{2}{G}{G}").unwrap(),
        },
        Commander { owner: player, cast_count: 2 }, // Already cast twice before
        Zone::CommandZone,
    )).id();
    
    // Player doesn't have enough mana for tax
    let mut player_mana = app.world.get_mut::<Mana>(player).unwrap();
    player_mana.add(ManaType::Green, 2);
    player_mana.add(ManaType::Colorless, 3);  // 2 original + 4 tax needed, only 3 available
    
    // Attempt to cast commander
    app.world.send_event(CastSpellEvent {
        caster: player,
        card: commander,
    });
    app.update();
    
    // Verify commander stayed in command zone
    assert_eq!(app.world.get::<Zone>(commander).unwrap(), &Zone::CommandZone);
    
    // Verify cast count was not incremented
    assert_eq!(app.world.get::<Commander>(commander).unwrap().cast_count, 2);
}
}

Test Case: Zone Transitions

Test: Commander Dies and Goes to Command Zone

#![allow(unused)]
fn main() {
#[test]
fn test_commander_death_to_command_zone() {
    // Test setup
    let mut app = App::new();
    app.add_plugins(MinimalPlugins)
       .add_systems(Update, (handle_zone_transitions, commander_replacement_effects));
       
    // Create player and their commander
    let player = app.world.spawn((
        Player {},
        CommanderZoneChoice { use_command_zone: true },
    )).id();
    
    let commander = app.world.spawn((
        Card { name: "Test Commander".to_string() },
        Commander { owner: player, cast_count: 1 },
        Zone::Battlefield,
    )).id();
    
    // Trigger death of commander
    app.world.send_event(ZoneChangeEvent {
        entity: commander,
        from: Zone::Battlefield,
        to: Zone::Graveyard,
        cause: ZoneChangeCause::Death,
    });
    app.update();
    
    // Verify commander went to command zone instead of graveyard
    assert_eq!(app.world.get::<Zone>(commander).unwrap(), &Zone::CommandZone);
}
}

Test: Commander Goes to Exile and Replaced to Command Zone

#![allow(unused)]
fn main() {
#[test]
fn test_commander_exile_to_command_zone() {
    // Test setup
    let mut app = App::new();
    app.add_plugins(MinimalPlugins)
       .add_systems(Update, (handle_zone_transitions, commander_replacement_effects));
       
    // Create player and their commander
    let player = app.world.spawn((
        Player {},
        CommanderZoneChoice { use_command_zone: true },
    )).id();
    
    let commander = app.world.spawn((
        Card { name: "Test Commander".to_string() },
        Commander { owner: player, cast_count: 1 },
        Zone::Battlefield,
    )).id();
    
    // Trigger exile of commander
    app.world.send_event(ZoneChangeEvent {
        entity: commander,
        from: Zone::Battlefield,
        to: Zone::Exile,
        cause: ZoneChangeCause::Exile,
    });
    app.update();
    
    // Verify commander went to command zone instead of exile
    assert_eq!(app.world.get::<Zone>(commander).unwrap(), &Zone::CommandZone);
}
}

Test: Commander Goes to Hand by Player Choice

#![allow(unused)]
fn main() {
#[test]
fn test_commander_to_hand_by_choice() {
    // Test setup
    let mut app = App::new();
    app.add_plugins(MinimalPlugins)
       .add_systems(Update, (handle_zone_transitions, commander_replacement_effects));
       
    // Create player and their commander
    let player = app.world.spawn((
        Player {},
        CommanderZoneChoice { use_command_zone: false }, // Choose not to use command zone
    )).id();
    
    let commander = app.world.spawn((
        Card { name: "Test Commander".to_string() },
        Commander { owner: player, cast_count: 1 },
        Zone::Battlefield,
    )).id();
    
    // Trigger bounce of commander
    app.world.send_event(ZoneChangeEvent {
        entity: commander,
        from: Zone::Battlefield,
        to: Zone::Hand,
        cause: ZoneChangeCause::ReturnToHand,
    });
    app.update();
    
    // Verify commander went to hand as chosen
    assert_eq!(app.world.get::<Zone>(commander).unwrap(), &Zone::Hand);
}
}

Test Case: Partner Commanders

Test: Two Partner Commanders in Command Zone

#![allow(unused)]
fn main() {
#[test]
fn test_partner_commanders() {
    // Test setup
    let mut app = App::new();
    app.add_plugins(MinimalPlugins)
       .add_systems(Update, (check_command_zone_validity, handle_partner_mechanics));
       
    // Create player
    let player = app.world.spawn((
        Player {},
        CommanderList::default(),
    )).id();
    
    // Create two partner commanders
    let commander1 = app.world.spawn((
        Card { name: "Partner Commander 1".to_string() },
        Commander { owner: player, cast_count: 0 },
        PartnerAbility,
        Zone::CommandZone,
    )).id();
    
    let commander2 = app.world.spawn((
        Card { name: "Partner Commander 2".to_string() },
        Commander { owner: player, cast_count: 0 },
        PartnerAbility,
        Zone::CommandZone,
    )).id();
    
    // Add commanders to player's commander list
    let mut commander_list = app.world.get_mut::<CommanderList>(player).unwrap();
    commander_list.add(commander1);
    commander_list.add(commander2);
    app.update();
    
    // Verify player can have two commanders because they have partner
    let validation_errors = app.world.resource::<ValidationErrors>();
    assert!(validation_errors.is_empty());
    
    // Verify both commanders are in the command zone
    assert_eq!(app.world.get::<Zone>(commander1).unwrap(), &Zone::CommandZone);
    assert_eq!(app.world.get::<Zone>(commander2).unwrap(), &Zone::CommandZone);
}
}

Test Case: Command Zone Visibility

Test: Command Zone Cards Visible to All Players

#![allow(unused)]
fn main() {
#[test]
fn test_command_zone_visibility() {
    // Test setup
    let mut app = App::new();
    app.add_plugins(MinimalPlugins)
       .add_systems(Update, check_card_visibility);
       
    // Create multiple players
    let player1 = app.world.spawn(Player {}).id();
    let player2 = app.world.spawn(Player {}).id();
    let player3 = app.world.spawn(Player {}).id();
    
    // Create a commander in the command zone
    let commander = app.world.spawn((
        Card { name: "Test Commander".to_string() },
        Commander { owner: player1, cast_count: 0 },
        Zone::CommandZone,
        Visibility::default(),
    )).id();
    
    // Update visibility
    app.update();
    
    // Verify all players can see the commander in command zone
    let visibility = app.world.get::<Visibility>(commander).unwrap();
    assert!(visibility.is_visible_to(player1));
    assert!(visibility.is_visible_to(player2));
    assert!(visibility.is_visible_to(player3));
}
}

Test Case: Commander Identity Restrictions

Test: Card Color Identity Validation for Commander Deck

#![allow(unused)]
fn main() {
#[test]
fn test_color_identity_restrictions() {
    // Test setup
    let mut app = App::new();
    app.add_plugins(MinimalPlugins)
       .add_systems(Update, validate_deck_color_identity);
       
    // Create player and commander
    let player = app.world.spawn(Player {}).id();
    
    let commander = app.world.spawn((
        Card { name: "Mono-Green Commander".to_string() },
        Commander { owner: player, cast_count: 0 },
        ColorIdentity { colors: vec![Color::Green] },
    )).id();
    
    // Create legal and illegal cards for the deck
    let legal_card = app.world.spawn((
        Card { name: "Green Card".to_string() },
        ColorIdentity { colors: vec![Color::Green] },
        InDeck { owner: player },
    )).id();
    
    let illegal_card = app.world.spawn((
        Card { name: "Blue Card".to_string() },
        ColorIdentity { colors: vec![Color::Blue] },
        InDeck { owner: player },
    )).id();
    
    // Create deck with the commander
    app.world.spawn((
        Deck { owner: player },
        CommanderDeck { commander: commander },
        Cards { entities: vec![legal_card, illegal_card] },
    ));
    
    // Validate deck
    app.update();
    
    // Verify validation errors for illegal card
    let validation_errors = app.world.resource::<ValidationErrors>();
    assert!(!validation_errors.is_empty());
    assert!(validation_errors.contains_error_about(illegal_card, "color identity"));
}
}

These test cases provide comprehensive coverage of the Command Zone mechanics and ensure that all the format-specific rules are correctly implemented and enforced.