如何使用promise使用方法对vuejs组件更新进行单元测试

时间:2017-07-12 09:55:53

标签: vue.js vuejs2 jestjs axios

我正在使用Jest测试Vue组件。这是我的工作目录: enter image description here

这是我的组件Subscription.vue

<template>
  <div id="page">
    <page-title icon="fa-list-alt">
      <translate slot="title">Subscription</translate>
      <translate slot="comment">Consult the detail of your subscription</translate>
    </page-title>

    <panel v-if="error">
      <span slot="title">
        <icon icon="fa-exclamation-triangle"></icon>
        <translate>Error</translate>
      </span>
      {{ error }}
    </panel>
    <panel v-else-if="subscription_dict">
      <span slot="title">{{ _subscription_address }}</span>
      <div class="row" v-if="subscription_dict.product.hsi">
        <div class="col-xs-12">
          <subscription-hsi-panel
            :hsi="subscription_dict.product.hsi"
            :business="context.business">
          </subscription-hsi-panel>
        </div>
      </div>
      <div class="row" v-if="subscription_dict.product.itv">
        <div class="col-xs-12">
          <subscription-itv-panel
            :itv="subscription_dict.product.itv">
          </subscription-itv-panel>
        </div>
      </div>
      <div class="row" v-if="subscription_dict.product.voip">
        <div class="col-xs-6">
          <panel icon="icon-voip">
            <translate slot="title">Phone</translate>
            telefon products
          </panel>
        </div>
      </div>
    </panel>

    <div v-else class="text-center">
      <i class="fa fa-spinner fa-pulse fa-3x fa-fw"></i>
    </div>

    <span v-if="subscription_dict"><b>subscription_dict.product.voip : </b>{{ subscription_dict.product.voip }}</br></span>
    <span v-if="subscription_dict"><b>subscription_dict.product : </b>{{ subscription_dict.product }}</br></span>
  </div>
</template>

<script>
  import PageTitle from '../../core/components/PageTitle.vue'
  import SubscriptionHsiPanel from './SubscriptionHsiPanel.vue'
  import SubscriptionItvPanel from './SubscriptionItvPanel.vue'
  import Panel from '../../core/components/Panel.vue'
  import Icon from '../../core/components/Icon.vue'
  import api from '../../core/api.js'

  export default {
    data() {
      return {
        subscription_dict: false,
        error: false
      }
    },
    props: ['requests_url', 'context'],
    computed: {
      _subscription_address() {
        var sub_address = this.subscription_dict.subscription_address
        return sub_address + ' - ' + this.subscription_dict.package.join(' - ')
      }
    },
    created() {
      this.get_subscription()
      this.translate()
    },
    methods: {
      get_subscription() {
        let self = this
        api.get_subscription(self.requests_url.subscriptions_request)
        .then(function(response) {
          self.subscription_dict = response
        })
        .catch(function(error) {
          if(error) {
            self.error = error
          } else {
            self.error = self.$gettext(
              'We were not able to retrieve your subscription information!')
          }
        })
      },
      translate() {
        this.$gettext('Bridge hsi')
        this.$gettext('Bridge voip_biz')
        this.$gettext('Router')
      }
    },
    components: {
      PageTitle,
      Panel,
      Icon,
      SubscriptionHsiPanel,
      SubscriptionItvPanel
    }
  }
</script>

<style lang="sass">
  @import "../../core/css/tooltip"

  .table
    table-layout: fixed

    > tbody > tr >
      th
        width: 33%
      td
        vertical-align: middle
</style>

这是我的测试subscription.js

import Vue from 'vue'
import translations from 'src/translations.json'
import GetTextPlugin from 'vue-gettext'
import VTooltip from 'v-tooltip'

import Subscription from 'src/subscription/components/Subscription'

jest.mock('../../core/api');

Vue.use(GetTextPlugin, {
  availableLanguages: {
    en: 'English',
    fr: 'Français',
    de: 'Deutsch',
  },
  defaultLanguage: 'fr',
  translations: translations
})
Vue.use(VTooltip)

it('render when error', (done) => {
  const renderer = require('vue-server-renderer').createRenderer()
  const vm = new Vue({
    el: document.createElement('div'),
    render: h => h(Subscription, {
      props: {
        requests_url: {
          subscriptions_request: 'error_empty_promise'
        }
      }
    })
  })
  renderer.renderToString(vm, (err, str) => {
    setImmediate(() => {
      expect(str).toMatchSnapshot()
      done()
    })
  })
})

组件的方法get_subscription()使用我的API函数get_subscription

import axios from 'axios'

export default {
  get_subscription(url) {
    return axios.get(url, {
      credentials: 'same-origin'
      })
      .then(function(response){
        if(response.data.error){
          return Promise.reject(response.data.error)
        }else{
          return Promise.resolve(response.data)
        }
      })
      .catch(function(error) {
        return Promise.reject(false)
      })
  }
}

对于我的测试,我已经像这样嘲笑了这个函数:

const promises_object = {
  error_empty_promise: new Promise((resolve, reject) => {
    process.nextTick(
      () => reject(false)
    )
  })
}

export default {
  get_subscription(url) {
    return promises_object[url]
  }
}

现在,在测试中我渲染并与快照进行比较。我的问题是,在进行比较之前,我找不到等待get_subscription的承诺是reject的方法。 结果是我的快照反映了DOM更新之前组件的状态,这是在对API进行异步调用之后完成的。 在致电Promise之前,有没有办法让jest等到rejectexpect(str).toMatchSnapshot()

1 个答案:

答案 0 :(得分:0)

Jest docs

  

it期望返回值为Promise   解决。

你有一个将被拒绝的承诺,所以你需要一个承诺,当你的承诺被拒绝时,它会解决。

  isRejected(rejectingPromise, someExpects) {
    return new Promise((resolve) => {
      rejectingPromise.then(
        () => null,  // if it resolves, fail
        (err) => {   // if it rejects, resolve
          // Maybe do someExpects() here
          resolve();
        }
    });
  }