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();
+ });
});