codegen.spec.ts 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774
  1. import {
  2. locStub,
  3. generate,
  4. NodeTypes,
  5. RootNode,
  6. createSimpleExpression,
  7. createObjectExpression,
  8. createObjectProperty,
  9. createArrayExpression,
  10. createCompoundExpression,
  11. createInterpolation,
  12. createCallExpression,
  13. createConditionalExpression,
  14. ForCodegenNode,
  15. createCacheExpression,
  16. createTemplateLiteral,
  17. createBlockStatement,
  18. createIfStatement,
  19. createAssignmentExpression,
  20. IfConditionalExpression,
  21. createVNodeCall,
  22. VNodeCall,
  23. DirectiveArguments
  24. } from '../src'
  25. import {
  26. CREATE_VNODE,
  27. TO_DISPLAY_STRING,
  28. RESOLVE_DIRECTIVE,
  29. helperNameMap,
  30. RESOLVE_COMPONENT,
  31. CREATE_COMMENT,
  32. FRAGMENT,
  33. RENDER_LIST
  34. } from '../src/runtimeHelpers'
  35. import { createElementWithCodegen, genFlagText } from './testUtils'
  36. import { PatchFlags } from '@vue/shared'
  37. function createRoot(options: Partial<RootNode> = {}): RootNode {
  38. return {
  39. type: NodeTypes.ROOT,
  40. children: [],
  41. helpers: [],
  42. components: [],
  43. directives: [],
  44. imports: [],
  45. hoists: [],
  46. cached: 0,
  47. temps: 0,
  48. codegenNode: createSimpleExpression(`null`, false),
  49. loc: locStub,
  50. ...options
  51. }
  52. }
  53. describe('compiler: codegen', () => {
  54. test('module mode preamble', () => {
  55. const root = createRoot({
  56. helpers: [CREATE_VNODE, RESOLVE_DIRECTIVE]
  57. })
  58. const { code } = generate(root, { mode: 'module' })
  59. expect(code).toMatch(
  60. `import { ${helperNameMap[CREATE_VNODE]} as _${
  61. helperNameMap[CREATE_VNODE]
  62. }, ${helperNameMap[RESOLVE_DIRECTIVE]} as _${
  63. helperNameMap[RESOLVE_DIRECTIVE]
  64. } } from "vue"`
  65. )
  66. expect(code).toMatchSnapshot()
  67. })
  68. test('module mode preamble w/ optimizeBindings: true', () => {
  69. const root = createRoot({
  70. helpers: [CREATE_VNODE, RESOLVE_DIRECTIVE]
  71. })
  72. const { code } = generate(root, { mode: 'module', optimizeBindings: true })
  73. expect(code).toMatch(
  74. `import { ${helperNameMap[CREATE_VNODE]}, ${
  75. helperNameMap[RESOLVE_DIRECTIVE]
  76. } } from "vue"`
  77. )
  78. expect(code).toMatch(
  79. `const _${helperNameMap[CREATE_VNODE]} = ${
  80. helperNameMap[CREATE_VNODE]
  81. }, _${helperNameMap[RESOLVE_DIRECTIVE]} = ${
  82. helperNameMap[RESOLVE_DIRECTIVE]
  83. }`
  84. )
  85. expect(code).toMatchSnapshot()
  86. })
  87. test('function mode preamble', () => {
  88. const root = createRoot({
  89. helpers: [CREATE_VNODE, RESOLVE_DIRECTIVE]
  90. })
  91. const { code } = generate(root, { mode: 'function' })
  92. expect(code).toMatch(`const _Vue = Vue`)
  93. expect(code).toMatch(
  94. `const { ${helperNameMap[CREATE_VNODE]}: _${
  95. helperNameMap[CREATE_VNODE]
  96. }, ${helperNameMap[RESOLVE_DIRECTIVE]}: _${
  97. helperNameMap[RESOLVE_DIRECTIVE]
  98. } } = _Vue`
  99. )
  100. expect(code).toMatchSnapshot()
  101. })
  102. test('function mode preamble w/ prefixIdentifiers: true', () => {
  103. const root = createRoot({
  104. helpers: [CREATE_VNODE, RESOLVE_DIRECTIVE]
  105. })
  106. const { code } = generate(root, {
  107. mode: 'function',
  108. prefixIdentifiers: true
  109. })
  110. expect(code).not.toMatch(`const _Vue = Vue`)
  111. expect(code).toMatch(
  112. `const { ${helperNameMap[CREATE_VNODE]}: _${
  113. helperNameMap[CREATE_VNODE]
  114. }, ${helperNameMap[RESOLVE_DIRECTIVE]}: _${
  115. helperNameMap[RESOLVE_DIRECTIVE]
  116. } } = Vue`
  117. )
  118. expect(code).toMatchSnapshot()
  119. })
  120. test('assets + temps', () => {
  121. const root = createRoot({
  122. components: [`Foo`, `bar-baz`, `barbaz`],
  123. directives: [`my_dir_0`, `my_dir_1`],
  124. temps: 3
  125. })
  126. const { code } = generate(root, { mode: 'function' })
  127. expect(code).toMatch(
  128. `const _component_Foo = _${helperNameMap[RESOLVE_COMPONENT]}("Foo")\n`
  129. )
  130. expect(code).toMatch(
  131. `const _component_bar_baz = _${
  132. helperNameMap[RESOLVE_COMPONENT]
  133. }("bar-baz")\n`
  134. )
  135. expect(code).toMatch(
  136. `const _component_barbaz = _${
  137. helperNameMap[RESOLVE_COMPONENT]
  138. }("barbaz")\n`
  139. )
  140. expect(code).toMatch(
  141. `const _directive_my_dir_0 = _${
  142. helperNameMap[RESOLVE_DIRECTIVE]
  143. }("my_dir_0")\n`
  144. )
  145. expect(code).toMatch(
  146. `const _directive_my_dir_1 = _${
  147. helperNameMap[RESOLVE_DIRECTIVE]
  148. }("my_dir_1")\n`
  149. )
  150. expect(code).toMatch(`let _temp0, _temp1, _temp2`)
  151. expect(code).toMatchSnapshot()
  152. })
  153. test('hoists', () => {
  154. const root = createRoot({
  155. hoists: [
  156. createSimpleExpression(`hello`, false, locStub),
  157. createObjectExpression(
  158. [
  159. createObjectProperty(
  160. createSimpleExpression(`id`, true, locStub),
  161. createSimpleExpression(`foo`, true, locStub)
  162. )
  163. ],
  164. locStub
  165. )
  166. ]
  167. })
  168. const { code } = generate(root)
  169. expect(code).toMatch(`const _hoisted_1 = hello`)
  170. expect(code).toMatch(`const _hoisted_2 = { id: "foo" }`)
  171. expect(code).toMatchSnapshot()
  172. })
  173. test('temps', () => {
  174. const root = createRoot({
  175. temps: 3
  176. })
  177. const { code } = generate(root)
  178. expect(code).toMatch(`let _temp0, _temp1, _temp2`)
  179. expect(code).toMatchSnapshot()
  180. })
  181. test('static text', () => {
  182. const { code } = generate(
  183. createRoot({
  184. codegenNode: {
  185. type: NodeTypes.TEXT,
  186. content: 'hello',
  187. loc: locStub
  188. }
  189. })
  190. )
  191. expect(code).toMatch(`return "hello"`)
  192. expect(code).toMatchSnapshot()
  193. })
  194. test('interpolation', () => {
  195. const { code } = generate(
  196. createRoot({
  197. codegenNode: createInterpolation(`hello`, locStub)
  198. })
  199. )
  200. expect(code).toMatch(`return _${helperNameMap[TO_DISPLAY_STRING]}(hello)`)
  201. expect(code).toMatchSnapshot()
  202. })
  203. test('comment', () => {
  204. const { code } = generate(
  205. createRoot({
  206. codegenNode: {
  207. type: NodeTypes.COMMENT,
  208. content: 'foo',
  209. loc: locStub
  210. }
  211. })
  212. )
  213. expect(code).toMatch(`return _${helperNameMap[CREATE_COMMENT]}("foo")`)
  214. expect(code).toMatchSnapshot()
  215. })
  216. test('compound expression', () => {
  217. const { code } = generate(
  218. createRoot({
  219. codegenNode: createCompoundExpression([
  220. `_ctx.`,
  221. createSimpleExpression(`foo`, false, locStub),
  222. ` + `,
  223. {
  224. type: NodeTypes.INTERPOLATION,
  225. loc: locStub,
  226. content: createSimpleExpression(`bar`, false, locStub)
  227. },
  228. // nested compound
  229. createCompoundExpression([` + `, `nested`])
  230. ])
  231. })
  232. )
  233. expect(code).toMatch(
  234. `return _ctx.foo + _${helperNameMap[TO_DISPLAY_STRING]}(bar) + nested`
  235. )
  236. expect(code).toMatchSnapshot()
  237. })
  238. test('ifNode', () => {
  239. const { code } = generate(
  240. createRoot({
  241. codegenNode: {
  242. type: NodeTypes.IF,
  243. loc: locStub,
  244. branches: [],
  245. codegenNode: createConditionalExpression(
  246. createSimpleExpression('foo', false),
  247. createSimpleExpression('bar', false),
  248. createSimpleExpression('baz', false)
  249. ) as IfConditionalExpression
  250. }
  251. })
  252. )
  253. expect(code).toMatch(/return foo\s+\? bar\s+: baz/)
  254. expect(code).toMatchSnapshot()
  255. })
  256. test('forNode', () => {
  257. const { code } = generate(
  258. createRoot({
  259. codegenNode: {
  260. type: NodeTypes.FOR,
  261. loc: locStub,
  262. source: createSimpleExpression('foo', false),
  263. valueAlias: undefined,
  264. keyAlias: undefined,
  265. objectIndexAlias: undefined,
  266. children: [],
  267. parseResult: {} as any,
  268. codegenNode: {
  269. type: NodeTypes.VNODE_CALL,
  270. tag: FRAGMENT,
  271. isBlock: true,
  272. disableTracking: true,
  273. props: undefined,
  274. children: createCallExpression(RENDER_LIST),
  275. patchFlag: '1',
  276. dynamicProps: undefined,
  277. directives: undefined,
  278. loc: locStub
  279. } as ForCodegenNode
  280. }
  281. })
  282. )
  283. expect(code).toMatch(`openBlock(true)`)
  284. expect(code).toMatchSnapshot()
  285. })
  286. test('forNode with constant expression', () => {
  287. const { code } = generate(
  288. createRoot({
  289. codegenNode: {
  290. type: NodeTypes.FOR,
  291. loc: locStub,
  292. source: createSimpleExpression('1 + 2', false, locStub, true),
  293. valueAlias: undefined,
  294. keyAlias: undefined,
  295. objectIndexAlias: undefined,
  296. children: [],
  297. parseResult: {} as any,
  298. codegenNode: {
  299. type: NodeTypes.VNODE_CALL,
  300. tag: FRAGMENT,
  301. isBlock: true,
  302. disableTracking: false,
  303. props: undefined,
  304. children: createCallExpression(RENDER_LIST),
  305. patchFlag: genFlagText(PatchFlags.STABLE_FRAGMENT),
  306. dynamicProps: undefined,
  307. directives: undefined,
  308. loc: locStub
  309. } as ForCodegenNode
  310. }
  311. })
  312. )
  313. expect(code).toMatch(`openBlock()`)
  314. expect(code).toMatchSnapshot()
  315. })
  316. test('Element (callExpression + objectExpression + TemplateChildNode[])', () => {
  317. const { code } = generate(
  318. createRoot({
  319. codegenNode: createElementWithCodegen(
  320. // string
  321. `"div"`,
  322. // ObjectExpression
  323. createObjectExpression(
  324. [
  325. createObjectProperty(
  326. createSimpleExpression(`id`, true, locStub),
  327. createSimpleExpression(`foo`, true, locStub)
  328. ),
  329. createObjectProperty(
  330. createSimpleExpression(`prop`, false, locStub),
  331. createSimpleExpression(`bar`, false, locStub)
  332. ),
  333. // compound expression as computed key
  334. createObjectProperty(
  335. {
  336. type: NodeTypes.COMPOUND_EXPRESSION,
  337. loc: locStub,
  338. children: [
  339. `foo + `,
  340. createSimpleExpression(`bar`, false, locStub)
  341. ]
  342. },
  343. createSimpleExpression(`bar`, false, locStub)
  344. )
  345. ],
  346. locStub
  347. ),
  348. // ChildNode[]
  349. [
  350. createElementWithCodegen(
  351. `"p"`,
  352. createObjectExpression(
  353. [
  354. createObjectProperty(
  355. // should quote the key!
  356. createSimpleExpression(`some-key`, true, locStub),
  357. createSimpleExpression(`foo`, true, locStub)
  358. )
  359. ],
  360. locStub
  361. )
  362. )
  363. ],
  364. // flag
  365. PatchFlags.FULL_PROPS + ''
  366. )
  367. })
  368. )
  369. expect(code).toMatch(`
  370. return _${helperNameMap[CREATE_VNODE]}("div", {
  371. id: "foo",
  372. [prop]: bar,
  373. [foo + bar]: bar
  374. }, [
  375. _${helperNameMap[CREATE_VNODE]}("p", { "some-key": "foo" })
  376. ], ${PatchFlags.FULL_PROPS})`)
  377. expect(code).toMatchSnapshot()
  378. })
  379. test('ArrayExpression', () => {
  380. const { code } = generate(
  381. createRoot({
  382. codegenNode: createArrayExpression([
  383. createSimpleExpression(`foo`, false),
  384. createCallExpression(`bar`, [`baz`])
  385. ])
  386. })
  387. )
  388. expect(code).toMatch(`return [
  389. foo,
  390. bar(baz)
  391. ]`)
  392. expect(code).toMatchSnapshot()
  393. })
  394. test('ConditionalExpression', () => {
  395. const { code } = generate(
  396. createRoot({
  397. codegenNode: createConditionalExpression(
  398. createSimpleExpression(`ok`, false),
  399. createCallExpression(`foo`),
  400. createConditionalExpression(
  401. createSimpleExpression(`orNot`, false),
  402. createCallExpression(`bar`),
  403. createCallExpression(`baz`)
  404. )
  405. )
  406. })
  407. )
  408. expect(code).toMatch(
  409. `return ok
  410. ? foo()
  411. : orNot
  412. ? bar()
  413. : baz()`
  414. )
  415. expect(code).toMatchSnapshot()
  416. })
  417. test('CacheExpression', () => {
  418. const { code } = generate(
  419. createRoot({
  420. cached: 1,
  421. codegenNode: createCacheExpression(
  422. 1,
  423. createSimpleExpression(`foo`, false)
  424. )
  425. }),
  426. {
  427. mode: 'module',
  428. prefixIdentifiers: true
  429. }
  430. )
  431. expect(code).toMatch(`_cache[1] || (_cache[1] = foo)`)
  432. expect(code).toMatchSnapshot()
  433. })
  434. test('CacheExpression w/ isVNode: true', () => {
  435. const { code } = generate(
  436. createRoot({
  437. cached: 1,
  438. codegenNode: createCacheExpression(
  439. 1,
  440. createSimpleExpression(`foo`, false),
  441. true
  442. )
  443. }),
  444. {
  445. mode: 'module',
  446. prefixIdentifiers: true
  447. }
  448. )
  449. expect(code).toMatch(
  450. `
  451. _cache[1] || (
  452. _setBlockTracking(-1),
  453. _cache[1] = foo,
  454. _setBlockTracking(1),
  455. _cache[1]
  456. )
  457. `.trim()
  458. )
  459. expect(code).toMatchSnapshot()
  460. })
  461. test('TemplateLiteral', () => {
  462. const { code } = generate(
  463. createRoot({
  464. codegenNode: createCallExpression(`_push`, [
  465. createTemplateLiteral([
  466. `foo`,
  467. createCallExpression(`_renderAttr`, ['id', 'foo']),
  468. `bar`
  469. ])
  470. ])
  471. }),
  472. { ssr: true, mode: 'module' }
  473. )
  474. expect(code).toMatchInlineSnapshot(`
  475. "
  476. export function ssrRender(_ctx, _push, _parent) {
  477. _push(\`foo\${_renderAttr(id, foo)}bar\`)
  478. }"
  479. `)
  480. })
  481. describe('IfStatement', () => {
  482. test('if', () => {
  483. const { code } = generate(
  484. createRoot({
  485. codegenNode: createBlockStatement([
  486. createIfStatement(
  487. createSimpleExpression('foo', false),
  488. createBlockStatement([createCallExpression(`ok`)])
  489. )
  490. ])
  491. }),
  492. { ssr: true, mode: 'module' }
  493. )
  494. expect(code).toMatchInlineSnapshot(`
  495. "
  496. export function ssrRender(_ctx, _push, _parent) {
  497. if (foo) {
  498. ok()
  499. }
  500. }"
  501. `)
  502. })
  503. test('if/else', () => {
  504. const { code } = generate(
  505. createRoot({
  506. codegenNode: createBlockStatement([
  507. createIfStatement(
  508. createSimpleExpression('foo', false),
  509. createBlockStatement([createCallExpression(`foo`)]),
  510. createBlockStatement([createCallExpression('bar')])
  511. )
  512. ])
  513. }),
  514. { ssr: true, mode: 'module' }
  515. )
  516. expect(code).toMatchInlineSnapshot(`
  517. "
  518. export function ssrRender(_ctx, _push, _parent) {
  519. if (foo) {
  520. foo()
  521. } else {
  522. bar()
  523. }
  524. }"
  525. `)
  526. })
  527. test('if/else-if', () => {
  528. const { code } = generate(
  529. createRoot({
  530. codegenNode: createBlockStatement([
  531. createIfStatement(
  532. createSimpleExpression('foo', false),
  533. createBlockStatement([createCallExpression(`foo`)]),
  534. createIfStatement(
  535. createSimpleExpression('bar', false),
  536. createBlockStatement([createCallExpression(`bar`)])
  537. )
  538. )
  539. ])
  540. }),
  541. { ssr: true, mode: 'module' }
  542. )
  543. expect(code).toMatchInlineSnapshot(`
  544. "
  545. export function ssrRender(_ctx, _push, _parent) {
  546. if (foo) {
  547. foo()
  548. } else if (bar) {
  549. bar()
  550. }
  551. }"
  552. `)
  553. })
  554. test('if/else-if/else', () => {
  555. const { code } = generate(
  556. createRoot({
  557. codegenNode: createBlockStatement([
  558. createIfStatement(
  559. createSimpleExpression('foo', false),
  560. createBlockStatement([createCallExpression(`foo`)]),
  561. createIfStatement(
  562. createSimpleExpression('bar', false),
  563. createBlockStatement([createCallExpression(`bar`)]),
  564. createBlockStatement([createCallExpression('baz')])
  565. )
  566. )
  567. ])
  568. }),
  569. { ssr: true, mode: 'module' }
  570. )
  571. expect(code).toMatchInlineSnapshot(`
  572. "
  573. export function ssrRender(_ctx, _push, _parent) {
  574. if (foo) {
  575. foo()
  576. } else if (bar) {
  577. bar()
  578. } else {
  579. baz()
  580. }
  581. }"
  582. `)
  583. })
  584. })
  585. test('AssignmentExpression', () => {
  586. const { code } = generate(
  587. createRoot({
  588. codegenNode: createAssignmentExpression(
  589. createSimpleExpression(`foo`, false),
  590. createSimpleExpression(`bar`, false)
  591. )
  592. })
  593. )
  594. expect(code).toMatchInlineSnapshot(`
  595. "
  596. return function render(_ctx, _cache) {
  597. with (_ctx) {
  598. return foo = bar
  599. }
  600. }"
  601. `)
  602. })
  603. describe('VNodeCall', () => {
  604. function genCode(node: VNodeCall) {
  605. return generate(
  606. createRoot({
  607. codegenNode: node
  608. })
  609. ).code.match(/with \(_ctx\) \{\s+([^]+)\s+\}\s+\}$/)![1]
  610. }
  611. const mockProps = createObjectExpression([
  612. createObjectProperty(`foo`, createSimpleExpression(`bar`, true))
  613. ])
  614. const mockChildren = createCompoundExpression(['children'])
  615. const mockDirs = createArrayExpression([
  616. createArrayExpression([`foo`, createSimpleExpression(`bar`, false)])
  617. ]) as DirectiveArguments
  618. test('tag only', () => {
  619. expect(genCode(createVNodeCall(null, `"div"`))).toMatchInlineSnapshot(`
  620. "return _createVNode(\\"div\\")
  621. "
  622. `)
  623. expect(genCode(createVNodeCall(null, FRAGMENT))).toMatchInlineSnapshot(`
  624. "return _createVNode(_Fragment)
  625. "
  626. `)
  627. })
  628. test('with props', () => {
  629. expect(genCode(createVNodeCall(null, `"div"`, mockProps)))
  630. .toMatchInlineSnapshot(`
  631. "return _createVNode(\\"div\\", { foo: \\"bar\\" })
  632. "
  633. `)
  634. })
  635. test('with children, no props', () => {
  636. expect(genCode(createVNodeCall(null, `"div"`, undefined, mockChildren)))
  637. .toMatchInlineSnapshot(`
  638. "return _createVNode(\\"div\\", null, children)
  639. "
  640. `)
  641. })
  642. test('with children + props', () => {
  643. expect(genCode(createVNodeCall(null, `"div"`, mockProps, mockChildren)))
  644. .toMatchInlineSnapshot(`
  645. "return _createVNode(\\"div\\", { foo: \\"bar\\" }, children)
  646. "
  647. `)
  648. })
  649. test('with patchFlag and no children/props', () => {
  650. expect(genCode(createVNodeCall(null, `"div"`, undefined, undefined, '1')))
  651. .toMatchInlineSnapshot(`
  652. "return _createVNode(\\"div\\", null, null, 1)
  653. "
  654. `)
  655. })
  656. test('as block', () => {
  657. expect(
  658. genCode(
  659. createVNodeCall(
  660. null,
  661. `"div"`,
  662. mockProps,
  663. mockChildren,
  664. undefined,
  665. undefined,
  666. undefined,
  667. true
  668. )
  669. )
  670. ).toMatchInlineSnapshot(`
  671. "return (_openBlock(), _createBlock(\\"div\\", { foo: \\"bar\\" }, children))
  672. "
  673. `)
  674. })
  675. test('as for block', () => {
  676. expect(
  677. genCode(
  678. createVNodeCall(
  679. null,
  680. `"div"`,
  681. mockProps,
  682. mockChildren,
  683. undefined,
  684. undefined,
  685. undefined,
  686. true,
  687. true
  688. )
  689. )
  690. ).toMatchInlineSnapshot(`
  691. "return (_openBlock(true), _createBlock(\\"div\\", { foo: \\"bar\\" }, children))
  692. "
  693. `)
  694. })
  695. test('with directives', () => {
  696. expect(
  697. genCode(
  698. createVNodeCall(
  699. null,
  700. `"div"`,
  701. mockProps,
  702. mockChildren,
  703. undefined,
  704. undefined,
  705. mockDirs
  706. )
  707. )
  708. ).toMatchInlineSnapshot(`
  709. "return _withDirectives(_createVNode(\\"div\\", { foo: \\"bar\\" }, children), [
  710. [foo, bar]
  711. ])
  712. "
  713. `)
  714. })
  715. test('block + directives', () => {
  716. expect(
  717. genCode(
  718. createVNodeCall(
  719. null,
  720. `"div"`,
  721. mockProps,
  722. mockChildren,
  723. undefined,
  724. undefined,
  725. mockDirs,
  726. true
  727. )
  728. )
  729. ).toMatchInlineSnapshot(`
  730. "return _withDirectives((_openBlock(), _createBlock(\\"div\\", { foo: \\"bar\\" }, children)), [
  731. [foo, bar]
  732. ])
  733. "
  734. `)
  735. })
  736. })
  737. })