diff --git a/native/kotlin/api/kotlin/src/integrationTest/kotlin/PostTypesEndpointTest.kt b/native/kotlin/api/kotlin/src/integrationTest/kotlin/PostTypesEndpointTest.kt index b1a5f31ca..f954e8037 100644 --- a/native/kotlin/api/kotlin/src/integrationTest/kotlin/PostTypesEndpointTest.kt +++ b/native/kotlin/api/kotlin/src/integrationTest/kotlin/PostTypesEndpointTest.kt @@ -26,7 +26,7 @@ class PostTypesEndpointTest { val postTypesPost = client.request { requestBuilder -> requestBuilder.postTypes().retrieveWithEditContext(PostType.Post) }.assertSuccessAndRetrieveData().data - assert(postTypesPost.supports[PostTypeSupports.Title]!!) + assert(postTypesPost.supports.map[PostTypeSupports.Title]!!) assertFalse(postTypesPost.capabilities[PostTypeCapabilities.EditPosts]!!.isEmpty()) } @@ -35,7 +35,7 @@ class PostTypesEndpointTest { val postTypesPost = client.request { requestBuilder -> requestBuilder.postTypes().retrieveWithEditContext(PostType.WpFontFace) }.assertSuccessAndRetrieveData().data - assertNull(postTypesPost.supports[PostTypeSupports.Author]) + assertNull(postTypesPost.supports.map[PostTypeSupports.Author]) } @Test diff --git a/native/swift/Example/Example/ExampleApp.swift b/native/swift/Example/Example/ExampleApp.swift index 3d4b372bd..fc98e3bde 100644 --- a/native/swift/Example/Example/ExampleApp.swift +++ b/native/swift/Example/Example/ExampleApp.swift @@ -128,7 +128,7 @@ struct ExampleApp: App { .postTypes .map(\.value) .filter { $0.visibility.showInNavMenus } - .filter { $0.supports.keys.contains(allOf: [.title, .author, .customFields]) } + .filter { $0.supports.map.keys.contains(allOf: [.title, .author, .customFields]) } for type in postTypes { baseData.append(RootListData(name: type.name, sequence: { diff --git a/scripts/setup-test-site.sh b/scripts/setup-test-site.sh index b5950b451..e8e9ee32b 100755 --- a/scripts/setup-test-site.sh +++ b/scripts/setup-test-site.sh @@ -136,6 +136,20 @@ create_nav_menu_item_autosave() { curl --silent --user "$ADMIN_USERNAME":"$ADMIN_PASSWORD" -H "Content-Type: application/json" -d "{\"title\":\"nav_menu_item_autosave_$autosave_number\", \"author\": $ADMIN_USER_ID}" "http://localhost/wp-json/wp/v2/menu-items/$nav_menu_item_id/autosaves" } +create_navigation_revision() { + local revision_number="$1" + local navigation_id="$2" + + curl --silent --user "$ADMIN_USERNAME":"$ADMIN_PASSWORD" -H "Content-Type: application/json" -d "{\"content\":\"content_revision_$revision_number\", \"author\": $ADMIN_USER_ID}" "http://localhost/wp-json/wp/v2/navigation/$navigation_id" > /dev/null +} + +create_navigation_autosave() { + local autosave_number="$1" + local navigation_id="$2" + + curl --silent --user "$ADMIN_USERNAME":"$ADMIN_PASSWORD" -H "Content-Type: application/json" -d "{\"content\":\"content_autosave_$autosave_number\", \"author\": $ADMIN_USER_ID}" "http://localhost/wp-json/wp/v2/navigation/$navigation_id/autosaves" +} + create_test_credentials () { local SITE_URL local ADMIN_USERNAME @@ -241,6 +255,22 @@ create_test_credentials () { NAVIGATION_RESPONSE="$(curl --silent --user "$ADMIN_USERNAME":"$ADMIN_PASSWORD" -H "Content-Type: application/json" -d '{"title":"Integration Test Navigation","content":"","status":"publish"}' http://localhost/wp-json/wp/v2/navigation)" NAVIGATION_ID="$(echo "$NAVIGATION_RESPONSE" | jq -r '.id')" + echo "Setting up navigation with 10 revisions for integration tests.." + # Create revisions for the navigation + for i in {1..10}; + do + create_navigation_revision "$i" "$NAVIGATION_ID" + done + # Generating revisions don't return an id, but since we just created the `NAVIGATION_ID`, we can use it to calculate the revision id + REVISION_ID_FOR_NAVIGATION_ID=$((NAVIGATION_ID + 1)) + + echo "Setting up navigation with autosave for integration tests.." + # Create navigation as author user to enable proper autosave behavior (same requirement as posts/pages) + AUTOSAVED_NAVIGATION_ID="$(wp post create --post_type=wp_navigation --post_title='Autosaved Navigation FOR INTEGRATION TESTS' --post_content='' --post_status=publish --post_author="$AUTHOR_USER_ID" --porcelain)" + # Create autosave as admin user (different from navigation author) and capture its ID + AUTOSAVE_NAVIGATION_RESPONSE="$(create_navigation_autosave "1" "$AUTOSAVED_NAVIGATION_ID")" + AUTOSAVE_ID_FOR_AUTOSAVED_NAVIGATION_ID="$(echo "$AUTOSAVE_NAVIGATION_RESPONSE" | jq -r '.id')" + rm -rf /app/test_credentials.json jo -p \ site_url="$SITE_URL" \ @@ -279,6 +309,9 @@ create_test_credentials () { nav_menu_item_id="$NAV_MENU_ITEM_ID" \ autosave_id_for_nav_menu_item_id="$AUTOSAVE_ID_FOR_NAV_MENU_ITEM_ID" \ navigation_id="$NAVIGATION_ID" \ + revision_id_for_navigation_id="$REVISION_ID_FOR_NAVIGATION_ID" \ + autosaved_navigation_id="$AUTOSAVED_NAVIGATION_ID" \ + autosave_id_for_autosaved_navigation_id="$AUTOSAVE_ID_FOR_AUTOSAVED_NAVIGATION_ID" \ > /app/test_credentials.json } create_test_credentials diff --git a/wp_api/src/api_client.rs b/wp_api/src/api_client.rs index dfd553096..0501789cf 100644 --- a/wp_api/src/api_client.rs +++ b/wp_api/src/api_client.rs @@ -19,6 +19,12 @@ use crate::{ }, nav_menu_items_endpoint::{NavMenuItemsRequestBuilder, NavMenuItemsRequestExecutor}, nav_menus_endpoint::{NavMenusRequestBuilder, NavMenusRequestExecutor}, + navigation_autosaves_endpoint::{ + NavigationAutosavesRequestBuilder, NavigationAutosavesRequestExecutor, + }, + navigation_revisions_endpoint::{ + NavigationRevisionsRequestBuilder, NavigationRevisionsRequestExecutor, + }, navigations_endpoint::{NavigationsRequestBuilder, NavigationsRequestExecutor}, plugins_endpoint::{PluginsRequestBuilder, PluginsRequestExecutor}, post_autosaves_endpoint::{AutosavesRequestBuilder, AutosavesRequestExecutor}, @@ -44,11 +50,6 @@ use crate::{ }; use std::sync::Arc; -#[derive(uniffi::Object)] -struct UniffiWpApiRequestBuilder { - inner: WpApiRequestBuilder, -} - pub struct WpApiRequestBuilder { api_root: Arc, application_passwords: Arc, @@ -59,6 +60,8 @@ pub struct WpApiRequestBuilder { nav_menu_item_autosaves: Arc, nav_menu_items: Arc, nav_menus: Arc, + navigation_autosaves: Arc, + navigation_revisions: Arc, navigations: Arc, plugins: Arc, post_revisions: Arc, @@ -95,6 +98,8 @@ impl WpApiRequestBuilder { nav_menu_item_autosaves, nav_menu_items, nav_menus, + navigation_autosaves, + navigation_revisions, navigations, plugins, post_revisions, @@ -141,6 +146,8 @@ pub struct WpApiClient { nav_menu_item_autosaves: Arc, nav_menu_items: Arc, nav_menus: Arc, + navigation_autosaves: Arc, + navigation_revisions: Arc, navigations: Arc, plugins: Arc, post_revisions: Arc, @@ -174,6 +181,8 @@ impl WpApiClient { nav_menu_item_autosaves, nav_menu_items, nav_menus, + navigation_autosaves, + navigation_revisions, navigations, plugins, post_revisions, @@ -217,6 +226,8 @@ api_client_generate_endpoint_impl!(WpApi, menu_locations); api_client_generate_endpoint_impl!(WpApi, nav_menu_item_autosaves); api_client_generate_endpoint_impl!(WpApi, nav_menu_items); api_client_generate_endpoint_impl!(WpApi, nav_menus); +api_client_generate_endpoint_impl!(WpApi, navigation_autosaves); +api_client_generate_endpoint_impl!(WpApi, navigation_revisions); api_client_generate_endpoint_impl!(WpApi, navigations); api_client_generate_endpoint_impl!(WpApi, plugins); api_client_generate_endpoint_impl!(WpApi, post_revisions); @@ -239,14 +250,6 @@ api_client_generate_endpoint_impl!(WpApi, wp_site_health_tests); macro_rules! api_client_generate_endpoint_impl { ($client_name_prefix: ident, $feature:ident) => { paste::paste! { - #[uniffi::export] - - impl [] { - fn $feature(&self) -> Arc<[<$feature:camel RequestBuilder>]> { - self.inner.$feature.clone() - } - } - impl [<$client_name_prefix RequestBuilder>] { pub fn $feature(&self) -> &[<$feature:camel RequestBuilder>] { self.$feature.as_ref() diff --git a/wp_api/src/jetpack/client.rs b/wp_api/src/jetpack/client.rs index 20e6bda4e..9ee567a86 100644 --- a/wp_api/src/jetpack/client.rs +++ b/wp_api/src/jetpack/client.rs @@ -8,32 +8,6 @@ use crate::{ }; use std::sync::Arc; -#[derive(uniffi::Object)] -struct UniffiJetpackApiRequestBuilder { - inner: JetpackApiRequestBuilder, -} - -#[uniffi::export] -impl UniffiJetpackApiRequestBuilder { - #[uniffi::constructor] - pub fn new( - api_url_resolver: Arc, - auth_provider: Arc, - ) -> Self { - Self { - inner: JetpackApiRequestBuilder::new(api_url_resolver, auth_provider), - } - } - - #[uniffi::constructor] - pub fn with_api_root_url( - api_root_url: Arc, - auth_provider: Arc, - ) -> Self { - Self::new(jetpack_api_url_resolver(api_root_url), auth_provider) - } -} - pub struct JetpackApiRequestBuilder { connection: Arc, } diff --git a/wp_api/src/lib.rs b/wp_api/src/lib.rs index 88e238b73..0aeb4a789 100644 --- a/wp_api/src/lib.rs +++ b/wp_api/src/lib.rs @@ -22,6 +22,7 @@ pub mod middleware; pub mod nav_menu_item_revisions; pub mod nav_menu_items; pub mod nav_menus; +pub mod navigation_revisions; pub mod navigations; pub mod parsed_url; pub mod plugins; diff --git a/wp_api/src/navigation_revisions.rs b/wp_api/src/navigation_revisions.rs new file mode 100644 index 000000000..2119222a0 --- /dev/null +++ b/wp_api/src/navigation_revisions.rs @@ -0,0 +1,111 @@ +use crate::{ + UserId, WpApiParamOrder, + date::WpGmtDateTime, + impl_as_query_value_from_to_string, + navigations::NavigationId, + url_query::{ + AppendUrlQueryPairs, FromUrlQueryPairs, QueryPairs, QueryPairsExtension, UrlQueryPairsMap, + }, + wp_content_i64_id, +}; +use serde::{Deserialize, Serialize}; +use wp_contextual::WpContextual; +use wp_derive::WpDeriveParamsField; + +wp_content_i64_id!(NavigationRevisionId); + +#[derive( + Debug, + Default, + Clone, + Copy, + PartialEq, + Eq, + uniffi::Enum, + strum_macros::EnumString, + strum_macros::Display, +)] +#[strum(serialize_all = "snake_case")] +pub enum WpApiParamNavigationRevisionsOrderBy { + #[default] + Date, + Id, + Include, + IncludeSlugs, + Relevance, + Slug, + Title, +} + +impl_as_query_value_from_to_string!(WpApiParamNavigationRevisionsOrderBy); + +#[derive(Debug, Default, PartialEq, Eq, uniffi::Record, WpDeriveParamsField)] +#[supports_pagination(true)] +pub struct NavigationRevisionListParams { + /// Current page of the collection. + /// Default: `1` + #[uniffi(default = None)] + pub page: Option, + /// Maximum number of items to be returned in result set. + #[uniffi(default = None)] + pub per_page: Option, + /// Limit results to those matching a string. + #[uniffi(default = None)] + pub search: Option, + /// Ensure result set excludes specific IDs. + #[uniffi(default = [])] + pub exclude: Vec, + /// Limit result set to specific IDs. + #[uniffi(default = [])] + pub include: Vec, + /// Offset the result set by a specific number of items. + #[uniffi(default = None)] + pub offset: Option, + /// Order sort attribute ascending or descending. + /// Default: desc + /// One of: asc, desc + #[uniffi(default = None)] + pub order: Option, + /// Sort collection by object attribute. + /// Default: date + /// One of: date, id, include, relevance, slug, include_slugs, title + #[uniffi(default = None)] + #[field_name("orderby")] + pub orderby: Option, +} + +#[derive(Debug, Serialize, Deserialize, uniffi::Record, WpContextual)] +pub struct SparseNavigationRevision { + #[WpContext(edit, embed, view)] + pub id: Option, + #[WpContext(edit, embed, view)] + pub author: Option, + #[WpContext(edit, embed, view)] + pub date: Option, + #[WpContext(edit, view)] + pub date_gmt: Option, + #[WpContext(edit, view)] + pub modified: Option, + #[WpContext(edit, view)] + pub modified_gmt: Option, + #[WpContext(edit, embed, view)] + pub parent: Option, + #[WpContext(edit, embed, view)] + pub slug: Option, + #[WpContext(edit, view)] + #[WpContextualField] + pub guid: Option, + #[WpContext(edit, embed, view)] + #[WpContextualField] + pub title: Option, + #[WpContext(edit, view)] + #[WpContextualField] + pub content: Option, + // meta field omitted for now +} + +#[derive(Debug, Serialize, Deserialize, uniffi::Record)] +pub struct NavigationRevisionDeleteResponse { + pub deleted: bool, + pub previous: NavigationRevisionWithEditContext, +} diff --git a/wp_api/src/post_revisions.rs b/wp_api/src/post_revisions.rs index 418025d3f..842d55119 100644 --- a/wp_api/src/post_revisions.rs +++ b/wp_api/src/post_revisions.rs @@ -105,6 +105,7 @@ pub struct SparseAnyPostRevision { #[WpContextualOption] pub excerpt: Option, #[WpContext(edit, view)] + #[WpContextualOption] pub meta: Option, } diff --git a/wp_api/src/post_types.rs b/wp_api/src/post_types.rs index 54181d930..b905d5c50 100644 --- a/wp_api/src/post_types.rs +++ b/wp_api/src/post_types.rs @@ -3,6 +3,7 @@ use serde::{Deserialize, Serialize}; use std::collections::HashMap; use std::str::FromStr; use wp_contextual::WpContextual; +use wp_serde_helper::deserialize_empty_array_or_hashmap; #[derive( Debug, @@ -74,7 +75,7 @@ pub struct SparsePostTypeDetails { #[WpContext(edit, embed, view)] pub slug: Option, #[WpContext(edit)] - pub supports: Option>, + pub supports: Option, #[WpContext(edit, view)] pub has_archive: Option, #[WpContext(edit, view)] @@ -90,6 +91,15 @@ pub struct SparsePostTypeDetails { pub icon: Option, } +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, uniffi::Record)] +#[serde(transparent)] +pub struct PostTypeSupportsMap { + #[serde(deserialize_with = "deserialize_empty_array_or_hashmap")] + #[serde(flatten)] + #[serde(rename = "supports")] + pub map: HashMap, +} + #[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize, uniffi::Record)] pub struct PostTypeLabels { pub name: String, diff --git a/wp_api/src/posts.rs b/wp_api/src/posts.rs index e2a888e13..4724a1f67 100644 --- a/wp_api/src/posts.rs +++ b/wp_api/src/posts.rs @@ -11,7 +11,7 @@ use crate::{ }; use serde::{Deserialize, Serialize}; use wp_contextual::WpContextual; -use wp_derive::WpDeriveParamsField; +use wp_derive::{WpDeriveParamsField, WpDeserialize}; use wp_serde_helper::{deserialize_from_string_of_json_array, serialize_as_json_string}; #[derive( @@ -474,11 +474,11 @@ pub struct SparsePostExcerpt { pub protected: Option, } -#[derive(Debug, Serialize, Deserialize, uniffi::Record)] +#[derive(Debug, Serialize, WpDeserialize, uniffi::Record)] pub struct PostMeta { #[serde(deserialize_with = "deserialize_from_string_of_json_array")] #[serde(serialize_with = "serialize_as_json_string")] - pub footnotes: Vec, + pub footnotes: Option>, } #[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize, uniffi::Record)] diff --git a/wp_api/src/request/endpoint.rs b/wp_api/src/request/endpoint.rs index 62cd1a954..f97fe19af 100644 --- a/wp_api/src/request/endpoint.rs +++ b/wp_api/src/request/endpoint.rs @@ -11,6 +11,8 @@ pub mod menu_locations_endpoint; pub mod nav_menu_item_autosaves_endpoint; pub mod nav_menu_items_endpoint; pub mod nav_menus_endpoint; +pub mod navigation_autosaves_endpoint; +pub mod navigation_revisions_endpoint; pub mod navigations_endpoint; pub mod plugins_endpoint; pub mod post_autosaves_endpoint; diff --git a/wp_api/src/request/endpoint/media_endpoint.rs b/wp_api/src/request/endpoint/media_endpoint.rs index 72844035b..d5b507b2d 100644 --- a/wp_api/src/request/endpoint/media_endpoint.rs +++ b/wp_api/src/request/endpoint/media_endpoint.rs @@ -154,7 +154,6 @@ impl NetworkRequestAccessor for MediaUploadRequest { } } -#[uniffi::export] impl MediaRequestBuilder { pub fn create( &self, diff --git a/wp_api/src/request/endpoint/navigation_autosaves_endpoint.rs b/wp_api/src/request/endpoint/navigation_autosaves_endpoint.rs new file mode 100644 index 000000000..e4ed3879f --- /dev/null +++ b/wp_api/src/request/endpoint/navigation_autosaves_endpoint.rs @@ -0,0 +1,19 @@ +use super::{AsNamespace, DerivedRequest, WpNamespace}; +use crate::{navigation_revisions::NavigationRevisionId, navigations::NavigationId}; +use wp_derive_request_builder::WpDerivedRequest; + +#[derive(WpDerivedRequest)] +enum NavigationAutosavesRequest { + #[contextual_get(url = "/navigation//autosaves", output = Vec, filter_by = crate::navigation_revisions::SparseNavigationRevisionField)] + List, + #[contextual_get(url = "/navigation//autosaves/", output = crate::navigation_revisions::SparseNavigationRevision, filter_by = crate::navigation_revisions::SparseNavigationRevisionField)] + Retrieve, + #[post(url = "/navigation//autosaves", params = &crate::navigations::NavigationCreateParams, output = crate::navigation_revisions::NavigationRevisionWithEditContext)] + Create, +} + +impl DerivedRequest for NavigationAutosavesRequest { + fn namespace() -> impl AsNamespace { + WpNamespace::WpV2 + } +} diff --git a/wp_api/src/request/endpoint/navigation_revisions_endpoint.rs b/wp_api/src/request/endpoint/navigation_revisions_endpoint.rs new file mode 100644 index 000000000..c87d6e79a --- /dev/null +++ b/wp_api/src/request/endpoint/navigation_revisions_endpoint.rs @@ -0,0 +1,29 @@ +use super::{AsNamespace, DerivedRequest, WpNamespace}; +use crate::{ + navigation_revisions::{NavigationRevisionId, NavigationRevisionListParams}, + navigations::NavigationId, +}; +use wp_derive_request_builder::WpDerivedRequest; + +#[derive(WpDerivedRequest)] +enum NavigationRevisionsRequest { + #[contextual_paged(url = "/navigation//revisions", params = &NavigationRevisionListParams, output = Vec, filter_by = crate::navigation_revisions::SparseNavigationRevisionField)] + List, + #[contextual_get(url = "/navigation//revisions/", output = crate::navigation_revisions::SparseNavigationRevision, filter_by = crate::navigation_revisions::SparseNavigationRevisionField)] + Retrieve, + #[delete(url = "/navigation//revisions/", output = crate::navigation_revisions::NavigationRevisionDeleteResponse)] + Delete, +} + +impl DerivedRequest for NavigationRevisionsRequest { + fn namespace() -> impl AsNamespace { + WpNamespace::WpV2 + } + + fn additional_query_pairs(&self) -> Vec<(&str, String)> { + match self { + NavigationRevisionsRequest::Delete => vec![("force", "true".to_string())], + _ => vec![], + } + } +} diff --git a/wp_api/src/templates.rs b/wp_api/src/templates.rs index 77800abf7..08610a9ea 100644 --- a/wp_api/src/templates.rs +++ b/wp_api/src/templates.rs @@ -94,6 +94,7 @@ pub struct SparseTemplate { #[WpContext(edit, embed, view)] pub slug: Option, #[WpContext(edit, embed, view)] + #[WpContextualOption] pub theme: Option, #[serde(rename = "type")] #[WpContext(edit, embed, view)] diff --git a/wp_api/src/wp_com/client.rs b/wp_api/src/wp_com/client.rs index af40faac9..b5250c6f7 100644 --- a/wp_api/src/wp_com/client.rs +++ b/wp_api/src/wp_com/client.rs @@ -20,21 +20,6 @@ use crate::{ }; use std::sync::Arc; -#[derive(uniffi::Object)] -struct UniffiWpComApiRequestBuilder { - inner: WpComApiRequestBuilder, -} - -#[uniffi::export] -impl UniffiWpComApiRequestBuilder { - #[uniffi::constructor] - pub fn new(auth_provider: Arc) -> Self { - Self { - inner: WpComApiRequestBuilder::new(auth_provider), - } - } -} - pub struct WpComApiRequestBuilder { followers: Arc, jetpack_connection: Arc, diff --git a/wp_api_integration_tests/src/lib.rs b/wp_api_integration_tests/src/lib.rs index bcaaf78c7..51a9c23de 100644 --- a/wp_api_integration_tests/src/lib.rs +++ b/wp_api_integration_tests/src/lib.rs @@ -48,6 +48,9 @@ pub struct TestCredentials { pub nav_menu_item_id: i64, pub autosave_id_for_nav_menu_item_id: i64, pub navigation_id: i64, + pub revision_id_for_navigation_id: i64, + pub autosaved_navigation_id: i64, + pub autosave_id_for_autosaved_navigation_id: i64, } impl TestCredentials { diff --git a/wp_api_integration_tests/tests/test_navigation_autosaves_err.rs b/wp_api_integration_tests/tests/test_navigation_autosaves_err.rs new file mode 100644 index 000000000..48a3e7d93 --- /dev/null +++ b/wp_api_integration_tests/tests/test_navigation_autosaves_err.rs @@ -0,0 +1,92 @@ +use wp_api::{ + navigation_revisions::NavigationRevisionId, + navigations::{NavigationCreateParams, NavigationId}, +}; +use wp_api_integration_tests::prelude::*; + +#[tokio::test] +#[parallel] +async fn list_err_post_invalid_parent() { + api_client() + .navigation_autosaves() + .list_with_edit_context(&NavigationId(99999999)) + .await + .assert_wp_error(WpErrorCode::PostInvalidParent) +} + +#[tokio::test] +#[parallel] +async fn list_err_cannot_read_as_subscriber() { + api_client_as_subscriber() + .navigation_autosaves() + .list_with_edit_context(&autosaved_navigation_id()) + .await + .assert_wp_error(WpErrorCode::CannotRead) +} + +#[tokio::test] +#[parallel] +async fn retrieve_err_post_invalid_parent() { + api_client() + .navigation_autosaves() + .retrieve_with_edit_context(&NavigationId(99999999), &NavigationRevisionId(1)) + .await + .assert_wp_error(WpErrorCode::PostInvalidParent) +} + +#[tokio::test] +#[parallel] +async fn retrieve_err_post_no_autosave() { + api_client() + .navigation_autosaves() + .retrieve_with_edit_context( + &NavigationId(TestCredentials::instance().navigation_id), + &NavigationRevisionId(1), + ) + .await + .assert_wp_error(WpErrorCode::PostNoAutosave) +} + +#[tokio::test] +#[parallel] +async fn retrieve_err_cannot_read_as_subscriber() { + api_client_as_subscriber() + .navigation_autosaves() + .retrieve_with_edit_context( + &autosaved_navigation_id(), + &autosave_id_for_autosaved_navigation_id(), + ) + .await + .assert_wp_error(WpErrorCode::CannotRead) +} + +#[tokio::test] +#[parallel] +async fn create_err_post_invalid_id() { + api_client() + .navigation_autosaves() + .create(&NavigationId(99999999), &NavigationCreateParams::default()) + .await + .assert_wp_error(WpErrorCode::PostInvalidId) +} + +#[tokio::test] +#[parallel] +async fn create_err_cannot_edit_as_subscriber() { + api_client_as_subscriber() + .navigation_autosaves() + .create( + &autosaved_navigation_id(), + &NavigationCreateParams::default(), + ) + .await + .assert_wp_error(WpErrorCode::CannotEdit) +} + +fn autosaved_navigation_id() -> NavigationId { + NavigationId(TestCredentials::instance().autosaved_navigation_id) +} + +fn autosave_id_for_autosaved_navigation_id() -> NavigationRevisionId { + NavigationRevisionId(TestCredentials::instance().autosave_id_for_autosaved_navigation_id) +} diff --git a/wp_api_integration_tests/tests/test_navigation_autosaves_immut.rs b/wp_api_integration_tests/tests/test_navigation_autosaves_immut.rs new file mode 100644 index 000000000..51e12836d --- /dev/null +++ b/wp_api_integration_tests/tests/test_navigation_autosaves_immut.rs @@ -0,0 +1,211 @@ +use wp_api::{ + navigation_revisions::{ + NavigationRevisionId, SparseNavigationRevisionFieldWithEditContext, + SparseNavigationRevisionFieldWithEmbedContext, + SparseNavigationRevisionFieldWithViewContext, + }, + navigations::NavigationId, +}; +use wp_api_integration_tests::prelude::*; + +#[tokio::test] +#[parallel] +async fn list_with_edit_context() { + api_client() + .navigation_autosaves() + .list_with_edit_context(&autosaved_navigation_id()) + .await + .assert_response(); +} + +#[tokio::test] +#[parallel] +async fn list_with_embed_context() { + api_client() + .navigation_autosaves() + .list_with_embed_context(&autosaved_navigation_id()) + .await + .assert_response(); +} + +#[tokio::test] +#[parallel] +async fn list_with_view_context() { + api_client() + .navigation_autosaves() + .list_with_view_context(&autosaved_navigation_id()) + .await + .assert_response(); +} + +#[tokio::test] +#[parallel] +async fn retrieve_with_edit_context() { + api_client() + .navigation_autosaves() + .retrieve_with_edit_context( + &autosaved_navigation_id(), + &autosave_id_for_autosaved_navigation_id(), + ) + .await + .assert_response(); +} + +#[tokio::test] +#[parallel] +async fn retrieve_with_embed_context() { + api_client() + .navigation_autosaves() + .retrieve_with_embed_context( + &autosaved_navigation_id(), + &autosave_id_for_autosaved_navigation_id(), + ) + .await + .assert_response(); +} + +#[tokio::test] +#[parallel] +async fn retrieve_with_view_context() { + api_client() + .navigation_autosaves() + .retrieve_with_view_context( + &autosaved_navigation_id(), + &autosave_id_for_autosaved_navigation_id(), + ) + .await + .assert_response(); +} + +fn autosaved_navigation_id() -> NavigationId { + NavigationId(TestCredentials::instance().autosaved_navigation_id) +} + +fn autosave_id_for_autosaved_navigation_id() -> NavigationRevisionId { + NavigationRevisionId(TestCredentials::instance().autosave_id_for_autosaved_navigation_id) +} + +mod filter { + use super::*; + + wp_api::generate_sparse_navigation_revision_field_with_edit_context_test_cases!(); + wp_api::generate_sparse_navigation_revision_field_with_embed_context_test_cases!(); + wp_api::generate_sparse_navigation_revision_field_with_view_context_test_cases!(); + + #[apply(sparse_navigation_revision_field_with_edit_context_test_cases)] + #[case(&[SparseNavigationRevisionFieldWithEditContext::Id, SparseNavigationRevisionFieldWithEditContext::Author])] + #[tokio::test] + #[parallel] + async fn filter_list_with_edit_context( + #[case] fields: &[SparseNavigationRevisionFieldWithEditContext], + ) { + api_client() + .navigation_autosaves() + .filter_list_with_edit_context(&autosaved_navigation_id(), fields) + .await + .assert_response() + .data + .iter() + .for_each(|autosave| { + autosave.assert_that_instance_fields_nullability_match_provided_fields(fields) + }); + } + + #[apply(sparse_navigation_revision_field_with_embed_context_test_cases)] + #[case(&[SparseNavigationRevisionFieldWithEmbedContext::Id, SparseNavigationRevisionFieldWithEmbedContext::Author])] + #[tokio::test] + #[parallel] + async fn filter_list_with_embed_context( + #[case] fields: &[SparseNavigationRevisionFieldWithEmbedContext], + ) { + api_client() + .navigation_autosaves() + .filter_list_with_embed_context(&autosaved_navigation_id(), fields) + .await + .assert_response() + .data + .iter() + .for_each(|autosave| { + autosave.assert_that_instance_fields_nullability_match_provided_fields(fields) + }); + } + + #[apply(sparse_navigation_revision_field_with_view_context_test_cases)] + #[case(&[SparseNavigationRevisionFieldWithViewContext::Id, SparseNavigationRevisionFieldWithViewContext::Author])] + #[tokio::test] + #[parallel] + async fn filter_list_with_view_context( + #[case] fields: &[SparseNavigationRevisionFieldWithViewContext], + ) { + api_client() + .navigation_autosaves() + .filter_list_with_view_context(&autosaved_navigation_id(), fields) + .await + .assert_response() + .data + .iter() + .for_each(|autosave| { + autosave.assert_that_instance_fields_nullability_match_provided_fields(fields) + }); + } + + #[apply(sparse_navigation_revision_field_with_edit_context_test_cases)] + #[case(&[SparseNavigationRevisionFieldWithEditContext::Id, SparseNavigationRevisionFieldWithEditContext::Author])] + #[tokio::test] + #[parallel] + async fn filter_retrieve_with_edit_context( + #[case] fields: &[SparseNavigationRevisionFieldWithEditContext], + ) { + api_client() + .navigation_autosaves() + .filter_retrieve_with_edit_context( + &autosaved_navigation_id(), + &autosave_id_for_autosaved_navigation_id(), + fields, + ) + .await + .assert_response() + .data + .assert_that_instance_fields_nullability_match_provided_fields(fields); + } + + #[apply(sparse_navigation_revision_field_with_embed_context_test_cases)] + #[case(&[SparseNavigationRevisionFieldWithEmbedContext::Id, SparseNavigationRevisionFieldWithEmbedContext::Author])] + #[tokio::test] + #[parallel] + async fn filter_retrieve_with_embed_context( + #[case] fields: &[SparseNavigationRevisionFieldWithEmbedContext], + ) { + api_client() + .navigation_autosaves() + .filter_retrieve_with_embed_context( + &autosaved_navigation_id(), + &autosave_id_for_autosaved_navigation_id(), + fields, + ) + .await + .assert_response() + .data + .assert_that_instance_fields_nullability_match_provided_fields(fields); + } + + #[apply(sparse_navigation_revision_field_with_view_context_test_cases)] + #[case(&[SparseNavigationRevisionFieldWithViewContext::Id, SparseNavigationRevisionFieldWithViewContext::Author])] + #[tokio::test] + #[parallel] + async fn filter_retrieve_with_view_context( + #[case] fields: &[SparseNavigationRevisionFieldWithViewContext], + ) { + api_client() + .navigation_autosaves() + .filter_retrieve_with_view_context( + &autosaved_navigation_id(), + &autosave_id_for_autosaved_navigation_id(), + fields, + ) + .await + .assert_response() + .data + .assert_that_instance_fields_nullability_match_provided_fields(fields); + } +} diff --git a/wp_api_integration_tests/tests/test_navigation_autosaves_mut.rs b/wp_api_integration_tests/tests/test_navigation_autosaves_mut.rs new file mode 100644 index 000000000..ca400b2fd --- /dev/null +++ b/wp_api_integration_tests/tests/test_navigation_autosaves_mut.rs @@ -0,0 +1,29 @@ +use wp_api::navigations::{NavigationCreateParams, NavigationId}; +use wp_api_integration_tests::prelude::*; + +#[tokio::test] +async fn create_autosave() { + let title = "Test Autosave Navigation Title".to_string(); + let content = + "Test autosave navigation content".to_string(); + let params = NavigationCreateParams { + title: Some(title.clone()), + content: Some(content.clone()), + ..Default::default() + }; + + let autosave = api_client() + .navigation_autosaves() + .create(&autosaved_navigation_id(), ¶ms) + .await + .assert_response() + .data; + + // Verify the autosave was created successfully + assert_eq!(autosave.title.raw, Some(title)); + assert_eq!(autosave.content.raw, Some(content)); +} + +fn autosaved_navigation_id() -> NavigationId { + NavigationId(TestCredentials::instance().autosaved_navigation_id) +} diff --git a/wp_api_integration_tests/tests/test_navigation_revisions_err.rs b/wp_api_integration_tests/tests/test_navigation_revisions_err.rs new file mode 100644 index 000000000..cd8228096 --- /dev/null +++ b/wp_api_integration_tests/tests/test_navigation_revisions_err.rs @@ -0,0 +1,164 @@ +use wp_api::{ + navigation_revisions::{ + NavigationRevisionId, NavigationRevisionListParams, WpApiParamNavigationRevisionsOrderBy, + }, + navigations::NavigationId, +}; +use wp_api_integration_tests::prelude::*; + +#[tokio::test] +#[parallel] +async fn list_err_post_invalid_parent() { + api_client() + .navigation_revisions() + .list_with_edit_context( + &NavigationId(99999999), + &NavigationRevisionListParams::default(), + ) + .await + .assert_wp_error(WpErrorCode::PostInvalidParent) +} + +#[tokio::test] +#[parallel] +async fn list_err_revision_invalid_offset_number() { + api_client() + .navigation_revisions() + .list_with_edit_context( + &navigation_id(), + &NavigationRevisionListParams { + offset: Some(99999999), + ..Default::default() + }, + ) + .await + .assert_wp_error(WpErrorCode::RevisionInvalidOffsetNumber) +} + +#[tokio::test] +#[parallel] +async fn list_err_revision_invalid_page_number() { + api_client() + .navigation_revisions() + .list_with_edit_context( + &navigation_id(), + &NavigationRevisionListParams { + page: Some(99999999), + ..Default::default() + }, + ) + .await + .assert_wp_error(WpErrorCode::RevisionInvalidPageNumber) +} + +#[tokio::test] +#[parallel] +async fn list_err_cannot_read_as_subscriber() { + api_client_as_subscriber() + .navigation_revisions() + .list_with_edit_context(&navigation_id(), &NavigationRevisionListParams::default()) + .await + .assert_wp_error(WpErrorCode::CannotRead) +} + +#[tokio::test] +#[parallel] +async fn list_err_no_search_term_defined() { + api_client() + .navigation_revisions() + .list_with_edit_context( + &navigation_id(), + &NavigationRevisionListParams { + orderby: Some(WpApiParamNavigationRevisionsOrderBy::Relevance), + search: None, + ..Default::default() + }, + ) + .await + .assert_wp_error(WpErrorCode::NoSearchTermDefined) +} + +#[tokio::test] +#[parallel] +async fn list_err_orderby_include_missing_include() { + api_client() + .navigation_revisions() + .list_with_edit_context( + &navigation_id(), + &NavigationRevisionListParams { + orderby: Some(WpApiParamNavigationRevisionsOrderBy::Include), + include: vec![], + ..Default::default() + }, + ) + .await + .assert_wp_error(WpErrorCode::OrderbyIncludeMissingInclude) +} + +#[tokio::test] +#[parallel] +async fn retrieve_err_post_invalid_parent() { + api_client() + .navigation_revisions() + .retrieve_with_edit_context(&NavigationId(99999999), &revision_id_for_navigation_id()) + .await + .assert_wp_error(WpErrorCode::PostInvalidParent) +} + +#[tokio::test] +#[parallel] +async fn retrieve_err_post_invalid_id() { + api_client() + .navigation_revisions() + .retrieve_with_edit_context(&navigation_id(), &NavigationRevisionId(99999999)) + .await + .assert_wp_error(WpErrorCode::PostInvalidId) +} + +#[tokio::test] +#[parallel] +async fn retrieve_err_cannot_read_as_subscriber() { + api_client_as_subscriber() + .navigation_revisions() + .retrieve_with_edit_context(&navigation_id(), &revision_id_for_navigation_id()) + .await + .assert_wp_error(WpErrorCode::CannotRead) +} + +#[tokio::test] +#[parallel] +async fn delete_err_cannot_delete_as_subscriber() { + api_client_as_subscriber() + .navigation_revisions() + .delete(&navigation_id(), &revision_id_for_navigation_id()) + .await + .assert_wp_error(WpErrorCode::CannotDelete) +} + +#[tokio::test] +#[parallel] +async fn delete_err_post_invalid_parent() { + api_client() + .navigation_revisions() + .delete(&NavigationId(99999999), &revision_id_for_navigation_id()) + .await + .assert_wp_error(WpErrorCode::PostInvalidParent) +} + +#[tokio::test] +#[parallel] +async fn delete_err_post_invalid_id() { + api_client() + .navigation_revisions() + .delete(&navigation_id(), &NavigationRevisionId(99999999)) + .await + .assert_wp_error(WpErrorCode::PostInvalidId) +} + +fn navigation_id() -> NavigationId { + NavigationId(TestCredentials::instance().navigation_id) +} + +fn revision_id_for_navigation_id() -> NavigationRevisionId { + NavigationRevisionId(TestCredentials::instance().revision_id_for_navigation_id) +} diff --git a/wp_api_integration_tests/tests/test_navigation_revisions_immut.rs b/wp_api_integration_tests/tests/test_navigation_revisions_immut.rs new file mode 100644 index 000000000..101dbe517 --- /dev/null +++ b/wp_api_integration_tests/tests/test_navigation_revisions_immut.rs @@ -0,0 +1,237 @@ +use wp_api::{ + navigation_revisions::{ + NavigationRevisionId, NavigationRevisionListParams, + SparseNavigationRevisionFieldWithEditContext, + SparseNavigationRevisionFieldWithEmbedContext, + SparseNavigationRevisionFieldWithViewContext, WpApiParamNavigationRevisionsOrderBy, + }, + navigations::NavigationId, +}; +use wp_api_integration_tests::prelude::*; + +#[tokio::test] +#[apply(list_cases)] +#[parallel] +async fn list_with_edit_context(#[case] params: NavigationRevisionListParams) { + api_client() + .navigation_revisions() + .list_with_edit_context(&navigation_id(), ¶ms) + .await + .assert_response(); +} + +#[tokio::test] +#[apply(list_cases)] +#[parallel] +async fn list_with_embed_context(#[case] params: NavigationRevisionListParams) { + api_client() + .navigation_revisions() + .list_with_embed_context(&navigation_id(), ¶ms) + .await + .assert_response(); +} + +#[tokio::test] +#[apply(list_cases)] +#[parallel] +async fn list_with_view_context(#[case] params: NavigationRevisionListParams) { + api_client() + .navigation_revisions() + .list_with_view_context(&navigation_id(), ¶ms) + .await + .assert_response(); +} + +#[tokio::test] +#[parallel] +async fn retrieve_with_edit_context() { + api_client() + .navigation_revisions() + .retrieve_with_edit_context(&navigation_id(), &revision_id_for_navigation_id()) + .await + .assert_response(); +} + +#[tokio::test] +#[parallel] +async fn retrieve_with_embed_context() { + api_client() + .navigation_revisions() + .retrieve_with_embed_context(&navigation_id(), &revision_id_for_navigation_id()) + .await + .assert_response(); +} + +#[tokio::test] +#[parallel] +async fn retrieve_with_view_context() { + api_client() + .navigation_revisions() + .retrieve_with_view_context(&navigation_id(), &revision_id_for_navigation_id()) + .await + .assert_response(); +} + +fn navigation_id() -> NavigationId { + NavigationId(TestCredentials::instance().navigation_id) +} + +fn revision_id_for_navigation_id() -> NavigationRevisionId { + NavigationRevisionId(TestCredentials::instance().revision_id_for_navigation_id) +} + +#[template] +#[rstest] +#[case::default(NavigationRevisionListParams::default())] +#[case::page(generate!(NavigationRevisionListParams, (page, Some(1))))] +#[case::per_page(generate!(NavigationRevisionListParams, (per_page, Some(3))))] +#[case::search(generate!(NavigationRevisionListParams, (search, Some("foo".to_string()))))] +#[case::exclude(generate!(NavigationRevisionListParams, (exclude, vec![NavigationRevisionId(1), NavigationRevisionId(2)])))] +#[case::include(generate!(NavigationRevisionListParams, (include, vec![NavigationRevisionId(1)])))] +#[case::offset(generate!(NavigationRevisionListParams, (offset, Some(5))))] +#[case::order(generate!(NavigationRevisionListParams, (order, Some(WpApiParamOrder::Asc))))] +#[case::orderby(generate!(NavigationRevisionListParams, (orderby, Some(WpApiParamNavigationRevisionsOrderBy::Slug))))] +fn list_cases(#[case] params: NavigationRevisionListParams) {} + +mod filter { + use super::*; + + wp_api::generate_sparse_navigation_revision_field_with_edit_context_test_cases!(); + wp_api::generate_sparse_navigation_revision_field_with_embed_context_test_cases!(); + wp_api::generate_sparse_navigation_revision_field_with_view_context_test_cases!(); + + #[apply(sparse_navigation_revision_field_with_edit_context_test_cases)] + #[case(&[SparseNavigationRevisionFieldWithEditContext::Id, SparseNavigationRevisionFieldWithEditContext::Author])] + #[tokio::test] + #[parallel] + async fn filter_list_with_edit_context( + #[case] fields: &[SparseNavigationRevisionFieldWithEditContext], + #[values( + NavigationRevisionListParams::default(), + generate!(NavigationRevisionListParams, (exclude, vec![NavigationRevisionId(2), NavigationRevisionId(3)])), + generate!(NavigationRevisionListParams, (search, Some("foo".to_string()))) + )] + params: NavigationRevisionListParams, + ) { + api_client() + .navigation_revisions() + .filter_list_with_edit_context(&navigation_id(), ¶ms, fields) + .await + .assert_response() + .data + .iter() + .for_each(|post| { + post.assert_that_instance_fields_nullability_match_provided_fields(fields) + }); + } + + #[apply(sparse_navigation_revision_field_with_embed_context_test_cases)] + #[case(&[SparseNavigationRevisionFieldWithEmbedContext::Id, SparseNavigationRevisionFieldWithEmbedContext::Author])] + #[tokio::test] + #[parallel] + async fn filter_list_with_embed_context( + #[case] fields: &[SparseNavigationRevisionFieldWithEmbedContext], + #[values( + NavigationRevisionListParams::default(), + generate!(NavigationRevisionListParams, (exclude, vec![NavigationRevisionId(2), NavigationRevisionId(3)])), + generate!(NavigationRevisionListParams, (search, Some("foo".to_string()))) + )] + params: NavigationRevisionListParams, + ) { + api_client() + .navigation_revisions() + .filter_list_with_embed_context(&navigation_id(), ¶ms, fields) + .await + .assert_response() + .data + .iter() + .for_each(|post| { + post.assert_that_instance_fields_nullability_match_provided_fields(fields) + }); + } + + #[apply(sparse_navigation_revision_field_with_view_context_test_cases)] + #[case(&[SparseNavigationRevisionFieldWithViewContext::Id, SparseNavigationRevisionFieldWithViewContext::Author])] + #[tokio::test] + #[parallel] + async fn filter_list_with_view_context( + #[case] fields: &[SparseNavigationRevisionFieldWithViewContext], + #[values( + NavigationRevisionListParams::default(), + generate!(NavigationRevisionListParams, (exclude, vec![NavigationRevisionId(2), NavigationRevisionId(3)])), + generate!(NavigationRevisionListParams, (search, Some("foo".to_string()))) + )] + params: NavigationRevisionListParams, + ) { + api_client() + .navigation_revisions() + .filter_list_with_view_context(&navigation_id(), ¶ms, fields) + .await + .assert_response() + .data + .iter() + .for_each(|post| { + post.assert_that_instance_fields_nullability_match_provided_fields(fields) + }); + } + + #[apply(sparse_navigation_revision_field_with_edit_context_test_cases)] + #[case(&[SparseNavigationRevisionFieldWithEditContext::Id, SparseNavigationRevisionFieldWithEditContext::Author])] + #[tokio::test] + #[parallel] + async fn filter_retrieve_with_edit_context( + #[case] fields: &[SparseNavigationRevisionFieldWithEditContext], + ) { + api_client() + .navigation_revisions() + .filter_retrieve_with_edit_context( + &navigation_id(), + &revision_id_for_navigation_id(), + fields, + ) + .await + .assert_response() + .data + .assert_that_instance_fields_nullability_match_provided_fields(fields); + } + + #[apply(sparse_navigation_revision_field_with_embed_context_test_cases)] + #[case(&[SparseNavigationRevisionFieldWithEmbedContext::Id, SparseNavigationRevisionFieldWithEmbedContext::Author])] + #[tokio::test] + #[parallel] + async fn filter_retrieve_with_embed_context( + #[case] fields: &[SparseNavigationRevisionFieldWithEmbedContext], + ) { + api_client() + .navigation_revisions() + .filter_retrieve_with_embed_context( + &navigation_id(), + &revision_id_for_navigation_id(), + fields, + ) + .await + .assert_response() + .data + .assert_that_instance_fields_nullability_match_provided_fields(fields); + } + + #[apply(sparse_navigation_revision_field_with_view_context_test_cases)] + #[case(&[SparseNavigationRevisionFieldWithViewContext::Id, SparseNavigationRevisionFieldWithViewContext::Author])] + #[tokio::test] + #[parallel] + async fn filter_retrieve_with_view_context( + #[case] fields: &[SparseNavigationRevisionFieldWithViewContext], + ) { + api_client() + .navigation_revisions() + .filter_retrieve_with_view_context( + &navigation_id(), + &revision_id_for_navigation_id(), + fields, + ) + .await + .assert_response() + .data + .assert_that_instance_fields_nullability_match_provided_fields(fields); + } +} diff --git a/wp_api_integration_tests/tests/test_navigation_revisions_mut.rs b/wp_api_integration_tests/tests/test_navigation_revisions_mut.rs new file mode 100644 index 000000000..525837546 --- /dev/null +++ b/wp_api_integration_tests/tests/test_navigation_revisions_mut.rs @@ -0,0 +1,31 @@ +use wp_api::{navigation_revisions::NavigationRevisionId, navigations::NavigationId}; +use wp_api_integration_tests::prelude::*; + +#[tokio::test] +#[serial] +async fn delete_navigation_revision() { + let revision_id = revision_id_for_navigation_id(); + let revision_delete_response = api_client() + .navigation_revisions() + .delete(&navigation_id(), &revision_id) + .await; + + assert!( + revision_delete_response.is_ok(), + "{revision_delete_response:#?}" + ); + + let delete_response = revision_delete_response.unwrap().data; + assert!(delete_response.deleted); + assert_eq!(delete_response.previous.id, revision_id); + + RestoreServer::db().await; +} + +fn navigation_id() -> NavigationId { + NavigationId(TestCredentials::instance().navigation_id) +} + +fn revision_id_for_navigation_id() -> NavigationRevisionId { + NavigationRevisionId(TestCredentials::instance().revision_id_for_navigation_id) +} diff --git a/wp_api_integration_tests/tests/test_pages_mut.rs b/wp_api_integration_tests/tests/test_pages_mut.rs index 43dc12f73..b107001d7 100644 --- a/wp_api_integration_tests/tests/test_pages_mut.rs +++ b/wp_api_integration_tests/tests/test_pages_mut.rs @@ -30,16 +30,17 @@ async fn create_page_with_title_and_meta() { &PostCreateParams { title: Some("foo".to_string()), meta: Some(PostMeta { - footnotes: vec![PostFootnote { + footnotes: Some(vec![PostFootnote { id: "bar".to_string(), content: "baz".to_string(), - }], + }]), }), ..Default::default() }, |created_page, page_from_wp_cli| { let meta = created_page.meta.unwrap(); - let footnote = meta.footnotes.first().unwrap(); + let footnotes = meta.footnotes.unwrap(); + let footnote = footnotes.first().unwrap(); assert_eq!(created_page.title.raw, Some("foo".to_string())); assert_eq!(page_from_wp_cli.title, "foo"); assert_eq!(footnote.id, "bar"); @@ -345,14 +346,15 @@ generate_update_test!( update_meta_to_add_footnote, meta, PostMeta { - footnotes: vec![PostFootnote { + footnotes: Some(vec![PostFootnote { id: "foo".to_string(), content: "bar".to_string() - }] + }]) }, |updated_page, _| { let meta = updated_page.meta.unwrap(); - let footnote = meta.footnotes.first().unwrap(); + let footnotes = meta.footnotes.unwrap(); + let footnote = footnotes.first().unwrap(); assert_eq!(footnote.id, "foo"); assert_eq!(footnote.content, "bar"); } diff --git a/wp_api_integration_tests/tests/test_post_types_immut.rs b/wp_api_integration_tests/tests/test_post_types_immut.rs index aa2248fea..140cba347 100644 --- a/wp_api_integration_tests/tests/test_post_types_immut.rs +++ b/wp_api_integration_tests/tests/test_post_types_immut.rs @@ -93,7 +93,7 @@ async fn retrieve_post_types_with_edit_context( // post types might not support `Title` in which case it's perfectly fine to completely // remove this assertion. assert_eq!( - post_type.supports.get(&PostTypeSupports::Title), + post_type.supports.map.get(&PostTypeSupports::Title), Some(true).as_ref() ); // All post types in our current testing sites have `EditPost` capability, so we use this diff --git a/wp_api_integration_tests/tests/test_posts_mut.rs b/wp_api_integration_tests/tests/test_posts_mut.rs index aef378423..43db6465e 100644 --- a/wp_api_integration_tests/tests/test_posts_mut.rs +++ b/wp_api_integration_tests/tests/test_posts_mut.rs @@ -32,16 +32,17 @@ async fn create_post_with_title_and_meta() { &PostCreateParams { title: Some("foo".to_string()), meta: Some(PostMeta { - footnotes: vec![PostFootnote { + footnotes: Some(vec![PostFootnote { id: "bar".to_string(), content: "baz".to_string(), - }], + }]), }), ..Default::default() }, |created_post, post_from_wp_cli| { let meta = created_post.meta.unwrap(); - let footnote = meta.footnotes.first().unwrap(); + let footnotes = meta.footnotes.unwrap(); + let footnote = footnotes.first().unwrap(); assert_eq!(created_post.title.raw, Some("foo".to_string())); assert_eq!(post_from_wp_cli.title, "foo"); assert_eq!(footnote.id, "bar"); @@ -313,14 +314,15 @@ generate_update_test!( update_meta_to_add_footnote, meta, PostMeta { - footnotes: vec![PostFootnote { + footnotes: Some(vec![PostFootnote { id: "foo".to_string(), content: "bar".to_string() - }] + }]) }, |updated_post, _| { let meta = updated_post.meta.unwrap(); - let footnote = meta.footnotes.first().unwrap(); + let footnotes = meta.footnotes.unwrap(); + let footnote = footnotes.first().unwrap(); assert_eq!(footnote.id, "foo"); assert_eq!(footnote.content, "bar"); } diff --git a/wp_api_integration_tests/tests/test_templates_mut.rs b/wp_api_integration_tests/tests/test_templates_mut.rs index d0008228f..fe69429a5 100644 --- a/wp_api_integration_tests/tests/test_templates_mut.rs +++ b/wp_api_integration_tests/tests/test_templates_mut.rs @@ -52,7 +52,7 @@ async fn create_template_with_slug_title_and_theme() { test_create_template(¶ms, |created_template| { assert_slug(&created_template); assert_title(&created_template); - assert_eq!(created_template.theme, theme); + assert_eq!(created_template.theme, Some(theme.to_string())); }) .await; } diff --git a/wp_derive_request_builder/src/generate.rs b/wp_derive_request_builder/src/generate.rs index 81a2eb056..4ba0b5600 100644 --- a/wp_derive_request_builder/src/generate.rs +++ b/wp_derive_request_builder/src/generate.rs @@ -296,7 +296,6 @@ fn generate_request_builder(config: &Config, parsed_enum: &ParsedEnum) -> TokenS }); quote! { - #[derive(uniffi::Object)] pub struct #generated_request_builder_ident { endpoint: #generated_endpoint_ident, inner: #static_inner_request_builder_type, @@ -309,7 +308,6 @@ fn generate_request_builder(config: &Config, parsed_enum: &ParsedEnum) -> TokenS } } } - #[uniffi::export] impl #generated_request_builder_ident { #(#functions)* } diff --git a/wp_serde_helper/src/lib.rs b/wp_serde_helper/src/lib.rs index bebf82ee5..e88d87e57 100644 --- a/wp_serde_helper/src/lib.rs +++ b/wp_serde_helper/src/lib.rs @@ -24,7 +24,7 @@ where struct StringOfJsonArrayVisitor(PhantomData); impl de::Visitor<'_> for StringOfJsonArrayVisitor { - type Value = Vec; + type Value = Option>; fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("a string containing json array") @@ -35,14 +35,16 @@ impl de::Visitor<'_> for StringOfJsonArrayVisitor { E: de::Error, { if v.is_empty() { - Ok(vec![]) + Ok(None) } else { serde_json::from_str(v).map_err(E::custom) } } } -pub fn deserialize_from_string_of_json_array<'de, T, D>(deserializer: D) -> Result, D::Error> +pub fn deserialize_from_string_of_json_array<'de, T, D>( + deserializer: D, +) -> Result>, D::Error> where T: DeserializeOwned, D: de::Deserializer<'de>,