1

I'm new to testing and I'm trying to test a component with Vue test-utils, but I'm having trouble when I try to test a click on a imported component.

This is my test file:

  import { Table, Input } from 'ant-design-vue';
  import { CheckOutlined, EditOutlined } from '@ant-design/icons-vue';
  
  import { shallowMount } from '@vue/test-utils';
  let wrapper;
  beforeEach(() => {
    wrapper = shallowMount(TableEditable, {
      global: {
        components: {
          'a-table': Table,
          'a-input': Input,
          'check-outlined': CheckOutlined,
          'edit-outlined': EditOutlined,
        }
      },
      emits: ['edit', 'save'],
      props: {
        tableData: {
          "data":[
            {"id":"0","monday":"0"}],
          "columns":[
            {"title":"Mon","dataIndex":"monday","slots":{"customRender":"monday"}}]
        },
        dataSrc: [{"id":"0","monday":"0","tuesday":"0","wednesday":"0","thursday":"0","friday":"0","saturday":"9","sunday":"10","key":"0"}]
      }
    })
  })
  
  describe('first test', () => {
    it('first test: check if theres a class name', () => {
      expect(wrapper.classes()).toContain('tableEditable')
    })
    it('click and emit buttons', async () => {
        await wrapper.findComponent({ref: 'edit-outlined'})
        await wrapper.trigger('click')
        expect(wrapper.emitted()).toHaveProperty('edit')
  
      })
  })

This is my component:

  <template>
     <a-table bordered :data-source="dataSrc" :columns="tableData.columns" :pagination="false" class="tableEditable">
      <template #title>
        <div class="formLayoutCrud">
          <p>{{this.title}}</p>
          <input-multiple-button :name="'buttonOptions'" :value="'percentage'" :options="this.buttonOptions"> </input-multiple-button>
        </div>
      </template>
      <template v-for="col in this.editableCells" #[col]="{ column, text, record }" :key="col">
        <div class="editable-cell">
          <div v-if="editableTableData[record.key + '|' + column.key] !== undefined" class="editable-cell-input-wrapper">
            <a-input v-model:value="editableTableData[record.key + '|' + column.key]" @pressEnter="save(record.key, column.key)" type="number" />
            <check-outlined class="editable-cell-icon-check" @click="save(record.key, column.key)" />
          </div>
          <div v-else class="editable-cell-text-wrapper">
            {{ text || ' ' }}
            <edit-outlined class="editable-cell-icon" @click="edit(record.key, column.key)" />
          </div>
        </div>
      </template>
    </a-table>
  </template>
  <script>
  
  import { CheckOutlined, EditOutlined } from '@ant-design/icons-vue';
  
  import InputMultipleButton from '@/components/crudForm/InputMultipleButton.vue';
  
  export default {
    name: 'TableEditable',
    props: {
      title: String,
      buttonOptions: Array,
      editableCells: Array,
      tableData: Object,
      dataSrc: Array,
      editableDataProp: Object
    },
    emits: ['edit', 'save'],
    components: {
      CheckOutlined,
      EditOutlined,
      InputMultipleButton
    },
    data(){
      return {
        editableTableData: this.editableDataProp
      }
    },
    methods: {
      edit(row, column) {
        this.$emit('edit', row, column)
      },
      save(row, column) {
        this.$emit('save', row, column)
      }
    }
  }
  </script>
  <style>

And this is the error I get when I run npm test

  > vue-cli-service test:unit "TableEditable.spec.js"
  
   FAIL  tests/unit/components/crudForm/TableEditable.spec.js
    checkbox first tests
    ✓ first test: check if theres a class name (18ms)
    ✕ click and emit buttons (7ms)
  
    ● checkbox first tests › click and emit buttons
  
    expect(received).toHaveProperty(path)
  
    Expected path: "edit"
    Received path: []
  
    Received value: {"click": [[{"isTrusted": false}]]}
  
      38 |       // await wrapper.vm.$nextTick()
      39 |       await wrapper.trigger('click')
    > 40 |       expect(wrapper.emitted()).toHaveProperty('edit')
       |                     ^
      41 |
      42 |     })
      43 | })
  
      at Object.<anonymous> (tests/unit/components/crudForm/TableEditable.spec.js:40:39)
  
  Test Suites: 1 failed, 1 total
  Tests:     1 failed, 1 passed, 2 total
  Snapshots: 0 total
  Time:      4.653s
  Ran all test suites matching /TableEditable.spec.js/i.

As I said, sorry if this is a simple error but I'm starting to learn tests so I don't have a lot of experience. If someone needs more information please let me know. Thanks in advance!

1 Answer 1

0

As far as I can tell expect(wrapper.emitted()).toHaveProperty('edit') should work.

So I think the issue is that the click is not working as you expect

you have

await wrapper.findComponent({ref: 'edit-outlined'})
await wrapper.trigger('click')

which will

  • find the edit-outlined button in the wrapper
  • click on the component/wrapper (NOT the button)

to fix that, you can try chaining it like this:

await wrapper
  .findComponent({ref: 'edit-outlined'})
  .trigger('click');

The trigger here is assigned to the result of findComponent

Update

I believe wrapper.findComponent({ref: 'edit-outlined'}) is not finding the component. When using ref it will look for components that have that value in the ref attribute.

you have

<div v-else class="editable-cell-text-wrapper">
  {{ text || ' ' }}
  <edit-outlined class="editable-cell-icon" @click="edit(record.key, column.key)" />
</div>

edit-outlined is the name/type of the component, and not a ref.

you could change it to

<div v-else class="editable-cell-text-wrapper">
  {{ text || ' ' }}
  <edit-outlined ref="edit-outlined" class="editable-cell-icon" @click="edit(record.key, column.key)" />
</div>

which would put it into this.$refs internal object (this.$refs['edit-outlined'] specifically) which would make it accessible using wrapper.findComponent({ref: 'edit-outlined'}).

You should also be able to change the way you target that element which should make it work without changing the code you are testing.

findcomponent has three type you can pass as the selector argument.

{Component|ref|string} selector

If you only have one instance or EditOutlined, you can target that using the Component type like this:

const btn = wrapper.findComponent(EditOutlined);
expect(btn.exists()).toBe(true);
await btn.trigger('click');

also, it's a good idea to add these: expect(btn.exists()).toBe(true); They also act as a "sanity test" and make sure when you get an error that you are looking in the right place.

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

4 Comments

Still not working and gives me the same error. :/ Not sure what I'm missing.
I think I see what's going on. I believe {ref: 'edit-outlined'} does not do what you think it does. I will update answer.
I've tried both possible solutions and it didn't work, also tried with #id but it doesn't work too. I don't know what to do, but thanks for the answers.
you could try console.logging the wrapper's .html() response. That might help with the debugging.

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.