Skip to content

Commit 521df64

Browse files
committed
♻️ Refactor lookupURL, searchURL
Resolves unused protocol method lint warnings by moving updated implementations back to StoreSearch. Added `country` to MasStoreSearch, set to fixed fvalue for tests.
1 parent 5aafd4c commit 521df64

File tree

3 files changed

+38
-71
lines changed

3 files changed

+38
-71
lines changed

Sources/MasKit/Controllers/MasStoreSearch.swift

Lines changed: 18 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -13,58 +13,25 @@ import Version
1313

1414
/// Manages searching the MAS catalog through the iTunes Search and Lookup APIs.
1515
class MasStoreSearch: StoreSearch {
16-
private let networkManager: NetworkManager
1716
private static let appVersionExpression = Regex(#"\"versionDisplay\"\:\"([^\"]+)\""#)
1817

19-
enum Entity: String {
20-
case macSoftware
21-
case iPadSoftware
22-
case iPhoneSoftware = "software"
23-
}
18+
// CommerceKit and StoreFoundation don't seem to expose the region of the Apple ID signed
19+
// into the App Store. Instead, we'll make an educated guess that it matches the currently
20+
// selected locale in macOS. This obviously isn't always going to match, but it's probably
21+
// better than passing no "country" at all to the iTunes Search API.
22+
// https://affiliate.itunes.apple.com/resources/documentation/itunes-store-web-service-search-api/
23+
private let country: String?
24+
private let networkManager: NetworkManager
2425

2526
/// Designated initializer.
26-
init(networkManager: NetworkManager = NetworkManager()) {
27+
init(
28+
country: String? = Locale.autoupdatingCurrent.regionCode,
29+
networkManager: NetworkManager = NetworkManager()
30+
) {
31+
self.country = country
2732
self.networkManager = networkManager
2833
}
2934

30-
/// Builds the search URL for an app.
31-
///
32-
/// - Parameter appName: MAS app identifier.
33-
/// - Returns: URL for the search service or nil if appName can't be encoded.
34-
static func searchURL(for appName: String, ofEntity entity: Entity = .macSoftware) -> URL {
35-
guard var components = URLComponents(string: "https://itunes.apple.com/search") else {
36-
fatalError("URLComponents failed to parse URL.")
37-
}
38-
39-
components.queryItems = [
40-
URLQueryItem(name: "media", value: "software"),
41-
URLQueryItem(name: "entity", value: entity.rawValue),
42-
URLQueryItem(name: "term", value: appName),
43-
]
44-
guard let url = components.url else {
45-
fatalError("URLComponents failed to generate URL.")
46-
}
47-
48-
return url
49-
}
50-
51-
/// Builds the lookup URL for an app.
52-
///
53-
/// - Parameter appId: MAS app identifier.
54-
/// - Returns: URL for the lookup service or nil if appId can't be encoded.
55-
static func lookupURL(forApp appId: Int) -> URL {
56-
guard var components = URLComponents(string: "https://itunes.apple.com/lookup") else {
57-
fatalError("URLComponents failed to parse URL.")
58-
}
59-
60-
components.queryItems = [URLQueryItem(name: "id", value: "\(appId)")]
61-
guard let url = components.url else {
62-
fatalError("URLComponents failed to generate URL.")
63-
}
64-
65-
return url
66-
}
67-
6835
/// Searches for an app.
6936
///
7037
/// - Parameter appName: MAS ID of app
@@ -79,7 +46,9 @@ class MasStoreSearch: StoreSearch {
7946
}
8047

8148
let results = entities.map { entity -> Promise<[SearchResult]> in
82-
let url = MasStoreSearch.searchURL(for: appName, ofEntity: entity)
49+
guard let url = searchURL(for: appName, inCountry: country, ofEntity: entity) else {
50+
fatalError("Failed to build URL for \(appName)")
51+
}
8352
return loadSearchResults(url)
8453
}
8554

@@ -96,7 +65,9 @@ class MasStoreSearch: StoreSearch {
9665
/// - Returns: A Promise for the search result record of app, or nil if no apps match the ID,
9766
/// or an Error if there is a problem with the network request.
9867
func lookup(app appId: Int) -> Promise<SearchResult?> {
99-
let url = MasStoreSearch.lookupURL(forApp: appId)
68+
guard let url = lookupURL(forApp: appId, inCountry: country) else {
69+
fatalError("Failed to build URL for \(appId)")
70+
}
10071
return firstly {
10172
loadSearchResults(url)
10273
}.then { results -> Guarantee<SearchResult?> in

Sources/MasKit/Controllers/StoreSearch.swift

Lines changed: 12 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -6,34 +6,40 @@
66
// Copyright © 2018 mas-cli. All rights reserved.
77
//
88

9-
import PromiseKit
109
import Foundation
10+
import PromiseKit
1111

1212
/// Protocol for searching the MAS catalog.
1313
protocol StoreSearch {
1414
func lookup(app appId: Int) -> Promise<SearchResult?>
1515
func search(for appName: String) -> Promise<[SearchResult]>
1616
}
1717

18+
enum Entity: String {
19+
case macSoftware
20+
case iPadSoftware
21+
case iPhoneSoftware = "software"
22+
}
23+
1824
// MARK: - Common methods
1925
extension StoreSearch {
2026
/// Builds the search URL for an app.
2127
///
2228
/// - Parameter appName: MAS app identifier.
2329
/// - Returns: URL for the search service or nil if appName can't be encoded.
24-
func searchURL(for appName: String) -> URL? {
30+
func searchURL(for appName: String, inCountry country: String?, ofEntity entity: Entity = .macSoftware) -> URL? {
2531
guard var components = URLComponents(string: "https://itunes.apple.com/search") else {
2632
return nil
2733
}
2834

2935
components.queryItems = [
3036
URLQueryItem(name: "media", value: "software"),
31-
URLQueryItem(name: "entity", value: "macSoftware"),
37+
URLQueryItem(name: "entity", value: entity.rawValue),
3238
URLQueryItem(name: "term", value: appName),
3339
]
3440

3541
if let country {
36-
components.queryItems!.append(country)
42+
components.queryItems!.append(URLQueryItem(name: "country", value: country))
3743
}
3844

3945
return components.url
@@ -43,7 +49,7 @@ extension StoreSearch {
4349
///
4450
/// - Parameter appId: MAS app identifier.
4551
/// - Returns: URL for the lookup service or nil if appId can't be encoded.
46-
func lookupURL(forApp appId: Int) -> URL? {
52+
func lookupURL(forApp appId: Int, inCountry country: String?) -> URL? {
4753
guard var components = URLComponents(string: "https://itunes.apple.com/lookup") else {
4854
return nil
4955
}
@@ -54,22 +60,9 @@ extension StoreSearch {
5460
]
5561

5662
if let country {
57-
components.queryItems!.append(country)
63+
components.queryItems!.append(URLQueryItem(name: "country", value: country))
5864
}
5965

6066
return components.url
6167
}
62-
63-
private var country: URLQueryItem? {
64-
// CommerceKit and StoreFoundation don't seem to expose the region of the Apple ID signed
65-
// into the App Store. Instead, we'll make an educated guess that it matches the currently
66-
// selected locale in macOS. This obviously isn't always going to match, but it's probably
67-
// better than passing no "country" at all to the iTunes Search API.
68-
// https://affiliate.itunes.apple.com/resources/documentation/itunes-store-web-service-search-api/
69-
guard let region = Locale.autoupdatingCurrent.regionCode else {
70-
return nil
71-
}
72-
73-
return URLQueryItem(name: "country", value: region)
74-
}
7568
}

Tests/MasKitTests/Controllers/MasStoreSearchSpec.swift

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,15 +19,18 @@ public class MasStoreSearchSpec: QuickSpec {
1919
describe("url string") {
2020
it("contains the app name") {
2121
let appName = "myapp"
22-
let urlString = MasStoreSearch.searchURL(for: appName).absoluteString
23-
expect(urlString) == "https://itunes.apple.com/search?media=software&entity=macSoftware&term=\(appName)"
22+
let urlString = MasStoreSearch().searchURL(for: appName, inCountry: "US")?.absoluteString
23+
expect(urlString) == """
24+
https://itunes.apple.com/search?media=software&entity=macSoftware&term=\(appName)&country=US
25+
"""
2426
}
2527
it("contains the encoded app name") {
2628
let appName = "My App"
2729
let appNameEncoded = "My%20App"
28-
let urlString = MasStoreSearch.searchURL(for: appName).absoluteString
29-
expect(urlString)
30-
== "https://itunes.apple.com/search?media=software&entity=macSoftware&term=\(appNameEncoded)"
30+
let urlString = MasStoreSearch().searchURL(for: appName, inCountry: "US")?.absoluteString
31+
expect(urlString) == """
32+
https://itunes.apple.com/search?media=software&entity=macSoftware&term=\(appNameEncoded)&country=US
33+
"""
3134
}
3235
}
3336
describe("store") {

0 commit comments

Comments
 (0)