diff options
author | Stefan Kangas <stefan@marxist.se> | 2020-10-18 02:28:22 +0200 |
---|---|---|
committer | Stefan Kangas <stefan@marxist.se> | 2020-10-18 02:28:22 +0200 |
commit | 335e3cf89f28b38ac0f5c9396ad6a49ca0261180 (patch) | |
tree | 5a059e889c327a7ac74cbc5743d746f1746df375 /test/lisp/progmodes | |
parent | f287fb45f574604f4e5cce1031cc6b73ddcccc3d (diff) | |
download | emacs-335e3cf89f28b38ac0f5c9396ad6a49ca0261180.tar.gz emacs-335e3cf89f28b38ac0f5c9396ad6a49ca0261180.tar.bz2 emacs-335e3cf89f28b38ac0f5c9396ad6a49ca0261180.zip |
Convert manual js indent tests to unit tests
* test/lisp/progmodes/js-tests.el (ert-x): Require.
(js-deftest-indent): New macro. Use it to define tests for indenting
the below files.
* test/manual/indent/js-chain.js:
* test/manual/indent/js-indent-align-list-continuation-nil.js:
* test/manual/indent/js-indent-init-dynamic.js:
* test/manual/indent/js-indent-init-t.js:
* test/manual/indent/js.js:
* test/manual/indent/jsx-align-gt-with-lt.jsx:
* test/manual/indent/jsx-comment-string.jsx:
* test/manual/indent/jsx-indent-level.jsx:
* test/manual/indent/jsx-quote.jsx:
* test/manual/indent/jsx-self-closing.jsx:
* test/manual/indent/jsx-unclosed-1.jsx:
* test/manual/indent/jsx-unclosed-2.jsx:
* test/manual/indent/jsx.jsx: Move from here...
* test/lisp/progmodes/js-resources/js-chain.js:
* test/lisp/progmodes/js-resources/js-indent-align-list-continuation-nil.js:
* test/lisp/progmodes/js-resources/js-indent-init-dynamic.js:
* test/lisp/progmodes/js-resources/js-indent-init-t.js:
* test/lisp/progmodes/js-resources/js.js:
* test/lisp/progmodes/js-resources/jsx-align-gt-with-lt.jsx:
* test/lisp/progmodes/js-resources/jsx-comment-string.jsx:
* test/lisp/progmodes/js-resources/jsx-indent-level.jsx:
* test/lisp/progmodes/js-resources/jsx-quote.jsx:
* test/lisp/progmodes/js-resources/jsx-self-closing.jsx:
* test/lisp/progmodes/js-resources/jsx-unclosed-1.jsx:
* test/lisp/progmodes/js-resources/jsx-unclosed-2.jsx:
* test/lisp/progmodes/js-resources/jsx.jsx: ...to here.
Diffstat (limited to 'test/lisp/progmodes')
-rw-r--r-- | test/lisp/progmodes/js-resources/js-chain.js | 29 | ||||
-rw-r--r-- | test/lisp/progmodes/js-resources/js-indent-align-list-continuation-nil.js | 20 | ||||
-rw-r--r-- | test/lisp/progmodes/js-resources/js-indent-init-dynamic.js | 30 | ||||
-rw-r--r-- | test/lisp/progmodes/js-resources/js-indent-init-t.js | 21 | ||||
-rw-r--r-- | test/lisp/progmodes/js-resources/js.js | 171 | ||||
-rw-r--r-- | test/lisp/progmodes/js-resources/jsx-align-gt-with-lt.jsx | 12 | ||||
-rw-r--r-- | test/lisp/progmodes/js-resources/jsx-comment-string.jsx | 23 | ||||
-rw-r--r-- | test/lisp/progmodes/js-resources/jsx-indent-level.jsx | 13 | ||||
-rw-r--r-- | test/lisp/progmodes/js-resources/jsx-quote.jsx | 16 | ||||
-rw-r--r-- | test/lisp/progmodes/js-resources/jsx-self-closing.jsx | 13 | ||||
-rw-r--r-- | test/lisp/progmodes/js-resources/jsx-unclosed-1.jsx | 13 | ||||
-rw-r--r-- | test/lisp/progmodes/js-resources/jsx-unclosed-2.jsx | 65 | ||||
-rw-r--r-- | test/lisp/progmodes/js-resources/jsx.jsx | 314 | ||||
-rw-r--r-- | test/lisp/progmodes/js-tests.el | 28 |
14 files changed, 768 insertions, 0 deletions
diff --git a/test/lisp/progmodes/js-resources/js-chain.js b/test/lisp/progmodes/js-resources/js-chain.js new file mode 100644 index 00000000000..2a290294026 --- /dev/null +++ b/test/lisp/progmodes/js-resources/js-chain.js @@ -0,0 +1,29 @@ +// Normal chaining. +let x = svg.mumble() + .zzz; + +// Chaining with an intervening line comment. +let x = svg.mumble() // line comment + .zzz; + +// Chaining with multiple dots. +let x = svg.selectAll().something() + .zzz; + +// Nested chaining. +let x = svg.selectAll(d3.svg.something() + .zzz); + +// Nothing to chain to. +let x = svg() + .zzz; + +// Nothing to chain to. +let x = svg().mumble.x() + 73 + .zzz; + +// Local Variables: +// indent-tabs-mode: nil +// js-chain-indent: t +// js-indent-level: 2 +// End: diff --git a/test/lisp/progmodes/js-resources/js-indent-align-list-continuation-nil.js b/test/lisp/progmodes/js-resources/js-indent-align-list-continuation-nil.js new file mode 100644 index 00000000000..383b2539a26 --- /dev/null +++ b/test/lisp/progmodes/js-resources/js-indent-align-list-continuation-nil.js @@ -0,0 +1,20 @@ +const funcAssignment = function (arg1, + arg2, + arg3) { + return { test: this, + which: "would", + align: "as well with the default setting" + }; +} + +function funcDeclaration(arg1, + arg2 +) { + return [arg1, + arg2]; +} + +// Local Variables: +// indent-tabs-mode: nil +// js-indent-align-list-continuation: nil +// End: diff --git a/test/lisp/progmodes/js-resources/js-indent-init-dynamic.js b/test/lisp/progmodes/js-resources/js-indent-init-dynamic.js new file mode 100644 index 00000000000..536a976e86e --- /dev/null +++ b/test/lisp/progmodes/js-resources/js-indent-init-dynamic.js @@ -0,0 +1,30 @@ +var foo = function() { + return 7; +}; + +var foo = function() { + return 7; + }, + bar = 8; + +var foo = function() { + return 7; + }, + bar = function() { + return 8; + }; + +// Local Variables: +// indent-tabs-mode: nil +// js-indent-level: 2 +// js-indent-first-init: dynamic +// End: + +// The following test intentionally produces a scan error and should +// be placed below all other tests to prevent awkward indentation. +// (It still thinks it's within the body of a function.) + +var foo = function() { + return 7; + , + bar = 8; diff --git a/test/lisp/progmodes/js-resources/js-indent-init-t.js b/test/lisp/progmodes/js-resources/js-indent-init-t.js new file mode 100644 index 00000000000..bb755420ba7 --- /dev/null +++ b/test/lisp/progmodes/js-resources/js-indent-init-t.js @@ -0,0 +1,21 @@ +var foo = function() { + return 7; + }; + +var foo = function() { + return 7; + }, + bar = 8; + +var foo = function() { + return 7; + }, + bar = function() { + return 8; + }; + +// Local Variables: +// indent-tabs-mode: nil +// js-indent-level: 2 +// js-indent-first-init: t +// End: diff --git a/test/lisp/progmodes/js-resources/js.js b/test/lisp/progmodes/js-resources/js.js new file mode 100644 index 00000000000..9658c95701c --- /dev/null +++ b/test/lisp/progmodes/js-resources/js.js @@ -0,0 +1,171 @@ +var a = 1; +b = 2; + +let c = 1, + d = 2; + +var e = 100500, + + 1; + +// Don't misinterpret "const" +/const/ + +function test () +{ + return /[/]/.test ('/') // (bug#19397) +} + +var f = bar('/protocols/') +baz(); + +var h = 100500 +1; + +const i = 1, + j = 2; + +var k = 1, + l = [ + 1, 2, + 3, 4 + ], + m = 5; + +var n = function() { + return 7; +}, + o = 8; + +foo(bar, function() { + return 2; +}); + +switch (b) { +case "a": + 2; +default: + 3; +} + +var p = { + case: 'zzzz', + default: 'donkey', + tee: 'ornery' +}; + +var evens = [e for each (e in range(0, 21)) + if (ed % 2 == 0)]; + +var funs = [ + function() { + for (;;) { + } + }, + function(){}, +]; + +!b + !=b + !==b + +a++ +b += + c + +var re = /some value/ +str.match(re) + +baz(`http://foo.bar/${tee}`) + .qux(); + +`multiline string + contents + are kept + unchanged!` + +class A { + * x() { + return 1 + * a(2); + } + + *[Symbol.iterator]() { + yield "Foo"; + yield "Bar"; + } +} + +if (true) + 1 +else + 2 + +Foobar + .find() + .catch((err) => { + return 2; + }) + .then((num) => { + console.log(num); + }); + +var z = [ + ...iterableObj, + 4, + 5 +] + +var arr = [ + -1, 2, + -3, 4 + + -5 +]; + +// Regression test for bug#15582. +if (x > 72 && + y < 85) { // found + do_something(); +} + +// Test that chaining doesn't happen when js-chain-indent is nil. +let x = svg.mumble() + .zzz; + +// https://github.com/mooz/js2-mode/issues/405 +if (1) { + isSet + ? (isEmpty ? 2 : 3) + : 4 +} + +// Regexp is not a continuation +bar( + "string arg1", + /abc/ +) + +// No infloop inside js--re-search-backward-inner +let b = { + a : ` + //1 + ` +} + +// bug#25904 +foo.bar.baz(very => // A comment + very +).biz(([baz={a: [123]}, boz]) => + baz +).snarf((snorf) => /* Another comment */ + snorf +); + +// Continuation of bug#25904; support broken arrow as N+1th arg +map(arr, (val) => + val +) + +// Local Variables: +// indent-tabs-mode: nil +// js-indent-level: 2 +// End: diff --git a/test/lisp/progmodes/js-resources/jsx-align-gt-with-lt.jsx b/test/lisp/progmodes/js-resources/jsx-align-gt-with-lt.jsx new file mode 100644 index 00000000000..8eb1d6d718c --- /dev/null +++ b/test/lisp/progmodes/js-resources/jsx-align-gt-with-lt.jsx @@ -0,0 +1,12 @@ +<element + attr="" + > +</element> +<input + /> + +// Local Variables: +// indent-tabs-mode: nil +// js-indent-level: 2 +// js-jsx-align->-with-<: nil +// End: diff --git a/test/lisp/progmodes/js-resources/jsx-comment-string.jsx b/test/lisp/progmodes/js-resources/jsx-comment-string.jsx new file mode 100644 index 00000000000..cae023e7288 --- /dev/null +++ b/test/lisp/progmodes/js-resources/jsx-comment-string.jsx @@ -0,0 +1,23 @@ +// Local Variables: +// indent-tabs-mode: nil +// js-indent-level: 2 +// End: + +// The following tests go below any comments to avoid including +// misindented comments among the erroring lines. + +// The JSX-like text in comments/strings should be treated like the enclosing +// syntax, not like JSX. + +// <Foo> +void 0 + +"<Bar>" +void 0 + +<Chicken> + {/* <Pork> */} + <Beef attr="<Turkey>"> + Yum! + </Beef> +</Chicken> diff --git a/test/lisp/progmodes/js-resources/jsx-indent-level.jsx b/test/lisp/progmodes/js-resources/jsx-indent-level.jsx new file mode 100644 index 00000000000..0a84b9eb77a --- /dev/null +++ b/test/lisp/progmodes/js-resources/jsx-indent-level.jsx @@ -0,0 +1,13 @@ +return ( + <element> + <element> + Hello World! + </element> + </element> +) + +// Local Variables: +// indent-tabs-mode: nil +// js-indent-level: 4 +// js-jsx-indent-level: 2 +// End: diff --git a/test/lisp/progmodes/js-resources/jsx-quote.jsx b/test/lisp/progmodes/js-resources/jsx-quote.jsx new file mode 100644 index 00000000000..1b2c6528734 --- /dev/null +++ b/test/lisp/progmodes/js-resources/jsx-quote.jsx @@ -0,0 +1,16 @@ +// JSX text node values should be strings, but only JS string syntax +// is considered, so quote marks delimit strings like normal, with +// disastrous results (https://github.com/mooz/js2-mode/issues/409). +function Bug() { + return <div>C'est Montréal</div>; +} +function Test(foo = /'/, + bar = 123) {} + +// This test is in a separate file because it can break other tests +// when indenting the whole buffer (not sure why). + +// Local Variables: +// indent-tabs-mode: nil +// js-indent-level: 2 +// End: diff --git a/test/lisp/progmodes/js-resources/jsx-self-closing.jsx b/test/lisp/progmodes/js-resources/jsx-self-closing.jsx new file mode 100644 index 00000000000..f8ea7a138ad --- /dev/null +++ b/test/lisp/progmodes/js-resources/jsx-self-closing.jsx @@ -0,0 +1,13 @@ +// Local Variables: +// indent-tabs-mode: nil +// js-indent-level: 2 +// End: + +// The following test goes below any comments to avoid including +// misindented comments among the erroring lines. + +// Properly parse/indent code with a self-closing tag inside the +// attribute of another self-closing tag. +<div> + <div attr={() => <div attr="" />} /> +</div> diff --git a/test/lisp/progmodes/js-resources/jsx-unclosed-1.jsx b/test/lisp/progmodes/js-resources/jsx-unclosed-1.jsx new file mode 100644 index 00000000000..1f5c3fba8da --- /dev/null +++ b/test/lisp/progmodes/js-resources/jsx-unclosed-1.jsx @@ -0,0 +1,13 @@ +// Local Variables: +// indent-tabs-mode: nil +// js-indent-level: 2 +// End: + +// The following test goes below any comments to avoid including +// misindented comments among the erroring lines. + +return ( + <div> + {array.map(function () { + return { + a: 1 diff --git a/test/lisp/progmodes/js-resources/jsx-unclosed-2.jsx b/test/lisp/progmodes/js-resources/jsx-unclosed-2.jsx new file mode 100644 index 00000000000..fb665b96a43 --- /dev/null +++ b/test/lisp/progmodes/js-resources/jsx-unclosed-2.jsx @@ -0,0 +1,65 @@ +// Local Variables: +// indent-tabs-mode: nil +// js-indent-level: 2 +// End: + +// The following tests go below any comments to avoid including +// misindented comments among the erroring lines. + +// Don’t misinterpret inequality operators as JSX. +for (; i < length;) void 0 +if (foo > bar) void 0 + +// Don’t misintrepet inequalities within JSX, either. +<div> + {foo < bar} +</div> + +// Don’t even misinterpret unary operators as JSX. +if (foo < await bar) void 0 +while (await foo > bar) void 0 + +<div> + {foo < await bar} +</div> + +// Allow unary keyword names as null-valued JSX attributes. +// (As if this will EVER happen…) +<Foo yield> + <Bar void> + <Baz + zorp + typeof> + <Please do_n0t delete this_stupidTest > + How would we ever live without unary support + </Please> + </Baz> + </Bar> +</Foo> + +// “-” is not allowed in a JSXBoundaryElement’s name. +<ABC /> + <A-B-C /> // Weirdly-indented “continued expression.” + +// “-” may be used in a JSXAttribute’s name. +<Foo a-b-c="" + x-y-z="" /> + +// Weird spaces should be tolerated. +< div > + < div > + < div + attr="" + / > + < div + attr="" + / > + < / div> +< / div > + +// Non-ASCII identifiers are acceptable. +<Über> + <Québec διακριτικός sueño=""> + Guten Tag! + </Québec> +</Über> diff --git a/test/lisp/progmodes/js-resources/jsx.jsx b/test/lisp/progmodes/js-resources/jsx.jsx new file mode 100644 index 00000000000..c200979df8c --- /dev/null +++ b/test/lisp/progmodes/js-resources/jsx.jsx @@ -0,0 +1,314 @@ +var foo = <div></div>; + +return ( + <div> + </div> + <div> + <div></div> + <div> + <div></div> + </div> + </div> +); + +React.render( + <div> + <div></div> + </div>, + { + a: 1 + }, + <div> + <div></div> + </div> +); + +return ( + // Sneaky! + <div></div> +); + +return ( + <div></div> + // Sneaky! +); + +React.render( + <input + />, + { + a: 1 + } +); + +return ( + <div> + {array.map(function () { + return { + a: 1 + }; + })} + </div> +); + +return ( + <div attribute={array.map(function () { + return { + a: 1 + }; + + return { + a: 1 + }; + + return { + a: 1 + }; + })}> + </div> +); + +return ( + <div attribute={{ + a: 1, // Indent relative to “attribute” column. + b: 2 + } && { // Dedent to “attribute” column. + a: 1, + b: 2 + }} /> // Also dedent. +); + +return ( + <div attribute= + { // Indent properly on another line, too. + { + a: 1, + b: 2, + } && ( + // Indent other forms, too. + a ? b : + c ? d : + e + ) + } /> +) + +// JSXMemberExpression names are parsed/indented: +<Foo.Bar> + <div> + <Foo.Bar> + Hello World! + </Foo.Bar> + <Foo.Bar> + <div> + </div> + </Foo.Bar> + </div> +</Foo.Bar> + +// JSXOpeningFragment and JSXClosingFragment are parsed/indented: +<> + <div> + <> + Hello World! + </> + <> + <div> + </div> + </> + </div> +</> + +// Indent void expressions (no need for contextual parens / commas) +// (https://github.com/mooz/js2-mode/issues/140#issuecomment-166250016). +<div className="class-name"> + <h2>Title</h2> + {array.map(() => { + return <Element />; + })} + {message} +</div> +// Another example of above issue +// (https://github.com/mooz/js2-mode/issues/490). +<App> + <div> + {variable1} + <Component/> + </div> +</App> + +// Comments and arrows can break indentation (Bug#24896 / +// https://github.com/mooz/js2-mode/issues/389). +const Component = props => ( + <FatArrow a={e => c} + b={123}> + </FatArrow> +); +const Component = props => ( + <NoFatArrow a={123} + b={123}> + </NoFatArrow> +); +const Component = props => ( // Parse this comment, please. + <FatArrow a={e => c} + b={123}> + </FatArrow> +); +const Component = props => ( // Parse this comment, please. + <NoFatArrow a={123} + b={123}> + </NoFatArrow> +); +// Another example of above issue (Bug#30225). +class { + render() { + return ( + <select style={{paddingRight: "10px"}} + onChange={e => this.setState({value: e.target.value})} + value={this.state.value}> + <option>Hi</option> + </select> + ); + } +} + +// JSX attributes of an arrow function’s expression body’s JSX +// expression should be indented with respect to the JSX opening +// element (Bug#26001 / +// https://github.com/mooz/js2-mode/issues/389#issuecomment-271869380). +class { + render() { + const messages = this.state.messages.map( + message => <Message key={message.id} + text={message.text} + mine={message.mine} /> + ); return messages; + } + render() { + const messages = this.state.messages.map(message => + <Message key={message.timestamp} + text={message.text} + mine={message.mine} /> + ); return messages; + } +} + +// Users expect tag closers to align with the tag’s start; this is the +// style used in the React docs, so it should be the default. +// - https://github.com/mooz/js2-mode/issues/389#issuecomment-390766873 +// - https://github.com/mooz/js2-mode/issues/482 +// - Bug#32158 +const foo = (props) => ( + <div> + <input + cat={i => i} + /> + <button + className="square" + > + {this.state.value} + </button> + </div> +); + +// Embedded JSX in parens breaks indentation +// (https://github.com/mooz/js2-mode/issues/411). +let a = ( + <div> + {condition && <Component/>} + {condition && <Component/>} + <div/> + </div> +) +let b = ( + <div> + {condition && (<Component/>)} + <div/> + </div> +) +let c = ( + <div> + {condition && (<Component/>)} + {condition && "something"} + </div> +) +let d = ( + <div> + {(<Component/>)} + {condition && "something"} + </div> +) +// Another example of the above issue (Bug#27000). +function testA() { + return ( + <div> + <div> { ( <div/> ) } </div> + </div> + ); +} +function testB() { + return ( + <div> + <div> { <div/> } </div> + </div> + ); +} +// Another example of the above issue +// (https://github.com/mooz/js2-mode/issues/451). +class Classy extends React.Component { + render () { + return ( + <div> + <ul className="tocListRoot"> + { this.state.list.map((item) => { + return (<div />) + })} + </ul> + </div> + ) + } +} + +// Self-closing tags should be indented properly +// (https://github.com/mooz/js2-mode/issues/459). +export default ({ stars }) => ( + <div className='overlay__container'> + <div className='overlay__header overlay--text'> + Congratulations! + </div> + <div className='overlay__reward'> + <Icon {...createIconProps(stars > 0)} size='large' /> + <div className='overlay__reward__bottom'> + <Icon {...createIconProps(stars > 1)} size='small' /> + <Icon {...createIconProps(stars > 2)} size='small' /> + </div> + </div> + <div className='overlay__description overlay--text'> + You have created <large>1</large> reminder + </div> + </div> +) + +// JS expressions should not break indentation +// (https://github.com/mooz/js2-mode/issues/462). +// +// In the referenced issue, the user actually wanted indentation which +// was simply different than Emacs’ SGML attribute indentation. +// Nevertheless, his issue highlighted our inability to properly +// indent code with JSX inside JSXExpressionContainers inside JSX. +return ( + <Router> + <Bar> + <Route exact path="/foo" + render={() => ( + <div>nothing</div> + )} /> + <Route exact path="/bar" /> + </Bar> + </Router> +) + +// Local Variables: +// indent-tabs-mode: nil +// js-indent-level: 2 +// End: diff --git a/test/lisp/progmodes/js-tests.el b/test/lisp/progmodes/js-tests.el index 681e51de0ed..1de2df0e85a 100644 --- a/test/lisp/progmodes/js-tests.el +++ b/test/lisp/progmodes/js-tests.el @@ -22,6 +22,7 @@ ;;; Code: (require 'ert) +(require 'ert-x) (require 'js) (require 'syntax) @@ -196,6 +197,33 @@ if (!/[ (:,='\"]/.test(value)) { ;; The bug was a hang. (should t))) +;;;; Indentation tests. + +(defmacro js-deftest-indent (file) + `(ert-deftest ,(intern (format "js-indent-test/%s" file)) () + :tags '(:expensive-test) + (let ((buf (find-file-noselect (ert-resource-file ,file)))) + (unwind-protect + (with-current-buffer buf + (let ((orig (buffer-string))) + (indent-region (point-min) (point-max)) + (should (equal (buffer-string) orig)))) + (kill-buffer buf))))) + +(js-deftest-indent "js-chain.js") +(js-deftest-indent "js-indent-align-list-continuation-nil.js") +(js-deftest-indent "js-indent-init-dynamic.js") +(js-deftest-indent "js-indent-init-t.js") +(js-deftest-indent "js.js") +(js-deftest-indent "jsx-align-gt-with-lt.jsx") +(js-deftest-indent "jsx-comment-string.jsx") +(js-deftest-indent "jsx-indent-level.jsx") +(js-deftest-indent "jsx-quote.jsx") +(js-deftest-indent "jsx-self-closing.jsx") +(js-deftest-indent "jsx-unclosed-1.jsx") +(js-deftest-indent "jsx-unclosed-2.jsx") +(js-deftest-indent "jsx.jsx") + (provide 'js-tests) ;;; js-tests.el ends here |