diff --git a/CHANGELOG.md b/CHANGELOG.md index f5aee739d..a34b6c114 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - WordPress.com `POST /me/shopping-cart` endpoint for creating shopping carts with domain and plan products - WordPress.com `GET /sites//domains` endpoint for fetching all domains associated with a site - WordPress.com REST API implementation checklist (`WPCOM_REST_API_CHECKLIST.md`) +- WordPress.com `POST /sites//domains/primary` endpoint for setting a site's primary domain ### Changed diff --git a/WPCOM_REST_API_CHECKLIST.md b/WPCOM_REST_API_CHECKLIST.md index fe6615fca..68482cbec 100644 --- a/WPCOM_REST_API_CHECKLIST.md +++ b/WPCOM_REST_API_CHECKLIST.md @@ -106,7 +106,7 @@ investigate the relevant code before making decisions based on this document. - [x] `GET /rest/v1.1/domains/supported-countries/` — supported countries - [x] `GET /rest/v1.1/domains/supported-states/$country/` — states for country - [x] `GET /rest/v1.1/sites/$site/domains/` — site domains -- [ ] `POST /rest/v1.1/sites/$site/domains/primary/` — set primary domain +- [x] `POST /rest/v1.1/sites/$site/domains/primary/` — set primary domain - [x] `GET /rest/v1.3/domains/$domain/is-available/` — check domain availability ## Geo diff --git a/wp_api/src/wp_com/domains.rs b/wp_api/src/wp_com/domains.rs index e951abeb1..77051bfdc 100644 --- a/wp_api/src/wp_com/domains.rs +++ b/wp_api/src/wp_com/domains.rs @@ -980,6 +980,20 @@ pub struct SiteDomain { pub whois_update_unmodifiable_fields: Option>, } +/// Request body for `POST /rest/v1.1/sites/{siteId}/domains/primary/`. +#[derive(Debug, Clone, Serialize, uniffi::Record)] +pub struct SetPrimaryDomainParams { + /// The domain name to set as the site's primary domain. + pub domain: DomainName, +} + +/// Response from `POST /rest/v1.1/sites/{siteId}/domains/primary/`. +#[derive(Debug, Clone, Serialize, Deserialize, uniffi::Record)] +pub struct SetPrimaryDomainResponse { + /// Whether the primary domain was set successfully. + pub success: bool, +} + #[cfg(test)] mod tests { use std::fs::File; @@ -1760,4 +1774,13 @@ mod tests { ); assert!(transfer.ssl_status.is_none()); } + + #[test] + fn test_set_primary_domain_response_deserialization() { + let file = File::open("tests/wpcom/domains/set_primary/success.json") + .expect("Failed to open file"); + let response: SetPrimaryDomainResponse = + serde_json::from_reader(file).expect("Unable to parse JSON"); + assert!(response.success); + } } diff --git a/wp_api/src/wp_com/endpoint/domains_endpoint.rs b/wp_api/src/wp_com/endpoint/domains_endpoint.rs index 2bce08ef7..a17e840d9 100644 --- a/wp_api/src/wp_com/endpoint/domains_endpoint.rs +++ b/wp_api/src/wp_com/endpoint/domains_endpoint.rs @@ -5,7 +5,8 @@ use crate::{ domains::{ AllDomainsParams, AllDomainsResponse, CountryCode, DomainAvailability, DomainAvailabilityParams, DomainName, DomainSuggestion, DomainSuggestionsParams, - SiteDomainsResponse, SupportedCountries, SupportedState, + SetPrimaryDomainParams, SetPrimaryDomainResponse, SiteDomainsResponse, + SupportedCountries, SupportedState, }, }, }; @@ -25,6 +26,8 @@ enum DomainsRequest { AllDomains, #[get(url = "/sites//domains", output = SiteDomainsResponse)] SiteDomains, + #[post(url = "/sites//domains/primary", params = &SetPrimaryDomainParams, output = SetPrimaryDomainResponse)] + SetPrimary, } impl DerivedRequest for DomainsRequest { @@ -177,6 +180,17 @@ mod tests { validate_wp_com_rest_v1_1_endpoint(endpoint.site_domains(&site_id), expected_path); } + #[rstest] + #[case::numeric_id(WpComSiteId(12345), "/sites/12345/domains/primary")] + #[case::large_id(WpComSiteId(229889220), "/sites/229889220/domains/primary")] + fn set_primary( + endpoint: DomainsRequestEndpoint, + #[case] site_id: WpComSiteId, + #[case] expected_path: &str, + ) { + validate_wp_com_rest_v1_1_endpoint(endpoint.set_primary(&site_id), expected_path); + } + fn base_domain_suggestions_params() -> DomainSuggestionsParams { DomainSuggestionsParams { query: "coolsite".to_string(), diff --git a/wp_api/tests/wpcom/domains/set_primary/success.json b/wp_api/tests/wpcom/domains/set_primary/success.json new file mode 100644 index 000000000..5550c6db4 --- /dev/null +++ b/wp_api/tests/wpcom/domains/set_primary/success.json @@ -0,0 +1,3 @@ +{ + "success": true +} diff --git a/wp_com_e2e/src/domains_tests.rs b/wp_com_e2e/src/domains_tests.rs index a8a4306e4..fc18a4c22 100644 --- a/wp_com_e2e/src/domains_tests.rs +++ b/wp_com_e2e/src/domains_tests.rs @@ -3,7 +3,7 @@ use libtest_mimic::Trial; use std::sync::Arc; use wp_api::wp_com::domains::{ AllDomainsParams, CountryCode, DomainAvailabilityParams, DomainAvailabilityStatus, - DomainListItemStatusType, DomainName, DomainSubtypeId, SiteDomainType, + DomainListItemStatusType, DomainName, DomainSubtypeId, SetPrimaryDomainParams, SiteDomainType, }; pub fn tests(ctx: Arc) -> Vec { @@ -283,5 +283,50 @@ pub fn tests(ctx: Arc) -> Vec { } })); + // POST /sites/{siteId}/domains/primary/ + // + // This endpoint mutates the site's primary domain, so the test reads the + // current primary and sets it again. This exercises the endpoint + // idempotently without changing the test site's effective primary domain. + trials.push(Trial::test("domains::set_primary", { + let ctx = Arc::clone(&ctx); + move || { + ctx.runtime.block_on(async { + let domains = ctx + .client + .domains() + .site_domains(&site_id) + .await + .map_err(|e| e.to_string())? + .data + .domains; + + let primary = match domains.iter().find(|d| d.primary_domain == Some(true)) { + Some(domain) => domain, + None => return Err("expected the test site to have a primary domain".into()), + }; + + let response = ctx + .client + .domains() + .set_primary( + &site_id, + &SetPrimaryDomainParams { + domain: primary.domain.clone(), + }, + ) + .await + .map_err(|e| e.to_string())? + .data; + + if !response.success { + return Err("expected set_primary to report success".into()); + } + + Ok(()) + }) + } + })); + trials }