Locations — QA Plan
Pre-requisites
- Test org on
liteplatform tier (lowest tier — capsmaxLocationslowest, lets you hit the tier ceiling quickly). - A second org for isolation tests.
- Owner, admin, coach, member personas.
- An org session with
location_idset to a location WITH coordinates, and another session withlocation_idset to a location WITHOUT coordinates.
Golden paths
G1 — Owner adds a location with autocomplete
| Step | Action | Expected |
|---|---|---|
| 1 | Owner navigates to settings → locations. | List loads. |
| 2 | Click “Add a location”. Type address into autocomplete. | Suggestions appear from Google Places. |
| 3 | Pick a result. | Fields populate: address, city, country, lat, lng. |
| 4 | Set name + capacity. Submit. | POST succeeds; row appears with non-null lat/lng. |
G2 — Owner adds a location without coords (manual)
| Step | Action | Expected |
|---|---|---|
| 1 | Submit form with name only, no autocomplete. | Row inserted; lat/lng null. |
| 2 | Try GPS check-in on a session linked to this location. | 400 ‘Session location coordinates are not configured’. |
G3 — Deactivate
| Step | Action | Expected |
|---|---|---|
| 1 | Delete location. | is_active=false. List omits it. |
| 2 | A future session still linked: opens fine; location name still resolvable for display. |
Edge cases
E1 — Tier limit
| Step | Action | Expected |
|---|---|---|
| 1 | Org at lite already has maxLocations active locations. | |
| 2 | POST a new location. | 403 ‘Location limit reached (N/M). Upgrade your plan to add more.‘ |
| 3 | Upgrade to pro (or whatever the next tier is — TODO verify mapping). | Now POST succeeds. |
E2 — Tier downgrade with over-limit
| Step | Action | Expected |
|---|---|---|
| 1 | Org at pro with locations > lite cap. Downgrade to lite. | Locations remain active. (Tier check is creation-time only — verify whether a separate enforcement exists in platform-billing TODO.) |
E3 — Cross-org access
| Step | Action | Expected |
|---|---|---|
| 1 | Owner of org A: GET /organizations/A/locations/{idFromB}. | 404. |
| 2 | Same for PATCH and DELETE. | 404 each. |
E4 — Non-staff mutation
| Step | Action | Expected |
|---|---|---|
| 1 | Coach POST/PATCH/DELETE. | 403. |
| 2 | Member same. | 403. |
E5 — Partial coords
| Step | Action | Expected |
|---|---|---|
| 1 | POST with latitude=32.07 and no longitude. | Row inserted (both nullable). |
| 2 | GPS check-in against a session linked here. | 400 ‘Session location coordinates are not configured’. |
E6 — GPS Haversine boundary
| Step | Action | Expected |
|---|---|---|
| 1 | Location at known coords. Self-checkin from just inside GPS_MAX_METERS. | Succeeds. |
| 2 | From just outside GPS_MAX_METERS. | 400 ‘GPS_TOO_FAR’. |
Cross-persona
- Members can list and get-by-id; cannot mutate.
- Coaches read but cannot mutate.
i18n
| Lang | Strings to verify |
|---|---|
| en | schedule.locationsTab.empty reads “No locations yet. Add one to assign to class sessions.” |
| he | Same key, Hebrew. |
| ru | Same key, Russian. |
| All | ”Location limit reached” copy localized; “GPS_TOO_FAR” is a stable machine string the client translates via schedule.checkinPage.tooFar. |
Expected vs actual
- After deactivation:
is_active=false,deleted_atstill NULL. - After autocomplete fill:
latitudeandlongitudeboth non-null and within plausible bounds (-90 to 90, -180 to 180). - Tier check: count of
is_active=truelocations in the org against the tier’s cap.