import { newSpecPage } from '@stencil/core/testing'; import { BcxMessageComposer } from '../bcx-message-composer'; describe('bcx-message-composer', () => { it('renders with default props', async () => { const page = await newSpecPage({ components: [BcxMessageComposer], html: '', }); expect(page.root).toEqualHtml(`
`); }); it('renders with custom props', async () => { const page = await newSpecPage({ components: [BcxMessageComposer], html: '', }); const textarea = page.root.shadowRoot.querySelector('textarea'); const button = page.root.shadowRoot.querySelector('button[type="submit"]'); expect(textarea.getAttribute('placeholder')).toBe('Custom placeholder'); expect(textarea.getAttribute('maxlength')).toBe('500'); expect(button.hasAttribute('disabled')).toBe(true); }); it('enables submit button when message is entered', async () => { const page = await newSpecPage({ components: [BcxMessageComposer], html: '', }); const component = page.rootInstance as BcxMessageComposer; const button = page.root.shadowRoot.querySelector('button[type="submit"]'); // Initially disabled expect(button.hasAttribute('disabled')).toBe(true); // Enter message component.message = 'Hello world'; await page.waitForChanges(); expect(button.hasAttribute('disabled')).toBe(false); }); it('emits messageSubmit event on form submit', async () => { const page = await newSpecPage({ components: [BcxMessageComposer], html: '', }); const component = page.rootInstance as BcxMessageComposer; const form = page.root.shadowRoot.querySelector('form'); // Set up event listener const messageSubmitSpy = jest.fn(); page.root.addEventListener('messageSubmit', messageSubmitSpy); // Enter message and submit component.message = 'Test message'; await page.waitForChanges(); form.dispatchEvent(new Event('submit')); await page.waitForChanges(); expect(messageSubmitSpy).toHaveBeenCalledWith( expect.objectContaining({ detail: { content: 'Test message', images: [] }, }), ); }); it('handles Enter key submission', async () => { const page = await newSpecPage({ components: [BcxMessageComposer], html: '', }); const component = page.rootInstance as BcxMessageComposer; const textarea = page.root.shadowRoot.querySelector('textarea'); // Set up event listener const messageSubmitSpy = jest.fn(); page.root.addEventListener('messageSubmit', messageSubmitSpy); // Enter message component.message = 'Test message'; await page.waitForChanges(); // Simulate Enter key const enterEvent = new KeyboardEvent('keydown', { key: 'Enter' }); textarea.dispatchEvent(enterEvent); await page.waitForChanges(); expect(messageSubmitSpy).toHaveBeenCalledWith( expect.objectContaining({ detail: { content: 'Test message', images: [] }, }), ); }); it('does not submit on Shift+Enter', async () => { const page = await newSpecPage({ components: [BcxMessageComposer], html: '', }); const component = page.rootInstance as BcxMessageComposer; const textarea = page.root.shadowRoot.querySelector('textarea'); // Set up event listener const messageSubmitSpy = jest.fn(); page.root.addEventListener('messageSubmit', messageSubmitSpy); // Enter message component.message = 'Test message'; await page.waitForChanges(); // Simulate Shift+Enter key const shiftEnterEvent = new KeyboardEvent('keydown', { key: 'Enter', shiftKey: true }); textarea.dispatchEvent(shiftEnterEvent); await page.waitForChanges(); expect(messageSubmitSpy).not.toHaveBeenCalled(); }); it('emits attachmentsChange with count 0 when clearAttachments is called', async () => { const page = await newSpecPage({ components: [BcxMessageComposer], html: '', }); const component = page.rootInstance as BcxMessageComposer; const attachmentsSpy = jest.fn(); page.root.addEventListener('attachmentsChange', attachmentsSpy); await component.clearAttachments(); await page.waitForChanges(); expect(attachmentsSpy).toHaveBeenCalledWith(expect.objectContaining({ detail: { count: 0 } })); }); it('emits attachmentsChange with count 0 after message submit clears previews', async () => { const page = await newSpecPage({ components: [BcxMessageComposer], html: '', }); const component = page.rootInstance as BcxMessageComposer; const form = page.root.shadowRoot.querySelector('form'); const attachmentsSpy = jest.fn(); page.root.addEventListener('attachmentsChange', attachmentsSpy); component.message = 'Hello'; await page.waitForChanges(); form.dispatchEvent(new Event('submit')); await page.waitForChanges(); expect(attachmentsSpy).toHaveBeenCalledWith(expect.objectContaining({ detail: { count: 0 } })); }); it('keeps submit disabled when only images are attached', async () => { const page = await newSpecPage({ components: [BcxMessageComposer], html: '', }); const component = page.rootInstance as BcxMessageComposer; const button = page.root.shadowRoot.querySelector('button[type="submit"]'); (component as any).images = [{ id: 'img-1', file: new File(['x'], 'img.png', { type: 'image/png' }), dataUrl: 'data:image/png;base64,xxx' }]; await page.waitForChanges(); expect(button.hasAttribute('disabled')).toBe(true); }); it('does not emit messageSubmit when only images are attached and submit is triggered', async () => { const page = await newSpecPage({ components: [BcxMessageComposer], html: '', }); const component = page.rootInstance as BcxMessageComposer; const form = page.root.shadowRoot.querySelector('form'); const messageSubmitSpy = jest.fn(); page.root.addEventListener('messageSubmit', messageSubmitSpy); (component as any).images = [{ id: 'img-1', file: new File(['x'], 'img.png', { type: 'image/png' }), dataUrl: 'data:image/png;base64,xxx' }]; await page.waitForChanges(); form.dispatchEvent(new Event('submit')); await page.waitForChanges(); expect(messageSubmitSpy).not.toHaveBeenCalled(); }); });