Skip to content
Merged
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
12 changes: 12 additions & 0 deletions Networking/Networking.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@
021EAA5625493B3600AA8CCD /* OrderItemAttribute.swift in Sources */ = {isa = PBXBuildFile; fileRef = 021EAA5525493B3600AA8CCD /* OrderItemAttribute.swift */; };
022902D422E2436400059692 /* stats_module_disabled_error.json in Resources */ = {isa = PBXBuildFile; fileRef = 022902D122E2436300059692 /* stats_module_disabled_error.json */; };
022902D622E2436400059692 /* no_stats_permission_error.json in Resources */ = {isa = PBXBuildFile; fileRef = 022902D322E2436400059692 /* no_stats_permission_error.json */; };
023930632918FF5400B2632F /* DomainRemote.swift in Sources */ = {isa = PBXBuildFile; fileRef = 023930622918FF5400B2632F /* DomainRemote.swift */; };
0239306B291A96F800B2632F /* DomainRemoteTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0239306A291A96F800B2632F /* DomainRemoteTests.swift */; };
0239306D291A973F00B2632F /* domain-suggestions.json in Resources */ = {isa = PBXBuildFile; fileRef = 0239306C291A973F00B2632F /* domain-suggestions.json */; };
025CA2C0238EB8CB00B05C81 /* ProductShippingClass.swift in Sources */ = {isa = PBXBuildFile; fileRef = 025CA2BF238EB8CB00B05C81 /* ProductShippingClass.swift */; };
025CA2C2238EBBAA00B05C81 /* ProductShippingClassListMapper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 025CA2C1238EBBAA00B05C81 /* ProductShippingClassListMapper.swift */; };
025CA2C4238EBC4300B05C81 /* ProductShippingClassRemote.swift in Sources */ = {isa = PBXBuildFile; fileRef = 025CA2C3238EBC4300B05C81 /* ProductShippingClassRemote.swift */; };
Expand Down Expand Up @@ -767,6 +770,9 @@
021EAA5525493B3600AA8CCD /* OrderItemAttribute.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OrderItemAttribute.swift; sourceTree = "<group>"; };
022902D122E2436300059692 /* stats_module_disabled_error.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = stats_module_disabled_error.json; sourceTree = "<group>"; };
022902D322E2436400059692 /* no_stats_permission_error.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = no_stats_permission_error.json; sourceTree = "<group>"; };
023930622918FF5400B2632F /* DomainRemote.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DomainRemote.swift; sourceTree = "<group>"; };
0239306A291A96F800B2632F /* DomainRemoteTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DomainRemoteTests.swift; sourceTree = "<group>"; };
0239306C291A973F00B2632F /* domain-suggestions.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = "domain-suggestions.json"; sourceTree = "<group>"; };
025CA2BF238EB8CB00B05C81 /* ProductShippingClass.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProductShippingClass.swift; sourceTree = "<group>"; };
025CA2C1238EBBAA00B05C81 /* ProductShippingClassListMapper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProductShippingClassListMapper.swift; sourceTree = "<group>"; };
025CA2C3238EBC4300B05C81 /* ProductShippingClassRemote.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProductShippingClassRemote.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -1720,6 +1726,7 @@
DE34051E28BDFB0B00CF0D97 /* JetpackConnectionRemoteTests.swift */,
68BD37B228D9B8BD00C2A517 /* CustomerRemoteTests.swift */,
68F48B0E28E3BB850045C15B /* WCAnalyticsCustomerRemoteTests.swift */,
0239306A291A96F800B2632F /* DomainRemoteTests.swift */,
);
path = Remote;
sourceTree = "<group>";
Expand Down Expand Up @@ -1859,6 +1866,7 @@
AEF94584272974F2001DCCFB /* TelemetryRemote.swift */,
68CB800F28D89A0400E169F8 /* CustomerRemote.swift */,
68F48B0A28E3B1CD0045C15B /* WCAnalyticsCustomerRemote.swift */,
023930622918FF5400B2632F /* DomainRemote.swift */,
);
path = Remote;
sourceTree = "<group>";
Expand Down Expand Up @@ -1985,6 +1993,7 @@
028CB713290223CB00331C09 /* create-account-error-password.json */,
028CB71A290224D700331C09 /* create-account-error-username.json */,
028CB712290223CB00331C09 /* create-account-success.json */,
0239306C291A973F00B2632F /* domain-suggestions.json */,
DE50295F28C609A300551736 /* jetpack-connected-user.json */,
DE34051A28BDF12C00CF0D97 /* jetpack-connection-url.json */,
DE50296228C609DE00551736 /* jetpack-user-not-connected.json */,
Expand Down Expand Up @@ -2886,6 +2895,7 @@
3158FE8426129F3A00E566B9 /* wcpay-account-unknown-status.json in Resources */,
314EDF2B27C02CD300A56B6F /* stripe-account-complete-null-descriptor.json in Resources */,
31054720262E2F9D00C5C02B /* wcpay-payment-intent-processing.json in Resources */,
0239306D291A973F00B2632F /* domain-suggestions.json in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down Expand Up @@ -2964,6 +2974,7 @@
26455E2425F66982008A1D32 /* ProductAttributeTermRemote.swift in Sources */,
036563DD29069BE400D84BFD /* JustInTimeMessageListMapper.swift in Sources */,
7426CA0D21AF27B9004E9FFC /* SiteAPIRemote.swift in Sources */,
023930632918FF5400B2632F /* DomainRemote.swift in Sources */,
451A97D1260A03900059D135 /* ShippingLabelCustomPackage.swift in Sources */,
DE34051328BDCA5100CF0D97 /* WordPressOrgRequest.swift in Sources */,
D88D5A45230BC6F9007B6E01 /* ProductReviewsRemote.swift in Sources */,
Expand Down Expand Up @@ -3338,6 +3349,7 @@
74AB5B4D21AF354E00859C12 /* SiteAPIMapperTests.swift in Sources */,
68F48B0F28E3BB850045C15B /* WCAnalyticsCustomerRemoteTests.swift in Sources */,
93D8BC01226BC20600AD2EB3 /* AccountSettingsRemoteTests.swift in Sources */,
0239306B291A96F800B2632F /* DomainRemoteTests.swift in Sources */,
262E5AD5255ACD6F000B2416 /* PaymentGatewayListMapperTests.swift in Sources */,
03DCB7442624AD9B00C8953D /* CouponListMapperTests.swift in Sources */,
AE2D6623272A8F6E004A2C3A /* TelemetryRemoteTests.swift in Sources */,
Expand Down
68 changes: 68 additions & 0 deletions Networking/Networking/Remote/DomainRemote.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import Foundation

