From 96f4a36ed3fea7350eae8c9c9f1c806d394fc40d Mon Sep 17 00:00:00 2001 From: David Christiandy <1299411+dvdchr@users.noreply.github.com> Date: Mon, 1 Nov 2021 17:20:41 +0700 Subject: [PATCH 1/8] Add remote comment model for v2 endpoint --- WordPressKit.xcodeproj/project.pbxproj | 4 ++++ WordPressKit/RemoteCommentV2.swift | 19 +++++++++++++++++++ 2 files changed, 23 insertions(+) create mode 100644 WordPressKit/RemoteCommentV2.swift diff --git a/WordPressKit.xcodeproj/project.pbxproj b/WordPressKit.xcodeproj/project.pbxproj index 38466b15..25d5ac20 100644 --- a/WordPressKit.xcodeproj/project.pbxproj +++ b/WordPressKit.xcodeproj/project.pbxproj @@ -591,6 +591,7 @@ FAD1344B259094C300A8FEB1 /* JetpackBackup.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAD1344A259094C300A8FEB1 /* JetpackBackup.swift */; }; FAD1345125909DEA00A8FEB1 /* JetpackBackupServiceRemoteTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAD1345025909DEA00A8FEB1 /* JetpackBackupServiceRemoteTests.swift */; }; FEB7A88F271873BD00A8CF85 /* reader-post-comments-update-notification-success.json in Resources */ = {isa = PBXBuildFile; fileRef = FEB7A88E271873BD00A8CF85 /* reader-post-comments-update-notification-success.json */; }; + FEE4EF57272FDD4B003CDA3C /* RemoteCommentV2.swift in Sources */ = {isa = PBXBuildFile; fileRef = FEE4EF56272FDD4B003CDA3C /* RemoteCommentV2.swift */; }; FEFFD99126C1347D00F34231 /* ShareAppContentServiceRemote.swift in Sources */ = {isa = PBXBuildFile; fileRef = FEFFD99026C1347D00F34231 /* ShareAppContentServiceRemote.swift */; }; FEFFD99326C141A800F34231 /* RemoteShareAppContent.swift in Sources */ = {isa = PBXBuildFile; fileRef = FEFFD99226C141A800F34231 /* RemoteShareAppContent.swift */; }; FEFFD99726C158F400F34231 /* share-app-content-success.json in Resources */ = {isa = PBXBuildFile; fileRef = FEFFD99626C158F400F34231 /* share-app-content-success.json */; }; @@ -1223,6 +1224,7 @@ FAD1344A259094C300A8FEB1 /* JetpackBackup.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JetpackBackup.swift; sourceTree = ""; }; FAD1345025909DEA00A8FEB1 /* JetpackBackupServiceRemoteTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JetpackBackupServiceRemoteTests.swift; sourceTree = ""; }; FEB7A88E271873BD00A8CF85 /* reader-post-comments-update-notification-success.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = "reader-post-comments-update-notification-success.json"; sourceTree = ""; }; + FEE4EF56272FDD4B003CDA3C /* RemoteCommentV2.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RemoteCommentV2.swift; sourceTree = ""; }; FEFFD99026C1347D00F34231 /* ShareAppContentServiceRemote.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShareAppContentServiceRemote.swift; sourceTree = ""; }; FEFFD99226C141A800F34231 /* RemoteShareAppContent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RemoteShareAppContent.swift; sourceTree = ""; }; FEFFD99626C158F400F34231 /* share-app-content-success.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = "share-app-content-success.json"; sourceTree = ""; }; @@ -1898,6 +1900,7 @@ 4624222C2548BA0F002B8A12 /* RemoteSiteDesign.swift */, 464BAB0A262F6736006AEED5 /* RemoteBlockEditorSettings.swift */, FEFFD99226C141A800F34231 /* RemoteShareAppContent.swift */, + FEE4EF56272FDD4B003CDA3C /* RemoteCommentV2.swift */, ); name = Models; sourceTree = ""; @@ -3002,6 +3005,7 @@ B5A4822B20AC6C0B009D95F6 /* CocoaLumberjack.swift in Sources */, B5A4822E20AC6C1A009D95F6 /* WPKitLogging.m in Sources */, 7430C9A61F1927180051B8E6 /* ReaderSiteServiceRemote.m in Sources */, + FEE4EF57272FDD4B003CDA3C /* RemoteCommentV2.swift in Sources */, 7430C9B21F1927C50051B8E6 /* RemoteReaderPost.m in Sources */, 74A44DCD1F13C533006CD8F4 /* PushAuthenticationServiceRemote.swift in Sources */, 742362DF1F1025B400BD0A7F /* RemoteMenu.m in Sources */, diff --git a/WordPressKit/RemoteCommentV2.swift b/WordPressKit/RemoteCommentV2.swift new file mode 100644 index 00000000..dab28d9b --- /dev/null +++ b/WordPressKit/RemoteCommentV2.swift @@ -0,0 +1,19 @@ +/// Captures the JSON structure for Comments returned from API v2 endpoint. +@objc public class RemoteCommentV2: NSObject { + public var commentID: Int = 0 + public var postID: Int = 0 + public var parentID: Int = 0 + public var authorID: Int = 0 + public var authorEmail: String? // only available on edit context. + public var authorName: String? + public var authorURL: String? + public var authorIP: String? // only available on edit context. + public var authorUserAgent: String? // only available on edit context. + public var authorAvatarURL: String? + public var date: NSDate? + public var content: String? + public var rawContent: String? + public var link: String? + public var status: String? + public var type: String? +} From de5c7e138f43b9e23012fa90f5f2dd07efafc881 Mon Sep 17 00:00:00 2001 From: David Christiandy <1299411+dvdchr@users.noreply.github.com> Date: Mon, 1 Nov 2021 19:49:22 +0700 Subject: [PATCH 2/8] Convert RemoteCommentV2 to a decodable struct --- .../CommentServiceRemoteREST+ApiV2.swift | 9 ++ WordPressKit/RemoteCommentV2.swift | 103 +++++++++++++++--- 2 files changed, 99 insertions(+), 13 deletions(-) create mode 100644 WordPressKit/CommentServiceRemoteREST+ApiV2.swift diff --git a/WordPressKit/CommentServiceRemoteREST+ApiV2.swift b/WordPressKit/CommentServiceRemoteREST+ApiV2.swift new file mode 100644 index 00000000..5b51bca5 --- /dev/null +++ b/WordPressKit/CommentServiceRemoteREST+ApiV2.swift @@ -0,0 +1,9 @@ +// +// CommentServiceRemoteREST+ApiV2.swift +// WordPressKit +// +// Created by David Christiandy on 01/11/21. +// Copyright © 2021 Automattic Inc. All rights reserved. +// + +import Foundation diff --git a/WordPressKit/RemoteCommentV2.swift b/WordPressKit/RemoteCommentV2.swift index dab28d9b..a7a659a2 100644 --- a/WordPressKit/RemoteCommentV2.swift +++ b/WordPressKit/RemoteCommentV2.swift @@ -1,19 +1,96 @@ /// Captures the JSON structure for Comments returned from API v2 endpoint. -@objc public class RemoteCommentV2: NSObject { - public var commentID: Int = 0 - public var postID: Int = 0 +public struct RemoteCommentV2 { + public var commentID: Int + public var postID: Int public var parentID: Int = 0 - public var authorID: Int = 0 - public var authorEmail: String? // only available on edit context. + public var authorID: Int public var authorName: String? + public var authorEmail: String? // only available in edit context public var authorURL: String? - public var authorIP: String? // only available on edit context. - public var authorUserAgent: String? // only available on edit context. + public var authorIP: String? // only available in edit context + public var authorUserAgent: String? // only available in edit context public var authorAvatarURL: String? - public var date: NSDate? - public var content: String? - public var rawContent: String? - public var link: String? - public var status: String? - public var type: String? + public var date: Date + public var content: String + public var rawContent: String? // only available in edit context + public var link: String + public var status: String + public var type: String +} + +// MARK: - Decodable + +extension RemoteCommentV2: Decodable { + + enum CodingKeys: String, CodingKey { + case id + case post + case parent + case author + case authorName = "author_name" + case authorEmail = "author_email" + case authorURL = "author_url" + case authorIP = "author_ip" + case authorUserAgent = "author_user_agent" + case date = "date_gmt" + case content + case authorAvatarURLs = "author_avatar_urls" + case link + case status + case type + } + + enum ContentKeys: String, CodingKey { + case rendered + case raw + } + + enum AuthorAvatarKeys: String, CodingKey { + case size96 = "96" + } + + public init(from decoder: Decoder) throws { + let container = try decoder.container(keyedBy: CodingKeys.self) + + self.commentID = try container.decode(Int.self, forKey: .id) + self.postID = try container.decode(Int.self, forKey: .post) + self.parentID = try container.decode(Int.self, forKey: .parent) + self.authorID = try container.decode(Int.self, forKey: .author) + self.authorName = try container.decode(String.self, forKey: .authorName) + self.authorEmail = try container.decodeIfPresent(String.self, forKey: .authorEmail) + self.authorURL = try container.decode(String.self, forKey: .authorURL) + self.authorIP = try container.decodeIfPresent(String.self, forKey: .authorIP) + self.authorUserAgent = try container.decodeIfPresent(String.self, forKey: .authorUserAgent) + + guard let dateString = try? container.decode(String.self, forKey: .date), + let date = NSDate(wordPressComJSONString: dateString) as Date? else { + throw DecodingError.dataCorruptedError(forKey: .date, in: container, debugDescription: "Date parsing failed") + } + + self.date = date + + let contentContainer = try container.nestedContainer(keyedBy: ContentKeys.self, forKey: .content) + self.rawContent = try contentContainer.decodeIfPresent(String.self, forKey: .raw) + self.content = try contentContainer.decode(String.self, forKey: .rendered) + + self.link = try container.decode(String.self, forKey: .link) + + let remoteStatus = try container.decode(String.self, forKey: .status) + self.status = Self.status(from: remoteStatus) + self.type = try container.decode(String.self, forKey: .type) + + let avatarContainer = try container.nestedContainer(keyedBy: AuthorAvatarKeys.self, forKey: .authorAvatarURLs) + self.authorAvatarURL = try avatarContainer.decode(String.self, forKey: .size96) + } + + private static func status(from remoteStatus: String) -> String { + switch remoteStatus { + case "unapproved": + return "hold" + case "approved": + return "approve" + default: + return remoteStatus + } + } } From d7d5141e2d2659e5a12ee36f6ad3c9285ba9dea3 Mon Sep 17 00:00:00 2001 From: David Christiandy <1299411+dvdchr@users.noreply.github.com> Date: Mon, 1 Nov 2021 20:19:18 +0700 Subject: [PATCH 3/8] Extend CommentService to fetch comment replies --- WordPressKit.xcodeproj/project.pbxproj | 4 ++ .../CommentServiceRemoteREST+ApiV2.swift | 67 ++++++++++++++++--- WordPressKit/RemoteCommentV2.swift | 8 +-- 3 files changed, 65 insertions(+), 14 deletions(-) diff --git a/WordPressKit.xcodeproj/project.pbxproj b/WordPressKit.xcodeproj/project.pbxproj index 25d5ac20..6766011b 100644 --- a/WordPressKit.xcodeproj/project.pbxproj +++ b/WordPressKit.xcodeproj/project.pbxproj @@ -592,6 +592,7 @@ FAD1345125909DEA00A8FEB1 /* JetpackBackupServiceRemoteTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAD1345025909DEA00A8FEB1 /* JetpackBackupServiceRemoteTests.swift */; }; FEB7A88F271873BD00A8CF85 /* reader-post-comments-update-notification-success.json in Resources */ = {isa = PBXBuildFile; fileRef = FEB7A88E271873BD00A8CF85 /* reader-post-comments-update-notification-success.json */; }; FEE4EF57272FDD4B003CDA3C /* RemoteCommentV2.swift in Sources */ = {isa = PBXBuildFile; fileRef = FEE4EF56272FDD4B003CDA3C /* RemoteCommentV2.swift */; }; + FEE4EF59272FF78C003CDA3C /* CommentServiceRemoteREST+ApiV2.swift in Sources */ = {isa = PBXBuildFile; fileRef = FEE4EF58272FF78C003CDA3C /* CommentServiceRemoteREST+ApiV2.swift */; }; FEFFD99126C1347D00F34231 /* ShareAppContentServiceRemote.swift in Sources */ = {isa = PBXBuildFile; fileRef = FEFFD99026C1347D00F34231 /* ShareAppContentServiceRemote.swift */; }; FEFFD99326C141A800F34231 /* RemoteShareAppContent.swift in Sources */ = {isa = PBXBuildFile; fileRef = FEFFD99226C141A800F34231 /* RemoteShareAppContent.swift */; }; FEFFD99726C158F400F34231 /* share-app-content-success.json in Resources */ = {isa = PBXBuildFile; fileRef = FEFFD99626C158F400F34231 /* share-app-content-success.json */; }; @@ -1225,6 +1226,7 @@ FAD1345025909DEA00A8FEB1 /* JetpackBackupServiceRemoteTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JetpackBackupServiceRemoteTests.swift; sourceTree = ""; }; FEB7A88E271873BD00A8CF85 /* reader-post-comments-update-notification-success.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = "reader-post-comments-update-notification-success.json"; sourceTree = ""; }; FEE4EF56272FDD4B003CDA3C /* RemoteCommentV2.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RemoteCommentV2.swift; sourceTree = ""; }; + FEE4EF58272FF78C003CDA3C /* CommentServiceRemoteREST+ApiV2.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "CommentServiceRemoteREST+ApiV2.swift"; sourceTree = ""; }; FEFFD99026C1347D00F34231 /* ShareAppContentServiceRemote.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShareAppContentServiceRemote.swift; sourceTree = ""; }; FEFFD99226C141A800F34231 /* RemoteShareAppContent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RemoteShareAppContent.swift; sourceTree = ""; }; FEFFD99626C158F400F34231 /* share-app-content-success.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = "share-app-content-success.json"; sourceTree = ""; }; @@ -1727,6 +1729,7 @@ 74BA04ED1F06DC0A00ED5CD8 /* CommentServiceRemote.h */, 74BA04EE1F06DC0A00ED5CD8 /* CommentServiceRemoteREST.h */, 74BA04EF1F06DC0A00ED5CD8 /* CommentServiceRemoteREST.m */, + FEE4EF58272FF78C003CDA3C /* CommentServiceRemoteREST+ApiV2.swift */, 74BA04F01F06DC0A00ED5CD8 /* CommentServiceRemoteXMLRPC.h */, 74BA04F11F06DC0A00ED5CD8 /* CommentServiceRemoteXMLRPC.m */, 74585B8D1F0D51A100E7E667 /* DomainsServiceRemote.swift */, @@ -2975,6 +2978,7 @@ 74B5F0E71EF8699C00B411E7 /* RemotePostType.m in Sources */, 93188D1F1F2262BF0028ED4D /* RemotePostTag.m in Sources */, 74D67F081F15BEB70010C5ED /* RemotePerson.swift in Sources */, + FEE4EF59272FF78C003CDA3C /* CommentServiceRemoteREST+ApiV2.swift in Sources */, 984E34EB22EF7209005C3F92 /* StatsFileDownloadsTimeIntervalData.swift in Sources */, 465F88A2263B325C00F4C950 /* ChecksumUtil.swift in Sources */, 40AB1ADA200FED25009B533D /* PluginDirectoryFeedPage.swift in Sources */, diff --git a/WordPressKit/CommentServiceRemoteREST+ApiV2.swift b/WordPressKit/CommentServiceRemoteREST+ApiV2.swift index 5b51bca5..3a0c8b65 100644 --- a/WordPressKit/CommentServiceRemoteREST+ApiV2.swift +++ b/WordPressKit/CommentServiceRemoteREST+ApiV2.swift @@ -1,9 +1,58 @@ -// -// CommentServiceRemoteREST+ApiV2.swift -// WordPressKit -// -// Created by David Christiandy on 01/11/21. -// Copyright © 2021 Automattic Inc. All rights reserved. -// - -import Foundation +public extension CommentServiceRemoteREST { + + enum RequestKeys: String { + case parent + case author + } + + /// Retrieves a list of comment replies for the specified comment. + /// - Parameters: + /// - commentID: The parent comment ID. + /// - siteID: The ID of the site that contains the specified comment. + /// - parameters: Contains additional request parameters. + /// - success: A closure that will be called when the request succeeds. + /// - failure: A closure that will be called when the request fails. + func getReplies(for commentID: Int, + siteID: Int, + parameters: [RequestKeys: AnyObject], + success: @escaping ([RemoteCommentV2]) -> Void, + failure: @escaping (Error) -> Void) { + let path = coreV2Path(for: "sites/\(siteID)/comments") + let requestParameters = [RequestKeys.parent: commentID as AnyObject] + .merging(parameters) { oldValue, newValue in oldValue } + .reduce([String: AnyObject]()) { result, pair in + var result = result + result[pair.key.rawValue] = pair.value + return result + } + + wordPressComRestApi.GET(path, parameters: requestParameters) { result, _ in + switch result { + case .success(let responseObject): + do { + let data = try JSONSerialization.data(withJSONObject: responseObject, options: []) + let comments = try JSONDecoder().decode([RemoteCommentV2].self, from: data) + success(comments) + } catch { + failure(error) + } + + case .failure(let error): + failure(error) + } + } + } + +} + +// MARK: - Private Helpers + +private extension CommentServiceRemoteREST { + struct Constants { + static let coreV2String = "wp/v2" + } + + func coreV2Path(for endpoint: String) -> String { + return "\(Constants.coreV2String)/\(endpoint)" + } +} diff --git a/WordPressKit/RemoteCommentV2.swift b/WordPressKit/RemoteCommentV2.swift index a7a659a2..4688d899 100644 --- a/WordPressKit/RemoteCommentV2.swift +++ b/WordPressKit/RemoteCommentV2.swift @@ -21,7 +21,6 @@ public struct RemoteCommentV2 { // MARK: - Decodable extension RemoteCommentV2: Decodable { - enum CodingKeys: String, CodingKey { case id case post @@ -61,28 +60,27 @@ extension RemoteCommentV2: Decodable { self.authorURL = try container.decode(String.self, forKey: .authorURL) self.authorIP = try container.decodeIfPresent(String.self, forKey: .authorIP) self.authorUserAgent = try container.decodeIfPresent(String.self, forKey: .authorUserAgent) + self.link = try container.decode(String.self, forKey: .link) + self.type = try container.decode(String.self, forKey: .type) guard let dateString = try? container.decode(String.self, forKey: .date), let date = NSDate(wordPressComJSONString: dateString) as Date? else { throw DecodingError.dataCorruptedError(forKey: .date, in: container, debugDescription: "Date parsing failed") } - self.date = date let contentContainer = try container.nestedContainer(keyedBy: ContentKeys.self, forKey: .content) self.rawContent = try contentContainer.decodeIfPresent(String.self, forKey: .raw) self.content = try contentContainer.decode(String.self, forKey: .rendered) - self.link = try container.decode(String.self, forKey: .link) - let remoteStatus = try container.decode(String.self, forKey: .status) self.status = Self.status(from: remoteStatus) - self.type = try container.decode(String.self, forKey: .type) let avatarContainer = try container.nestedContainer(keyedBy: AuthorAvatarKeys.self, forKey: .authorAvatarURLs) self.authorAvatarURL = try avatarContainer.decode(String.self, forKey: .size96) } + /// Maintain parity with the client-side comment statuses. Refer to `CommentServiceRemoteREST:statusWithRemoteStatus`. private static func status(from remoteStatus: String) -> String { switch remoteStatus { case "unapproved": From f160a8fc3336eb8e05cb8c77432dcba4b3b3cffe Mon Sep 17 00:00:00 2001 From: David Christiandy <1299411+dvdchr@users.noreply.github.com> Date: Mon, 1 Nov 2021 20:28:06 +0700 Subject: [PATCH 4/8] Add some docs --- WordPressKit/RemoteCommentV2.swift | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/WordPressKit/RemoteCommentV2.swift b/WordPressKit/RemoteCommentV2.swift index 4688d899..d041ebc8 100644 --- a/WordPressKit/RemoteCommentV2.swift +++ b/WordPressKit/RemoteCommentV2.swift @@ -31,7 +31,7 @@ extension RemoteCommentV2: Decodable { case authorURL = "author_url" case authorIP = "author_ip" case authorUserAgent = "author_user_agent" - case date = "date_gmt" + case date = "date_gmt" // take the gmt version, as the other `date` parameter doesn't provide timezone information. case content case authorAvatarURLs = "author_avatar_urls" case link @@ -39,13 +39,13 @@ extension RemoteCommentV2: Decodable { case type } - enum ContentKeys: String, CodingKey { + enum ContentCodingKeys: String, CodingKey { case rendered case raw } - enum AuthorAvatarKeys: String, CodingKey { - case size96 = "96" + enum AuthorAvatarCodingKeys: String, CodingKey { + case size96 = "96" // this is the default size for avatar URL in API v1.1. } public init(from decoder: Decoder) throws { @@ -69,14 +69,14 @@ extension RemoteCommentV2: Decodable { } self.date = date - let contentContainer = try container.nestedContainer(keyedBy: ContentKeys.self, forKey: .content) + let contentContainer = try container.nestedContainer(keyedBy: ContentCodingKeys.self, forKey: .content) self.rawContent = try contentContainer.decodeIfPresent(String.self, forKey: .raw) self.content = try contentContainer.decode(String.self, forKey: .rendered) let remoteStatus = try container.decode(String.self, forKey: .status) self.status = Self.status(from: remoteStatus) - let avatarContainer = try container.nestedContainer(keyedBy: AuthorAvatarKeys.self, forKey: .authorAvatarURLs) + let avatarContainer = try container.nestedContainer(keyedBy: AuthorAvatarCodingKeys.self, forKey: .authorAvatarURLs) self.authorAvatarURL = try avatarContainer.decode(String.self, forKey: .size96) } From 432e951373d36f4a29664251e30fd524690d9089 Mon Sep 17 00:00:00 2001 From: David Christiandy <1299411+dvdchr@users.noreply.github.com> Date: Mon, 1 Nov 2021 22:30:30 +0700 Subject: [PATCH 5/8] Add tests --- WordPressKit.xcodeproj/project.pbxproj | 16 ++ .../CommentServiceRemoteREST+APIv2Tests.swift | 155 ++++++++++++++++++ .../comments-v2-edit-context-success.json | 52 ++++++ .../comments-v2-view-context-success.json | 44 +++++ WordPressKitTests/Mock Data/empty-array.json | 1 + 5 files changed, 268 insertions(+) create mode 100644 WordPressKitTests/CommentServiceRemoteREST+APIv2Tests.swift create mode 100644 WordPressKitTests/Mock Data/comments-v2-edit-context-success.json create mode 100644 WordPressKitTests/Mock Data/comments-v2-view-context-success.json create mode 100644 WordPressKitTests/Mock Data/empty-array.json diff --git a/WordPressKit.xcodeproj/project.pbxproj b/WordPressKit.xcodeproj/project.pbxproj index 6766011b..cd67c373 100644 --- a/WordPressKit.xcodeproj/project.pbxproj +++ b/WordPressKit.xcodeproj/project.pbxproj @@ -593,6 +593,10 @@ FEB7A88F271873BD00A8CF85 /* reader-post-comments-update-notification-success.json in Resources */ = {isa = PBXBuildFile; fileRef = FEB7A88E271873BD00A8CF85 /* reader-post-comments-update-notification-success.json */; }; FEE4EF57272FDD4B003CDA3C /* RemoteCommentV2.swift in Sources */ = {isa = PBXBuildFile; fileRef = FEE4EF56272FDD4B003CDA3C /* RemoteCommentV2.swift */; }; FEE4EF59272FF78C003CDA3C /* CommentServiceRemoteREST+ApiV2.swift in Sources */ = {isa = PBXBuildFile; fileRef = FEE4EF58272FF78C003CDA3C /* CommentServiceRemoteREST+ApiV2.swift */; }; + FEE4EF5B27302317003CDA3C /* CommentServiceRemoteREST+APIv2Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = FEE4EF5A27302317003CDA3C /* CommentServiceRemoteREST+APIv2Tests.swift */; }; + FEE4EF5D2730315C003CDA3C /* empty-array.json in Resources */ = {isa = PBXBuildFile; fileRef = FEE4EF5C2730315C003CDA3C /* empty-array.json */; }; + FEE4EF5F2730334D003CDA3C /* comments-v2-view-context-success.json in Resources */ = {isa = PBXBuildFile; fileRef = FEE4EF5E2730334D003CDA3C /* comments-v2-view-context-success.json */; }; + FEE4EF6127303361003CDA3C /* comments-v2-edit-context-success.json in Resources */ = {isa = PBXBuildFile; fileRef = FEE4EF6027303361003CDA3C /* comments-v2-edit-context-success.json */; }; FEFFD99126C1347D00F34231 /* ShareAppContentServiceRemote.swift in Sources */ = {isa = PBXBuildFile; fileRef = FEFFD99026C1347D00F34231 /* ShareAppContentServiceRemote.swift */; }; FEFFD99326C141A800F34231 /* RemoteShareAppContent.swift in Sources */ = {isa = PBXBuildFile; fileRef = FEFFD99226C141A800F34231 /* RemoteShareAppContent.swift */; }; FEFFD99726C158F400F34231 /* share-app-content-success.json in Resources */ = {isa = PBXBuildFile; fileRef = FEFFD99626C158F400F34231 /* share-app-content-success.json */; }; @@ -1227,6 +1231,10 @@ FEB7A88E271873BD00A8CF85 /* reader-post-comments-update-notification-success.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = "reader-post-comments-update-notification-success.json"; sourceTree = ""; }; FEE4EF56272FDD4B003CDA3C /* RemoteCommentV2.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RemoteCommentV2.swift; sourceTree = ""; }; FEE4EF58272FF78C003CDA3C /* CommentServiceRemoteREST+ApiV2.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "CommentServiceRemoteREST+ApiV2.swift"; sourceTree = ""; }; + FEE4EF5A27302317003CDA3C /* CommentServiceRemoteREST+APIv2Tests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "CommentServiceRemoteREST+APIv2Tests.swift"; sourceTree = ""; }; + FEE4EF5C2730315C003CDA3C /* empty-array.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = "empty-array.json"; sourceTree = ""; }; + FEE4EF5E2730334D003CDA3C /* comments-v2-view-context-success.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = "comments-v2-view-context-success.json"; sourceTree = ""; }; + FEE4EF6027303361003CDA3C /* comments-v2-edit-context-success.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = "comments-v2-edit-context-success.json"; sourceTree = ""; }; FEFFD99026C1347D00F34231 /* ShareAppContentServiceRemote.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShareAppContentServiceRemote.swift; sourceTree = ""; }; FEFFD99226C141A800F34231 /* RemoteShareAppContent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RemoteShareAppContent.swift; sourceTree = ""; }; FEFFD99626C158F400F34231 /* share-app-content-success.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = "share-app-content-success.json"; sourceTree = ""; }; @@ -1950,6 +1958,8 @@ FA79F1952591809C00D235A9 /* backup-get-backup-status-in-progress-success.json */, FA79F1862591730D00D235A9 /* backup-prepare-backup-success.json */, ABD95B8425DD6DA200735BEE /* comment-likes-success.json */, + FEE4EF5E2730334D003CDA3C /* comments-v2-view-context-success.json */, + FEE4EF6027303361003CDA3C /* comments-v2-edit-context-success.json */, C92EFF7225E7444400E0308D /* common-starter-site-designs-empty-designs.json */, C92EFF6C25E741E900E0308D /* common-starter-site-designs-malformed.json */, C92EFF6825E7403F00E0308D /* common-starter-site-designs-success.json */, @@ -1958,6 +1968,7 @@ 74585B9E1F0D6E7500E7E667 /* domain-service-bad-json.json */, 74585BA01F0D6F5300E7E667 /* domain-service-empty.json */, FFE247BC20C9C88B002DF3A2 /* empty.json */, + FEE4EF5C2730315C003CDA3C /* empty-array.json */, 930999531F16598A00F006A1 /* get-multiple-themes-v1.2.json */, 930999541F16598A00F006A1 /* get-purchased-themes-v1.1.json */, 930999551F16598A00F006A1 /* get-single-theme-v1.1.json */, @@ -2251,6 +2262,7 @@ ABD95B7E25DD6C4B00735BEE /* CommentServiceRemoteRESTLikesTests.swift */, 98F884D326BC6445009ADF57 /* CommentServiceRemoteRESTTests.swift */, 9817D9D326BC8AF000ECBD8C /* CommentServiceRemoteXMLRPCTests.swift */, + FEE4EF5A27302317003CDA3C /* CommentServiceRemoteREST+APIv2Tests.swift */, ); name = Comment; sourceTree = ""; @@ -2701,6 +2713,7 @@ 7403A3001EF06FEB00DED7DC /* me-settings-success.json in Resources */, 439A44DE2107CF6F00795ED7 /* site-plans-v3-bad-json-failure.json in Resources */, 74B335EA1F06F76B0053A184 /* xmlrpc-response-getpost.xml in Resources */, + FEE4EF6127303361003CDA3C /* comments-v2-edit-context-success.json in Resources */, 740B23E91F17FB4200067A2A /* xmlrpc-wp-getpost-invalid-id-failure.xml in Resources */, 930999561F16598A00F006A1 /* get-multiple-themes-v1.2.json in Resources */, 17BF9A7620C7E18200BF57D2 /* reader-site-search-success-no-data.json in Resources */, @@ -2722,6 +2735,7 @@ BA4BFC582498C04D005C83E7 /* plugin-update-jetpack-already-updated.json in Resources */, 740B23E51F17FB4200067A2A /* xmlrpc-metaweblog-newpost-bad-xml-failure.xml in Resources */, 74C473C91EF335B8009918F2 /* site-active-purchases-empty-response.json in Resources */, + FEE4EF5D2730315C003CDA3C /* empty-array.json in Resources */, 93A4232326CBC845004CCA31 /* me-settings-close-account-success.json in Resources */, 740B23EA1F17FB4200067A2A /* xmlrpc-wp-getpost-success.xml in Resources */, 829BA4331FACF187003ADEEA /* activity-rewind-status-restore-queued.json in Resources */, @@ -2762,6 +2776,7 @@ 74D67F381F15C3740010C5ED /* site-viewers-delete-auth-failure.json in Resources */, 826016FA1F9FAF6300533B6C /* activity-log-success-1.json in Resources */, 9A881752223C01E400A3AB20 /* jetpack-service-error-login-failure.json in Resources */, + FEE4EF5F2730334D003CDA3C /* comments-v2-view-context-success.json in Resources */, 740B23E41F17FB4200067A2A /* xmlrpc-metaweblog-editpost-success.xml in Resources */, 7434E1DE1F17C3C900C40DDB /* site-users-update-role-unknown-user-failure.json in Resources */, 4081977B221F153B00A298E4 /* stats-visits-week.json in Resources */, @@ -3085,6 +3100,7 @@ 74B335D81F06F1CA0053A184 /* MockWordPressComRestApi.swift in Sources */, 32AF21E3236DEB3C001C6502 /* PostServiceRemoteRESTAutosaveTests.swift in Sources */, 3236F79A24AE406D0088E8F3 /* ReaderTopicServiceRemote+InterestsTests.swift in Sources */, + FEE4EF5B27302317003CDA3C /* CommentServiceRemoteREST+APIv2Tests.swift in Sources */, 74B5F0DE1EF82A9600B411E7 /* BlogServiceRemoteRESTTests.m in Sources */, ABD95B7F25DD6C4B00735BEE /* CommentServiceRemoteRESTLikesTests.swift in Sources */, 8B749E8225AF7DDA00023F03 /* JetpackCapabilitiesServiceRemoteTests.swift in Sources */, diff --git a/WordPressKitTests/CommentServiceRemoteREST+APIv2Tests.swift b/WordPressKitTests/CommentServiceRemoteREST+APIv2Tests.swift new file mode 100644 index 00000000..b709ed56 --- /dev/null +++ b/WordPressKitTests/CommentServiceRemoteREST+APIv2Tests.swift @@ -0,0 +1,155 @@ +import Foundation +import XCTest + +@testable import WordPressKit + +final class CommentServiceRemoteREST_APIv2Tests: RemoteTestCase, RESTTestable { + private let successFilename = "comments-v2-view-context-success.json" + private let editContextSuccessFilename = "comments-v2-edit-context-success.json" + private let emptyResultFilename = "empty-array.json" + private let siteId = 0 + private let commentId = 1 + private var remote: CommentServiceRemoteREST! + private var siteCommentsEndpoint: String { + return "sites/\(siteId)/comments" + } + + override func setUp() { + super.setUp() + remote = CommentServiceRemoteREST(wordPressComRestApi: getRestApi(), siteID: NSNumber(value: siteId)) + } + + override func tearDown() { + remote = nil + super.tearDown() + } + + // MARK: - Tests + + func test_getCommentsV2_works() { + let expect = expectation(description: "Fetching comments should succeed") + stubRemoteResponse(siteCommentsEndpoint, filename: successFilename, contentType: .ApplicationJSON) + + remote.getCommentsV2(for: siteId) { comments in + XCTAssertEqual(comments.count, 2) + + let firstComment = comments.first! + XCTAssertEqual(firstComment.commentID, 2) + XCTAssertEqual(firstComment.postID, 49) + XCTAssertEqual(firstComment.parentID, 1) + XCTAssertEqual(firstComment.authorID, 135) + XCTAssertEqual(firstComment.authorName, "John Doe") + XCTAssertEqual(firstComment.authorURL, "https://example.com/john-doe") + XCTAssertEqual(firstComment.date, NSDate(wordPressComJSONString: "2021-07-01T10:50:11+00:00") as Date) + XCTAssertEqual(firstComment.content, "

