hello world
'; await el.updateComplete; expect(el.getHTML()).to.equal('hello world
'); }); it('sanitizes hostile content set via value', async () => { const el = await editorFixture(); el.value = 'ok
click
'; await el.updateComplete; expect(el.getHTML()).to.not.include('script'); expect(el.getHTML()).to.not.include('onclick'); }); it('emits nile-input on document changes', async () => { const el = await editorFixture(); const view = el.pmView!; setTimeout(() => view.dispatch(view.state.tr.insertText('typed', 1))); const event = await oneEvent(el, 'nile-input'); expect(event.detail.value).to.equal('typed
'); expect(event.detail.content).to.equal('typed
'); expect(el.value).to.equal('typed
'); }); it('emits a debounced nile-change', async () => { const el = await editorFixture(); const view = el.pmView!; setTimeout(() => view.dispatch(view.state.tr.insertText('x', 1))); const event = await oneEvent(el, 'nile-change'); expect(event.detail.value).to.equal('x
'); }); it('applies commands via execCommand', async () => { const el = await editorFixture(); el.value = 'format me
'; await el.updateComplete; selectAll(el); expect(el.execCommand('bold')).to.equal(true); expect(el.getHTML()).to.equal('format me
'); expect(el.isCommandActive('bold')).to.equal(true); }); it('insertHTML inserts sanitized content at the selection', async () => { const el = await editorFixture(); el.insertHTML('safe'); expect(el.getHTML()).to.equal('safe
'); }); it('respects disabled and readonly', async () => { const el = await editorFixture( html`one
two
three
'; await el.updateComplete; expect(el.pmView!.state.doc.childCount).to.equal(1); }); it('executes toolbar commands dispatched as wysiwyg-command events', async () => { const el = await editorFixture(); el.value = 'toolbar
'; await el.updateComplete; selectAll(el); const toolbar = el.shadowRoot!.querySelector('nile-wysiwyg-toolbar')!; toolbar.dispatchEvent( new CustomEvent('wysiwyg-command', { detail: { name: 'italic' }, bubbles: true, composed: true, }) ); expect(el.getHTML()).to.equal('toolbar
'); }); it('participates in forms with name, required, and reset', async () => { const form = await fixturefilled
'); expect(el.checkValidity()).to.equal(true); expect(new FormData(form).get('notes')).to.equal('filled
'); form.reset(); await el.updateComplete; expect(el.getHTML()).to.equal(''); expect(el.checkValidity()).to.equal(false); }); it('uploads image files through uploadHandler with a placeholder', async () => { const el = await editorFixture(); let uploadedName = ''; el.uploadHandler = async file => { uploadedName = file.name; // Placeholder should be visible while the upload is pending. await new Promise(resolve => setTimeout(resolve, 30)); return { src: 'https://cdn.x.dev/uploaded.png', alt: 'uploaded' }; }; const file = new File(['x'], 'pic.png', { type: 'image/png' }); const pending = el.insertImageFile(file); await new Promise(resolve => setTimeout(resolve, 10)); expect( el.shadowRoot!.querySelector('.nile-wysiwyg__upload-placeholder'), 'placeholder while uploading' ).to.exist; await pending; expect(uploadedName).to.equal('pic.png'); expect(el.getHTML()).to.include('https://cdn.x.dev/uploaded.png'); expect(el.shadowRoot!.querySelector('.nile-wysiwyg__upload-placeholder')).to.not.exist; }); it('lets nile-image-upload-request listeners own the upload', async () => { const el = await editorFixture(); el.addEventListener('nile-image-upload-request', (e: Event) => { e.preventDefault(); (e as CustomEvent).detail.insert('https://custom.x.dev/own.png', 'mine'); }); await el.insertImageFile(new File(['x'], 'a.png', { type: 'image/png' })); expect(el.getHTML()).to.include('https://custom.x.dev/own.png'); expect(el.getHTML()).to.include('alt="mine"'); }); it('falls back to base64 embedding without a handler', async () => { const el = await editorFixture(); await el.insertImageFile(new File(['x'], 'a.png', { type: 'image/png' })); expect(el.getHTML()).to.include('data:image/png;base64'); }); it('emits nile-image-upload-error when the handler rejects', async () => { const el = await editorFixture(); el.uploadHandler = async () => { throw new Error('boom'); }; setTimeout(() => el.insertImageFile(new File(['x'], 'a.png', { type: 'image/png' }))); const event = await oneEvent(el, 'nile-image-upload-error'); expect(event.detail.error.message).to.equal('boom'); expect(el.getHTML()).to.equal(''); }); it('inserts tables from the table picker command event', async () => { const el = await editorFixture(); const toolbar = el.shadowRoot!.querySelector('nile-wysiwyg-toolbar')!; toolbar.dispatchEvent( new CustomEvent('wysiwyg-command', { detail: { name: 'insertTable', attrs: { rows: 2, cols: 3 } }, bubbles: true, composed: true, }) ); expect(el.getHTML()).to.include('