Skip to content

Commit

Permalink
Merge pull request #1 from larshisken/feat-improve-errors
Browse files Browse the repository at this point in the history
feat: improve parse errors
  • Loading branch information
larshisken authored Apr 29, 2021
2 parents 4c9c8e3 + d4832a3 commit 331cf82
Show file tree
Hide file tree
Showing 6 changed files with 95 additions and 32 deletions.
15 changes: 15 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
.PHONY: clean

unit_test_files := $(shell find test/unit/ -name '*.ts')

coverage: $(unit_test_files)
deno test --coverage=coverage --unstable test/unit

coverage.lcov: coverage
deno coverage --unstable test/unit coverage --lcov > coverage.lcov

coverage/html: coverage.lcov
genhtml --output-directory=coverage/html coverage.lcov

clean:
rm --recursive --force coverage coverage.lcov
5 changes: 5 additions & 0 deletions deps.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export {
assert,
assertEquals,
assertThrows
} from "https://deno.land/[email protected]/testing/asserts.ts";
30 changes: 22 additions & 8 deletions mod.ts
Original file line number Diff line number Diff line change
Expand Up @@ -175,10 +175,14 @@ function parse(template: string): Expression[] {
if (length === index + 1 /* last char */) {
if (
char === "{" ||
cursor.over === ExpressionType.Variable && char !== "}"
(cursor.over === ExpressionType.Variable && char !== "}")
) {
throw new Error("ParseError");
throw new Error(
`Unexpected char '${char}' at position ${index +
1} in '${template}', expected a closing brace.`,
);
}

if (cursor.over === ExpressionType.Literal) {
expressions.push({
type: ExpressionType.Literal,
Expand All @@ -188,11 +192,18 @@ function parse(template: string): Expression[] {
}
}

if (
cursor.over === ExpressionType.Literal && char === "}" ||
cursor.over === ExpressionType.Variable && char === "{"
) {
throw new Error("ParseError");
if (cursor.over === ExpressionType.Variable && char === "{") {
throw new Error(
`Unexpected char '{' at position ${index +
1} in '${template}', expected a closing brace.`,
);
}

if (cursor.over === ExpressionType.Literal && char === "}") {
throw new Error(
`Unexpected char '}' at position ${index +
1} in '${template}', expected an opening brace before a closing brace.`,
);
}

if (cursor.over === ExpressionType.Literal && char === "{") {
Expand All @@ -215,7 +226,10 @@ function parse(template: string): Expression[] {
if (cursor.over === ExpressionType.Variable && char === "}") {
if (index === cursor.pos + 1) {
// braces are empty
throw new Error("ParseError");
throw new Error(
`Unexpected char '${template[index]}' at position ${index +
1} in '${template}', expected a pair of braces to have content.`,
);
}

const from = cursor.pos + 1;
Expand Down
16 changes: 7 additions & 9 deletions test/integration/spec.test.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,6 @@
import {
assert,
assertEquals,
} from "https://deno.land/[email protected]/testing/asserts.ts";

import { doTest, Example } from "./helper.ts";
import { assert, assertEquals } from "../../deps.ts";
import { expand } from "../../mod.ts";
import { doTest, Example } from "./helper.ts";

const [x, y] = await Promise.all([
Deno.readTextFile("./uritemplate-test/spec-examples.json"),
Expand All @@ -19,7 +15,9 @@ const examples: Record<string, Example> = {
doTest(
examples,
({ testcase: [x, y], variables }) =>
typeof y === "string"
? assertEquals(expand(x, variables), y)
: assert(y.includes(expand(x, variables))),
typeof y === "string" ? assertEquals(expand(x, variables), y) : assert(
y.includes(
expand(x, variables),
),
),
);
58 changes: 45 additions & 13 deletions test/unit/parse.test.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,5 @@
import {
assertEquals,
assertThrows,
} from "https://deno.land/[email protected]/testing/asserts.ts";

import { Expression, ExpressionType, parse } from "../../mod.ts";
import { assertEquals, assertThrows } from "../../deps.ts";

Deno.test("Should parse '{foo}' to a list of expressions", () => {
const expected: Expression[] = [
Expand Down Expand Up @@ -79,21 +75,57 @@ Deno.test("Should parse 'foo/{bar}/baz' to a list of expressions", () => {
});

Deno.test("Should throw when a closing brace is found without an opening brace", () => {
assertThrows(() => parse("}"), Error, "ParseError");
assertThrows(() => parse("foo}bar"), Error, "ParseError");
assertThrows(
() => parse("}"),
Error,
"Unexpected char '}' at position 1 in '}', expected an opening brace before a closing brace.",
);

assertThrows(
() => parse("foo}bar"),
Error,
"Unexpected char '}' at position 4 in 'foo}bar', expected an opening brace before a closing brace.",
);
});

Deno.test("Should throw when an opening brace is found at the end", () => {
assertThrows(() => parse("{"), Error, "ParseError");
assertThrows(() => parse("foo{"), Error, "ParseError");
assertThrows(
() => parse("{"),
Error,
"Unexpected char '{' at position 1 in '{', expected a closing brace.",
);

assertThrows(
() => parse("foo{"),
Error,
"Unexpected char '{' at position 4 in 'foo{', expected a closing brace.",
);
});

Deno.test("Should throw when an opening brace is not closed", () => {
assertThrows(() => parse("foo{bar"), Error, "ParseError");
assertThrows(() => parse("foo{bar{baz}"), Error, "ParseError");
assertThrows(
() => parse("foo{bar"),
Error,
"Unexpected char 'r' at position 7 in 'foo{bar', expected a closing brace.",
);

assertThrows(
() => parse("foo{bar{baz}"),
Error,
"Unexpected char '{' at position 8 in 'foo{bar{baz}', expected a closing brace.",
);
});

Deno.test("Should throw when empty braces are found", () => {
assertThrows(() => parse("{}"), Error, "ParseError");
assertThrows(() => parse("foo/{}"), Error, "ParseError");
assertThrows(
() => parse("{}"),
Error,
"Unexpected char '}' at position 2 in '{}', expected a pair of braces to have content.",
);

assertThrows(
() => parse("foo/{}"),
Error,
"Unexpected char '}' at position 6 in 'foo/{}', expected a pair of braces to have content.",
);
});
3 changes: 1 addition & 2 deletions test/unit/pct.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { assertEquals } from "https://deno.land/[email protected]/testing/asserts.ts";

import { assertEquals } from "../../deps.ts";
import { pctEncode, pctEncodeChar } from "../../pct.ts";

Deno.test("Should encode individual characters", () => {
Expand Down

0 comments on commit 331cf82

Please sign in to comment.