/// Protocol for `DomainRemote` mainly used for mocking.
public protocol DomainRemoteProtocol {
/// Loads domain suggestions that are free (`*.wordpress.com` only) based on the query.
/// - Parameter query: What the domain suggestions are based on.
/// - Returns: The result of free domain suggestions.
func loadFreeDomainSuggestions(query: String) async -> Result<[FreeDomainSuggestion], Error>
}

/// Domain: Remote Endpoints
///
public class DomainRemote: Remote, DomainRemoteProtocol {
public func loadFreeDomainSuggestions(query: String) async -> Result<[FreeDomainSuggestion], Error> {
let path = Path.domainSuggestions
let parameters: [String: Any] = [
ParameterKey.query: query,
ParameterKey.quantity: Defaults.domainSuggestionsQuantity,
ParameterKey.wordPressDotComSubdomainsOnly: true
]
let request = DotcomRequest(wordpressApiVersion: .mark1_1, method: .get, path: path, parameters: parameters)
do {
let suggestions: [FreeDomainSuggestion] = try await enqueue(request)
return .success(suggestions)
} catch {
return .failure(error)
}
}
}

/// Necessary data for a free domain suggestion.
public struct FreeDomainSuggestion: Decodable, Equatable {
/// Domain name.
public let name: String
/// Theoretically `true` for all domains in the result, but the client side can still filter any exceptions in the UI.
public let isFree: Bool

public init(name: String, isFree: Bool) {
self.name = name
self.isFree = isFree
}

private enum CodingKeys: String, CodingKey {
case name = "domain_name"
case isFree = "is_free"
}
}

