Skip to content

Commit

Permalink
fix: Added test coverage and cleanup to more parsers
Browse files Browse the repository at this point in the history
Signed-off-by: Lawrence Brooks <[email protected]>
  • Loading branch information
lbrooks committed Nov 15, 2024
1 parent c796a7d commit 6325546
Show file tree
Hide file tree
Showing 7 changed files with 237 additions and 99 deletions.
23 changes: 23 additions & 0 deletions src/api/parsers/colormap.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { expect, describe, it } from "vitest";
import { parseColormapRaw } from "./colormap";

describe("parseColormapRaw", () => {
it("should split into groups", () => {
expect(parseColormapRaw("10 20 30 40", 2)).toEqual([
[10, 20],
[30, 40],
]);
});

it("should normalize numbers data", () => {
expect(parseColormapRaw("-10 400 10", 3)).toEqual([[0, 255, 10]]);
});

it("should fill in missing numbers with zeros", () => {
expect(parseColormapRaw("10", 3)).toEqual([[10, 0, 0]]);
});

it("should not care about extra whitespace", () => {
expect(parseColormapRaw(" 10 20 30 40 ", 4)).toEqual([[10, 20, 30, 40]]);
});
});
30 changes: 16 additions & 14 deletions src/api/parsers/colormap.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
export const parseColormapRaw = (colormap: string, ColorLayerSize: number): number[][] =>
colormap
.split(" ")
.filter(v => v.length > 0)
.map((k: string) => parseInt(k, 10))
.reduce((resultArray, item, index) => {
const localResult: number[][] = resultArray;
const chunkIndex = Math.floor(index / ColorLayerSize);
export function parseColormapRaw(colormap: string, ColorLayerSize: number): number[][] {
const rawColorMapAsNumbers = colormap
.trim()
.split(/ +/)
.map((value: string) => parseInt(value, 10))
.map((value: number) => Math.max(0, Math.min(255, value)));

if (!localResult[chunkIndex]) {
localResult[chunkIndex] = []; // start a new chunk
}
localResult[chunkIndex].push(item);
return localResult;
}, []);
const result: number[][] = [];
for (let i = 0; i < rawColorMapAsNumbers.length; ) {
const color: number[] = [];
for (let c = 0; c < ColorLayerSize; c++) {
color.push(i < rawColorMapAsNumbers.length ? rawColorMapAsNumbers[i++] : 0);
}
result.push(color);
}
return result;
}
52 changes: 52 additions & 0 deletions src/api/parsers/keymap.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import { expect, describe, it } from "vitest";
import { parseKeymapRaw, serializeKeymap } from "./keymap";

describe("parseKeymapRaw", () => {
it("should split into groups", () => {
expect(parseKeymapRaw("10 20 30 40", 2)).toEqual([
[10, 20],
[30, 40],
]);
});

it("should NOT normalize numbers data", () => {
expect(parseKeymapRaw("-10 400 10", 3)).toEqual([[-10, 400, 10]]);
});

it("should fill in missing numbers with zeros", () => {
expect(parseKeymapRaw("10", 3)).toEqual([[10, 0, 0]]);
});

it("should not care about extra whitespace", () => {
expect(parseKeymapRaw(" 10 20 30 40 ", 4)).toEqual([[10, 20, 30, 40]]);
});
});

describe("serializeKeymap", () => {
it("should serialize empty", () => {
expect(serializeKeymap([])).toEqual("");
});

it("should serialize no actions to empty", () => {
expect(serializeKeymap([[]])).toEqual("");
});

it("should serialize a keymap with one key", () => {
expect(serializeKeymap([[{ keyCode: 10, label: "test" }]])).toEqual("10");
});

it("should serialize a keymap with 2 keys in one nested array", () => {
expect(
serializeKeymap([
[
{ keyCode: 10, label: "test" },
{ keyCode: 20, label: "test_2" },
],
]),
).toEqual("10 20");
});

it("should serialize a keymap with 2 keys in separate nested arrays", () => {
expect(serializeKeymap([[{ keyCode: 10, label: "test" }], [{ keyCode: 20, label: "test_2" }]])).toEqual("10 20");
});
});
33 changes: 17 additions & 16 deletions src/api/parsers/keymap.ts
Original file line number Diff line number Diff line change
@@ -1,26 +1,27 @@
import { KeyType } from "@Renderer/types/layout";
import { KeyType } from "@Types/layout";
import { KeymapDB } from "../keymap";

