carlos / platform Public

Clone
git clone https://amadan.net/carlos/platform

Plain git — no account needed to clone.

Download

Download this file

1package main
2
3import (
4 "bytes"
5 "context"
6 "encoding/json"
7 "net/http"
8 "net/http/httptest"
9 "os"
10 "path/filepath"
11 "strings"
12 "testing"
13)
14
15func TestCreateAppSendsRegionAndTimezone(t *testing.T) {
16 var got map[string]any
17 ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
18 json.NewDecoder(r.Body).Decode(&got)
19 json.NewEncoder(w).Encode(map[string]any{"account": "a", "app": "blog",
20 "region": "uk", "region_name": "UK · London", "region_source": "timezone", "regions_available": 3})
21 }))
22 defer ts.Close()
23 res, err := newTestSession(ts.URL).createApp(context.Background(), apiAcct{Seg: "a"}, "blog", "", false, "", "", "Europe/London")
24 if err != nil {
25 t.Fatal(err)
26 }
27 if got["timezone"] != "Europe/London" {
28 t.Fatalf("body = %v", got)
29 }
30 if _, sent := got["region"]; sent {
31 t.Fatal("region sent without --region")
32 }
33 if res.RegionName != "UK · London" || res.RegionsAvailable != 3 || res.Region != "uk" || res.RegionSource != "timezone" {
34 t.Fatalf("result = %+v", res)
35 }
36}
37
38// An explicit region travels in the body; an empty timezone is left out, so
39// a machine with no readable zone sends nothing.
40func TestCreateAppSendsExplicitRegionAndOmitsEmptyTimezone(t *testing.T) {
41 var got map[string]any
42 ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
43 json.NewDecoder(r.Body).Decode(&got)
44 json.NewEncoder(w).Encode(map[string]any{"account": "a", "app": "blog"})
45 }))
46 defer ts.Close()
47 if _, err := newTestSession(ts.URL).createApp(context.Background(), apiAcct{Seg: "a"}, "blog", "", false, "", "us-east", ""); err != nil {
48 t.Fatal(err)
49 }
50 if got["region"] != "us-east" {
51 t.Fatalf("body = %v", got)
52 }
53 if _, sent := got["timezone"]; sent {
54 t.Fatalf("empty timezone sent: %v", got)
55 }
56}
57
58// A console that predates the region fields answers as it always did; the
59// new fields read as zero values.
60func TestCreateAppOldConsoleResponse(t *testing.T) {
61 ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
62 json.NewEncoder(w).Encode(map[string]any{"account": "a", "app": "blog", "url": "https://x/a/a/apps/blog"})
63 }))
64 defer ts.Close()
65 res, err := newTestSession(ts.URL).createApp(context.Background(), apiAcct{Seg: "a"}, "blog", "", false, "", "", "Europe/London")
66 if err != nil {
67 t.Fatal(err)
68 }
69 if res.App != "blog" || res.Region != "" || res.RegionName != "" || res.RegionSource != "" || res.RegionsAvailable != 0 {
70 t.Fatalf("result = %+v", res)
71 }
72}
73
74func TestPrintAppRegion(t *testing.T) {
75 cases := []struct {
76 name string
77 res apiCreateAppResult
78 asked string
79 want string
80 }{
81 {"timezone", apiCreateAppResult{Region: "uk", RegionName: "UK · London", RegionSource: "timezone", RegionsAvailable: 2}, "", regionCreatedLine("UK · London", "timezone") + "\n"},
82 {"single region", apiCreateAppResult{Region: "ie", RegionName: "Ireland · Dublin", RegionSource: "default", RegionsAvailable: 1}, "", ""},
83 {"old console asked", apiCreateAppResult{}, "uk", regionNotRecordedOldConsole + "\n"},
84 {"switch off asked", apiCreateAppResult{Region: "ie", RegionName: "Ireland · Dublin", RegionSource: "default", RegionsAvailable: 2}, "uk", regionNotAppliedSwitchOff("Ireland · Dublin") + "\n"},
85 {"switch off, asked the home itself", apiCreateAppResult{Region: "ie", RegionName: "Ireland · Dublin", RegionSource: "default", RegionsAvailable: 1}, "ie", regionNotAppliedSwitchOff("Ireland · Dublin") + "\n"},
86 {"switch on, explicit region", apiCreateAppResult{Region: "uk", RegionName: "UK · London", RegionSource: "chosen", RegionsAvailable: 2}, "uk", regionCreatedLine("UK · London", "chosen") + "\n"},
87 {"old console not asked", apiCreateAppResult{}, "", ""},
88 }
89 for _, c := range cases {
90 var b bytes.Buffer
91 printAppRegion(&b, c.res, c.asked, false)
92 if b.String() != c.want {
93 t.Errorf("%s: %q, want %q", c.name, b.String(), c.want)
94 }
95 }
96}
97
98// The full printed line for each source, with a place name and a region code
99// that differ, so a swapped argument shows.
100func TestPrintAppRegionFullLines(t *testing.T) {
101 cases := []struct {
102 source, asked, want string
103 }{
104 {"timezone", "", "Region: UK · London (from your timezone). Use --region to choose another.\n"},
105 {"ip", "", "Region: UK · London (from your network location). Use --region to choose another.\n"},
106 {"default", "", "Region: UK · London (the platform default). Use --region to choose another.\n"},
107 {"chosen", "uk", "Region: UK · London.\n"},
108 }
109 for _, c := range cases {
110 var b bytes.Buffer
111 printAppRegion(&b, apiCreateAppResult{Region: "uk", RegionName: "UK · London", RegionSource: c.source, RegionsAvailable: 3}, c.asked, false)
112 if b.String() != c.want {
113 t.Errorf("source %q: %q, want %q", c.source, b.String(), c.want)
114 }
115 }
116}
117
118// Controller ruling, switch off: the console ignores --region, and answers
119// the home with source "default". The CLI says so (C13b), in full.
120func TestPrintAppRegionSwitchOffFullLine(t *testing.T) {
121 var b bytes.Buffer
122 printAppRegion(&b, apiCreateAppResult{Region: "ie", RegionName: "Ireland · Dublin", RegionSource: "default", RegionsAvailable: 1}, "uk", false)
123 want := "This console is not assigning app regions yet, so --region was not applied. This app's instances start in Ireland · Dublin.\n"
124 if b.String() != want {
125 t.Fatalf("got %q, want %q", b.String(), want)
126 }
127}
128
129// Controller ruling, read-back failure: the console answers region = the home
130// and region_source = "". That is not "the console did not apply --region",
131// so the CLI prints neither C13a nor C13b, and no C9 to C12 line that would
132// claim a source it does not know.
133func TestPrintAppRegionReadBackFailureIsSilent(t *testing.T) {
134 for _, asked := range []string{"", "uk", "ie"} {
135 for _, avail := range []int{0, 1, 3} {
136 var b bytes.Buffer
137 printAppRegion(&b, apiCreateAppResult{Region: "ie", RegionName: "Ireland · Dublin", RegionSource: "", RegionsAvailable: avail}, asked, false)
138 if b.String() != "" {
139 t.Errorf("asked %q available %d: printed %q, want nothing", asked, avail, b.String())
140 }
141 }
142 }
143}
144
145// deploy's onboarding prints the region line after "created app", sends the
146// asked region, and never prints the timezone it sends.
147func TestOfferCreateAppPrintsRegionLine(t *testing.T) {
148 useTempCredentials(t)
149 out := captureStdout(t)
150 forceTerminal(t, true)
151 t.Setenv("TZ", "Europe/Secretville")
152 var got map[string]any
153 ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
154 json.NewDecoder(r.Body).Decode(&got)
155 json.NewEncoder(w).Encode(map[string]any{"app": "taskmonger", "account": "bdk",
156 "url": "https://x/a/bdk/taskmonger", "region": "uk", "region_name": "UK · London",
157 "region_source": "chosen", "regions_available": 3})
158 }))
159 t.Cleanup(ts.Close)
160 dir := filepath.Join(t.TempDir(), "taskmonger")
161 if err := os.MkdirAll(dir, 0o755); err != nil {
162 t.Fatal(err)
163 }
164 t.Chdir(dir)
165 swapChooserIn(t, "y\n")
166 app := offerCreateApp(context.Background(), newTestSession(ts.URL), apiAcct{Seg: "bdk", Exact: true},
167 &noAppsError{Account: "tom@keymail.dev"}, "uk")
168 if app != "taskmonger" {
169 t.Fatalf("app = %q", app)
170 }
171 if got["region"] != "uk" || got["timezone"] != "Europe/Secretville" {
172 t.Fatalf("body = %v", got)
173 }
174 if !strings.Contains(out.String(), "created app") || !strings.Contains(out.String(), "Region: UK · London.\n") {
175 t.Fatalf("stdout = %q", out.String())
176 }
177 if strings.Contains(out.String(), "Secretville") {
178 t.Fatalf("the timezone was printed: %q", out.String())
179 }
180}
181
182// A create that named a fleet is placed by the fleet: C13b would be wrong, so
183// nothing prints. Every other case is unchanged by onFleet.
184func TestPrintAppRegionOnFleet(t *testing.T) {
185 off := apiCreateAppResult{Region: "ie", RegionName: "Ireland · Dublin", RegionSource: "default", RegionsAvailable: 2}
186 var b bytes.Buffer
187 printAppRegion(&b, off, "uk", true)
188 if b.String() != "" {
189 t.Fatalf("on a fleet: %q, want nothing", b.String())
190 }
191 b.Reset()
192 printAppRegion(&b, off, "uk", false)
193 if b.String() != regionNotAppliedSwitchOff("Ireland · Dublin")+"\n" {
194 t.Fatalf("off a fleet: %q", b.String())
195 }
196 // A console that did apply --region still says where the app starts.
197 b.Reset()
198 printAppRegion(&b, apiCreateAppResult{Region: "uk", RegionName: "UK · London", RegionSource: "chosen", RegionsAvailable: 2}, "uk", true)
199 if b.String() != regionCreatedLine("UK · London", "chosen")+"\n" {
200 t.Fatalf("chosen on a fleet: %q", b.String())
201 }
202}
203