From 8b8d2097edb6f19568978807cfdbef10c3e7c184 Mon Sep 17 00:00:00 2001 From: Chris McGraw <2454408+wargcm@users.noreply.github.com> Date: Mon, 11 Mar 2024 16:41:51 -0400 Subject: [PATCH] Update Reader cards fetch call to use async method --- .../ReaderPostServiceRemote+Cards.swift | 24 ++---- .../MockWordPressComRestApi.swift | 15 ++++ .../ReaderPostServiceRemote+CardsTests.swift | 85 +++++++++++++------ 3 files changed, 79 insertions(+), 45 deletions(-) diff --git a/WordPressKit/ReaderPostServiceRemote+Cards.swift b/WordPressKit/ReaderPostServiceRemote+Cards.swift index 3fd995345..36ae18df7 100644 --- a/WordPressKit/ReaderPostServiceRemote+Cards.swift +++ b/WordPressKit/ReaderPostServiceRemote+Cards.swift @@ -74,24 +74,12 @@ extension ReaderPostServiceRemote { private func fetch(_ endpoint: String, success: @escaping ([RemoteReaderCard], String?) -> Void, failure: @escaping (Error) -> Void) { - wordPressComRestApi.GET(endpoint, - parameters: nil, - success: { response, _ in - do { - let decoder = JSONDecoder() - let data = try JSONSerialization.data(withJSONObject: response, options: []) - let envelope = try decoder.decode(ReaderCardEnvelope.self, from: data) - - success(envelope.cards, envelope.nextPageHandle) - } catch { - WPKitLogError("Error parsing the reader cards response: \(error)") - failure(error) - } - }, failure: { error, _ in - WPKitLogError("Error fetching reader cards: \(error)") - - failure(error) - }) + Task { @MainActor [wordPressComRestApi] in + await wordPressComRestApi.perform(.get, URLString: endpoint, type: ReaderCardEnvelope.self) + .map { ($0.body.cards, $0.body.nextPageHandle) } + .mapError { error -> Error in error.asNSError() } + .execute(onSuccess: success, onFailure: failure) + } } private func cardsEndpoint(with path: String, diff --git a/WordPressKitTests/MockWordPressComRestApi.swift b/WordPressKitTests/MockWordPressComRestApi.swift index b1a369e5e..9b552f7f8 100644 --- a/WordPressKitTests/MockWordPressComRestApi.swift +++ b/WordPressKitTests/MockWordPressComRestApi.swift @@ -9,6 +9,8 @@ class MockWordPressComRestApi: WordPressComRestApi { @objc var successBlockPassedIn: ((AnyObject, HTTPURLResponse?) -> Void)? @objc var failureBlockPassedIn: ((NSError, HTTPURLResponse?) -> Void)? + var performMethodCall: HTTPRequestBuilder.Method? + override func GET(_ URLString: String?, parameters: [String: AnyObject]?, success: @escaping ((AnyObject, HTTPURLResponse?) -> Void), failure: @escaping ((NSError, HTTPURLResponse?) -> Void)) -> Progress? { getMethodCalled = true URLStringPassedIn = URLString @@ -44,6 +46,19 @@ class MockWordPressComRestApi: WordPressComRestApi { return Progress() } + override func perform( + _ method: HTTPRequestBuilder.Method, + URLString: String, + parameters: [String: AnyObject]? = nil, + fulfilling progress: Progress? = nil, + jsonDecoder: JSONDecoder? = nil, + type: T.Type = T.self + ) async -> APIResult { + performMethodCall = method + URLStringPassedIn = URLString + return .failure(.connection(.init(.cancelled))) + } + @objc func methodCalled() -> String { var method = "Unknown" diff --git a/WordPressKitTests/ReaderPostServiceRemote+CardsTests.swift b/WordPressKitTests/ReaderPostServiceRemote+CardsTests.swift index 9ac52db39..d87d8dde3 100644 --- a/WordPressKitTests/ReaderPostServiceRemote+CardsTests.swift +++ b/WordPressKitTests/ReaderPostServiceRemote+CardsTests.swift @@ -86,51 +86,66 @@ class ReaderPostServiceRemoteCardTests: RemoteTestCase, RESTTestable { waitForExpectations(timeout: timeout, handler: nil) } + func testHTTPMethod() { + let expect = expectation(description: "Executes fetch call") + let failure: (Error) -> Void = { _ in expect.fulfill() } + let readerPostServiceRemote = ReaderPostServiceRemote(wordPressComRestApi: mockRemoteApi) + + readerPostServiceRemote.fetchCards(for: ["dogs"], success: { _, _ in }, failure: failure) + + waitForExpectations(timeout: timeout) + XCTAssertEqual(mockRemoteApi.performMethodCall, .get) + } + // Calls the API with the given page handle // func testCallAPIWithTheGivenPageHandle() { + let expect = expectation(description: "Executes fetch call") + let failure: (Error) -> Void = { _ in expect.fulfill() } let readerPostServiceRemote = ReaderPostServiceRemote(wordPressComRestApi: mockRemoteApi) - readerPostServiceRemote.fetchCards(for: ["dogs"], page: "foobar", success: { _, _ in }, failure: { _ in }) - - XCTAssertTrue(mockRemoteApi.getMethodCalled) + readerPostServiceRemote.fetchCards(for: ["dogs"], page: "foobar", success: { _, _ in }, failure: failure) + waitForExpectations(timeout: timeout) XCTAssertTrue(mockRemoteApi.URLStringPassedIn?.contains("&page_handle=foobar") ?? false) } // Calls the API with .popularity as the given sorting option // func testCallAPIWithPopularityAsTheGivenSortingOption() { + let expect = expectation(description: "Executes fetch call") + let failure: (Error) -> Void = { _ in expect.fulfill() } let readerPostServiceRemote = ReaderPostServiceRemote(wordPressComRestApi: mockRemoteApi) - readerPostServiceRemote.fetchCards(for: [], sortingOption: .popularity, success: { _, _ in }, failure: { _ in }) - - XCTAssertTrue(mockRemoteApi.getMethodCalled) + readerPostServiceRemote.fetchCards(for: [], sortingOption: .popularity, success: { _, _ in }, failure: failure) + waitForExpectations(timeout: timeout) XCTAssertTrue(mockRemoteApi.URLStringPassedIn?.contains("sort=popularity") ?? false) } // Calls the API with .date as the given sorting option // func testCallAPIWithDateAsTheGivenSortingOption() { + let expect = expectation(description: "Executes fetch call") + let failure: (Error) -> Void = { _ in expect.fulfill() } let readerPostServiceRemote = ReaderPostServiceRemote(wordPressComRestApi: mockRemoteApi) - readerPostServiceRemote.fetchCards(for: [], sortingOption: .date, success: { _, _ in }, failure: { _ in }) - - XCTAssertTrue(mockRemoteApi.getMethodCalled) + readerPostServiceRemote.fetchCards(for: [], sortingOption: .date, success: { _, _ in }, failure: failure) + waitForExpectations(timeout: timeout) XCTAssertTrue(mockRemoteApi.URLStringPassedIn?.contains("sort=date") ?? false) } // Calls the API without the given sorting option // func testCallAPIWithoutTheGivenSortingOption() { + let expect = expectation(description: "Executes fetch call") + let failure: (Error) -> Void = { _ in expect.fulfill() } let readerPostServiceRemote = ReaderPostServiceRemote(wordPressComRestApi: mockRemoteApi) - readerPostServiceRemote.fetchCards(for: [], success: { _, _ in }, failure: { _ in }) - - XCTAssertTrue(mockRemoteApi.getMethodCalled) + readerPostServiceRemote.fetchCards(for: [], success: { _, _ in }, failure: failure) + waitForExpectations(timeout: timeout) XCTAssertFalse(mockRemoteApi.URLStringPassedIn?.contains("sort=") ?? true) } @@ -221,54 +236,70 @@ class ReaderPostServiceRemoteCardTests: RemoteTestCase, RESTTestable { waitForExpectations(timeout: timeout, handler: nil) } - func testStreamsCallAPIWithTheGivenPageHandle() { + func testStreamsHTTPMethod() { + let expect = expectation(description: "Executes fetch call") + let failure: (Error) -> Void = { _ in expect.fulfill() } let readerPostServiceRemote = ReaderPostServiceRemote(wordPressComRestApi: mockRemoteApi) - readerPostServiceRemote.fetchStreamCards(for: ["dogs"], page: "foobar", success: { _, _ in }, failure: { _ in }) + readerPostServiceRemote.fetchStreamCards(for: ["dogs"], success: { _, _ in }, failure: failure) - XCTAssertTrue(mockRemoteApi.getMethodCalled) + waitForExpectations(timeout: timeout) + XCTAssertEqual(mockRemoteApi.performMethodCall, .get) + } + + func testStreamsCallAPIWithTheGivenPageHandle() { + let expect = expectation(description: "Executes fetch call") + let failure: (Error) -> Void = { _ in expect.fulfill() } + let readerPostServiceRemote = ReaderPostServiceRemote(wordPressComRestApi: mockRemoteApi) + + readerPostServiceRemote.fetchStreamCards(for: ["dogs"], page: "foobar", success: { _, _ in }, failure: failure) + waitForExpectations(timeout: timeout) XCTAssertTrue(mockRemoteApi.URLStringPassedIn?.contains("&page_handle=foobar") ?? false) } func testStreamsCallAPIWithPopularityAsTheGivenSortingOption() { + let expect = expectation(description: "Executes fetch call") + let failure: (Error) -> Void = { _ in expect.fulfill() } let readerPostServiceRemote = ReaderPostServiceRemote(wordPressComRestApi: mockRemoteApi) - readerPostServiceRemote.fetchStreamCards(for: [], sortingOption: .popularity, success: { _, _ in }, failure: { _ in }) - - XCTAssertTrue(mockRemoteApi.getMethodCalled) + readerPostServiceRemote.fetchStreamCards(for: [], sortingOption: .popularity, success: { _, _ in }, failure: failure) + waitForExpectations(timeout: timeout) XCTAssertTrue(mockRemoteApi.URLStringPassedIn?.contains("sort=popularity") ?? false) } func testStreamsCallAPIWithDateAsTheGivenSortingOption() { + let expect = expectation(description: "Executes fetch call") + let failure: (Error) -> Void = { _ in expect.fulfill() } let readerPostServiceRemote = ReaderPostServiceRemote(wordPressComRestApi: mockRemoteApi) - readerPostServiceRemote.fetchStreamCards(for: [], sortingOption: .date, success: { _, _ in }, failure: { _ in }) - - XCTAssertTrue(mockRemoteApi.getMethodCalled) + readerPostServiceRemote.fetchStreamCards(for: [], sortingOption: .date, success: { _, _ in }, failure: failure) + waitForExpectations(timeout: timeout) XCTAssertTrue(mockRemoteApi.URLStringPassedIn?.contains("sort=date") ?? false) } func testStreamsCallAPIWithoutTheGivenSortingOption() { + let expect = expectation(description: "Executes fetch call") + let failure: (Error) -> Void = { _ in expect.fulfill() } let readerPostServiceRemote = ReaderPostServiceRemote(wordPressComRestApi: mockRemoteApi) - readerPostServiceRemote.fetchStreamCards(for: [], success: { _, _ in }, failure: { _ in }) - - XCTAssertTrue(mockRemoteApi.getMethodCalled) + readerPostServiceRemote.fetchStreamCards(for: [], success: { _, _ in }, failure: failure) + waitForExpectations(timeout: timeout) XCTAssertFalse(mockRemoteApi.URLStringPassedIn?.contains("sort=") ?? true) } func testStreamsCallAPIWithCountValue() { + let expect = expectation(description: "Executes fetch call") + let failure: (Error) -> Void = { _ in expect.fulfill() } let readerPostServiceRemote = ReaderPostServiceRemote(wordPressComRestApi: mockRemoteApi) let expectedCount = 5 - readerPostServiceRemote.fetchStreamCards(for: ["dogs"], count: expectedCount, success: { _, _ in }, failure: { _ in }) - - XCTAssertTrue(mockRemoteApi.getMethodCalled) + readerPostServiceRemote.fetchStreamCards(for: ["dogs"], count: expectedCount, success: { _, _ in }, failure: failure) + waitForExpectations(timeout: timeout) XCTAssertTrue(mockRemoteApi.URLStringPassedIn?.contains("&count=\(expectedCount)") ?? false) }