Skip to content
This repository was archived by the owner on Jun 1, 2023. It is now read-only.

Testing vue-form-wizard as component fails #259

Open
thepill opened this issue Aug 14, 2018 · 3 comments
Open

Testing vue-form-wizard as component fails #259

thepill opened this issue Aug 14, 2018 · 3 comments

Comments

@thepill
Copy link

thepill commented Aug 14, 2018

Hello,

i try to test a custom component using jest which uses vue-form-wizard as a child component.

but my test fails with the error message
Prop startIndex set to 0 is greater than the number of tabs - 0. Make sure that the starting index is less than the number of tabs registered

the test looks like this:

 describe('Step Stammdaten', () => {
    it('shows all field errors on next click', () => {
      const wrapper = mount(NewEmployeeForm)
      wrapper.vm.$data.loading = false
      wrapper.find('button').trigger('click')
      expect(wrapper.findAll('#Stammdaten0 .form-input-error')).toHaveLength(6)
    })
  })

if i take a snapshot i can see that all id´s of the tab-panels are missing.

Any idea?

@cristijora
Copy link
Collaborator

cristijora commented Aug 14, 2018

Hey @thepill

can you show the NewEmployeeForm code ?
You could try waiting for nextTick or

import flushPromises from 'flush-promises'

const wrapper = mount(NewEmployeeForm)
await flushPromises();

@thepill
Copy link
Author

thepill commented Aug 15, 2018

Hey @cristijora

thanks for your reply - i tried using flushPromises() but it didn't work, but i might found my problem:

Im using https://github.com/baianat/vee-validate to validate my inputs.
If i remove the v-validate tags from my inputs within the tab-content it works!?!

Code (sorry that it is not as simple):

NewEmployeeForm:

<template>
  <div
    v-if="!loading"
    class="wizard">
    <form-wizard
      :finish-button-text="submitButtonText"
      title=""
      subtitle=""
      next-button-text="Weiter"
      back-button-text="Zurück"
      step-size="xs"
      color="#2a887c"
      @on-complete="sendForm">
      <tab-content
        :before-change="beforeChangeFromBasicDataStep"
        title="Stammdaten">
        <div class="form">
          <div class="form-group-container">
            <div class="form-group">
              <input
                v-validate="'required'"
                id="gender-male"
                v-model="form.gender"
                type="radio"
                name="gender"
                value="Herr"
                data-vv-scope="basics"
                data-vv-as="Anrede">
              <label for="gender-male">Herr</label>
            </div>
          </div>
        </div>
      </tab-content>
      <tab-content
        v-if="customer.businessCategories.exchange === true"
        :before-change="beforeChangeFromEMailStep"
        title="E-Mail">

      </tab-content>
      <tab-content
        :before-change="beforeChangeFromPermissionsStep"
        title="System">

      </tab-content>
      <tab-content
        v-if="customer.businessCategories.datev === true"
        title="DATEV">

      </tab-content>
      <tab-content
        :before-change="beforeChangeFromAditionaltep"
        title="Zusätzliche Informationen">

      </tab-content>
      <tab-content title="Abschluss">
        <div>
          <h3>Zusammenfassung</h3>
          <p>Sie erhalten nach Abschluss ebenfalls eine Zusammenfassung per E-Mail.</p>
          <br>
          <form-summary :summary="formSummary"/>
        </div>
      </tab-content>
    </form-wizard>
  </div>
  <div v-else>
    <loading-spinner/>
  </div>
</template>

<script>
import { mapState } from 'vuex'
import utils from 'utils'
import api from 'api'
import FormMixin from 'mixins/FormMixin'
import WarningElement from 'components/basic/WarningElement'
import DatetimePicker from 'components/basic/DatetimePicker'
import MailboxAccessPermissions from 'components/mailbox/MailboxAccessPermissions'
import EmployeeSharePermissions from 'components/employee/EmployeeSharePermissions'
import LoadingSpinner from 'components/basic/LoadingSpinner'
import FormSummary from 'components/basic/forms/FormSummary'
import FormRemarks from 'components/basic/forms/FormRemarks'
import ContactPersonForm from 'components/basic/forms/ContactPersonForm'