Some example comment.

\n") + XCTAssertEqual(firstComment.link, "https://example.com/2021/05/25/example-post/comment-page-1/#comment-2") + XCTAssertEqual(firstComment.status, "approve") // verify that it's converted correctly. + XCTAssertEqual(firstComment.type, "comment") + XCTAssertEqual(firstComment.authorAvatarURL, "https://example.com/avatar/sample?s=96&d=identicon&r=g") + + // verify that all the edit-only fields are nil. + XCTAssertNil(firstComment.authorEmail) + XCTAssertNil(firstComment.authorIP) + XCTAssertNil(firstComment.authorUserAgent) + XCTAssertNil(firstComment.rawContent) + + // only verify that the second comment contains a different value. + // assignment correctness has been verified through the first comment. + let secondComment = comments.last! + XCTAssertEqual(secondComment.commentID, 3) + + expect.fulfill() + } failure: { error in + XCTFail("This block shouldn't be called: \(error)") + expect.fulfill() + } + + wait(for: [expect], timeout: timeout) + } + + func test_getCommentsV2_correctlyPassesCustomParameters() { + let mockApi = MockWordPressComRestApi() + let expectedParentId = 4 + let expectedAuthorId = 5 + let expectedContext = "edit" + let parameters: [CommentServiceRemoteREST.RequestKeys: AnyHashable] = [ + .parent: expectedParentId, + .author: expectedAuthorId, + .context: expectedContext + ] + remote = CommentServiceRemoteREST(wordPressComRestApi: mockApi, siteID: NSNumber(value: siteId)) + + remote.getCommentsV2(for: siteId, parameters: parameters, success: { _ in }, failure: { _ in }) + + XCTAssertNotNil(mockApi.parametersPassedIn) + XCTAssertTrue((mockApi.parametersPassedIn! as? [String: AnyObject]) != nil) + + let params = mockApi.parametersPassedIn! as! [String: AnyObject] + XCTAssertNotNil(params[CommentServiceRemoteREST.RequestKeys.parent.rawValue]) + XCTAssertEqual(params[CommentServiceRemoteREST.RequestKeys.parent.rawValue] as! Int, expectedParentId) + XCTAssertNotNil(params[CommentServiceRemoteREST.RequestKeys.author.rawValue]) + XCTAssertEqual(params[CommentServiceRemoteREST.RequestKeys.author.rawValue] as! Int, expectedAuthorId) + XCTAssertNotNil(params[CommentServiceRemoteREST.RequestKeys.context.rawValue]) + XCTAssertEqual(params[CommentServiceRemoteREST.RequestKeys.context.rawValue] as! String, expectedContext) + } + + func test_getCommentsV2_givenEditContext_parsesAdditionalFields() { + let expect = expectation(description: "Fetching comments should succeed") + stubRemoteResponse(siteCommentsEndpoint, filename: editContextSuccessFilename, contentType: .ApplicationJSON) + + remote.getCommentsV2(for: siteId) { comments in + XCTAssertEqual(comments.count, 2) + + let firstComment = comments.first! + XCTAssertEqual(firstComment.authorEmail, "john.doe@example.com") + XCTAssertEqual(firstComment.authorIP, "192.168.1.1") + XCTAssertEqual(firstComment.authorUserAgent, "Mozilla/5.0 (iPhone; CPU iPhone OS 14_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 wp-iphone/17.6") + XCTAssertEqual(firstComment.rawContent, "Some example comment.") + + // only verify that the second comment contains a different value. + // assignment correctness has been verified through the first comment. + let secondComment = comments.last! + XCTAssertEqual(secondComment.authorEmail, "mary.sue@example.com") + + expect.fulfill() + } failure: { _ in + XCTFail("This block shouldn't be called") + expect.fulfill() + } + + wait(for: [expect], timeout: timeout) + } + + func test_getReplies_givenEmptyResult_callsSuccessBlock() { + let expect = expectation(description: "Fetching comments should succeed") + + stubRemoteResponse(siteCommentsEndpoint, filename: emptyResultFilename, contentType: .ApplicationJSON) + remote.getCommentsV2(for: siteId) { comments in + XCTAssertTrue(comments.isEmpty) + expect.fulfill() + } failure: { _ in + XCTFail("This callback shouldn't get called") + } + + wait(for: [expect], timeout: timeout) + } + + func test_getReplies_givenFailureResult_callsFailureBlock() { + let expect = expectation(description: "Fetching comments should fail") + + stubRemoteResponse(siteCommentsEndpoint, filename: emptyResultFilename, contentType: .ApplicationJSON, status: 500) + remote.getCommentsV2(for: siteId) { _ in + XCTFail("This callback shouldn't get called") + } failure: { _ in + expect.fulfill() + } + + wait(for: [expect], timeout: timeout) + } +} + +private extension CommentServiceRemoteREST_APIv2Tests { + + + +} diff --git a/WordPressKitTests/Mock Data/comments-v2-edit-context-success.json b/WordPressKitTests/Mock Data/comments-v2-edit-context-success.json new file mode 100644 index 00000000..282b3505 --- /dev/null +++ b/WordPressKitTests/Mock Data/comments-v2-edit-context-success.json @@ -0,0 +1,52 @@ +[ + { + "id": 2, + "post": 49, + "parent": 1, + "author": 135, + "author_name": "John Doe", + "author_email": "john.doe@example.com", + "author_url": "https://example.com/john-doe", + "author_ip": "192.168.1.1", + "author_user_agent": "Mozilla\/5.0 (iPhone; CPU iPhone OS 14_5 like Mac OS X) AppleWebKit\/605.1.15 (KHTML, like Gecko) Mobile\/15E148 wp-iphone\/17.6", + "date": "2021-07-01T17:50:11", + "date_gmt": "2021-07-01T10:50:11", + "content": { + "rendered": "

