| 1 | package console |
| 2 | |
| 3 | // claim_invariant_probes_read_test.go is the probe table for every read: each |
| 4 | // is a valid request for a resource that exists (staged where the plain world |
| 5 | // has none), accepted only on the exact success status with the resource named |
| 6 | // in the answer. A read that comes back 404 because the id was made up, 401 |
| 7 | // because the bearer was missing, or a redirect to sign-in is not coverage. |
| 8 | |
| 9 | import ( |
| 10 | "bytes" |
| 11 | "context" |
| 12 | "encoding/json" |
| 13 | "net/http" |
| 14 | "testing" |
| 15 | "time" |
| 16 | |
| 17 | "github.com/carlosframework/platform/internal/geo" |
| 18 | "github.com/carlosframework/platform/internal/geoip" |
| 19 | "github.com/carlosframework/platform/internal/release" |
| 20 | "github.com/carlosframework/platform/internal/reqrec" |
| 21 | ) |
| 22 | |
| 23 | // claimPageRead is a browser GET of a page, the owner signed in. |
| 24 | func claimPageRead(setup func(*testing.T, *claimCase), path string, want ...string) claimProbe { |
| 25 | return claimProbe{setup: setup, do: claimPageReply(path), body: want} |
| 26 | } |
| 27 | |
| 28 | // claimAPIRead is the GET the CLI sends, as the owner's bearer. |
| 29 | func claimAPIRead(setup func(*testing.T, *claimCase), path string, want ...string) claimProbe { |
| 30 | return claimProbe{setup: setup, do: claimGetAPI(path), body: want} |
| 31 | } |
| 32 | |
| 33 | // claimRedirectRead is a GET whose answer is the one named redirect. |
| 34 | func claimRedirectRead(path string, status int, loc string) claimProbe { |
| 35 | return claimProbe{do: claimPageReply(path), status: status, loc: loc} |
| 36 | } |
| 37 | |
| 38 | // ---- the worlds reads need ------------------------------------------------------- |
| 39 | |
| 40 | func claimWorldInstance(t *testing.T, cx *claimCase) { |
| 41 | t.Helper() |
| 42 | cx.instanceWorld(t) |
| 43 | cx.instance(t, `{"host":"acme.go.tito.io","region":"ie"}`) |
| 44 | } |
| 45 | |
| 46 | func claimWorldFleet(t *testing.T, cx *claimCase) { t.Helper(); cx.fleet(t) } |
| 47 | |
| 48 | func claimWorldMove(t *testing.T, cx *claimCase) { t.Helper(); cx.movableInstance(t) } |
| 49 | |
| 50 | func claimWorldAlias(t *testing.T, cx *claimCase) { |
| 51 | t.Helper() |
| 52 | cx.claimedAlias(t, "tickets.example.com") |
| 53 | } |
| 54 | |
| 55 | func claimWorldDoorKey(t *testing.T, cx *claimCase) { |
| 56 | t.Helper() |
| 57 | cx.mustAPI(t, http.MethodPost, "/api/cli/apps/bab/titogo/door-keys", `{"label":"router"}`, http.StatusCreated) |
| 58 | } |
| 59 | |
| 60 | func claimWorldLedger(t *testing.T, cx *claimCase) { |
| 61 | t.Helper() |
| 62 | cx.mustAPI(t, http.MethodPost, "/api/cli/apps/bab/titogo/ledgers/carbon/append", `{"payload":{"kg_central":1}}`, http.StatusOK) |
| 63 | } |
| 64 | |
| 65 | func claimWorldSchedule(t *testing.T, cx *claimCase) { |
| 66 | t.Helper() |
| 67 | cx.mustAPI(t, http.MethodPost, "/api/cli/apps/bab/titogo/schedules", `{"name":"sync","every":"6h","path":"/jobs/sync"}`, http.StatusOK) |
| 68 | } |
| 69 | |
| 70 | func claimWorldTag(t *testing.T, cx *claimCase) { |
| 71 | t.Helper() |
| 72 | body, err := json.Marshal(release.Tag{Schema: 1, Version: "0.1.0", Release: "v1", TaggedAt: time.Now().UTC(), Actor: claimFxOwner, Changelog: "census"}) |
| 73 | if err != nil { |
| 74 | t.Fatal(err) |
| 75 | } |
| 76 | if _, err := cx.rel.Put(context.Background(), release.TagKey("bab", "kass", "0.1.0"), body, ""); err != nil { |
| 77 | t.Fatalf("stage a tag: %v", err) |
| 78 | } |
| 79 | } |
| 80 | |
| 81 | func claimWorldApply(t *testing.T, cx *claimCase) { |
| 82 | t.Helper() |
| 83 | cx.mustAPI(t, http.MethodPost, "/api/cli/accounts/bab/store/apply", `{"note":"census"}`, http.StatusOK) |
| 84 | } |
| 85 | |
| 86 | func claimWorldGeoip(t *testing.T, cx *claimCase) { |
| 87 | t.Helper() |
| 88 | claimMustRunAlone(t, "claimWorldGeoip") |
| 89 | withFixtureProbes(t) |
| 90 | if _, err := cx.srv.geoip.Publish(context.Background(), bytes.NewReader(fixture(t, "GeoIP2-City-Test.mmdb")), geoipPublishOpts{Origin: "manual"}); err != nil { |
| 91 | t.Fatalf("stage a published geoip database: %v", err) |
| 92 | } |
| 93 | if !cx.bucketHas(geoip.PointerKey) { |
| 94 | t.Fatal("stage a published geoip database: no pointer") |
| 95 | } |
| 96 | } |
| 97 | |
| 98 | func claimInvitePageProbe() claimProbe { |
| 99 | return claimProbe{ |
| 100 | setup: claimInviteWorld, |
| 101 | do: func(t *testing.T, cx *claimCase) claimReply { |
| 102 | // The invitation is kim's: its page is kim's own signed-in browser. |
| 103 | cx.setUser("kim@keymail.dev") |
| 104 | c := newBrowser(t) |
| 105 | signUp(t, cx.consoleFixture, c, "code-claim-kim-page") |
| 106 | return cx.pageReplyAs(t, c, "/invite/<invite>") |
| 107 | }, |
| 108 | body: []string{"<h1>Join "}, |
| 109 | } |
| 110 | } |
| 111 | |
| 112 | var claimReadProbes = map[string]claimProbe{ |
| 113 | // ---- methodless ---- |
| 114 | "route /api/economics/backhaul": claimAPIRead(nil, "/api/economics/backhaul", `"period"`, `"accounts"`), |
| 115 | "route /fleet/architecture": claimPageRead(nil, "/fleet/architecture", "<h1>Architecture</h1>"), |
| 116 | |
| 117 | // ---- browser pages ---- |
| 118 | "route GET /a/{sqid}/apps/new": claimPageRead(nil, "/a/bab/apps/new", `action="/a/bab/apps/new"`), |
| 119 | "route GET /a/{sqid}/apps/{app}": claimPageRead(nil, "/a/bab/apps/kass", "kass"), |
| 120 | "route GET /a/{sqid}/apps/{app}/account-review": claimPageRead(nil, "/a/bab/apps/kass/account-review", "kass"), |
| 121 | "route GET /a/{sqid}/apps/{app}/activity": claimPageRead(nil, "/a/bab/apps/kass/activity", "kass"), |
| 122 | "route GET /a/{sqid}/apps/{app}/analytics": claimPageRead(nil, "/a/bab/apps/titogo/analytics", "titogo"), |
| 123 | "route GET /a/{sqid}/apps/{app}/availability": claimPageRead(nil, "/a/bab/apps/titogo/availability", "titogo"), |
| 124 | "route GET /a/{sqid}/apps/{app}/deployments": claimPageRead(nil, "/a/bab/apps/kass/deployments", "v1"), |
| 125 | "route GET /a/{sqid}/apps/{app}/errors": claimPageRead(nil, "/a/bab/apps/titogo/errors", "titogo"), |
| 126 | "route GET /a/{sqid}/apps/{app}/instances": claimPageRead(nil, "/a/bab/apps/kass/instances", "kass.carlosapp.dev"), |
| 127 | "route GET /a/{sqid}/apps/{app}/instances/{host}": claimPageRead(nil, "/a/bab/apps/kass/instances/kass.carlosapp.dev", "kass.carlosapp.dev"), |
| 128 | "route GET /a/{sqid}/apps/{app}/logs": claimPageRead(nil, "/a/bab/apps/titogo/logs", "titogo"), |
| 129 | "route GET /a/{sqid}/apps/{app}/logs/data": claimPageRead(nil, "/a/bab/apps/titogo/logs/data", `"lines"`), |
| 130 | "route GET /a/{sqid}/apps/{app}/pipeline": claimPageRead(nil, "/a/bab/apps/titogo/pipeline", "titogo"), |
| 131 | "route GET /a/{sqid}/apps/{app}/releases": claimPageRead(nil, "/a/bab/apps/kass/releases", "v1"), |
| 132 | "route GET /a/{sqid}/apps/{app}/settings": claimPageRead(nil, "/a/bab/apps/titogo/settings", "titogo"), |
| 133 | "route GET /a/{sqid}/apps/{app}/settings/{section}": claimPageRead(nil, "/a/bab/apps/titogo/settings/advanced", |
| 134 | "/apps/titogo/control-plane/set"), |
| 135 | "route GET /a/{sqid}/fleet": claimPageRead(claimWorldFleet, "/a/bab/fleet", "pi"), |
| 136 | "route GET /a/{sqid}/fleet/byo": claimPageRead(nil, "/a/bab/fleet/byo", "<h1>Bring your own fleet</h1>"), |
| 137 | "route GET /a/{sqid}/fleets/{fleet}": claimPageRead(claimWorldFleet, "/a/bab/fleets/pi", "<h1>pi</h1>"), |
| 138 | "route GET /a/{sqid}/settings": claimPageRead(nil, "/a/bab/settings", "<h1>Account settings</h1>"), |
| 139 | "route GET /a/{sqid}/team": claimPageRead(nil, "/a/bab/team", "<h1>Team</h1>", claimFxOwner), |
| 140 | "route GET /a/{sqid}/trash": claimPageRead(func(t *testing.T, cx *claimCase) { cx.trash(t, "titogo") }, |
| 141 | "/a/bab/trash", "<h1>Trash</h1>", "titogo"), |
| 142 | "route GET /a/{sqid}/{$}": claimPageRead(nil, "/a/bab/", "kass"), |
| 143 | "route GET /accounts/new": claimPageRead(nil, "/accounts/new", "<h1>New account</h1>"), |
| 144 | "route GET /settings": claimPageRead(nil, "/settings", "<h1>Your settings</h1>"), |
| 145 | "route GET /auth/cli": claimPageRead(nil, "/auth/cli", "<h1>Approve a terminal</h1>"), |
| 146 | "route GET /invite/{token}": claimInvitePageProbe(), |
| 147 | "route GET /fleet": claimPageRead(nil, "/fleet", "<h1>Fleet status</h1>"), |
| 148 | "route GET /fleet/economics": claimPageRead(nil, "/fleet/economics", "<h1>Fleet economics</h1>"), |
| 149 | "route GET /fleet/economics/accounts": claimPageRead(nil, "/fleet/economics/accounts", "<h1>Fleet economics: accounts</h1>"), |
| 150 | "route GET /fleet/metrics": claimPageRead(nil, "/fleet/metrics", "<h1>Fleet metrics</h1>"), |
| 151 | "route GET /fleet/store": claimPageRead(claimWorldApply, "/fleet/store", "<h1>Object storage applications</h1>"), |
| 152 | "route GET /healthz": claimPageRead(nil, "/healthz", "ok"), |
| 153 | |
| 154 | // ---- redirects ---- |
| 155 | "route GET /apps": claimRedirectRead("/apps", http.StatusFound, "/a/"), |
| 156 | "route GET /apps/{app}": claimRedirectRead("/apps/kass", http.StatusFound, "/a/"), |
| 157 | "route GET /auth/cli/tokens": claimRedirectRead("/auth/cli/tokens", http.StatusSeeOther, "/settings"), |
| 158 | "route GET /{$}": claimRedirectRead("/", http.StatusFound, "/a/"), |
| 159 | |
| 160 | // ---- the CLI's reads ---- |
| 161 | "route GET /api/cli/apps": claimAPIRead(nil, "/api/cli/apps", `"sqid":"bab"`, `"kass"`), |
| 162 | "route GET /api/cli/apps/{account}/list": claimAPIRead(nil, "/api/cli/apps/bab/list", `"kass"`), |
| 163 | "route GET /api/cli/apps/{account}/{app}/analytics": claimAPIRead(nil, "/api/cli/apps/bab/titogo/analytics", `"pv"`), |
| 164 | "route GET /api/cli/apps/{account}/{app}/availability": claimAPIRead(nil, "/api/cli/apps/bab/titogo/availability", `"groups"`), |
| 165 | "route GET /api/cli/apps/{account}/{app}/channels": claimAPIRead(nil, "/api/cli/apps/bab/kass/channels", `"stable"`), |
| 166 | "route GET /api/cli/apps/{account}/{app}/config": claimAPIRead(nil, "/api/cli/apps/bab/titogo/config", `"bundle"`), |
| 167 | "route GET /api/cli/apps/{account}/{app}/db/{host}/ltx/{level}": claimAPIRead(func(t *testing.T, cx *claimCase) { cx.dbWorld(t) }, |
| 168 | "/api/cli/apps/bab/titogo/db/"+claimDBHost+"/ltx/0", `"files"`, `"handle"`, `"min_txid":1`), |
| 169 | "route GET /api/cli/apps/{account}/{app}/domains": claimAPIRead(claimWorldAlias, "/api/cli/apps/bab/titogo/domains", "tickets.example.com"), |
| 170 | "route GET /api/cli/apps/{account}/{app}/domains/{host}": claimAPIRead(claimWorldAlias, "/api/cli/apps/bab/titogo/domains/tickets.example.com", "tickets.example.com"), |
| 171 | "route GET /api/cli/apps/{account}/{app}/door-keys": claimAPIRead(claimWorldDoorKey, "/api/cli/apps/bab/titogo/door-keys", `"label":"router"`), |
| 172 | "route GET /api/cli/apps/{account}/{app}/email": claimAPIRead(func(t *testing.T, cx *claimCase) { cx.emailDeclared(t) }, |
| 173 | "/api/cli/apps/bab/titogo/email", claimMailDomain), |
| 174 | "route GET /api/cli/apps/{account}/{app}/email/events": claimAPIRead(func(t *testing.T, cx *claimCase) { cx.emailProvisioned(t) }, |
| 175 | "/api/cli/apps/bab/titogo/email/events", `"events"`), |
| 176 | "route GET /api/cli/apps/{account}/{app}/email/events/push": claimAPIRead(func(t *testing.T, cx *claimCase) { cx.emailPush(t) }, |
| 177 | "/api/cli/apps/bab/titogo/email/events/push", "/mail/events"), |
| 178 | // An unsealed code needs no mesh key to decode, so the probe answers 200 |
| 179 | // without seeding one; the record is simply not found. |
| 180 | "route GET /api/cli/apps/{account}/{app}/edge-refs/{code}": claimAPIRead(nil, |
| 181 | "/api/cli/apps/bab/titogo/edge-refs/"+reqrec.NewRef(time.Now(), reqrec.TierProbe, "probe-paths", "box1", nil), `"tier":"probe"`), |
| 182 | "route GET /api/cli/apps/{account}/{app}/errors": claimAPIRead(nil, "/api/cli/apps/bab/titogo/errors", `"log_level"`), |
| 183 | "route GET /api/cli/apps/{account}/{app}/features": claimAPIRead(nil, "/api/cli/apps/bab/titogo/features", `"features"`), |
| 184 | "route GET /api/cli/apps/{account}/{app}/geo": claimAPIRead(func(t *testing.T, cx *claimCase) { |
| 185 | db, err := geo.OpenMMDB("../geo/testdata/GeoIP2-City-Test.mmdb") |
| 186 | if err != nil { |
| 187 | t.Fatal(err) |
| 188 | } |
| 189 | sw := geo.NewSwappable() |
| 190 | sw.Swap(db) |
| 191 | t.Cleanup(func() { sw.Swap(nil) }) |
| 192 | cx.srv.cfg.GeoIPReader = sw |
| 193 | }, "/api/cli/apps/bab/titogo/geo?ip=81.2.69.142", `"found":true`, `"country":"GB"`), |
| 194 | "route GET /api/cli/apps/{account}/{app}/instances": claimAPIRead(claimWorldInstance, "/api/cli/apps/bab/titogo/instances", "acme.go.tito.io"), |
| 195 | "route GET /api/cli/apps/{account}/{app}/instances/{host}": claimAPIRead(claimWorldInstance, |
| 196 | "/api/cli/apps/bab/titogo/instances/acme.go.tito.io", "acme.go.tito.io"), |
| 197 | "route GET /api/cli/apps/{account}/{app}/instances/{host}/move": claimAPIRead(claimWorldMove, |
| 198 | "/api/cli/apps/bab/titogo/instances/acme.go.tito.io/move", `"state":"none"`), |
| 199 | "route GET /api/cli/apps/{account}/{app}/instances/{host}/updates": claimAPIRead(claimWorldInstance, |
| 200 | "/api/cli/apps/bab/titogo/instances/acme.go.tito.io/updates", `"host":"acme.go.tito.io"`, `"updates":"auto"`), |
| 201 | "route GET /api/cli/apps/{account}/{app}/ledgers": claimAPIRead(claimWorldLedger, "/api/cli/apps/bab/titogo/ledgers", `"carbon"`), |
| 202 | "route GET /api/cli/apps/{account}/{app}/ledgers/{ledger}/head": claimAPIRead(claimWorldLedger, |
| 203 | "/api/cli/apps/bab/titogo/ledgers/carbon/head", `"head_sha256"`), |
| 204 | "route GET /api/cli/apps/{account}/{app}/logs": claimAPIRead(nil, "/api/cli/apps/bab/titogo/logs", `"records"`), |
| 205 | "route GET /api/cli/apps/{account}/{app}/pending": claimAPIRead(func(t *testing.T, cx *claimCase) { cx.proposal(t) }, |
| 206 | "/api/cli/apps/bab/titogo/pending", "<pending>"), |
| 207 | "route GET /api/cli/apps/{account}/{app}/pipeline": claimAPIRead(nil, "/api/cli/apps/bab/titogo/pipeline", `"pipeline"`), |
| 208 | "route GET /api/cli/apps/{account}/{app}/regions": claimAPIRead(nil, "/api/cli/apps/bab/titogo/regions", `"regions"`), |
| 209 | "route GET /api/cli/apps/{account}/{app}/relay": claimSerialProbe("relayEnabled stages the region's relay master through t.Setenv: process environment", |
| 210 | claimAPIRead(func(t *testing.T, cx *claimCase) { cx.relayEnabled(t) }, |
| 211 | "/api/cli/apps/bab/titogo/relay", `"app":"titogo"`, `"enabled":true`)), |
| 212 | "route GET /api/cli/apps/{account}/{app}/releases": claimAPIRead(nil, "/api/cli/apps/bab/kass/releases", `"version":"v1"`), |
| 213 | "route GET /api/cli/apps/{account}/{app}/releases/{version}/authorize": claimAPIRead(nil, |
| 214 | "/api/cli/apps/bab/kass/releases/v1/authorize", `"version":"v1"`, `"manifest_digest":"`), |
| 215 | "route GET /api/cli/apps/{account}/{app}/retention": claimAPIRead(nil, "/api/cli/apps/bab/titogo/retention", `"keep"`), |
| 216 | "route GET /api/cli/apps/{account}/{app}/routes": claimAPIRead(nil, "/api/cli/apps/bab/kass/routes", `"kass.carlosapp.dev"`), |
| 217 | "route GET /api/cli/apps/{account}/{app}/schedules": claimAPIRead(claimWorldSchedule, "/api/cli/apps/bab/titogo/schedules", `"sync"`), |
| 218 | "route GET /api/cli/apps/{account}/{app}/sidecars": claimAPIRead(func(t *testing.T, cx *claimCase) { cx.sidecar(t) }, |
| 219 | "/api/cli/apps/bab/titogo/sidecars", `"bot"`), |
| 220 | "route GET /api/cli/apps/{account}/{app}/sidecars/{name}": claimAPIRead(func(t *testing.T, cx *claimCase) { cx.sidecar(t) }, |
| 221 | "/api/cli/apps/bab/titogo/sidecars/bot", `"bot"`), |
| 222 | "route GET /api/cli/apps/{account}/{app}/store": claimAPIRead(func(t *testing.T, cx *claimCase) { cx.storeGranted(t) }, |
| 223 | "/api/cli/apps/bab/titogo/store", `"app":"titogo"`, `"entitlement"`), |
| 224 | "route GET /api/cli/apps/{account}/{app}/store/scan": claimAPIRead(func(t *testing.T, cx *claimCase) { cx.scanGranted(t) }, |
| 225 | "/api/cli/apps/bab/titogo/store/scan", `"app":"titogo"`, `"scanning"`), |
| 226 | "route GET /api/cli/apps/{account}/{app}/store/scan/object": claimAPIRead(func(t *testing.T, cx *claimCase) { |
| 227 | cx.scanObjectStaged(t) |
| 228 | cx.mustAPI(t, http.MethodPost, "/api/cli/apps/bab/titogo/store/scan/sweep", `{}`, http.StatusOK) |
| 229 | }, "/api/cli/apps/bab/titogo/store/scan/object?key=claim-fixture.txt", `"state":"clean"`), |
| 230 | "route GET /api/cli/apps/{account}/{app}/tags": claimAPIRead(claimWorldTag, "/api/cli/apps/bab/kass/tags", `"version":"0.1.0"`), |
| 231 | "route GET /api/cli/apps/{account}/{app}/tags/{version}": claimAPIRead(claimWorldTag, "/api/cli/apps/bab/kass/tags/0.1.0", `"version":"0.1.0"`, `"changelog":"census"`), |
| 232 | "route GET /api/cli/apps/{account}/{app}/version-target": claimAPIRead(nil, "/api/cli/apps/bab/titogo/version-target", `"target"`), |
| 233 | "route GET /api/cli/fleets/{account}": claimAPIRead(claimWorldFleet, "/api/cli/fleets/bab", `"pi"`, `"pi-fleet-data"`), |
| 234 | "route GET /api/cli/services/{account}": claimAPIRead(func(t *testing.T, cx *claimCase) { cx.service(t) }, |
| 235 | "/api/cli/services/bab", `"svc-a"`), |
| 236 | "route GET /api/cli/status/instances": claimAPIRead(nil, "/api/cli/status/instances", `"instances"`), |
| 237 | "route GET /api/cli/status/layout": claimAPIRead(nil, "/api/cli/status/layout", `"boxes"`), |
| 238 | "route GET /api/cli/store/approvals": claimAPIRead(claimWorldApply, "/api/cli/store/approvals", `"applications"`, claimFxOwner), |
| 239 | "route GET /api/cli/accounts/{account}/plan": claimAPIRead(func(t *testing.T, cx *claimCase) { cx.srv.cfg.PlanCatalog = examplePlanCatalog(t) }, |
| 240 | "/api/cli/accounts/bab/plan", `"plan":"free"`), |
| 241 | "route GET /api/cli/system/antivirus": claimAPIRead(nil, "/api/cli/system/antivirus", `"wired":true`), |
| 242 | "route GET /api/cli/system/geoip": func() claimProbe { |
| 243 | p := claimAPIRead(claimWorldGeoip, "/api/cli/system/geoip", `"pointer"`, "GeoIP2-City") |
| 244 | p.serial = "claimWorldGeoip swaps the package variable geoipProbeAddrs (withFixtureProbes)" |
| 245 | return p |
| 246 | }(), |
| 247 | "route GET /api/cli/system/jobs/{id}": { |
| 248 | setup: func(t *testing.T, cx *claimCase) { cx.vars["job"] = cx.systemRelease(t, "canary", "66587fa") }, |
| 249 | do: claimGetAPI("/api/cli/system/jobs/<job>"), |
| 250 | body: []string{`"steps"`, `"done":true`}, |
| 251 | }, |
| 252 | "route GET /api/cli/system/layout": claimAPIRead(nil, "/api/cli/system/layout", `"mode":"none"`), |
| 253 | "route GET /api/cli/system/pointer-digests": claimAPIRead(nil, "/api/cli/system/pointer-digests", |
| 254 | `"account":"bab"`, `"app":"kass","channel":"stable"`), |
| 255 | "route GET /api/cli/system/status": claimAPIRead(func(t *testing.T, cx *claimCase) { cx.systemRelease(t, "canary", "66587fa") }, |
| 256 | "/api/cli/system/status", `"pointers"`, `"version":"66587fa"`), |
| 257 | "route GET /auth/cli/whoami": claimAPIRead(nil, "/auth/cli/whoami", `"address":"`+claimFxOwner+`"`), |
| 258 | |
| 259 | // ---- POSTs that only read ---- |
| 260 | "route POST /a/{sqid}/apps/new/region": { |
| 261 | do: claimFormReply("/a/bab/apps/new/region", "tz", "Europe/Dublin"), |
| 262 | body: []string{`"code"`, `"source"`}, |
| 263 | }, |
| 264 | "route POST /api/cli/apps/{account}/{app}/regions/guess": { |
| 265 | do: claimAPIReply(http.MethodPost, "/api/cli/apps/bab/titogo/regions/guess", `{"tz":"Europe/Dublin"}`), |
| 266 | body: []string{`"guess"`}, |
| 267 | }, |
| 268 | "route POST /api/cli/ops/hosts/{host}/resolve/inspect": { |
| 269 | setup: func(t *testing.T, cx *claimCase) { cx.hostLossWorld(t) }, |
| 270 | do: claimAPIReply(http.MethodPost, "/api/cli/ops/hosts/"+claimLossHost+"/resolve/inspect", |
| 271 | `{"action":"declare-lost","box":"`+claimLossBox+`"}`), |
| 272 | body: []string{`"challenge"`, `"details"`, `"` + claimLossBox + `"`}, |
| 273 | }, |
| 274 | } |
| 275 | |