github.com/fastly/cli@v1.7.2-0.20240304164155-9d0f1d77c3bf/pkg/commands/vcl/snippet/snippet_test.go (about)

     1  package snippet_test
     2  
     3  import (
     4  	"bytes"
     5  	"io"
     6  	"testing"
     7  
     8  	"github.com/fastly/go-fastly/v9/fastly"
     9  
    10  	"github.com/fastly/cli/pkg/app"
    11  	"github.com/fastly/cli/pkg/global"
    12  	"github.com/fastly/cli/pkg/mock"
    13  	"github.com/fastly/cli/pkg/testutil"
    14  )
    15  
    16  func TestVCLSnippetCreate(t *testing.T) {
    17  	var content string
    18  	args := testutil.Args
    19  	scenarios := []testutil.TestScenario{
    20  		{
    21  			Name:      "validate missing --service-id flag",
    22  			Args:      args("vcl snippet create --content /path/to/snippet.vcl --name foo --type recv --version 3"),
    23  			WantError: "error reading service: no service ID found",
    24  		},
    25  		{
    26  			Name: "validate missing --autoclone flag",
    27  			API: mock.API{
    28  				ListVersionsFn: testutil.ListVersions,
    29  			},
    30  			Args:      args("vcl snippet create --content ./testdata/snippet.vcl --name foo --type recv --service-id 123 --version 1"),
    31  			WantError: "service version 1 is not editable",
    32  		},
    33  		{
    34  			Name: "validate CreateSnippet API error",
    35  			API: mock.API{
    36  				ListVersionsFn: testutil.ListVersions,
    37  				CreateSnippetFn: func(i *fastly.CreateSnippetInput) (*fastly.Snippet, error) {
    38  					return nil, testutil.Err
    39  				},
    40  			},
    41  			Args:      args("vcl snippet create --content ./testdata/snippet.vcl --name foo --type recv --service-id 123 --version 3"),
    42  			WantError: testutil.Err.Error(),
    43  		},
    44  		{
    45  			Name: "validate CreateSnippet API success for versioned Snippet",
    46  			API: mock.API{
    47  				ListVersionsFn: testutil.ListVersions,
    48  				CreateSnippetFn: func(i *fastly.CreateSnippetInput) (*fastly.Snippet, error) {
    49  					// Track the contents parsed
    50  					content = *i.Content
    51  					if i.Content == nil {
    52  						i.Content = fastly.ToPointer("")
    53  					}
    54  					if i.Dynamic == nil {
    55  						i.Dynamic = fastly.ToPointer(0)
    56  					}
    57  					if i.Name == nil {
    58  						i.Name = fastly.ToPointer("")
    59  					}
    60  					return &fastly.Snippet{
    61  						Content:        i.Content,
    62  						Dynamic:        i.Dynamic,
    63  						Name:           i.Name,
    64  						ServiceID:      fastly.ToPointer(i.ServiceID),
    65  						ServiceVersion: fastly.ToPointer(i.ServiceVersion),
    66  						SnippetID:      fastly.ToPointer("123"),
    67  					}, nil
    68  				},
    69  			},
    70  			Args:       args("vcl snippet create --content ./testdata/snippet.vcl --name foo --service-id 123 --type recv --version 3"),
    71  			WantOutput: "Created VCL snippet 'foo' (service: 123, version: 3, dynamic: false, snippet id: 123, type: recv, priority: 0)",
    72  		},
    73  		{
    74  			Name: "validate CreateSnippet API success for dynamic Snippet",
    75  			API: mock.API{
    76  				ListVersionsFn: testutil.ListVersions,
    77  				CreateSnippetFn: func(i *fastly.CreateSnippetInput) (*fastly.Snippet, error) {
    78  					// Track the contents parsed
    79  					content = *i.Content
    80  					if i.Content == nil {
    81  						i.Content = fastly.ToPointer("")
    82  					}
    83  					if i.Dynamic == nil {
    84  						i.Dynamic = fastly.ToPointer(0)
    85  					}
    86  					if i.Name == nil {
    87  						i.Name = fastly.ToPointer("")
    88  					}
    89  					return &fastly.Snippet{
    90  						Content:        i.Content,
    91  						Dynamic:        i.Dynamic,
    92  						Name:           i.Name,
    93  						ServiceID:      fastly.ToPointer(i.ServiceID),
    94  						ServiceVersion: fastly.ToPointer(i.ServiceVersion),
    95  						SnippetID:      fastly.ToPointer("123"),
    96  					}, nil
    97  				},
    98  			},
    99  			Args:       args("vcl snippet create --content ./testdata/snippet.vcl --dynamic --name foo --service-id 123 --type recv --version 3"),
   100  			WantOutput: "Created VCL snippet 'foo' (service: 123, version: 3, dynamic: true, snippet id: 123, type: recv, priority: 0)",
   101  		},
   102  		{
   103  			Name: "validate Priority set",
   104  			API: mock.API{
   105  				ListVersionsFn: testutil.ListVersions,
   106  				CreateSnippetFn: func(i *fastly.CreateSnippetInput) (*fastly.Snippet, error) {
   107  					// Track the contents parsed
   108  					content = *i.Content
   109  					if i.Content == nil {
   110  						i.Content = fastly.ToPointer("")
   111  					}
   112  					if i.Dynamic == nil {
   113  						i.Dynamic = fastly.ToPointer(0)
   114  					}
   115  					if i.Name == nil {
   116  						i.Name = fastly.ToPointer("")
   117  					}
   118  					return &fastly.Snippet{
   119  						Content:        i.Content,
   120  						Dynamic:        i.Dynamic,
   121  						Name:           i.Name,
   122  						Priority:       i.Priority,
   123  						ServiceID:      fastly.ToPointer(i.ServiceID),
   124  						ServiceVersion: fastly.ToPointer(i.ServiceVersion),
   125  						SnippetID:      fastly.ToPointer("123"),
   126  					}, nil
   127  				},
   128  			},
   129  			Args:       args("vcl snippet create --content ./testdata/snippet.vcl --name foo --priority 1 --service-id 123 --type recv --version 3"),
   130  			WantOutput: "Created VCL snippet 'foo' (service: 123, version: 3, dynamic: false, snippet id: 123, type: recv, priority: 1)",
   131  		},
   132  		{
   133  			Name: "validate --autoclone results in cloned service version",
   134  			API: mock.API{
   135  				ListVersionsFn: testutil.ListVersions,
   136  				CloneVersionFn: testutil.CloneVersionResult(4),
   137  				CreateSnippetFn: func(i *fastly.CreateSnippetInput) (*fastly.Snippet, error) {
   138  					// Track the contents parsed
   139  					content = *i.Content
   140  					if i.Content == nil {
   141  						i.Content = fastly.ToPointer("")
   142  					}
   143  					if i.Dynamic == nil {
   144  						i.Dynamic = fastly.ToPointer(0)
   145  					}
   146  					if i.Name == nil {
   147  						i.Name = fastly.ToPointer("")
   148  					}
   149  					return &fastly.Snippet{
   150  						Content:        i.Content,
   151  						Dynamic:        i.Dynamic,
   152  						Name:           i.Name,
   153  						ServiceID:      fastly.ToPointer(i.ServiceID),
   154  						ServiceVersion: fastly.ToPointer(i.ServiceVersion),
   155  						SnippetID:      fastly.ToPointer("123"),
   156  					}, nil
   157  				},
   158  			},
   159  			Args:       args("vcl snippet create --autoclone --content ./testdata/snippet.vcl --name foo --service-id 123 --type recv --version 1"),
   160  			WantOutput: "Created VCL snippet 'foo' (service: 123, version: 4, dynamic: false, snippet id: 123, type: recv, priority: 0)",
   161  		},
   162  		{
   163  			Name: "validate CreateSnippet API success with inline Snippet content",
   164  			API: mock.API{
   165  				ListVersionsFn: testutil.ListVersions,
   166  				CreateSnippetFn: func(i *fastly.CreateSnippetInput) (*fastly.Snippet, error) {
   167  					// Track the contents parsed
   168  					content = *i.Content
   169  					if i.Content == nil {
   170  						i.Content = fastly.ToPointer("")
   171  					}
   172  					if i.Dynamic == nil {
   173  						i.Dynamic = fastly.ToPointer(0)
   174  					}
   175  					if i.Name == nil {
   176  						i.Name = fastly.ToPointer("")
   177  					}
   178  					return &fastly.Snippet{
   179  						Content:        i.Content,
   180  						Dynamic:        i.Dynamic,
   181  						Name:           i.Name,
   182  						ServiceID:      fastly.ToPointer(i.ServiceID),
   183  						ServiceVersion: fastly.ToPointer(i.ServiceVersion),
   184  						SnippetID:      fastly.ToPointer("123"),
   185  					}, nil
   186  				},
   187  			},
   188  			Args:       args("vcl snippet create --content inline_vcl --name foo --service-id 123 --type recv --version 3"),
   189  			WantOutput: "Created VCL snippet 'foo' (service: 123, version: 3, dynamic: false, snippet id: 123, type: recv, priority: 0)",
   190  		},
   191  	}
   192  
   193  	for testcaseIdx := range scenarios {
   194  		testcase := &scenarios[testcaseIdx]
   195  		t.Run(testcase.Name, func(t *testing.T) {
   196  			var stdout bytes.Buffer
   197  			app.Init = func(_ []string, _ io.Reader) (*global.Data, error) {
   198  				opts := testutil.MockGlobalData(testcase.Args, &stdout)
   199  				opts.APIClientFactory = mock.APIClient(testcase.API)
   200  				return opts, nil
   201  			}
   202  			err := app.Run(testcase.Args, nil)
   203  			t.Log(stdout.String())
   204  			testutil.AssertErrorContains(t, err, testcase.WantError)
   205  			testutil.AssertStringContains(t, testutil.StripNewLines(stdout.String()), testcase.WantOutput)
   206  			testutil.AssertPathContentFlag("content", testcase.WantError, testcase.Args, "snippet.vcl", content, t)
   207  		})
   208  	}
   209  }
   210  
   211  func TestVCLSnippetDelete(t *testing.T) {
   212  	args := testutil.Args
   213  	scenarios := []testutil.TestScenario{
   214  		{
   215  			Name:      "validate missing --name flag",
   216  			Args:      args("vcl snippet delete --version 3"),
   217  			WantError: "error parsing arguments: required flag --name not provided",
   218  		},
   219  		{
   220  			Name:      "validate missing --version flag",
   221  			Args:      args("vcl snippet delete --name foobar"),
   222  			WantError: "error parsing arguments: required flag --version not provided",
   223  		},
   224  		{
   225  			Name:      "validate missing --service-id flag",
   226  			Args:      args("vcl snippet delete --name foobar --version 3"),
   227  			WantError: "error reading service: no service ID found",
   228  		},
   229  		{
   230  			Name: "validate missing --autoclone flag",
   231  			API: mock.API{
   232  				ListVersionsFn: testutil.ListVersions,
   233  			},
   234  			Args:      args("vcl snippet delete --name foobar --service-id 123 --version 1"),
   235  			WantError: "service version 1 is not editable",
   236  		},
   237  		{
   238  			Name: "validate DeleteSnippet API error",
   239  			API: mock.API{
   240  				ListVersionsFn: testutil.ListVersions,
   241  				DeleteSnippetFn: func(i *fastly.DeleteSnippetInput) error {
   242  					return testutil.Err
   243  				},
   244  			},
   245  			Args:      args("vcl snippet delete --name foobar --service-id 123 --version 3"),
   246  			WantError: testutil.Err.Error(),
   247  		},
   248  		{
   249  			Name: "validate DeleteSnippet API success",
   250  			API: mock.API{
   251  				ListVersionsFn: testutil.ListVersions,
   252  				DeleteSnippetFn: func(i *fastly.DeleteSnippetInput) error {
   253  					return nil
   254  				},
   255  			},
   256  			Args:       args("vcl snippet delete --name foobar --service-id 123 --version 3"),
   257  			WantOutput: "Deleted VCL snippet 'foobar' (service: 123, version: 3)",
   258  		},
   259  		{
   260  			Name: "validate --autoclone results in cloned service version",
   261  			API: mock.API{
   262  				ListVersionsFn: testutil.ListVersions,
   263  				CloneVersionFn: testutil.CloneVersionResult(4),
   264  				DeleteSnippetFn: func(i *fastly.DeleteSnippetInput) error {
   265  					return nil
   266  				},
   267  			},
   268  			Args:       args("vcl snippet delete --autoclone --name foo --service-id 123 --version 1"),
   269  			WantOutput: "Deleted VCL snippet 'foo' (service: 123, version: 4)",
   270  		},
   271  	}
   272  
   273  	for testcaseIdx := range scenarios {
   274  		testcase := &scenarios[testcaseIdx]
   275  		t.Run(testcase.Name, func(t *testing.T) {
   276  			var stdout bytes.Buffer
   277  			app.Init = func(_ []string, _ io.Reader) (*global.Data, error) {
   278  				opts := testutil.MockGlobalData(testcase.Args, &stdout)
   279  				opts.APIClientFactory = mock.APIClient(testcase.API)
   280  				return opts, nil
   281  			}
   282  			err := app.Run(testcase.Args, nil)
   283  			testutil.AssertErrorContains(t, err, testcase.WantError)
   284  			testutil.AssertStringContains(t, stdout.String(), testcase.WantOutput)
   285  		})
   286  	}
   287  }
   288  
   289  func TestVCLSnippetDescribe(t *testing.T) {
   290  	args := testutil.Args
   291  	scenarios := []testutil.TestScenario{
   292  		{
   293  			Name:      "validate missing --version flag",
   294  			Args:      args("vcl snippet describe"),
   295  			WantError: "error parsing arguments: required flag --version not provided",
   296  		},
   297  		{
   298  			Name:      "validate missing --service-id flag",
   299  			Args:      args("vcl snippet describe --version 3"),
   300  			WantError: "error reading service: no service ID found",
   301  		},
   302  		{
   303  			Name: "validate missing --name flag with versioned snippet",
   304  			API: mock.API{
   305  				ListVersionsFn: testutil.ListVersions,
   306  			},
   307  			Args:      args("vcl snippet describe --service-id 123 --version 3"),
   308  			WantError: "error parsing arguments: must provide --name with a versioned VCL snippet",
   309  		},
   310  		{
   311  			Name: "validate missing --snippet-id flag with dynamic snippet",
   312  			API: mock.API{
   313  				ListVersionsFn: testutil.ListVersions,
   314  			},
   315  			Args:      args("vcl snippet describe --dynamic --service-id 123 --version 3"),
   316  			WantError: "error parsing arguments: must provide --snippet-id with a dynamic VCL snippet",
   317  		},
   318  		{
   319  			Name: "validate GetSnippet API error",
   320  			API: mock.API{
   321  				ListVersionsFn: testutil.ListVersions,
   322  				GetSnippetFn: func(i *fastly.GetSnippetInput) (*fastly.Snippet, error) {
   323  					return nil, testutil.Err
   324  				},
   325  			},
   326  			Args:      args("vcl snippet describe --name foobar --service-id 123 --version 3"),
   327  			WantError: testutil.Err.Error(),
   328  		},
   329  		{
   330  			Name: "validate GetSnippet API success",
   331  			API: mock.API{
   332  				ListVersionsFn: testutil.ListVersions,
   333  				GetSnippetFn:   getSnippet,
   334  			},
   335  			Args:       args("vcl snippet describe --name foobar --service-id 123 --version 3"),
   336  			WantOutput: "\nService ID: 123\nService Version: 3\n\nName: foobar\nID: 456\nPriority: 0\nDynamic: false\nType: recv\nContent: \n# some vcl content\nCreated at: 2021-06-15 23:00:00 +0000 UTC\nUpdated at: 2021-06-15 23:00:00 +0000 UTC\nDeleted at: 2021-06-15 23:00:00 +0000 UTC\n",
   337  		},
   338  		{
   339  			Name: "validate missing --autoclone flag is OK",
   340  			API: mock.API{
   341  				ListVersionsFn: testutil.ListVersions,
   342  				GetSnippetFn:   getSnippet,
   343  			},
   344  			Args:       args("vcl snippet describe --name foobar --service-id 123 --version 1"),
   345  			WantOutput: "\nService ID: 123\nService Version: 1\n\nName: foobar\nID: 456\nPriority: 0\nDynamic: false\nType: recv\nContent: \n# some vcl content\nCreated at: 2021-06-15 23:00:00 +0000 UTC\nUpdated at: 2021-06-15 23:00:00 +0000 UTC\nDeleted at: 2021-06-15 23:00:00 +0000 UTC\n",
   346  		},
   347  		{
   348  			Name: "validate dynamic GetSnippet API success",
   349  			API: mock.API{
   350  				ListVersionsFn:      testutil.ListVersions,
   351  				GetDynamicSnippetFn: getDynamicSnippet,
   352  			},
   353  			Args:       args("vcl snippet describe --dynamic --service-id 123 --snippet-id 456 --version 3"),
   354  			WantOutput: "\nService ID: 123\nID: 456\nContent: \n# some vcl content\nCreated at: 2021-06-15 23:00:00 +0000 UTC\nUpdated at: 2021-06-15 23:00:00 +0000 UTC\n",
   355  		},
   356  	}
   357  
   358  	for testcaseIdx := range scenarios {
   359  		testcase := &scenarios[testcaseIdx]
   360  		t.Run(testcase.Name, func(t *testing.T) {
   361  			var stdout bytes.Buffer
   362  			app.Init = func(_ []string, _ io.Reader) (*global.Data, error) {
   363  				opts := testutil.MockGlobalData(testcase.Args, &stdout)
   364  				opts.APIClientFactory = mock.APIClient(testcase.API)
   365  				return opts, nil
   366  			}
   367  			err := app.Run(testcase.Args, nil)
   368  			testutil.AssertErrorContains(t, err, testcase.WantError)
   369  			testutil.AssertStringContains(t, stdout.String(), testcase.WantOutput)
   370  		})
   371  	}
   372  }
   373  
   374  func TestVCLSnippetList(t *testing.T) {
   375  	args := testutil.Args
   376  	scenarios := []testutil.TestScenario{
   377  		{
   378  			Name:      "validate missing --version flag",
   379  			Args:      args("vcl snippet list"),
   380  			WantError: "error parsing arguments: required flag --version not provided",
   381  		},
   382  		{
   383  			Name:      "validate missing --service-id flag",
   384  			Args:      args("vcl snippet list --version 3"),
   385  			WantError: "error reading service: no service ID found",
   386  		},
   387  		{
   388  			Name: "validate ListSnippets API error",
   389  			API: mock.API{
   390  				ListVersionsFn: testutil.ListVersions,
   391  				ListSnippetsFn: func(i *fastly.ListSnippetsInput) ([]*fastly.Snippet, error) {
   392  					return nil, testutil.Err
   393  				},
   394  			},
   395  			Args:      args("vcl snippet list --service-id 123 --version 3"),
   396  			WantError: testutil.Err.Error(),
   397  		},
   398  		{
   399  			Name: "validate ListSnippets API success",
   400  			API: mock.API{
   401  				ListVersionsFn: testutil.ListVersions,
   402  				ListSnippetsFn: listSnippets,
   403  			},
   404  			Args:       args("vcl snippet list --service-id 123 --version 3"),
   405  			WantOutput: "SERVICE ID  VERSION  NAME  DYNAMIC  SNIPPET ID\n123         3        foo   true     abc\n123         3        bar   false    abc\n",
   406  		},
   407  		{
   408  			Name: "validate missing --autoclone flag is OK",
   409  			API: mock.API{
   410  				ListVersionsFn: testutil.ListVersions,
   411  				ListSnippetsFn: listSnippets,
   412  			},
   413  			Args:       args("vcl snippet list --service-id 123 --version 1"),
   414  			WantOutput: "SERVICE ID  VERSION  NAME  DYNAMIC  SNIPPET ID\n123         1        foo   true     abc\n123         1        bar   false    abc\n",
   415  		},
   416  		{
   417  			Name: "validate missing --verbose flag",
   418  			API: mock.API{
   419  				ListVersionsFn: testutil.ListVersions,
   420  				ListSnippetsFn: listSnippets,
   421  			},
   422  			Args:       args("vcl snippet list --service-id 123 --verbose --version 1"),
   423  			WantOutput: "Fastly API endpoint: https://api.fastly.com\nFastly API token provided via config file (profile: user)\n\nService ID (via --service-id): 123\n\nService Version: 1\n\nName: foo\nID: abc\nPriority: 0\nDynamic: true\nType: recv\nContent: \n# some vcl content\nCreated at: 2021-06-15 23:00:00 +0000 UTC\nUpdated at: 2021-06-15 23:00:00 +0000 UTC\nDeleted at: 2021-06-15 23:00:00 +0000 UTC\n\nName: bar\nID: abc\nPriority: 0\nDynamic: false\nType: recv\nContent: \n# some vcl content\nCreated at: 2021-06-15 23:00:00 +0000 UTC\nUpdated at: 2021-06-15 23:00:00 +0000 UTC\nDeleted at: 2021-06-15 23:00:00 +0000 UTC\n",
   424  		},
   425  	}
   426  
   427  	for testcaseIdx := range scenarios {
   428  		testcase := &scenarios[testcaseIdx]
   429  		t.Run(testcase.Name, func(t *testing.T) {
   430  			var stdout bytes.Buffer
   431  			app.Init = func(_ []string, _ io.Reader) (*global.Data, error) {
   432  				opts := testutil.MockGlobalData(testcase.Args, &stdout)
   433  				opts.APIClientFactory = mock.APIClient(testcase.API)
   434  				return opts, nil
   435  			}
   436  			err := app.Run(testcase.Args, nil)
   437  			testutil.AssertErrorContains(t, err, testcase.WantError)
   438  			testutil.AssertStringContains(t, stdout.String(), testcase.WantOutput)
   439  		})
   440  	}
   441  }
   442  
   443  func TestVCLSnippetUpdate(t *testing.T) {
   444  	var content string
   445  	args := testutil.Args
   446  	scenarios := []testutil.TestScenario{
   447  		{
   448  			Name:      "validate missing --version flag",
   449  			Args:      args("vcl snippet update"),
   450  			WantError: "error parsing arguments: required flag --version not provided",
   451  		},
   452  		{
   453  			Name:      "validate missing --service-id flag",
   454  			Args:      args("vcl snippet update --version 3"),
   455  			WantError: "error reading service: no service ID found",
   456  		},
   457  		{
   458  			Name: "validate missing --autoclone flag",
   459  			API: mock.API{
   460  				ListVersionsFn: testutil.ListVersions,
   461  			},
   462  			Args:      args("vcl snippet update --service-id 123 --version 1"),
   463  			WantError: "service version 1 is not editable",
   464  		},
   465  		{
   466  			Name: "validate versioned snippet missing --name",
   467  			API: mock.API{
   468  				ListVersionsFn: testutil.ListVersions,
   469  			},
   470  			Args:      args("vcl snippet update --content inline_vcl --new-name bar --service-id 123 --type recv --version 3"),
   471  			WantError: "error parsing arguments: must provide --name to update a versioned VCL snippet",
   472  		},
   473  		{
   474  			Name: "validate dynamic snippet missing --snippet-id",
   475  			API: mock.API{
   476  				ListVersionsFn: testutil.ListVersions,
   477  			},
   478  			Args:      args("vcl snippet update --content inline_vcl --dynamic --service-id 123 --version 3"),
   479  			WantError: "error parsing arguments: must provide --snippet-id to update a dynamic VCL snippet",
   480  		},
   481  		{
   482  			Name: "validate versioned snippet with --snippet-id is not allowed",
   483  			API: mock.API{
   484  				ListVersionsFn: testutil.ListVersions,
   485  			},
   486  			Args:      args("vcl snippet update --content inline_vcl --new-name foobar --service-id 123 --snippet-id 456 --version 3"),
   487  			WantError: "error parsing arguments: --snippet-id is not supported when updating a versioned VCL snippet",
   488  		},
   489  		{
   490  			Name: "validate dynamic snippet with --new-name is not allowed",
   491  			API: mock.API{
   492  				ListVersionsFn: testutil.ListVersions,
   493  			},
   494  			Args:      args("vcl snippet update --content inline_vcl --dynamic --new-name foobar --service-id 123 --snippet-id 456 --version 3"),
   495  			WantError: "error parsing arguments: --new-name is not supported when updating a dynamic VCL snippet",
   496  		},
   497  		{
   498  			Name: "validate UpdateSnippet API error",
   499  			API: mock.API{
   500  				ListVersionsFn: testutil.ListVersions,
   501  				UpdateSnippetFn: func(i *fastly.UpdateSnippetInput) (*fastly.Snippet, error) {
   502  					return nil, testutil.Err
   503  				},
   504  			},
   505  			Args:      args("vcl snippet update --content inline_vcl --name foo --new-name bar --service-id 123 --type recv --version 3"),
   506  			WantError: testutil.Err.Error(),
   507  		},
   508  		{
   509  			Name: "validate UpdateSnippet API success",
   510  			API: mock.API{
   511  				ListVersionsFn: testutil.ListVersions,
   512  				UpdateSnippetFn: func(i *fastly.UpdateSnippetInput) (*fastly.Snippet, error) {
   513  					// Track the contents parsed
   514  					content = *i.Content
   515  
   516  					return &fastly.Snippet{
   517  						Content:        i.Content,
   518  						Name:           i.NewName,
   519  						Priority:       fastly.ToPointer(100),
   520  						ServiceID:      fastly.ToPointer(i.ServiceID),
   521  						ServiceVersion: fastly.ToPointer(i.ServiceVersion),
   522  						Type:           i.Type,
   523  					}, nil
   524  				},
   525  			},
   526  			Args:       args("vcl snippet update --content inline_vcl --name foo --new-name bar --service-id 123 --type recv --version 3"),
   527  			WantOutput: "Updated VCL snippet 'bar' (previously: 'foo', service: 123, version: 3, type: recv, priority: 100)",
   528  		},
   529  		{
   530  			Name: "validate UpdateDynamicSnippet API success",
   531  			API: mock.API{
   532  				ListVersionsFn: testutil.ListVersions,
   533  				UpdateDynamicSnippetFn: func(i *fastly.UpdateDynamicSnippetInput) (*fastly.DynamicSnippet, error) {
   534  					// Track the contents parsed
   535  					content = *i.Content
   536  
   537  					return &fastly.DynamicSnippet{
   538  						Content:   i.Content,
   539  						SnippetID: fastly.ToPointer(i.SnippetID),
   540  						ServiceID: fastly.ToPointer(i.ServiceID),
   541  					}, nil
   542  				},
   543  			},
   544  			Args:       args("vcl snippet update --content inline_vcl --dynamic --service-id 123 --snippet-id 456 --version 3"),
   545  			WantOutput: "Updated dynamic VCL snippet '456' (service: 123)",
   546  		},
   547  		{
   548  			Name: "validate --autoclone results in cloned service version",
   549  			API: mock.API{
   550  				ListVersionsFn: testutil.ListVersions,
   551  				CloneVersionFn: testutil.CloneVersionResult(4),
   552  				UpdateSnippetFn: func(i *fastly.UpdateSnippetInput) (*fastly.Snippet, error) {
   553  					// Track the contents parsed
   554  					content = *i.Content
   555  
   556  					return &fastly.Snippet{
   557  						Content:        i.Content,
   558  						Name:           i.NewName,
   559  						Priority:       i.Priority,
   560  						ServiceID:      fastly.ToPointer(i.ServiceID),
   561  						ServiceVersion: fastly.ToPointer(i.ServiceVersion),
   562  						Type:           i.Type,
   563  					}, nil
   564  				},
   565  			},
   566  			Args:       args("vcl snippet update --autoclone --content inline_vcl --name foo --new-name bar --priority 1 --service-id 123 --type recv --version 1"),
   567  			WantOutput: "Updated VCL snippet 'bar' (previously: 'foo', service: 123, version: 4, type: recv, priority: 1)",
   568  		},
   569  	}
   570  
   571  	for testcaseIdx := range scenarios {
   572  		testcase := &scenarios[testcaseIdx]
   573  		t.Run(testcase.Name, func(t *testing.T) {
   574  			var stdout bytes.Buffer
   575  			app.Init = func(_ []string, _ io.Reader) (*global.Data, error) {
   576  				opts := testutil.MockGlobalData(testcase.Args, &stdout)
   577  				opts.APIClientFactory = mock.APIClient(testcase.API)
   578  				return opts, nil
   579  			}
   580  			err := app.Run(testcase.Args, nil)
   581  			testutil.AssertErrorContains(t, err, testcase.WantError)
   582  			testutil.AssertStringContains(t, testutil.StripNewLines(stdout.String()), testcase.WantOutput)
   583  			testutil.AssertPathContentFlag("content", testcase.WantError, testcase.Args, "snippet.vcl", content, t)
   584  		})
   585  	}
   586  }
   587  
   588  func getSnippet(i *fastly.GetSnippetInput) (*fastly.Snippet, error) {
   589  	t := testutil.Date
   590  
   591  	return &fastly.Snippet{
   592  		Content:        fastly.ToPointer("# some vcl content"),
   593  		Dynamic:        fastly.ToPointer(0),
   594  		SnippetID:      fastly.ToPointer("456"),
   595  		Name:           fastly.ToPointer(i.Name),
   596  		Priority:       fastly.ToPointer(0),
   597  		ServiceID:      fastly.ToPointer(i.ServiceID),
   598  		ServiceVersion: fastly.ToPointer(i.ServiceVersion),
   599  		Type:           fastly.ToPointer(fastly.SnippetTypeRecv),
   600  
   601  		CreatedAt: &t,
   602  		DeletedAt: &t,
   603  		UpdatedAt: &t,
   604  	}, nil
   605  }
   606  
   607  func getDynamicSnippet(i *fastly.GetDynamicSnippetInput) (*fastly.DynamicSnippet, error) {
   608  	t := testutil.Date
   609  
   610  	return &fastly.DynamicSnippet{
   611  		Content:   fastly.ToPointer("# some vcl content"),
   612  		SnippetID: fastly.ToPointer(i.SnippetID),
   613  		ServiceID: fastly.ToPointer(i.ServiceID),
   614  
   615  		CreatedAt: &t,
   616  		UpdatedAt: &t,
   617  	}, nil
   618  }
   619  
   620  func listSnippets(i *fastly.ListSnippetsInput) ([]*fastly.Snippet, error) {
   621  	t := testutil.Date
   622  	vs := []*fastly.Snippet{
   623  		{
   624  			Content:        fastly.ToPointer("# some vcl content"),
   625  			Dynamic:        fastly.ToPointer(1),
   626  			SnippetID:      fastly.ToPointer("abc"),
   627  			Name:           fastly.ToPointer("foo"),
   628  			Priority:       fastly.ToPointer(0),
   629  			ServiceID:      fastly.ToPointer(i.ServiceID),
   630  			ServiceVersion: fastly.ToPointer(i.ServiceVersion),
   631  			Type:           fastly.ToPointer(fastly.SnippetTypeRecv),
   632  
   633  			CreatedAt: &t,
   634  			DeletedAt: &t,
   635  			UpdatedAt: &t,
   636  		},
   637  		{
   638  			Content:        fastly.ToPointer("# some vcl content"),
   639  			Dynamic:        fastly.ToPointer(0),
   640  			SnippetID:      fastly.ToPointer("abc"),
   641  			Name:           fastly.ToPointer("bar"),
   642  			Priority:       fastly.ToPointer(0),
   643  			ServiceID:      fastly.ToPointer(i.ServiceID),
   644  			ServiceVersion: fastly.ToPointer(i.ServiceVersion),
   645  			Type:           fastly.ToPointer(fastly.SnippetTypeRecv),
   646  
   647  			CreatedAt: &t,
   648  			DeletedAt: &t,
   649  			UpdatedAt: &t,
   650  		},
   651  	}
   652  	return vs, nil
   653  }