Some example comment.<\/p>\n", + "raw": "Some example comment." + }, + "link": "https:\/\/example.com\/2021\/05\/25\/example-post\/comment-page-1\/#comment-2", + "status": "approved", + "type": "comment", + "author_avatar_urls": { + "24": "https:\/\/example.com\/avatar\/sample?s=24&d=identicon&r=g", + "48": "https:\/\/example.com\/avatar\/sample?s=48&d=identicon&r=g", + "96": "https:\/\/example.com\/avatar\/sample?s=96&d=identicon&r=g" + } + }, + { + "id": 3, + "post": 49, + "parent": 1, + "author": 202, + "author_name": "Mary Sue", + "author_email": "mary.sue@example.com", + "author_url": "https://example.com/mary-sue", + "author_ip": "192.168.100.1", + "author_user_agent": "Mozilla\/5.0 (iPhone; CPU iPhone OS 15_0 like Mac OS X) AppleWebKit\/605.1.15 (KHTML, like Gecko) Mobile\/15E148 wp-iphone\/17.6", + "date": "2021-07-01T17:50:20", + "date_gmt": "2021-07-01T10:50:20", + "content": { + "rendered": "

Some reply comment.<\/p>\n", + "raw": "Some reply comment." + }, + "link": "https:\/\/example.com\/2021\/05\/25\/example-post\/comment-page-1\/#comment-3", + "status": "approved", + "type": "comment", + "author_avatar_urls": { + "24": "https:\/\/example.com\/avatar\/sample2?s=24&d=identicon&r=g", + "48": "https:\/\/example.com\/avatar\/sample2?s=48&d=identicon&r=g", + "96": "https:\/\/example.com\/avatar\/sample2?s=96&d=identicon&r=g" + } + } +] diff --git a/WordPressKitTests/Mock Data/comments-v2-view-context-success.json b/WordPressKitTests/Mock Data/comments-v2-view-context-success.json new file mode 100644 index 00000000..fa71ca06 --- /dev/null +++ b/WordPressKitTests/Mock Data/comments-v2-view-context-success.json @@ -0,0 +1,44 @@ +[ + { + "id": 2, + "post": 49, + "parent": 1, + "author": 135, + "author_name": "John Doe", + "author_url": "https://example.com/john-doe", + "date": "2021-07-01T17:50:11", + "date_gmt": "2021-07-01T10:50:11", + "content": { + "rendered": "

