IT이야기

Vue 테스트 유틸리티가 구성 요소 데이터를 업데이트하지만 돔을 다시 렌더링하지 않는 경우

cyworld 2022. 4. 14. 00:43
반응형

Vue 테스트 유틸리티가 구성 요소 데이터를 업데이트하지만 돔을 다시 렌더링하지 않는 경우

구성 요소 데이터의 한 변수를 변경하는 ajax 요청을 한 후 내 Vue 앱의 템플릿을 테스트하려고 해.이 변수(책)는 갤러리를 조건부로 렌더링하는 데 사용된다.

컨텍스트: 나는 뒷면에 저장한 책을 보여주기 위해 갤러리를 만들고 싶다.이를 위해 부품 장착에 관한 책을 가져온다.그 결과는 가변 서적에 나와 있다.내가 테스트하려는 것은, 아약스 콜이 끝난 후, 부품이 갤러리에 책을 렌더링한다는 것이다.

문제: 책 변수가 설정되면 div<div v-else-if='books.length > 0'>SHOW GALLERY</div>렌더링되어야 하지만 " but" 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');
        });
    }

가장 최근의 주장을 위해 어떻게 DOM을 갱신할 수 있을까?see("SHOW GALLERY")-?

갱신하다

기능 이 함수는 vue-test-utils가 애플리케이션 마운트에 사용하는 HTML 요소만 래퍼에서 검색한다.이 경우, null로 두었으므로, HTML 파일 전체에 걸쳐 "SHOW GARILLER"라는 텍스트를 검색하고 있다.

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

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

나는 방금 얄팍한 마운트와 그것의 비슷한 문제를 해결했다.sync: false옵션

이렇게 하면 동기화 렌더링이 비활성화되어 렌더러에게 작업을 수행할 수 있는 시간을 주어야 한다(예:await wrapper.vm.$nextTick()) 필요한 경우.이 작업이 완료되면 예상대로 내 반응 데이터를 기반으로 구성 요소를 다시 렌더링했다.

나는 매우 비슷한 문제에 부딪쳐 그것을 해결했다.await wrapper.vm.$forceUpdate();그 주장이 실패하기 전에이로 인해 Vue는 보기를 업데이트해야 한다.

처음에 Vue Test Utils는 업데이트를 동시에 실행한다.그러나 나중에 그들은 동기화 모드를 제거했다.여기서 그들은 이유를 설명하고 시험을 작성하는 방법을 보여준다.

테스트 코드는 다음과 같이 변경된다.

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');

나는 어린이 부품 마크업이 마운트에 렌더링되지 않은 경우와 유사한 문제를 겪었으며 다른 답변에 기초하여 다음과 같은 문제가 있었다.

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

참조URL: https://stackoverflow.com/questions/53781794/vue-test-utils-is-updating-the-component-data-but-not-re-rendering-the-dom

반응형