diff --git a/packages/@twokeys/core/src/config.ts b/packages/@twokeys/core/src/config.ts index f9b1645c..781831da 100644 --- a/packages/@twokeys/core/src/config.ts +++ b/packages/@twokeys/core/src/config.ts @@ -22,6 +22,7 @@ * Requires config to be given * @packageDocumentation */ +// TODO: Config validation of everything import { promises as fs } from "fs"; import YAML from "yaml"; import { MainConfig, DetectorConfig, ClientConfig, ProjectConfig, CombinedConfigs, AddConfigUtils, MakeKeysOptional, ConfigUtils } from "./interfaces"; diff --git a/packages/@twokeys/server/src/index.ts b/packages/@twokeys/server/src/index.ts index 9799b2b3..e60da87a 100644 --- a/packages/@twokeys/server/src/index.ts +++ b/packages/@twokeys/server/src/index.ts @@ -54,7 +54,7 @@ const server = async (port: number = DEFAULT_PORT, argv: ServerArgs, projectDir: // Error handler app.use((err, req, res, next) => { logger.err(`An error was encountered on router ${req.originalUrl}`); - logger.throw_noexit(err); + logger.printError(err); next(err); }); diff --git a/packages/@twokeys/server/src/routes/api.ts b/packages/@twokeys/server/src/routes/api.ts index 8a09a6b1..f87e0133 100644 --- a/packages/@twokeys/server/src/routes/api.ts +++ b/packages/@twokeys/server/src/routes/api.ts @@ -119,7 +119,7 @@ export default async function getAPI(projectConfig: ProjectConfig, projectDir: s * } * ``` */ - router.post("/post/:detector/:keyboard/trigger", getTriggerHotkey(detectors, executors)); + router.post("/post/trigger/:detector/:keyboard", getTriggerHotkey(detectors, executors)); /** * Trigger a hotkey @@ -182,6 +182,7 @@ export default async function getAPI(projectConfig: ProjectConfig, projectDir: s /** * Handles keyboard path update */ + // TODO: Update this route to use whatever new method for config updates we decide on router.post("/post/update-keyboard-path", (req, res, next) => { const { keyboard, path } = req.body; logger.info(`Got update for ${keyboard}, path ${path}`); diff --git a/packages/@twokeys/server/src/routes/triggerHotkey.ts b/packages/@twokeys/server/src/routes/triggerHotkey.ts index ee78f9a2..62dceaac 100644 --- a/packages/@twokeys/server/src/routes/triggerHotkey.ts +++ b/packages/@twokeys/server/src/routes/triggerHotkey.ts @@ -34,6 +34,7 @@ function isMultiHotkey(hotkey: Hotkey): hotkey is HotkeyTypeKeypressValue { * @param executors Loaded executors */ // TODO: Execute on a different thread, because the server hangs and fails any in progress runs if it is still waiting for this +// TODO: Normalise hotkeys so they are all in lowercase, since ^A and ^a are the same key. (might not be needed though, as detectors should read directly from config) async function executeHotKey(hotkey: HotkeyTypeSingle, hotkeyCode: string, keyboard: Keyboard, executors: ExtractGeneric>): Promise { logger.info(`Executing hotkey ${hotkey}...`); const executorToCall = hotkey.executor || keyboard.executors.default; @@ -70,6 +71,7 @@ async function executeHotKey(hotkey: HotkeyTypeSingle, hotkeyCode: string, keybo * * @param detectors Loaded detector configs to use * @param executor Loaded executors from registry + * @returns Exprss route handler for triggering a hotkey */ const getTriggerHotkey = (detectors: Map, executors: ExtractGeneric>): RequestHandler => { return function (req, res, next): void { @@ -111,7 +113,7 @@ const getTriggerHotkey = (detectors: Map, executors: Ext } const detector = detectors.get(detectorName) as DetectorConfig; if (hasOwnProperty(detector.keyboards, keyboardName)) { // Check the keyboard is present - logger.debug(`Keybaord ${keyboardName} found`); + logger.debug(`Keyboard ${keyboardName} found`); const keyboard = detector.keyboards[keyboardName]; if (!hasOwnProperty(keyboard.hotkeys, hotkey)) { // Check hotkey is present @@ -129,7 +131,11 @@ const getTriggerHotkey = (detectors: Map, executors: Ext if (isMultiHotkey(theHotkey)) { logger.debug("Got a multi type hotkey!"); if (typeof theHotkey[eventType] !== "object") { - return next(new CodedError(`Hotkey event ${eventType} not found!`, ERR_BAD_EVENT_TYPE)); + res.statusCode = 422; + res.json({ + message: `Hotkey event type ${eventType} not found` + }); + return; } else { configToGive = theHotkey[eventType] as HotkeyTypeSingle; } diff --git a/packages/@twokeys/server/test/routes/new-api.ts b/packages/@twokeys/server/test/routes/new-api.ts index 51efc793..d844e16d 100644 --- a/packages/@twokeys/server/test/routes/new-api.ts +++ b/packages/@twokeys/server/test/routes/new-api.ts @@ -9,7 +9,7 @@ import { expect } from "chai"; import sinon from "sinon"; import { constants } from "@twokeys/core"; -let agent; +let agent: request.SuperAgentTest; describe("New API tests", () => { @@ -81,5 +81,102 @@ describe("New API tests", () => { }); }); + describe("/post/trigger/:detector/:keyboard", () => { + it("should return 422 when an invalid post body is sent", (done) => { + agent + .post("/api/post/trigger/someDetector/someKDB") + .expect(422) + .end((err, res) => { + if (err) { done(err); } + expect(res.body).to.deep.equal({ + message: "Invalid POST body! Properties were missing!" + }); + done(); + }); + }); + it("should return 422 when the hotkey proeprty is missing from the body", (done) => { + agent + .post("/api/post/trigger/someDetector/someKDB") + .send({ event: "down" }) + .expect(422) + .end((err, res) => { + if (err) { done(err); } + expect(res.body).to.deep.equal({ + message: "Invalid POST body! Properties were missing!" + }); + done(); + }); + }); + it("should not accept an invalid event field", (done) => { + agent + .post("/api/post/trigger/someDetector/someKDB") + .send({ hotkey: "^A", event: "NOT AN EVENT" }) + .expect(422) + .end((err, res) => { + if (err) { done(err); } + expect(res.body).to.deep.equal({ + message: "Bad event field given!" + }); + done(); + }); + }); + + it("should return 404 when triggering a detector or hotkey that was not found", (done) => { + agent + .post("/api/post/trigger/someDetector/someKDB") + .send({ hotkey: "^A" }) + .expect(404) + .end((err, res) => { + if (err) { done(err); } + expect(res.body).to.deep.equal({ + message: "Detector Not Found" + }); + done(); + }); + }); + + it("should return 404 when a keyboard is not found", (done) => { + agent + .post("/api/post/trigger/Test Detector/someKDB") + .send({ hotkey: "^A" }) + .expect(404) + .end((err, res) => { + if (err) { done(err); } + expect(res.body).to.deep.equal({ + message: "Keyboard Not Found" + }); + done(); + }); + }); + + it("should return 404 when a hotkey is not found", (done) => { + agent + .post("/api/post/trigger/Test Detector/keyboard_1") + .send({ hotkey: "NotAHotkey" }) + .expect(404) + .end((err, res) => { + if (err) { done(err); } + expect(res.body).to.deep.equal({ + message: "Hotkey Not Found" + }); + done(); + }); + }); + + it("should return 422 when a hotkey event type is not found", (done) => { + agent + .post("/api/post/trigger/Test Detector/keyboard_1") + .send({ hotkey: "+C", event: "hold" }) + .expect(422) + .end((err, res) => { + if (err) { done(err); } + expect(res.body).to.deep.equal({ + message: "Hotkey event type hold not found" + }); + done(); + }); + }); + }); + after(() => sinon.restore()); }); \ No newline at end of file diff --git a/packages/@twokeys/server/test/util/copy-contents.ts b/packages/@twokeys/server/test/util/copy-contents.ts index 86f5c8b0..b44372a2 100644 --- a/packages/@twokeys/server/test/util/copy-contents.ts +++ b/packages/@twokeys/server/test/util/copy-contents.ts @@ -13,7 +13,7 @@ const { expect } = chai; // Consts const MOCK_ROOT_COPY = join(MOCK_ROOT, "../non-mocha-copy"); -describe("Copy contents of folder function test", () => { +describe.skip("Copy contents of folder function test", () => { it("should successfully copy contents of a dir to another", async () => { await copy_contents(MOCK_ROOT, MOCK_ROOT_COPY); diff --git a/packages/@twokeys/server/testing/project/detector-test.yml b/packages/@twokeys/server/testing/project/detector-test.yml index 187f2e92..e71f790f 100644 --- a/packages/@twokeys/server/testing/project/detector-test.yml +++ b/packages/@twokeys/server/testing/project/detector-test.yml @@ -11,6 +11,9 @@ detector_config: # Schema specified by detector; this configures the detector cli-args: --debug # CLI args for detector keyboards: # Specifies keybaord and hotkeys + malformed_KD: + hotkeys: + ^A: "" keyboard_1: root: ./Keyboard_1 # Root folder where macro file (e.g. .ahk files) are executors: @@ -27,6 +30,13 @@ keyboards: # Specifies keybaord and hotkeys ^A: # Ultmately the keycodes is up to the detector to decide executor: "@twokeys/executor-ahk" # If default, don't need to give this func: CallFunc + +C: + up: + executor: "@twokeys/executor-ahk" + func: CallFunc # AHK function to call + down: + executor: executor-ahk + func: add-ons/packs/essentials-pack/TestIfWorking # Use function TestIfWorking from pack essentials-pack ^B: up: executor: "@twokeys/executor-ahk"