mod common;
use apollo_errors::{CodeCase, FieldCase, FormatConfig, HeapErrorExt};
use common::{ErrorWithFields, ErrorWithStatus};
use std::sync::Arc;
use tower::BoxError;
#[test]
fn test_box_error_to_json() {
let error: BoxError = Box::new(ErrorWithFields::InvalidPort {
port: 8080,
config_file: "/etc/config.toml".to_string(),
});
let json = error.to_json(FormatConfig::default()).unwrap();
insta::assert_json_snapshot!(json, @r###"
{
"config_file": "/etc/config.toml",
"error": "config::invalid_port",
"message": "Invalid port",
"port": 8080
}
"###);
}
#[test]
fn test_box_error_to_html() {
let error: BoxError = Box::new(ErrorWithFields::InvalidPort {
port: 9000,
config_file: "/app/config.conf".to_string(),
});
let html = error.to_html(FormatConfig::default());
insta::assert_snapshot!(html, @r###"
<div class="error">
<h3 class="error-code">config::invalid_port</h3>
<p class="error-message">Invalid port</p>
<div class="error-extensions">
<div class="error-field"><span class="field-name">port:</span> <span class="field-value">9000</span></div>
<div class="error-field"><span class="field-name">config_file:</span> <span class="field-value">/app/config.conf</span></div>
</div>
</div>
"###);
}
#[test]
fn test_box_error_to_graphql() {
let error: BoxError = Box::new(ErrorWithFields::MissingConfig {
expected_path: "/etc/app.yaml".to_string(),
});
let json = error.to_graphql(FormatConfig::default()).unwrap();
insta::assert_json_snapshot!(json, @r###"
{
"extensions": {
"code": "config::missing",
"expected_path": "/etc/app.yaml"
},
"message": "Missing configuration"
}
"###);
}
#[test]
fn test_box_error_to_text() {
let error: BoxError = Box::new(ErrorWithFields::InvalidPort {
port: 3000,
config_file: "/config.toml".to_string(),
});
let text = error.to_text(FormatConfig::default());
insta::assert_snapshot!(text, @"[config::invalid_port] Invalid port");
}
#[test]
fn test_arc_error_to_json() {
let error: Arc<dyn std::error::Error + Send + Sync> = Arc::new(ErrorWithFields::InvalidPort {
port: 8080,
config_file: "/etc/config.toml".to_string(),
});
let json = error.to_json(FormatConfig::default()).unwrap();
insta::assert_json_snapshot!(json, @r###"
{
"config_file": "/etc/config.toml",
"error": "config::invalid_port",
"message": "Invalid port",
"port": 8080
}
"###);
}
#[test]
fn test_arc_error_to_html() {
let error: Arc<dyn std::error::Error + Send + Sync> =
Arc::new(ErrorWithFields::MissingConfig {
expected_path: "/app/config.yaml".to_string(),
});
let html = error.to_html(FormatConfig::default());
insta::assert_snapshot!(html, @r###"
<div class="error">
<h3 class="error-code">config::missing</h3>
<p class="error-message">Missing configuration</p>
<div class="error-extensions">
<div class="error-field"><span class="field-name">expected_path:</span> <span class="field-value">/app/config.yaml</span></div>
</div>
</div>
"###);
}
#[test]
fn test_arc_error_to_graphql() {
let error: Arc<dyn std::error::Error + Send + Sync> = Arc::new(ErrorWithFields::InvalidPort {
port: 5000,
config_file: "/etc/server.conf".to_string(),
});
let json = error.to_graphql(FormatConfig::default()).unwrap();
insta::assert_json_snapshot!(json, @r###"
{
"extensions": {
"code": "config::invalid_port",
"config_file": "/etc/server.conf",
"port": 5000
},
"message": "Invalid port"
}
"###);
}
#[test]
fn test_arc_error_to_text() {
let error: Arc<dyn std::error::Error + Send + Sync> =
Arc::new(ErrorWithFields::MissingConfig {
expected_path: "/config/app.yaml".to_string(),
});
let text = error.to_text(FormatConfig::default());
insta::assert_snapshot!(text, @"[config::missing] Missing configuration");
}
#[test]
fn test_box_error_to_jsonrpc() {
let error: BoxError = Box::new(ErrorWithFields::InvalidPort {
port: 8080,
config_file: "/etc/config.toml".to_string(),
});
let jsonrpc = error.to_jsonrpc(FormatConfig::default()).unwrap();
insta::assert_json_snapshot!(jsonrpc, @r#"
{
"code": -32000,
"data": {
"config_file": "/etc/config.toml",
"diagnostic_code": "config::invalid_port",
"port": 8080
},
"message": "Invalid port"
}
"#);
}
#[test]
fn test_arc_error_to_jsonrpc() {
let error: Arc<dyn std::error::Error + Send + Sync> = Arc::new(ErrorWithFields::InvalidPort {
port: 9000,
config_file: "/app/server.toml".to_string(),
});
let jsonrpc = error.to_jsonrpc(FormatConfig::default()).unwrap();
insta::assert_json_snapshot!(jsonrpc, @r#"
{
"code": -32000,
"data": {
"config_file": "/app/server.toml",
"diagnostic_code": "config::invalid_port",
"port": 9000
},
"message": "Invalid port"
}
"#);
}
#[test]
fn test_format_config_threads_through_arc() {
let error: Arc<dyn std::error::Error + Send + Sync> = Arc::new(ErrorWithFields::InvalidPort {
port: 8080,
config_file: "/etc/config.toml".to_string(),
});
let config = FormatConfig {
field_case: FieldCase::CamelCase,
code_case: CodeCase::ScreamingSnakeCase,
};
let json = error.to_json(config).unwrap();
insta::assert_json_snapshot!(json, @r#"
{
"configFile": "/etc/config.toml",
"error": "CONFIG_INVALID_PORT",
"message": "Invalid port",
"port": 8080
}
"#);
}
#[test]
fn test_box_with_nested_arc() {
let arc_error: Arc<dyn std::error::Error + Send + Sync> =
Arc::new(ErrorWithFields::InvalidPort {
port: 7000,
config_file: "/nested/config.toml".to_string(),
});
let box_error: BoxError = Box::new(arc_error);
let json = box_error.to_json(FormatConfig::default()).unwrap();
insta::assert_json_snapshot!(json, @r###"
{
"config_file": "/nested/config.toml",
"error": "config::invalid_port",
"message": "Invalid port",
"port": 7000
}
"###);
}
#[test]
fn test_error_with_status_to_json() {
let error: BoxError = Box::new(ErrorWithStatus::NotFound);
let json = error.to_json(FormatConfig::default()).unwrap();
insta::assert_json_snapshot!(json, @r###"
{
"error": "resource::not_found",
"message": "Resource not found"
}
"###);
}
#[test]
fn test_unregistered_error_fallback() {
#[derive(Debug)]
struct UnregisteredError;
impl std::fmt::Display for UnregisteredError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "This error is not registered")
}
}
impl std::error::Error for UnregisteredError {}
let error: BoxError = Box::new(UnregisteredError);
let json = error.to_json(FormatConfig::default()).unwrap();
insta::assert_json_snapshot!(json, @r###"
{
"error": "UNKNOWN_ERROR",
"message": "This error is not registered"
}
"###);
let html = error.to_html(FormatConfig::default());
insta::assert_snapshot!(html, @r###"
<div class="error">
<h3 class="error-code">UNKNOWN_ERROR</h3>
<p class="error-message">This error is not registered</p>
</div>
"###);
let graphql = error.to_graphql(FormatConfig::default()).unwrap();
insta::assert_json_snapshot!(graphql, @r###"
{
"extensions": {
"code": "UNKNOWN_ERROR"
},
"message": "This error is not registered"
}
"###);
let text = error.to_text(FormatConfig::default());
insta::assert_snapshot!(text, @"[UNKNOWN_ERROR] This error is not registered");
let jsonrpc = error.to_jsonrpc(FormatConfig::default()).unwrap();
insta::assert_json_snapshot!(jsonrpc, @r#"
{
"code": -32000,
"data": {
"diagnostic_code": "UNKNOWN_ERROR"
},
"message": "This error is not registered"
}
"#);
}