React Resource Hub - Your curated collection of React learning
diff --git a/src/components/googlelogo/GoogleLogo.test.tsx b/src/components/googlelogo/GoogleLogo.test.tsx
new file mode 100644
index 0000000..0e416ca
--- /dev/null
+++ b/src/components/googlelogo/GoogleLogo.test.tsx
@@ -0,0 +1,43 @@
+import { render } from "@testing-library/react";
+import { describe, it, expect } from "vitest";
+import { GoogleLogo } from "./GoogleLogo";
+
+interface RenderOptions {
+ className?: string;
+}
+
+const defaultProps: RenderOptions = {
+ className: "w-5 h-5",
+};
+
+const renderGoogleLogo = (additionalProps: RenderOptions = {}) => {
+ const props = { ...defaultProps, ...additionalProps };
+
+ return render();
+};
+
+describe("GoogleLogo", () => {
+ it("should render an svg element", () => {
+ const { container } = renderGoogleLogo();
+
+ const svg = container.querySelector("svg");
+
+ expect(svg).toBeInTheDocument();
+ });
+
+ it("should apply provided className when passed", () => {
+ const { container } = renderGoogleLogo({ className: "w-8 h-8" });
+
+ const svg = container.querySelector("svg");
+
+ expect(svg).toHaveClass("w-8");
+ });
+
+ it("should be hidden from the accessibility tree", () => {
+ const { container } = renderGoogleLogo();
+
+ const svg = container.querySelector("svg");
+
+ expect(svg).toHaveAttribute("aria-hidden", "true");
+ });
+});
diff --git a/src/components/googlelogo/GoogleLogo.tsx b/src/components/googlelogo/GoogleLogo.tsx
new file mode 100644
index 0000000..9860ae0
--- /dev/null
+++ b/src/components/googlelogo/GoogleLogo.tsx
@@ -0,0 +1,32 @@
+type GoogleLogoProps = {
+ className?: string;
+};
+
+export const GoogleLogo = ({ className }: GoogleLogoProps) => {
+ return (
+
+ );
+};
diff --git a/src/features/auth/SignInPage.test.tsx b/src/features/auth/SignInPage.test.tsx
new file mode 100644
index 0000000..7c78578
--- /dev/null
+++ b/src/features/auth/SignInPage.test.tsx
@@ -0,0 +1,69 @@
+import { render, screen } from "@testing-library/react";
+import userEvent from "@testing-library/user-event";
+import { describe, it } from "vitest";
+import { BrowserRouter } from "react-router-dom";
+import { SignInPage } from "./SignInPage";
+
+const renderSignInPage = () => {
+ return render(
+
+
+ ,
+ );
+};
+
+describe("SignInPage", () => {
+ it("should render the email input field", () => {
+ renderSignInPage();
+
+ expect(screen.getByLabelText(/email/i)).toBeInTheDocument();
+ });
+
+ it("should render the password input field", () => {
+ renderSignInPage();
+
+ expect(screen.getByLabelText(/password/i)).toBeInTheDocument();
+ });
+
+ it("should allow typing in the email input", async () => {
+ renderSignInPage();
+ const user = userEvent.setup();
+
+ const emailInput = screen.getByLabelText(/email/i);
+ await user.type(emailInput, "test@example.com");
+
+ expect(emailInput).toHaveValue("test@example.com");
+ });
+
+ it("should allow typing in the password input", async () => {
+ renderSignInPage();
+ const user = userEvent.setup();
+
+ const passwordInput = screen.getByLabelText(/password/i);
+ await user.type(passwordInput, "password123");
+
+ expect(passwordInput).toHaveValue("password123");
+ });
+
+ it("should render the sign in button", () => {
+ renderSignInPage();
+
+ expect(
+ screen.getByRole("button", { name: /sign in/i }),
+ ).toBeInTheDocument();
+ });
+
+ it("should render the continue with google button", () => {
+ renderSignInPage();
+
+ expect(
+ screen.getByRole("button", { name: /continue with google/i }),
+ ).toBeInTheDocument();
+ });
+
+ it("should render the sign up link", () => {
+ renderSignInPage();
+
+ expect(screen.getByRole("link", { name: /sign up/i })).toBeInTheDocument();
+ });
+});
diff --git a/src/features/auth/SignInPage.tsx b/src/features/auth/SignInPage.tsx
new file mode 100644
index 0000000..d11143b
--- /dev/null
+++ b/src/features/auth/SignInPage.tsx
@@ -0,0 +1,92 @@
+import { useState } from "react";
+import { Link } from "react-router-dom";
+import { Button } from "../../components/button/Button";
+import { Input } from "../../components/input/Input";
+import { Card, CardBody } from "../../components/card/Card";
+import { GoogleLogo } from "../../components/googlelogo/GoogleLogo";
+
+export const SignInPage = () => {
+ const [email, setEmail] = useState("");
+ const [password, setPassword] = useState("");
+
+ const handleSubmit = (event: React.FormEvent) => {
+ event.preventDefault();
+ };
+
+ return (
+
+
+
+
+
+
+ Welcome Back
+
+
+ Sign in to access your saved resources
+
+
+
+
+
+
+
+
+
+ Or continue with
+
+
+
+
+
+
+
+ Don't have an account?{" "}
+
+ Sign up
+
+
+
+
+
+
+ );
+};