From 3979481d279afdfc973aa4f1a8cfddb398401440 Mon Sep 17 00:00:00 2001 From: 417-72KI <417.72ki@gmail.com> Date: Fri, 27 Nov 2020 18:15:15 +0900 Subject: [PATCH 1/5] Add list releases request --- OctoKit/Releases.swift | 32 +++++++++++++++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/OctoKit/Releases.swift b/OctoKit/Releases.swift index 271d37ed..20d65f50 100644 --- a/OctoKit/Releases.swift +++ b/OctoKit/Releases.swift @@ -49,6 +49,25 @@ public struct Release: Codable { // MARK: request public extension Octokit { + /// Fetches the list of releases. + /// - Parameters: + /// - session: RequestKitURLSession, defaults to URLSession.shared() + /// - owner: The user or organization that owns the repositories. + /// - repository: The name of the repository. + /// - completion: Callback for the outcome of the fetch. + @discardableResult + func listReleases(_ session: RequestKitURLSession = URLSession.shared, owner: String, repository: String, completion: @escaping (_ response: Response<[Release]>) -> Void) -> URLSessionDataTaskProtocol? { + let router = ReleaseRouter.listReleases(configuration, owner, repository) + return router.load(session, dateDecodingStrategy: .formatted(Time.rfc3339DateFormatter), expectedResultType: [Release].self) { releases, error in + if let error = error { + completion(Response.failure(error)) + } else { + if let releases = releases { + completion(Response.success(releases)) + } + } + } + } /// Creates a new release. /// - Parameters: @@ -83,16 +102,23 @@ public extension Octokit { // MARK: Router enum ReleaseRouter: JSONPostRouter { + case listReleases(Configuration, String, String) case postRelease(Configuration, String, String, String, String?, String?, String?, Bool, Bool) var configuration: Configuration { switch self { + case .listReleases(let config, _, _): return config case .postRelease(let config, _, _, _, _, _, _, _, _): return config } } var method: HTTPMethod { - return .POST + switch self { + case .listReleases: + return .GET + case .postRelease: + return .POST + } } var encoding: HTTPEncoding { @@ -101,6 +127,8 @@ enum ReleaseRouter: JSONPostRouter { var params: [String: Any] { switch self { + case .listReleases: + return [:] case .postRelease(_, _, _, let tagName, let targetCommitish, let name, let body, let prerelease, let draft): var params: [String: Any] = [ "tag_name": tagName, @@ -122,6 +150,8 @@ enum ReleaseRouter: JSONPostRouter { var path: String { switch self { + case let .listReleases(_, owner, repo): + return "repos/\(owner)/\(repo)/releases" case .postRelease(_, let owner, let repo, _, _, _, _, _, _): return "repos/\(owner)/\(repo)/releases" } From 8c6b73c3503022e67480511ca6ecfff577a11e7e Mon Sep 17 00:00:00 2001 From: 417-72KI <417.72ki@gmail.com> Date: Fri, 27 Nov 2020 18:16:07 +0900 Subject: [PATCH 2/5] set Optional for some properties which will be null on draft release. --- OctoKit/Releases.swift | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/OctoKit/Releases.swift b/OctoKit/Releases.swift index 20d65f50..ea7d6b5d 100644 --- a/OctoKit/Releases.swift +++ b/OctoKit/Releases.swift @@ -18,8 +18,8 @@ public struct Release: Codable { public let url: URL public let htmlURL: URL public let assetsURL: URL - public let tarballURL: URL - public let zipballURL: URL + public let tarballURL: URL? + public let zipballURL: URL? public let nodeId: String public let tagName: String public let commitish: String @@ -28,7 +28,7 @@ public struct Release: Codable { public let draft: Bool public let prerelease: Bool public let createdAt: Date - public let publishedAt: Date + public let publishedAt: Date? public let author: User enum CodingKeys: String, CodingKey { @@ -122,7 +122,12 @@ enum ReleaseRouter: JSONPostRouter { } var encoding: HTTPEncoding { - return .json + switch self { + case .listReleases: + return .url + case .postRelease: + return .json + } } var params: [String: Any] { From b364e6c5abb9ffe021a13d608f51a1ac8d80ef2f Mon Sep 17 00:00:00 2001 From: 417-72KI <417.72ki@gmail.com> Date: Fri, 27 Nov 2020 18:36:15 +0900 Subject: [PATCH 3/5] add test case for list releases request --- Tests/OctoKitTests/Fixtures/releases.json | 80 +++++++++++++++++++++++ Tests/OctoKitTests/ReleasesTests.swift | 43 ++++++++++++ 2 files changed, 123 insertions(+) create mode 100644 Tests/OctoKitTests/Fixtures/releases.json diff --git a/Tests/OctoKitTests/Fixtures/releases.json b/Tests/OctoKitTests/Fixtures/releases.json new file mode 100644 index 00000000..198aba8c --- /dev/null +++ b/Tests/OctoKitTests/Fixtures/releases.json @@ -0,0 +1,80 @@ +[ + { + "url": "https://api.github.com/repos/octocat/Hello-World/releases/1", + "html_url": "https://github.com/octocat/Hello-World/releases/v1.0.0", + "assets_url": "https://api.github.com/repos/octocat/Hello-World/releases/1/assets", + "upload_url": "https://uploads.github.com/repos/octocat/Hello-World/releases/1/assets{?name,label}", + "tarball_url": null, + "zipball_url": null, + "id": 1, + "node_id": "MDc6UmVsZWFzZTE=", + "tag_name": "v1.0.0", + "target_commitish": "master", + "name": "v1.0.0 Release", + "body": "The changelog of this release", + "draft": true, + "prerelease": false, + "created_at": "2013-02-27T19:35:32Z", + "published_at": null, + "author": { + "login": "octocat", + "id": 1, + "node_id": "MDQ6VXNlcjE=", + "avatar_url": "https://github.com/images/error/octocat_happy.gif", + "gravatar_id": "", + "url": "https://api.github.com/users/octocat", + "html_url": "https://github.com/octocat", + "followers_url": "https://api.github.com/users/octocat/followers", + "following_url": "https://api.github.com/users/octocat/following{/other_user}", + "gists_url": "https://api.github.com/users/octocat/gists{/gist_id}", + "starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/octocat/subscriptions", + "organizations_url": "https://api.github.com/users/octocat/orgs", + "repos_url": "https://api.github.com/users/octocat/repos", + "events_url": "https://api.github.com/users/octocat/events{/privacy}", + "received_events_url": "https://api.github.com/users/octocat/received_events", + "type": "User", + "site_admin": false + }, + "assets": [] + }, + { + "url": "https://api.github.com/repos/octocat/Hello-World/releases/1", + "html_url": "https://github.com/octocat/Hello-World/releases/v1.0.0", + "assets_url": "https://api.github.com/repos/octocat/Hello-World/releases/1/assets", + "upload_url": "https://uploads.github.com/repos/octocat/Hello-World/releases/1/assets{?name,label}", + "tarball_url": "https://api.github.com/repos/octocat/Hello-World/tarball/v1.0.0", + "zipball_url": "https://api.github.com/repos/octocat/Hello-World/zipball/v1.0.0", + "id": 1, + "node_id": "MDc6UmVsZWFzZTE=", + "tag_name": "v1.0.0", + "target_commitish": "master", + "name": "v1.0.0 Release", + "body": "The changelog of this release", + "draft": false, + "prerelease": false, + "created_at": "2013-02-27T19:35:32Z", + "published_at": "2013-02-27T19:35:32Z", + "author": { + "login": "octocat", + "id": 1, + "node_id": "MDQ6VXNlcjE=", + "avatar_url": "https://github.com/images/error/octocat_happy.gif", + "gravatar_id": "", + "url": "https://api.github.com/users/octocat", + "html_url": "https://github.com/octocat", + "followers_url": "https://api.github.com/users/octocat/followers", + "following_url": "https://api.github.com/users/octocat/following{/other_user}", + "gists_url": "https://api.github.com/users/octocat/gists{/gist_id}", + "starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/octocat/subscriptions", + "organizations_url": "https://api.github.com/users/octocat/orgs", + "repos_url": "https://api.github.com/users/octocat/repos", + "events_url": "https://api.github.com/users/octocat/events{/privacy}", + "received_events_url": "https://api.github.com/users/octocat/received_events", + "type": "User", + "site_admin": false + }, + "assets": [] + } +] \ No newline at end of file diff --git a/Tests/OctoKitTests/ReleasesTests.swift b/Tests/OctoKitTests/ReleasesTests.swift index 71574644..dd8b3d35 100644 --- a/Tests/OctoKitTests/ReleasesTests.swift +++ b/Tests/OctoKitTests/ReleasesTests.swift @@ -11,12 +11,55 @@ import OctoKit final class ReleasesTests: XCTestCase { static var allTests = [ + ("testListReleases", testListReleases), ("testPostRelease", testPostRelease), ("testLinuxTestSuiteIncludesAllTests", testLinuxTestSuiteIncludesAllTests) ] // MARK: Actual Request tests + func testListReleases() { + let session = OctoKitURLTestSession(expectedURL: "https://api.github.com/repos/octocat/Hello-World/releases", expectedHTTPMethod: "GET", jsonFile: "Fixtures/releases", statusCode: 200) + let task = Octokit().listReleases(session, owner: "octocat", repository: "Hello-World") { + switch $0 { + case let .success(releases): + XCTAssertEqual(releases.count, 2) + do { + let release = try XCTUnwrap(releases.first) + XCTAssertEqual(release.tagName, "v1.0.0") + XCTAssertEqual(release.commitish, "master") + XCTAssertEqual(release.name, "v1.0.0 Release") + XCTAssertEqual(release.body, "The changelog of this release") + XCTAssertFalse(release.prerelease) + XCTAssertTrue(release.draft) + XCTAssertNil(release.tarballURL) + XCTAssertNil(release.zipballURL) + XCTAssertNil(release.publishedAt) + } catch { + XCTFail("Unwrap failed with error \(error)") + } + do { + let release = try XCTUnwrap(releases.last) + XCTAssertEqual(release.tagName, "v1.0.0") + XCTAssertEqual(release.commitish, "master") + XCTAssertEqual(release.name, "v1.0.0 Release") + XCTAssertEqual(release.body, "The changelog of this release") + XCTAssertFalse(release.prerelease) + XCTAssertFalse(release.draft) + XCTAssertNotNil(release.tarballURL) + XCTAssertNotNil(release.zipballURL) + XCTAssertNotNil(release.publishedAt) + } catch { + XCTFail("Unwrap failed with error \(error)") + } + case let .failure(error): + XCTAssert(false, "Endpoint failed with error \(error)") + } + } + XCTAssertNotNil(task) + XCTAssertTrue(session.wasCalled) + } + func testPostRelease() { let session = OctoKitURLTestSession(expectedURL: "https://api.github.com/repos/octocat/Hello-World/releases", expectedHTTPMethod: "POST", jsonFile: "post_release", statusCode: 201) let task = Octokit().postRelease(session, owner: "octocat", repository: "Hello-World", tagName: "v1.0.0", targetCommitish: "master", name: "v1.0.0 Release", body: "The changelog of this release", prerelease: false, draft: false) { response in From c26d7c17f9970c65ed156485b20520840abc5bbf Mon Sep 17 00:00:00 2001 From: 417-72KI <417.72ki@gmail.com> Date: Fri, 27 Nov 2020 19:04:50 +0900 Subject: [PATCH 4/5] replace `XCTUnwrap` (not supported in Swift 4.2) to `if let` clause. --- Tests/OctoKitTests/ReleasesTests.swift | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/Tests/OctoKitTests/ReleasesTests.swift b/Tests/OctoKitTests/ReleasesTests.swift index dd8b3d35..5fdc6f2b 100644 --- a/Tests/OctoKitTests/ReleasesTests.swift +++ b/Tests/OctoKitTests/ReleasesTests.swift @@ -24,8 +24,7 @@ final class ReleasesTests: XCTestCase { switch $0 { case let .success(releases): XCTAssertEqual(releases.count, 2) - do { - let release = try XCTUnwrap(releases.first) + if let release = releases.first { XCTAssertEqual(release.tagName, "v1.0.0") XCTAssertEqual(release.commitish, "master") XCTAssertEqual(release.name, "v1.0.0 Release") @@ -35,11 +34,10 @@ final class ReleasesTests: XCTestCase { XCTAssertNil(release.tarballURL) XCTAssertNil(release.zipballURL) XCTAssertNil(release.publishedAt) - } catch { - XCTFail("Unwrap failed with error \(error)") + } else { + XCTFail("Failed to unwrap `releases.first`") } - do { - let release = try XCTUnwrap(releases.last) + if let release = releases.last { XCTAssertEqual(release.tagName, "v1.0.0") XCTAssertEqual(release.commitish, "master") XCTAssertEqual(release.name, "v1.0.0 Release") @@ -49,8 +47,8 @@ final class ReleasesTests: XCTestCase { XCTAssertNotNil(release.tarballURL) XCTAssertNotNil(release.zipballURL) XCTAssertNotNil(release.publishedAt) - } catch { - XCTFail("Unwrap failed with error \(error)") + } else { + XCTFail("Failed to unwrap `releases.last`") } case let .failure(error): XCTAssert(false, "Endpoint failed with error \(error)") From 423767f7bd7e214a5f579f90199c396966bed72b Mon Sep 17 00:00:00 2001 From: 417-72KI <417.72ki@gmail.com> Date: Tue, 1 Dec 2020 01:05:11 +0900 Subject: [PATCH 5/5] use `XCTAssertEqual` rather than `XCTAssertNotNil` --- Tests/OctoKitTests/ReleasesTests.swift | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Tests/OctoKitTests/ReleasesTests.swift b/Tests/OctoKitTests/ReleasesTests.swift index 5fdc6f2b..b1a42f6c 100644 --- a/Tests/OctoKitTests/ReleasesTests.swift +++ b/Tests/OctoKitTests/ReleasesTests.swift @@ -44,9 +44,9 @@ final class ReleasesTests: XCTestCase { XCTAssertEqual(release.body, "The changelog of this release") XCTAssertFalse(release.prerelease) XCTAssertFalse(release.draft) - XCTAssertNotNil(release.tarballURL) - XCTAssertNotNil(release.zipballURL) - XCTAssertNotNil(release.publishedAt) + XCTAssertEqual(release.tarballURL?.absoluteString, "https://api.github.com/repos/octocat/Hello-World/tarball/v1.0.0") + XCTAssertEqual(release.zipballURL?.absoluteString, "https://api.github.com/repos/octocat/Hello-World/zipball/v1.0.0") + XCTAssertEqual(release.publishedAt, Date(timeIntervalSince1970: 1361993732.0)) } else { XCTFail("Failed to unwrap `releases.last`") }