import { type Mock, type SpyInstance, afterEach, beforeEach, describe, expect, it, vi } from 'vitest' import { axe } from 'vitest-axe' import type { DOMWrapper, VueWrapper } from '@vue/test-utils' import { mount } from '@vue/test-utils' import { defineComponent, nextTick } from 'vue' import { DialogClose, DialogContent, DialogOverlay, DialogRoot, DialogTitle, DialogTrigger } from '.' import { findByText, fireEvent, render } from '@testing-library/vue' const OPEN_TEXT = 'Open' const CLOSE_TEXT = 'Close' const TITLE_TEXT = 'Title' const NoLabelDialogTest = defineComponent({ components: { DialogRoot, DialogTrigger, DialogOverlay, DialogContent, DialogClose }, template: ` ${OPEN_TEXT} ${CLOSE_TEXT} `, }) const UndefinedDescribedByDialog = defineComponent({ components: { DialogRoot, DialogTrigger, DialogOverlay, DialogContent, DialogClose, DialogTitle }, template: ` ${OPEN_TEXT} ${TITLE_TEXT} ${CLOSE_TEXT} `, }) function renderAndClickDialogTrigger(Dialog: any) { fireEvent.click(render(Dialog).getByText(OPEN_TEXT)) } const DialogTest = defineComponent({ components: { DialogRoot, DialogTrigger, DialogOverlay, DialogContent, DialogClose, DialogTitle }, template: ` ${OPEN_TEXT} ${TITLE_TEXT} ${CLOSE_TEXT} `, }) describe('given a default Dialog', () => { let wrapper: VueWrapper> let trigger: DOMWrapper let closeButton: HTMLElement let consoleWarnMock: SpyInstance let consoleWarnMockFunction: Mock beforeEach(() => { document.body.innerHTML = '' wrapper = mount(DialogTest, { attachTo: document.body }) trigger = wrapper.find('button') consoleWarnMockFunction = vi.fn() consoleWarnMock = vi.spyOn(console, 'warn').mockImplementation(consoleWarnMockFunction) }) afterEach(() => { consoleWarnMock.mockRestore() consoleWarnMockFunction.mockClear }) it('should pass axe accessibility tests', async () => { expect(await axe(document.body)).toHaveNoViolations() // open modal wrapper.find('button').element.click() await nextTick() expect(await axe(document.body)).toHaveNoViolations() }) describe('after clicking the trigger', () => { beforeEach(async () => { fireEvent.click(trigger.element) closeButton = await findByText(document.body, CLOSE_TEXT) }) describe('when no description has been provided', () => { it('should warn to the console', () => { expect(consoleWarnMockFunction).toHaveBeenCalledTimes(1) }) }) describe('when no title has been provided', () => { beforeEach(() => { document.body.innerHTML = '' }) it('should warn to the console', () => { renderAndClickDialogTrigger(NoLabelDialogTest) expect(consoleWarnMockFunction).toHaveBeenCalledTimes(1) }) }) describe('when aria-describedby is set to undefined', () => { beforeEach(() => { document.body.innerHTML = '' }) it('should not warn to the console', () => { consoleWarnMockFunction.mockClear() renderAndClickDialogTrigger(UndefinedDescribedByDialog) expect(consoleWarnMockFunction).not.toHaveBeenCalled() }) }) it('should open the content', () => { expect(document.body.innerHTML).toContain(closeButton.innerHTML) }) it('should focus the close button', () => { expect(closeButton).toBe(document.activeElement) }) describe('when pressing escape', () => { beforeEach(() => { fireEvent.keyDown(document.activeElement!, { key: 'Escape' }) }) it('should close the content', () => { expect(document.body.innerHTML).not.toContain(closeButton.innerHTML) }) it('should focus trigger', async () => { expect(document.activeElement).toBe(trigger.element) }) }) }) })