rust-mc-status 3.0.0

High-performance asynchronous Rust library for querying Minecraft server status (Java & Bedrock)
Documentation
//! Unit tests for `JavaStatus::from_json`.

use rust_mc_status::JavaStatus;
use serde_json::{json, Value};

fn parse(v: Value) -> JavaStatus {
    JavaStatus::from_json_test(v).expect("from_json should not fail on valid input")
}

fn parse_err(v: Value) -> rust_mc_status::McError {
    JavaStatus::from_json_test(v).expect_err("from_json should fail on invalid input")
}

// ─── Description variants ─────────────────────────────────────────────────────

#[test]
fn description_as_plain_string() {
    let s = parse(json!({
        "version":     { "name": "1.21", "protocol": 767 },
        "players":     { "online": 10, "max": 100 },
        "description": "A Minecraft Server"
    }));
    assert_eq!(s.description, "A Minecraft Server");
}

#[test]
fn description_as_text_object() {
    // Many servers send { "text": "..." } instead of a plain string
    let s = parse(json!({
        "version":     { "name": "1.21", "protocol": 767 },
        "players":     { "online": 5, "max": 50 },
        "description": { "text": "Object MOTD" }
    }));
    assert_eq!(s.description, "Object MOTD");
}

#[test]
fn description_missing_returns_empty_string() {
    let s = parse(json!({
        "version": { "name": "1.21", "protocol": 767 },
        "players": { "online": 0, "max": 20 }
    }));
    assert_eq!(s.description, "");
}

#[test]
fn description_object_without_text_key_returns_empty() {
    let s = parse(json!({
        "version":     { "name": "1.21", "protocol": 767 },
        "players":     { "online": 0, "max": 20 },
        "description": { "translate": "multiplayer.status.unknown" }
    }));
    assert_eq!(s.description, "");
}

// ─── Version ──────────────────────────────────────────────────────────────────

#[test]
fn version_name_and_protocol_parsed() {
    let s = parse(json!({
        "version":     { "name": "1.21.4", "protocol": 769 },
        "players":     { "online": 0, "max": 20 },
        "description": "Test"
    }));
    assert_eq!(s.version.name, "1.21.4");
    assert_eq!(s.version.protocol, 769);
}

// ─── Players ──────────────────────────────────────────────────────────────────

#[test]
fn players_online_and_max_parsed() {
    let s = parse(json!({
        "version": { "name": "1.21", "protocol": 767 },
        "players": { "online": 42, "max": 1000 },
        "description": "Test"
    }));
    assert_eq!(s.players.online, 42);
    assert_eq!(s.players.max, 1000);
}

#[test]
fn players_sample_parsed_when_present() {
    let s = parse(json!({
        "version": { "name": "1.21", "protocol": 767 },
        "players": {
            "online": 2, "max": 10,
            "sample": [
                { "name": "Player1", "id": "uuid-1" },
                { "name": "Player2", "id": "uuid-2" }
            ]
        },
        "description": "Test"
    }));
    let sample = s.players.sample.expect("sample should be present");
    assert_eq!(sample.len(), 2);
    assert_eq!(sample[0].name, "Player1");
    assert_eq!(sample[1].name, "Player2");
}

#[test]
fn players_sample_absent_is_none() {
    let s = parse(json!({
        "version": { "name": "1.21", "protocol": 767 },
        "players": { "online": 0, "max": 10 },
        "description": "Test"
    }));
    assert!(s.players.sample.is_none());
}

// ─── Optional fields ──────────────────────────────────────────────────────────

#[test]
fn favicon_present_when_provided() {
    let s = parse(json!({
        "version":     { "name": "1.21", "protocol": 767 },
        "players":     { "online": 0, "max": 10 },
        "description": "Test",
        "favicon":     "data:image/png;base64,abc123"
    }));
    assert_eq!(s.favicon.as_deref(), Some("data:image/png;base64,abc123"));
}

#[test]
fn favicon_absent_is_none() {
    let s = parse(json!({
        "version":     { "name": "1.21", "protocol": 767 },
        "players":     { "online": 0, "max": 10 },
        "description": "Test"
    }));
    assert!(s.favicon.is_none());
}

#[test]
fn map_field_parsed() {
    let s = parse(json!({
        "version":     { "name": "1.21", "protocol": 767 },
        "players":     { "online": 0, "max": 10 },
        "description": "Test",
        "map":         "world"
    }));
    assert_eq!(s.map.as_deref(), Some("world"));
}

#[test]
fn software_field_parsed() {
    let s = parse(json!({
        "version":     { "name": "1.21", "protocol": 767 },
        "players":     { "online": 0, "max": 10 },
        "description": "Test",
        "software":    "Paper 1.21"
    }));
    assert_eq!(s.software.as_deref(), Some("Paper 1.21"));
}

#[test]
fn unknown_fields_ignored() {
    // Extra fields in JSON should not cause parse failure
    let s = parse(json!({
        "version":      { "name": "1.21", "protocol": 767 },
        "players":      { "online": 0, "max": 10 },
        "description":  "Test",
        "unknownField": "should be ignored",
        "deepNested":   { "a": { "b": 42 } }
    }));
    assert_eq!(s.description, "Test");
}

// ─── Errors ───────────────────────────────────────────────────────────────────

#[test]
fn missing_version_is_error() {
    use rust_mc_status::McError;
    use rust_mc_status::error::ProtocolError;
    let e = parse_err(json!({
        "players":     { "online": 0, "max": 10 },
        "description": "Test"
    }));
    assert!(
        matches!(e, McError::Protocol(ProtocolError::Json(_))),
        "expected Protocol::Json, got {e:?}"
    );
}

#[test]
fn missing_players_is_error() {
    use rust_mc_status::McError;
    use rust_mc_status::error::ProtocolError;
    let e = parse_err(json!({
        "version":     { "name": "1.21", "protocol": 767 },
        "description": "Test"
    }));
    assert!(matches!(e, McError::Protocol(ProtocolError::Json(_))));
}