-
Notifications
You must be signed in to change notification settings - Fork 190
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #566 from glimmerjs/migrate-compiler-errors
Migrate compile and syntax errors
- Loading branch information
Showing
4 changed files
with
175 additions
and
177 deletions.
There are no files selected for viewing
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
96 changes: 96 additions & 0 deletions
96
packages/@glimmer/runtime/test/invalid-html-errors-test.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,96 @@ | ||
import { RenderTests, test, module } from "@glimmer/test-helpers"; | ||
|
||
class CompileErrorTests extends RenderTests { | ||
@test "A helpful error message is provided for unclosed elements"() { | ||
this.assert.throws(() => { | ||
this.compile('\n<div class="my-div" \n foo={{bar}}>\n<span>\n</span>\n'); | ||
}, /Unclosed element `div` \(on line 2\)\./); | ||
|
||
this.assert.throws(() => { | ||
this.compile('\n<div class="my-div">\n<span>\n'); | ||
}, /Unclosed element `span` \(on line 3\)\./); | ||
} | ||
|
||
@test "A helpful error message is provided for unmatched end tags"() { | ||
this.assert.throws(() => { | ||
this.compile("</p>"); | ||
}, /Closing tag `p` \(on line 1\) without an open tag\./); | ||
|
||
this.assert.throws(() => { | ||
this.compile("<em>{{ foo }}</em> \n {{ bar }}\n</div>"); | ||
}, /Closing tag `div` \(on line 3\) without an open tag\./); | ||
} | ||
|
||
@test "A helpful error message is provided for end tags for void elements"() { | ||
this.assert.throws(() => { | ||
this.compile("<input></input>"); | ||
}, /Invalid end tag `input` \(on line 1\) \(void elements cannot have end tags\)./); | ||
|
||
this.assert.throws(() => { | ||
this.compile("<div>\n <input></input>\n</div>"); | ||
}, /Invalid end tag `input` \(on line 2\) \(void elements cannot have end tags\)./); | ||
|
||
this.assert.throws(() => { | ||
this.compile("\n\n</br>"); | ||
}, /Invalid end tag `br` \(on line 3\) \(void elements cannot have end tags\)./); | ||
} | ||
|
||
@test "A helpful error message is provided for end tags with attributes"() { | ||
this.assert.throws(() => { | ||
this.compile('<div>\nSomething\n\n</div foo="bar">'); | ||
}, /Invalid end tag: closing tag must not have attributes, in `div` \(on line 4\)\./); | ||
} | ||
|
||
@test "A helpful error message is provided for mismatched start/end tags"() { | ||
this.assert.throws(() => { | ||
this.compile("<div>\n<p>\nSomething\n\n</div>"); | ||
}, /Closing tag `div` \(on line 5\) did not match last open tag `p` \(on line 2\)\./); | ||
} | ||
|
||
@test "error line numbers include comment lines"() { | ||
this.assert.throws(() => { | ||
this.compile("<div>\n<p>\n{{! some comment}}\n\n</div>"); | ||
}, /Closing tag `div` \(on line 5\) did not match last open tag `p` \(on line 2\)\./); | ||
} | ||
|
||
@test "error line numbers include mustache only lines"() { | ||
this.assert.throws(() => { | ||
this.compile("<div>\n<p>\n{{someProp}}\n\n</div>"); | ||
}, /Closing tag `div` \(on line 5\) did not match last open tag `p` \(on line 2\)\./); | ||
} | ||
|
||
@test "error line numbers include block lines"() { | ||
this.assert.throws(() => { | ||
this.compile("<div>\n<p>\n{{#some-comment}}\n{{/some-comment}}\n</div>"); | ||
}, /Closing tag `div` \(on line 5\) did not match last open tag `p` \(on line 2\)\./); | ||
} | ||
|
||
@test "error line numbers include whitespace control mustaches"() { | ||
this.assert.throws(() => { | ||
this.compile("<div>\n<p>\n{{someProp~}}\n\n</div>{{some-comment}}"); | ||
}, /Closing tag `div` \(on line 5\) did not match last open tag `p` \(on line 2\)\./); | ||
} | ||
|
||
@test "error line numbers include multiple mustache lines"() { | ||
this.assert.throws(() => { | ||
this.compile("<div>\n<p>\n{{some-comment}}</div>{{some-comment}}"); | ||
}, /Closing tag `div` \(on line 3\) did not match last open tag `p` \(on line 2\)\./); | ||
} | ||
|
||
@test "Unquoted attribute with expression throws an exception"() { | ||
this.assert.throws(() => this.compile('<img class=foo{{bar}}>'), expectedError(1)); | ||
this.assert.throws(() => this.compile('<img class={{foo}}{{bar}}>'), expectedError(1)); | ||
this.assert.throws(() => this.compile('<img \nclass={{foo}}bar>'), expectedError(2)); | ||
this.assert.throws(() => this.compile('<div \nclass\n=\n{{foo}}&bar ></div>'), expectedError(4)); | ||
|
||
function expectedError(line: number) { | ||
return new Error( | ||
`An unquoted attribute value must be a string or a mustache, ` + | ||
`preceeded by whitespace or a '=' character, and ` + | ||
`followed by whitespace, a '>' character, or '/>' (on line ${line})` | ||
); | ||
} | ||
} | ||
} | ||
|
||
module("Rendering Error Cases", CompileErrorTests); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
import { RenderTests, module, test } from "@glimmer/test-helpers"; | ||
|
||
class SyntaxErrors extends RenderTests { | ||
@test "context switching using ../ is not allowed"() { | ||
this.assert.throws(() => { | ||
this.compile('<div><p>{{../value}}</p></div>'); | ||
}, new Error("Changing context using \"../\" is not supported in Glimmer: \"../value\" on line 1.")); | ||
} | ||
|
||
@test "mixing . and / is not allowed"() { | ||
this.assert.throws(() => { | ||
this.compile('<div><p>{{a/b.c}}</p></div>'); | ||
}, new Error("Mixing '.' and '/' in paths is not supported in Glimmer; use only '.' to separate property paths: \"a/b.c\" on line 1.")); | ||
} | ||
|
||
@test "explicit self ref with ./ is not allowed"() { | ||
this.assert.throws(() => { | ||
this.compile('<div><p>{{./value}}</p></div>'); | ||
}, new Error("Using \"./\" is not supported in Glimmer and unnecessary: \"./value\" on line 1.")); | ||
} | ||
|
||
@test "helper invocation with dot-paths are not allowed"() { | ||
this.assert.throws(() => { | ||
this.compile('{{foo.bar some="args"}}'); | ||
}, new Error("`foo.bar` is not a valid name for a helper on line 1.")); | ||
} | ||
|
||
@test "sub-expression helper invocation with dot-paths are not allowed"() { | ||
this.assert.throws(() => { | ||
this.compile('{{log (foo.bar some="args")}}'); | ||
}, new Error("`foo.bar` is not a valid name for a helper on line 1.")); | ||
} | ||
|
||
@test "sub-expression modifier invocation with dot-paths are not allowed"() { | ||
this.assert.throws(() => { | ||
this.compile('<div {{foo.bar some="args"}} />'); | ||
}, new Error("`foo.bar` is not a valid name for a modifier on line 1.")); | ||
} | ||
|
||
@test "Block params in HTML syntax - Throws exception if given zero parameters"() { | ||
this.assert.throws(() => { | ||
this.compile('<x-bar as ||>foo</x-bar>'); | ||
}, /Cannot use zero block parameters: 'as \|\|'/); | ||
|
||
this.assert.throws(() => { | ||
this.compile('<x-bar as | |>foo</x-bar>'); | ||
}, /Cannot use zero block parameters: 'as \| \|'/); | ||
} | ||
|
||
@test "Block params in HTML syntax - Throws an error on invalid block params syntax"() { | ||
this.assert.throws(() => { | ||
this.compile('<x-bar as |x y>{{x}},{{y}}</x-bar>'); | ||
}, /Invalid block parameters syntax: 'as |x y'/); | ||
|
||
this.assert.throws(() => { | ||
this.compile('<x-bar as |x| y>{{x}},{{y}}</x-bar>'); | ||
}, /Invalid block parameters syntax: 'as \|x\| y'/); | ||
|
||
this.assert.throws(() => { | ||
this.compile('<x-bar as |x| y|>{{x}},{{y}}</x-bar>'); | ||
}, /Invalid block parameters syntax: 'as \|x\| y\|'/); | ||
} | ||
|
||
@test "Block params in HTML syntax - Throws an error on invalid identifiers for params"() { | ||
this.assert.throws(() => { | ||
this.compile('<x-bar as |x foo.bar|></x-bar>'); | ||
}, /Invalid identifier for block parameters: 'foo\.bar' in 'as \|x foo\.bar|'/); | ||
|
||
this.assert.throws(() => { | ||
this.compile('<x-bar as |x "foo"|></x-bar>'); | ||
}, /Syntax error at line 1 col 17: " is not a valid character within attribute names/); | ||
|
||
this.assert.throws(() => { | ||
this.compile('<x-bar as |foo[bar]|></x-bar>'); | ||
}, /Invalid identifier for block parameters: 'foo\[bar\]' in 'as \|foo\[bar\]\|'/); | ||
} | ||
} | ||
|
||
module('Syntax Errors', SyntaxErrors); |