Skip to content

Commit 53db86b

Browse files
authored
List & retrieve /posts/<post_id>/autosaves endpoint (#865)
1 parent d509da8 commit 53db86b

File tree

6 files changed

+317
-1
lines changed

6 files changed

+317
-1
lines changed

scripts/setup-test-site.sh

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,20 @@ wp theme activate twentytwentyfour
8585
wp comment trash 22
8686
wp comment spam 23
8787

88+
create_post_revision() {
89+
local revision_number="$1"
90+
local post_id="$2"
91+
92+
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/posts/$post_id" > /dev/null
93+
}
94+
95+
create_post_autosave() {
96+
local autosave_number="$1"
97+
local post_id="$2"
98+
99+
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/posts/$post_id/autosaves"
100+
}
101+
88102
create_test_credentials () {
89103
local SITE_URL
90104
local ADMIN_USERNAME
@@ -98,6 +112,8 @@ create_test_credentials () {
98112
local PASSWORD_PROTECTED_COMMENT_ID
99113
local PASSWORD_PROTECTED_COMMENT_AUTHOR
100114
local REVISIONED_POST_ID
115+
local AUTOSAVED_POST_ID
116+
local AUTOSAVE_ID_FOR_AUTOSAVED_POST_ID
101117
local FIRST_POST_DATE_GMT
102118
local WORDPRESS_VERSION
103119
local INTEGRATION_TEST_CUSTOM_TEMPLATE_ID
@@ -133,13 +149,26 @@ create_test_credentials () {
133149

134150
echo "Setting up a post with 10 revisions for integration tests.."
135151
REVISIONED_POST_ID="$(wp post create --post_type=post --post_title=Revisioned_POST_FOR_INTEGRATION_TESTS --porcelain)"
152+
# Create revisions
136153
for i in {1..10};
137154
do
138-
curl --silent --user "$ADMIN_USERNAME":"$ADMIN_PASSWORD" -H "Content-Type: application/json" -d "{\"content\":\"content_revision_$i\", \"author\": $ADMIN_USER_ID}" "http://localhost/wp-json/wp/v2/posts/$REVISIONED_POST_ID" > /dev/null
155+
create_post_revision "$i" "$REVISIONED_POST_ID"
139156
done
140157
# Generating revisions don't return an id, but since we just created the `REVISIONED_POST_ID`, we can use it to calculate the revision id
141158
REVISION_ID_FOR_REVISIONED_POST_ID=$((REVISIONED_POST_ID + 1))
142159

160+
echo "Setting up a post with autosave for integration tests.."
161+
# Autosaves require special setup: WordPress only creates separate autosave revisions when
162+
# the autosave is made by a different user than the post author. If the same user creates
163+
# an autosave, WordPress just updates the original post instead of creating a revision.
164+
# See: https://github.com/WordPress/WordPress/blob/c90da2b67323e36b0390a9efa95f2b4bbb3be31b/wp-includes/rest-api/endpoints/class-wp-rest-autosaves-controller.php#L235-L244
165+
# Create post as author user to enable proper autosave behavior
166+
AUTHOR_USER_ID="$(wp user get "$AUTHOR_USERNAME" --field=ID)"
167+
AUTOSAVED_POST_ID="$(wp post create --post_type=post --post_title=Autosaved_POST_FOR_INTEGRATION_TESTS --post_author="$AUTHOR_USER_ID" --porcelain)"
168+
# Create autosave as admin user (different from post author) and capture its ID
169+
AUTOSAVE_RESPONSE="$(create_post_autosave "1" "$AUTOSAVED_POST_ID")"
170+
AUTOSAVE_ID_FOR_AUTOSAVED_POST_ID="$(echo "$AUTOSAVE_RESPONSE" | jq -r '.id')"
171+
143172
rm -rf /app/test_credentials.json
144173
jo -p \
145174
site_url="$SITE_URL" \
@@ -162,6 +191,8 @@ create_test_credentials () {
162191
integration_test_custom_template_id="$INTEGRATION_TEST_CUSTOM_TEMPLATE_ID" \
163192
revisioned_post_id="$REVISIONED_POST_ID" \
164193
revision_id_for_revisioned_post_id="$REVISION_ID_FOR_REVISIONED_POST_ID" \
194+
autosaved_post_id="$AUTOSAVED_POST_ID" \
195+
autosave_id_for_autosaved_post_id="$AUTOSAVE_ID_FOR_AUTOSAVED_POST_ID" \
165196
> /app/test_credentials.json
166197
}
167198
create_test_credentials

wp_api/src/api_client.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ use crate::{
1010
application_passwords_endpoint::{
1111
ApplicationPasswordsRequestBuilder, ApplicationPasswordsRequestExecutor,
1212
},
13+
autosaves_endpoint::{AutosavesRequestBuilder, AutosavesRequestExecutor},
1314
categories_endpoint::{CategoriesRequestBuilder, CategoriesRequestExecutor},
1415
comments_endpoint::{CommentsRequestBuilder, CommentsRequestExecutor},
1516
media_endpoint::{MediaRequestBuilder, MediaRequestExecutor},
@@ -54,6 +55,7 @@ impl UniffiWpApiRequestBuilder {
5455

5556
pub struct WpApiRequestBuilder {
5657
application_passwords: Arc<ApplicationPasswordsRequestBuilder>,
58+
autosaves: Arc<AutosavesRequestBuilder>,
5759
categories: Arc<CategoriesRequestBuilder>,
5860
comments: Arc<CommentsRequestBuilder>,
5961
media: Arc<MediaRequestBuilder>,
@@ -82,6 +84,7 @@ impl WpApiRequestBuilder {
8284
api_url_resolver,
8385
auth_provider;
8486
application_passwords,
87+
autosaves,
8588
categories,
8689
comments,
8790
media,
@@ -120,6 +123,7 @@ impl UniffiWpApiClient {
120123

121124
pub struct WpApiClient {
122125
application_passwords: Arc<ApplicationPasswordsRequestExecutor>,
126+
autosaves: Arc<AutosavesRequestExecutor>,
123127
categories: Arc<CategoriesRequestExecutor>,
124128
comments: Arc<CommentsRequestExecutor>,
125129
media: Arc<MediaRequestExecutor>,
@@ -145,6 +149,7 @@ impl WpApiClient {
145149
api_url_resolver,
146150
delegate;
147151
application_passwords,
152+
autosaves,
148153
categories,
149154
comments,
150155
media,
@@ -180,6 +185,7 @@ pub trait IsWpApiClientDelegate {
180185
}
181186

182187
api_client_generate_endpoint_impl!(WpApi, application_passwords);
188+
api_client_generate_endpoint_impl!(WpApi, autosaves);
183189
api_client_generate_endpoint_impl!(WpApi, categories);
184190
api_client_generate_endpoint_impl!(WpApi, comments);
185191
api_client_generate_endpoint_impl!(WpApi, media);

wp_api/src/request/endpoint.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ use strum_macros::EnumIter;
44
use url::Url;
55

66
pub mod application_passwords_endpoint;
7+
pub mod autosaves_endpoint;
78
pub mod categories_endpoint;
89
pub mod comments_endpoint;
910
pub mod media_endpoint;
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
use super::{AsNamespace, DerivedRequest, WpNamespace};
2+
use crate::{post_revisions::PostRevisionId, posts::PostId};
3+
use wp_derive_request_builder::WpDerivedRequest;
4+
5+
#[derive(WpDerivedRequest)]
6+
enum AutosavesRequest {
7+
#[contextual_get(url = "/posts/<post_id>/autosaves", output = Vec<crate::post_revisions::SparsePostRevision>, filter_by = crate::post_revisions::SparsePostRevisionField)]
8+
List,
9+
#[contextual_get(url = "/posts/<post_id>/autosaves/<post_revision_id>", output = crate::post_revisions::SparsePostRevision, filter_by = crate::post_revisions::SparsePostRevisionField)]
10+
Retrieve,
11+
}
12+
13+
impl DerivedRequest for AutosavesRequest {
14+
fn namespace() -> impl AsNamespace {
15+
WpNamespace::WpV2
16+
}
17+
}
18+
19+
#[cfg(test)]
20+
mod tests {
21+
use super::*;
22+
use crate::request::endpoint::ApiUrlResolver;
23+
use crate::{
24+
posts::PostId,
25+
request::endpoint::tests::{fixture_wp_org_site_api_url_resolver, validate_wp_v2_endpoint},
26+
};
27+
use rstest::*;
28+
use std::sync::Arc;
29+
30+
#[rstest]
31+
fn list_autosaves(endpoint: AutosavesRequestEndpoint) {
32+
let post_id = PostId(777);
33+
let expected_path = |context: &str| format!("/posts/{post_id}/autosaves?context={context}");
34+
validate_wp_v2_endpoint(
35+
endpoint.list_with_edit_context(&post_id),
36+
&expected_path("edit"),
37+
);
38+
validate_wp_v2_endpoint(
39+
endpoint.list_with_embed_context(&post_id),
40+
&expected_path("embed"),
41+
);
42+
validate_wp_v2_endpoint(
43+
endpoint.list_with_view_context(&post_id),
44+
&expected_path("view"),
45+
);
46+
}
47+
48+
#[rstest]
49+
fn retrieve_autosave(endpoint: AutosavesRequestEndpoint) {
50+
let post_id = PostId(777);
51+
let post_revision_id = PostRevisionId(888);
52+
let expected_path = |context: &str| {
53+
format!("/posts/{post_id}/autosaves/{post_revision_id}?context={context}")
54+
};
55+
validate_wp_v2_endpoint(
56+
endpoint.retrieve_with_edit_context(&post_id, &post_revision_id),
57+
&expected_path("edit"),
58+
);
59+
validate_wp_v2_endpoint(
60+
endpoint.retrieve_with_embed_context(&post_id, &post_revision_id),
61+
&expected_path("embed"),
62+
);
63+
validate_wp_v2_endpoint(
64+
endpoint.retrieve_with_view_context(&post_id, &post_revision_id),
65+
&expected_path("view"),
66+
);
67+
}
68+
69+
#[fixture]
70+
fn endpoint(
71+
fixture_wp_org_site_api_url_resolver: Arc<dyn ApiUrlResolver>,
72+
) -> AutosavesRequestEndpoint {
73+
AutosavesRequestEndpoint::new(fixture_wp_org_site_api_url_resolver)
74+
}
75+
}

wp_api_integration_tests/src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ pub struct TestCredentials {
2929
pub integration_test_custom_template_id: &'static str,
3030
pub revisioned_post_id: i64,
3131
pub revision_id_for_revisioned_post_id: i64,
32+
pub autosaved_post_id: i64,
33+
pub autosave_id_for_autosaved_post_id: i64,
3234
}
3335

3436
impl TestCredentials {

0 commit comments

Comments
 (0)