Adds a standalone Node smoke test (smoke/) that exercises every REST endpoint consumed by the Flutter app against a seeded local dev server and compares responses to committed snapshots. This is the safety net for the Meteor upgrade: it must stay byte-identical after every escala. - smoke/seed.js: deterministic Mongo seed (fixed ObjectIds, geo indexes) - smoke/run.js: calls endpoints, normalizes volatile fields, diffs snapshots - smoke/smoke.sh: seed + run wrapper - smoke/snapshots/: baseline captured on Meteor 1.6.1.1 - IPGeocoder.js: degrade gracefully when MaxMind DB absent (dev boot) - settings-development.json: dev-only internalApiToken to enable the REST API - .meteorignore: exclude smoke/ from the Meteor server build |
||
|---|---|---|
| .. | ||
| snapshots | ||
| README.md | ||
| run.js | ||
| seed.js | ||
| smoke.sh | ||
REST smoke test
Regression harness for the REST API in imports/api/Rest/Rest.js — the API the
Flutter app (fires_flutter/lib/models/fires_api.dart) depends on.
It calls every Flutter-consumed endpoint against a locally running dev server
with deterministic seed data, normalizes the intrinsically volatile fields
(uptime, generated ids, insert timestamps) and compares the responses to
committed snapshots in smoke/snapshots/.
It must stay green after every Meteor upgrade escala. The snapshots are the contract: any drift is treated as an upgrade bug.
Reproducible local startup
-
MongoDB (prod parity = 3.2; a dev-only instance in Docker):
docker run -d --name tcef-mongo32 -p 27018:27017 mongo:3.2 -
Meteor dev server (from the repo root):
export PATH="$HOME/.meteor:$PATH" export MONGO_URL="mongodb://localhost:27018/fuegos" meteor --settings settings-development.json --port 3100settings-development.jsoncarries a dev-onlyprivate.internalApiToken(dev-smoke-token) which is what enables the REST API. Without it the API routes are not even registered (seeRest.js).Note:
IPGeocoder.jsdegrades gracefully when the MaxMind GeoLite2 DB is absent (it is provisioned by cron in production) so the server boots in a clean checkout.
Running the smoke test
./smoke/smoke.sh # seed + compare against baseline snapshots
./smoke/smoke.sh --update # seed + regenerate the baseline snapshots
Env overrides: MONGO_CONTAINER (default tcef-mongo32), MONGO_DB
(fuegos), BASE_URL (http://localhost:3100).
What is covered
| Snapshot | Endpoint | Flutter call |
|---|---|---|
status_uptime |
GET status/uptime |
— |
status_active_fires_count |
GET status/active-fires-count |
— |
status_last_fire_check |
GET status/last-fire-check |
— |
status_last_fire_detected |
GET status/last-fire-detected |
— |
status_subs_public_union |
GET status/subs-public-union/:token |
getMonitoredAreas |
fires_in |
GET fires-in/:token/:lat/:lng/:km |
— |
fires_in_full |
GET fires-in-full/:token/:lat/:lng/:km |
getFiresInLocation |
mobile_users_post |
POST mobile/users |
createUser |
mobile_subscriptions_post |
POST mobile/subscriptions |
subscribe |
mobile_subscriptions_all |
GET mobile/subscriptions/all/:token/:mobileToken |
fetchYourLocations |
mobile_subscriptions_delete |
DELETE mobile/subscriptions/:token/:mobileToken/:subsId |
unsubscribe |
mobile_falsepositive_post |
POST mobile/falsepositive |
markFalsePositive |
Normalized (volatile) fields
Compared structurally but blanked to a placeholder because they cannot be
deterministic: status/uptime → ms; mobile/users → userId, username,
upsertResult.insertedId; mobile/subscriptions/all → owner, createdAt,
updatedAt; mobile/falsepositive → upsert.insertedId.
Everything else (ids of seeded docs, geometries, counts, jsend envelope, field names and types) is asserted byte-for-byte.