github.1git.de/docker/cli@v26.1.3+incompatible/cli/command/registry/formatter_search_test.go (about) 1 package registry 2 3 import ( 4 "bytes" 5 "testing" 6 7 "github.com/docker/cli/cli/command/formatter" 8 registrytypes "github.com/docker/docker/api/types/registry" 9 "gotest.tools/v3/assert" 10 is "gotest.tools/v3/assert/cmp" 11 "gotest.tools/v3/golden" 12 ) 13 14 func TestSearchContext(t *testing.T) { 15 var ctx searchContext 16 cases := []struct { 17 searchCtx searchContext 18 expValue string 19 call func() string 20 }{ 21 { 22 searchCtx: searchContext{ 23 s: registrytypes.SearchResult{Name: "nginx"}, 24 }, 25 expValue: "nginx", 26 call: ctx.Name, 27 }, 28 { 29 searchCtx: searchContext{ 30 s: registrytypes.SearchResult{StarCount: 5000}, 31 }, 32 expValue: "5000", 33 call: ctx.StarCount, 34 }, 35 { 36 searchCtx: searchContext{ 37 s: registrytypes.SearchResult{IsOfficial: true}, 38 }, 39 expValue: "[OK]", 40 call: ctx.IsOfficial, 41 }, 42 { 43 searchCtx: searchContext{ 44 s: registrytypes.SearchResult{IsOfficial: false}, 45 }, 46 call: ctx.IsOfficial, 47 }, 48 { 49 searchCtx: searchContext{ 50 s: registrytypes.SearchResult{IsAutomated: true}, //nolint:nolintlint,staticcheck // ignore SA1019 (IsAutomated is deprecated). 51 }, 52 expValue: "[OK]", 53 call: ctx.IsAutomated, //nolint:nolintlint,staticcheck // ignore SA1019 (IsAutomated is deprecated). 54 }, 55 { 56 searchCtx: searchContext{ 57 s: registrytypes.SearchResult{}, 58 }, 59 call: ctx.IsAutomated, //nolint:nolintlint,staticcheck // ignore SA1019 (IsAutomated is deprecated). 60 }, 61 } 62 63 for _, c := range cases { 64 ctx = c.searchCtx 65 v := c.call() 66 assert.Check(t, is.Equal(v, c.expValue)) 67 } 68 } 69 70 func TestSearchContextDescription(t *testing.T) { 71 const ( 72 shortDescription = "Official build of Nginx." 73 longDescription = "Automated Nginx reverse proxy for docker containers" 74 descriptionWReturns = "Automated\nNginx reverse\rproxy\rfor docker\ncontainers" 75 ) 76 77 var ctx searchContext 78 cases := []struct { 79 searchCtx searchContext 80 expValue string 81 call func() string 82 }{ 83 { 84 searchCtx: searchContext{ 85 s: registrytypes.SearchResult{Description: shortDescription}, 86 trunc: true, 87 }, 88 expValue: shortDescription, 89 call: ctx.Description, 90 }, 91 { 92 searchCtx: searchContext{ 93 s: registrytypes.SearchResult{Description: shortDescription}, 94 trunc: false, 95 }, 96 expValue: shortDescription, 97 call: ctx.Description, 98 }, 99 { 100 searchCtx: searchContext{ 101 s: registrytypes.SearchResult{Description: longDescription}, 102 trunc: false, 103 }, 104 expValue: longDescription, 105 call: ctx.Description, 106 }, 107 { 108 searchCtx: searchContext{ 109 s: registrytypes.SearchResult{Description: longDescription}, 110 trunc: true, 111 }, 112 expValue: formatter.Ellipsis(longDescription, 45), 113 call: ctx.Description, 114 }, 115 { 116 searchCtx: searchContext{ 117 s: registrytypes.SearchResult{Description: descriptionWReturns}, 118 trunc: false, 119 }, 120 expValue: longDescription, 121 call: ctx.Description, 122 }, 123 { 124 searchCtx: searchContext{ 125 s: registrytypes.SearchResult{Description: descriptionWReturns}, 126 trunc: true, 127 }, 128 expValue: formatter.Ellipsis(longDescription, 45), 129 call: ctx.Description, 130 }, 131 } 132 133 for _, c := range cases { 134 ctx = c.searchCtx 135 v := c.call() 136 assert.Check(t, is.Equal(v, c.expValue)) 137 } 138 } 139 140 func TestSearchContextWrite(t *testing.T) { 141 cases := []struct { 142 doc string 143 format formatter.Format 144 expected string 145 expectedErr string 146 }{ 147 { 148 doc: "Errors", 149 format: "{{InvalidFunction}}", 150 expectedErr: `template parsing error: template: :1: function "InvalidFunction" not defined`, 151 }, 152 { 153 doc: "Nil format", 154 format: "{{nil}}", 155 expectedErr: `template parsing error: template: :1:2: executing "" at <nil>: nil is not a command`, 156 }, 157 { 158 doc: "JSON format", 159 format: "{{json .}}", 160 expected: `{"Description":"Official build","IsAutomated":"false","IsOfficial":"true","Name":"result1","StarCount":"5000"} 161 {"Description":"Not official","IsAutomated":"true","IsOfficial":"false","Name":"result2","StarCount":"5"} 162 `, 163 }, 164 { 165 doc: "JSON format, single field", 166 format: "{{json .Name}}", 167 expected: `"result1" 168 "result2" 169 `, 170 }, 171 { 172 doc: "Table format", 173 format: NewSearchFormat("table"), 174 expected: string(golden.Get(t, "search-context-write-table.golden")), 175 }, 176 { 177 doc: "Table format, single column", 178 format: NewSearchFormat("table {{.Name}}"), 179 expected: `NAME 180 result1 181 result2 182 `, 183 }, 184 { 185 doc: "Custom format, single field", 186 format: NewSearchFormat("{{.Name}}"), 187 expected: `result1 188 result2 189 `, 190 }, 191 { 192 doc: "Custom Format, two columns", 193 format: NewSearchFormat("{{.Name}} {{.StarCount}}"), 194 expected: `result1 5000 195 result2 5 196 `, 197 }, 198 } 199 200 results := []registrytypes.SearchResult{ 201 {Name: "result1", Description: "Official build", StarCount: 5000, IsOfficial: true}, 202 {Name: "result2", Description: "Not official", StarCount: 5, IsAutomated: true}, 203 } 204 205 for _, tc := range cases { 206 tc := tc 207 t.Run(tc.doc, func(t *testing.T) { 208 var out bytes.Buffer 209 err := SearchWrite(formatter.Context{Format: tc.format, Output: &out}, results) 210 if tc.expectedErr != "" { 211 assert.Check(t, is.Error(err, tc.expectedErr)) 212 } else { 213 assert.Check(t, err) 214 } 215 assert.Check(t, is.Equal(out.String(), tc.expected)) 216 }) 217 } 218 }