// MARK: - Constants
//
private extension DomainRemote {
enum Defaults {
static let domainSuggestionsQuantity = 20
}

enum ParameterKey {
/// Term (e.g "flowers") or domain name (e.g. "flowers.com") to search alternative domain names from.
static let query = "query"
/// Maximum number of suggestions to return.
static let quantity = "quantity"
/// Whether to restrict suggestions to only wordpress.com subdomains. If `true`, only `quantity` and `query` parameters are respected.
static let wordPressDotComSubdomainsOnly = "only_wordpressdotcom"
}

enum Path {
static let domainSuggestions = "domains/suggestions"
}
}
47 changes: 47 additions & 0 deletions Networking/NetworkingTests/Remote/DomainRemoteTests.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import XCTest
@testable import Networking

final class DomainRemoteTests: XCTestCase {
/// Mock network wrapper.
private var network: MockNetwork!

override func setUp() {
super.setUp()
network = MockNetwork()
}

override func tearDown() {
network = nil
super.tearDown()
}

func test_loadFreeDomainSuggestions_returns_suggestions_on_success() async throws {
// Given
let remote = DomainRemote(network: network)
network.simulateResponse(requestUrlSuffix: "domains/suggestions", filename: "domain-suggestions")

// When
let result = await remote.loadFreeDomainSuggestions(query: "domain")

// Then
XCTAssertTrue(result.isSuccess)
let suggestions = try XCTUnwrap(result.get())
XCTAssertEqual(suggestions, [
.init(name: "domaintestingtips.wordpress.com", isFree: true),
.init(name: "domaintestingtoday.wordpress.com", isFree: true),
])
}

func test_loadFreeDomainSuggestions_returns_error_on_empty_response() async throws {
// Given
let remote = DomainRemote(network: network)

// When
let result = await remote.loadFreeDomainSuggestions(query: "domain")

// Then
XCTAssertTrue(result.isFailure)
let error = try XCTUnwrap(result.failure as? NetworkError)
XCTAssertEqual(error, .notFound)
}
}
12 changes: 12 additions & 0 deletions Networking/NetworkingTests/Responses/domain-suggestions.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
[
{
"domain_name": "domaintestingtips.wordpress.com",
"cost": "Free",
"is_free": true
},
{
"domain_name": "domaintestingtoday.wordpress.com",
"cost": "Free",
"is_free": true
}
]
16 changes: 16 additions & 0 deletions Yosemite/Yosemite.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@
022F9319257F24730011CD94 /* MockShippingLabel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 022F9318257F24730011CD94 /* MockShippingLabel.swift */; };
022F931D257F27B40011CD94 /* MockShippingLabelAddress.swift in Sources */ = {isa = PBXBuildFile; fileRef = 022F931C257F27B40011CD94 /* MockShippingLabelAddress.swift */; };
0232372922F7DA6E00715FAB /* StatsTimeRangeV4.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0232372822F7DA6E00715FAB /* StatsTimeRangeV4.swift */; };
02393065291A018600B2632F /* DomainAction.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02393064291A018600B2632F /* DomainAction.swift */; };
02393067291A02AC00B2632F /* DomainStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02393066291A02AC00B2632F /* DomainStore.swift */; };
0248B3652459018100A271A4 /* ResultsController+FilterProducts.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0248B3642459018100A271A4 /* ResultsController+FilterProducts.swift */; };
0248B3672459020500A271A4 /* ResultsController+FilterProductTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0248B3662459020500A271A4 /* ResultsController+FilterProductTests.swift */; };
0248B36924590FC300A271A4 /* ProductStore+FilterProductsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0248B36824590FC300A271A4 /* ProductStore+FilterProductsTests.swift */; };
Expand All @@ -65,6 +67,8 @@
02C254FA2563B66600A04423 /* ShippingLabelRefund+ReadOnlyConvertible.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02C254F92563B66600A04423 /* ShippingLabelRefund+ReadOnlyConvertible.swift */; };
02C254FE2563C6E500A04423 /* ShippingLabelSettings+ReadOnlyConvertible.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02C254FD2563C6E500A04423 /* ShippingLabelSettings+ReadOnlyConvertible.swift */; };
02C255022563C76A00A04423 /* ShippingLabel+ReadOnlyConvertible.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02C255012563C76A00A04423 /* ShippingLabel+ReadOnlyConvertible.swift */; };
02DAE7F8291A9F11009342B7 /* DomainStoreTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02DAE7F7291A9F11009342B7 /* DomainStoreTests.swift */; };
02DAE7FA291A9F36009342B7 /* MockDomainRemote.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02DAE7F9291A9F36009342B7 /* MockDomainRemote.swift */; };
02E262BD238CE46A00B79588 /* ShippingSettingsService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02E262BC238CE46A00B79588 /* ShippingSettingsService.swift */; };
02E262C0238CE80100B79588 /* StorageShippingSettingsServiceTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02E262BF238CE80100B79588 /* StorageShippingSettingsServiceTests.swift */; };
02E262C2238CF74D00B79588 /* StorageShippingSettingsService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02E262C1238CF74D00B79588 /* StorageShippingSettingsService.swift */; };
Expand Down Expand Up @@ -456,6 +460,8 @@
022F9318257F24730011CD94 /* MockShippingLabel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockShippingLabel.swift; sourceTree = "<group>"; };
022F931C257F27B40011CD94 /* MockShippingLabelAddress.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockShippingLabelAddress.swift; sourceTree = "<group>"; };
0232372822F7DA6E00715FAB /* StatsTimeRangeV4.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StatsTimeRangeV4.swift; sourceTree = "<group>"; };
02393064291A018600B2632F /* DomainAction.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DomainAction.swift; sourceTree = "<group>"; };
02393066291A02AC00B2632F /* DomainStore.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DomainStore.swift; sourceTree = "<group>"; };
0248B3642459018100A271A4 /* ResultsController+FilterProducts.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "ResultsController+FilterProducts.swift"; sourceTree = "<group>"; };
0248B3662459020500A271A4 /* ResultsController+FilterProductTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "ResultsController+FilterProductTests.swift"; sourceTree = "<group>"; };
0248B36824590FC300A271A4 /* ProductStore+FilterProductsTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "ProductStore+FilterProductsTests.swift"; sourceTree = "<group>"; };
Expand All @@ -482,6 +488,8 @@
02C254F92563B66600A04423 /* ShippingLabelRefund+ReadOnlyConvertible.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "ShippingLabelRefund+ReadOnlyConvertible.swift"; sourceTree = "<group>"; };
02C254FD2563C6E500A04423 /* ShippingLabelSettings+ReadOnlyConvertible.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "ShippingLabelSettings+ReadOnlyConvertible.swift"; sourceTree = "<group>"; };
02C255012563C76A00A04423 /* ShippingLabel+ReadOnlyConvertible.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "ShippingLabel+ReadOnlyConvertible.swift"; sourceTree = "<group>"; };
02DAE7F7291A9F11009342B7 /* DomainStoreTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DomainStoreTests.swift; sourceTree = "<group>"; };
02DAE7F9291A9F36009342B7 /* MockDomainRemote.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockDomainRemote.swift; sourceTree = "<group>"; };
02E262BC238CE46A00B79588 /* ShippingSettingsService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShippingSettingsService.swift; sourceTree = "<group>"; };
02E262BF238CE80100B79588 /* StorageShippingSettingsServiceTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StorageShippingSettingsServiceTests.swift; sourceTree = "<group>"; };
02E262C1238CF74D00B79588 /* StorageShippingSettingsService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StorageShippingSettingsService.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -1188,6 +1196,7 @@
02A26F1D2744FE97008E4EDB /* MockAccountRemote.swift */,
029249E7274B8AEE002E9C34 /* MockMediaRemote.swift */,
021BA0C328576940006E9886 /* MockDotcomAccountRemote.swift */,
02DAE7F9291A9F36009342B7 /* MockDomainRemote.swift */,
);
path = Remote;
sourceTree = "<group>";
Expand Down Expand Up @@ -1399,6 +1408,7 @@
DE3404FD28BC5F4200CF0D97 /* JetpackConnectionStore.swift */,
68BD37B428DB2E9800C2A517 /* CustomerStore.swift */,
02E3B622290267D3007E0F13 /* AccountCreationStore.swift */,
02393066291A02AC00B2632F /* DomainStore.swift */,
);
path = Stores;
sourceTree = "<group>";
Expand Down Expand Up @@ -1458,6 +1468,7 @@
DE50296628C7114800551736 /* JetpackConnectionStoreTests.swift */,
68BD37B828DB323D00C2A517 /* CustomerStoreTests.swift */,
02E3B629290622DE007E0F13 /* AccountCreationStoreTests.swift */,
02DAE7F7291A9F11009342B7 /* DomainStoreTests.swift */,
);
path = Stores;
sourceTree = "<group>";
Expand Down Expand Up @@ -1643,6 +1654,7 @@
B9AECD3D2850F41100E78584 /* OrderCardPresentPaymentEligibilityAction.swift */,
DE3404FB28BC5E7800CF0D97 /* JetpackConnectionAction.swift */,
02E3B624290267F2007E0F13 /* AccountCreationAction.swift */,
02393064291A018600B2632F /* DomainAction.swift */,
);
path = Actions;
sourceTree = "<group>";
Expand Down Expand Up @@ -2036,6 +2048,7 @@
2618707C2540B6A4006522A1 /* ShippingLineTax+ReadOnlyConvertible.swift in Sources */,
749375002249605E007D85D1 /* ProductAction.swift in Sources */,
D831E2E4230E3524000037D0 /* ProductReviewAction.swift in Sources */,
02393065291A018600B2632F /* DomainAction.swift in Sources */,
D831E2E6230E7149000037D0 /* ProductReview+ReadOnlyConvertible.swift in Sources */,
CE4FD4502350F27C00A16B31 /* OrderItemTax+ReadOnlyConvertible.swift in Sources */,
02FF055123D983F30058E6E7 /* MediaAssetExporter.swift in Sources */,
Expand Down Expand Up @@ -2162,6 +2175,7 @@
453305F7245AE68C00264E50 /* SitePostStore.swift in Sources */,
026CF62A237D92C6009563D4 /* ProductVariation+ReadOnlyConvertible.swift in Sources */,
02F6AAAC270556A4002425D0 /* Models+Copiable.generated.swift in Sources */,
02393067291A02AC00B2632F /* DomainStore.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down Expand Up @@ -2192,6 +2206,7 @@
E1F54D0427AD4DAF00012983 /* CardPresentConfigurationTests.swift in Sources */,
025CA2D0238F54E800B05C81 /* ProductShippingClassStoreTests.swift in Sources */,
74A7688E20D45ED400F9D437 /* OrderStoreTests.swift in Sources */,
02DAE7F8291A9F11009342B7 /* DomainStoreTests.swift in Sources */,
D8652E322630741000350F37 /* PaymentIntent+ReceiptParametersTests.swift in Sources */,
029249E8274B8AEE002E9C34 /* MockMediaRemote.swift in Sources */,
021BA0C428576940006E9886 /* MockDotcomAccountRemote.swift in Sources */,
Expand Down Expand Up @@ -2249,6 +2264,7 @@
265BCA0024301ACD004E53EE /* ProductCategoryStoreTests.swift in Sources */,
02FF056D23DEDCB90058E6E7 /* MockImageSourceWriter.swift in Sources */,
FE28F6F2268462A6004465C7 /* UserStoreTests.swift in Sources */,
02DAE7FA291A9F36009342B7 /* MockDomainRemote.swift in Sources */,
741F34842195F752005F5BD9 /* CommentStoreTests.swift in Sources */,
B5C9DE282087FF20006B910A /* MockSiteStore.swift in Sources */,
FEEB2F5F268A1C5E0075A6E0 /* User+RolesTests.swift in Sources */,
Expand Down
7 changes: 7 additions & 0 deletions Yosemite/Yosemite/Actions/DomainAction.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import Foundation

// MARK: - DomainAction: Defines all of the Actions supported by the DomainStore.
//
public enum DomainAction: Action {
case loadFreeDomainSuggestions(query: String, completion: (Result<[FreeDomainSuggestion], Error>) -> Void)
}
Loading