Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
55c7a92
fix(tooltip): emits close and beforeClose events when container is se…
Elijbet Jun 30, 2023
ae243dd
mark connect/disconnectOpenCloseComponent as @deprecated and update t…
Elijbet Jul 3, 2023
c6c5768
Merge branch 'main' into elijbet/6279-emit-close-and-before-close-whe…
Elijbet Jul 3, 2023
b70f025
e2e test for cancelled transition
Elijbet Jul 3, 2023
39a1a1b
Merge branch 'main' into elijbet/6279-emit-close-and-before-close-whe…
Elijbet Jul 3, 2023
3df762c
cleanup
Elijbet Jul 4, 2023
cff99e5
Merge branch 'main' into elijbet/6279-emit-close-and-before-close-whe…
Elijbet Jul 5, 2023
0b4ec0b
provide example to deprecation notice and refactor test
Elijbet Jul 6, 2023
54c4647
chore: release next
github-actions[bot] Jul 5, 2023
84c5332
fix(flow): Call setFocus() on back button click (#7285)
driskull Jul 5, 2023
ddc5c1d
chore: release next
github-actions[bot] Jul 6, 2023
7ce6011
build(deps): Bump focus-trap from 7.4.3 to 7.5.2 (#7279)
dependabot[bot] Jul 6, 2023
48b6359
refactor(popover): renames private method (#7286)
driskull Jul 6, 2023
e0850b5
feat: improve focus behavior in components (#7277)
driskull Jul 6, 2023
7aed1b2
move the example to onToggle
Elijbet Jul 6, 2023
7375c49
Merge branch 'main' into elijbet/6279-emit-close-and-before-close-whe…
Elijbet Jul 6, 2023
89f361b
Merge branch 'main' into elijbet/6279-emit-close-and-before-close-whe…
Elijbet Jul 12, 2023
171c331
resolved merge conflict
Elijbet Jul 20, 2023
8d91830
additional info to implementation details of onToggleOpenCloseComponent
Elijbet Jul 20, 2023
3f3396b
Merge branch 'main' into elijbet/6279-emit-close-and-before-close-whe…
Elijbet Jul 28, 2023
6424c3d
Merge branch 'main' into elijbet/6279-emit-close-and-before-close-whe…
Elijbet Aug 1, 2023
b3f3d9d
modify onToggleOpenCloseComponent to account for the cases when open …
Elijbet Aug 1, 2023
4d9434a
Merge branch 'main' into elijbet/6279-emit-close-and-before-close-whe…
Elijbet Aug 1, 2023
1aa3869
Merge branch 'main' into elijbet/6279-emit-close-and-before-close-whe…
Elijbet Aug 2, 2023
baf463b
Merge branch 'main' into elijbet/6279-emit-close-and-before-close-whe…
Elijbet Aug 2, 2023
a3eef42
merge main
jcfranco Aug 3, 2023
a638fc4
fix: ensure open/close components emit events when removed before, du…
jcfranco Aug 3, 2023
ec85604
tidy up
jcfranco Aug 3, 2023
2005e86
fix modal test
jcfranco Aug 3, 2023
5df1aec
add extra delay for focus trap to kick in
jcfranco Aug 3, 2023
6a3d52b
isolate modal E2E test for quicker CI troubleshooting
jcfranco Aug 3, 2023
ab6597b
wait longer before asserting on focus target
jcfranco Aug 3, 2023
3d71180
restore animation delay
jcfranco Aug 3, 2023
cdb7ed7
remove delay after modal opens
jcfranco Aug 3, 2023
4d3d7d7
restore test suites
jcfranco Aug 3, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
125 changes: 51 additions & 74 deletions packages/calcite-components/src/components/modal/modal.e2e.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { newE2EPage } from "@stencil/core/testing";
import { focusable, renders, slots, hidden, t9n } from "../../tests/commonTests";
import { html } from "../../../support/formatting";
import { CSS, SLOTS, DURATIONS } from "./resources";
import { isElementFocused, newProgrammaticE2EPage, skipAnimations } from "../../tests/utils";
import { CSS, SLOTS } from "./resources";
import { GlobalTestProps, isElementFocused, newProgrammaticE2EPage, skipAnimations } from "../../tests/utils";

describe("calcite-modal properties", () => {
describe("renders", () => {
Expand Down Expand Up @@ -132,29 +132,24 @@ describe("calcite-modal properties", () => {
});

describe("opening and closing behavior", () => {
function getTransitionTransform(
modalSelector: string,
modalContainerSelector: string,
type: "none" | "matrix"
): boolean {
const modalContainer = document
.querySelector(modalSelector)
.shadowRoot.querySelector<HTMLElement>(modalContainerSelector);
return getComputedStyle(modalContainer).transform.startsWith(type);
}

const getTransitionDuration = (): { duration: string } => {
const modal = document.querySelector("calcite-modal");
const { transitionDuration } = window.getComputedStyle(modal);
return {
duration: transitionDuration,
};
};

it.skip("opens and closes", async () => {
it("opens and closes", async () => {
const page = await newE2EPage();
await page.setContent(html`<calcite-modal style="transition: opacity ${DURATIONS.test}s"></calcite-modal>`);
await page.setContent(html`<calcite-modal></calcite-modal>`);
const modal = await page.find("calcite-modal");

type ModalEventOrderWindow = GlobalTestProps<{ events: string[] }>;

await page.$eval("calcite-modal", (modal: HTMLCalciteModalElement) => {
const receivedEvents: string[] = [];
(window as ModalEventOrderWindow).events = receivedEvents;

["calciteModalBeforeOpen", "calciteModalOpen", "calciteModalBeforeClose", "calciteModalClose"].forEach(
(eventType) => {
modal.addEventListener(eventType, (event) => receivedEvents.push(event.type));
}
);
});

const beforeOpenSpy = await modal.spyOnEvent("calciteModalBeforeOpen");
const openSpy = await modal.spyOnEvent("calciteModalOpen");
const beforeCloseSpy = await modal.spyOnEvent("calciteModalBeforeClose");
Expand All @@ -164,54 +159,45 @@ describe("opening and closing behavior", () => {
expect(openSpy).toHaveReceivedEventTimes(0);
expect(beforeCloseSpy).toHaveReceivedEventTimes(0);
expect(closeSpy).toHaveReceivedEventTimes(0);
await page.waitForFunction(getTransitionTransform, {}, "calcite-modal", `.${CSS.modal}`, "none");

expect(await modal.isVisible()).toBe(false);

const modalBeforeOpen = page.waitForEvent("calciteModalBeforeOpen");
const modalOpen = page.waitForEvent("calciteModalOpen");
await modal.setProperty("open", true);
let waitForEvent = page.waitForEvent("calciteModalBeforeOpen");
await page.waitForChanges();
await waitForEvent;

expect(beforeOpenSpy).toHaveReceivedEventTimes(1);
expect(openSpy).toHaveReceivedEventTimes(0);
expect(beforeCloseSpy).toHaveReceivedEventTimes(0);
expect(closeSpy).toHaveReceivedEventTimes(0);
await page.waitForFunction(getTransitionTransform, {}, "calcite-modal", `.${CSS.modal}`, "matrix");

waitForEvent = page.waitForEvent("calciteModalOpen");
await waitForEvent;
await modalBeforeOpen;
await modalOpen;

expect(beforeOpenSpy).toHaveReceivedEventTimes(1);
expect(openSpy).toHaveReceivedEventTimes(1);
expect(beforeCloseSpy).toHaveReceivedEventTimes(0);
expect(closeSpy).toHaveReceivedEventTimes(0);
expect(await modal.getProperty("open")).toBe(true);
await page.waitForFunction(getTransitionTransform, {}, "calcite-modal", `.${CSS.modal}`, "matrix");
await page.waitForFunction(getTransitionTransform, {}, "calcite-modal", `.${CSS.modal}`, "none");

expect(await modal.isVisible()).toBe(true);

const modalBeforeClose = page.waitForEvent("calciteModalBeforeClose");
const modalClose = page.waitForEvent("calciteModalClose");
await modal.setProperty("open", false);
waitForEvent = page.waitForEvent("calciteModalBeforeClose");
await page.waitForChanges();
await waitForEvent;

const opacityTransition = await page.evaluate(getTransitionDuration);
expect(opacityTransition.duration).toEqual(`${DURATIONS.test}s`);
await modalBeforeClose;
await modalClose;

expect(beforeOpenSpy).toHaveReceivedEventTimes(1);
expect(openSpy).toHaveReceivedEventTimes(1);
expect(beforeCloseSpy).toHaveReceivedEventTimes(1);
expect(closeSpy).toHaveReceivedEventTimes(0);
await page.waitForFunction(getTransitionTransform, {}, "calcite-modal", `.${CSS.modal}`, "matrix");
expect(closeSpy).toHaveReceivedEventTimes(1);

waitForEvent = page.waitForEvent("calciteModalClose");
await waitForEvent;
expect(await modal.isVisible()).toBe(false);

expect(beforeOpenSpy).toHaveReceivedEventTimes(1);
expect(openSpy).toHaveReceivedEventTimes(1);
expect(beforeCloseSpy).toHaveReceivedEventTimes(1);
expect(closeSpy).toHaveReceivedEventTimes(1);
await page.waitForFunction(getTransitionTransform, {}, "calcite-modal", `.${CSS.modal}`, "matrix");
await page.waitForFunction(getTransitionTransform, {}, "calcite-modal", `.${CSS.modal}`, "none");
expect(await modal.getProperty("open")).toBe(false);
expect(await page.evaluate(() => (window as ModalEventOrderWindow).events)).toEqual([
"calciteModalBeforeOpen",
"calciteModalOpen",
"calciteModalBeforeClose",
"calciteModalClose",
]);
});

it("emits when set to open on initial render", async () => {
Expand All @@ -220,18 +206,16 @@ describe("opening and closing behavior", () => {
const beforeOpenSpy = await page.spyOnEvent("calciteModalBeforeOpen");
const openSpy = await page.spyOnEvent("calciteModalOpen");

await page.evaluate((transitionDuration: string): void => {
const waitForBeforeOpenEvent = page.waitForEvent("calciteModalBeforeOpen");
const waitForOpenEvent = page.waitForEvent("calciteModalOpen");

await page.evaluate((): void => {
const modal = document.createElement("calcite-modal");
modal.open = true;
modal.style.transition = `opacity ${transitionDuration}s`;
document.body.append(modal);
}, `${DURATIONS.test}`);

await page.waitForTimeout(DURATIONS.test);

const waitForBeforeOpenEvent = page.waitForEvent("calciteModalBeforeOpen");
const waitForOpenEvent = page.waitForEvent("calciteModalOpen");
});

await page.waitForChanges();
await waitForBeforeOpenEvent;
await waitForOpenEvent;

Expand All @@ -246,28 +230,24 @@ describe("opening and closing behavior", () => {
const beforeOpenSpy = await page.spyOnEvent("calciteModalBeforeOpen");
const openSpy = await page.spyOnEvent("calciteModalOpen");

const waitForOpenEvent = page.waitForEvent("calciteModalOpen");
const waitForBeforeOpenEvent = page.waitForEvent("calciteModalBeforeOpen");

await page.evaluate((): void => {
const modal = document.createElement("calcite-modal");
modal.open = true;
document.body.append(modal);
});

const opacityTransition = await page.evaluate(getTransitionDuration);
expect(opacityTransition.duration).toEqual("0s");

await page.waitForChanges;

const waitForOpenEvent = page.waitForEvent("calciteModalOpen");
const waitForBeforeOpenEvent = page.waitForEvent("calciteModalBeforeOpen");

await page.waitForChanges();
await waitForBeforeOpenEvent;
await waitForOpenEvent;

expect(beforeOpenSpy).toHaveReceivedEventTimes(1);
expect(openSpy).toHaveReceivedEventTimes(1);
});

it.skip("emits when duration is set to 0", async () => {
it("emits when duration is set to 0", async () => {
const page = await newProgrammaticE2EPage();
await skipAnimations(page);

Expand All @@ -283,9 +263,6 @@ describe("opening and closing behavior", () => {
document.body.append(modal);
});

const opacityTransition = await page.evaluate(getTransitionDuration);
expect(opacityTransition.duration).toEqual("0s");

await page.waitForChanges();
await beforeOpenSpy;
await openSpy;
Expand Down Expand Up @@ -320,11 +297,11 @@ describe("calcite-modal accessibility checks", () => {
</div>
</calcite-modal>`
);
await skipAnimations(page);
await page.waitForChanges();
const modal = await page.find("calcite-modal");
const opened = page.waitForEvent("calciteModalOpen");
modal.setProperty("open", true);
await page.waitForChanges();
await opened;

expect(await isElementFocused(page, `.${CSS.close}`, { shadowed: true })).toBe(true);
await page.keyboard.press("Tab");
Expand Down
68 changes: 68 additions & 0 deletions packages/calcite-components/src/components/tooltip/tooltip.e2e.ts
Original file line number Diff line number Diff line change
Expand Up @@ -783,6 +783,73 @@ describe("calcite-tooltip", () => {
expect(beforeCloseEvent).toHaveReceivedEventTimes(1);
expect(closeEvent).toHaveReceivedEventTimes(1);
}

it("when open, it emits close events if no longer rendered", async () => {
const page = await newE2EPage();
await page.setContent(html`
<style>
.container {
height: 100px;
width: 100px;
border: 1px solid red;
}

.container:hover .template {
display: initial;
}

.template {
display: none;
}
</style>
<div class="container">
<div class="template">
<button id="ref">referenceElement</button>
<calcite-tooltip reference-element="ref">content</calcite-tooltip>
</div>
</div>
<button class="hoverOutsideContainer">some other content</button>
`);

const beforeCloseEvent = await page.spyOnEvent("calciteTooltipBeforeClose");
const closeEvent = await page.spyOnEvent("calciteTooltipClose");
const beforeOpenEvent = await page.spyOnEvent("calciteTooltipBeforeOpen");
const openEvent = await page.spyOnEvent("calciteTooltipOpen");

const container = await page.find(".container");
const tooltip = await page.find(`calcite-tooltip`);

expect(await tooltip.isVisible()).toBe(false);

await container.hover();
await page.waitForChanges();

const ref = await page.find("#ref");
await ref.hover();

await page.waitForTimeout(TOOLTIP_OPEN_DELAY_MS);
await page.waitForChanges();

expect(await tooltip.isVisible()).toBe(true);

expect(beforeOpenEvent).toHaveReceivedEventTimes(1);
expect(openEvent).toHaveReceivedEventTimes(1);
expect(beforeCloseEvent).toHaveReceivedEventTimes(0);
expect(closeEvent).toHaveReceivedEventTimes(0);

const hoverOutsideContainer = await page.find(".hoverOutsideContainer");
await hoverOutsideContainer.hover();

await page.waitForTimeout(TOOLTIP_CLOSE_DELAY_MS);
await page.waitForChanges();

expect(await tooltip.isVisible()).not.toBe(true);

expect(beforeOpenEvent).toHaveReceivedEventTimes(1);
expect(openEvent).toHaveReceivedEventTimes(1);
expect(beforeCloseEvent).toHaveReceivedEventTimes(1);
expect(closeEvent).toHaveReceivedEventTimes(1);
});
});

it.skip("should open hovered tooltip while pointer is moving", async () => {
Expand Down Expand Up @@ -905,6 +972,7 @@ describe("calcite-tooltip", () => {
describe("within shadowRoot", () => {
async function defineTestComponents(page: E2EPage): Promise<void> {
await page.setContent("<calcite-tooltip></calcite-tooltip>");

await page.evaluate((): void => {
const customComponents: { name: string; html: string }[] = [
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,12 @@ export class Tooltip implements FloatingUIComponent, OpenCloseComponent {
}
}

async componentWillLoad(): Promise<void> {
if (this.open) {
onToggleOpenCloseComponent(this);
}
}

componentDidLoad(): void {
if (this.referenceElement && !this.effectiveReferenceElement) {
this.setUpReferenceElement();
Expand Down
Loading