diff --git a/CHANGELOG.md b/CHANGELOG.md index 64604045..9a62e3af 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -46,7 +46,7 @@ _None._ ### Internal Changes -_None._ +Add POST requests helper in `WordPressOrgRestApi`. [#589] ## 7.0.0 diff --git a/WordPressKit.xcodeproj/project.pbxproj b/WordPressKit.xcodeproj/project.pbxproj index 790ceb6d..a2116047 100644 --- a/WordPressKit.xcodeproj/project.pbxproj +++ b/WordPressKit.xcodeproj/project.pbxproj @@ -19,6 +19,7 @@ 17CE77F420C701C8001DEA5A /* ReaderSiteSearchServiceRemoteTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 17CE77F320C701C8001DEA5A /* ReaderSiteSearchServiceRemoteTests.swift */; }; 17D936252475D8AB008B2205 /* RemoteHomepageType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 17D936242475D8AB008B2205 /* RemoteHomepageType.swift */; }; 1A4F98672279A87D00D86E8E /* WPKit-Swift.h in Headers */ = {isa = PBXBuildFile; fileRef = 1A4F98662279A87D00D86E8E /* WPKit-Swift.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 1D969EB329D45745001FE37C /* wp-reusable-blocks.json in Resources */ = {isa = PBXBuildFile; fileRef = 1D969EB229D45745001FE37C /* wp-reusable-blocks.json */; }; 1DAC3D2629AF4F250068FE13 /* RemoteVideoPressVideo.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1DAC3D2529AF4F250068FE13 /* RemoteVideoPressVideo.swift */; }; 1DC837C229B9F04F009DCD4B /* RemoteVideoPressVideoTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1DC837C129B9F04F009DCD4B /* RemoteVideoPressVideoTests.swift */; }; 1DF972BA29B0DF8C007A72BC /* videopress-token.json in Resources */ = {isa = PBXBuildFile; fileRef = 1DF972B729B0DF8C007A72BC /* videopress-token.json */; }; @@ -683,6 +684,7 @@ 17CE77F320C701C8001DEA5A /* ReaderSiteSearchServiceRemoteTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReaderSiteSearchServiceRemoteTests.swift; sourceTree = ""; }; 17D936242475D8AB008B2205 /* RemoteHomepageType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RemoteHomepageType.swift; sourceTree = ""; }; 1A4F98662279A87D00D86E8E /* WPKit-Swift.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "WPKit-Swift.h"; sourceTree = ""; }; + 1D969EB229D45745001FE37C /* wp-reusable-blocks.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = "wp-reusable-blocks.json"; sourceTree = ""; }; 1DAC3D2529AF4F250068FE13 /* RemoteVideoPressVideo.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RemoteVideoPressVideo.swift; sourceTree = ""; }; 1DC837C129B9F04F009DCD4B /* RemoteVideoPressVideoTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RemoteVideoPressVideoTests.swift; sourceTree = ""; }; 1DF972B729B0DF8C007A72BC /* videopress-token.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = "videopress-token.json"; sourceTree = ""; }; @@ -2284,6 +2286,7 @@ FFA4D4AC2423B1FE00BF5180 /* wp-admin-post-new.html */, FFA4D4AE2423B33800BF5180 /* wp-forbidden.json */, FFA4D4AF2423B33800BF5180 /* wp-pages.json */, + 1D969EB229D45745001FE37C /* wp-reusable-blocks.json */, 740B23EB1F17FB7E00067A2A /* xmlrpc-bad-username-password-error.xml */, 740B23EC1F17FB7E00067A2A /* xmlrpc-malformed-request-xml-error.xml */, 740B23D71F17FB4200067A2A /* xmlrpc-metaweblog-editpost-bad-xml-failure.xml */, @@ -2745,6 +2748,7 @@ E14694031F344F71004052C8 /* site-plugins-error.json in Resources */, C738CAF728622B94001BE107 /* qrlogin-authenticate-200.json in Resources */, 829BA4311FACF187003ADEEA /* activity-rewind-status-success.json in Resources */, + 1D969EB329D45745001FE37C /* wp-reusable-blocks.json in Resources */, 93BD27571EE73442002BB00B /* auth-send-login-email-no-user-failure.json in Resources */, 9A88174C223C01E400A3AB20 /* jetpack-service-success.json in Resources */, 9A881755223C01E400A3AB20 /* jetpack-service-error-activation-response.json in Resources */, diff --git a/WordPressKit/WordPressOrgRestApi.swift b/WordPressKit/WordPressOrgRestApi.swift index e62e1845..c9971bb2 100644 --- a/WordPressKit/WordPressOrgRestApi.swift +++ b/WordPressKit/WordPressOrgRestApi.swift @@ -31,6 +31,13 @@ open class WordPressOrgRestApi: NSObject, WordPressRestApi { return request(method: .get, path: path, parameters: parameters, completion: completion) } + @discardableResult + open func POST(_ path: String, + parameters: [String: AnyObject]?, + completion: @escaping Completion) -> Progress? { + return request(method: .post, path: path, parameters: parameters, completion: completion) + } + @discardableResult open func request(method: HTTPMethod, path: String, diff --git a/WordPressKitTests/Mock Data/wp-reusable-blocks.json b/WordPressKitTests/Mock Data/wp-reusable-blocks.json new file mode 100644 index 00000000..5e818f84 --- /dev/null +++ b/WordPressKitTests/Mock Data/wp-reusable-blocks.json @@ -0,0 +1,50 @@ +{ + "id": 6, + "date": "2021-02-10T11:51:53", + "date_gmt": "2021-02-10T11:51:53", + "guid": { + "rendered": "https:\/\/test-site.org\/2021\/02\/10\/untitled-reusable-block\/", + "raw": "https:\/\/test-site.org\/2021\/02\/10\/untitled-reusable-block\/" + }, + "modified": "2021-02-10T12:31:39", + "modified_gmt": "2021-02-10T12:31:39", + "password": "", + "slug": "untitled-reusable-block", + "status": "publish", + "type": "wp_block", + "link": "https:\/\/test-site.org\/2021\/02\/10\/untitled-reusable-block\/", + "title": { + "raw": "A resuable block" + }, + "content": { + "raw": "\n

Some text<\/p>\n\n\n\n

  • Item 1<\/li>
  • Item 2<\/li>
  • Item 3<\/li><\/ul>\n", + "protected": false, + "block_version": 1 + }, + "template": "", + "_links": { + "self": [{ + "href": "https:\/\/test-site.org\/wp-json\/wp\/v2\/blocks\/6" + }], + "collection": [{ + "href": "https:\/\/test-site.org\/wp-json\/wp\/v2\/blocks" + }], + "about": [{ + "href": "https:\/\/test-site.org\/wp-json\/wp\/v2\/types\/wp_block" + }], + "wp:attachment": [{ + "href": "https:\/\/test-site.org\/wp-json\/wp\/v2\/media?parent=6" + }], + "wp:action-publish": [{ + "href": "https:\/\/test-site.org\/wp-json\/wp\/v2\/blocks\/6" + }], + "wp:action-unfiltered-html": [{ + "href": "https:\/\/test-site.org\/wp-json\/wp\/v2\/blocks\/6" + }], + "curies": [{ + "name": "wp", + "href": "https:\/\/api.w.org\/{rel}", + "templated": true + }] + } +} diff --git a/WordPressKitTests/WordPressOrgRestApiTests.swift b/WordPressKitTests/WordPressOrgRestApiTests.swift index bc6b0fce..00655838 100644 --- a/WordPressKitTests/WordPressOrgRestApiTests.swift +++ b/WordPressKitTests/WordPressOrgRestApiTests.swift @@ -41,7 +41,7 @@ class WordPressOrgRestApiTests: XCTestCase { waitForExpectations(timeout: 2, handler: nil) } - func testSuccessfulCall() { + func testSuccessfulGetCall() { stub(condition: isAPIRequest()) { _ in let stubPath = OHPathForFile("wp-pages.json", type(of: self)) return fixture(filePath: stubPath!, headers: ["Content-Type" as NSObject: "application/json" as AnyObject]) @@ -63,4 +63,34 @@ class WordPressOrgRestApiTests: XCTestCase { } waitForExpectations(timeout: 2, handler: nil) } + + func testSuccessfulPostCall() { + stub(condition: isAPIRequest()) { _ in + let stubPath = OHPathForFile("wp-reusable-blocks.json", type(of: self)) + return fixture(filePath: stubPath!, headers: ["Content-Type" as NSObject: "application/json" as AnyObject]) + } + let expect = self.expectation(description: "One callback should be invoked") + let api = WordPressOrgRestApi(apiBase: apiBase) + let blockContent = "\n

    Some text

    \n\n\n\n
    • Item 1
    • Item 2
    • Item 3
    \n" + let parameters: [String: String] = ["id": "6", "content": blockContent] + api.POST("wp/v2/blocks/6", parameters: parameters as [String: AnyObject]) { (result, _) in + expect.fulfill() + switch result { + case .success(let object): + guard + let block = object as? [String: AnyObject], + let content = block["content"] as? [String: AnyObject], + let rawContent = content["raw"] as? String + else { + XCTFail("Unexpected API result") + return + } + XCTAssertEqual(block.count, 15, "The API should return the block") + XCTAssertEqual(rawContent, blockContent, "The API should return the block") + case .failure: + XCTFail("This call should not fail") + } + } + waitForExpectations(timeout: 2, handler: nil) + } }