diff --git a/Cargo.lock b/Cargo.lock index 68ed72f15..35e904bb0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -193,9 +193,9 @@ checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" [[package]] name = "base64" -version = "0.22.0" +version = "0.22.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9475866fec1451be56a3c2400fd081ff546538961565ccb5b7142cbd22bc7a51" +checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" [[package]] name = "base64ct" @@ -297,9 +297,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.0.95" +version = "1.0.96" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d32a725bc159af97c3e629873bb9f88fb8cf8a4867175f76dc987815ea07c83b" +checksum = "065a29261d53ba54260972629f9ca6bffa69bac13cd1fed61420f7fa68b9f8bd" [[package]] name = "cfg-if" @@ -526,9 +526,9 @@ checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" [[package]] name = "fastrand" -version = "2.0.2" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "658bd65b1cf4c852a3cc96f18a8ce7b5640f6b703f905c7d74532294c2a63984" +checksum = "9fc0510504f03c51ada170672ac806f1f105a88aa97a5281117e1ddc3368e51a" [[package]] name = "finl_unicode" @@ -727,9 +727,9 @@ checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" [[package]] name = "goblin" -version = "0.8.0" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb07a4ffed2093b118a525b1d8f5204ae274faed5604537caf7135d0f18d9887" +checksum = "1b363a30c165f666402fe6a3024d3bec7ebc898f96a4a23bd1c99f8dbf3f4f47" dependencies = [ "log", "plain", @@ -757,9 +757,9 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.14.3" +version = "0.14.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604" +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" dependencies = [ "ahash", "allocator-api2", @@ -1019,9 +1019,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.153" +version = "0.2.154" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" +checksum = "ae743338b92ff9146ce83992f766a31066a91a8c84a45e0e9f21e7cf6de6d346" [[package]] name = "libm" @@ -1048,9 +1048,9 @@ checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c" [[package]] name = "lock_api" -version = "0.4.11" +version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c168f8615b12bc01f9c17e2eb0cc07dcae1940121185446edc3744920e8ef45" +checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" dependencies = [ "autocfg", "scopeguard", @@ -1272,9 +1272,9 @@ dependencies = [ [[package]] name = "parking_lot" -version = "0.12.1" +version = "0.12.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" +checksum = "7e4af0ca4f6caed20e900d564c242b8e5d4903fdacf31d3daf527b66fe6f42fb" dependencies = [ "lock_api", "parking_lot_core", @@ -1282,15 +1282,15 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.9.9" +version = "0.9.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c42a9226546d68acdd9c0a280d17ce19bfe27a46bf68784e4066115788d008e" +checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" dependencies = [ "cfg-if", "libc", - "redox_syscall", + "redox_syscall 0.5.1", "smallvec", - "windows-targets 0.48.5", + "windows-targets 0.52.5", ] [[package]] @@ -1453,6 +1453,15 @@ dependencies = [ "bitflags 1.3.2", ] +[[package]] +name = "redox_syscall" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "469052894dcb553421e483e4209ee581a45100d31b4018de03e5a7ad86374a7e" +dependencies = [ + "bitflags 2.5.0", +] + [[package]] name = "regex" version = "1.10.4" @@ -1494,7 +1503,7 @@ version = "0.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "566cafdd92868e0939d3fb961bd0dc25fcfaaed179291093b3d43e6b3150ea10" dependencies = [ - "base64 0.22.0", + "base64 0.22.1", "bytes", "encoding_rs", "futures-channel", @@ -1580,6 +1589,18 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "rstest_reuse" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88530b681abe67924d42cca181d070e3ac20e0740569441a9e35a7cedd2b34a4" +dependencies = [ + "quote", + "rand", + "rustc_version", + "syn 2.0.60", +] + [[package]] name = "rustc-demangle" version = "0.1.23" @@ -1614,7 +1635,7 @@ version = "2.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "29993a25686778eb88d4189742cd713c9bce943bc54251a33509dc63cbacf73d" dependencies = [ - "base64 0.22.0", + "base64 0.22.1", "rustls-pki-types", ] @@ -1699,18 +1720,18 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.198" +version = "1.0.200" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9846a40c979031340571da2545a4e5b7c4163bdae79b301d5f86d03979451fcc" +checksum = "ddc6f9cc94d67c0e21aaf7eda3a010fd3af78ebf6e096aa6e2e13c79749cce4f" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.198" +version = "1.0.200" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e88edab869b01783ba905e7d0153f9fc1a6505a96e4ad3018011eedb838566d9" +checksum = "856f046b9400cee3c8c94ed572ecdb752444c24528c035cd35882aad6f492bcb" dependencies = [ "proc-macro2", "quote", @@ -1819,9 +1840,9 @@ checksum = "b7c388c1b5e93756d0c740965c41e8822f866621d41acbdf6336a6a168f8840c" [[package]] name = "socket2" -version = "0.5.6" +version = "0.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05ffd9c0a93b7543e062e759284fcf5f5e3b098501104bfbdde4d404db792871" +checksum = "ce305eb0b4296696835b71df73eb912e0f1ffd2556a501fcede6e0c50349191c" dependencies = [ "libc", "windows-sys 0.52.0", @@ -2447,9 +2468,9 @@ checksum = "d4c87d22b6e3f4a18d4d40ef354e97c90fcb14dd91d7dc0aa9d8a1172ebf7202" [[package]] name = "unicode-width" -version = "0.1.11" +version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85" +checksum = "68f5e5f3158ecfd4b8ff6fe086db7c8467a2dfdac97fe420f2b7c4aa97af66d6" [[package]] name = "unicode_categories" @@ -2737,15 +2758,15 @@ version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a44ab49fad634e88f55bf8f9bb3abd2f27d7204172a112c7c9987e01c1c94ea9" dependencies = [ - "redox_syscall", + "redox_syscall 0.4.1", "wasite", ] [[package]] name = "winapi-util" -version = "0.1.7" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "134306a13c5647ad6453e8deaec55d3a44d6021970129e6188735e74bf546697" +checksum = "4d4cc384e1e73b93bafa6fb4f1df8c41695c8a91cf9c4c64358067d15a7b6c6b" dependencies = [ "windows-sys 0.52.0", ] @@ -2900,9 +2921,9 @@ checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0" [[package]] name = "winnow" -version = "0.6.6" +version = "0.6.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0c976aaaa0e1f90dbb21e9587cdaf1d9679a1cde8875c0d6bd83ab96a208352" +checksum = "14b9415ee827af173ebb3f15f9083df5a122eb93572ec28741fb153356ea2578" dependencies = [ "memchr", ] @@ -2949,11 +2970,13 @@ dependencies = [ name = "wp_networking" version = "0.1.0" dependencies = [ - "base64 0.22.0", + "base64 0.22.1", "chrono", "futures", "http 1.1.0", "reqwest", + "rstest", + "rstest_reuse", "serde_json", "sqlx", "tokio", diff --git a/Cargo.toml b/Cargo.toml index 2db4fcc17..5e026668a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,6 +10,8 @@ resolver = "2" [workspace.dependencies] base64 = "0.22" http = "1.1" +rstest = "0.19" +rstest_reuse = "0.6.0" serde = { version = "1.0", features = [ "derive" ] } serde_json = "1.0" thiserror = "1.0" diff --git a/wp_api/Cargo.toml b/wp_api/Cargo.toml index efbd2db17..db5d688fd 100644 --- a/wp_api/Cargo.toml +++ b/wp_api/Cargo.toml @@ -18,7 +18,7 @@ uniffi = { workspace = true } wp_derive = { path = "../wp_derive" } [dev-dependencies] -rstest = "0.19" +rstest = { workspace = true } [build-dependencies] uniffi = { workspace = true , features = [ "build", "cli" ] } diff --git a/wp_api/src/endpoint/users_endpoint.rs b/wp_api/src/endpoint/users_endpoint.rs index 6ac92c55c..e47b4f751 100644 --- a/wp_api/src/endpoint/users_endpoint.rs +++ b/wp_api/src/endpoint/users_endpoint.rs @@ -1,6 +1,6 @@ use url::Url; -use crate::{ApiBaseUrl, UserDeleteParams, UserId, UserListParams, WPContext}; +use crate::{ApiBaseUrl, SparseUserField, UserDeleteParams, UserId, UserListParams, WPContext}; pub struct UsersEndpoint { api_base_url: ApiBaseUrl, @@ -39,6 +39,15 @@ impl UsersEndpoint { url } + pub fn filter_list( + &self, + context: WPContext, + params: Option<&UserListParams>, + fields: &[SparseUserField], + ) -> Url { + self.append_filter_fields(self.list(context, params), fields) + } + pub fn retrieve(&self, user_id: UserId, context: WPContext) -> Url { let mut url = self .api_base_url @@ -48,6 +57,15 @@ impl UsersEndpoint { url } + pub fn filter_retrieve( + &self, + user_id: UserId, + context: WPContext, + fields: &[SparseUserField], + ) -> Url { + self.append_filter_fields(self.retrieve(user_id, context), fields) + } + pub fn retrieve_me(&self, context: WPContext) -> Url { let mut url = self.api_base_url.by_extending(["users", "me"]); url.query_pairs_mut() @@ -55,6 +73,10 @@ impl UsersEndpoint { url } + pub fn filter_retrieve_me(&self, context: WPContext, fields: &[SparseUserField]) -> Url { + self.append_filter_fields(self.retrieve_me(context), fields) + } + pub fn update(&self, user_id: UserId) -> Url { self.api_base_url .by_extending(["users", &user_id.to_string()]) @@ -63,6 +85,19 @@ impl UsersEndpoint { pub fn update_me(&self) -> Url { self.api_base_url.by_extending(["users", "me"]) } + + fn append_filter_fields(&self, mut url: Url, fields: &[SparseUserField]) -> Url { + url.query_pairs_mut().append_pair( + "_fields", + fields + .iter() + .map(|f| f.as_str()) + .collect::<Vec<&str>>() + .join(",") + .as_str(), + ); + url + } } #[cfg(test)] @@ -134,6 +169,30 @@ mod tests { ); } + #[rstest] + fn filter_list_users_with_params(api_base_url: ApiBaseUrl, users_endpoint: UsersEndpoint) { + let params = UserListParams { + page: Some(2), + per_page: Some(60), + search: Some("foo".to_string()), + exclude: Vec::new(), + include: Vec::new(), + offset: None, + order: None, + orderby: None, + slug: vec!["bar".to_string(), "baz".to_string()], + roles: Vec::new(), + capabilities: Vec::new(), + who: None, + has_published_posts: Some(true), + }; + validate_endpoint( + users_endpoint.filter_list(WPContext::Edit, Some(¶ms), &vec![SparseUserField::Name, SparseUserField::Email]), + "/users?context=edit&page=2&per_page=60&search=foo&slug=bar%2Cbaz&has_published_post=true&_fields=name%2Cemail", + &api_base_url, + ); + } + #[rstest] fn retrieve_user(api_base_url: ApiBaseUrl, users_endpoint: UsersEndpoint) { validate_endpoint( @@ -143,6 +202,19 @@ mod tests { ); } + #[rstest] + fn filter_retrieve_user(api_base_url: ApiBaseUrl, users_endpoint: UsersEndpoint) { + validate_endpoint( + users_endpoint.filter_retrieve( + UserId(98), + WPContext::View, + &vec![SparseUserField::Nickname, SparseUserField::Url], + ), + "/users/98?context=view&_fields=nickname%2Curl", + &api_base_url, + ); + } + #[rstest] fn retrieve_current_user(api_base_url: ApiBaseUrl, users_endpoint: UsersEndpoint) { validate_endpoint( @@ -152,6 +224,18 @@ mod tests { ); } + #[rstest] + fn filter_retrieve_current_user(api_base_url: ApiBaseUrl, users_endpoint: UsersEndpoint) { + validate_endpoint( + users_endpoint.filter_retrieve_me( + WPContext::Embed, + &vec![SparseUserField::Roles, SparseUserField::Capabilities], + ), + "/users/me?context=embed&_fields=roles%2Ccapabilities", + &api_base_url, + ); + } + #[rstest] fn update_user(api_base_url: ApiBaseUrl, users_endpoint: UsersEndpoint) { validate_endpoint( diff --git a/wp_api/src/lib.rs b/wp_api/src/lib.rs index addb65958..b49a68058 100644 --- a/wp_api/src/lib.rs +++ b/wp_api/src/lib.rs @@ -87,6 +87,24 @@ impl WPApiHelper { } } + pub fn filter_list_users_request( + &self, + context: WPContext, + params: &Option<UserListParams>, // UniFFI doesn't support Option<&T> + fields: &[SparseUserField], + ) -> WPNetworkRequest { + WPNetworkRequest { + method: RequestMethod::GET, + url: self + .api_endpoint + .users + .filter_list(context, params.as_ref(), fields) + .into(), + header_map: self.header_map(), + body: None, + } + } + pub fn retrieve_user_request(&self, user_id: UserId, context: WPContext) -> WPNetworkRequest { WPNetworkRequest { method: RequestMethod::GET, @@ -96,6 +114,24 @@ impl WPApiHelper { } } + pub fn filter_retrieve_user_request( + &self, + user_id: UserId, + context: WPContext, + fields: &[SparseUserField], + ) -> WPNetworkRequest { + WPNetworkRequest { + method: RequestMethod::GET, + url: self + .api_endpoint + .users + .filter_retrieve(user_id, context, fields) + .into(), + header_map: self.header_map(), + body: None, + } + } + pub fn retrieve_current_user_request(&self, context: WPContext) -> WPNetworkRequest { WPNetworkRequest { method: RequestMethod::GET, @@ -105,6 +141,23 @@ impl WPApiHelper { } } + pub fn filter_retrieve_current_user_request( + &self, + context: WPContext, + fields: &[SparseUserField], + ) -> WPNetworkRequest { + WPNetworkRequest { + method: RequestMethod::GET, + url: self + .api_endpoint + .users + .filter_retrieve_me(context, fields) + .into(), + header_map: self.header_map(), + body: None, + } + } + pub fn create_user_request(&self, params: &UserCreateParams) -> WPNetworkRequest { WPNetworkRequest { method: RequestMethod::POST, diff --git a/wp_api/src/users.rs b/wp_api/src/users.rs index d7b0c18e3..876cc07fd 100644 --- a/wp_api/src/users.rs +++ b/wp_api/src/users.rs @@ -5,6 +5,20 @@ use wp_derive::WPContextual; use crate::{parse_response_for_generic_errors, WPApiError, WPApiParamOrder, WPNetworkResponse}; +#[uniffi::export] +pub fn parse_filter_users_response( + response: &WPNetworkResponse, +) -> Result<Vec<SparseUser>, WPApiError> { + parse_users_response(response) +} + +#[uniffi::export] +pub fn parse_filter_retrieve_user_response( + response: &WPNetworkResponse, +) -> Result<SparseUser, WPApiError> { + parse_users_response(response) +} + #[uniffi::export] pub fn parse_list_users_response_with_edit_context( response: &WPNetworkResponse, @@ -385,3 +399,47 @@ pub struct SparseUser { pub avatar_urls: Option<HashMap<String, String>>, // meta field is omitted for now: https://github.com/Automattic/wordpress-rs/issues/57 } + +#[derive(Debug, Clone, Copy, PartialEq, Eq, uniffi::Enum)] +pub enum SparseUserField { + Id, + Username, + Name, + LastName, + Email, + Url, + Description, + Link, + Locale, + Nickname, + Slug, + RegisteredDate, + Roles, + Capabilities, + ExtraCapabilities, + AvatarUrls, + // meta field is omitted for now: https://github.com/Automattic/wordpress-rs/issues/57 +} + +impl SparseUserField { + pub fn as_str(&self) -> &str { + match self { + Self::Id => "id", + Self::Username => "username", + Self::Name => "name", + Self::LastName => "last_name", + Self::Email => "email", + Self::Url => "url", + Self::Description => "description", + Self::Link => "link", + Self::Locale => "locale", + Self::Nickname => "nickname", + Self::Slug => "slug", + Self::RegisteredDate => "registered_date", + Self::Roles => "roles", + Self::Capabilities => "capabilities", + Self::ExtraCapabilities => "extra_capabilities", + Self::AvatarUrls => "avatar_urls", + } + } +} diff --git a/wp_networking/Cargo.toml b/wp_networking/Cargo.toml index 51428a5e4..fff47f9cf 100644 --- a/wp_networking/Cargo.toml +++ b/wp_networking/Cargo.toml @@ -12,6 +12,8 @@ wp_api = { path = "../wp_api" } [dev-dependencies] chrono = { version = "0.4" } futures = "0.3" +rstest = { workspace = true } +rstest_reuse = { workspace = true } serde_json = { workspace = true } sqlx = { version = "0.7", features = [ "chrono", "mysql", "runtime-tokio", "tls-native-tls" ]} tokio = { version = "1.37", features = [ "full" ] } diff --git a/wp_networking/tests/test_users_immut.rs b/wp_networking/tests/test_users_immut.rs index 43e76b44f..84fbe530c 100644 --- a/wp_networking/tests/test_users_immut.rs +++ b/wp_networking/tests/test_users_immut.rs @@ -1,5 +1,8 @@ +use rstest::*; +use rstest_reuse::{self, apply, template}; use wp_api::{ - UserListParams, WPApiParamOrder, WPApiParamUsersOrderBy, WPApiParamUsersWho, WPContext, + SparseUser, SparseUserField, UserListParams, WPApiParamOrder, WPApiParamUsersOrderBy, + WPApiParamUsersWho, WPContext, }; use crate::test_helpers::{ @@ -8,6 +11,48 @@ use crate::test_helpers::{ pub mod test_helpers; +#[apply(filter_fields_cases)] +#[tokio::test] +async fn filter_users(#[case] fields: &[SparseUserField]) { + let parsed_response = api() + .filter_list_users_request(WPContext::Edit, &None, fields) + .execute() + .await + .unwrap() + .parse(wp_api::parse_filter_users_response); + assert!(parsed_response.is_ok()); + parsed_response + .unwrap() + .iter() + .for_each(|user| validate_sparse_user_fields(&user, fields)); +} + +#[apply(filter_fields_cases)] +#[tokio::test] +async fn filter_retrieve_user(#[case] fields: &[SparseUserField]) { + let user_result = api() + .filter_retrieve_user_request(FIRST_USER_ID, WPContext::Edit, fields) + .execute() + .await + .unwrap() + .parse(wp_api::parse_filter_retrieve_user_response); + assert!(user_result.is_ok()); + validate_sparse_user_fields(&user_result.unwrap(), fields); +} + +#[apply(filter_fields_cases)] +#[tokio::test] +async fn filter_retrieve_current_user(#[case] fields: &[SparseUserField]) { + let user_result = api() + .filter_retrieve_current_user_request(WPContext::Edit, fields) + .execute() + .await + .unwrap() + .parse(wp_api::parse_filter_retrieve_user_response); + assert!(user_result.is_ok()); + validate_sparse_user_fields(&user_result.unwrap(), fields); +} + #[tokio::test] async fn list_users_with_edit_context() { assert!(api() @@ -274,3 +319,77 @@ async fn test_user_list_params(params: UserListParams) { parsed_response ); } + +fn validate_sparse_user_fields(user: &SparseUser, fields: &[SparseUserField]) { + assert_eq!(user.id.is_some(), fields.contains(&SparseUserField::Id)); + assert_eq!( + user.username.is_some(), + fields.contains(&SparseUserField::Username) + ); + assert_eq!(user.name.is_some(), fields.contains(&SparseUserField::Name)); + assert_eq!( + user.last_name.is_some(), + fields.contains(&SparseUserField::LastName) + ); + assert_eq!( + user.email.is_some(), + fields.contains(&SparseUserField::Email) + ); + assert_eq!(user.url.is_some(), fields.contains(&SparseUserField::Url)); + assert_eq!( + user.description.is_some(), + fields.contains(&SparseUserField::Description) + ); + assert_eq!(user.link.is_some(), fields.contains(&SparseUserField::Link)); + assert_eq!( + user.locale.is_some(), + fields.contains(&SparseUserField::Locale) + ); + assert_eq!( + user.nickname.is_some(), + fields.contains(&SparseUserField::Nickname) + ); + assert_eq!(user.slug.is_some(), fields.contains(&SparseUserField::Slug)); + assert_eq!( + user.registered_date.is_some(), + fields.contains(&SparseUserField::RegisteredDate) + ); + assert_eq!( + user.roles.is_some(), + fields.contains(&SparseUserField::Roles) + ); + assert_eq!( + user.capabilities.is_some(), + fields.contains(&SparseUserField::Capabilities) + ); + assert_eq!( + user.extra_capabilities.is_some(), + fields.contains(&SparseUserField::ExtraCapabilities) + ); + assert_eq!( + user.avatar_urls.is_some(), + fields.contains(&SparseUserField::AvatarUrls) + ); +} + +#[template] +#[rstest] +#[case(&[SparseUserField::Id])] +#[case(&[SparseUserField::Username])] +#[case(&[SparseUserField::Name])] +#[case(&[SparseUserField::LastName])] +#[case(&[SparseUserField::Email])] +#[case(&[SparseUserField::Url])] +#[case(&[SparseUserField::Description])] +#[case(&[SparseUserField::Link])] +#[case(&[SparseUserField::Locale])] +#[case(&[SparseUserField::Nickname])] +#[case(&[SparseUserField::Slug])] +#[case(&[SparseUserField::RegisteredDate])] +#[case(&[SparseUserField::Roles])] +#[case(&[SparseUserField::Capabilities])] +#[case(&[SparseUserField::ExtraCapabilities])] +#[case(&[SparseUserField::AvatarUrls])] +#[case(&[SparseUserField::Id, SparseUserField::Name])] +#[case(&[SparseUserField::Email, SparseUserField::Nickname])] +fn filter_fields_cases(#[case] fields: &[SparseUserField]) {}