export default {
  name: 'NewEmployeeForm',
  components: {
    WarningElement,
    DatetimePicker,
    LoadingSpinner,
    MailboxAccessPermissions,
    EmployeeSharePermissions,
    FormSummary,
    FormRemarks,
    ContactPersonForm
  },
  mixins: [FormMixin],
  data () {
    return {
      form: {
        gender: '',
        firstname: '',
        lastname: '',
        initials: '',
        staffId: undefined,
        phone: '',
        mailbox: false,
        email: undefined,
        datevEmailEncryption: false,
        vpn: 'Nein',
        scanner: false,
        increaseAllowedSimultaneousSessions: true,
        contact: {
          name: '',
          phone: ''
        },
        remarks: {},
        executionDate: undefined,
        blockTenantsInDatev: false
      },
      selectedWindowsReferenceUser: undefined,
      selectedDatevNukoReferenceUser: undefined,
      selectedDatevDMSReferenceUser: undefined,
      loading: true,
      sharePermissions: [],
      sharePermissionsLoading: false,
      showSystemPermissions: false
    }
  },
  computed: {
    ...mapState('employees', {
      employees: state => state.employees
    }),
    minExecutionDate () {
      return utils.getNextWorkingDate(5)
    },
    formSummary () {
      let summary = [
        {title: 'Stammdaten', isSectionHeader: true}
      ]
      return summary
    }
  },
  watch: {
    'selectedWindowsReferenceUser': function (user) {
      this.sharePermissionsLoading = true
      this.$store.dispatch('employees/FETCH_SHARE_PERMISSIONS', user.guid)
        .then(permissions => {
          this.sharePermissions = permissions.filter(s => s.name.toUpperCase().indexOf('WINDVSW') === -1)
          this.sharePermissionsLoading = false
        })
    }
  },
  async mounted () {
    this.$store.dispatch('employees/FETCH_EMPLOYEES')
    await this.$store.dispatch('customer/FETCH_CUSTOMER')
    this.form.executionDate = this.minExecutionDate
    this.loading = false
  },
  methods: {
    beforeChangeFromBasicDataStep () {
      this.form.email = utils.getEmailAdressFromPolicy(this.customer.primaryDomain, '%g.%s', this.form.firstname, this.form.lastname)
      this.form.mailbox = this.customer.businessCategories.exchange
      return this.$validator.validateAll('basics')
    },
    beforeChangeFromEMailStep () {
      return this.$validator.validateAll('mail')
    },
    beforeChangeFromPermissionsStep () {
      return this.$validator.validateAll('permissions')
    },
    beforeChangeFromAditionaltep () {
      return new Promise((resolve, reject) => {
        if (this.form.contact.name.length > 0 && this.form.executionDate !== undefined) {
          resolve(true)
        } else {
          reject(new Error('Missing contact name or execution date'))
        }
      })
    },
    async sendForm () {
      this.waitForSubmitResponse = true
      let formData = this.form
      formData.SystemReferenceUser = this.selectedWindowsReferenceUser.displayName
      formData.DatevNukoReferenceUser = this.selectedDatevNukoReferenceUser !== undefined ? this.selectedDatevNukoReferenceUser.displayName : ''
      formData.DatevDMSReferenceUser = this.selectedDatevDMSReferenceUser !== undefined ? this.selectedDatevDMSReferenceUser.displayName : ''

      let response = await api.sendForm('employees/new', 'POST', formData)
      const success = (response.status === 200)

      this.$router.push({ name: 'FormResultView', query: { success } })
    },
    showEmployeesDisplayNameWithState (employee) {
      return utils.showEmployeesDisplayNameWithState(employee)
    }
  }
}

</script>

<style scoped>

.reference-user {
  margin-bottom: 40px;
}

</style>

Test

import { createLocalVue, mount } from '@vue/test-utils'
import Vuex from 'vuex'
import NewEmployeeForm from 'components/employee/NewEmployeeForm'
import VeeValidate, {Validator} from 'vee-validate'
import VeeValidateDE from 'vee-validate/dist/locale/de'
import VueFormWizard from 'vue-form-wizard'
import flushPromises from 'flush-promises'

