github.com/charmbracelet/glamour@v0.7.0/glamour_test.go (about) 1 package glamour 2 3 import ( 4 "bytes" 5 "errors" 6 "io" 7 "os" 8 "strings" 9 "testing" 10 ) 11 12 const ( 13 generate = false 14 markdown = "testdata/readme.markdown.in" 15 testFile = "testdata/readme.test" 16 ) 17 18 func TestTermRendererWriter(t *testing.T) { 19 r, err := NewTermRenderer( 20 WithStandardStyle(DarkStyle), 21 ) 22 if err != nil { 23 t.Fatal(err) 24 } 25 26 in, err := os.ReadFile(markdown) 27 if err != nil { 28 t.Fatal(err) 29 } 30 31 _, err = r.Write(in) 32 if err != nil { 33 t.Fatal(err) 34 } 35 err = r.Close() 36 if err != nil { 37 t.Fatal(err) 38 } 39 40 b, err := io.ReadAll(r) 41 if err != nil { 42 t.Fatal(err) 43 } 44 45 // generate 46 if generate { 47 err := os.WriteFile(testFile, b, 0o644) 48 if err != nil { 49 t.Fatal(err) 50 } 51 return 52 } 53 54 // verify 55 td, err := os.ReadFile(testFile) 56 if err != nil { 57 t.Fatal(err) 58 } 59 60 if !bytes.Equal(td, b) { 61 t.Errorf("Rendered output doesn't match!\nExpected: `\n%s`\nGot: `\n%s`\n", 62 string(td), b) 63 } 64 } 65 66 func TestTermRenderer(t *testing.T) { 67 r, err := NewTermRenderer( 68 WithStandardStyle("dark"), 69 ) 70 if err != nil { 71 t.Fatal(err) 72 } 73 74 in, err := os.ReadFile(markdown) 75 if err != nil { 76 t.Fatal(err) 77 } 78 79 b, err := r.Render(string(in)) 80 if err != nil { 81 t.Fatal(err) 82 } 83 84 // verify 85 td, err := os.ReadFile(testFile) 86 if err != nil { 87 t.Fatal(err) 88 } 89 90 if !bytes.Equal(td, []byte(b)) { 91 t.Errorf("Rendered output doesn't match!\nExpected: `\n%s`\nGot: `\n%s`\n", 92 string(td), b) 93 } 94 } 95 96 func TestWithEmoji(t *testing.T) { 97 r, err := NewTermRenderer( 98 WithEmoji(), 99 ) 100 if err != nil { 101 t.Fatal(err) 102 } 103 104 b, err := r.Render(":+1:") 105 if err != nil { 106 t.Fatal(err) 107 } 108 b = strings.TrimSpace(b) 109 110 // Thumbs up unicode character 111 td := "\U0001f44d" 112 113 if td != b { 114 t.Errorf("Rendered output doesn't match!\nExpected: `\n%s`\nGot: `\n%s`\n", td, b) 115 } 116 } 117 118 func TestWithPreservedNewLines(t *testing.T) { 119 r, err := NewTermRenderer( 120 WithPreservedNewLines(), 121 ) 122 if err != nil { 123 t.Fatal(err) 124 } 125 126 in, err := os.ReadFile("testdata/preserved_newline.in") 127 if err != nil { 128 t.Fatal(err) 129 } 130 131 b, err := r.Render(string(in)) 132 if err != nil { 133 t.Fatal(err) 134 } 135 136 // verify 137 td, err := os.ReadFile("testdata/preserved_newline.test") 138 if err != nil { 139 t.Fatal(err) 140 } 141 142 if !bytes.Equal(td, []byte(b)) { 143 t.Errorf("Rendered output doesn't match!\nExpected: `\n%s`\nGot: `\n%s`\n", 144 string(td), b) 145 } 146 } 147 148 func TestStyles(t *testing.T) { 149 _, err := NewTermRenderer( 150 WithAutoStyle(), 151 ) 152 if err != nil { 153 t.Fatal(err) 154 } 155 156 _, err = NewTermRenderer( 157 WithStandardStyle(AutoStyle), 158 ) 159 if err != nil { 160 t.Fatal(err) 161 } 162 163 _, err = NewTermRenderer( 164 WithEnvironmentConfig(), 165 ) 166 if err != nil { 167 t.Fatal(err) 168 } 169 } 170 171 // TestCustomStyle checks the expected errors with custom styling. We need to 172 // support built-in styles and custom style sheets. 173 func TestCustomStyle(t *testing.T) { 174 md := "testdata/example.md" 175 tests := []struct { 176 name string 177 stylePath string 178 err error 179 expected string 180 }{ 181 {name: "style exists", stylePath: "testdata/custom.style", err: nil, expected: "testdata/custom.style"}, 182 {name: "style doesn't exist", stylePath: "testdata/notfound.style", err: os.ErrNotExist, expected: AutoStyle}, 183 {name: "style is empty", stylePath: "", err: nil, expected: AutoStyle}, 184 } 185 186 for _, tc := range tests { 187 t.Run(tc.name, func(t *testing.T) { 188 t.Setenv("GLAMOUR_STYLE", tc.stylePath) 189 g, err := NewTermRenderer( 190 WithEnvironmentConfig(), 191 ) 192 if !errors.Is(err, tc.err) { 193 t.Fatal(err) 194 } 195 if !errors.Is(tc.err, os.ErrNotExist) { 196 w, err := NewTermRenderer(WithStylePath(tc.expected)) 197 if err != nil { 198 t.Fatal(err) 199 } 200 text, _ := os.ReadFile(md) 201 want, err := w.RenderBytes(text) 202 got, err := g.RenderBytes(text) 203 if !bytes.Equal(want, got) { 204 t.Error("Wrong style used") 205 } 206 } 207 }) 208 } 209 } 210 211 func TestRenderHelpers(t *testing.T) { 212 in, err := os.ReadFile(markdown) 213 if err != nil { 214 t.Fatal(err) 215 } 216 217 b, err := Render(string(in), "dark") 218 if err != nil { 219 t.Error(err) 220 } 221 222 // verify 223 td, err := os.ReadFile(testFile) 224 if err != nil { 225 t.Fatal(err) 226 } 227 228 if b != string(td) { 229 t.Errorf("Rendered output doesn't match!\nExpected: `\n%s`\nGot: `\n%s`\n", 230 string(td), b) 231 } 232 } 233 234 func TestCapitalization(t *testing.T) { 235 p := true 236 style := DarkStyleConfig 237 style.H1.Upper = &p 238 style.H2.Title = &p 239 style.H3.Lower = &p 240 241 r, err := NewTermRenderer( 242 WithStyles(style), 243 ) 244 if err != nil { 245 t.Fatal(err) 246 } 247 248 b, err := r.Render("# everything is uppercase\n## everything is titled\n### everything is lowercase") 249 if err != nil { 250 t.Fatal(err) 251 } 252 253 // expected outcome 254 td, err := os.ReadFile("testdata/capitalization.test") 255 if err != nil { 256 t.Fatal(err) 257 } 258 259 if string(td) != b { 260 t.Errorf("Rendered output doesn't match!\nExpected: `\n%s`\nGot: `\n%s`\n", td, b) 261 } 262 }