A small full-stack calculator. The React frontend collects calculator input and delegates arithmetic to a Go HTTP API. The backend validates requests, performs the selected operation, and returns a JSON result.
backend/ Go HTTP server and handler tests
frontend/ React, TypeScript, Vite, and browser-facing tests
The frontend keeps the current expression and request state in a local React reducer. frontend/src/Calculator/api.ts is the typed boundary to the backend; the backend has no persistent storage or authentication.
Vite was chosen for the frontend because it provides a quick setup and a productive development baseline with fast feedback. Material UI was chosen to make styling and common interface components straightforward, while its responsive, mobile-first approach supports the calculator across screen sizes.
Calculator state is kept local to the feature rather than introduced as global application state. A reducer keeps related transitions together, including key presses, request loading, successful results, and errors. This makes the interaction rules explicit and allows them to be tested independently from the rendered components.
The API module is the single boundary between the UI and the backend. It maps calculator operators to endpoint paths, sends the request payload, and checks the response at runtime. TypeScript types document the expected response, but they cannot validate data received over the network, so malformed or non-finite results are rejected before reaching the UI.
The backend is intentionally small and uses focused HTTP handlers. The four operations share one handler for request validation, error handling, and JSON responses, while each operation supplies only its arithmetic behavior. This keeps the API behavior consistent and avoids duplicating boundary logic.
Requests are validated strictly: unknown fields, missing operands, trailing JSON, and oversized bodies are rejected. The server also sets HTTP timeouts and handles interrupt and termination signals with a bounded graceful shutdown. These choices provide basic reliability without adding infrastructure that the calculator does not need.
Tests are layered around the main boundaries of the application. Backend tests cover operation handlers and router behavior. Frontend unit tests cover the reducer transitions and API request/response behavior, while browser tests verify the calculator through rendered, user-like button interactions. Together these provide coverage from individual state changes through the full frontend interaction path.
- Go 1.27.1 or newer
- Node.js 20 or newer
- npm
- Chromium, if running the frontend browser tests
Start the backend in one terminal:
cd backend
go run .The API listens on http://localhost:3000.
Start the frontend in a second terminal:
cd frontend
npm install
printf 'VITE_BACKEND_URL=http://localhost:3000\n' > .env
npm run devVite prints the local frontend URL, normally http://localhost:5173. VITE_BACKEND_URL may be changed when the API runs elsewhere.
The backend does not currently emit CORS headers or define a Vite development proxy. As a result, using the frontend from a different browser origin may require adding one of those integrations; the API itself can always be tested directly with the examples below.
Each operation accepts a POST request with exactly two numeric JSON fields:
{"first": 10, "second": 2}| Endpoint | Operation |
|---|---|
POST /sum |
Addition |
POST /diff |
Subtraction |
POST /prod |
Multiplication |
POST /div |
Division |
Successful responses have status 200:
{"result": 12}For example:
curl -X POST http://localhost:3000/sum \
-H 'Content-Type: application/json' \
-d '{"first":10,"second":2}'Invalid JSON, missing or unknown fields, trailing JSON values, and request bodies larger than 1 KiB return 400 with {"error":"invalid parameters"}. Division by zero returns 400 with {"error":"division by zero"}. A non-finite arithmetic result returns 500 with {"error":"internal server error"}.
Backend checks:
cd backend
gofmt -w .
go test ./...
go vet ./...Frontend checks:
cd frontend
npm test
npm run lint
npm run buildThe frontend browser tests use Vitest Browser Mode with Playwright. Install Chromium once before running them:
cd frontend
npx playwright install chromium
npm run test:browserUse npm run test:watch for an interactive frontend test run.