question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Cannot read property 't' of undefined when testing components with v-data-table

See original GitHub issue

Versions and Environment

Vuetify: 1.1.9 Vue: 2.5.2 Vue Test Utils: 1.0.0-beta.23 Browsers: JSDom OS: High Sierra 10.13.4

Steps to reproduce

Companies.vue

<template>
  <div>
    <v-container grid-list-md text-xs-center>
      <v-layout row wrap>
        <v-flex xs12>
          <v-card>
            <v-data-table
              :headers="headers"
              :items="items"
              :loading="loading"
              class="elevation-1"
            >
              <v-progress-linear slot="progress" color="blue" indeterminate></v-progress-linear>
              <template slot="headerCell" slot-scope="props">
                <v-tooltip bottom>
                  <span slot="activator">
                    {{ props.header.text }}
                  </span>
                  <span>
                    {{ props.header.text }}
                  </span>
                </v-tooltip>
              </template>
              <template slot="items" slot-scope="props">
                <td>{{ props.item.name }}</td>
                <td>{{ props.item.contactName }}</td>
                <td>{{ props.item.contactEmail }}</td>
                <td class="justify-center layout px-0">
                  <v-icon
                    small
                    class="mr-2"
                    @click="viewItem(props.item)"
                  >
                    domain
                  </v-icon>
                  <v-icon
                    small
                    class="mr-2"
                    @click="editItem(props.item)"
                  >
                    edit
                  </v-icon>
                  <v-icon
                    small
                    @click="deleteItem(props.item)"
                  >
                    delete
                  </v-icon>
                </td>
              </template>
              <template slot="no-data">
                <v-btn color="primary" flat @click="createNewCompany">
                  Add company
                  <v-icon right dark>add_box</v-icon>
                </v-btn>
              </template>
            </v-data-table>
          </v-card>
        </v-flex>
        <v-flex xs12>
          <v-btn
            color="primary"
            class="white--text"
            @click="createNewCompany"
          >
            Create New Company
            <v-icon right dark>domain</v-icon>
          </v-btn>
        </v-flex>
      </v-layout>
      <ConfirmModal ref="Confirm"></ConfirmModal>
    </v-container>
  </div>
</template>
<script>
import vuetifyToast from 'vuetify-toast';
import { getCompanies, deleteCompany } from '@/services/database/company';
import { ConfirmModal } from '@/components/commons';

export default {
  name: 'companies',
  data() {
    return {
      headers: [
        { text: 'Company', align: 'center', value: 'name' },
        { text: 'Contact Name', align: 'center', value: 'contactName' },
        { text: 'Contact Email', align: 'center', value: 'contactEmail' },
        { text: 'Actions', value: 'name', sortable: false },
      ],
      items: [],
      loading: false,
      selectedItem: null,
    };
  },
  mounted() {
    this.loadInfo();
  },
  methods: {
    loadInfo() {
      this.items = [];
      this.loading = true;

      getCompanies()
        .then(companies => {
          this.items = companies.map(c => ({
            id: c.id,
            name: c.value.name,
            contactName: c.value.contact.name,
            contactEmail: c.value.contact.email,
          }));

          this.loading = false;
        })
        .catch(() => {
          this.loading = false;
          vuetifyToast.error('Error getting companies');
        });
    },
    viewItem(item) {
      this.$router.push({
        name: 'company',
        params: { companyId: item.id, originPage: 'companies' },
      });
    },
    editItem(item) {
      this.$router.push({
        name: 'companyDetail',
        params: { companyId: item.id, originPage: 'companies' },
      });
    },
    deleteItem(item) {
      this.selectedItem = item;
      this.$refs.Confirm.open(
        `Are you sure you want to delete company ${this.selectedItem.name}?`,
        this.removeCompany,
      );
    },
    removeCompany() {
      deleteCompany(this.selectedItem.id)
        .then(() => {
          vuetifyToast.success(`Company ${this.selectedItem.name} was deleted`);
          this.items = this.items.filter(item => item.id !== this.selectedItem.id);
          this.selectedItem = null;
        })
        .catch(() => {
          vuetifyToast.error(`Error deleting company ${this.selectedItem.name}`);
        });
    },
    createNewCompany() {
      this.$router.push({
        name: 'companyDetail',
        params: { companyId: 'new', originPage: 'companies' },
      });
    },
  },
  components: {
    ConfirmModal,
  },
};
</script>

Companies.spec.js

import Vue from 'vue';
import Vuetify from 'vuetify';
import VueRouter from 'vue-router';
import flushPromises from 'flush-promises';
import { mount, createLocalVue } from '@vue/test-utils';
import VeeValidate from 'vee-validate';
import * as companiesDatabase from '@/services/database/company';
import Companies from './Companies';

Vue.config.silent = true;

const localVue = createLocalVue();
localVue.use(VueRouter);
localVue.use(Vuetify);
localVue.use(VeeValidate);

