vuejs / vue-jest

Jest Vue transformer
MIT License
748 stars 156 forks source link

Test failing because of template's content in SFC #235

Closed Edmund1645 closed 4 years ago

Edmund1645 commented 4 years ago

I'm beginning to write unit tests for a project and the first test suite I'm writing is failing with this error:

Templates should only be responsible for mapping the state to the UI. Avoid placing tags with side-effects in your templates, such as <style>, as they
 will not be parsed.

But I've tried remove ing the <style></style> tag and it still fails. The only thing that solved it was removing the contents of <template></template> and leaving the root node element.

This is the full error I get.

 FAIL  __tests__/SideBar.spec.js
  ● Test suite failed to run

    [vue-jest] Error: Vue template compilation failed

      at error (node_modules/vue-jest/lib/throw-error.js:2:9)
      at compileTemplate (node_modules/vue-jest/lib/template-compiler.js:29:5)
      at Object.module.exports [as process] (node_modules/vue-jest/lib/process.js:66:29)
      at ScriptTransformer.transformSource (node_modules/@jest/transform/build/ScriptTransformer.js:479:35)
      at ScriptTransformer._transformAndBuildScript (node_modules/@jest/transform/build/ScriptTransformer.js:569:40)
      at ScriptTransformer.transform (node_modules/@jest/transform/build/ScriptTransformer.js:609:25)

my SideBar.vue component:

