-
Notifications
You must be signed in to change notification settings - Fork 0
/
flush_test.go
126 lines (110 loc) · 3.03 KB
/
flush_test.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
package templ
import (
"context"
"fmt"
"io"
"strings"
"testing"
)
type flushableErrorWriter struct {
lastFlushPos int
pos int
sb strings.Builder
flushedSections []string
}
func (f *flushableErrorWriter) Write(p []byte) (n int, err error) {
n, err = f.sb.Write(p)
if err != nil {
return
}
if n < len(p) {
err = io.ErrShortWrite
}
f.pos += n
return
}
func (f *flushableErrorWriter) Flush() error {
f.flushedSections = append(f.flushedSections, f.sb.String()[f.lastFlushPos:f.pos])
f.lastFlushPos = f.pos
return nil
}
type flushableWriter struct {
lastFlushPos int
pos int
sb strings.Builder
flushedSections []string
}
func (f *flushableWriter) Write(p []byte) (n int, err error) {
n, err = f.sb.Write(p)
if err != nil {
return
}
if n < len(p) {
err = io.ErrShortWrite
}
f.pos += n
return
}
func (f *flushableWriter) Flush() {
f.flushedSections = append(f.flushedSections, f.sb.String()[f.lastFlushPos:f.pos])
f.lastFlushPos = f.pos
}
func TestFlush(t *testing.T) {
t.Run("errors in child components are propagated", func(t *testing.T) {
expectedErr := fmt.Errorf("test error")
child := ComponentFunc(func(ctx context.Context, w io.Writer) error {
return expectedErr
})
sb := new(strings.Builder)
ctx := WithChildren(context.Background(), child)
err := Flush().Render(ctx, sb)
if err == nil {
t.Fatalf("expected an error, got nil")
}
if err != expectedErr {
t.Fatalf("expected error to be %v, got %v", expectedErr, err)
}
})
t.Run("can render to a flushable error writer", func(t *testing.T) {
child := ComponentFunc(func(ctx context.Context, w io.Writer) error {
_, err := w.Write([]byte("hello"))
return err
})
b := &flushableErrorWriter{}
ctx := WithChildren(context.Background(), child)
// Render the FlushComponent to the buffer
if err := Flush().Render(ctx, b); err != nil {
t.Fatalf("unexpected error: %v", err)
}
if len(b.flushedSections) != 1 {
t.Fatalf("expected 1 flushed section, got %d", len(b.flushedSections))
}
if b.flushedSections[0] != "hello" {
t.Fatalf("expected flushed section to be 'hello', got %q", b.flushedSections[0])
}
})
t.Run("can render to a flushable writer", func(t *testing.T) {
child := ComponentFunc(func(ctx context.Context, w io.Writer) error {
_, err := w.Write([]byte("hello"))
return err
})
b := &flushableWriter{}
ctx := WithChildren(context.Background(), child)
// Render the FlushComponent to the buffer
if err := Flush().Render(ctx, b); err != nil {
t.Fatalf("unexpected error: %v", err)
}
if len(b.flushedSections) != 1 {
t.Fatalf("expected 1 flushed section, got %d", len(b.flushedSections))
}
if b.flushedSections[0] != "hello" {
t.Fatalf("expected flushed section to be 'hello', got %q", b.flushedSections[0])
}
})
t.Run("non-flushable streams are a no-op", func(t *testing.T) {
sb := new(strings.Builder)
if err := Flush().Render(context.Background(), sb); err != nil {
t.Fatalf("expected no error, got %v", err)
}
})
}