Venue & Lantern Testing Guide
Overview
This guide walks you through testing the new venue and lantern lighting functionality across multiple devices.
Quick Setup
1. Seed Test Venues (One-Time Setup)
Make sure dev server is running first: npm run dev
Open your browser's developer console (F12) and run:
// The seed function is automatically available in dev mode
await window.seedVenues()You should see output like:
🌱 Seeding test venues...
✅ Created: Brew & Co Coffee
✅ Created: Sunset Yoga Studio
... (8 venues total)
🎉 Seeding complete! Created 8/8 venues.Verify in Firestore Console:
- Go to Firebase Console → Firestore Database
- You should see a
venuescollection with 8 documents - Each document has: name, address, lat, lng, category, activeLanternCount, etc.
If you don't see venues in Firestore:
- Check browser console for errors
- Verify you're logged in (auth required to create venues)
- Check Firebase project: Should be
lantern-app-dev - Deploy Firestore rules if needed:
firebase deploy --only firestore:rules
This will create 8 test venues in downtown San Diego.
2. Set Location Spoofing
In .env.local:
# San Diego coordinates (downtown Gaslamp Quarter)
VITE_DEV_TEST_LOCATION="32.7157,-117.1611"Restart dev server: npm run dev
Testing Workflow
Single Device Test
Login to the app with a test account
Open Dashboard (should be default view)
Click the Fire icon (bottom nav)
Lantern Hub opens → Click "Light Lantern"
Select a venue from the nearby list (should show all 8 test venues)
Lantern lights → You'll see:
- Active lantern in Lantern Hub
- Countdown timer (2 hours)
- Venue name and details
Extinguish → Click "Extinguish Lantern" in Lantern Hub
Multi-Device Test (Waves)
Device A (User 1)
- Login with
user1@test.com - Set location spoof to San Diego (
32.7157,-117.1611) - Light lantern at Brew & Co Coffee
- Leave Lantern Hub open
Device B (User 2)
- Login with
user2@test.com - Set same location spoof
- Light lantern at Brew & Co Coffee (same venue)
- Both users now have active lanterns at the same venue
Test Wave Interaction (Coming Next)
- User 2 should see User 1's lantern in the venue
- User 2 can send a "Wave" to User 1
- User 1 receives wave notification
- Both can start a chat
Test Venues
All venues are clustered around downtown San Diego:
| Venue Name | Category | Merchant? |
|---|---|---|
| Brew & Co Coffee | Coffee Shop | No |
| Sunset Yoga Studio | Yoga Studio | No |
| The Gaslamp Tavern | Bar | No |
| Pacific Bites Restaurant | Restaurant | No |
| Zen Wellness Spa | Wellness | No |
| Harbor Fitness Gym | Gym | No |
| Pages & Prose Bookstore | Bookstore | No |
| Urban Bowls | Restaurant | Yes (demo merchant) |
Firestore Security Rules
Before testing, ensure these rules are deployed:
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
// Venues - read-only for all authenticated users
match /venues/{venueId} {
allow read: if request.auth != null;
allow write: if false; // Admin only (manual seed)
}
// Lanterns - users can only manage their own
match /lanterns/{lanternId} {
allow read: if request.auth != null;
allow create: if request.auth != null
&& request.resource.data.userId == request.auth.uid;
allow update, delete: if request.auth != null
&& resource.data.userId == request.auth.uid;
}
}
}Deploy with:
firebase deploy --only firestore:rulesTroubleshooting
"No venues found nearby"
- Check
.env.localhasVITE_DEV_TEST_LOCATIONset - Restart dev server
- Open ProfileSettings → Location Spoofing panel → Verify coordinates
- Ensure venues were seeded successfully
"Unable to get your location"
- Browser location permission may be blocked
- Use the debug panel in ProfileSettings to manually set location
- Check console for geolocation errors
"Lantern not appearing in Hub"
- Check Firestore console →
lanternscollection - Verify user is authenticated (check localStorage for auth token)
- Check browser console for errors
- Try refreshing the page
"Lantern expired immediately"
- Check system clock (ensure it's accurate)
- Lanterns expire after 2 hours by default
- Check
expiresAtfield in Firestore document
Next Steps
Once basic venue/lantern functionality works:
Build Wave System
- Query active lanterns at same venue
- Send/receive wave notifications
- Accept/reject wave UI
Add Real-time Sync
- Live lantern count updates
- Wave notifications via Firestore listeners
- Chat message sync
Add Merchant Offers
- Wire
Urban Bowls(demo merchant) to offer system - Show offers when checking in at merchant venues
- Redemption flow
- Wire
Geofencing Testing
Added: 2026-01-18 (Issue #28)
Overview
Lantern lighting now requires users to be within a venue's geofence (default 100m, or custom venue.radius). This is validated both client-side and server-side via Cloud Functions.
Why server-side validation?
Client-side JavaScript can be modified by users (via DevTools or direct Firestore writes). The lightLanternSecure Cloud Function performs tamper-proof validation on Google's servers, preventing users from faking their location to light lanterns at venues they're not actually at. This is critical for merchant trust and offer redemption integrity.
Test Scenarios
Test 1: Within Geofence (Should Succeed)
- Set location at venue coordinates:javascript
localStorage.setItem('dev_spoofed_location', JSON.stringify({latitude: 32.7157, longitude: -117.1611})) location.reload() - Navigate to a nearby venue and light a lantern
- Expected: Lantern lights successfully
- Console shows:
🔥 Lantern lit via Cloud Function (Xm from venue)
Test 2: Outside Geofence (Should Fail)
- Set location 500m away:javascript
localStorage.setItem('dev_spoofed_location', JSON.stringify({latitude: 32.7200, longitude: -117.1611})) location.reload() - Try to light a lantern at Brew & Co Coffee
- Expected: Error message: "You must be within 100m of Brew & Co Coffee to light a lantern. You are currently 478m away."
Test 3: Boundary Edge Case (~100m)
- Set location approximately 100m from venue:javascript
localStorage.setItem('dev_spoofed_location', JSON.stringify({latitude: 32.7166, longitude: -117.1611})) location.reload() - Try to light a lantern
- Expected: Should succeed (boundary is inclusive)
Test 4: Custom Venue Radius
Some venues may have custom radius values in Firestore. To test:
- In Firestore, set a venue's
radiusfield to200(meters) - Position yourself at 150m away
- Expected: Should succeed (within 200m custom radius)
Unit Tests
Run the automated geofencing tests:
npm test -- --run src/__tests__/geofencing.test.js src/__tests__/lanternProximity.test.jsCoverage:
geofencing.test.js- 15 tests for distance calculation and formattinglanternProximity.test.js- 13 tests for lantern lighting proximity validation
Cloud Function Verification
To verify server-side validation is working:
- Open browser DevTools → Network tab
- Light a lantern successfully
- Look for
lightLanternSecurerequest to Cloud Functions - Response should include
distanceMetersfield
If Cloud Function is unavailable, client falls back to local validation with console warning:
Cloud Function unavailable, falling back to client-side validationClean Up Test Data
To remove all test venues:
// In browser console
import { db } from './src/firebase'
import { collection, getDocs, deleteDoc } from 'firebase/firestore'
const venuesRef = collection(db, 'venues')
const snapshot = await getDocs(venuesRef)
for (const doc of snapshot.docs) {
await deleteDoc(doc.ref)
console.log('Deleted:', doc.id)
}To remove all test lanterns:
const lanternsRef = collection(db, 'lanterns')
const snapshot = await getDocs(lanternsRef)
for (const doc of snapshot.docs) {
await deleteDoc(doc.ref)
console.log('Deleted:', doc.id)
}