Skip to content

Commit

Permalink
test(path): improve test coverage (#5038)
Browse files Browse the repository at this point in the history
  • Loading branch information
mbhrznr committed Jun 13, 2024
1 parent 0ad578f commit 22b4d03
Show file tree
Hide file tree
Showing 6 changed files with 185 additions and 16 deletions.
17 changes: 17 additions & 0 deletions path/_common/assert_path_test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.

import { assertEquals, assertThrows } from "@std/assert";
import { assertPath } from "./assert_path.ts";

Deno.test("assertPath()", () => {
assertEquals(assertPath(""), undefined);
assertEquals(assertPath("foo"), undefined);
});

Deno.test("assertPath() throws", () => {
assertThrows(
() => assertPath(undefined),
TypeError,
"Path must be a string. Received undefined",
);
});
49 changes: 49 additions & 0 deletions path/_common/basename_test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.

import { assertEquals, assertThrows } from "@std/assert";
import { assertArgs, lastPathSegment, stripSuffix } from "./basename.ts";
import { CHAR_FORWARD_SLASH } from "./constants.ts";

Deno.test("assertArgs()", () => {
assertEquals(assertArgs("", ""), "");
assertEquals(assertArgs("foo", "bar"), undefined);
// @ts-expect-error - testing invalid input for suffix
assertEquals(assertArgs("", undefined), "");
});

Deno.test("assertArgs() throws", () => {
assertThrows(
// @ts-expect-error - testing invalid input
() => assertArgs(undefined, "bar"),
TypeError,
"Path must be a string. Received undefined",
);
assertThrows(
// @ts-expect-error - testing invalid input
() => assertArgs("foo", undefined),
TypeError,
"Suffix must be a string. Received undefined",
);
});

Deno.test("lastPathSegment()", () => {
assertEquals(
lastPathSegment("foo", (char) => char === CHAR_FORWARD_SLASH),
"foo",
);
assertEquals(
lastPathSegment("foo/bar", (char) => char === CHAR_FORWARD_SLASH),
"bar",
);
assertEquals(
lastPathSegment("foo/bar/baz", (char) => char === CHAR_FORWARD_SLASH),
"baz",
);
});

Deno.test("stripSuffix()", () => {
assertEquals(stripSuffix("foo", "bar"), "foo");
assertEquals(stripSuffix("foobar", "bar"), "foo");
assertEquals(stripSuffix("foobar", "baz"), "foobar");
assertEquals(stripSuffix("foobar", "foobar"), "foobar");
});
54 changes: 54 additions & 0 deletions path/_common/format_test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.

import { assertEquals, assertThrows } from "@std/assert";
import { _format, assertArg } from "./format.ts";

Deno.test("_format()", () => {
assertEquals(_format("", {}), "");
assertEquals(_format("", { root: "/" }), "/");
assertEquals(_format("", { dir: "/foo/bar" }), "/foo/bar");
assertEquals(_format("", { base: "baz" }), "baz");
assertEquals(_format("", { name: "baz" }), "baz");
assertEquals(_format("", { ext: ".js" }), ".js");
assertEquals(_format("", { name: "baz", ext: ".js" }), "baz.js");
assertEquals(_format("", { root: "/", base: "baz" }), "/baz");
assertEquals(_format("", { root: "/", name: "baz" }), "/baz");
assertEquals(_format("", { root: "/", ext: ".js" }), "/.js");
assertEquals(_format("", { root: "/", name: "baz", ext: ".js" }), "/baz.js");
assertEquals(_format("/", { dir: "/foo/bar", base: "baz" }), "/foo/bar/baz");
assertEquals(
_format("/", { dir: "/foo/bar", base: "baz", ext: ".js" }),
"/foo/bar/baz",
);
assertEquals(
_format("/", { dir: "/foo/bar", name: "baz", ext: ".js" }),
"/foo/bar/baz.js",
);
});

Deno.test("assertArg()", () => {
assertEquals(assertArg({}), undefined);
assertEquals(assertArg({ root: "/" }), undefined);
assertEquals(assertArg({ dir: "/foo/bar" }), undefined);
});

Deno.test("assertArg() throws", () => {
assertThrows(
// @ts-expect-error - testing invalid input
() => assertArg(null),
TypeError,
`The "pathObject" argument must be of type Object. Received type object`,
);
assertThrows(
// @ts-expect-error - testing invalid input
() => assertArg(undefined),
TypeError,
`The "pathObject" argument must be of type Object. Received type undefined`,
);
assertThrows(
// @ts-expect-error - testing invalid input
() => assertArg(""),
TypeError,
`The "pathObject" argument must be of type Object. Received type string`,
);
});
34 changes: 18 additions & 16 deletions path/_common/glob_to_reg_exp.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ export interface GlobOptions {
/** Options for {@linkcode globToRegExp}. */
export type GlobToRegExpOptions = GlobOptions;

const regExpEscapeChars = [
const REG_EXP_ESCAPE_CHARS = [
"!",
"$",
"(",
Expand All @@ -42,8 +42,12 @@ const regExpEscapeChars = [
"^",
"{",
"|",
];
const rangeEscapeChars = ["-", "\\", "]"];
] as const;
const RANGE_ESCAPE_CHARS = ["-", "\\", "]"] as const;

type RegExpEscapeChar = typeof REG_EXP_ESCAPE_CHARS[number];
type RangeEscapeChar = typeof RANGE_ESCAPE_CHARS[number];
type EscapeChar = RegExpEscapeChar | RangeEscapeChar;

export interface GlobConstants {
sep: string;
Expand Down Expand Up @@ -88,8 +92,12 @@ export function _globToRegExp(
for (; i < glob.length && !c.seps.includes(glob[i]!); i++) {
if (inEscape) {
inEscape = false;
const escapeChars = inRange ? rangeEscapeChars : regExpEscapeChars;
segment += escapeChars.includes(glob[i]!) ? `\\${glob[i]}` : glob[i];
const escapeChars = (inRange
? RANGE_ESCAPE_CHARS
: REG_EXP_ESCAPE_CHARS) as unknown as EscapeChar[];
segment += escapeChars.includes(glob[i]! as EscapeChar)
? `\\${glob[i]}`
: glob[i];
continue;
}

Expand Down Expand Up @@ -146,11 +154,7 @@ export function _globToRegExp(
}

if (inRange) {
if (glob[i] === "\\") {
segment += `\\\\`;
} else {
segment += glob[i];
}
segment += glob[i];
continue;
}

Expand Down Expand Up @@ -252,7 +256,7 @@ export function _globToRegExp(
continue;
}

segment += regExpEscapeChars.includes(glob[i]!)
segment += REG_EXP_ESCAPE_CHARS.includes(glob[i]! as RegExpEscapeChar)
? `\\${glob[i]}`
: glob[i];
}
Expand All @@ -262,7 +266,9 @@ export function _globToRegExp(
// Parse failure. Take all characters from this segment literally.
segment = "";
for (const c of glob.slice(j, i)) {
segment += regExpEscapeChars.includes(c) ? `\\${c}` : c;
segment += REG_EXP_ESCAPE_CHARS.includes(c as RegExpEscapeChar)
? `\\${c}`
: c;
endsWithSep = false;
}
}
Expand All @@ -276,10 +282,6 @@ export function _globToRegExp(
// Terminates with `i` at the start of the next segment.
while (c.seps.includes(glob[i]!)) i++;

// Check that the next value of `j` is indeed higher than the current value.
if (!(i > j)) {
throw new Error("Assertion failure: i > j (potential infinite loop)");
}
j = i;
}

Expand Down
26 changes: 26 additions & 0 deletions path/_common/normalize_string_test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.

import { assertEquals } from "@std/assert";
import { CHAR_FORWARD_SLASH } from "./constants.ts";
import { normalizeString } from "./normalize_string.ts";

function isSeparator(code: number): boolean {
return code === CHAR_FORWARD_SLASH;
}

Deno.test("normalizeSring()", () => {
assertEquals(normalizeString("", true, "/", isSeparator), "");
assertEquals(normalizeString("", false, "/", isSeparator), "");
assertEquals(normalizeString("a/../b", true, "/", isSeparator), "b");
assertEquals(normalizeString("foo/bar/", true, "/", isSeparator), "foo/bar");
assertEquals(normalizeString("/foo/bar", true, "/", isSeparator), "foo/bar");
assertEquals(normalizeString("./foo/bar", true, "/", isSeparator), "foo/bar");
assertEquals(
normalizeString("../foo/bar/baz/", true, "/", isSeparator),
"../foo/bar/baz",
);
assertEquals(
normalizeString("/foo/../../bar", true, "/", isSeparator),
"../bar",
);
});
21 changes: 21 additions & 0 deletions path/_common/to_file_url_test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.

import { assertEquals } from "@std/assert";
import { encodeWhitespace } from "./to_file_url.ts";

Deno.test("encodeWhitespace()", () => {
assertEquals(encodeWhitespace("foo"), "foo");
assertEquals(encodeWhitespace("foo\tbar"), "foo%09bar");
assertEquals(encodeWhitespace("foo\nbar"), "foo%0Abar");
assertEquals(encodeWhitespace("foo\vbar"), "foo%0Bbar");
assertEquals(encodeWhitespace("foo\fbar"), "foo%0Cbar");
assertEquals(encodeWhitespace("foo\rbar"), "foo%0Dbar");
assertEquals(encodeWhitespace("foo bar"), "foo%20bar");
assertEquals(encodeWhitespace("foo\u0009bar"), "foo%09bar");
assertEquals(encodeWhitespace("foo\u000Abar"), "foo%0Abar");
assertEquals(encodeWhitespace("foo\u000Bbar"), "foo%0Bbar");
assertEquals(encodeWhitespace("foo\u000Cbar"), "foo%0Cbar");
assertEquals(encodeWhitespace("foo\u000Dbar"), "foo%0Dbar");
assertEquals(encodeWhitespace("foo\u0020bar"), "foo%20bar");
assertEquals(encodeWhitespace("foo\ufeffbar"), "foobar");
});

0 comments on commit 22b4d03

Please sign in to comment.