Add fonts, autotable, autotable examples

This commit is contained in:
2026-07-13 13:01:26 -04:00
parent ea3d2a6d03
commit cf8342f8d4
71 changed files with 16084 additions and 1443 deletions

View File

@@ -0,0 +1,81 @@
package webui
import (
"strings"
"testing"
)
// What a table renders on the SERVER, in each of the three shapes. The distinction
// exists because a saved layout lives in localStorage, which the server cannot read:
//
// - no persistence -> nothing can arrive late. Render in full. (default)
// - persistence -> a skeleton, until the client says what the layout is.
// - persistence + ShowWhile.. -> render the DECLARED table at once, and accept that
// the client may rearrange it (the flash).
func ssrTable(t *testing.T, cols AutoTableColumnOptions) string {
t.Helper()
s := NewAutoTableState([]AutoTableColumn{
{Key: "name", DisplayName: "Client", SortIdentifier: "Name"},
}, AutoTableStateOptions{Columns: cols})
s.SetRows([]any{calcRec{"Ada", "100", "40"}})
return renderNode(s.Render())
}
// A plain, static table — no personalisation — must server-render its CONTENT. This
// is the common case and it must not pay for a feature it does not use.
func TestStaticTableServerRendersInFull(t *testing.T) {
html := ssrTable(t, AutoTableColumnOptions{})
if !strings.Contains(html, "Client") {
t.Errorf("a table with no persistence must SSR its content:\n%s", html)
}
if strings.Contains(html, `aria-busy="true"`) {
t.Error("a table with no persistence rendered a skeleton — it has nothing to wait for")
}
}
// Turn persistence on and the server no longer knows the layout, so it holds a
// skeleton rather than showing a table that is about to rearrange itself.
func TestPersistedTableHoldsASkeletonUntilTheLayoutSettles(t *testing.T) {
html := ssrTable(t, AutoTableColumnOptions{StorageKey: "k"})
if !strings.Contains(html, `aria-busy="true"`) {
t.Errorf("a persisted table should hold a skeleton on the server:\n%s", html)
}
if strings.Contains(html, "Client") {
t.Error("it rendered table content — a user with a saved layout would watch it rearrange")
}
}
// ...unless the caller says it would rather have the content and accept the flash.
func TestShowWhileRestoringServerRendersInFull(t *testing.T) {
html := ssrTable(t, AutoTableColumnOptions{StorageKey: "k", ShowWhileRestoring: true})
if !strings.Contains(html, "Client") {
t.Errorf("ShowWhileRestoring must SSR the declared table:\n%s", html)
}
if strings.Contains(html, `aria-busy="true"`) {
t.Error("ShowWhileRestoring rendered a skeleton anyway")
}
}
// And once the layout has settled, a persisted table renders normally.
func TestPersistedTableRevealsAfterRestore(t *testing.T) {
s := NewAutoTableState([]AutoTableColumn{
{Key: "name", DisplayName: "Client", SortIdentifier: "Name"},
}, AutoTableStateOptions{Columns: AutoTableColumnOptions{StorageKey: "k"}})
s.SetRows([]any{calcRec{"Ada", "100", "40"}})
if s.LayoutSettled() {
t.Fatal("a persisted table should not start settled")
}
s.RestoreLayout() // nothing to restore here; it just settles
if !s.LayoutSettled() {
t.Fatal("RestoreLayout did not settle the layout")
}
if html := renderNode(s.Render()); !strings.Contains(html, "Client") {
t.Errorf("the table did not reveal after restore:\n%s", html)
}
}