0

I have a Vue.js component that uses a jQuery-based library called Summernote:

<template>
  <div id="summernote" class="full-height"/>
</template>

<script>
  //See https://github.com/summernote/summernote/issues/2597
  import $ from 'jquery'
  import 'summernote/dist/summernote-lite.min.css'
  import 'summernote/dist/summernote-lite.min.js'
  export default {
    name: "summernote",
    mounted() {
      console.log("mounting...")
      $('#summernote').summernote({
        focus: true,
        callbacks: {
          onInit: function () {
            console.log('Summernote is launched');
          }
        }
      });

      $('#summernote').on('summernote.change', function (we, contents) {
        console.log("content.changed",contents);
      });
      console.log("summernote mounted");
    },
  }
</script>

I tried to test it with Jest using @vue/test-utils using this code:

import { mount } from '@vue/test-utils'
import summernote from './Summernote.vue'

describe('Mount Summernote', () => {
  const elem = document.createElement('div')
  if (document.body) {
    document.body.appendChild(elem)
  }
  const wrapper = mount(summernote,{ attachTo: elem })

  test("load",async ()=>{
    console.log(wrapper.html())
    await wrapper.vm.$nextTick()
    console.log("done")
  })
})

Here's the output of the test:

  console.log test/jest/__tests__/Summernote.vue:13
    mounting...

  console.error node_modules/vue/dist/vue.common.dev.js:630
    [Vue warn]: Error in mounted hook: "TypeError: Cannot read property 'createRange' of undefined"
    
    found in
    
    ---> <Summernote>
           <Root>

  console.error node_modules/vue/dist/vue.common.dev.js:1893
    TypeError: Cannot read property 'createRange' of undefined
        at Object.createFromSelection (node_modules/summernote/dist/webpack:/src/js/base/core/range.js:819:44)
        at Object.create (node_modules/summernote/dist/webpack:/src/js/base/core/range.js:783:31)
        at t.makeSnapshot (node_modules/summernote/dist/webpack:/src/js/base/editing/History.js:13:23)
        at t.recordUndo (node_modules/summernote/dist/webpack:/src/js/base/editing/History.js:119:26)
        at t.initialize (node_modules/summernote/dist/webpack:/src/js/base/module/Editor.js:426:18)
        at t.initializeModule (node_modules/summernote/dist/webpack:/src/js/base/Context.js:156:14)
        at forEach (node_modules/summernote/dist/webpack:/src/js/base/Context.js:79:12)
        at Array.forEach (<anonymous>)
        at t._initialize (node_modules/summernote/dist/webpack:/src/js/base/Context.js:78:31)
        at t.initialize (node_modules/summernote/dist/webpack:/src/js/base/Context.js:31:10)
        at new t (node_modules/summernote/dist/webpack:/src/js/base/Context.js:23:10)
        at HTMLDivElement.<anonymous> (node_modules/summernote/dist/webpack:/src/js/summernote.js:28:25)
        at Function.each (node_modules/jquery/dist/jquery.js:381:19)
        at jQuery.fn.init.each (node_modules/jquery/dist/jquery.js:203:17)
        at jQuery.fn.init.summernote (node_modules/summernote/dist/webpack:/src/js/summernote.js:25:10)
        at VueComponent.mounted (test/jest/__tests__/Summernote.vue:14:1)
        at invokeWithErrorHandling (node_modules/vue/dist/vue.common.dev.js:1859:57)
        at callHook (node_modules/vue/dist/vue.common.dev.js:4216:7)
        at Object.insert (node_modules/vue/dist/vue.common.dev.js:3142:7)
        at invokeInsertHook (node_modules/vue/dist/vue.common.dev.js:6337:28)
        at VueComponent.patch [as __patch__] (node_modules/vue/dist/vue.common.dev.js:6554:5)
        at VueComponent.Vue._update (node_modules/vue/dist/vue.common.dev.js:3942:19)
        at VueComponent.updateComponent (node_modules/vue/dist/vue.common.dev.js:4063:10)
        at Watcher.get (node_modules/vue/dist/vue.common.dev.js:4474:25)
        at new Watcher (node_modules/vue/dist/vue.common.dev.js:4463:12)
        at mountComponent (node_modules/vue/dist/vue.common.dev.js:4070:3)
        at VueComponent.Object.<anonymous>.Vue.$mount (node_modules/vue/dist/vue.common.dev.js:9040:10)
        at VueComponent.Object.<anonymous>.Vue.$mount (node_modules/vue/dist/vue.common.dev.js:11940:16)
        at mount (node_modules/@vue/test-utils/dist/vue-test-utils.js:13855:21)
        at Suite.<anonymous> (test/jest/__tests__/Summernote.spec.js:9:19)
        at addSpecsToSuite (node_modules/jest-jasmine2/build/jasmine/Env.js:496:51)
        at Env.describe (node_modules/jest-jasmine2/build/jasmine/Env.js:466:11)
        at describe (node_modules/jest-jasmine2/build/jasmine/jasmineLight.js:81:18)
        at Object.<anonymous> (test/jest/__tests__/Summernote.spec.js:4:1)
        at Runtime._execModule (node_modules/jest-runtime/build/index.js:867:68)
        at Runtime._loadModule (node_modules/jest-runtime/build/index.js:577:12)
        at Runtime.requireModule (node_modules/jest-runtime/build/index.js:433:10)
        at node_modules/jest-jasmine2/build/index.js:202:13
        at Generator.next (<anonymous>)
        at asyncGeneratorStep (node_modules/jest-jasmine2/build/index.js:27:24)
        at _next (node_modules/jest-jasmine2/build/index.js:47:9)
        at node_modules/jest-jasmine2/build/index.js:52:7
        at new Promise (<anonymous>)
        at node_modules/jest-jasmine2/build/index.js:44:12
        at _jasmine (node_modules/jest-jasmine2/build/index.js:207:19)
        at jasmine2 (node_modules/jest-jasmine2/build/index.js:60:19)
        at node_modules/jest-runner/build/runTest.js:385:24
        at Generator.next (<anonymous>)
        at asyncGeneratorStep (node_modules/jest-runner/build/runTest.js:161:24)
        at _next (node_modules/jest-runner/build/runTest.js:181:9)
        at processTicksAndRejections (internal/process/task_queues.js:97:5)

It appears that the summernote code is trying to interact with certain types of browsers and fails. Is there some settings in Jest or on the DOM to modify that would make this code not fail?

UPDATE: thank you @Phiter for recommending the use of attachTo(). It got me further than when I started.

User1
  • 39,458
  • 69
  • 187
  • 265
  • 2
    Man I would not suggest mixing jquery with vue. There are tons of great WISIWYG libraries for Vue. However, in this case, seems like you need to wait for summernote to load, which seems to be running asynchronously. Try changing this test suite to an async function and then run `await wrapper.vm.$nextTick()` before `console.log('done')` to see if something happens. It might also be related to DOM, so I would suggest trying to pass a config parameter to `mount`: { attachToDocument: true }. Try it and see if you get a different result. – Phiter Jul 28 '20 at 02:26
  • attachTo helped and I updated the question with the result. Now I have a different error. It looks like there is some browser dependent code that is causing trouble. I hope there's a simple fix??? – User1 Jul 28 '20 at 17:43
  • 1
    You should not test third party libraries in your code. Can you mock it or something? You could test it in an e2e test, but unit tests are supposed to be small and test only your own code. – Phiter Jul 28 '20 at 18:55

0 Answers0