import { mount } from '@vue/test-utils' import { describe, expect, it } from 'vitest' import GroupAssigner from '../../components/GroupAssigner.vue' import type { GroupItem } from '../../types' const groups: GroupItem[] = [ { name: 'control-a', color: '#3B82F6', count: 3 }, { name: 'treatment-a', color: '#F43F5E', count: 4 }, ] describe('GroupAssigner', () => { it('uses shared assignment state for counts, validation, and emitted updates', async () => { const wrapper = mount(GroupAssigner, { props: { groups, group1: ['control-a'], group2: [], minPerGroup: 1, }, }) expect(wrapper.text()).toContain('3 samples') expect(wrapper.text()).toContain('0 samples') expect(wrapper.text()).toContain('Add 1 more to Treatment') await wrapper.find('.mint-group-assigner__pill-remove').trigger('click') expect(wrapper.emitted('update:group1')?.[0]).toEqual([[]]) expect(wrapper.emitted('update:group2')).toBeUndefined() }) it('does not throw when drag events omit dataTransfer', async () => { const wrapper = mount(GroupAssigner, { props: { groups, group1: [], group2: [], }, }) await expect( wrapper.find('.mint-group-assigner__pill--unassigned').trigger('dragstart', { dataTransfer: null }), ).resolves.toBeUndefined() await expect( wrapper.find('.mint-group-assigner__zone').trigger('dragover', { dataTransfer: null }), ).resolves.toBeUndefined() }) it('assigns and unassigns groups with Alt and the arrow keys', async () => { const wrapper = mount(GroupAssigner, { props: { groups, group1: [], group2: [] }, }) const pill = wrapper.get('.mint-group-assigner__pill--unassigned') expect(pill.attributes('tabindex')).toBe('0') expect(pill.attributes('aria-label')).toContain('Available Groups') await pill.trigger('keydown', { key: 'ArrowLeft', altKey: true }) expect(wrapper.emitted('update:group1')?.[0]).toEqual([['control-a']]) await wrapper.get('.mint-group-assigner__pill--unassigned') .trigger('keydown', { key: 'ArrowRight', altKey: true }) expect(wrapper.emitted('update:group2')?.at(-1)).toEqual([['control-a']]) }) it('moves an assigned group back to the unassigned pool', async () => { const wrapper = mount(GroupAssigner, { props: { groups, group1: ['control-a'], group2: [] }, }) await wrapper.get('.mint-group-assigner__zone--1 .mint-group-assigner__pill') .trigger('keydown', { key: 'ArrowRight', altKey: true }) expect(wrapper.emitted('update:group1')?.[0]).toEqual([[]]) }) it('announces keyboard assignments politely', async () => { const wrapper = mount(GroupAssigner, { props: { groups, group1: [], group2: [] }, }) await wrapper.get('.mint-group-assigner__pill--unassigned') .trigger('keydown', { key: 'ArrowLeft', altKey: true }) await wrapper.vm.$nextTick() const liveRegion = wrapper.get('[role="status"]') expect(liveRegion.attributes('aria-live')).toBe('polite') expect(liveRegion.text()).toBe('control-a moved to Control.') }) it('ignores arrow keys without Alt', async () => { const wrapper = mount(GroupAssigner, { props: { groups, group1: [], group2: [] }, }) await wrapper.get('.mint-group-assigner__pill--unassigned') .trigger('keydown', { key: 'ArrowLeft' }) expect(wrapper.emitted('update:group1')).toBeUndefined() }) })