import { render } from '@stencil/vitest'; describe('ontario-dropdown-list', () => { describe('render', () => { it('should render a dropdown list element', async () => { const page = await render( ``, ); expect(page.root).toEqualHtml(`
`); }); it('should reflect attributes/props being set', async () => { const page = await render(``); expect(page.instance.name).toBe('dropdown-options'); expect(page.instance.elementId).toBe('dropdown-list'); expect(page.instance.isEmptyStartOption).toBe('Please select'); expect(page.instance.captionState.captionText).toBe('Label'); expect(page.instance.options).toBe('[{ "value": "dropdown-option-1", "label": "Option 1" }]'); }); it('should keep the host value empty when the start option is shown first', async () => { const page = await render( ``, ); const select = page.root?.shadowRoot?.querySelector('select') as HTMLSelectElement; const startOption = select.querySelector('option') as HTMLOptionElement; expect(page.root?.value).toBe(''); expect(startOption.getAttribute('value')).toBe(''); }); it('should warn and fall back when the provided value does not match an option', async () => { const warnSpy = vi.spyOn(console, 'warn').mockImplementation(() => undefined); const page = await render( ``, ); expect(page.root?.value).toBe('dropdown-option-1'); expect(warnSpy).toHaveBeenCalled(); warnSpy.mockRestore(); }); it('should apply the provided value over selected option flags', async () => { const page = await render( ``, ); const select = page.root?.shadowRoot?.querySelector('select') as HTMLSelectElement; const options = Array.from(select.querySelectorAll('option')) as HTMLOptionElement[]; expect(page.root?.value).toBe('dropdown-option-2'); expect(options[0].hasAttribute('selected')).toBe(false); expect(options[1].getAttribute('selected')).toBe(''); }); it('should keep the host value in sync with the selected option', async () => { const page = await render( ``, ); const select = page.root?.shadowRoot?.querySelector('select') as HTMLSelectElement; select.value = 'dropdown-option-2'; select.dispatchEvent(new Event('input', { bubbles: true, composed: true })); await page.waitForChanges(); expect(page.root?.value).toBe('dropdown-option-2'); }); it('should reflect external value updates in the rendered select', async () => { const page = await render( ``, ); const select = page.root?.shadowRoot?.querySelector('select') as HTMLSelectElement; let options = Array.from(select.querySelectorAll('option')) as HTMLOptionElement[]; expect(options[0].getAttribute('selected')).toBe(''); expect(options[1].hasAttribute('selected')).toBe(false); (page.root as HTMLOntarioDropdownListElement).value = 'dropdown-option-2'; await page.waitForChanges(); options = Array.from(select.querySelectorAll('option')) as HTMLOptionElement[]; expect(page.root?.value).toBe('dropdown-option-2'); expect(options[0].hasAttribute('selected')).toBe(false); expect(options[1].getAttribute('selected')).toBe(''); }); it('should emit a host input event with the current value in detail', async () => { const page = await render( ``, ); const onInput = vi.fn(); page.root?.addEventListener('input', onInput); const select = page.root?.shadowRoot?.querySelector('select') as HTMLSelectElement; select.value = 'dropdown-option-2'; select.dispatchEvent(new Event('input', { bubbles: true, composed: true })); await page.waitForChanges(); expect(onInput).toHaveBeenCalledTimes(1); expect(page.root?.value).toBe('dropdown-option-2'); expect(onInput.mock.calls[0][0].detail.value).toBe('dropdown-option-2'); }); it('should emit a host change event with the current value in detail', async () => { const page = await render( ``, ); const onChange = vi.fn(); page.root?.addEventListener('change', onChange); const select = page.root?.shadowRoot?.querySelector('select') as HTMLSelectElement; select.value = 'dropdown-option-2'; select.dispatchEvent(new Event('change', { bubbles: true, composed: true })); await page.waitForChanges(); expect(onChange).toHaveBeenCalledTimes(1); expect(page.root?.value).toBe('dropdown-option-2'); expect(onChange.mock.calls[0][0].detail.value).toBe('dropdown-option-2'); }); it('should preserve the dropdownOnChange custom event detail', async () => { const page = await render( ``, ); const onDropdownChange = vi.fn(); document.addEventListener('dropdownOnChange', onDropdownChange); const select = page.root?.shadowRoot?.querySelector('select') as HTMLSelectElement; select.value = 'dropdown-option-2'; select.dispatchEvent(new Event('change', { bubbles: true, composed: true })); await page.waitForChanges(); expect(onDropdownChange).toHaveBeenCalledTimes(1); expect(onDropdownChange.mock.calls[0][0].detail).toEqual({ id: 'dropdown-list', value: 'dropdown-option-2', }); }); }); });