Refactor GH parser to expose a functional api (#145)
Our GitHub parser is implemented via a `GithubParser` class which builds the GitHub graph. This is a convenient implementation, but an awkward API. This commit refactors the module so that it exposes a clean `parse` function, which ingests the GitHub JSON data and returns as completed graph. Test plan: The unit tests have been re-written to use the new public API. All the snapshots are unchanged, and flow passes. Additionally, I ran `yarn start` and verified that the GithubGraphFetcher for the Artifact plugin is still working.
This commit is contained in:
parent
5e4b7b1fcc
commit
18ce9982d2
|
@ -9,7 +9,7 @@ import type {
|
|||
NodePayload as GithubNodePayload,
|
||||
EdgePayload as GithubEdgePayload,
|
||||
} from "../../github/types";
|
||||
import {GithubParser} from "../../github/parser";
|
||||
import {parse} from "../../github/parser";
|
||||
|
||||
type Props = {
|
||||
settings: Settings,
|
||||
|
@ -32,9 +32,7 @@ export class GithubGraphFetcher extends React.Component<Props> {
|
|||
const {repoOwner, repoName, githubApiToken} = this.props.settings;
|
||||
fetchGithubRepo(repoOwner, repoName, githubApiToken)
|
||||
.then((json) => {
|
||||
const parser = new GithubParser(`${repoOwner}/${repoName}`);
|
||||
parser.addData(json);
|
||||
return Promise.resolve(parser.graph);
|
||||
return Promise.resolve(parse(`${repoOwner}/${repoName}`, json));
|
||||
})
|
||||
.then((graph) => {
|
||||
this.props.onCreateGraph(graph);
|
||||
|
|
|
@ -5,7 +5,7 @@ import {shallow} from "enzyme";
|
|||
import enzymeToJSON from "enzyme-to-json";
|
||||
import stringify from "json-stable-stringify";
|
||||
|
||||
import {GithubParser} from "../../../github/parser";
|
||||
import {parse} from "../../../github/parser";
|
||||
import exampleRepoData from "../../../github/demoData/example-repo.json";
|
||||
import adapter from "./githubPluginAdapter";
|
||||
|
||||
|
@ -13,9 +13,7 @@ require("../testUtil").configureEnzyme();
|
|||
|
||||
describe("githubPluginAdapter", () => {
|
||||
it("operates on the example repo", () => {
|
||||
const parser = new GithubParser("sourcecred/example-repo");
|
||||
parser.addData(exampleRepoData);
|
||||
const graph = parser.graph;
|
||||
const graph = parse("sourcecred/example-repo", exampleRepoData);
|
||||
|
||||
const result = graph
|
||||
.getNodes()
|
||||
|
|
|
@ -30,7 +30,16 @@ import {PLUGIN_NAME} from "./pluginName";
|
|||
import {Graph, edgeID} from "../../core/graph";
|
||||
const stringify = require("json-stable-stringify");
|
||||
|
||||
export class GithubParser {
|
||||
export function parse(
|
||||
repositoryName: string,
|
||||
repositoryJSON: RepositoryJSON
|
||||
): Graph<NodePayload, EdgePayload> {
|
||||
const parser = new GithubParser(repositoryName);
|
||||
parser.addData(repositoryJSON);
|
||||
return parser.graph;
|
||||
}
|
||||
|
||||
class GithubParser {
|
||||
repositoryName: string;
|
||||
graph: Graph<NodePayload, EdgePayload>;
|
||||
|
||||
|
|
|
@ -1,15 +1,15 @@
|
|||
// @flow
|
||||
|
||||
import {AUTHORS_EDGE_TYPE, CONTAINS_EDGE_TYPE} from "./types";
|
||||
|
||||
import {GithubParser} from "./parser";
|
||||
import type {NodePayload, EdgePayload} from "./types";
|
||||
import {parse} from "./parser";
|
||||
import type {RepositoryJSON, PullRequestJSON, IssueJSON} from "./graphql";
|
||||
import {Graph} from "../../core/graph";
|
||||
import exampleRepoData from "./demoData/example-repo.json";
|
||||
|
||||
describe("GithubParser", () => {
|
||||
describe("whole repo parsing", () => {
|
||||
const parser = new GithubParser("sourcecred/example-repo");
|
||||
parser.addData(exampleRepoData);
|
||||
const graph = parser.graph;
|
||||
const graph = parse("sourcecred/example-repo", exampleRepoData);
|
||||
|
||||
it("parses the entire example-repo as expected", () => {
|
||||
expect(graph).toMatchSnapshot();
|
||||
|
@ -66,38 +66,70 @@ describe("GithubParser", () => {
|
|||
});
|
||||
});
|
||||
|
||||
function getIssue(n: number): IssueJSON {
|
||||
const issues = exampleRepoData.repository.issues.nodes;
|
||||
const selected = issues.filter((x) => x.number === n);
|
||||
if (selected.length !== 1) {
|
||||
throw new Error(`Failure finding issue #${n}`);
|
||||
}
|
||||
return selected[0];
|
||||
}
|
||||
function getPR(n: number): PullRequestJSON {
|
||||
const pulls = exampleRepoData.repository.pullRequests.nodes;
|
||||
const selected = pulls.filter((x) => x.number === n);
|
||||
if (selected.length !== 1) {
|
||||
throw new Error(`Failure finding PR #${n}`);
|
||||
}
|
||||
return selected[0];
|
||||
}
|
||||
type ExampleInput = {
|
||||
issues?: number[],
|
||||
prs?: number[],
|
||||
};
|
||||
function parseExample({
|
||||
issues: issueNums = [],
|
||||
prs: prNums = [],
|
||||
}: ExampleInput): Graph<NodePayload, EdgePayload> {
|
||||
const issues = issueNums.map(getIssue);
|
||||
const pullRequests = prNums.map(getPR);
|
||||
const exampleData: RepositoryJSON = {
|
||||
repository: {
|
||||
id: exampleRepoData.repository.id,
|
||||
issues: {
|
||||
nodes: issues,
|
||||
pageInfo: {
|
||||
hasNextPage: false,
|
||||
endCursor: null,
|
||||
},
|
||||
},
|
||||
pullRequests: {
|
||||
nodes: pullRequests,
|
||||
pageInfo: {
|
||||
hasNextPage: false,
|
||||
endCursor: null,
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
return parse("sourcecred/example-repo", exampleData);
|
||||
}
|
||||
|
||||
describe("issue parsing", () => {
|
||||
it("parses a simple issue (https://github.com/sourcecred/example-repo/issues/1)", () => {
|
||||
const issue1 = exampleRepoData.repository.issues.nodes[0];
|
||||
expect(issue1.number).toBe(1);
|
||||
const parser = new GithubParser("sourcecred/example-repo");
|
||||
parser.addIssue(issue1);
|
||||
expect(parser.graph).toMatchSnapshot();
|
||||
expect(parseExample({issues: [1]})).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it("parses an issue with comments (https://github.com/sourcecred/example-repo/issues/6)", () => {
|
||||
const issue6 = exampleRepoData.repository.issues.nodes[3];
|
||||
expect(issue6.number).toBe(6);
|
||||
const parser = new GithubParser("sourcecred/example-repo");
|
||||
parser.addIssue(issue6);
|
||||
expect(parser.graph).toMatchSnapshot();
|
||||
expect(parseExample({issues: [6]})).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
|
||||
describe("pull request parsing", () => {
|
||||
it("parses a simple pull request (https://github.com/sourcecred/example-repo/pull/3)", () => {
|
||||
const pr3 = exampleRepoData.repository.pullRequests.nodes[0];
|
||||
expect(pr3.number).toBe(3);
|
||||
const parser = new GithubParser("sourcecred/example-repo");
|
||||
parser.addPullRequest(pr3);
|
||||
expect(parser.graph).toMatchSnapshot();
|
||||
expect(parseExample({prs: [3]})).toMatchSnapshot();
|
||||
});
|
||||
it("parses a pr with review comments (https://github.com/sourcecred/example-repo/pull/3)", () => {
|
||||
const pr5 = exampleRepoData.repository.pullRequests.nodes[1];
|
||||
expect(pr5.number).toBe(5);
|
||||
const parser = new GithubParser("sourcecred/example-repo");
|
||||
parser.addPullRequest(pr5);
|
||||
expect(parser.graph).toMatchSnapshot();
|
||||
expect(parseExample({prs: [5]})).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
Loading…
Reference in New Issue