Vue测试工具正在更新组件数据,但不重新渲染dom

时间:2018-12-14 14:40:59

标签: vuejs2 vue-test-utils

我在发出ajax请求后尝试测试Vue应用程序的模板,该请求正在更改组件数据的一个变量。这个变量(书籍)用于有条件地渲染画廊

语境:我想创建一个图库以显示我存储在后端的书。为此,我获取了有关安装组件的书籍。其结果在变量 books 中设置。我要测试的是,在ajax调用之后,该组件将使用书籍呈现图库

问题:设置books变量后,应呈现div <div v-else-if='books.length > 0'>SHOW GALLERY</div>,但仍会呈现“ else” div(<div v-else class='loader'>Loading</div>

接下来的两个代码块是组件和测试本身:

BookGallery.vue (我正在测试的组件)

 <template>
      <v-content>
          <v-container fluid>

               /*** Conditional rendering: After the ajax request books > 0, so this div should be rendered ***/
              <div v-if='books.length > 0'>SHOW GALLERY</div>

              <div v-else class='loader'>Loading</div>
          </v-container>
      </v-content>
    </template>

    <script lang='ts'>
      import {Component} from 'vue-property-decorator';
      import {MyMixin} from '../mixin';

      @Component({components: {BookInformation}})
      export default class BookGallery extends MyMixin {
          public books: string[] = [];

          public async mounted() {

               /*** books is set as the result of the ajax request ***/

               this.books = (await this.$http.get(this.host + '/books')).data;
          }
      }
    </script>

    <style scoped lang='scss'></style>

测试

    @test
    public async 'after calling the books, the gallery show all of them'() {

        /*** MOCKING THE RESPONSE ***/
        TestCase.OK_200({
            books: [
                { uri: 'img/covers/1.jpg', title: 'El Prinicipito'},
                { uri: 'img/covers/2.jpeg', title: 'The Lord of the Rings'},
            ],
        });


        /*** MOUNTING MY COMPONENT ***/
        const wrapper = TestCase.shallowMount(BookGallery);


        /** ASSERTING **/
        await flushPromises().then(() => {

            /**  the first "expect" passes, so books > 0 = true **/
            expect(wrapper.vm.$data.books).to.eqls({
                books: [
                    { uri: 'img/covers/1.jpg', title: 'El Prinicipito'},
                    { uri: 'img/covers/2.jpeg', title: 'The Lord of the Rings'},
                ],
            });

            /** This is failing. The application should read 'SHOW GALLERY' when books > 0 (something tested in the previous assert), as explained in the first comment of the component's template, but is not updating the dom, only the data **/
            see('SHOW GALLERY');
        });
    }
  

疑问:如何为最后一个断言-see("SHOW GALLERY")-更新DOM?

更新

请参见功能 该函数仅在vue-test-utils用于挂载应用程序的包装器中搜索HTML元素。在这种情况下,我将其保留为空,它将在整个HTML文件中搜索文本“ SHOW GALLERY”

export const see = (text: string, selector?: string) => {
    const wrap = selector ? wrapper.find(selector) : wrapper;

    expect(wrap.html()).contains(text);
};

4 个答案:

答案 0 :(得分:4)

最初,Vue Test Utils同步运行更新。但是后来他们删除了同步模式。 Here他们解释了原因并展示了如何编写测试:

测试代码将与此不同:

it('render text', (done) => {
    const wrapper = mount(TestComponent)
    wrapper.trigger('click')
    wrapper.text().toContain('some text')
})

对此:

it('render text', async () => {
    const wrapper = mount(TestComponent)
    wrapper.trigger('click')
    await Vue.nextTick()
    wrapper.text().toContain('some text')
})

因此,要解决您的问题,您需要在断言await wrapper.vm.$nextTick()之前添加see('SHOW GALLERY');

答案 1 :(得分:3)

我刚刚使用了deepMount及其sync: false选项解决了类似的问题。

这将停用同步渲染,需要您在需要的时候给渲染器一些时间来执行其工作(await wrapper.vm.$nextTick())。 完成此操作后,将按预期根据我的反应数据重新渲染该组件。

答案 2 :(得分:1)

我遇到了非常相似的问题,并在断言失败之前使用await wrapper.vm.$forceUpdate();解决了这个问题。这迫使Vue更新视图。

答案 3 :(得分:0)

我遇到了类似的问题,即子组件标记未在安装时呈现,并且基于其他答案,以下内容对我有用:

test('it works as expected', async () => {
  const wrapper = await mount(TestComponent);
  //expect(...)
});