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

     1  package condition_test
     2  
     3  import (
     4  	"bytes"
     5  	"errors"
     6  	"io"
     7  	"strings"
     8  	"testing"
     9  
    10  	"github.com/fastly/go-fastly/v9/fastly"
    11  
    12  	"github.com/fastly/cli/pkg/app"
    13  	"github.com/fastly/cli/pkg/global"
    14  	"github.com/fastly/cli/pkg/mock"
    15  	"github.com/fastly/cli/pkg/testutil"
    16  )
    17  
    18  func TestConditionCreate(t *testing.T) {
    19  	args := testutil.Args
    20  	scenarios := []testutil.TestScenario{
    21  		{
    22  			Args:      args("vcl condition create --version 1"),
    23  			WantError: "error reading service: no service ID found",
    24  		},
    25  		{
    26  			Args: args("vcl condition create --service-id 123 --version 1 --name always_false --statement false --type REQUEST --autoclone"),
    27  			API: mock.API{
    28  				ListVersionsFn:    testutil.ListVersions,
    29  				CloneVersionFn:    testutil.CloneVersionResult(4),
    30  				CreateConditionFn: createConditionOK,
    31  			},
    32  			WantOutput: "Created condition always_false (service 123 version 4)",
    33  		},
    34  		{
    35  			Args: args("vcl condition create --service-id 123 --version 1 --name always_false --statement false --type REQUEST --priority 10 --autoclone"),
    36  			API: mock.API{
    37  				ListVersionsFn:    testutil.ListVersions,
    38  				CloneVersionFn:    testutil.CloneVersionResult(4),
    39  				CreateConditionFn: createConditionError,
    40  			},
    41  			WantError: errTest.Error(),
    42  		},
    43  	}
    44  
    45  	for _, testcase := range scenarios {
    46  		t.Run(testcase.Name, func(t *testing.T) {
    47  			var stdout bytes.Buffer
    48  			app.Init = func(_ []string, _ io.Reader) (*global.Data, error) {
    49  				opts := testutil.MockGlobalData(testcase.Args, &stdout)
    50  				opts.APIClientFactory = mock.APIClient(testcase.API)
    51  				return opts, nil
    52  			}
    53  			err := app.Run(testcase.Args, nil)
    54  			testutil.AssertErrorContains(t, err, testcase.WantError)
    55  			testutil.AssertStringContains(t, stdout.String(), testcase.WantOutput)
    56  		})
    57  	}
    58  }
    59  
    60  func TestConditionDelete(t *testing.T) {
    61  	args := testutil.Args
    62  	scenarios := []testutil.TestScenario{
    63  		{
    64  			Args:      args("vcl condition delete --service-id 123 --version 1"),
    65  			WantError: "error parsing arguments: required flag --name not provided",
    66  		},
    67  		{
    68  			Args: args("vcl condition delete --service-id 123 --version 1 --name always_false --autoclone"),
    69  			API: mock.API{
    70  				ListVersionsFn:    testutil.ListVersions,
    71  				CloneVersionFn:    testutil.CloneVersionResult(4),
    72  				DeleteConditionFn: deleteConditionError,
    73  			},
    74  			WantError: errTest.Error(),
    75  		},
    76  		{
    77  			Args: args("vcl condition delete --service-id 123 --version 1 --name always_false --autoclone"),
    78  			API: mock.API{
    79  				ListVersionsFn:    testutil.ListVersions,
    80  				CloneVersionFn:    testutil.CloneVersionResult(4),
    81  				DeleteConditionFn: deleteConditionOK,
    82  			},
    83  			WantOutput: "Deleted condition always_false (service 123 version 4)",
    84  		},
    85  	}
    86  	for testcaseIdx := range scenarios {
    87  		testcase := &scenarios[testcaseIdx]
    88  		t.Run(testcase.Name, func(t *testing.T) {
    89  			var stdout bytes.Buffer
    90  			app.Init = func(_ []string, _ io.Reader) (*global.Data, error) {
    91  				opts := testutil.MockGlobalData(testcase.Args, &stdout)
    92  				opts.APIClientFactory = mock.APIClient(testcase.API)
    93  				return opts, nil
    94  			}
    95  			err := app.Run(testcase.Args, nil)
    96  			testutil.AssertErrorContains(t, err, testcase.WantError)
    97  			testutil.AssertStringContains(t, stdout.String(), testcase.WantOutput)
    98  		})
    99  	}
   100  }
   101  
   102  func TestConditionUpdate(t *testing.T) {
   103  	args := testutil.Args
   104  	scenarios := []testutil.TestScenario{
   105  		{
   106  			Args:      args("vcl condition update --service-id 123 --version 1 --new-name false_always --comment "),
   107  			WantError: "error parsing arguments: required flag --name not provided",
   108  		},
   109  		{
   110  			Args: args("vcl condition update --service-id 123 --version 1 --name always_false --autoclone"),
   111  			API: mock.API{
   112  				ListVersionsFn:    testutil.ListVersions,
   113  				CloneVersionFn:    testutil.CloneVersionResult(4),
   114  				UpdateConditionFn: updateConditionOK,
   115  			},
   116  			WantError: "error parsing arguments: must provide either --new-name, --statement, --type or --priority to update condition",
   117  		},
   118  		{
   119  			Args: args("vcl condition update --service-id 123 --version 1 --name always_false --new-name false_always --autoclone"),
   120  			API: mock.API{
   121  				ListVersionsFn:    testutil.ListVersions,
   122  				CloneVersionFn:    testutil.CloneVersionResult(4),
   123  				UpdateConditionFn: updateConditionError,
   124  			},
   125  			WantError: errTest.Error(),
   126  		},
   127  		{
   128  			Args: args("vcl condition update --service-id 123 --version 1 --name always_false --new-name false_always --autoclone"),
   129  			API: mock.API{
   130  				ListVersionsFn:    testutil.ListVersions,
   131  				CloneVersionFn:    testutil.CloneVersionResult(4),
   132  				UpdateConditionFn: updateConditionOK,
   133  			},
   134  			WantOutput: "Updated condition false_always (service 123 version 4)",
   135  		},
   136  	}
   137  	for testcaseIdx := range scenarios {
   138  		testcase := &scenarios[testcaseIdx]
   139  		t.Run(testcase.Name, func(t *testing.T) {
   140  			var stdout bytes.Buffer
   141  			app.Init = func(_ []string, _ io.Reader) (*global.Data, error) {
   142  				opts := testutil.MockGlobalData(testcase.Args, &stdout)
   143  				opts.APIClientFactory = mock.APIClient(testcase.API)
   144  				return opts, nil
   145  			}
   146  			err := app.Run(testcase.Args, nil)
   147  			testutil.AssertErrorContains(t, err, testcase.WantError)
   148  			testutil.AssertStringContains(t, stdout.String(), testcase.WantOutput)
   149  		})
   150  	}
   151  }
   152  
   153  func TestConditionDescribe(t *testing.T) {
   154  	args := testutil.Args
   155  	scenarios := []testutil.TestScenario{
   156  		{
   157  			Args:      args("vcl condition describe --service-id 123 --version 1"),
   158  			WantError: "error parsing arguments: required flag --name not provided",
   159  		},
   160  		{
   161  			Args: args("vcl condition describe --service-id 123 --version 1 --name always_false"),
   162  			API: mock.API{
   163  				ListVersionsFn: testutil.ListVersions,
   164  				GetConditionFn: getConditionError,
   165  			},
   166  			WantError: errTest.Error(),
   167  		},
   168  		{
   169  			Args: args("vcl condition describe --service-id 123 --version 1 --name always_false"),
   170  			API: mock.API{
   171  				ListVersionsFn: testutil.ListVersions,
   172  				GetConditionFn: getConditionOK,
   173  			},
   174  			WantOutput: describeConditionOutput,
   175  		},
   176  	}
   177  	for testcaseIdx := range scenarios {
   178  		testcase := &scenarios[testcaseIdx]
   179  		t.Run(testcase.Name, func(t *testing.T) {
   180  			var stdout bytes.Buffer
   181  			app.Init = func(_ []string, _ io.Reader) (*global.Data, error) {
   182  				opts := testutil.MockGlobalData(testcase.Args, &stdout)
   183  				opts.APIClientFactory = mock.APIClient(testcase.API)
   184  				return opts, nil
   185  			}
   186  			err := app.Run(testcase.Args, nil)
   187  			testutil.AssertErrorContains(t, err, testcase.WantError)
   188  			testutil.AssertString(t, testcase.WantOutput, stdout.String())
   189  		})
   190  	}
   191  }
   192  
   193  func TestConditionList(t *testing.T) {
   194  	args := testutil.Args
   195  	scenarios := []testutil.TestScenario{
   196  		{
   197  			Args: args("vcl condition list --service-id 123 --version 1"),
   198  			API: mock.API{
   199  				ListVersionsFn:   testutil.ListVersions,
   200  				ListConditionsFn: listConditionsOK,
   201  			},
   202  			WantOutput: listConditionsShortOutput,
   203  		},
   204  		{
   205  			Args: args("vcl condition list --service-id 123 --version 1 --verbose"),
   206  			API: mock.API{
   207  				ListVersionsFn:   testutil.ListVersions,
   208  				ListConditionsFn: listConditionsOK,
   209  			},
   210  			WantOutput: listConditionsVerboseOutput,
   211  		},
   212  		{
   213  			Args: args("vcl condition list --service-id 123 --version 1 -v"),
   214  			API: mock.API{
   215  				ListVersionsFn:   testutil.ListVersions,
   216  				ListConditionsFn: listConditionsOK,
   217  			},
   218  			WantOutput: listConditionsVerboseOutput,
   219  		},
   220  		{
   221  			Args: args("vcl condition --verbose list --service-id 123 --version 1"),
   222  			API: mock.API{
   223  				ListVersionsFn:   testutil.ListVersions,
   224  				ListConditionsFn: listConditionsOK,
   225  			},
   226  			WantOutput: listConditionsVerboseOutput,
   227  		},
   228  		{
   229  			Args: args("-v vcl condition list --service-id 123 --version 1"),
   230  			API: mock.API{
   231  				ListVersionsFn:   testutil.ListVersions,
   232  				ListConditionsFn: listConditionsOK,
   233  			},
   234  			WantOutput: listConditionsVerboseOutput,
   235  		},
   236  		{
   237  			Args: args("vcl condition list --service-id 123 --version 1"),
   238  			API: mock.API{
   239  				ListVersionsFn:   testutil.ListVersions,
   240  				ListConditionsFn: listConditionsError,
   241  			},
   242  			WantError: errTest.Error(),
   243  		},
   244  	}
   245  	for testcaseIdx := range scenarios {
   246  		testcase := &scenarios[testcaseIdx]
   247  		t.Run(testcase.Name, func(t *testing.T) {
   248  			var stdout bytes.Buffer
   249  			app.Init = func(_ []string, _ io.Reader) (*global.Data, error) {
   250  				opts := testutil.MockGlobalData(testcase.Args, &stdout)
   251  				opts.APIClientFactory = mock.APIClient(testcase.API)
   252  				return opts, nil
   253  			}
   254  			err := app.Run(testcase.Args, nil)
   255  			testutil.AssertErrorContains(t, err, testcase.WantError)
   256  			testutil.AssertString(t, testcase.WantOutput, stdout.String())
   257  		})
   258  	}
   259  }
   260  
   261  var describeConditionOutput = "\n" + strings.TrimSpace(`
   262  Service ID: 123
   263  Version: 1
   264  Name: always_false
   265  Statement: false
   266  Type: CACHE
   267  Priority: 10
   268  `) + "\n"
   269  
   270  var listConditionsShortOutput = strings.TrimSpace(`
   271  SERVICE  VERSION  NAME                  STATEMENT  TYPE     PRIORITY
   272  123      1        always_false_request  false      REQUEST  10
   273  123      1        always_false_cache    false      CACHE    10
   274  `) + "\n"
   275  
   276  var listConditionsVerboseOutput = strings.TrimSpace(`
   277  Fastly API endpoint: https://api.fastly.com
   278  Fastly API token provided via config file (profile: user)
   279  
   280  Service ID (via --service-id): 123
   281  
   282  Version: 1
   283  	Condition 1/2
   284  		Name: always_false_request
   285  		Statement: false
   286  		Type: REQUEST
   287  		Priority: 10
   288  	Condition 2/2
   289  		Name: always_false_cache
   290  		Statement: false
   291  		Type: CACHE
   292  		Priority: 10
   293  `) + "\n\n"
   294  
   295  var errTest = errors.New("fixture error")
   296  
   297  func createConditionOK(i *fastly.CreateConditionInput) (*fastly.Condition, error) {
   298  	priority := 10
   299  	if i.Priority != nil {
   300  		priority = *i.Priority
   301  	}
   302  
   303  	conditionType := "REQUEST"
   304  	if i.Type != nil {
   305  		conditionType = *i.Type
   306  	}
   307  
   308  	return &fastly.Condition{
   309  		ServiceID:      fastly.ToPointer(i.ServiceID),
   310  		ServiceVersion: fastly.ToPointer(i.ServiceVersion),
   311  		Name:           i.Name,
   312  		Statement:      i.Statement,
   313  		Type:           fastly.ToPointer(conditionType),
   314  		Priority:       fastly.ToPointer(priority),
   315  	}, nil
   316  }
   317  
   318  func createConditionError(_ *fastly.CreateConditionInput) (*fastly.Condition, error) {
   319  	return nil, errTest
   320  }
   321  
   322  func deleteConditionOK(_ *fastly.DeleteConditionInput) error {
   323  	return nil
   324  }
   325  
   326  func deleteConditionError(_ *fastly.DeleteConditionInput) error {
   327  	return errTest
   328  }
   329  
   330  func updateConditionOK(i *fastly.UpdateConditionInput) (*fastly.Condition, error) {
   331  	priority := 10
   332  	if i.Priority != nil {
   333  		priority = *i.Priority
   334  	}
   335  
   336  	conditionType := "REQUEST"
   337  	if i.Type != nil {
   338  		conditionType = *i.Type
   339  	}
   340  
   341  	statement := "false"
   342  	if i.Statement != nil {
   343  		statement = *i.Type
   344  	}
   345  
   346  	return &fastly.Condition{
   347  		ServiceID:      fastly.ToPointer(i.ServiceID),
   348  		ServiceVersion: fastly.ToPointer(i.ServiceVersion),
   349  		Name:           fastly.ToPointer(i.Name),
   350  		Statement:      fastly.ToPointer(statement),
   351  		Type:           fastly.ToPointer(conditionType),
   352  		Priority:       fastly.ToPointer(priority),
   353  	}, nil
   354  }
   355  
   356  func updateConditionError(_ *fastly.UpdateConditionInput) (*fastly.Condition, error) {
   357  	return nil, errTest
   358  }
   359  
   360  func getConditionOK(i *fastly.GetConditionInput) (*fastly.Condition, error) {
   361  	priority := 10
   362  	conditionType := "CACHE"
   363  	statement := "false"
   364  
   365  	return &fastly.Condition{
   366  		ServiceID:      fastly.ToPointer(i.ServiceID),
   367  		ServiceVersion: fastly.ToPointer(i.ServiceVersion),
   368  		Name:           fastly.ToPointer(i.Name),
   369  		Statement:      fastly.ToPointer(statement),
   370  		Type:           fastly.ToPointer(conditionType),
   371  		Priority:       fastly.ToPointer(priority),
   372  	}, nil
   373  }
   374  
   375  func getConditionError(_ *fastly.GetConditionInput) (*fastly.Condition, error) {
   376  	return nil, errTest
   377  }
   378  
   379  func listConditionsOK(i *fastly.ListConditionsInput) ([]*fastly.Condition, error) {
   380  	return []*fastly.Condition{
   381  		{
   382  			ServiceID:      fastly.ToPointer(i.ServiceID),
   383  			ServiceVersion: fastly.ToPointer(i.ServiceVersion),
   384  			Name:           fastly.ToPointer("always_false_request"),
   385  			Statement:      fastly.ToPointer("false"),
   386  			Type:           fastly.ToPointer("REQUEST"),
   387  			Priority:       fastly.ToPointer(10),
   388  		},
   389  		{
   390  			ServiceID:      fastly.ToPointer(i.ServiceID),
   391  			ServiceVersion: fastly.ToPointer(i.ServiceVersion),
   392  			Name:           fastly.ToPointer("always_false_cache"),
   393  			Statement:      fastly.ToPointer("false"),
   394  			Type:           fastly.ToPointer("CACHE"),
   395  			Priority:       fastly.ToPointer(10),
   396  		},
   397  	}, nil
   398  }
   399  
   400  func listConditionsError(_ *fastly.ListConditionsInput) ([]*fastly.Condition, error) {
   401  	return nil, errTest
   402  }