From 8838f856ab9ed2d73a1e8638ab30cd1872421800 Mon Sep 17 00:00:00 2001 From: Robin van Boven <497556+Beanow@users.noreply.github.com> Date: Tue, 4 Feb 2020 00:02:54 +0100 Subject: [PATCH] Backend: implement PluginLoaders.declarations (#1616) This is the first of several commits to create the PluginLoaders abstraction. Using this allows us to define "for all plugins" semantics, while keeping each underlying plugin interface flexible. --- src/backend/pluginLoaders.js | 39 +++++++++++++++++ src/backend/pluginLoaders.test.js | 72 +++++++++++++++++++++++++++++++ src/plugins/discourse/loader.js | 12 ++++++ src/plugins/github/loader.js | 12 ++++++ src/plugins/identity/loader.js | 12 ++++++ 5 files changed, 147 insertions(+) create mode 100644 src/backend/pluginLoaders.js create mode 100644 src/backend/pluginLoaders.test.js create mode 100644 src/plugins/discourse/loader.js create mode 100644 src/plugins/github/loader.js create mode 100644 src/plugins/identity/loader.js diff --git a/src/backend/pluginLoaders.js b/src/backend/pluginLoaders.js new file mode 100644 index 0000000..6725d22 --- /dev/null +++ b/src/backend/pluginLoaders.js @@ -0,0 +1,39 @@ +//@flow + +import {type Project} from "../core/project"; +import {type PluginDeclaration} from "../analysis/pluginDeclaration"; +import {type Loader as GithubLoader} from "../plugins/github/loader"; +import {type Loader as IdentityLoader} from "../plugins/identity/loader"; +import {type Loader as DiscourseLoader} from "../plugins/discourse/loader"; + +/** + * A type combining all known plugin Loader interfaces. + * + * Using this allows us to define "for all plugins" semantics, while keeping + * each underlying plugin's interface flexible. + */ +export type PluginLoaders = {| + +github: GithubLoader, + +discourse: DiscourseLoader, + +identity: IdentityLoader, +|}; + +/** + * Gets all relevant PluginDeclarations for a given Project. + */ +export function declarations( + {github, discourse, identity}: PluginLoaders, + project: Project +): $ReadOnlyArray { + const plugins: PluginDeclaration[] = []; + if (project.repoIds.length) { + plugins.push(github.declaration()); + } + if (project.discourseServer != null) { + plugins.push(discourse.declaration()); + } + if (project.identities.length) { + plugins.push(identity.declaration()); + } + return plugins; +} diff --git a/src/backend/pluginLoaders.test.js b/src/backend/pluginLoaders.test.js new file mode 100644 index 0000000..ae3e844 --- /dev/null +++ b/src/backend/pluginLoaders.test.js @@ -0,0 +1,72 @@ +// @flow + +import {createProject} from "../core/project"; +import {makeRepoId} from "../plugins/github/repoId"; +import * as PluginLoaders from "./pluginLoaders"; + +const fakeGithubDec = ("fake-github-dec": any); +const fakeDiscourseDec = ("fake-discourse-dec": any); +const fakeIdentityDec = ("fake-identity-dec": any); + +const mockPluginLoaders = () => ({ + github: { + declaration: jest.fn().mockReturnValue(fakeGithubDec), + }, + discourse: { + declaration: jest.fn().mockReturnValue(fakeDiscourseDec), + }, + identity: { + declaration: jest.fn().mockReturnValue(fakeIdentityDec), + }, +}); + +describe("src/backend/pluginLoaders", () => { + const exampleRepoId = makeRepoId("sourcecred-test", "example-github"); + + describe("declarations", () => { + it("should include discourse declaration", async () => { + // Given + const loaders = mockPluginLoaders(); + const project = createProject({ + id: "has-discourse", + discourseServer: {serverUrl: "http://foo.bar"}, + }); + + // When + const decs = PluginLoaders.declarations(loaders, project); + + // Then + expect(decs).toEqual([fakeDiscourseDec]); + }); + + it("should include github declaration", async () => { + // Given + const loaders = mockPluginLoaders(); + const project = createProject({ + id: "has-github", + repoIds: [exampleRepoId], + }); + + // When + const decs = PluginLoaders.declarations(loaders, project); + + // Then + expect(decs).toEqual([fakeGithubDec]); + }); + + it("should include identity declaration", async () => { + // Given + const loaders = mockPluginLoaders(); + const project = createProject({ + id: "has-identity", + identities: [{username: "foo", aliases: ["github/foo"]}], + }); + + // When + const decs = PluginLoaders.declarations(loaders, project); + + // Then + expect(decs).toEqual([fakeIdentityDec]); + }); + }); +}); diff --git a/src/plugins/discourse/loader.js b/src/plugins/discourse/loader.js new file mode 100644 index 0000000..9360176 --- /dev/null +++ b/src/plugins/discourse/loader.js @@ -0,0 +1,12 @@ +// @flow + +import {type PluginDeclaration} from "../../analysis/pluginDeclaration"; +import {declaration} from "./declaration"; + +export interface Loader { + declaration(): PluginDeclaration; +} + +export default ({ + declaration: () => declaration, +}: Loader); diff --git a/src/plugins/github/loader.js b/src/plugins/github/loader.js new file mode 100644 index 0000000..9360176 --- /dev/null +++ b/src/plugins/github/loader.js @@ -0,0 +1,12 @@ +// @flow + +import {type PluginDeclaration} from "../../analysis/pluginDeclaration"; +import {declaration} from "./declaration"; + +export interface Loader { + declaration(): PluginDeclaration; +} + +export default ({ + declaration: () => declaration, +}: Loader); diff --git a/src/plugins/identity/loader.js b/src/plugins/identity/loader.js new file mode 100644 index 0000000..9360176 --- /dev/null +++ b/src/plugins/identity/loader.js @@ -0,0 +1,12 @@ +// @flow + +import {type PluginDeclaration} from "../../analysis/pluginDeclaration"; +import {declaration} from "./declaration"; + +export interface Loader { + declaration(): PluginDeclaration; +} + +export default ({ + declaration: () => declaration, +}: Loader);