Monorepo for Tangled
at 67c0e9bc7d93ce141284b0554feacb3c1d57f6d0 206 lines 5.8 kB view raw
1package searchquery 2 3import ( 4 "testing" 5 6 "github.com/stretchr/testify/assert" 7) 8 9func TestParseMixed(t *testing.T) { 10 q := Parse(`state:open bug "critical issue" label:good-first-issue fix`) 11 items := q.Items() 12 assert.Equal(t, 5, len(items)) 13 14 assert.Equal(t, KindTagValue, items[0].Kind) 15 assert.Equal(t, "state", items[0].Key) 16 assert.Equal(t, "open", items[0].Value) 17 18 assert.Equal(t, KindKeyword, items[1].Kind) 19 assert.Equal(t, "bug", items[1].Raw) 20 21 assert.Equal(t, KindQuoted, items[2].Kind) 22 assert.Equal(t, `"critical issue"`, items[2].Raw) 23 24 assert.Equal(t, KindTagValue, items[3].Kind) 25 assert.Equal(t, "label", items[3].Key) 26 assert.Equal(t, "good-first-issue", items[3].Value) 27 28 assert.Equal(t, KindKeyword, items[4].Kind) 29 30 assert.Equal(t, `state:open bug "critical issue" label:good-first-issue fix`, q.String()) 31} 32 33func TestGetSetLifecycle(t *testing.T) { 34 q := Parse("label:bug state:open keyword label:feature label:urgent") 35 36 // Get returns first match 37 val := q.Get("state") 38 assert.NotNil(t, val) 39 assert.Equal(t, "open", *val) 40 41 // Get returns nil for missing key 42 assert.Nil(t, q.Get("author")) 43 44 // Has 45 assert.True(t, q.Has("state")) 46 assert.False(t, q.Has("author")) 47 48 // GetAll 49 assert.Equal(t, []string{"bug", "feature", "urgent"}, q.GetAll("label")) 50 assert.Equal(t, 0, len(q.GetAll("missing"))) 51 52 // Set updates existing, preserving position 53 q.Set("state", "closed") 54 assert.Equal(t, "label:bug state:closed keyword label:feature label:urgent", q.String()) 55 56 // Set deduplicates 57 q.Set("label", "single") 58 assert.Equal(t, "label:single state:closed keyword", q.String()) 59 60 // Set appends new tag 61 q.Set("author", "bob") 62 assert.Equal(t, "label:single state:closed keyword author:bob", q.String()) 63} 64 65func TestParseEmpty(t *testing.T) { 66 q := Parse(" ") 67 assert.Equal(t, 0, len(q.Items())) 68 assert.Equal(t, "", q.String()) 69} 70 71func TestParseUnclosedQuote(t *testing.T) { 72 q := Parse(`"hello world`) 73 items := q.Items() 74 assert.Equal(t, 1, len(items)) 75 assert.Equal(t, KindQuoted, items[0].Kind) 76 assert.Equal(t, `"hello world`, items[0].Raw) 77 assert.Equal(t, "hello world", items[0].Value) 78} 79 80func TestParseLeadingColon(t *testing.T) { 81 q := Parse(":value") 82 items := q.Items() 83 assert.Equal(t, 1, len(items)) 84 assert.Equal(t, KindKeyword, items[0].Kind) 85 assert.Equal(t, ":value", items[0].Raw) 86} 87 88func TestParseColonInValue(t *testing.T) { 89 q := Parse("key:value:with:colons") 90 items := q.Items() 91 assert.Equal(t, 1, len(items)) 92 assert.Equal(t, "key", items[0].Key) 93 assert.Equal(t, "value:with:colons", items[0].Value) 94} 95 96func TestParseEmptyValue(t *testing.T) { 97 q := Parse("state:") 98 items := q.Items() 99 assert.Equal(t, 1, len(items)) 100 assert.Equal(t, KindTagValue, items[0].Kind) 101 assert.Equal(t, "state", items[0].Key) 102 assert.Equal(t, "", items[0].Value) 103} 104 105func TestQuotedKeyValueIsNotTag(t *testing.T) { 106 q := Parse(`"state:open"`) 107 items := q.Items() 108 assert.Equal(t, 1, len(items)) 109 assert.Equal(t, KindQuoted, items[0].Kind) 110 assert.Equal(t, "state:open", items[0].Value) 111 assert.False(t, q.Has("state")) 112} 113 114func TestConsecutiveQuotes(t *testing.T) { 115 q := Parse(`"one""two"`) 116 items := q.Items() 117 assert.Equal(t, 2, len(items)) 118 assert.Equal(t, `"one"`, items[0].Raw) 119 assert.Equal(t, `"two"`, items[1].Raw) 120} 121 122func TestEscapedQuotes(t *testing.T) { 123 q := Parse(`"hello \"world\""`) 124 items := q.Items() 125 assert.Equal(t, 1, len(items)) 126 assert.Equal(t, KindQuoted, items[0].Kind) 127 assert.Equal(t, `"hello \"world\""`, items[0].Raw) 128 assert.Equal(t, `hello "world"`, items[0].Value) 129} 130 131func TestEscapedBackslash(t *testing.T) { 132 q := Parse(`"hello\\"`) 133 items := q.Items() 134 assert.Equal(t, 1, len(items)) 135 assert.Equal(t, KindQuoted, items[0].Kind) 136 assert.Equal(t, `hello\`, items[0].Value) 137} 138 139func TestNegatedTag(t *testing.T) { 140 q := Parse("state:open -label:bug keyword -label:wontfix") 141 items := q.Items() 142 assert.Equal(t, 4, len(items)) 143 144 assert.False(t, items[0].Negated) 145 assert.Equal(t, "state", items[0].Key) 146 147 assert.True(t, items[1].Negated) 148 assert.Equal(t, KindTagValue, items[1].Kind) 149 assert.Equal(t, "label", items[1].Key) 150 assert.Equal(t, "bug", items[1].Value) 151 assert.Equal(t, "-label:bug", items[1].Raw) 152 153 assert.True(t, items[3].Negated) 154 assert.Equal(t, "wontfix", items[3].Value) 155 156 // Get/GetAll/Has skip negated tags 157 assert.False(t, q.Has("label")) 158 assert.Equal(t, 0, len(q.GetAll("label"))) 159 160 // Set doesn't touch negated tags 161 q.Set("label", "feature") 162 assert.Equal(t, "state:open -label:bug keyword -label:wontfix label:feature", q.String()) 163} 164 165func TestNegatedBareWordIsKeyword(t *testing.T) { 166 q := Parse("-keyword") 167 items := q.Items() 168 assert.Equal(t, 1, len(items)) 169 assert.Equal(t, KindKeyword, items[0].Kind) 170 assert.Equal(t, "-keyword", items[0].Raw) 171} 172 173func TestNegatedQuotedPhrase(t *testing.T) { 174 q := Parse(`-"critical bug" state:open`) 175 items := q.Items() 176 assert.Equal(t, 2, len(items)) 177 178 assert.Equal(t, KindQuoted, items[0].Kind) 179 assert.True(t, items[0].Negated) 180 assert.Equal(t, `-"critical bug"`, items[0].Raw) 181 assert.Equal(t, "critical bug", items[0].Value) 182 183 assert.Equal(t, KindTagValue, items[1].Kind) 184 assert.Equal(t, "state", items[1].Key) 185} 186 187func TestNegatedQuotedPhraseAmongOthers(t *testing.T) { 188 q := Parse(`"good phrase" -"bad phrase" keyword`) 189 items := q.Items() 190 assert.Equal(t, 3, len(items)) 191 192 assert.Equal(t, KindQuoted, items[0].Kind) 193 assert.False(t, items[0].Negated) 194 assert.Equal(t, "good phrase", items[0].Value) 195 196 assert.Equal(t, KindQuoted, items[1].Kind) 197 assert.True(t, items[1].Negated) 198 assert.Equal(t, "bad phrase", items[1].Value) 199 200 assert.Equal(t, KindKeyword, items[2].Kind) 201} 202 203func TestWhitespaceNormalization(t *testing.T) { 204 q := Parse(" state:open keyword ") 205 assert.Equal(t, "state:open keyword", q.String()) 206}