import { type E2EElement, type E2EPage, newE2EPage } from '@stencil/core/testing'; import { type OdsSelect } from '../../src/'; describe('ods-select rendering', () => { let el: E2EElement; let innerSelect: HTMLSelectElement; let page: E2EPage; let selectComponent: HTMLElement; async function setup(content: string, customStyle?: string): Promise { page = await newE2EPage(); await page.setContent(content); await page.evaluate(() => document.body.style.setProperty('margin', '0px')); if (customStyle) { await page.addStyleTag({ content: customStyle }); } el = await page.find('ods-select'); innerSelect = el.shadowRoot!.querySelector('select')!; selectComponent = el.shadowRoot!.querySelector('.ts-wrapper')!; } it('should render the web component', async() => { await setup(''); expect(el.shadowRoot).not.toBeNull(); expect(innerSelect).not.toBeNull(); expect(selectComponent).not.toBeNull(); }); it('should move the slot content to the inner select', async() => { await setup(''); expect(innerSelect.innerHTML).toBe(''); }); it('should render a placeholder', async() => { const dummyPlaceholder = 'dummy placeholder'; await setup(``); expect(await page.evaluate(() => { return document.querySelector('ods-select')?.shadowRoot?.querySelector('.ts-control')?.innerText; })).toBe(dummyPlaceholder); }); it('should render with an option disabled', async() => { await setup(''); await el.callMethod('open'); await page.waitForChanges(); const disabledStates = await page.evaluate(() => { const options = document.querySelector('ods-select')?.shadowRoot?.querySelectorAll('.ts-wrapper .option'); return (Array.from(options || [])).map((option) => option.getAttribute('aria-disabled')); }) || []; expect(disabledStates[0]).toBeNull(); expect(disabledStates[1]).toBe('true'); }); it('should render with an optgroup', async() => { const dummyLabel = 'dummy optgroup'; await setup(``); await el.callMethod('open'); await page.waitForChanges(); expect(await page.evaluate(() => { return !!document.querySelector('ods-select')?.shadowRoot?.querySelector('.ts-wrapper .optgroup'); })).toBe(true); expect(await page.evaluate(() => { return document.querySelector('ods-select')?.shadowRoot?.querySelector('.ts-wrapper .optgroup-header')?.innerText; })).toBe(dummyLabel); }); it('should render with a whole optgroup disabled', async() => { await setup(''); await el.callMethod('open'); await page.waitForChanges(); expect(await page.evaluate(() => { return document.querySelector('ods-select')?.shadowRoot?.querySelector('.ts-wrapper .optgroup')?.hasAttribute('data-disabled'); })).toBe(true); }); it('should render with checkboxes if multiple', async() => { await setup(''); await el.callMethod('open'); await page.waitForChanges(); expect(await page.evaluate(() => { return !!document.querySelector('ods-select')?.shadowRoot?.querySelector('.ts-wrapper .option [type="checkbox"]'); })).toBe(true); }); it('should render with a custom renderer', async() => { await setup(''); await page.evaluate(() => { const select = document.querySelector('ods-select'); select!.customRenderer = { option: ({ text }: { text: string }): string => { return `
>>> ${text} <<<
`; }, }; select!.updateCustomRenderer(); }); await el.callMethod('open'); await page.waitForChanges(); expect(await page.evaluate(() => { return document.querySelector('ods-select')?.shadowRoot?.querySelector('.ts-wrapper .option')?.innerText; })).toBe('>>> 1 <<<'); }); it('should render with is-disabled', async() => { await setup(''); expect(selectComponent.classList.contains('disabled')).toBe(true); }); it('should render the web component without options', async() => { await setup(''); expect(innerSelect).toHaveClass('tomselected'); expect(selectComponent).toBeDefined(); }); describe('watchers', () => { describe('isDisabled', () => { it('should disable the select component', async() => { await setup(''); expect(selectComponent.classList.contains('disabled')).toBe(false); el.setAttribute('is-disabled', true); await page.waitForChanges(); expect(await page.evaluate(() => { return document.querySelector('ods-select')?.shadowRoot?.querySelector('.ts-wrapper')?.classList.contains('disabled') || false; })).toBe(true); }); }); describe('onSlotChange', () => { it('should render 2 options after slot change', async() => { await setup(''); el.innerHTML = ''; await page.waitForChanges(); const optionsNumber = [...innerSelect.children].filter((child) => child.tagName === 'OPTION').length; expect(optionsNumber).toBe(2); }); it('should change options but not the selected one', async() => { const value = '1'; await setup(``); el.innerHTML = ``; await page.waitForChanges(); const selectedOption = selectComponent.querySelector('.ts-control')?.querySelector(`[data-value="${value}"]`); expect(selectedOption).toBeDefined(); }); }); }); describe('in a fixed context (like ods-modal)', () => { async function setupModal(content: string): Promise { page = await newE2EPage(); await page.setContent(` ${content} `); await page.evaluate(() => { const dialog = document.querySelector('ods-modal')?.shadowRoot?.querySelector('dialog'); dialog?.style.setProperty('animation', 'none'); }); el = await page.find('ods-select'); await el.click(); await page.waitForChanges(); } it('should position regarding dialog element (thus not at the right place) in absolute strategy', async() => { await setupModal(''); const hasScroll = await page.evaluate(() => { const dialogContent = document.querySelector('ods-modal')?.shadowRoot?.querySelector('.ods-modal__dialog__content'); return dialogContent && dialogContent.scrollHeight > dialogContent.clientHeight; }); expect(hasScroll).toBe(true); }); it('should position regarding viewport (thus at the right place) in fixed strategy', async() => { await setupModal(''); const hasScroll = await page.evaluate(() => { const dialogContent = document.querySelector('ods-modal')?.shadowRoot?.querySelector('.ods-modal__dialog__content'); return dialogContent && dialogContent.scrollHeight > dialogContent.clientHeight; }); expect(hasScroll).toBe(false); }); }); });