Skip to content

Commit

Permalink
bulletproof part selectors
Browse files Browse the repository at this point in the history
  • Loading branch information
claviska committed Nov 17, 2022
1 parent 23414fe commit a3f6589
Show file tree
Hide file tree
Showing 25 changed files with 109 additions and 109 deletions.
12 changes: 6 additions & 6 deletions src/components/alert/alert.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,21 +5,21 @@ import type SlAlert from './alert';
describe('<sl-alert>', () => {
it('should be visible with the open attribute', async () => {
const el = await fixture<SlAlert>(html` <sl-alert open>I am an alert</sl-alert> `);
const base = el.shadowRoot!.querySelector<HTMLElement>('[part="base"]')!;
const base = el.shadowRoot!.querySelector<HTMLElement>('[part~="base"]')!;

expect(base.hidden).to.be.false;
});

it('should not be visible without the open attribute', async () => {
const el = await fixture<SlAlert>(html` <sl-alert>I am an alert</sl-alert> `);
const base = el.shadowRoot!.querySelector<HTMLElement>('[part="base"]')!;
const base = el.shadowRoot!.querySelector<HTMLElement>('[part~="base"]')!;

expect(base.hidden).to.be.true;
});

it('should emit sl-show and sl-after-show when calling show()', async () => {
const el = await fixture<SlAlert>(html` <sl-alert>I am an alert</sl-alert> `);
const base = el.shadowRoot!.querySelector<HTMLElement>('[part="base"]')!;
const base = el.shadowRoot!.querySelector<HTMLElement>('[part~="base"]')!;
const showHandler = sinon.spy();
const afterShowHandler = sinon.spy();

Expand All @@ -37,7 +37,7 @@ describe('<sl-alert>', () => {

it('should emit sl-hide and sl-after-hide when calling hide()', async () => {
const el = await fixture<SlAlert>(html` <sl-alert open>I am an alert</sl-alert> `);
const base = el.shadowRoot!.querySelector<HTMLElement>('[part="base"]')!;
const base = el.shadowRoot!.querySelector<HTMLElement>('[part~="base"]')!;
const hideHandler = sinon.spy();
const afterHideHandler = sinon.spy();

Expand All @@ -55,7 +55,7 @@ describe('<sl-alert>', () => {

it('should emit sl-show and sl-after-show when setting open = true', async () => {
const el = await fixture<SlAlert>(html` <sl-alert>I am an alert</sl-alert> `);
const base = el.shadowRoot!.querySelector<HTMLElement>('[part="base"]')!;
const base = el.shadowRoot!.querySelector<HTMLElement>('[part~="base"]')!;
const showHandler = sinon.spy();
const afterShowHandler = sinon.spy();

Expand All @@ -73,7 +73,7 @@ describe('<sl-alert>', () => {

it('should emit sl-hide and sl-after-hide when setting open = false', async () => {
const el = await fixture<SlAlert>(html` <sl-alert open>I am an alert</sl-alert> `);
const base = el.shadowRoot!.querySelector<HTMLElement>('[part="base"]')!;
const base = el.shadowRoot!.querySelector<HTMLElement>('[part~="base"]')!;
const hideHandler = sinon.spy();
const afterHideHandler = sinon.spy();

Expand Down
2 changes: 1 addition & 1 deletion src/components/alert/alert.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ export default class SlAlert extends ShoelaceElement {
private readonly hasSlotController = new HasSlotController(this, 'icon', 'suffix');
private readonly localize = new LocalizeController(this);

@query('[part="base"]') base: HTMLElement;
@query('[part~="base"]') base: HTMLElement;

/** Indicates whether or not the alert is open. You can use this in lieu of the show/hide methods. */
@property({ type: Boolean, reflect: true }) open = false;
Expand Down
10 changes: 5 additions & 5 deletions src/components/avatar/avatar.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ describe('<sl-avatar>', () => {
});

it('should default to circle styling', () => {
const part = el.shadowRoot!.querySelector('[part="base"]')!;
const part = el.shadowRoot!.querySelector('[part~="base"]')!;
expect(el.getAttribute('shape')).to.eq('circle');
expect(part.classList.value.trim()).to.eq('avatar avatar--circle');
});
Expand All @@ -40,13 +40,13 @@ describe('<sl-avatar>', () => {
});

it('renders "image" part, with src and a role of presentation', () => {
const part = el.shadowRoot!.querySelector('[part="image"]')!;
const part = el.shadowRoot!.querySelector('[part~="image"]')!;

expect(part.getAttribute('src')).to.eq(image);
});

it('renders the label attribute in the "base" part', () => {
const part = el.shadowRoot!.querySelector('[part="base"]')!;
const part = el.shadowRoot!.querySelector('[part~="base"]')!;

expect(part.getAttribute('aria-label')).to.eq(label);
});
Expand All @@ -63,7 +63,7 @@ describe('<sl-avatar>', () => {
});

it('renders "initials" part, with initials as the text node', () => {
const part = el.shadowRoot!.querySelector<HTMLElement>('[part="initials"]')!;
const part = el.shadowRoot!.querySelector<HTMLElement>('[part~="initials"]')!;

expect(part.innerText).to.eq(initials);
});
Expand All @@ -80,7 +80,7 @@ describe('<sl-avatar>', () => {
});

it('appends the appropriate class on the "base" part', () => {
const part = el.shadowRoot!.querySelector('[part="base"]')!;
const part = el.shadowRoot!.querySelector('[part~="base"]')!;

expect(el.getAttribute('shape')).to.eq(shape);
expect(part.classList.value.trim()).to.eq(`avatar avatar--${shape}`);
Expand Down
10 changes: 5 additions & 5 deletions src/components/badge/badge.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ describe('<sl-badge>', () => {
it('should pass accessibility tests with a role of status on the base part.', async () => {
await expect(el).to.be.accessible();

const part = el.shadowRoot!.querySelector('[part="base"]')!;
const part = el.shadowRoot!.querySelector('[part~="base"]')!;
expect(part.getAttribute('role')).to.eq('status');
});

Expand All @@ -21,7 +21,7 @@ describe('<sl-badge>', () => {
});

it('should default to square styling, with the primary color', () => {
const part = el.shadowRoot!.querySelector('[part="base"]')!;
const part = el.shadowRoot!.querySelector('[part~="base"]')!;
expect(part.classList.value.trim()).to.eq('badge badge--primary');
});
});
Expand All @@ -36,7 +36,7 @@ describe('<sl-badge>', () => {
});

it('should append the pill class to the classlist to render a pill', () => {
const part = el.shadowRoot!.querySelector('[part="base"]')!;
const part = el.shadowRoot!.querySelector('[part~="base"]')!;
expect(part.classList.value.trim()).to.eq('badge badge--primary badge--pill');
});
});
Expand All @@ -51,7 +51,7 @@ describe('<sl-badge>', () => {
});

it('should append the pulse class to the classlist to render a pulse', () => {
const part = el.shadowRoot!.querySelector('[part="base"]')!;
const part = el.shadowRoot!.querySelector('[part~="base"]')!;
expect(part.classList.value.trim()).to.eq('badge badge--primary badge--pulse');
});
});
Expand All @@ -67,7 +67,7 @@ describe('<sl-badge>', () => {
});

it('should default to square styling, with the primary color', () => {
const part = el.shadowRoot!.querySelector('[part="base"]')!;
const part = el.shadowRoot!.querySelector('[part~="base"]')!;
expect(part.classList.value.trim()).to.eq(`badge badge--${variant}`);
});
});
Expand Down
12 changes: 6 additions & 6 deletions src/components/breadcrumb-item/breadcrumb-item.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,12 @@ describe('<sl-breadcrumb-item>', () => {
});

it('should hide the separator from screen readers', () => {
const separator = el.shadowRoot!.querySelector<HTMLSpanElement>('[part="separator"]');
const separator = el.shadowRoot!.querySelector<HTMLSpanElement>('[part~="separator"]');
expect(separator).attribute('aria-hidden', 'true');
});

it('should render a HTMLButtonElement as the part "label", with a set type "button"', () => {
const button = el.shadowRoot!.querySelector<HTMLButtonElement>('[part="label"]');
const button = el.shadowRoot!.querySelector<HTMLButtonElement>('[part~="label"]');
expect(button).to.exist;
expect(button).attribute('type', 'button');
});
Expand All @@ -38,7 +38,7 @@ describe('<sl-breadcrumb-item>', () => {
});

it('should render a HTMLAnchorElement as the part "label", with the supplied href value', () => {
const hyperlink = el.shadowRoot!.querySelector<HTMLAnchorElement>('[part="label"]');
const hyperlink = el.shadowRoot!.querySelector<HTMLAnchorElement>('[part~="label"]');
expect(hyperlink).attribute('href', 'https://jsonplaceholder.typicode.com/');
});
});
Expand All @@ -58,7 +58,7 @@ describe('<sl-breadcrumb-item>', () => {
let hyperlink: HTMLAnchorElement | null;

before(() => {
hyperlink = el.shadowRoot!.querySelector<HTMLAnchorElement>('[part="label"]');
hyperlink = el.shadowRoot!.querySelector<HTMLAnchorElement>('[part~="label"]');
});

it('should use the supplied href value, as the href attribute value', () => {
Expand Down Expand Up @@ -124,7 +124,7 @@ describe('<sl-breadcrumb-item>', () => {
});

it('should append class "breadcrumb-item--has-prefix" to "base" part', () => {
const part = el.shadowRoot!.querySelector('[part="base"]')!;
const part = el.shadowRoot!.querySelector('[part~="base"]')!;
expect(part.classList.value.trim()).to.equal('breadcrumb-item breadcrumb-item--has-prefix');
});
});
Expand All @@ -151,7 +151,7 @@ describe('<sl-breadcrumb-item>', () => {
});

it('should append class "breadcrumb-item--has-suffix" to "base" part', () => {
const part = el.shadowRoot!.querySelector<HTMLElement>('[part="base"]')!;
const part = el.shadowRoot!.querySelector<HTMLElement>('[part~="base"]')!;
expect(part.classList.value.trim()).to.equal('breadcrumb-item breadcrumb-item--has-suffix');
});
});
Expand Down
4 changes: 2 additions & 2 deletions src/components/button/button.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ describe('<sl-button>', () => {

it('should not have a caret present', async () => {
const el = await fixture<SlButton>(html` <sl-button>Button Label</sl-button> `);
expect(el.shadowRoot?.querySelector('[part="caret"]')).not.to.exist;
expect(el.shadowRoot?.querySelector('[part~="caret"]')).not.to.exist;
});
});

Expand Down Expand Up @@ -98,7 +98,7 @@ describe('<sl-button>', () => {
describe('when caret', () => {
it('should have a caret present', async () => {
const el = await fixture<SlButton>(html` <sl-button caret>Button Label</sl-button> `);
expect(el.shadowRoot!.querySelector('[part="caret"]')).to.exist;
expect(el.shadowRoot!.querySelector('[part~="caret"]')).to.exist;
});
});

Expand Down
4 changes: 2 additions & 2 deletions src/components/checkbox/checkbox.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -205,14 +205,14 @@ describe('<sl-checkbox>', () => {
describe('indeterminate', () => {
it('should render indeterminate icon until checked', async () => {
const el = await fixture<SlCheckbox>(html`<sl-checkbox indeterminate></sl-checkbox>`);
let indeterminateIcon = el.shadowRoot!.querySelector('[part="indeterminate-icon"]')!;
let indeterminateIcon = el.shadowRoot!.querySelector('[part~="indeterminate-icon"]')!;

expect(indeterminateIcon).not.to.be.null;

el.click();
await el.updateComplete;

indeterminateIcon = el.shadowRoot!.querySelector('[part="indeterminate-icon"]')!;
indeterminateIcon = el.shadowRoot!.querySelector('[part~="indeterminate-icon"]')!;

expect(indeterminateIcon).to.be.null;
});
Expand Down
8 changes: 4 additions & 4 deletions src/components/color-picker/color-picker.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import type SlColorPicker from './color-picker';
describe('<sl-color-picker>', () => {
it('should emit change and show correct color when the value changes', async () => {
const el = await fixture<SlColorPicker>(html` <sl-color-picker></sl-color-picker> `);
const trigger = el.shadowRoot!.querySelector<HTMLElement>('[part="trigger"]')!;
const trigger = el.shadowRoot!.querySelector<HTMLElement>('[part~="trigger"]')!;
const changeHandler = sinon.spy();
const color = 'rgb(255, 204, 0)';

Expand Down Expand Up @@ -41,15 +41,15 @@ describe('<sl-color-picker>', () => {

it('should display a color when an initial value is provided', async () => {
const el = await fixture<SlColorPicker>(html` <sl-color-picker value="#000"></sl-color-picker> `);
const trigger = el.shadowRoot!.querySelector<HTMLButtonElement>('[part="trigger"]');
const trigger = el.shadowRoot!.querySelector<HTMLButtonElement>('[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<SlColorPicker>(html` <sl-color-picker opacity value="#ff000050"></sl-color-picker> `);
const trigger = el.shadowRoot!.querySelector<HTMLButtonElement>('[part="trigger"]');
const previewButton = el.shadowRoot!.querySelector<HTMLButtonElement>('[part="preview"]');
const trigger = el.shadowRoot!.querySelector<HTMLButtonElement>('[part~="trigger"]');
const previewButton = el.shadowRoot!.querySelector<HTMLButtonElement>('[part~="preview"]');
const previewColor = getComputedStyle(previewButton!).getPropertyValue('--preview-color');

expect(trigger!.style.color).to.equal('rgba(255, 0, 0, 0.314)');
Expand Down
4 changes: 2 additions & 2 deletions src/components/color-picker/color-picker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -87,8 +87,8 @@ declare const EyeDropper: EyeDropperConstructor;
export default class SlColorPicker extends ShoelaceElement {
static styles: CSSResultGroup = styles;

@query('[part="input"]') input: SlInput;
@query('[part="preview"]') previewButton: HTMLButtonElement;
@query('[part~="input"]') input: SlInput;
@query('[part~="preview"]') previewButton: HTMLButtonElement;
@query('.color-dropdown') dropdown: SlDropdown;

// @ts-expect-error -- Controller is currently unused
Expand Down
14 changes: 7 additions & 7 deletions src/components/dialog/dialog.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ describe('<sl-dialog>', () => {
const el = await fixture<SlDialog>(html`
<sl-dialog open>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</sl-dialog>
`);
const base = el.shadowRoot!.querySelector<HTMLElement>('[part="base"]')!;
const base = el.shadowRoot!.querySelector<HTMLElement>('[part~="base"]')!;

expect(base.hidden).to.be.false;
});
Expand All @@ -18,7 +18,7 @@ describe('<sl-dialog>', () => {
const el = await fixture<SlDialog>(
html` <sl-dialog>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</sl-dialog> `
);
const base = el.shadowRoot!.querySelector<HTMLElement>('[part="base"]')!;
const base = el.shadowRoot!.querySelector<HTMLElement>('[part~="base"]')!;

expect(base.hidden).to.be.true;
});
Expand All @@ -27,7 +27,7 @@ describe('<sl-dialog>', () => {
const el = await fixture<SlDialog>(html`
<sl-dialog>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</sl-dialog>
`);
const base = el.shadowRoot!.querySelector<HTMLElement>('[part="base"]')!;
const base = el.shadowRoot!.querySelector<HTMLElement>('[part~="base"]')!;
const showHandler = sinon.spy();
const afterShowHandler = sinon.spy();

Expand All @@ -47,7 +47,7 @@ describe('<sl-dialog>', () => {
const el = await fixture<SlDialog>(html`
<sl-dialog open>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</sl-dialog>
`);
const base = el.shadowRoot!.querySelector<HTMLElement>('[part="base"]')!;
const base = el.shadowRoot!.querySelector<HTMLElement>('[part~="base"]')!;
const hideHandler = sinon.spy();
const afterHideHandler = sinon.spy();

Expand All @@ -67,7 +67,7 @@ describe('<sl-dialog>', () => {
const el = await fixture<SlDialog>(html`
<sl-dialog>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</sl-dialog>
`);
const base = el.shadowRoot!.querySelector<HTMLElement>('[part="base"]')!;
const base = el.shadowRoot!.querySelector<HTMLElement>('[part~="base"]')!;
const showHandler = sinon.spy();
const afterShowHandler = sinon.spy();

Expand All @@ -87,7 +87,7 @@ describe('<sl-dialog>', () => {
const el = await fixture<SlDialog>(html`
<sl-dialog open>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</sl-dialog>
`);
const base = el.shadowRoot!.querySelector<HTMLElement>('[part="base"]')!;
const base = el.shadowRoot!.querySelector<HTMLElement>('[part~="base"]')!;
const hideHandler = sinon.spy();
const afterHideHandler = sinon.spy();

Expand All @@ -107,7 +107,7 @@ describe('<sl-dialog>', () => {
const el = await fixture<SlDialog>(html`
<sl-dialog open>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</sl-dialog>
`);
const overlay = el.shadowRoot!.querySelector<HTMLElement>('[part="overlay"]')!;
const overlay = el.shadowRoot!.querySelector<HTMLElement>('[part~="overlay"]')!;

el.addEventListener('sl-request-close', event => {
event.preventDefault();
Expand Down
14 changes: 7 additions & 7 deletions src/components/drawer/drawer.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ describe('<sl-drawer>', () => {
const el = await fixture<SlDrawer>(html`
<sl-drawer open>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</sl-drawer>
`);
const base = el.shadowRoot!.querySelector<HTMLElement>('[part="base"]')!;
const base = el.shadowRoot!.querySelector<HTMLElement>('[part~="base"]')!;

expect(base.hidden).to.be.false;
});
Expand All @@ -18,7 +18,7 @@ describe('<sl-drawer>', () => {
const el = await fixture<SlDrawer>(
html` <sl-drawer>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</sl-drawer> `
);
const base = el.shadowRoot!.querySelector<HTMLElement>('[part="base"]')!;
const base = el.shadowRoot!.querySelector<HTMLElement>('[part~="base"]')!;

expect(base.hidden).to.be.true;
});
Expand All @@ -27,7 +27,7 @@ describe('<sl-drawer>', () => {
const el = await fixture<SlDrawer>(html`
<sl-drawer>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</sl-drawer>
`);
const base = el.shadowRoot!.querySelector<HTMLElement>('[part="base"]')!;
const base = el.shadowRoot!.querySelector<HTMLElement>('[part~="base"]')!;
const showHandler = sinon.spy();
const afterShowHandler = sinon.spy();

Expand All @@ -47,7 +47,7 @@ describe('<sl-drawer>', () => {
const el = await fixture<SlDrawer>(html`
<sl-drawer open>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</sl-drawer>
`);
const base = el.shadowRoot!.querySelector<HTMLElement>('[part="base"]')!;
const base = el.shadowRoot!.querySelector<HTMLElement>('[part~="base"]')!;
const hideHandler = sinon.spy();
const afterHideHandler = sinon.spy();

Expand All @@ -67,7 +67,7 @@ describe('<sl-drawer>', () => {
const el = await fixture<SlDrawer>(html`
<sl-drawer>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</sl-drawer>
`);
const base = el.shadowRoot!.querySelector<HTMLElement>('[part="base"]')!;
const base = el.shadowRoot!.querySelector<HTMLElement>('[part~="base"]')!;
const showHandler = sinon.spy();
const afterShowHandler = sinon.spy();

Expand All @@ -87,7 +87,7 @@ describe('<sl-drawer>', () => {
const el = await fixture<SlDrawer>(html`
<sl-drawer open>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</sl-drawer>
`);
const base = el.shadowRoot!.querySelector<HTMLElement>('[part="base"]')!;
const base = el.shadowRoot!.querySelector<HTMLElement>('[part~="base"]')!;
const hideHandler = sinon.spy();
const afterHideHandler = sinon.spy();

Expand All @@ -107,7 +107,7 @@ describe('<sl-drawer>', () => {
const el = await fixture<SlDrawer>(html`
<sl-drawer open>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</sl-drawer>
`);
const overlay = el.shadowRoot!.querySelector<HTMLElement>('[part="overlay"]')!;
const overlay = el.shadowRoot!.querySelector<HTMLElement>('[part~="overlay"]')!;

el.addEventListener('sl-request-close', event => {
event.preventDefault();
Expand Down

0 comments on commit a3f6589

Please sign in to comment.