diff --git a/src/common/user-store_spec.ts b/src/common/user-store_spec.ts index 53901732c6..657dced485 100644 --- a/src/common/user-store_spec.ts +++ b/src/common/user-store_spec.ts @@ -13,7 +13,6 @@ describe("for an empty config", () => { } } mockFs(mockOpts) - const userStore = UserStore.getInstance() }) afterEach(() => { @@ -57,12 +56,10 @@ describe("migrations", () => { 'config.json': JSON.stringify({ user: { username: 'foobar' }, preferences: { colorTheme: 'light' }, - lastSeenAppVersion: '1.2.3' }) } } mockFs(mockOpts) - const userStore = UserStore.getInstance() }) afterEach(() => { diff --git a/src/main/context-handler.ts b/src/main/context-handler.ts index ad0bd85019..6dd8daa0f4 100644 --- a/src/main/context-handler.ts +++ b/src/main/context-handler.ts @@ -1,5 +1,4 @@ import { CoreV1Api, KubeConfig } from "@kubernetes/client-node" -import http from "http" import { ServerOptions } from "http-proxy" import * as url from "url" import logger from "./logger" diff --git a/src/main/kubectl.ts b/src/main/kubectl.ts index 73efc507b3..a4c21095d6 100644 --- a/src/main/kubectl.ts +++ b/src/main/kubectl.ts @@ -125,7 +125,7 @@ export class Kubectl { } try { - const { stdout, stderr } = await promiseExec(`"${this.path}" version --client=true -o json`) + const { stdout } = await promiseExec(`"${this.path}" version --client=true -o json`) const output = JSON.parse(stdout) let version: string = output.clientVersion.gitVersion if (version[0] === 'v') { diff --git a/src/renderer/utils/formatDuration.ts b/src/renderer/utils/formatDuration.ts index 48107d3c0b..84f90731b5 100644 --- a/src/renderer/utils/formatDuration.ts +++ b/src/renderer/utils/formatDuration.ts @@ -1,24 +1,35 @@ -// Formatting date duration in shorten format, e.g. "2d", or "25m" - import moment from "moment"; +const suffixes = ["w", "d", "h", "m", "s"]; + +/** + * This function formats durations in a more human readable form. + * @param timeValue the duration in milliseconds to format + * @param compact when true, only the largest non-zero time frame will be returned + */ export function formatDuration(timeValue: number, compact: boolean) { - let result = ""; - const duration = moment.duration(timeValue); - const suffixes = ["d", "h", "m"]; + const duration = moment.duration(timeValue, "milliseconds"); const durationValues = [ - Math.round(duration.asDays()), + Math.floor(duration.asWeeks()), + Math.floor(duration.asDays()) % 7, duration.hours(), duration.minutes(), + duration.seconds(), ]; - durationValues.forEach((value, index) => { - if (value) result += value + suffixes[index] + " "; - }); + + const meaningfulValues = durationValues + .map((a, i): [number, string] => [a, suffixes[i]]) + .filter(([dur, _suf]) => dur > 0) + .filter(([_dur, suf], i) => i === 0 || suf !== "s") // remove seconds, unless it is the only one + .map(([dur, suf]) => dur + suf); + + if (meaningfulValues.length === 0) { + return "0s"; + } + if (compact) { - result = result.split(" ")[0]; + return meaningfulValues[0]; } - if (!result) { - return "<1m"; - } - return result; -} \ No newline at end of file + + return meaningfulValues.join(" "); +} diff --git a/src/renderer/utils/formatDuration_spec.ts b/src/renderer/utils/formatDuration_spec.ts new file mode 100644 index 0000000000..53e2148286 --- /dev/null +++ b/src/renderer/utils/formatDuration_spec.ts @@ -0,0 +1,56 @@ +import { formatDuration } from "./formatDuration"; + +const second = 1000; +const minute = 60 * second; +const hour = 60 * minute; +const day = 24 * hour; +const week = 7 * day; + +describe("human format durations", () => { + test("long formatted durations less than 24 hours long shouldn't have a 'd' component", () => { + const res = formatDuration(19 * 60 * 60 * 1000, false); + + expect(res).not.toContain("d"); + expect(res).toBe("19h"); + }); + + test("long formatted durations more than a week have correct day count", () => { + const res = formatDuration(2 * week + 2 * day, false); + + expect(res).toBe("2w 2d"); + }); + + test("durations > 1/2 week shouldn't show 1w has passed", () => { + const res = formatDuration(5 * 24 * 60 * 60 * 1000, false); + + expect(res).not.toContain("w"); + expect(res).toBe("5d"); + }); + + test("durations shouldn't include zero magnitude parts", () => { + const res = formatDuration(6 * day + 2 * minute, false); + + expect(res).not.toContain("h"); + expect(res).toBe("6d 2m"); + }); + + test("seconds are ignored unless they are significant (< 1m)", () => { + const insignificant = formatDuration(1 * hour + 2 * minute + 31 * second, false); + + expect(insignificant).not.toContain("s"); + expect(insignificant).toBe("1h 2m"); + + const significant = formatDuration(31 * second, false); + expect(significant).toBe("31s"); + }); + + test("zero duration should output something", () => { + expect(formatDuration(0, false)).toBe("0s"); + expect(formatDuration(0, true)).toBe("0s"); + }); + + test("small duration should output something", () => { + expect(formatDuration(1, false)).toBe("0s"); + expect(formatDuration(3, true)).toBe("0s"); + }); +}); diff --git a/tsconfig.json b/tsconfig.json index 2a110d2c5a..890a428d85 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -6,7 +6,6 @@ "target": "ES2017", "module": "ESNext", "lib": ["ESNext", "DOM", "DOM.Iterable"], - "importsNotUsedAsValues": "preserve", "moduleResolution": "Node", "sourceMap": true, "strict": false, @@ -32,5 +31,12 @@ "compilerOptions": { "module": "CommonJS" } - } + }, + "exclude": [ + "node_modules", + "dist", + "coverage", + "dashboard", + "binaries" + ] }