From 7357a0d341c511934cf1a6c87119d8bb687a97a0 Mon Sep 17 00:00:00 2001 From: Neeraj Mandal Date: Fri, 28 Jun 2019 14:37:33 -0700 Subject: [PATCH 1/6] New barch created to make final chnages before PR --- src/plugins/invoke/azureInvoke.test.ts | 28 +++++++++ src/plugins/invoke/azureInvoke.ts | 65 +++++++++++++++----- src/services/invokeService.test.ts | 48 +++++++++++++++ src/services/invokeService.ts | 84 ++++++++++++++++++++++++++ 4 files changed, 211 insertions(+), 14 deletions(-) create mode 100644 src/plugins/invoke/azureInvoke.test.ts create mode 100644 src/services/invokeService.test.ts create mode 100644 src/services/invokeService.ts diff --git a/src/plugins/invoke/azureInvoke.test.ts b/src/plugins/invoke/azureInvoke.test.ts new file mode 100644 index 00000000..a0294154 --- /dev/null +++ b/src/plugins/invoke/azureInvoke.test.ts @@ -0,0 +1,28 @@ +import { MockFactory } from "../../test/mockFactory"; +import { invokeHook } from "../../test/utils"; +jest.mock("../../services/functionAppService"); + +jest.mock("../../services/resourceService"); +import { ResourceService } from "../../services/resourceService"; +import { Site } from "@azure/arm-appservice/esm/models"; +import { AzureInvoke } from "./azureInvoke"; +jest.mock("../../services/invokeService"); +import { InvokeService } from "../../services/invokeService"; + +describe("Azure Invoke Plugin", () => { + it("calls invoke hook", async () => { + + const invoke = jest.fn(); + const functionAppStub: Site = MockFactory.createTestSite(); + const azureinvoke = jest.fn(() => Promise.resolve(functionAppStub)); + + InvokeService.prototype.invoke = invoke; + + const sls = MockFactory.createTestServerless(); + const options = MockFactory.createTestServerlessOptions(); + const plugin = new AzureInvoke(sls, options); + //Not sure + await invokeHook(plugin, "invoke:invoke"); + expect(invoke).toBeCalled(); + }); + }); \ No newline at end of file diff --git a/src/plugins/invoke/azureInvoke.ts b/src/plugins/invoke/azureInvoke.ts index f8da7e26..03313ee5 100644 --- a/src/plugins/invoke/azureInvoke.ts +++ b/src/plugins/invoke/azureInvoke.ts @@ -1,41 +1,78 @@ +import { isAbsolute, join } from "path"; import Serverless from "serverless"; -import { join, isAbsolute } from "path"; import AzureProvider from "../../provider/azureProvider"; +import { InvokeService } from "../../services/invokeService"; +import { AzureLoginPlugin } from "../login/loginPlugin"; export class AzureInvoke { public hooks: { [eventName: string]: Promise }; + private commands: any; private provider: AzureProvider; - + private login: AzureLoginPlugin + private invokeService: InvokeService; public constructor(private serverless: Serverless, private options: Serverless.Options) { this.provider = (this.serverless.getProvider("azure") as any) as AzureProvider; const path = this.options["path"]; - + this.login = new AzureLoginPlugin(this.serverless, this.options); + if (path) { const absolutePath = isAbsolute(path) ? path : join(this.serverless.config.servicePath, path); + this.serverless.cli.log(this.serverless.config.servicePath); + this.serverless.cli.log(path); if (!this.serverless.utils.fileExistsSync(absolutePath)) { throw new Error("The file you provided does not exist."); } this.options["data"] = this.serverless.utils.readFileSync(absolutePath); } - + this.commands = { + invoke: { + usage: "Invoke command", + lifecycleEvents: [ + "invoke" + ], + options: { + function: { + usage: "Function to call", + shortcut: "f", + }, + path: { + usage: "Path to file to put in body", + shortcut: "p" + }, + data: { + usage: "Data string for body of request", + shortcut: "d" + }, + method: { + usage: "GET or POST request (Default is GET)", + shortcut: "m" + } + } + } + } this.hooks = { - "before:invoke:invoke": this.provider.getAdminKey.bind(this), "invoke:invoke": this.invoke.bind(this) }; + } private async invoke() { - const func = this.options.function; - const functionObject = this.serverless.service.getFunction(func); - const eventType = Object.keys(functionObject["events"][0])[0]; - - if (!this.options["data"]) { - this.options["data"] = {}; + const functionName = this.options["function"]; + const data = this.options["data"]; + const method = this.options["method"] || "GET"; + if (!functionName) { + this.serverless.cli.log("Need to provide a name of function to invoke"); + return; } - - return this.provider.invoke(func, eventType, this.options["data"]); + if (!data) { + this.serverless.cli.log("Need to provide data or path"); + return; + } + this.invokeService = new InvokeService(this.serverless, this.options); + const response = await this.invokeService.invoke(functionName, data, method); + this.serverless.cli.log(response.data); } -} +} \ No newline at end of file diff --git a/src/services/invokeService.test.ts b/src/services/invokeService.test.ts new file mode 100644 index 00000000..26da6884 --- /dev/null +++ b/src/services/invokeService.test.ts @@ -0,0 +1,48 @@ +import axios from "axios"; +import MockAdapter from "axios-mock-adapter"; +import mockFs from "mock-fs"; +import Serverless from "serverless"; +import { MockFactory } from "../test/mockFactory"; +import { InvokeService } from "./invokeService"; +import { Site } from "@azure/arm-appservice/esm/models"; + +jest.mock("@azure/arm-appservice") +import { WebSiteManagementClient } from "@azure/arm-appservice"; +jest.mock("@azure/arm-resources") + +describe("Invoke Service ", () => { + const app = MockFactory.createTestSite(); + const slsService = MockFactory.createTestService(); + const variables = MockFactory.createTestVariables(); + const provider = MockFactory.createTestAzureServiceProvider(); + const functionName = "test"; + const authKey = "authKey"; + const baseUrl = "https://management.azure.com" + const masterKeyUrl = `https://${app.defaultHostName}/admin/host/systemkeys/_master`; + const authKeyUrl = `${baseUrl}${app.id}/functions/admin/token?api-version=2016-08-01`; + let functionApp: Site; + let masterKey: string; + + beforeAll(() => { + + const axiosMock = new MockAdapter(axios); + + // Master Key + axiosMock.onGet(masterKeyUrl).reply(200, { value: masterKey }); + // Auth Key + axiosMock.onGet(authKeyUrl).reply(200, authKey); + }); + + it("Invokes a function", async () => { + const sls = MockFactory.createTestServerless(); + const options = MockFactory.createTestServerlessOptions(); + options["function"] = "hello"; + options["data"] = '{"name": "AzureTest"}'; + options["method"] = "GET"; + + const service = new InvokeService(sls, options); + const response = await service.invoke(options["function"], options["data"], options["method"]); + + expect().toEqual(response.data) + }); +}); \ No newline at end of file diff --git a/src/services/invokeService.ts b/src/services/invokeService.ts new file mode 100644 index 00000000..ddb3fb23 --- /dev/null +++ b/src/services/invokeService.ts @@ -0,0 +1,84 @@ +import { BaseService } from "./baseService" +import Serverless from "serverless"; +import config from "../config"; +import axios from "axios"; +import { FunctionAppService } from "./functionAppService"; + +export class InvokeService extends BaseService { + public functionAppService: FunctionAppService; + public serverless: Serverless; + public options: Serverless.Options; + public constructor(serverless: Serverless, options: Serverless.Options) { + super(serverless, options); + this.functionAppService = new FunctionAppService(serverless, options); + this.serverless = serverless; + this.options = options; + } + + /** + * Invoke an Azure Function + * @param functionName Name of function to invoke + * @param data Data to use as body or query params + * @param method GET or POST + */ + public async invoke(functionName: string, data: any, method: string){ + /* accesses the admin key */ + if (!(functionName in this.slsFunctions())) { + this.serverless.cli.log(`Function ${functionName} does not exist`); + return; + } + const functionObject = this.slsFunctions()[functionName]; + const eventType = Object.keys(functionObject["events"][0])[0]; + if (eventType !== "http") { + this.log("Needs to be an http function"); + return; + } + let url = `http://${this.serviceName}${config.functionAppDomain}${config.functionAppApiPath + functionName}`; + + if (method === "GET") { + const queryString = this.getQueryString(data); + url += `?${queryString}` + } + + this.log(url); + const options = await this.getOptions(method, data); + this.log(`Invoking function ${functionName} with ${method} request`); + return await axios(url, options); + } + + private getQueryString(eventData: any) { + if (typeof eventData === "string") { + try { + eventData = JSON.parse(eventData); + } + catch (error) { + return Promise.reject("The specified input data isn't a valid JSON string. " + + "Please correct it and try invoking the function again."); + } + } + return Object.keys(eventData) + .map((key) => `${key}=${eventData[key]}`) + .join("&"); + } + + /** + * Get options object + * @param method The method used (POST or GET) + * @param data Data to use as body or query params + */ + private async getOptions(method: string, data?: any) { + const functionsAdminKey = await this.functionAppService.getMasterKey(); + this.log(functionsAdminKey); + const options: any = { + host: config.functionAppDomain, + headers: { + "x-functions-key": functionsAdminKey + }, + method, + }; + if (method === "POST" && data) { + options.body = data; + } + return options; + } +} \ No newline at end of file From 377549093d9628d7d60318b2216c13ca1429f899 Mon Sep 17 00:00:00 2001 From: Neeraj Mandal Date: Mon, 1 Jul 2019 15:11:53 -0700 Subject: [PATCH 2/6] Test files added --- src/plugins/invoke/azureInvoke.test.ts | 80 ++++++++++++++++++++------ src/plugins/invoke/azureInvoke.ts | 11 ++-- src/services/invokeService.test.ts | 18 ++++-- src/services/invokeService.ts | 6 +- 4 files changed, 83 insertions(+), 32 deletions(-) diff --git a/src/plugins/invoke/azureInvoke.test.ts b/src/plugins/invoke/azureInvoke.test.ts index a0294154..ca38b6b3 100644 --- a/src/plugins/invoke/azureInvoke.test.ts +++ b/src/plugins/invoke/azureInvoke.test.ts @@ -1,28 +1,70 @@ import { MockFactory } from "../../test/mockFactory"; import { invokeHook } from "../../test/utils"; -jest.mock("../../services/functionAppService"); +import mockFs from "mock-fs"; +jest.mock("../../services/functionAppService"); jest.mock("../../services/resourceService"); -import { ResourceService } from "../../services/resourceService"; -import { Site } from "@azure/arm-appservice/esm/models"; import { AzureInvoke } from "./azureInvoke"; jest.mock("../../services/invokeService"); import { InvokeService } from "../../services/invokeService"; describe("Azure Invoke Plugin", () => { - it("calls invoke hook", async () => { - - const invoke = jest.fn(); - const functionAppStub: Site = MockFactory.createTestSite(); - const azureinvoke = jest.fn(() => Promise.resolve(functionAppStub)); - - InvokeService.prototype.invoke = invoke; - - const sls = MockFactory.createTestServerless(); - const options = MockFactory.createTestServerlessOptions(); - const plugin = new AzureInvoke(sls, options); - //Not sure - await invokeHook(plugin, "invoke:invoke"); - expect(invoke).toBeCalled(); - }); - }); \ No newline at end of file + const fileContent = JSON.stringify({ + name: "Azure-Test", + }); + afterEach(() => { + jest.resetAllMocks(); + }) + + beforeAll(() => { + mockFs({ + "testFile.json": fileContent, + }, { createCwd: true, createTmp: true }); + }); + afterAll(() => { + mockFs.restore(); + }); + + it("calls invoke hook", async () => { + + const invoke = jest.fn(); + InvokeService.prototype.invoke = invoke; + + const sls = MockFactory.createTestServerless(); + const options = MockFactory.createTestServerlessOptions(); + options["function"] = "testApp"; + options["data"] = "{\"name\": \"AzureTest\"}"; + options["method"] = "GET"; + + const plugin = new AzureInvoke(sls, options); + await invokeHook(plugin, "invoke:invoke"); + expect(invoke).toBeCalledWith(options["function"], options["data"], options["method"]); + }); + + it("calls the invoke hook with file path", async () => { + const invoke = jest.fn(); + InvokeService.prototype.invoke = invoke; + const sls = MockFactory.createTestServerless(); + const options = MockFactory.createTestServerlessOptions(); + options["function"] = "testApp"; + options["path"] = "testFile.json"; + options["method"] = "GET"; + + const plugin = new AzureInvoke(sls, options); + await invokeHook(plugin, "invoke:invoke"); + expect(invoke).toBeCalledWith(options["function"], fileContent, options["method"]); + }); + + it("calls the invooke hook with file path", async () => { + const invoke = jest.fn(); + InvokeService.prototype.invoke = invoke; + const sls = MockFactory.createTestServerless(); + const options = MockFactory.createTestServerlessOptions(); + options["function"] = "testApp"; + options["path"] = "garbage.json"; + options["method"] = "GET"; + + const plugin = await new AzureInvoke(sls, options); + await expect(invokeHook(plugin, "invoke:invoke")).toThrow(); + }); +}); diff --git a/src/plugins/invoke/azureInvoke.ts b/src/plugins/invoke/azureInvoke.ts index 03313ee5..27c80888 100644 --- a/src/plugins/invoke/azureInvoke.ts +++ b/src/plugins/invoke/azureInvoke.ts @@ -3,6 +3,7 @@ import Serverless from "serverless"; import AzureProvider from "../../provider/azureProvider"; import { InvokeService } from "../../services/invokeService"; import { AzureLoginPlugin } from "../login/loginPlugin"; +import fs from "fs"; export class AzureInvoke { public hooks: { [eventName: string]: Promise }; @@ -19,13 +20,13 @@ export class AzureInvoke { const absolutePath = isAbsolute(path) ? path : join(this.serverless.config.servicePath, path); - this.serverless.cli.log(this.serverless.config.servicePath); - this.serverless.cli.log(path); + this.serverless.cli.log(this.serverless.config.servicePath); + this.serverless.cli.log(path); - if (!this.serverless.utils.fileExistsSync(absolutePath)) { + if (!fs.existsSync(absolutePath)) { throw new Error("The file you provided does not exist."); } - this.options["data"] = this.serverless.utils.readFileSync(absolutePath); + this.options["data"] = fs.readFileSync(absolutePath).toString(); } this.commands = { invoke: { @@ -73,6 +74,6 @@ export class AzureInvoke { } this.invokeService = new InvokeService(this.serverless, this.options); const response = await this.invokeService.invoke(functionName, data, method); - this.serverless.cli.log(response.data); + //this.serverless.cli.log(response.data); } } \ No newline at end of file diff --git a/src/services/invokeService.test.ts b/src/services/invokeService.test.ts index 26da6884..2a54c47d 100644 --- a/src/services/invokeService.test.ts +++ b/src/services/invokeService.test.ts @@ -5,7 +5,7 @@ import Serverless from "serverless"; import { MockFactory } from "../test/mockFactory"; import { InvokeService } from "./invokeService"; import { Site } from "@azure/arm-appservice/esm/models"; - +import { FunctionAppService } from "./functionAppService"; jest.mock("@azure/arm-appservice") import { WebSiteManagementClient } from "@azure/arm-appservice"; jest.mock("@azure/arm-resources") @@ -16,10 +16,13 @@ describe("Invoke Service ", () => { const variables = MockFactory.createTestVariables(); const provider = MockFactory.createTestAzureServiceProvider(); const functionName = "test"; + const testData = "test-data"; + const result = "result"; const authKey = "authKey"; const baseUrl = "https://management.azure.com" const masterKeyUrl = `https://${app.defaultHostName}/admin/host/systemkeys/_master`; const authKeyUrl = `${baseUrl}${app.id}/functions/admin/token?api-version=2016-08-01`; + const functionUrl = `http://${slsService.getServiceName()}.azurewebsites.net/api/hello?name=${testData}`; let functionApp: Site; let masterKey: string; @@ -31,18 +34,23 @@ describe("Invoke Service ", () => { axiosMock.onGet(masterKeyUrl).reply(200, { value: masterKey }); // Auth Key axiosMock.onGet(authKeyUrl).reply(200, authKey); + axiosMock.onGet(functionUrl).reply(200, result); + }); + beforeEach(() => { + FunctionAppService.prototype.getMasterKey = jest.fn(); }); + it("Invokes a function", async () => { const sls = MockFactory.createTestServerless(); const options = MockFactory.createTestServerlessOptions(); options["function"] = "hello"; - options["data"] = '{"name": "AzureTest"}'; + options["data"] = `{"name": "${testData}"}`; options["method"] = "GET"; + //"http://serviceName.azurewebsites.net/api/hello?name=Test-Data" const service = new InvokeService(sls, options); const response = await service.invoke(options["function"], options["data"], options["method"]); - - expect().toEqual(response.data) - }); + expect(response.data).toEqual(result); + }); }); \ No newline at end of file diff --git a/src/services/invokeService.ts b/src/services/invokeService.ts index ddb3fb23..e836fc47 100644 --- a/src/services/invokeService.ts +++ b/src/services/invokeService.ts @@ -5,12 +5,10 @@ import axios from "axios"; import { FunctionAppService } from "./functionAppService"; export class InvokeService extends BaseService { - public functionAppService: FunctionAppService; public serverless: Serverless; public options: Serverless.Options; public constructor(serverless: Serverless, options: Serverless.Options) { super(serverless, options); - this.functionAppService = new FunctionAppService(serverless, options); this.serverless = serverless; this.options = options; } @@ -67,7 +65,9 @@ export class InvokeService extends BaseService { * @param data Data to use as body or query params */ private async getOptions(method: string, data?: any) { - const functionsAdminKey = await this.functionAppService.getMasterKey(); + + const functionAppService = new FunctionAppService(this.serverless, this.options); + const functionsAdminKey = await functionAppService.getMasterKey(); this.log(functionsAdminKey); const options: any = { host: config.functionAppDomain, From ebe6b24a0f8a83b09cb23abe26b6d2429c8ed886 Mon Sep 17 00:00:00 2001 From: Neeraj Mandal Date: Mon, 1 Jul 2019 17:01:19 -0700 Subject: [PATCH 3/6] Test files added --- src/plugins/invoke/azureInvoke.test.ts | 22 +++++++++++++++++----- src/services/invokeService.test.ts | 9 --------- 2 files changed, 17 insertions(+), 14 deletions(-) diff --git a/src/plugins/invoke/azureInvoke.test.ts b/src/plugins/invoke/azureInvoke.test.ts index ca38b6b3..38832ff9 100644 --- a/src/plugins/invoke/azureInvoke.test.ts +++ b/src/plugins/invoke/azureInvoke.test.ts @@ -25,7 +25,7 @@ describe("Azure Invoke Plugin", () => { mockFs.restore(); }); - it("calls invoke hook", async () => { + it("Calls invoke hook", async () => { const invoke = jest.fn(); InvokeService.prototype.invoke = invoke; @@ -39,9 +39,10 @@ describe("Azure Invoke Plugin", () => { const plugin = new AzureInvoke(sls, options); await invokeHook(plugin, "invoke:invoke"); expect(invoke).toBeCalledWith(options["function"], options["data"], options["method"]); + }); - it("calls the invoke hook with file path", async () => { + it("Calls the invoke hook with file path", async () => { const invoke = jest.fn(); InvokeService.prototype.invoke = invoke; const sls = MockFactory.createTestServerless(); @@ -55,7 +56,7 @@ describe("Azure Invoke Plugin", () => { expect(invoke).toBeCalledWith(options["function"], fileContent, options["method"]); }); - it("calls the invooke hook with file path", async () => { + it("Fails if wrong file name is provided", async () => { const invoke = jest.fn(); InvokeService.prototype.invoke = invoke; const sls = MockFactory.createTestServerless(); @@ -63,8 +64,19 @@ describe("Azure Invoke Plugin", () => { options["function"] = "testApp"; options["path"] = "garbage.json"; options["method"] = "GET"; + expect(() => new AzureInvoke(sls, options)).toThrow(); + }); - const plugin = await new AzureInvoke(sls, options); - await expect(invokeHook(plugin, "invoke:invoke")).toThrow(); + it("The invoke function should not be called when no data is passsed", async () => { + const invoke = jest.fn(); + InvokeService.prototype.invoke = invoke; + const sls = MockFactory.createTestServerless(); + const options = MockFactory.createTestServerlessOptions(); + options["function"] = "testApp"; + options["data"] = null; + options["method"] = "GET"; + const plugin = new AzureInvoke(sls, options); + await invokeHook(plugin, "invoke:invoke"); + expect(invoke).not.toBeCalled(); }); }); diff --git a/src/services/invokeService.test.ts b/src/services/invokeService.test.ts index 2a54c47d..6754bece 100644 --- a/src/services/invokeService.test.ts +++ b/src/services/invokeService.test.ts @@ -1,21 +1,14 @@ import axios from "axios"; import MockAdapter from "axios-mock-adapter"; -import mockFs from "mock-fs"; -import Serverless from "serverless"; import { MockFactory } from "../test/mockFactory"; import { InvokeService } from "./invokeService"; -import { Site } from "@azure/arm-appservice/esm/models"; import { FunctionAppService } from "./functionAppService"; jest.mock("@azure/arm-appservice") -import { WebSiteManagementClient } from "@azure/arm-appservice"; jest.mock("@azure/arm-resources") describe("Invoke Service ", () => { const app = MockFactory.createTestSite(); const slsService = MockFactory.createTestService(); - const variables = MockFactory.createTestVariables(); - const provider = MockFactory.createTestAzureServiceProvider(); - const functionName = "test"; const testData = "test-data"; const result = "result"; const authKey = "authKey"; @@ -23,7 +16,6 @@ describe("Invoke Service ", () => { const masterKeyUrl = `https://${app.defaultHostName}/admin/host/systemkeys/_master`; const authKeyUrl = `${baseUrl}${app.id}/functions/admin/token?api-version=2016-08-01`; const functionUrl = `http://${slsService.getServiceName()}.azurewebsites.net/api/hello?name=${testData}`; - let functionApp: Site; let masterKey: string; beforeAll(() => { @@ -48,7 +40,6 @@ describe("Invoke Service ", () => { options["data"] = `{"name": "${testData}"}`; options["method"] = "GET"; - //"http://serviceName.azurewebsites.net/api/hello?name=Test-Data" const service = new InvokeService(sls, options); const response = await service.invoke(options["function"], options["data"], options["method"]); expect(response.data).toEqual(result); From 9cb0d91ca28065742a61d6056a3acfffd1549ade Mon Sep 17 00:00:00 2001 From: Neeraj Mandal Date: Tue, 2 Jul 2019 08:46:58 -0700 Subject: [PATCH 4/6] test files added --- src/plugins/invoke/azureInvoke.test.ts | 46 +++++++++++++++++++++----- src/plugins/invoke/azureInvoke.ts | 2 +- 2 files changed, 38 insertions(+), 10 deletions(-) diff --git a/src/plugins/invoke/azureInvoke.test.ts b/src/plugins/invoke/azureInvoke.test.ts index ca38b6b3..6f9cd1a7 100644 --- a/src/plugins/invoke/azureInvoke.test.ts +++ b/src/plugins/invoke/azureInvoke.test.ts @@ -1,12 +1,12 @@ import { MockFactory } from "../../test/mockFactory"; import { invokeHook } from "../../test/utils"; import mockFs from "mock-fs"; +import { AzureInvoke } from "./azureInvoke"; +import { InvokeService } from "../../services/invokeService"; jest.mock("../../services/functionAppService"); jest.mock("../../services/resourceService"); -import { AzureInvoke } from "./azureInvoke"; jest.mock("../../services/invokeService"); -import { InvokeService } from "../../services/invokeService"; describe("Azure Invoke Plugin", () => { const fileContent = JSON.stringify({ @@ -26,9 +26,9 @@ describe("Azure Invoke Plugin", () => { }); it("calls invoke hook", async () => { - - const invoke = jest.fn(); - InvokeService.prototype.invoke = invoke; + const expectedResult = { data: "test" }; + const invoke = jest.fn(() => expectedResult); + InvokeService.prototype.invoke = invoke as any; const sls = MockFactory.createTestServerless(); const options = MockFactory.createTestServerlessOptions(); @@ -39,11 +39,13 @@ describe("Azure Invoke Plugin", () => { const plugin = new AzureInvoke(sls, options); await invokeHook(plugin, "invoke:invoke"); expect(invoke).toBeCalledWith(options["function"], options["data"], options["method"]); + expect(sls.cli.log).toBeCalledWith(expectedResult.data); }); it("calls the invoke hook with file path", async () => { - const invoke = jest.fn(); - InvokeService.prototype.invoke = invoke; + const expectedResult = { data: "test" }; + const invoke = jest.fn(() => expectedResult); + InvokeService.prototype.invoke = invoke as any; const sls = MockFactory.createTestServerless(); const options = MockFactory.createTestServerlessOptions(); options["function"] = "testApp"; @@ -53,6 +55,8 @@ describe("Azure Invoke Plugin", () => { const plugin = new AzureInvoke(sls, options); await invokeHook(plugin, "invoke:invoke"); expect(invoke).toBeCalledWith(options["function"], fileContent, options["method"]); + expect(sls.cli.log).toBeCalledWith(expectedResult.data); + }); it("calls the invooke hook with file path", async () => { @@ -63,8 +67,32 @@ describe("Azure Invoke Plugin", () => { options["function"] = "testApp"; options["path"] = "garbage.json"; options["method"] = "GET"; + expect(() => new AzureInvoke(sls, options)).toThrow(); + }); + + it("The invoke function fails when no data is passsed", async () => { + const invoke = jest.fn(); + InvokeService.prototype.invoke = invoke; + const sls = MockFactory.createTestServerless(); + const options = MockFactory.createTestServerlessOptions(); + options["function"] = "testApp"; + options["data"] = null; + options["method"] = "GET"; + const plugin = new AzureInvoke(sls, options); + await invokeHook(plugin, "invoke:invoke"); + expect(invoke).not.toBeCalled(); + }); - const plugin = await new AzureInvoke(sls, options); - await expect(invokeHook(plugin, "invoke:invoke")).toThrow(); + it("The invoke function fails when no function name is passsed", async () => { + const invoke = jest.fn(); + InvokeService.prototype.invoke = invoke; + const sls = MockFactory.createTestServerless(); + const options = MockFactory.createTestServerlessOptions(); + options["function"] = null; + options["data"] = "{\"name\": \"AzureTest\"}"; + options["method"] = "GET"; + const plugin = new AzureInvoke(sls, options); + await invokeHook(plugin, "invoke:invoke"); + expect(invoke).not.toBeCalled(); }); }); diff --git a/src/plugins/invoke/azureInvoke.ts b/src/plugins/invoke/azureInvoke.ts index 27c80888..804f686b 100644 --- a/src/plugins/invoke/azureInvoke.ts +++ b/src/plugins/invoke/azureInvoke.ts @@ -74,6 +74,6 @@ export class AzureInvoke { } this.invokeService = new InvokeService(this.serverless, this.options); const response = await this.invokeService.invoke(functionName, data, method); - //this.serverless.cli.log(response.data); + this.serverless.cli.log(response.data); } } \ No newline at end of file From b9865ce0ffcb62e17bae7a4615178a45fc775574 Mon Sep 17 00:00:00 2001 From: Neeraj Mandal Date: Tue, 2 Jul 2019 08:51:21 -0700 Subject: [PATCH 5/6] Test for azureInvoke and InvokeService added --- src/plugins/invoke/azureInvoke.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/invoke/azureInvoke.test.ts b/src/plugins/invoke/azureInvoke.test.ts index 19023c7c..f5c85561 100644 --- a/src/plugins/invoke/azureInvoke.test.ts +++ b/src/plugins/invoke/azureInvoke.test.ts @@ -83,7 +83,7 @@ describe("Azure Invoke Plugin", () => { expect(invoke).not.toBeCalled(); }); - it("The invoke function fails when no function name is passsed", async () => { + it("The invoke function fails when no function name is passed", async () => { const invoke = jest.fn(); InvokeService.prototype.invoke = invoke; const sls = MockFactory.createTestServerless(); From 56aa3f6cf251393fee59e52fdc4e803203251d66 Mon Sep 17 00:00:00 2001 From: Neeraj Mandal Date: Tue, 2 Jul 2019 08:54:02 -0700 Subject: [PATCH 6/6] Test for azureInvoke and InvokeService added --- src/plugins/invoke/azureInvoke.test.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/plugins/invoke/azureInvoke.test.ts b/src/plugins/invoke/azureInvoke.test.ts index f5c85561..7f45eb47 100644 --- a/src/plugins/invoke/azureInvoke.test.ts +++ b/src/plugins/invoke/azureInvoke.test.ts @@ -1,12 +1,12 @@ import { MockFactory } from "../../test/mockFactory"; import { invokeHook } from "../../test/utils"; import mockFs from "mock-fs"; +import { AzureInvoke } from "./azureInvoke"; +import { InvokeService } from "../../services/invokeService"; jest.mock("../../services/functionAppService"); jest.mock("../../services/resourceService"); -import { AzureInvoke } from "./azureInvoke"; jest.mock("../../services/invokeService"); -import { InvokeService } from "../../services/invokeService"; describe("Azure Invoke Plugin", () => { const fileContent = JSON.stringify({