Skip to content

Commit

Permalink
Merge pull request #752 from onewelcome/UCL-575
Browse files Browse the repository at this point in the history
UCL-575
  • Loading branch information
szmejk authored Dec 19, 2024
2 parents d41f16d + 3ecf30a commit 0b9b5ac
Show file tree
Hide file tree
Showing 5 changed files with 150 additions and 110 deletions.
156 changes: 83 additions & 73 deletions src/components/Button/BaseButton.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -39,95 +39,105 @@ const createBaseButton = (params?: (defaultParams: Props) => Props) => {
};
};

describe("BaseButton should render", () => {
it("renders without crashing", () => {
describe("BaseButton", () => {
it("should render without crashing", () => {
const { baseButton } = createBaseButton();

expect(baseButton).toBeDefined();
expect(baseButton).toHaveTextContent("baseButton content");
});
});

describe("On click handler", () => {
it("executes the onclick handler", async () => {
const onClickHandler = jest.fn();
const { baseButton } = createBaseButton(defaultParams => ({
it("should not be rendered when hidden attribute is used", () => {
const { queryByRole } = createBaseButton(defaultParams => ({
...defaultParams,
onClick: onClickHandler
hidden: true
}));

await userEvent.click(baseButton);

expect(onClickHandler).toBeCalled();
expect(queryByRole("button")).toBeNull();
expect(queryByRole("button", { hidden: true })).toBeDefined();
});
});

describe("Properties of the button", () => {
it("should be disabled, function should not have been called", async () => {
const onClickHandler = jest.fn();
const { baseButton } = createBaseButton(defaultParams => ({
...defaultParams,
disabled: true,
onClick: onClickHandler
}));

await userEvent.click(baseButton);
expect(onClickHandler).toHaveBeenCalledTimes(0);
});

it("when loading onClick function should not have been called", async () => {
const onClickHandler = jest.fn();
const { baseButton } = createBaseButton(defaultParams => ({
...defaultParams,
loading: true,
onClick: onClickHandler
}));

await userEvent.click(baseButton);
expect(onClickHandler).toHaveBeenCalledTimes(0);
});
describe("On click handler", () => {
it("executes the onclick handler", async () => {
const onClickHandler = jest.fn();
const { baseButton } = createBaseButton(defaultParams => ({
...defaultParams,
onClick: onClickHandler
}));

it('should have the class "TESTING"', () => {
const { baseButton } = createBaseButton(defaultParams => ({
...defaultParams,
className: "TESTING"
}));
await userEvent.click(baseButton);

expect(baseButton).toHaveClass("TESTING");
expect(onClickHandler).toBeCalled();
});
});

it('should have a "name" property with the value "button"', () => {
const { baseButton } = createBaseButton(defaultParams => ({
...defaultParams,
name: "button"
}));

expect(baseButton).toHaveAttribute("name", "button");
describe("Properties of the button", () => {
it("should be disabled, function should not have been called", async () => {
const onClickHandler = jest.fn();
const { baseButton } = createBaseButton(defaultParams => ({
...defaultParams,
disabled: true,
onClick: onClickHandler
}));

await userEvent.click(baseButton);
expect(onClickHandler).toHaveBeenCalledTimes(0);
});

it("when loading onClick function should not have been called", async () => {
const onClickHandler = jest.fn();
const { baseButton } = createBaseButton(defaultParams => ({
...defaultParams,
loading: true,
onClick: onClickHandler
}));

await userEvent.click(baseButton);
expect(onClickHandler).toHaveBeenCalledTimes(0);
});

it('should have the class "TESTING"', () => {
const { baseButton } = createBaseButton(defaultParams => ({
...defaultParams,
className: "TESTING"
}));

expect(baseButton).toHaveClass("TESTING");
});

it('should have a "name" property with the value "button"', () => {
const { baseButton } = createBaseButton(defaultParams => ({
...defaultParams,
name: "button"
}));

expect(baseButton).toHaveAttribute("name", "button");
});
});
});

describe("ref should work", () => {
it("should give back the proper data prop, this also checks if the component propagates ...rest properly", () => {
const ExampleComponent = ({
propagateRef
}: {
propagateRef?: (ref: React.RefObject<HTMLElement>) => void;
}) => {
const ref = useRef(null);

useEffect(() => {
if (ref.current) {
propagateRef && propagateRef(ref);
}
}, [ref]);

return <BaseButton {...defaultParams} data-ref="testing" ref={ref} />;
};

const refCheck = (ref: React.RefObject<HTMLElement>) => {
expect(ref.current).toHaveAttribute("data-ref", "testing");
};

render(<ExampleComponent propagateRef={refCheck} />);
describe("ref should work", () => {
it("should give back the proper data prop, this also checks if the component propagates ...rest properly", () => {
const ExampleComponent = ({
propagateRef
}: {
propagateRef?: (ref: React.RefObject<HTMLElement>) => void;
}) => {
const ref = useRef(null);

useEffect(() => {
if (ref.current) {
propagateRef && propagateRef(ref);
}
}, [ref]);

return <BaseButton {...defaultParams} data-ref="testing" ref={ref} />;
};

const refCheck = (ref: React.RefObject<HTMLElement>) => {
expect(ref.current).toHaveAttribute("data-ref", "testing");
};

render(<ExampleComponent propagateRef={refCheck} />);
});
});
});
11 changes: 7 additions & 4 deletions src/components/Button/BaseButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ export interface Props extends ComponentPropsWithRef<"button"> {
}

const BaseButtonComponent: ForwardRefRenderFunction<HTMLButtonElement, Props> = (
{ children, type = "button", className, loading, disabled, ...rest },
{ children, type = "button", className, loading, disabled, hidden, ...rest },
ref
) => {
const validTypes = ["submit", "button", "reset"];
Expand All @@ -36,15 +36,18 @@ const BaseButtonComponent: ForwardRefRenderFunction<HTMLButtonElement, Props> =
`You have entered an invalid button type. Expected 'submit', 'button' or 'reset' got ${type}`
);

const buttonClasses = [classes.button];
loading && buttonClasses.push(classes.loading);
className && buttonClasses.push(className);

return (
<button
{...rest}
disabled={isDisabled}
ref={ref}
type={type}
className={`${classes.button} ${loading ? classes.loading : ""} ${
className ? className : ""
}`}
hidden={hidden}
className={hidden ? "" : buttonClasses.join(" ")}
>
{loading ? (
<Fragment>
Expand Down
34 changes: 24 additions & 10 deletions src/components/Button/Button.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -39,14 +39,6 @@ const createButton = (params?: (defaultParams: Props) => Props) => {
};
};

describe("Button should render", () => {
it("renders without crashing", () => {
const { button } = createButton();

expect(button).toBeDefined();
});
});

describe("ref should work", () => {
it("should give back the proper data prop, this also checks if the component propagates ...rest properly", () => {
const ExampleComponent = ({
Expand All @@ -73,12 +65,22 @@ describe("ref should work", () => {
});
});

describe("Button should render", () => {
it("renders without crashing", () => {
describe("Button", () => {
it("should render without crashing", () => {
const { button } = createButton();

expect(button).toBeDefined();
});

it("should not be rendered when hidden attribute is used", () => {
const { queryByRole } = createButton(defaultParams => ({
...defaultParams,
hidden: true
}));

expect(queryByRole("button")).toBeNull();
expect(queryByRole("button", { hidden: true })).toBeDefined();
});
});

describe("Different variants of the button", () => {
Expand Down Expand Up @@ -147,4 +149,16 @@ describe("Button contains an icon", () => {
expect(button.lastElementChild?.nodeName).toBe("I");
expect(button.querySelector("span")!.innerHTML).toBe("button content");
});

it("Should not be rendered when hidden attribute is used", () => {
const { button, queryByRole } = createButton(defaultParams => ({
...defaultParams,
hidden: true,
endIcon: <Icon icon={Icons.Calendar} />,
startIcon: <Icon icon={Icons.Calendar} />
}));

expect(queryByRole("button")).toBeNull();
expect(queryByRole("button", { hidden: true })).toBeDefined();
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ exports[`DataGridBody should render renders without crashing 1`] = `
aria-controls="consent_menu_Paweł-menu"
aria-expanded="false"
aria-haspopup="true"
class="button icon-button text default button-m"
class="button icon-button text default button-m"
id="consent_menu_Paweł"
tabindex="0"
title="Actions for Paweł"
Expand Down Expand Up @@ -109,7 +109,7 @@ exports[`DataGridBody should render renders without crashing 1`] = `
aria-controls="consent_menu_Michał-menu"
aria-expanded="false"
aria-haspopup="true"
class="button icon-button text default button-m"
class="button icon-button text default button-m"
id="consent_menu_Michał"
tabindex="0"
title="Actions for Michał"
Expand Down Expand Up @@ -173,7 +173,7 @@ exports[`DataGridBody should render renders without crashing 1`] = `
aria-controls="consent_menu_Daniel-menu"
aria-expanded="false"
aria-haspopup="true"
class="button icon-button text default button-m"
class="button icon-button text default button-m"
id="consent_menu_Daniel"
tabindex="0"
title="Actions for Daniel"
Expand Down Expand Up @@ -237,7 +237,7 @@ exports[`DataGridBody should render renders without crashing 1`] = `
aria-controls="consent_menu_Jasha-menu"
aria-expanded="false"
aria-haspopup="true"
class="button icon-button text default button-m"
class="button icon-button text default button-m"
id="consent_menu_Jasha"
tabindex="0"
title="Actions for Jasha"
Expand Down
51 changes: 32 additions & 19 deletions stories/Button/Button.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,10 @@ SingleButton.args = {

export const ButtonStates = Template.bind({});

type ButtonStorybookProps = Pick<ButtonProps, "color" | "variant" | "disabled" | "loading"> & {
type ButtonStorybookProps = Pick<
ButtonProps,
"color" | "variant" | "disabled" | "loading" | "hidden"
> & {
endIcon?: boolean;
startIcon?: boolean;
event?: "hover" | "active" | "focus";
Expand Down Expand Up @@ -148,6 +151,17 @@ const uniqueButtonStates: Array<ButtonStorybookProps> = [
color: "primary",
variant: "fill",
endIcon: true
},
{
color: "primary",
variant: "fill",
startIcon: true,
hidden: true
},
{
color: "primary",
variant: "fill",
hidden: true
}
];

Expand All @@ -164,24 +178,23 @@ ButtonStates.decorators = [
gridTemplateColumns: "auto auto auto auto"
}}
>
{mainButtonStates.map((states, index) => (
<div style={{ marginBottom: "10px" }} key={index}>
<Button
id={states.event}
disabled={states.disabled}
color={states.color}
variant={states.variant}
type={states.type}
endIcon={states.endIcon ? <Icon icon={Icons.Calendar} /> : false}
startIcon={states.startIcon ? <Icon icon={Icons.Calendar} /> : false}
loading={states.loading}
>
{`${states.color} ${states.variant} ${states.disabled ? "disabled" : ""} ${
states.event !== undefined ? states.event : ""
}`}
</Button>
</div>
))}
{mainButtonStates.map((states, index) => {
const { event, startIcon, endIcon, ...props } = states;
return (
<div style={{ marginBottom: "10px" }} key={index}>
<Button
{...props}
id={event}
endIcon={endIcon ? <Icon icon={Icons.Calendar} /> : false}
startIcon={startIcon ? <Icon icon={Icons.Calendar} /> : false}
>
{`${states.color} ${states.variant} ${states.disabled ? "disabled" : ""} ${
states.event !== undefined ? states.event : ""
}${states.hidden ? "hidden" : ""} `}
</Button>
</div>
);
})}
</div>
);
}
Expand Down

0 comments on commit 0b9b5ac

Please sign in to comment.