const localVue = createLocalVue()
localVue.use(VeeValidate, {errorBagName: 'formErrors'})
Validator.localize('de', VeeValidateDE)
localVue.use(VueFormWizard)
localVue.use(Vuex)

describe('Component NewEmployeeForm', () => {
  let store

  beforeEach(() => {
    const customer = {
      namespaced: true,
      state: {
        cachetime: undefined,
        customer: {
          businessCategories: {}
        }
      },
      actions: {
        FETCH_CUSTOMER: jest.fn()
      }
    }

    const user = {
      namespaced: true,
      state: {
        currentUser: {
          displayName: 'asdasd'
        }
      },
      actions: {
        FETCH_CURRENT_USER: jest.fn()
      },
      getters: {
        currentUser: state => state.currentUser
      }
    }

    const employees = {
      namespaced: true,
      state: {
        employees: []
      }
    }

    store = new Vuex.Store({
      modules: {
        customer,
        user,
        employees
      }
    })
  })

  it('test', async () => {
    const wrapper = mount(NewEmployeeForm, {store, localVue, attachToDocument: true})
    wrapper.vm.$data.loading = false
    await flushPromises()
    expect(wrapper).toMatchSnapshot()
  })
})

Test Snapshot Output

// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`Component NewEmployeeForm sets the correct default data 1`] = `
<div class="wizard">
  <div class="vue-form-wizard xs">
    <div class="wizard-header">
      <h4 class="wizard-title"></h4>
      <p class="category"></p>
    </div>
    <div class="wizard-navigation">
      <div class="wizard-progress-with-circle">
        <div class="wizard-progress-bar" style="background-color: rgb(42, 136, 124); color: rgb(42, 136, 124);"></div>
      </div>
      <ul role="tablist" class="wizard-nav wizard-nav-pills"></ul>
      <div class="wizard-tab-content">
        <div role="tabpanel" id="" aria-hidden="true" aria-labelledby="step-" class="wizard-tab-container" style="display: none;">
          <div class="form">
            <div class="form-group-container">
              <div class="form-group">
                <input id="gender-male" type="radio" name="gender" value="Herr" data-vv-scope="basics" data-vv-as="Anrede" aria-required="true" aria-invalid="false">
                <label for="gender-male">Herr</label>
              </div>
            </div>
          </div>
        </div>
        <!---->
        <div role="tabpanel" id="" aria-hidden="true" aria-labelledby="step-" class="wizard-tab-container" style="display: none;"></div>
        <!---->
        <div role="tabpanel" id="" aria-hidden="true" aria-labelledby="step-" class="wizard-tab-container" style="display: none;"></div>
        <div role="tabpanel" id="" aria-hidden="true" aria-labelledby="step-" class="wizard-tab-container" style="display: none;">
          <div>
            <h3>Zusammenfassung</h3>
            <p>Sie erhalten nach Abschluss ebenfalls eine Zusammenfassung per E-Mail.</p>
            <br>
            <div class="form-summary">
              <table>
                <tr>
                  <td class="form-summary-section top-section">Stammdaten</td>
                </tr>
              </table>
            </div>
          </div>
        </div>
      </div>
    </div>
    <div class="wizard-card-footer clearfix">
      <div class="wizard-footer-left">
        <!---->
      </div>
      <div class="wizard-footer-right"> <span role="button" tabindex="0"><button tabindex="-1" type="button" class="wizard-btn" style="background-color: rgb(42, 136, 124); border-color: #2a887c; color: white;">
            Weiter
           </button></span></div>
    </div>
  </div>
