aboutsummaryrefslogblamecommitdiff
path: root/telegram/formatter/formatter_test.go
blob: 187d486ea0632f6ef9e964b2deaaf880095bfdcc (plain) (tree)
1
2
3
4
5
6
7
8
9




                 
                                            


                                     
                                                                                











                                                                   
                              


















                                                               
                              





















                                                                 
                              
                                                     




                                                                        


                                      
         
                              






                                                                                      


                                      
         


                                       









                                                                              


                                      
         


                                       









                                                                            


                                      
         


                                       









                                                                      
                             







                                                                                


                                      




























































                                                                                  

                                            
                                                                               











                                                                   
                             


















                                                               
                             





















                                                                 
                             
                                                   


                                                                        

















                                                                                                                                                                                                                                  
                             


























                                                                                                                                                                                                             
                             


























                                                                          
                             



                                                                     












                                                                                                           
                             



                                                                                              







                                                                         
                              











                                                                         
                             



                                                                      

                                  
                                           













                                                                     
                                           













                                                                     
                                           













                                                                     
                                           


















                                                                     
                                              











                                                                     











































































































                                                                            
package formatter

import (
	"testing"

	"github.com/zelenin/go-tdlib/client"
)

func TestNoFormatting(t *testing.T) {
	markup := Format("abc\ndef", []*client.TextEntity{}, MarkupModeMarkdown)
	if markup != "abc\ndef" {
		t.Errorf("No formatting expected, but: %v", markup)
	}
}

func TestFormattingSimple(t *testing.T) {
	markup := Format("👙🐧🐖", []*client.TextEntity{
		&client.TextEntity{
			Offset: 2,
			Length: 4,
			Type:   &client.TextEntityTypeBold{},
		},
	}, MarkupModeMarkdown)
	if markup != "👙**🐧🐖**" {
		t.Errorf("Wrong simple formatting: %v", markup)
	}
}

func TestFormattingAdjacent(t *testing.T) {
	markup := Format("a👙🐧🐖", []*client.TextEntity{
		&client.TextEntity{
			Offset: 3,
			Length: 2,
			Type:   &client.TextEntityTypeItalic{},
		},
		&client.TextEntity{
			Offset: 5,
			Length: 2,
			Type: &client.TextEntityTypeTextUrl{
				Url: "https://narayana.im/",
			},
		},
	}, MarkupModeMarkdown)
	if markup != "a👙_🐧_[🐖](https://narayana.im/)" {
		t.Errorf("Wrong adjacent formatting: %v", markup)
	}
}

func TestFormattingAdjacentAndNested(t *testing.T) {
	markup := Format("👙🐧🐖", []*client.TextEntity{
		&client.TextEntity{
			Offset: 0,
			Length: 4,
			Type:   &client.TextEntityTypePre{},
		},
		&client.TextEntity{
			Offset: 0,
			Length: 2,
			Type:   &client.TextEntityTypeBold{},
		},
		&client.TextEntity{
			Offset: 4,
			Length: 2,
			Type:   &client.TextEntityTypeItalic{},
		},
	}, MarkupModeMarkdown)
	if markup != "```\n**👙**🐧\n```_🐖_" {
		t.Errorf("Wrong adjacent&nested formatting: %v", markup)
	}
}

func TestRebalanceTwoZero(t *testing.T) {
	s1 := insertionStack{
		&insertion{Offset: 7},
		&insertion{Offset: 8},
	}
	s2 := insertionStack{}
	s1, s2 = s1.rebalance(s2, 7)
	if !(len(s1) == 2 && len(s2) == 0 && s1[0].Offset == 7 && s1[1].Offset == 8) {
		t.Errorf("Wrong rebalance 2–0: %#v %#v", s1, s2)
	}
}

func TestRebalanceNeeded(t *testing.T) {
	s1 := insertionStack{
		&insertion{Offset: 7},
		&insertion{Offset: 8},
	}
	s2 := insertionStack{
		&insertion{Offset: 10},
		&insertion{Offset: 9},
	}
	s1, s2 = s1.rebalance(s2, 9)
	if !(len(s1) == 3 && len(s2) == 1 &&
		s1[0].Offset == 7 && s1[1].Offset == 8 && s1[2].Offset == 9 &&
		s2[0].Offset == 10) {
		t.Errorf("Wrong rebalance when needed: %#v %#v", s1, s2)
	}
}

func TestRebalanceNotNeeded(t *testing.T) {
	s1 := insertionStack{
		&insertion{Offset: 7},
		&insertion{Offset: 8},
	}
	s2 := insertionStack{
		&insertion{Offset: 10},
		&insertion{Offset: 9},
	}
	s1, s2 = s1.rebalance(s2, 8)
	if !(len(s1) == 2 && len(s2) == 2 &&
		s1[0].Offset == 7 && s1[1].Offset == 8 &&
		s2[0].Offset == 10 && s2[1].Offset == 9) {
		t.Errorf("Wrong rebalance when not needed: %#v %#v", s1, s2)
	}
}

func TestRebalanceLate(t *testing.T) {
	s1 := insertionStack{
		&insertion{Offset: 7},
		&insertion{Offset: 8},
	}
	s2 := insertionStack{
		&insertion{Offset: 10},
		&insertion{Offset: 9},
	}
	s1, s2 = s1.rebalance(s2, 10)
	if !(len(s1) == 4 && len(s2) == 0 &&
		s1[0].Offset == 7 && s1[1].Offset == 8 &&
		s1[2].Offset == 9 && s1[3].Offset == 10) {
		t.Errorf("Wrong rebalance when late: %#v %#v", s1, s2)
	}
}

func TestIteratorEmpty(t *testing.T) {
	s := insertionStack{}
	g := s.NewIterator()
	v := g()
	if v != nil {
		t.Errorf("Empty iterator should return nil but returned %#v", v)
	}
}

func TestIterator(t *testing.T) {
	s := insertionStack{
		&insertion{Offset: 7},
		&insertion{Offset: 8},
	}
	g := s.NewIterator()
	v := g()
	if v == nil || v.Offset != 7 {
		t.Errorf("Wrong insertion instead of 7: %#v", v)
	}
	v = g()
	if v == nil || v.Offset != 8 {
		t.Errorf("Wrong insertion instead of 8: %#v", v)
	}
	v = g()
	if v != nil {
		t.Errorf("nil should be returned after end, %#v instead", v)
	}
	v = g()
	if v != nil {
		t.Errorf("Further attempts should return nil too, %#v instead", v)
	}
}

func TestSortEntities(t *testing.T) {
	entities := []*client.TextEntity{
		&client.TextEntity{
			Offset: 3,
			Length: 2,
		},
		&client.TextEntity{
			Offset: 5,
			Length: 2,
		},
		&client.TextEntity{
			Offset: 7,
			Length: 2,
		},
		&client.TextEntity{
			Offset: 6,
			Length: 1,
		},
		&client.TextEntity{
			Offset: 5,
			Length: 1,
		},
	}
	entities = SortEntities(entities)
	if !(len(entities) == 5 &&
		entities[0].Offset == 3 && entities[0].Length == 2 &&
		entities[1].Offset == 5 && entities[1].Length == 2 &&
		entities[2].Offset == 5 && entities[2].Length == 1 &&
		entities[3].Offset == 6 && entities[3].Length == 1 &&
		entities[4].Offset == 7 && entities[4].Length == 2) {
		t.Errorf("Wrong sorting order: %#v", entities)
	}
}

func TestSortEmpty(t *testing.T) {
	entities := []*client.TextEntity{}
	entities = SortEntities(entities)
	if len(entities) != 0 {
		t.Errorf("Empty entities set sorting error: %#v", entities)
	}
}

func TestNoFormattingXEP0393(t *testing.T) {
	markup := Format("abc\ndef", []*client.TextEntity{}, MarkupModeXEP0393)
	if markup != "abc\ndef" {
		t.Errorf("No formatting expected, but: %v", markup)
	}
}

