vue-transform.js 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657
  1. /**
  2. * Jest transformer for uni-app `.vue` Single File Components (Vue 2.7).
  3. *
  4. * PURPOSE: cfc-frontend's default jest.config.js only transforms `.js` via
  5. * babel-jest, so `.vue` SFCs cannot be imported by tests. This transformer
  6. * compiles the SFC `<script>` block (Options API) to CommonJS and precompiles
  7. * the `<template>` block to a Vue 2 render function (the default `vue` entry
  8. * in Node is runtime-only and has no template compiler), so tests can `mount`
  9. * real page components with `@vue/test-utils`.
  10. *
  11. * TEST-ONLY infrastructure: this file lives under `__tests__/` and is NOT part
  12. * of the app runtime. It does not modify any `pages/` / `utils/` business code.
  13. */
  14. const { parseComponent, compileTemplate } = require('@vue/compiler-sfc')
  15. const babel = require('@babel/core')
  16. module.exports = {
  17. process(src, filename) {
  18. const descriptor = parseComponent(src, { filename })
  19. if (descriptor.errors && descriptor.errors.length) {
  20. throw new Error('[vue-transform] SFC parse error in ' + filename + ':\n' + descriptor.errors.join('\n'))
  21. }
  22. let code = ''
  23. if (descriptor.script && descriptor.script.content) {
  24. // Options API: `export default {...}` -> `const __sfc_main = {...}`
  25. code += descriptor.script.content.replace(/export\s+default/, 'const __sfc_main =')
  26. } else {
  27. code += 'const __sfc_main = {}'
  28. }
  29. if (descriptor.template && descriptor.template.content) {
  30. const res = compileTemplate({
  31. source: descriptor.template.content,
  32. filename,
  33. id: filename.replace(/[^\w]/g, '_')
  34. })
  35. if (res.errors && res.errors.length) {
  36. throw new Error('[vue-transform] template compile error in ' + filename + ':\n' + res.errors.join('\n'))
  37. }
  38. code += '\n' + res.code
  39. code += '\n__sfc_main.render = render'
  40. code += '\n__sfc_main.staticRenderFns = staticRenderFns'
  41. }
  42. code += '\nmodule.exports = __sfc_main'
  43. // Transpile the assembled module to CommonJS (the <script> block keeps ES
  44. // `import` statements; Node cannot execute them in a jest CJS module).
  45. const out = babel.transformSync(code, {
  46. filename,
  47. presets: [['@babel/preset-env', { targets: { node: 'current' } }]],
  48. babelrc: false,
  49. configFile: false
  50. })
  51. return { code: out.code, map: null }
  52. }
  53. }