0

I'm trying to make a test using jest with Vue.

the details below.

Problem:

  • Can't mount using shallowMount option.

Situation:

  1. Run the test after mounting the component using shallowMount option that provides in Vue-test-utils.
  2. Throw error "Cannot read property 'XXXX' of undefined

This is my test code.

import myComponent from '@/~';
import Vuex from 'vuex';
import Vuelidate from 'vuelidate';
import { shallowMount, createLocalVue } from '@vue/test-utils';

const localVue = createLocalVue();
localVue.use(Vuex);
localVue.use(Vuelidate);

describe('myComponent~', () => {
  let store;

  beforeEach(() => {
    store = new Vuex.Store({
      modules: {
        user: {
          namespaced: true,
          getters: {
            profile: () => {
              const profile = { name: 'blahblah' };
              return profile;
            },
          },
        },
      },
    });
  });

  describe('profile.name is "blahblah"', () => {
    it('return something~', () => {
      const wrapper = shallowMount(myComponent, {
        localVue,
        store,
        mocks: {
          $api: {
            options: {
              testMethod() {
                return new Promise((resolve, reject) => {
                  resolve('test');
                });
              },
            },
          },
          $i18n: {
            t() {
              return {
                EN: 'EN',
                KO: 'KO',
                JP: 'JA',
                SC: 'zh-CN',
                TC: 'tw-CN',
              };
            },
          },
        },
      });
      expect(wrapper.find('.profile').text()).toBe('blahblah');
    });

I think the problem is that property isn't set as a specified value or an empty value like an array or object.

But I don't know how I set properly the properties in my logic.

For example,

when the error yields "Cannot read property 'images' of undefined",

I add to a wrapper in the relevant method like this.

exampleMethod() {
 this.something = this.something.map(item => {
  if (item.detailContent.images) { // <-- the added wrapper is here
   ~~~logic~~~~
  }
 })
}

But the undefined properties are so many, I also think this way is not proper.

How I do solve this problem?

added

These are details about the above example method:

    exampleMethod() {
      this.something = this.something.map(item => {
        let passValidation = false;
        let failValidation = false;
        if (item.detailContent.images) {
          if (this.detail.showLanguages.includes(item.code)) {
            if (this.configId !== 'OPTION1') {
              item.detailContent.images = item.detailContent.images.map(element => {
                return {
                  ...element,
                  required: true,
                }
              });
            }
            checkValidationPass = true;
          } else {
            if (this.configId !== 'OPTION1') {
              item.detailContent.images = item.detailContent.images.map(element => {
                return {
                  ...element,
                  required: false,
                }
              });
            }
            checkValidationPass = false;
          }
          return {
            ...item,
            required: passValidation,
            warning: failValidation,
          }
        }
      });
      if (this.configId === 'OPTION2') {
        this.checkOption2Validation();
      } else if (this.configId === 'OPTION3') {
        this.checkOption3Validation();
      } else {
        this.checkOption1Validation();
      }
    },

And this is 'this.something':

data() {
  return {
    something: []
  }
}

The detailContent is set here.

    setMethod() {
      this.something = [
        ...this.otherthings,
      ];
      this.something = this.something.map(item => {
        let details1 = {};
        if (this.configId === 'OPTION2') {
          details1 = {
            images: [
              { deviceType: 'PC', titleList: [null, null], imageType: 'IMAGE' },
              { deviceType: 'MOBILE', titleList: [null, null, null] }
            ]
          };
        } else if (this.configId === 'OPTION3') {
          details1 = {
            images: [
              { deviceType: 'PC' },
              { deviceType: 'MOBILE' }
            ],
            links: { linkType: 'EMPTY' },
          };
        }
        let details2 = {
          mainTitle: {
            content: null,
          }
        }
        let checkValidation = false;
        this.detail.detailLanguages.forEach(element => {
          if (element.language === item.code) {
            details1 = { ...element };
            if (!!element.mainTitle) {
              details2 = { ...element };
            } else {
              details2 = {
                ...details2,
                ...element
              };
            }
            if (this.configId !== 'OPTION1') {
              details1.images = details1.images.map(image => {
                return {
                  ...image,
                  required: true,
                }
              });
            }
            checkValidation = true;
          }
        });
        return {
          ...item,
          detailContent: this.configId !== 'OPTION1' ? details1 : details2,
          required: false,
          warning: false,
        }
      });
    },
Jun
  • 13
  • 1
  • 4
  • perhaps this.something isn't an array of objects containing a property called `detailContent` - can you show why it would contain such objects? There's nothing in the question to suggest what `this.something` even is - your example code is way too vague to help you – Jaromanda X Dec 27 '19 at 01:53
  • Okay, please give me a moment. I will add some code relevant to them. – Jun Dec 27 '19 at 02:05
  • I added the details. – Jun Dec 27 '19 at 02:31

0 Answers0