func TestFormattingXEP0393Simple(t *testing.T) {
	markup := Format("👙🐧🐖", []*client.TextEntity{
		&client.TextEntity{
			Offset: 2,
			Length: 4,
			Type:   &client.TextEntityTypeBold{},
		},
	}, MarkupModeXEP0393)
	if markup != "👙*🐧🐖*" {
		t.Errorf("Wrong simple formatting: %v", markup)
	}
}

func TestFormattingXEP0393Adjacent(t *testing.T) {
	markup := Format("a👙🐧🐖", []*client.TextEntity{
		&client.TextEntity{
			Offset: 3,
			Length: 2,
			Type:   &client.TextEntityTypeItalic{},
		},
		&client.TextEntity{
			Offset: 5,
			Length: 2,
			Type: &client.TextEntityTypeTextUrl{
				Url: "https://narayana.im/",
			},
		},
	}, MarkupModeXEP0393)
	if markup != "a👙_🐧_🐖 <https://narayana.im/>" {
		t.Errorf("Wrong adjacent formatting: %v", markup)
	}
}

func TestFormattingXEP0393AdjacentAndNested(t *testing.T) {
	markup := Format("👙🐧🐖", []*client.TextEntity{
		&client.TextEntity{
			Offset: 0,
			Length: 4,
			Type:   &client.TextEntityTypePre{},
		},
		&client.TextEntity{
			Offset: 0,
			Length: 2,
			Type:   &client.TextEntityTypeBold{},
		},
		&client.TextEntity{
			Offset: 4,
			Length: 2,
			Type:   &client.TextEntityTypeItalic{},
		},
	}, MarkupModeXEP0393)
	if markup != "```\n*👙*🐧\n```_🐖_" {
		t.Errorf("Wrong adjacent&nested formatting: %v", markup)
	}
}

func TestFormattingXEP0393AdjacentItalicBoldItalic(t *testing.T) {
	markup := Format("раса двуногих крысолюдей, которую так редко замечают, что многие отрицают само их существование", []*client.TextEntity{
		&client.TextEntity{
			Offset: 0,
			Length: 26,
			Type:   &client.TextEntityTypeItalic{},
		},
		&client.TextEntity{
			Offset: 26,
			Length: 69,
			Type:   &client.TextEntityTypeBold{},
		},
		&client.TextEntity{
			Offset: 26,
			Length: 69,
			Type:   &client.TextEntityTypeItalic{},
		},
	}, MarkupModeXEP0393)
	if markup != "_раса двуногих крысолюдей, *которую так редко замечают, что многие отрицают само их существование*_" {
		t.Errorf("Wrong adjacent italic/bold-italic formatting: %v", markup)
	}
}

func TestFormattingXEP0393MultipleAdjacent(t *testing.T) {
	markup := Format("abcde", []*client.TextEntity{
		&client.TextEntity{
			Offset: 1,
			Length: 1,
			Type:   &client.TextEntityTypeBold{},
		},
		&client.TextEntity{
			Offset: 2,
			Length: 1,
			Type:   &client.TextEntityTypeBold{},
		},
		&client.TextEntity{
			Offset: 3,
			Length: 1,
			Type:   &client.TextEntityTypeBold{},
		},
		&client.TextEntity{
			Offset: 4,
			Length: 1,
			Type:   &client.TextEntityTypeItalic{},
		},
	}, MarkupModeXEP0393)
	if markup != "a*bcd*_e_" {
		t.Errorf("Wrong multiple adjacent formatting: %v", markup)
	}
}

func TestFormattingXEP0393Intersecting(t *testing.T) {
	markup := Format("abcde", []*client.TextEntity{
		&client.TextEntity{
			Offset: 1,
			Length: 1,
			Type:   &client.TextEntityTypeBold{},
		},
		&client.TextEntity{
			Offset: 2,
			Length: 3,
			Type:   &client.TextEntityTypeItalic{},
		},
		&client.TextEntity{
			Offset: 2,
			Length: 1,
			Type:   &client.TextEntityTypeBold{},
		},
		&client.TextEntity{
			Offset: 3,
			Length: 1,
			Type:   &client.TextEntityTypeBold{},
		},
	}, MarkupModeXEP0393)
	if markup != "a*b*_*cd*e_" {
		t.Errorf("Wrong intersecting formatting: %v", markup)
	}
}

