mod common;
use apollo_errors::{CodeCase, Error as ErrorTrait, FieldCase, FormatConfig};
use common::{ErrorWithFields, ErrorWithHelp, ErrorWithRenamedField, SimpleError};
use insta::assert_snapshot;
#[test]
fn test_simple_error_html() {
let error = SimpleError::Simple;
let html = error.to_html(FormatConfig::default());
assert_snapshot!(html, @r#"
<div class="error">
<h3 class="error-code">errors::simple</h3>
<p class="error-message">Something went wrong</p>
</div>
"#);
}
#[test]
fn test_error_with_help_html() {
let error = ErrorWithHelp::ConfigError;
let html = error.to_html(FormatConfig::default());
assert_snapshot!(html, @r#"
<div class="error">
<h3 class="error-code">config::error</h3>
<p class="error-message">Configuration error</p>
<p class="error-help">Check your configuration file</p>
</div>
"#);
}
#[test]
fn test_error_with_single_extension_field_html() {
let error = ErrorWithFields::MissingConfig {
expected_path: "/etc/app/config.yaml".to_string(),
};
let html = error.to_html(FormatConfig::default());
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">/etc/app/config.yaml</span></div>
</div>
</div>
"###);
}
#[test]
fn test_error_with_multiple_extension_fields_html() {
let error = ErrorWithFields::InvalidPort {
port: 8080,
config_file: "/etc/server.conf".to_string(),
};
let html = error.to_html(FormatConfig::default());
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">8080</span></div>
<div class="error-field"><span class="field-name">config_file:</span> <span class="field-value">/etc/server.conf</span></div>
</div>
</div>
"###);
}
#[test]
fn test_error_with_numeric_extension_html() {
let error = ErrorWithFields::InvalidPort {
port: 65535,
config_file: "/app/settings.toml".to_string(),
};
let html = error.to_html(FormatConfig::default());
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">65535</span></div>
<div class="error-field"><span class="field-name">config_file:</span> <span class="field-value">/app/settings.toml</span></div>
</div>
</div>
"###);
}
#[test]
fn test_html_escapes_dangerous_characters() {
let error = ErrorWithFields::MissingConfig {
expected_path: "<script>alert('xss')</script>".to_string(),
};
let html = error.to_html(FormatConfig::default());
assert!(html.contains("<script>alert('xss')</script>"));
assert!(!html.contains("<script>"));
}
#[test]
fn test_html_escapes_ampersand_and_quotes() {
let error = ErrorWithFields::MissingConfig {
expected_path: "path with & and \"quotes\"".to_string(),
};
let html = error.to_html(FormatConfig::default());
assert!(html.contains("path with & and "quotes""));
assert!(!html.contains("path with & and"));
}
#[test]
fn test_html_with_interpolated_message() {
use common::ConfigStructError;
let error = ConfigStructError {
port: 8080,
config_path: "/etc/config.toml".to_string(),
};
let html = error.to_html(FormatConfig::default());
assert!(
html.contains("Configuration error: invalid port 8080"),
"HTML message should contain interpolated port value, got: {}",
html
);
}
#[test]
fn test_error_with_fields_kebab_case_code_case_screaming_snake_case() {
let config = FormatConfig {
field_case: FieldCase::KebabCase,
code_case: CodeCase::ScreamingSnakeCase,
};
let error = ErrorWithFields::InvalidPort {
port: 8080,
config_file: "/etc/config.toml".to_string(),
};
let html = error.to_html(config);
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">8080</span></div>
<div class="error-field"><span class="field-name">config-file:</span> <span class="field-value">/etc/config.toml</span></div>
</div>
</div>
"#);
}
#[test]
fn test_error_with_fields_pascal_case_code_case_default() {
let config = FormatConfig {
field_case: FieldCase::PascalCase,
..FormatConfig::default()
};
let error = ErrorWithFields::InvalidPort {
port: 8080,
config_file: "/etc/config.toml".to_string(),
};
let html = error.to_html(config);
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">8080</span></div>
<div class="error-field"><span class="field-name">ConfigFile:</span> <span class="field-value">/etc/config.toml</span></div>
</div>
</div>
"#);
}
#[test]
fn test_error_with_fields_default_case_code_case_screaming_snake_case() {
let config = FormatConfig {
code_case: CodeCase::ScreamingSnakeCase,
..FormatConfig::default()
};
let error = ErrorWithFields::InvalidPort {
port: 8080,
config_file: "/etc/config.toml".to_string(),
};
let html = error.to_html(config);
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">8080</span></div>
<div class="error-field"><span class="field-name">config_file:</span> <span class="field-value">/etc/config.toml</span></div>
</div>
</div>
"#);
}
#[test]
fn test_renamed_field_pascal_case_screaming_snake_code_html() {
let error = ErrorWithRenamedField::WithRename {
my_field: "value".to_string(),
};
let config = FormatConfig {
field_case: FieldCase::PascalCase,
code_case: CodeCase::ScreamingSnakeCase,
};
let html = error.to_html(config);
assert_snapshot!(html, @r#"
<div class="error">
<h3 class="error-code">TEST_RENAMED_FIELD</h3>
<p class="error-message">Field was renamed</p>
<div class="error-extensions">
<div class="error-field"><span class="field-name">MyRenamedField:</span> <span class="field-value">value</span></div>
</div>
</div>
"#);
}