web-dev-qa-db-ja.com

Vue test utilsはコンポーネントデータを更新していますが、DOMを再レンダリングしていません

コンポーネントのデータの1つの変数を変更するajaxリクエストを行った後、Vueアプリのテンプレートをテストしようとしています。この変数(本)は、ギャラリーを条件付きでレンダリングするために使用されます

[〜#〜] context [〜#〜]:バックエンドに保存した本を表示するためにギャラリーを作成したいと思います。このために、コンポーネントのマウントに関する本を取得します。この結果は、変数booksに設定されます。私がテストしようとしているのは、ajax呼び出しの後、コンポーネントが本でギャラリーをレンダリングすることです

[〜#〜] problem [〜#〜]:books変数が設定されている場合、div _<div v-else-if='books.length > 0'>SHOW GALLERY</div>_がレンダリングされますが、 "else" div(_<div v-else class='loader'>Loading</div>_)まだレンダリングされています

次の2つのコードブロックは、コンポーネントとテスト自体です。

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 [〜#〜]

_    @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');
        });
    }
_

QUIESTION:最後のアサートのDOMを更新するにはどうすればよいですか-see("SHOW GALLERY")-?

[〜#〜] update [〜#〜]

関数を参照この関数は、vue-test-utilsがアプリケーションのマウントに使用しているラッパー内のHTML要素のみを検索します。この場合、nullのままにしているので、HTMLファイル全体で「SHOWGALLERY」というテキストを検索しています。

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

    expect(wrap.html()).contains(text);
};
_
8
Fran Roa Prieto

浅いマウントとその_sync: false_オプションを使用して、同様の問題を解決しました。

これにより、同期レンダリングが非アクティブになり、必要に応じてレンダラーにジョブ(await wrapper.vm.$nextTick())を実行する時間を与える必要があります。これが完了すると、予想どおり、コンポーネントは私のリアクティブデータに基づいて再レンダリングされました。

8
Brice Pernet

私は非常によく似た問題に遭遇し、アサーションが失敗する前にawait wrapper.vm.$forceUpdate();でそれを解決しました。これにより、Vueはビューを更新します。

2
Lukáš Irsák