func TestFormattingXEP0393InlineCode(t *testing.T) {
	markup := Format("Is Gajim a thing?\n\necho 'Hello'\necho 'world'\n\nhruck(", []*client.TextEntity{
		&client.TextEntity{
			Offset: 3,
			Length: 5,
			Type:   &client.TextEntityTypeCode{},
		},
		&client.TextEntity{
			Offset: 19,
			Length: 25,
			Type:   &client.TextEntityTypePre{},
		},
	}, MarkupModeXEP0393)
	if markup != "Is `Gajim` a thing?\n\n```\necho 'Hello'\necho 'world'\n```\n\nhruck(" {
		t.Errorf("Wrong intersecting formatting: %v", markup)
	}
}

func TestFormattingMarkdownStrikethrough(t *testing.T) {
	markup := Format("Everyone dislikes cake.", []*client.TextEntity{
		&client.TextEntity{
			Offset: 9,
			Length: 3,
			Type:   &client.TextEntityTypeStrikethrough{},
		},
	}, MarkupModeMarkdown)
	if markup != "Everyone ~~dis~~likes cake." {
		t.Errorf("Wrong strikethrough formatting: %v", markup)
	}
}

func TestFormattingXEP0393Strikethrough(t *testing.T) {
	markup := Format("Everyone dislikes cake.", []*client.TextEntity{
		&client.TextEntity{
			Offset: 9,
			Length: 3,
			Type:   &client.TextEntityTypeStrikethrough{},
		},
	}, MarkupModeXEP0393)
	if markup != "Everyone ~dis~likes cake." {
		t.Errorf("Wrong strikethrough formatting: %v", markup)
	}
}

func TestClaspLeft(t *testing.T) {
	text := textToDoubledRunes("a b c")
	entities := []*client.TextEntity{
		&client.TextEntity{
			Offset: 1,
			Length: 2,
		},
	}
	entities = ClaspDirectives(text, entities)
	if !(len(entities) == 1 &&
		entities[0].Offset == 2 && entities[0].Length == 1) {
		t.Errorf("Wrong claspleft: %#v", entities)
	}
}

func TestClaspBoth(t *testing.T) {
	text := textToDoubledRunes("a b c")
	entities := []*client.TextEntity{
		&client.TextEntity{
			Offset: 1,
			Length: 3,
		},
	}
	entities = ClaspDirectives(text, entities)
	if !(len(entities) == 1 &&
		entities[0].Offset == 2 && entities[0].Length == 1) {
		t.Errorf("Wrong claspboth: %#v", entities)
	}
}

func TestClaspNotNeeded(t *testing.T) {
	text := textToDoubledRunes(" abc ")
	entities := []*client.TextEntity{
		&client.TextEntity{
			Offset: 1,
			Length: 3,
		},
	}
	entities = ClaspDirectives(text, entities)
	if !(len(entities) == 1 &&
		entities[0].Offset == 1 && entities[0].Length == 3) {
		t.Errorf("Wrong claspnotneeded: %#v", entities)
	}
}

func TestClaspNested(t *testing.T) {
	text := textToDoubledRunes("a b c")
	entities := []*client.TextEntity{
		&client.TextEntity{
			Offset: 1,
			Length: 3,
		},
		&client.TextEntity{
			Offset: 2,
			Length: 2,
		},
	}
	entities = ClaspDirectives(text, entities)
	if !(len(entities) == 2 &&
		entities[0].Offset == 2 && entities[0].Length == 1 &&
		entities[1].Offset == 2 && entities[1].Length == 1) {
		t.Errorf("Wrong claspnested: %#v", entities)
	}
}

