import { aTimeout, expect, fixture as _fixture, html } from '@open-wc/testing'; import sinon from 'sinon'; import '../lion-textarea.js'; /** * @typedef {import('../src/LionTextarea').LionTextarea} LionTextarea * @typedef {import('lit-html').TemplateResult} TemplateResult */ const fixture = /** @type {(arg: TemplateResult|string) => Promise} */ (_fixture); function hasBrowserResizeSupport() { const textarea = document.createElement('textarea'); return textarea.style.resize !== undefined; } describe('', () => { it(`can be used with the following declaration ~~~ ~~~`, async () => { const el = await fixture(``); expect(el.querySelector('textarea')?.nodeName).to.equal('TEXTAREA'); }); it('has .rows=2 and .maxRows=6', async () => { const el = await fixture(``); expect(el.rows).to.equal(2); expect(el.maxRows).to.equal(6); }); it('has .readOnly=false .rows=2 and rows="2" by default', async () => { const el = await fixture(`foo`); expect(el.rows).to.equal(2); expect(el.getAttribute('rows')).to.be.equal('2'); expect(el._inputNode.rows).to.equal(2); expect(el._inputNode.getAttribute('rows')).to.be.equal('2'); expect(el.readOnly).to.be.false; expect(el._inputNode.hasAttribute('readonly')).to.be.false; }); it('sync rows down to the native textarea', async () => { const el = await fixture(`foo`); expect(el.rows).to.equal(8); expect(el.getAttribute('rows')).to.be.equal('8'); expect(el._inputNode.rows).to.equal(8); expect(el._inputNode.getAttribute('rows')).to.be.equal('8'); }); it('sync readOnly to the native textarea', async () => { const el = await fixture(`foo`); expect(el.readOnly).to.be.true; expect(el.querySelector('textarea')?.readOnly).to.be.true; }); it('disables user resize behavior', async () => { if (!hasBrowserResizeSupport()) { return; } const el = await fixture(``); const computedStyle = window.getComputedStyle(el._inputNode); expect(computedStyle.resize).to.equal('none'); }); it('supports initial modelValue', async () => { const el = await fixture( html``, ); expect(el.querySelector('textarea')?.value).to.equal('From value attribute'); }); it('adjusts height based on content', async () => { const el = await fixture(``); const initialHeight = el.offsetHeight; el.modelValue = 'batman\nand\nrobin\nand\ncatwoman'; await el.updateComplete; const hightWith5TextLines = el.offsetHeight; expect(hightWith5TextLines > initialHeight).to.equal(true); el.modelValue = 'batman'; await el.updateComplete; const hightWith1Line = el.offsetHeight; expect(hightWith1Line < hightWith5TextLines).to.equal(true); }); it(`starts growing when content is bigger than "rows" 'and stops growing after property "maxRows" is reached`, async () => { const el = await fixture(``); return [1, 2, 3, 4, 5, 6, 7, 8].reduce(async (heightPromise, i) => { const oldHeight = await heightPromise; el.modelValue += '\n'; await el.updateComplete; const newHeight = el.offsetHeight; if (i > el.maxRows) { // stop growing expect(newHeight).to.equal(oldHeight); } else if (i > el.rows) { // growing normally expect(newHeight >= oldHeight).to.equal(true); } return Promise.resolve(newHeight); }, Promise.resolve(0)); }); it('stops growing after property "maxRows" is reached when there was an initial value', async () => { const el = await fixture(html``); return [4, 5, 6, 7, 8].reduce(async (heightPromise, i) => { const oldHeight = await heightPromise; el.modelValue += `\n`; await el.updateComplete; const newHeight = el.offsetHeight; if (i > el.maxRows) { // stop growing expect(newHeight).to.equal(oldHeight); } else if (i > el.rows) { // growing normally expect(newHeight >= oldHeight).to.equal(true); } return Promise.resolve(newHeight); }, Promise.resolve(0)); }); it('stops shrinking after property "rows" is reached', async () => { const el = await fixture(html``); expect(el.scrollHeight).to.be.equal(el.clientHeight); const oneRowHeight = el.clientHeight; el.rows = 3; el.resizeTextarea(); await el.updateComplete; expect(oneRowHeight).to.be.below(el.clientHeight).and.to.be.below(el.scrollHeight); }); it('has an attribute that can be used to set the placeholder text of the textarea', async () => { const el = await fixture(``); expect(el.getAttribute('placeholder')).to.equal('text'); expect(el._inputNode.getAttribute('placeholder')).to.equal('text'); el.placeholder = 'foo'; await el.updateComplete; expect(el.getAttribute('placeholder')).to.equal('foo'); expect(el._inputNode.getAttribute('placeholder')).to.equal('foo'); }); it('fires resize textarea when a visibility change has been detected', async () => { const el = await fixture(`
`); const textArea = /** @type {LionTextarea} */ (el.firstElementChild); await textArea.updateComplete; const resizeSpy = sinon.spy(textArea, 'resizeTextarea'); el.style.display = 'block'; await aTimeout(0); expect(resizeSpy.calledOnce).to.be.true; }); it('is accessible', async () => { const el = await fixture(``); await expect(el).to.be.accessible(); }); it('is accessible when disabled', async () => { const el = await fixture(``); await expect(el).to.be.accessible(); }); });