nuxt / vue-meta

Manage HTML metadata in Vue.js components with SSR support
https://vue-meta.nuxtjs.org
Other
4.07k stars 249 forks source link

Unit testing a metaInfo() statement #493

Closed terazus closed 4 years ago

terazus commented 4 years ago

Hello,

Let's say I have this vueJS component:

export default {
        name: "Record",
        id: 'ABA',
        methods: {
            // @vuese
            // Method to build and return the page title to be included as a metadata
            getTitle: function(){
                return 'MywebSite  | ' + this.$route.params['id']
            }
        },
        // @vuese
        // set the meta-data of the page
        metaInfo() {
            return {
                title: this.getTitle()
            }
        }
    }

How would you unit test that the meta title of the page is correctly set? I couldn't fiund the way to trigger the function within the following test:

import { shallowMount } from '@vue/test-utils'
import Record from './Record.vue'

const $route = {
    path: '/',
    params: {
        id: '120'
    }
};

describe('Record.vue', function() {

    // Set up the wrapper
    let wrapper;
    beforeEach(() => {
        wrapper = shallowMount(Record, {
            mocks: {$route}
        });
    });
    const title = 'MywebSite  | 120 ' ;

    it('can be instantiated', () => {
        expect(wrapper.name()).toMatch('Record');
        expect(wrapper.attributes('id')).toMatch('ABA');
    });

    it('has a getTitle() method that returns the page title', () => {
        expect(wrapper.vm.getTitle()).toBe(title);
    });

    it('has its meta title correctly set', () => {
        // test metaInfo() here
    });
})

Thank you very much :)

pimlie commented 4 years ago

Create a localVue instance with the vue-meta plugin installed, use that when mounting the component and then call wrapper.vm.$meta().refresh()

Have a look at our unit tests for more/other info: https://github.com/nuxt/vue-meta/blob/master/test/unit/components.test.js

terazus commented 4 years ago

Final solution for those we would arrive here:

import { shallowMount } from '@vue/test-utils'
import Record from './Record.vue'
import VueMeta from 'vue-meta'

const $route = {
    path: '/',
    params: {
        id: '120'
    }
};

let localVue = createLocalVue();
localVue.use(VueMeta);

describe('Record.vue', function() {

    // Set up the wrapper
    let wrapper;
    beforeEach(() => {
        wrapper = shallowMount(Record, {
            mocks: {$route}
        });
    });
    const title = 'MywebSite  | 120 ' ;

    it('can be instantiated', () => {
        expect(wrapper.name()).toMatch('Record');
        expect(wrapper.attributes('id')).toMatch('ABA');
    });

    it('has a getTitle() method that returns the page title', () => {
        expect(wrapper.vm.getTitle()).toBe(title);
    });

    it('has its meta title correctly set', () => {
        expect(wrapper.vm.$meta().refresh().metaInfo.title).toBe(title)
    });
})

Thx again, Im closing the issue :)

pimlie commented 4 years ago

Do you plan to test more then your example shows? Because if you dont, then it seems that you are mostly testing whether vue-meta still works as expected. Which we already do for you on every commit/release. So you could say that what you are testing is whether 1 + 1 is still really 2.

vue-meta merges the meta information of all components on the page, which means that it would make sense if you would be doing a full mount to test what metainfo the combination of your child components returns. But testing a shallow mount on a single component against a single expected title value doesnt seem that useful to me 🤔

terazus commented 4 years ago

Hello, I will. Im just setting up a new project making sure we can cover all the tests we will need in the future. I'm just scaffolding stuff up at the moment :)

haversnail commented 4 years ago

Was looking to close the gap on some unit test coverage with a Nuxt.js project and this helped; thanks @pimlie. 👏 For those working with Nuxt, you'll also have to make sure to specify the keyName option when adding the plugin to your local Vue instance, since Nuxt uses head instead of metaInfo. Updated from @terazus' comment:

import { shallowMount, createLocalVue } from '@vue/test-utils' 
import VueMeta from 'vue-meta'

// ...

const localVue = createLocalVue();
localVue.use(VueMeta, { keyName: 'head' });

Hopefully this helps. 👍

collyrooms commented 4 years ago

@haversnail would you be able to post your full code? im struggling to understand this with a nuxt project

sinjaz commented 4 years ago

wrapper.vm.$meta is still undefined for me. Any ideas? My metaInfo () is never called.

import { shallowMount, createLocalVue } from '@vue/test-utils'
import VueMeta from 'vue-meta'
import Component from '@/components/Component.vue'

const localVue = createLocalVue()
localVue.use(VueMeta)

describe('Component.vue', () => {
  it('should do kewl things', () => {
    const wrapper = shallowMount(Component, {})
    // console.log(wrapper.vm.$meta) // undefined
  })
})
cheesecomer commented 3 years ago

@sinjaz I think it's solved, but I'll post it just in case. It cannot be read unless localVue is set in shallowMount.

describe('Component.vue', () => {
  it('should do kewl things', () => {
    const wrapper = shallowMount(Component, { localVue })
    const meta = wrapper.vm.$meta().refresh();

    console.log(meta.metaInfo);
  })
})
danieldanielecki commented 3 years ago

Anyone with TypeError: wrapper.vm.$meta is not a function error when trying wrapper.vm.$meta().refresh();?

Gilson401 commented 2 years ago

@sinjaz I think it's solved, but I'll post it just in case. It cannot be read unless localVue is set in shallowMount.

describe('Component.vue', () => {
  it('should do kewl things', () => {
    const wrapper = shallowMount(Component, { localVue })
    const meta = wrapper.vm.$meta().refresh();

    console.log(meta.metaInfo);
  })
})

Thanks. This worked for me.