Some example comment.<\/p>\n" + }, + "link": "https:\/\/example.com\/2021\/05\/25\/example-post\/comment-page-1\/#comment-2", + "status": "approved", + "type": "comment", + "author_avatar_urls": { + "24": "https:\/\/example.com\/avatar\/sample?s=24&d=identicon&r=g", + "48": "https:\/\/example.com\/avatar\/sample?s=48&d=identicon&r=g", + "96": "https:\/\/example.com\/avatar\/sample?s=96&d=identicon&r=g" + } + }, + { + "id": 3, + "post": 49, + "parent": 1, + "author": 202, + "author_name": "Mary Sue", + "author_url": "https://example.com/mary-sue", + "date": "2021-07-01T17:50:20", + "date_gmt": "2021-07-01T10:50:20", + "content": { + "rendered": "

Some reply comment.<\/p>\n" + }, + "link": "https:\/\/example.com\/2021\/05\/25\/example-post\/comment-page-1\/#comment-3", + "status": "approved", + "type": "comment", + "author_avatar_urls": { + "24": "https:\/\/example.com\/avatar\/sample2?s=24&d=identicon&r=g", + "48": "https:\/\/example.com\/avatar\/sample2?s=48&d=identicon&r=g", + "96": "https:\/\/example.com\/avatar\/sample2?s=96&d=identicon&r=g" + } + } +] diff --git a/WordPressKitTests/Mock Data/empty-array.json b/WordPressKitTests/Mock Data/empty-array.json new file mode 100644 index 00000000..fe51488c --- /dev/null +++ b/WordPressKitTests/Mock Data/empty-array.json @@ -0,0 +1 @@ +[] From 0dbd013daaeab9d91d914f52ba45d1154495e2ab Mon Sep 17 00:00:00 2001 From: David Christiandy <1299411+dvdchr@users.noreply.github.com> Date: Mon, 1 Nov 2021 22:31:00 +0700 Subject: [PATCH 6/8] Tidy up code, add docs, fix a small date issue --- .../CommentServiceRemoteREST+ApiV2.swift | 42 ++++++++++++------- WordPressKit/RemoteCommentV2.swift | 3 +- 2 files changed, 28 insertions(+), 17 deletions(-) diff --git a/WordPressKit/CommentServiceRemoteREST+ApiV2.swift b/WordPressKit/CommentServiceRemoteREST+ApiV2.swift index 3a0c8b65..bcf7a124 100644 --- a/WordPressKit/CommentServiceRemoteREST+ApiV2.swift +++ b/WordPressKit/CommentServiceRemoteREST+ApiV2.swift @@ -1,32 +1,42 @@ public extension CommentServiceRemoteREST { - + /// Lists the available keys for the request parameter. enum RequestKeys: String { + /// The parent comment's ID. In API v2, supplying this parameter filters the list to only contain + /// the child/reply comments of the specified ID. case parent + + /// The dotcom user ID of the comment author. In API v2, supplying this parameter filters the list + /// to only contain comments authored by the specified ID. case author + + /// Valid values are `view`, `edit`, or `embed`. When not specified, the default context is `view`. + case context } - /// Retrieves a list of comment replies for the specified comment. + /// Retrieves a list of comments in a site with the specified siteID. /// - Parameters: - /// - commentID: The parent comment ID. - /// - siteID: The ID of the site that contains the specified comment. - /// - parameters: Contains additional request parameters. - /// - success: A closure that will be called when the request succeeds. - /// - failure: A closure that will be called when the request fails. - func getReplies(for commentID: Int, - siteID: Int, - parameters: [RequestKeys: AnyObject], - success: @escaping ([RemoteCommentV2]) -> Void, - failure: @escaping (Error) -> Void) { + /// - siteID: The ID of the site that contains the specified comment. + /// - parameters: Additional request parameters. Optional. + /// - success: A closure that will be called when the request succeeds. + /// - failure: A closure that will be called when the request fails. + func getCommentsV2(for siteID: Int, + parameters: [RequestKeys: AnyHashable]? = nil, + success: @escaping ([RemoteCommentV2]) -> Void, + failure: @escaping (Error) -> Void) { let path = coreV2Path(for: "sites/\(siteID)/comments") - let requestParameters = [RequestKeys.parent: commentID as AnyObject] - .merging(parameters) { oldValue, newValue in oldValue } - .reduce([String: AnyObject]()) { result, pair in + let requestParameters: [String: AnyHashable] = { + guard let someParameters = parameters else { + return [:] + } + + return someParameters.reduce([String: AnyHashable]()) { result, pair in var result = result result[pair.key.rawValue] = pair.value return result } + }() - wordPressComRestApi.GET(path, parameters: requestParameters) { result, _ in + wordPressComRestApi.GET(path, parameters: requestParameters as [String: AnyObject]) { result, _ in switch result { case .success(let responseObject): do { diff --git a/WordPressKit/RemoteCommentV2.swift b/WordPressKit/RemoteCommentV2.swift index d041ebc8..b407bf6d 100644 --- a/WordPressKit/RemoteCommentV2.swift +++ b/WordPressKit/RemoteCommentV2.swift @@ -63,8 +63,9 @@ extension RemoteCommentV2: Decodable { self.link = try container.decode(String.self, forKey: .link) self.type = try container.decode(String.self, forKey: .type) + // since `date_gmt` is already in GMT timezone, manually add the timezone string to make the rfc3339 formatter happy (or it will throw otherwise). guard let dateString = try? container.decode(String.self, forKey: .date), - let date = NSDate(wordPressComJSONString: dateString) as Date? else { + let date = NSDate(wordPressComJSONString: dateString + "+00:00") as Date? else { throw DecodingError.dataCorruptedError(forKey: .date, in: container, debugDescription: "Date parsing failed") } self.date = date From cd7e22481644928e6c2169e287e1cf1d559dd7fe Mon Sep 17 00:00:00 2001 From: David Christiandy <1299411+dvdchr@users.noreply.github.com> Date: Mon, 1 Nov 2021 22:52:42 +0700 Subject: [PATCH 7/8] Bump podspec version to 4.43.0-beta.1 --- WordPressKit.podspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/WordPressKit.podspec b/WordPressKit.podspec index 670a7a13..4020753c 100644 --- a/WordPressKit.podspec +++ b/WordPressKit.podspec @@ -2,7 +2,7 @@ Pod::Spec.new do |s| s.name = 'WordPressKit' - s.version = '4.42.3' + s.version = '4.43.0-beta.1' s.summary = 'WordPressKit offers a clean and simple WordPress.com and WordPress.org API.' s.description = <<-DESC From 9692556b69369874fbc154774029c3f0daa65647 Mon Sep 17 00:00:00 2001 From: David Christiandy <1299411+dvdchr@users.noreply.github.com> Date: Mon, 1 Nov 2021 23:07:07 +0700 Subject: [PATCH 8/8] Remove unused code --- WordPressKitTests/CommentServiceRemoteREST+APIv2Tests.swift | 6 ------ 1 file changed, 6 deletions(-) diff --git a/WordPressKitTests/CommentServiceRemoteREST+APIv2Tests.swift b/WordPressKitTests/CommentServiceRemoteREST+APIv2Tests.swift index b709ed56..7214d5c2 100644 --- a/WordPressKitTests/CommentServiceRemoteREST+APIv2Tests.swift +++ b/WordPressKitTests/CommentServiceRemoteREST+APIv2Tests.swift @@ -147,9 +147,3 @@ final class CommentServiceRemoteREST_APIv2Tests: RemoteTestCase, RESTTestable { wait(for: [expect], timeout: timeout) } } - -private extension CommentServiceRemoteREST_APIv2Tests { - - - -}