Adding tests for textarea question component
This commit is contained in:
parent
51daeb0028
commit
a1f5d577a0
5 changed files with 376 additions and 25 deletions
|
|
@ -1 +1,348 @@
|
|||
// TODO finish
|
||||
// Components
|
||||
import textareaQuestion from '@/digital-components/textarea-question/textarea-question.vue';
|
||||
|
||||
// Supporting Files
|
||||
import { shallowMount } from '@vue/test-utils';
|
||||
import { getRandomString, getRandomInt } from '@/helpers/data-generation';
|
||||
import { nextTick } from 'vue';
|
||||
import { defineRule } from 'vee-validate';
|
||||
import { required } from '@/helpers/validation-rules';
|
||||
|
||||
describe('textarea-question.vue', () => {
|
||||
const mockMixin = {
|
||||
methods: {
|
||||
getCmsContent: jest.fn().mockImplementation(() =>
|
||||
getRandomString(10, 20)),
|
||||
setCmsContent: jest.fn()
|
||||
}
|
||||
};
|
||||
describe('Expected components rendered', () => {
|
||||
test('Label rendered', () => {
|
||||
// Arrange
|
||||
const questionText = getRandomString(10, 20);
|
||||
const mixinWithQuestion = {
|
||||
methods: {
|
||||
getCmsContent: jest.fn().mockImplementation(() =>
|
||||
questionText),
|
||||
setCmsContent: jest.fn()
|
||||
}
|
||||
};
|
||||
const wrapper = shallowMount(textareaQuestion, {
|
||||
propsData: {
|
||||
inputId: getRandomString(10, 20),
|
||||
cmsWidgetName: getRandomString(10, 20)
|
||||
},
|
||||
mixins: [mixinWithQuestion]
|
||||
});
|
||||
|
||||
// Act
|
||||
const label = wrapper.find('label');
|
||||
|
||||
// Assert
|
||||
expect(label.exists()).toBe(true);
|
||||
expect(wrapper.text()).toContain(questionText);
|
||||
});
|
||||
test('Textarea rendered', () => {
|
||||
// Arrange
|
||||
const wrapper = shallowMount(textareaQuestion, {
|
||||
propsData: {
|
||||
inputId: getRandomString(10, 20),
|
||||
cmsWidgetName: getRandomString(10, 20)
|
||||
},
|
||||
mixins: [mockMixin]
|
||||
});
|
||||
|
||||
// Act
|
||||
const textarea = wrapper.find('textarea');
|
||||
|
||||
// Assert
|
||||
expect(textarea.exists()).toBe(true);
|
||||
});
|
||||
test('Character count rendered', () => {
|
||||
// Arrange
|
||||
const maxLength = getRandomInt(100, 900);
|
||||
const wrapper = shallowMount(textareaQuestion, {
|
||||
propsData: {
|
||||
inputId: getRandomString(10, 20),
|
||||
cmsWidgetName: getRandomString(10, 20),
|
||||
maxLength
|
||||
},
|
||||
mixins: [mockMixin]
|
||||
});
|
||||
const expected = `0/${maxLength}`;
|
||||
|
||||
// Act
|
||||
// Assert
|
||||
expect(wrapper.text()).toContain(expected);
|
||||
});
|
||||
test('Error rendered', async () => {
|
||||
// Arrange
|
||||
const maxLength = getRandomInt(100, 900);
|
||||
const wrapper = shallowMount(textareaQuestion, {
|
||||
propsData: {
|
||||
inputId: getRandomString(10, 20),
|
||||
cmsWidgetName: getRandomString(10, 20),
|
||||
maxLength
|
||||
},
|
||||
mixins: [mockMixin]
|
||||
});
|
||||
|
||||
// Act
|
||||
const errorComponent = wrapper.find('#error-message');
|
||||
expect(errorComponent.text()).toBe('');
|
||||
|
||||
const errorMessage = getRandomString(20, 30);
|
||||
wrapper.vm.resetField({
|
||||
errors: [errorMessage]
|
||||
});
|
||||
await nextTick();
|
||||
|
||||
// Assert
|
||||
expect(errorComponent.text()).toBe(errorMessage);
|
||||
});
|
||||
test('Not required => optional text rendered', () => {
|
||||
// Arrange
|
||||
const wrapper = shallowMount(textareaQuestion, {
|
||||
propsData: {
|
||||
inputId: getRandomString(10, 20),
|
||||
cmsWidgetName: getRandomString(10, 20),
|
||||
isRequired: false
|
||||
},
|
||||
mixins: [mockMixin]
|
||||
});
|
||||
|
||||
// Act
|
||||
// Assert
|
||||
expect(wrapper.text()).toContain('Optional');
|
||||
});
|
||||
test('Required => optional text not rendered', () => {
|
||||
// Arrange
|
||||
const wrapper = shallowMount(textareaQuestion, {
|
||||
propsData: {
|
||||
inputId: getRandomString(10, 20),
|
||||
cmsWidgetName: getRandomString(10, 20),
|
||||
isRequired: true
|
||||
},
|
||||
mixins: [mockMixin]
|
||||
});
|
||||
|
||||
// Act
|
||||
// Assert
|
||||
expect(wrapper.text()).not.toContain('Optional');
|
||||
});
|
||||
});
|
||||
describe('Computed properties rendered', () => {
|
||||
describe('characterCount', () => {
|
||||
test('Model value null => character count is 0 ', () => {
|
||||
// Arrange
|
||||
const wrapper = shallowMount(textareaQuestion, {
|
||||
propsData: {
|
||||
inputId: getRandomString(10, 20),
|
||||
cmsWidgetName: getRandomString(10, 20),
|
||||
modelValue: null
|
||||
},
|
||||
mixins: [mockMixin]
|
||||
});
|
||||
|
||||
// Act
|
||||
// Assert
|
||||
expect(wrapper.vm.characterCount).toBe(0);
|
||||
});
|
||||
test('Model value undefined => character count is 0', () => {
|
||||
// Arrange
|
||||
const wrapper = shallowMount(textareaQuestion, {
|
||||
propsData: {
|
||||
inputId: getRandomString(10, 20),
|
||||
cmsWidgetName: getRandomString(10, 20),
|
||||
modelValue: undefined
|
||||
},
|
||||
mixins: [mockMixin]
|
||||
});
|
||||
|
||||
// Act
|
||||
// Assert
|
||||
expect(wrapper.vm.characterCount).toBe(0);
|
||||
});
|
||||
test('Model value empty string => character count is 0', () => {
|
||||
// Arrange
|
||||
const wrapper = shallowMount(textareaQuestion, {
|
||||
propsData: {
|
||||
inputId: getRandomString(10, 20),
|
||||
cmsWidgetName: getRandomString(10, 20),
|
||||
modelValue: ''
|
||||
},
|
||||
mixins: [mockMixin]
|
||||
});
|
||||
|
||||
// Act
|
||||
// Assert
|
||||
expect(wrapper.vm.characterCount).toBe(0);
|
||||
});
|
||||
test('Model value non-empty string => character count is as expected', () => {
|
||||
// Arrange
|
||||
const length = getRandomInt(10, 30);
|
||||
const value = getRandomString(length, length);
|
||||
const wrapper = shallowMount(textareaQuestion, {
|
||||
propsData: {
|
||||
inputId: getRandomString(10, 20),
|
||||
cmsWidgetName: getRandomString(10, 20),
|
||||
modelValue: value
|
||||
},
|
||||
mixins: [mockMixin]
|
||||
});
|
||||
|
||||
// Act
|
||||
// Assert
|
||||
expect(wrapper.vm.characterCount).toBe(length);
|
||||
});
|
||||
});
|
||||
describe('value', () => {
|
||||
test('Get value corresponds to modelValue', () => {
|
||||
// Arrange
|
||||
const modelValue = getRandomString(10, 20);
|
||||
const wrapper = shallowMount(textareaQuestion, {
|
||||
propsData: {
|
||||
inputId: getRandomString(10, 20),
|
||||
cmsWidgetName: getRandomString(10, 20),
|
||||
modelValue
|
||||
},
|
||||
mixins: [mockMixin]
|
||||
});
|
||||
|
||||
// Act
|
||||
// Assert
|
||||
expect(wrapper.vm.value).toBe(modelValue);
|
||||
});
|
||||
test('Set value => update modelValue event emitted with new value', () => {
|
||||
// Arrange
|
||||
const modelValue = getRandomString(10, 20);
|
||||
const wrapper = shallowMount(textareaQuestion, {
|
||||
propsData: {
|
||||
inputId: getRandomString(10, 20),
|
||||
cmsWidgetName: getRandomString(10, 20),
|
||||
modelValue
|
||||
},
|
||||
mixins: [mockMixin]
|
||||
});
|
||||
const newValue = getRandomString(10, 20);
|
||||
|
||||
// Act
|
||||
wrapper.vm.value = newValue;
|
||||
|
||||
// Assert
|
||||
expect(wrapper.emitted('update:modelValue')).toBeTruthy();
|
||||
expect(wrapper.emitted('update:modelValue')[0][0]).toEqual(newValue);
|
||||
});
|
||||
});
|
||||
});
|
||||
describe('Properties properly affect initial state', () => {
|
||||
test('Placeholder text sets placeholder text of text area', () => {
|
||||
// Arrange
|
||||
const placeholderText = getRandomString(10, 20);
|
||||
const wrapper = shallowMount(textareaQuestion, {
|
||||
propsData: {
|
||||
inputId: getRandomString(10, 20),
|
||||
cmsWidgetName: getRandomString(10, 20),
|
||||
placeholderText
|
||||
},
|
||||
mixins: [mockMixin]
|
||||
});
|
||||
|
||||
// Act
|
||||
const textarea = wrapper.find('textarea');
|
||||
|
||||
// Assert
|
||||
expect(textarea.attributes().placeholder).toBe(placeholderText);
|
||||
});
|
||||
test('isDisabled true => textarea disabled', () => {
|
||||
// Arrange
|
||||
const wrapper = shallowMount(textareaQuestion, {
|
||||
propsData: {
|
||||
inputId: getRandomString(10, 20),
|
||||
cmsWidgetName: getRandomString(10, 20),
|
||||
isDisabled: true
|
||||
},
|
||||
mixins: [mockMixin]
|
||||
});
|
||||
|
||||
// Act
|
||||
const textarea = wrapper.find('textarea');
|
||||
|
||||
// Assert
|
||||
expect(textarea.attributes().disabled).toBeDefined();
|
||||
});
|
||||
test('isRequired true => textarea required', () => {
|
||||
// Arrange
|
||||
const wrapper = shallowMount(textareaQuestion, {
|
||||
propsData: {
|
||||
inputId: getRandomString(10, 20),
|
||||
cmsWidgetName: getRandomString(10, 20),
|
||||
isRequired: true
|
||||
},
|
||||
mixins: [mockMixin]
|
||||
});
|
||||
|
||||
// Act
|
||||
const textarea = wrapper.find('textarea');
|
||||
|
||||
// Assert
|
||||
expect(textarea.attributes().required).toBeDefined();
|
||||
});
|
||||
test('validationRules set rules of text area', () => {
|
||||
// Arrange
|
||||
const rule = getRandomString(10, 20);
|
||||
const errorMessage = getRandomString(20, 30);
|
||||
defineRule(rule, required(errorMessage));
|
||||
const wrapper = shallowMount(textareaQuestion, {
|
||||
propsData: {
|
||||
inputId: getRandomString(10, 20),
|
||||
cmsWidgetName: getRandomString(10, 20),
|
||||
validationRules: rule
|
||||
},
|
||||
mixins: [mockMixin]
|
||||
});
|
||||
|
||||
// Act
|
||||
const textarea = wrapper.find('textarea');
|
||||
|
||||
// Assert
|
||||
expect(textarea.attributes().validationrules).toBe(rule);
|
||||
});
|
||||
test('maxLength set max length of text area', () => {
|
||||
// Arrange
|
||||
const maxLength = toString(getRandomInt(100, 900));
|
||||
const wrapper = shallowMount(textareaQuestion, {
|
||||
propsData: {
|
||||
inputId: getRandomString(10, 20),
|
||||
cmsWidgetName: getRandomString(10, 20),
|
||||
maxLength
|
||||
},
|
||||
mixins: [mockMixin]
|
||||
});
|
||||
|
||||
// Act
|
||||
const textarea = wrapper.find('textarea');
|
||||
|
||||
// Assert
|
||||
expect(textarea.attributes().maxlength).toBe(maxLength);
|
||||
});
|
||||
test('inputRows set input rows of text area', () => {
|
||||
// Arrange
|
||||
const inputRows = getRandomInt(10, 20);
|
||||
const wrapper = shallowMount(textareaQuestion, {
|
||||
propsData: {
|
||||
inputId: getRandomString(10, 20),
|
||||
cmsWidgetName: getRandomString(10, 20),
|
||||
inputRows
|
||||
},
|
||||
mixins: [mockMixin]
|
||||
});
|
||||
|
||||
// Act
|
||||
const textarea = wrapper.find('textarea');
|
||||
|
||||
// Assert
|
||||
expect(textarea.attributes().rows).toBe(`${inputRows}`);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
<template>
|
||||
<div
|
||||
class="textarea-question"
|
||||
:class="(errors && errors.length) || hasError ? 'has-error' : ''">
|
||||
:class="(errors && errors.length) ? 'has-error' : ''">
|
||||
<label
|
||||
:for="inputId"
|
||||
class="form-label">
|
||||
|
|
@ -17,12 +17,14 @@
|
|||
v-model.trim="value"
|
||||
class="form-control"
|
||||
:name="inputId"
|
||||
:rows="[inputRows ?? 3]"
|
||||
:rows="[inputRows ?? 10]"
|
||||
:placeholder="placeholderText"
|
||||
:disabled="isDisabled"
|
||||
:required="isRequired"
|
||||
:maxlength="maxLength"
|
||||
:validationRules="validationRules"
|
||||
@change="validationRules ? handleChange : () => {}"
|
||||
@blur="validationRules ? handleBlur : () => {}"
|
||||
@paste="trimOnPaste"
|
||||
@drop="trimOnPaste">
|
||||
</textarea>
|
||||
|
|
@ -32,6 +34,7 @@
|
|||
</p>
|
||||
<div
|
||||
v-show="errorMessage"
|
||||
id="error-message"
|
||||
class="row my-1 form-test-error">
|
||||
<span
|
||||
class="d-inline-flex mt-0"
|
||||
|
|
@ -58,13 +61,18 @@ export default {
|
|||
modelValue: String,
|
||||
isDisabled: Boolean,
|
||||
isRequired: Boolean,
|
||||
hasError: Boolean,
|
||||
validationRules: String,
|
||||
cmsWidgetName: String,
|
||||
maxLength: String,
|
||||
cmsWidgetName: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
maxLength: {
|
||||
type: String,
|
||||
default: '300'
|
||||
},
|
||||
inputRows: Number
|
||||
},
|
||||
emits: ['update:modelValue', 'textareaQuestionEvent.inputIdAssigned'],
|
||||
emits: ['update:modelValue'],
|
||||
setup(props) {
|
||||
const propsClone = { ...props };
|
||||
const { modelValue } = propsClone;
|
||||
|
|
@ -78,8 +86,10 @@ export default {
|
|||
|
||||
const { errorMessage,
|
||||
handleChange,
|
||||
handleBlur,
|
||||
validate,
|
||||
errors }
|
||||
errors,
|
||||
resetField }
|
||||
= useField(props.inputId,
|
||||
props.validationRules,
|
||||
fieldOptions);
|
||||
|
|
@ -87,8 +97,10 @@ export default {
|
|||
return {
|
||||
errorMessage,
|
||||
handleChange,
|
||||
handleBlur,
|
||||
validate,
|
||||
errors
|
||||
errors,
|
||||
resetField
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
|
|
@ -107,18 +119,6 @@ export default {
|
|||
}
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
async value(newValue) {
|
||||
const result = await this.validate(newValue, this.validationRules);
|
||||
if (result.valid) {
|
||||
this.handleChange(newValue);
|
||||
}
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
// TODO do we need to do anything else for this event?
|
||||
this.$emit('textareaQuestionEvent.inputIdAssigned', this.inputId);
|
||||
},
|
||||
methods: {
|
||||
trimOnPaste(evt) {
|
||||
evt.stopPropagation();
|
||||
|
|
@ -147,7 +147,7 @@ export default {
|
|||
}
|
||||
|
||||
.form-control {
|
||||
max-height: 5rem;
|
||||
max-height: 30rem;
|
||||
border: 1px solid $gray-500;
|
||||
border-radius: 0.5rem;
|
||||
padding: 12px 16px;
|
||||
|
|
|
|||
|
|
@ -62,10 +62,9 @@
|
|||
inputId="technicianNotes"
|
||||
:isDisabled="false"
|
||||
:isRequired="false"
|
||||
hasError="hasError"
|
||||
:cmsWidgetName="widget.notesQuestion"
|
||||
maxLength="500"
|
||||
inputRows="30" />
|
||||
:inputRows="3" />
|
||||
|
||||
<p
|
||||
ref="disclaimerText"
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ import { issPageValues } from "@/router/router-constants/issPage-values";
|
|||
import { Form } from "vee-validate";
|
||||
import vehicleQuestionsMixin from "@/mixins/vehicle-questions-mixin";
|
||||
import BaseFormMixin from '@/mixins/base-form-mixin.js';
|
||||
import globalRules from '@/helpers/global-rules';
|
||||
import globalRules from '@/constants/global-rules';
|
||||
|
||||
export default {
|
||||
name: "part-questions",
|
||||
|
|
|
|||
|
|
@ -8,6 +8,10 @@ import {vinLookupMethodSelections} from '@/constants/vin-lookup-methods';
|
|||
import { useMainStore } from '@/store';
|
||||
import { createTestingPinia } from '@pinia/testing';
|
||||
import { mapStores } from "pinia";
|
||||
import { defineRule } from 'vee-validate';
|
||||
import { errorMessages } from '@/constants/error-messages';
|
||||
import globalRules from '@/constants/global-rules';
|
||||
import { required } from '@/helpers/validation-rules';
|
||||
|
||||
const pinia = createTestingPinia();
|
||||
useMainStore(pinia);
|
||||
|
|
@ -44,6 +48,7 @@ const siteFooterWidgetMockData = {
|
|||
};
|
||||
|
||||
function setupMocks() {
|
||||
defineRule(globalRules.OPTION_REQUIRED, required(errorMessages.OPTION_REQUIRED));
|
||||
const mockRoute = {
|
||||
query: {
|
||||
issPage: 'vehicle-lookup',
|
||||
|
|
|
|||
Loading…
Reference in a new issue