oficina / slides Public

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

Plain git — no account needed to clone.

Download

Download this file

1package core_test
2
3import (
4 "os"
5 "path/filepath"
6 "strings"
7 "testing"
8
9 "amadan.net/oficina/slides/internal/slides/core"
10)
11
12// TestCheckPassesWhatTheOpsWrite: a document the core's own ops built
13// is within the §2.6 vocabulary, and Check says so with nil.
14func TestCheckPassesWhatTheOpsWrite(t *testing.T) {
15 ctx, rt := newRuntime(t)
16 h := newDoc(t, ctx, rt, "check-ops", 1)
17 if _, err := h.Ops(ctx, []byte(addSlide)); err != nil {
18 t.Fatalf("Ops: %v", err)
19 }
20 if err := h.Check(ctx); err != nil {
21 t.Errorf("Check on an ops-built document: %v", err)
22 }
23 // And on an empty one.
24 empty := newDoc(t, ctx, rt, "check-empty", 1)
25 if err := empty.Check(ctx); err != nil {
26 t.Errorf("Check on an empty document: %v", err)
27 }
28}
29
30// TestCheckRefusesAnUnknownMark: the update fixtures/poison.mjs writes
31// with a run under `unknown_mark` applies cleanly — the CRDT has no
32// opinion — and Check comes back as a RejectedError naming the block
33// and the attribute, while the view still reads the words. That gap is
34// the whole of codex 3.
35func TestCheckRefusesAnUnknownMark(t *testing.T) {
36 ctx, rt := newRuntime(t)
37 update, err := os.ReadFile(filepath.Join("..", "..", "slidestest", "testdata", "poison", "unknownmark.yjs"))
38 if err != nil {
39 t.Fatalf("read the unknownmark poison update (run node fixtures/poison.mjs): %v", err)
40 }
41 h := newDoc(t, ctx, rt, "check-poison", 1)
42 if err := h.Apply(ctx, update); err != nil {
43 t.Fatalf("Apply: %v", err)
44 }
45 view, err := h.JSON(ctx)
46 if err != nil {
47 t.Fatalf("JSON: %v", err)
48 }
49 if !strings.Contains(string(view), `"keep these words"`) {
50 t.Errorf("the view lost the words the projection is supposed to tolerate: %s", view)
51 }
52 err = h.Check(ctx)
53 if err == nil {
54 t.Fatal("Check accepted a run under an unknown formatting attribute")
55 }
56 if !core.Rejected(err) {
57 t.Errorf("Check's finding is not a RejectedError: %T %v", err, err)
58 }
59 want := `slide "poisonmrksld" block "poisonmrkblk" text: paragraph 0 carries the formatting attribute "unknown_mark", which is not one of b, i, c, h, href`
60 if err.Error() != want {
61 t.Errorf("Check message:\n got %q\nwant %q", err.Error(), want)
62 }
63 // The check only reads: the handle is as usable as before.
64 if _, err := h.Ops(ctx, []byte(addSlide)); err != nil {
65 t.Errorf("Ops after a Check finding: %v", err)
66 }
67}
68
69// TestVectorsPassTheCheck: every committed vector is a document the
70// wire would accept. fixtures/generate.mjs asserts the same through
71// check.mjs when it writes them, so this is the two implementations
72// agreeing on the fixtures they share.
73func TestVectorsPassTheCheck(t *testing.T) {
74 ctx, rt := newRuntime(t)
75 for _, name := range vectorNames(t) {
76 t.Run(name, func(t *testing.T) {
77 update, err := os.ReadFile(filepath.Join(vectorsDir, name+".yjs"))
78 if err != nil {
79 t.Fatalf("read update: %v", err)
80 }
81 h := newDoc(t, ctx, rt, name, 1)
82 if err := h.Apply(ctx, update); err != nil {
83 t.Fatalf("Apply: %v", err)
84 }
85 if err := h.Check(ctx); err != nil {
86 t.Errorf("Check: %v", err)
87 }
88 })
89 }
90}
91