</div>
`;

@saraElsanan
Copy link

saraElsanan commented Jan 10, 2019

@thepill
well i tried to use veevalidate with form-wizard but idon't know what's wrong .. how did you use it please ?
i have two forms to validate so i used scoops

<form-wizard title="" subtitle="" color="#48285f" @on-complete="onComplete">

{{ t('register_customer') }}


{{ t('register_provider') }}



{{ t('continue_customer') }}
{{ t('continue_provider') }}


{{ t('back') }}

  <div class="row">
    <div class="col-xs-12 col-sm-12 col-md-6 col-md-offset-3 col-lg-6 col-lg-offset-3">
      <div class="form-group">
        <label class="user-type">
          <i class="ci_user ci-service-provider"></i>
          <span> {{ t('service_provider') }}</span>
          <input type="radio" id="role_id" name="role_id" v-model="account_type" value="3"  v-validate="'required|included:3,2'" /><span></span>
        </label>
        <label class="user-type">
          <i class="ci_user ci-user"></i>
          <span>{{ t('customer') }}</span>
          <input type="radio" id="role_id" name="role_id" v-model="account_type" value="2" v-validate="'required|included:3,2'" checked/><span></span>
        </label>
      </div>
    </div>
  </div>
</tab-content>
<tab-content :title="t('account_data')" :before-change="()=>validateStep('step1')">
  <form data-vv-scope="step1"  @on-validate="mergePartialModels">
    <div class="row">
      <div class="col-xs-12 col-sm-12 col-md-6 col-md-offset-3 col-lg-6 col-lg-offset-3">
        <div class="form-group">
          <input id="name" type="text" class="form-control" v-model="name" name="name" :placeholder="t('fullname')" v-validate="{ required: true , min:8 ,max:30}" :class="{'is-danger': errors.has('name') }" required autofocus>
          <span v-show="errors.has('name')" class="help is-danger">{{ errors.first('name') }}</span>
        </div>
        <div class="form-group">
          <input id="email" type="email" class="form-control" v-model="email" name="email" :placeholder="t('email')" required>
        </div>
        <div class="form-group">
          <input type="text" class="form-control" v-model="phone" name="phone" :placeholder="t('phone')" required>
        </div>
        <div class="form-group">
          <input id="password" type="password" class="form-control" v-model="password" name="password" required :placeholder="t('password')">
        </div>
        <div class="form-group">
          <input id="password-confirm" type="password" class="form-control" v-model="password_confirmation" name="password_confirmation" :placeholder="t('password_confirm')" required>
        </div>
      </div>
    </div>
  </form>
</tab-content>
<tab-content title="Last step">
  Yuhuuu! This seems pretty damn simple
</tab-content>
<script> import axios from "axios"; import {FormWizard, TabContent} from 'vue-form-wizard' import 'vue-form-wizard/dist/vue-form-wizard.min.css' import arabic from "vee-validate/dist/locale/ar"; import { Validator, mapFields } from "vee-validate"; import trans from "./translation/trans.json"; export default { name: "Register", components: { FormWizard, TabContent }, props: { sitelocale: { type: String, required: true }, }, data: () => ({ account_type:"2", name:'', email:'', phone:'', password:'', password_confirmation:''

}),
mounted() {
  this.$translate.setLang(this.sitelocale);
},
locales: trans,
created() {
  this.$validator.localize("ar", {
    messages: arabic.messages,
    attributes: trans.ar,
    custom: trans.ar.custom
  });
  this.$validator.localize("en", {
    custom: trans.en.custom,
    attributes: trans.en
  });

  Validator.localize(this.sitelocale);
},
methods: {
  validateForm(scope) {
    // console.log(this.$validator.fields.items);
    // this.$validator.validateAll(scope).then((result) => {
    //   if (result) {
    //     alert('submitted');
    //   }
    // });
  },
  validateStep(name) {
    console.log(name);
     console.log(this.$validator.fields.items);
    this.$validator.validateAll(name).then((result) => {
      if (result) {
        alert('submitted');
      }
    });
  },
  mergePartialModels(model, isValid){
  if(isValid){
  // merging each step model into the final model
   this.finalModel = Object.assign({},this.finalModel, model)
  }
},

  onComplete: function(){
    alert('Yay. Done!');
  }
},
watch: {

},
computed: {

}

};
</script>

<style type="text/css"> .wizard-btn{ background-color: #48285f!important; color: #fff; } </style>

any help please

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants