diff --git a/resources/fixture/async_fixture.rs b/resources/fixture/async_fixture.rs new file mode 100644 index 0000000..5d282b5 --- /dev/null +++ b/resources/fixture/async_fixture.rs @@ -0,0 +1,34 @@ +use std::future::Future; +use std::io::prelude::*; + +use rstest::*; + +#[fixture] +async fn async_u32() -> u32 { + 42 +} + +#[fixture] +async fn nest_fixture(async_u32: impl Future) -> u32 { + async_u32.await +} + +#[rstest] +async fn default_is_async() { + assert_eq!(42, async_u32::default().await); +} + +#[rstest] +async fn use_async_fixture(async_u32: impl Future) { + assert_eq!(42, async_u32.await); +} + +#[fixture] +async fn async_impl_output() -> impl Read { + std::io::Cursor::new(vec![1, 2, 3, 4, 5]) +} + +#[rstest] +async fn use_async_impl_output(async_impl_output: impl Future) { + let reader = async_impl_output.await; +} diff --git a/src/render/fixture.rs b/src/render/fixture.rs index 1f6575b..8ee826f 100644 --- a/src/render/fixture.rs +++ b/src/render/fixture.rs @@ -10,6 +10,7 @@ use crate::utils::{fn_args, fn_args_idents}; pub(crate) fn render<'a>(fixture: ItemFn, info: FixtureInfo) -> TokenStream { let name = &fixture.sig.ident; + let asyncness = &fixture.sig.asyncness.clone(); let vargs = fn_args_idents(&fixture).cloned().collect::>(); let args = &vargs; let orig_args = &fixture.sig.inputs; @@ -29,6 +30,23 @@ pub(crate) fn render<'a>(fixture: ItemFn, info: FixtureInfo) -> TokenStream { let inject = resolve_args(fn_args_idents(&fixture), &resolver); let partials = (1..=orig_args.len()).map(|n| render_partial_impl(&fixture, n, &resolver, &info)); + + let (self_get_default, self_get) = if asyncness.is_none() { + ( + quote! { + Self::get(#(#args),*) + }, + quote! {#name(#(#args),*)}, + ) + } else { + ( + quote! { + Self::get(#(#args),*).await + }, + quote! {#name(#(#args),*).await}, + ) + }; + quote! { #[allow(non_camel_case_types)] #visibility struct #name {} @@ -36,13 +54,13 @@ pub(crate) fn render<'a>(fixture: ItemFn, info: FixtureInfo) -> TokenStream { impl #name { #(#orig_attrs)* #[allow(unused_mut)] - pub fn get #generics (#orig_args) #output #where_clause { - #name(#(#args),*) + pub #asyncness fn get #generics (#orig_args) #output #where_clause { + #self_get } - pub fn default #default_generics () #default_output #default_where_clause { + pub #asyncness fn default #default_generics () #default_output #default_where_clause { #inject - Self::get(#(#args),*) + #self_get_default } #(#partials)* @@ -66,6 +84,7 @@ fn render_partial_impl( let generics = generics_clean_up(&fixture.sig.generics, fn_args(fixture).take(n), &output); let where_clause = &generics.where_clause; + let asyncness = &fixture.sig.asyncness; let inject = resolve_args(fn_args_idents(fixture).skip(n), resolver); @@ -73,11 +92,21 @@ fn render_partial_impl( let fixture_args = fn_args_idents(fixture); let name = Ident::new(&format!("partial_{}", n), Span::call_site()); + let self_get = if asyncness.is_none() { + quote! { + Self::get(#(#fixture_args),*) + } + } else { + quote! { + Self::get(#(#fixture_args),*).await + } + }; + quote! { #[allow(unused_mut)] - pub fn #name #generics (#(#sign_args),*) #output #where_clause { + pub #asyncness fn #name #generics (#(#sign_args),*) #output #where_clause { #inject - Self::get(#(#fixture_args),*) + #self_get } } } diff --git a/tests/fixture/mod.rs b/tests/fixture/mod.rs index 6c24c0e..bd28db6 100644 --- a/tests/fixture/mod.rs +++ b/tests/fixture/mod.rs @@ -83,6 +83,20 @@ mod should { } } + #[test] + fn resolve_async_fixture() { + let prj = prj("async_fixture.rs"); + prj.add_dependency("async-std", r#"{version="*", features=["attributes"]}"#); + + let output = prj.run_tests().unwrap(); + + TestResults::new() + .ok("default_is_async") + .ok("use_async_fixture") + .ok("use_async_impl_output") + .assert(output); + } + #[test] fn resolve_fixture_generics_by_fixture_input() { let (output, _) = run_test("resolve.rs");