0

My application is using astrouxds web components and I am getting a warning in my tests that I would like to fix. I'm also not sure how to assert on a value in the web component.

  console.error node_modules/vue/dist/vue.runtime.common.dev.js:621
    [Vue warn]: Unknown custom element: <rux-toggle> - did you register the component correctly? For recursive components, make sure to provide the "name" option.
    
    found in
    
    ---> <App>
           <Root>

I have setup an example application here. It uses rux-toggle as an example.

The application has a simple template and script in a .vue file.

<template>
  <div id="app">
    <rux-toggle
        id="app-toggle"
        :checked="toggle"
        @click.prevent="toggle = !toggle"></rux-toggle> {{ toggle }}
  </div>
</template>

<script>

export default {
  name: 'App',
  computed: {
    toggle: {
      get() {
        return this.$store.state.toggle
      },
      set(value) {
        this.$store.commit('setToggle', value)
      }
    }
  }
}
</script>

The test uses mount to create a wrapper and test that the web component is checked.

import Vuex from 'vuex';
import {createLocalVue, mount} from '@vue/test-utils';
import storeConfig from '@/store'
import App from '@/App'

describe("App", () => {
  let localVue;
  let store;
  let wrapper;

  beforeEach(() => {
    localVue = createLocalVue();
    localVue.use(Vuex);
    store = new Vuex.Store(storeConfig);
    wrapper = mount(App, {store, localVue});
  });

  it("test toggle default", () => {
    const result = wrapper.find('#app-toggle').checked;
    expect(result).toEqual(true);
  })
})

The test fails with:

Error: expect(received).toEqual(expected) // deep equality

Expected: true
Received: undefined

I'm not exactly sure how to get the checked value of the web component to do the assertion correctly.

Things I have tried

  1. Switched from shallowMount to mount
  2. Register globally using Vue.component(rux-toggle, RuxToggle)
  3. Added Vue.config.productionTip = false to jest setup
9
  • 1
    Why exactly are you importing the RuxToggle component in your main.js file and not in the App.vue file and add it properly to the components property of your App.vue component? Commented Jul 26, 2021 at 15:18
  • 1
    If you want to register it globally you should add Vue.component('rux-toggle', RuxToggle) to the main.js file. Else it makes no sense to import the component like that and ignore that eslint tells you you're doing something fishy :D Commented Jul 26, 2021 at 15:20
  • I'm not 100% sure from what I saw the imported file has customElements.define('rux-toggle', RuxToggle); at the bottom. I thought maybe this should be global rather than in each component that uses it. Commented Jul 26, 2021 at 15:24
  • 1
    Yeah no I'm just dumb, I actually thought the rux thing is a "normal" component but after considering your question it's obviously a web component you want to use :D Sorry for that. There is another answer to this question that I believe might solve your issue. It's right here Commented Jul 26, 2021 at 15:30
  • 1
    You might be able to avoid those by adding a setup file for jest (you're using jest I assume?) So add a index.js or index.ts file to your test directory or wherver. In it you'll put Vue.config.productionTip = false;. Then add setupFiles: ["<rootDir>/tests/index.ts"] to your jest.config.js file. Commented Jul 26, 2021 at 15:42

1 Answer 1

2

The rux-toggle component is only registered in main.js, leading to the warnings/errors you observed.

Regarding your attempts:

  1. Switched from shallowMount to mount

Custom elements must be explicitly registered by your own code, and mount isn't going to do that for you.

  1. Register globally using Vue.component(rux-toggle, RuxToggle)

RuxToggle from @astrouxds/rux-toggle is a LitElement, which does not meet the requirements of a Vue component definition that Vue.component() expects.

  1. Added Vue.config.productionTip = false to jest setup

That merely disables a browser console warning about using the developent build in production, and has nothing to do with custom elements or component registration. Perhaps you meant to use Vue.config.ignoredElements = ['rux-toggle'], which would mute the warning about unknown custom elements (this is actually unnecessary in unit tests), but it does not register the custom element.

Solution

To properly use rux-toggle in your tests:

  1. Create a Jest setup file that registers rux-toggle. Importing it is enough to do that, as the custom element registration happens as a side effect.

    // tests/jest.setup.js
    import '@astrouxds/rux-toggle'
    
  2. Configure Jest to use the setup file:

    // jest.config.js
    module.exports = {
      setupFiles: ['<rootDir>/tests/jest.setup.js'],
    }
    
  3. Configure Jest to transpile @astrouxds/rux-toggle:

    // jest.config.js
    module.exports = {
      transformIgnorePatterns: ['/node_modules//(?!@astrouxds/rux-toggle)'],
    }
    
  4. Your project uses jest 24.9.0, which depends on jsdom 15, which does not support Custom Elements. To enable Custom Elements in this version of Jest, install jest-environment-jsdom-sixteen:

    npm install -D jest-environment-jsdom-sixteen
    
  5. Configure Jest to use that test environment:

    // jest.config.js
    module.exports = {
      testEnvironment: 'jest-environment-jsdom-sixteen',
    }
    
  6. Update your test to read the checked attribute with attributes('checked'), and verify the value is "true" (attributes are string values):

    it("test toggle default", () => {
      const result = wrapper.find('#app-toggle').attributes('checked');
      expect(result).toEqual('true');
    })
    

GitHub PR

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks! This all worked. My team can now write tests!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.