diff --git a/okapi-operation-macro/CHANGELOG.md b/okapi-operation-macro/CHANGELOG.md index fea21ba..e678b9e 100644 --- a/okapi-operation-macro/CHANGELOG.md +++ b/okapi-operation-macro/CHANGELOG.md @@ -7,7 +7,8 @@ This project follows the [Semantic Versioning standard](https://semver.org/). ### Added - Feature `axum` for enable axum-specific functionality; - Request body detection from function arguments for specific frameworks (i.e. axum); - - `#[body]` attribute as replacement for `#[request_body]` (now considered deprecated). + - `#[body]` attribute as replacement for `#[request_body]` (now considered deprecated); + - Updates `syn` crate to version 2. ## [0.1.4] - 2024-07-18 diff --git a/okapi-operation-macro/Cargo.toml b/okapi-operation-macro/Cargo.toml index a071647..aa9314d 100644 --- a/okapi-operation-macro/Cargo.toml +++ b/okapi-operation-macro/Cargo.toml @@ -14,8 +14,7 @@ repository = "https://github.com/Flowneee/okapi-operation" proc-macro = true [dependencies] - -darling = "0.20.10" +darling = "0.20" lazy_static = "1" proc-macro2 = "1" quote = "1" @@ -24,3 +23,6 @@ thiserror = "1" [features] axum = [] + +[dev-dependencies] +assert_matches = "1" diff --git a/okapi-operation-macro/src/operation/external_docs.rs b/okapi-operation-macro/src/operation/external_docs.rs index 2757ac1..e8130d4 100644 --- a/okapi-operation-macro/src/operation/external_docs.rs +++ b/okapi-operation-macro/src/operation/external_docs.rs @@ -4,7 +4,7 @@ use quote::{quote, ToTokens}; use crate::utils::quote_option; -#[derive(Debug, FromMeta)] +#[derive(Debug, FromMeta, PartialEq)] pub(super) struct ExternalDocs { url: String, #[darling(default)] @@ -17,10 +17,69 @@ impl ToTokens for ExternalDocs { let description = quote_option(&self.description); tokens.extend(quote! { okapi::openapi3::ExternalDocs { - description: #description, url: #url.into(), + description: #description, ..Default::default() } }) } } + +#[cfg(test)] +mod tests { + use syn::{parse_quote, ExprStruct, Meta}; + + use super::*; + + #[test] + fn parse() { + let url = "test_url".to_string(); + let description = "test_description".to_string(); + + let input: Meta = parse_quote! { external_docs(url = #url, description = #description) }; + + assert_eq!( + ExternalDocs::from_meta(&input).expect("Successfullt parsed"), + ExternalDocs { + url, + description: Some(description) + } + ); + } + + // NOTE: codegen test is kinda useless by itself, better to test expectations + // in some kind of integration tests. But I will leave it here as reference in case + // they needed. + + // #[test] + // fn codegen() { + // let url = "test_url".to_string(); + // let description = "test_description".to_string(); + + // let test_value = ExternalDocs { + // url: url.clone(), + // description: Some(description.clone()), + // }; + + // let expected_output = quote! { + // okapi::openapi3::ExternalDocs { + // url: #url.into(), + // description: Some(#description.into()), + // ..Default::default() + // } + // }; + + // assert_eq_tokens::(&test_value, &expected_output); + // } + + // pub fn assert_eq_tokens(actual: &impl ToTokens, expected: &TokenStream) + // where + // T: Parse + Debug + PartialEq, + // { + // let actual: T = + // syn::parse2(actual.to_token_stream()).expect("Failed to parse actual value"); + // let expected: T = syn::parse2(expected.clone()).expect("Failed to parse expected value"); + + // assert_eq!(actual, expected); + // } +} diff --git a/okapi-operation-macro/src/operation/security.rs b/okapi-operation-macro/src/operation/security.rs index 4103c2d..234f4ba 100644 --- a/okapi-operation-macro/src/operation/security.rs +++ b/okapi-operation-macro/src/operation/security.rs @@ -9,12 +9,12 @@ static SECURITY_SCHEME_ATTRIBUTE_NAME: &str = "security_scheme"; static SECURITY_SCHEME_NAME_ATTRIBUTE_NAME: &str = "name"; static SECURITY_SCHEME_SCOPES_ATTRIBUTE_NAME: &str = "scopes"; -#[derive(Default, Debug)] +#[derive(Default, Debug, PartialEq)] pub struct Security { schemes: Vec, } -#[derive(Default, Debug)] +#[derive(Default, Debug, PartialEq)] struct SecurityScheme { name: String, scopes: Vec, @@ -124,3 +124,57 @@ impl ToTokens for SecurityScheme { }); } } + +#[cfg(test)] +mod tests { + use assert_matches::assert_matches; + use syn::{parse_quote, ExprTuple, Meta}; + + use crate::utils::test_utils::assert_eq_tokens; + + use super::*; + + #[test] + fn parse_security_scheme() { + let name = "test_name".to_string(); + let scopes = "scope1,scope2,scope3".to_string(); + + let input: Meta = parse_quote! { security_scheme(name = #name, scopes = #scopes) }; + + assert_eq!( + SecurityScheme::from_meta(&input).expect("Successfullt parsed"), + SecurityScheme { + name, + scopes: scopes.split(',').map(Into::into).collect() + } + ); + } + + #[test] + fn parse_security() { + let name1 = "test_name1".to_string(); + let name2 = "test_name2".to_string(); + let scopes = "scope1,scope2,scope3".to_string(); + + let input: Meta = parse_quote! { security( + security_scheme(name = #name1, scopes = #scopes), + security_scheme(name = #name2, scopes = #scopes) + ) }; + + assert_eq!( + Security::from_meta(&input).expect("Failed to parse"), + Security { + schemes: vec![ + SecurityScheme { + name: name1, + scopes: scopes.split(',').map(Into::into).collect() + }, + SecurityScheme { + name: name2, + scopes: scopes.split(',').map(Into::into).collect() + } + ] + } + ); + } +}