Skip to content

Commit

Permalink
jest: handle colored output
Browse files Browse the repository at this point in the history
  • Loading branch information
raine committed May 11, 2024
1 parent 2d4531b commit 21a6464
Show file tree
Hide file tree
Showing 3 changed files with 67 additions and 3 deletions.
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,10 @@ Any ideas on how to improve this are appreciated.

## Changelog

## 0.10.5 (12.05.2024)

- jest: Handle colored output.

## 0.10.3 (11.05.2024)

- jest: Allow parsing logs where jest runs using docker-compose.
Expand Down
64 changes: 62 additions & 2 deletions ghtool/src/commands/test/jest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,12 +45,22 @@ impl JestLogParser {
}

fn parse_line(&mut self, raw_line: &str) -> Result<(), eyre::Error> {
let line_no_ansi = String::from_utf8(strip_ansi_escapes::strip(raw_line.as_bytes()))?;
let line_no_timestamp = TIMESTAMP.replace(raw_line, "");

match self.state {
State::LookingForFail => {
if let Some(caps) = JEST_FAIL_LINE.captures(&line_no_timestamp) {
self.current_fail_start_col = caps.name("fail").unwrap().start();
if let Some(caps) = JEST_FAIL_LINE.captures(&line_no_ansi) {
// Attempt to find the column where the colored FAIL text starts.
// This column position will be used to determine where jest output starts.
// We can't just take everything after timestamp because there's possibility
// that jest is running inside docker-compose in which case there would be
// service name after timestamp.
// https://github.com/raine/ghtool/assets/11027/c349807a-cad1-45cb-b02f-4d5020bb3c23
let reset_escape_code = "\u{1b}[0m\u{1b}[7m";
let reset_pos = line_no_timestamp.find(reset_escape_code);
let fail_pos = line_no_timestamp.find("FAIL");
self.current_fail_start_col = reset_pos.unwrap_or(fail_pos.unwrap());
let path = caps.name("path").unwrap().as_str().to_string();
// Get line discarding things before the column where FAIL starts
let line = line_no_timestamp
Expand Down Expand Up @@ -353,4 +363,54 @@ mod tests {
}]
);
}

#[test]
fn test_colors() {
let logs = r#"
2024-05-11T20:44:13.9945728Z $ jest ./src --color --ci --shard=1/2
2024-05-11T20:45:16.0032874Z  FAIL  src/test2.test.ts (61.458 s)
2024-05-11T20:45:16.0034300Z test2
2024-05-11T20:45:16.0037347Z ✓ succeeds (1 ms)
2024-05-11T20:45:16.0038258Z ✕ fails (2 ms)
2024-05-11T20:45:16.0039034Z ✓ foo (60001 ms)
2024-05-11T20:45:16.0039463Z
2024-05-11T20:45:16.0039981Z  ● test2 › fails
2024-05-11T20:45:16.0040506Z
2024-05-11T20:45:16.0041462Z expect(received).toBe(expected) // Object.is equality
2024-05-11T20:45:16.0045857Z
2024-05-11T20:45:16.0046210Z Expected: false
2024-05-11T20:45:16.0046774Z Received: true
2024-05-11T20:45:16.0047256Z 
2024-05-11T20:45:16.0047765Z    5 |
2024-05-11T20:45:16.0048791Z    6 | it("fails", () => {
2024-05-11T20:45:16.0051048Z  > 7 | expect(true).toBe(false);
2024-05-11T20:45:16.0052427Z    | ^
2024-05-11T20:45:16.0053352Z    8 | });
2024-05-11T20:45:16.0054060Z    9 |
2024-05-11T20:45:16.0055164Z    10 | it("foo", async () => {
2024-05-11T20:45:16.0056008Z 
2024-05-11T20:45:16.0057064Z  at Object.<anonymous> (src/test2.test.ts:7:18)
2024-05-11T20:45:16.0057817Z
2024-05-11T20:45:16.0064933Z Test Suites: 1 failed, 1 total
2024-05-11T20:45:16.0065943Z Tests: 1 failed, 2 passed, 3 total
2024-05-11T20:45:16.0066489Z Snapshots: 0 total
2024-05-11T20:45:16.0066847Z Time: 61.502 s
2024-05-11T20:45:16.0067359Z Ran all test suites matching /.\/src/i.
"#;

let failing_tests = JestLogParser::parse(logs).unwrap();
assert_eq!(
failing_tests,
vec![CheckError {
path: "src/test2.test.ts".to_string(),
lines: vec![
"\u{1b}[0m\u{1b}[7m\u{1b}[1m\u{1b}[31m FAIL \u{1b}[39m\u{1b}[22m\u{1b}[27m\u{1b}[0m \u{1b}[2msrc/\u{1b}[22m\u{1b}[1mtest2.test.ts\u{1b}[22m (\u{1b}[0m\u{1b}[1m\u{1b}[41m61.458 s\u{1b}[49m\u{1b}[22m\u{1b}[0m)".to_string(),
" test2".to_string(),
" \u{1b}[32m✓\u{1b}[39m \u{1b}[2msucceeds (1 ms)\u{1b}[22m".to_string(),
" \u{1b}[31m✕\u{1b}[39m \u{1b}[2mfails (2 ms)\u{1b}[22m".to_string(),
" \u{1b}[32m✓\u{1b}[39m \u{1b}[2mfoo (60001 ms)\u{1b}[22m".to_string(),
]
},]
);
}
}

0 comments on commit 21a6464

Please sign in to comment.