From 6401639635c54f022cfa7da55313440c1b9f81ca Mon Sep 17 00:00:00 2001 From: Stevan Freeborn <65925598+StevanFreeborn@users.noreply.github.com> Date: Fri, 26 Dec 2025 05:57:32 -0600 Subject: [PATCH] tests: add tests to cover initial form implementation --- .../package-lock.json | 15 ++ src/GroundsForSupport.Client/package.json | 1 + .../tests/App.spec.tsx | 135 ++++++++++++++++-- 3 files changed, 143 insertions(+), 8 deletions(-) diff --git a/src/GroundsForSupport.Client/package-lock.json b/src/GroundsForSupport.Client/package-lock.json index 378c8da..be14638 100644 --- a/src/GroundsForSupport.Client/package-lock.json +++ b/src/GroundsForSupport.Client/package-lock.json @@ -16,6 +16,7 @@ "@testing-library/dom": "^10.4.1", "@testing-library/jest-dom": "^6.9.1", "@testing-library/react": "^16.3.0", + "@testing-library/user-event": "^14.6.1", "@types/node": "^24.10.1", "@types/react": "^19.2.7", "@types/react-dom": "^19.2.3", @@ -1197,6 +1198,20 @@ } } }, + "node_modules/@testing-library/user-event": { + "version": "14.6.1", + "resolved": "https://registry.npmjs.org/@testing-library/user-event/-/user-event-14.6.1.tgz", + "integrity": "sha512-vq7fv0rnt+QTXgPxr5Hjc210p6YKq2kmdziLgnsZGgLJ9e6VAShx1pACLuRjd/AS/sr7phAR58OIIpf0LlmQNw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12", + "npm": ">=6" + }, + "peerDependencies": { + "@testing-library/dom": ">=7.21.4" + } + }, "node_modules/@tybys/wasm-util": { "version": "0.10.1", "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.1.tgz", diff --git a/src/GroundsForSupport.Client/package.json b/src/GroundsForSupport.Client/package.json index 4abf119..04f08ca 100644 --- a/src/GroundsForSupport.Client/package.json +++ b/src/GroundsForSupport.Client/package.json @@ -20,6 +20,7 @@ "@testing-library/dom": "^10.4.1", "@testing-library/jest-dom": "^6.9.1", "@testing-library/react": "^16.3.0", + "@testing-library/user-event": "^14.6.1", "@types/node": "^24.10.1", "@types/react": "^19.2.7", "@types/react-dom": "^19.2.3", diff --git a/src/GroundsForSupport.Client/tests/App.spec.tsx b/src/GroundsForSupport.Client/tests/App.spec.tsx index 97b8ce7..960babc 100644 --- a/src/GroundsForSupport.Client/tests/App.spec.tsx +++ b/src/GroundsForSupport.Client/tests/App.spec.tsx @@ -1,15 +1,134 @@ -import { expect, test } from 'vitest'; +import { beforeEach, describe, expect, test, vi } from 'vitest'; import App from '@/App.tsx'; -import { render, fireEvent } from '@testing-library/react'; +import { render } from '@testing-library/react'; import '@testing-library/jest-dom'; +import userEvent, { type UserEvent } from '@testing-library/user-event'; -test('counter button increments the count', () => { - const screen = render(); +describe('profile info', () => { + let user: UserEvent; - const button = screen.getByRole('button'); + beforeEach(() => { + user = userEvent.setup(); + }); - fireEvent.click(button); - fireEvent.click(button); + test('it should display a profile image', () => { + const screen = render(); + + const profileImage = screen.getByAltText('Profile picture of Stevan Freeborn'); - expect(button).toHaveTextContent('count is 2'); + expect(profileImage).toBeInTheDocument(); + }); + + test('it should display name', () => { + const screen = render(); + + const nameElement = screen.getByRole('heading', { name: 'Stevan Freeborn' }); + + expect(nameElement).toBeInTheDocument(); + }); +}); + +describe('form', () => { + test('it should have an amount input', () => { + const screen = render(); + + const amountInput = screen.getByLabelText('Amount'); + + expect(amountInput).toBeInTheDocument(); + }); + + test('it should have an email input', () => { + const screen = render(); + + const emailInput = screen.getByLabelText('Email'); + + expect(emailInput).toBeInTheDocument(); + }); + + test('it should have a button to submit the form', () => { + const screen = render(); + + const submitButton = screen.getByRole('button', { name: 'Buy' }); + + expect(submitButton).toBeInTheDocument(); + }); + + test('it should require the amount to be provided', async () => { + const screen = render(); + + const submitButton = screen.getByRole('button', { name: 'Buy' }); + + await userEvent.click(submitButton); + + const errorMessage = screen.getByText('Please enter a valid amount greater than 0.'); + expect(errorMessage).toBeInTheDocument(); + }); + + test('it should clear amount error when input changes', async () => { + const screen = render(); + + const amountInput = screen.getByLabelText('Amount'); + const submitButton = screen.getByRole('button', { name: 'Buy' }); + + await userEvent.click(submitButton); + + let errorMessage = screen.queryByText('Please enter a valid amount greater than 0.'); + expect(errorMessage).toBeInTheDocument(); + + await userEvent.type(amountInput, '10'); + + errorMessage = screen.queryByText('Please enter a valid amount greater than 0.'); + + expect(errorMessage).not.toBeInTheDocument(); + }); + + test('it should allow form to be submitted without email', async () => { + const windowSpy = vi.spyOn(window, 'alert').mockImplementation(() => {}); + + const screen = render(); + + const amountInput = screen.getByLabelText('Amount'); + const submitButton = screen.getByRole('button', { name: 'Buy' }); + + await userEvent.type(amountInput, '10'); + await userEvent.click(submitButton); + + expect(windowSpy).toHaveBeenCalledWith('Form is valid! Amount: 10, Email: '); + }); + + test('it should validate email if provided', async () => { + const screen = render(); + + const amountInput = screen.getByLabelText('Amount'); + const emailInput = screen.getByLabelText('Email'); + const submitButton = screen.getByRole('button', { name: 'Buy' }); + + await userEvent.type(amountInput, '10'); + await userEvent.type(emailInput, 'invalid-email'); + await userEvent.click(submitButton); + + const errorMessage = screen.getByText('Please enter a valid email address.'); + expect(errorMessage).toBeInTheDocument(); + }); + + test('it should clear email error when input changes', async () => { + const screen = render(); + + const amountInput = screen.getByLabelText('Amount'); + const emailInput = screen.getByLabelText('Email'); + const submitButton = screen.getByRole('button', { name: 'Buy' }); + + await userEvent.type(amountInput, '10'); + await userEvent.type(emailInput, 'invalid-email'); + await userEvent.click(submitButton); + + let errorMessage = screen.queryByText('Please enter a valid email address.'); + expect(errorMessage).toBeInTheDocument(); + + await userEvent.clear(emailInput); + await userEvent.type(emailInput, 'test@test.com'); + + errorMessage = screen.queryByText('Please enter a valid email address.'); + expect(errorMessage).not.toBeInTheDocument(); + }); });