UNPKG

actionhero

Version:

The reusable, scalable, and quick node.js API server for stateless and stateful applications

331 lines (293 loc) 11.7 kB
import { api, Process, specHelper, task } from "./../../src/index"; const actionhero = new Process(); describe("Core: specHelper", () => { beforeAll(async () => { await actionhero.start(); }); afterAll(async () => { await actionhero.stop(); }); test("can make a request with just params", async () => { const { randomNumber } = await specHelper.runAction("randomNumber"); expect(randomNumber).toBeGreaterThanOrEqual(0); expect(randomNumber).toBeLessThan(1); }); test("will stack up messages received", async () => { const connection = await specHelper.buildConnection(); connection.params.thing = "stuff"; const { error } = await specHelper.runAction("x", connection); expect(connection.messages).toHaveLength(2); expect(connection.messages[0].welcome).toEqual( "Hello! Welcome to the actionhero api" ); expect(connection.messages[1].error).toEqual( "Error: unknown action or invalid apiVersion" ); expect(error).toEqual("Error: unknown action or invalid apiVersion"); }); describe("metadata, type-safety, and errors", () => { beforeAll(() => { api.actions.versions.stringResponseTestAction = [1]; api.actions.actions.stringResponseTestAction = { //@ts-ignore 1: { name: "stringResponseTestAction", description: "stringResponseTestAction", version: 1, run: async (data) => { //@ts-ignore data.response = "something response"; }, }, }; api.actions.versions.stringErrorTestAction = [1]; api.actions.actions.stringErrorTestAction = { //@ts-ignore 1: { name: "stringErrorTestAction", description: "stringErrorTestAction", version: 1, run: (data) => { //@ts-ignore data.response = "something response"; throw new Error("some error"); }, }, }; api.actions.versions.arrayResponseTestAction = [1]; api.actions.actions.arrayResponseTestAction = { //@ts-ignore 1: { name: "arrayResponseTestAction", description: "arrayResponseTestAction", version: 1, run: async (data) => { data.response = [1, 2, 3]; }, }, }; api.actions.versions.arrayErrorTestAction = [1]; api.actions.actions.arrayErrorTestAction = { //@ts-ignore 1: { name: "arrayErrorTestAction", description: "arrayErrorTestAction", version: 1, run: (data) => { data.response = [1, 2, 3]; throw new Error("some error"); }, }, }; }); afterAll(() => { delete api.actions.actions.stringResponseTestAction; delete api.actions.versions.stringResponseTestAction; delete api.actions.actions.stringErrorTestAction; delete api.actions.versions.stringErrorTestAction; delete api.actions.actions.arrayResponseTestAction; delete api.actions.versions.arrayResponseTestAction; delete api.actions.actions.arrayErrorTestAction; delete api.actions.versions.arrayErrorTestAction; }); describe("happy-path", () => { test("if the response payload is an object, it appends metadata", async () => { const response = await specHelper.runAction("randomNumber"); expect(response.error).toBeUndefined(); expect(response.randomNumber).toBeTruthy(); expect(response.messageId).toBeTruthy(); expect(response.serverInformation.serverName).toEqual("actionhero"); expect(response.requesterInformation.remoteIP).toEqual("testServer"); }); test("if the response payload is a string, it maintains type", async () => { const response = await specHelper.runAction("stringResponseTestAction"); expect(response).toEqual("something response"); expect(response.error).toBeUndefined(); expect(response.messageId).toBeUndefined(); expect(response.serverInformation).toBeUndefined(); expect(response.requesterInformation).toBeUndefined(); }); test("if the response payload is a array, it maintains type", async () => { const response = await specHelper.runAction("arrayResponseTestAction"); expect(response).toEqual([1, 2, 3]); expect(response.error).toBeUndefined(); expect(response.messageId).toBeUndefined(); expect(response.serverInformation).toBeUndefined(); expect(response.requesterInformation).toBeUndefined(); }); }); describe("disabling metadata", () => { beforeAll(() => { api.specHelper.returnMetadata = false; }); afterAll(() => { api.specHelper.returnMetadata = true; }); test("if the response payload is an object, it should not append metadata", async () => { const response = await specHelper.runAction("randomNumber"); expect(response.error).toBeUndefined(); expect(response.randomNumber).toBeTruthy(); expect(response.messageId).toBeUndefined(); expect(response.serverInformation).toBeUndefined(); expect(response.requesterInformation).toBeUndefined(); }); }); describe("errors", () => { test("if the response payload is an object and there is an error, it appends metadata", async () => { const response = await specHelper.runAction("x"); expect(response.error).toEqual( "Error: unknown action or invalid apiVersion" ); expect(response.messageId).toBeTruthy(); expect(response.serverInformation.serverName).toEqual("actionhero"); expect(response.requesterInformation.remoteIP).toEqual("testServer"); }); test("if the response payload is a string, just the error will be returned", async () => { const response = await specHelper.runAction("stringErrorTestAction"); expect(response).toEqual("Error: some error"); expect(response.messageId).toBeUndefined(); expect(response.serverInformation).toBeUndefined(); expect(response.requesterInformation).toBeUndefined(); }); test("if the response payload is a array, just the error will be returned", async () => { const response = await specHelper.runAction("arrayErrorTestAction"); expect(response).toEqual("Error: some error"); expect(response.messageId).toBeUndefined(); expect(response.serverInformation).toBeUndefined(); expect(response.requesterInformation).toBeUndefined(); }); }); }); describe("test responses", () => { test("will not report a broken test as a broken action (sync)", async () => { const response = await specHelper.runAction("randomNumber"); try { response.not.a.real.thing(); throw new Error("should not get here"); } catch (e) { expect(String(e)).toEqual( "TypeError: Cannot read property 'a' of undefined" ); } }); test("will not report a broken test as a broken action (async)", async () => { const response = await specHelper.runAction("sleepTest"); try { response.not.a.real.thing(); throw new Error("should not get here"); } catch (e) { expect(String(e)).toEqual( "TypeError: Cannot read property 'a' of undefined" ); } }); test("messageId can be configurable", async () => { const response = await specHelper.runAction("randomNumber", { messageId: "aaa", }); expect(response.messageId).toEqual("aaa"); }); }); describe("files", () => { test("can request file data", async () => { const data = await specHelper.getStaticFile("simple.html"); expect(data.error).toBeUndefined(); expect(data.content).toContain("<h1>Actionhero</h1>"); expect(data.mime).toEqual("text/html"); expect(data.length).toEqual(101); }); test("missing files", async () => { const data = await specHelper.getStaticFile("missing.html"); expect(data.error).toEqual("That file is not found"); expect(data.mime).toEqual("text/html"); expect(data.content).toBeNull(); }); }); describe("persistent test connections", () => { let connection; let connId; const messageIds = []; test("can make a request with a specified connection", async () => { connection = await specHelper.buildConnection(); connection.params = { key: "someKey", value: "someValue", }; connId = connection.id; const response = await specHelper.runAction("cacheTest", connection); messageIds.push(response.messageId); expect(connection.messages).toHaveLength(2); expect(connId).toEqual(connection.id); expect(connection.fingerprint).toEqual(connId); }); test("can make second request", async () => { const response = await specHelper.runAction("randomNumber", connection); messageIds.push(response.messageId); expect(connection.messages).toHaveLength(3); expect(connId).toEqual(connection.id); expect(connection.fingerprint).toEqual(connId); }); test("will generate new ids and fingerprints for a new connection", async () => { const response = await specHelper.runAction("randomNumber"); messageIds.push(response.messageId); expect(response.requesterInformation.id).not.toEqual(connId); expect(response.requesterInformation.fingerprint).not.toEqual(connId); }); test("message ids are unique", () => { expect(messageIds).toHaveLength(3); expect(messageIds[0]).not.toEqual(messageIds[1]); expect(messageIds[1]).not.toEqual(messageIds[2]); }); }); describe("tasks", () => { let taskRan = false; beforeAll(() => { api.tasks.tasks.testTask = { name: "testTask", description: "task: test: " + Math.random(), queue: "default", frequency: 0, plugins: [], pluginOptions: {}, run: (api, params) => { taskRan = true; return "OK"; }, }; api.tasks.jobs.testTask = api.tasks.jobWrapper("testTask"); }); afterAll(() => { delete api.testOutput; delete api.tasks.tasks.testTask; }); test("can run tasks", async () => { const response = await specHelper.runTask("testTask", {}); expect(response).toEqual("OK"); expect(taskRan).toEqual(true); }); describe("flushed redis", () => { beforeEach(async () => { await api.redis.clients.client.flushdb(); }); test("findEnqueuedTasks (normal queues)", async () => { await task.enqueue("testTask", { a: 1 }); const foundTasks = await specHelper.findEnqueuedTasks("testTask"); expect(foundTasks.length).toBe(1); expect(foundTasks[0].args[0]).toEqual({ a: 1 }); }); test("findEnqueuedTasks (delayed queues)", async () => { await task.enqueueIn(1, "testTask", { a: 1 }); const foundTasks = await specHelper.findEnqueuedTasks("testTask"); expect(foundTasks.length).toBe(1); expect(foundTasks[0].args[0]).toEqual({ a: 1 }); }); test("deleteEnqueuedTasks", async () => { await task.enqueue("testTask", { a: 1 }); await task.enqueueAt(10, "testTask", { a: 1 }); await specHelper.deleteEnqueuedTasks("testTask", { a: 1 }); const foundTasks = await specHelper.findEnqueuedTasks("testTask"); expect(foundTasks.length).toBe(0); }); }); }); });