apollo-errors 0.7.0

Structured error handling with automatic format conversion
Documentation
//! Tests for extension field handling

mod common;

use apollo_errors::{CodeCase, Error as ErrorTrait, FieldCase, FormatConfig};
use common::{ErrorWithFields, ErrorWithRenamedField};
use insta::assert_json_snapshot;

#[test]
fn test_extension_fields_json() {
    let error = ErrorWithFields::InvalidPort {
        port: 3000,
        config_file: "/app/config.json".to_string(),
    };
    let json = error.to_json(FormatConfig::default()).unwrap();
    assert_json_snapshot!(json, @r#"
    {
      "config_file": "/app/config.json",
      "error": "config::invalid_port",
      "message": "Invalid port",
      "port": 3000
    }
    "#);
}

#[test]
fn test_multiple_fields_graphql() {
    let error = ErrorWithFields::InvalidPort {
        port: 443,
        config_file: "/etc/ssl/config.yaml".to_string(),
    };
    let graphql = error.to_graphql(FormatConfig::default()).unwrap();
    assert_json_snapshot!(graphql, @r#"
    {
      "extensions": {
        "code": "config::invalid_port",
        "config_file": "/etc/ssl/config.yaml",
        "port": 443
      },
      "message": "Invalid port"
    }
    "#);
}

#[test]
fn test_single_field() {
    let error = ErrorWithFields::MissingConfig {
        expected_path: "/var/lib/app/settings.toml".to_string(),
    };
    let graphql = error.to_graphql(FormatConfig::default()).unwrap();
    assert_json_snapshot!(graphql, @r#"
    {
      "extensions": {
        "code": "config::missing",
        "expected_path": "/var/lib/app/settings.toml"
      },
      "message": "Missing configuration"
    }
    "#);
}

#[test]
fn test_numeric_field() {
    let error = ErrorWithFields::InvalidPort {
        port: 65535,
        config_file: String::new(),
    };
    let json = error.to_json(FormatConfig::default()).unwrap();
    // Verify numeric fields are serialized as numbers, not strings
    assert_json_snapshot!(json, @r#"
    {
      "config_file": "",
      "error": "config::invalid_port",
      "message": "Invalid port",
      "port": 65535
    }
    "#);
}

#[test]
fn test_renamed_field_default_config() {
    let error = ErrorWithRenamedField::WithRename {
        my_field: "value".to_string(),
    };
    let json = error.to_json(FormatConfig::default()).unwrap();
    assert_json_snapshot!(json, @r#"
    {
      "error": "test::renamed_field",
      "message": "Field was renamed",
      "my_renamed_field": "value"
    }
    "#);
}

#[test]
fn test_renamed_field_camel_case_code_camel_case() {
    let error = ErrorWithRenamedField::WithRename {
        my_field: "value".to_string(),
    };
    let config = FormatConfig {
        field_case: FieldCase::CamelCase,
        code_case: CodeCase::CamelCase,
    };
    let json = error.to_json(config).unwrap();
    assert_json_snapshot!(json, @r#"
    {
      "error": "testRenamedField",
      "message": "Field was renamed",
      "myRenamedField": "value"
    }
    "#);
}

#[test]
fn test_renamed_field_kebab_case_code_screaming_snake_case() {
    let error = ErrorWithRenamedField::WithRename {
        my_field: "value".to_string(),
    };
    let config = FormatConfig {
        field_case: FieldCase::KebabCase,
        code_case: CodeCase::ScreamingSnakeCase,
    };
    let json = error.to_json(config).unwrap();
    assert_json_snapshot!(json, @r#"
    {
      "error": "TEST_RENAMED_FIELD",
      "message": "Field was renamed",
      "my-renamed-field": "value"
    }
    "#);
}

#[test]
fn test_renamed_field_screaming_snake_case_code_pascal_case() {
    let error = ErrorWithRenamedField::WithRename {
        my_field: "value".to_string(),
    };
    let config = FormatConfig {
        field_case: FieldCase::ScreamingSnakeCase,
        code_case: CodeCase::PascalCase,
    };
    let json = error.to_json(config).unwrap();
    assert_json_snapshot!(json, @r#"
    {
      "MY_RENAMED_FIELD": "value",
      "error": "TestRenamedField",
      "message": "Field was renamed"
    }
    "#);
}