package console
import (
"bytes"
"net/http"
"net/url"
"strings"
"testing"
)
func TestAppSettingsSectionRoutes(t *testing.T) {
fx, _ := instanceFixture(t, "code-settings-sections")
c := newBrowser(t)
signUp(t, fx, c, "code-settings-sections-browser")
for _, section := range []string{"general", "domains", "storage", "email", "features", "advanced", "delete"} {
status, _, body := get(t, c, fx.u("/apps/titogo/settings/"+section))
if status != http.StatusOK {
t.Errorf("GET settings/%s = %d, want 200: %s", section, status, body)
}
}
_, _, general := get(t, c, fx.u("/apps/titogo/settings"))
for _, want := range []string{
`aria-label="Settings sections"`, ">General", ">Domains",
">Release pipeline", ">Storage", ">Email",
">Feature flags", ">Advanced", ">Delete",
} {
if !strings.Contains(general, want) {
t.Errorf("Settings navigation missing %q", want)
}
}
if strings.Contains(general, "Domains & TLS") {
t.Fatal("General still renders the Domains section")
}
_, _, domains := get(t, c, fx.u("/apps/titogo/settings/domains"))
if !strings.Contains(domains, "Domains & TLS") || strings.Contains(domains, "
Identity
") {
t.Fatal("Domains does not render as an isolated section")
}
status, _, _ := get(t, c, fx.u("/apps/titogo/settings/not-a-section"))
if status != http.StatusNotFound {
t.Errorf("GET unknown settings section = %d, want 404", status)
}
assertNonMember404(t, fx, "/apps/titogo/settings/domains")
}
func TestAppSettingsURL(t *testing.T) {
if got := appSettingsURL("a b", "an/app", "general"); got != "/a/a%20b/apps/an%2Fapp/settings" {
t.Errorf("general URL = %q", got)
}
if got := appSettingsURL("bab", "kass", "storage"); got != "/a/bab/apps/kass/settings/storage" {
t.Errorf("storage URL = %q", got)
}
}
func TestPipelineSettingsCanonicalSectionURL(t *testing.T) {
fx, _ := instanceFixture(t, "code-settings-pipeline-section")
c := newBrowser(t)
signUp(t, fx, c, "code-settings-pipeline-section-browser")
status, _, body := get(t, c, fx.u("/apps/titogo/settings/pipeline"))
if status != http.StatusOK || !strings.Contains(body, "Release pipeline") {
t.Fatalf("GET settings/pipeline = %d: %s", status, body)
}
status, _, body = get(t, c, fx.u("/apps/titogo/pipeline"))
if status != http.StatusOK || !strings.Contains(body, "Release pipeline") {
t.Fatalf("legacy GET pipeline = %d: %s", status, body)
}
csrf := sessionToken(t, fx, c)
status, _, body = postForm(t, c, fx.u("/apps/titogo/pipeline"), url.Values{
"csrf": {csrf}, "action": {"add"}, "ch.0.name": {"edge"},
})
if status != http.StatusOK || !strings.Contains(body, `aria-label="Settings sections"`) ||
!strings.Contains(body, `aria-current="page">Release pipeline`) {
t.Fatalf("pipeline draft rerender lost Settings navigation = %d: %s", status, body)
}
}
func TestSettingsValidationRetainsTypedValues(t *testing.T) {
fx := newConsoleFixture(t)
freshApp(t, fx, "sprout")
c := signInPaul(t, fx)
csrf := sessionToken(t, fx, c)
status, _, body := postForm(t, c, fx.u("/apps/sprout/rename"), url.Values{
"csrf": {csrf}, "to": {"Still Typing"},
})
if status != http.StatusUnprocessableEntity || !strings.Contains(body, `value="Still Typing"`) {
t.Fatalf("rename refusal did not retain the typed name = %d: %s", status, body)
}
status, _, body = postForm(t, c, fx.u("/apps/sprout/domains/attach"), url.Values{
"csrf": {csrf}, "host": {"not a host"}, "channel": {"canary/draft"},
})
if status != http.StatusUnprocessableEntity || !strings.Contains(body, `value="not a host"`) ||
!strings.Contains(body, `value="canary/draft"`) {
t.Fatalf("domain refusal did not retain host and channel = %d: %s", status, body)
}
}
func TestBucketlessSettingsSectionsExplainConfiguration(t *testing.T) {
for section, want := range map[string]string{
"storage": "no deployment bucket on this host — this console cannot serve object storage",
"email": "no deployment bucket on this host — this console cannot serve email",
"features": "no deployment bucket on this host — this console cannot read features",
} {
p := page{
Title: "Settings", AppName: "sprout", ActiveTab: "settings", SettingsSection: section,
Account: &Account{Name: "paul@example.com", Sqid: "bab"},
Detail: &AppView{App: "sprout"}, Settings: &SettingsView{NoBucket: true},
}
var buf bytes.Buffer
if err := templates.ExecuteTemplate(&buf, "app_settings", p); err != nil {
t.Fatalf("render %s: %v", section, err)
}
body := buf.String()
if !strings.Contains(body, want) || strings.Contains(body, "Please try again") {
t.Fatalf("bucketless %s section is not explicit: %s", section, body)
}
}
}