diff --git a/src/js/helpers/ajaxWrapper.js b/src/js/helpers/ajaxWrapper.js index 70f3439eb..b36e1d8a1 100644 --- a/src/js/helpers/ajaxWrapper.js +++ b/src/js/helpers/ajaxWrapper.js @@ -1,7 +1,10 @@ import fetch from "isomorphic-fetch"; import Util from "./Util"; +import PipelineStore from "../plugin/sdk/pipeline/PipelineStore"; +import PipelineOperations from "../plugin/sdk/pipeline/PipelineOperations"; var uniqueCalls = []; +const pipeline = new PipelineStore(); function removeCall(options) { uniqueCalls.splice(uniqueCalls.indexOf(options.url), 1); @@ -47,6 +50,10 @@ var ajaxWrapper = function (opts = {}) { }); } + options = pipeline.applyFilter( + PipelineOperations.PRE_AJAX_REQUEST, + options + ); return fetch(options.url, fetchOptions); }; diff --git a/src/js/plugin/PluginLoader.js b/src/js/plugin/PluginLoader.js index d548b83cb..a91886a40 100644 --- a/src/js/plugin/PluginLoader.js +++ b/src/js/plugin/PluginLoader.js @@ -12,6 +12,8 @@ import PluginDispatcherProxy from "./PluginDispatcherProxy"; import MarathonService from "./sdk/services/MarathonService"; import MarathonActions from "./sdk/actions/MarathonActions"; +import PipelineStore from "./sdk/pipeline/PipelineStore"; +import PipelineOperations from "./sdk/pipeline/PipelineOperations"; const PLUGIN_STARTUP_TIMEOUT = 10000; // in ms @@ -51,6 +53,8 @@ const PluginLoader = { config: Object.freeze(config), MarathonService: MarathonService, MarathonActions: MarathonActions, + PipelineStore: new PipelineStore(), + PipelineOperations: PipelineOperations, }); let dispatchToken = PluginDispatcher.register(function (event) { diff --git a/src/js/plugin/sdk/pipeline/PipelineModel.js b/src/js/plugin/sdk/pipeline/PipelineModel.js new file mode 100644 index 000000000..ab0f7689c --- /dev/null +++ b/src/js/plugin/sdk/pipeline/PipelineModel.js @@ -0,0 +1,48 @@ + +class PipelineModel { + + constructor() { + this.pipelines = new Map(); + }; + + clearPipeline() { + this.pipelines.clear(); + }; + + applyFilter(operationName, filterParameters) { + const pipeline = this.getPipeline(operationName); + + pipeline.forEach((filter) => { + filter(filterParameters); + }); + return filterParameters; + }; + + register(operationName, callback) { + + const pipeline = this.getPipeline(operationName); + + if (pipeline.indexOf(callback) === -1) { + pipeline.push(callback); + } + }; + + deregister(operationName, callback) { + const pipeline = this.getPipeline(operationName); + + var callbckPosition = pipeline.indexOf(callback); + if (callbckPosition !== -1) { + pipeline.splice(callbckPosition, 1); + } + }; + + getPipeline(pipelineName) { + if (!this.pipelines.has(pipelineName)) { + this.pipelines.set(pipelineName, []); + } + return this.pipelines.get(pipelineName); + }; + +}; + +export default new PipelineModel(); diff --git a/src/js/plugin/sdk/pipeline/PipelineOperations.js b/src/js/plugin/sdk/pipeline/PipelineOperations.js new file mode 100644 index 000000000..78a7b90af --- /dev/null +++ b/src/js/plugin/sdk/pipeline/PipelineOperations.js @@ -0,0 +1,8 @@ + +const PRE_AJAX_REQUEST = "PRE_AJAX_REQUEST"; + +const PipelineOperations = { + PRE_AJAX_REQUEST +}; + +export default PipelineOperations; diff --git a/src/js/plugin/sdk/pipeline/PipelineStore.js b/src/js/plugin/sdk/pipeline/PipelineStore.js new file mode 100644 index 000000000..c90f05fc4 --- /dev/null +++ b/src/js/plugin/sdk/pipeline/PipelineStore.js @@ -0,0 +1,21 @@ +import PipelineModel from "./PipelineModel"; + +export default class PipelineStore { + + constructor() { + Object.defineProperty(this, "pipeline", {value: PipelineModel}); + }; + + applyFilter(operationName, filterParameters) { + return this.pipeline.applyFilter(operationName, filterParameters); + }; + + register(operationName, callback) { + return this.pipeline.register(operationName, callback); + }; + + deregister(operationName, callback) { + return this.deregister(operationName, callback); + }; + +}; diff --git a/src/test/units/PipelineModel.test.js b/src/test/units/PipelineModel.test.js new file mode 100644 index 000000000..eb634d302 --- /dev/null +++ b/src/test/units/PipelineModel.test.js @@ -0,0 +1,96 @@ +import {expect} from "chai"; +import pipelineModel from "../../js/plugin/sdk/pipeline/PipelineModel" + +import PipelineOperations from "../../js/plugin/sdk/pipeline/PipelineOperations" + +describe("PipelineModel tests", function () { + + beforeEach(function (){ + pipelineModel.clearPipeline(); + }); + + it("should return an empty list for a non-existant pipeline", function () { + expect(pipelineModel.getPipeline(PipelineOperations.PRE_AJAX_REQUEST)).to.have.lengthOf(0); + }); + + it("should clear the pipeline when requested to", function () { + const filter = function () {}; + pipelineModel.getPipeline(PipelineOperations.PRE_AJAX_REQUEST).push(filter); + expect(pipelineModel.getPipeline(PipelineOperations.PRE_AJAX_REQUEST)).to.have.lengthOf(1); + pipelineModel.clearPipeline(); + expect(pipelineModel.getPipeline(PipelineOperations.PRE_AJAX_REQUEST)).to.have.lengthOf(0); + }); + + it("should add a new function to the pipeline", function () { + const filter = function() {}; + + expect(pipelineModel.getPipeline(PipelineOperations.PRE_AJAX_REQUEST)).to.have.lengthOf(0); + pipelineModel.register(PipelineOperations.PRE_AJAX_REQUEST, filter); + expect(pipelineModel.getPipeline(PipelineOperations.PRE_AJAX_REQUEST)).to.have.lengthOf(1); + expect(pipelineModel.getPipeline(PipelineOperations.PRE_AJAX_REQUEST)[0]).to.be.equal(filter); + }); + + it("should add multiple functions to the pipeline", function () { + var filter = function() {}; + var filter2 = function() {}; + + expect(pipelineModel.getPipeline(PipelineOperations.PRE_AJAX_REQUEST)).to.have.lengthOf(0); + pipelineModel.register(PipelineOperations.PRE_AJAX_REQUEST, filter); + pipelineModel.register(PipelineOperations.PRE_AJAX_REQUEST, filter2); + expect(pipelineModel.getPipeline(PipelineOperations.PRE_AJAX_REQUEST)).to.have.lengthOf(2); + expect(pipelineModel.getPipeline(PipelineOperations.PRE_AJAX_REQUEST)[0]).to.be.equal(filter); + expect(pipelineModel.getPipeline(PipelineOperations.PRE_AJAX_REQUEST)[1]).to.be.equal(filter2); + }); + + it("should remove a function from the pipeline", function () { + var filter = function() {}; + + expect(pipelineModel.getPipeline(PipelineOperations.PRE_AJAX_REQUEST)).to.have.lengthOf(0); + + pipelineModel.register(PipelineOperations.PRE_AJAX_REQUEST, filter); + expect(pipelineModel.getPipeline(PipelineOperations.PRE_AJAX_REQUEST)).to.have.lengthOf(1); + + pipelineModel.deregister(PipelineOperations.PRE_AJAX_REQUEST, filter); + expect(pipelineModel.getPipeline(PipelineOperations.PRE_AJAX_REQUEST)).to.have.lengthOf(0); + }); + + it("should not error when removing the same function twice", function () { + var filter = function() {}; + + pipelineModel.register(PipelineOperations.PRE_AJAX_REQUEST, filter); + + pipelineModel.deregister(PipelineOperations.PRE_AJAX_REQUEST, filter); + pipelineModel.deregister(PipelineOperations.PRE_AJAX_REQUEST, filter); + expect(pipelineModel.getPipeline(PipelineOperations.PRE_AJAX_REQUEST)).to.have.lengthOf(0); + }); + + it("should not add the same function twice", function () { + var filter = function() {}; + + pipelineModel.register(PipelineOperations.PRE_AJAX_REQUEST, filter); + pipelineModel.register(PipelineOperations.PRE_AJAX_REQUEST, filter); + expect(pipelineModel.getPipeline(PipelineOperations.PRE_AJAX_REQUEST)).to.have.lengthOf(1); + expect(pipelineModel.getPipeline(PipelineOperations.PRE_AJAX_REQUEST)[0]).to.be.equal(filter); + }); + + it("should call all functions of the chosen pipeline", function () { + var filter_one = function(data) { + data.value = data.value + "_filter_one"; + }; + var filter_two = function(data) { + data.value = data.value + "_filter_two"; + }; + + pipelineModel.register(PipelineOperations.PRE_AJAX_REQUEST, filter_one); + pipelineModel.register(PipelineOperations.PRE_AJAX_REQUEST, filter_two); + let filtered_data = pipelineModel.applyFilter(PipelineOperations.PRE_AJAX_REQUEST, {value: "initial"}); + expect(filtered_data.value).to.be.equal("initial_filter_one_filter_two"); + }); + + it("should be able to run an empty pipeline", function () { + let filtered_data = pipelineModel.applyFilter(PipelineOperations.PRE_AJAX_REQUEST, {value: "initial"}); + expect(filtered_data.value).to.be.equal("initial"); + }); + +}); + diff --git a/src/test/units/PipelineStore.test.js b/src/test/units/PipelineStore.test.js new file mode 100644 index 000000000..fcd6b0f00 --- /dev/null +++ b/src/test/units/PipelineStore.test.js @@ -0,0 +1,25 @@ +import {expect} from "chai"; +import PipelineStore from "../../js/plugin/sdk/pipeline/PipelineStore"; +import pipelineModel from "../../js/plugin/sdk/pipeline/PipelineModel"; +import PipelineOperations from "../../js/plugin/sdk/pipeline/PipelineOperations"; + +describe("PipelineStore tests", function () { + + beforeEach(function (){ + pipelineModel.clearPipeline(); + }); + + it ("should share the same filters between multiple pipeline instances", function (){ + const filter = function (){}; + const filter2 = function (){}; + + const pipeline_one = new PipelineStore(); + const pipeline_two = new PipelineStore(); + pipeline_one.register(PipelineOperations.PRE_AJAX_REQUEST, filter); + pipeline_two.register(PipelineOperations.PRE_AJAX_REQUEST, filter2); + expect(pipelineModel.getPipeline(PipelineOperations.PRE_AJAX_REQUEST)).to.have.lengthOf(2); + expect(pipelineModel.getPipeline(PipelineOperations.PRE_AJAX_REQUEST)[0]).to.be.equal(filter); + expect(pipelineModel.getPipeline(PipelineOperations.PRE_AJAX_REQUEST)[1]).to.be.equal(filter2); + }); + +});