jsx-indent.js 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978
  1. /**
  2. * @fileoverview Validate JSX indentation
  3. * @author Yannick Croissant
  4. */
  5. 'use strict';
  6. // ------------------------------------------------------------------------------
  7. // Requirements
  8. // ------------------------------------------------------------------------------
  9. const rule = require('../../../lib/rules/jsx-indent');
  10. const RuleTester = require('eslint').RuleTester;
  11. const parserOptions = {
  12. ecmaVersion: 2018,
  13. sourceType: 'module',
  14. ecmaFeatures: {
  15. jsx: true
  16. }
  17. };
  18. // ------------------------------------------------------------------------------
  19. // Tests
  20. // ------------------------------------------------------------------------------
  21. const ruleTester = new RuleTester({parserOptions});
  22. ruleTester.run('jsx-indent', rule, {
  23. valid: [{
  24. code: [
  25. '<App></App>'
  26. ].join('\n')
  27. }, {
  28. code: [
  29. '<App>',
  30. '</App>'
  31. ].join('\n')
  32. }, {
  33. code: [
  34. '<App>',
  35. ' <Foo />',
  36. '</App>'
  37. ].join('\n'),
  38. options: [2]
  39. }, {
  40. code: [
  41. '<App>',
  42. '<Foo />',
  43. '</App>'
  44. ].join('\n'),
  45. options: [0]
  46. }, {
  47. code: [
  48. ' <App>',
  49. '<Foo />',
  50. ' </App>'
  51. ].join('\n'),
  52. options: [-2]
  53. }, {
  54. code: [
  55. '<App>',
  56. '\t<Foo />',
  57. '</App>'
  58. ].join('\n'),
  59. options: ['tab']
  60. }, {
  61. code: [
  62. 'function App() {',
  63. ' return <App>',
  64. ' <Foo />',
  65. ' </App>;',
  66. '}'
  67. ].join('\n'),
  68. options: [2]
  69. }, {
  70. code: [
  71. 'function App() {',
  72. ' return (<App>',
  73. ' <Foo />',
  74. ' </App>);',
  75. '}'
  76. ].join('\n'),
  77. options: [2]
  78. }, {
  79. code: [
  80. 'function App() {',
  81. ' return (',
  82. ' <App>',
  83. ' <Foo />',
  84. ' </App>',
  85. ' );',
  86. '}'
  87. ].join('\n'),
  88. options: [2]
  89. }, {
  90. code: [
  91. 'it(',
  92. ' (',
  93. ' <div>',
  94. ' <span />',
  95. ' </div>',
  96. ' )',
  97. ')'
  98. ].join('\n'),
  99. options: [2]
  100. }, {
  101. code: [
  102. 'it(',
  103. ' (<div>',
  104. ' <span />',
  105. ' <span />',
  106. ' <span />',
  107. ' </div>)',
  108. ')'
  109. ].join('\n'),
  110. options: [2]
  111. }, {
  112. code: [
  113. '(',
  114. ' <div>',
  115. ' <span />',
  116. ' </div>',
  117. ')'
  118. ].join('\n'),
  119. options: [2]
  120. }, {
  121. code: [
  122. '{',
  123. ' head.title &&',
  124. ' <h1>',
  125. ' {head.title}',
  126. ' </h1>',
  127. '}'
  128. ].join('\n'),
  129. options: [2]
  130. }, {
  131. code: [
  132. '{',
  133. ' head.title &&',
  134. ' <h1>',
  135. ' {head.title}',
  136. ' </h1>',
  137. '}'
  138. ].join('\n'),
  139. options: [2]
  140. }, {
  141. code: [
  142. '{',
  143. ' head.title && (',
  144. ' <h1>',
  145. ' {head.title}',
  146. ' </h1>)',
  147. '}'
  148. ].join('\n'),
  149. options: [2]
  150. }, {
  151. code: [
  152. '{',
  153. ' head.title && (',
  154. ' <h1>',
  155. ' {head.title}',
  156. ' </h1>',
  157. ' )',
  158. '}'
  159. ].join('\n'),
  160. options: [2]
  161. }, {
  162. code: [
  163. '[',
  164. ' <div />,',
  165. ' <div />',
  166. ']'
  167. ].join('\n'),
  168. options: [2]
  169. }, {
  170. code: [
  171. '<div>',
  172. ' {',
  173. ' [',
  174. ' <Foo />,',
  175. ' <Bar />',
  176. ' ]',
  177. ' }',
  178. '</div>'
  179. ].join('\n')
  180. }, {
  181. code: [
  182. '<div>',
  183. ' {foo &&',
  184. ' [',
  185. ' <Foo />,',
  186. ' <Bar />',
  187. ' ]',
  188. ' }',
  189. '</div>'
  190. ].join('\n')
  191. }, {
  192. // Literals indentation is not touched
  193. code: [
  194. '<div>',
  195. 'bar <div>',
  196. ' bar',
  197. ' bar {foo}',
  198. 'bar </div>',
  199. '</div>'
  200. ].join('\n')
  201. }, {
  202. // Multiline ternary
  203. // (colon at the end of the first expression)
  204. code: [
  205. 'foo ?',
  206. ' <Foo /> :',
  207. ' <Bar />'
  208. ].join('\n')
  209. }, {
  210. // Multiline ternary
  211. // (colon at the start of the second expression)
  212. code: [
  213. 'foo ?',
  214. ' <Foo />',
  215. ' : <Bar />'
  216. ].join('\n')
  217. }, {
  218. // Multiline ternary
  219. // (colon on its own line)
  220. code: [
  221. 'foo ?',
  222. ' <Foo />',
  223. ':',
  224. ' <Bar />'
  225. ].join('\n')
  226. }, {
  227. // Multiline ternary
  228. // (multiline JSX, colon on its own line)
  229. code: [
  230. '{!foo ?',
  231. ' <Foo',
  232. ' onClick={this.onClick}',
  233. ' />',
  234. ':',
  235. ' <Bar',
  236. ' onClick={this.onClick}',
  237. ' />',
  238. '}'
  239. ].join('\n')
  240. }, {
  241. // Multiline ternary
  242. // (first expression on test line, colon at the end of the first expression)
  243. code: [
  244. 'foo ? <Foo /> :',
  245. '<Bar />'
  246. ].join('\n')
  247. }, {
  248. // Multiline ternary
  249. // (first expression on test line, colon at the start of the second expression)
  250. code: [
  251. 'foo ? <Foo />',
  252. ': <Bar />'
  253. ].join('\n')
  254. }, {
  255. // Multiline ternary
  256. // (first expression on test line, colon on its own line)
  257. code: [
  258. 'foo ? <Foo />',
  259. ':',
  260. '<Bar />'
  261. ].join('\n')
  262. }, {
  263. // Multiline ternary
  264. // (colon at the end of the first expression, parenthesized first expression)
  265. code: [
  266. 'foo ? (',
  267. ' <Foo />',
  268. ') :',
  269. ' <Bar />'
  270. ].join('\n')
  271. }, {
  272. // Multiline ternary
  273. // (colon at the start of the second expression, parenthesized first expression)
  274. code: [
  275. 'foo ? (',
  276. ' <Foo />',
  277. ')',
  278. ' : <Bar />'
  279. ].join('\n')
  280. }, {
  281. // Multiline ternary
  282. // (colon on its own line, parenthesized first expression)
  283. code: [
  284. 'foo ? (',
  285. ' <Foo />',
  286. ')',
  287. ':',
  288. ' <Bar />'
  289. ].join('\n')
  290. }, {
  291. // Multiline ternary
  292. // (colon at the end of the first expression, parenthesized second expression)
  293. code: [
  294. 'foo ?',
  295. ' <Foo /> : (',
  296. ' <Bar />',
  297. ' )'
  298. ].join('\n')
  299. }, {
  300. // Multiline ternary
  301. // (colon on its own line, parenthesized second expression)
  302. code: [
  303. 'foo ?',
  304. ' <Foo />',
  305. ': (',
  306. ' <Bar />',
  307. ')'
  308. ].join('\n')
  309. }, {
  310. // Multiline ternary
  311. // (colon indented on its own line, parenthesized second expression)
  312. code: [
  313. 'foo ?',
  314. ' <Foo />',
  315. ' : (',
  316. ' <Bar />',
  317. ' )'
  318. ].join('\n')
  319. }, {
  320. // Multiline ternary
  321. // (colon at the end of the first expression, both expression parenthesized)
  322. code: [
  323. 'foo ? (',
  324. ' <Foo />',
  325. ') : (',
  326. ' <Bar />',
  327. ')'
  328. ].join('\n')
  329. }, {
  330. // Multiline ternary
  331. // (colon on its own line, both expression parenthesized)
  332. code: [
  333. 'foo ? (',
  334. ' <Foo />',
  335. ')',
  336. ': (',
  337. ' <Bar />',
  338. ')'
  339. ].join('\n')
  340. }, {
  341. // Multiline ternary
  342. // (colon on its own line, both expression parenthesized)
  343. code: [
  344. 'foo ? (',
  345. ' <Foo />',
  346. ')',
  347. ':',
  348. '(',
  349. ' <Bar />',
  350. ')'
  351. ].join('\n')
  352. }, {
  353. // Multiline ternary
  354. // (first expression on test line, colon at the end of the first expression, parenthesized second expression)
  355. code: [
  356. 'foo ? <Foo /> : (',
  357. ' <Bar />',
  358. ')'
  359. ].join('\n')
  360. }, {
  361. // Multiline ternary
  362. // (first expression on test line, colon at the start of the second expression, parenthesized second expression)
  363. code: [
  364. 'foo ? <Foo />',
  365. ': (<Bar />)'
  366. ].join('\n')
  367. }, {
  368. // Multiline ternary
  369. // (first expression on test line, colon on its own line, parenthesized second expression)
  370. code: [
  371. 'foo ? <Foo />',
  372. ': (',
  373. ' <Bar />',
  374. ')'
  375. ].join('\n')
  376. }, {
  377. code: [
  378. '<span>',
  379. ' {condition ?',
  380. ' <Thing',
  381. ' foo={`bar`}',
  382. ' /> :',
  383. ' <Thing/>',
  384. ' }',
  385. '</span>'
  386. ].join('\n'),
  387. options: [2]
  388. }, {
  389. code: [
  390. '<span>',
  391. ' {condition ?',
  392. ' <Thing',
  393. ' foo={"bar"}',
  394. ' /> :',
  395. ' <Thing/>',
  396. ' }',
  397. '</span>'
  398. ].join('\n'),
  399. options: [2]
  400. }, {
  401. code: [
  402. 'function foo() {',
  403. ' <span>',
  404. ' {condition ?',
  405. ' <Thing',
  406. ' foo={superFoo}',
  407. ' /> :',
  408. ' <Thing/>',
  409. ' }',
  410. ' </span>',
  411. '}'
  412. ].join('\n'),
  413. options: [2]
  414. }],
  415. invalid: [{
  416. code: [
  417. '<App>',
  418. ' <Foo />',
  419. '</App>'
  420. ].join('\n'),
  421. output: [
  422. '<App>',
  423. ' <Foo />',
  424. '</App>'
  425. ].join('\n'),
  426. errors: [{message: 'Expected indentation of 4 space characters but found 2.'}]
  427. }, {
  428. code: [
  429. '<App>',
  430. ' <Foo />',
  431. '</App>'
  432. ].join('\n'),
  433. output: [
  434. '<App>',
  435. ' <Foo />',
  436. '</App>'
  437. ].join('\n'),
  438. options: [2],
  439. errors: [{message: 'Expected indentation of 2 space characters but found 4.'}]
  440. }, {
  441. code: [
  442. '<App>',
  443. ' <Foo />',
  444. '</App>'
  445. ].join('\n'),
  446. output: [
  447. '<App>',
  448. '\t<Foo />',
  449. '</App>'
  450. ].join('\n'),
  451. options: ['tab'],
  452. errors: [{message: 'Expected indentation of 1 tab character but found 0.'}]
  453. }, {
  454. code: [
  455. 'function App() {',
  456. ' return <App>',
  457. ' <Foo />',
  458. ' </App>;',
  459. '}'
  460. ].join('\n'),
  461. output: [
  462. 'function App() {',
  463. ' return <App>',
  464. ' <Foo />',
  465. ' </App>;',
  466. '}'
  467. ].join('\n'),
  468. options: [2],
  469. errors: [{message: 'Expected indentation of 2 space characters but found 9.'}]
  470. }, {
  471. code: [
  472. 'function App() {',
  473. ' return (<App>',
  474. ' <Foo />',
  475. ' </App>);',
  476. '}'
  477. ].join('\n'),
  478. output: [
  479. 'function App() {',
  480. ' return (<App>',
  481. ' <Foo />',
  482. ' </App>);',
  483. '}'
  484. ].join('\n'),
  485. options: [2],
  486. errors: [{message: 'Expected indentation of 2 space characters but found 4.'}]
  487. }, {
  488. code: [
  489. 'function App() {',
  490. ' return (',
  491. '<App>',
  492. ' <Foo />',
  493. '</App>',
  494. ' );',
  495. '}'
  496. ].join('\n'),
  497. // The detection logic only thinks <App> is indented wrong, not the other
  498. // two lines following. I *think* because it incorrectly uses <App>'s indention
  499. // as the baseline for the next two, instead of the realizing the entire three
  500. // lines are wrong together. See #608
  501. /* output: [
  502. 'function App() {',
  503. ' return (',
  504. ' <App>',
  505. ' <Foo />',
  506. ' </App>',
  507. ' );',
  508. '}'
  509. ].join('\n'), */
  510. options: [2],
  511. errors: [{message: 'Expected indentation of 4 space characters but found 0.'}]
  512. }, {
  513. code: [
  514. '<App>',
  515. ' {test}',
  516. '</App>'
  517. ].join('\n'),
  518. output: [
  519. '<App>',
  520. ' {test}',
  521. '</App>'
  522. ].join('\n'),
  523. errors: [
  524. {message: 'Expected indentation of 4 space characters but found 3.'}
  525. ]
  526. }, {
  527. code: [
  528. '<App>',
  529. ' {options.map((option, index) => (',
  530. ' <option key={index} value={option.key}>',
  531. ' {option.name}',
  532. ' </option>',
  533. ' ))}',
  534. '</App>'
  535. ].join('\n'),
  536. output: [
  537. '<App>',
  538. ' {options.map((option, index) => (',
  539. ' <option key={index} value={option.key}>',
  540. ' {option.name}',
  541. ' </option>',
  542. ' ))}',
  543. '</App>'
  544. ].join('\n'),
  545. errors: [
  546. {message: 'Expected indentation of 12 space characters but found 11.'}
  547. ]
  548. }, {
  549. code: [
  550. '<App>',
  551. '{test}',
  552. '</App>'
  553. ].join('\n'),
  554. output: [
  555. '<App>',
  556. '\t{test}',
  557. '</App>'
  558. ].join('\n'),
  559. options: ['tab'],
  560. errors: [
  561. {message: 'Expected indentation of 1 tab character but found 0.'}
  562. ]
  563. }, {
  564. code: [
  565. '<App>',
  566. '\t{options.map((option, index) => (',
  567. '\t\t<option key={index} value={option.key}>',
  568. '\t\t{option.name}',
  569. '\t\t</option>',
  570. '\t))}',
  571. '</App>'
  572. ].join('\n'),
  573. output: [
  574. '<App>',
  575. '\t{options.map((option, index) => (',
  576. '\t\t<option key={index} value={option.key}>',
  577. '\t\t\t{option.name}',
  578. '\t\t</option>',
  579. '\t))}',
  580. '</App>'
  581. ].join('\n'),
  582. options: ['tab'],
  583. errors: [
  584. {message: 'Expected indentation of 3 tab characters but found 2.'}
  585. ]
  586. }, {
  587. code: [
  588. '<App>\n',
  589. '<Foo />\n',
  590. '</App>'
  591. ].join('\n'),
  592. output: [
  593. '<App>\n',
  594. '\t<Foo />\n',
  595. '</App>'
  596. ].join('\n'),
  597. options: ['tab'],
  598. errors: [
  599. {message: 'Expected indentation of 1 tab character but found 0.'}
  600. ]
  601. }, {
  602. code: [
  603. '[',
  604. ' <div />,',
  605. ' <div />',
  606. ']'
  607. ].join('\n'),
  608. output: [
  609. '[',
  610. ' <div />,',
  611. ' <div />',
  612. ']'
  613. ].join('\n'),
  614. options: [2],
  615. errors: [
  616. {message: 'Expected indentation of 2 space characters but found 4.'}
  617. ]
  618. }, {
  619. code: [
  620. '<App>\n',
  621. ' <Foo />\n',
  622. '</App>'
  623. ].join('\n'),
  624. output: [
  625. '<App>\n',
  626. '\t<Foo />\n',
  627. '</App>'
  628. ].join('\n'),
  629. options: ['tab'],
  630. errors: [
  631. {message: 'Expected indentation of 1 tab character but found 0.'}
  632. ]
  633. }, {
  634. code: [
  635. '<App>\n',
  636. '\t<Foo />\n',
  637. '</App>'
  638. ].join('\n'),
  639. output: [
  640. '<App>\n',
  641. ' <Foo />\n',
  642. '</App>'
  643. ].join('\n'),
  644. options: [2],
  645. errors: [
  646. {message: 'Expected indentation of 2 space characters but found 0.'}
  647. ]
  648. }, {
  649. code: [
  650. '<div>',
  651. ' {',
  652. ' [',
  653. ' <Foo />,',
  654. ' <Bar />',
  655. ' ]',
  656. ' }',
  657. '</div>'
  658. ].join('\n'),
  659. output: [
  660. '<div>',
  661. ' {',
  662. ' [',
  663. ' <Foo />,',
  664. ' <Bar />',
  665. ' ]',
  666. ' }',
  667. '</div>'
  668. ].join('\n'),
  669. errors: [
  670. {message: 'Expected indentation of 12 space characters but found 8.'}
  671. ]
  672. }, {
  673. code: [
  674. '<div>',
  675. ' {foo &&',
  676. ' [',
  677. ' <Foo />,',
  678. ' <Bar />',
  679. ' ]',
  680. ' }',
  681. '</div>'
  682. ].join('\n'),
  683. output: [
  684. '<div>',
  685. ' {foo &&',
  686. ' [',
  687. ' <Foo />,',
  688. ' <Bar />',
  689. ' ]',
  690. ' }',
  691. '</div>'
  692. ].join('\n'),
  693. errors: [
  694. {message: 'Expected indentation of 12 space characters but found 8.'}
  695. ]
  696. }, {
  697. // Multiline ternary
  698. // (colon at the end of the first expression)
  699. code: [
  700. 'foo ?',
  701. ' <Foo /> :',
  702. '<Bar />'
  703. ].join('\n'),
  704. output: [
  705. 'foo ?',
  706. ' <Foo /> :',
  707. ' <Bar />'
  708. ].join('\n'),
  709. errors: [
  710. {message: 'Expected indentation of 4 space characters but found 0.'}
  711. ]
  712. }, {
  713. // Multiline ternary
  714. // (colon on its own line)
  715. code: [
  716. 'foo ?',
  717. ' <Foo />',
  718. ':',
  719. '<Bar />'
  720. ].join('\n'),
  721. output: [
  722. 'foo ?',
  723. ' <Foo />',
  724. ':',
  725. ' <Bar />'
  726. ].join('\n'),
  727. errors: [
  728. {message: 'Expected indentation of 4 space characters but found 0.'}
  729. ]
  730. }, {
  731. // Multiline ternary
  732. // (first expression on test line, colon at the end of the first expression)
  733. code: [
  734. 'foo ? <Foo /> :',
  735. ' <Bar />'
  736. ].join('\n'),
  737. output: [
  738. 'foo ? <Foo /> :',
  739. '<Bar />'
  740. ].join('\n'),
  741. errors: [
  742. {message: 'Expected indentation of 0 space characters but found 4.'}
  743. ]
  744. }, {
  745. // Multiline ternary
  746. // (first expression on test line, colon on its own line)
  747. code: [
  748. 'foo ? <Foo />',
  749. ':',
  750. ' <Bar />'
  751. ].join('\n'),
  752. output: [
  753. 'foo ? <Foo />',
  754. ':',
  755. '<Bar />'
  756. ].join('\n'),
  757. errors: [
  758. {message: 'Expected indentation of 0 space characters but found 6.'}
  759. ]
  760. }, {
  761. // Multiline ternary
  762. // (colon at the end of the first expression, parenthesized first expression)
  763. code: [
  764. 'foo ? (',
  765. ' <Foo />',
  766. ') :',
  767. '<Bar />'
  768. ].join('\n'),
  769. output: [
  770. 'foo ? (',
  771. ' <Foo />',
  772. ') :',
  773. ' <Bar />'
  774. ].join('\n'),
  775. errors: [
  776. {message: 'Expected indentation of 4 space characters but found 0.'}
  777. ]
  778. }, {
  779. // Multiline ternary
  780. // (colon on its own line, parenthesized first expression)
  781. code: [
  782. 'foo ? (',
  783. ' <Foo />',
  784. ')',
  785. ':',
  786. '<Bar />'
  787. ].join('\n'),
  788. output: [
  789. 'foo ? (',
  790. ' <Foo />',
  791. ')',
  792. ':',
  793. ' <Bar />'
  794. ].join('\n'),
  795. errors: [
  796. {message: 'Expected indentation of 4 space characters but found 0.'}
  797. ]
  798. }, {
  799. // Multiline ternary
  800. // (colon at the end of the first expression, parenthesized second expression)
  801. code: [
  802. 'foo ?',
  803. ' <Foo /> : (',
  804. ' <Bar />',
  805. ' )'
  806. ].join('\n'),
  807. output: [
  808. 'foo ?',
  809. ' <Foo /> : (',
  810. ' <Bar />',
  811. ' )'
  812. ].join('\n'),
  813. errors: [
  814. {message: 'Expected indentation of 8 space characters but found 4.'}
  815. ]
  816. }, {
  817. // Multiline ternary
  818. // (colon on its own line, parenthesized second expression)
  819. code: [
  820. 'foo ?',
  821. ' <Foo />',
  822. ': (',
  823. '<Bar />',
  824. ')'
  825. ].join('\n'),
  826. output: [
  827. 'foo ?',
  828. ' <Foo />',
  829. ': (',
  830. ' <Bar />',
  831. ')'
  832. ].join('\n'),
  833. errors: [
  834. {message: 'Expected indentation of 4 space characters but found 0.'}
  835. ]
  836. }, {
  837. // Multiline ternary
  838. // (colon indented on its own line, parenthesized second expression)
  839. code: [
  840. 'foo ?',
  841. ' <Foo />',
  842. ' : (',
  843. ' <Bar />',
  844. ' )'
  845. ].join('\n'),
  846. output: [
  847. 'foo ?',
  848. ' <Foo />',
  849. ' : (',
  850. ' <Bar />',
  851. ' )'
  852. ].join('\n'),
  853. errors: [
  854. {message: 'Expected indentation of 8 space characters but found 4.'}
  855. ]
  856. }, {
  857. // Multiline ternary
  858. // (colon at the end of the first expression, both expression parenthesized)
  859. code: [
  860. 'foo ? (',
  861. '<Foo />',
  862. ') : (',
  863. '<Bar />',
  864. ')'
  865. ].join('\n'),
  866. output: [
  867. 'foo ? (',
  868. ' <Foo />',
  869. ') : (',
  870. ' <Bar />',
  871. ')'
  872. ].join('\n'),
  873. errors: [
  874. {message: 'Expected indentation of 4 space characters but found 0.'},
  875. {message: 'Expected indentation of 4 space characters but found 0.'}
  876. ]
  877. }, {
  878. // Multiline ternary
  879. // (colon on its own line, both expression parenthesized)
  880. code: [
  881. 'foo ? (',
  882. '<Foo />',
  883. ')',
  884. ': (',
  885. '<Bar />',
  886. ')'
  887. ].join('\n'),
  888. output: [
  889. 'foo ? (',
  890. ' <Foo />',
  891. ')',
  892. ': (',
  893. ' <Bar />',
  894. ')'
  895. ].join('\n'),
  896. errors: [
  897. {message: 'Expected indentation of 4 space characters but found 0.'},
  898. {message: 'Expected indentation of 4 space characters but found 0.'}
  899. ]
  900. }, {
  901. // Multiline ternary
  902. // (colon on its own line, both expression parenthesized)
  903. code: [
  904. 'foo ? (',
  905. '<Foo />',
  906. ')',
  907. ':',
  908. '(',
  909. '<Bar />',
  910. ')'
  911. ].join('\n'),
  912. output: [
  913. 'foo ? (',
  914. ' <Foo />',
  915. ')',
  916. ':',
  917. '(',
  918. ' <Bar />',
  919. ')'
  920. ].join('\n'),
  921. errors: [
  922. {message: 'Expected indentation of 4 space characters but found 0.'},
  923. {message: 'Expected indentation of 4 space characters but found 0.'}
  924. ]
  925. }, {
  926. // Multiline ternary
  927. // (first expression on test line, colon at the end of the first expression, parenthesized second expression)
  928. code: [
  929. 'foo ? <Foo /> : (',
  930. '<Bar />',
  931. ')'
  932. ].join('\n'),
  933. output: [
  934. 'foo ? <Foo /> : (',
  935. ' <Bar />',
  936. ')'
  937. ].join('\n'),
  938. errors: [
  939. {message: 'Expected indentation of 4 space characters but found 0.'}
  940. ]
  941. }, {
  942. // Multiline ternary
  943. // (first expression on test line, colon on its own line, parenthesized second expression)
  944. code: [
  945. 'foo ? <Foo />',
  946. ': (',
  947. '<Bar />',
  948. ')'
  949. ].join('\n'),
  950. output: [
  951. 'foo ? <Foo />',
  952. ': (',
  953. ' <Bar />',
  954. ')'
  955. ].join('\n'),
  956. errors: [
  957. {message: 'Expected indentation of 4 space characters but found 0.'}
  958. ]
  959. }, {
  960. code: [
  961. '<p>',
  962. ' <div>',
  963. ' <SelfClosingTag />Text',
  964. ' </div>',
  965. '</p>'
  966. ].join('\n'),
  967. errors: [
  968. {message: 'Expected indentation of 4 space characters but found 2.'}
  969. ]
  970. }]
  971. });