Skip to content

Commit f454995

Browse files
authored
Merge pull request #8095 from woocommerce/issue/8075-yosemite-plugin-management
Login: Update Yosemite layer to handle Jetpack plugin management with cookie authentication
2 parents 11235c7 + d158891 commit f454995

File tree

3 files changed

+176
-3
lines changed

3 files changed

+176
-3
lines changed

Yosemite/Yosemite/Actions/JetpackConnectionAction.swift

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,12 @@ public enum JetpackConnectionAction: Action {
66
/// Updates the store remote with the input siteURL and network to handle cookie authentication.
77
/// Call this before triggering any other case in this action.
88
case authenticate(siteURL: String, network: Network)
9+
/// Retrieves details about Jetpack plugin for the current site.
10+
case retrieveJetpackPluginDetails(completion: (Result<SitePlugin, Error>) -> Void)
11+
/// Installs Jetpack the plugin for the current site.
12+
case installJetpackPlugin(completion: (Result<Void, Error>) -> Void)
13+
/// Updates Jetpack the plugin for the current site.
14+
case activateJetpackPlugin(completion: (Result<Void, Error>) -> Void)
915
/// Fetches the URL used for setting up Jetpack connection.
1016
case fetchJetpackConnectionURL(completion: (Result<URL, Error>) -> Void)
1117
/// Fetches the user connection state with the given site's Jetpack.

Yosemite/Yosemite/Stores/JetpackConnectionStore.swift

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,12 @@ public final class JetpackConnectionStore: DeauthenticatedStore {
2626
switch action {
2727
case .authenticate(let siteURL, let network):
2828
updateRemote(with: siteURL, network: network)
29+
case .retrieveJetpackPluginDetails(let completion):
30+
retrieveJetpackPluginDetails(completion: completion)
31+
case .installJetpackPlugin(let completion):
32+
installJetpackPlugin(completion: completion)
33+
case .activateJetpackPlugin(let completion):
34+
activateJetpackPlugin(completion: completion)
2935
case .fetchJetpackConnectionURL(let completion):
3036
fetchJetpackConnectionURL(completion: completion)
3137
case .fetchJetpackUser(let completion):
@@ -39,6 +45,32 @@ private extension JetpackConnectionStore {
3945
self.remote = JetpackConnectionRemote(siteURL: siteURL, network: network)
4046
}
4147

48+
func retrieveJetpackPluginDetails(completion: @escaping (Result<SitePlugin, Error>) -> Void) {
49+
remote?.retrieveJetpackPluginDetails(completion: completion)
50+
}
51+
52+
func installJetpackPlugin(completion: @escaping (Result<Void, Error>) -> Void) {
53+
remote?.installJetpackPlugin(completion: { result in
54+
switch result {
55+
case .success:
56+
completion(.success(()))
57+
case .failure(let error):
58+
completion(.failure(error))
59+
}
60+
})
61+
}
62+
63+
func activateJetpackPlugin(completion: @escaping (Result<Void, Error>) -> Void) {
64+
remote?.activateJetpackPlugin(completion: { result in
65+
switch result {
66+
case .success:
67+
completion(.success(()))
68+
case .failure(let error):
69+
completion(.failure(error))
70+
}
71+
})
72+
}
73+
4274
func fetchJetpackConnectionURL(completion: @escaping (Result<URL, Error>) -> Void) {
4375
remote?.fetchJetpackConnectionURL { [weak self] result in
4476
guard let self else { return }

Yosemite/YosemiteTests/Stores/JetpackConnectionStoreTests.swift

Lines changed: 138 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ import XCTest
44

55
final class JetpackConnectionStoreTests: XCTestCase {
66

7+
private let siteURL = "http://test.com"
8+
79
/// Mock Dispatcher
810
///
911
private var dispatcher: Dispatcher!
@@ -18,9 +20,144 @@ final class JetpackConnectionStoreTests: XCTestCase {
1820
dispatcher = Dispatcher()
1921
}
2022

23+
func test_retrieveJetpackPluginDetails_returns_correct_plugin() throws {
24+
// Given
25+
let urlSuffix = "/wp/v2/plugins/jetpack/jetpack"
26+
network.simulateResponse(requestUrlSuffix: urlSuffix, filename: "site-plugin-without-envelope")
27+
let store = JetpackConnectionStore(dispatcher: dispatcher)
28+
29+
let setupAction = JetpackConnectionAction.authenticate(siteURL: siteURL, network: network)
30+
store.onAction(setupAction)
31+
32+
// When
33+
let result: Result<SitePlugin, Error> = waitFor { promise in
34+
let action = JetpackConnectionAction.retrieveJetpackPluginDetails { result in
35+
promise(result)
36+
}
37+
store.onAction(action)
38+
}
39+
40+
// Then
41+
XCTAssertTrue(result.isSuccess)
42+
let plugin = try XCTUnwrap(result.get())
43+
assertEqual(plugin.plugin, "jetpack/jetpack")
44+
assertEqual(plugin.status, .active)
45+
assertEqual(plugin.name, "Jetpack")
46+
}
47+
48+
func test_retrieveJetpackPluginDetails_properly_relays_errors() {
49+
// Given
50+
let urlSuffix = "/wp/v2/plugins/jetpack/jetpack"
51+
let error = NetworkError.unacceptableStatusCode(statusCode: 500)
52+
network.simulateError(requestUrlSuffix: urlSuffix, error: error)
53+
let store = JetpackConnectionStore(dispatcher: dispatcher)
54+
55+
let setupAction = JetpackConnectionAction.authenticate(siteURL: siteURL, network: network)
56+
store.onAction(setupAction)
57+
58+
// When
59+
let result: Result<SitePlugin, Error> = waitFor { promise in
60+
let action = JetpackConnectionAction.retrieveJetpackPluginDetails { result in
61+
promise(result)
62+
}
63+
store.onAction(action)
64+
}
65+
66+
// Then
67+
XCTAssertTrue(result.isFailure)
68+
XCTAssertEqual(result.failure as? NetworkError, error)
69+
}
70+
71+
func test_installJetpackPlugin_completes_successfully_when_the_installation_succeeds() throws {
72+
// Given
73+
let urlSuffix = "/wp/v2/plugins"
74+
network.simulateResponse(requestUrlSuffix: urlSuffix, filename: "site-plugin-without-envelope")
75+
let store = JetpackConnectionStore(dispatcher: dispatcher)
76+
77+
let setupAction = JetpackConnectionAction.authenticate(siteURL: siteURL, network: network)
78+
store.onAction(setupAction)
79+
80+
// When
81+
let result: Result<Void, Error> = waitFor { promise in
82+
let action = JetpackConnectionAction.installJetpackPlugin { result in
83+
promise(result)
84+
}
85+
store.onAction(action)
86+
}
87+
88+
// Then
89+
XCTAssertTrue(result.isSuccess)
90+
}
91+
92+
func test_installJetpackPlugin_properly_relays_errors() {
93+
// Given
94+
let urlSuffix = "/wp/v2/plugins"
95+
let error = NetworkError.unacceptableStatusCode(statusCode: 500)
96+
network.simulateError(requestUrlSuffix: urlSuffix, error: error)
97+
let store = JetpackConnectionStore(dispatcher: dispatcher)
98+
99+
let setupAction = JetpackConnectionAction.authenticate(siteURL: siteURL, network: network)
100+
store.onAction(setupAction)
101+
102+
// When
103+
let result: Result<Void, Error> = waitFor { promise in
104+
let action = JetpackConnectionAction.installJetpackPlugin { result in
105+
promise(result)
106+
}
107+
store.onAction(action)
108+
}
109+
110+
// Then
111+
XCTAssertTrue(result.isFailure)
112+
XCTAssertEqual(result.failure as? NetworkError, error)
113+
}
114+
115+
func test_activateJetpackPlugin_completes_successfully_when_the_activation_succeeds() throws {
116+
// Given
117+
let urlSuffix = "/wp/v2/plugins/jetpack/jetpack"
118+
network.simulateResponse(requestUrlSuffix: urlSuffix, filename: "site-plugin-without-envelope")
119+
let store = JetpackConnectionStore(dispatcher: dispatcher)
120+
121+
let setupAction = JetpackConnectionAction.authenticate(siteURL: siteURL, network: network)
122+
store.onAction(setupAction)
123+
124+
// When
125+
let result: Result<Void, Error> = waitFor { promise in
126+
let action = JetpackConnectionAction.activateJetpackPlugin { result in
127+
promise(result)
128+
}
129+
store.onAction(action)
130+
}
131+
132+
// Then
133+
XCTAssertTrue(result.isSuccess)
134+
}
135+
136+
func test_activateJetpackPlugin_properly_relays_errors() {
137+
// Given
138+
let urlSuffix = "/wp/v2/plugins/jetpack/jetpack"
139+
let error = NetworkError.unacceptableStatusCode(statusCode: 500)
140+
network.simulateError(requestUrlSuffix: urlSuffix, error: error)
141+
let store = JetpackConnectionStore(dispatcher: dispatcher)
142+
143+
let setupAction = JetpackConnectionAction.authenticate(siteURL: siteURL, network: network)
144+
store.onAction(setupAction)
145+
146+
// When
147+
let result: Result<Void, Error> = waitFor { promise in
148+
let action = JetpackConnectionAction.activateJetpackPlugin { result in
149+
promise(result)
150+
}
151+
store.onAction(action)
152+
}
153+
154+
// Then
155+
XCTAssertTrue(result.isFailure)
156+
XCTAssertEqual(result.failure as? NetworkError, error)
157+
}
158+
21159
func test_fetchJetpackConnectionURL_returns_correct_url() throws {
22160
// Given
23-
let siteURL = "http://test.com"
24161
let urlSuffix = "/jetpack/v4/connection/url"
25162
network.simulateResponse(requestUrlSuffix: urlSuffix, filename: "jetpack-connection-url")
26163
let store = JetpackConnectionStore(dispatcher: dispatcher)
@@ -45,7 +182,6 @@ final class JetpackConnectionStoreTests: XCTestCase {
45182

46183
func test_fetchJetpackConnectionURL_properly_relays_errors() {
47184
// Given
48-
let siteURL = "http://test.com"
49185
let urlSuffix = "/jetpack/v4/connection/url"
50186
let error = NetworkError.unacceptableStatusCode(statusCode: 500)
51187
network.simulateError(requestUrlSuffix: urlSuffix, error: error)
@@ -69,7 +205,6 @@ final class JetpackConnectionStoreTests: XCTestCase {
69205

70206
func test_fetchJetpackUser_correctly_returns_parsed_user() throws {
71207
// Given
72-
let siteURL = "http://test.com"
73208
let urlSuffix = "/jetpack/v4/connection/data"
74209
network.simulateResponse(requestUrlSuffix: urlSuffix, filename: "jetpack-connected-user")
75210
let store = JetpackConnectionStore(dispatcher: dispatcher)

0 commit comments

Comments
 (0)