Skip to content

Commit

Permalink
Cover basic and colored output regressions with unit tests (#302, #299)
Browse files Browse the repository at this point in the history
Additionally:
- use deterministic order of possible matches in `AmbiguousMatchError`
- reduce count of cursor moves in `writer::out::WriteStrExt::clear_last_lines()`
- unify code style of lines accessing `writer::Basic`

Co-authored-by: 50U10FCA7 <[email protected]>
  • Loading branch information
50U10FCA7 and 50U10FCA7 authored Oct 16, 2023
1 parent f4ff0db commit 169fcff
Show file tree
Hide file tree
Showing 84 changed files with 714 additions and 244 deletions.
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,12 @@ All user visible changes to `cucumber` crate will be documented in this file. Th
### Fixed

- Incorrect terminal width detection when its height is low. ([#298])
- Incorrect terminal lines clearing in interactive mode. ([#300], [#299])
- Incorrect terminal lines clearing in interactive mode. ([#300], [#302], [#299])

[#298]: /../../pull/298
[#299]: /../../issues/299
[#300]: /../../pull/300
[#302]: /../../pull/302



Expand Down
2 changes: 2 additions & 0 deletions src/step.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ use std::{
use derive_more::{Deref, DerefMut, Display, Error};
use futures::future::LocalBoxFuture;
use gherkin::StepType;
use itertools::Itertools as _;
use regex::Regex;

/// Alias for a [`gherkin::Step`] function that returns a [`LocalBoxFuture`].
Expand Down Expand Up @@ -199,6 +200,7 @@ impl<World> Collection<World> {
possible_matches: captures
.into_iter()
.map(|(re, loc, ..)| (re.clone(), *loc))
.sorted()
.collect(),
})
}
Expand Down
10 changes: 6 additions & 4 deletions src/writer/basic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -548,7 +548,7 @@ impl<Out: io::Write> Basic<Out> {
indent = " ".repeat(self.indent),
);
self.lines_to_clear += self.styles.lines_count(&out);
self.write_line(&out)?;
self.output.write_line(&out)?;
}
Ok(())
}
Expand Down Expand Up @@ -734,7 +734,8 @@ impl<Out: io::Write> Basic<Out> {
.unwrap_or_default(),
));

self.write_line(&format!("{step_keyword}{step_value}{diagnostics}"))
self.output
.write_line(&format!("{step_keyword}{step_value}{diagnostics}"))
}

/// Outputs the [`Background`] [`Step`]'s
Expand Down Expand Up @@ -823,7 +824,7 @@ impl<Out: io::Write> Basic<Out> {
indent = " ".repeat(self.indent.saturating_sub(2)),
);
self.lines_to_clear += self.styles.lines_count(&out);
self.write_line(&out)?;
self.output.write_line(&out)?;
}
Ok(())
}
Expand Down Expand Up @@ -1011,7 +1012,8 @@ impl<Out: io::Write> Basic<Out> {
.unwrap_or_default(),
));

self.write_line(&format!("{step_keyword}{step_value}{diagnostics}"))
self.output
.write_line(&format!("{step_keyword}{step_value}{diagnostics}"))
}
}

Expand Down
8 changes: 5 additions & 3 deletions src/writer/out.rs
Original file line number Diff line number Diff line change
Expand Up @@ -250,16 +250,18 @@ pub trait WriteStrExt: io::Write {

/// Writes a special sequence into this writer clearing the last `n` lines.
///
/// __NOTE:__ This method doesn't clear the current line, only the `n` lines
/// above it.
///
/// # Errors
///
/// If this writer fails to write a special sequence.
fn clear_last_lines(&mut self, n: usize) -> io::Result<()> {
self.move_cursor_up(n)?;
for _ in 0..n {
self.move_cursor_up(1)?;
self.clear_line()?;
self.move_cursor_down(1)?;
}
self.move_cursor_up(n)
Ok(())
}

/// Writes a special sequence into this writer clearing the last line.
Expand Down
5 changes: 5 additions & 0 deletions tests/features/output/.feature.basic.out
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
Feature: output
Scenario: output
✔ Given foo is 0
✔ When foo is 1
✔ Then foo is 2
8 changes: 8 additions & 0 deletions tests/features/output/.feature.colored.out
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
Feature: output
 Scenario: output
Given foo is 0
 ✔ Given foo is 0
When foo is 1
 ✔ When foo is 1
Then foo is 2
 ✔ Then foo is 2
Expand Down

Large diffs are not rendered by default.

8 changes: 8 additions & 0 deletions tests/features/output/ambiguous_step.feature.basic.out
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
Feature: ambiguous
Scenario: ambiguous
✘ Given foo is 0 ambiguous
Step failed:
Defined: tests/features/output/ambiguous_step.feature:3:5
Step match is ambiguous: Possible matches:
foo is (\d+) --> tests/output.rs:12:1
foo is (\d+) ambiguous --> tests/output.rs:20:1
9 changes: 9 additions & 0 deletions tests/features/output/ambiguous_step.feature.colored.out
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
Feature: ambiguous
 Scenario: ambiguous
Given foo is 0 ambiguous
 ✘ Given foo is 0 ambiguous
Step failed:
Defined: tests/features/output/ambiguous_step.feature:3:5
Step match is ambiguous: Possible matches:
foo is (\d+) --> tests/output.rs:12:1
foo is (\d+) ambiguous --> tests/output.rs:20:1
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ Started
Feature(Feature { keyword: "Feature", name: "ambiguous", description: None, background: None, scenarios: [Scenario { keyword: "Scenario", name: "ambiguous", description: None, steps: [Step { keyword: "Given ", ty: Given, value: "foo is 0 ambiguous", docstring: None, table: None, position: LineCol { line: 3 } }], examples: [], tags: [], position: LineCol { line: 2 } }], rules: [], tags: [], position: LineCol { line: 1 }, }, Started)
Feature(Feature { keyword: "Feature", name: "ambiguous", description: None, background: None, scenarios: [Scenario { keyword: "Scenario", name: "ambiguous", description: None, steps: [Step { keyword: "Given ", ty: Given, value: "foo is 0 ambiguous", docstring: None, table: None, position: LineCol { line: 3 } }], examples: [], tags: [], position: LineCol { line: 2 } }], rules: [], tags: [], position: LineCol { line: 1 }, }, Scenario(Scenario { keyword: "Scenario", name: "ambiguous", description: None, steps: [Step { keyword: "Given ", ty: Given, value: "foo is 0 ambiguous", docstring: None, table: None, position: LineCol { line: 3 } }], examples: [], tags: [], position: LineCol { line: 2 } }, RetryableScenario { event: Started, retries: None }))
Feature(Feature { keyword: "Feature", name: "ambiguous", description: None, background: None, scenarios: [Scenario { keyword: "Scenario", name: "ambiguous", description: None, steps: [Step { keyword: "Given ", ty: Given, value: "foo is 0 ambiguous", docstring: None, table: None, position: LineCol { line: 3 } }], examples: [], tags: [], position: LineCol { line: 2 } }], rules: [], tags: [], position: LineCol { line: 1 }, }, Scenario(Scenario { keyword: "Scenario", name: "ambiguous", description: None, steps: [Step { keyword: "Given ", ty: Given, value: "foo is 0 ambiguous", docstring: None, table: None, position: LineCol { line: 3 } }], examples: [], tags: [], position: LineCol { line: 2 } }, RetryableScenario { event: Step(Step { keyword: "Given ", ty: Given, value: "foo is 0 ambiguous", docstring: None, table: None, position: LineCol { line: 3 } }, Started), retries: None }))
Feature(Feature { keyword: "Feature", name: "ambiguous", description: None, background: None, scenarios: [Scenario { keyword: "Scenario", name: "ambiguous", description: None, steps: [Step { keyword: "Given ", ty: Given, value: "foo is 0 ambiguous", docstring: None, table: None, position: LineCol { line: 3 } }], examples: [], tags: [], position: LineCol { line: 2 } }], rules: [], tags: [], position: LineCol { line: 1 }, }, Scenario(Scenario { keyword: "Scenario", name: "ambiguous", description: None, steps: [Step { keyword: "Given ", ty: Given, value: "foo is 0 ambiguous", docstring: None, table: None, position: LineCol { line: 3 } }], examples: [], tags: [], position: LineCol { line: 2 } }, RetryableScenario { event: Step(Step { keyword: "Given ", ty: Given, value: "foo is 0 ambiguous", docstring: None, table: None, position: LineCol { line: 3 } }, Failed(None, None, None, AmbiguousMatch(AmbiguousMatchError { possible_matches: [(HashableRegex(Regex("foo is (\\d+)")), Some(Location { line: 13, column: 1 })), (HashableRegex(Regex("foo is (\\d+) ambiguous")), Some(Location { line: 21, column: 1 }))] }))), retries: None }))
Feature(Feature { keyword: "Feature", name: "ambiguous", description: None, background: None, scenarios: [Scenario { keyword: "Scenario", name: "ambiguous", description: None, steps: [Step { keyword: "Given ", ty: Given, value: "foo is 0 ambiguous", docstring: None, table: None, position: LineCol { line: 3 } }], examples: [], tags: [], position: LineCol { line: 2 } }], rules: [], tags: [], position: LineCol { line: 1 }, }, Scenario(Scenario { keyword: "Scenario", name: "ambiguous", description: None, steps: [Step { keyword: "Given ", ty: Given, value: "foo is 0 ambiguous", docstring: None, table: None, position: LineCol { line: 3 } }], examples: [], tags: [], position: LineCol { line: 2 } }, RetryableScenario { event: Step(Step { keyword: "Given ", ty: Given, value: "foo is 0 ambiguous", docstring: None, table: None, position: LineCol { line: 3 } }, Failed(None, None, None, AmbiguousMatch(AmbiguousMatchError { possible_matches: [(HashableRegex(Regex("foo is (\\d+)")), Some(Location { line: 12, column: 1 })), (HashableRegex(Regex("foo is (\\d+) ambiguous")), Some(Location { line: 20, column: 1 }))] }))), retries: None }))
Feature(Feature { keyword: "Feature", name: "ambiguous", description: None, background: None, scenarios: [Scenario { keyword: "Scenario", name: "ambiguous", description: None, steps: [Step { keyword: "Given ", ty: Given, value: "foo is 0 ambiguous", docstring: None, table: None, position: LineCol { line: 3 } }], examples: [], tags: [], position: LineCol { line: 2 } }], rules: [], tags: [], position: LineCol { line: 1 }, }, Scenario(Scenario { keyword: "Scenario", name: "ambiguous", description: None, steps: [Step { keyword: "Given ", ty: Given, value: "foo is 0 ambiguous", docstring: None, table: None, position: LineCol { line: 3 } }], examples: [], tags: [], position: LineCol { line: 2 } }, RetryableScenario { event: Finished, retries: None }))
Feature(Feature { keyword: "Feature", name: "ambiguous", description: None, background: None, scenarios: [Scenario { keyword: "Scenario", name: "ambiguous", description: None, steps: [Step { keyword: "Given ", ty: Given, value: "foo is 0 ambiguous", docstring: None, table: None, position: LineCol { line: 3 } }], examples: [], tags: [], position: LineCol { line: 2 } }], rules: [], tags: [], position: LineCol { line: 1 }, }, Finished)
Finished
Finished
7 changes: 7 additions & 0 deletions tests/features/output/background_rule.feature.basic.out
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
Feature: output
Rule: output
Scenario: output
✔> Given foo is 0
✔ Given foo is 1
✔ When foo is 2
✔ Then foo is 3
11 changes: 11 additions & 0 deletions tests/features/output/background_rule.feature.colored.out
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
Feature: output
Rule: output
 Scenario: output
> Given foo is 0
 ✔> Given foo is 0
Given foo is 1
 ✔ Given foo is 1
When foo is 2
 ✔ When foo is 2
Then foo is 3
 ✔ Then foo is 3
Expand Down
Loading

0 comments on commit 169fcff

Please sign in to comment.