Skip to content
This repository was archived by the owner on Sep 15, 2025. It is now read-only.

Commit 83483a8

Browse files
authored
Merge pull request #124 from wordpress-mobile/feature/10277-jetpack-installation-api
[Jetpack Remote Install] New Blog service API
2 parents 7f01628 + 35c2112 commit 83483a8

17 files changed

+355
-3
lines changed

Podfile.lock

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ PODS:
2727
- OHHTTPStubs/Swift (6.1.0):
2828
- OHHTTPStubs/Default
2929
- UIDeviceIdentifier (1.1.4)
30-
- WordPressShared (1.7.0):
30+
- WordPressShared (1.7.2):
3131
- CocoaLumberjack (~> 3.4)
3232
- FormatterKit/TimeIntervalFormatter (= 1.8.2)
3333
- wpxmlrpc (0.8.4)
@@ -63,7 +63,7 @@ SPEC CHECKSUMS:
6363
OCMock: 43565190abc78977ad44a61c0d20d7f0784d35ab
6464
OHHTTPStubs: 1e21c7d2c084b8153fc53d48400d8919d2d432d0
6565
UIDeviceIdentifier: 8f8a24b257a4d978c8d40ad1e7355b944ffbfa8c
66-
WordPressShared: cfbda56868419842dd7a106a4e807069a0c17aa9
66+
WordPressShared: 63d57a4a07ad9f9a1ee5e8a7162e48fbb5192014
6767
wpxmlrpc: 6ba55c773cfa27083ae4a2173e69b19f46da98e2
6868

6969
PODFILE CHECKSUM: 34d4f957f37c097c360d2863370ce2e5e06511cc

WordPressKit.podspec

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
Pod::Spec.new do |s|
22
s.name = "WordPressKit"
3-
s.version = "3.1.0"
3+
s.version = "3.2.0-beta.1"
44
s.summary = "WordPressKit offers a clean and simple WordPress.com and WordPress.org API."
55

66
s.description = <<-DESC

WordPressKit.xcodeproj/project.pbxproj