const keymapDB = new KeymapDB();

export const parseKeymapRaw = (keymap: string, keyLayerSize: number): number[][] =>
keymap
.split(" ")
.filter(v => v.length > 0)
.map((k: string) => parseInt(k, 10))
.reduce((resultArray, item, index) => {
const localResult = resultArray;
const chunkIndex = Math.floor(index / keyLayerSize);
export function parseKeymapRaw(keymap: string, keyLayerSize: number): number[][] {
const rawColorMapAsNumbers = keymap
.trim()
.split(/ +/)
.map((value: string) => parseInt(value, 10));

if (!localResult[chunkIndex]) {
localResult[chunkIndex] = []; // start a new chunk
}
localResult[chunkIndex].push(item);
return localResult;
}, []);
const result: number[][] = [];
for (let i = 0; i < rawColorMapAsNumbers.length; ) {
const keys: number[] = [];
for (let c = 0; c < keyLayerSize; c++) {
keys.push(i < rawColorMapAsNumbers.length ? rawColorMapAsNumbers[i++] : 0);
}
result.push(keys);
}
return result;
}

export const serializeKeymap = (keymap: KeyType[][]) =>
keymap
.flat()
.map(k => (typeof k === "number" ? String(k) : keymapDB.serialize(k).toString()))
.map(k => keymapDB.serialize(k).toString())
.join(" ");
81 changes: 81 additions & 0 deletions src/api/parsers/superkeys.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
import { expect, describe, it } from "vitest";
import { parseSuperkeysRaw, serializeSuperkeys } from "./superkeys";

describe("parseSuperkeysRaw", () => {
it("should parse", () => {
expect(
parseSuperkeysRaw("55 2104 54 2078 1 0 2099 51 1 1 1 0 2100 52 1 53 1 0 0 65535 65535 65535 65535", [
{ id: 0, name: "first", actions: [] },
{ id: 1, name: "second", actions: [] },
]),
).toEqual([
{
actions: [55, 2104, 54, 2078, 1],
id: 0,
name: "first",
},
{
actions: [2099, 51, 1, 1, 1],
id: 1,
name: "second",
},
{
actions: [2100, 52, 1, 53, 1],
id: 2,
name: "",
},
]);
});

it("should return empty array when no superkeys", () => {
expect(
parseSuperkeysRaw("65535 65535 65535 65535", [
{ id: 0, name: "first", actions: [] },
{ id: 1, name: "second", actions: [] },
]),
).toEqual([]);
});
});

describe("serializeSuperkeysRaw", () => {
it("should serialize empty", () => {
expect(serializeSuperkeys([])).toEqual(Array(512).fill(0xffff).join(" "));
});

it("should serialize no actions to empty", () => {
expect(serializeSuperkeys([{ actions: [], id: 0, name: "test" }])).toEqual(Array(512).fill(0xffff).join(" "));
});

it("should serialize a zero actions to empty", () => {
expect(serializeSuperkeys([{ actions: [0], id: 0, name: "test" }])).toEqual(Array(512).fill(0xffff).join(" "));
});

it("should serialize a superkey", () => {
expect(serializeSuperkeys([{ actions: [10, 20], id: 0, name: "test" }])).toEqual("10 20 1 1 1 0 0");
});

it("should handle zero", () => {
expect(serializeSuperkeys([{ actions: [10, 0, 20], id: 0, name: "test" }])).toEqual("10 1 20 1 1 0 0");
});

it("should handle undefined", () => {
expect(serializeSuperkeys([{ actions: [10, undefined, 20], id: 0, name: "test" }])).toEqual("10 1 20 1 1 0 0");
});

it("should handle null", () => {
expect(serializeSuperkeys([{ actions: [10, null, 20], id: 0, name: "test" }])).toEqual("10 1 20 1 1 0 0");
});

it("should serialize two superkeys", () => {
expect(
serializeSuperkeys([
{ actions: [10, 20], id: 0, name: "test" },
{
actions: [30, 40],
id: 1,
name: "second",
},
]),
).toEqual("10 20 1 1 1 0 30 40 1 1 1 0 0");
});
});
109 changes: 40 additions & 69 deletions src/api/parsers/superkeys.ts
Original file line number Diff line number Diff line change
@@ -1,79 +1,50 @@
import log from "electron-log/renderer";
// import log from "electron-log/renderer";
import { SuperkeysType } from "@Renderer/types/superkeys";

