Use different error string output for Terminal and JSON

This commit is contained in:
Fabrice Reix 2024-06-21 09:00:12 +02:00 committed by hurl-bot
parent 9a03dece9c
commit ef2a85d7e7
No known key found for this signature in database
GPG Key ID: 1283A2B4A0DCAF8D
9 changed files with 96 additions and 25 deletions

View File

@ -17,7 +17,7 @@
*/
use chrono::SecondsFormat;
use hurl_core::ast::SourceInfo;
use hurl_core::error::error_string;
use hurl_core::error::{error_string, OutputFormat};
use serde::{Deserialize, Serialize};
use std::fs::File;
use std::io;
@ -459,7 +459,7 @@ impl AssertJson {
content,
&err,
Some(entry_src_info),
false,
OutputFormat::Json,
)
});
AssertJson {

View File

@ -15,7 +15,7 @@
* limitations under the License.
*
*/
use hurl_core::error::error_string;
use hurl_core::error::{error_string, OutputFormat};
use hurl_core::typing::Repeat;
use std::sync::mpsc::{Receiver, Sender};
use std::sync::{mpsc, Arc, Mutex};
@ -315,7 +315,7 @@ impl ParallelRunner {
content,
&e,
None,
color,
OutputFormat::Terminal(color),
)));
}
}

View File

