oficina / sheets Public

Clone
git clone https://amadan.net/oficina/sheets

Plain git — no account needed to clone.

Download

Download this file

1//go:build browser
2
3package sheets
4
5import (
6 "context"
7 "fmt"
8 "net/http"
9 "testing"
10 "time"
11
12 "amadan.net/rastrillo/rastrillo/harness"
13 "github.com/chromedp/cdproto/network"
14 "github.com/chromedp/chromedp"
15)
16
17// TestDocumentStylesSurviveTheProductionCSP: Sheets in Chromium behind
18// the production serving stack (productionHandler: rastrillo's security
19// headers and Sheets' CSP), standalone. A filled cell and an inked cell
20// in the scriptless table view paint differently from a plain one, the
21// table scrolls sideways in its wrapper, and the grid's Format palette
22// swatches carry their colours.
23//
24// Every one of those is a style attribute. Under rastrillo fb806a2's
25// default style-src the browser drops them all — the cell turns
26// transparent on black, the swatch loses --sheet-h, the wrapper stops
27// scrolling — while the other browser checks, which serve app.Router()
28// with no CSP at all, stay green (Astra on #46).
29func TestDocumentStylesSurviveTheProductionCSP(t *testing.T) {
30 app, cookies := signIn(t)
31 s, cells := newSheet(t, app, cookies, "Painted")
32 postCell(t, app, cookies, cells, `{"r":0,"c":0,"raw":"filled"}`)
33 postCell(t, app, cookies, cells, `{"r":0,"c":1,"raw":"inked"}`)
34 postCell(t, app, cookies, cells, `{"r":0,"c":2,"raw":"plain"}`)
35 postFormatForm(t, app, cookies, s, map[string]string{"r1": "0", "c1": "0", "r2": "0", "c2": "0", "fill": "red", "page": "1"})
36 postFormatForm(t, app, cookies, s, map[string]string{"r1": "0", "c1": "1", "r2": "0", "c2": "1", "ink": "blue", "page": "1"})
37
38 rig := harness.New(t, func(string) http.Handler { return productionHandler(t, app) })
39 run := func(what string, actions ...chromedp.Action) {
40 t.Helper()
41 ctx, cancel := context.WithTimeout(rig.Context(), 20*time.Second)
42 defer cancel()
43 if err := chromedp.Run(ctx, actions...); err != nil {
44 t.Fatalf("%s: %v", what, err)
45 }
46 }
47 var set []chromedp.Action
48 for _, c := range cookies {
49 set = append(set, network.SetCookie(c.Name, c.Value).WithURL(rig.Origin+"/").
50 WithHTTPOnly(c.HttpOnly).WithSecure(c.Secure).WithSameSite(network.CookieSameSiteLax))
51 }
52 run("sign in", set...)
53
54 var table struct {
55 FilledBg, PlainBg, InkedInk, PlainInk, Overflow string
56 }
57 run("table view",
58 chromedp.Navigate(fmt.Sprintf("%s/sheets/%d/table", rig.Origin, s.ID)),
59 chromedp.WaitVisible(`table[data-cell-table]`),
60 chromedp.Evaluate(`(() => {
61 const cell = (x) => [...document.querySelectorAll('table[data-cell-table] tbody td')].find(td => td.textContent.trim() === x);
62 const cs = (x) => getComputedStyle(cell(x));
63 return {
64 FilledBg: cs('filled').backgroundColor,
65 PlainBg: cs('plain').backgroundColor,
66 InkedInk: cs('inked').color,
67 PlainInk: cs('plain').color,
68 Overflow: getComputedStyle(document.querySelector('table[data-cell-table]').parentElement).overflowX,
69 };
70 })()`, &table),
71 )
72 if table.FilledBg == table.PlainBg {
73 t.Errorf("a red-filled cell paints %s, the same as a plain one: its style attribute was refused", table.FilledBg)
74 }
75 if table.InkedInk == table.PlainInk {
76 t.Errorf("a blue-inked cell paints %s text, the same as a plain one: its style attribute was refused", table.InkedInk)
77 }
78 if table.Overflow != "auto" {
79 t.Errorf("the table's wrapper has overflow-x %q, want auto: wide sheets cannot scroll", table.Overflow)
80 }
81
82 var swatch string
83 run("grid palette",
84 chromedp.Navigate(fmt.Sprintf("%s/sheets/%d", rig.Origin, s.ID)),
85 chromedp.WaitVisible(`td[data-x="0"][data-y="0"]`),
86 chromedp.Evaluate(`getComputedStyle(document.querySelector('[data-swatch][data-value="red"]')).getPropertyValue('--sheet-h').trim()`, &swatch),
87 )
88 if swatch == "" {
89 t.Error("the Fill palette's red swatch has no --sheet-h: its style attribute was refused")
90 }
91}
92