export const parseSuperkeysRaw = (raw: string, stored: SuperkeysType[]) => {
const superArray = raw.split(" 0 0")[0].split(" ").map(Number);
export function parseSuperkeysRaw(raw: string, stored: SuperkeysType[]) {
return raw
.trim()
.split(" 0 0")[0] // " 0 0" marks the end of the defined super keys
.split(" 0 ") // " 0 " marks the end of each super key
.map(actionString =>
actionString
.trim()
.split(/ +/)
.map(v => parseInt(v, 10))
.filter(v => v > 0 && v < 65535),
)
.filter(actions => actions.length > 0)
.map(
(actions, id): SuperkeysType => ({
id,
actions,
// The "match" to lookup the name is based on array index position
name: stored.length >= id + 1 ? stored[id].name : "",
}),
);
}

let superkey: number[] = [];
const superkeys: SuperkeysType[] = [];
let iter = 0;
let superindex = 0;

if (superArray.length < 1) {
log.warn("Discarded Superkeys due to short length of string", raw, raw.length);
return [];
}
// log.info(raw, raw.length);
while (superArray.length > iter) {
// log.info(iter, raw[iter], superkey);
if (superArray[iter] === 0) {
superkeys[superindex] = { actions: superkey, name: "", id: superindex };
superindex += 1;
superkey = [];
} else {
superkey.push(superArray[iter]);
}
iter += 1;
}
superkeys[superindex] = { actions: superkey, name: "", id: superindex };

if (superkeys[0].actions.length === 0 || superkeys[0].actions.length > 5) {
log.warn(`Superkeys were empty`);
return [];
}
// log.info(`Got Superkeys:${JSON.stringify(superkeys)} from ${raw}`);
// TODO: Check if stored superKeys match the received ones, if they match, retrieve name and apply it to current superKeys
let finalSuper: SuperkeysType[] = [];
finalSuper = superkeys.map((superky, i) => {
const superk = superky;
if (stored.length > i && stored.length > 0) {
const aux = superk;
aux.name = stored[i].name;
return aux;
}
return superk;
});
log.info("final superkeys", finalSuper);
return finalSuper;
};

export const serializeSuperkeys = (superkeys: SuperkeysType[]) => {
export function serializeSuperkeys(superkeys: SuperkeysType[]): string {
if (
superkeys.length === 0 ||
(superkeys.length === 1 && superkeys[0].actions.length === 0) ||
(superkeys.length === 1 && superkeys[0].actions.length === 1 && superkeys[0].actions[0] === 0)
) {
return Array(512).fill("65535").join(" ");
}
let keyMap = JSON.parse(JSON.stringify(superkeys));
// log.info("First", JSON.stringify(keyMap));
keyMap = keyMap.map((sky: SuperkeysType) => {
const sk = sky;
sk.actions = sk.actions.map(act => {
if (act === 0 || act === null || act === undefined) return 1;
return act;
});
if (sk.actions.length < 5) sk.actions = sk.actions.concat(Array(5 - sk.actions.length).fill(1));
return sk;
});
// log.info("Third", JSON.parse(JSON.stringify(keyMap)));
const mapped = keyMap
.map((superkey: SuperkeysType) => superkey.actions.filter(act => act !== 0).concat([0]))
.flat()
.concat([0])
.join(" ")
.split(",")
.join(" ");
log.info("Mapped superkeys: ", mapped, keyMap);
return mapped;
};

return (
superkeys
.map((sky: SuperkeysType) => {
const sanitizedActions = sky.actions.map(action =>
action === 0 || action === undefined || action === null ? 1 : action,
);
while (sanitizedActions.length < 5) {
sanitizedActions.push(1);
}
sanitizedActions.push(0);
return sanitizedActions.join(" ");
})
.join(" ") + " 0"
);
}
8 changes: 8 additions & 0 deletions vite.config.mts
Original file line number Diff line number Diff line change
@@ -1,8 +1,16 @@
import { defineConfig } from "vitest/config";
import { resolve } from "path";

export default defineConfig({
plugins: [],
root: 'src',
resolve: {
alias: [
{ find: "@Renderer", replacement: resolve(__dirname, "./src/renderer") },
{ find: "@Assets", replacement: resolve(__dirname, "./src/static") },
{ find: "@Types", replacement: resolve(__dirname, "./src/renderer/types") },
]
},
test: {
coverage: {
exclude: ['**/*.{spec,test,unit,accept,integrate,system,perf,stress}.ts']
Expand Down

0 comments on commit 6325546

Please sign in to comment.