feat: Replace SLA validationMixin within the component (#9804)
# Pull Request Template ## Description This PR will completely remove the SLA `validationMixin` and be used in the component as it is with a name change. Fixes https://linear.app/chatwoot/issue/CW-3456/rewrite-sla-validationmixin-mixin-to-a-composable ## Type of change - [x] New feature (non-breaking change which adds functionality) ## How Has This Been Tested? Take a look at these components 1. `dashboard/routes/dashboard/settings/sla/AddSLA.vue` **(Not used)** 2. `dashboard/routes/dashboard/settings/sla/SlaForm.vue` 3. `dashboard/routes/dashboard/settings/sla/SlaTimeInput.vue` ## Checklist: - [x] My code follows the style guidelines of this project - [x] I have performed a self-review of my code - [ ] I have commented on my code, particularly in hard-to-understand areas - [ ] I have made corresponding changes to the documentation - [x] My changes generate no new warnings - [x] I have added tests that prove my fix is effective or that my feature works - [x] New and existing unit tests pass locally with my changes - [ ] Any dependent changes have been merged and published in downstream modules
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="h-auto overflow-auto flex flex-col">
|
<div class="flex flex-col h-auto overflow-auto">
|
||||||
<woot-modal-header
|
<woot-modal-header
|
||||||
:header-title="$t('SLA.ADD.TITLE')"
|
:header-title="$t('SLA.ADD.TITLE')"
|
||||||
:header-content="$t('SLA.ADD.DESC')"
|
:header-content="$t('SLA.ADD.DESC')"
|
||||||
@@ -14,17 +14,14 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
import alertMixin from 'shared/mixins/alertMixin';
|
import alertMixin from 'shared/mixins/alertMixin';
|
||||||
import validationMixin from './validationMixin';
|
|
||||||
import { mapGetters } from 'vuex';
|
import { mapGetters } from 'vuex';
|
||||||
import validations from './validations';
|
|
||||||
import SlaForm from './SlaForm.vue';
|
import SlaForm from './SlaForm.vue';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
SlaForm,
|
SlaForm,
|
||||||
},
|
},
|
||||||
mixins: [alertMixin, validationMixin],
|
mixins: [alertMixin],
|
||||||
validations,
|
|
||||||
computed: {
|
computed: {
|
||||||
...mapGetters({
|
...mapGetters({
|
||||||
uiFlags: 'sla/getUIFlags',
|
uiFlags: 'sla/getUIFlags',
|
||||||
|
|||||||
@@ -12,7 +12,7 @@
|
|||||||
}"
|
}"
|
||||||
:label="$t('SLA.FORM.NAME.LABEL')"
|
:label="$t('SLA.FORM.NAME.LABEL')"
|
||||||
:placeholder="$t('SLA.FORM.NAME.PLACEHOLDER')"
|
:placeholder="$t('SLA.FORM.NAME.PLACEHOLDER')"
|
||||||
:error="getSlaNameErrorMessage"
|
:error="slaNameErrorMessage"
|
||||||
@input="$v.name.$touch"
|
@input="$v.name.$touch"
|
||||||
/>
|
/>
|
||||||
<woot-input
|
<woot-input
|
||||||
@@ -70,7 +70,6 @@
|
|||||||
<script>
|
<script>
|
||||||
import { mapGetters } from 'vuex';
|
import { mapGetters } from 'vuex';
|
||||||
import { convertSecondsToTimeUnit } from '@chatwoot/utils';
|
import { convertSecondsToTimeUnit } from '@chatwoot/utils';
|
||||||
import validationMixin from './validationMixin';
|
|
||||||
import validations from './validations';
|
import validations from './validations';
|
||||||
import SlaTimeInput from './SlaTimeInput.vue';
|
import SlaTimeInput from './SlaTimeInput.vue';
|
||||||
|
|
||||||
@@ -78,7 +77,6 @@ export default {
|
|||||||
components: {
|
components: {
|
||||||
SlaTimeInput,
|
SlaTimeInput,
|
||||||
},
|
},
|
||||||
mixins: [validationMixin],
|
|
||||||
props: {
|
props: {
|
||||||
selectedResponse: {
|
selectedResponse: {
|
||||||
type: Object,
|
type: Object,
|
||||||
@@ -130,6 +128,17 @@ export default {
|
|||||||
this.uiFlags.isUpdating
|
this.uiFlags.isUpdating
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
slaNameErrorMessage() {
|
||||||
|
let errorMessage = '';
|
||||||
|
if (this.$v.name.$error) {
|
||||||
|
if (!this.$v.name.required) {
|
||||||
|
errorMessage = this.$t('SLA.FORM.NAME.REQUIRED_ERROR');
|
||||||
|
} else if (!this.$v.name.minLength) {
|
||||||
|
errorMessage = this.$t('SLA.FORM.NAME.MINIMUM_LENGTH_ERROR');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return errorMessage;
|
||||||
|
},
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
if (this.selectedResponse) this.setFormValues();
|
if (this.selectedResponse) this.setFormValues();
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
}"
|
}"
|
||||||
:label="label"
|
:label="label"
|
||||||
:placeholder="placeholder"
|
:placeholder="placeholder"
|
||||||
:error="getThresholdTimeErrorMessage"
|
:error="thresholdTimeErrorMessage"
|
||||||
@input="onThresholdTimeChange"
|
@input="onThresholdTimeChange"
|
||||||
/>
|
/>
|
||||||
<!-- the mt-7 handles the label offset -->
|
<!-- the mt-7 handles the label offset -->
|
||||||
@@ -34,11 +34,9 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import validationMixin from './validationMixin';
|
|
||||||
import validations from './validations';
|
import validations from './validations';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
mixins: [validationMixin],
|
|
||||||
props: {
|
props: {
|
||||||
threshold: {
|
threshold: {
|
||||||
type: Number,
|
type: Number,
|
||||||
@@ -69,6 +67,19 @@ export default {
|
|||||||
};
|
};
|
||||||
},
|
},
|
||||||
validations,
|
validations,
|
||||||
|
computed: {
|
||||||
|
thresholdTimeErrorMessage() {
|
||||||
|
let errorMessage = '';
|
||||||
|
if (this.$v.thresholdTime.$error) {
|
||||||
|
if (!this.$v.thresholdTime.numeric || !this.$v.thresholdTime.minValue) {
|
||||||
|
errorMessage = this.$t(
|
||||||
|
'SLA.FORM.THRESHOLD_TIME.INVALID_FORMAT_ERROR'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return errorMessage;
|
||||||
|
},
|
||||||
|
},
|
||||||
watch: {
|
watch: {
|
||||||
threshold: {
|
threshold: {
|
||||||
immediate: true,
|
immediate: true,
|
||||||
|
|||||||
@@ -1,106 +0,0 @@
|
|||||||
import { shallowMount, createLocalVue } from '@vue/test-utils';
|
|
||||||
import VueI18n from 'vue-i18n';
|
|
||||||
import Vuelidate from 'vuelidate';
|
|
||||||
|
|
||||||
import validationMixin from '../validationMixin';
|
|
||||||
import validations from '../validations';
|
|
||||||
import i18n from 'dashboard/i18n';
|
|
||||||
|
|
||||||
const localVue = createLocalVue();
|
|
||||||
localVue.use(VueI18n);
|
|
||||||
localVue.use(Vuelidate);
|
|
||||||
|
|
||||||
const i18nConfig = new VueI18n({
|
|
||||||
locale: 'en',
|
|
||||||
messages: i18n,
|
|
||||||
});
|
|
||||||
|
|
||||||
const TestComponent = {
|
|
||||||
render() {},
|
|
||||||
mixins: [validationMixin],
|
|
||||||
validations,
|
|
||||||
};
|
|
||||||
|
|
||||||
describe('validationMixin', () => {
|
|
||||||
let wrapper;
|
|
||||||
|
|
||||||
beforeEach(() => {
|
|
||||||
wrapper = shallowMount(TestComponent, {
|
|
||||||
localVue,
|
|
||||||
i18n: i18nConfig,
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
name: '',
|
|
||||||
thresholdTime: '',
|
|
||||||
};
|
|
||||||
},
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should not return required error message if name is empty but not touched', () => {
|
|
||||||
wrapper.setData({ name: '' });
|
|
||||||
expect(wrapper.vm.getSlaNameErrorMessage).toBe('');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should return empty error message if name is valid', () => {
|
|
||||||
wrapper.setData({ name: 'ValidName' });
|
|
||||||
wrapper.vm.$v.name.$touch();
|
|
||||||
expect(wrapper.vm.getSlaNameErrorMessage).toBe('');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should return required error message if name is empty', () => {
|
|
||||||
wrapper.setData({ name: '' });
|
|
||||||
wrapper.vm.$v.name.$touch();
|
|
||||||
expect(wrapper.vm.getSlaNameErrorMessage).toBe(
|
|
||||||
wrapper.vm.$t('SLA.FORM.NAME.REQUIRED_ERROR')
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should return minimum length error message if name is too short', () => {
|
|
||||||
wrapper.setData({ name: 'a' });
|
|
||||||
wrapper.vm.$v.name.$touch();
|
|
||||||
expect(wrapper.vm.getSlaNameErrorMessage).toBe(
|
|
||||||
wrapper.vm.$t('SLA.FORM.NAME.MINIMUM_LENGTH_ERROR')
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should accept valid threshold values', () => {
|
|
||||||
wrapper.setData({ thresholdTime: 10 });
|
|
||||||
wrapper.vm.$v.thresholdTime.$touch();
|
|
||||||
expect(wrapper.vm.getThresholdTimeErrorMessage).toBe(wrapper.vm.$t(''));
|
|
||||||
|
|
||||||
wrapper.setData({ thresholdTime: 10.5 });
|
|
||||||
wrapper.vm.$v.thresholdTime.$touch();
|
|
||||||
expect(wrapper.vm.getThresholdTimeErrorMessage).toBe(wrapper.vm.$t(''));
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should not return invalid format error message if thresholdTime is empty but not touched', () => {
|
|
||||||
wrapper.setData({ thresholdTime: '' });
|
|
||||||
expect(wrapper.vm.getThresholdTimeErrorMessage).toBe('');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should return invalid format error message if thresholdTime has an invalid format', () => {
|
|
||||||
wrapper.setData({ thresholdTime: 'fsdfsdfsdfsd' });
|
|
||||||
wrapper.vm.$v.thresholdTime.$touch();
|
|
||||||
|
|
||||||
expect(wrapper.vm.getThresholdTimeErrorMessage).toBe(
|
|
||||||
wrapper.vm.$t('SLA.FORM.THRESHOLD_TIME.INVALID_FORMAT_ERROR')
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should reject invalid threshold values', () => {
|
|
||||||
wrapper.setData({ thresholdTime: 0 });
|
|
||||||
wrapper.vm.$v.thresholdTime.$touch();
|
|
||||||
expect(wrapper.vm.getThresholdTimeErrorMessage).toBe(
|
|
||||||
wrapper.vm.$t('SLA.FORM.THRESHOLD_TIME.INVALID_FORMAT_ERROR')
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should reject invalid threshold values', () => {
|
|
||||||
wrapper.setData({ thresholdTime: -1 });
|
|
||||||
wrapper.vm.$v.thresholdTime.$touch();
|
|
||||||
expect(wrapper.vm.getThresholdTimeErrorMessage).toBe(
|
|
||||||
wrapper.vm.$t('SLA.FORM.THRESHOLD_TIME.INVALID_FORMAT_ERROR')
|
|
||||||
);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@@ -1,26 +0,0 @@
|
|||||||
export default {
|
|
||||||
computed: {
|
|
||||||
getSlaNameErrorMessage() {
|
|
||||||
let errorMessage = '';
|
|
||||||
if (this.$v.name.$error) {
|
|
||||||
if (!this.$v.name.required) {
|
|
||||||
errorMessage = this.$t('SLA.FORM.NAME.REQUIRED_ERROR');
|
|
||||||
} else if (!this.$v.name.minLength) {
|
|
||||||
errorMessage = this.$t('SLA.FORM.NAME.MINIMUM_LENGTH_ERROR');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return errorMessage;
|
|
||||||
},
|
|
||||||
getThresholdTimeErrorMessage() {
|
|
||||||
let errorMessage = '';
|
|
||||||
if (this.$v.thresholdTime.$error) {
|
|
||||||
if (!this.$v.thresholdTime.numeric || !this.$v.thresholdTime.minValue) {
|
|
||||||
errorMessage = this.$t(
|
|
||||||
'SLA.FORM.THRESHOLD_TIME.INVALID_FORMAT_ERROR'
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return errorMessage;
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
Reference in New Issue
Block a user