//go:build browser package check import ( "context" "encoding/json" "html" "net/http" "strings" "testing" "time" "github.com/chromedp/chromedp" "amadan.net/rastrillo/fiesta" "amadan.net/rastrillo/fiesta/internal/harness" ) // The Node tests in strings_test.go hold the lookup on a stub; these // hold it on a real page, through real enhancement: a page that // carries no string attributes at all, only the table, still puts the // table's words on screen; and a page with no table still reads the // vocabulary off its attribute, as JSON text, and falls back to the // English labels. // spanishDoc is a lang="es" page carrying a date field armed with // data-rst-date and a twelve-option select armed with data-rst-select, // and no data-rst-date-* or data-rst-select-* attribute (asserted) // beyond the two this builder adds: with table, an inline // ahead of the // deferred scripts; with words, data-rst-date-words on the input, // holding that JSON text. func spanishDoc(t *testing.T, table []byte, words string) string { t.Helper() var b strings.Builder b.WriteString(`
` + "\n") b.WriteString(``) doc := sizingDoc("strings", b.String()) wantWords := 0 if words != "" { wantWords = 1 } if strings.Count(doc, "data-rst-date-") != wantWords || strings.Count(doc, "data-rst-date-words") != wantWords || strings.Contains(doc, "data-rst-select-") { t.Fatalf("the page carries a string attribute it should not:\n%s", doc) } es := strings.Replace(doc, ``, ``, 1) if withTable == es { t.Fatal("the fixture page has no to put the table in") } return withTable } // esStrings is what the two drives read out of es.json. type esStrings struct { Set string `json:"date-set"` Today string `json:"date-quick-today"` Filter string `json:"select-filter"` Words json.RawMessage `json:"date-words"` } // loadES reads es.json and checks it can tell the table from the // fallback: a table whose strings were the English ones would let // either drive pass for the wrong reason. func loadES(t *testing.T) ([]byte, esStrings, string) { t.Helper() es, ok := fiesta.Strings("es") if !ok { t.Fatal("no es table") } var want esStrings if err := json.Unmarshal(es, &want); err != nil { t.Fatal(err) } var words map[string]string if err := json.Unmarshal(want.Words, &words); err != nil { t.Fatal(err) } if want.Set == "" || want.Today == "" || want.Filter == "" || words["tomorrow"] == "" { t.Fatalf("es.json is missing a string these drives read: %+v", want) } if want.Set == "Set" || want.Filter == "Type to filter" { t.Fatalf("es.json's strings are the English fallbacks, so these drives could not tell the table from the fallback: %+v", want) } return es, want, strings.Split(words["tomorrow"], "|")[0] } // spanishScreen is what the page shows once both fields are enhanced // and tomorrow's word has been typed into the date field: the select's // filter placeholder, and the armed reading's set label, its text and // the first quick pick's label. type spanishScreen struct { Placeholder, Set, Label, Quick string } // driveSpanish serves doc, waits for both enhancements, types tomorrow // into the date field and reads the screen. A reading arms the first // row; text the parser refused arms nothing, so a vocabulary that did // not arrive fails on the wait. func driveSpanish(t *testing.T, doc, tomorrow string) spanishScreen { t.Helper() pages := map[string]string{"/": doc} rig := harness.New(t, func(string) http.Handler { return sizingMux(t, pages) }) ctx, cancel := context.WithTimeout(rig.Context(), 120*time.Second) defer cancel() mustRun(t, ctx, chromedp.Navigate(rig.Origin+"/"), chromedp.WaitVisible(`[rst-dtp] input[role="combobox"]`, chromedp.ByQuery), chromedp.WaitVisible(`[rst-combo] input[role="combobox"]`, chromedp.ByQuery), chromedp.Click(`[rst-dtp] input[role="combobox"]`, chromedp.ByQuery), chromedp.SendKeys(`[rst-dtp] input[role="combobox"]`, tomorrow, chromedp.ByQuery)) settleUntil(t, ctx, `!!document.querySelector('[rst-dtp] [role="option"].is-active [rst-dtp-label]')`) var got spanishScreen at(t, ctx, `JSON.stringify({ Placeholder: document.querySelector('[rst-combo] input[role="combobox"]').placeholder, Set: document.querySelector('[rst-dtp] [role="option"].is-active [rst-dtp-set]')?.textContent ?? '', Label: document.querySelector('[rst-dtp] [role="option"].is-active [rst-dtp-label]')?.textContent ?? '', Quick: document.querySelector('[rst-dtp] [rst-dtp-quick] [rst-dtp-label]')?.textContent ?? ''})`, &got) if got.Label == "" { t.Errorf("typing %q armed no reading; the vocabulary did not reach the parser", tomorrow) } rig.Screen("body", "the Spanish page after typing "+tomorrow) return got } // TestTableOnlyStringsReachTheScreen: on the table-only page, the // select's filter placeholder is es.json's select-filter, typing // mañana resolves (the vocabulary came from the table's date-words, // an object, not an attribute), the armed reading's set label is // es.json's date-set, and the first quick pick is date-quick-today. func TestTableOnlyStringsReachTheScreen(t *testing.T) { es, want, tomorrow := loadES(t) got := driveSpanish(t, spanishDoc(t, es, ""), tomorrow) if got.Placeholder != want.Filter { t.Errorf("the select's filter placeholder reads %q, want es.json's select-filter %q", got.Placeholder, want.Filter) } if got.Set != want.Set { t.Errorf("the date field's set label reads %q, want es.json's date-set %q", got.Set, want.Set) } if got.Quick != want.Today { t.Errorf("the first quick pick reads %q, want es.json's date-quick-today %q", got.Quick, want.Today) } } // TestAttributeWordsReachTheParser is the other way in: no table on // the page, and es.json's date-words on the input as JSON text, the // form a server-rendered page carries. Typing mañana still resolves, // and every label is the script's English fallback, since the page's // language has no table and nothing else says otherwise. func TestAttributeWordsReachTheParser(t *testing.T) { _, want, tomorrow := loadES(t) got := driveSpanish(t, spanishDoc(t, nil, string(want.Words)), tomorrow) if got.Placeholder != "Type to filter" { t.Errorf("with no table, the select's filter placeholder reads %q, want the fallback", got.Placeholder) } if got.Set != "Set" { t.Errorf("with no table, the date field's set label reads %q, want the fallback", got.Set) } if got.Quick != "Today" { t.Errorf("with no table, the first quick pick reads %q, want the fallback", got.Quick) } }