-
Notifications
You must be signed in to change notification settings - Fork 0
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
34bfb6b
commit 6205a55
Showing
25 changed files
with
698 additions
and
35 deletions.
There are no files selected for viewing
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 |
---|---|---|
|
@@ -16,6 +16,9 @@ dist-ssr | |
# Cache | ||
cache | ||
|
||
# Firebase data | ||
firebase/data | ||
|
||
# Editor directories and files | ||
.idea | ||
.DS_Store | ||
|
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 |
---|---|---|
@@ -1,4 +1,4 @@ | ||
{ | ||
"ignoreWords": ["tseslint", "tailwindcss", "testid", "svgr"], | ||
"ignoreWords": ["tseslint", "tailwindcss", "testid", "svgr", "firestore"], | ||
"words": ["crwn"] | ||
} |
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 |
---|---|---|
@@ -1,3 +1,8 @@ | ||
rules_version = '2'; | ||
service cloud.firestore { | ||
service cloud.firestore { | ||
match /databases/{database}/documents { | ||
match /{document=**} { | ||
allow read, write: if true; | ||
} | ||
} | ||
} |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -5,3 +5,9 @@ body { | |
a { | ||
color: black; | ||
} | ||
|
||
#root { | ||
width: 80%; | ||
max-width: 85rem; | ||
margin: auto; | ||
} |
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,33 @@ | ||
import { render, screen } from "@testing-library/react"; | ||
|
||
import Button from "./Button"; | ||
|
||
test("should render with default styles", () => { | ||
render(<Button>Default Button</Button>); | ||
const buttonElement = screen.getByText("Default Button"); | ||
expect(buttonElement).toBeInTheDocument(); | ||
expect(buttonElement).toHaveClass("bg-black text-white"); | ||
}); | ||
|
||
test("should render with google-sign-in styles", () => { | ||
render(<Button buttonType="google-sign-in">Google Sign In</Button>); | ||
const buttonElement = screen.getByText("Google Sign In"); | ||
expect(buttonElement).toBeInTheDocument(); | ||
expect(buttonElement).toHaveClass("bg-google text-white"); | ||
}); | ||
|
||
test("should render with inverted styles", () => { | ||
render(<Button buttonType="inverted">Inverted Button</Button>); | ||
const buttonElement = screen.getByText("Inverted Button"); | ||
expect(buttonElement).toBeInTheDocument(); | ||
expect(buttonElement).toHaveClass( | ||
"border-2 border-black bg-white text-black", | ||
); | ||
}); | ||
|
||
test("should pass other props to the button element", () => { | ||
render(<Button disabled>Disabled Button</Button>); | ||
const buttonElement = screen.getByText("Disabled Button"); | ||
expect(buttonElement).toBeInTheDocument(); | ||
expect(buttonElement).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,33 @@ | ||
import { ButtonHTMLAttributes, ReactNode } from "react"; | ||
import tw from "../../utils/tw-identity"; | ||
|
||
interface ButtonProps extends ButtonHTMLAttributes<HTMLButtonElement> { | ||
children: ReactNode; | ||
buttonType?: "inverted" | "google-sign-in"; | ||
} | ||
|
||
export default function Button({ | ||
children, | ||
buttonType, | ||
...otherProps | ||
}: ButtonProps) { | ||
let classes = tw`h-12 min-w-40 px-8 font-bold uppercase hover:border-2` + " "; | ||
|
||
if (!buttonType) { | ||
classes += tw`bg-black text-white hover:border-black hover:bg-white hover:text-black`; | ||
} | ||
|
||
if (buttonType === "google-sign-in") { | ||
classes += tw`bg-google text-white hover:border-google hover:bg-white hover:text-google`; | ||
} | ||
|
||
if (buttonType === "inverted") { | ||
classes += tw`border-2 border-black bg-white text-black hover:border-white hover:bg-black hover:text-white`; | ||
} | ||
|
||
return ( | ||
<button className={classes} {...otherProps}> | ||
{children} | ||
</button> | ||
); | ||
} |
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,42 @@ | ||
import { render, screen } from "@testing-library/react"; | ||
import userEvent from "@testing-library/user-event"; | ||
|
||
import FormInput from "./FormInput"; | ||
|
||
test("should render with the correct label", () => { | ||
render(<FormInput label="Username" />); | ||
const labelElement = screen.getByLabelText("Username"); | ||
expect(labelElement).toBeInTheDocument(); | ||
}); | ||
|
||
test("should apply shrink classes when input has value", () => { | ||
render(<FormInput label="Username" value="test" />); | ||
const labelElement = screen.getByText("Username"); | ||
expect(labelElement).toHaveClass("-top-5 text-xs text-black"); | ||
}); | ||
|
||
test("should apply default classes when input is empty", () => { | ||
render(<FormInput label="Username" />); | ||
const labelElement = screen.getByText("Username"); | ||
expect(labelElement).toHaveClass("top-3 text-gray-600"); | ||
}); | ||
|
||
test("should apply password classes when input type is password", () => { | ||
render(<FormInput label="Password" type="password" />); | ||
const inputElement = screen.getByLabelText("Password"); | ||
expect(inputElement).toHaveClass("tracking-wider"); | ||
}); | ||
|
||
test("should focus input when label is clicked", async () => { | ||
render(<FormInput label="Username" />); | ||
const labelElement = screen.getByText("Username"); | ||
const inputElement = screen.getByLabelText("Username"); | ||
await userEvent.click(labelElement); | ||
expect(inputElement).toHaveFocus(); | ||
}); | ||
|
||
test("should pass other props to the input element", () => { | ||
render(<FormInput label="Username" disabled />); | ||
const inputElement = screen.getByLabelText("Username"); | ||
expect(inputElement).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,29 @@ | ||
import { InputHTMLAttributes } from "react"; | ||
|
||
import tw from "../../utils/tw-identity"; | ||
|
||
interface FormInputProps extends InputHTMLAttributes<HTMLInputElement> { | ||
label: string; | ||
} | ||
|
||
export default function FormInput({ label, ...otherProps }: FormInputProps) { | ||
const inputId = label.toLowerCase().replace(" ", "-"); | ||
|
||
const shrinkClasses = otherProps.value?.toString().length | ||
? tw`-top-5 text-xs text-black` | ||
: tw`top-3 text-gray-600`; | ||
const passwordClasses = | ||
otherProps.type === "password" ? "tracking-wider" : ""; | ||
|
||
const inputClasses = tw`peer my-6 block w-full border-b-2 border-b-gray-600 bg-slate-100 py-2.5 pl-1 pr-2.5 text-lg text-gray-600 focus:outline-none ${passwordClasses}`; | ||
const labelClasses = tw`pointer-events-none absolute left-1 transition-all peer-focus:-top-5 peer-focus:text-xs peer-focus:text-black ${shrinkClasses}`; | ||
|
||
return ( | ||
<div className="relative my-12"> | ||
<input id={inputId} className={inputClasses} {...otherProps} /> | ||
<label htmlFor={inputId} className={labelClasses}> | ||
{label} | ||
</label> | ||
</div> | ||
); | ||
} |
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,102 @@ | ||
import { render, screen } from "@testing-library/react"; | ||
import userEvent from "@testing-library/user-event"; | ||
|
||
import SignInForm from "./SignInForm"; | ||
|
||
const mockedMethods = vi.hoisted(function () { | ||
return { | ||
signInAuthUserFn: vi.fn(), | ||
}; | ||
}); | ||
|
||
vi.mock("../../utils/firebase", function () { | ||
return { | ||
signInAuthUserWithEmailAndPassword: mockedMethods.signInAuthUserFn, | ||
}; | ||
}); | ||
|
||
vi.spyOn(window, "alert").mockImplementation(() => {}); | ||
|
||
test("should render the correct titles", function () { | ||
render(<SignInForm />); | ||
|
||
expect(screen.getByRole("heading", { name: /sign in/i })).toBeInTheDocument(); | ||
expect(screen.getByText(/already have an account/i)).toBeInTheDocument(); | ||
}); | ||
|
||
test("should render the correct form fields", function () { | ||
render(<SignInForm />); | ||
|
||
expect(screen.getByLabelText(/email/i)).toBeInTheDocument(); | ||
expect(screen.getByLabelText(/password/i)).toBeInTheDocument(); | ||
}); | ||
|
||
test("should render the correct buttons", function () { | ||
render(<SignInForm />); | ||
|
||
expect( | ||
screen.getByRole("button", { name: /^sign in$/i }), | ||
).toBeInTheDocument(); | ||
expect( | ||
screen.getByRole("button", { name: /google sign in/i }), | ||
).toBeInTheDocument(); | ||
}); | ||
|
||
test("should submit the form with the correct data", async function () { | ||
render(<SignInForm />); | ||
|
||
const emailInput = screen.getByLabelText(/email/i); | ||
const passwordInput = screen.getByLabelText(/password/i); | ||
const submitButton = screen.getByRole("button", { name: /^sign in$/i }); | ||
|
||
const user = userEvent.setup(); | ||
|
||
await user.type(emailInput, "[email protected]"); | ||
await user.type(passwordInput, "password"); | ||
await user.click(submitButton); | ||
|
||
expect(mockedMethods.signInAuthUserFn).toHaveBeenCalledWith( | ||
"[email protected]", | ||
"password", | ||
); | ||
}); | ||
|
||
test("should show an alert if the password is incorrect", async function () { | ||
mockedMethods.signInAuthUserFn.mockRejectedValue({ | ||
code: "auth/wrong-password", | ||
}); | ||
|
||
render(<SignInForm />); | ||
|
||
const emailInput = screen.getByLabelText(/email/i); | ||
const passwordInput = screen.getByLabelText(/password/i); | ||
const submitButton = screen.getByRole("button", { name: /^sign in$/i }); | ||
|
||
const user = userEvent.setup(); | ||
|
||
await user.type(emailInput, "[email protected]"); | ||
await user.type(passwordInput, "password"); | ||
await user.click(submitButton); | ||
|
||
expect(window.alert).toHaveBeenCalledWith("Wrong email or password"); | ||
}); | ||
|
||
test("should show an alert if the user is not found", async function () { | ||
mockedMethods.signInAuthUserFn.mockRejectedValue({ | ||
code: "auth/user-not-found", | ||
}); | ||
|
||
render(<SignInForm />); | ||
|
||
const emailInput = screen.getByLabelText(/email/i); | ||
const passwordInput = screen.getByLabelText(/password/i); | ||
const submitButton = screen.getByRole("button", { name: /^sign in$/i }); | ||
|
||
const user = userEvent.setup(); | ||
|
||
await user.type(emailInput, "[email protected]"); | ||
await user.type(passwordInput, "password"); | ||
await user.click(submitButton); | ||
|
||
expect(window.alert).toHaveBeenCalledWith("Wrong email or password"); | ||
}); |
Oops, something went wrong.