Skip to content

Commit

Permalink
Merge pull request #448 from sebgroup/develop
Browse files Browse the repository at this point in the history
New release
  • Loading branch information
kherP authored Jul 23, 2020
2 parents 36e4a5a + 84c6f4f commit 658d609
Show file tree
Hide file tree
Showing 7 changed files with 262 additions and 148 deletions.
30 changes: 27 additions & 3 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 3 additions & 3 deletions src/Dropdown/Dropdown.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -330,10 +330,10 @@ const Dropdown: React.FunctionComponent<DropdownProps> = (props: DropdownProps):
return props.placeholders?.emptyText || "Empty";
}
if (selectedList && selectedList.length > 0) {
if (allSelected) {
return props.placeholders?.selectAllText || `All selected (${selectedList.length})`;
}
if (props.multi) {
if (allSelected) {
return props.placeholders?.selectAllText || `All selected (${selectedList.length})`;
}
if (selectedList.length === 1) {
return selectedList[0].label;
}
Expand Down
92 changes: 46 additions & 46 deletions src/Tooltip/Tooltip.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,67 +34,67 @@ describe("Component: Tooltip", () => {
document.body.innerHTML = "";
});

it("Should render", () => {
act(() => {
it("Should render", async () => {
await act(async () => {
render(<Tooltip content="tooltip message" />, container);
});
expect(container.querySelector(".tooltip-container")).toBeDefined();
});

it("Should pass custom class and id", () => {
it("Should pass custom class and id", async () => {
const className: string = "myTooltipClass";
const id: string = "myTooltipId";
act(() => {
await act(async () => {
render(<Tooltip content="tooltip message" id={id} className={className} />, container);
});
expect(container.querySelector(".tooltip-container").classList.contains(className)).toBeTruthy();
expect(container.querySelector(".tooltip-container").id).toBe(id);
});

it("Should render reference with custom svg if svg is passed", () => {
it("Should render reference with custom svg if svg is passed", async () => {
const content: string = "test";
const svg: JSX.Element = <svg>{content}</svg>;
act(() => {
await act(async () => {
render(<Tooltip customSvg={svg} />, container);
});
expect(document.body.querySelectorAll(".default-content").length).toBe(1);
expect(document.body.querySelector(".default-content>svg").innerHTML).toEqual(content);
});

it("Should render content", () => {
it("Should render content", async () => {
const content: string = "my tooltip";
act(() => {
await act(async () => {
render(<Tooltip content={content} />, container);
});
expect(document.body.querySelectorAll(".tooltip").length).toBe(1);
expect(document.body.querySelector(".tooltip-inner").innerHTML).toEqual(content);
});

it("Should render message and default message if no message is passed", () => {
it("Should render message and default message if no message is passed", async () => {
const message: string = "my tooltip";
act(() => {
await act(async () => {
render(<Tooltip />, container);
});
expect(document.body.querySelectorAll(".tooltip").length).toBe(1);
expect(document.body.querySelector(".message-container>.message").innerHTML).toEqual("Tooltip is empty. Please pass a message.");
act(() => {
await act(async () => {
render(<Tooltip message={message} />, container);
});
expect(document.body.querySelectorAll(".tooltip").length).toBe(1);
expect(document.body.querySelector(".message-container>.message").innerHTML).toEqual(message);
});

it("Should render message with title", () => {
it("Should render message with title", async () => {
const message: string = "my tooltip";
const title: string = "title";
act(() => {
await act(async () => {
render(<Tooltip message={message} title={title} />, container);
});
expect(document.body.querySelectorAll(".tooltip").length).toBe(1);
expect(document.body.querySelector(".message-container>.title").innerHTML).toEqual(title);
});

it("Should render message group", () => {
it("Should render message group", async () => {
const messageGroup: Array<TooltipMessageGroupItem> = [
{
title: "Tooltip title",
Expand All @@ -104,16 +104,16 @@ describe("Component: Tooltip", () => {
message: "tooltip 2",
},
];
act(() => {
await act(async () => {
render(<Tooltip messageGroup={messageGroup} />, container);
});
expect(document.body.querySelectorAll(".tooltip").length).toBe(1);
expect(document.body.querySelectorAll(".message-list-item").length).toEqual(messageGroup.length);
});

it("Should render node as message", () => {
it("Should render node as message", async () => {
const tooltipStr: string = "this is tooltip";
act(() => {
await act(async () => {
render(<Tooltip content={tooltipStr} />, container);
});
expect(document.body.querySelector(".tooltip-inner").textContent).toBe(tooltipStr);
Expand All @@ -124,37 +124,37 @@ describe("Component: Tooltip", () => {
<div>tooltip body</div>
</div>
);
act(() => {
await act(async () => {
render(<Tooltip content={content} />, container);
});
expect(document.body.querySelectorAll(".tooltip").length).toBe(1);
expect(document.body.querySelectorAll(`.${customClassName}`).length).toBe(1);
});

it("Should render tooltip with one of the supported themes", () => {
it("Should render tooltip with one of the supported themes", async () => {
const theme: TooltipTheme = "danger";
act(() => {
await act(async () => {
render(<Tooltip content="this is tooltip" />, container);
});
expect(document.body.querySelector(".tooltip").classList.contains("default")).toBeTruthy();
act(() => {
await act(async () => {
render(<Tooltip content="this is tooltip" theme={theme} />, container);
});
expect(document.body.querySelector(".tooltip").classList.contains(theme)).toBeTruthy();
});

it("Should call callback on visibility change if callback is set", () => {
it("Should call callback on visibility change if callback is set", async () => {
const callback: jest.Mock = jest.fn();
act(() => {
await act(async () => {
render(<Tooltip content="this is tooltip" onVisibleChange={callback} />, container);
});
act(() => {
await act(async () => {
container.querySelector(".default-content").dispatchEvent(new MouseEvent("click", { bubbles: true }));
});
expect(callback).toBeCalledTimes(1);
});

it("Should be able to force show and force hide the tooltip from another component", () => {
it("Should be able to force show and force hide the tooltip from another component", async () => {
const content: string = "my tooltip";
let myTooltip: Tooltip;
let forceShowSpy: jest.SpyInstance;
Expand All @@ -167,7 +167,7 @@ describe("Component: Tooltip", () => {
myTooltip.forceShow();
}
};
act(() => {
await act(async () => {
render(
<div>
<button onClick={toggleTooltip}>click</button>
Expand All @@ -183,11 +183,11 @@ describe("Component: Tooltip", () => {
forceShowSpy = jest.spyOn(myTooltip, "forceShow");
forceDismissSpy = jest.spyOn(myTooltip, "forceDismiss");
});
act(() => {
await act(async () => {
container.querySelector("button").dispatchEvent(new MouseEvent("click", { bubbles: true }));
});
expect(forceShowSpy).toBeCalledTimes(1);
act(() => {
await act(async () => {
container.querySelector("button").dispatchEvent(new MouseEvent("click", { bubbles: true }));
});
expect(forceDismissSpy).toBeCalledTimes(1);
Expand Down Expand Up @@ -225,30 +225,30 @@ describe("Component: Tooltip", () => {
},
];
triggerTestCases.map((testCase: TriggerTestCase) => {
it(`Should enable tooltip on ${testCase.trigger} when trigger mode is set to ${testCase.trigger}`, () => {
act(() => {
it(`Should enable tooltip on ${testCase.trigger} when trigger mode is set to ${testCase.trigger}`, async () => {
await act(async () => {
render(<Tooltip content="this is tooltip" trigger={testCase.trigger} />, container);
});
act(() => {
await act(async () => {
container.querySelector(".default-content").dispatchEvent(testCase.toggleEvent);
});
expect(document.body.querySelector(".overlay-container.show")).toBeDefined();
act(() => {
await act(async () => {
document.body.querySelector(testCase.untoggleEventElementClass).dispatchEvent(testCase.untoggleEvent);
});
expect(document.body.querySelector(".overlay-container.show")).toBeNull();
});
});
});

it("Should not set auto position if disableAutoPosition is true", () => {
act(() => {
it("Should not set auto position if disableAutoPosition is true", async () => {
await act(async () => {
render(<Tooltip content="tooltip" position={"asd" as any} />, container);
});
act(() => {
await act(async () => {
render(<Tooltip content="tooltip" position={"asd" as any} disableAutoPosition />, container);
});
act(() => {
await act(async () => {
container.querySelector(".default-content").dispatchEvent(new MouseEvent("click", { bubbles: true }));
});
expect(document.body.querySelector(".overlay-container").classList.contains("asd")).toBeTruthy();
Expand Down Expand Up @@ -318,9 +318,9 @@ describe("Component: Tooltip", () => {
},
];
for (const testCase of positionTestCases) {
test(`able to render on ${testCase.position}`, () => {
test(`able to render on ${testCase.position}`, async () => {
container.style.position = "relative";
act(() => {
await act(async () => {
render(<Tooltip content="tooltip" position={testCase.position} />, container);
});
(container.querySelector(".tooltip-reference").getBoundingClientRect as any) = jest.fn(() => {
Expand All @@ -329,7 +329,7 @@ describe("Component: Tooltip", () => {
(document.body.querySelector(".tooltip").getBoundingClientRect as any) = jest.fn(() => {
return testCase.mockTooltipBoundingClientRect;
});
act(() => {
await act(async () => {
container.querySelector(".default-content").dispatchEvent(new MouseEvent("click", { bubbles: true }));
});
expect(document.body.querySelector(".overlay-container").classList.contains(testCase.position)).toBeTruthy();
Expand Down Expand Up @@ -413,9 +413,9 @@ describe("Component: Tooltip", () => {
},
];
for (const testCase of positionTestCases) {
test(`able to render on ${testCase.relativePosition} when tooltip is overflow on ${testCase.position}`, () => {
test(`able to render on ${testCase.relativePosition} when tooltip is overflow on ${testCase.position}`, async () => {
container.style.position = "relative";
act(() => {
await act(async () => {
render(<Tooltip content="tooltip" position={testCase.position} />, container);
});
expect(document.body.querySelector(".overlay-container").classList.contains(testCase.position)).toBeTruthy();
Expand All @@ -425,24 +425,24 @@ describe("Component: Tooltip", () => {
(document.body.querySelector(".tooltip").getBoundingClientRect as any) = jest.fn(() => {
return testCase.mockTooltipBoundingClientRect;
});
act(() => {
await act(async () => {
container.querySelector(".default-content").dispatchEvent(new MouseEvent("click", { bubbles: true }));
});
expect(document.body.querySelector(".overlay-container").classList.contains(testCase.relativePosition)).toBeTruthy();
});
}
});

it("Should retain tooltip if user click on tooltip reference on focus mode", () => {
it("Should retain tooltip if user click on tooltip reference on focus mode", async () => {
let tooltip: Tooltip;
act(() => {
await act(async () => {
render(<Tooltip ref={(e: Tooltip) => (tooltip = e)} content="this is tooltip" trigger="focus" />, container);
});
act(() => {
await act(async () => {
container.querySelector(".default-content").dispatchEvent(new Event("focus", { bubbles: true }));
});
expect(document.body.querySelector(".overlay-container.show")).toBeDefined();
act(() => {
await act(async () => {
tooltip.onTooltipContentBlur({ relatedTarget: container.querySelector(".default-content") } as any);
});
expect(document.body.querySelector(".overlay-container.show")).toBeDefined();
Expand Down
6 changes: 3 additions & 3 deletions src/__utils/Overlay/Overlay.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -44,12 +44,12 @@ describe("Component: Overlay", () => {
expect(overlayContainer.innerHTML).toEqual(content);
});

it("Should be set to focus on overlay show", () => {
it("Should be set to focus on overlay show", async () => {
const newProps: OverlayProps = { ...overlayProps, overlayReference: () => container.querySelector(".ref") };
act(() => { render(<div><div className="ref">ref</div><Overlay {...newProps}>overlay</Overlay></div>, container); });
await act(async () => { render(<div><div className="ref">ref</div><Overlay {...newProps}>overlay</Overlay></div>, container); });
expect(document.body.querySelector(".overlay-container:focus")).toBeFalsy();
const updatedProps: OverlayProps = { ...newProps, show: true };
act(() => { render(<div><div className="ref">ref</div><Overlay {...updatedProps}>overlay</Overlay></div>, container); });
await act(async () => { render(<div><div className="ref">ref</div><Overlay {...updatedProps}>overlay</Overlay></div>, container); });
expect(document.body.querySelector(".overlay-container:focus")).toBeTruthy();
});

Expand Down
15 changes: 9 additions & 6 deletions src/__utils/Overlay/Overlay.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -59,22 +59,25 @@ const Overlay: React.FC<OverlayProps> = React.forwardRef((props: OverlayProps, r
* onScroll handler
* @param {Event} ev The window scroll event
*/
function onScroll(ev: Event): void {
async function onScroll(ev: Event) {
const target: HTMLElement = ev.target as HTMLElement;
if (props.show && target.contains(props.overlayReference())) {
const referenceDomRect: DOMRect = props.overlayReference().getBoundingClientRect();
if (referenceDomRect.bottom < 0 || referenceDomRect.right < 0 || referenceDomRect.left > window.innerWidth || referenceDomRect.top > window.innerHeight) {
overlayContentRef?.current?.blur();
}
setPlacementWithCoords(overlayPositionChecker.getPosition(props.position || "top"));
overlayPositionChecker.getPosition(props.position || "top").then((position: ElementPlacementWithCoord) => {
setPlacementWithCoords(position);
});
}
}

/** Get position within view port */
function getWithinViewportPosition(disableFocus?: boolean): void {
!disableFocus && overlayContentRef.current.focus();
const placementCoords: ElementPlacementWithCoord = overlayPositionChecker.getPosition(props.position || "top");
setPlacementWithCoords(placementCoords);
async function getWithinViewportPosition(disableFocus?: boolean) {
overlayPositionChecker.getPosition(props.position || "top").then((position: ElementPlacementWithCoord) => {
setPlacementWithCoords(position);
!disableFocus && overlayContentRef.current.focus();
});
}

return createPortal(
Expand Down
Loading

0 comments on commit 658d609

Please sign in to comment.