<template>
  <div
    id="sidebar"
    class="h-full md:w-1/3 lg:w-1/5 xl:w-3/13 fixed bg-m-army-green"
  >
    <div
      id="borrower-id"
      class="p-3 w-9/12 mx-auto mt-10 border rounded-lg border-m-army-green-lighter"
    >
      <h3 class="text-white text-3xl font-medium inline-block ml-3 mb-0">
        {{ businessInitials }}
      </h3>
      <p class="ml-3 -mt-2 text-sm text-gray-500">ID: {{ userId }}</p>
    </div>

    <!-- conditionally render the sidebar navigation -->
    <div v-if="!onboardingScreen" id="menu-buttons">
      <div
        id="menus"
        class="grid grid-cols-3 w-10/12 gap-4 row-gap-10 mt-20  mx-auto"
      >
        <div class="flex flex-col content-center">
          <nuxt-link
            to="/dashboard"
            tag="button"
            class="w-12 h-12 xl:h-16 xl:w-16 mx-auto rounded-md border border-gray-700 p-3 focus:outline-none disabled:cursor-not-allowed sidebar-button-link"
            :disabled="onboardingScreen"
          >
            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 62.99 60.23">
              <defs>
                <style>
                  .cls-1 {
                    fill: #68717a;
                  }
                  button.nuxt-link-exact-active:not([disabled]) .cls-1 {
                    fill: #02cb63;
                  }
                </style>
              </defs>
              <title>Home</title>
              <g id="Layer_2" data-name="Layer 2">
                <g id="Layer_1-2" data-name="Layer 1">
                  <path
                    class="cls-1"
                    d="M49.06,54.23H14.22V26.59h-6V56.17a4.06,4.06,0,0,0,4.06,4.06H51a4.06,4.06,0,0,0,4.06-4.06V26.59h-6Z"
                  />
                  <path
                    class="cls-1"
                    d="M34,.77a4.05,4.05,0,0,0-4.74,0L0,21.66l3.49,4.88L31.64,6.45,59.47,26.54,63,21.67Z"
                  />
                  <path
                    class="cls-1"
                    d="M42.52,49.93V36a4,4,0,0,0-3.92-4.06H24.68A4,4,0,0,0,20.77,36v14h6v-12h9.75v12Z"
                  />
                </g>
              </g>
            </svg>
          </nuxt-link>
          <p class="text-white text-center mt-2 text-md sidebar-labels">Home</p>
        </div>
        <div class="flex flex-col content-center">
          <nuxt-link
            to="/dashboard/wallet"
            tag="button"
            class="w-12 h-12 xl:h-16 xl:w-16 mx-auto rounded-md border border-gray-700 p-3 focus:outline-none disabled:cursor-not-allowed sidebar-button-link"
            :disabled="onboardingScreen"
          >
            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 58.88 52.7">
              <defs>
                <style>
                  .cls-1 {
                    fill: #68717a;
                  }
                  button.nuxt-link-exact-active:not([disabled]) .cls-1 {
                    fill: #02cb63;
                  }
                </style>
              </defs>
              <title>Wallet</title>
              <g id="Layer_2" data-name="Layer 2">
                <g id="Layer_1-2" data-name="Layer 1">
                  <path
                    class="cls-1"
                    d="M58.87,9.1A9.11,9.11,0,0,0,49.77,0H19.32a4.25,4.25,0,0,0-4.25,4.25V9.2h6V6h28.7a3.1,3.1,0,0,1,0,6.2H9.22A4.26,4.26,0,0,0,5,16.45v6.72H4.25A4.26,4.26,0,0,0,0,27.42v9.71a4.26,4.26,0,0,0,4.25,4.25H5v7.07A4.25,4.25,0,0,0,9.22,52.7h45.4a4.25,4.25,0,0,0,4.26-4.25V9.1ZM6,35.38V29.17H18.83a3.11,3.11,0,1,1,0,6.21ZM11,46.7V41.38h7.86a9.11,9.11,0,1,0,0-18.21H11v-5h38.8a9.16,9.16,0,0,0,3.11-.55V46.7Z"
                  />
                </g>
              </g>
            </svg>
          </nuxt-link>
          <p class="text-white text-center mt-2 text-md sidebar-labels">
            Wallet
          </p>
        </div>
        <div class="flex flex-col content-center">
          <nuxt-link
            to="/dashboard/transactions"
            tag="button"
            class="w-12 h-12 xl:h-16 xl:w-16 mx-auto rounded-md border border-gray-700 p-3 focus:outline-none disabled:cursor-not-allowed sidebar-button-link"
            :disabled="onboardingScreen"
          >
            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 59.3 45.85">
              <defs>
                <style>
                  .cls-1 {
                    fill: #68717a;
                  }
                  button.nuxt-link-exact-active:not([disabled]) .cls-1 {
                    fill: #02cb63;
                  }
                </style>
              </defs>
              <title>Transaction</title>
              <g id="Layer_2" data-name="Layer 2">
                <g id="Layer_1-2" data-name="Layer 1">
                  <path
                    class="cls-1"
                    d="M46.19,28.38v-24A4.37,4.37,0,0,0,41.83,0H4.37A4.37,4.37,0,0,0,0,4.37v24a4.37,4.37,0,0,0,4.37,4.37H41.83A4.37,4.37,0,0,0,46.19,28.38ZM40.19,6v4.26H6V6ZM6,26.75V16.26H40.19V26.75Z"
                  />
                  <path
                    class="cls-1"
                    d="M54.93,13.11H49.75v6H53.3V39.85H19.11V36h-6v5.46a4.36,4.36,0,0,0,4.36,4.36H54.93a4.37,4.37,0,0,0,4.37-4.36v-24A4.37,4.37,0,0,0,54.93,13.11Z"
                  />
                </g>
              </g>
            </svg>
          </nuxt-link>
          <p class="text-white text-center mt-2 text-md sidebar-labels">
            Transactions
          </p>
        </div>
        <div class="flex flex-col content-center">
          <nuxt-link
            to="/dashboard/report"
            tag="button"
            class="w-12 h-12 xl:h-16 xl:w-16 mx-auto rounded-md border border-gray-700 p-3 focus:outline-none disabled:cursor-not-allowed sidebar-button-link"
            :disabled="onboardingScreen"
          >
            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 51.68 56.96">
              <defs>
                <style>
                  .cls-1 {
                    fill: #68717a;
                  }
                  button.nuxt-link-exact-active:not([disabled]) .cls-1 {
                    fill: #02cb63;
                  }
                </style>
              </defs>
              <title>Report</title>
              <g id="Layer_2" data-name="Layer 2">
                <g id="Layer_1-2" data-name="Layer 1">
                  <path
                    class="cls-1"
                    d="M47.43,0H17.52a4.26,4.26,0,0,0-2.85,1.1L1.4,13.08A4.24,4.24,0,0,0,0,16.23V52.71A4.26,4.26,0,0,0,4.25,57H47.43a4.25,4.25,0,0,0,4.25-4.25V4.25A4.25,4.25,0,0,0,47.43,0ZM45.68,51H6V17L18.19,6H45.68Z"
                  />
                  <rect
                    class="cls-1"
                    x="11.82"
                    y="16.47"
                    width="12.04"
                    height="6"
                    transform="translate(-0.12 0.11) rotate(-0.35)"
                  />
                  <rect
                    class="cls-1"
                    x="11.82"
                    y="29.89"
                    width="22.88"
                    height="6"
                    transform="translate(-0.11 0.07) rotate(-0.18)"
                  />
                  <rect
                    class="cls-1"
                    x="11.82"
                    y="39.03"
                    width="22.88"
                    height="6"
                    transform="translate(-0.11 0.06) rotate(-0.15)"
                  />
                </g>
              </g>
            </svg>
          </nuxt-link>
          <p class="text-white text-center mt-2 text-md sidebar-labels">
            Report
          </p>
        </div>
        <div class="flex flex-col content-center">
          <nuxt-link
            to="/dashboard/pending"
            tag="button"
            class="w-12 h-12 xl:h-16 xl:w-16 mx-auto rounded-md border border-gray-700 p-3 focus:outline-none disabled:cursor-not-allowed sidebar-button-link"
            :disabled="onboardingScreen"
          >
            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 49.37 58.34">
              <defs>
                <style>
                  .cls-1 {
                    fill: #68717a;
                  }
                  button.nuxt-link-exact-active:not([disabled]) .cls-1 {
                    fill: #02cb63;
                  }
                </style>
              </defs>
              <title>Pending</title>
              <g id="Layer_2" data-name="Layer 2">
                <g id="Layer_1-2" data-name="Layer 1">
                  <rect class="cls-1" x="12.46" width="23.57" height="6" />
                  <path
                    class="cls-1"
                    d="M49.37,14.47l-4.24-4.24-5.31,5.31a24.24,24.24,0,1,0,4.08,4.39ZM24.24,52.34A18.25,18.25,0,1,1,42.48,34.09,18.27,18.27,0,0,1,24.24,52.34Z"
                  />
                  <path
                    class="cls-1"
                    d="M27.24,29.21V23.72h-6v5.49a5.74,5.74,0,1,0,6,0ZM24,34.09a.27.27,0,0,1,.53,0C24.51,34.38,24,34.38,24,34.09Z"
                  />
                </g>
              </g>
            </svg>
          </nuxt-link>
          <p class="text-white text-center mt-2 text-md sidebar-labels">
            Pending
          </p>
        </div>
        <div class="flex flex-col content-center">
          <nuxt-link
            to="/dashboard/approved"
            tag="button"
            class="w-12 h-12 xl:h-16 xl:w-16 mx-auto rounded-md border border-gray-700 p-3 focus:outline-none disabled:cursor-not-allowed sidebar-button-link"
            :disabled="onboardingScreen"
          >
            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 55.88 60.23">
              <defs>
                <style>
                  .cls-1 {
                    fill: #68717a;
                  }
                  button.nuxt-link-exact-active:not([disabled]) .cls-1 {
                    fill: #02cb63;
                  }
                </style>
              </defs>
              <title>Approved</title>
              <g id="Layer_2" data-name="Layer 2">
                <g id="Layer_1-2" data-name="Layer 1">
                  <path
                    class="cls-1"
                    d="M6,6H44V23.6h6V3.91A3.92,3.92,0,0,0,46.1,0H3.91A3.91,3.91,0,0,0,0,3.91V51.63a3.92,3.92,0,0,0,3.91,3.91H19.26v-6H6V40.9H19.26v-6H6Z"
                  />
                  <path
                    class="cls-1"
                    d="M39.38,27.23a16.5,16.5,0,1,0,16.5,16.5A16.52,16.52,0,0,0,39.38,27.23Zm0,27a10.5,10.5,0,1,1,10.5-10.5A10.51,10.51,0,0,1,39.38,54.23Z"
                  />
                  <polygon
                    class="cls-1"
                    points="38.11 43.02 35.69 40.6 31.45 44.85 38.11 51.51 47.3 42.31 43.06 38.07 38.11 43.02"
                  />
                </g>
              </g>
            </svg>
          </nuxt-link>
          <p class="text-white text-center mt-2 text-md sidebar-labels">
            Approved
          </p>
        </div>
      </div>
      <button
        class="block font-medium text-lg focus:outline-none bg-m-green text-white w-5/6 mx-auto py-3 mt-6 rounded-sm disabled:bg-gray-700 disabled:text-white disabled:cursor-not-allowed"
        :disabled="onboardingScreen"
      >
        Request Loan
      </button>
    </div>

    <!-- Empty sidebar -->
    <div v-else id="blank-menu">
      <div
        id="menus"
        class="grid grid-cols-3 w-10/12 gap-4 row-gap-10 mt-20  mx-auto"
      >
        <div class="menu-item">
          <div
            class="w-12 h-12 xl:w-16 xl:h-16 mx-auto rounded md bg-m-gray-darker opacity-50"
          ></div>
          <div
            class="menu-item-text h-3 w-12 xl:w-16 rounded-full mt-3 mx-auto bg-m-gray-darker opacity-50"
          ></div>
        </div>
        <div class="menu-item">
          <div
            class="w-12 h-12 xl:w-16 xl:h-16 mx-auto rounded-md bg-m-gray-darker opacity-50"
          ></div>
          <div
            class="menu-item-text h-3 w-12 xl:w-16 rounded-full mt-3 mx-auto bg-m-gray-darker opacity-50"
          ></div>
        </div>
        <div class="menu-item">
          <div
            class="w-12 h-12 xl:w-16 xl:h-16 mx-auto rounded-md bg-m-gray-darker opacity-50"
          ></div>
          <div
            class="menu-item-text h-3 w-12 xl:w-16 rounded-full mt-3 mx-auto bg-m-gray-darker opacity-50"
          ></div>
        </div>
        <div class="menu-item">
          <div
            class="w-12 h-12 xl:w-16 xl:h-16 mx-auto rounded-md bg-m-gray-darker opacity-50"
          ></div>
          <div
            class="menu-item-text h-3 w-12 xl:w-16 rounded-full mt-3 mx-auto bg-m-gray-darker opacity-50"
          ></div>
        </div>
        <div class="menu-item">
          <div
            class="w-12 h-12 xl:w-16 xl:h-16 mx-auto rounded-md bg-m-gray-darker opacity-50"
          ></div>
          <div
            class="menu-item-text h-3 w-12 xl:w-16 rounded-full mt-3 mx-auto bg-m-gray-darker opacity-50"
          ></div>
        </div>
        <div class="menu-item">
          <div
            class="w-12 h-12 xl:w-16 xl:h-16 mx-auto rounded-md bg-m-gray-darker opacity-50"
          ></div>
          <div
            class="menu-item-text h-3 w-12 xl:w-16 rounded-full mt-3 mx-auto bg-m-gray-darker opacity-50"
          ></div>
        </div>
      </div>
      <div
        class="bg-m-gray-darker opacity-50 w-5/6 mx-auto py-6 mt-8 rounded-sm "
      ></div>
    </div>
    <div id="support" class="px-6 mt-16">
      <button class="block focus:outline-none py-3 my-5 text-white font-medium">
        <img
          src="~/assets/vectors/ui/sidebar/unknown.svg"
          alt=""
          width="35px"
          class="inline-block"
        />
        Help
      </button>
      <button class="block focus:outline-none py-3 my-5 text-white font-medium">
        <img
          src="~/assets/vectors/ui/sidebar/settings.svg"
          alt=""
          width="35px"
          class="inline-block"
        />
        Settings
      </button>
    </div>
  </div>
