Skip to content

Commit

Permalink
Replace #[derive(WorldInit)] macro with #[derive(World)] (#219, #217
Browse files Browse the repository at this point in the history
)

- merge `WorldInit` trait into the `World` trait

Co-authored-by: Kai Ren <[email protected]>
  • Loading branch information
ilslv and tyranron authored Jul 7, 2022
1 parent 3d4b5c7 commit 820dd99
Show file tree
Hide file tree
Showing 42 changed files with 1,142 additions and 1,347 deletions.
7 changes: 6 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,19 @@ All user visible changes to `cucumber` crate will be documented in this file. Th

### BC Breaks

- Bump up [MSRV] to 1.62 for more clever support of [Cargo feature]s and simplified codegen. ([fbd08ec2], [cf055ac0], [todo])
- Bumped up [MSRV] to 1.62 for more clever support of [Cargo feature]s and simplified codegen. ([fbd08ec2], [cf055ac0], [8ad5cc86])
- Replaced `#[derive(WorldInit)]` with `#[derive(World)]` to remove the need of manual `World` trait implementation. ([#219], [#217])
- Merged `WorldInit` trait into the `World` trait. ([#219])

### Changed

- Provided default CLI options are now global (allowed to be specified after custom subcommands). ([#216], [#215])

[#215]: /../../issues/215
[#216]: /../../pull/216
[#217]: /../../issues/217
[#219]: /../../pull/219
[8ad5cc86]: /../../commit/8ad5cc866bb9d6b49470790e3b0dd40690f63a09
[cf055ac0]: /../../commit/cf055ac06c7b72f572882ce15d6a60da92ad60a0
[fbd08ec2]: /../../commit/fbd08ec24dbd036c89f5f0af4d936b616790a166

Expand Down
3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ rustdoc-args = ["--cfg", "docsrs"]
[features]
default = ["macros"]
# Enables step attributes and auto-wiring.
macros = ["dep:cucumber-codegen", "dep:cucumber-expressions", "dep:inventory"]
macros = ["dep:anyhow", "dep:cucumber-codegen", "dep:cucumber-expressions", "dep:inventory"]
# Enables support for outputting in Cucumber JSON format.
output-json = ["dep:Inflector", "dep:serde", "dep:serde_json", "timestamps"]
# Enables support for outputting JUnit XML report.
Expand All @@ -37,6 +37,7 @@ output-junit = ["dep:junit-report", "timestamps"]
timestamps = []

[dependencies]
anyhow = { version = "1.0.58", optional = true }
async-trait = "0.1.40"
atty = "0.2.14"
clap = { version = "3.0", features = ["derive"] }
Expand Down
16 changes: 3 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,27 +29,17 @@ Feature: Eating too much cucumbers may not be good for you

Implement `World` trait and describe steps:
```rust
use std::{convert::Infallible, time::Duration};
use std::time::Duration;

use async_trait::async_trait;
use cucumber::{given, then, when, WorldInit};
use cucumber::{given, then, when, World as _};
use tokio::time::sleep;

#[derive(Debug, WorldInit)]
#[derive(cucumber::World, Debug, Default)]
struct World {
user: Option<String>,
capacity: usize,
}

#[async_trait(?Send)]
impl cucumber::World for World {
type Error = Infallible;

async fn new() -> Result<Self, Self::Error> {
Ok(Self { user: None, capacity: 0 })
}
}

#[given(expr = "{word} is hungry")] // Cucumber Expression
async fn someone_is_hungry(w: &mut World, user: String) {
sleep(Duration::from_secs(2)).await;
Expand Down
17 changes: 3 additions & 14 deletions book/src/architecture/parser.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@ Let's start by implementing a custom [`Parser`] which statically emits a single
[`Parser`] represents anything that emits a [`Stream`] of [feature]s.

```rust
# use std::{convert::Infallible, path::PathBuf, time::Duration};
# use std::{path::PathBuf, time::Duration};
#
# use async_trait::async_trait;
# use cucumber::{cli, gherkin, given, parser, then, when, World, WorldInit};
# use cucumber::{cli, gherkin, given, parser, then, when, World};
# use futures::{future, stream};
# use tokio::time::sleep;
#
Expand All @@ -24,22 +24,11 @@ Let's start by implementing a custom [`Parser`] which statically emits a single
# }
# }
#
# #[derive(Debug, WorldInit)]
# #[derive(Debug, Default, World)]
# pub struct AnimalWorld {
# cat: Animal,
# }
#
# #[async_trait(?Send)]
# impl World for AnimalWorld {
# type Error = Infallible;
#
# async fn new() -> Result<Self, Infallible> {
# Ok(Self {
# cat: Animal::default(),
# })
# }
# }
#
# #[given(regex = r"^a (hungry|satiated) cat$")]
# async fn hungry_cat(world: &mut AnimalWorld, state: String) {
# sleep(Duration::from_secs(2)).await;
Expand Down
15 changes: 1 addition & 14 deletions book/src/architecture/runner.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ Now, let's implement a custom [`Runner`] which simply executes [scenario]s in [f

```rust
# use std::{
# convert::Infallible,
# panic::{self, AssertUnwindSafe},
# path::PathBuf,
# sync::Arc,
Expand All @@ -17,7 +16,6 @@ Now, let's implement a custom [`Runner`] which simply executes [scenario]s in [f
# use async_trait::async_trait;
# use cucumber::{
# cli, event, gherkin, given, parser, step, then, when, Event, World,
# WorldInit,
# };
# use futures::{
# future::{self, FutureExt as _},
Expand All @@ -37,22 +35,11 @@ Now, let's implement a custom [`Runner`] which simply executes [scenario]s in [f
# }
# }
#
# #[derive(Clone, Debug, WorldInit)]
# #[derive(Clone, Debug, Default, World)]
# pub struct AnimalWorld {
# cat: Animal,
# }
#
# #[async_trait(?Send)]
# impl World for AnimalWorld {
# type Error = Infallible;
#
# async fn new() -> Result<Self, Infallible> {
# Ok(Self {
# cat: Animal::default(),
# })
# }
# }
#
# #[given(regex = r"^a (hungry|satiated) cat$")]
# async fn hungry_cat(world: &mut AnimalWorld, state: String) {
# sleep(Duration::from_secs(2)).await;
Expand Down
33 changes: 5 additions & 28 deletions book/src/architecture/writer.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ Finally, let's implement a custom [`Writer`] which simply outputs [cucumber even

```rust
# use std::{
# convert::Infallible,
# panic::{self, AssertUnwindSafe},
# path::PathBuf,
# sync::Arc,
Expand All @@ -17,7 +16,7 @@ Finally, let's implement a custom [`Writer`] which simply outputs [cucumber even
# use async_trait::async_trait;
# use cucumber::{
# cli, event, gherkin, given, parser, step, then, when, Event, World,
# WorldInit, WriterExt as _,
# WriterExt as _,
# };
# use futures::{
# future::{self, FutureExt as _},
Expand All @@ -37,22 +36,11 @@ Finally, let's implement a custom [`Writer`] which simply outputs [cucumber even
# }
# }
#
# #[derive(Clone, Debug, WorldInit)]
# #[derive(Clone, Debug, Default, World)]
# pub struct AnimalWorld {
# cat: Animal,
# }
#
# #[async_trait(?Send)]
# impl World for AnimalWorld {
# type Error = Infallible;
#
# async fn new() -> Result<Self, Infallible> {
# Ok(Self {
# cat: Animal::default(),
# })
# }
# }
#
# #[given(regex = r"^a (hungry|satiated) cat$")]
# async fn hungry_cat(world: &mut AnimalWorld, state: String) {
# sleep(Duration::from_secs(2)).await;
Expand Down Expand Up @@ -301,11 +289,11 @@ async fn main() {
> __TIP__: `CustomWriter` will print trash if we feed unordered [`event::Cucumber`]s into it. Though, we shouldn't care about order normalization in our implementations. Instead, we may just wrap `CustomWriter` into [`writer::Normalize`], which will do that for us.
```rust
# use std::{convert::Infallible, path::PathBuf, time::Duration};
# use std::{path::PathBuf, time::Duration};
#
# use async_trait::async_trait;
# use cucumber::{
# cli, event, gherkin, given, parser, then, when, Event, World, WorldInit,
# cli, event, gherkin, given, parser, then, when, Event, World,
# WriterExt as _,
# };
# use futures::{future, stream};
Expand All @@ -322,22 +310,11 @@ async fn main() {
# }
# }
#
# #[derive(Clone, Debug, WorldInit)]
# #[derive(Clone, Debug, Default, World)]
# pub struct AnimalWorld {
# cat: Animal,
# }
#
# #[async_trait(?Send)]
# impl World for AnimalWorld {
# type Error = Infallible;
#
# async fn new() -> Result<Self, Infallible> {
# Ok(Self {
# cat: Animal::default(),
# })
# }
# }
#
# #[given(regex = r"^a (hungry|satiated) cat$")]
# async fn hungry_cat(world: &mut AnimalWorld, state: String) {
# sleep(Duration::from_secs(2)).await;
Expand Down
36 changes: 6 additions & 30 deletions book/src/cli.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,10 +68,9 @@ By default, the whole CLI is composed of [`Parser::Cli`], [`Runner::Cli`] and [`
CLI may be extended even more with arbitrary options, if required. In such case we should combine the final CLI by ourselves and apply it via [`Cucumber::with_cli()`] method.

```rust
# use std::{convert::Infallible, time::Duration};
# use std::time::Duration;
#
# use async_trait::async_trait;
# use cucumber::{cli, given, then, when, World, WorldInit};
# use cucumber::{cli, given, then, when, World};
# use futures::FutureExt as _;
# use tokio::time::sleep;
#
Expand All @@ -86,22 +85,11 @@ CLI may be extended even more with arbitrary options, if required. In such case
# }
# }
#
# #[derive(Debug, WorldInit)]
# #[derive(Debug, Default, World)]
# pub struct AnimalWorld {
# cat: Animal,
# }
#
# #[async_trait(?Send)]
# impl World for AnimalWorld {
# type Error = Infallible;
#
# async fn new() -> Result<Self, Infallible> {
# Ok(Self {
# cat: Animal::default(),
# })
# }
# }
#
# #[given(regex = r"^a (hungry|satiated) cat$")]
# async fn hungry_cat(world: &mut AnimalWorld, state: String) {
# match state.as_str() {
Expand Down Expand Up @@ -157,10 +145,9 @@ async fn main() {
[Cargo alias] is a neat way to define shortcuts for regularly used customized tests running commands.

```rust
# use std::{convert::Infallible, time::Duration};
# use std::time::Duration;
#
# use async_trait::async_trait;
# use cucumber::{cli, given, then, when, World, WorldInit};
# use cucumber::{cli, given, then, when, World};
# use futures::FutureExt as _;
# use tokio::time::sleep;
#
Expand All @@ -175,22 +162,11 @@ async fn main() {
# }
# }
#
# #[derive(Debug, WorldInit)]
# #[derive(Debug, Default, World)]
# pub struct AnimalWorld {
# cat: Animal,
# }
#
# #[async_trait(?Send)]
# impl World for AnimalWorld {
# type Error = Infallible;
#
# async fn new() -> Result<Self, Infallible> {
# Ok(Self {
# cat: Animal::default(),
# })
# }
# }
#
# #[given(regex = r"^a (hungry|satiated) cat$")]
# async fn hungry_cat(world: &mut AnimalWorld, state: String) {
# match state.as_str() {
Expand Down
16 changes: 3 additions & 13 deletions book/src/introduction.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,27 +18,17 @@ These features are agnostic to the implementation, the only requirement is that
[Cucumber] implementations then simply hook into these keywords and execute the logic corresponding to the keywords. [`cucumber`] crate is one of such implementations and is the subject of this book.

```rust
# use std::{convert::Infallible, time::Duration};
# use std::time::Duration;
#
# use async_trait::async_trait;
# use cucumber::{given, then, when, WorldInit};
# use cucumber::{given, then, when, World as _};
# use tokio::time::sleep;
#
# #[derive(Debug, WorldInit)]
# #[derive(cucumber::World, Debug, Default)]
# struct World {
# user: Option<String>,
# capacity: usize,
# }
#
# #[async_trait(?Send)]
# impl cucumber::World for World {
# type Error = Infallible;
#
# async fn new() -> Result<Self, Self::Error> {
# Ok(Self { user: None, capacity: 0 })
# }
# }
#
#[given(expr = "{word} is hungry")] // Cucumber Expression
async fn someone_is_hungry(w: &mut World, user: String) {
sleep(Duration::from_secs(2)).await;
Expand Down
18 changes: 3 additions & 15 deletions book/src/output/json.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,23 +10,11 @@ cucumber = { version = "0.13", features = ["output-json"] }

And configuring output to [`writer::Json`]:
```rust
# use std::{convert::Infallible, fs, io};
#
# use async_trait::async_trait;
# use cucumber::WorldInit;
use cucumber::writer;
# use std::{fs, io};
use cucumber::{writer, World as _};

# #[derive(Debug, WorldInit)]
# #[derive(cucumber::World, Debug, Default)]
# struct World;
#
# #[async_trait(?Send)]
# impl cucumber::World for World {
# type Error = Infallible;
#
# async fn new() -> Result<Self, Self::Error> {
# Ok(World)
# }
# }
#
# #[tokio::main]
# async fn main() -> io::Result<()> {
Expand Down
18 changes: 3 additions & 15 deletions book/src/output/junit.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,23 +10,11 @@ cucumber = { version = "0.13", features = ["output-junit"] }

And configuring output to [`writer::JUnit`]:
```rust
# use std::{convert::Infallible, fs, io};
#
# use async_trait::async_trait;
# use cucumber::WorldInit;
use cucumber::writer;
# use std::{fs, io};
use cucumber::{writer, World as _};

# #[derive(Debug, WorldInit)]
# #[derive(cucumber::World, Debug, Default)]
# struct World;
#
# #[async_trait(?Send)]
# impl cucumber::World for World {
# type Error = Infallible;
#
# async fn new() -> Result<Self, Self::Error> {
# Ok(World)
# }
# }
#
# #[tokio::main]
# async fn main() -> io::Result<()> {
Expand Down
Loading

0 comments on commit 820dd99

Please sign in to comment.