| package hooks_test | |
| import ( | |
| "testing" | |
| "github.com/docker/cli/cli-plugins/hooks" | |
| "github.com/spf13/cobra" | |
| "gotest.tools/v3/assert" | |
| ) | |
| // TestParseTemplate tests parsing templates as returned by plugins. | |
| // | |
| // It uses fixed string fixtures to lock in compatibility with existing | |
| // plugin templates, so older formats continue to work even if we add new | |
| // template forms. | |
| // | |
| // For helper-backed cases, it also verifies that templates produced by the | |
| // current TemplateReplace* helpers parse to the same output. This lets us | |
| // evolve the emitted template format without breaking older plugins. | |
| func TestParseTemplate(t *testing.T) { | |
| type testFlag struct { | |
| name string | |
| value string | |
| } | |
| tests := []struct { | |
| doc string | |
| template string // compatibility fixture; keep even if helpers emit a newer form | |
| templateFunc func() string | |
| flags []testFlag | |
| args []string | |
| expectedOutput []string | |
| }{ | |
| { | |
| doc: "empty template", | |
| template: "", | |
| expectedOutput: nil, | |
| }, | |
| { | |
| doc: "only empty lines", | |
| template: "\n\n", | |
| expectedOutput: nil, | |
| }, | |
| { | |
| doc: "whitespace-only lines", | |
| template: " \n\t\n ", | |
| expectedOutput: nil, | |
| }, | |
| { | |
| doc: "plain message", | |
| template: "a plain template message", | |
| expectedOutput: []string{"a plain template message"}, | |
| }, | |
| { | |
| doc: "subcommand name", | |
| template: "hello {{.Name}}", // NOTE: fixture; do not modify without considering plugin compatibility | |
| templateFunc: func() string { return "hello " + hooks.TemplateReplaceSubcommandName() }, | |
| expectedOutput: []string{"hello pull"}, | |
| }, | |
| { | |
| doc: "single flag", | |
| template: `{{flag . "tag"}}`, // NOTE: fixture; do not modify without considering plugin compatibility | |
| templateFunc: func() string { return hooks.TemplateReplaceFlagValue("tag") }, | |
| flags: []testFlag{ | |
| {name: "tag", value: "my-tag"}, | |
| }, | |
| expectedOutput: []string{"my-tag"}, | |
| }, | |
| { | |
| doc: "multiple flags", | |
| template: `{{flag . "test-one"}} {{flag . "test2"}}`, // NOTE: fixture; do not modify without considering plugin compatibility | |
| templateFunc: func() string { | |
| return hooks.TemplateReplaceFlagValue("test-one") + " " + hooks.TemplateReplaceFlagValue("test2") | |
| }, | |
| flags: []testFlag{ | |
| { | |
| name: "test-one", | |
| value: "value", | |
| }, | |
| { | |
| name: "test2", | |
| value: "value2", | |
| }, | |
| }, | |
| expectedOutput: []string{"value value2"}, | |
| }, | |
| { | |
| doc: "multiple args", | |
| template: `{{arg . 0}} {{arg . 1}}`, // NOTE: fixture; do not modify without considering plugin compatibility | |
| templateFunc: func() string { return hooks.TemplateReplaceArg(0) + " " + hooks.TemplateReplaceArg(1) }, | |
| args: []string{"zero", "one"}, | |
| expectedOutput: []string{"zero one"}, | |
| }, | |
| { | |
| doc: "arg in sentence", | |
| template: "You just pulled {{arg . 0}}", // NOTE: fixture; do not modify without considering plugin compatibility | |
| templateFunc: func() string { return "You just pulled " + hooks.TemplateReplaceArg(0) }, | |
| args: []string{"alpine"}, | |
| expectedOutput: []string{"You just pulled alpine"}, | |
| }, | |
| { | |
| doc: "multiline output", | |
| template: "one line\nanother line!", | |
| expectedOutput: []string{"one line", "another line!"}, | |
| }, | |
| } | |
| for _, tc := range tests { | |
| t.Run(tc.doc, func(t *testing.T) { | |
| testCmd := &cobra.Command{ | |
| Use: "pull", | |
| Args: cobra.ExactArgs(len(tc.args)), | |
| } | |
| for _, f := range tc.flags { | |
| _ = testCmd.Flags().String(f.name, "", "") | |
| err := testCmd.Flag(f.name).Value.Set(f.value) | |
| assert.NilError(t, err) | |
| } | |
| err := testCmd.Flags().Parse(tc.args) | |
| assert.NilError(t, err) | |
| // Validate using fixtures. | |
| out, err := hooks.ParseTemplate(tc.template, testCmd) | |
| assert.NilError(t, err) | |
| assert.DeepEqual(t, out, tc.expectedOutput) | |
| if tc.templateFunc != nil { | |
| // Validate using the current template function equivalent. | |
| out, err = hooks.ParseTemplate(tc.templateFunc(), testCmd) | |
| assert.NilError(t, err) | |
| assert.DeepEqual(t, out, tc.expectedOutput) | |
| } | |
| }) | |
| } | |
| } |