Skip to content

Commit

Permalink
Feat/update swe test (#25)
Browse files Browse the repository at this point in the history
* fix(deps): update next to a version that exists

* feat(tests): refactor into smaller tests
  • Loading branch information
rob1256 authored Feb 8, 2024
1 parent 38c4070 commit fd3482b
Show file tree
Hide file tree
Showing 15 changed files with 303 additions and 276 deletions.
10 changes: 9 additions & 1 deletion swe/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,4 +42,12 @@ npx prisma studio
yarn prisma studio
```

Then, open [http://localhost:5555](http://localhost:5555) with your browser launch Prisma Studio.
Then, open [http://localhost:5555](http://localhost:5555) with your browser launch Prisma Studio.

### Tests

You can run tests via Jest by:

```bash
yarn jest
```
26 changes: 26 additions & 0 deletions swe/components/courses.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import React from "react"
import { render, screen } from "@testing-library/react"

import Courses, { Props } from "./courses"

describe("<Courses />", () => {
it("should render correctly with 1 course", async() => {
const mockCourses: Props["courses"] = [
{
id: 1,
title: "fake title 1",
description: "fake description 1",
cost: 1,
type: "fake type 1",
capacity: 1,
registered: 1,
},
];

render(<Courses courses={mockCourses} />);

expect(screen.getByText("Courses")).toBeInTheDocument();
expect(screen.getAllByTestId("course-row").length).toStrictEqual(1);
expect(screen.getByRole("cell", { name: "fake title 1" })).toBeInTheDocument();
})
})
9 changes: 6 additions & 3 deletions swe/components/courses.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
import { Course } from "@prisma/client"

// Courses Components
export default function Courses({ courses }: { courses: Course[] }) {
export type Props = {
courses: Course[];
};

export default function Courses({ courses }: Props) {
return (
<div className="bg-white rounded-lg shadow-md p-6">
<h2 className="text-3xl text-gray-700 mb-6">Courses</h2>
Expand Down Expand Up @@ -33,7 +36,7 @@ export default function Courses({ courses }: { courses: Course[] }) {
</thead>
<tbody className="divide-y divide-gray-200">
{courses.map((course) => (
<tr key={course.id}>
<tr key={course.id} data-testid="course-row">
<td className="py-4 px-6 whitespace-nowrap">{course.id}</td>
<td className="py-4 px-6 whitespace-nowrap">{course.title}</td>
<td className="py-4 px-6 whitespace-nowrap">{course.description}</td>
Expand Down
101 changes: 101 additions & 0 deletions swe/components/registration-form.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
import { Prisma } from '@prisma/client';
import { rest } from "msw";
import { setupServer } from "msw/node";
import { render, screen } from "@testing-library/react";
import userEvent from "@testing-library/user-event";

import { RegistrationFormDto } from "@/types/RegistrationFormDto";
import RegistrationForm, { Props } from "./registration-form";

const server = setupServer();

describe("RegistrationForm", () => {
beforeAll(() => server.listen());
afterEach(() => server.resetHandlers());
afterAll(() => server.close());

it("renders the page correctly", () => {
const mockCourses: Props["courses"] = [
{
id: 1,
title: "fake title 1",
description: "fake description 1",
cost: 1,
type: "fake type 1",
capacity: 1,
registered: 1,
},
];

render(
<RegistrationForm courses={mockCourses} />
);

expect(screen.getByText("Register onto Course")).toBeInTheDocument();
expect(screen.getByPlaceholderText("First Name")).toBeInTheDocument();
expect(screen.getByPlaceholderText("Last Name")).toBeInTheDocument();
expect(screen.getByPlaceholderText("Email")).toBeInTheDocument();
expect(
screen.getByRole("button", { name: "Register" })
).toBeInTheDocument();
});

it("handles form submission correctly", async () => {
const mockRegistrationData: RegistrationFormDto = {
firstName: "John",
lastName: "Doe",
email: "johndoe@example.com",
courseId: "1",
};

server.use(
rest.post("http://localhost:3000/api/register", async (req, res, ctx) => {
const requestJson = await req.json() as Prisma.RegistrationCreateInput;
const { firstName, lastName, email, course } = requestJson;

// Return a mock response
return res(ctx.json({ id: 1, firstName, lastName, email }));
})
);

const mockCourses: Props["courses"] = [
{
id: 1,
title: "fake title 1",
description: "fake description 1",
cost: 1,
type: "fake type 1",
capacity: 1,
registered: 1,
},
];
const user = userEvent.setup();

render(<RegistrationForm courses={mockCourses} />);

// Enter form input values
await user.type(
screen.getByPlaceholderText("First Name"),
mockRegistrationData.firstName
);
await user.type(
screen.getByPlaceholderText("Last Name"),
mockRegistrationData.lastName
);
await user.type(screen.getByPlaceholderText("Email"), mockRegistrationData.email);

// Select a course from the dropdown
await user.selectOptions(
screen.getByPlaceholderText("Course"),
mockRegistrationData.courseId.toString()
);

// Submit the form
await user.click(screen.getByRole("button", { name: "Register" }));

// Assert that form fields are cleared
expect(screen.getByPlaceholderText("First Name")).toHaveValue("");
expect(screen.getByPlaceholderText("Last Name")).toHaveValue("");
expect(screen.getByPlaceholderText("Email")).toHaveValue("");
});
});
6 changes: 3 additions & 3 deletions swe/components/registration-form.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,11 @@ const FormError = ({ errorMessage }: { errorMessage: string }) => {
return <p className="text-red-300 mt-1">{errorMessage}</p>;
};

interface RegisterCourseProps {
export interface Props {
courses: Course[];
}

export default function RegistrationForm(props: RegisterCourseProps) {
export default function RegistrationForm({ courses }: Props) {
const { register, handleSubmit, setError, formState: { errors } } = useForm();

const onFormSubmission = async (data: any, event: any) => {
Expand Down Expand Up @@ -63,7 +63,7 @@ export default function RegistrationForm(props: RegisterCourseProps) {
<InputSpacer>
<Dropdown
placeholder="Course"
courses={props.courses}
courses={courses}
name="courseId"
register={register}
validationSchema={{ required: true }}
Expand Down
36 changes: 36 additions & 0 deletions swe/components/registrations.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import { render, screen } from "@testing-library/react";

import { Course } from "@/types";
import Registrations, { Props } from './registrations';

describe("Registrations", () => {
it("should render correctly with 1 registration", () => {
const mockCourse: Course = {
id: 1,
title: "fake title 1",
description: "fake description 1",
cost: 1,
type: "fake type 1",
capacity: 1,
registered: 1,
}

const mockRegistrations: Props["registrations"] = [
{
id: 1,
firstName: "John",
lastName: "Doe",
email: "john@example.com",
courseId: 1,
course: mockCourse,
},
];

render(
<Registrations registrations={mockRegistrations} />
);

expect(screen.getByText("Registrations")).toBeInTheDocument();
expect(screen.getByText("John Doe")).toBeInTheDocument();
});
});
11 changes: 6 additions & 5 deletions swe/components/registrations.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,18 @@
import { HomePageProps } from "@/pages";
import Image from "next/image";

interface RegistrationsProps {
registrations: HomePageProps["registrations"];
import { RegistrationWithCourse } from "@/types";

export interface Props {
registrations: RegistrationWithCourse[];
}

export default function Registrations(props: RegistrationsProps) {
export default function Registrations({ registrations }: Props) {
return (
<>
<div className="mb-3">
<h2 className="text-3xl text-gray-700">Registrations</h2>
</div>
{props.registrations.map((registration, i: number) => (
{registrations.map((registration, i: number) => (
<div className="mb-3" key={i}>
<div className="border rounded-lg p-4 flex">
<div className="my-auto">
Expand Down
18 changes: 8 additions & 10 deletions swe/lib/services/saveRegistrationFormService.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,14 @@
import { RegistrationForm } from '@/types/RegistrationForm';
import axios from 'axios';

import { RegistrationFormDto } from '@/types/RegistrationFormDto';
import transformRegistrationForm from '../utils/transformRegistrationForm';

export default async function saveRegistrationForm(registrationForm: RegistrationForm) {
let registrationData = transformRegistrationForm(registrationForm)
export default async function saveRegistrationForm(registrationFormDto: RegistrationFormDto) {
let registrationData = transformRegistrationForm(registrationFormDto)

const response = await fetch('/api/register', {
method: 'POST',
body: JSON.stringify(registrationData)
const response = await axios.post('http://localhost:3000/api/register', {
...registrationData
});

if (!response.ok) {
throw new Error(response.statusText);
}
return await response.json();
return response.data;
}
22 changes: 10 additions & 12 deletions swe/lib/utils/transformRegistrationForm.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,13 @@
import { Prisma } from '@prisma/client';
import { RegistrationForm as RegistrationFormDto } from '@/types/RegistrationForm';
import { RegistrationFormDto } from '@/types/RegistrationFormDto';

export default function transformRegistrationForm(registrationForm: RegistrationFormDto): Prisma.RegistrationCreateInput {
const registrationDb: Prisma.RegistrationCreateInput = {
firstName: registrationForm.firstName,
lastName: registrationForm.lastName,
email: registrationForm.email,
course: {
connect: { id: parseInt(registrationForm.courseId, 10) }
}
};
const transformRegistrationForm = (registrationForm: RegistrationFormDto): Prisma.RegistrationCreateInput => ({
firstName: registrationForm.firstName,
lastName: registrationForm.lastName,
email: registrationForm.email,
course: {
connect: { id: parseInt(registrationForm.courseId, 10) }
}
});

return registrationDb;
}
export default transformRegistrationForm;
3 changes: 2 additions & 1 deletion swe/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,10 @@
"@types/react": "18.2.12",
"@types/react-dom": "18.2.5",
"autoprefixer": "10.4.14",
"axios": "^1.6.7",
"eslint": "8.42.0",
"eslint-config-next": "13.4.5",
"next": "13.5.0",
"next": "13.5.6",
"postcss": "8.4.31",
"react": "18.2.0",
"react-dom": "18.2.0",
Expand Down
10 changes: 6 additions & 4 deletions swe/pages/index.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import { PrismaClient, Course, Registration } from "@prisma/client";
import { PrismaClient } from "@prisma/client";
import Head from "next/head";

import { Course, RegistrationWithCourse } from "@/types";
import Courses from "../components/courses";
import RegistrationForm from "../components/registration-form";
import Registrations from "../components/registrations";
Expand All @@ -24,12 +26,12 @@ export async function getServerSideProps() {
}
};
}
export type HomePageProps = {
export type Props = {
courses: Course[];
registrations: (Registration & { course: Course })[];
registrations: RegistrationWithCourse[];
};

export default function HomePage({ courses, registrations }: HomePageProps) {
export default function HomePage({ courses, registrations }: Props) {
return (
<>
<Head>
Expand Down
Loading

0 comments on commit fd3482b

Please sign in to comment.