Last active
October 8, 2020 04:10
-
-
Save lmiller1990/4a15e496772802b213608111590a1221 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { mount } from '@vue/test-utils' | |
import FormValidation from './form-validation.vue' | |
describe('FormValidation', () => { | |
it('fills out form correctly', async () => { | |
const wrapper = mount(FormValidation) | |
await wrapper.find('#name').setValue('lachlan') | |
await wrapper.find('#weight-units').setValue('lb') | |
await wrapper.find('#weight').setValue('150') | |
expect(wrapper.findAll('.error')).toHaveLength(0) | |
}) | |
it('shows errors for invalid inputs', async () => { | |
const wrapper = mount(FormValidation) | |
await wrapper.find('#name').setValue('') | |
await wrapper.find('#weight-units').setValue('lb') | |
await wrapper.find('#weight').setValue('50') | |
expect(wrapper.findAll('.error')).toHaveLength(2) | |
}) | |
it('emits a submit event with patientForm when valid form submitted', async () => { | |
const wrapper = mount(FormValidation) | |
await wrapper.find('#name').setValue('lachlan') | |
await wrapper.find('#weight-units').setValue('kg') | |
await wrapper.find('#weight').setValue('100') | |
await wrapper.find('form').trigger('submit.prevent') | |
expect(wrapper.emitted('submit')[0]).toEqual([ | |
{ | |
patient: { | |
name: 'lachlan', | |
weight: { | |
value: 100, | |
units: 'kg' | |
} | |
} | |
} | |
]) | |
}) | |
}) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* name | |
* weight (imp|metric) | |
*/ | |
export function required(value) { | |
if (!value) { | |
return { | |
valid: false, | |
message: 'Required' | |
} | |
} | |
return { valid: true } | |
} | |
export function isBetween(value, { min, max }) { | |
if (value < min || value > max) { | |
return { | |
valid: false, | |
message: `Must be between ${min} and ${max}` | |
} | |
} | |
return { valid: true } | |
} | |
const limits = { | |
kg: { min: 30, max: 200 }, | |
lb: { min: 66, max: 440 }, | |
} | |
export function validateMeasurement(value, { constraints }) { | |
const result = required(value) | |
if (!result.valid) { | |
return result | |
} | |
return isBetween(value, constraints) | |
} | |
export function isFormValid(form) { | |
return form.name.valid && form.weight.valid | |
} | |
export function patientForm(patient) { | |
const name = required(patient.name) | |
const weight = validateMeasurement(patient.weight.value, { | |
nullable: false, | |
constraints: limits[patient.weight.units] | |
}) | |
return { | |
name, | |
weight, | |
} | |
} | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { | |
required, | |
isBetween, | |
validateMeasurement, | |
patientForm, | |
isFormValid | |
} from './form.js' | |
describe('required', () => { | |
it('is invalid when undefined', () => { | |
expect(required(undefined)).toEqual({ valid: false, message: 'Required' }) | |
}) | |
it('is invalid when empty string', () => { | |
expect(required('')).toEqual({ valid: false, message: 'Required' }) | |
}) | |
it('returns true false value is present', () => { | |
expect(required('some value')).toEqual({ valid: true }) | |
}) | |
}) | |
describe('isBetween', () => { | |
it('returns true when value is equal to min', () => { | |
expect(isBetween(5, { min: 5, max: 10 })).toEqual({ valid: true }) | |
}) | |
it('returns true when value is between min/max', () => { | |
expect(isBetween(7, { min: 5, max: 10 })).toEqual({ valid: true }) | |
}) | |
it('returns true when value is equal to max', () => { | |
expect(isBetween(10, { min: 5, max: 10 })).toEqual({ valid: true }) | |
}) | |
it('returns false when value is less than min', () => { | |
expect(isBetween(4, { min: 5, max: 10 })).toEqual({ valid: false, message: 'Must be between 5 and 10' }) | |
}) | |
it('returns false when value is greater than max', () => { | |
expect(isBetween(11, { min: 5, max: 10 })).toEqual({ valid: false, message: 'Must be between 5 and 10' }) | |
}) | |
}) | |
describe('validateMeasurement', () => { | |
it('returns invalid for input', () => { | |
const constraints = { min: 10, max: 30 } | |
const actual = validateMeasurement(undefined, { constraints, nullable: false }) | |
expect(actual).toEqual({ valid: false, message: 'Required' }) | |
}) | |
it('returns invalid when outside range', () => { | |
const constraints = { min: 10, max: 30 } | |
const actual = validateMeasurement(40, { constraints, nullable: false }) | |
expect(actual).toEqual({ valid: false, message: 'Must be between 10 and 30' }) | |
}) | |
it('returns valid when value is in range', () => { | |
const constraints = { min: 10, max: 30 } | |
const actual = validateMeasurement(20, { constraints, nullable: false }) | |
expect(actual).toEqual({ valid: true }) | |
}) | |
}) | |
describe('isFormValid', () => { | |
it('returns true when name and weight field are valid', () => { | |
const form = { | |
name: { valid: true }, | |
weight: { valid: true } | |
} | |
expect(isFormValid(form)).toBe(true) | |
}) | |
it('returns false when any field is invalid', () => { | |
const form = { | |
name: { valid: false }, | |
weight: { valid: true } | |
} | |
expect(isFormValid(form)).toBe(false) | |
}) | |
}) | |
describe('patientForm', () => { | |
const validPatient = { | |
name: 'test patient', | |
weight: { value: 100, units: 'kg' } | |
} | |
it('is valid when form is filled out correctly', () => { | |
const form = patientForm(validPatient) | |
expect(form.name).toEqual({ valid: true }) | |
expect(form.weight).toEqual({ valid: true }) | |
}) | |
it('is invalid when name is null', () => { | |
const form = patientForm({ ...validPatient, name: '' }) | |
expect(form.name).toEqual({ valid: false, message: 'Required' }) | |
}) | |
it('validates weight in imperial', () => { | |
const form = patientForm({ | |
...validPatient, | |
weight: { | |
value: 65, | |
units: 'lb' | |
} | |
}) | |
expect(form.weight).toEqual({ valid: false, message: 'Must be between 66 and 440' }) | |
}) | |
it('validates weight in metric', () => { | |
const form = patientForm({ | |
...validPatient, | |
weight: { | |
value: 29, | |
units: 'kg' | |
} | |
}) | |
expect(form.weight).toEqual({ valid: false, message: 'Must be between 30 and 200' }) | |
}) | |
}) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<template> | |
<h3>Patient Data</h3> | |
<form @submit.prevent="submit"> | |
<div class="field"> | |
<div v-if="!validatedForm.name.valid" class="error"> | |
{{ validatedForm.name.message }} | |
</div> | |
<label for="name">Name</label> | |
<input id="name" name="name" v-model="form.name" /> | |
</div> | |
<div class="field"> | |
<div v-if="!validatedForm.weight.valid" class="error"> | |
{{ validatedForm.weight.message }} | |
</div> | |
<label for="weight">Weight</label> | |
<input id="weight" name="weight" v-model.number="form.weight.value" /> | |
<select id="weight-units" v-model="form.weight.units"> | |
<option value="kg">kg</option> | |
<option value="lb">lb</option> | |
</select> | |
</div> | |
<div class="field"> | |
<button :disabled="!valid">Submit</button> | |
</div> | |
</form> | |
<pre> | |
Patient Data | |
{{ form }} | |
</pre> | |
<br /> | |
<pre> | |
Form State | |
{{ validatedForm }} | |
</pre> | |
</template> | |
<script> | |
import { reactive, computed, ref } from 'vue' | |
import { patientForm, isFormValid } from './form.js' | |
export default { | |
setup(props, { emit }) { | |
const form = reactive({ | |
name: '', | |
weight: { | |
value: '', | |
units: 'kg' | |
} | |
}) | |
const validatedForm = computed(() => { | |
return patientForm(form) | |
}) | |
const submit = () => { | |
emit('submit', { patient: form }) | |
} | |
const valid = computed(() => isFormValid(validatedForm.value)) | |
return { | |
form, | |
validatedForm, | |
submit, | |
valid, | |
} | |
} | |
} | |
</script> | |
<style> | |
.field > label { | |
display: inline-block; | |
width: 50px; | |
margin: 0 0 20px 0; | |
} | |
.field > input { | |
display: inline-block; | |
margin: 2px; | |
} | |
.error { | |
color: red; | |
} | |
</style> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment