Skip to content

Commit 24452bd

Browse files
authored
Delete /templates endpoint (#721)
* Delete `/templates` endpoint * Setup a custom template in test site for integration tests * Introduce `BoolOrWpGmtDateTime` for `SparseTemplate::modified` * Add a trash template integration test
1 parent 36043a3 commit 24452bd

File tree

7 files changed

+127
-1
lines changed

7 files changed

+127
-1
lines changed

scripts/setup-test-site.sh

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@ create_test_credentials () {
9595
local PASSWORD_PROTECTED_COMMENT_AUTHOR
9696
local FIRST_POST_DATE_GMT
9797
local WORDPRESS_VERSION
98+
local INTEGRATION_TEST_CUSTOM_TEMPLATE_ID
9899
SITE_URL="http://localhost"
99100
ADMIN_USERNAME="[email protected]"
100101
ADMIN_PASSWORD="$(wp user application-password create [email protected] test --porcelain)"
@@ -115,9 +116,15 @@ create_test_credentials () {
115116

116117
WORDPRESS_VERSION="$(wp core version)"
117118

119+
INTEGRATION_TEST_CUSTOM_TEMPLATE_SLUG="integration_test_custom_template"
120+
118121
# Trash the post
119122
wp post delete "$TRASHED_POST_ID"
120123

124+
# Create a custom template
125+
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
126+
INTEGRATION_TEST_CUSTOM_TEMPLATE_ID="twentytwentyfour//integration_test_custom_template"
127+
121128
rm -rf /app/test_credentials.json
122129
jo -p \
123130
site_url="$SITE_URL" \
@@ -137,6 +144,7 @@ create_test_credentials () {
137144
trashed_post_id="$TRASHED_POST_ID" \
138145
first_post_date_gmt="$FIRST_POST_DATE_GMT" \
139146
wordpress_core_version="\"$WORDPRESS_VERSION\"" \
147+
integration_test_custom_template_id="$INTEGRATION_TEST_CUSTOM_TEMPLATE_ID" \
140148
> /app/test_credentials.json
141149
}
142150
create_test_credentials

wp_api/src/api_error.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -260,6 +260,8 @@ pub enum WpErrorCode {
260260
InvalidField,
261261
#[serde(rename = "rest_invalid_param")]
262262
InvalidParam,
263+
#[serde(rename = "rest_invalid_template")]
264+
InvalidTemplate,
263265
#[serde(rename = "rest_no_search_term_defined")]
264266
NoSearchTermDefined,
265267
#[serde(rename = "rest_orderby_include_missing_include")]
@@ -274,6 +276,10 @@ pub enum WpErrorCode {
274276
PostInvalidPageNumber,
275277
#[serde(rename = "rest_taxonomy_invalid")]
276278
TaxonomyInvalid,
279+
#[serde(rename = "rest_template_already_trashed")]
280+
TemplateAlreadyTrashed,
281+
#[serde(rename = "rest_template_not_found")]
282+
TemplateNotFound,
277283
#[serde(rename = "rest_term_invalid")]
278284
TermInvalid,
279285
#[serde(rename = "rest_theme_not_found")]

wp_api/src/request/endpoint/templates_endpoint.rs

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,21 @@ enum TemplatesRequest {
1212
List,
1313
#[contextual_get(url = "/templates/<template_id>", output = crate::templates::SparseTemplate, filter_by = crate::templates::SparseTemplateField)]
1414
Retrieve,
15+
#[delete(url = "/templates/<template_id>", output = crate::templates::TemplateDeleteResponse)]
16+
Delete,
17+
#[delete(url = "/templates/<template_id>", output = crate::templates::TemplateWithEditContext)]
18+
Trash,
1519
}
1620

1721
impl DerivedRequest for TemplatesRequest {
22+
fn additional_query_pairs(&self) -> Vec<(&str, String)> {
23+
match self {
24+
TemplatesRequest::Delete => vec![("force", true.to_string())],
25+
TemplatesRequest::Trash => vec![("force", false.to_string())],
26+
_ => vec![],
27+
}
28+
}
29+
1830
fn namespace() -> impl AsNamespace {
1931
WpNamespace::WpV2
2032
}
@@ -163,6 +175,22 @@ mod tests {
163175
);
164176
}
165177

178+
#[rstest]
179+
fn delete_template(endpoint: TemplatesRequestEndpoint) {
180+
validate_wp_v2_endpoint(
181+
endpoint.delete(&TemplateId("foo".to_string())),
182+
"/templates/foo?force=true",
183+
);
184+
}
185+
186+
#[rstest]
187+
fn trash_template(endpoint: TemplatesRequestEndpoint) {
188+
validate_wp_v2_endpoint(
189+
endpoint.trash(&TemplateId("foo".to_string())),
190+
"/templates/foo?force=false",
191+
);
192+
}
193+
166194
const EXPECTED_QUERY_PAIRS_FOR_TEMPLATE_LIST_PARAMS_WITH_ALL_FIELDS: &str =
167195
"wp_id=2&area=header&post_type=page";
168196
fn template_list_params_with_all_fields() -> TemplateListParams {

wp_api/src/templates.rs

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ pub enum TemplateStatus {
4545
Private,
4646
#[default]
4747
Publish,
48+
Trash,
4849
#[serde(untagged)]
4950
#[strum(default)]
5051
Custom(String),
@@ -160,7 +161,12 @@ pub struct SparseTemplate {
160161
#[WpContext(edit, embed, view)]
161162
pub author: Option<UserId>,
162163
#[WpContext(edit, view)]
163-
pub modified: Option<bool>,
164+
#[WpContextualOption]
165+
#[serde(
166+
default,
167+
deserialize_with = "wp_serde_helper::deserialize_false_or_string"
168+
)]
169+
pub modified: Option<String>,
164170
#[WpContext(edit, view, embed)]
165171
pub is_custom: Option<bool>,
166172
#[WpContext(edit, view, embed)]
@@ -196,3 +202,9 @@ pub struct SparseTemplateTitle {
196202
pub raw: Option<String>,
197203
pub rendered: Option<String>,
198204
}
205+
206+
#[derive(Debug, Serialize, Deserialize, uniffi::Record)]
207+
pub struct TemplateDeleteResponse {
208+
pub deleted: bool,
209+
pub previous: TemplateWithEditContext,
210+
}

wp_api_integration_tests/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ pub struct TestCredentials {
4040
pub trashed_post_id: i64,
4141
pub first_post_date_gmt: &'static str,
4242
pub wordpress_core_version: &'static str,
43+
pub integration_test_custom_template_id: &'static str,
4344
}
4445

4546
impl TestCredentials {
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
use serial_test::parallel;
2+
use wp_api::{WpErrorCode, templates::TemplateId};
3+
use wp_api_integration_tests::{AssertWpError, TEMPLATE_TWENTY_TWENTY_FOUR_SINGLE, api_client};
4+
5+
#[tokio::test]
6+
#[parallel]
7+
async fn delete_template_err_invalid_template() {
8+
api_client()
9+
.templates()
10+
.delete(&TemplateId(TEMPLATE_TWENTY_TWENTY_FOUR_SINGLE.to_string()))
11+
.await
12+
.assert_wp_error(WpErrorCode::InvalidTemplate)
13+
}
14+
15+
#[tokio::test]
16+
#[parallel]
17+
async fn delete_template_err_template_not_found() {
18+
api_client()
19+
.templates()
20+
.delete(&TemplateId("foo".to_string()))
21+
.await
22+
.assert_wp_error(WpErrorCode::TemplateNotFound)
23+
}
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
use serial_test::serial;
2+
use wp_api::templates::{TemplateId, TemplateStatus};
3+
use wp_api_integration_tests::{TestCredentials, api_client, backend::RestoreServer};
4+
5+
#[tokio::test]
6+
#[serial]
7+
async fn delete_template() {
8+
let template_delete_response = api_client()
9+
.templates()
10+
.delete(&TemplateId(
11+
TestCredentials::instance()
12+
.integration_test_custom_template_id
13+
.to_string(),
14+
))
15+
.await;
16+
assert!(
17+
template_delete_response.is_ok(),
18+
"{:#?}",
19+
template_delete_response
20+
);
21+
assert!(template_delete_response.unwrap().data.deleted);
22+
23+
RestoreServer::db().await;
24+
}
25+
26+
#[tokio::test]
27+
#[serial]
28+
async fn trash_template() {
29+
let template_trash_response = api_client()
30+
.templates()
31+
.trash(&TemplateId(
32+
TestCredentials::instance()
33+
.integration_test_custom_template_id
34+
.to_string(),
35+
))
36+
.await;
37+
assert!(
38+
template_trash_response.is_ok(),
39+
"{:#?}",
40+
template_trash_response
41+
);
42+
assert_eq!(
43+
template_trash_response.unwrap().data.status,
44+
TemplateStatus::Trash
45+
);
46+
47+
RestoreServer::db().await;
48+
}

0 commit comments

Comments
 (0)