Lines changed: 56 additions & 0 deletions
Large diffs are not rendered by default.
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
public enum JetpackInstallError: String, Error {
2+
case invalidCredentials = "INVALID_CREDENTIALS"
3+
case forbidden = "FORBIDDEN"
4+
case installFailure = "INSTALL_FAILURE"
5+
case installResponseError = "INSTALL_RESPONSE_ERROR"
6+
case loginFailure = "LOGIN_FAILURE"
7+
case siteIsJetpack = "SITE_IS_JETPACK"
8+
case activationOnInstallFailure = "ACTIVATION_ON_INSTALL_FAILURE"
9+
case activationResponseError = "ACTIVATION_RESPONSE_ERROR"
10+
case activationFailure = "ACTIVATION_FAILURE"
11+
case unknown
12+
13+
init(error key: String) {
14+
self = JetpackInstallError(rawValue: key) ?? .unknown
15+
}
16+
}
17+
18+
public extension BlogServiceRemoteREST {
19+
public func installJetpack(url: String,
20+
username: String,
21+
password: String,
22+
completion: @escaping (Bool, JetpackInstallError?) -> Void) {
23+
guard let escapedURL = url.addingPercentEncoding(withAllowedCharacters: .urlHostAllowed) else {
24+
completion(false, .unknown)
25+
return
26+
}
27+
let path = String(format: "jetpack-install/%@/", escapedURL)
28+
let requestUrl = self.path(forEndpoint: path, withVersion: ._1_0)
29+
let parameters = ["user": username,
30+
"password": password]
31+
32+
wordPressComRestApi.POST(requestUrl,
33+
parameters: parameters as [String : AnyObject],
34+
success: { (response: AnyObject, httpResponse: HTTPURLResponse?) in
35+
if let response = response as? [String: Bool],
36+
let success = response[Constants.status] {
37+
completion(success, nil)
38+
} else {
39+
completion(false, .installResponseError)
40+
}
41+
}) { (error: NSError, httpResponse: HTTPURLResponse?) in
42+
if let key = error.userInfo[WordPressComRestApi.ErrorKeyErrorCode] as? String {
43+
completion(false, JetpackInstallError(error: key))
44+
} else {
45+
completion(false, .unknown)
46+
}
47+
}
48+
}
49+
50+
private enum Constants {
51+
static let status = "status"
52+
}
53+
}
Lines changed: 197 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,197 @@
1+
import Foundation
2+
import XCTest
3+
@testable import WordPressKit
4+
5+
class BlogServiceRemoteRESTTests_Jetpack: RemoteTestCase, RESTTestable {
6+
let siteId = 12345
7+
let url = "http://www.wordpress.com"
8+
let encodedURL = "http%3A%2F%2Fwww.wordpress.com"
9+
let username = "username"
10+
let password = "qwertyuiop"
11+
12+
let jetpackRemoteSuccessMockFilename = "blog-service-jetpack-remote-success.json"
13+
let jetpackRemoteFailureMockFilename = "blog-service-jetpack-remote-failure.json"
14+
15+
let jetpackRemoteErrorUnknownMockFilename = "blog-service-jetpack-remote-error-unknown.json"
16+
let jetpackRemoteErrorInvalidCredentialsMockFilename = "blog-service-jetpack-remote-error-invalid-credentials.json"
17+
let jetpackRemoteErrorForbiddenMockFilename = "blog-service-jetpack-remote-error-forbidden.json"
18+
let jetpackRemoteErrorInstallFailureMockFilename = "blog-service-jetpack-remote-error-install-failure.json"
19+
let jetpackRemoteErrorInstallResponseMockFilename = "blog-service-jetpack-remote-error-install-response.json"
20+
let jetpackRemoteErrorLoginFailureMockFilename = "blog-service-jetpack-remote-error-login-failure.json"
21+
let jetpackRemoteErrorSiteIsJetpackMockFilename = "blog-service-jetpack-remote-error-site-is-jetpack.json"
22+
let jetpackRemoteErrorActivationInstallMockFilename = "blog-service-jetpack-remote-error-activation-install.json"
23+
let jetpackRemoteErrorActivationResponseMockFilename = "blog-service-jetpack-remote-error-activation-response.json"
24+
let jetpackRemoteErrorActivationFailureMockFilename = "blog-service-jetpack-remote-error-activation-failure.json"
25+
26+
var endpoint: String { return "jetpack-install/\(encodedURL)/" }
27+
28+
var remote: BlogServiceRemoteREST!
29+
30+
// MARK: - Overridden Methods
31+
32+
override func setUp() {
33+
super.setUp()
34+
35+
remote = BlogServiceRemoteREST(wordPressComRestApi: getRestApi(), siteID: NSNumber(value: siteId))
36+
}
37+
38+
override func tearDown() {
39+
super.tearDown()
40+
41+
remote = nil
42+
}
43+
44+
func testJetpackRemoteInstallationSuccess() {
45+
let expect = expectation(description: "Install Jetpack success")
46+
47+
stubRemoteResponse(endpoint, filename: jetpackRemoteSuccessMockFilename, contentType: .ApplicationJSON, status: 200)
48+
remote.installJetpack(url: url, username: username, password: password) { (success, error) in
49+
XCTAssertTrue(success, "Success should be true")
50+
expect.fulfill()
51+
}
52+
53+
waitForExpectations(timeout: timeout, handler: nil)
54+
}
55+
56+
func testJetpackRemoteInstallationFailure() {
57+
let expect = expectation(description: "Install Jetpack failure")
58+
59+
stubRemoteResponse(endpoint, filename: jetpackRemoteFailureMockFilename, contentType: .ApplicationJSON, status: 200)
60+
remote.installJetpack(url: url, username: username, password: password) { (success, error) in
61+
XCTAssertFalse(success, "Success should be false")
62+
expect.fulfill()
63+
}
64+
65+
waitForExpectations(timeout: timeout, handler: nil)
66+
}
67+
68+
func testJetpackRemoteInstallationErrorInvalidCredentials() {
69+
let expect = expectation(description: "Install Jetpack failure")
70+
71+
stubRemoteResponse(endpoint, filename: jetpackRemoteErrorInvalidCredentialsMockFilename, contentType: .ApplicationJSON, status: 400)
72+
remote.installJetpack(url: url, username: username, password: password) { (success, error) in
73+
XCTAssertFalse(success, "Success should be false")
74+
XCTAssertEqual(error, .invalidCredentials)
75+
expect.fulfill()
76+
}
77+
78+
waitForExpectations(timeout: timeout, handler: nil)
79+
}
80+
81+
func testJetpackRemoteInstallationErrorUnknown() {
82+
let expect = expectation(description: "Install Jetpack failure")
83+
84+
stubRemoteResponse(endpoint, filename: jetpackRemoteErrorUnknownMockFilename, contentType: .ApplicationJSON, status: 400)
85+
remote.installJetpack(url: url, username: username, password: password) { (success, error) in
86+
XCTAssertFalse(success, "Success should be false")
87+
XCTAssertEqual(error, .unknown)
88+
expect.fulfill()
89+
}
90+
91+
waitForExpectations(timeout: timeout, handler: nil)
92+
}
93+
94+
func testJetpackRemoteInstallationErrorForbidden() {
95+
let expect = expectation(description: "Install Jetpack failure")
96+
97+
stubRemoteResponse(endpoint, filename: jetpackRemoteErrorForbiddenMockFilename, contentType: .ApplicationJSON, status: 400)
98+
remote.installJetpack(url: url, username: username, password: password) { (success, error) in
99+
XCTAssertFalse(success, "Success should be false")
100+
XCTAssertEqual(error, .forbidden)
101+
expect.fulfill()
102+
}
103+
104+
waitForExpectations(timeout: timeout, handler: nil)
105+
}
106+
107+
func testJetpackRemoteInstallationInstallFailure() {
108+
let expect = expectation(description: "Install Jetpack failure")
109+
110+
stubRemoteResponse(endpoint, filename: jetpackRemoteErrorInstallFailureMockFilename, contentType: .ApplicationJSON, status: 400)
111+
remote.installJetpack(url: url, username: username, password: password) { (success, error) in
112+
XCTAssertFalse(success, "Success should be false")
113+
XCTAssertEqual(error, .installFailure)
114+
expect.fulfill()
115+
}
116+
117+
waitForExpectations(timeout: timeout, handler: nil)
118+
}
119+
120+
func testJetpackRemoteInstallationInstallResponse() {
121+
let expect = expectation(description: "Install Jetpack failure")
122+
123+
stubRemoteResponse(endpoint, filename: jetpackRemoteErrorInstallResponseMockFilename, contentType: .ApplicationJSON, status: 400)
124+
remote.installJetpack(url: url, username: username, password: password) { (success, error) in
125+
XCTAssertFalse(success, "Success should be false")
126+
XCTAssertEqual(error, .installResponseError)
127+
expect.fulfill()
128+
}
129+
130+
waitForExpectations(timeout: timeout, handler: nil)
131+
}
132+
133+
func testJetpackRemoteInstallationLoginFailure() {
134+
let expect = expectation(description: "Install Jetpack failure")
135+
136+
stubRemoteResponse(endpoint, filename: jetpackRemoteErrorLoginFailureMockFilename, contentType: .ApplicationJSON, status: 400)
137+
remote.installJetpack(url: url, username: username, password: password) { (success, error) in
138+
XCTAssertFalse(success, "Success should be false")
139+
XCTAssertEqual(error, .loginFailure)
140+
expect.fulfill()
141+
}
142+
143+
waitForExpectations(timeout: timeout, handler: nil)
144+
}
145+
146+
func testJetpackRemoteInstallationSiteIsJetpack() {
147+
let expect = expectation(description: "Install Jetpack failure")
148+
149+
stubRemoteResponse(endpoint, filename: jetpackRemoteErrorSiteIsJetpackMockFilename, contentType: .ApplicationJSON, status: 400)
150+
remote.installJetpack(url: url, username: username, password: password) { (success, error) in
151+
XCTAssertFalse(success, "Success should be false")
152+
XCTAssertEqual(error, .siteIsJetpack)
153+
expect.fulfill()
154+
}
155+
156+
waitForExpectations(timeout: timeout, handler: nil)
157+
}
158+
159+
func testJetpackRemoteInstallationActivationInstall() {
160+
let expect = expectation(description: "Install Jetpack failure")
161+
162+
stubRemoteResponse(endpoint, filename: jetpackRemoteErrorActivationInstallMockFilename, contentType: .ApplicationJSON, status: 400)
163+
remote.installJetpack(url: url, username: username, password: password) { (success, error) in
164+
XCTAssertFalse(success, "Success should be false")
165+
XCTAssertEqual(error, .activationOnInstallFailure)
166+
expect.fulfill()
167+
}
168+
169+
waitForExpectations(timeout: timeout, handler: nil)
170+
}
171+
172+
func testJetpackRemoteInstallationActivationResponse() {
173+
let expect = expectation(description: "Install Jetpack failure")
174+
175+
stubRemoteResponse(endpoint, filename: jetpackRemoteErrorActivationResponseMockFilename, contentType: .ApplicationJSON, status: 400)
176+
remote.installJetpack(url: url, username: username, password: password) { (success, error) in
177+
XCTAssertFalse(success, "Success should be false")
178+
XCTAssertEqual(error, .activationResponseError)
179+
expect.fulfill()
180+
}
181+
182+
waitForExpectations(timeout: timeout, handler: nil)
183+
}
184+
185+
func testJetpackRemoteInstallationActivationFailure() {
186+
let expect = expectation(description: "Install Jetpack failure")
187+
188+
stubRemoteResponse(endpoint, filename: jetpackRemoteErrorActivationFailureMockFilename, contentType: .ApplicationJSON, status: 400)
189+
remote.installJetpack(url: url, username: username, password: password) { (success, error) in
190+
XCTAssertFalse(success, "Success should be false")
191+
XCTAssertEqual(error, .activationFailure)
192+
expect.fulfill()
193+
}
194+
195+
waitForExpectations(timeout: timeout, handler: nil)
196+
}
197+
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
"error": "ACTIVATION_FAILURE",
3+
"message": "message"
4+
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
"error": "ACTIVATION_ON_INSTALL_FAILURE",
3+
"message": "message"
4+
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
"error": "ACTIVATION_RESPONSE_ERROR",
3+
"message": "message"
4+
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
"error": "FORBIDDEN",
3+
"message": "message"
4+
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
"error": "INSTALL_FAILURE",
3+
"message": "message"
4+
}

0 commit comments

Comments
 (0)