rename packages, refactor out tailwind compiler,
This commit is contained in:
@@ -490,3 +490,115 @@ func TestEditingJumpsToTheRightForm(t *testing.T) {
|
||||
t.Error("reset did not return the editor to a clean chooser")
|
||||
}
|
||||
}
|
||||
|
||||
// ---- the function insert menu ----
|
||||
|
||||
// Thirty-five function names in one flat list is a wall. Grouped by what they are FOR,
|
||||
// with a signature and a sentence, it is something you can find SUM in.
|
||||
func TestFormulaFunctionGroups(t *testing.T) {
|
||||
want := []string{"Aggregate", "Math", "Trigonometry", "Logic", "Row"}
|
||||
if len(FormulaFunctionGroups) != len(want) {
|
||||
t.Fatalf("got %d groups, want %d", len(FormulaFunctionGroups), len(want))
|
||||
}
|
||||
for i, label := range want {
|
||||
if FormulaFunctionGroups[i].Label != label {
|
||||
t.Errorf("group %d is %q, want %q", i, FormulaFunctionGroups[i].Label, label)
|
||||
}
|
||||
}
|
||||
|
||||
// Every function carries a signature and a description — they are what the menu
|
||||
// shows and what its search matches, not decoration.
|
||||
for _, g := range FormulaFunctionGroups {
|
||||
for _, f := range g.Fns {
|
||||
if f.Name == "" || f.Sig == "" || f.Desc == "" {
|
||||
t.Errorf("%s/%s is missing its signature or description: %+v", g.Label, f.Name, f)
|
||||
}
|
||||
if !strings.HasPrefix(f.Sig, f.Name+"(") {
|
||||
t.Errorf("%s's signature %q does not start with its own name", f.Name, f.Sig)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Every function the menu offers must actually EXIST in the engine — an insert menu
|
||||
// that offers a function the evaluator rejects is worse than no menu.
|
||||
func TestEveryOfferedFunctionEvaluates(t *testing.T) {
|
||||
// A formula per function, using its own arity.
|
||||
args := map[string]string{
|
||||
"IF": "IF(1, 2, 3)", "ATAN2": "ATAN2(1, 1)", "POWER": "POWER(2, 3)",
|
||||
"MOD": "MOD(5, 2)", "LOG": "LOG(100, 10)", "ROUND": "ROUND(1.5, 0)",
|
||||
"ROW": "ROW()", "PI": "PI()", "AND": "AND(1, 1)", "OR": "OR(1, 0)", "NOT": "NOT(0)",
|
||||
}
|
||||
for _, g := range FormulaFunctionGroups {
|
||||
for _, f := range g.Fns {
|
||||
src, ok := args[f.Name]
|
||||
if !ok {
|
||||
src = f.Name + "(1)"
|
||||
}
|
||||
if _, err := CompileFormula(src); err != nil {
|
||||
t.Errorf("the menu offers %s, but %q does not compile: %v", f.Name, src, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// And every constant it offers must be one the evaluator knows.
|
||||
func TestEveryOfferedConstantExists(t *testing.T) {
|
||||
if len(FormulaConstantOptions) != len(FormulaConstants) {
|
||||
t.Errorf("the menu offers %d constants, the engine knows %d",
|
||||
len(FormulaConstantOptions), len(FormulaConstants))
|
||||
}
|
||||
for _, c := range FormulaConstantOptions {
|
||||
if _, ok := FormulaConstants[c.Name]; !ok {
|
||||
t.Errorf("the menu offers %q, which the engine does not know", c.Name)
|
||||
}
|
||||
if c.Desc == "" {
|
||||
t.Errorf("%q has no description — the name alone says nothing", c.Name)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// The menu's search matches the DESCRIPTION too, which is the whole point of carrying
|
||||
// the prose around: someone who wants a total types "total", not "SUM".
|
||||
func TestFormulaMenuSearch(t *testing.T) {
|
||||
got := filterFormulaGroups("total")
|
||||
found := false
|
||||
for _, g := range got {
|
||||
for _, f := range g.Fns {
|
||||
if f.Name == "SUM" {
|
||||
found = true
|
||||
}
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
t.Error(`searching "total" did not find SUM — the description is not being matched`)
|
||||
}
|
||||
|
||||
// Empty groups drop out rather than leaving a bare heading behind.
|
||||
for _, g := range filterFormulaGroups("sine") {
|
||||
if len(g.Fns) == 0 {
|
||||
t.Errorf("group %q survived the filter with no functions in it", g.Label)
|
||||
}
|
||||
}
|
||||
|
||||
// An empty query is everything.
|
||||
if len(filterFormulaGroups("")) != len(FormulaFunctionGroups) {
|
||||
t.Error("an empty query should show every group")
|
||||
}
|
||||
// A query matching nothing yields nothing (the menu shows its own empty state).
|
||||
if got := filterFormulaGroups("zzzz"); len(got) != 0 {
|
||||
t.Errorf("a query matching nothing returned %d groups", len(got))
|
||||
}
|
||||
}
|
||||
|
||||
func TestFormulaFunctionNamesFlattensTheGroups(t *testing.T) {
|
||||
names := FormulaFunctionNames()
|
||||
if len(names) < 30 {
|
||||
t.Errorf("flattened to %d names, want the full set", len(names))
|
||||
}
|
||||
for _, want := range []string{"SUM", "ROUND", "ATAN2", "IF", "ROW"} {
|
||||
if !contains2(names, want) {
|
||||
t.Errorf("%s missing from the flattened names", want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user