# Product Requirements Document

## Validation Checklist

- [x] All required sections are complete
- [x] No [NEEDS CLARIFICATION] markers remain
- [x] Problem statement is specific and measurable
- [x] Problem is validated by evidence (not assumptions)
- [x] Context → Problem → Solution flow makes sense
- [x] Every persona has at least one user journey
- [x] All MoSCoW categories addressed (Must/Should/Could/Won't)
- [x] Every feature has testable acceptance criteria
- [x] Every metric has corresponding tracking events
- [x] No feature redundancy (check for duplicates)
- [x] No contradictions between sections
- [x] No technical implementation details included
- [x] A new team member could understand this PRD

---

## Product Overview

### Vision
Enable BuyerKiosk to ship code with confidence by establishing comprehensive test coverage (90%+) through a robust, maintainable testing infrastructure that documents business rules, catches regressions, and supports rapid feature development.

### Problem Statement
The BuyerKiosk application currently has only ~15% test coverage (37 test files, ~400 test cases) despite having 316 source files and ~94,000 lines of code. Critical business-critical modules like Backstock (inventory management), Cash (financial operations), and SMS (customer communications) have ZERO test coverage. This creates significant pain:

1. **Deployment Risk**: Every deployment is a gamble - regressions go undetected until customers report issues
2. **Refactoring Paralysis**: Developers avoid improving code because they can't verify changes don't break functionality
3. **Onboarding Friction**: New developers take 2-3x longer to understand business rules because they're not documented in tests
4. **Integration Failures**: External API changes (Twilio, QuickBooks, FiveStars) cause production outages with no early warning
5. **Knowledge Loss**: Business logic exists only in developers' heads, not in executable specifications

**Consequences of Inaction**: Continued regression bugs, slower feature velocity, increased support burden, and potential financial/operational errors in critical modules (Cash, SMS).

### Value Proposition
Unlike ad-hoc testing efforts, this infrastructure provides:
1. **Executable Documentation**: Tests become living documentation of business rules (following ComebackCash patterns)
2. **Regression Prevention**: Automated detection of breaking changes before deployment
3. **Developer Confidence**: Refactor and improve code knowing tests will catch issues
4. **API Stability**: Mock infrastructure for external services prevents integration surprises
5. **CI/CD Foundation**: Enable automated quality gates and deployment pipelines

## User Personas

### Primary Persona: Backend Developer
- **Demographics:** Mid-level PHP developer (2-5 years experience), works on BuyerKiosk features and bug fixes daily
- **Goals:** Ship reliable code quickly, understand existing business rules before making changes, refactor without fear of breaking things
- **Pain Points:**
  - Spends hours debugging issues that tests would catch
  - Hesitates to refactor spaghetti code because no safety net exists
  - Reverse-engineers business rules from production code instead of reading test documentation
  - Gets blamed when "minor changes" break production

### Secondary Personas

#### DevOps Engineer
- **Demographics:** Infrastructure-focused engineer managing deployments
- **Goals:** Automated quality gates before deployment, confidence that code is production-ready
- **Pain Points:** Manual testing before deploys is time-consuming and unreliable; rollbacks are frequent

#### Tech Lead / Architect
- **Demographics:** Senior developer responsible for code quality standards
- **Goals:** Establish testing patterns the team follows, measure and improve code quality over time, enforce coverage minimums on PRs
- **Pain Points:** No visibility into coverage metrics; inconsistent testing approaches across modules

#### New Team Member
- **Demographics:** Developer joining the project (0-3 months tenure)
- **Goals:** Understand business rules quickly, contribute without breaking things
- **Pain Points:** Business logic is tribal knowledge; no documentation of expected behaviors

## User Journey Maps

### Primary User Journey: Feature Development with Tests
1. **Awareness:** Developer receives ticket to add new feature or fix bug; realizes they need to understand existing behavior first
2. **Consideration:** Checks for existing tests in the module; if tests exist, reads them to understand business rules; if not, must reverse-engineer from code
3. **Adoption:** For new features, writes tests first (TDD) using established fixtures and mocks; for bug fixes, writes failing test reproducing the bug
4. **Usage:**
   - Uses fixtures to create test data (`StoreFixtures::createTestStore()`)
   - Uses mocks to isolate external dependencies (`TwilioMock`, `PdoMock`)
   - Runs tests locally with `./test.sh` before committing
   - CI runs full suite on PR; coverage gate prevents merging below threshold
5. **Retention:** Tests document their work for future developers; test failures in CI catch regressions before they reach production

### Secondary User Journeys

#### CI/CD Quality Gate Journey
1. Developer pushes PR to GitHub
2. GitHub Actions triggers test suite
3. Coverage report generated and compared to threshold
4. PR blocked if coverage below 80% on changed files OR if any test fails
5. Developer fixes issues and re-pushes
6. Upon passing, PR can be merged

#### Module Coverage Improvement Journey
1. Tech lead identifies module with low coverage (e.g., Backstock at 0%)
2. Reviews test infrastructure docs to understand patterns
3. Creates fixtures for module entities
4. Writes unit tests for business logic
5. Writes integration tests for workflows
6. Coverage improves incrementally; CI enforces no regression

## Feature Requirements

### Must Have Features

#### Feature 1: Mock Infrastructure Library
- **User Story:** As a developer, I want pre-built mocks for external services so that I can write unit tests without hitting real APIs
- **Acceptance Criteria:**
  - [ ] PDO/PDOStatement mock builder with fluent API for query result setup
  - [ ] TwilioMock wrapping `Twilio\Rest\Client` with expectation verification
  - [ ] VonageMock for cURL-based SMS operations with response simulation
  - [ ] RedisMock for `Predis\Client` operations
  - [ ] StoreMock for creating configured Store objects with property presets
  - [ ] All mocks can be injected into classes under test without code changes

#### Feature 2: Fixture System
- **User Story:** As a developer, I want reusable test data factories so that I can quickly create valid test objects
- **Acceptance Criteria:**
  - [ ] Fixture classes for all Tier 1 modules: Core (Store, Buy, Customer, BuyQueue), Backstock (Event, Bin, Category), SMS (TextMessage), Cash (CashActivity, SafeConfiguration)
  - [ ] Override pattern: `createTestX(array $overrides = [])` for customization
  - [ ] Database insertion helpers: `insertTestX(PDO $db, array $overrides = [])` returning IDs
  - [ ] Multi-record set generators: `createTestXSet()` for common scenarios
  - [ ] Fixtures follow existing EmployeeFixtures pattern (see `tests/Employee/Fixtures/`)

#### Feature 3: Database Test Infrastructure
- **User Story:** As a developer, I want isolated database tests so that tests don't interfere with each other or require manual cleanup
- **Acceptance Criteria:**
  - [ ] Transaction-based isolation: all tests wrapped in `beginTransaction()`/`rollBack()`
  - [ ] Multi-database support: test helpers for store-specific databases (pattern: `kiosk_[typeNum]`)
  - [ ] Seeding utilities for lookup tables (employees, categories, locations)
  - [ ] Cross-database query testing support (e.g., BuyQueue's cross-store recent buy detection)
  - [ ] DatabaseTestCase enhanced to support store database switching

#### Feature 4: CI/CD Integration
- **User Story:** As a tech lead, I want automated test execution on pull requests so that broken code cannot be merged
- **Acceptance Criteria:**
  - [ ] GitHub Actions workflow running PHPUnit on every PR
  - [ ] MySQL and Redis services available in CI environment
  - [ ] Test results visible in PR checks with pass/fail status
  - [ ] Workflow exits non-zero on test failures
  - [ ] Test script updated to run full suite (not just ApiNewBuyTest)

#### Feature 5: Coverage Reporting
- **User Story:** As a tech lead, I want visibility into test coverage so that I can track progress and identify gaps
- **Acceptance Criteria:**
  - [ ] PHPUnit configured to generate coverage reports (HTML and Clover XML)
  - [ ] Coverage threshold configured (80% for new code, 90% target overall)
  - [ ] Coverage badge available for README
  - [ ] Source directories configured: `src/BuyerKiosk/`, `models/`, `routes/`

#### Feature 6: Tier 1 Module Test Suites
- **User Story:** As a developer, I want comprehensive tests for critical business modules so that I can refactor and extend them safely
- **Acceptance Criteria:**
  - [ ] Backstock EventService: 50+ tests covering event lifecycle, phases, alerts, bin operations
  - [ ] Core Store: 25+ tests covering store entity, integrations, token management
  - [ ] SMS TextMessageService: 25+ tests covering providers, flood protection, message building
  - [ ] Cash CashBalancer: 20+ tests covering variance calculations, transaction types
  - [ ] All critical business rules documented in test comments (following ComebackCash pattern)

### Should Have Features

#### Feature 7: Data Providers for Parameterized Tests
- **User Story:** As a developer, I want to run the same test logic with multiple data sets so that I can thoroughly test edge cases
- **Acceptance Criteria:**
  - [ ] PHPUnit data provider pattern documented and exemplified
  - [ ] Example: Phone number validation with valid/invalid cases
  - [ ] Example: Coupon threshold calculations with different tiers

#### Feature 8: Integration Test Suite
- **User Story:** As a developer, I want end-to-end workflow tests so that I can verify multi-component interactions
- **Acceptance Criteria:**
  - [ ] Buy queue lifecycle test (enter → sort → process → complete)
  - [ ] Backstock event lifecycle test (create → progress → alerts → complete)
  - [ ] Cash reconciliation workflow test
  - [ ] Each integration test uses real database with transaction rollback

#### Feature 9: Test Documentation
- **User Story:** As a new team member, I want documentation on testing patterns so that I can write consistent tests
- **Acceptance Criteria:**
  - [ ] Testing guide in `docs/guides/testing-guide.md`
  - [ ] Mocking patterns documented with examples
  - [ ] Fixture usage documented
  - [ ] Business rule documentation pattern (from ComebackCash) explained

#### Feature 10: Test Suite Reorganization
- **User Story:** As a developer, I want existing tests organized in a consistent structure so that I can easily find and maintain tests
- **Acceptance Criteria:**
  - [ ] Audit existing 45 test files against target directory structure
  - [ ] Relocate misplaced tests to appropriate directories (Unit/, Integration/, Fixtures/)
  - [ ] Rename test files to follow `*Test.php` convention consistently
  - [ ] Update namespaces to match new directory locations
  - [ ] Consolidate scattered fixture classes into module-specific `Fixtures/` directories
  - [ ] Ensure all tests pass after reorganization (no broken imports)
  - [ ] Document migration map showing old → new locations

### Could Have Features

#### Feature 11: Coverage Regression Gate
- **User Story:** As a tech lead, I want to prevent coverage from decreasing so that we maintain quality over time
- **Acceptance Criteria:**
  - [ ] CI step comparing coverage to baseline
  - [ ] PR blocked if coverage decreases by more than 1%
  - [ ] Override mechanism for justified cases

#### Feature 12: Test Performance Monitoring
- **User Story:** As a developer, I want to identify slow tests so that the test suite runs quickly
- **Acceptance Criteria:**
  - [ ] PHPUnit configured to log slow tests (>1 second)
  - [ ] Top 10 slow tests reported in CI output

#### Feature 13: API Route Testing Framework
- **User Story:** As a developer, I want to test API routes without a running server so that I can verify endpoints
- **Acceptance Criteria:**
  - [ ] Slim framework request/response mocking utilities
  - [ ] Example API tests for 3 key endpoints

### Won't Have (This Phase)

- **Browser/UI Testing**: Frontend testing (Cypress, Selenium) is out of scope; focus is backend only
- **Performance/Load Testing**: phpbench or similar tools for benchmarking are deferred
- **Mutation Testing**: Tools like Infection for mutation testing are deferred
- **Test Database Migrations**: Automated schema setup; assumes test DB mirrors production schema
- **100% Coverage**: Target is 90%; remaining 10% (legacy routes, simple getters) is acceptable
- **External Service Integration Tests**: No tests that hit real Twilio/Vonage/QuickBooks APIs

## Detailed Feature Specifications

### Feature: Mock Infrastructure Library (Feature 1 - Most Complex)
**Description:** A library of pre-built mock classes and utilities that allow developers to isolate units of code from external dependencies during testing. Mocks simulate the behavior of real objects (PDO, Twilio, Redis) and allow verification that expected interactions occur.

**User Flow:**
1. Developer creates test class extending `TestCase` or `DatabaseTestCase`
2. In `setUp()`, developer instantiates mock objects using builder pattern:
   ```php
   $this->pdoMock = PdoMockBuilder::create()
       ->expectQuery('SELECT * FROM stores WHERE id = ?')
       ->withParams([1])
       ->willReturn(['id' => 1, 'typeNum' => 'ou00'])
       ->build();
   ```
3. Developer injects mock into class under test via constructor or setter
4. Test executes and mock records interactions
5. PHPUnit assertions verify expected behavior occurred

**Business Rules:**
- Rule 1: Mocks must implement the same interface as real objects (Liskov Substitution)
- Rule 2: PDO mocks must support prepared statements pattern (`prepare()` → `execute()` → `fetch()`)
- Rule 3: External service mocks must be configurable to return success or failure responses
- Rule 4: Mocks should record call history for `expects()` assertions
- Rule 5: Mock builders should provide fluent API for chaining configuration

**Edge Cases:**
- Scenario 1: Database query returns no results → Mock returns empty array or `false` based on fetch method
- Scenario 2: External API throws exception → Mock can be configured to throw expected exception type
- Scenario 3: Multiple queries in same test → Mock supports `willReturnOnConsecutiveCalls()` pattern
- Scenario 4: Query executed with wrong parameters → Test should fail with clear assertion message

### Feature: Test Suite Reorganization (Feature 10)
**Description:** A systematic reorganization of existing test files to follow a consistent directory structure and naming convention. This enables developers to quickly locate tests, understand test coverage by module, and maintain tests alongside their source code.

**Current State (45 test files):**
```
userfrosting/tests/
├── bootstrap.php                    # Keep as-is
├── DatabaseTestCase.php             # Keep as-is
├── Unit/                            # Mixed - needs audit
│   ├── ApiNewBuyTest.php           # Should move to Integration/Api/
│   ├── BuyQueueTest.php            # Should move to Unit/Core/
│   ├── KLoggerTest.php             # Keep (utility test)
│   ├── Autoload/                   # Keep as-is
│   └── ComebackCash/               # Reference structure ✓
├── Integration/                     # Good structure
├── Employee/                        # Hybrid - has Unit/, Integration/, Fixtures/
├── Workbook/                        # Has Fixtures/, Unit/
├── Task/                           # Flat - needs reorganization
└── DigitalSign/                    # New - correct structure
```

**Target Structure:**
```
userfrosting/tests/
├── bootstrap.php
├── DatabaseTestCase.php
├── Unit/
│   ├── Core/                       # Store, Buy, Customer, BuyQueue tests
│   ├── Backstock/                  # EventService, Bin, Category tests
│   ├── SMS/                        # TextMessageService tests
│   ├── Cash/                       # CashBalancer, CashActivity tests
│   ├── ComebackCash/               # Existing (reference)
│   ├── Employee/                   # Moved from tests/Employee/Unit/
│   ├── Workbook/                   # Moved from tests/Workbook/Unit/
│   └── Autoload/                   # Keep as-is
├── Integration/
│   ├── Api/                        # API endpoint tests
│   ├── Core/                       # Cross-component workflows
│   ├── ComebackCash/               # Existing
│   ├── Employee/                   # Moved from tests/Employee/Integration/
│   └── Workbook/                   # Workflow tests
└── Fixtures/
    ├── Core/                       # StoreFixtures, BuyFixtures
    ├── Backstock/                  # EventFixtures, BinFixtures
    ├── SMS/                        # MessageFixtures
    ├── Cash/                       # CashActivityFixtures
    ├── Employee/                   # Moved from tests/Employee/Fixtures/
    └── Workbook/                   # Moved from tests/Workbook/Fixtures/
```

**Migration Rules:**
- Rule 1: Test files testing a single class go to `Unit/[Module]/[ClassName]Test.php`
- Rule 2: Test files testing multi-component interactions go to `Integration/[Module]/`
- Rule 3: Fixture classes go to `Fixtures/[Module]/[Entity]Fixtures.php`
- Rule 4: Namespaces must match directory structure: `Tests\Unit\Core\StoreTest`
- Rule 5: Base test cases stay at root level (`DatabaseTestCase.php`)
- Rule 6: No test logic in fixture classes - fixtures only create data

**Edge Cases:**
- Scenario 1: Test covers multiple modules → Place in primary module, add cross-reference comment
- Scenario 2: Legacy test with no clear module → Create `Legacy/` directory, flag for refactor
- Scenario 3: Test file not following `*Test.php` convention → Rename during migration
- Scenario 4: Circular fixture dependencies → Refactor fixtures to use builder pattern

## Success Metrics

### Key Performance Indicators

- **Adoption:**
  - 100% of new features include tests (enforced by CI)
  - 80% of developers contribute tests within 3 months
- **Engagement:**
  - Average 10+ tests written per developer per week
  - `./test.sh` run locally 5+ times per developer per day
- **Quality:**
  - Overall code coverage: 90%+ (up from ~15%)
  - Test pass rate: 99%+ (no flaky tests)
  - Mean time to detect regression: < 15 minutes (CI feedback)
- **Business Impact:**
  - Production bug rate reduced by 50% within 6 months
  - Deployment rollback rate reduced by 75%
  - Developer onboarding time reduced by 30% (business rules in tests)

### Tracking Requirements

| Event | Properties | Purpose |
|-------|------------|---------|
| Test Suite Execution | `total_tests`, `passed`, `failed`, `skipped`, `duration`, `coverage_percent` | Track test reliability and performance |
| Coverage Report | `module_name`, `line_coverage`, `branch_coverage`, `changed_since_baseline` | Identify gaps and track improvement |
| CI Build Result | `pr_number`, `result`, `tests_run`, `coverage_diff` | Enforce quality gates |
| Developer Test Contribution | `developer_id`, `tests_added`, `week` | Track adoption and engagement |
| Production Bug | `module`, `severity`, `had_test_coverage` | Validate ROI of testing

---

## Constraints and Assumptions

### Constraints
- **Timeline**: Must establish infrastructure within first 2 weeks; Tier 1 module coverage by week 15
- **Developer Resources**: 1-2 developers available for dedicated testing work; others must balance with feature development
- **Existing Codebase**: Some legacy code uses global functions (`dbConnectByName()`, `gen_uuid()`) that are difficult to mock without refactoring
- **Test Database**: Must use copy of production schema; no automated migrations for test setup
- **PHPUnit Version**: Locked to PHPUnit 12.x; cannot upgrade/downgrade without compatibility review
- **CI/CD Platform**: GitHub Actions is the target; no budget for external CI services

### Assumptions
- Developers have basic PHPUnit knowledge and can write tests with guidance
- Test database (`buyerkiosk_test`) will be provisioned locally and in CI
- Existing ComebackCash test patterns represent best practices to follow
- External API credentials for Twilio/Vonage not available in CI; all external calls must be mocked
- Production code can be modified to accept dependency injection where necessary for testability
- Faker library (already installed) provides sufficient test data generation capabilities

## Risks and Mitigations

| Risk | Impact | Likelihood | Mitigation |
|------|--------|------------|------------|
| Global function dependencies prevent mocking | High | High | Create wrapper classes for global functions; use dependency injection pattern |
| Database coupling makes tests slow | Medium | High | Use transaction rollback; minimize DB hits; prefer unit tests over integration |
| Legacy code too tangled to test | High | Medium | Prioritize refactoring alongside testing; accept lower coverage for untestable code |
| CI takes too long (>10 min) | Medium | Medium | Parallel test execution; fast-fail on first error; separate quick/slow test suites |
| Flaky tests erode confidence | High | Medium | Avoid time-dependent tests; use deterministic fixtures; immediate flaky test fixes |
| Team doesn't adopt testing culture | High | Low | Require tests for PR approval; celebrate coverage milestones; make tests easy to write |
| External API changes break mocks | Medium | Low | Version mock responses; monitor API changelogs; update mocks promptly |

## Open Questions

- [x] Should we use Mockery or stick with PHPUnit's built-in mocking? → **Decision: Use Mockery for cleaner syntax and more powerful expectations; add as dev dependency**
- [ ] What's the minimum coverage threshold that blocks PR merge? (Recommendation: 80% on changed files)
- [ ] Should we run full test suite on every push or only on PR creation? (Trade-off: speed vs. confidence)
- [ ] Who will be the "test champion" responsible for reviewing test PRs and maintaining infrastructure?
- [ ] Do we need a dedicated test database server or is local MySQL sufficient for CI?

---

## Supporting Research

### Competitive Analysis

Industry best practices for PHP testing infrastructure:

| Approach | Pros | Cons | Applicability |
|----------|------|------|---------------|
| **PHPUnit + Native Mocks** | No additional deps, well-documented, team knows it | Verbose syntax, limited features | Used for simple mocks |
| **PHPUnit + Mockery** | Cleaner syntax, powerful expectations | Additional dependency, learning curve | ✅ **Chosen** - cleaner API for complex mocks |
| **Pest PHP** | Modern syntax, less boilerplate | Major migration, team unfamiliar | ❌ Rejected - too disruptive |
| **Codeception** | Behavior-driven, multi-layer testing | Overkill for backend-only focus | ❌ Rejected - wrong scope |

**ComebackCash Module as Reference Implementation:**
The existing ComebackCash test suite demonstrates best practices we'll follow:
- Business rules documented in docblocks
- Fixtures with override pattern
- Clear unit/integration separation
- Mock setup helpers in base classes
- 85% coverage achieved as proof of concept

### User Research

**Developer Pain Points (from codebase analysis):**
1. **EventService.php (1,325 LOC)** - No tests; any change is high-risk
2. **Store.php (100+ properties)** - Integration complexity untested
3. **Buy.php** - Raw SQL queries without prepared statements; testing would expose security issues
4. **SMS module** - External API calls untested; production failures occur

**Existing Test Adoption:**
- 37 test files exist, mostly in ComebackCash, Employee, and Workbook modules
- Developers DO write tests when infrastructure exists
- Pattern compliance is high when examples are available

### Market Data

**Industry Standards:**
- 80%+ code coverage is standard for production applications
- 90%+ is considered "high quality" for financial/healthcare software
- Test-driven development (TDD) increases code quality by 40-80% (Microsoft Research)
- Bug fix cost increases 10x when found in production vs. testing

**BuyerKiosk Context:**
- Multi-tenant (100+ stores) means bugs affect many customers
- Financial operations (Cash module) require high confidence
- Customer communications (SMS) impact brand reputation
- Inventory management (Backstock) affects business operations
