compileTemplate.spec.ts 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  1. import {
  2. compileTemplate,
  3. SFCTemplateCompileOptions
  4. } from '../src/compileTemplate'
  5. import { parse, SFCTemplateBlock } from '../src/parse'
  6. function compile(opts: Omit<SFCTemplateCompileOptions, 'id'>) {
  7. return compileTemplate({
  8. ...opts,
  9. id: ''
  10. })
  11. }
  12. test('should work', () => {
  13. const source = `<div><p>{{ render }}</p></div>`
  14. const result = compile({ filename: 'example.vue', source })
  15. expect(result.errors.length).toBe(0)
  16. expect(result.source).toBe(source)
  17. // should expose render fn
  18. expect(result.code).toMatch(`export function render(`)
  19. })
  20. test('preprocess pug', () => {
  21. const template = parse(
  22. `
  23. <template lang="pug">
  24. body
  25. h1 Pug Examples
  26. div.container
  27. p Cool Pug example!
  28. </template>
  29. `,
  30. { filename: 'example.vue', sourceMap: true }
  31. ).descriptor.template as SFCTemplateBlock
  32. const result = compile({
  33. filename: 'example.vue',
  34. source: template.content,
  35. preprocessLang: template.lang
  36. })
  37. expect(result.errors.length).toBe(0)
  38. })
  39. test('warn missing preprocessor', () => {
  40. const template = parse(`<template lang="unknownLang">hi</template>\n`, {
  41. filename: 'example.vue',
  42. sourceMap: true
  43. }).descriptor.template as SFCTemplateBlock
  44. const result = compile({
  45. filename: 'example.vue',
  46. source: template.content,
  47. preprocessLang: template.lang
  48. })
  49. expect(result.errors.length).toBe(1)
  50. })
  51. test('transform asset url options', () => {
  52. const input = { source: `<foo bar="~baz"/>`, filename: 'example.vue' }
  53. // Object option
  54. const { code: code1 } = compile({
  55. ...input,
  56. transformAssetUrls: {
  57. tags: { foo: ['bar'] }
  58. }
  59. })
  60. expect(code1).toMatch(`import _imports_0 from 'baz'\n`)
  61. // legacy object option (direct tags config)
  62. const { code: code2 } = compile({
  63. ...input,
  64. transformAssetUrls: {
  65. foo: ['bar']
  66. }
  67. })
  68. expect(code2).toMatch(`import _imports_0 from 'baz'\n`)
  69. // false option
  70. const { code: code3 } = compile({
  71. ...input,
  72. transformAssetUrls: false
  73. })
  74. expect(code3).not.toMatch(`import _imports_0 from 'baz'\n`)
  75. })
  76. test('source map', () => {
  77. const template = parse(
  78. `
  79. <template>
  80. <div><p>{{ render }}</p></div>
  81. </template>
  82. `,
  83. { filename: 'example.vue', sourceMap: true }
  84. ).descriptor.template as SFCTemplateBlock
  85. const result = compile({
  86. filename: 'example.vue',
  87. source: template.content
  88. })
  89. expect(result.map).toMatchSnapshot()
  90. })
  91. test('template errors', () => {
  92. const result = compile({
  93. filename: 'example.vue',
  94. source: `<div :foo
  95. :bar="a[" v-model="baz"/>`
  96. })
  97. expect(result.errors).toMatchSnapshot()
  98. })
  99. test('preprocessor errors', () => {
  100. const template = parse(
  101. `
  102. <template lang="pug">
  103. div(class='class)
  104. </template>
  105. `,
  106. { filename: 'example.vue', sourceMap: true }
  107. ).descriptor.template as SFCTemplateBlock
  108. const result = compile({
  109. filename: 'example.vue',
  110. source: template.content,
  111. preprocessLang: template.lang
  112. })
  113. expect(result.errors.length).toBe(1)
  114. const message = result.errors[0].toString()
  115. expect(message).toMatch(`Error: example.vue:3:1`)
  116. expect(message).toMatch(
  117. `The end of the string reached with no closing bracket ) found.`
  118. )
  119. })