</template>
<script>
export default {
  name: 'SideBar',
  props: {
    onboardingScreen: {
      type: Boolean,
      default: false
    },
    businessInitials: {
      type: String,
      required: true
    },
    userId: {
      type: Number,
      required: true
    }
  }
}
</script>
<style lang="postcss" scoped>
button.nuxt-link-exact-active:not([disabled]) {
  border-color: #02cb63;
}
button.sidebar-button-link:disabled + p.sidebar-labels {
  color: #68717a;
}
</style>

In Sidebar.spec.js file

import { shallowMount } from '@vue/test-utils'
import SideBar from '@/components/dashboards/SideBar.vue'

describe('SideBar.vue', () => {
  let wrapper
  beforeEach(() => {
    wrapper = shallowMount(SideBar, {
      propsData: {
        userId: 900,
        businessInitials: 'Mandango'
      }
    })
  })
  it('should render a blank menu when onboardingScreen prop is true', () => {
    wrapper.setProps({ onboardingScreen: true })
    expect(wrapper.vm.onboardingScreen).toBe(true)
    expect(wrapper.find('div#menu-buttons').exists()).toBe(false)
    expect(wrapper.find('div#blank-menu').exists()).toBe(true)
  })
})

here's my jest config in package.json

 "jest": {
    "moduleFileExtensions": [
      "js",
      "json",
      "vue"
    ],
    "moduleNameMapper": {
      "^@/(.*)$": "<rootDir>/$1",
      "^~/(.*)$": "<rootDir>/$1"
    },
    "transform": {
      ".*\\.(vue)$": "vue-jest",
      "^.+\\.js$": "babel-jest"
    }
  }

I noticed removing all inline SVGs seemed to make the error gone but I need the interactivity of the icons so I cannot use plain img tags.

jameesjohn commented 4 years ago

The issue seems to be from the style tags placed in the SVG elements.

Edmund1645 commented 4 years ago

Got it working @jameesjohn, I removed the style tags since they were all repetitive and used placed the two classes in the component's style instead.