Skip to content

Commit

Permalink
fix e2e
Browse files Browse the repository at this point in the history
  • Loading branch information
alizedebray committed Jul 3, 2024
1 parent 6b8095d commit 7e1bf77
Show file tree
Hide file tree
Showing 7 changed files with 87 additions and 72 deletions.
72 changes: 45 additions & 27 deletions packages/components/cypress/e2e/collapsible.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,57 +3,75 @@ const COLLAPSIBLE_ID = '6a91848c-16ec-4a23-bc45-51c797b5b2c3';
describe('collapsible', () => {
describe('default', () => {
beforeEach(() => {
cy.getComponent('collapsible', COLLAPSIBLE_ID);
cy.get('@collapsible').find('.collapse').as('collapse');
cy.get(`#button--${COLLAPSIBLE_ID}--default`).as('toggler');
cy.getComponents(COLLAPSIBLE_ID, 'default', 'post-collapsible', 'post-collapsible-trigger');
cy.get('@collapsible-trigger').find('.btn').as('trigger');
});

it('should render', () => {
it('should have a collapsible', () => {
cy.get('@collapsible').should('exist');
});

it('should have a collapse', () => {
cy.get('@collapse').should('exist');
it('should have a trigger', () => {
cy.get('@trigger').should('exist');
});

it('should have a toggle button', () => {
cy.get('@toggler').should('exist');
it('should show the collapsible', () => {
cy.get('@collapsible').should(`be.visible`);
});

it('should be expanded', () => {
cy.get('@collapse').should(`be.visible`);
it('should set the correct ARIA attribute on the trigger', () => {
cy.get('@collapsible')
.invoke('attr', 'id')
.then(collapsibleId => {
cy.get('@trigger').should('have.attr', 'aria-controls', collapsibleId);
});
cy.get('@trigger').should('have.attr', 'aria-expanded', 'true');
});

it('should be collapsed after clicking on the toggle button once', () => {
cy.get('@toggler').click();
cy.get('@collapse').should(`be.hidden`);
it('should hide the collapsible after clicking on the trigger once', () => {
cy.get('@trigger').click();
cy.get('@collapsible').should(`be.hidden`);
});

it('should be expanded after clicking on the toggle button twice', () => {
cy.get('@toggler').dblclick();
cy.get('@collapse').should(`be.visible`);
it('should update the "aria-expanded" attribute after hiding the collapsible', () => {
cy.get('@trigger').click();
cy.get('@trigger').should('have.attr', 'aria-expanded', 'false');
});

it('should show the collapsible after clicking on the trigger twice', () => {
cy.get('@trigger').dblclick();
cy.get('@collapsible').should(`be.visible`);
});

it('should update the "aria-expanded" attribute after showing the collapsible', () => {
cy.get('@trigger').click();
cy.get('@trigger').should('have.attr', 'aria-expanded', 'true');
});
});

describe('initially collapsed', () => {
beforeEach(() => {
cy.getComponent('collapsible', COLLAPSIBLE_ID, 'initially-collapsed');
cy.get('@collapsible').find('.collapse').as('collapse');
cy.get(`#button--${COLLAPSIBLE_ID}--initially-collapsed`).as('toggler');
cy.getComponents(
COLLAPSIBLE_ID,
'initially-collapsed',
'post-collapsible',
'post-collapsible-trigger',
);
cy.get('@collapsible-trigger').find('.btn').as('trigger');
});

it('should be collapsed', () => {
cy.get('@collapse').should(`be.hidden`);
it('should hide the collapsible', () => {
cy.get('@collapsible').should(`be.hidden`);
});

it('should be expanded after clicking on the toggle button once', () => {
cy.get('@toggler').click();
cy.get('@collapse').should(`be.visible`);
it('should show the collapsible after clicking on the trigger once', () => {
cy.get('@trigger').click();
cy.get('@collapsible').should(`be.visible`);
});

it('should be collapsed after clicking on the toggle button twice', () => {
cy.get('@toggler').dblclick();
cy.get('@collapse').should(`be.hidden`);
it('should hide the collapsible after clicking on the trigger twice', () => {
cy.get('@trigger').dblclick();
cy.get('@collapsible').should(`be.hidden`);
});
});
});
Expand Down
10 changes: 8 additions & 2 deletions packages/components/cypress/support/commands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,10 +49,16 @@ export const isInViewport = function (_chai: Chai.ChaiStatic) {
chai.use(isInViewport);

Cypress.Commands.add('getComponent', (component: string, id: string, story = 'default') => {
cy.getComponents(id, story, component);
});

Cypress.Commands.add('getComponents', (id: string, story: string, ...components: string[]) => {
cy.visit(`/iframe.html?id=${id}--${story}`);

const alias = component.replace(/^post-/, '');
cy.get(`post-${alias}`, { timeout: 30000 }).as(alias);
components.forEach(component => {
const alias = component.replace(/^post-/, '');
cy.get(`post-${alias}.hydrated`, { timeout: 30000 }).as(alias);
});

cy.injectAxe();
});
Expand Down
1 change: 1 addition & 0 deletions packages/components/cypress/support/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ declare global {
namespace Cypress {
interface Chainable {
getComponent(component: string, id: string, story?: string): Chainable<any>;
getComponents(id: string, story: string, ...component: string[]): Chainable<any>;
getSnapshots(component: string): Chainable<any>;
checkAriaExpanded(
controlledElementSelector: string,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Component, Element, Host, h, Prop, Listen, Watch } from '@stencil/core';
import { Component, Element, Prop, Listen, Watch } from '@stencil/core';
import { version } from 'typescript';
import { isFocusable } from '@/utils/is-focusable';
import { checkNonEmpty, checkType } from '@/utils';
Expand All @@ -17,15 +17,22 @@ export class PostCollapsibleTrigger {
@Prop() for: string;

@Watch('for')
setAriaControls() {
setAriaAttributes() {
checkNonEmpty(this.for, 'The post-collapsible-trigger "for" prop is required.');
checkType(this.for, 'string', 'The post-collapsible-trigger "for" prop should be a id.');

// Add collapsible id to aria-controls
if (this.trigger) this.trigger.setAttribute('aria-controls', this.for);
if (this.trigger) {
this.trigger.setAttribute('aria-controls', this.for);

const isOpen = !this.collapsible?.collapsed;
if (isOpen !== undefined) this.trigger.setAttribute('aria-expanded', `${isOpen}`);
}
}

componentDidLoad() {
componentWillLoad() {
this.host.setAttribute('data-version', version);

const firstChild = this.host.children[0];
if (firstChild && firstChild.nodeType === Node.ELEMENT_NODE) {
this.trigger = firstChild as HTMLElement;
Expand All @@ -43,7 +50,7 @@ export class PostCollapsibleTrigger {
this.trigger.setAttribute('role', 'button');
}

this.setAriaControls();
this.setAriaAttributes();
}

@Listen('pointerdown')
Expand Down Expand Up @@ -71,12 +78,4 @@ export class PostCollapsibleTrigger {

return null;
}

render() {
return (
<Host data-version={version}>
<slot></slot>
</Host>
);
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,4 @@
:host {
display: block;
}

.collapse {
overflow: hidden;
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import {
Host,
Method,
Prop,
State,
Watch,
} from '@stencil/core';
import { version } from '@root/package.json';
Expand All @@ -26,12 +25,9 @@ import { checkEmptyOrType, isMotionReduced } from '@/utils';
export class PostCollapsible {
private isLoaded = false;
private isOpen = true;
private collapsible: HTMLElement;

@Element() host: HTMLPostCollapsibleElement;

@State() id: string;

/**
* If `true`, the element is initially collapsed otherwise it is displayed.
*/
Expand All @@ -57,10 +53,6 @@ export class PostCollapsible {
this.validateCollapsed();
}

componentWillRender() {
this.id = this.host.id || `c${crypto.randomUUID()}`;
}

componentDidLoad() {
if (this.collapsed) void this.toggle(false);
this.isLoaded = true;
Expand All @@ -78,7 +70,7 @@ export class PostCollapsible {
this.isOpen = !this.isOpen;
if (this.isLoaded) this.postToggle.emit(this.isOpen);

const animation = open ? expand(this.collapsible) : collapse(this.collapsible);
const animation = open ? expand(this.host) : collapse(this.host);

if (!this.isLoaded || isMotionReduced()) animation.finish();

Expand All @@ -91,10 +83,8 @@ export class PostCollapsible {

render() {
return (
<Host id={this.id} data-version={version}>
<div class="collapse" id={`${this.id}--collapse`} ref={el => (this.collapsible = el)}>
<slot />
</div>
<Host data-version={version}>
<slot />
</Host>
);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,35 +2,39 @@ import { html } from 'lit';
import type { Args, StoryContext, StoryObj } from '@storybook/web-components';
import { bombArgs } from '@/utils';

import meta, { Default } from './collapsible.stories';
import meta from './collapsible.stories';

const { id, ...metaWithoutId } = meta;

export default {
...metaWithoutId,
decorators: [],
title: 'Snapshots',
};

type Story = StoryObj<HTMLPostCollapsibleElement>;

export const Collapsible: Story = {
render: (_args: Args, context: StoryContext<HTMLPostCollapsibleElement>) => {
const templateVariants = bombArgs({
collapsed: [false, true],
}).map((args: Args) => {
return html`
<div class="col-6 p-3">
<p>collapsed: ${args.collapsed}</p>
${meta.render?.({ ...context.args, ...Default.args, ...args }, context)}
</div>
`;
});

return html`
<div>
${['white', 'dark'].map(
bg => html` <div class=${'row bg-' + bg}>${templateVariants}</div> `,
bg => html`
<div class=${'row bg-' + bg}>
${bombArgs({
collapsed: [false, true],
}).map(
(args: Args, i: number) => html`
<div class="col-6 p-3 d-flex flex-column gap-regular">
<p class="m-0">collapsed: ${args.collapsed}</p>
${meta.render?.(
{ ...context.args, ...args },
{ ...context, id: `${context.id}-${bg}-${i}` },
)}
</div>
`,
)}
</div>
`,
)}
</div>
`;
Expand Down

0 comments on commit 7e1bf77

Please sign in to comment.