feat: Rewrite labels/validationMixin mixin to a helper (#9818)
This commit is contained in:
@@ -1,17 +1,17 @@
|
|||||||
<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('LABEL_MGMT.ADD.TITLE')"
|
:header-title="$t('LABEL_MGMT.ADD.TITLE')"
|
||||||
:header-content="$t('LABEL_MGMT.ADD.DESC')"
|
:header-content="$t('LABEL_MGMT.ADD.DESC')"
|
||||||
/>
|
/>
|
||||||
<form class="mx-0 flex flex-wrap" @submit.prevent="addLabel">
|
<form class="flex flex-wrap mx-0" @submit.prevent="addLabel">
|
||||||
<woot-input
|
<woot-input
|
||||||
v-model.trim="title"
|
v-model.trim="title"
|
||||||
:class="{ error: $v.title.$error }"
|
:class="{ error: $v.title.$error }"
|
||||||
class="w-full label-name--input"
|
class="w-full label-name--input"
|
||||||
:label="$t('LABEL_MGMT.FORM.NAME.LABEL')"
|
:label="$t('LABEL_MGMT.FORM.NAME.LABEL')"
|
||||||
:placeholder="$t('LABEL_MGMT.FORM.NAME.PLACEHOLDER')"
|
:placeholder="$t('LABEL_MGMT.FORM.NAME.PLACEHOLDER')"
|
||||||
:error="getLabelTitleErrorMessage"
|
:error="labelTitleErrorMessage"
|
||||||
data-testid="label-title"
|
data-testid="label-title"
|
||||||
@input="$v.title.$touch"
|
@input="$v.title.$touch"
|
||||||
/>
|
/>
|
||||||
@@ -32,13 +32,13 @@
|
|||||||
<woot-color-picker v-model="color" />
|
<woot-color-picker v-model="color" />
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
<div class="w-full flex items-center gap-2">
|
<div class="flex items-center w-full gap-2">
|
||||||
<input v-model="showOnSidebar" type="checkbox" :value="true" />
|
<input v-model="showOnSidebar" type="checkbox" :value="true" />
|
||||||
<label for="conversation_creation">
|
<label for="conversation_creation">
|
||||||
{{ $t('LABEL_MGMT.FORM.SHOW_ON_SIDEBAR.LABEL') }}
|
{{ $t('LABEL_MGMT.FORM.SHOW_ON_SIDEBAR.LABEL') }}
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex justify-end items-center py-2 px-0 gap-2 w-full">
|
<div class="flex items-center justify-end w-full gap-2 px-0 py-2">
|
||||||
<woot-button
|
<woot-button
|
||||||
:is-disabled="$v.title.$invalid || uiFlags.isCreating"
|
:is-disabled="$v.title.$invalid || uiFlags.isCreating"
|
||||||
:is-loading="uiFlags.isCreating"
|
:is-loading="uiFlags.isCreating"
|
||||||
@@ -56,13 +56,12 @@
|
|||||||
|
|
||||||
<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 validations, { getLabelTitleErrorMessage } from './validations';
|
||||||
import { getRandomColor } from 'dashboard/helper/labelColor';
|
import { getRandomColor } from 'dashboard/helper/labelColor';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
mixins: [alertMixin, validationMixin],
|
mixins: [alertMixin],
|
||||||
props: {
|
props: {
|
||||||
prefillTitle: {
|
prefillTitle: {
|
||||||
type: String,
|
type: String,
|
||||||
@@ -82,6 +81,10 @@ export default {
|
|||||||
...mapGetters({
|
...mapGetters({
|
||||||
uiFlags: 'labels/getUIFlags',
|
uiFlags: 'labels/getUIFlags',
|
||||||
}),
|
}),
|
||||||
|
labelTitleErrorMessage() {
|
||||||
|
const errorMessage = getLabelTitleErrorMessage(this.$v);
|
||||||
|
return this.$t(errorMessage);
|
||||||
|
},
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
this.color = getRandomColor();
|
this.color = getRandomColor();
|
||||||
|
|||||||
@@ -1,14 +1,14 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="h-auto overflow-auto flex flex-col">
|
<div class="flex flex-col h-auto overflow-auto">
|
||||||
<woot-modal-header :header-title="pageTitle" />
|
<woot-modal-header :header-title="pageTitle" />
|
||||||
<form class="mx-0 flex flex-wrap" @submit.prevent="editLabel">
|
<form class="flex flex-wrap mx-0" @submit.prevent="editLabel">
|
||||||
<woot-input
|
<woot-input
|
||||||
v-model.trim="title"
|
v-model.trim="title"
|
||||||
:class="{ error: $v.title.$error }"
|
:class="{ error: $v.title.$error }"
|
||||||
class="w-full label-name--input"
|
class="w-full label-name--input"
|
||||||
:label="$t('LABEL_MGMT.FORM.NAME.LABEL')"
|
:label="$t('LABEL_MGMT.FORM.NAME.LABEL')"
|
||||||
:placeholder="$t('LABEL_MGMT.FORM.NAME.PLACEHOLDER')"
|
:placeholder="$t('LABEL_MGMT.FORM.NAME.PLACEHOLDER')"
|
||||||
:error="getLabelTitleErrorMessage"
|
:error="labelTitleErrorMessage"
|
||||||
@input="$v.title.$touch"
|
@input="$v.title.$touch"
|
||||||
/>
|
/>
|
||||||
<woot-input
|
<woot-input
|
||||||
@@ -26,13 +26,13 @@
|
|||||||
<woot-color-picker v-model="color" />
|
<woot-color-picker v-model="color" />
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
<div class="w-full flex items-center gap-2">
|
<div class="flex items-center w-full gap-2">
|
||||||
<input v-model="showOnSidebar" type="checkbox" :value="true" />
|
<input v-model="showOnSidebar" type="checkbox" :value="true" />
|
||||||
<label for="conversation_creation">
|
<label for="conversation_creation">
|
||||||
{{ $t('LABEL_MGMT.FORM.SHOW_ON_SIDEBAR.LABEL') }}
|
{{ $t('LABEL_MGMT.FORM.SHOW_ON_SIDEBAR.LABEL') }}
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex justify-end items-center py-2 px-0 gap-2 w-full">
|
<div class="flex items-center justify-end w-full gap-2 px-0 py-2">
|
||||||
<woot-button
|
<woot-button
|
||||||
:is-disabled="$v.title.$invalid || uiFlags.isUpdating"
|
:is-disabled="$v.title.$invalid || uiFlags.isUpdating"
|
||||||
:is-loading="uiFlags.isUpdating"
|
:is-loading="uiFlags.isUpdating"
|
||||||
@@ -50,11 +50,10 @@
|
|||||||
<script>
|
<script>
|
||||||
import { mapGetters } from 'vuex';
|
import { mapGetters } from 'vuex';
|
||||||
import alertMixin from 'shared/mixins/alertMixin';
|
import alertMixin from 'shared/mixins/alertMixin';
|
||||||
import validationMixin from './validationMixin';
|
import validations, { getLabelTitleErrorMessage } from './validations';
|
||||||
import validations from './validations';
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
mixins: [alertMixin, validationMixin],
|
mixins: [alertMixin],
|
||||||
props: {
|
props: {
|
||||||
selectedResponse: {
|
selectedResponse: {
|
||||||
type: Object,
|
type: Object,
|
||||||
@@ -79,6 +78,10 @@ export default {
|
|||||||
this.selectedResponse.title
|
this.selectedResponse.title
|
||||||
}`;
|
}`;
|
||||||
},
|
},
|
||||||
|
labelTitleErrorMessage() {
|
||||||
|
const errorMessage = getLabelTitleErrorMessage(this.$v);
|
||||||
|
return this.$t(errorMessage);
|
||||||
|
},
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
this.setFormValues();
|
this.setFormValues();
|
||||||
|
|||||||
@@ -1,72 +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 Component = {
|
|
||||||
render() {},
|
|
||||||
title: 'TestComponent',
|
|
||||||
mixins: [validationMixin],
|
|
||||||
validations,
|
|
||||||
};
|
|
||||||
|
|
||||||
describe('validationMixin', () => {
|
|
||||||
it('it should return empty error message if valid label name passed', async () => {
|
|
||||||
const wrapper = shallowMount(Component, {
|
|
||||||
i18n: i18nConfig,
|
|
||||||
localVue,
|
|
||||||
data() {
|
|
||||||
return { title: 'sales' };
|
|
||||||
},
|
|
||||||
});
|
|
||||||
wrapper.vm.$v.$touch();
|
|
||||||
expect(wrapper.vm.getLabelTitleErrorMessage).toBe('');
|
|
||||||
});
|
|
||||||
it('it should return label required error message if empty name is passed', async () => {
|
|
||||||
const wrapper = shallowMount(Component, {
|
|
||||||
i18n: i18nConfig,
|
|
||||||
localVue,
|
|
||||||
data() {
|
|
||||||
return { title: '' };
|
|
||||||
},
|
|
||||||
});
|
|
||||||
wrapper.vm.$v.$touch();
|
|
||||||
expect(wrapper.vm.getLabelTitleErrorMessage).toBe('Label name is required');
|
|
||||||
});
|
|
||||||
it('it should return label minimum length error message if one charceter label name is passed', async () => {
|
|
||||||
const wrapper = shallowMount(Component, {
|
|
||||||
i18n: i18nConfig,
|
|
||||||
localVue,
|
|
||||||
data() {
|
|
||||||
return { title: 's' };
|
|
||||||
},
|
|
||||||
});
|
|
||||||
wrapper.vm.$v.$touch();
|
|
||||||
expect(wrapper.vm.getLabelTitleErrorMessage).toBe(
|
|
||||||
'Minimum length 2 is required'
|
|
||||||
);
|
|
||||||
});
|
|
||||||
it('it should return invalid character error message if invalid lable name passed', async () => {
|
|
||||||
const wrapper = shallowMount(Component, {
|
|
||||||
i18n: i18nConfig,
|
|
||||||
localVue,
|
|
||||||
data() {
|
|
||||||
return { title: 'sales enquiry' };
|
|
||||||
},
|
|
||||||
});
|
|
||||||
wrapper.vm.$v.$touch();
|
|
||||||
expect(wrapper.vm.getLabelTitleErrorMessage).toBe(
|
|
||||||
'Only Alphabets, Numbers, Hyphen and Underscore are allowed'
|
|
||||||
);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@@ -1,4 +1,7 @@
|
|||||||
import { validLabelCharacters } from '../validations';
|
import {
|
||||||
|
validLabelCharacters,
|
||||||
|
getLabelTitleErrorMessage,
|
||||||
|
} from '../validations';
|
||||||
|
|
||||||
describe('#validLabelCharacters', () => {
|
describe('#validLabelCharacters', () => {
|
||||||
it('validates the label', () => {
|
it('validates the label', () => {
|
||||||
@@ -8,3 +11,64 @@ describe('#validLabelCharacters', () => {
|
|||||||
expect(validLabelCharacters('str-str')).toEqual(true);
|
expect(validLabelCharacters('str-str')).toEqual(true);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('#getLabelTitleErrorMessage', () => {
|
||||||
|
const createValidation = titleValidation => ({
|
||||||
|
title: {
|
||||||
|
$error: titleValidation.$error,
|
||||||
|
required: titleValidation.required,
|
||||||
|
minLength: titleValidation.minLength,
|
||||||
|
validLabelCharacters: titleValidation.validLabelCharacters,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
it('returns an empty string when there are no validation errors', () => {
|
||||||
|
const validation = createValidation({
|
||||||
|
$error: false,
|
||||||
|
required: true,
|
||||||
|
minLength: true,
|
||||||
|
validLabelCharacters: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(getLabelTitleErrorMessage(validation)).toEqual('');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('returns a required error message when the title is required but not provided', () => {
|
||||||
|
const validation = createValidation({
|
||||||
|
$error: true,
|
||||||
|
required: false,
|
||||||
|
minLength: true,
|
||||||
|
validLabelCharacters: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(getLabelTitleErrorMessage(validation)).toEqual(
|
||||||
|
'LABEL_MGMT.FORM.NAME.REQUIRED_ERROR'
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('returns a minimum length error message when the title is too short', () => {
|
||||||
|
const validation = createValidation({
|
||||||
|
$error: true,
|
||||||
|
required: true,
|
||||||
|
minLength: false,
|
||||||
|
validLabelCharacters: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(getLabelTitleErrorMessage(validation)).toEqual(
|
||||||
|
'LABEL_MGMT.FORM.NAME.MINIMUM_LENGTH_ERROR'
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('returns a valid label characters error message when the title has invalid characters', () => {
|
||||||
|
const validation = createValidation({
|
||||||
|
$error: true,
|
||||||
|
required: true,
|
||||||
|
minLength: true,
|
||||||
|
validLabelCharacters: false,
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(getLabelTitleErrorMessage(validation)).toEqual(
|
||||||
|
'LABEL_MGMT.FORM.NAME.VALID_ERROR'
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|||||||
@@ -1,17 +0,0 @@
|
|||||||
export default {
|
|
||||||
computed: {
|
|
||||||
getLabelTitleErrorMessage() {
|
|
||||||
let errorMessage = '';
|
|
||||||
if (!this.$v.title.$error) {
|
|
||||||
errorMessage = '';
|
|
||||||
} else if (!this.$v.title.required) {
|
|
||||||
errorMessage = this.$t('LABEL_MGMT.FORM.NAME.REQUIRED_ERROR');
|
|
||||||
} else if (!this.$v.title.minLength) {
|
|
||||||
errorMessage = this.$t('LABEL_MGMT.FORM.NAME.MINIMUM_LENGTH_ERROR');
|
|
||||||
} else if (!this.$v.title.validLabelCharacters) {
|
|
||||||
errorMessage = this.$t('LABEL_MGMT.FORM.NAME.VALID_ERROR');
|
|
||||||
}
|
|
||||||
return errorMessage;
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
@@ -2,6 +2,20 @@ import { required, minLength } from 'vuelidate/lib/validators';
|
|||||||
|
|
||||||
export const validLabelCharacters = (str = '') => !!str && !str.includes(' ');
|
export const validLabelCharacters = (str = '') => !!str && !str.includes(' ');
|
||||||
|
|
||||||
|
export const getLabelTitleErrorMessage = validation => {
|
||||||
|
let errorMessage = '';
|
||||||
|
if (!validation.title.$error) {
|
||||||
|
errorMessage = '';
|
||||||
|
} else if (!validation.title.required) {
|
||||||
|
errorMessage = 'LABEL_MGMT.FORM.NAME.REQUIRED_ERROR';
|
||||||
|
} else if (!validation.title.minLength) {
|
||||||
|
errorMessage = 'LABEL_MGMT.FORM.NAME.MINIMUM_LENGTH_ERROR';
|
||||||
|
} else if (!validation.title.validLabelCharacters) {
|
||||||
|
errorMessage = 'LABEL_MGMT.FORM.NAME.VALID_ERROR';
|
||||||
|
}
|
||||||
|
return errorMessage;
|
||||||
|
};
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
title: {
|
title: {
|
||||||
required,
|
required,
|
||||||
|
|||||||
Reference in New Issue
Block a user