diff --git a/scripts/setup-test-site.sh b/scripts/setup-test-site.sh index e109d971..25dba48e 100755 --- a/scripts/setup-test-site.sh +++ b/scripts/setup-test-site.sh @@ -93,6 +93,7 @@ create_test_credentials () { local PASSWORD_PROTECTED_POST_ID local PASSWORD_PROTECTED_COMMENT_ID local PASSWORD_PROTECTED_COMMENT_AUTHOR + local REVISIONED_POST_ID local FIRST_POST_DATE_GMT local WORDPRESS_VERSION local INTEGRATION_TEST_CUSTOM_TEMPLATE_ID @@ -125,6 +126,13 @@ create_test_credentials () { curl --user "$ADMIN_USERNAME":"$ADMIN_PASSWORD" -H "Content-Type: application/json" -d '{"slug":"INTEGRATION_TEST_CUSTOM_TEMPLATE", "content": "Integration test custom template content"}' http://localhost/wp-json/wp/v2/templates INTEGRATION_TEST_CUSTOM_TEMPLATE_ID="twentytwentyfour//integration_test_custom_template" + # Setup a post with post revisions for integration tests + REVISIONED_POST_ID="$(wp post create --post_type=post --post_title=Revisioned_POST_FOR_INTEGRATION_TESTS --porcelain)" + for i in {1..10}; + do + curl --user "$ADMIN_USERNAME":"$ADMIN_PASSWORD" -H "Content-Type: application/json" -d "{\"content\":\"content_revision_$i\"}" "http://localhost/wp-json/wp/v2/posts/$REVISIONED_POST_ID" + done + rm -rf /app/test_credentials.json jo -p \ site_url="$SITE_URL" \ @@ -145,6 +153,7 @@ create_test_credentials () { first_post_date_gmt="$FIRST_POST_DATE_GMT" \ wordpress_core_version="\"$WORDPRESS_VERSION\"" \ integration_test_custom_template_id="$INTEGRATION_TEST_CUSTOM_TEMPLATE_ID" \ + revisioned_post_id="$REVISIONED_POST_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 c1f3c4f9..44295ff7 100644 --- a/wp_api/src/api_client.rs +++ b/wp_api/src/api_client.rs @@ -14,6 +14,7 @@ use crate::{ comments_endpoint::{CommentsRequestBuilder, CommentsRequestExecutor}, media_endpoint::{MediaRequestBuilder, MediaRequestExecutor}, plugins_endpoint::{PluginsRequestBuilder, PluginsRequestExecutor}, + post_revisions_endpoint::{PostRevisionsRequestBuilder, PostRevisionsRequestExecutor}, post_types_endpoint::{PostTypesRequestBuilder, PostTypesRequestExecutor}, posts_endpoint::{PostsRequestBuilder, PostsRequestExecutor}, search_endpoint::{SearchRequestBuilder, SearchRequestExecutor}, @@ -55,6 +56,7 @@ pub struct WpApiRequestBuilder { comments: Arc, media: Arc, plugins: Arc, + post_revisions: Arc, post_types: Arc, posts: Arc, search: Arc, @@ -80,6 +82,7 @@ impl WpApiRequestBuilder { comments, media, plugins, + post_revisions, post_types, posts, search, @@ -115,6 +118,7 @@ pub struct WpApiClient { comments: Arc, media: Arc, plugins: Arc, + post_revisions: Arc, post_types: Arc, posts: Arc, search: Arc, @@ -137,6 +141,7 @@ impl WpApiClient { comments, media, plugins, + post_revisions, post_types, posts, search, @@ -169,6 +174,7 @@ api_client_generate_endpoint_impl!(WpApi, categories); api_client_generate_endpoint_impl!(WpApi, comments); api_client_generate_endpoint_impl!(WpApi, media); api_client_generate_endpoint_impl!(WpApi, plugins); +api_client_generate_endpoint_impl!(WpApi, post_revisions); api_client_generate_endpoint_impl!(WpApi, post_types); api_client_generate_endpoint_impl!(WpApi, posts); api_client_generate_endpoint_impl!(WpApi, search); diff --git a/wp_api/src/api_error.rs b/wp_api/src/api_error.rs index 5bb76453..6f9e4018 100644 --- a/wp_api/src/api_error.rs +++ b/wp_api/src/api_error.rs @@ -274,6 +274,10 @@ pub enum WpErrorCode { PostInvalidId, #[serde(rename = "rest_post_invalid_page_number")] PostInvalidPageNumber, + #[serde(rename = "rest_post_invalid_parent")] + PostInvalidParent, + #[serde(rename = "rest_revision_invalid_offset_number")] + RevisionInvalidOffsetNumber, #[serde(rename = "rest_taxonomy_invalid")] TaxonomyInvalid, #[serde(rename = "rest_template_already_trashed")] diff --git a/wp_api/src/lib.rs b/wp_api/src/lib.rs index bf1bd05f..913fee69 100644 --- a/wp_api/src/lib.rs +++ b/wp_api/src/lib.rs @@ -20,6 +20,7 @@ pub mod media; pub mod middleware; pub mod parsed_url; pub mod plugins; +pub mod post_revisions; pub mod post_types; pub mod posts; pub mod prelude; diff --git a/wp_api/src/post_revisions.rs b/wp_api/src/post_revisions.rs new file mode 100644 index 00000000..c243f77d --- /dev/null +++ b/wp_api/src/post_revisions.rs @@ -0,0 +1,243 @@ +use crate::{ + UserId, WpApiParamOrder, + date::WpGmtDateTime, + impl_as_query_value_for_new_type, impl_as_query_value_from_to_string, + posts::PostId, + url_query::{ + AppendUrlQueryPairs, FromUrlQueryPairs, QueryPairs, QueryPairsExtension, UrlQueryPairsMap, + }, +}; +use serde::{Deserialize, Serialize}; +use std::{num::ParseIntError, str::FromStr}; +use strum_macros::IntoStaticStr; +use wp_contextual::WpContextual; + +impl_as_query_value_for_new_type!(PostRevisionId); +uniffi::custom_newtype!(PostRevisionId, i64); +#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] +pub struct PostRevisionId(pub i64); + +impl FromStr for PostRevisionId { + type Err = ParseIntError; + + fn from_str(s: &str) -> Result { + s.parse().map(Self) + } +} + +impl std::fmt::Display for PostRevisionId { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{}", self.0) + } +} + +#[derive( + Debug, + Default, + Clone, + Copy, + PartialEq, + Eq, + uniffi::Enum, + strum_macros::EnumString, + strum_macros::Display, +)] +#[strum(serialize_all = "snake_case")] +pub enum WpApiParamPostRevisionsOrderBy { + #[default] + Date, + Id, + Include, + IncludeSlugs, + Relevance, + Slug, + Title, +} + +impl_as_query_value_from_to_string!(WpApiParamPostRevisionsOrderBy); + +#[derive(Debug, Default, PartialEq, Eq, uniffi::Record)] +pub struct PostRevisionListParams { + /// 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)] + pub orderby: Option, +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, IntoStaticStr)] +enum PostRevisionListParamsField { + #[strum(serialize = "page")] + Page, + #[strum(serialize = "per_page")] + PerPage, + #[strum(serialize = "search")] + Search, + #[strum(serialize = "exclude")] + Exclude, + #[strum(serialize = "include")] + Include, + #[strum(serialize = "offset")] + Offset, + #[strum(serialize = "order")] + Order, + #[strum(serialize = "orderby")] + Orderby, +} + +impl AppendUrlQueryPairs for PostRevisionListParams { + fn append_query_pairs(&self, query_pairs_mut: &mut QueryPairs) { + query_pairs_mut + .append_option_query_value_pair(PostRevisionListParamsField::Page, self.page.as_ref()) + .append_option_query_value_pair( + PostRevisionListParamsField::PerPage, + self.per_page.as_ref(), + ) + .append_option_query_value_pair( + PostRevisionListParamsField::Search, + self.search.as_ref(), + ) + .append_vec_query_value_pair(PostRevisionListParamsField::Exclude, &self.exclude) + .append_vec_query_value_pair(PostRevisionListParamsField::Include, &self.include) + .append_option_query_value_pair( + PostRevisionListParamsField::Offset, + self.offset.as_ref(), + ) + .append_option_query_value_pair(PostRevisionListParamsField::Order, self.order.as_ref()) + .append_option_query_value_pair( + PostRevisionListParamsField::Orderby, + self.orderby.as_ref(), + ); + } +} + +impl FromUrlQueryPairs for PostRevisionListParams { + fn from_url_query_pairs(query_pairs: UrlQueryPairsMap) -> Option { + Some(Self { + page: query_pairs.get(PostRevisionListParamsField::Page), + per_page: query_pairs.get(PostRevisionListParamsField::PerPage), + search: query_pairs.get(PostRevisionListParamsField::Search), + exclude: query_pairs.get_csv(PostRevisionListParamsField::Exclude), + include: query_pairs.get_csv(PostRevisionListParamsField::Include), + offset: query_pairs.get(PostRevisionListParamsField::Offset), + order: query_pairs.get(PostRevisionListParamsField::Order), + orderby: query_pairs.get(PostRevisionListParamsField::Orderby), + }) + } + + fn supports_pagination() -> bool { + true + } +} + +#[derive(Debug, Serialize, Deserialize, uniffi::Record, WpContextual)] +pub struct SparsePostRevision { + #[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, + #[WpContext(edit, embed, view)] + #[WpContextualField] + pub excerpt: Option, + #[WpContext(edit, view)] + pub meta: Option, +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::{generate, unit_test_common::assert_expected_and_from_query_pairs}; + use rstest::*; + + #[rstest] + #[case(PostRevisionListParams::default(), "")] + #[case(generate!(PostRevisionListParams, (page, Some(2))), "page=2")] + #[case(generate!(PostRevisionListParams, (per_page, Some(2))), "per_page=2")] + #[case(generate!(PostRevisionListParams, (search, Some("foo".to_string()))), "search=foo")] + #[case(generate!(PostRevisionListParams, (exclude, vec![PostRevisionId(1), PostRevisionId(2)])), "exclude=1%2C2")] + #[case(generate!(PostRevisionListParams, (include, vec![PostRevisionId(1), PostRevisionId(2)])), "include=1%2C2")] + #[case(generate!(PostRevisionListParams, (offset, Some(2))), "offset=2")] + #[case(generate!(PostRevisionListParams, (order, Some(WpApiParamOrder::Asc))), "order=asc")] + #[case(generate!(PostRevisionListParams, (order, Some(WpApiParamOrder::Desc))), "order=desc")] + #[case(generate!(PostRevisionListParams, (orderby, Some(WpApiParamPostRevisionsOrderBy::Date))), "orderby=date")] + #[case(generate!(PostRevisionListParams, (orderby, Some(WpApiParamPostRevisionsOrderBy::Id))), "orderby=id")] + #[case(generate!(PostRevisionListParams, (orderby, Some(WpApiParamPostRevisionsOrderBy::Include))), "orderby=include")] + #[case(generate!(PostRevisionListParams, (orderby, Some(WpApiParamPostRevisionsOrderBy::IncludeSlugs))), "orderby=include_slugs")] + #[case(generate!(PostRevisionListParams, (orderby, Some(WpApiParamPostRevisionsOrderBy::Relevance))), "orderby=relevance")] + #[case(generate!(PostRevisionListParams, (orderby, Some(WpApiParamPostRevisionsOrderBy::Slug))), "orderby=slug")] + #[case(generate!(PostRevisionListParams, (orderby, Some(WpApiParamPostRevisionsOrderBy::Title))), "orderby=title")] + #[case( + post_revision_list_params_with_all_fields(), + &expected_query_pairs_for_post_revision_list_params_with_all_fields() + )] + #[trace] + fn test_post_list_query_pairs( + #[case] params: PostRevisionListParams, + #[case] expected_query: &str, + ) { + assert_expected_and_from_query_pairs(params, expected_query); + } + + fn expected_query_pairs_for_post_revision_list_params_with_all_fields() -> String { + "page=2&per_page=2&search=foo&exclude=1%2C2&include=1%2C2&offset=2&order=asc&orderby=id" + .to_string() + } + + fn post_revision_list_params_with_all_fields() -> PostRevisionListParams { + PostRevisionListParams { + page: Some(2), + per_page: Some(2), + search: Some("foo".to_string()), + exclude: vec![PostRevisionId(1), PostRevisionId(2)], + include: vec![PostRevisionId(1), PostRevisionId(2)], + offset: Some(2), + order: Some(WpApiParamOrder::Asc), + orderby: Some(WpApiParamPostRevisionsOrderBy::Id), + } + } +} diff --git a/wp_api/src/posts.rs b/wp_api/src/posts.rs index b0d4bf45..819df75b 100644 --- a/wp_api/src/posts.rs +++ b/wp_api/src/posts.rs @@ -551,8 +551,10 @@ pub struct SparsePostContent { #[WpContext(edit, view)] pub rendered: Option, #[WpContext(edit, view)] + #[WpContextualOption] pub protected: Option, #[WpContext(edit)] + #[WpContextualOption] pub block_version: Option, } @@ -563,6 +565,7 @@ pub struct SparsePostExcerpt { #[WpContext(edit, embed, view)] pub rendered: Option, #[WpContext(edit, embed, view)] + #[WpContextualOption] pub protected: Option, } diff --git a/wp_api/src/request/endpoint.rs b/wp_api/src/request/endpoint.rs index ad74d3bc..32f5933c 100644 --- a/wp_api/src/request/endpoint.rs +++ b/wp_api/src/request/endpoint.rs @@ -8,6 +8,7 @@ pub mod categories_endpoint; pub mod comments_endpoint; pub mod media_endpoint; pub mod plugins_endpoint; +pub mod post_revisions_endpoint; pub mod post_types_endpoint; pub mod posts_endpoint; pub mod search_endpoint; diff --git a/wp_api/src/request/endpoint/post_revisions_endpoint.rs b/wp_api/src/request/endpoint/post_revisions_endpoint.rs new file mode 100644 index 00000000..446c378e --- /dev/null +++ b/wp_api/src/request/endpoint/post_revisions_endpoint.rs @@ -0,0 +1,156 @@ +use super::{AsNamespace, DerivedRequest, WpNamespace}; +use crate::{ + SparseField, + post_revisions::{ + PostRevisionListParams, SparsePostRevisionFieldWithEditContext, + SparsePostRevisionFieldWithEmbedContext, SparsePostRevisionFieldWithViewContext, + }, + posts::PostId, +}; +use wp_derive_request_builder::WpDerivedRequest; + +#[derive(WpDerivedRequest)] +enum PostRevisionsRequest { + #[contextual_paged(url = "/posts//revisions", params = &PostRevisionListParams, output = Vec, filter_by = crate::post_revisions::SparsePostRevisionField)] + List, +} + +impl DerivedRequest for PostRevisionsRequest { + fn namespace() -> impl AsNamespace { + WpNamespace::WpV2 + } +} + +super::macros::default_sparse_field_implementation_from_field_name!( + SparsePostRevisionFieldWithEditContext +); +super::macros::default_sparse_field_implementation_from_field_name!( + SparsePostRevisionFieldWithEmbedContext +); +super::macros::default_sparse_field_implementation_from_field_name!( + SparsePostRevisionFieldWithViewContext +); + +#[cfg(test)] +mod tests { + use super::*; + use crate::post_revisions::{PostRevisionId, WpApiParamPostRevisionsOrderBy}; + use crate::request::endpoint::ApiUrlResolver; + use crate::{ + WpApiParamOrder, generate, + posts::PostId, + request::endpoint::tests::{fixture_wp_org_site_api_url_resolver, validate_wp_v2_endpoint}, + }; + use rstest::*; + use std::sync::Arc; + + #[rstest] + #[case(PostRevisionListParams::default(), "")] + #[case(generate!(PostRevisionListParams, (page, Some(2))), "page=2")] + #[case(generate!(PostRevisionListParams, (per_page, Some(2))), "per_page=2")] + #[case(generate!(PostRevisionListParams, (search, Some("foo".to_string()))), "search=foo")] + #[case(generate!(PostRevisionListParams, (exclude, vec![PostRevisionId(1), PostRevisionId(2)])), "exclude=1%2C2")] + #[case(generate!(PostRevisionListParams, (include, vec![PostRevisionId(1), PostRevisionId(2)])), "include=1%2C2")] + #[case(generate!(PostRevisionListParams, (offset, Some(2))), "offset=2")] + #[case(generate!(PostRevisionListParams, (order, Some(WpApiParamOrder::Asc))), "order=asc")] + #[case(generate!(PostRevisionListParams, (order, Some(WpApiParamOrder::Desc))), "order=desc")] + #[case(generate!(PostRevisionListParams, (orderby, Some(WpApiParamPostRevisionsOrderBy::Date))), "orderby=date")] + #[case(generate!(PostRevisionListParams, (orderby, Some(WpApiParamPostRevisionsOrderBy::Id))), "orderby=id")] + #[case(generate!(PostRevisionListParams, (orderby, Some(WpApiParamPostRevisionsOrderBy::Include))), "orderby=include")] + #[case(generate!(PostRevisionListParams, (orderby, Some(WpApiParamPostRevisionsOrderBy::IncludeSlugs))), "orderby=include_slugs")] + #[case(generate!(PostRevisionListParams, (orderby, Some(WpApiParamPostRevisionsOrderBy::Relevance))), "orderby=relevance")] + #[case(generate!(PostRevisionListParams, (orderby, Some(WpApiParamPostRevisionsOrderBy::Slug))), "orderby=slug")] + #[case(generate!(PostRevisionListParams, (orderby, Some(WpApiParamPostRevisionsOrderBy::Title))), "orderby=title")] + #[case( + post_revision_list_params_with_all_fields(), + &expected_query_pairs_for_post_revision_list_params_with_all_fields() + )] + fn list_posts( + endpoint: PostRevisionsRequestEndpoint, + #[case] params: PostRevisionListParams, + #[case] expected_additional_params: &str, + ) { + let post_id = PostId(777); + let expected_path = |context: &str| { + if expected_additional_params.is_empty() { + format!("/posts/{post_id}/revisions?context={}", context) + } else { + format!( + "/posts/{post_id}/revisions?context={}&{}", + context, expected_additional_params + ) + } + }; + validate_wp_v2_endpoint( + endpoint.list_with_edit_context(&post_id, ¶ms), + &expected_path("edit"), + ); + validate_wp_v2_endpoint( + endpoint.list_with_embed_context(&post_id, ¶ms), + &expected_path("embed"), + ); + validate_wp_v2_endpoint( + endpoint.list_with_view_context(&post_id, ¶ms), + &expected_path("view"), + ); + } + + #[rstest] + #[case(PostRevisionListParams::default(), &[], "/posts/777/revisions?context=edit&_fields=")] + #[case(generate!(PostRevisionListParams, (orderby, Some(WpApiParamPostRevisionsOrderBy::Id))), &[SparsePostRevisionFieldWithEditContext::Date], "/posts/777/revisions?context=edit&orderby=id&_fields=date")] + #[case(post_revision_list_params_with_all_fields(), ALL_SPARSE_POST_REVISION_FIELDS_WITH_EDIT_CONTEXT, &format!("/posts/777/revisions?context=edit&{}&{}", expected_query_pairs_for_post_revision_list_params_with_all_fields(), EXPECTED_QUERY_PAIRS_FOR_ALL_SPARSE_POST_REVISION_FIELDS_WITH_EDIT_CONTEXT))] + fn filter_list_post_revision_with_edit_context( + endpoint: PostRevisionsRequestEndpoint, + #[case] params: PostRevisionListParams, + #[case] fields: &[SparsePostRevisionFieldWithEditContext], + #[case] expected_path: &str, + ) { + validate_wp_v2_endpoint( + endpoint.filter_list_with_edit_context(&PostId(777), ¶ms, fields), + expected_path, + ); + } + + fn expected_query_pairs_for_post_revision_list_params_with_all_fields() -> String { + "page=2&per_page=2&search=foo&exclude=1%2C2&include=1%2C2&offset=2&order=asc&orderby=id" + .to_string() + } + + fn post_revision_list_params_with_all_fields() -> PostRevisionListParams { + PostRevisionListParams { + page: Some(2), + per_page: Some(2), + search: Some("foo".to_string()), + exclude: vec![PostRevisionId(1), PostRevisionId(2)], + include: vec![PostRevisionId(1), PostRevisionId(2)], + offset: Some(2), + order: Some(WpApiParamOrder::Asc), + orderby: Some(WpApiParamPostRevisionsOrderBy::Id), + } + } + + const EXPECTED_QUERY_PAIRS_FOR_ALL_SPARSE_POST_REVISION_FIELDS_WITH_EDIT_CONTEXT: &str = "_fields=id%2Cauthor%2Cdate%2Cdate_gmt%2Cmodified%2Cmodified_gmt%2Cparent%2Cslug%2Cguid%2Ctitle%2Ccontent%2Cexcerpt%2Cmeta"; + const ALL_SPARSE_POST_REVISION_FIELDS_WITH_EDIT_CONTEXT: &[SparsePostRevisionFieldWithEditContext; + 13] = &[ + SparsePostRevisionFieldWithEditContext::Id, + SparsePostRevisionFieldWithEditContext::Author, + SparsePostRevisionFieldWithEditContext::Date, + SparsePostRevisionFieldWithEditContext::DateGmt, + SparsePostRevisionFieldWithEditContext::Modified, + SparsePostRevisionFieldWithEditContext::ModifiedGmt, + SparsePostRevisionFieldWithEditContext::Parent, + SparsePostRevisionFieldWithEditContext::Slug, + SparsePostRevisionFieldWithEditContext::Guid, + SparsePostRevisionFieldWithEditContext::Title, + SparsePostRevisionFieldWithEditContext::Content, + SparsePostRevisionFieldWithEditContext::Excerpt, + SparsePostRevisionFieldWithEditContext::Meta, + ]; + + #[fixture] + fn endpoint( + fixture_wp_org_site_api_url_resolver: Arc, + ) -> PostRevisionsRequestEndpoint { + PostRevisionsRequestEndpoint::new(fixture_wp_org_site_api_url_resolver) + } +} diff --git a/wp_api_integration_tests/src/lib.rs b/wp_api_integration_tests/src/lib.rs index 8f2663a4..58c6b9ab 100644 --- a/wp_api_integration_tests/src/lib.rs +++ b/wp_api_integration_tests/src/lib.rs @@ -26,6 +26,7 @@ pub struct TestCredentials { pub first_post_date_gmt: &'static str, pub wordpress_core_version: &'static str, pub integration_test_custom_template_id: &'static str, + pub revisioned_post_id: i64, } impl TestCredentials { diff --git a/wp_api_integration_tests/tests/test_post_revisions_err.rs b/wp_api_integration_tests/tests/test_post_revisions_err.rs new file mode 100644 index 00000000..088cc73e --- /dev/null +++ b/wp_api_integration_tests/tests/test_post_revisions_err.rs @@ -0,0 +1,32 @@ +use wp_api::{post_revisions::PostRevisionListParams, posts::PostId}; +use wp_api_integration_tests::prelude::*; + +#[tokio::test] +#[parallel] +async fn list_err_post_invalid_parent() { + api_client() + .post_revisions() + .list_with_edit_context(&PostId(99999999), &PostRevisionListParams::default()) + .await + .assert_wp_error(WpErrorCode::PostInvalidParent) +} + +#[tokio::test] +#[parallel] +async fn list_err_revision_invalid_offset_number() { + api_client() + .post_revisions() + .list_with_edit_context( + &revisioned_post_id(), + &PostRevisionListParams { + offset: Some(99999999), + ..Default::default() + }, + ) + .await + .assert_wp_error(WpErrorCode::RevisionInvalidOffsetNumber) +} + +fn revisioned_post_id() -> PostId { + PostId(TestCredentials::instance().revisioned_post_id) +} diff --git a/wp_api_integration_tests/tests/test_post_revisions_immut.rs b/wp_api_integration_tests/tests/test_post_revisions_immut.rs new file mode 100644 index 00000000..93b4bac7 --- /dev/null +++ b/wp_api_integration_tests/tests/test_post_revisions_immut.rs @@ -0,0 +1,142 @@ +use wp_api::{ + post_revisions::{ + PostRevisionId, PostRevisionListParams, SparsePostRevisionFieldWithEditContext, + SparsePostRevisionFieldWithEmbedContext, SparsePostRevisionFieldWithViewContext, + WpApiParamPostRevisionsOrderBy, + }, + posts::PostId, +}; +use wp_api_integration_tests::prelude::*; + +#[tokio::test] +#[apply(list_cases)] +#[parallel] +async fn list_with_edit_context(#[case] params: PostRevisionListParams) { + api_client() + .post_revisions() + .list_with_edit_context(&revisioned_post_id(), ¶ms) + .await + .assert_response(); +} + +#[tokio::test] +#[apply(list_cases)] +#[parallel] +async fn list_with_embed_context(#[case] params: PostRevisionListParams) { + api_client() + .post_revisions() + .list_with_embed_context(&revisioned_post_id(), ¶ms) + .await + .assert_response(); +} + +#[tokio::test] +#[apply(list_cases)] +#[parallel] +async fn list_with_view_context(#[case] params: PostRevisionListParams) { + api_client() + .post_revisions() + .list_with_view_context(&revisioned_post_id(), ¶ms) + .await + .assert_response(); +} + +fn revisioned_post_id() -> PostId { + PostId(TestCredentials::instance().revisioned_post_id) +} + +#[template] +#[rstest] +#[case::default(PostRevisionListParams::default())] +#[case::page(generate!(PostRevisionListParams, (page, Some(1))))] +#[case::per_page(generate!(PostRevisionListParams, (per_page, Some(3))))] +#[case::search(generate!(PostRevisionListParams, (search, Some("foo".to_string()))))] +#[case::exclude(generate!(PostRevisionListParams, (exclude, vec![PostRevisionId(1), PostRevisionId(2)])))] +#[case::include(generate!(PostRevisionListParams, (include, vec![PostRevisionId(1)])))] +#[case::offset(generate!(PostRevisionListParams, (offset, Some(5))))] +#[case::order(generate!(PostRevisionListParams, (order, Some(WpApiParamOrder::Asc))))] +#[case::orderby(generate!(PostRevisionListParams, (orderby, Some(WpApiParamPostRevisionsOrderBy::Slug))))] +fn list_cases(#[case] params: PostRevisionListParams) {} + +mod filter { + use super::*; + + wp_api::generate_sparse_post_revision_field_with_edit_context_test_cases!(); + wp_api::generate_sparse_post_revision_field_with_embed_context_test_cases!(); + wp_api::generate_sparse_post_revision_field_with_view_context_test_cases!(); + + #[apply(sparse_post_revision_field_with_edit_context_test_cases)] + #[case(&[SparsePostRevisionFieldWithEditContext::Id, SparsePostRevisionFieldWithEditContext::Author])] + #[tokio::test] + #[parallel] + async fn filter_list_with_edit_context( + #[case] fields: &[SparsePostRevisionFieldWithEditContext], + #[values( + PostRevisionListParams::default(), + generate!(PostRevisionListParams, (exclude, vec![PostRevisionId(2), PostRevisionId(3)])), + generate!(PostRevisionListParams, (search, Some("foo".to_string()))) + )] + params: PostRevisionListParams, + ) { + api_client() + .post_revisions() + .filter_list_with_edit_context(&revisioned_post_id(), ¶ms, fields) + .await + .assert_response() + .data + .iter() + .for_each(|post| { + post.assert_that_instance_fields_nullability_match_provided_fields(fields) + }); + } + + #[apply(sparse_post_revision_field_with_embed_context_test_cases)] + #[case(&[SparsePostRevisionFieldWithEmbedContext::Id, SparsePostRevisionFieldWithEmbedContext::Author])] + #[tokio::test] + #[parallel] + async fn filter_list_with_embed_context( + #[case] fields: &[SparsePostRevisionFieldWithEmbedContext], + #[values( + PostRevisionListParams::default(), + generate!(PostRevisionListParams, (exclude, vec![PostRevisionId(2), PostRevisionId(3)])), + generate!(PostRevisionListParams, (search, Some("foo".to_string()))) + )] + params: PostRevisionListParams, + ) { + api_client() + .post_revisions() + .filter_list_with_embed_context(&revisioned_post_id(), ¶ms, fields) + .await + .assert_response() + .data + .iter() + .for_each(|post| { + post.assert_that_instance_fields_nullability_match_provided_fields(fields) + }); + } + + #[apply(sparse_post_revision_field_with_view_context_test_cases)] + #[case(&[SparsePostRevisionFieldWithViewContext::Id, SparsePostRevisionFieldWithViewContext::Author])] + #[tokio::test] + #[parallel] + async fn filter_list_with_view_context( + #[case] fields: &[SparsePostRevisionFieldWithViewContext], + #[values( + PostRevisionListParams::default(), + generate!(PostRevisionListParams, (exclude, vec![PostRevisionId(2), PostRevisionId(3)])), + generate!(PostRevisionListParams, (search, Some("foo".to_string()))) + )] + params: PostRevisionListParams, + ) { + api_client() + .post_revisions() + .filter_list_with_view_context(&revisioned_post_id(), ¶ms, fields) + .await + .assert_response() + .data + .iter() + .for_each(|post| { + post.assert_that_instance_fields_nullability_match_provided_fields(fields) + }); + } +} diff --git a/wp_api_integration_tests/tests/test_posts_err.rs b/wp_api_integration_tests/tests/test_posts_err.rs index ab8196f7..b0ce5aeb 100644 --- a/wp_api_integration_tests/tests/test_posts_err.rs +++ b/wp_api_integration_tests/tests/test_posts_err.rs @@ -9,7 +9,7 @@ use wp_api_integration_tests::prelude::*; #[tokio::test] #[parallel] -async fn create_post_err() { +async fn create_post_err_empty_content() { api_client() .posts() .create(&PostCreateParams::default())