func TestClaspEmoji(t *testing.T) {
	text := textToDoubledRunes("a 🐖 c")
	entities := []*client.TextEntity{
		&client.TextEntity{
			Offset: 1,
			Length: 4,
		},
	}
	entities = ClaspDirectives(text, entities)
	if !(len(entities) == 1 &&
		entities[0].Offset == 2 && entities[0].Length == 2) {
		t.Errorf("Wrong claspemoji: %#v", entities)
	}
}

func TestNoNewlineBlockquoteXEP0393(t *testing.T) {
	markup := Format("yes it can i think", []*client.TextEntity{
		&client.TextEntity{
			Offset: 4,
			Length: 6,
			Type:   &client.TextEntityTypeBlockQuote{},
		},
	}, MarkupModeXEP0393)
	if markup != "yes \n> it can\n i think" {
		t.Errorf("Wrong blockquote formatting: %v", markup)
	}
}

func TestNoNewlineBlockquoteMarkdown(t *testing.T) {
	markup := Format("yes it can i think", []*client.TextEntity{
		&client.TextEntity{
			Offset: 4,
			Length: 6,
			Type:   &client.TextEntityTypeBlockQuote{},
		},
	}, MarkupModeMarkdown)
	if markup != "yes \n> it can\n\n i think" {
		t.Errorf("Wrong blockquote formatting: %v", markup)
	}
}

func TestMultilineBlockquoteXEP0393(t *testing.T) {
	markup := Format("hruck\npuck\n\nshuck\ntext", []*client.TextEntity{
		&client.TextEntity{
			Offset: 0,
			Length: 17,
			Type:   &client.TextEntityTypeBlockQuote{},
		},
	}, MarkupModeXEP0393)
	if markup != "> hruck\n> puck\n> \n> shuck\ntext" {
		t.Errorf("Wrong blockquote formatting: %v", markup)
	}
}

func TestMultilineBlockquoteMarkdown(t *testing.T) {
	markup := Format("hruck\npuck\n\nshuck\ntext", []*client.TextEntity{
		&client.TextEntity{
			Offset: 0,
			Length: 17,
			Type:   &client.TextEntityTypeBlockQuote{},
		},
	}, MarkupModeMarkdown)
	if markup != "> hruck\npuck\n\n> shuck\n\ntext" {
		t.Errorf("Wrong blockquote formatting: %v", markup)
	}
}

func TestMixedBlockquoteXEP0393(t *testing.T) {
	markup := Format("hruck\npuck\nshuck\ntext", []*client.TextEntity{
		&client.TextEntity{
			Offset: 0,
			Length: 16,
			Type:   &client.TextEntityTypeBlockQuote{},
		},
		&client.TextEntity{
			Offset: 0,
			Length: 16,
			Type:   &client.TextEntityTypeBold{},
		},
		&client.TextEntity{
			Offset: 0,
			Length: 10,
			Type:   &client.TextEntityTypeItalic{},
		},
		&client.TextEntity{
			Offset: 7,
			Length: 2,
			Type:   &client.TextEntityTypeStrikethrough{},
		},
	}, MarkupModeXEP0393)
	if markup != "> *_hruck\n> p~uc~k_\n> shuck*\ntext" {
		t.Errorf("Wrong blockquote formatting: %v", markup)
	}
}

func TestMixedBlockquoteMarkdown(t *testing.T) {
	markup := Format("hruck\npuck\nshuck\ntext", []*client.TextEntity{
		&client.TextEntity{
			Offset: 0,
			Length: 16,
			Type:   &client.TextEntityTypeBlockQuote{},
		},
		&client.TextEntity{
			Offset: 0,
			Length: 16,
			Type:   &client.TextEntityTypeBold{},
		},
		&client.TextEntity{
			Offset: 0,
			Length: 10,
			Type:   &client.TextEntityTypeItalic{},
		},
		&client.TextEntity{
			Offset: 7,
			Length: 2,
			Type:   &client.TextEntityTypeStrikethrough{},
		},
	}, MarkupModeMarkdown)
	if markup != "> **_hruck\np~~uc~~k_\nshuck**\n\ntext" {
		t.Errorf("Wrong blockquote formatting: %v", markup)
	}
}