Vue-test-utils: Value set with setComputed method not being used in other computed methods

Created on 24 Oct 2017  路  8Comments  路  Source: vuejs/vue-test-utils

I'm trying to test a computed method that depends on other computed values within the wrapper
However, when I stub those computed values dependencies using the newly added setComputed method the computed method that I'm trying to test does not update.

Example failing test:

    describe('formattedValue', () => {
      it('updates with specified format from other computed value', () => {
        wrapper.setComputed({
          format: 'date_format'
        });

        console.log('format', wrapper.vm.format); // outputs 'date_format' as expected
        assert.equal(wrapper.vm.formattedValue, '12/4/18'); //fails

Example method under test:

formattedValue () {
      let formattedValue = this.rawData;
      switch (this.format) {
        case 'date_format':
          formattedValue = moment.utc(moment.unix(this.rawData)).format(this.dateFormatString);
          break;
      }
      return formattedValue;
    }
need repro

All 8 comments

Hey @jonnyparris ,

I just tried this out and it seems to be working fine for me. One thing I noticed was you not only have to shallow or mount your component, but you must _use_ the computed value in the <template> section of your component - otherwise Vue doesn't even bother to updated the new computed value.

Maybe you aren't using {{ format }} in your template? Does that help?

If you can post the component you are testing and the entire test that might help too (like where you are calling mount or shallow on your component.

Here is my working example. Note that removing {{ format }} causes the test to fail, since the value is never initially computed.

import { mount } from 'vue-test-utils'
import App from './App'

describe('App', () => {
  it('works', () => {
    const wrapper = mount(App)

    wrapper.setComputed({ format: 'date_format' })

    expect(wrapper.vm.formattedValue).toEqual('updated')
  })
})
<template>
  <div id="app">
    {{ format }}
  </div>
</template>

<script>
export default {
  name: 'app',

  computed: {
    format () {
      return 'placeholder'
    },

    formattedValue () {
      let formattedValue = ''
      switch (this.format) {
        case 'date_format':
          formattedValue = 'updated'
          break
      }
      return formattedValue
    }
  }
}
</script>

Thanks for the quick reply!
I am using the computed values in the template as part of v-if and styling conditions. Moreover, the component functions as intended regardless of the failing test.
After inserting some console logs to verify values in both the component and the unit test, it seems as though the setComputed does override the specified values but that doesn't trigger a reactive update to the dependent method under test.

Here's a more expanded snippets that may help to diagnose what's wrong:

import assert from 'assert';
import { shallow } from 'vue-test-utils';
import DatatableCellValue from '~/components/DatatableCellValue';
import dummyData from '~/static/thp_smaller_dummy_response.json';

describe('DatatableCellValue.vue', () => {
  let wrapper;

  wrapper = shallow(DatatableCellValue, {
    propsData: {
      row: dummyData.data[0],
      column: dummyData.columns[0]
    }
  });

  // TODO - Get this test working.
  describe('computed properties', () => {
    describe('formattedColumnValue', () => {
      it('returns cell value according to self-described column formatting presets', () => {
        // ----------- no specified format -----------
        let testColumnName = 'publisher';

        console.log('raw before', wrapper.vm.rawCellData); // => 3520

        wrapper.setComputed({
          columnFormat: 'unspecified_format',
          rawCellData: dummyData.data[0][testColumnName]
        });

        console.log('raw after', wrapper.vm.rawCellData); // => monkeys
        console.log('format', wrapper.vm.columnFormat); // => unspecified_format
        console.log('formatted', wrapper.vm.formattedColumnValue); // => 3520

        assert.equal(wrapper.vm.formattedColumnValue, 'monkeys'); // => fail
      });
    });
  });
});

component:

<template>
  <div class="wrapper">
    <div v-if="columnFormat === 'compound' && row[column.name] !== undefined && rawCellData.hyperlink">
      <a
        :href="rawCellData.hyperlink" rel="noopener"
        v-tooltip.right="rawCellData.additional_info"
        :style="{ color: rawCellData.color }"
        >
        <span class="cell-value" :style="{ color: rawCellData.color }">
          {{ formattedColumnValue }}
        </span>
      </a>
    </div>
    <div v-else>
      <span class="cell-value">
        {{ formattedColumnValue }}
        }
      </span>
    </div>
  </div>
</template>

<script>
import moment from 'moment';
import { VTooltip } from 'v-tooltip';

export default {

  name: 'DatatableCellValue',

  directives: {
    tooltip: VTooltip
  },
  props: {
    row: {
      type: Object,
      required: true
    },
    column: {
      type: Object,
      required: true
    },
    dateFormatString: {
      type: String,
      default: 'YYYY-MM-DD HH:mm:ss'
    }
  },
  data () {
    return {
    };
  },
  computed: {
    columnFormat () {
      if ('format' in this.column) {
        return this.column.format;
      } else {
        return 'unspecified_format';
      }
    },
    rawCellData () {
      return this.row[this.column.name];
    },
    formattedColumnValue () {
      let formattedValue = this.rawCellData;
      console.log('testyMcTestFace raw', this.rawCellData); // => 3520
      switch (this.columnFormat) {
        case 'date_as_long':
          formattedValue = moment.utc(moment.unix(this.rawCellData)).format(this.dateFormatString);
          break;
        case 'compound':
          formattedValue = this.rawCellData.display_value;
          break;
      }
      return formattedValue;
    }
  }
};
</script>

Thanks for the bug report 馃檪

Can you make a minimal reproduction please, it makes it much easier to debug

@jonnyparris did you solve your problem? Was it an issue with setComputed, or with your component logic?

Same issue in my case:

Here is a little reproduction of my component

computed: {
    ...mapGetters([
      'isTeamAdmin'
    ]),

    placeholder() {
      return this.isTeamAdmin ? 'Leader' : 'inboxMember'
    }
  }
test.only('placeholder computed is Leader if isTeamAdmin is true', () => {
    wrapper.setComputed({ isTeamAdmin: true });
    expect(wrapper.vm.placeholder).toContain('Leader');
  });

Thanks @disitec . I think yours is a seperate issue to @jonnyparris , I'm moving it out to its own issue.

Haven't forgotten but haven't had time to revisit this just yet...

I believe this will be fixed in https://github.com/vuejs/vue-test-utils/commit/ebccc8dc686223003771022a00fa932e03378fc4

This will be released in beta.9. If this doesn't fix the issue, feel free to reopen.

Was this page helpful?
0 / 5 - 0 ratings