mirror of
https://github.com/status-im/sourcecred.git
synced 2025-02-17 06:56:36 +00:00
Add PR reviews and comments to GitHub api (#179)
Also, a slight re-organization of the GitHub api test code.
This commit is contained in:
parent
16e8e399e6
commit
a1d072846d
@ -1,8 +1,8 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`GitHub porcelain API Author 1`] = `2`;
|
||||
exports[`GitHub porcelain API has wrappers for Authors 1`] = `2`;
|
||||
|
||||
exports[`GitHub porcelain API Author 2`] = `
|
||||
exports[`GitHub porcelain API has wrappers for Authors 2`] = `
|
||||
Object {
|
||||
"address": Object {
|
||||
"id": "https://github.com/decentralion",
|
||||
@ -18,9 +18,9 @@ Object {
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`GitHub porcelain API Comment 1`] = `3`;
|
||||
exports[`GitHub porcelain API has wrappers for Comments 1`] = `3`;
|
||||
|
||||
exports[`GitHub porcelain API Comment 2`] = `
|
||||
exports[`GitHub porcelain API has wrappers for Comments 2`] = `
|
||||
Object {
|
||||
"address": Object {
|
||||
"id": "https://github.com/sourcecred/example-repo/issues/6#issuecomment-373768442",
|
||||
@ -35,7 +35,7 @@ Object {
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`GitHub porcelain API Issue 1`] = `
|
||||
exports[`GitHub porcelain API has wrappers for Issues 1`] = `
|
||||
Object {
|
||||
"address": Object {
|
||||
"id": "https://github.com/sourcecred/example-repo/issues/1",
|
||||
@ -52,7 +52,7 @@ Object {
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`GitHub porcelain API PullRequest 1`] = `
|
||||
exports[`GitHub porcelain API has wrappers for PullRequests 1`] = `
|
||||
Object {
|
||||
"address": Object {
|
||||
"id": "https://github.com/sourcecred/example-repo/pull/3",
|
||||
|
@ -11,6 +11,9 @@ import type {
|
||||
NodeType,
|
||||
IssueNodePayload,
|
||||
PullRequestNodePayload,
|
||||
PullRequestReviewNodePayload,
|
||||
PullRequestReviewCommentNodePayload,
|
||||
PullRequestReviewState,
|
||||
CommentNodePayload,
|
||||
AuthorNodePayload,
|
||||
AuthorSubtype,
|
||||
@ -23,9 +26,17 @@ import {
|
||||
AUTHOR_NODE_TYPE,
|
||||
ISSUE_NODE_TYPE,
|
||||
PULL_REQUEST_NODE_TYPE,
|
||||
PULL_REQUEST_REVIEW_NODE_TYPE,
|
||||
PULL_REQUEST_REVIEW_COMMENT_NODE_TYPE,
|
||||
} from "./types";
|
||||
|
||||
export type Entity = Issue | PullRequest | Comment | Author;
|
||||
export type Entity =
|
||||
| Issue
|
||||
| PullRequest
|
||||
| Comment
|
||||
| Author
|
||||
| PullRequestReview
|
||||
| PullRequestReviewComment;
|
||||
|
||||
function assertEntityType(e: Entity, t: NodeType) {
|
||||
if (e.type() !== t) {
|
||||
@ -105,7 +116,12 @@ class GithubEntity<T: NodePayload> {
|
||||
}
|
||||
|
||||
class Post<
|
||||
T: IssueNodePayload | PullRequestNodePayload | CommentNodePayload
|
||||
T:
|
||||
| IssueNodePayload
|
||||
| PullRequestNodePayload
|
||||
| CommentNodePayload
|
||||
| PullRequestReviewNodePayload
|
||||
| PullRequestReviewCommentNodePayload
|
||||
> extends GithubEntity<T> {
|
||||
authors(): Author[] {
|
||||
return this.graph
|
||||
@ -159,6 +175,14 @@ export class PullRequest extends Commentable<PullRequestNodePayload> {
|
||||
title(): string {
|
||||
return this.node().payload.title;
|
||||
}
|
||||
reviews(): PullRequestReview[] {
|
||||
return this.graph
|
||||
.neighborhood(this.nodeAddress, {
|
||||
edgeType: CONTAINS_EDGE_TYPE,
|
||||
nodeType: PULL_REQUEST_REVIEW_NODE_TYPE,
|
||||
})
|
||||
.map(({neighbor}) => new PullRequestReview(this.graph, neighbor));
|
||||
}
|
||||
}
|
||||
|
||||
export class Issue extends Commentable<IssueNodePayload> {
|
||||
@ -180,3 +204,31 @@ export class Comment extends Post<CommentNodePayload> {
|
||||
return (e: any);
|
||||
}
|
||||
}
|
||||
|
||||
export class PullRequestReview extends Post<PullRequestReviewNodePayload> {
|
||||
static from(e: Entity): PullRequestReview {
|
||||
assertEntityType(e, PULL_REQUEST_REVIEW_NODE_TYPE);
|
||||
return (e: any);
|
||||
}
|
||||
state(): PullRequestReviewState {
|
||||
return this.node().payload.state;
|
||||
}
|
||||
|
||||
comments(): PullRequestReviewComment[] {
|
||||
return this.graph
|
||||
.neighborhood(this.nodeAddress, {
|
||||
edgeType: CONTAINS_EDGE_TYPE,
|
||||
nodeType: PULL_REQUEST_REVIEW_COMMENT_NODE_TYPE,
|
||||
})
|
||||
.map(({neighbor}) => new PullRequestReviewComment(this.graph, neighbor));
|
||||
}
|
||||
}
|
||||
|
||||
export class PullRequestReviewComment extends Post<
|
||||
PullRequestReviewCommentNodePayload
|
||||
> {
|
||||
static from(e: Entity): PullRequestReviewComment {
|
||||
assertEntityType(e, PULL_REQUEST_REVIEW_COMMENT_NODE_TYPE);
|
||||
return (e: any);
|
||||
}
|
||||
}
|
||||
|
@ -19,66 +19,90 @@ describe("GitHub porcelain API", () => {
|
||||
}
|
||||
return result;
|
||||
}
|
||||
describe("has wrappers for", () => {
|
||||
it("Issues", () => {
|
||||
const issue = issueOrPRByNumber(1);
|
||||
expect(issue.title()).toBe("An example issue.");
|
||||
expect(issue.body()).toBe("This is just an example issue.");
|
||||
expect(issue.number()).toBe(1);
|
||||
expect(issue.type()).toBe(ISSUE_NODE_TYPE);
|
||||
expect(issue.url()).toBe(
|
||||
"https://github.com/sourcecred/example-repo/issues/1"
|
||||
);
|
||||
expect(issue.node()).toMatchSnapshot();
|
||||
expect(issue.address()).toEqual(issue.node().address);
|
||||
expect(issue.authors().map((x) => x.login())).toEqual(["decentralion"]);
|
||||
});
|
||||
|
||||
it("Issue", () => {
|
||||
const issue = issueOrPRByNumber(1);
|
||||
expect(issue.title()).toBe("An example issue.");
|
||||
expect(issue.body()).toBe("This is just an example issue.");
|
||||
expect(issue.number()).toBe(1);
|
||||
expect(issue.type()).toBe(ISSUE_NODE_TYPE);
|
||||
expect(issue.url()).toBe(
|
||||
"https://github.com/sourcecred/example-repo/issues/1"
|
||||
);
|
||||
expect(issue.node()).toMatchSnapshot();
|
||||
expect(issue.address()).toEqual(issue.node().address);
|
||||
expect(issue.authors().map((x) => x.login())).toEqual(["decentralion"]);
|
||||
it("PullRequests", () => {
|
||||
const pullRequest = issueOrPRByNumber(3);
|
||||
expect(pullRequest.body()).toBe("Oh look, it's a pull request.");
|
||||
expect(pullRequest.title()).toBe("Add README, merge via PR.");
|
||||
expect(pullRequest.url()).toBe(
|
||||
"https://github.com/sourcecred/example-repo/pull/3"
|
||||
);
|
||||
expect(pullRequest.number()).toBe(3);
|
||||
expect(pullRequest.type()).toBe(PULL_REQUEST_NODE_TYPE);
|
||||
expect(pullRequest.node()).toMatchSnapshot();
|
||||
expect(pullRequest.address()).toEqual(pullRequest.node().address);
|
||||
});
|
||||
|
||||
it("Pull Request Reviews", () => {
|
||||
const pr = PullRequest.from(issueOrPRByNumber(5));
|
||||
const reviews = pr.reviews();
|
||||
expect(reviews).toHaveLength(2);
|
||||
expect(reviews[0].state()).toBe("CHANGES_REQUESTED");
|
||||
expect(reviews[1].state()).toBe("APPROVED");
|
||||
});
|
||||
|
||||
it("Pull Request Review Comments", () => {
|
||||
const pr = PullRequest.from(issueOrPRByNumber(5));
|
||||
const reviews = pr.reviews();
|
||||
expect(reviews).toHaveLength(2);
|
||||
const comments = reviews[0].comments();
|
||||
expect(comments).toHaveLength(1);
|
||||
const comment = comments[0];
|
||||
expect(comment.url()).toBe(
|
||||
"https://github.com/sourcecred/example-repo/pull/5#discussion_r171460198"
|
||||
);
|
||||
expect(comment.body()).toBe("seems a bit capricious");
|
||||
expect(comment.authors().map((a) => a.login())).toEqual(["wchargin"]);
|
||||
});
|
||||
|
||||
it("Comments", () => {
|
||||
const issue = issueOrPRByNumber(6);
|
||||
const comments = issue.comments();
|
||||
expect(comments.length).toMatchSnapshot();
|
||||
const comment = comments[0];
|
||||
expect(comment.type()).toBe(COMMENT_NODE_TYPE);
|
||||
expect(comment.body()).toBe("A wild COMMENT appeared!");
|
||||
expect(comment.url()).toBe(
|
||||
"https://github.com/sourcecred/example-repo/issues/6#issuecomment-373768442"
|
||||
);
|
||||
expect(comment.node()).toMatchSnapshot();
|
||||
expect(comment.address()).toEqual(comment.node().address);
|
||||
expect(comment.authors().map((x) => x.login())).toEqual(["decentralion"]);
|
||||
});
|
||||
|
||||
it("Authors", () => {
|
||||
const authors = repo.authors();
|
||||
// So we don't need to manually update the test if a new person posts
|
||||
expect(authors.length).toMatchSnapshot();
|
||||
|
||||
const decentralion = authors.find((x) => x.login() === "decentralion");
|
||||
if (decentralion == null) {
|
||||
throw new Error("Who let the lions out?");
|
||||
}
|
||||
expect(decentralion.url()).toBe("https://github.com/decentralion");
|
||||
expect(decentralion.type()).toBe(AUTHOR_NODE_TYPE);
|
||||
expect(decentralion.subtype()).toBe("USER");
|
||||
expect(decentralion.node()).toMatchSnapshot();
|
||||
expect(decentralion.address()).toEqual(decentralion.node().address);
|
||||
});
|
||||
});
|
||||
|
||||
it("PullRequest", () => {
|
||||
const pullRequest = issueOrPRByNumber(3);
|
||||
expect(pullRequest.body()).toBe("Oh look, it's a pull request.");
|
||||
expect(pullRequest.url()).toBe(
|
||||
"https://github.com/sourcecred/example-repo/pull/3"
|
||||
);
|
||||
expect(pullRequest.number()).toBe(3);
|
||||
expect(pullRequest.type()).toBe(PULL_REQUEST_NODE_TYPE);
|
||||
expect(pullRequest.node()).toMatchSnapshot();
|
||||
expect(pullRequest.address()).toEqual(pullRequest.node().address);
|
||||
});
|
||||
|
||||
it("Comment", () => {
|
||||
const issue = issueOrPRByNumber(6);
|
||||
const comments = issue.comments();
|
||||
expect(comments.length).toMatchSnapshot();
|
||||
const comment = comments[0];
|
||||
expect(comment.type()).toBe(COMMENT_NODE_TYPE);
|
||||
expect(comment.body()).toBe("A wild COMMENT appeared!");
|
||||
expect(comment.url()).toBe(
|
||||
"https://github.com/sourcecred/example-repo/issues/6#issuecomment-373768442"
|
||||
);
|
||||
expect(comment.node()).toMatchSnapshot();
|
||||
expect(comment.address()).toEqual(comment.node().address);
|
||||
expect(comment.authors().map((x) => x.login())).toEqual(["decentralion"]);
|
||||
});
|
||||
|
||||
it("Author", () => {
|
||||
const authors = repo.authors();
|
||||
// So we don't need to manually update the test if a new person posts
|
||||
expect(authors.length).toMatchSnapshot();
|
||||
|
||||
const decentralion = authors.find((x) => x.login() === "decentralion");
|
||||
if (decentralion == null) {
|
||||
throw new Error("Who let the lions out?");
|
||||
}
|
||||
expect(decentralion.url()).toBe("https://github.com/decentralion");
|
||||
expect(decentralion.type()).toBe(AUTHOR_NODE_TYPE);
|
||||
expect(decentralion.subtype()).toBe("USER");
|
||||
expect(decentralion.node()).toMatchSnapshot();
|
||||
expect(decentralion.address()).toEqual(decentralion.node().address);
|
||||
});
|
||||
|
||||
describe("type coercion", () => {
|
||||
it("type coercion works when typed correctly", () => {
|
||||
describe("has type coercion that", () => {
|
||||
it("allows refining types when correct", () => {
|
||||
const _unused_issue: Issue = Issue.from(issueOrPRByNumber(1));
|
||||
const _unused_pr: PullRequest = PullRequest.from(issueOrPRByNumber(3));
|
||||
const _unused_author: Author = Author.from(
|
||||
@ -88,7 +112,7 @@ describe("GitHub porcelain API", () => {
|
||||
issueOrPRByNumber(2).comments()[0]
|
||||
);
|
||||
});
|
||||
it("type coercion throws error when typed incorrectly", () => {
|
||||
it("throws an error on bad type refinement", () => {
|
||||
expect(() => PullRequest.from(issueOrPRByNumber(1))).toThrowError(
|
||||
"to have type PULL_REQUEST"
|
||||
);
|
||||
|
Loading…
x
Reference in New Issue
Block a user