Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add /tags related errors and their integration tests #469

Draft
wants to merge 2 commits into
base: update-tags
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,12 @@ package rs.wordpress.api.kotlin

import kotlinx.coroutines.test.runTest
import org.junit.jupiter.api.Test
import uniffi.wp_api.PostListParams
import uniffi.wp_api.SparseTagFieldWithEditContext
import uniffi.wp_api.TagCreateParams
import uniffi.wp_api.TagListParams
import uniffi.wp_api.TagUpdateParams
import uniffi.wp_api.WpErrorCode
import uniffi.wp_api.wpAuthenticationFromUsernameAndPassword
import kotlin.test.assertEquals
import kotlin.test.assertNotNull
Expand Down Expand Up @@ -104,4 +106,13 @@ class TagsEndpointTest {
assertEquals("new_slug", updatedTag.slug)
restoreTestServer()
}

@Test
fun testErrorTermInvalid() = runTest {
val result =
client.request { requestBuilder ->
requestBuilder.tags().retrieveWithEditContext(9999999)
}
assert(result.wpErrorCode() is WpErrorCode.TermInvalid)
}
}
4 changes: 4 additions & 0 deletions wp_api/src/api_error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,8 @@ pub enum WpErrorCode {
CannotRead,
#[serde(rename = "rest_cannot_read_post")]
CannotReadPost,
#[serde(rename = "rest_cannot_update")]
CannotUpdate,
#[serde(rename = "rest_cannot_view")]
CannotView,
#[serde(rename = "rest_cannot_view_plugin")]
Expand Down Expand Up @@ -213,6 +215,8 @@ pub enum WpErrorCode {
PostInvalidPageNumber,
#[serde(rename = "rest_taxonomy_invalid")]
TaxonomyInvalid,
#[serde(rename = "rest_term_invalid")]
TermInvalid,
#[serde(rename = "rest_type_invalid")]
TypeInvalid,
#[serde(rename = "rest_not_logged_in")]
Expand Down
222 changes: 222 additions & 0 deletions wp_api/src/request/endpoint/tags_endpoint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,3 +40,225 @@ impl DerivedRequest for TagsRequest {
super::macros::default_sparse_field_implementation_from_field_name!(SparseTagFieldWithEditContext);
super::macros::default_sparse_field_implementation_from_field_name!(SparseTagFieldWithEmbedContext);
super::macros::default_sparse_field_implementation_from_field_name!(SparseTagFieldWithViewContext);

#[cfg(test)]
mod tests {
use super::*;
use crate::{
generate,
posts::PostId,
request::endpoint::{
tests::{fixture_api_base_url, validate_wp_v2_endpoint},
ApiBaseUrl,
},
tags::{TagId, WpApiParamTagsOrderBy},
WpApiParamOrder,
};
use rstest::*;
use std::sync::Arc;

#[rstest]
#[case(TagListParams::default(), "")]
#[case(generate!(TagListParams, (page, Some(2))), "page=2")]
#[case(generate!(TagListParams, (per_page, Some(2))), "per_page=2")]
#[case(generate!(TagListParams, (search, Some("foo".to_string()))), "search=foo")]
#[case(generate!(TagListParams, (exclude, vec![TagId(1), TagId(2)])), "exclude=1%2C2")]
#[case(generate!(TagListParams, (include, vec![TagId(1), TagId(2)])), "include=1%2C2")]
#[case(generate!(TagListParams, (offset, Some(2))), "offset=2")]
#[case(generate!(TagListParams, (order, Some(WpApiParamOrder::Asc))), "order=asc")]
#[case(generate!(TagListParams, (order, Some(WpApiParamOrder::Desc))), "order=desc")]
#[case(generate!(TagListParams, (orderby, Some(WpApiParamTagsOrderBy::Id))), "orderby=id")]
#[case(generate!(TagListParams, (orderby, Some(WpApiParamTagsOrderBy::Include))), "orderby=include")]
#[case(generate!(TagListParams, (orderby, Some(WpApiParamTagsOrderBy::Name))), "orderby=name")]
#[case(generate!(TagListParams, (orderby, Some(WpApiParamTagsOrderBy::Slug))), "orderby=slug")]
#[case(generate!(TagListParams, (orderby, Some(WpApiParamTagsOrderBy::IncludeSlugs))), "orderby=include_slugs")]
#[case(generate!(TagListParams, (orderby, Some(WpApiParamTagsOrderBy::TermGroup))), "orderby=term_group")]
#[case(generate!(TagListParams, (orderby, Some(WpApiParamTagsOrderBy::Description))), "orderby=description")]
#[case(generate!(TagListParams, (orderby, Some(WpApiParamTagsOrderBy::Count))), "orderby=count")]
#[case(generate!(TagListParams, (hide_empty, Some(true))), "hide_empty=true")]
#[case(generate!(TagListParams, (post, Some(PostId(3)))), "post=3")]
#[case(generate!(TagListParams, (slug, vec!["slug_1".to_string(), "slug_2".to_string()])), "slug=slug_1%2Cslug_2")]
// TODO
#[case(
tag_list_params_with_all_fields(),
EXPECTED_QUERY_PAIRS_FOR_TAG_LIST_PARAMS_WITH_ALL_FIELDS
)]
fn list_tags(
endpoint: TagsRequestEndpoint,
#[case] params: TagListParams,
#[case] expected_additional_params: &str,
) {
let expected_path = |context: &str| {
if expected_additional_params.is_empty() {
format!("/tags?context={}", context)
} else {
format!("/tags?context={}&{}", context, expected_additional_params)
}
};
validate_wp_v2_endpoint(
endpoint.list_with_edit_context(&params),
&expected_path("edit"),
);
validate_wp_v2_endpoint(
endpoint.list_with_embed_context(&params),
&expected_path("embed"),
);
validate_wp_v2_endpoint(
endpoint.list_with_view_context(&params),
&expected_path("view"),
);
}

#[rstest]
#[case(TagListParams::default(), &[], "/tags?context=edit&_fields=")]
#[case(generate!(TagListParams, (orderby, Some(WpApiParamTagsOrderBy::Id))), &[SparseTagFieldWithEditContext::Count], "/tags?context=edit&orderby=id&_fields=count")]
#[case(tag_list_params_with_all_fields(), ALL_SPARSE_TAG_FIELDS_WITH_EDIT_CONTEXT, &format!("/tags?context=edit&{}&{}", EXPECTED_QUERY_PAIRS_FOR_TAG_LIST_PARAMS_WITH_ALL_FIELDS, EXPECTED_QUERY_PAIRS_FOR_ALL_SPARSE_TAG_FIELDS_WITH_EDIT_CONTEXT))]
fn filter_list_tags_with_edit_context(
endpoint: TagsRequestEndpoint,
#[case] params: TagListParams,
#[case] fields: &[SparseTagFieldWithEditContext],
#[case] expected_path: &str,
) {
validate_wp_v2_endpoint(
endpoint.filter_list_with_edit_context(&params, fields),
expected_path,
);
}

#[rstest]
#[case(TagListParams::default(), &[], "/tags?context=embed&_fields=")]
#[case(generate!(TagListParams, (orderby, Some(WpApiParamTagsOrderBy::Slug))), &[SparseTagFieldWithEmbedContext::Link], "/tags?context=embed&orderby=slug&_fields=link")]
#[case(tag_list_params_with_all_fields(), ALL_SPARSE_TAG_FIELDS_WITH_EMBED_CONTEXT, &format!("/tags?context=embed&{}&{}", EXPECTED_QUERY_PAIRS_FOR_TAG_LIST_PARAMS_WITH_ALL_FIELDS, EXPECTED_QUERY_PAIRS_FOR_ALL_SPARSE_TAG_FIELDS_WITH_EMBED_CONTEXT))]
fn filter_list_tags_with_embed_context(
endpoint: TagsRequestEndpoint,
#[case] params: TagListParams,
#[case] fields: &[SparseTagFieldWithEmbedContext],
#[case] expected_path: &str,
) {
validate_wp_v2_endpoint(
endpoint.filter_list_with_embed_context(&params, fields),
expected_path,
);
}

#[rstest]
#[case(TagListParams::default(), &[], "/tags?context=view&_fields=")]
#[case(generate!(TagListParams, (orderby, Some(WpApiParamTagsOrderBy::Include))), &[SparseTagFieldWithViewContext::Description], "/tags?context=view&orderby=include&_fields=description")]
#[case(tag_list_params_with_all_fields(), ALL_SPARSE_TAG_FIELDS_WITH_VIEW_CONTEXT, &format!("/tags?context=view&{}&{}", EXPECTED_QUERY_PAIRS_FOR_TAG_LIST_PARAMS_WITH_ALL_FIELDS, EXPECTED_QUERY_PAIRS_FOR_ALL_SPARSE_TAG_FIELDS_WITH_VIEW_CONTEXT))]
fn filter_list_tags_with_view_context(
endpoint: TagsRequestEndpoint,
#[case] params: TagListParams,
#[case] fields: &[SparseTagFieldWithViewContext],
#[case] expected_path: &str,
) {
validate_wp_v2_endpoint(
endpoint.filter_list_with_view_context(&params, fields),
expected_path,
);
}

const EXPECTED_QUERY_PAIRS_FOR_TAG_LIST_PARAMS_WITH_ALL_FIELDS: &str = "page=11&per_page=22&search=s_q&exclude=1111%2C1112&include=2111%2C2112&offset=11111&order=desc&orderby=slug&hide_empty=true&post=33333&slug=slug_1%2Cslug_2";
fn tag_list_params_with_all_fields() -> TagListParams {
TagListParams {
page: Some(11),
per_page: Some(22),
search: Some("s_q".to_string()),
exclude: vec![TagId(1111), TagId(1112)],
include: vec![TagId(2111), TagId(2112)],
offset: Some(11111),
order: Some(WpApiParamOrder::Desc),
orderby: Some(WpApiParamTagsOrderBy::Slug),
hide_empty: Some(true),
post: Some(PostId(33333)),
slug: vec!["slug_1".to_string(), "slug_2".to_string()],
}
}

#[rstest]
fn retrieve_tag(endpoint: TagsRequestEndpoint) {
let tag_id = TagId(54);
let expected_path = |context: &str| format!("/tags/54?context={}", context);
validate_wp_v2_endpoint(
endpoint.retrieve_with_edit_context(&tag_id),
&expected_path("edit"),
);
validate_wp_v2_endpoint(
endpoint.retrieve_with_embed_context(&tag_id),
&expected_path("embed"),
);
validate_wp_v2_endpoint(
endpoint.retrieve_with_view_context(&tag_id),
&expected_path("view"),
);
}

#[rstest]
#[case(None, &[], "/tags/54?context=view&_fields=")]
#[case(Some("foo"), &[SparseTagFieldWithViewContext::Count], "/tags/54?context=view&_fields=count")]
#[case(Some("foo"), ALL_SPARSE_TAG_FIELDS_WITH_VIEW_CONTEXT, &format!("/tags/54?context=view&{}", EXPECTED_QUERY_PAIRS_FOR_ALL_SPARSE_TAG_FIELDS_WITH_VIEW_CONTEXT))]
fn filter_retrieve_tag_with_view_context(
endpoint: TagsRequestEndpoint,
#[case] password: Option<&str>,
#[case] fields: &[SparseTagFieldWithViewContext],
#[case] expected_path: &str,
) {
validate_wp_v2_endpoint(
endpoint.filter_retrieve_with_view_context(&TagId(54), fields),
expected_path,
);
}

#[rstest]
fn create_tag(endpoint: TagsRequestEndpoint) {
validate_wp_v2_endpoint(endpoint.create(), "/tags");
}

#[rstest]
fn delete_tag(endpoint: TagsRequestEndpoint) {
validate_wp_v2_endpoint(endpoint.delete(&TagId(54)), "/tags/54?force=true");
}

#[rstest]
fn update_tag(endpoint: TagsRequestEndpoint) {
validate_wp_v2_endpoint(endpoint.update(&TagId(54)), "/tags/54");
}

const EXPECTED_QUERY_PAIRS_FOR_ALL_SPARSE_TAG_FIELDS_WITH_EDIT_CONTEXT: &str =
"_fields=id%2Ccount%2Cdescription%2Clink%2Cname%2Cslug%2Ctaxonomy";
const ALL_SPARSE_TAG_FIELDS_WITH_EDIT_CONTEXT: &[SparseTagFieldWithEditContext; 7] = &[
SparseTagFieldWithEditContext::Id,
SparseTagFieldWithEditContext::Count,
SparseTagFieldWithEditContext::Description,
SparseTagFieldWithEditContext::Link,
SparseTagFieldWithEditContext::Name,
SparseTagFieldWithEditContext::Slug,
SparseTagFieldWithEditContext::Taxonomy,
];

const EXPECTED_QUERY_PAIRS_FOR_ALL_SPARSE_TAG_FIELDS_WITH_EMBED_CONTEXT: &str =
"_fields=id%2Clink%2Cname%2Cslug%2Ctaxonomy";
const ALL_SPARSE_TAG_FIELDS_WITH_EMBED_CONTEXT: &[SparseTagFieldWithEmbedContext; 5] = &[
SparseTagFieldWithEmbedContext::Id,
SparseTagFieldWithEmbedContext::Link,
SparseTagFieldWithEmbedContext::Name,
SparseTagFieldWithEmbedContext::Slug,
SparseTagFieldWithEmbedContext::Taxonomy,
];

const EXPECTED_QUERY_PAIRS_FOR_ALL_SPARSE_TAG_FIELDS_WITH_VIEW_CONTEXT: &str =
"_fields=id%2Ccount%2Cdescription%2Clink%2Cname%2Cslug%2Ctaxonomy";
const ALL_SPARSE_TAG_FIELDS_WITH_VIEW_CONTEXT: &[SparseTagFieldWithViewContext; 7] = &[
SparseTagFieldWithViewContext::Id,
SparseTagFieldWithViewContext::Count,
SparseTagFieldWithViewContext::Description,
SparseTagFieldWithViewContext::Link,
SparseTagFieldWithViewContext::Name,
SparseTagFieldWithViewContext::Slug,
SparseTagFieldWithViewContext::Taxonomy,
];

#[fixture]
fn endpoint(fixture_api_base_url: Arc<ApiBaseUrl>) -> TagsRequestEndpoint {
TagsRequestEndpoint::new(fixture_api_base_url)
}
}
1 change: 1 addition & 0 deletions wp_api_integration_tests/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ pub const MEDIA_TEST_FILE_PATH: &str = "../test_media.jpg";
pub const MEDIA_TEST_FILE_CONTENT_TYPE: &str = "image/jpeg";
pub const CATEGORY_ID_1: CategoryId = CategoryId(1);
pub const TAG_ID_100: TagId = TagId(100);
pub const TAG_ID_INVALID: TagId = TagId(99999999);
pub const POST_TEMPLATE_SINGLE_WITH_SIDEBAR: &str = "single-with-sidebar";

pub fn api_client() -> WpApiClient {
Expand Down
76 changes: 76 additions & 0 deletions wp_api_integration_tests/tests/test_tags_err.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
use serial_test::parallel;
use wp_api::{
tags::{TagCreateParams, TagListParams, TagUpdateParams},
WpErrorCode,
};
use wp_api_integration_tests::{
api_client, api_client_as_subscriber, AssertWpError, POST_ID_INVALID, TAG_ID_100,
TAG_ID_INVALID,
};

#[tokio::test]
#[parallel]
async fn create_err_cannot_create() {
api_client_as_subscriber()
.tags()
.create(&TagCreateParams {
name: "foo".to_string(),
description: None,
slug: None,
})
.await
.assert_wp_error(WpErrorCode::CannotCreate);
}

#[tokio::test]
#[parallel]
async fn delete_err_cannot_delete() {
api_client_as_subscriber()
.tags()
.delete(&TAG_ID_100)
.await
.assert_wp_error(WpErrorCode::CannotDelete);
}

#[tokio::test]
#[parallel]
async fn list_err_forbidden_context() {
api_client_as_subscriber()
.tags()
.list_with_edit_context(&TagListParams::default())
.await
.assert_wp_error(WpErrorCode::ForbiddenContext);
}

#[tokio::test]
#[parallel]
async fn list_err_post_invalid_id() {
api_client()
.tags()
.list_with_edit_context(&TagListParams {
post: Some(POST_ID_INVALID),
..Default::default()
})
.await
.assert_wp_error(WpErrorCode::PostInvalidId);
}

#[tokio::test]
#[parallel]
async fn retrieve_err_term_invalid() {
api_client()
.tags()
.retrieve_with_edit_context(&TAG_ID_INVALID)
.await
.assert_wp_error(WpErrorCode::TermInvalid);
}

#[tokio::test]
#[parallel]
async fn update_err_cannot_update() {
api_client_as_subscriber()
.tags()
.update(&TAG_ID_100, &TagUpdateParams::default())
.await
.assert_wp_error(WpErrorCode::CannotUpdate);
}
Loading