From 607adeca296990e58f0b30b75fece09583fb54df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dandelion=20Man=C3=A9?= Date: Thu, 28 Jun 2018 16:53:52 -0700 Subject: [PATCH] GH: Add a `description` method for entities (#439) This commit adds a `description` method that takes a GitHub entity, and returns a description of that entity. Based on the work in #261. In contrast to the implementation in #261: - It won't crash on entities without an author (although we don't have a test case for this; see #389). - It handles multi-authors reasonably (although we can't test that, as we haven't implemented multi-authorship yet; see #218). Test plan: Inspect snapshot to see some examples. --- .../github/__snapshots__/render.test.js.snap | 12 ++++++++++ src/v3/plugins/github/example/example.js | 18 +++++++++++++++ src/v3/plugins/github/render.js | 23 +++++++++++++++++++ src/v3/plugins/github/render.test.js | 16 +++++++++++++ 4 files changed, 69 insertions(+) create mode 100644 src/v3/plugins/github/__snapshots__/render.test.js.snap create mode 100644 src/v3/plugins/github/render.js create mode 100644 src/v3/plugins/github/render.test.js diff --git a/src/v3/plugins/github/__snapshots__/render.test.js.snap b/src/v3/plugins/github/__snapshots__/render.test.js.snap new file mode 100644 index 0000000..9d85e5f --- /dev/null +++ b/src/v3/plugins/github/__snapshots__/render.test.js.snap @@ -0,0 +1,12 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`plugins/github/render descriptions are as expected 1`] = ` +Object { + "comment": "comment by @wchargin on review by @wchargin of #5: This pull request will be more contentious. I can feel it...", + "issue": "#2: A referencing issue.", + "pull": "#5: This pull request will be more contentious. I can feel it...", + "repo": "sourcecred/example-github", + "review": "review by @wchargin of #5: This pull request will be more contentious. I can feel it...", + "userlike": "@wchargin", +} +`; diff --git a/src/v3/plugins/github/example/example.js b/src/v3/plugins/github/example/example.js index fc829c0..7057fdf 100644 --- a/src/v3/plugins/github/example/example.js +++ b/src/v3/plugins/github/example/example.js @@ -17,3 +17,21 @@ export function exampleRelationalView(): RelationalView { export function exampleGraph(): Graph { return createGraph(exampleRelationalView()); } + +export function exampleEntities() { + const view = exampleRelationalView(); + const repo = Array.from(view.repos())[0]; + const issue = Array.from(repo.issues())[1]; + const pull = Array.from(repo.pulls())[1]; + const review = Array.from(pull.reviews())[0]; + const comment = Array.from(review.comments())[0]; + const userlike = Array.from(review.authors())[0]; + return { + repo, + issue, + pull, + review, + comment, + userlike, + }; +} diff --git a/src/v3/plugins/github/render.js b/src/v3/plugins/github/render.js new file mode 100644 index 0000000..e9eae93 --- /dev/null +++ b/src/v3/plugins/github/render.js @@ -0,0 +1,23 @@ +// @flow + +import * as R from "./relationalView"; + +export function description(e: R.Entity) { + const withAuthors = (x: R.AuthoredEntity) => { + const authors = Array.from(x.authors()); + if (authors.length === 0) { + // ghost author - probably a deleted account + return ""; + } + return "by " + authors.map((x) => description(x)).join(" & ") + " "; + }; + const handlers = { + repo: (x) => `${x.owner()}/${x.name()}`, + issue: (x) => `#${x.number()}: ${x.title()}`, + pull: (x) => `#${x.number()}: ${x.title()}`, + review: (x) => `review ${withAuthors(x)}of ${description(x.parent())}`, + comment: (x) => `comment ${withAuthors(x)}on ${description(x.parent())}`, + userlike: (x) => `@${x.login()}`, + }; + return R.match(handlers, e); +} diff --git a/src/v3/plugins/github/render.test.js b/src/v3/plugins/github/render.test.js new file mode 100644 index 0000000..e074581 --- /dev/null +++ b/src/v3/plugins/github/render.test.js @@ -0,0 +1,16 @@ +// @flow + +import {exampleEntities} from "./example/example"; +import {description} from "./render"; + +describe("plugins/github/render", () => { + it("descriptions are as expected", () => { + const examples = exampleEntities(); + const withDescriptions = {}; + for (const name of Object.keys(exampleEntities())) { + const entity = examples[name]; + withDescriptions[name] = description(entity); + } + expect(withDescriptions).toMatchSnapshot(); + }); +});