Development Strategy
This is the operating manual for building HireForGig: how code gets written, how it gets tested, how every test case is documented in a form a non-engineer stakeholder can actually read, and how work moves from a phase in 11-roadmap.md into shipped, verified functionality. Every other doc in this set says what to build; this doc says how.
1. Guiding principles
- Every roadmap phase maps to a checklist of shippable, independently testable units of work — no "big bang" integration at the end of a phase. See §6.
- Tests are the specification, not an afterthought. Test names are written in plain English so the test suite itself doubles as a living, always-accurate feature spec — see §3.
- Financial/escrow code gets extra scrutiny. Anything touching money (
08-payments-escrow.md) requires a second reviewer and a higher test-coverage bar than the rest of the codebase, no exceptions. - Stakeholder-facing test documentation is generated, not hand-written. Hand-maintained test-case spreadsheets drift out of sync with the real code within weeks. Instead, the test suite's own descriptions generate the report — see §4.
- Consistent with this org's existing stack (
10-technical-architecture.md): Node/Express + React + MySQL, matching the CRM platform already running in production — reduces onboarding cost for anyone who's worked on that codebase, and reuses proven operational patterns (pm2, Apache-fronted, systemd health checks).
2. Repository structure
Following this org's established convention (separate repos per app, e.g. crm-node/crm-react, not a monorepo):
/opt/hireforgig-backend/ Node/Express API
/opt/hireforgig-frontend/ React SPA
/opt/hireforgig-docs/ This planning doc set (already live at hireforgig.dmll.in/docs)
Each app repo follows this internal layout:
hireforgig-backend/
src/
routes/ one file per resource (users.js, gigs.js, engagements.js, payments.js, ...)
services/ business logic that doesn't belong in a route handler (escrow state machine, matching/ranking)
middleware/
config/
test/
unit/ mirrors src/ 1:1 — services/escrow.test.js tests services/escrow.js
integration/ API-level tests (supertest against a real test DB)
migrations/ SQL migration files, numbered, matching the pattern already used on crm-node
DEVELOPMENT_STRATEGY.md (symlink or copy of this doc — kept in sync, see §8)
README.md
hireforgig-frontend/
src/
pages/
components/
api/
test/
unit/ component tests (React Testing Library)
README.md
3. Testing strategy
3.1 Test levels and tools
| Level | Tool | What it covers | Runs |
|---|---|---|---|
| Unit | Jest | Pure functions, business logic (escrow state transitions, commission calculation, matching/ranking logic) — no DB, no network | On every commit (pre-commit hook) and CI |
| Integration | Jest + Supertest | API endpoints against a real (test) MySQL instance — request in, DB state + response out | CI, on every push |
| Component | Jest + React Testing Library | Frontend components in isolation — render, user interaction, assert output | CI, on every push |
| End-to-end | gstack browse/qa skill (already used throughout this org's other projects on this host) |
Full user flows through a real browser against a running instance — post a gig, hire, deliver, approve, get paid | Before every deploy to staging/production, and for every PR touching a critical flow (escrow, auth) |
| Manual QA pass | Human, using qa checklist derived from 05-campaign-lifecycle.md state machine |
Edge cases automation doesn't catch well (real payment gateway sandbox flows, email/SMS delivery) | Before every production release |
3.2 Where test cases live and how they're written
Rule: every src/X.js has a corresponding test/unit/X.test.js (or test/integration/ for route files). No source file ships without a co-located test file existing, even if that file currently only has a placeholder test.
Test descriptions are written as plain-English specifications, not implementation notes. This is the single most important convention in this document, because it's what makes §4 (stakeholder documentation) possible without extra manual work.
// test/unit/services/escrow.test.js
describe('Escrow — funding', () => {
it('holds the full gig amount when a hirer accepts an offer', () => { ... });
it('rejects funding if the hirer\'s payment method fails verification', () => { ... });
});
describe('Escrow — release', () => {
it('releases funds to the creator when the hirer explicitly approves delivery', () => { ... });
it('auto-releases funds after the review window elapses with no hirer action', () => { ... });
it('does not release funds while a dispute is open on the engagement', () => { ... });
});
describe('Escrow — refund', () => {
it('fully refunds the hirer if the gig is cancelled before HIRED', () => { ... });
it('splits funds per admin resolution when a dispute is partially upheld', () => { ... });
});
Every describe block corresponds to a feature area from 05-campaign-lifecycle.md or 08-payments-escrow.md; every it corresponds to one rule or edge case from those same docs. When a doc changes, the first thing that should change is the relevant test descriptions — write the new/updated it() names before writing the implementation (see §3.3).
3.3 TDD for anything state-machine or money related
For the gig lifecycle state machine and all escrow/payment code specifically (not required project-wide, but mandatory for these two areas given their stakes):
- Write the failing test(s) describing the new behavior, in plain English, first.
- Confirm they fail for the right reason.
- Implement until green.
- Refactor with the tests as a safety net.
This isn't dogma for the whole codebase — a marketing page component doesn't need TDD — but the transactional core does, because a bug there is a real money/trust incident, not a cosmetic issue.
3.4 Coverage targets
| Area | Minimum line coverage | Rationale |
|---|---|---|
services/escrow*, services/payments* |
95% | Money. No excuses. |
services/* (matching, ranking, state machine) |
85% | Core business logic |
routes/* (integration tests) |
80% | Every endpoint has at least a happy-path + one failure-path test |
| Frontend components | 60% | Prioritize components with logic (forms, state) over pure presentation |
Coverage is a floor, not a target to game — a test that asserts nothing meaningful but pads coverage numbers is worse than no test, because it creates false confidence. Code review should reject tests that don't actually assert real behavior.
4. Stakeholder-facing test documentation (the part you asked about specifically)
Problem this solves: a hand-maintained "test case document" (spreadsheet or Word doc listing test cases) goes stale the moment a developer adds, removes, or changes a test without remembering to update the spreadsheet too — and in practice, nobody remembers reliably.
Solution: generate the stakeholder document directly from the test suite, every time it runs.
- Use
jest-html-reporter(or equivalent) configured to output a clean HTML report: everydescribe/itblock, pass/fail status, and duration, grouped by suite. - Because every
it()name is already written in plain English (§3.2), this report is a readable "here is everything we test and confirm works" document — no translation layer, no separate document to keep in sync. - CI writes this report to
reports/test-report.htmlon every run; the latest one for themainbranch is what gets shared with stakeholders. - For an even more presentable version: a short script converts the same Jest JSON output into a Markdown summary (
reports/TEST_SUMMARY.md) grouped by the feature docs they map to (Escrow, Gig Lifecycle, Discovery, etc.) — this is the file to literally attach to a stakeholder email or walk through in a review meeting.
reports/
test-report.html full detail, every test, pass/fail, timing — generated every CI run
TEST_SUMMARY.md grouped-by-feature summary, generated every CI run — this is the shareable one
coverage/ istanbul/nyc HTML coverage report
What a stakeholder sees in TEST_SUMMARY.md (illustrative — real content is generated, not hand-written):
## Escrow & Payments (47 tests, 47 passing)
- ✅ Holds the full gig amount when a hirer accepts an offer
- ✅ Releases funds to the creator when the hirer explicitly approves delivery
- ✅ Auto-releases funds after the review window elapses with no hirer action
- ✅ Does not release funds while a dispute is open on the engagement
...
## Gig Lifecycle (32 tests, 32 passing)
- ✅ Moves a gig from OPEN to PITCHED when a creator applies
- ✅ Prevents a hirer from approving a gig with no submitted deliverable
...
This means: the moment you need to show a stakeholder "here's proof this works," you run one command and hand them a generated, always-current document — never a document you have to remember to update by hand.
5. Git workflow
mainis always deployable. No direct commits — everything goes through a PR (even solo development benefits from the PR-as-changelog habit; also sets the org up correctly once a second developer joins).- Branch naming:
feature/<short-description>,fix/<short-description>. - Commit messages: imperative mood, explain why not what (matches this org's existing convention — see recent commits on
crm-node/crm-reactfor the house style). - PR requirements: all tests passing, coverage thresholds met (§3.4), no direct-to-
mainfor anything touchingservices/escrow*orservices/payments*without a second review.
6. Roadmap → checklist mapping (Phase 1/MVP)
Each bullet below is an independently shippable, independently testable slice, sequenced to de-risk the highest-uncertainty pieces first (payment/escrow integration is the biggest unknown — build and prove it early, not last):
- Foundations: auth, user model (creator/hirer/both flag), DB schema + migrations for the core entities in
10-technical-architecture.md. - Payment gateway integration spike: prove the escrow flow works end-to-end against the chosen gateway's sandbox before building the rest of the product around it — this is the highest-risk unknown in the entire MVP and should not be discovered late.
- Creator profile + rate card (CRUD, no payments yet).
- Hirer profile + gig posting (CRUD, brief builder, no payments yet).
- Discovery/search (filters from
09-discovery-matching.md, deterministic, no ML). - Application/direct-offer flow (the PITCHED/OFFER_SENT states from
05-campaign-lifecycle.md). - Full escrow-backed hire → deliver → approve → payout loop, wired to the gateway spike from step 2.
- Messaging (per-engagement scoped chat).
- Reviews/ratings.
- Admin: moderation queue, dispute case management, payout oversight — cannot launch without this, per
04-features-admin.md. - End-to-end QA pass (gstack
browse/qaskill) against the full lifecycle, staging environment. - Launch to the initial supply-first geo/niche cohort per
11-roadmap.md.
Each numbered step above gets its own PR(s), its own test suite additions, and its own entry in the generated TEST_SUMMARY.md — so progress is demonstrable to stakeholders incrementally, not just at the end.
7. Environments
- Local dev: each developer runs the API + a local/dev MySQL instance.
- Staging: mirrors production config, seeded with realistic (fake) data, used for the E2E QA pass in step 11 above and for stakeholder demos before a feature reaches production.
- Production:
hireforgig.dmll.in— deploy only frommain, only after CI is green.
8. Keeping this document current
This file is the source of truth and lives at /opt/hireforgig-backend/DEVELOPMENT_STRATEGY.md (canonical) with a copy published at hireforgig.dmll.in/docs/development-strategy for easy stakeholder sharing. If the two drift, the repo copy wins — update the published copy to match, not the other way around.