A full-stack math problem-solving application built as a teaching resource for a lecture series about the principles and main working methods in software quality assurance.
Each branch contains the examples of the topics for each lecture in the series talks. The main branch of this repository does not contain any testing code.
This is a teaching tool only, not a production-ready software product.
MathWizz was created specifically for educational purposes to demonstrate quality assurance concepts and testing methodologies in a realistically-sized and complex codebase. The codebase has been vibe-coded to serve as a learning resource and likely contains more bugs than have been discovered or documented by either human or her AI viber.
Recommended Use: Use this repository solely as a teaching tool for understanding QA principles, testing strategies, and software quality concepts. Do not use this code in a production environments or as a foundation for any real-world applications.
- Architecture
- Prerequisites
- Quick Start
- Configuration
- Known Limitations
- Secrets Management
- Running Tests Locally
- Running Linters
- Project Structure
- Development
- Teardown
- CI/CD
- Cross-Platform Support
- Troubleshooting
- Contributing
- License
The application consists of 5 services:
- frontend (React): User interface with pixel art theme
- web-server (Go): RESTful API server
- database (PostgreSQL): Persistent storage
- message-queue (NATS): Event broker
- history-worker (Go): Async event processor
- Docker (>= 20.10) - required for Kind cluster and E2E tests
- Kind (>= 0.20) - for Kubernetes deployment
- kubectl (>= 1.28) - for managing Kubernetes cluster
- Go (>= 1.22) - for running backend tests locally
- Node.js (>= 18) - for frontend development and E2E tests
- Docker: https://docs.docker.com/get-docker/
- Kind: https://kind.sigs.k8s.io/docs/user/quick-start/#installation
- kubectl: https://kubernetes.io/docs/tasks/tools/
- Go: https://golang.org/doc/install
- Node.js: https://nodejs.org/
git clone <repository-url>
cd MathWizzchmod +x setup-kind.sh
./setup-kind.shThis script will:
- Create a Kind cluster
- Build all Docker images
- Load images into Kind
- Deploy all services to Kubernetes
- Frontend: http://localhost:3000
- API: http://localhost:8080
- Register a new account
- Login with your credentials
- Solve a math problem (e.g., "25+75")
- Check your history to see the solved problem
All the tests written for this codebase exist in branches Lecture_02_ and onwards - they've intentionally not been committed to the main branch.
To view and run them, switch to any of these later branches.
cd web-server
# Run all tests
ginkgo -r
# Run unit tests only
ginkgo -r --skip-package=*integration*
# Run integration tests only
ginkgo -r --focus-file=*integration*cd history-worker
# Run all tests
ginkgo -r
# Run unit tests only
ginkgo -r --skip-package=*integration*
# Run integration tests only
ginkgo -r --focus-file=*integration*cd frontend
# Run unit and component tests
npm test
# Run E2E tests (fully automated - starts all backend services automatically)
npm run e2e
# Run E2E tests with visible browser
npm run e2e:headed
# Run E2E tests in interactive UI mode
npm run e2e:uiE2E Test Coverage (16 tests across 3 files):
- Login Flow (
login.e2e.test.js) - 7 tests: Complete login through UI, error handling, navigation - Registration Flow (
register.e2e.test.js) - 6 tests: Complete registration through UI, validation, full user journey - Solve & History Flow (
solve.e2e.test.js) - 3 tests: Problem solving, history retrieval, eventual consistency
E2E Test Setup:
- E2E tests automatically start all backend services (database, NATS, web-server, history-worker) using Docker Compose
- No manual setup required!
- First run takes 2-3 minutes (builds images), subsequent runs take 30-60 seconds
- See
frontend/e2e/README.mdfor details
Running Tests as CI/CD Workflows:
- You can also run these tests as part of automated GitHub Actions workflows using the
acttool - This simulates the CI/CD pipeline locally in Docker containers
- See the CI/CD section for instructions on running workflows with
act
Speed Up Ginkgo Tests:
- Add the
-pflag toginkgocommands to run tests in parallel for faster execution - Recommended for unit tests:
ginkgo -r -p --skip-package=*integration* ⚠️ NOT recommended for integration tests:ginkgo -r --focus-file=*integration*(without-p)- This significantly reduces test runtime by running specs concurrently
Why avoid -p for integration tests?
- Integration tests often use shared resources (database connections, NATS queues, Docker containers)
- Running them in parallel can cause race conditions, connection pool exhaustion, or port conflicts
- Sequential execution ensures tests don't interfere with each other's state
- Parallel integration test failures are harder to debug due to interleaved output
- The CI/CD pipeline (
.github/workflows/go-ci.yml) uses-ponly for unit tests for this reason
# Web-server
cd web-server
golangci-lint run
# History-worker
cd history-worker
golangci-lint runcd frontend
npm run lintMathWizz/
├── frontend/ # React application
├── web-server/ # Go API server
├── database/ # PostgreSQL configuration
├── message-queue/ # NATS configuration
├── history-worker/ # Go async worker
├── k8s/ # Kubernetes manifests
└── scripts/ # Deployment scripts
# Database
docker build -t mathwizz/database:latest ./database
# Message Queue
docker build -t mathwizz/message-queue:latest ./message-queue
# Web-Server
docker build -t mathwizz/web-server:latest ./web-server
# History-Worker
docker build -t mathwizz/history-worker:latest ./history-worker
# Frontend
docker build -t mathwizz/frontend:latest ./frontend# List all pods
kubectl get pods -n mathwizz
# View logs for a specific pod
kubectl logs -f <pod-name> -n mathwizz
# View web-server logs
kubectl logs -f deployment/web-server -n mathwizz
# View history-worker logs
kubectl logs -f deployment/history-worker -n mathwizz# Describe a pod
kubectl describe pod <pod-name> -n mathwizz
# Get events
kubectl get events -n mathwizz --sort-by='.lastTimestamp'
# Execute commands in a pod
kubectl exec -it <pod-name> -n mathwizz -- /bin/shTo delete the Kind cluster and all resources:
chmod +x teardown-kind.sh
./teardown-kind.shNote: This repository contains GitHub Actions workflow files (.github/workflows/*.yml) as teaching examples to demonstrate CI/CD concepts. These workflows are not actually connected to GitHub Actions since this is a teaching tool, not a production project.
The example workflows demonstrate a typical CI/CD pipeline that would run on every push and pull request:
- Runs all unit and integration tests
- Runs linters for all services
- Builds Docker images
- Reports test coverage
You can test the GitHub Actions workflows locally using act, a tool that runs GitHub Actions workflows in Docker containers on your local machine.
Installation:
- Visit https://github.com/nektos/act for installation instructions
Basic Usage:
# List all jobs in the pull_request workflow
act pull_request --list
# Run a specific job
act pull_request -j <job-name>
# Example: Run the test-setup-script job
act pull_request -j test-setup-script
# Run all jobs in the pull_request workflow
act pull_requestImportant Notes:
- Complex workflows (Docker builds, Kind clusters) may be resource-intensive and time-consuming
- At minimum, verify YAML syntax by running
act pull_request --list- it should show all jobs without errors - For full integration tests (like
setup-kind.sh), local testing withactis optional but recommended if you have sufficient resources actuses Docker to simulate the GitHub Actions environment, so ensure Docker is running
This project is designed to work on:
- Linux (Fedora CSB OS and other distributions)
- macOS (Intel and Apple Silicon)
If ports 3000 or 8080 are already in use, modify the kind-config.yaml port mappings.
Ensure Docker is running and you have built the images:
./build-images.sh
./load-images-to-kind.shCheck pod status and logs:
kubectl get pods -n mathwizz
kubectl describe pod <pod-name> -n mathwizz
kubectl logs <pod-name> -n mathwizzIf the web-server fails to start with errors about JWT_SECRET:
Error: "JWT_SECRET environment variable is required" Solution: Set the JWT_SECRET environment variable:
# Generate a secure secret
export JWT_SECRET=$(openssl rand -base64 48)
# Or use a manual secret (min 32 characters)
export JWT_SECRET="your-secure-secret-at-least-32-characters-long"Error: "JWT_SECRET must be at least 32 characters long" Solution: Use a longer secret (at least 32 characters):
# This is too short (will fail)
export JWT_SECRET="short"
# This is valid (32+ characters)
export JWT_SECRET="my-secure-jwt-secret-key-for-development-use-only"For Kubernetes: The setup-kind.sh script automatically generates a secure JWT_SECRET, so you shouldn't encounter these errors when using the setup script.
If you encounter SSL-related database connection errors:
Error: "SSL not supported" or "failed to ping database: SSL not supported"
Cause: Your local PostgreSQL instance doesn't have SSL enabled, but DB_SSL_MODE defaults to "require"
Solution: Set DB_SSL_MODE to "disable" for local development:
# For local development without SSL
export DB_SSL_MODE=disableError: "certificate verify failed" or SSL certificate verification errors
Cause: Using verify-ca or verify-full mode without proper certificate configuration
Solution: Either use a lower SSL mode or configure certificates:
# Option 1: Use require mode (doesn't verify certificate)
export DB_SSL_MODE=require
# Option 2: Configure certificates for verify-ca/verify-full
# Mount CA certificate and configure PostgreSQL SSL settingsIf you encounter "rate limit exceeded" errors on /login or /register:
Error: HTTP 429 with body "rate limit exceeded"
Cause: You've exceeded 5 requests per minute from your IP address
Solutions:
-
For Development/Testing: Wait 12 seconds between requests, or 60 seconds for full reset
# Wait for token refill sleep 12 curl -X POST http://localhost:8080/login -d '{"email":"test@example.com","password":"pass"}'
-
For Automated Tests: Add delays between authentication requests
// Example: Add 12-second delay between login attempts await new Promise(resolve => setTimeout(resolve, 12000));
-
For Load Testing: Use multiple IP addresses or test from distributed locations
Rate Limit Details:
- Limit: 5 requests per minute per IP
- Refill rate: 1 token per 12 seconds
- Only affects /register and /login endpoints
- Other endpoints (/solve, /history) are not rate limited
Note: Rate limits are per-IP and per-server-instance. If you're behind a shared NAT, multiple users may share the same limit.
If you encounter CORS errors in the browser console:
Error: "Access to fetch at 'http://localhost:8080/...' from origin 'http://localhost:3001' has been blocked by CORS policy"
Cause: Your frontend is running on a different origin than what's configured in ALLOWED_ORIGINS
Solutions:
-
Frontend on Different Port: Update ALLOWED_ORIGINS to match your frontend
# Frontend on port 3001 instead of default 3000 export ALLOWED_ORIGINS="http://localhost:3001" # Or allow both export ALLOWED_ORIGINS="http://localhost:3000,http://localhost:3001"
-
Multiple Subdomains: Include all subdomains explicitly
export ALLOWED_ORIGINS="https://mathwizz.com,https://www.mathwizz.com,https://app.mathwizz.com"
Common Mistakes:
- ❌ Using wildcard:
ALLOWED_ORIGINS="*"(not supported, security risk) - ❌ Spaces after commas:
"https://a.com, https://b.com"(use no spaces) - ❌ Missing protocol:
"mathwizz.com"(must includehttp://orhttps://) - ❌ Wrong case:
"https://MathWizz.com"vs"https://mathwizz.com"(case-sensitive)
Security Headers: The web-server also adds these security headers to all responses:
X-Frame-Options: DENY- Prevents clickjacking (page cannot be embedded in iframe)X-Content-Type-Options: nosniff- Prevents MIME type sniffing attacksX-XSS-Protection: 1; mode=block- Enables browser XSS filter
This is a teaching resource and does not accept pull requests at this time. For improvements or bug fixes, please open an issue via the GitHub web console. Please feel free to fork the project for your own use.
This project is for educational purposes.