Skip to content

Commit

Permalink
Fix and add some endpoints for review (#171)
Browse files Browse the repository at this point in the history
* `Review.submittedAt` may be nil when just only created

* add `Delete a pending review for a pull request` endpoint

* add `Submit a review for a pull request` endpoint

* add tests

* replace `load` with `post`

* run swiftformat

* bump RequestKit to 3.3.0

* Resolve `FIXME`s

* fix RequestKit version in xcodeproj
  • Loading branch information
417-72KI authored Jul 8, 2024
1 parent 000ad75 commit a8290f7
Show file tree
Hide file tree
Showing 6 changed files with 228 additions and 21 deletions.
2 changes: 1 addition & 1 deletion OctoKit.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -1720,7 +1720,7 @@
repositoryURL = "https://github.com/nerdishbynature/RequestKit.git";
requirement = {
kind = upToNextMajorVersion;
minimumVersion = 3.2.1;
minimumVersion = 3.3.0;
};
};
/* End XCRemoteSwiftPackageReference section */
Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,15 @@
{
"object": {
"pins": [
{
"package": "RequestKit",
"repositoryURL": "https://github.com/nerdishbynature/RequestKit.git",
"state": {
"branch": null,
"revision": "8b0258ea2a4345cbcac90509b764faacea12efb0",
"version": "3.2.1"
}
"originHash" : "530774d6f20b0f00dacedf9498eab8ef4fc75274d7d10f28ee2fdbb4aab6bbb8",
"pins" : [
{
"identity" : "requestkit",
"kind" : "remoteSourceControl",
"location" : "https://github.com/nerdishbynature/RequestKit.git",
"state" : {
"revision" : "e4d905fed938807e36d87f28375f88b7c1c26840",
"version" : "3.3.0"
}
]
},
"version": 1
}
],
"version" : 3
}
86 changes: 82 additions & 4 deletions OctoKit/Review.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ public struct Review {
public let commitID: String
public let id: Int
public let state: State
public let submittedAt: Date
public let submittedAt: Date?
public let user: User

public init(body: String,
Expand Down Expand Up @@ -116,6 +116,40 @@ public extension Octokit {
}
}

@discardableResult
func deletePendingReview(owner: String,
repository: String,
pullRequestNumber: Int,
reviewId: Int,
completion: @escaping (_ response: Result<Review, Error>) -> Void) -> URLSessionDataTaskProtocol? {
let router = ReviewsRouter.deletePendingReview(configuration, owner, repository, pullRequestNumber, reviewId)
return router.load(session, dateDecodingStrategy: .formatted(Time.rfc3339DateFormatter), expectedResultType: Review.self) { pullRequest, error in
if let error = error {
completion(.failure(error))
} else if let pullRequest = pullRequest {
completion(.success(pullRequest))
}
}
}

@discardableResult
func submitReview(owner: String,
repository: String,
pullRequestNumber: Int,
reviewId: Int,
event: Review.Event,
body: String? = nil,
completion: @escaping (_ response: Result<Review, Error>) -> Void) -> URLSessionDataTaskProtocol? {
let router = ReviewsRouter.submitReview(configuration, owner, repository, pullRequestNumber, reviewId, event, body)
return router.load(session, dateDecodingStrategy: .formatted(Time.rfc3339DateFormatter), expectedResultType: Review.self) { pullRequest, error in
if let error = error {
completion(.failure(error))
} else if let pullRequest = pullRequest {
completion(.success(pullRequest))
}
}
}

#if compiler(>=5.5.2) && canImport(_Concurrency)
@available(macOS 12.0, iOS 15.0, tvOS 15.0, watchOS 8.0, *)
func reviews(owner: String,
Expand All @@ -135,27 +169,55 @@ public extension Octokit {
body: String? = nil,
comments: [Review.Comment] = []) async throws -> Review {
let router = ReviewsRouter.postReview(configuration, owner, repository, pullRequestNumber, commitId, event, body, comments)
return try await router.load(session, dateDecodingStrategy: .formatted(Time.rfc3339DateFormatter), expectedResultType: Review.self)
return try await router.post(session, dateDecodingStrategy: .formatted(Time.rfc3339DateFormatter), expectedResultType: Review.self)
}

@available(macOS 12.0, iOS 15.0, tvOS 15.0, watchOS 8.0, *)
@discardableResult
func deletePendingReview(owner: String,
repository: String,
pullRequestNumber: Int,
reviewId: Int) async throws -> Review {
let router = ReviewsRouter.deletePendingReview(configuration, owner, repository, pullRequestNumber, reviewId)
return try await router.post(session, dateDecodingStrategy: .formatted(Time.rfc3339DateFormatter), expectedResultType: Review.self)
}

@available(macOS 12.0, iOS 15.0, tvOS 15.0, watchOS 8.0, *)
@discardableResult
func submitReview(owner: String,
repository: String,
pullRequestNumber: Int,
reviewId: Int,
event: Review.Event,
body: String? = nil) async throws -> Review {
let router = ReviewsRouter.submitReview(configuration, owner, repository, pullRequestNumber, reviewId, event, body)
return try await router.post(session, dateDecodingStrategy: .formatted(Time.rfc3339DateFormatter), expectedResultType: Review.self)
}
#endif
}

enum ReviewsRouter: JSONPostRouter {
case listReviews(Configuration, String, String, Int)
case postReview(Configuration, String, String, Int, String?, Review.Event?, String?, [Review.Comment]?)
case deletePendingReview(Configuration, String, String, Int, Int)
case submitReview(Configuration, String, String, Int, Int, Review.Event, String?)

var method: HTTPMethod {
switch self {
case .listReviews:
return .GET
case .postReview:
return .POST
case .deletePendingReview:
return .DELETE
case .submitReview:
return .POST
}
}

var encoding: HTTPEncoding {
switch self {
case .postReview:
case .postReview, .deletePendingReview, .submitReview:
return .json
default:
return .url
Expand All @@ -168,12 +230,16 @@ enum ReviewsRouter: JSONPostRouter {
return config
case let .postReview(config, _, _, _, _, _, _, _):
return config
case let .deletePendingReview(config, _, _, _, _):
return config
case let .submitReview(config, _, _, _, _, _, _):
return config
}
}

var params: [String: Any] {
switch self {
case .listReviews:
case .listReviews, .deletePendingReview:
return [:]
case let .postReview(_, _, _, _, commitId, event, body, comments):
var parameters = [String: Any]()
Expand Down Expand Up @@ -211,6 +277,14 @@ enum ReviewsRouter: JSONPostRouter {
}
}
return parameters
case let .submitReview(_, _, _, _, _, event, body):
var parameters: [String: Any] = [
"event": event.rawValue
]
if let body = body {
parameters["body"] = body
}
return parameters
}
}

Expand All @@ -220,6 +294,10 @@ enum ReviewsRouter: JSONPostRouter {
return "repos/\(owner)/\(repository)/pulls/\(pullRequestNumber)/reviews"
case let .postReview(_, owner, repository, pullRequestNumber, _, _, _, _):
return "repos/\(owner)/\(repository)/pulls/\(pullRequestNumber)/reviews"
case let .deletePendingReview(_, owner, repository, pullRequestNumber, reviewId):
return "repos/\(owner)/\(repository)/pulls/\(pullRequestNumber)/reviews/\(reviewId)"
case let .submitReview(_, owner, repository, pullRequestNumber, reviewId, _, _):
return "repos/\(owner)/\(repository)/pulls/\(pullRequestNumber)/reviews/\(reviewId)/events"
}
}
}
4 changes: 2 additions & 2 deletions Package.resolved
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@
"repositoryURL": "https://github.com/nerdishbynature/RequestKit.git",
"state": {
"branch": null,
"revision": "8b0258ea2a4345cbcac90509b764faacea12efb0",
"version": "3.2.1"
"revision": "e4d905fed938807e36d87f28375f88b7c1c26840",
"version": "3.3.0"
}
},
{
Expand Down
2 changes: 1 addition & 1 deletion Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ let package = Package(
),
],
dependencies: [
.package(url: "https://github.com/nerdishbynature/RequestKit.git", from: "3.2.1"),
.package(url: "https://github.com/nerdishbynature/RequestKit.git", from: "3.3.0"),
.package(url: "https://github.com/nicklockwood/SwiftFormat", from: "0.52.8")
],
targets: [
Expand Down
130 changes: 130 additions & 0 deletions Tests/OctoKitTests/ReviewTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -133,4 +133,134 @@ class ReviewTests: XCTestCase {
XCTAssertTrue(session.wasCalled)
}
#endif

func testDeletePendingReview() {
let session = OctoKitURLTestSession(expectedURL: "https://api.github.com/repos/octocat/Hello-World/pulls/1/reviews/80", expectedHTTPMethod: "DELETE", jsonFile: "review", statusCode: 200)
let task = Octokit(session: session).deletePendingReview(owner: "octocat",
repository: "Hello-World",
pullRequestNumber: 1,
reviewId: 80) {
switch $0 {
case let .success(review):
XCTAssertEqual(review.body, "Here is the body for the review.")
XCTAssertEqual(review.commitID, "ecdd80bb57125d7ba9641ffaa4d7d2c19d3f3091")
XCTAssertEqual(review.id, 80)
XCTAssertEqual(review.state, .approved)
XCTAssertEqual(review.submittedAt, Date(timeIntervalSince1970: 1_574_012_623.0))
XCTAssertEqual(review.user.avatarURL, "https://github.com/images/error/octocat_happy.gif")
XCTAssertNil(review.user.blog)
XCTAssertNil(review.user.company)
XCTAssertNil(review.user.email)
XCTAssertEqual(review.user.gravatarID, "")
XCTAssertEqual(review.user.id, 1)
XCTAssertNil(review.user.location)
XCTAssertEqual(review.user.login, "octocat")
XCTAssertNil(review.user.name)
XCTAssertNil(review.user.numberOfPublicGists)
XCTAssertNil(review.user.numberOfPublicRepos)
XCTAssertNil(review.user.numberOfPrivateRepos)
XCTAssertEqual(review.user.type, "User")
case .failure:
XCTFail("should not get an error")
}
}
XCTAssertNotNil(task)
XCTAssertTrue(session.wasCalled)
}

#if compiler(>=5.5.2) && canImport(_Concurrency)
@available(macOS 12.0, iOS 15.0, tvOS 15.0, watchOS 8.0, *)
func testDeletePendingReviewAsync() async throws {
let session = OctoKitURLTestSession(expectedURL: "https://api.github.com/repos/octocat/Hello-World/pulls/1/reviews/80", expectedHTTPMethod: "DELETE", jsonFile: "review", statusCode: 200)
let review = try await Octokit(session: session).deletePendingReview(owner: "octocat",
repository: "Hello-World",
pullRequestNumber: 1,
reviewId: 80)
XCTAssertEqual(review.body, "Here is the body for the review.")
XCTAssertEqual(review.commitID, "ecdd80bb57125d7ba9641ffaa4d7d2c19d3f3091")
XCTAssertEqual(review.id, 80)
XCTAssertEqual(review.state, .approved)
XCTAssertEqual(review.submittedAt, Date(timeIntervalSince1970: 1_574_012_623.0))
XCTAssertEqual(review.user.avatarURL, "https://github.com/images/error/octocat_happy.gif")
XCTAssertNil(review.user.blog)
XCTAssertNil(review.user.company)
XCTAssertNil(review.user.email)
XCTAssertEqual(review.user.gravatarID, "")
XCTAssertEqual(review.user.id, 1)
XCTAssertNil(review.user.location)
XCTAssertEqual(review.user.login, "octocat")
XCTAssertNil(review.user.name)
XCTAssertNil(review.user.numberOfPublicGists)
XCTAssertNil(review.user.numberOfPublicRepos)
XCTAssertNil(review.user.numberOfPrivateRepos)
XCTAssertEqual(review.user.type, "User")
XCTAssertTrue(session.wasCalled)
}
#endif

func testSubmitReview() {
let session = OctoKitURLTestSession(expectedURL: "https://api.github.com/repos/octocat/Hello-World/pulls/1/reviews/80/events", expectedHTTPMethod: "POST", jsonFile: "review", statusCode: 200)
let task = Octokit(session: session).submitReview(owner: "octocat",
repository: "Hello-World",
pullRequestNumber: 1,
reviewId: 80,
event: .approve) {
switch $0 {
case let .success(review):
XCTAssertEqual(review.body, "Here is the body for the review.")
XCTAssertEqual(review.commitID, "ecdd80bb57125d7ba9641ffaa4d7d2c19d3f3091")
XCTAssertEqual(review.id, 80)
XCTAssertEqual(review.state, .approved)
XCTAssertEqual(review.submittedAt, Date(timeIntervalSince1970: 1_574_012_623.0))
XCTAssertEqual(review.user.avatarURL, "https://github.com/images/error/octocat_happy.gif")
XCTAssertNil(review.user.blog)
XCTAssertNil(review.user.company)
XCTAssertNil(review.user.email)
XCTAssertEqual(review.user.gravatarID, "")
XCTAssertEqual(review.user.id, 1)
XCTAssertNil(review.user.location)
XCTAssertEqual(review.user.login, "octocat")
XCTAssertNil(review.user.name)
XCTAssertNil(review.user.numberOfPublicGists)
XCTAssertNil(review.user.numberOfPublicRepos)
XCTAssertNil(review.user.numberOfPrivateRepos)
XCTAssertEqual(review.user.type, "User")
case .failure:
XCTFail("should not get an error")
}
}
XCTAssertNotNil(task)
XCTAssertTrue(session.wasCalled)
}

#if compiler(>=5.5.2) && canImport(_Concurrency)
@available(macOS 12.0, iOS 15.0, tvOS 15.0, watchOS 8.0, *)
func testSubmitReviewAsync() async throws {
let session = OctoKitURLTestSession(expectedURL: "https://api.github.com/repos/octocat/Hello-World/pulls/1/reviews/80/events", expectedHTTPMethod: "POST", jsonFile: "review", statusCode: 200)
let review = try await Octokit(session: session).submitReview(owner: "octocat",
repository: "Hello-World",
pullRequestNumber: 1,
reviewId: 80,
event: .approve)
XCTAssertEqual(review.body, "Here is the body for the review.")
XCTAssertEqual(review.commitID, "ecdd80bb57125d7ba9641ffaa4d7d2c19d3f3091")
XCTAssertEqual(review.id, 80)
XCTAssertEqual(review.state, .approved)
XCTAssertEqual(review.submittedAt, Date(timeIntervalSince1970: 1_574_012_623.0))
XCTAssertEqual(review.user.avatarURL, "https://github.com/images/error/octocat_happy.gif")
XCTAssertNil(review.user.blog)
XCTAssertNil(review.user.company)
XCTAssertNil(review.user.email)
XCTAssertEqual(review.user.gravatarID, "")
XCTAssertEqual(review.user.id, 1)
XCTAssertNil(review.user.location)
XCTAssertEqual(review.user.login, "octocat")
XCTAssertNil(review.user.name)
XCTAssertNil(review.user.numberOfPublicGists)
XCTAssertNil(review.user.numberOfPublicRepos)
XCTAssertNil(review.user.numberOfPrivateRepos)
XCTAssertEqual(review.user.type, "User")
XCTAssertTrue(session.wasCalled)
}
#endif
}

0 comments on commit a8290f7

Please sign in to comment.