Skip to content

Commit

Permalink
test(cli): Unit test the core logic
Browse files Browse the repository at this point in the history
  • Loading branch information
akash1810 committed Dec 13, 2023
1 parent a60705e commit 40e1814
Show file tree
Hide file tree
Showing 6 changed files with 151 additions and 53 deletions.
32 changes: 32 additions & 0 deletions cli/deno.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

35 changes: 35 additions & 0 deletions cli/elk.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { assertEquals } from "https://deno.land/[email protected]/assert/mod.ts";
import { getLink } from "./elk.ts";

// NOTE: Each of these URLs should be opened in a browser to verify that they work as expected.

Deno.test("getLink with simple input", () => {
const got = getLink("devx", { app: "riff-raff", stage: "PROD" });
const want =
"https://logs.gutools.co.uk/s/devx/app/discover#/?_g=(filters:!((query:(match_phrase:(app:'riff-raff'))),(query:(match_phrase:(stage:'PROD')))))";
assertEquals(got, want);
});

Deno.test("getLink with columns", () => {
const got = getLink("devx", { app: "riff-raff", stage: "PROD" }, [
"message",
"level",
]);
const want =
"https://logs.gutools.co.uk/s/devx/app/discover#/?_g=(filters:!((query:(match_phrase:(app:'riff-raff'))),(query:(match_phrase:(stage:'PROD')))))&_a=(columns:!(message,level))";
assertEquals(got, want);
});

/*
Filters and columns with colon(:) input should get wrapped in single quotes(') so that Kibana can parse them correctly.
That is, gu:repo should become 'gu:repo'.
*/
Deno.test("getLink with colon(:) input", () => {
const got = getLink("devx", {
"gu:repo.keyword": "guardian/amigo",
stage: "PROD",
}, ["message", "gu:repo"]);
const want =
"https://logs.gutools.co.uk/s/devx/app/discover#/?_g=(filters:!((query:(match_phrase:('gu:repo.keyword':'guardian/amigo'))),(query:(match_phrase:(stage:'PROD')))))&_a=(columns:!(message,'gu:repo'))";
assertEquals(got, want);
});
31 changes: 31 additions & 0 deletions cli/elk.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
function escapeColon(str: string): string {
return str.includes(":") ? `'${str}'` : str;
}
export function getLink(
space: string,
filters: Record<string, string>,
columns: string[] = [],
): string {
const kibanaFilters = Object.entries(filters).map(([key, value]) => {
return `(query:(match_phrase:(${escapeColon(key)}:'${value}')))`;
});

// The `#/` at the end is important for Kibana to correctly parse the query string
// The `URL` object moves this to the end of the string, which breaks the link.
const base = `https://logs.gutools.co.uk/s/${space}/app/discover#/`;

const query = {
...(kibanaFilters.length > 0 && {
_g: `(filters:!(${kibanaFilters.join(",")}))`,
}),
...(columns.length > 0 && {
_a: `(columns:!(${columns.map(escapeColon).join(",")}))`,
}),
};

const queryString = Object.entries(query)
.map(([key, value]) => `${key}=${value}`)
.join("&");

return `${base}?${queryString}`;
}
56 changes: 3 additions & 53 deletions cli/index.ts
Original file line number Diff line number Diff line change
@@ -1,35 +1,8 @@
import type { Args } from "https://deno.land/[email protected]/flags/mod.ts";
import { parse } from "https://deno.land/[email protected]/flags/mod.ts";
import { open } from "https://deno.land/x/[email protected]/index.ts";

export function getLink(
space: string,
filters: Record<string, string>,
columns: string[],
): string {
const kibanaFilters = Object.entries(filters).map(([key, value]) => {
return `(query:(match_phrase:(${key}:'${value}')))`;
});

// The `#/` at the end is important for Kibana to correctly parse the query string
// The `URL` object moves this to the end of the string, which breaks the link.
const base = `https://logs.gutools.co.uk/s/${space}/app/discover#/`;

const query = {
...(kibanaFilters.length > 0 && {
_g: `(filters:!(${kibanaFilters.join(",")}))`,
}),
...(columns.length > 0 && {
_a: `(columns:!(${columns.join(",")}))`,
}),
};

const queryString = Object.entries(query)
.map(([key, value]) => `${key}=${value}`)
.join("&");

return `${base}?${queryString}`;
}
import { getLink } from "./elk.ts";
import { parseFilters, removeUndefined } from "./transform.ts";

function parseArguments(args: string[]): Args {
return parse(args, {
Expand All @@ -48,29 +21,6 @@ function parseArguments(args: string[]): Args {
});
}

function escapeColon(str: string): string {
return str.includes(":") ? `'${str}'` : str;
}

function parseFilters(filter: string[]): Record<string, string> {
return filter.reduce((acc, curr) => {
const [key, value] = curr.split("=");
return { ...acc, [escapeColon(key)]: value };
}, {});
}

function removeUndefined(
obj: Record<string, string | undefined>,
): Record<string, string> {
return Object.entries(obj).filter(([, value]) => !!value).reduce(
(acc, [key, value]) => ({
...acc,
[key]: value,
}),
{},
);
}

function printHelp(): void {
console.log(`Usage: devx-logs [OPTIONS...]`);
console.log("\nOptional flags:");
Expand Down Expand Up @@ -114,7 +64,7 @@ async function main(inputArgs: string[]) {
};

const filters = removeUndefined(mergedFilters);
const link = getLink(space, filters, column.map(escapeColon));
const link = getLink(space, filters, column);

console.log(link);

Expand Down
26 changes: 26 additions & 0 deletions cli/transform.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { assertEquals } from "https://deno.land/[email protected]/assert/assert_equals.ts";
import { parseFilters, removeUndefined } from "./transform.ts";

Deno.test("parseFilters", () => {
const got = parseFilters(["stack=deploy", "stage=PROD", "app=riff-raff"]);
const want = {
stack: "deploy",
stage: "PROD",
app: "riff-raff",
};
assertEquals(got, want);
});

Deno.test("removeUndefined", () => {
const got = removeUndefined({
stack: "deploy",
stage: undefined,
app: "riff-raff",
team: undefined,
});
const want = {
stack: "deploy",
app: "riff-raff",
};
assertEquals(got, want);
});
24 changes: 24 additions & 0 deletions cli/transform.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/**
* Turn an array of strings of form `key=value` into an object of form `{ key: value }`
*/
export function parseFilters(filter: string[]): Record<string, string> {
return filter.reduce((acc, curr) => {
const [key, value] = curr.split("=");
return { ...acc, [key]: value };
}, {});
}

/**
* Remove keys from a `Record` whose value is `undefined`
*/
export function removeUndefined(
obj: Record<string, string | undefined>,
): Record<string, string> {
return Object.entries(obj).filter(([, value]) => !!value).reduce(
(acc, [key, value]) => ({
...acc,
[key]: value,
}),
{},
);
}

0 comments on commit 40e1814

Please sign in to comment.