From e725b3b3688cc5b518be4596fbbc1694ab26dc33 Mon Sep 17 00:00:00 2001 From: Jaclyn Chen Date: Mon, 9 Jan 2023 16:23:08 +0800 Subject: [PATCH 1/2] Networking layer changes for 2 domain settings endpoints. --- .../Networking.xcodeproj/project.pbxproj | 12 + .../Networking/Remote/DomainRemote.swift | 44 +++- .../Networking/Remote/PaymentRemote.swift | 39 +++- .../Networking/Requests/DotcomRequest.swift | 2 +- .../Settings/WordPressAPIVersion.swift | 4 + .../Remote/DomainRemoteTests.swift | 30 +++ .../Remote/PaymentRemoteTests.swift | 41 ++++ .../load-site-current-plan-success.json | 53 +++++ .../load-site-plans-no-current-plan.json | 29 +++ .../Responses/site-domains.json | 217 ++++++++++++++++++ .../Settings/Domains/DomainSettingsView.swift | 10 +- 11 files changed, 466 insertions(+), 15 deletions(-) create mode 100644 Networking/NetworkingTests/Responses/load-site-current-plan-success.json create mode 100644 Networking/NetworkingTests/Responses/load-site-plans-no-current-plan.json create mode 100644 Networking/NetworkingTests/Responses/site-domains.json diff --git a/Networking/Networking.xcodeproj/project.pbxproj b/Networking/Networking.xcodeproj/project.pbxproj index 6619872a11a..2aba2bf7b90 100644 --- a/Networking/Networking.xcodeproj/project.pbxproj +++ b/Networking/Networking.xcodeproj/project.pbxproj @@ -70,6 +70,9 @@ 02AF07EA27492DBC00B2D81E /* WordPressMedia.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02AF07E927492DBC00B2D81E /* WordPressMedia.swift */; }; 02AF07EC27492FDD00B2D81E /* media-library-from-wordpress-site.json in Resources */ = {isa = PBXBuildFile; fileRef = 02AF07EB27492FDD00B2D81E /* media-library-from-wordpress-site.json */; }; 02AF07EE27493AE700B2D81E /* media-upload-to-wordpress-site.json in Resources */ = {isa = PBXBuildFile; fileRef = 02AF07ED27493AE700B2D81E /* media-upload-to-wordpress-site.json */; }; + 02B41A90296BC85800FE3311 /* site-domains.json in Resources */ = {isa = PBXBuildFile; fileRef = 02B41A8F296BC85800FE3311 /* site-domains.json */; }; + 02B41A92296BEB3000FE3311 /* load-site-current-plan-success.json in Resources */ = {isa = PBXBuildFile; fileRef = 02B41A91296BEB3000FE3311 /* load-site-current-plan-success.json */; }; + 02B41A94296C04BC00FE3311 /* load-site-plans-no-current-plan.json in Resources */ = {isa = PBXBuildFile; fileRef = 02B41A93296C04BC00FE3311 /* load-site-plans-no-current-plan.json */; }; 02BA23C922EEF62C009539E7 /* order-stats-v4-wcadmin-deactivated.json in Resources */ = {isa = PBXBuildFile; fileRef = 02BA23C722EEF62C009539E7 /* order-stats-v4-wcadmin-deactivated.json */; }; 02BA23CA22EEF62C009539E7 /* order-stats-v4-wcadmin-activated.json in Resources */ = {isa = PBXBuildFile; fileRef = 02BA23C822EEF62C009539E7 /* order-stats-v4-wcadmin-activated.json */; }; 02BDB83523EA98C800BCC63E /* String+HTML.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02BDB83423EA98C800BCC63E /* String+HTML.swift */; }; @@ -880,6 +883,9 @@ 02AF07E927492DBC00B2D81E /* WordPressMedia.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WordPressMedia.swift; sourceTree = ""; }; 02AF07EB27492FDD00B2D81E /* media-library-from-wordpress-site.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = "media-library-from-wordpress-site.json"; sourceTree = ""; }; 02AF07ED27493AE700B2D81E /* media-upload-to-wordpress-site.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = "media-upload-to-wordpress-site.json"; sourceTree = ""; }; + 02B41A8F296BC85800FE3311 /* site-domains.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = "site-domains.json"; sourceTree = ""; }; + 02B41A91296BEB3000FE3311 /* load-site-current-plan-success.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = "load-site-current-plan-success.json"; sourceTree = ""; }; + 02B41A93296C04BC00FE3311 /* load-site-plans-no-current-plan.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = "load-site-plans-no-current-plan.json"; sourceTree = ""; }; 02BA23C722EEF62C009539E7 /* order-stats-v4-wcadmin-deactivated.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = "order-stats-v4-wcadmin-deactivated.json"; sourceTree = ""; }; 02BA23C822EEF62C009539E7 /* order-stats-v4-wcadmin-activated.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = "order-stats-v4-wcadmin-activated.json"; sourceTree = ""; }; 02BDB83423EA98C800BCC63E /* String+HTML.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "String+HTML.swift"; sourceTree = ""; }; @@ -2155,7 +2161,10 @@ DE50295F28C609A300551736 /* jetpack-connected-user.json */, DE34051A28BDF12C00CF0D97 /* jetpack-connection-url.json */, DE50296228C609DE00551736 /* jetpack-user-not-connected.json */, + 02B41A91296BEB3000FE3311 /* load-site-current-plan-success.json */, + 02B41A93296C04BC00FE3311 /* load-site-plans-no-current-plan.json */, EE8A86F0286C5226003E8AA4 /* media-update-product-id-in-wordpress-site.json */, + 02B41A8F296BC85800FE3311 /* site-domains.json */, D865CE6D278CC19A002C8520 /* stripe-location-error.json */, D865CE6C278CC19A002C8520 /* stripe-location.json */, D865CE6A278CA266002C8520 /* stripe-payment-intent-error.json */, @@ -2951,6 +2960,7 @@ 743E84FC22174CE100FAC9D7 /* restnoroute_error.json in Resources */, CE20179320E3EFA7005B4C18 /* broken-orders.json in Resources */, D8FBFF2722D529F2006E3336 /* order-stats-v4-month.json in Resources */, + 02B41A92296BEB3000FE3311 /* load-site-current-plan-success.json in Resources */, 02EF1672292F0D1900D90AD6 /* load-plan-success.json in Resources */, 2685C0DE263B5A4200D9EE97 /* add-on-groups.json in Resources */, DEC51A9B274E3206009F3DF4 /* plugin-inactive.json in Resources */, @@ -2962,6 +2972,7 @@ DE5CA111288A3E080077BEF9 /* product-malformed-variations-and-image-alt.json in Resources */, 02DD6492248A3EC00082523E /* product-external.json in Resources */, 03DCB7522624B3BE00C8953D /* coupons-all.json in Resources */, + 02B41A94296C04BC00FE3311 /* load-site-plans-no-current-plan.json in Resources */, 028CB716290223CB00331C09 /* create-account-success.json in Resources */, 036563E129069D3500D84BFD /* just-in-time-message-list.json in Resources */, 45A4B85C25D2FAB500776FB4 /* shipping-label-address-validation-error.json in Resources */, @@ -3117,6 +3128,7 @@ 2683D71024456EE4002A1589 /* categories-extra.json in Resources */, A69FE19D2588D70E0059A96B /* order-with-deleted-refunds.json in Resources */, E18152C228F85E0A0011A0EC /* iap-products.json in Resources */, + 02B41A90296BC85800FE3311 /* site-domains.json in Resources */, EEA658462966C67C00112DF0 /* products-ids-only-without-data.json in Resources */, DE2095C127966EC800171F1C /* coupon-reports.json in Resources */, 453305F52459ED2700264E50 /* site-post-update.json in Resources */, diff --git a/Networking/Networking/Remote/DomainRemote.swift b/Networking/Networking/Remote/DomainRemote.swift index 2f2d7b039eb..9a1f3e56c1d 100644 --- a/Networking/Networking/Remote/DomainRemote.swift +++ b/Networking/Networking/Remote/DomainRemote.swift @@ -6,6 +6,11 @@ public protocol DomainRemoteProtocol { /// - Parameter query: What the domain suggestions are based on. /// - Returns: The result of free domain suggestions. func loadFreeDomainSuggestions(query: String) async throws -> [FreeDomainSuggestion] + + /// Loads all domains for a site. + /// - Parameter siteID: ID of the site to load the domains for. + /// - Returns: A list of domains. + func loadDomains(siteID: Int64) async throws -> [SiteDomain] } /// Domain: Remote Endpoints @@ -21,6 +26,13 @@ public class DomainRemote: Remote, DomainRemoteProtocol { let request = DotcomRequest(wordpressApiVersion: .mark1_1, method: .get, path: path, parameters: parameters) return try await enqueue(request) } + + public func loadDomains(siteID: Int64) async throws -> [SiteDomain] { + let path = "sites/\(siteID)/\(Path.domains)" + let request = DotcomRequest(wordpressApiVersion: .mark1_1, method: .get, path: path) + let response: SiteDomainEnvelope = try await enqueue(request) + return response.domains + } } /// Necessary data for a free domain suggestion. @@ -42,7 +54,7 @@ public struct FreeDomainSuggestion: Decodable, Equatable { } /// Necessary data for a site's domain. -public struct SiteDomain: Equatable { +public struct SiteDomain: Decodable, Equatable { /// Domain name. public let name: String @@ -57,6 +69,35 @@ public struct SiteDomain: Equatable { self.isPrimary = isPrimary self.renewalDate = renewalDate } + + /// Custom decoding implementation since `renewalDate` is an empty string instead of `null` when it's unavailable. + public init(from decoder: Decoder) throws { + let container = try decoder.container(keyedBy: CodingKeys.self) + let name = try container.decode(String.self, forKey: .name) + let isPrimary = try container.decode(Bool.self, forKey: .isPrimary) + + let renewalDate: Date? = { + guard let dateString = try? container.decodeIfPresent(String.self, forKey: .renewalDate) else { + return nil + } + let dateFormatter = DateFormatter() + dateFormatter.dateFormat = "MMMM d, yyyy" + return dateFormatter.date(from: dateString) + }() + + self.init(name: name, isPrimary: isPrimary, renewalDate: renewalDate) + } + + private enum CodingKeys: String, CodingKey { + case name = "domain" + case isPrimary = "primary_domain" + case renewalDate = "auto_renewal_date" + } +} + +/// Maps to a list of domains to match the API response. +private struct SiteDomainEnvelope: Decodable { + let domains: [SiteDomain] } // MARK: - Constants @@ -77,5 +118,6 @@ private extension DomainRemote { enum Path { static let domainSuggestions = "domains/suggestions" + static let domains = "domains" } } diff --git a/Networking/Networking/Remote/PaymentRemote.swift b/Networking/Networking/Remote/PaymentRemote.swift index d67f964e115..597bc1198bc 100644 --- a/Networking/Networking/Remote/PaymentRemote.swift +++ b/Networking/Networking/Remote/PaymentRemote.swift @@ -7,6 +7,11 @@ public protocol PaymentRemoteProtocol { /// - Returns: The WPCOM plan that matches the given product ID. func loadPlan(thatMatchesID productID: Int64) async throws -> WPComPlan + /// Loads the current WPCOM plan of a site. + /// - Parameter siteID: ID of the site to load the current plan for. + /// - Returns: The current WPCOM plan of the given site. + func loadSiteCurrentPlan(siteID: Int64) async throws -> WPComSitePlan + /// Creates a cart with the given product ID for the site ID. /// - Parameters: /// - siteID: The ID of the site that the product is being added to. @@ -28,6 +33,16 @@ public class PaymentRemote: Remote, PaymentRemoteProtocol { return plan } + public func loadSiteCurrentPlan(siteID: Int64) async throws -> WPComSitePlan { + let path = "sites/\(siteID)/\(Path.products)" + let request = DotcomRequest(wordpressApiVersion: .mark1_3, method: .get, path: path) + let plansByID: [String: SiteCurrentPlanResponse] = try await enqueue(request) + guard let currentPlan = plansByID.values.filter({ $0.isCurrentPlan == true }).first else { + throw LoadSiteCurrentPlanError.noCurrentPlan + } + return .init(hasDomainCredit: currentPlan.hasDomainCredit ?? false) + } + public func createCart(siteID: Int64, productID: Int64) async throws { let path = "\(Path.cartCreation)/\(siteID)" @@ -69,14 +84,11 @@ public struct WPComPlan: Decodable, Equatable { } /// Contains necessary data for a site's WPCOM plan. -public struct WPComSitePlan { - /// WPCOM plan of a site. - public let plan: WPComPlan +public struct WPComSitePlan: Equatable { /// Whether a site has domain credit from the WPCOM plan. public let hasDomainCredit: Bool - public init(plan: WPComPlan, hasDomainCredit: Bool) { - self.plan = plan + public init(hasDomainCredit: Bool) { self.hasDomainCredit = hasDomainCredit } } @@ -86,11 +98,28 @@ public enum LoadPlanError: Error { case noMatchingPlan } +/// Possible error cases from loading a site's current WPCOM plan. +public enum LoadSiteCurrentPlanError: Error { + case noCurrentPlan +} + /// Possible error cases from creating cart for a site with a WPCOM plan. public enum CreateCartError: Error { case productNotInCart } +/// Contains necessary data for handling the remote response from loading a site's current plan. +/// The fields are all optional because only the current plan has these fields. +private struct SiteCurrentPlanResponse: Decodable { + let isCurrentPlan: Bool? + let hasDomainCredit: Bool? + + private enum CodingKeys: String, CodingKey { + case isCurrentPlan = "current_plan" + case hasDomainCredit = "has_domain_credit" + } +} + /// Contains necessary data for handling the remote response from creating a cart. private struct CreateCartResponse: Decodable { let products: [Product] diff --git a/Networking/Networking/Requests/DotcomRequest.swift b/Networking/Networking/Requests/DotcomRequest.swift index 19323ff81bc..79eb0e89b31 100644 --- a/Networking/Networking/Requests/DotcomRequest.swift +++ b/Networking/Networking/Requests/DotcomRequest.swift @@ -53,7 +53,7 @@ struct DotcomRequest: Request { func responseDataValidator() -> ResponseDataValidator { switch wordpressApiVersion { - case .mark1_1, .mark1_2, .mark1_5: + case .mark1_1, .mark1_2, .mark1_3, .mark1_5: return DotcomValidator() case .wpcomMark2, .wpMark2: return WordPressApiValidator() diff --git a/Networking/Networking/Settings/WordPressAPIVersion.swift b/Networking/Networking/Settings/WordPressAPIVersion.swift index 5d90e18743b..0a9ce66f00c 100644 --- a/Networking/Networking/Settings/WordPressAPIVersion.swift +++ b/Networking/Networking/Settings/WordPressAPIVersion.swift @@ -13,6 +13,10 @@ enum WordPressAPIVersion: String { /// case mark1_2 = "rest/v1.2/" + /// WordPress.com Endpoint Mark 1.3 + /// + case mark1_3 = "rest/v1.3/" + /// WordPress.com Endpoint Mark 1.5 /// case mark1_5 = "rest/v1.5/" diff --git a/Networking/NetworkingTests/Remote/DomainRemoteTests.swift b/Networking/NetworkingTests/Remote/DomainRemoteTests.swift index fb3559438d1..80dd34bae40 100644 --- a/Networking/NetworkingTests/Remote/DomainRemoteTests.swift +++ b/Networking/NetworkingTests/Remote/DomainRemoteTests.swift @@ -16,6 +16,8 @@ final class DomainRemoteTests: XCTestCase { super.tearDown() } + // MARK: - `loadFreeDomainSuggestions` + func test_loadFreeDomainSuggestions_returns_suggestions_on_success() async throws { // Given let remote = DomainRemote(network: network) @@ -37,4 +39,32 @@ final class DomainRemoteTests: XCTestCase { await assertThrowsError({_ = try await remote.loadFreeDomainSuggestions(query: "domain")}, errorAssert: { ($0 as? NetworkError) == .notFound }) } + + // MARK: - `loadDomains` + + func test_loadDomains_returns_domains_on_success() async throws { + // Given + let remote = DomainRemote(network: network) + network.simulateResponse(requestUrlSuffix: "domains", filename: "site-domains") + + // When + let domains = try await remote.loadDomains(siteID: 23) + + // Then + let dateFormatter = DateFormatter() + dateFormatter.dateFormat = "MMMM d, yyyy" + let renewalDate = try XCTUnwrap(dateFormatter.date(from: "December 10, 2023")) + XCTAssertEqual(domains, [ + .init(name: "crabparty.wpcomstaging.com", isPrimary: true), + .init(name: "crabparty.com", isPrimary: false, renewalDate: renewalDate), + .init(name: "crabparty.wordpress.com", isPrimary: false) + ]) + } + + func test_loadDomains_returns_error_on_empty_response() async throws { + // Given + let remote = DomainRemote(network: network) + + await assertThrowsError({_ = try await remote.loadDomains(siteID: 23)}, errorAssert: { ($0 as? NetworkError) == .notFound }) + } } diff --git a/Networking/NetworkingTests/Remote/PaymentRemoteTests.swift b/Networking/NetworkingTests/Remote/PaymentRemoteTests.swift index 7f70b53009c..23eb3c68112 100644 --- a/Networking/NetworkingTests/Remote/PaymentRemoteTests.swift +++ b/Networking/NetworkingTests/Remote/PaymentRemoteTests.swift @@ -59,6 +59,47 @@ final class PaymentRemoteTests: XCTestCase { } } + // MARK: - `loadSiteCurrentPlan` + + func test_loadSiteCurrentPlan_returns_site_plan_on_success() async throws { + // Given + let remote = PaymentRemote(network: network) + network.simulateResponse(requestUrlSuffix: "plans", filename: "load-site-current-plan-success") + + // When + let plan = try await remote.loadSiteCurrentPlan(siteID: 134) + + // Then + XCTAssertEqual(plan, .init(hasDomainCredit: false)) + } + + func test_loadSiteCurrentPlan_returns_noCurrentPlan_error_when_response_has_no_current_plan() async throws { + // Given + let remote = PaymentRemote(network: network) + network.simulateResponse(requestUrlSuffix: "plans", filename: "load-site-plans-no-current-plan") + + // When + await assertThrowsError { + _ = try await remote.loadSiteCurrentPlan(siteID: 6) + } errorAssert: { error in + // Then + (error as? LoadSiteCurrentPlanError) == LoadSiteCurrentPlanError.noCurrentPlan + } + } + + func test_loadSiteCurrentPlan_throws_notFound_error_when_no_response() async throws { + // Given + let remote = PaymentRemote(network: network) + + // When + await assertThrowsError { + _ = try await remote.loadSiteCurrentPlan(siteID: 6) + } errorAssert: { error in + // Then + (error as? NetworkError) == .notFound + } + } + // MARK: - `createCart` func test_createCart_returns_on_success() async throws { diff --git a/Networking/NetworkingTests/Responses/load-site-current-plan-success.json b/Networking/NetworkingTests/Responses/load-site-current-plan-success.json new file mode 100644 index 00000000000..784d457cf82 --- /dev/null +++ b/Networking/NetworkingTests/Responses/load-site-current-plan-success.json @@ -0,0 +1,53 @@ +{ + "1": { + "formatted_original_price": "US$0", + "raw_price": 0, + "formatted_price": "US$0", + "raw_discount": 0, + "formatted_discount": "US$0", + "product_slug": "free_plan", + "product_name": "WordPress.com Free", + "discount_reason": null, + "is_domain_upgrade": null, + "currency_code": "USD", + "interval": -1 + }, + "1008": { + "formatted_original_price": "US$0", + "raw_price": 300, + "formatted_price": "US$300", + "raw_discount": 0, + "formatted_discount": "US$0", + "product_slug": "business-bundle", + "product_name": "WordPress.com Business", + "discount_reason": null, + "is_domain_upgrade": null, + "currency_code": "USD", + "current_plan": true, + "user_is_owner": true, + "id": "", + "has_domain_credit": false, + "expiry": "2025-01-01T00:00:00+00:00", + "free_trial": false, + "subscribed_date": "2019-04-29T04:32:29+00:00", + "auto_renew": false, + "auto_renew_date": "2024-12-02T00:00:00+00:00", + "partner_name": "", + "user_facing_expiry": "2025-01-01T00:00:00+00:00", + "interval": 365 + }, + "1011": { + "formatted_original_price": "US$540", + "raw_price": 240, + "formatted_price": "US$240", + "raw_discount": 300, + "formatted_discount": "US$300", + "product_slug": "ecommerce-bundle", + "product_name": "WordPress.com eCommerce", + "discount_reason": "Your recent plan purchase is deducted from the price (US$540).", + "is_domain_upgrade": false, + "currency_code": "USD", + "can_start_trial": false, + "interval": 365 + } +} diff --git a/Networking/NetworkingTests/Responses/load-site-plans-no-current-plan.json b/Networking/NetworkingTests/Responses/load-site-plans-no-current-plan.json new file mode 100644 index 00000000000..9f1d24a0679 --- /dev/null +++ b/Networking/NetworkingTests/Responses/load-site-plans-no-current-plan.json @@ -0,0 +1,29 @@ +{ + "1": { + "formatted_original_price": "US$0", + "raw_price": 0, + "formatted_price": "US$0", + "raw_discount": 0, + "formatted_discount": "US$0", + "product_slug": "free_plan", + "product_name": "WordPress.com Free", + "discount_reason": null, + "is_domain_upgrade": null, + "currency_code": "USD", + "interval": -1 + }, + "1009": { + "formatted_original_price": "US$0", + "raw_price": 48, + "formatted_price": "US$48", + "raw_discount": 0, + "formatted_discount": "US$0", + "product_slug": "personal-bundle", + "product_name": "WordPress.com Personal", + "discount_reason": null, + "is_domain_upgrade": null, + "currency_code": "USD", + "can_start_trial": false, + "interval": 365 + } +} diff --git a/Networking/NetworkingTests/Responses/site-domains.json b/Networking/NetworkingTests/Responses/site-domains.json new file mode 100644 index 00000000000..6f6087e2cdd --- /dev/null +++ b/Networking/NetworkingTests/Responses/site-domains.json @@ -0,0 +1,217 @@ +{ + "domains": [ + { + "primary_domain": true, + "blog_id": 2023, + "subscription_id": null, + "can_manage_dns_records": false, + "can_manage_name_servers": false, + "can_update_contact_info": false, + "cannot_manage_dns_records_reason": null, + "cannot_manage_name_servers_reason": null, + "cannot_update_contact_info_reason": null, + "connection_mode": null, + "current_user_can_add_email": false, + "current_user_can_create_site_from_domain_only": true, + "current_user_cannot_add_email_reason": null, + "current_user_can_manage": true, + "current_user_is_owner": null, + "can_set_as_primary": true, + "domain": "crabparty.wpcomstaging.com", + "domain_notice_states": null, + "supports_domain_connect": null, + "email_forwards_count": 0, + "expiry": false, + "expiry_soon": false, + "expired": false, + "auto_renewing": false, + "pending_registration": false, + "pending_registration_time": "", + "has_registration": false, + "has_email_forward_dns_records": null, + "points_to_wpcom": true, + "privacy_available": false, + "private_domain": false, + "partner_domain": false, + "wpcom_domain": true, + "has_zone": false, + "is_renewable": false, + "is_redeemable": false, + "is_subdomain": true, + "is_eligible_for_inbound_transfer": false, + "is_locked": false, + "is_wpcom_staging_domain": true, + "transfer_away_eligible_at": null, + "type": "wpcom", + "registration_date": "", + "auto_renewal_date": "", + "google_apps_subscription": null, + "titan_mail_subscription": null, + "pending_whois_update": false, + "tld_maintenance_end_time": null, + "ssl_status": null, + "supports_gdpr_consent_management": false, + "supports_transfer_approval": false, + "domain_registration_agreement_url": "", + "contact_info_disclosure_available": false, + "contact_info_disclosed": false, + "renewable_until": null, + "redeemable_until": null, + "bundled_plan_subscription_id": null, + "product_slug": null, + "owner": "", + "pending_renewal": false, + "aftermarket_auction": false, + "aftermarket_auction_start": null, + "aftermarket_auction_end": null + }, + { + "primary_domain": false, + "blog_id": 2023, + "subscription_id": "20023245", + "can_manage_dns_records": true, + "can_manage_name_servers": true, + "can_update_contact_info": true, + "cannot_manage_dns_records_reason": null, + "cannot_manage_name_servers_reason": null, + "cannot_update_contact_info_reason": null, + "connection_mode": null, + "current_user_can_add_email": true, + "current_user_can_create_site_from_domain_only": false, + "current_user_cannot_add_email_reason": null, + "current_user_can_manage": true, + "current_user_is_owner": true, + "can_set_as_primary": true, + "domain": "crabparty.com", + "domain_notice_states": null, + "supports_domain_connect": null, + "email_forwards_count": 0, + "expiry": "January 9, 2024", + "expiry_soon": false, + "expired": false, + "auto_renewing": 1, + "pending_registration": false, + "pending_registration_time": "", + "has_registration": true, + "has_email_forward_dns_records": null, + "points_to_wpcom": false, + "privacy_available": true, + "private_domain": false, + "partner_domain": false, + "wpcom_domain": false, + "has_zone": true, + "is_renewable": true, + "is_redeemable": false, + "is_subdomain": false, + "is_eligible_for_inbound_transfer": true, + "is_locked": true, + "is_wpcom_staging_domain": false, + "transfer_away_eligible_at": "2023-03-10 04:11:04", + "type": "mapping", + "registration_date": "January 9, 2023", + "auto_renewal_date": "December 10, 2023", + "google_apps_subscription": { + "status": "no_subscription", + "is_eligible_for_introductory_offer": false + }, + "titan_mail_subscription": { + "status": "no_subscription", + "is_eligible_for_introductory_offer": true + }, + "pending_whois_update": false, + "tld_maintenance_end_time": 0, + "ssl_status": "pending", + "supports_gdpr_consent_management": false, + "supports_transfer_approval": true, + "domain_registration_agreement_url": "https://wordpress.com/automattic-domain-name-registration-agreement/", + "contact_info_disclosure_available": true, + "contact_info_disclosed": false, + "renewable_until": "February 21, 2024", + "redeemable_until": null, + "bundled_plan_subscription_id": null, + "product_slug": "domain_reg", + "owner": "Jaclyn Chen (wasseryi)", + "pending_renewal": false, + "aftermarket_auction": false, + "aftermarket_auction_start": null, + "aftermarket_auction_end": null, + "has_private_registration": false, + "is_pending_icann_verification": true, + "manual_transfer_required": false, + "is_icann_verification_suspended": false, + "registrar": "KS_RAM", + "domain_locking_available": true, + "is_premium": false, + "transfer_lock_on_whois_update_optional": true, + "whois_update_unmodifiable_fields": [], + "is_whois_editable": true, + "pending_transfer": false, + "has_wpcom_nameservers": true + }, + { + "primary_domain": false, + "blog_id": 2023, + "subscription_id": null, + "can_manage_dns_records": false, + "can_manage_name_servers": false, + "can_update_contact_info": false, + "cannot_manage_dns_records_reason": null, + "cannot_manage_name_servers_reason": null, + "cannot_update_contact_info_reason": null, + "connection_mode": null, + "current_user_can_add_email": false, + "current_user_can_create_site_from_domain_only": true, + "current_user_cannot_add_email_reason": null, + "current_user_can_manage": true, + "current_user_is_owner": null, + "can_set_as_primary": true, + "domain": "crabparty.wordpress.com", + "domain_notice_states": null, + "supports_domain_connect": null, + "email_forwards_count": 0, + "expiry": false, + "expiry_soon": false, + "expired": false, + "auto_renewing": false, + "pending_registration": false, + "pending_registration_time": "", + "has_registration": false, + "has_email_forward_dns_records": null, + "points_to_wpcom": true, + "privacy_available": false, + "private_domain": false, + "partner_domain": false, + "wpcom_domain": true, + "has_zone": false, + "is_renewable": false, + "is_redeemable": false, + "is_subdomain": true, + "is_eligible_for_inbound_transfer": false, + "is_locked": false, + "is_wpcom_staging_domain": false, + "transfer_away_eligible_at": null, + "type": "wpcom", + "registration_date": "", + "auto_renewal_date": "", + "google_apps_subscription": null, + "titan_mail_subscription": null, + "pending_whois_update": false, + "tld_maintenance_end_time": null, + "ssl_status": null, + "supports_gdpr_consent_management": false, + "supports_transfer_approval": false, + "domain_registration_agreement_url": "", + "contact_info_disclosure_available": false, + "contact_info_disclosed": false, + "renewable_until": null, + "redeemable_until": null, + "bundled_plan_subscription_id": null, + "product_slug": null, + "owner": "", + "pending_renewal": false, + "aftermarket_auction": false, + "aftermarket_auction_start": null, + "aftermarket_auction_end": null + } + ] +} diff --git a/WooCommerce/Classes/ViewRelated/Dashboard/Settings/Domains/DomainSettingsView.swift b/WooCommerce/Classes/ViewRelated/Dashboard/Settings/Domains/DomainSettingsView.swift index ed43261a4b5..a5f8197041e 100644 --- a/WooCommerce/Classes/ViewRelated/Dashboard/Settings/Domains/DomainSettingsView.swift +++ b/WooCommerce/Classes/ViewRelated/Dashboard/Settings/Domains/DomainSettingsView.swift @@ -131,10 +131,7 @@ struct DomainSettingsView_Previews: PreviewProvider { .init(name: "duo.test", isPrimary: true, renewalDate: .now) ]), // The site has domain credit. - sitePlanResult: .success(.init(plan: .init(productID: 0, - name: "", - formattedPrice: ""), - hasDomainCredit: true))))) + sitePlanResult: .success(.init(hasDomainCredit: true))))) } NavigationView { @@ -145,10 +142,7 @@ struct DomainSettingsView_Previews: PreviewProvider { domainsResult: .success([ .init(name: "free.test", isPrimary: true) ]), - sitePlanResult: .success(.init(plan: .init(productID: 0, - name: "", - formattedPrice: ""), - hasDomainCredit: true))))) + sitePlanResult: .success(.init(hasDomainCredit: true))))) } } } From d4330c3bc80040cfc7184cbef25346c134636c59 Mon Sep 17 00:00:00 2001 From: Jaclyn Chen Date: Tue, 10 Jan 2023 10:38:56 +0800 Subject: [PATCH 2/2] Fix build errors. --- Yosemite/Yosemite/Stores/PaymentStore.swift | 2 +- .../Mocks/Networking/Remote/MockDomainRemote.swift | 5 +++++ .../Mocks/Networking/Remote/MockPaymentRemote.swift | 5 +++++ 3 files changed, 11 insertions(+), 1 deletion(-) diff --git a/Yosemite/Yosemite/Stores/PaymentStore.swift b/Yosemite/Yosemite/Stores/PaymentStore.swift index 87f910686a1..45ef7c0af31 100644 --- a/Yosemite/Yosemite/Stores/PaymentStore.swift +++ b/Yosemite/Yosemite/Stores/PaymentStore.swift @@ -64,7 +64,7 @@ private extension PaymentStore { func loadSiteCurrentPlan(siteID: Int64, completion: (Result) -> Void) { // TODO: 8558 - fetch site's current plan - completion(.success(.init(plan: .init(productID: 0, name: "", formattedPrice: ""), hasDomainCredit: true))) + completion(.success(.init(hasDomainCredit: true))) } func createCart(productID: String, diff --git a/Yosemite/YosemiteTests/Mocks/Networking/Remote/MockDomainRemote.swift b/Yosemite/YosemiteTests/Mocks/Networking/Remote/MockDomainRemote.swift index d62891b695c..97874da9932 100644 --- a/Yosemite/YosemiteTests/Mocks/Networking/Remote/MockDomainRemote.swift +++ b/Yosemite/YosemiteTests/Mocks/Networking/Remote/MockDomainRemote.swift @@ -21,4 +21,9 @@ extension MockDomainRemote: DomainRemoteProtocol { } return try result.get() } + + func loadDomains(siteID: Int64) async throws -> [SiteDomain] { + // TODO: 8558 - Yosemite layer + throw NetworkError.notFound + } } diff --git a/Yosemite/YosemiteTests/Mocks/Networking/Remote/MockPaymentRemote.swift b/Yosemite/YosemiteTests/Mocks/Networking/Remote/MockPaymentRemote.swift index fcf2d88d31f..9d92e08f907 100644 --- a/Yosemite/YosemiteTests/Mocks/Networking/Remote/MockPaymentRemote.swift +++ b/Yosemite/YosemiteTests/Mocks/Networking/Remote/MockPaymentRemote.swift @@ -30,6 +30,11 @@ extension MockPaymentRemote: PaymentRemoteProtocol { return try result.get() } + func loadSiteCurrentPlan(siteID: Int64) async throws -> WPComSitePlan { + // TODO: 8558 - Yosemite layer + throw NetworkError.notFound + } + func createCart(siteID: Int64, productID: Int64) async throws { guard let result = createCartResult else { XCTFail("Could not find result for creating a cart.")