Skip to content

Commit 07e1028

Browse files
committed
Create /templates endpoint
1 parent d6b89bc commit 07e1028

File tree

5 files changed

+200
-11
lines changed

5 files changed

+200
-11
lines changed

wp_api/src/api_error.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -278,6 +278,8 @@ pub enum WpErrorCode {
278278
TaxonomyInvalid,
279279
#[serde(rename = "rest_template_already_trashed")]
280280
TemplateAlreadyTrashed,
281+
#[serde(rename = "rest_template_insert_error")]
282+
TemplateInsertError,
281283
#[serde(rename = "rest_template_not_found")]
282284
TemplateNotFound,
283285
#[serde(rename = "rest_term_invalid")]

wp_api/src/request/endpoint/templates_endpoint.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ enum TemplatesRequest {
1212
List,
1313
#[contextual_get(url = "/templates/<template_id>", output = crate::templates::SparseTemplate, filter_by = crate::templates::SparseTemplateField)]
1414
Retrieve,
15+
#[post(url = "/templates", params = &crate::templates::TemplateCreateParams, output = crate::templates::TemplateWithEditContext)]
16+
Create,
1517
#[delete(url = "/templates/<template_id>", output = crate::templates::TemplateDeleteResponse)]
1618
Delete,
1719
#[delete(url = "/templates/<template_id>", output = crate::templates::TemplateWithEditContext)]
@@ -80,6 +82,11 @@ mod tests {
8082
use rstest::*;
8183
use std::sync::Arc;
8284

85+
#[rstest]
86+
fn create_template(endpoint: TemplatesRequestEndpoint) {
87+
validate_wp_v2_endpoint(endpoint.create(), "/templates");
88+
}
89+
8390
#[rstest]
8491
#[case(TemplateListParams::default(), "")]
8592
#[case(generate!(TemplateListParams, (post_id, Some(PostId(2)))), "wp_id=2")]

wp_api/src/templates.rs

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -232,3 +232,53 @@ pub struct TemplateUpdateParams {
232232
// don't seem to take place when they are included in the request. So, we decided not to
233233
// include them until we figure out under which conditions they'll be allowed to update.
234234
}
235+
236+
#[derive(Debug, Serialize, uniffi::Record)]
237+
pub struct TemplateCreateParams {
238+
// Unique slug identifying the template.
239+
pub slug: String,
240+
// Theme identifier for the template.
241+
#[uniffi(default = None)]
242+
#[serde(skip_serializing_if = "Option::is_none")]
243+
pub theme: Option<String>,
244+
// Type of template.
245+
#[uniffi(default = None)]
246+
#[serde(skip_serializing_if = "Option::is_none")]
247+
pub template_type: Option<String>,
248+
// Content of template.
249+
#[uniffi(default = None)]
250+
#[serde(skip_serializing_if = "Option::is_none")]
251+
pub content: Option<String>,
252+
// Title of template.
253+
#[uniffi(default = None)]
254+
#[serde(skip_serializing_if = "Option::is_none")]
255+
pub title: Option<String>,
256+
// Description of template.
257+
#[uniffi(default = None)]
258+
#[serde(skip_serializing_if = "Option::is_none")]
259+
pub description: Option<String>,
260+
// Status of template.
261+
// One of: publish, future, draft, pending, private
262+
#[uniffi(default = None)]
263+
#[serde(skip_serializing_if = "Option::is_none")]
264+
pub status: Option<TemplateStatus>,
265+
// The ID for the author of the template.
266+
#[uniffi(default = None)]
267+
#[serde(skip_serializing_if = "Option::is_none")]
268+
pub author: Option<UserId>,
269+
}
270+
271+
impl TemplateCreateParams {
272+
pub fn new(slug: String) -> Self {
273+
Self {
274+
slug,
275+
theme: None,
276+
template_type: None,
277+
content: None,
278+
title: None,
279+
description: None,
280+
status: None,
281+
author: None,
282+
}
283+
}
284+
}

wp_api_integration_tests/tests/test_templates_err.rs

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,21 @@
11
use serial_test::parallel;
22
use wp_api::{
33
WpErrorCode,
4-
templates::{TemplateId, TemplateUpdateParams},
4+
templates::{TemplateCreateParams, TemplateId, TemplateUpdateParams},
55
};
66
use wp_api_integration_tests::{AssertWpError, TEMPLATE_TWENTY_TWENTY_FOUR_SINGLE, api_client};
77

8+
#[tokio::test]
9+
#[parallel]
10+
async fn create_template_err_empty_content() {
11+
// Creating a template requires `title` or `content`
12+
api_client()
13+
.templates()
14+
.create(&TemplateCreateParams::new("foo".to_string()))
15+
.await
16+
.assert_wp_error(WpErrorCode::EmptyContent)
17+
}
18+
819
#[tokio::test]
920
#[parallel]
1021
async fn delete_template_err_invalid_template() {

wp_api_integration_tests/tests/test_templates_mut.rs

Lines changed: 129 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,111 @@ use macro_helper::generate_update_test;
22
use serial_test::serial;
33
use wp_api::templates::{
44
SparseTemplateContent, SparseTemplateContentWrapper, SparseTemplateTitle,
5-
SparseTemplateTitleWrapper, TemplateId, TemplateStatus, TemplateUpdateParams,
6-
TemplateWithEditContext,
5+
SparseTemplateTitleWrapper, TemplateCreateParams, TemplateId, TemplateStatus,
6+
TemplateUpdateParams, TemplateWithEditContext,
77
};
88
use wp_api_integration_tests::{
99
AssertResponse, SECOND_USER_ID, TestCredentials, api_client, backend::RestoreServer,
1010
};
1111

12+
const TEST_SLUG: &str = "foo_template_slug";
13+
const TEST_TITLE: &str = "foo template title";
14+
15+
#[tokio::test]
16+
#[serial]
17+
async fn create_template_with_slug_and_content() {
18+
let content = "foo template content";
19+
let mut params = TemplateCreateParams::new(TEST_SLUG.to_string());
20+
params.content = Some(content.to_string());
21+
test_create_template(&params, |created_template| {
22+
assert_slug(&created_template);
23+
assert_eq!(
24+
created_template.content,
25+
SparseTemplateContentWrapper::Object(SparseTemplateContent {
26+
raw: Some(content.to_string()),
27+
rendered: None,
28+
protected: None,
29+
block_version: None
30+
})
31+
);
32+
})
33+
.await;
34+
}
35+
36+
#[tokio::test]
37+
#[serial]
38+
async fn create_template_with_slug_and_title() {
39+
let mut params = TemplateCreateParams::new(TEST_SLUG.to_string());
40+
params.title = Some(TEST_TITLE.to_string());
41+
test_create_template(&params, |created_template| {
42+
assert_slug(&created_template);
43+
assert_title(&created_template);
44+
})
45+
.await;
46+
}
47+
48+
#[tokio::test]
49+
#[serial]
50+
async fn create_template_with_slug_title_and_theme() {
51+
let theme = "foo template theme";
52+
let mut params = TemplateCreateParams::new(TEST_SLUG.to_string());
53+
params.title = Some(TEST_TITLE.to_string());
54+
params.theme = Some(theme.to_string());
55+
test_create_template(&params, |created_template| {
56+
assert_slug(&created_template);
57+
assert_title(&created_template);
58+
assert_eq!(created_template.theme, theme);
59+
})
60+
.await;
61+
}
62+
63+
#[tokio::test]
64+
#[serial]
65+
async fn create_template_with_slug_title_and_author() {
66+
let mut params = TemplateCreateParams::new(TEST_SLUG.to_string());
67+
params.title = Some(TEST_TITLE.to_string());
68+
params.author = Some(SECOND_USER_ID);
69+
test_create_template(&params, |created_template| {
70+
assert_title(&created_template);
71+
assert_eq!(created_template.author, SECOND_USER_ID);
72+
})
73+
.await;
74+
}
75+
76+
#[tokio::test]
77+
#[serial]
78+
// TODO: `template_type` parameter doesn't seem to be working. It either requires the template type
79+
// to be set up in advance or the parameter is always ignored.
80+
#[ignore]
81+
async fn create_template_with_slug_title_and_template_type() {
82+
let template_type = "foo template type";
83+
let mut params = TemplateCreateParams::new(TEST_SLUG.to_string());
84+
params.title = Some(TEST_TITLE.to_string());
85+
params.template_type = Some(template_type.to_string());
86+
test_create_template(&params, |created_template| {
87+
assert_title(&created_template);
88+
assert_eq!(created_template.template_type, template_type);
89+
})
90+
.await;
91+
}
92+
93+
#[tokio::test]
94+
#[serial]
95+
// TODO: `status` parameter seems to be ignored as the server is always responding with
96+
// `TemplateStatus::Publish`
97+
#[ignore]
98+
async fn create_template_with_slug_title_and_template_status_future() {
99+
let status = TemplateStatus::Future;
100+
let mut params = TemplateCreateParams::new(TEST_SLUG.to_string());
101+
params.title = Some(TEST_TITLE.to_string());
102+
params.status = Some(status.clone());
103+
test_create_template(&params, |created_template| {
104+
assert_title(&created_template);
105+
assert_eq!(created_template.status, status);
106+
})
107+
.await;
108+
}
109+
12110
#[tokio::test]
13111
#[serial]
14112
async fn delete_template() {
@@ -73,15 +171,9 @@ generate_update_test!(
73171
generate_update_test!(
74172
update_title,
75173
title,
76-
"new_title".to_string(),
174+
TEST_TITLE.to_string(),
77175
|updated_template| {
78-
assert_eq!(
79-
updated_template.title,
80-
SparseTemplateTitleWrapper::Object(SparseTemplateTitle {
81-
raw: Some("new_title".to_string()),
82-
rendered: Some("new_title".to_string())
83-
})
84-
);
176+
assert_title(&updated_template);
85177
}
86178
);
87179
generate_update_test!(
@@ -116,6 +208,33 @@ where
116208
RestoreServer::db().await;
117209
}
118210

211+
async fn test_create_template<F>(params: &TemplateCreateParams, assert: F)
212+
where
213+
F: Fn(TemplateWithEditContext),
214+
{
215+
let response = api_client()
216+
.templates()
217+
.create(params)
218+
.await
219+
.assert_response();
220+
assert(response.data);
221+
RestoreServer::db().await;
222+
}
223+
224+
fn assert_slug(template: &TemplateWithEditContext) {
225+
assert_eq!(template.slug, TEST_SLUG);
226+
}
227+
228+
fn assert_title(template: &TemplateWithEditContext) {
229+
assert_eq!(
230+
template.title,
231+
SparseTemplateTitleWrapper::Object(SparseTemplateTitle {
232+
raw: Some(TEST_TITLE.to_string()),
233+
rendered: Some(TEST_TITLE.to_string())
234+
})
235+
);
236+
}
237+
119238
mod macro_helper {
120239
macro_rules! generate_update_test {
121240
($ident:ident, $field:ident, $new_value:expr, $assertion:expr) => {

0 commit comments

Comments
 (0)