import { aTimeout, expect, fixture, html, oneEvent } from '@open-wc/testing';
import { clickOnElement } from '../../internal/test';
import { sendKeys } from '@web/test-runner-commands';
import { serialize } from '../../utilities/form';
import sinon from 'sinon';
import type SlColorPicker from './color-picker';
describe('', () => {
describe('when the value changes', () => {
it('should not emit sl-change or sl-input when the value is changed programmatically', async () => {
const el = await fixture(html` `);
const color = 'rgb(255, 204, 0)';
el.addEventListener('sl-change', () => expect.fail('sl-change should not be emitted'));
el.addEventListener('sl-input', () => expect.fail('sl-change should not be emitted'));
el.value = color;
await el.updateComplete;
});
it('should emit sl-change and sl-input when the color grid selector is moved', async () => {
const el = await fixture(html` `);
const trigger = el.shadowRoot!.querySelector('[part~="trigger"]')!;
const grid = el.shadowRoot!.querySelector('[part~="grid"]')!;
const changeHandler = sinon.spy();
const inputHandler = sinon.spy();
el.addEventListener('sl-change', changeHandler);
el.addEventListener('sl-input', inputHandler);
await clickOnElement(trigger); // open the dropdown
await aTimeout(200); // wait for the dropdown to open
await clickOnElement(grid); // click on the grid
await el.updateComplete;
expect(changeHandler).to.have.been.calledOnce;
expect(inputHandler).to.have.been.calledOnce;
});
it('should emit sl-change and sl-input when the hue slider is moved', async () => {
const el = await fixture(html` `);
const trigger = el.shadowRoot!.querySelector('[part~="trigger"]')!;
const slider = el.shadowRoot!.querySelector('[part~="hue-slider"]')!;
const changeHandler = sinon.spy();
const inputHandler = sinon.spy();
el.addEventListener('sl-change', changeHandler);
el.addEventListener('sl-input', inputHandler);
await clickOnElement(trigger); // open the dropdown
await aTimeout(200); // wait for the dropdown to open
await clickOnElement(slider); // click on the hue slider
await el.updateComplete;
expect(changeHandler).to.have.been.calledOnce;
expect(inputHandler).to.have.been.calledOnce;
});
it('should emit sl-change and sl-input when the opacity slider is moved', async () => {
const el = await fixture(html` `);
const trigger = el.shadowRoot!.querySelector('[part~="trigger"]')!;
const slider = el.shadowRoot!.querySelector('[part~="opacity-slider"]')!;
const changeHandler = sinon.spy();
const inputHandler = sinon.spy();
el.addEventListener('sl-change', changeHandler);
el.addEventListener('sl-input', inputHandler);
await clickOnElement(trigger); // open the dropdown
await aTimeout(200); // wait for the dropdown to open
await clickOnElement(slider); // click on the opacity slider
await el.updateComplete;
expect(changeHandler).to.have.been.calledOnce;
expect(inputHandler).to.have.been.calledOnce;
});
it('should emit sl-change and sl-input when toggling the format', async () => {
const el = await fixture(html` `);
const trigger = el.shadowRoot!.querySelector('[part~="trigger"]')!;
const formatButton = el.shadowRoot!.querySelector('[part~="format-button"]')!;
const changeHandler = sinon.spy();
const inputHandler = sinon.spy();
el.addEventListener('sl-change', changeHandler);
el.addEventListener('sl-input', inputHandler);
await clickOnElement(trigger); // open the dropdown
await aTimeout(200); // wait for the dropdown to open
await clickOnElement(formatButton); // click on the format button
await el.updateComplete;
expect(el.value).to.equal('rgb(255, 255, 255)');
expect(changeHandler).to.have.been.calledOnce;
expect(inputHandler).to.have.been.calledOnce;
});
it('should render the correct swatches when passing a string of color values', async () => {
const el = await fixture(
html` `
);
const swatches = [...el.shadowRoot!.querySelectorAll('[part~="swatch"] > div')];
expect(swatches.length).to.equal(3);
expect(getComputedStyle(swatches[0]).backgroundColor).to.equal('rgb(255, 0, 0)');
expect(getComputedStyle(swatches[1]).backgroundColor).to.equal('rgb(0, 128, 0)');
expect(getComputedStyle(swatches[2]).backgroundColor).to.equal('rgb(0, 0, 255)');
});
it('should render the correct swatches when passing an array of color values', async () => {
const el = await fixture(html` `);
el.swatches = ['red', '#008000', 'rgb(0,0,255)'];
await el.updateComplete;
const swatches = [...el.shadowRoot!.querySelectorAll('[part~="swatch"] > div')];
expect(swatches.length).to.equal(3);
expect(getComputedStyle(swatches[0]).backgroundColor).to.equal('rgb(255, 0, 0)');
expect(getComputedStyle(swatches[1]).backgroundColor).to.equal('rgb(0, 128, 0)');
expect(getComputedStyle(swatches[2]).backgroundColor).to.equal('rgb(0, 0, 255)');
});
it('should emit sl-change and sl-input when clicking on a swatch', async () => {
const el = await fixture(html` `);
const trigger = el.shadowRoot!.querySelector('[part~="trigger"]')!;
const swatch = el.shadowRoot!.querySelector('[part~="swatch"]')!;
const changeHandler = sinon.spy();
const inputHandler = sinon.spy();
el.addEventListener('sl-change', changeHandler);
el.addEventListener('sl-input', inputHandler);
await clickOnElement(trigger); // open the dropdown
await aTimeout(200); // wait for the dropdown to open
await clickOnElement(swatch); // click on the swatch
await el.updateComplete;
expect(changeHandler).to.have.been.calledOnce;
expect(inputHandler).to.have.been.calledOnce;
});
it('should emit sl-change and sl-input when selecting a color with the keyboard', async () => {
const el = await fixture(html` `);
const trigger = el.shadowRoot!.querySelector('[part~="trigger"]')!;
const gridHandle = el.shadowRoot!.querySelector('[part~="grid-handle"]')!;
const changeHandler = sinon.spy();
const inputHandler = sinon.spy();
el.addEventListener('sl-change', changeHandler);
el.addEventListener('sl-input', inputHandler);
await clickOnElement(trigger); // open the dropdown
await aTimeout(200); // wait for the dropdown to open
gridHandle.focus();
await sendKeys({ press: 'ArrowRight' }); // move the grid handle
await el.updateComplete;
expect(changeHandler).to.have.been.calledOnce;
expect(inputHandler).to.have.been.calledOnce;
});
it('should emit sl-change and sl-input when selecting a color with the keyboard', async () => {
const el = await fixture(html` `);
const trigger = el.shadowRoot!.querySelector('[part~="trigger"]')!;
const handle = el.shadowRoot!.querySelector('[part~="grid-handle"]')!;
const changeHandler = sinon.spy();
const inputHandler = sinon.spy();
el.addEventListener('sl-change', changeHandler);
el.addEventListener('sl-input', inputHandler);
await clickOnElement(trigger); // open the dropdown
await aTimeout(200); // wait for the dropdown to open
handle.focus();
await sendKeys({ press: 'ArrowRight' }); // move the handle
await el.updateComplete;
expect(changeHandler).to.have.been.calledOnce;
expect(inputHandler).to.have.been.calledOnce;
});
it('should emit sl-change and sl-input when selecting hue with the keyboard', async () => {
const el = await fixture(html` `);
const trigger = el.shadowRoot!.querySelector('[part~="trigger"]')!;
const handle = el.shadowRoot!.querySelector('[part~="hue-slider"] > span')!;
const changeHandler = sinon.spy();
const inputHandler = sinon.spy();
el.addEventListener('sl-change', changeHandler);
el.addEventListener('sl-input', inputHandler);
await clickOnElement(trigger); // open the dropdown
await aTimeout(200); // wait for the dropdown to open
handle.focus();
await sendKeys({ press: 'ArrowRight' }); // move the handle
await el.updateComplete;
expect(changeHandler).to.have.been.calledOnce;
expect(inputHandler).to.have.been.calledOnce;
});
it('should emit sl-change and sl-input when selecting opacity with the keyboard', async () => {
const el = await fixture(html` `);
const trigger = el.shadowRoot!.querySelector('[part~="trigger"]')!;
const handle = el.shadowRoot!.querySelector('[part~="opacity-slider"] > span')!;
const changeHandler = sinon.spy();
const inputHandler = sinon.spy();
el.addEventListener('sl-change', changeHandler);
el.addEventListener('sl-input', inputHandler);
await clickOnElement(trigger); // open the dropdown
await aTimeout(200); // wait for the dropdown to open
handle.focus();
await sendKeys({ press: 'ArrowRight' }); // move the handle
await el.updateComplete;
expect(changeHandler).to.have.been.calledOnce;
expect(inputHandler).to.have.been.calledOnce;
});
it('should emit sl-change and sl-input when entering a value in the color input and pressing enter', async () => {
const el = await fixture(html` `);
const trigger = el.shadowRoot!.querySelector('[part~="trigger"]')!;
const input = el.shadowRoot!.querySelector('[part~="input"]')!;
const changeHandler = sinon.spy();
const inputHandler = sinon.spy();
el.addEventListener('sl-change', changeHandler);
el.addEventListener('sl-input', inputHandler);
await clickOnElement(trigger); // open the dropdown
await aTimeout(200); // wait for the dropdown to open
input.focus(); // focus the input
await el.updateComplete;
await sendKeys({ type: 'fc0' }); // type in a color
await sendKeys({ press: 'Enter' }); // press enter
await el.updateComplete;
expect(changeHandler).to.have.been.calledOnce;
expect(inputHandler).to.have.been.calledOnce;
});
it('should emit sl-change and sl-input when entering a value in the color input and blurring the field', async () => {
const el = await fixture(html` `);
const trigger = el.shadowRoot!.querySelector('[part~="trigger"]')!;
const input = el.shadowRoot!.querySelector('[part~="input"]')!;
const changeHandler = sinon.spy();
const inputHandler = sinon.spy();
el.addEventListener('sl-change', changeHandler);
el.addEventListener('sl-input', inputHandler);
await clickOnElement(trigger); // open the dropdown
await aTimeout(200); // wait for the dropdown to open
input.focus(); // focus the input
await el.updateComplete;
await sendKeys({ type: 'fc0' }); // type in a color
input.blur(); // commit changes by blurring the field
await el.updateComplete;
expect(changeHandler).to.have.been.calledOnce;
expect(inputHandler).to.have.been.calledOnce;
});
it('should render the correct format when selecting a swatch of a different format', async () => {
const el = await fixture(html` `);
const trigger = el.shadowRoot!.querySelector('[part~="trigger"]')!;
const changeHandler = sinon.spy();
const inputHandler = sinon.spy();
el.addEventListener('sl-change', changeHandler);
el.addEventListener('sl-input', inputHandler);
el.swatches = ['#fff'];
await el.updateComplete;
const swatch = el.shadowRoot!.querySelector('[part~="swatch"]')!;
await clickOnElement(trigger); // open the dropdown
await aTimeout(200); // wait for the dropdown to open
await clickOnElement(swatch); // click on the swatch
await el.updateComplete;
expect(el.value).to.equal('rgb(255, 255, 255)');
expect(changeHandler).to.have.been.calledOnce;
expect(inputHandler).to.have.been.calledOnce;
});
});
it('should render in a dropdown', async () => {
const el = await fixture(html` `);
const dropdown = el.shadowRoot!.querySelector('sl-dropdown');
expect(dropdown).to.exist;
});
it('should not render in a dropdown when inline is enabled', async () => {
const el = await fixture(html` `);
const dropdown = el.shadowRoot!.querySelector('sl-dropdown');
expect(dropdown).to.not.exist;
});
it('should show opacity slider when opacity is enabled', async () => {
const el = await fixture(html` `);
const opacitySlider = el.shadowRoot!.querySelector('[part*="opacity-slider"]')!;
expect(opacitySlider).to.exist;
});
it('should display a color when an initial value is provided', async () => {
const el = await fixture(html` `);
const trigger = el.shadowRoot!.querySelector('[part~="trigger"]');
expect(trigger?.style.color).to.equal('rgb(0, 0, 0)');
});
it('should display a color with opacity when an initial value with opacity is provided', async () => {
const el = await fixture(html` `);
const trigger = el.shadowRoot!.querySelector('[part~="trigger"]')!;
const previewButton = el.shadowRoot!.querySelector('[part~="preview"]');
const previewColor = getComputedStyle(previewButton!).getPropertyValue('--preview-color');
expect(trigger.style.color).to.equal('rgba(255, 0, 0, 0.314)');
expect(previewColor).to.equal('#ff000050');
});
describe('when submitting a form', () => {
it('should serialize its name and value with FormData', async () => {
const form = await fixture(html`
`);
const formData = new FormData(form);
expect(formData.get('a')).to.equal('#ffcc00');
});
it('should serialize its name and value with JSON', async () => {
const form = await fixture(html`
`);
const json = serialize(form);
expect(json.a).to.equal('#ffcc00');
});
it('should be present in form data when using the form attribute and located outside of a