github.com/ActiveState/cli@v0.0.0-20240508170324-6801f60cd051/test/integration/update_lock_int_test.go (about)

     1  package integration
     2  
     3  import (
     4  	"fmt"
     5  	"os"
     6  	"path/filepath"
     7  	"regexp"
     8  
     9  	"github.com/ActiveState/cli/internal/config"
    10  	"github.com/ActiveState/cli/internal/constants"
    11  	"github.com/ActiveState/cli/internal/fileutils"
    12  	"github.com/ActiveState/cli/internal/rtutils/singlethread"
    13  	"github.com/ActiveState/cli/internal/testhelpers/e2e"
    14  	"github.com/ActiveState/cli/internal/testhelpers/tagsuite"
    15  	"github.com/ActiveState/cli/pkg/projectfile"
    16  )
    17  
    18  func (suite *UpdateIntegrationTestSuite) TestLocked() {
    19  	suite.OnlyRunForTags(tagsuite.Update)
    20  	suite.T().Skip("Requires https://www.pivotaltracker.com/story/show/177827538 and needs to be adapted.")
    21  	pjfile := projectfile.Project{
    22  		Project: lockedProjectURL(),
    23  	}
    24  	ts := e2e.New(suite.T(), false)
    25  	defer ts.Close()
    26  
    27  	cfg, err := config.NewCustom(ts.Dirs.Config, singlethread.New(), true)
    28  	suite.Require().NoError(err)
    29  	defer cfg.Close()
    30  
    31  	pjfile.SetPath(filepath.Join(ts.Dirs.Work, constants.ConfigFileName))
    32  	err = pjfile.Save(cfg)
    33  	suite.Require().NoError(err)
    34  
    35  	cp := ts.SpawnWithOpts(
    36  		e2e.OptArgs("update", "lock"),
    37  		e2e.OptAppendEnv(suite.env(false, false)...),
    38  	)
    39  
    40  	cp.Expect("Version locked at")
    41  	cp.ExpectExitCode(0)
    42  
    43  	suite.versionCompare(ts, constants.Version, suite.NotEqual)
    44  }
    45  
    46  func (suite *UpdateIntegrationTestSuite) TestLockedChannel() {
    47  	suite.OnlyRunForTags(tagsuite.Update)
    48  	targetBranch := "release"
    49  	if constants.ChannelName == "release" {
    50  		targetBranch = "master"
    51  	}
    52  	tests := []struct {
    53  		name            string
    54  		lock            string
    55  		expectLockError bool
    56  		expectedChannel string
    57  	}{
    58  		{
    59  			"oldVersion",
    60  			oldUpdateVersion,
    61  			true,
    62  			"beta",
    63  		},
    64  		{
    65  			"channel",
    66  			targetBranch,
    67  			true,
    68  			targetBranch,
    69  		},
    70  		{
    71  			"locked-multi-file-version",
    72  			fmt.Sprintf("%s@0.29.0-SHA000000", targetBranch),
    73  			true,
    74  			targetBranch,
    75  		},
    76  	}
    77  
    78  	for _, tt := range tests {
    79  		suite.Run(tt.name, func() {
    80  			pjfile := projectfile.Project{
    81  				Project: lockedProjectURL(),
    82  			}
    83  			ts := e2e.New(suite.T(), false)
    84  			defer ts.Close()
    85  
    86  			cfg, err := config.NewCustom(ts.Dirs.Config, singlethread.New(), true)
    87  			suite.Require().NoError(err)
    88  			defer cfg.Close()
    89  
    90  			yamlPath := filepath.Join(ts.Dirs.Work, constants.ConfigFileName)
    91  			pjfile.SetPath(yamlPath)
    92  			err = pjfile.Save(cfg)
    93  			suite.Require().NoError(err)
    94  
    95  			cp := ts.SpawnWithOpts(
    96  				e2e.OptArgs("update", "lock", "--set-channel", tt.lock),
    97  				e2e.OptAppendEnv(suite.env(false, false)...),
    98  			)
    99  			cp.Expect("Version locked at")
   100  			cp.Expect(tt.expectedChannel + "@")
   101  			cp.ExpectExitCode(0)
   102  
   103  			yamlContents, err := fileutils.ReadFile(yamlPath)
   104  			suite.Require().NoError(err)
   105  			suite.Contains(string(yamlContents), tt.lock)
   106  
   107  			if tt.expectLockError {
   108  				cp = ts.SpawnWithOpts(e2e.OptArgs("--version"), e2e.OptAppendEnv(suite.env(true, false)...))
   109  				cp.Expect("This project is locked at State Tool version")
   110  				cp.ExpectExitCode(1)
   111  				ts.IgnoreLogErrors()
   112  				return
   113  			}
   114  		})
   115  	}
   116  }
   117  
   118  func (suite *UpdateIntegrationTestSuite) TestUpdateLockedConfirmation() {
   119  	tests := []struct {
   120  		Name    string
   121  		Confirm bool
   122  		Forced  bool
   123  	}{
   124  		{"Negative", false, false},
   125  		{"Positive", true, false},
   126  		{"Forced", true, true},
   127  	}
   128  
   129  	for _, tt := range tests {
   130  		if tt.Forced || tt.Confirm {
   131  			suite.T().Skip("Requires https://www.pivotaltracker.com/story/show/177827538 and needs to be adapted.")
   132  		}
   133  		suite.Run(tt.Name, func() {
   134  			suite.OnlyRunForTags(tagsuite.Update)
   135  			pjfile := projectfile.Project{
   136  				Project: lockedProjectURL(),
   137  				Lock:    fmt.Sprintf("%s@%s", constants.ChannelName, constants.Version),
   138  			}
   139  
   140  			ts := e2e.New(suite.T(), false)
   141  			defer ts.Close()
   142  
   143  			cfg, err := config.NewCustom(ts.Dirs.Config, singlethread.New(), true)
   144  			suite.Require().NoError(err)
   145  			defer cfg.Close()
   146  
   147  			pjfile.SetPath(filepath.Join(ts.Dirs.Work, constants.ConfigFileName))
   148  			err = pjfile.Save(cfg)
   149  			suite.Require().NoError(err)
   150  
   151  			args := []string{"update", "lock"}
   152  			if tt.Forced {
   153  				args = append(args, "--non-interactive")
   154  			}
   155  			cp := ts.SpawnWithOpts(
   156  				e2e.OptArgs(args...),
   157  				e2e.OptAppendEnv(suite.env(true, true)...),
   158  			)
   159  			cp.Expect("sure you want")
   160  			if tt.Confirm || tt.Forced {
   161  				cp.SendLine("y")
   162  				cp.Expect("Version locked at")
   163  			} else {
   164  				cp.SendLine("n")
   165  				cp.Expect("Cancelling")
   166  			}
   167  			cp.ExpectNotExitCode(0)
   168  			ts.IgnoreLogErrors()
   169  		})
   170  	}
   171  }
   172  
   173  func (suite *UpdateIntegrationTestSuite) TestLockUnlock() {
   174  	suite.OnlyRunForTags(tagsuite.Update)
   175  
   176  	pjfile := projectfile.Project{
   177  		Project: lockedProjectURL(),
   178  	}
   179  	ts := e2e.New(suite.T(), false)
   180  	defer ts.Close()
   181  
   182  	cfg, err := config.New()
   183  	suite.Require().NoError(err)
   184  	defer cfg.Close()
   185  
   186  	pjfile.SetPath(filepath.Join(ts.Dirs.Work, constants.ConfigFileName))
   187  	err = pjfile.Save(cfg)
   188  	suite.Require().NoError(err)
   189  
   190  	cp := ts.SpawnWithOpts(
   191  		e2e.OptArgs("update", "lock", "--non-interactive"),
   192  		e2e.OptAppendEnv(suite.env(false, false)...),
   193  	)
   194  	cp.Expect("locked at")
   195  
   196  	data, err := os.ReadFile(pjfile.Path())
   197  	suite.Require().NoError(err)
   198  
   199  	lockRegex := regexp.MustCompile(`(?m)^lock:.*`)
   200  	suite.Assert().True(lockRegex.Match(data), "lock info was not written to "+pjfile.Path())
   201  
   202  	cp = ts.SpawnWithOpts(
   203  		e2e.OptArgs("update", "unlock", "-n"),
   204  		e2e.OptAppendEnv(suite.env(false, false)...),
   205  	)
   206  	cp.Expect("unlocked")
   207  
   208  	data, err = os.ReadFile(pjfile.Path())
   209  	suite.Require().NoError(err)
   210  	suite.Assert().False(lockRegex.Match(data), "lock info was not removed from "+pjfile.Path())
   211  	// Ignore log errors here as the project we are using in this test does not
   212  	// actually exist. So there will be some errors related to fetching the
   213  	// project into.
   214  	ts.IgnoreLogErrors()
   215  }
   216  
   217  func (suite *UpdateIntegrationTestSuite) TestJSON() {
   218  	suite.OnlyRunForTags(tagsuite.Update, tagsuite.JSON)
   219  	ts := e2e.New(suite.T(), false)
   220  	defer ts.Close()
   221  
   222  	cp := ts.Spawn("checkout", "ActiveState-CLI/Python3", ".")
   223  	cp.Expect("Skipping runtime setup")
   224  	cp.Expect("Checked out")
   225  	cp.ExpectExitCode(0)
   226  
   227  	cp = ts.Spawn("update", "lock", "-o", "json")
   228  	cp.Expect(`"channel":`)
   229  	cp.Expect(`"version":`)
   230  	cp.ExpectExitCode(0)
   231  	AssertValidJSON(suite.T(), cp)
   232  }