describe('Companies', () => {
  const routes = [
    { path: '/', name: 'home' },
  ];

  const router = new VueRouter({
    routes,
  });

  let wrapper;
  beforeAll(() => {
    console.log('version', Vuetify.version);
    const { getComputedStyle } = global;
    global.getComputedStyle = function getComputedStyleStub(el) {
      return {
        ...getComputedStyle(el),
        transitionDelay: '',
        transitionDuration: '',
        animationDelay: '',
        animationDuration: '',
      };
    };
  });

  beforeEach(async () => {
    companiesDatabase.getCompanies = jest.fn();
    companiesDatabase.getCompanies.mockReturnValueOnce(Promise.resolve([
      {
        id: '1',
        value: {
          name: 'name',
          contact: {
            name: 'contact',
            email: 'email@contact.com',
          },
        },
      },
    ]));

    const App = localVue.component('App', {
      components: { Companies },
      template: `
        <div data-app>
          <companies />
        </div>
      `,
    });

    const mountedApp = mount(App, {
      localVue,
      attachToDocument: true,
      router,
      sync: false,
    });

    wrapper = mountedApp.find(Companies);
  });

  it('should render the companies', () => {
    expect(wrapper.is(Companies)).toBe(true);
  });
});

Expected Behavior

Test should pass

Actual Behavior

An error appears in the console:

TypeError: Cannot read property 't' of undefined
      
      at VueComponent.listData (node_modules/vuetify/dist/vuetify.js:9433:47)
      at Watcher.get (node_modules/vue/dist/vue.runtime.common.js:3140:25)
      at Watcher.evaluate (node_modules/vue/dist/vue.runtime.common.js:3247:21)
      at VueComponent.computedGetter [as listData] (node_modules/vue/dist/vue.runtime.common.js:3505:17)
      at VueComponent.staticList (node_modules/vuetify/dist/vuetify.js:9452:99)
      at Watcher.get (node_modules/vue/dist/vue.runtime.common.js:3140:25)
      at Watcher.evaluate (node_modules/vue/dist/vue.runtime.common.js:3247:21)
      at VueComponent.computedGetter [as staticList] (node_modules/vue/dist/vue.runtime.common.js:3505:17)
      at VueComponent.genList (node_modules/vuetify/dist/vuetify.js:9606:29)
      at VueComponent.genMenu (node_modules/vuetify/dist/vuetify.js:9662:33)
      at VueComponent.genDefaultSlot (node_modules/vuetify/dist/vuetify.js:9592:26)
      at VueComponent.genInputSlot (node_modules/vuetify/dist/vuetify.js:6067:22)
      at VueComponent.genInputSlot (node_modules/vuetify/dist/vuetify.js:12793:94)
      at VueComponent.genControl (node_modules/vuetify/dist/vuetify.js:6011:22)
      at VueComponent.genContent (node_modules/vuetify/dist/vuetify.js:6006:49)
      at Proxy.render (node_modules/vuetify/dist/vuetify.js:6138:17)
      at VueComponent.Vue._render (node_modules/vue/dist/vue.runtime.common.js:4542:22)
      at VueComponent.updateComponent (node_modules/vue/dist/vue.runtime.common.js:2786:21)
      at Watcher.get (node_modules/vue/dist/vue.runtime.common.js:3140:25)
      at new Watcher (node_modules/vue/dist/vue.runtime.common.js:3129:12)
      at mountComponent (node_modules/vue/dist/vue.runtime.common.js:2793:3)
      at VueComponent.Object.<anonymous>.Vue.$mount (node_modules/vue/dist/vue.runtime.common.js:7997:10)

Reproduction Link


Additional Comments:

Looking at the stacktrace the following line in the vuetify.js file is the one having the issue: noDataText: this.$vuetify.t(this.noDataText),

Thanks in advance for the help

Issue Analytics

  • State:closed
  • Created 5 years ago
  • Reactions:7
  • Comments:11 (3 by maintainers)

github_iconTop GitHub Comments

8reactions
KaelWDcommented, Aug 15, 2018

Simply

Vue.use(VueRouter);
Vue.use(Vuetify);

instead

2reactions
andreixkcommented, Jan 22, 2019

Polluting global Vue instance is a terrible idea.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Cannot read property 't' of undefined using Vuetify and Laravel
You need to create an instance of Vuetify. e.g.: new Vue({ el: '#app', vuetify: new Vuetify() }). This is documented here, though they...
Read more >
Laravel vuejs 'Cannot read property of data' error-Vue.js
Coding example for the question Laravel vuejs 'Cannot read property of data' ... You can, for example, add it to data() ... And...
Read more >
cannot read properties of undefined (reading 'dtinstance')
I am trying to add a new button to datatable DOM in angular using renderer2. But its triggering an error in runtime saying....
Read more >
Jest: TypeError: Cannot read property 'default' of undefined
Vue CLI bundles Jest as its default test runner. All is fine and good until one day, running your unit tests you get...
Read more >
LWC Jest test can't set @api array/object
I have and array @api property and can't set it in test. ... We'd need to see the component controller as well to...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found