Skip to content Search Apps Documentation Source Content File Folder Download Copy Actions State String Boolean Number Struct Map Slice Pointer Function Closure Reference Nil Package Type Interface Unknown

Community realm. Read the code first. Community realm, deployed by its author. Read the code before you interact or send coins.

md_test.gno

8.09 Kb · 374 lines
  1package md_test
  2
  3import (
  4	"testing"
  5
  6	"gno.land/p/nym-moultest123/md/v0"
  7)
  8
  9func TestHelpers(t *testing.T) {
 10	tests := []struct {
 11		name     string
 12		function func() string
 13		expected string
 14	}{
 15		{"Bold", func() string { return md.Bold("foo") }, "**foo**"},
 16		{"Italic", func() string { return md.Italic("foo") }, "*foo*"},
 17		{"Strikethrough", func() string { return md.Strikethrough("foo") }, "~~foo~~"},
 18		{"H1", func() string { return md.H1("foo") }, "# foo\n"},
 19		{"HorizontalRule", md.HorizontalRule, "---\n"},
 20		{"InlineCode", func() string { return md.InlineCode("foo") }, "`foo`"},
 21		{"CodeBlock", func() string { return md.CodeBlock("foo") }, "```\nfoo\n```\n"},
 22		{"LanguageCodeBlock", func() string { return md.LanguageCodeBlock("go", "foo") }, "```go\nfoo\n```\n"},
 23		{"Link", func() string { return md.Link("foo", "http://example.com") }, "[foo](http://example.com)"},
 24		{"UserLink", func() string { return md.UserLink("moul") }, "[@moul](/u/moul)"},
 25		{"Image", func() string { return md.Image("foo", "http://example.com") }, "![foo](http://example.com)"},
 26		{"InlineImageWithLink", func() string {
 27			return md.InlineImageWithLink("alt", "http://img.example.com/x.png", "http://link.example.com")
 28		}, "[![alt](http://img.example.com/x.png)](http://link.example.com)"},
 29		{"FootnoteDefinition", func() string { return md.FootnoteDefinition("foo", "bar") }, "[^foo]:\n    bar\n"},
 30		{"LinkReferenceDefinition", func() string {
 31			return md.LinkReferenceDefinition("foo", "http://example.com", "")
 32		}, "\n\n[foo]: http://example.com\n\n"},
 33		{"Paragraph", func() string { return md.Paragraph("foo") }, "foo\n\n"},
 34	}
 35
 36	for _, tt := range tests {
 37		t.Run(tt.name, func(t *testing.T) {
 38			result := tt.function()
 39			if result != tt.expected {
 40				t.Errorf("%s() = %q, want %q", tt.name, result, tt.expected)
 41			}
 42		})
 43	}
 44}
 45
 46func TestLists(t *testing.T) {
 47	t.Run("BulletList", func(t *testing.T) {
 48		items := []string{"foo", "bar"}
 49		expected := "- foo\n- bar\n"
 50		result := md.BulletList(items)
 51		if result != expected {
 52			t.Errorf("BulletList(%q) = %q, want %q", items, result, expected)
 53		}
 54	})
 55
 56	t.Run("OrderedList", func(t *testing.T) {
 57		items := []string{"foo", "bar"}
 58		expected := "1. foo\n2. bar\n"
 59		result := md.OrderedList(items)
 60		if result != expected {
 61			t.Errorf("OrderedList(%q) = %q, want %q", items, result, expected)
 62		}
 63	})
 64
 65	t.Run("TodoList", func(t *testing.T) {
 66		items := []string{"foo", "bar\nmore bar"}
 67		done := []bool{true, false}
 68		expected := "- [x] foo\n- [ ] bar\n  more bar\n"
 69		result := md.TodoList(items, done)
 70		if result != expected {
 71			t.Errorf("TodoList(%q, %q) = %q, want %q", items, done, result, expected)
 72		}
 73	})
 74}
 75
 76func TestUserLink(t *testing.T) {
 77	tests := []struct {
 78		name     string
 79		input    string
 80		expected string
 81	}{
 82		{"username", "moul", "[@moul](/u/moul)"},
 83		// "g1blah" data part is too short for a bech32 address (min 6
 84		// chars after "1"); UserLink validates as a username instead.
 85		{"short g1-prefixed string treated as username", "g1blah", "[@g1blah](/u/g1blah)"},
 86		// "user_name" is a valid username (charset includes _ and -);
 87		// the validator returns it verbatim, so no markdown escape of _.
 88		{"username with underscore", "user_name", "[@user_name](/u/user_name)"},
 89		// "g1abc123" has a 6-char data part — valid bech32 shape.
 90		{"address with 6-char data", "g1abc123", "[g1abc123](/u/g1abc123)"},
 91		// invalid identifier (spaces, uppercase, etc.) → empty.
 92		{"rejected: spaces", "hello world", ""},
 93		{"rejected: uppercase first char", "Alice", ""},
 94	}
 95
 96	for _, tt := range tests {
 97		t.Run(tt.name, func(t *testing.T) {
 98			result := md.UserLink(tt.input)
 99			if result != tt.expected {
100				t.Errorf("UserLink(%q) = %q, want %q", tt.input, result, tt.expected)
101			}
102		})
103	}
104}
105
106func TestNested(t *testing.T) {
107	t.Run("Nested Single Level", func(t *testing.T) {
108		content := "- foo\n- bar"
109		expected := "  - foo\n  - bar"
110		result := md.Nested(content, "  ")
111		if result != expected {
112			t.Errorf("Nested(%q) = %q, want %q", content, result, expected)
113		}
114	})
115
116	t.Run("Nested Double Level", func(t *testing.T) {
117		content := "  - foo\n  - bar"
118		expected := "    - foo\n    - bar"
119		result := md.Nested(content, "  ")
120		if result != expected {
121			t.Errorf("Nested(%q) = %q, want %q", content, result, expected)
122		}
123	})
124}
125
126func TestColumns(t *testing.T) {
127	tests := []struct {
128		name     string
129		input    []string
130		padded   bool
131		expected string
132	}{
133		{
134			name:     "no columns",
135			input:    []string{},
136			padded:   false,
137			expected: "",
138		},
139		{
140			name:     "no columns padded",
141			input:    []string{},
142			padded:   true,
143			expected: "",
144		},
145		{
146			name:   "one column",
147			input:  []string{"Column 1"},
148			padded: false,
149			expected: `<gno-columns>
150Column 1
151</gno-columns>
152`,
153		},
154		{
155			name:   "one column padded",
156			input:  []string{"Column 1"},
157			padded: true,
158			expected: `<gno-columns>
159Column 1
160<gno-columns-sep>
161
162<gno-columns-sep>
163
164<gno-columns-sep>
165
166</gno-columns>
167`,
168		},
169		{
170			name:   "two columns",
171			input:  []string{"Column 1", "Column 2"},
172			padded: false,
173			expected: `<gno-columns>
174Column 1
175<gno-columns-sep>
176Column 2
177</gno-columns>
178`,
179		},
180		{
181			name:   "two columns padded",
182			input:  []string{"Column 1", "Column 2"},
183			padded: true,
184			expected: `<gno-columns>
185Column 1
186<gno-columns-sep>
187Column 2
188<gno-columns-sep>
189
190<gno-columns-sep>
191
192</gno-columns>
193`,
194		},
195		{
196			name:   "four columns",
197			input:  []string{"A", "B", "C", "D"},
198			padded: false,
199			expected: `<gno-columns>
200A
201<gno-columns-sep>
202B
203<gno-columns-sep>
204C
205<gno-columns-sep>
206D
207</gno-columns>
208`,
209		},
210		{
211			name:   "four columns padded",
212			input:  []string{"A", "B", "C", "D"},
213			padded: true,
214			expected: `<gno-columns>
215A
216<gno-columns-sep>
217B
218<gno-columns-sep>
219C
220<gno-columns-sep>
221D
222</gno-columns>
223`,
224		},
225		{
226			name:   "more than four columns",
227			input:  []string{"1", "2", "3", "4", "5"},
228			padded: false,
229			expected: `<gno-columns>
2301
231<gno-columns-sep>
2322
233<gno-columns-sep>
2343
235<gno-columns-sep>
2364
237<gno-columns-sep>
2385
239</gno-columns>
240`,
241		},
242		{
243			name:   "more than four columns padded",
244			input:  []string{"1", "2", "3", "4", "5"},
245			padded: true,
246			expected: `<gno-columns>
2471
248<gno-columns-sep>
2492
250<gno-columns-sep>
2513
252<gno-columns-sep>
2534
254<gno-columns-sep>
2555
256<gno-columns-sep>
257
258<gno-columns-sep>
259
260<gno-columns-sep>
261
262</gno-columns>
263`,
264		},
265	}
266
267	for _, tt := range tests {
268		t.Run(tt.name, func(t *testing.T) {
269			result := md.Columns(tt.input, tt.padded)
270			if result != tt.expected {
271				t.Errorf("Columns(%v, %v) =\n%q\nwant:\n%q", tt.input, tt.padded, result, tt.expected)
272			}
273		})
274	}
275}
276
277func TestColumnsN(t *testing.T) {
278	tests := []struct {
279		name       string
280		content    []string
281		colsPerRow int
282		padded     bool
283		expected   string
284	}{
285		{
286			name:       "empty input",
287			content:    []string{},
288			colsPerRow: 2,
289			padded:     false,
290			expected:   "",
291		},
292		{
293			name:       "colsPerRow <= 0",
294			content:    []string{"A", "B", "C"},
295			colsPerRow: 0,
296			padded:     false,
297			expected: `<gno-columns>
298A
299<gno-columns-sep>
300B
301<gno-columns-sep>
302C
303</gno-columns>
304`,
305		},
306		{
307			name:       "exact full row, no padding",
308			content:    []string{"A", "B"},
309			colsPerRow: 2,
310			padded:     false,
311			expected: `<gno-columns>
312A
313<gno-columns-sep>
314B
315</gno-columns>
316`,
317		},
318		{
319			name:       "partial last row, no padding",
320			content:    []string{"A", "B", "C"},
321			colsPerRow: 2,
322			padded:     false,
323			expected: `<gno-columns>
324A
325<gno-columns-sep>
326B
327</gno-columns>
328<gno-columns>
329C
330</gno-columns>
331`,
332		},
333		{
334			name:       "partial last row, with padding",
335			content:    []string{"A", "B", "C"},
336			colsPerRow: 2,
337			padded:     true,
338			expected: `<gno-columns>
339A
340<gno-columns-sep>
341B
342</gno-columns>
343<gno-columns>
344C
345<gno-columns-sep>
346
347</gno-columns>
348`,
349		},
350		{
351			name:       "padded with more empty cells",
352			content:    []string{"X"},
353			colsPerRow: 3,
354			padded:     true,
355			expected: `<gno-columns>
356X
357<gno-columns-sep>
358
359<gno-columns-sep>
360
361</gno-columns>
362`,
363		},
364	}
365
366	for _, tt := range tests {
367		t.Run(tt.name, func(t *testing.T) {
368			result := md.ColumnsN(tt.content, tt.colsPerRow, tt.padded)
369			if result != tt.expected {
370				t.Errorf("ColumnsN(%v, %d, %v) =\n%q\nwant:\n%q", tt.content, tt.colsPerRow, tt.padded, result, tt.expected)
371			}
372		})
373	}
374}