This repository has been archived by the owner on Feb 16, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 10
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
270dad4
commit 1b34bc8
Showing
6 changed files
with
247 additions
and
10 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,112 @@ | ||
import { describe, expect, it, vi } from 'vitest'; | ||
import { render, screen } from '@testing-library/react'; | ||
import userEvent from '@testing-library/user-event' | ||
import { Button } from '..'; | ||
|
||
describe("Button component", () => { | ||
it('should render the button with children', async () => { | ||
render(<Button>Button</Button>); | ||
const btnElement = screen.getByText("Button"); | ||
expect(btnElement).toBeInTheDocument(); | ||
}); | ||
|
||
it("should call the onClick handler when button is clicked", async () => { | ||
const onClickMock = vi.fn(); | ||
render(<Button onClick={onClickMock}>Button</Button>); | ||
const btnElement = screen.getByText("Button"); | ||
await userEvent.click(btnElement) | ||
expect(onClickMock).toHaveBeenCalled() | ||
}) | ||
|
||
it("should apply the default styling when no props are passed", () => { | ||
render(<Button>Button</Button>); | ||
const btnElement = screen.getByText("Button"); | ||
expect(btnElement).toHaveClass("bg-primary", "text-white", "text-base") | ||
}); | ||
|
||
it("should apply contained secondary styling when color prop is 'secondary' and variant prop is 'contained'", () => { | ||
render(<Button variant="contained" color="secondary">Button</Button>); | ||
const btnElement = screen.getByText("Button"); | ||
expect(btnElement).toHaveClass("bg-secondary") | ||
}) | ||
|
||
it("should apply outlined primary styling when color prop is 'primary' and variant prop is 'outlined'", () => { | ||
render(<Button variant="outlined" color="primary">Button</Button>); | ||
const btnElement = screen.getByText("Button"); | ||
expect(btnElement).toHaveClass("bg-transparent", "border-primary") | ||
}) | ||
|
||
it("should apply outlined secondary styling when color prop is 'secondary' and variant prop is 'outlined'", () => { | ||
render(<Button variant="outlined" color="secondary">Button</Button>); | ||
const btnElement = screen.getByText("Button"); | ||
expect(btnElement).toHaveClass("bg-transparent", "border-secondary") | ||
}) | ||
|
||
it("should apply outlined secondary styling when color prop is 'secondary' and variant prop is 'outlined'", () => { | ||
render(<Button variant="outlined" color="secondary">Button</Button>); | ||
const btnElement = screen.getByText("Button"); | ||
expect(btnElement).toHaveClass("bg-transparent", "border-secondary") | ||
}) | ||
|
||
it("should apply small size style when size prop is 'sm'", () => { | ||
render(<Button size="sm">Button</Button>); | ||
const btnElement = screen.getByText("Button"); | ||
expect(btnElement).toHaveClass("px-3") | ||
}) | ||
|
||
it("should apply medium size style when size prop is 'md'", () => { | ||
render(<Button size="md">Button</Button>); | ||
const btnElement = screen.getByText("Button"); | ||
expect(btnElement).toHaveClass("text-[0.875rem]") | ||
}) | ||
|
||
it("should have few same classes for size 'default' and 'md'", () => { | ||
render(<div> | ||
<Button size="default">Default Button</Button> | ||
<Button size="md">Medium Button</Button> | ||
</div>); | ||
const defaultBtnElement = screen.getByText("Default Button"); | ||
const mediumBtnElement = screen.getByText("Medium Button"); | ||
|
||
const commonClass = "min-h-[2rem]" | ||
expect(defaultBtnElement).toHaveClass(commonClass) | ||
expect(mediumBtnElement).toHaveClass(commonClass) | ||
}) | ||
|
||
it("should have same padding block classe for all size", () => { | ||
render(<div> | ||
<Button size="default">Default Button</Button> | ||
<Button size="md">Medium Button</Button> | ||
<Button size="sm">Small Button</Button> | ||
</div>); | ||
const defaultBtnElement = screen.getByText("Default Button"); | ||
const mediumBtnElement = screen.getByText("Medium Button"); | ||
const smallBtnElement = screen.getByText("Small Button"); | ||
|
||
const commonClass = "py-1" | ||
expect(defaultBtnElement).toHaveClass(commonClass) | ||
expect(mediumBtnElement).toHaveClass(commonClass) | ||
expect(smallBtnElement).toHaveClass(commonClass) | ||
}) | ||
|
||
it('should apply the fullwidth styling when fullwidth prop is true', () => { | ||
render(<Button fullwidth={true}>Full Width Button</Button>) | ||
const btnElement = screen.getByText("Full Width Button"); | ||
expect(btnElement).toHaveClass("w-full"); | ||
}); | ||
|
||
it('should apply custom class and styles correctly', () => { | ||
render( | ||
<Button className="custom-class" style={{ fontSize: "20px" }}>Button</Button> | ||
); | ||
const btnElement = screen.getByText("Button"); | ||
expect(btnElement).toHaveClass("custom-class"); | ||
expect(btnElement).toHaveStyle({ fontSize: "20px" }); | ||
}); | ||
|
||
it('should render a disabled button when disabled prop is true', () => { | ||
const { getByText } = render(<Button disabled={true}>Click me</Button>); | ||
const button = getByText('Click me'); | ||
expect(button).toBeDisabled(); | ||
}); | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
import * as React from "react" | ||
import { Slot } from "@radix-ui/react-slot" | ||
import { cva, type VariantProps } from "class-variance-authority" | ||
import { cn } from "Utils/cn" | ||
|
||
const buttonVariants = cva( | ||
"inline-flex items-center justify-center rounded font-bold border border-solid transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-slate-950 disabled:pointer-events-none disabled:opacity-50", | ||
{ | ||
variants: { | ||
variant: { | ||
contained: "text-white", | ||
outlined: "bg-transparent text-prominent" | ||
}, | ||
color: { | ||
primary: "border-primary hover:border-primary-hover focus:border-primary-hover", | ||
secondary: "border-secondary", | ||
success: "border-success", | ||
}, | ||
size: { | ||
default: "text-base", | ||
sm: "text-[0.75rem] px-3", | ||
md: "text-[0.875rem]", | ||
}, | ||
fullwidth: { | ||
true: "flex w-full", | ||
}, | ||
}, | ||
compoundVariants: [ | ||
{ | ||
variant: "contained", | ||
color: "primary", | ||
className: "bg-primary hover:bg-primary-hover focus:bg-primary-hover" | ||
}, | ||
{ | ||
variant: "contained", | ||
color: "secondary", | ||
className: "bg-secondary" | ||
}, | ||
{ | ||
variant: "outlined", | ||
color: "primary", | ||
className: "hover:bg-primary-hover focus:bg-primary-hover" | ||
}, | ||
{ | ||
variant: "outlined", | ||
color: "secondary", | ||
className: "hover:bg-secondary/[0.08] focus:bg-secondary/[0.08]" | ||
}, | ||
{ | ||
size: ["default", "md"], | ||
className: "px-5 min-h-[2rem] min-w-[3.5rem]" | ||
}, | ||
{ | ||
size: ["default", "md", "sm"], | ||
className: "py-1" | ||
} | ||
], | ||
defaultVariants: { | ||
variant: "contained", | ||
color: "primary", | ||
size: "default", | ||
fullwidth: false | ||
}, | ||
} | ||
) | ||
|
||
export interface ButtonProps | ||
extends Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, "color">, | ||
VariantProps<typeof buttonVariants> { | ||
asChild?: boolean | ||
} | ||
|
||
const Button = React.forwardRef<HTMLButtonElement, ButtonProps>( | ||
({ className, variant, size, color, fullwidth, asChild = false, ...props }, ref) => { | ||
const Comp = asChild ? Slot : "button" | ||
return ( | ||
<Comp | ||
className={cn(buttonVariants({ variant, size, color, fullwidth, className }))} | ||
ref={ref} | ||
{...props} | ||
/> | ||
) | ||
} | ||
) | ||
Button.displayName = "Button" | ||
|
||
export { Button, buttonVariants } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters