import { mount } from '@vue/test-utils' import { describe, expect, it } from 'vitest' import SequenceInput from '../../components/SequenceInput.vue' describe('SequenceInput', () => { it('should lead the toolbar with the sequence type when tools are shown', () => { const wrapper = mount(SequenceInput, { props: { modelValue: 'ATGC' } }) expect(wrapper.get('.mint-sequence-input__toolbar').element.firstElementChild?.className) .toBe('mint-sequence-input__type-badge') }) }) describe('SequenceInput problems (9c)', () => { it('should keep emitting the sanitised value when invalid characters are typed', async () => { const wrapper = mount(SequenceInput, { props: { modelValue: 'ATG' } }) await wrapper.get('textarea').setValue('ATGXZ') expect(wrapper.emitted('update:modelValue')?.at(-1)).toEqual(['ATG']) }) it('should keep the typed text in the field when invalid characters are typed', async () => { const wrapper = mount(SequenceInput, { props: { modelValue: 'ATG' } }) await wrapper.get('textarea').setValue('ATGXZ') await wrapper.setProps({ modelValue: 'ATG' }) expect((wrapper.get('textarea').element as HTMLTextAreaElement).value).toBe('ATGXZ') }) it('should show an error naming the invalid characters when they are typed', async () => { const wrapper = mount(SequenceInput, { props: { modelValue: 'ATG' } }) await wrapper.get('textarea').setValue('ATGXZ') expect(wrapper.get('.mint-sequence-input__problem--error').text()).toBe('Invalid characters: X Z') }) it('should mark the field as error when invalid characters are typed', async () => { const wrapper = mount(SequenceInput, { props: { modelValue: 'ATG' } }) await wrapper.get('textarea').setValue('ATGX') expect(wrapper.classes()).toContain('mint-sequence-input--error') }) it('should warn with the count when the sequence has N bases', () => { const wrapper = mount(SequenceInput, { props: { modelValue: 'ATNNG' } }) expect(wrapper.get('.mint-sequence-input__problem--warning').text()).toBe('2 ambiguous bases (N)') }) it('should show the typed text when the parent replaces the value', async () => { const wrapper = mount(SequenceInput, { props: { modelValue: 'ATG' } }) await wrapper.get('textarea').setValue('ATGX') await wrapper.setProps({ modelValue: 'CCC' }) expect((wrapper.get('textarea').element as HTMLTextAreaElement).value).toBe('CCC') }) it('should show the model value when a tool returns it to the last typed text', async () => { const wrapper = mount(SequenceInput, { props: { modelValue: '', 'onUpdate:modelValue': (value: string) => wrapper.setProps({ modelValue: value }) }, }) await wrapper.get('textarea').setValue('ACG') const revComp = wrapper.findAll('button').find(button => button.text() === 'Rev Comp')! await revComp.trigger('click') await revComp.trigger('click') expect((wrapper.get('textarea').element as HTMLTextAreaElement).value).toBe('ACG') }) it('should not report protein residues typed after a DNA-like prefix when the type is auto', async () => { const wrapper = mount(SequenceInput, { props: { modelValue: 'ATG' } }) await wrapper.get('textarea').setValue('ATGKLV') expect(wrapper.find('.mint-sequence-input__problem--error').exists()).toBe(false) }) }) describe('SequenceInput maxLength', () => { it('should count only valid bases against maxLength when invalid characters are typed', async () => { const wrapper = mount(SequenceInput, { props: { modelValue: '', type: 'dna', maxLength: 5 } }) await wrapper.get('textarea').setValue('AT??GC') expect(wrapper.emitted('update:modelValue')?.at(-1)).toEqual(['ATGC']) }) it('should cap the emitted sequence at maxLength bases when more are typed', async () => { const wrapper = mount(SequenceInput, { props: { modelValue: '', type: 'dna', maxLength: 5 } }) await wrapper.get('textarea').setValue('ATGCATG') expect(wrapper.emitted('update:modelValue')?.at(-1)).toEqual(['ATGCA']) }) })