@ -17,7 +17,7 @@
*/
use crate::report::html::Testcase;
use crate::runner::RunnerError;
use hurl_core::error::error_string;
use hurl_core::error::{error_string, OutputFormat};
#[derive(Copy, Clone, Eq, PartialEq)]
pub enum Tab {
@ -83,7 +83,13 @@ fn error_to_html(
) -> String {
let line = error.source_info.start.line;
let column = error.source_info.start.column;
let message = error_string(filename, content, error, Some(error.source_info), false);
let message = error_string(
filename,
content,
error,
Some(error.source_info),
OutputFormat::Terminal(false),
);
let message = html_escape(&message);
// We override the first part of the error string to add an anchor to
// the error context.

View File

@ -17,7 +17,7 @@
*/
use crate::report::junit::xml::Element;
use crate::runner::{HurlResult, Input};
use hurl_core::error::error_string;
use hurl_core::error::{error_string, OutputFormat};
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct Testcase {
@ -38,7 +38,13 @@ impl Testcase {
let mut errors = vec![];
for (error, entry_src_info) in hurl_result.errors() {
let message = error_string(&name, content, error, Some(entry_src_info), false);
let message = error_string(
&name,
content,
error,
Some(entry_src_info),
OutputFormat::Json,
);
if error.assert {
failures.push(message);
} else {

View File

@ -27,7 +27,7 @@ use hurl::parallel::runner::ParallelRunner;
use hurl::runner::{HurlResult, Input, Output};
use hurl::util::term::{Stdout, WriteMode};
use hurl::{output, parallel, runner};
use hurl_core::error::error_string;
use hurl_core::error::{error_string, OutputFormat};
use hurl_core::typing::Repeat;
/// Runs Hurl `files` sequentially, given a current directory and command-line options (see
@ -128,7 +128,7 @@ fn print_output(
content,
&e,
None,
options.color,
OutputFormat::Terminal(options.color),
)));
}
}

View File

@ -318,7 +318,7 @@ mod tests {
use crate::http::HttpError;
use crate::runner::{RunnerError, RunnerErrorKind};
use hurl_core::ast::{Pos, SourceInfo};
use hurl_core::error::{error_string, split_lines, DisplaySourceError};
use hurl_core::error::{error_string, split_lines, DisplaySourceError, OutputFormat};
use hurl_core::text::Format;
#[test]
@ -339,7 +339,13 @@ mod tests {
"\n 1 | GET http://unknown\n | ^^^^^^^^^^^^^^ (6) Could not resolve host: unknown\n |"
);
assert_eq!(
error_string(filename, content, &error, Some(entry_source_info), false),
error_string(
filename,
content,
&error,
Some(entry_source_info),
OutputFormat::Terminal(false)
),
r#"HTTP connection
--> test.hurl:1:5
|
@ -375,7 +381,13 @@ HTTP/1.0 200
);
assert_eq!(
error_string(filename, content, &error, Some(entry_source_info), false),
error_string(
filename,
content,
&error,
Some(entry_source_info),
OutputFormat::Terminal(false)
),
r#"Assert status code
--> test.hurl:2:10
|
@ -406,7 +418,13 @@ xpath "strong(//head/title)" == "Hello"
"\n 4 | xpath \"strong(//head/title)\" == \"Hello\"\n | ^^^^^^^^^^^^^^^^^^^^^^ the XPath expression is not valid\n |"
);
assert_eq!(
error_string(filename, content, &error, Some(entry_source_info), false),
error_string(
filename,
content,
&error,
Some(entry_source_info),
OutputFormat::Terminal(false)
),
r#"Invalid XPath expression
--> test.hurl:4:7
|
@ -450,7 +468,13 @@ jsonpath "$.count" >= 5
);
assert_eq!(
error_string(filename, content, &error, Some(entry_source_info), false),
error_string(
filename,
content,
&error,
Some(entry_source_info),
OutputFormat::Terminal(false)
),
r#"Assert failure
--> test.hurl:4:0
|
@ -486,7 +510,13 @@ HTTP/1.0 200
"\n 3 | ```<p>Hello</p>\n | ^ actual value is <<p>Hello</p>\n |\n | >\n |"
);
assert_eq!(
error_string(filename, content, &error, Some(entry_source_info), false),
error_string(
filename,
content,
&error,
Some(entry_source_info),
OutputFormat::Terminal(false)
),
r#"Assert body value
--> test.hurl:3:4
|

View File

@ -18,7 +18,7 @@
//! Log utilities.
use hurl_core::ast::SourceInfo;
use hurl_core::error::{error_string, split_lines, DisplaySourceError};
use hurl_core::error::{error_string, split_lines, DisplaySourceError, OutputFormat};
use hurl_core::text::{Format, Style, StyledString};
use crate::runner::Value;
@ -205,7 +205,7 @@ impl Logger {
content,
error,
Some(entry_src_info),
self.color,
OutputFormat::Terminal(self.color),
);
split_lines(&message).iter().for_each(|l| self.debug(l));
}
@ -274,7 +274,13 @@ impl Logger {
}
pub fn error_parsing_rich<E: DisplaySourceError>(&mut self, content: &str, error: &E) {
let message = error_string(&self.filename, content, error, None, self.color);
let message = error_string(
&self.filename,
content,
error,
None,
OutputFormat::Terminal(self.color),
);
self.error_rich(&message);
}
@ -289,7 +295,7 @@ impl Logger {
content,
error,
Some(entry_src_info),
self.color,
OutputFormat::Terminal(self.color),
);
self.error_rich(&message);
}

View File

@ -80,6 +80,13 @@ pub fn add_carets(message: &str, source_info: SourceInfo, content: &[&str]) -> S
s
}
/// Format used by error_string
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum OutputFormat {
Terminal(bool), // Replace \r\n by \n
Json,
}
/// Returns the string representation of an `error`, given `lines` of content and a `filename`.
///
/// The source information where the error occurred can be retrieved in `error`; optionally,
@ -102,7 +109,7 @@ pub fn error_string<E: DisplaySourceError>(
content: &str,
error: &E,
entry_src_info: Option<SourceInfo>,
colored: bool,
format: OutputFormat,
) -> String {
let mut text = String::new();
let lines = split_lines(content);
@ -112,6 +119,7 @@ pub fn error_string<E: DisplaySourceError>(
// The number of digits of the lines count.
let loc_max_width = max(lines.len().to_string().len(), 2);
let separator = "|";
let colored = format == OutputFormat::Terminal(true);
let spaces = " ".repeat(loc_max_width);
let prefix = format!("{spaces} {separator}");
@ -182,7 +190,10 @@ pub fn error_string<E: DisplaySourceError>(
text.push_str(&message);
text
match format {
OutputFormat::Terminal(_) => text.replace("\r\n", "\n"), // CRLF must be replaced by LF in the terminal
OutputFormat::Json => text,
}
}
pub fn add_line_info_prefix(
@ -366,7 +377,13 @@ HTTP 200
);
assert_eq!(
error_string(filename, content, &error, None, false),
error_string(
filename,
content,
&error,
None,
OutputFormat::Terminal(false)
),
r#"Assert body value
--> test.hurl:4:1
|

View File

@ -314,7 +314,7 @@ fn levenshtein_distance(s1: &str, s2: &str) -> usize {
#[cfg(test)]
mod tests {
use super::*;
use crate::error::error_string;
use crate::error::{error_string, OutputFormat};
#[test]
fn test_levenshtein() {
@ -350,7 +350,13 @@ mod tests {
kind: ParseErrorKind::UrlInvalidStart,
};
assert_eq!(
error_string(filename, content, &error, None, false),
error_string(
filename,
content,
&error,
None,
OutputFormat::Terminal(false)
),
r#"Parsing URL
--> test.hurl:1:5
|