diff --git a/.golangci.yaml b/.golangci.yaml index 9e1124808..b79168c94 100644 --- a/.golangci.yaml +++ b/.golangci.yaml @@ -18,6 +18,7 @@ linters: - errorlint - govet - zerologlint + - testifylint settings: staticcheck: checks: ["all", "-ST1003", "-ST1005", "-ST1016", "-SA1019", "-QF1003"] diff --git a/api/apikey/apikey_test.go b/api/apikey/apikey_test.go index a11a08237..b3f8027d5 100644 --- a/api/apikey/apikey_test.go +++ b/api/apikey/apikey_test.go @@ -10,31 +10,31 @@ func Test_generateRandomKey(t *testing.T) { is := assert.New(t) tests := []struct { - name string - wantLenth int + name string + wantLength int }{ { - name: "Generate a random key of length 16", - wantLenth: 16, + name: "Generate a random key of length 16", + wantLength: 16, }, { - name: "Generate a random key of length 32", - wantLenth: 32, + name: "Generate a random key of length 32", + wantLength: 32, }, { - name: "Generate a random key of length 64", - wantLenth: 64, + name: "Generate a random key of length 64", + wantLength: 64, }, { - name: "Generate a random key of length 128", - wantLenth: 128, + name: "Generate a random key of length 128", + wantLength: 128, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - got := GenerateRandomKey(tt.wantLenth) - is.Equal(tt.wantLenth, len(got)) + got := GenerateRandomKey(tt.wantLength) + is.Len(got, tt.wantLength) }) } diff --git a/api/apikey/service_test.go b/api/apikey/service_test.go index 17d95a213..cd234e0a4 100644 --- a/api/apikey/service_test.go +++ b/api/apikey/service_test.go @@ -10,9 +10,10 @@ import ( portainer "github.com/portainer/portainer/api" "github.com/portainer/portainer/api/datastore" - "github.com/stretchr/testify/assert" "github.com/rs/zerolog/log" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func Test_SatisfiesAPIKeyServiceInterface(t *testing.T) { @@ -30,7 +31,7 @@ func Test_GenerateApiKey(t *testing.T) { t.Run("Successfully generates API key", func(t *testing.T) { desc := "test-1" rawKey, apiKey, err := service.GenerateApiKey(portainer.User{ID: 1}, desc) - is.NoError(err) + require.NoError(t, err) is.NotEmpty(rawKey) is.NotEmpty(apiKey) is.Equal(desc, apiKey.Description) @@ -38,7 +39,7 @@ func Test_GenerateApiKey(t *testing.T) { t.Run("Api key prefix is 7 chars", func(t *testing.T) { rawKey, apiKey, err := service.GenerateApiKey(portainer.User{ID: 1}, "test-2") - is.NoError(err) + require.NoError(t, err) is.Equal(rawKey[:7], apiKey.Prefix) is.Len(apiKey.Prefix, 7) @@ -46,7 +47,7 @@ func Test_GenerateApiKey(t *testing.T) { t.Run("Api key has 'ptr_' as prefix", func(t *testing.T) { rawKey, _, err := service.GenerateApiKey(portainer.User{ID: 1}, "test-x") - is.NoError(err) + require.NoError(t, err) is.Equal(portainerAPIKeyPrefix, "ptr_") is.True(strings.HasPrefix(rawKey, "ptr_")) @@ -55,7 +56,7 @@ func Test_GenerateApiKey(t *testing.T) { t.Run("Successfully caches API key", func(t *testing.T) { user := portainer.User{ID: 1} _, apiKey, err := service.GenerateApiKey(user, "test-3") - is.NoError(err) + require.NoError(t, err) userFromCache, apiKeyFromCache, ok := service.cache.Get(apiKey.Digest) is.True(ok) @@ -65,7 +66,7 @@ func Test_GenerateApiKey(t *testing.T) { t.Run("Decoded raw api-key digest matches generated digest", func(t *testing.T) { rawKey, apiKey, err := service.GenerateApiKey(portainer.User{ID: 1}, "test-4") - is.NoError(err) + require.NoError(t, err) generatedDigest := sha256.Sum256([]byte(rawKey)) @@ -83,10 +84,10 @@ func Test_GetAPIKey(t *testing.T) { t.Run("Successfully returns all API keys", func(t *testing.T) { user := portainer.User{ID: 1} _, apiKey, err := service.GenerateApiKey(user, "test-1") - is.NoError(err) + require.NoError(t, err) apiKeyGot, err := service.GetAPIKey(apiKey.ID) - is.NoError(err) + require.NoError(t, err) is.Equal(apiKey, apiKeyGot) }) @@ -102,12 +103,12 @@ func Test_GetAPIKeys(t *testing.T) { t.Run("Successfully returns all API keys", func(t *testing.T) { user := portainer.User{ID: 1} _, _, err := service.GenerateApiKey(user, "test-1") - is.NoError(err) + require.NoError(t, err) _, _, err = service.GenerateApiKey(user, "test-2") - is.NoError(err) + require.NoError(t, err) keys, err := service.GetAPIKeys(user.ID) - is.NoError(err) + require.NoError(t, err) is.Len(keys, 2) }) } @@ -122,10 +123,10 @@ func Test_GetDigestUserAndKey(t *testing.T) { t.Run("Successfully returns user and api key associated to digest", func(t *testing.T) { user := portainer.User{ID: 1} _, apiKey, err := service.GenerateApiKey(user, "test-1") - is.NoError(err) + require.NoError(t, err) userGot, apiKeyGot, err := service.GetDigestUserAndKey(apiKey.Digest) - is.NoError(err) + require.NoError(t, err) is.Equal(user, userGot) is.Equal(*apiKey, apiKeyGot) }) @@ -133,10 +134,10 @@ func Test_GetDigestUserAndKey(t *testing.T) { t.Run("Successfully caches user and api key associated to digest", func(t *testing.T) { user := portainer.User{ID: 1} _, apiKey, err := service.GenerateApiKey(user, "test-1") - is.NoError(err) + require.NoError(t, err) userGot, apiKeyGot, err := service.GetDigestUserAndKey(apiKey.Digest) - is.NoError(err) + require.NoError(t, err) is.Equal(user, userGot) is.Equal(*apiKey, apiKeyGot) @@ -158,14 +159,14 @@ func Test_UpdateAPIKey(t *testing.T) { user := portainer.User{ID: 1} store.User().Create(&user) _, apiKey, err := service.GenerateApiKey(user, "test-x") - is.NoError(err) + require.NoError(t, err) apiKey.LastUsed = time.Now().UTC().Unix() err = service.UpdateAPIKey(apiKey) - is.NoError(err) + require.NoError(t, err) _, apiKeyGot, err := service.GetDigestUserAndKey(apiKey.Digest) - is.NoError(err) + require.NoError(t, err) log.Debug().Str("wanted", fmt.Sprintf("%+v", apiKey)).Str("got", fmt.Sprintf("%+v", apiKeyGot)).Msg("") @@ -174,7 +175,7 @@ func Test_UpdateAPIKey(t *testing.T) { t.Run("Successfully updates api-key in cache upon api-key update", func(t *testing.T) { _, apiKey, err := service.GenerateApiKey(portainer.User{ID: 1}, "test-x2") - is.NoError(err) + require.NoError(t, err) _, apiKeyFromCache, ok := service.cache.Get(apiKey.Digest) is.True(ok) @@ -184,7 +185,7 @@ func Test_UpdateAPIKey(t *testing.T) { is.NotEqual(*apiKey, apiKeyFromCache) err = service.UpdateAPIKey(apiKey) - is.NoError(err) + require.NoError(t, err) _, updatedAPIKeyFromCache, ok := service.cache.Get(apiKey.Digest) is.True(ok) @@ -202,30 +203,30 @@ func Test_DeleteAPIKey(t *testing.T) { t.Run("Successfully updates the api-key", func(t *testing.T) { user := portainer.User{ID: 1} _, apiKey, err := service.GenerateApiKey(user, "test-1") - is.NoError(err) + require.NoError(t, err) _, apiKeyGot, err := service.GetDigestUserAndKey(apiKey.Digest) - is.NoError(err) + require.NoError(t, err) is.Equal(*apiKey, apiKeyGot) err = service.DeleteAPIKey(apiKey.ID) - is.NoError(err) + require.NoError(t, err) _, _, err = service.GetDigestUserAndKey(apiKey.Digest) - is.Error(err) + require.Error(t, err) }) t.Run("Successfully removes api-key from cache upon deletion", func(t *testing.T) { user := portainer.User{ID: 1} _, apiKey, err := service.GenerateApiKey(user, "test-1") - is.NoError(err) + require.NoError(t, err) _, apiKeyFromCache, ok := service.cache.Get(apiKey.Digest) is.True(ok) is.Equal(*apiKey, apiKeyFromCache) err = service.DeleteAPIKey(apiKey.ID) - is.NoError(err) + require.NoError(t, err) _, _, ok = service.cache.Get(apiKey.Digest) is.False(ok) @@ -243,10 +244,10 @@ func Test_InvalidateUserKeyCache(t *testing.T) { // generate api keys user := portainer.User{ID: 1} _, apiKey1, err := service.GenerateApiKey(user, "test-1") - is.NoError(err) + require.NoError(t, err) _, apiKey2, err := service.GenerateApiKey(user, "test-2") - is.NoError(err) + require.NoError(t, err) // verify api keys are present in cache _, apiKeyFromCache, ok := service.cache.Get(apiKey1.Digest) @@ -273,11 +274,11 @@ func Test_InvalidateUserKeyCache(t *testing.T) { // generate keys for 2 users user1 := portainer.User{ID: 1} _, apiKey1, err := service.GenerateApiKey(user1, "test-1") - is.NoError(err) + require.NoError(t, err) user2 := portainer.User{ID: 2} _, apiKey2, err := service.GenerateApiKey(user2, "test-2") - is.NoError(err) + require.NoError(t, err) // verify keys in cache _, apiKeyFromCache, ok := service.cache.Get(apiKey1.Digest) diff --git a/api/archive/targz_test.go b/api/archive/targz_test.go index 70e1e2fc4..675b6d60e 100644 --- a/api/archive/targz_test.go +++ b/api/archive/targz_test.go @@ -8,15 +8,19 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func listFiles(dir string) []string { items := make([]string, 0) + filepath.Walk(dir, func(path string, info os.FileInfo, err error) error { if path == dir { return nil } + items = append(items, path) + return nil }) @@ -26,13 +30,21 @@ func listFiles(dir string) []string { func Test_shouldCreateArchive(t *testing.T) { tmpdir := t.TempDir() content := []byte("content") - os.WriteFile(path.Join(tmpdir, "outer"), content, 0600) + + err := os.WriteFile(path.Join(tmpdir, "outer"), content, 0600) + require.NoError(t, err) + os.MkdirAll(path.Join(tmpdir, "dir"), 0700) - os.WriteFile(path.Join(tmpdir, "dir", ".dotfile"), content, 0600) - os.WriteFile(path.Join(tmpdir, "dir", "inner"), content, 0600) + require.NoError(t, err) + + err = os.WriteFile(path.Join(tmpdir, "dir", ".dotfile"), content, 0600) + require.NoError(t, err) + + err = os.WriteFile(path.Join(tmpdir, "dir", "inner"), content, 0600) + require.NoError(t, err) gzPath, err := TarGzDir(tmpdir) - assert.Nil(t, err) + require.NoError(t, err) assert.Equal(t, filepath.Join(tmpdir, filepath.Base(tmpdir)+".tar.gz"), gzPath) extractionDir := t.TempDir() @@ -45,7 +57,8 @@ func Test_shouldCreateArchive(t *testing.T) { wasExtracted := func(p string) { fullpath := path.Join(extractionDir, p) assert.Contains(t, extractedFiles, fullpath) - copyContent, _ := os.ReadFile(fullpath) + copyContent, err := os.ReadFile(fullpath) + require.NoError(t, err) assert.Equal(t, content, copyContent) } @@ -57,13 +70,21 @@ func Test_shouldCreateArchive(t *testing.T) { func Test_shouldCreateArchive2(t *testing.T) { tmpdir := t.TempDir() content := []byte("content") - os.WriteFile(path.Join(tmpdir, "outer"), content, 0600) - os.MkdirAll(path.Join(tmpdir, "dir"), 0700) - os.WriteFile(path.Join(tmpdir, "dir", ".dotfile"), content, 0600) - os.WriteFile(path.Join(tmpdir, "dir", "inner"), content, 0600) + + err := os.WriteFile(path.Join(tmpdir, "outer"), content, 0600) + require.NoError(t, err) + + err = os.MkdirAll(path.Join(tmpdir, "dir"), 0700) + require.NoError(t, err) + + err = os.WriteFile(path.Join(tmpdir, "dir", ".dotfile"), content, 0600) + require.NoError(t, err) + + err = os.WriteFile(path.Join(tmpdir, "dir", "inner"), content, 0600) + require.NoError(t, err) gzPath, err := TarGzDir(tmpdir) - assert.Nil(t, err) + require.NoError(t, err) assert.Equal(t, filepath.Join(tmpdir, filepath.Base(tmpdir)+".tar.gz"), gzPath) extractionDir := t.TempDir() diff --git a/api/archive/zip_test.go b/api/archive/zip_test.go index 056bc1c0d..bfc0d06a8 100644 --- a/api/archive/zip_test.go +++ b/api/archive/zip_test.go @@ -5,6 +5,7 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func TestUnzipFile(t *testing.T) { @@ -20,7 +21,7 @@ func TestUnzipFile(t *testing.T) { err := UnzipFile("./testdata/sample_archive.zip", dir) - assert.NoError(t, err) + require.NoError(t, err) archiveDir := dir + "/sample_archive" assert.FileExists(t, filepath.Join(archiveDir, "0.txt")) assert.FileExists(t, filepath.Join(archiveDir, "0", "1.txt")) diff --git a/api/crypto/aes_test.go b/api/crypto/aes_test.go index f5772d2bb..2d0e42944 100644 --- a/api/crypto/aes_test.go +++ b/api/crypto/aes_test.go @@ -55,17 +55,19 @@ func Test_encryptAndDecrypt_withTheSamePassword(t *testing.T) { encryptedFileWriter, _ := os.Create(encryptedFilePath) err := encrypt(originFile, encryptedFileWriter, []byte(passphrase)) - require.Nil(t, err, "Failed to encrypt a file") + require.NoError(t, err, "Failed to encrypt a file") encryptedFileWriter.Close() encryptedContent, err := os.ReadFile(encryptedFilePath) - require.Nil(t, err, "Couldn't read encrypted file") + require.NoError(t, err, "Couldn't read encrypted file") assert.NotEqual(t, encryptedContent, content, "Content wasn't encrypted") - encryptedFileReader, _ := os.Open(encryptedFilePath) + encryptedFileReader, err := os.Open(encryptedFilePath) + require.NoError(t, err) defer encryptedFileReader.Close() - decryptedFileWriter, _ := os.Create(decryptedFilePath) + decryptedFileWriter, err := os.Create(decryptedFilePath) + require.NoError(t, err) defer decryptedFileWriter.Close() decryptedReader, err := decrypt(encryptedFileReader, []byte(passphrase)) @@ -155,11 +157,11 @@ func Test_encryptAndDecrypt_withStrongPassphrase(t *testing.T) { encryptedFileWriter, _ := os.Create(encryptedFilePath) err := encrypt(originFile, encryptedFileWriter, []byte(passphrase)) - assert.Nil(t, err, "Failed to encrypt a file") + require.NoError(t, err, "Failed to encrypt a file") encryptedFileWriter.Close() encryptedContent, err := os.ReadFile(encryptedFilePath) - assert.Nil(t, err, "Couldn't read encrypted file") + require.NoError(t, err, "Couldn't read encrypted file") assert.NotEqual(t, encryptedContent, content, "Content wasn't encrypted") encryptedFileReader, _ := os.Open(encryptedFilePath) @@ -169,7 +171,7 @@ func Test_encryptAndDecrypt_withStrongPassphrase(t *testing.T) { defer decryptedFileWriter.Close() decryptedReader, err := decrypt(encryptedFileReader, []byte(passphrase)) - assert.Nil(t, err, "Failed to decrypt file") + require.NoError(t, err, "Failed to decrypt file") io.Copy(decryptedFileWriter, decryptedReader) @@ -205,25 +207,29 @@ func Test_encryptAndDecrypt_withTheSamePasswordSmallFile(t *testing.T) { encryptedFileWriter, _ := os.Create(encryptedFilePath) err := encrypt(originFile, encryptedFileWriter, []byte("passphrase")) - assert.Nil(t, err, "Failed to encrypt a file") + require.NoError(t, err, "Failed to encrypt a file") encryptedFileWriter.Close() encryptedContent, err := os.ReadFile(encryptedFilePath) - assert.Nil(t, err, "Couldn't read encrypted file") + require.NoError(t, err, "Couldn't read encrypted file") assert.NotEqual(t, encryptedContent, content, "Content wasn't encrypted") - encryptedFileReader, _ := os.Open(encryptedFilePath) + encryptedFileReader, err := os.Open(encryptedFilePath) + require.NoError(t, err) defer encryptedFileReader.Close() - decryptedFileWriter, _ := os.Create(decryptedFilePath) + decryptedFileWriter, err := os.Create(decryptedFilePath) + require.NoError(t, err) defer decryptedFileWriter.Close() decryptedReader, err := decrypt(encryptedFileReader, []byte("passphrase")) - assert.Nil(t, err, "Failed to decrypt file") + require.NoError(t, err, "Failed to decrypt file") - io.Copy(decryptedFileWriter, decryptedReader) + _, err = io.Copy(decryptedFileWriter, decryptedReader) + require.NoError(t, err) - decryptedContent, _ := os.ReadFile(decryptedFilePath) + decryptedContent, err := os.ReadFile(decryptedFilePath) + require.NoError(t, err) assert.Equal(t, content, decryptedContent, "Original and decrypted content should match") } @@ -247,32 +253,40 @@ func Test_encryptAndDecrypt_withEmptyPassword(t *testing.T) { ) content := randBytes(1024 * 50) - os.WriteFile(originFilePath, content, 0600) + err := os.WriteFile(originFilePath, content, 0600) + require.NoError(t, err) - originFile, _ := os.Open(originFilePath) + originFile, err := os.Open(originFilePath) + require.NoError(t, err) defer originFile.Close() - encryptedFileWriter, _ := os.Create(encryptedFilePath) + encryptedFileWriter, err := os.Create(encryptedFilePath) + require.NoError(t, err) defer encryptedFileWriter.Close() - err := encrypt(originFile, encryptedFileWriter, []byte("")) - assert.Nil(t, err, "Failed to encrypt a file") + err = encrypt(originFile, encryptedFileWriter, []byte("")) + require.NoError(t, err, "Failed to encrypt a file") + encryptedContent, err := os.ReadFile(encryptedFilePath) - assert.Nil(t, err, "Couldn't read encrypted file") + require.NoError(t, err, "Couldn't read encrypted file") assert.NotEqual(t, encryptedContent, content, "Content wasn't encrypted") - encryptedFileReader, _ := os.Open(encryptedFilePath) + encryptedFileReader, err := os.Open(encryptedFilePath) + require.NoError(t, err) defer encryptedFileReader.Close() - decryptedFileWriter, _ := os.Create(decryptedFilePath) + decryptedFileWriter, err := os.Create(decryptedFilePath) + require.NoError(t, err) defer decryptedFileWriter.Close() decryptedReader, err := decrypt(encryptedFileReader, []byte("")) - assert.Nil(t, err, "Failed to decrypt file") + require.NoError(t, err, "Failed to decrypt file") - io.Copy(decryptedFileWriter, decryptedReader) + _, err = io.Copy(decryptedFileWriter, decryptedReader) + require.NoError(t, err) - decryptedContent, _ := os.ReadFile(decryptedFilePath) + decryptedContent, err := os.ReadFile(decryptedFilePath) + require.NoError(t, err) assert.Equal(t, content, decryptedContent, "Original and decrypted content should match") } @@ -305,9 +319,9 @@ func Test_decryptWithDifferentPassphrase_shouldProduceWrongResult(t *testing.T) defer encryptedFileWriter.Close() err := encrypt(originFile, encryptedFileWriter, []byte("passphrase")) - assert.Nil(t, err, "Failed to encrypt a file") + require.NoError(t, err, "Failed to encrypt a file") encryptedContent, err := os.ReadFile(encryptedFilePath) - assert.Nil(t, err, "Couldn't read encrypted file") + require.NoError(t, err, "Couldn't read encrypted file") assert.NotEqual(t, encryptedContent, content, "Content wasn't encrypted") encryptedFileReader, _ := os.Open(encryptedFilePath) @@ -317,7 +331,7 @@ func Test_decryptWithDifferentPassphrase_shouldProduceWrongResult(t *testing.T) defer decryptedFileWriter.Close() _, err = decrypt(encryptedFileReader, []byte("garbage")) - assert.NotNil(t, err, "Should not allow decrypt with wrong passphrase") + require.Error(t, err, "Should not allow decrypt with wrong passphrase") } t.Run("fips", func(t *testing.T) { diff --git a/api/crypto/ecdsa_test.go b/api/crypto/ecdsa_test.go index 62141268a..adc3f9188 100644 --- a/api/crypto/ecdsa_test.go +++ b/api/crypto/ecdsa_test.go @@ -11,12 +11,12 @@ func TestCreateSignature(t *testing.T) { privKey, pubKey, err := s.GenerateKeyPair() require.NoError(t, err) - require.Greater(t, len(privKey), 0) - require.Greater(t, len(pubKey), 0) + require.NotEmpty(t, privKey) + require.NotEmpty(t, pubKey) m := "test message" r, err := s.CreateSignature(m) require.NoError(t, err) require.NotEqual(t, r, m) - require.Greater(t, len(r), 0) + require.NotEmpty(t, r) } diff --git a/api/crypto/tls_test.go b/api/crypto/tls_test.go index 77abdff73..cf00b08eb 100644 --- a/api/crypto/tls_test.go +++ b/api/crypto/tls_test.go @@ -44,7 +44,7 @@ func TestCreateTLSConfigurationFIPS(t *testing.T) { func TestCreateTLSConfigurationFromBytes(t *testing.T) { // No TLS config, err := CreateTLSConfigurationFromBytes(false, nil, nil, nil, false, false) - require.Nil(t, err) + require.NoError(t, err) require.Nil(t, config) // Skip TLS client/server verifications @@ -61,7 +61,7 @@ func TestCreateTLSConfigurationFromBytes(t *testing.T) { func TestCreateTLSConfigurationFromDisk(t *testing.T) { // No TLS config, err := CreateTLSConfigurationFromDisk(portainer.TLSConfiguration{}) - require.Nil(t, err) + require.NoError(t, err) require.Nil(t, config) // Skip TLS verifications diff --git a/api/database/boltdb/json_test.go b/api/database/boltdb/json_test.go index 32813f907..719fd6ff7 100644 --- a/api/database/boltdb/json_test.go +++ b/api/database/boltdb/json_test.go @@ -94,7 +94,7 @@ func Test_MarshalObjectUnencrypted(t *testing.T) { for _, test := range tests { t.Run(fmt.Sprintf("%s -> %s", test.object, test.expected), func(t *testing.T) { data, err := conn.MarshalObject(test.object) - is.NoError(err) + require.NoError(t, err) is.Equal(test.expected, string(data)) }) } @@ -135,7 +135,7 @@ func Test_UnMarshalObjectUnencrypted(t *testing.T) { t.Run(fmt.Sprintf("%s -> %s", test.object, test.expected), func(t *testing.T) { var object string err := conn.UnmarshalObject(test.object, &object) - is.NoError(err) + require.NoError(t, err) is.Equal(test.expected, object) }) } @@ -172,12 +172,12 @@ func Test_ObjectMarshallingEncrypted(t *testing.T) { t.Run(fmt.Sprintf("%s -> %s", test.object, test.expected), func(t *testing.T) { data, err := conn.MarshalObject(test.object) - is.NoError(err) + require.NoError(t, err) var object []byte err = conn.UnmarshalObject(data, &object) - is.NoError(err) + require.NoError(t, err) is.Equal(test.object, object) }) } diff --git a/api/dataservices/endpointrelation/endpointrelation_test.go b/api/dataservices/endpointrelation/endpointrelation_test.go index 8e5807b82..707400d17 100644 --- a/api/dataservices/endpointrelation/endpointrelation_test.go +++ b/api/dataservices/endpointrelation/endpointrelation_test.go @@ -136,5 +136,5 @@ func TestEndpointRelations(t *testing.T) { require.NoError(t, service.Create(&portainer.EndpointRelation{EndpointID: 1})) rels, err := service.EndpointRelations() require.NoError(t, err) - require.Equal(t, 1, len(rels)) + require.Len(t, rels, 1) } diff --git a/api/dataservices/stack/tests/stack_test.go b/api/dataservices/stack/tests/stack_test.go index a2bf83635..5ef8521ff 100644 --- a/api/dataservices/stack/tests/stack_test.go +++ b/api/dataservices/stack/tests/stack_test.go @@ -4,17 +4,18 @@ import ( "testing" "time" + portainer "github.com/portainer/portainer/api" "github.com/portainer/portainer/api/datastore" + "github.com/portainer/portainer/api/filesystem" "github.com/gofrs/uuid" - portainer "github.com/portainer/portainer/api" - "github.com/portainer/portainer/api/filesystem" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func newGuidString(t *testing.T) string { uuid, err := uuid.NewV4() - assert.NoError(t, err) + require.NoError(t, err) return uuid.String() } @@ -41,7 +42,7 @@ func TestService_StackByWebhookID(t *testing.T) { // can find a stack by webhook ID got, err := store.StackService.StackByWebhookID(webhookID) - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, stack, *got) // returns nil and object not found error if there's no stack associated with the webhook @@ -94,10 +95,10 @@ func Test_RefreshableStacks(t *testing.T) { for _, stack := range []*portainer.Stack{&staticStack, &stackWithWebhook, &refreshableStack} { err := store.Stack().Create(stack) - assert.NoError(t, err) + require.NoError(t, err) } stacks, err := store.Stack().RefreshableStacks() - assert.NoError(t, err) + require.NoError(t, err) assert.ElementsMatch(t, []portainer.Stack{refreshableStack}, stacks) } diff --git a/api/dataservices/team/tests/team_test.go b/api/dataservices/team/tests/team_test.go index ae2bec576..1c76c7be8 100644 --- a/api/dataservices/team/tests/team_test.go +++ b/api/dataservices/team/tests/team_test.go @@ -5,7 +5,9 @@ import ( "github.com/portainer/portainer/api/dataservices/errors" "github.com/portainer/portainer/api/datastore" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func Test_teamByName(t *testing.T) { @@ -13,7 +15,7 @@ func Test_teamByName(t *testing.T) { _, store := datastore.MustNewTestStore(t, true, true) _, err := store.Team().TeamByName("name") - assert.ErrorIs(t, err, errors.ErrObjectNotFound) + require.ErrorIs(t, err, errors.ErrObjectNotFound) }) @@ -29,7 +31,7 @@ func Test_teamByName(t *testing.T) { teamBuilder.createNew("name1") _, err := store.Team().TeamByName("name") - assert.ErrorIs(t, err, errors.ErrObjectNotFound) + require.ErrorIs(t, err, errors.ErrObjectNotFound) }) t.Run("When there is an object with the same name should return the object", func(t *testing.T) { @@ -44,7 +46,7 @@ func Test_teamByName(t *testing.T) { expectedTeam := teamBuilder.createNew("name1") team, err := store.Team().TeamByName("name1") - assert.NoError(t, err, "TeamByName should succeed") + require.NoError(t, err, "TeamByName should succeed") assert.Equal(t, expectedTeam, team) }) } diff --git a/api/datastore/datastore_test.go b/api/datastore/datastore_test.go index a6805c447..1a92953d0 100644 --- a/api/datastore/datastore_test.go +++ b/api/datastore/datastore_test.go @@ -6,12 +6,14 @@ import ( "strings" "testing" - "github.com/dchest/uniuri" - "github.com/pkg/errors" portainer "github.com/portainer/portainer/api" "github.com/portainer/portainer/api/chisel" "github.com/portainer/portainer/api/crypto" + + "github.com/dchest/uniuri" + "github.com/pkg/errors" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) const ( @@ -30,45 +32,21 @@ func TestStoreFull(t *testing.T) { _, store := MustNewTestStore(t, true, true) testCases := map[string]func(t *testing.T){ - "User Accounts": func(t *testing.T) { - store.testUserAccounts(t) - }, - "Environments": func(t *testing.T) { - store.testEnvironments(t) - }, - "Settings": func(t *testing.T) { - store.testSettings(t) - }, - "SSL Settings": func(t *testing.T) { - store.testSSLSettings(t) - }, - "Tunnel Server": func(t *testing.T) { - store.testTunnelServer(t) - }, - "Custom Templates": func(t *testing.T) { - store.testCustomTemplates(t) - }, - "Registries": func(t *testing.T) { - store.testRegistries(t) - }, - "Resource Control": func(t *testing.T) { - store.testResourceControl(t) - }, - "Schedules": func(t *testing.T) { - store.testSchedules(t) - }, - "Tags": func(t *testing.T) { - store.testTags(t) - }, - - // "Test Title": func(t *testing.T) { - // }, + "User Accounts": store.testUserAccounts, + "Environments": store.testEnvironments, + "Settings": store.testSettings, + "SSL Settings": store.testSSLSettings, + "Tunnel Server": store.testTunnelServer, + "Custom Templates": store.testCustomTemplates, + "Registries": store.testRegistries, + "Resource Control": store.testResourceControl, + "Schedules": store.testSchedules, + "Tags": store.testTags, } for name, test := range testCases { t.Run(name, test) } - } func (store *Store) testEnvironments(t *testing.T) { @@ -167,7 +145,7 @@ func (store *Store) CreateEndpoint(t *testing.T, name string, endpointType porta store.Endpoint().Create(expectedEndpoint) endpoint, err := store.Endpoint().Endpoint(id) - is.NoError(err, "Endpoint() should not return an error") + require.NoError(t, err, "Endpoint() should not return an error") is.Equal(expectedEndpoint, endpoint, "endpoint should be the same") return endpoint.ID @@ -194,7 +172,7 @@ func (store *Store) testSSLSettings(t *testing.T) { store.SSLSettings().UpdateSettings(ssl) settings, err := store.SSLSettings().Settings() - is.NoError(err, "Get sslsettings should succeed") + require.NoError(t, err, "Get sslsettings should succeed") is.Equal(ssl, settings, "Stored SSLSettings should be the same as what is read out") } @@ -203,27 +181,27 @@ func (store *Store) testTunnelServer(t *testing.T) { expectPrivateKeySeed := uniuri.NewLen(16) err := store.TunnelServer().UpdateInfo(&portainer.TunnelServerInfo{PrivateKeySeed: expectPrivateKeySeed}) - is.NoError(err, "UpdateInfo should have succeeded") + require.NoError(t, err, "UpdateInfo should have succeeded") serverInfo, err := store.TunnelServer().Info() - is.NoError(err, "Info should have succeeded") + require.NoError(t, err, "Info should have succeeded") is.Equal(expectPrivateKeySeed, serverInfo.PrivateKeySeed, "hashed passwords should not differ") } // add users, read them back and check the details are unchanged func (store *Store) testUserAccounts(t *testing.T) { - is := assert.New(t) - err := store.createAccount(adminUsername, adminPassword, portainer.AdministratorRole) - is.NoError(err, "CreateAccount should succeed") - store.checkAccount(adminUsername, adminPassword, portainer.AdministratorRole) - is.NoError(err, "Account failure") + require.NoError(t, err, "CreateAccount should succeed") + + err = store.checkAccount(adminUsername, adminPassword, portainer.AdministratorRole) + require.NoError(t, err, "Account failure") err = store.createAccount(standardUsername, standardPassword, portainer.StandardUserRole) - is.NoError(err, "CreateAccount should succeed") - store.checkAccount(standardUsername, standardPassword, portainer.StandardUserRole) - is.NoError(err, "Account failure") + require.NoError(t, err, "CreateAccount should succeed") + + err = store.checkAccount(standardUsername, standardPassword, portainer.StandardUserRole) + require.NoError(t, err, "Account failure") } // create an account with the provided details @@ -238,12 +216,7 @@ func (store *Store) createAccount(username, password string, role portainer.User return err } - err = store.User().Create(user) - if err != nil { - return err - } - - return nil + return store.User().Create(user) } func (store *Store) checkAccount(username, expectPassword string, expectRole portainer.UserRole) error { @@ -260,12 +233,7 @@ func (store *Store) checkAccount(username, expectPassword string, expectRole por // Check the password cs := crypto.Service{} - expectPasswordHash, err := cs.Hash(expectPassword) - if err != nil { - return errors.Wrap(err, "hash failed") - } - - if user.Password != expectPasswordHash { + if cs.CompareHashAndData(user.Password, expectPassword) != nil { return fmt.Errorf("%s user password hash failure", user.Username) } @@ -277,7 +245,7 @@ func (store *Store) testSettings(t *testing.T) { // since many settings are default and basically nil, I'm going to update some and read them back expectedSettings, err := store.Settings().Settings() - is.NoError(err, "Settings() should not return an error") + require.NoError(t, err, "Settings() should not return an error") expectedSettings.TemplatesURL = "http://portainer.io/application-templates" expectedSettings.HelmRepositoryURL = "http://portainer.io/helm-repository" expectedSettings.EdgeAgentCheckinInterval = 60 @@ -291,10 +259,10 @@ func (store *Store) testSettings(t *testing.T) { expectedSettings.SnapshotInterval = "10m" err = store.Settings().UpdateSettings(expectedSettings) - is.NoError(err, "UpdateSettings() should succeed") + require.NoError(t, err, "UpdateSettings() should succeed") settings, err := store.Settings().Settings() - is.NoError(err, "Settings() should not return an error") + require.NoError(t, err, "Settings() should not return an error") is.Equal(expectedSettings, settings, "stored settings should match") } @@ -317,7 +285,7 @@ func (store *Store) testCustomTemplates(t *testing.T) { customTemplate.Create(expectedTemplate) actualTemplate, err := customTemplate.Read(expectedTemplate.ID) - is.NoError(err, "CustomTemplate should not return an error") + require.NoError(t, err, "CustomTemplate should not return an error") is.Equal(expectedTemplate, actualTemplate, "expected and actual template do not match") } @@ -345,17 +313,17 @@ func (store *Store) testRegistries(t *testing.T) { } err := regService.Create(reg1) - is.NoError(err) + require.NoError(t, err) err = regService.Create(reg2) - is.NoError(err) + require.NoError(t, err) actualReg1, err := regService.Read(reg1.ID) - is.NoError(err) + require.NoError(t, err) is.Equal(reg1, actualReg1, "registries differ") actualReg2, err := regService.Read(reg2.ID) - is.NoError(err) + require.NoError(t, err) is.Equal(reg2, actualReg2, "registries differ") } @@ -378,10 +346,10 @@ func (store *Store) testSchedules(t *testing.T) { } err := schedule.CreateSchedule(s) - is.NoError(err, "CreateSchedule should succeed") + require.NoError(t, err, "CreateSchedule should succeed") actual, err := schedule.Schedule(s.ID) - is.NoError(err, "schedule should be found") + require.NoError(t, err, "schedule should be found") is.Equal(s, actual, "schedules differ") } @@ -401,16 +369,16 @@ func (store *Store) testTags(t *testing.T) { } err := tags.Create(tag1) - is.NoError(err, "Tags.Create should succeed") + require.NoError(t, err, "Tags.Create should succeed") err = tags.Create(tag2) - is.NoError(err, "Tags.Create should succeed") + require.NoError(t, err, "Tags.Create should succeed") actual, err := tags.Read(tag1.ID) - is.NoError(err, "tag1 should be found") + require.NoError(t, err, "tag1 should be found") is.Equal(tag1, actual, "tags differ") actual, err = tags.Read(tag2.ID) - is.NoError(err, "tag2 should be found") + require.NoError(t, err, "tag2 should be found") is.Equal(tag2, actual, "tags differ") } diff --git a/api/datastore/migrate_dbversion33_test.go b/api/datastore/migrate_dbversion33_test.go index a01eedcc4..f2fe61ad7 100644 --- a/api/datastore/migrate_dbversion33_test.go +++ b/api/datastore/migrate_dbversion33_test.go @@ -6,7 +6,9 @@ import ( portainer "github.com/portainer/portainer/api" "github.com/portainer/portainer/api/datastore/migrator" gittypes "github.com/portainer/portainer/api/git/types" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func TestMigrateStackEntryPoint(t *testing.T) { @@ -28,25 +30,25 @@ func TestMigrateStackEntryPoint(t *testing.T) { for _, s := range stacks { err := stackService.Create(s) - assert.NoError(t, err, "failed to create stack") + require.NoError(t, err, "failed to create stack") } s, err := stackService.Read(1) - assert.NoError(t, err) + require.NoError(t, err) assert.Nil(t, s.GitConfig, "first stack should not have git config") s, err = stackService.Read(2) - assert.NoError(t, err) - assert.Equal(t, "", s.GitConfig.ConfigFilePath, "not migrated yet migrated") + require.NoError(t, err) + assert.Empty(t, s.GitConfig.ConfigFilePath, "not migrated yet migrated") err = migrator.MigrateStackEntryPoint(stackService) - assert.NoError(t, err, "failed to migrate entry point to Git ConfigFilePath") + require.NoError(t, err, "failed to migrate entry point to Git ConfigFilePath") s, err = stackService.Read(1) - assert.NoError(t, err) + require.NoError(t, err) assert.Nil(t, s.GitConfig, "first stack should not have git config") s, err = stackService.Read(2) - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, "dir/sub/compose.yml", s.GitConfig.ConfigFilePath, "second stack should have config file path migrated") } diff --git a/api/datastore/migrator/migrate_2_33_test.go b/api/datastore/migrator/migrate_2_33_test.go index 2b197f54f..f0965cfb9 100644 --- a/api/datastore/migrator/migrate_2_33_test.go +++ b/api/datastore/migrator/migrate_2_33_test.go @@ -39,7 +39,7 @@ func TestMigrateEdgeGroupEndpointsToRoars_2_33_0Idempotency(t *testing.T) { migratedEdgeGroup, err := edgeGroupService.Read(edgeGroup.ID) require.NoError(t, err) - require.Len(t, migratedEdgeGroup.Endpoints, 0) + require.Empty(t, migratedEdgeGroup.Endpoints) require.Equal(t, len(edgeGroup.Endpoints), migratedEdgeGroup.EndpointIDs.Len()) // Run migration again to ensure the results didn't change @@ -50,6 +50,6 @@ func TestMigrateEdgeGroupEndpointsToRoars_2_33_0Idempotency(t *testing.T) { migratedEdgeGroup, err = edgeGroupService.Read(edgeGroup.ID) require.NoError(t, err) - require.Len(t, migratedEdgeGroup.Endpoints, 0) + require.Empty(t, migratedEdgeGroup.Endpoints) require.Equal(t, len(edgeGroup.Endpoints), migratedEdgeGroup.EndpointIDs.Len()) } diff --git a/api/datastore/postinit/migrate_post_init_test.go b/api/datastore/postinit/migrate_post_init_test.go index 7ca909149..e5305fe9e 100644 --- a/api/datastore/postinit/migrate_post_init_test.go +++ b/api/datastore/postinit/migrate_post_init_test.go @@ -22,8 +22,9 @@ func TestMigrateGPUs(t *testing.T) { if strings.HasSuffix(r.URL.Path, "/containers/json") { containerSummary := []container.Summary{{ID: "container1"}} - err := json.NewEncoder(w).Encode(containerSummary) - require.NoError(t, err) + if err := json.NewEncoder(w).Encode(containerSummary); err != nil { + w.WriteHeader(http.StatusInternalServerError) + } return } @@ -41,8 +42,9 @@ func TestMigrateGPUs(t *testing.T) { }, } - err := json.NewEncoder(w).Encode(container) - require.NoError(t, err) + if err := json.NewEncoder(w).Encode(container); err != nil { + w.WriteHeader(http.StatusInternalServerError) + } })) defer srv.Close() @@ -129,12 +131,12 @@ func TestPostInitMigrate_PendingActionsCreated(t *testing.T) { EdgeID: "edgeID", } err := store.Endpoint().Create(endpoint) - is.NoError(err, "error creating endpoint") + require.NoError(t, err, "error creating endpoint") // Create any existing pending actions for _, action := range tt.existingPendingActions { err = store.PendingActions().Create(action) - is.NoError(err, "error creating pending action") + require.NoError(t, err, "error creating pending action") } migrator := NewPostInitMigrator( @@ -146,11 +148,11 @@ func TestPostInitMigrate_PendingActionsCreated(t *testing.T) { ) err = migrator.PostInitMigrate() - is.NoError(err, "PostInitMigrate should not return error") + require.NoError(t, err, "PostInitMigrate should not return error") // Verify the results pendingActions, err := store.PendingActions().ReadAll() - is.NoError(err, "error reading pending actions") + require.NoError(t, err, "error reading pending actions") is.Len(pendingActions, tt.expectedPendingActions, "unexpected number of pending actions") // If we expect any actions, verify at least one has the expected action type @@ -160,9 +162,11 @@ func TestPostInitMigrate_PendingActionsCreated(t *testing.T) { if action.Action == tt.expectedAction { hasExpectedAction = true is.Equal(endpoint.ID, action.EndpointID, "action should reference correct endpoint") + break } } + is.True(hasExpectedAction, "should have found action of expected type") } }) diff --git a/api/docker/images/image_test.go b/api/docker/images/image_test.go index 713a67732..22ba27a2e 100644 --- a/api/docker/images/image_test.go +++ b/api/docker/images/image_test.go @@ -4,6 +4,7 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func TestImageParser(t *testing.T) { @@ -14,7 +15,7 @@ func TestImageParser(t *testing.T) { image, err := ParseImage(ParseImageOptions{ Name: "portainer/portainer-ee", }) - is.NoError(err, "") + require.NoError(t, err) is.Equal("docker.io/portainer/portainer-ee:latest", image.FullName()) is.Equal("portainer/portainer-ee", image.Opts.Name) is.Equal("latest", image.Tag) @@ -30,10 +31,10 @@ func TestImageParser(t *testing.T) { image, err := ParseImage(ParseImageOptions{ Name: "gcr.io/k8s-minikube/kicbase@sha256:02c921df998f95e849058af14de7045efc3954d90320967418a0d1f182bbc0b2", }) - is.NoError(err, "") + require.NoError(t, err) is.Equal("gcr.io/k8s-minikube/kicbase@sha256:02c921df998f95e849058af14de7045efc3954d90320967418a0d1f182bbc0b2", image.FullName()) is.Equal("gcr.io/k8s-minikube/kicbase@sha256:02c921df998f95e849058af14de7045efc3954d90320967418a0d1f182bbc0b2", image.Opts.Name) - is.Equal("", image.Tag) + is.Empty(image.Tag) is.Equal("k8s-minikube/kicbase", image.Path) is.Equal("gcr.io", image.Domain) is.Equal("https://gcr.io/k8s-minikube/kicbase", image.HubLink) @@ -47,7 +48,7 @@ func TestImageParser(t *testing.T) { image, err := ParseImage(ParseImageOptions{ Name: "gcr.io/k8s-minikube/kicbase:v0.0.30@sha256:02c921df998f95e849058af14de7045efc3954d90320967418a0d1f182bbc0b2", }) - is.NoError(err, "") + require.NoError(t, err) is.Equal("gcr.io/k8s-minikube/kicbase:v0.0.30", image.FullName()) is.Equal("gcr.io/k8s-minikube/kicbase:v0.0.30@sha256:02c921df998f95e849058af14de7045efc3954d90320967418a0d1f182bbc0b2", image.Opts.Name) is.Equal("v0.0.30", image.Tag) @@ -68,8 +69,9 @@ func TestUpdateParsedImage(t *testing.T) { image, err := ParseImage(ParseImageOptions{ Name: "gcr.io/k8s-minikube/kicbase:v0.0.30@sha256:02c921df998f95e849058af14de7045efc3954d90320967418a0d1f182bbc0b2", }) - is.NoError(err, "") - _ = image.WithTag("v0.0.31") + require.NoError(t, err) + err = image.WithTag("v0.0.31") + require.NoError(t, err) is.Equal("gcr.io/k8s-minikube/kicbase:v0.0.31", image.FullName()) is.Equal("gcr.io/k8s-minikube/kicbase:v0.0.30@sha256:02c921df998f95e849058af14de7045efc3954d90320967418a0d1f182bbc0b2", image.Opts.Name) is.Equal("v0.0.31", image.Tag) @@ -86,8 +88,9 @@ func TestUpdateParsedImage(t *testing.T) { image, err := ParseImage(ParseImageOptions{ Name: "gcr.io/k8s-minikube/kicbase:v0.0.30@sha256:02c921df998f95e849058af14de7045efc3954d90320967418a0d1f182bbc0b2", }) - is.NoError(err, "") - _ = image.WithDigest("sha256:02c921df998f95e849058af14de7045efc3954d90320967418a0d1f182bbc0b3") + require.NoError(t, err) + err = image.WithDigest("sha256:02c921df998f95e849058af14de7045efc3954d90320967418a0d1f182bbc0b3") + require.NoError(t, err) is.Equal("gcr.io/k8s-minikube/kicbase:v0.0.30", image.FullName()) is.Equal("gcr.io/k8s-minikube/kicbase:v0.0.30@sha256:02c921df998f95e849058af14de7045efc3954d90320967418a0d1f182bbc0b2", image.Opts.Name) is.Equal("v0.0.30", image.Tag) @@ -104,8 +107,9 @@ func TestUpdateParsedImage(t *testing.T) { image, err := ParseImage(ParseImageOptions{ Name: "gcr.io/k8s-minikube/kicbase:v0.0.30@sha256:02c921df998f95e849058af14de7045efc3954d90320967418a0d1f182bbc0b2", }) - is.NoError(err, "") - _ = image.TrimDigest() + require.NoError(t, err) + err = image.TrimDigest() + require.NoError(t, err) is.Equal("gcr.io/k8s-minikube/kicbase:v0.0.30", image.FullName()) is.Equal("gcr.io/k8s-minikube/kicbase:v0.0.30@sha256:02c921df998f95e849058af14de7045efc3954d90320967418a0d1f182bbc0b2", image.Opts.Name) is.Equal("v0.0.30", image.Tag) diff --git a/api/docker/images/registry_test.go b/api/docker/images/registry_test.go index 125c4fb40..6b0a1bd65 100644 --- a/api/docker/images/registry_test.go +++ b/api/docker/images/registry_test.go @@ -4,7 +4,9 @@ import ( "testing" portainer "github.com/portainer/portainer/api" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func TestFindBestMatchNeedAuthRegistry(t *testing.T) { @@ -15,9 +17,9 @@ func TestFindBestMatchNeedAuthRegistry(t *testing.T) { registries := []portainer.Registry{createNewRegistry("docker.io", "USERNAME", false), createNewRegistry("hub-mirror.c.163.com", "", false)} r, err := findBestMatchRegistry(image, registries) - is.NoError(err, "") - is.NotNil(r, "") - is.False(r.Authentication, "") + require.NoError(t, err) + is.NotNil(r) + is.False(r.Authentication) is.Equal("docker.io", r.URL) }) @@ -26,9 +28,9 @@ func TestFindBestMatchNeedAuthRegistry(t *testing.T) { registries := []portainer.Registry{createNewRegistry("docker.io", "", false), createNewRegistry("hub-mirror.c.163.com", "USERNAME", false)} r, err := findBestMatchRegistry(image, registries) - is.NoError(err, "") - is.NotNil(r, "") - is.False(r.Authentication, "") + require.NoError(t, err) + is.NotNil(r) + is.False(r.Authentication) is.Equal("docker.io", r.URL) }) @@ -37,9 +39,9 @@ func TestFindBestMatchNeedAuthRegistry(t *testing.T) { registries := []portainer.Registry{createNewRegistry("docker.io", "USERNAME", true), createNewRegistry("hub-mirror.c.163.com", "", false)} r, err := findBestMatchRegistry(image, registries) - is.NoError(err, "") - is.NotNil(r, "") - is.True(r.Authentication, "") + require.NoError(t, err) + is.NotNil(r) + is.True(r.Authentication) is.Equal("docker.io", r.URL) }) @@ -47,9 +49,9 @@ func TestFindBestMatchNeedAuthRegistry(t *testing.T) { image := "portainer/portainer-ee:latest" registries := []portainer.Registry{createNewRegistry("docker.io", "", true)} r, err := findBestMatchRegistry(image, registries) - is.NoError(err, "") - is.NotNil(r, "") - is.True(r.Authentication, "") + require.NoError(t, err) + is.NotNil(r) + is.True(r.Authentication) is.Equal("docker.io", r.URL) }) } diff --git a/api/exec/compose_stack_test.go b/api/exec/compose_stack_test.go index 4abbb0d21..cc6dd1102 100644 --- a/api/exec/compose_stack_test.go +++ b/api/exec/compose_stack_test.go @@ -8,7 +8,9 @@ import ( "testing" portainer "github.com/portainer/portainer/api" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func Test_createEnvFile(t *testing.T) { @@ -61,7 +63,7 @@ func Test_createEnvFile(t *testing.T) { assert.Equal(t, tt.expected, string(content)) } else { - assert.Equal(t, "", result) + assert.Empty(t, result) } }) } @@ -79,7 +81,7 @@ func Test_createEnvFile_mergesDefultAndInplaceEnvVars(t *testing.T) { } result, err := createEnvFile(stack) assert.Equal(t, filepath.Join(stack.ProjectPath, "stack.env"), result) - assert.NoError(t, err) + require.NoError(t, err) assert.FileExists(t, path.Join(dir, "stack.env")) f, _ := os.Open(path.Join(dir, "stack.env")) content, _ := io.ReadAll(f) diff --git a/api/exec/kubernetes_deploy_test.go b/api/exec/kubernetes_deploy_test.go index cd49a2b92..ce4534098 100644 --- a/api/exec/kubernetes_deploy_test.go +++ b/api/exec/kubernetes_deploy_test.go @@ -7,6 +7,7 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) type mockKubectlClient struct { @@ -68,7 +69,7 @@ func TestExecuteKubectlOperation_Apply_Success(t *testing.T) { manifests := []string{"manifest1.yaml", "manifest2.yaml"} err := testExecuteKubectlOperation(mockClient, "apply", manifests) - assert.NoError(t, err) + require.NoError(t, err) assert.True(t, called) } @@ -86,7 +87,7 @@ func TestExecuteKubectlOperation_Apply_Error(t *testing.T) { manifests := []string{"error.yaml"} err := testExecuteKubectlOperation(mockClient, "apply", manifests) - assert.Error(t, err) + require.Error(t, err) assert.Contains(t, err.Error(), expectedErr.Error()) assert.True(t, called) } @@ -104,7 +105,7 @@ func TestExecuteKubectlOperation_Delete_Success(t *testing.T) { manifests := []string{"manifest1.yaml"} err := testExecuteKubectlOperation(mockClient, "delete", manifests) - assert.NoError(t, err) + require.NoError(t, err) assert.True(t, called) } @@ -122,7 +123,7 @@ func TestExecuteKubectlOperation_Delete_Error(t *testing.T) { manifests := []string{"error.yaml"} err := testExecuteKubectlOperation(mockClient, "delete", manifests) - assert.Error(t, err) + require.Error(t, err) assert.Contains(t, err.Error(), expectedErr.Error()) assert.True(t, called) } @@ -140,7 +141,7 @@ func TestExecuteKubectlOperation_RolloutRestart_Success(t *testing.T) { resources := []string{"deployment/nginx"} err := testExecuteKubectlOperation(mockClient, "rollout-restart", resources) - assert.NoError(t, err) + require.NoError(t, err) assert.True(t, called) } @@ -158,7 +159,7 @@ func TestExecuteKubectlOperation_RolloutRestart_Error(t *testing.T) { resources := []string{"deployment/error"} err := testExecuteKubectlOperation(mockClient, "rollout-restart", resources) - assert.Error(t, err) + require.Error(t, err) assert.Contains(t, err.Error(), expectedErr.Error()) assert.True(t, called) } @@ -168,6 +169,6 @@ func TestExecuteKubectlOperation_UnsupportedOperation(t *testing.T) { err := testExecuteKubectlOperation(mockClient, "unsupported", []string{}) - assert.Error(t, err) + require.Error(t, err) assert.Contains(t, err.Error(), "unsupported operation") } diff --git a/api/filesystem/copy_test.go b/api/filesystem/copy_test.go index a91754975..8e27765dd 100644 --- a/api/filesystem/copy_test.go +++ b/api/filesystem/copy_test.go @@ -7,12 +7,13 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func Test_copyFile_returnsError_whenSourceDoesNotExist(t *testing.T) { tmpdir := t.TempDir() err := copyFile("does-not-exist", tmpdir) - assert.Error(t, err) + require.Error(t, err) } func Test_copyFile_shouldMakeAbackup(t *testing.T) { @@ -21,7 +22,7 @@ func Test_copyFile_shouldMakeAbackup(t *testing.T) { os.WriteFile(path.Join(tmpdir, "origin"), content, 0600) err := copyFile(path.Join(tmpdir, "origin"), path.Join(tmpdir, "copy")) - assert.NoError(t, err) + require.NoError(t, err) copyContent, _ := os.ReadFile(path.Join(tmpdir, "copy")) assert.Equal(t, content, copyContent) @@ -30,7 +31,7 @@ func Test_copyFile_shouldMakeAbackup(t *testing.T) { func Test_CopyDir_shouldCopyAllFilesAndDirectories(t *testing.T) { destination := t.TempDir() err := CopyDir("./testdata/copy_test", destination, true) - assert.NoError(t, err) + require.NoError(t, err) assert.FileExists(t, filepath.Join(destination, "copy_test", "outer")) assert.FileExists(t, filepath.Join(destination, "copy_test", "dir", ".dotfile")) @@ -40,7 +41,7 @@ func Test_CopyDir_shouldCopyAllFilesAndDirectories(t *testing.T) { func Test_CopyDir_shouldCopyOnlyDirContents(t *testing.T) { destination := t.TempDir() err := CopyDir("./testdata/copy_test", destination, false) - assert.NoError(t, err) + require.NoError(t, err) assert.FileExists(t, filepath.Join(destination, "outer")) assert.FileExists(t, filepath.Join(destination, "dir", ".dotfile")) @@ -50,7 +51,7 @@ func Test_CopyDir_shouldCopyOnlyDirContents(t *testing.T) { func Test_CopyPath_shouldSkipWhenNotExist(t *testing.T) { tmpdir := t.TempDir() err := CopyPath("does-not-exists", tmpdir) - assert.NoError(t, err) + require.NoError(t, err) assert.NoFileExists(t, tmpdir) } @@ -62,17 +63,17 @@ func Test_CopyPath_shouldCopyFile(t *testing.T) { os.MkdirAll(path.Join(tmpdir, "backup"), 0700) err := CopyPath(path.Join(tmpdir, "file"), path.Join(tmpdir, "backup")) - assert.NoError(t, err) + require.NoError(t, err) copyContent, err := os.ReadFile(path.Join(tmpdir, "backup", "file")) - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, content, copyContent) } func Test_CopyPath_shouldCopyDir(t *testing.T) { destination := t.TempDir() err := CopyPath("./testdata/copy_test", destination) - assert.NoError(t, err) + require.NoError(t, err) assert.FileExists(t, filepath.Join(destination, "copy_test", "outer")) assert.FileExists(t, filepath.Join(destination, "copy_test", "dir", ".dotfile")) diff --git a/api/filesystem/filesystem_fileexists_test.go b/api/filesystem/filesystem_fileexists_test.go index ceac521cb..6679aa419 100644 --- a/api/filesystem/filesystem_fileexists_test.go +++ b/api/filesystem/filesystem_fileexists_test.go @@ -8,6 +8,7 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func Test_fileSystemService_FileExists_whenFileExistsShouldReturnTrue(t *testing.T) { @@ -30,14 +31,14 @@ func Test_FileExists_whenFileNotExistsShouldReturnFalse(t *testing.T) { func testHelperFileExists_fileExists(t *testing.T, checker func(path string) (bool, error)) { file, err := os.CreateTemp("", t.Name()) - assert.NoError(t, err, "CreateTemp should not fail") + require.NoError(t, err, "CreateTemp should not fail") t.Cleanup(func() { os.RemoveAll(file.Name()) }) exists, err := checker(file.Name()) - assert.NoError(t, err, "FileExists should not fail") + require.NoError(t, err, "FileExists should not fail") assert.True(t, exists) } @@ -46,10 +47,10 @@ func testHelperFileExists_fileNotExists(t *testing.T, checker func(path string) filePath := path.Join(t.TempDir(), fmt.Sprintf("%s%d", t.Name(), rand.Int())) err := os.RemoveAll(filePath) - assert.NoError(t, err, "RemoveAll should not fail") + require.NoError(t, err, "RemoveAll should not fail") exists, err := checker(filePath) - assert.NoError(t, err, "FileExists should not fail") + require.NoError(t, err, "FileExists should not fail") assert.False(t, exists) } diff --git a/api/filesystem/filesystem_move_test.go b/api/filesystem/filesystem_move_test.go index e2965c953..e78b8b7e8 100644 --- a/api/filesystem/filesystem_move_test.go +++ b/api/filesystem/filesystem_move_test.go @@ -6,6 +6,7 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) var content = []byte("content") @@ -13,25 +14,25 @@ var content = []byte("content") func Test_movePath_shouldFailIfSourceDirDoesNotExist(t *testing.T) { sourceDir := "missing" destinationDir := t.TempDir() - file1 := addFile(destinationDir, "dir", "file") - file2 := addFile(destinationDir, "file") + file1 := addFile(t, destinationDir, "dir", "file") + file2 := addFile(t, destinationDir, "file") err := MoveDirectory(sourceDir, destinationDir, false) - assert.Error(t, err, "move directory should fail when source path is missing") + require.Error(t, err, "move directory should fail when source path is missing") assert.FileExists(t, file1, "destination dir contents should remain") assert.FileExists(t, file2, "destination dir contents should remain") } func Test_movePath_shouldFailIfDestinationDirExists(t *testing.T) { sourceDir := t.TempDir() - file1 := addFile(sourceDir, "dir", "file") - file2 := addFile(sourceDir, "file") + file1 := addFile(t, sourceDir, "dir", "file") + file2 := addFile(t, sourceDir, "file") destinationDir := t.TempDir() - file3 := addFile(destinationDir, "dir", "file") - file4 := addFile(destinationDir, "file") + file3 := addFile(t, destinationDir, "dir", "file") + file4 := addFile(t, destinationDir, "file") err := MoveDirectory(sourceDir, destinationDir, false) - assert.Error(t, err, "move directory should fail when destination directory already exists") + require.Error(t, err, "move directory should fail when destination directory already exists") assert.FileExists(t, file1, "source dir contents should remain") assert.FileExists(t, file2, "source dir contents should remain") assert.FileExists(t, file3, "destination dir contents should remain") @@ -40,14 +41,14 @@ func Test_movePath_shouldFailIfDestinationDirExists(t *testing.T) { func Test_movePath_succesIfOverwriteSetWhenDestinationDirExists(t *testing.T) { sourceDir := t.TempDir() - file1 := addFile(sourceDir, "dir", "file") - file2 := addFile(sourceDir, "file") + file1 := addFile(t, sourceDir, "dir", "file") + file2 := addFile(t, sourceDir, "file") destinationDir := t.TempDir() - file3 := addFile(destinationDir, "dir", "file") - file4 := addFile(destinationDir, "file") + file3 := addFile(t, destinationDir, "dir", "file") + file4 := addFile(t, destinationDir, "file") err := MoveDirectory(sourceDir, destinationDir, true) - assert.NoError(t, err) + require.NoError(t, err) assert.NoFileExists(t, file1, "source dir contents should be moved") assert.NoFileExists(t, file2, "source dir contents should be moved") assert.FileExists(t, file3, "destination dir contents should remain") @@ -58,32 +59,34 @@ func Test_movePath_successWhenSourceExistsAndDestinationIsMissing(t *testing.T) tmp := t.TempDir() sourceDir := path.Join(tmp, "source") os.Mkdir(sourceDir, 0766) - file1 := addFile(sourceDir, "dir", "file") - file2 := addFile(sourceDir, "file") + file1 := addFile(t, sourceDir, "dir", "file") + file2 := addFile(t, sourceDir, "file") destinationDir := path.Join(tmp, "destination") err := MoveDirectory(sourceDir, destinationDir, false) - assert.NoError(t, err) + require.NoError(t, err) assert.NoFileExists(t, file1, "source dir contents should be moved") assert.NoFileExists(t, file2, "source dir contents should be moved") assertFileContent(t, path.Join(destinationDir, "file")) assertFileContent(t, path.Join(destinationDir, "dir", "file")) } -func addFile(fileParts ...string) (filepath string) { +func addFile(t *testing.T, fileParts ...string) (filepath string) { if len(fileParts) > 2 { dir := path.Join(fileParts[:len(fileParts)-1]...) - os.MkdirAll(dir, 0766) + err := os.MkdirAll(dir, 0766) + require.NoError(t, err) } p := path.Join(fileParts...) - os.WriteFile(p, content, 0766) + err := os.WriteFile(p, content, 0766) + require.NoError(t, err) return p } func assertFileContent(t *testing.T, filePath string) { actualContent, err := os.ReadFile(filePath) - assert.NoErrorf(t, err, "failed to read file %s", filePath) + require.NoError(t, err, "failed to read file %s", filePath) assert.Equal(t, content, actualContent, "file %s content doesn't match", filePath) } diff --git a/api/filesystem/filesystem_test.go b/api/filesystem/filesystem_test.go index f6cdf9d2b..37068742b 100644 --- a/api/filesystem/filesystem_test.go +++ b/api/filesystem/filesystem_test.go @@ -5,14 +5,14 @@ import ( "path" "testing" - "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func createService(t *testing.T) *Service { dataStorePath := path.Join(t.TempDir(), t.Name()) service, err := NewService(dataStorePath, "") - assert.NoError(t, err, "NewService should not fail") + require.NoError(t, err, "NewService should not fail") t.Cleanup(func() { os.RemoveAll(dataStorePath) diff --git a/api/filesystem/write_test.go b/api/filesystem/write_test.go index 17606ace0..7e839a248 100644 --- a/api/filesystem/write_test.go +++ b/api/filesystem/write_test.go @@ -6,6 +6,7 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func Test_WriteFile_CanStoreContentInANewFile(t *testing.T) { @@ -14,7 +15,7 @@ func Test_WriteFile_CanStoreContentInANewFile(t *testing.T) { content := []byte("content") err := WriteToFile(tmpFilePath, content) - assert.NoError(t, err) + require.NoError(t, err) fileContent, _ := os.ReadFile(tmpFilePath) assert.Equal(t, content, fileContent) @@ -25,11 +26,11 @@ func Test_WriteFile_CanOverwriteExistingFile(t *testing.T) { tmpFilePath := path.Join(tmpDir, "dummy") err := WriteToFile(tmpFilePath, []byte("content")) - assert.NoError(t, err) + require.NoError(t, err) content := []byte("new content") err = WriteToFile(tmpFilePath, content) - assert.NoError(t, err) + require.NoError(t, err) fileContent, _ := os.ReadFile(tmpFilePath) assert.Equal(t, content, fileContent) @@ -41,7 +42,7 @@ func Test_WriteFile_CanWriteANestedPath(t *testing.T) { content := []byte("content") err := WriteToFile(tmpFilePath, content) - assert.NoError(t, err) + require.NoError(t, err) fileContent, _ := os.ReadFile(tmpFilePath) assert.Equal(t, content, fileContent) diff --git a/api/git/azure_integration_test.go b/api/git/azure_integration_test.go index 5de18b303..b7b53e655 100644 --- a/api/git/azure_integration_test.go +++ b/api/git/azure_integration_test.go @@ -12,6 +12,7 @@ import ( _ "github.com/joho/godotenv/autoload" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) const privateAzureRepoURL = "https://portainer.visualstudio.com/gitops-test/_git/gitops-test" @@ -67,7 +68,7 @@ func TestService_ClonePublicRepository_Azure(t *testing.T) { gittypes.GitCredentialAuthType_Basic, false, ) - assert.NoError(t, err) + require.NoError(t, err) assert.FileExists(t, filepath.Join(dst, "README.md")) }) } @@ -90,7 +91,7 @@ func TestService_ClonePrivateRepository_Azure(t *testing.T) { gittypes.GitCredentialAuthType_Basic, false, ) - assert.NoError(t, err) + require.NoError(t, err) assert.FileExists(t, filepath.Join(dst, "README.md")) } @@ -108,7 +109,7 @@ func TestService_LatestCommitID_Azure(t *testing.T) { gittypes.GitCredentialAuthType_Basic, false, ) - assert.NoError(t, err) + require.NoError(t, err) assert.NotEmpty(t, id, "cannot guarantee commit id, but it should be not empty") } @@ -127,7 +128,7 @@ func TestService_ListRefs_Azure(t *testing.T) { false, false, ) - assert.NoError(t, err) + require.NoError(t, err) assert.GreaterOrEqual(t, len(refs), 1) } @@ -289,14 +290,14 @@ func TestService_ListFiles_Azure(t *testing.T) { false, ) if tt.expect.shouldFail { - assert.Error(t, err) + require.Error(t, err) if tt.expect.err != nil { assert.Equal(t, tt.expect.err, err) } } else { - assert.NoError(t, err) + require.NoError(t, err) if tt.expect.matchedCount > 0 { - assert.Greater(t, len(paths), 0) + assert.NotEmpty(t, paths) } } }) diff --git a/api/git/azure_test.go b/api/git/azure_test.go index 0280cf2df..4b44a4afd 100644 --- a/api/git/azure_test.go +++ b/api/git/azure_test.go @@ -9,7 +9,9 @@ import ( gittypes "github.com/portainer/portainer/api/git/types" "github.com/portainer/portainer/pkg/fips" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func Test_buildDownloadUrl(t *testing.T) { @@ -19,15 +21,18 @@ func Test_buildDownloadUrl(t *testing.T) { project: "project", repository: "repository", }, "refs/heads/main") + require.NoError(t, err) - expectedUrl, _ := url.Parse("https://dev.azure.com/organisation/project/_apis/git/repositories/repository/items?scopePath=/&download=true&versionDescriptor.version=main&$format=zip&recursionLevel=full&api-version=6.0&versionDescriptor.versionType=branch") - actualUrl, _ := url.Parse(u) - if assert.NoError(t, err) { - assert.Equal(t, expectedUrl.Host, actualUrl.Host) - assert.Equal(t, expectedUrl.Scheme, actualUrl.Scheme) - assert.Equal(t, expectedUrl.Path, actualUrl.Path) - assert.Equal(t, expectedUrl.Query(), actualUrl.Query()) - } + expectedUrl, err := url.Parse("https://dev.azure.com/organisation/project/_apis/git/repositories/repository/items?scopePath=/&download=true&versionDescriptor.version=main&$format=zip&recursionLevel=full&api-version=6.0&versionDescriptor.versionType=branch") + require.NoError(t, err) + + actualUrl, err := url.Parse(u) + require.NoError(t, err) + + assert.Equal(t, expectedUrl.Host, actualUrl.Host) + assert.Equal(t, expectedUrl.Scheme, actualUrl.Scheme) + assert.Equal(t, expectedUrl.Path, actualUrl.Path) + assert.Equal(t, expectedUrl.Query(), actualUrl.Query()) } func Test_buildRootItemUrl(t *testing.T) { @@ -40,7 +45,7 @@ func Test_buildRootItemUrl(t *testing.T) { expectedUrl, _ := url.Parse("https://dev.azure.com/organisation/project/_apis/git/repositories/repository/items?scopePath=/&api-version=6.0&versionDescriptor.version=main&versionDescriptor.versionType=branch") actualUrl, _ := url.Parse(u) - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, expectedUrl.Host, actualUrl.Host) assert.Equal(t, expectedUrl.Scheme, actualUrl.Scheme) assert.Equal(t, expectedUrl.Path, actualUrl.Path) @@ -57,7 +62,7 @@ func Test_buildRefsUrl(t *testing.T) { expectedUrl, _ := url.Parse("https://dev.azure.com/organisation/project/_apis/git/repositories/repository/refs?api-version=6.0") actualUrl, _ := url.Parse(u) - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, expectedUrl.Host, actualUrl.Host) assert.Equal(t, expectedUrl.Scheme, actualUrl.Scheme) assert.Equal(t, expectedUrl.Path, actualUrl.Path) @@ -74,7 +79,7 @@ func Test_buildTreeUrl(t *testing.T) { expectedUrl, _ := url.Parse("https://dev.azure.com/organisation/project/_apis/git/repositories/repository/trees/sha1?api-version=6.0&recursive=true") actualUrl, _ := url.Parse(u) - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, expectedUrl.Host, actualUrl.Host) assert.Equal(t, expectedUrl.Scheme, actualUrl.Scheme) assert.Equal(t, expectedUrl.Path, actualUrl.Path) @@ -304,7 +309,7 @@ func Test_azureDownloader_downloadZipFromAzureDevOps(t *testing.T) { }, } _, err := a.downloadZipFromAzureDevOps(context.Background(), option) - assert.Error(t, err) + require.Error(t, err) assert.Equal(t, tt.want, zipRequestAuth) }) } @@ -502,12 +507,12 @@ func Test_listRefs_azure(t *testing.T) { t.Run(tt.name, func(t *testing.T) { refs, err := client.listRefs(context.TODO(), tt.args) if tt.expect.err == nil { - assert.NoError(t, err) + require.NoError(t, err) if tt.expect.refsCount > 0 { - assert.Greater(t, len(refs), 0) + assert.NotEmpty(t, refs) } } else { - assert.Error(t, err) + require.Error(t, err) assert.Equal(t, tt.expect.err, err) } }) @@ -613,14 +618,14 @@ func Test_listFiles_azure(t *testing.T) { t.Run(tt.name, func(t *testing.T) { paths, err := client.listFiles(context.TODO(), tt.args) if tt.expect.shouldFail { - assert.Error(t, err) + require.Error(t, err) if tt.expect.err != nil { assert.Equal(t, tt.expect.err, err) } } else { - assert.NoError(t, err) + require.NoError(t, err) if tt.expect.matchedCount > 0 { - assert.Greater(t, len(paths), 0) + assert.NotEmpty(t, paths) } } }) diff --git a/api/git/git_integration_test.go b/api/git/git_integration_test.go index 6cb10253a..e497b1910 100644 --- a/api/git/git_integration_test.go +++ b/api/git/git_integration_test.go @@ -9,7 +9,9 @@ import ( "time" gittypes "github.com/portainer/portainer/api/git/types" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) const ( @@ -35,7 +37,7 @@ func TestService_ClonePrivateRepository_GitHub(t *testing.T) { gittypes.GitCredentialAuthType_Basic, false, ) - assert.NoError(t, err) + require.NoError(t, err) assert.FileExists(t, filepath.Join(dst, "README.md")) } @@ -55,7 +57,7 @@ func TestService_LatestCommitID_GitHub(t *testing.T) { gittypes.GitCredentialAuthType_Basic, false, ) - assert.NoError(t, err) + require.NoError(t, err) assert.NotEmpty(t, id, "cannot guarantee commit id, but it should be not empty") } @@ -68,7 +70,7 @@ func TestService_ListRefs_GitHub(t *testing.T) { repositoryUrl := privateGitRepoURL refs, err := service.ListRefs(repositoryUrl, username, accessToken, gittypes.GitCredentialAuthType_Basic, false, false) - assert.NoError(t, err) + require.NoError(t, err) assert.GreaterOrEqual(t, len(refs), 1) } @@ -231,14 +233,14 @@ func TestService_ListFiles_GitHub(t *testing.T) { false, ) if tt.expect.shouldFail { - assert.Error(t, err) + require.Error(t, err) if tt.expect.err != nil { assert.Equal(t, tt.expect.err, err) } } else { - assert.NoError(t, err) + require.NoError(t, err) if tt.expect.matchedCount > 0 { - assert.Greater(t, len(paths), 0) + assert.NotEmpty(t, paths) } } }) @@ -361,12 +363,12 @@ func TestService_HardRefresh_ListRefs_GitHub(t *testing.T) { repositoryUrl := privateGitRepoURL refs, err := service.ListRefs(repositoryUrl, username, accessToken, gittypes.GitCredentialAuthType_Basic, false, false) - assert.NoError(t, err) + require.NoError(t, err) assert.GreaterOrEqual(t, len(refs), 1) assert.Equal(t, 1, service.repoRefCache.Len()) _, err = service.ListRefs(repositoryUrl, username, "fake-token", gittypes.GitCredentialAuthType_Basic, false, false) - assert.Error(t, err) + require.Error(t, err) assert.Equal(t, 1, service.repoRefCache.Len()) } @@ -379,7 +381,7 @@ func TestService_HardRefresh_ListRefs_And_RemoveAllCaches_GitHub(t *testing.T) { repositoryUrl := privateGitRepoURL refs, err := service.ListRefs(repositoryUrl, username, accessToken, gittypes.GitCredentialAuthType_Basic, false, false) - assert.NoError(t, err) + require.NoError(t, err) assert.GreaterOrEqual(t, len(refs), 1) assert.Equal(t, 1, service.repoRefCache.Len()) @@ -394,7 +396,7 @@ func TestService_HardRefresh_ListRefs_And_RemoveAllCaches_GitHub(t *testing.T) { []string{}, false, ) - assert.NoError(t, err) + require.NoError(t, err) assert.GreaterOrEqual(t, len(files), 1) assert.Equal(t, 1, service.repoFileCache.Len()) @@ -409,16 +411,16 @@ func TestService_HardRefresh_ListRefs_And_RemoveAllCaches_GitHub(t *testing.T) { []string{}, false, ) - assert.NoError(t, err) + require.NoError(t, err) assert.GreaterOrEqual(t, len(files), 1) assert.Equal(t, 2, service.repoFileCache.Len()) _, err = service.ListRefs(repositoryUrl, username, "fake-token", gittypes.GitCredentialAuthType_Basic, false, false) - assert.Error(t, err) + require.Error(t, err) assert.Equal(t, 1, service.repoRefCache.Len()) _, err = service.ListRefs(repositoryUrl, username, "fake-token", gittypes.GitCredentialAuthType_Basic, true, false) - assert.Error(t, err) + require.Error(t, err) assert.Equal(t, 1, service.repoRefCache.Len()) // The relevant file caches should be removed too assert.Equal(t, 0, service.repoFileCache.Len()) @@ -442,7 +444,7 @@ func TestService_HardRefresh_ListFiles_GitHub(t *testing.T) { []string{}, false, ) - assert.NoError(t, err) + require.NoError(t, err) assert.GreaterOrEqual(t, len(files), 1) assert.Equal(t, 1, service.repoFileCache.Len()) @@ -457,7 +459,7 @@ func TestService_HardRefresh_ListFiles_GitHub(t *testing.T) { []string{}, false, ) - assert.Error(t, err) + require.Error(t, err) assert.Equal(t, 0, service.repoFileCache.Len()) } diff --git a/api/git/git_test.go b/api/git/git_test.go index b14e45596..1158cc49e 100644 --- a/api/git/git_test.go +++ b/api/git/git_test.go @@ -13,6 +13,7 @@ import ( "github.com/go-git/go-git/v5/plumbing/object" "github.com/pkg/errors" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func setup(t *testing.T) string { @@ -39,7 +40,7 @@ func Test_ClonePublicRepository_Shallow(t *testing.T) { dir := t.TempDir() t.Logf("Cloning into %s", dir) err := service.CloneRepository(dir, repositoryURL, referenceName, "", "", gittypes.GitCredentialAuthType_Basic, false) - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, 1, getCommitHistoryLength(t, dir), "cloned repo has incorrect depth") } @@ -51,7 +52,7 @@ func Test_ClonePublicRepository_NoGitDirectory(t *testing.T) { dir := t.TempDir() t.Logf("Cloning into %s", dir) err := service.CloneRepository(dir, repositoryURL, referenceName, "", "", gittypes.GitCredentialAuthType_Basic, false) - assert.NoError(t, err) + require.NoError(t, err) assert.NoDirExists(t, filepath.Join(dir, ".git")) } @@ -74,7 +75,7 @@ func Test_cloneRepository(t *testing.T) { depth: 10, }) - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, 4, getCommitHistoryLength(t, dir), "cloned repo has incorrect depth") } @@ -86,7 +87,7 @@ func Test_latestCommitID(t *testing.T) { id, err := service.LatestCommitID(repositoryURL, referenceName, "", "", gittypes.GitCredentialAuthType_Basic, false) - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, "68dcaa7bd452494043c64252ab90db0f98ecf8d2", id) } @@ -97,7 +98,7 @@ func Test_ListRefs(t *testing.T) { fs, err := service.ListRefs(repositoryURL, "", "", gittypes.GitCredentialAuthType_Basic, false, false) - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, []string{"refs/heads/main"}, fs) } @@ -119,7 +120,7 @@ func Test_ListFiles(t *testing.T) { false, ) - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, []string{"docker-compose.yml"}, fs) } @@ -214,12 +215,12 @@ func Test_listRefsPrivateRepository(t *testing.T) { t.Run(tt.name, func(t *testing.T) { refs, err := client.listRefs(context.TODO(), tt.args) if tt.expect.err == nil { - assert.NoError(t, err) + require.NoError(t, err) if tt.expect.refsCount > 0 { - assert.Greater(t, len(refs), 0) + assert.NotEmpty(t, refs) } } else { - assert.Error(t, err) + require.Error(t, err) assert.Equal(t, tt.expect.err, err) } }) @@ -325,14 +326,14 @@ func Test_listFilesPrivateRepository(t *testing.T) { t.Run(tt.name, func(t *testing.T) { paths, err := client.listFiles(context.TODO(), tt.args) if tt.expect.shouldFail { - assert.Error(t, err) + require.Error(t, err) if tt.expect.err != nil { assert.Equal(t, tt.expect.err, err) } } else { - assert.NoError(t, err) + require.NoError(t, err) if tt.expect.matchedCount > 0 { - assert.Greater(t, len(paths), 0) + assert.NotEmpty(t, paths) } } }) diff --git a/api/http/handler/backup/restore_test.go b/api/http/handler/backup/restore_test.go index a85eec079..80c5b41e6 100644 --- a/api/http/handler/backup/restore_test.go +++ b/api/http/handler/backup/restore_test.go @@ -18,6 +18,7 @@ import ( "github.com/portainer/portainer/api/internal/testhelpers" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func Test_restoreArchive_usingCombinationOfPasswords(t *testing.T) { @@ -64,13 +65,12 @@ func Test_restoreArchive_usingCombinationOfPasswords(t *testing.T) { adminMonitor, ) - //backup + // backup archive := backup(t, h, test.backupPassword) - //restore + // restore w := httptest.NewRecorder() - r, err := prepareMultipartRequest(test.restorePassword, archive) - assert.Nil(t, err, "Shouldn't fail to write multipart form") + r := prepareMultipartRequest(t, test.restorePassword, archive) restoreErr := h.restore(w, r) assert.Equal(t, test.fails, restoreErr != nil, "Didn't meet expectation of failing restore handler") @@ -96,13 +96,12 @@ func Test_restoreArchive_shouldFailIfSystemWasAlreadyInitialized(t *testing.T) { adminMonitor, ) - //backup + // backup archive := backup(t, h, "password") - //restore + // restore w := httptest.NewRecorder() - r, err := prepareMultipartRequest("password", archive) - assert.Nil(t, err, "Shouldn't fail to write multipart form") + r := prepareMultipartRequest(t, "password", archive) restoreErr := h.restore(w, r) assert.NotNil(t, restoreErr, "Should fail, because system it already initialized") @@ -117,31 +116,31 @@ func backup(t *testing.T, h *Handler, password string) []byte { assert.Nil(t, backupErr, "Backup should not fail") response := w.Result() - archive, _ := io.ReadAll(response.Body) + archive, err := io.ReadAll(response.Body) + require.NoError(t, err) response.Body.Close() return archive } -func prepareMultipartRequest(password string, file []byte) (*http.Request, error) { +func prepareMultipartRequest(t *testing.T, password string, file []byte) *http.Request { var body bytes.Buffer w := multipart.NewWriter(&body) err := w.WriteField("password", password) - if err != nil { - return nil, err - } + require.NoError(t, err) fw, err := w.CreateFormFile("file", "filename") - if err != nil { - return nil, err - } - io.Copy(fw, bytes.NewReader(file)) + require.NoError(t, err) + + _, err = io.Copy(fw, bytes.NewReader(file)) + require.NoError(t, err) r := httptest.NewRequest(http.MethodPost, "http://localhost/", &body) r.Header.Set("Content-Type", w.FormDataContentType()) - w.Close() + err = w.Close() + require.NoError(t, err) - return r, nil + return r } diff --git a/api/http/handler/customtemplates/customtemplate_git_fetch_test.go b/api/http/handler/customtemplates/customtemplate_git_fetch_test.go index 6cb614449..83083d0db 100644 --- a/api/http/handler/customtemplates/customtemplate_git_fetch_test.go +++ b/api/http/handler/customtemplates/customtemplate_git_fetch_test.go @@ -9,7 +9,6 @@ import ( "net/http/httptest" "os" "path/filepath" - "sync" "testing" "time" @@ -25,6 +24,8 @@ import ( "github.com/segmentio/encoding/json" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "golang.org/x/sync/errgroup" ) func init() { @@ -112,15 +113,14 @@ func createTestFile(targetPath string) error { } func prepareTestFolder(projectPath, filename string) error { - err := os.MkdirAll(projectPath, fs.ModePerm) - if err != nil { + if err := os.MkdirAll(projectPath, fs.ModePerm); err != nil { return err } return createTestFile(filepath.Join(projectPath, filename)) } -func singleAPIRequest(h *Handler, jwt string, is *assert.Assertions, expect string) { +func singleAPIRequest(h *Handler, jwt string, expect string) error { type response struct { FileContent string } @@ -131,15 +131,25 @@ func singleAPIRequest(h *Handler, jwt string, is *assert.Assertions, expect stri rr := httptest.NewRecorder() h.ServeHTTP(rr, req) - is.Equal(http.StatusOK, rr.Code) + if rr.Code != http.StatusOK { + return errors.New("unexpected status code: " + http.StatusText(rr.Code)) + } body, err := io.ReadAll(rr.Body) - is.NoError(err, "ReadAll should not return error") + if err != nil { + return err + } var resp response - err = json.Unmarshal(body, &resp) - is.NoError(err, "response should be list json") - is.Equal(resp.FileContent, expect) + if err := json.Unmarshal(body, &resp); err != nil { + return err + } + + if resp.FileContent != expect { + return errors.New("unexpected file content: " + resp.FileContent + ", expected: " + expect) + } + + return nil } func Test_customTemplateGitFetch(t *testing.T) { @@ -150,28 +160,29 @@ func Test_customTemplateGitFetch(t *testing.T) { // create user(s) user1 := &portainer.User{ID: 1, Username: "user-1", Role: portainer.StandardUserRole, PortainerAuthorizations: authorization.DefaultPortainerAuthorizations()} err := store.User().Create(user1) - is.NoError(err, "error creating user 1") + require.NoError(t, err, "error creating user 1") user2 := &portainer.User{ID: 2, Username: "user-2", Role: portainer.StandardUserRole, PortainerAuthorizations: authorization.DefaultPortainerAuthorizations()} err = store.User().Create(user2) - is.NoError(err, "error creating user 2") + require.NoError(t, err, "error creating user 2") dir, err := os.Getwd() - is.NoError(err, "error to get working directory") + require.NoError(t, err, "error to get working directory") template1 := &portainer.CustomTemplate{ID: 1, Title: "custom-template-1", ProjectPath: filepath.Join(dir, "fixtures/custom_template_1"), GitConfig: &gittypes.RepoConfig{ConfigFilePath: "test-config-path.txt"}} err = store.CustomTemplateService.Create(template1) - is.NoError(err, "error creating custom template 1") + require.NoError(t, err, "error creating custom template 1") // prepare testing folder err = prepareTestFolder(template1.ProjectPath, template1.GitConfig.ConfigFilePath) - is.NoError(err, "error creating testing folder") + require.NoError(t, err, "error creating testing folder") defer os.RemoveAll(filepath.Join(dir, "fixtures")) // setup services jwtService, err := jwt.NewService("1h", store) - is.NoError(err, "Error initiating jwt service") + require.NoError(t, err, "Error initiating jwt service") + requestBouncer := security.NewRequestBouncer(store, jwtService, nil) gitService := &TestGitService{ @@ -182,52 +193,55 @@ func Test_customTemplateGitFetch(t *testing.T) { h := NewHandler(requestBouncer, store, fileService, gitService) // generate two standard users' tokens - jwt1, _, _ := jwtService.GenerateToken(&portainer.TokenData{ID: user1.ID, Username: user1.Username, Role: user1.Role}) - jwt2, _, _ := jwtService.GenerateToken(&portainer.TokenData{ID: user2.ID, Username: user2.Username, Role: user2.Role}) + jwt1, _, err := jwtService.GenerateToken(&portainer.TokenData{ID: user1.ID, Username: user1.Username, Role: user1.Role}) + require.NoError(t, err) + + jwt2, _, err := jwtService.GenerateToken(&portainer.TokenData{ID: user2.ID, Username: user2.Username, Role: user2.Role}) + require.NoError(t, err) t.Run("can return the expected file content by a single call from one user", func(t *testing.T) { - singleAPIRequest(h, jwt1, is, "abcdefg") + err := singleAPIRequest(h, jwt1, "abcdefg") + require.NoError(t, err) }) t.Run("can return the expected file content by multiple calls from one user", func(t *testing.T) { - var wg sync.WaitGroup - wg.Add(5) + var g errgroup.Group for range 5 { - go func() { - singleAPIRequest(h, jwt1, is, "abcdefg") - wg.Done() - }() + g.Go(func() error { + return singleAPIRequest(h, jwt1, "abcdefg") + }) } - wg.Wait() + err := g.Wait() + require.NoError(t, err) }) t.Run("can return the expected file content by multiple calls from different users", func(t *testing.T) { - var wg sync.WaitGroup - wg.Add(10) + var g errgroup.Group for i := range 10 { - go func(j int) { - if j%2 == 0 { - singleAPIRequest(h, jwt1, is, "abcdefg") - } else { - singleAPIRequest(h, jwt2, is, "abcdefg") + g.Go(func() error { + if i%2 == 0 { + return singleAPIRequest(h, jwt1, "abcdefg") } - wg.Done() - }(i) + return singleAPIRequest(h, jwt2, "abcdefg") + }) } - wg.Wait() + err := g.Wait() + require.NoError(t, err) }) t.Run("can return the expected file content after a new commit is made", func(t *testing.T) { - singleAPIRequest(h, jwt1, is, "abcdefg") + err := singleAPIRequest(h, jwt1, "abcdefg") + require.NoError(t, err) testFileContent = "gfedcba" - singleAPIRequest(h, jwt2, is, "gfedcba") + err = singleAPIRequest(h, jwt2, "gfedcba") + require.NoError(t, err) }) t.Run("restore git repository if it is failed to download the new git repository", func(t *testing.T) { @@ -246,11 +260,11 @@ func Test_customTemplateGitFetch(t *testing.T) { var errResp httperror.HandlerError err = json.NewDecoder(rr.Body).Decode(&errResp) - assert.NoError(t, err, "failed to parse error body") + require.NoError(t, err, "failed to parse error body") assert.FileExists(t, gitService.targetFilePath, "previous git repository is not restored") fileContent, err := os.ReadFile(gitService.targetFilePath) - assert.NoError(t, err, "failed to read target file") + require.NoError(t, err, "failed to read target file") assert.Equal(t, "gfedcba", string(fileContent)) }) } diff --git a/api/http/handler/docker/utils/get_stacks_test.go b/api/http/handler/docker/utils/get_stacks_test.go index 1f14e6a77..a50150144 100644 --- a/api/http/handler/docker/utils/get_stacks_test.go +++ b/api/http/handler/docker/utils/get_stacks_test.go @@ -11,6 +11,7 @@ import ( "github.com/portainer/portainer/api/internal/testhelpers" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func TestHandler_getDockerStacks(t *testing.T) { @@ -69,7 +70,7 @@ func TestHandler_getDockerStacks(t *testing.T) { stacksList, err := GetDockerStacks(datastore, &security.RestrictedRequestContext{ IsAdmin: true, }, environment.ID, containers, services) - assert.NoError(t, err) + require.NoError(t, err) assert.Len(t, stacksList, 3) expectedStacks := []StackViewModel{ diff --git a/api/http/handler/edgegroups/edgegroup_inspect_test.go b/api/http/handler/edgegroups/edgegroup_inspect_test.go index 5af282372..259c06b00 100644 --- a/api/http/handler/edgegroups/edgegroup_inspect_test.go +++ b/api/http/handler/edgegroups/edgegroup_inspect_test.go @@ -105,7 +105,7 @@ func TestEmptyEdgeGroupInspectHandler(t *testing.T) { // Make sure the frontend does not get a null value but a [] instead require.NotNil(t, responseGroup.Endpoints) - require.Len(t, responseGroup.Endpoints, 0) + require.Empty(t, responseGroup.Endpoints) } func TestDynamicEdgeGroupInspectHandler(t *testing.T) { diff --git a/api/http/handler/edgegroups/edgegroup_list_test.go b/api/http/handler/edgegroups/edgegroup_list_test.go index bf084c377..662f1fcde 100644 --- a/api/http/handler/edgegroups/edgegroup_list_test.go +++ b/api/http/handler/edgegroups/edgegroup_list_test.go @@ -47,7 +47,7 @@ func Test_getEndpointTypes(t *testing.T) { for _, test := range tests { ans, err := getEndpointTypes(datastore, roar.FromSlice(test.endpointIds)) - assert.NoError(t, err, "getEndpointTypes shouldn't fail") + require.NoError(t, err, "getEndpointTypes shouldn't fail") assert.ElementsMatch(t, test.expected, ans, "getEndpointTypes expected to return %b for %v, but returned %b", test.expected, test.endpointIds, ans) } @@ -57,7 +57,7 @@ func Test_getEndpointTypes_failWhenEndpointDontExist(t *testing.T) { datastore := testhelpers.NewDatastore(testhelpers.WithEndpoints([]portainer.Endpoint{})) _, err := getEndpointTypes(datastore, roar.FromSlice([]portainer.EndpointID{1})) - assert.Error(t, err, "getEndpointTypes should fail") + require.Error(t, err, "getEndpointTypes should fail") } func TestEdgeGroupListHandler(t *testing.T) { @@ -112,5 +112,5 @@ func TestEdgeGroupListHandler(t *testing.T) { require.Len(t, responseGroups, 1) require.ElementsMatch(t, []portainer.EndpointID{1, 2, 3}, responseGroups[0].Endpoints) - require.Len(t, responseGroups[0].TrustedEndpoints, 0) + require.Empty(t, responseGroups[0].TrustedEndpoints) } diff --git a/api/http/handler/edgejobs/edgejob_tasks_list_test.go b/api/http/handler/edgejobs/edgejob_tasks_list_test.go index 6224ed628..9e962d4be 100644 --- a/api/http/handler/edgejobs/edgejob_tasks_list_test.go +++ b/api/http/handler/edgejobs/edgejob_tasks_list_test.go @@ -11,6 +11,7 @@ import ( "github.com/portainer/portainer/api/datastore" "github.com/portainer/portainer/api/internal/testhelpers" "github.com/portainer/portainer/api/roar" + "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) @@ -68,14 +69,16 @@ func Test_EdgeJobTasksListHandler(t *testing.T) { tcStr := rr.Header().Get("x-total-count") assert.NotEmpty(t, tcStr) + totalCount, err := strconv.Atoi(tcStr) - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, expectedCount, totalCount) taStr := rr.Header().Get("x-total-available") assert.NotEmpty(t, taStr) + totalAvailable, err := strconv.Atoi(taStr) - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, envCount, totalAvailable) } diff --git a/api/http/handler/edgestacks/endpoints_test.go b/api/http/handler/edgestacks/endpoints_test.go index 6cc94b17c..064ad9839 100644 --- a/api/http/handler/edgestacks/endpoints_test.go +++ b/api/http/handler/edgestacks/endpoints_test.go @@ -5,7 +5,9 @@ import ( portainer "github.com/portainer/portainer/api" "github.com/portainer/portainer/api/internal/testhelpers" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func Test_hasKubeEndpoint(t *testing.T) { @@ -40,7 +42,7 @@ func Test_hasKubeEndpoint(t *testing.T) { for _, test := range tests { ans, err := hasKubeEndpoint(datastore.Endpoint(), test.endpointIds) - assert.NoError(t, err, "hasKubeEndpoint shouldn't fail") + require.NoError(t, err, "hasKubeEndpoint shouldn't fail") assert.Equal(t, test.expected, ans, "hasKubeEndpoint expected to return %b for %v, but returned %b", test.expected, test.endpointIds, ans) } @@ -50,7 +52,7 @@ func Test_hasKubeEndpoint_failWhenEndpointDontExist(t *testing.T) { datastore := testhelpers.NewDatastore(testhelpers.WithEndpoints([]portainer.Endpoint{})) _, err := hasKubeEndpoint(datastore.Endpoint(), []portainer.EndpointID{1}) - assert.Error(t, err, "hasKubeEndpoint should fail") + require.Error(t, err, "hasKubeEndpoint should fail") } func Test_hasDockerEndpoint(t *testing.T) { @@ -85,7 +87,7 @@ func Test_hasDockerEndpoint(t *testing.T) { for _, test := range tests { ans, err := hasDockerEndpoint(datastore.Endpoint(), test.endpointIds) - assert.NoError(t, err, "hasDockerEndpoint shouldn't fail") + require.NoError(t, err, "hasDockerEndpoint shouldn't fail") assert.Equal(t, test.expected, ans, "hasDockerEndpoint expected to return %b for %v, but returned %b", test.expected, test.endpointIds, ans) } @@ -95,5 +97,5 @@ func Test_hasDockerEndpoint_failWhenEndpointDontExist(t *testing.T) { datastore := testhelpers.NewDatastore(testhelpers.WithEndpoints([]portainer.Endpoint{})) _, err := hasDockerEndpoint(datastore.Endpoint(), []portainer.EndpointID{1}) - assert.Error(t, err, "hasDockerEndpoint should fail") + require.Error(t, err, "hasDockerEndpoint should fail") } diff --git a/api/http/handler/endpoints/endpoint_list_test.go b/api/http/handler/endpoints/endpoint_list_test.go index 90b74c4ee..f868eefb8 100644 --- a/api/http/handler/endpoints/endpoint_list_test.go +++ b/api/http/handler/endpoints/endpoint_list_test.go @@ -15,6 +15,7 @@ import ( "github.com/segmentio/encoding/json" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) type endpointListTest struct { @@ -86,9 +87,9 @@ func Test_EndpointList_AgentVersion(t *testing.T) { req := buildEndpointListRequest(query) resp, err := doEndpointListRequest(req, handler, is) - is.NoError(err) + require.NoError(t, err) - is.Equal(len(test.expected), len(resp)) + is.Len(resp, len(test.expected)) respIds := []portainer.EndpointID{} @@ -164,9 +165,9 @@ func Test_endpointList_edgeFilter(t *testing.T) { req := buildEndpointListRequest(query) resp, err := doEndpointListRequest(req, handler, is) - is.NoError(err) + require.NoError(t, err) - is.Equal(len(test.expected), len(resp)) + is.Len(resp, len(test.expected)) respIds := []portainer.EndpointID{} @@ -180,16 +181,15 @@ func Test_endpointList_edgeFilter(t *testing.T) { } func setupEndpointListHandler(t *testing.T, endpoints []portainer.Endpoint) *Handler { - is := assert.New(t) _, store := datastore.MustNewTestStore(t, true, true) for _, endpoint := range endpoints { err := store.Endpoint().Create(&endpoint) - is.NoError(err, "error creating environment") + require.NoError(t, err, "error creating environment") } err := store.User().Create(&portainer.User{Username: "admin", Role: portainer.AdministratorRole}) - is.NoError(err, "error creating a user") + require.NoError(t, err, "error creating a user") bouncer := testhelpers.NewTestRequestBouncer() diff --git a/api/http/handler/endpoints/filter_test.go b/api/http/handler/endpoints/filter_test.go index 1e483bee8..6565464eb 100644 --- a/api/http/handler/endpoints/filter_test.go +++ b/api/http/handler/endpoints/filter_test.go @@ -261,9 +261,9 @@ func runTest(t *testing.T, test filterTest, handler *Handler, endpoints []portai &security.RestrictedRequestContext{IsAdmin: true}, ) - is.NoError(err) + require.NoError(t, err) - is.Equal(len(test.expected), len(filteredEndpoints)) + is.Len(filteredEndpoints, len(test.expected)) respIds := []portainer.EndpointID{} @@ -275,16 +275,15 @@ func runTest(t *testing.T, test filterTest, handler *Handler, endpoints []portai } func setupFilterTest(t *testing.T, endpoints []portainer.Endpoint) *Handler { - is := assert.New(t) _, store := datastore.MustNewTestStore(t, true, true) for _, endpoint := range endpoints { err := store.Endpoint().Create(&endpoint) - is.NoError(err, "error creating environment") + require.NoError(t, err, "error creating environment") } err := store.User().Create(&portainer.User{Username: "admin", Role: portainer.AdministratorRole}) - is.NoError(err, "error creating a user") + require.NoError(t, err, "error creating a user") bouncer := testhelpers.NewTestRequestBouncer() handler := NewHandler(bouncer) @@ -408,11 +407,11 @@ func TestFilterEndpointsByExcludeEdgeGroupIDs(t *testing.T) { require.NoError(t, err) require.Len(t, es, 3) - require.Equal(t, es, []portainer.Endpoint{ + require.Equal(t, []portainer.Endpoint{ {ID: 2, Name: "Endpoint 2"}, {ID: 3, Name: "Endpoint 3"}, {ID: 4, Name: "Endpoint 4"}, - }) + }, es) require.Len(t, egs, 1) require.Equal(t, egs[0].ID, portainer.EdgeGroupID(2)) diff --git a/api/http/handler/endpoints/utils_update_edge_groups_test.go b/api/http/handler/endpoints/utils_update_edge_groups_test.go index a57651fae..3f9539307 100644 --- a/api/http/handler/endpoints/utils_update_edge_groups_test.go +++ b/api/http/handler/endpoints/utils_update_edge_groups_test.go @@ -8,6 +8,7 @@ import ( "github.com/portainer/portainer/api/datastore" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func Test_updateEdgeGroups(t *testing.T) { @@ -33,7 +34,7 @@ func Test_updateEdgeGroups(t *testing.T) { checkGroups := func(store *datastore.Store, is *assert.Assertions, groupIDs []portainer.EdgeGroupID, endpointID portainer.EndpointID) { for _, groupID := range groupIDs { group, err := store.EdgeGroup().Read(groupID) - is.NoError(err) + require.NoError(t, err) is.True(group.EndpointIDs.Contains(endpointID), "expected endpoint to be in group") @@ -69,17 +70,17 @@ func Test_updateEdgeGroups(t *testing.T) { _, store := datastore.MustNewTestStore(t, true, true) err := store.Endpoint().Create(testCase.endpoint) - is.NoError(err) + require.NoError(t, err) groups, err := createGroups(store, testCase.groupNames) - is.NoError(err) + require.NoError(t, err) endpointGroups := groupsByName(groups, testCase.endpointGroupNames) for _, group := range endpointGroups { group.EndpointIDs.Add(testCase.endpoint.ID) err = store.EdgeGroup().Update(group.ID, &group) - is.NoError(err) + require.NoError(t, err) } expectedGroups := groupsByName(groups, testCase.groupsToApply) @@ -91,14 +92,14 @@ func Test_updateEdgeGroups(t *testing.T) { err = store.UpdateTx(func(tx dataservices.DataStoreTx) error { updated, err := updateEnvironmentEdgeGroups(tx, expectedIDs, testCase.endpoint.ID) - is.NoError(err) + require.NoError(t, err) is.Equal(testCase.shouldNotBeUpdated, !updated) return nil }) - is.NoError(err) + require.NoError(t, err) checkGroups(store, is, expectedIDs, testCase.endpoint.ID) } diff --git a/api/http/handler/endpoints/utils_update_tags_test.go b/api/http/handler/endpoints/utils_update_tags_test.go index 527f963a4..d176a71dd 100644 --- a/api/http/handler/endpoints/utils_update_tags_test.go +++ b/api/http/handler/endpoints/utils_update_tags_test.go @@ -6,7 +6,9 @@ import ( portainer "github.com/portainer/portainer/api" "github.com/portainer/portainer/api/dataservices" "github.com/portainer/portainer/api/datastore" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func Test_updateTags(t *testing.T) { @@ -33,7 +35,7 @@ func Test_updateTags(t *testing.T) { checkTags := func(store *datastore.Store, is *assert.Assertions, tagIDs []portainer.TagID, endpointID portainer.EndpointID) { for _, tagID := range tagIDs { tag, err := store.Tag().Read(tagID) - is.NoError(err) + require.NoError(t, err) _, ok := tag.Endpoints[endpointID] is.True(ok, "expected endpoint to be tagged") @@ -77,23 +79,23 @@ func Test_updateTags(t *testing.T) { _, store := datastore.MustNewTestStore(t, true, true) err := store.Endpoint().Create(testCase.endpoint) - is.NoError(err) + require.NoError(t, err) tags, err := createTags(store, testCase.tagNames) - is.NoError(err) + require.NoError(t, err) endpointTags := tagsByName(tags, testCase.endpointTagNames) for _, tag := range endpointTags { tag.Endpoints[testCase.endpoint.ID] = true err = store.Tag().Update(tag.ID, &tag) - is.NoError(err) + require.NoError(t, err) } endpointTagIDs := getIDs(endpointTags) testCase.endpoint.TagIDs = endpointTagIDs err = store.Endpoint().UpdateEndpoint(testCase.endpoint.ID, testCase.endpoint) - is.NoError(err) + require.NoError(t, err) expectedTags := tagsByName(tags, testCase.tagsToApply) expectedTagIDs := make([]portainer.TagID, len(expectedTags)) @@ -103,14 +105,14 @@ func Test_updateTags(t *testing.T) { err = store.UpdateTx(func(tx dataservices.DataStoreTx) error { updated, err := updateEnvironmentTags(tx, expectedTagIDs, testCase.endpoint.TagIDs, testCase.endpoint.ID) - is.NoError(err) + require.NoError(t, err) is.Equal(testCase.shouldNotBeUpdated, !updated) return nil }) - is.NoError(err) + require.NoError(t, err) checkTags(store, is, expectedTagIDs, testCase.endpoint.ID) } diff --git a/api/http/handler/helm/helm_delete_test.go b/api/http/handler/helm/helm_delete_test.go index 65bdd49f4..348b0cb36 100644 --- a/api/http/handler/helm/helm_delete_test.go +++ b/api/http/handler/helm/helm_delete_test.go @@ -16,6 +16,7 @@ import ( "github.com/portainer/portainer/pkg/libhelm/test" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func Test_helmDelete(t *testing.T) { @@ -24,13 +25,13 @@ func Test_helmDelete(t *testing.T) { _, store := datastore.MustNewTestStore(t, true, true) err := store.Endpoint().Create(&portainer.Endpoint{ID: 1}) - is.NoError(err, "Error creating environment") + require.NoError(t, err, "Error creating environment") err = store.User().Create(&portainer.User{Username: "admin", Role: portainer.AdministratorRole}) - is.NoError(err, "Error creating a user") + require.NoError(t, err, "Error creating a user") jwtService, err := jwt.NewService("1h", store) - is.NoError(err, "Error initiating jwt service") + require.NoError(t, err, "Error initiating jwt service") kubernetesDeployer := exectest.NewKubernetesDeployer() helmPackageManager := test.NewMockHelmPackageManager() diff --git a/api/http/handler/helm/helm_get_test.go b/api/http/handler/helm/helm_get_test.go index c77e7e940..cdf987112 100644 --- a/api/http/handler/helm/helm_get_test.go +++ b/api/http/handler/helm/helm_get_test.go @@ -19,6 +19,7 @@ import ( "github.com/segmentio/encoding/json" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func Test_helmGet(t *testing.T) { @@ -27,13 +28,13 @@ func Test_helmGet(t *testing.T) { _, store := datastore.MustNewTestStore(t, true, true) err := store.Endpoint().Create(&portainer.Endpoint{ID: 1}) - is.NoError(err, "Error creating environment") + require.NoError(t, err, "Error creating environment") err = store.User().Create(&portainer.User{Username: "admin", Role: portainer.AdministratorRole}) - is.NoError(err, "Error creating a user") + require.NoError(t, err, "Error creating a user") jwtService, err := jwt.NewService("1h", store) - is.NoError(err, "Error initiating jwt service") + require.NoError(t, err, "Error initiating jwt service") kubernetesDeployer := exectest.NewKubernetesDeployer() helmPackageManager := test.NewMockHelmPackageManager() @@ -57,7 +58,7 @@ func Test_helmGet(t *testing.T) { data := release.Release{} body, err := io.ReadAll(rr.Body) - is.NoError(err, "ReadAll should not return error") + require.NoError(t, err, "ReadAll should not return error") json.Unmarshal(body, &data) is.Equal(http.StatusOK, rr.Code, "Status should be 200") is.Equal("nginx-1", data.Name) diff --git a/api/http/handler/helm/helm_history_test.go b/api/http/handler/helm/helm_history_test.go index ce069b7ae..68b459b52 100644 --- a/api/http/handler/helm/helm_history_test.go +++ b/api/http/handler/helm/helm_history_test.go @@ -19,6 +19,7 @@ import ( "github.com/segmentio/encoding/json" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func Test_helmGetHistory(t *testing.T) { @@ -27,13 +28,13 @@ func Test_helmGetHistory(t *testing.T) { _, store := datastore.MustNewTestStore(t, true, true) err := store.Endpoint().Create(&portainer.Endpoint{ID: 1}) - is.NoError(err, "Error creating environment") + require.NoError(t, err, "Error creating environment") err = store.User().Create(&portainer.User{Username: "admin", Role: portainer.AdministratorRole}) - is.NoError(err, "Error creating a user") + require.NoError(t, err, "Error creating a user") jwtService, err := jwt.NewService("1h", store) - is.NoError(err, "Error initiating jwt service") + require.NoError(t, err, "Error initiating jwt service") kubernetesDeployer := exectest.NewKubernetesDeployer() helmPackageManager := test.NewMockHelmPackageManager() @@ -57,10 +58,10 @@ func Test_helmGetHistory(t *testing.T) { data := []release.Release{} body, err := io.ReadAll(rr.Body) - is.NoError(err, "ReadAll should not return error") + require.NoError(t, err, "ReadAll should not return error") json.Unmarshal(body, &data) is.Equal(http.StatusOK, rr.Code, "Status should be 200") - is.Equal(1, len(data)) + is.Len(data, 1) is.Equal("nginx-1", data[0].Name) }) } diff --git a/api/http/handler/helm/helm_install_test.go b/api/http/handler/helm/helm_install_test.go index d75511af6..508e892bc 100644 --- a/api/http/handler/helm/helm_install_test.go +++ b/api/http/handler/helm/helm_install_test.go @@ -20,6 +20,7 @@ import ( "github.com/segmentio/encoding/json" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func Test_helmInstall(t *testing.T) { @@ -28,13 +29,13 @@ func Test_helmInstall(t *testing.T) { _, store := datastore.MustNewTestStore(t, true, true) err := store.Endpoint().Create(&portainer.Endpoint{ID: 1}) - is.NoError(err, "error creating environment") + require.NoError(t, err, "error creating environment") err = store.User().Create(&portainer.User{Username: "admin", Role: portainer.AdministratorRole}) - is.NoError(err, "error creating a user") + require.NoError(t, err, "error creating a user") jwtService, err := jwt.NewService("1h", store) - is.NoError(err, "Error initiating jwt service") + require.NoError(t, err, "Error initiating jwt service") kubernetesDeployer := exectest.NewKubernetesDeployer() helmPackageManager := test.NewMockHelmPackageManager() @@ -46,7 +47,7 @@ func Test_helmInstall(t *testing.T) { // Install a single chart. We expect to get these values back options := options.InstallOptions{Name: "nginx-1", Chart: "nginx", Namespace: "default", Repo: "https://charts.bitnami.com/bitnami"} optdata, err := json.Marshal(options) - is.NoError(err) + require.NoError(t, err) t.Run("helmInstall succeeds with admin user", func(t *testing.T) { req := httptest.NewRequest(http.MethodPost, "/1/kubernetes/helm", bytes.NewBuffer(optdata)) @@ -60,12 +61,12 @@ func Test_helmInstall(t *testing.T) { is.Equal(http.StatusCreated, rr.Code, "Status should be 201") body, err := io.ReadAll(rr.Body) - is.NoError(err, "ReadAll should not return error") + require.NoError(t, err, "ReadAll should not return error") resp := release.Release{} err = json.Unmarshal(body, &resp) - is.NoError(err, "response should be json") - is.EqualValues(options.Name, resp.Name, "Name doesn't match") - is.EqualValues(options.Namespace, resp.Namespace, "Namespace doesn't match") + require.NoError(t, err, "response should be json") + is.Equal(options.Name, resp.Name, "Name doesn't match") + is.Equal(options.Namespace, resp.Namespace, "Namespace doesn't match") }) } diff --git a/api/http/handler/helm/helm_list_test.go b/api/http/handler/helm/helm_list_test.go index 58c6e9620..d752dd03b 100644 --- a/api/http/handler/helm/helm_list_test.go +++ b/api/http/handler/helm/helm_list_test.go @@ -19,6 +19,7 @@ import ( "github.com/segmentio/encoding/json" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func Test_helmList(t *testing.T) { @@ -27,13 +28,13 @@ func Test_helmList(t *testing.T) { _, store := datastore.MustNewTestStore(t, true, true) err := store.Endpoint().Create(&portainer.Endpoint{ID: 1}) - assert.NoError(t, err, "error creating environment") + require.NoError(t, err, "error creating environment") err = store.User().Create(&portainer.User{Username: "admin", Role: portainer.AdministratorRole}) - assert.NoError(t, err, "error creating a user") + require.NoError(t, err, "error creating a user") jwtService, err := jwt.NewService("1h", store) - is.NoError(err, "Error initialising jwt service") + require.NoError(t, err, "Error initialising jwt service") kubernetesDeployer := exectest.NewKubernetesDeployer() helmPackageManager := test.NewMockHelmPackageManager() @@ -56,13 +57,13 @@ func Test_helmList(t *testing.T) { is.Equal(http.StatusOK, rr.Code, "Status should be 200 OK") body, err := io.ReadAll(rr.Body) - is.NoError(err, "ReadAll should not return error") + require.NoError(t, err, "ReadAll should not return error") data := []release.ReleaseElement{} json.Unmarshal(body, &data) - if is.Equal(1, len(data), "Expected one chart entry") { - is.EqualValues(options.Name, data[0].Name, "Name doesn't match") - is.EqualValues(options.Chart, data[0].Chart, "Chart doesn't match") + if is.Len(data, 1, "Expected one chart entry") { + is.Equal(options.Name, data[0].Name, "Name doesn't match") + is.Equal(options.Chart, data[0].Chart, "Chart doesn't match") } }) } diff --git a/api/http/handler/helm/helm_repo_search_test.go b/api/http/handler/helm/helm_repo_search_test.go index e2815e1a4..3348f3eea 100644 --- a/api/http/handler/helm/helm_repo_search_test.go +++ b/api/http/handler/helm/helm_repo_search_test.go @@ -11,6 +11,7 @@ import ( "github.com/portainer/portainer/pkg/libhelm/test" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func Test_helmRepoSearch(t *testing.T) { @@ -33,7 +34,7 @@ func Test_helmRepoSearch(t *testing.T) { is.Equal(http.StatusOK, rr.Code, "Status should be 200 OK") body, err := io.ReadAll(rr.Body) - is.NoError(err, "ReadAll should not return error") + require.NoError(t, err, "ReadAll should not return error") is.NotEmpty(body, "Body should not be empty") }) } diff --git a/api/http/handler/helm/helm_show_test.go b/api/http/handler/helm/helm_show_test.go index f68fa49b2..6196a580a 100644 --- a/api/http/handler/helm/helm_show_test.go +++ b/api/http/handler/helm/helm_show_test.go @@ -10,7 +10,9 @@ import ( "github.com/portainer/portainer/api/internal/testhelpers" "github.com/portainer/portainer/pkg/libhelm/test" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func Test_helmShow(t *testing.T) { @@ -37,11 +39,11 @@ func Test_helmShow(t *testing.T) { rr := httptest.NewRecorder() h.ServeHTTP(rr, req) - is.Equal(rr.Code, http.StatusOK, "Status should be 200 OK") + is.Equal(http.StatusOK, rr.Code, "Status should be 200 OK") body, err := io.ReadAll(rr.Body) - is.NoError(err, "ReadAll should not return error") - is.EqualValues(string(body), expect, "Unexpected search response") + require.NoError(t, err, "ReadAll should not return error") + is.Equal(string(body), expect, "Unexpected search response") }) } } diff --git a/api/http/handler/kubernetes/config_test.go b/api/http/handler/kubernetes/config_test.go index 46875a460..f349760bc 100644 --- a/api/http/handler/kubernetes/config_test.go +++ b/api/http/handler/kubernetes/config_test.go @@ -4,6 +4,7 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func TestIsSelfSignedCertificate(t *testing.T) { @@ -179,7 +180,7 @@ w/pjiPVy for _, tt := range tc { t.Run(tt.name, func(t *testing.T) { actual, err := IsSelfSignedCertificate([]byte(tt.cert)) - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, tt.expected, actual) }) } diff --git a/api/http/handler/kubernetes/event_test.go b/api/http/handler/kubernetes/event_test.go index 77f38c511..e85306479 100644 --- a/api/http/handler/kubernetes/event_test.go +++ b/api/http/handler/kubernetes/event_test.go @@ -13,7 +13,9 @@ import ( "github.com/portainer/portainer/api/jwt" "github.com/portainer/portainer/api/kubernetes" kubeClient "github.com/portainer/portainer/api/kubernetes/cli" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) // Currently this test just tests the HTTP Handler is setup correctly, in the future we should move the ClientFactory to a mock in order @@ -28,13 +30,13 @@ func TestGetKubernetesEvents(t *testing.T) { Type: portainer.AgentOnKubernetesEnvironment, }, ) - is.NoError(err, "error creating environment") + require.NoError(t, err, "error creating environment") err = store.User().Create(&portainer.User{Username: "admin", Role: portainer.AdministratorRole}) - is.NoError(err, "error creating a user") + require.NoError(t, err, "error creating a user") jwtService, err := jwt.NewService("1h", store) - is.NoError(err, "Error initiating jwt service") + require.NoError(t, err, "Error initiating jwt service") tk, _, _ := jwtService.GenerateToken(&portainer.TokenData{ID: 1, Username: "admin", Role: portainer.AdministratorRole}) diff --git a/api/http/handler/registries/registry_access_test.go b/api/http/handler/registries/registry_access_test.go index e3798c5f2..2355c8bb7 100644 --- a/api/http/handler/registries/registry_access_test.go +++ b/api/http/handler/registries/registry_access_test.go @@ -12,6 +12,7 @@ import ( "github.com/gorilla/mux" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func Test_RegistryAccess_RequiresAuthentication(t *testing.T) { @@ -21,11 +22,11 @@ func Test_RegistryAccess_RequiresAuthentication(t *testing.T) { Name: "test-registry", URL: "https://registry.test.com", } + err := store.Registry().Create(registry) - assert.NoError(t, err) - handler := &Handler{ - DataStore: store, - } + require.NoError(t, err) + + handler := &Handler{DataStore: store} req := httptest.NewRequest(http.MethodGet, "/registries/1", nil) req = mux.SetURLVars(req, map[string]string{"id": "1"}) rr := httptest.NewRecorder() @@ -39,16 +40,13 @@ func Test_RegistryAccess_InvalidRegistryID(t *testing.T) { _, store := datastore.MustNewTestStore(t, true, true) user := &portainer.User{ID: 1, Username: "test", Role: portainer.StandardUserRole} err := store.User().Create(user) - assert.NoError(t, err) + require.NoError(t, err) - handler := &Handler{ - DataStore: store, - } + handler := &Handler{DataStore: store} req := httptest.NewRequest(http.MethodGet, "/registries/invalid", nil) req = mux.SetURLVars(req, map[string]string{"id": "invalid"}) tokenData := &portainer.TokenData{ID: 1, Role: portainer.StandardUserRole} req = req.WithContext(security.StoreTokenData(req, tokenData)) - rr := httptest.NewRecorder() testHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {}) @@ -60,14 +58,16 @@ func Test_RegistryAccess_InvalidRegistryID(t *testing.T) { func Test_RegistryAccess_RegistryNotFound(t *testing.T) { _, store := datastore.MustNewTestStore(t, true, true) + user := &portainer.User{ID: 1, Username: "test", Role: portainer.StandardUserRole} err := store.User().Create(user) - assert.NoError(t, err) + require.NoError(t, err) handler := &Handler{ DataStore: store, requestBouncer: testhelpers.NewTestRequestBouncer(), } + req := httptest.NewRequest(http.MethodGet, "/registries/999", nil) req = mux.SetURLVars(req, map[string]string{"id": "999"}) tokenData := &portainer.TokenData{ID: 1, Role: portainer.StandardUserRole} diff --git a/api/http/handler/registries/registry_create_test.go b/api/http/handler/registries/registry_create_test.go index 515dc6c5e..13954cb74 100644 --- a/api/http/handler/registries/registry_create_test.go +++ b/api/http/handler/registries/registry_create_test.go @@ -4,7 +4,8 @@ import ( "testing" portainer "github.com/portainer/portainer/api" - "github.com/stretchr/testify/assert" + + "github.com/stretchr/testify/require" ) func Test_registryCreatePayload_Validate(t *testing.T) { @@ -13,33 +14,33 @@ func Test_registryCreatePayload_Validate(t *testing.T) { payload := basePayload payload.Type = portainer.ProGetRegistry err := payload.Validate(nil) - assert.Error(t, err) + require.Error(t, err) }) t.Run("Can create a GitLab registry if BaseURL is empty", func(t *testing.T) { payload := basePayload payload.Type = portainer.GitlabRegistry err := payload.Validate(nil) - assert.NoError(t, err) + require.NoError(t, err) }) t.Run("Can create a ProGet registry if BaseURL is not empty", func(t *testing.T) { payload := basePayload payload.Type = portainer.ProGetRegistry payload.BaseURL = "http://example.com" err := payload.Validate(nil) - assert.NoError(t, err) + require.NoError(t, err) }) t.Run("Can't create a AWS ECR registry if authentication required, but access key ID, secret access key or region is empty", func(t *testing.T) { payload := basePayload payload.Type = portainer.EcrRegistry payload.Authentication = true err := payload.Validate(nil) - assert.Error(t, err) + require.Error(t, err) }) t.Run("Do not require access key ID, secret access key, region for public AWS ECR registry", func(t *testing.T) { payload := basePayload payload.Type = portainer.EcrRegistry payload.Authentication = false err := payload.Validate(nil) - assert.NoError(t, err) + require.NoError(t, err) }) } diff --git a/api/http/handler/stacks/webhook_invoke_test.go b/api/http/handler/stacks/webhook_invoke_test.go index b78b75579..0ed33dcf2 100644 --- a/api/http/handler/stacks/webhook_invoke_test.go +++ b/api/http/handler/stacks/webhook_invoke_test.go @@ -11,6 +11,7 @@ import ( "github.com/gofrs/uuid" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func TestHandler_webhookInvoke(t *testing.T) { @@ -51,7 +52,7 @@ func TestHandler_webhookInvoke(t *testing.T) { func newGuidString(t *testing.T) string { uuid, err := uuid.NewV4() - assert.NoError(t, err) + require.NoError(t, err) return uuid.String() } diff --git a/api/http/handler/system/version_test.go b/api/http/handler/system/version_test.go index 98c64d6a3..71d26ffa3 100644 --- a/api/http/handler/system/version_test.go +++ b/api/http/handler/system/version_test.go @@ -16,6 +16,7 @@ import ( "github.com/segmentio/encoding/json" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func Test_getSystemVersion(t *testing.T) { @@ -26,16 +27,16 @@ func Test_getSystemVersion(t *testing.T) { // create version data version := &models.Version{SchemaVersion: "2.20.0", Edition: 1} err := store.Version().UpdateVersion(version) - is.NoError(err, "error creating version data") + require.NoError(t, err, "error creating version data") // create admin and standard user(s) adminUser := &portainer.User{ID: 1, Username: "admin", Role: portainer.AdministratorRole} err = store.User().Create(adminUser) - is.NoError(err, "error creating admin user") + require.NoError(t, err, "error creating admin user") // setup services jwtService, err := jwt.NewService("1h", store) - is.NoError(err, "Error initiating jwt service") + require.NoError(t, err, "Error initiating jwt service") apiKeyService := apikey.NewAPIKeyService(store.APIKeyRepository(), store.User()) requestBouncer := security.NewRequestBouncer(store, jwtService, apiKeyService) @@ -55,11 +56,11 @@ func Test_getSystemVersion(t *testing.T) { is.Equal(http.StatusOK, rr.Code) body, err := io.ReadAll(rr.Body) - is.NoError(err, "ReadAll should not return error") + require.NoError(t, err, "ReadAll should not return error") var resp versionResponse err = json.Unmarshal(body, &resp) - is.NoError(err, "response should be list json") + require.NoError(t, err, "response should be list json") is.Equal("CE", resp.ServerEdition, "Edition is not expected") }) diff --git a/api/http/handler/tags/tag_delete_test.go b/api/http/handler/tags/tag_delete_test.go index c933610c5..3887475ba 100644 --- a/api/http/handler/tags/tag_delete_test.go +++ b/api/http/handler/tags/tag_delete_test.go @@ -153,23 +153,23 @@ func TestHandler_tagDelete(t *testing.T) { // Check that the endpoints are updated endpoint1, err = store.Endpoint().Endpoint(endpoint1.ID) require.NoError(t, err) - assert.Len(t, endpoint1.TagIDs, 0, "endpoint-1 should not have any tags") + assert.Empty(t, endpoint1.TagIDs, "endpoint-1 should not have any tags") assert.Equal(t, endpoint1.GroupID, endpointGroup.ID, "endpoint-1 should still belong to the endpoint group") endpoint2, err = store.Endpoint().Endpoint(endpoint2.ID) require.NoError(t, err) - assert.Len(t, endpoint2.TagIDs, 0, "endpoint-2 should not have any tags") + assert.Empty(t, endpoint2.TagIDs, "endpoint-2 should not have any tags") // Check that the dynamic edge group is updated dynamicEdgeGroup, err = store.EdgeGroup().Read(dynamicEdgeGroup.ID) require.NoError(t, err) - assert.Len(t, dynamicEdgeGroup.TagIDs, 0, "dynamic edge group should not have any tags") + assert.Empty(t, dynamicEdgeGroup.TagIDs, "dynamic edge group should not have any tags") assert.Equal(t, 0, dynamicEdgeGroup.EndpointIDs.Len(), "dynamic edge group should not have any endpoints") // Check that the static edge group is not updated staticEdgeGroup, err = store.EdgeGroup().Read(staticEdgeGroup.ID) require.NoError(t, err) - assert.Len(t, staticEdgeGroup.TagIDs, 0, "static edge group should not have any tags") + assert.Empty(t, staticEdgeGroup.TagIDs, "static edge group should not have any tags") assert.Equal(t, 1, staticEdgeGroup.EndpointIDs.Len(), "static edge group should have one endpoint") assert.True(t, staticEdgeGroup.EndpointIDs.Contains(endpoint2.ID), "static edge group should have the endpoint-2") }) diff --git a/api/http/handler/teams/team_list_test.go b/api/http/handler/teams/team_list_test.go index 8c0bdfc90..5d7d412cf 100644 --- a/api/http/handler/teams/team_list_test.go +++ b/api/http/handler/teams/team_list_test.go @@ -18,6 +18,7 @@ import ( "github.com/segmentio/encoding/json" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func Test_teamList(t *testing.T) { @@ -28,11 +29,11 @@ func Test_teamList(t *testing.T) { // create admin adminUser := &portainer.User{ID: 1, Username: "admin", Role: portainer.AdministratorRole} err := store.User().Create(adminUser) - is.NoError(err, "error creating admin user") + require.NoError(t, err, "error creating admin user") // setup services jwtService, err := jwt.NewService("1h", store) - is.NoError(err, "Error initiating jwt service") + require.NoError(t, err, "Error initiating jwt service") apiKeyService := apikey.NewAPIKeyService(store.APIKeyRepository(), store.User()) requestBouncer := security.NewRequestBouncer(store, jwtService, apiKeyService) @@ -46,25 +47,25 @@ func Test_teamList(t *testing.T) { // create teams teamWithEndpointAccess := &portainer.Team{ID: 1, Name: "team-with-endpoint-access"} err = store.Team().Create(teamWithEndpointAccess) - is.NoError(err, "error creating team") + require.NoError(t, err, "error creating team") teamWithoutEndpointAccess := &portainer.Team{ID: 2, Name: "team-without-endpoint-access"} err = store.Team().Create(teamWithoutEndpointAccess) - is.NoError(err, "error creating team") + require.NoError(t, err, "error creating team") // create users userWithEndpointAccessByTeam := &portainer.User{ID: 2, Username: "standard-user-inherit-endpoint-access-from-team", Role: portainer.StandardUserRole, PortainerAuthorizations: authorization.DefaultPortainerAuthorizations()} err = store.User().Create(userWithEndpointAccessByTeam) - is.NoError(err, "error creating user") + require.NoError(t, err, "error creating user") userWithoutEndpointAccess := &portainer.User{ID: 3, Username: "standard-user-without-endpoint-access", Role: portainer.StandardUserRole, PortainerAuthorizations: authorization.DefaultPortainerAuthorizations()} err = store.User().Create(userWithoutEndpointAccess) - is.NoError(err, "error creating user") + require.NoError(t, err, "error creating user") // create team membership teamMembership := &portainer.TeamMembership{ID: 1, UserID: userWithEndpointAccessByTeam.ID, TeamID: teamWithEndpointAccess.ID} err = store.TeamMembership().Create(teamMembership) - is.NoError(err, "error creating team membership") + require.NoError(t, err, "error creating team membership") // create endpoint and team access policies teamAccessPolicies := make(portainer.TeamAccessPolicies, 0) @@ -72,11 +73,11 @@ func Test_teamList(t *testing.T) { endpointGroupOnly := &portainer.EndpointGroup{ID: 5, Name: "endpoint-group"} err = store.EndpointGroup().Create(endpointGroupOnly) - is.NoError(err, "error creating endpoint group") + require.NoError(t, err, "error creating endpoint group") endpointWithTeamAccessPolicy := &portainer.Endpoint{ID: 1, GroupID: endpointGroupOnly.ID, TeamAccessPolicies: teamAccessPolicies} err = store.Endpoint().Create(endpointWithTeamAccessPolicy) - is.NoError(err, "error creating endpoint") + require.NoError(t, err, "error creating endpoint") jwt, _, _ := jwtService.GenerateToken(&portainer.TokenData{ID: userWithEndpointAccessByTeam.ID, Username: userWithEndpointAccessByTeam.Username, Role: userWithEndpointAccessByTeam.Role}) @@ -90,11 +91,11 @@ func Test_teamList(t *testing.T) { is.Equal(http.StatusOK, rr.Code) body, err := io.ReadAll(rr.Body) - is.NoError(err, "ReadAll should not return error") + require.NoError(t, err, "ReadAll should not return error") var resp []portainer.Team err = json.Unmarshal(body, &resp) - is.NoError(err, "response should be list json") + require.NoError(t, err, "response should be list json") is.Len(resp, 2) }) @@ -111,11 +112,11 @@ func Test_teamList(t *testing.T) { is.Equal(http.StatusOK, rr.Code) body, err := io.ReadAll(rr.Body) - is.NoError(err, "ReadAll should not return error") + require.NoError(t, err, "ReadAll should not return error") var resp []portainer.Team err = json.Unmarshal(body, &resp) - is.NoError(err, "response should be list json") + require.NoError(t, err, "response should be list json") is.Len(resp, 1) if len(resp) == 1 { @@ -133,11 +134,11 @@ func Test_teamList(t *testing.T) { is.Equal(http.StatusOK, rr.Code) body, err := io.ReadAll(rr.Body) - is.NoError(err, "ReadAll should not return error") + require.NoError(t, err, "ReadAll should not return error") var resp []portainer.Team err = json.Unmarshal(body, &resp) - is.NoError(err, "response should be list json") + require.NoError(t, err, "response should be list json") is.Len(resp, 1) if len(resp) == 1 { @@ -150,7 +151,7 @@ func Test_teamList(t *testing.T) { // create team teamUnderGroup := &portainer.Team{ID: 3, Name: "team-under-environment-group"} err = store.Team().Create(teamUnderGroup) - is.NoError(err, "error creating user") + require.NoError(t, err, "error creating user") // create environment group including a team teamAccessPoliciesUnderGroup := make(portainer.TeamAccessPolicies, 0) @@ -158,12 +159,12 @@ func Test_teamList(t *testing.T) { endpointGroupWithTeam := &portainer.EndpointGroup{ID: 2, Name: "endpoint-group-with-team", TeamAccessPolicies: teamAccessPoliciesUnderGroup} err = store.EndpointGroup().Create(endpointGroupWithTeam) - is.NoError(err, "error creating endpoint group") + require.NoError(t, err, "error creating endpoint group") // create endpoint endpointUnderGroupWithTeam := &portainer.Endpoint{ID: 2, GroupID: endpointGroupWithTeam.ID} err = store.Endpoint().Create(endpointUnderGroupWithTeam) - is.NoError(err, "error creating endpoint") + require.NoError(t, err, "error creating endpoint") t.Run("admin user can list teams who inherit endpoint access from an environment group", func(t *testing.T) { params := url.Values{} @@ -177,11 +178,11 @@ func Test_teamList(t *testing.T) { is.Equal(http.StatusOK, rr.Code) body, err := io.ReadAll(rr.Body) - is.NoError(err, "ReadAll should not return error") + require.NoError(t, err, "ReadAll should not return error") var resp []portainer.Team err = json.Unmarshal(body, &resp) - is.NoError(err, "response should be list json") + require.NoError(t, err, "response should be list json") is.Len(resp, 1) if len(resp) == 1 { diff --git a/api/http/handler/users/user_create_access_token_test.go b/api/http/handler/users/user_create_access_token_test.go index b7e49d96b..996f00cd6 100644 --- a/api/http/handler/users/user_create_access_token_test.go +++ b/api/http/handler/users/user_create_access_token_test.go @@ -17,6 +17,7 @@ import ( "github.com/segmentio/encoding/json" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func Test_userCreateAccessToken(t *testing.T) { @@ -27,15 +28,15 @@ func Test_userCreateAccessToken(t *testing.T) { // create admin and standard user(s) adminUser := &portainer.User{ID: 1, Password: "password", Username: "admin", Role: portainer.AdministratorRole} err := store.User().Create(adminUser) - is.NoError(err, "error creating admin user") + require.NoError(t, err, "error creating admin user") user := &portainer.User{ID: 2, Username: "standard", Role: portainer.StandardUserRole} err = store.User().Create(user) - is.NoError(err, "error creating user") + require.NoError(t, err, "error creating user") // setup services jwtService, err := jwt.NewService("1h", store) - is.NoError(err, "Error initiating jwt service") + require.NoError(t, err, "Error initiating jwt service") apiKeyService := apikey.NewAPIKeyService(store.APIKeyRepository(), store.User()) requestBouncer := security.NewRequestBouncer(store, jwtService, apiKeyService) rateLimiter := security.NewRateLimiter(10, 1*time.Second, 1*time.Hour) @@ -52,7 +53,7 @@ func Test_userCreateAccessToken(t *testing.T) { t.Run("standard user successfully generates API key", func(t *testing.T) { data := userAccessTokenCreatePayload{Password: "password", Description: "test-token"} payload, err := json.Marshal(data) - is.NoError(err) + require.NoError(t, err) req := httptest.NewRequest(http.MethodPost, "/users/2/tokens", bytes.NewBuffer(payload)) testhelpers.AddTestSecurityCookie(req, jwt) @@ -63,19 +64,19 @@ func Test_userCreateAccessToken(t *testing.T) { is.Equal(http.StatusOK, rr.Code) body, err := io.ReadAll(rr.Body) - is.NoError(err, "ReadAll should not return error") + require.NoError(t, err, "ReadAll should not return error") var resp accessTokenResponse err = json.Unmarshal(body, &resp) - is.NoError(err, "response should be json") - is.EqualValues(data.Description, resp.APIKey.Description) + require.NoError(t, err, "response should be json") + is.Equal(data.Description, resp.APIKey.Description) is.NotEmpty(resp.RawAPIKey) }) t.Run("admin cannot generate API key for standard user", func(t *testing.T) { data := userAccessTokenCreatePayload{Password: "password", Description: "test-token-admin"} payload, err := json.Marshal(data) - is.NoError(err) + require.NoError(t, err) req := httptest.NewRequest(http.MethodPost, "/users/2/tokens", bytes.NewBuffer(payload)) testhelpers.AddTestSecurityCookie(req, adminJWT) @@ -86,16 +87,16 @@ func Test_userCreateAccessToken(t *testing.T) { is.Equal(http.StatusForbidden, rr.Code) _, err = io.ReadAll(rr.Body) - is.NoError(err, "ReadAll should not return error") + require.NoError(t, err, "ReadAll should not return error") }) t.Run("endpoint cannot generate api-key using api-key auth", func(t *testing.T) { rawAPIKey, _, err := apiKeyService.GenerateApiKey(*user, "test-api-key") - is.NoError(err) + require.NoError(t, err) data := userAccessTokenCreatePayload{Password: "password", Description: "test-token-fails"} payload, err := json.Marshal(data) - is.NoError(err) + require.NoError(t, err) req := httptest.NewRequest(http.MethodPost, "/users/2/tokens", bytes.NewBuffer(payload)) req.Header.Add("x-api-key", rawAPIKey) @@ -106,14 +107,12 @@ func Test_userCreateAccessToken(t *testing.T) { is.Equal(http.StatusUnauthorized, rr.Code) body, err := io.ReadAll(rr.Body) - is.NoError(err, "ReadAll should not return error") - is.Equal(`{"message":"Auth not supported","details":"Authentication required"}`, string(body)) + require.NoError(t, err, "ReadAll should not return error") + is.JSONEq(`{"message":"Auth not supported","details":"Authentication required"}`, string(body)) }) } func Test_userAccessTokenCreatePayload(t *testing.T) { - is := assert.New(t) - tests := []struct { payload userAccessTokenCreatePayload shouldFail bool @@ -150,9 +149,9 @@ this string is longer than 128 characters and hence this will fail. for _, test := range tests { err := test.payload.Validate(nil) if test.shouldFail { - is.Error(err) + require.Error(t, err) } else { - is.NoError(err) + require.NoError(t, err) } } } diff --git a/api/http/handler/users/user_delete_test.go b/api/http/handler/users/user_delete_test.go index f3cff97db..b8a5f031f 100644 --- a/api/http/handler/users/user_delete_test.go +++ b/api/http/handler/users/user_delete_test.go @@ -11,7 +11,9 @@ import ( "github.com/portainer/portainer/api/datastore" "github.com/portainer/portainer/api/http/security" "github.com/portainer/portainer/api/jwt" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func Test_deleteUserRemovesAccessTokens(t *testing.T) { @@ -22,11 +24,11 @@ func Test_deleteUserRemovesAccessTokens(t *testing.T) { // create standard user user := &portainer.User{ID: 2, Username: "standard", Role: portainer.StandardUserRole} err := store.User().Create(user) - is.NoError(err, "error creating user") + require.NoError(t, err, "error creating user") // setup services jwtService, err := jwt.NewService("1h", store) - is.NoError(err, "Error initiating jwt service") + require.NoError(t, err, "Error initiating jwt service") apiKeyService := apikey.NewAPIKeyService(store.APIKeyRepository(), store.User()) requestBouncer := security.NewRequestBouncer(store, jwtService, apiKeyService) rateLimiter := security.NewRateLimiter(10, 1*time.Second, 1*time.Hour) @@ -37,10 +39,10 @@ func Test_deleteUserRemovesAccessTokens(t *testing.T) { t.Run("standard user deletion removes all associated access tokens", func(t *testing.T) { _, _, err := apiKeyService.GenerateApiKey(*user, "test-user-token") - is.NoError(err) + require.NoError(t, err) keys, err := apiKeyService.GetAPIKeys(user.ID) - is.NoError(err) + require.NoError(t, err) is.Len(keys, 1) rr := httptest.NewRecorder() @@ -50,7 +52,7 @@ func Test_deleteUserRemovesAccessTokens(t *testing.T) { is.Equal(http.StatusNoContent, rr.Code) keys, err = apiKeyService.GetAPIKeys(user.ID) - is.NoError(err) - is.Equal(0, len(keys)) + require.NoError(t, err) + is.Empty(keys) }) } diff --git a/api/http/handler/users/user_get_access_tokens_test.go b/api/http/handler/users/user_get_access_tokens_test.go index 0d471d858..8d4b6fee9 100644 --- a/api/http/handler/users/user_get_access_tokens_test.go +++ b/api/http/handler/users/user_get_access_tokens_test.go @@ -16,6 +16,7 @@ import ( "github.com/segmentio/encoding/json" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func Test_userGetAccessTokens(t *testing.T) { @@ -26,15 +27,15 @@ func Test_userGetAccessTokens(t *testing.T) { // create admin and standard user(s) adminUser := &portainer.User{ID: 1, Username: "admin", Role: portainer.AdministratorRole} err := store.User().Create(adminUser) - is.NoError(err, "error creating admin user") + require.NoError(t, err, "error creating admin user") user := &portainer.User{ID: 2, Username: "standard", Role: portainer.StandardUserRole} err = store.User().Create(user) - is.NoError(err, "error creating user") + require.NoError(t, err, "error creating user") // setup services jwtService, err := jwt.NewService("1h", store) - is.NoError(err, "Error initiating jwt service") + require.NoError(t, err, "Error initiating jwt service") apiKeyService := apikey.NewAPIKeyService(store.APIKeyRepository(), store.User()) requestBouncer := security.NewRequestBouncer(store, jwtService, apiKeyService) rateLimiter := security.NewRateLimiter(10, 1*time.Second, 1*time.Hour) @@ -49,7 +50,7 @@ func Test_userGetAccessTokens(t *testing.T) { t.Run("standard user can successfully retrieve API key", func(t *testing.T) { _, apiKey, err := apiKeyService.GenerateApiKey(*user, "test-get-token") - is.NoError(err) + require.NoError(t, err) req := httptest.NewRequest(http.MethodGet, "/users/2/tokens", nil) testhelpers.AddTestSecurityCookie(req, jwt) @@ -60,15 +61,15 @@ func Test_userGetAccessTokens(t *testing.T) { is.Equal(http.StatusOK, rr.Code) body, err := io.ReadAll(rr.Body) - is.NoError(err, "ReadAll should not return error") + require.NoError(t, err, "ReadAll should not return error") var resp []portainer.APIKey err = json.Unmarshal(body, &resp) - is.NoError(err, "response should be list json") + require.NoError(t, err, "response should be list json") is.Len(resp, 1) if len(resp) == 1 { - is.Equal(resp[0].Digest, "") + is.Empty(resp[0].Digest) is.Equal(apiKey.ID, resp[0].ID) is.Equal(apiKey.UserID, resp[0].UserID) is.Equal(apiKey.Prefix, resp[0].Prefix) @@ -78,7 +79,7 @@ func Test_userGetAccessTokens(t *testing.T) { t.Run("admin can retrieve standard user API Key", func(t *testing.T) { _, _, err := apiKeyService.GenerateApiKey(*user, "test-get-admin-token") - is.NoError(err) + require.NoError(t, err) req := httptest.NewRequest(http.MethodGet, "/users/2/tokens", nil) testhelpers.AddTestSecurityCookie(req, adminJWT) @@ -89,18 +90,18 @@ func Test_userGetAccessTokens(t *testing.T) { is.Equal(http.StatusOK, rr.Code) body, err := io.ReadAll(rr.Body) - is.NoError(err, "ReadAll should not return error") + require.NoError(t, err, "ReadAll should not return error") var resp []portainer.APIKey err = json.Unmarshal(body, &resp) - is.NoError(err, "response should be list json") + require.NoError(t, err, "response should be list json") - is.True(len(resp) > 0) + is.NotEmpty(resp) }) t.Run("user can retrieve API Key using api-key auth", func(t *testing.T) { rawAPIKey, _, err := apiKeyService.GenerateApiKey(*user, "test-api-key") - is.NoError(err) + require.NoError(t, err) req := httptest.NewRequest(http.MethodGet, "/users/2/tokens", nil) req.Header.Add("x-api-key", rawAPIKey) @@ -111,19 +112,17 @@ func Test_userGetAccessTokens(t *testing.T) { is.Equal(http.StatusOK, rr.Code) body, err := io.ReadAll(rr.Body) - is.NoError(err, "ReadAll should not return error") + require.NoError(t, err, "ReadAll should not return error") var resp []portainer.APIKey err = json.Unmarshal(body, &resp) - is.NoError(err, "response should be list json") + require.NoError(t, err, "response should be list json") - is.True(len(resp) > 0) + is.NotEmpty(resp) }) } func Test_hideAPIKeyFields(t *testing.T) { - is := assert.New(t) - apiKey := &portainer.APIKey{ ID: 1, UserID: 2, @@ -134,5 +133,5 @@ func Test_hideAPIKeyFields(t *testing.T) { hideAPIKeyFields(apiKey) - is.Equal(apiKey.Digest, "", "digest should be cleared when hiding api key fields") + require.Empty(t, apiKey.Digest, "digest should be cleared when hiding api key fields") } diff --git a/api/http/handler/users/user_list_test.go b/api/http/handler/users/user_list_test.go index 33bd5f04b..64b99f442 100644 --- a/api/http/handler/users/user_list_test.go +++ b/api/http/handler/users/user_list_test.go @@ -19,6 +19,7 @@ import ( "github.com/segmentio/encoding/json" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func Test_userList(t *testing.T) { @@ -29,11 +30,11 @@ func Test_userList(t *testing.T) { // Create admin and standard user(s) adminUser := &portainer.User{ID: 1, Username: "admin", Role: portainer.AdministratorRole} err := store.User().Create(adminUser) - is.NoError(err, "error creating admin user") + require.NoError(t, err, "error creating admin user") // Setup services jwtService, err := jwt.NewService("1h", store) - is.NoError(err, "Error initiating jwt service") + require.NoError(t, err, "Error initiating jwt service") apiKeyService := apikey.NewAPIKeyService(store.APIKeyRepository(), store.User()) requestBouncer := security.NewRequestBouncer(store, jwtService, apiKeyService) rateLimiter := security.NewRateLimiter(10, 1*time.Second, 1*time.Hour) @@ -48,16 +49,16 @@ func Test_userList(t *testing.T) { // Case 1: the user is given the endpoint access directly userWithEndpointAccess := &portainer.User{ID: 2, Username: "standard-user-with-endpoint-access", Role: portainer.StandardUserRole, PortainerAuthorizations: authorization.DefaultPortainerAuthorizations()} err = store.User().Create(userWithEndpointAccess) - is.NoError(err, "error creating user") + require.NoError(t, err, "error creating user") userWithoutEndpointAccess := &portainer.User{ID: 3, Username: "standard-user-without-endpoint-access", Role: portainer.StandardUserRole, PortainerAuthorizations: authorization.DefaultPortainerAuthorizations()} err = store.User().Create(userWithoutEndpointAccess) - is.NoError(err, "error creating user") + require.NoError(t, err, "error creating user") // Create environment group endpointGroup := &portainer.EndpointGroup{ID: 1, Name: "default-endpoint-group"} err = store.EndpointGroup().Create(endpointGroup) - is.NoError(err, "error creating endpoint group") + require.NoError(t, err, "error creating endpoint group") // Create endpoint and user access policies userAccessPolicies := make(portainer.UserAccessPolicies, 0) @@ -65,7 +66,7 @@ func Test_userList(t *testing.T) { endpointWithUserAccessPolicy := &portainer.Endpoint{ID: 1, UserAccessPolicies: userAccessPolicies, GroupID: endpointGroup.ID} err = store.Endpoint().Create(endpointWithUserAccessPolicy) - is.NoError(err, "error creating endpoint") + require.NoError(t, err, "error creating endpoint") jwt, _, _ := jwtService.GenerateToken(&portainer.TokenData{ID: userWithEndpointAccess.ID, Username: userWithEndpointAccess.Username, Role: userWithEndpointAccess.Role}) @@ -79,11 +80,11 @@ func Test_userList(t *testing.T) { is.Equal(http.StatusOK, rr.Code) body, err := io.ReadAll(rr.Body) - is.NoError(err, "ReadAll should not return error") + require.NoError(t, err, "ReadAll should not return error") var resp []portainer.User err = json.Unmarshal(body, &resp) - is.NoError(err, "response should be list json") + require.NoError(t, err, "response should be list json") is.Len(resp, 3) }) @@ -100,11 +101,11 @@ func Test_userList(t *testing.T) { is.Equal(http.StatusOK, rr.Code) body, err := io.ReadAll(rr.Body) - is.NoError(err, "ReadAll should not return error") + require.NoError(t, err, "ReadAll should not return error") var resp []portainer.User err = json.Unmarshal(body, &resp) - is.NoError(err, "response should be list json") + require.NoError(t, err, "response should be list json") is.Len(resp, 1) if len(resp) == 1 { @@ -127,7 +128,7 @@ func Test_userList(t *testing.T) { // create user userUnderGroup := &portainer.User{ID: 4, Username: "standard-user-under-environment-group", Role: portainer.StandardUserRole, PortainerAuthorizations: authorization.DefaultPortainerAuthorizations()} err = store.User().Create(userUnderGroup) - is.NoError(err, "error creating user") + require.NoError(t, err, "error creating user") // Create environment group including a user userAccessPoliciesUnderGroup := make(portainer.UserAccessPolicies, 0) @@ -135,12 +136,12 @@ func Test_userList(t *testing.T) { endpointGroupWithUser := &portainer.EndpointGroup{ID: 2, Name: "endpoint-group-with-user", UserAccessPolicies: userAccessPoliciesUnderGroup} err = store.EndpointGroup().Create(endpointGroupWithUser) - is.NoError(err, "error creating endpoint group") + require.NoError(t, err, "error creating endpoint group") // Create endpoint endpointUnderGroupWithUser := &portainer.Endpoint{ID: 2, GroupID: endpointGroupWithUser.ID} err = store.Endpoint().Create(endpointUnderGroupWithUser) - is.NoError(err, "error creating endpoint") + require.NoError(t, err, "error creating endpoint") t.Run("admin user can list users who inherit endpoint access from an environment group", func(t *testing.T) { params := url.Values{} @@ -154,11 +155,11 @@ func Test_userList(t *testing.T) { is.Equal(http.StatusOK, rr.Code) body, err := io.ReadAll(rr.Body) - is.NoError(err, "ReadAll should not return error") + require.NoError(t, err, "ReadAll should not return error") var resp []portainer.User err = json.Unmarshal(body, &resp) - is.NoError(err, "response should be list json") + require.NoError(t, err, "response should be list json") is.Len(resp, 1) if len(resp) == 1 { @@ -172,15 +173,15 @@ func Test_userList(t *testing.T) { // create a team including a user teamUnderGroup := &portainer.Team{ID: 1, Name: "team-under-environment-group"} err = store.Team().Create(teamUnderGroup) - is.NoError(err, "error creating team") + require.NoError(t, err, "error creating team") userUnderTeam := &portainer.User{ID: 4, Username: "standard-user-under-team", Role: portainer.StandardUserRole, PortainerAuthorizations: authorization.DefaultPortainerAuthorizations()} err = store.User().Create(userUnderTeam) - is.NoError(err, "error creating user") + require.NoError(t, err, "error creating user") teamMembership := &portainer.TeamMembership{ID: 1, UserID: userUnderTeam.ID, TeamID: teamUnderGroup.ID} err = store.TeamMembership().Create(teamMembership) - is.NoError(err, "error creating team membership") + require.NoError(t, err, "error creating team membership") // Create environment group including a team teamAccessPoliciesUnderGroup := make(portainer.TeamAccessPolicies, 0) @@ -188,12 +189,12 @@ func Test_userList(t *testing.T) { endpointGroupWithTeam := &portainer.EndpointGroup{ID: 3, Name: "endpoint-group-with-team", TeamAccessPolicies: teamAccessPoliciesUnderGroup} err = store.EndpointGroup().Create(endpointGroupWithTeam) - is.NoError(err, "error creating endpoint group") + require.NoError(t, err, "error creating endpoint group") // Create endpoint endpointUnderGroupWithTeam := &portainer.Endpoint{ID: 3, GroupID: endpointGroupWithTeam.ID} err = store.Endpoint().Create(endpointUnderGroupWithTeam) - is.NoError(err, "error creating endpoint") + require.NoError(t, err, "error creating endpoint") t.Run("admin user can list users who inherit endpoint access from a team that inherit from an environment group", func(t *testing.T) { params := url.Values{} params.Add("environmentId", fmt.Sprintf("%d", endpointUnderGroupWithTeam.ID)) @@ -206,11 +207,11 @@ func Test_userList(t *testing.T) { is.Equal(http.StatusOK, rr.Code) body, err := io.ReadAll(rr.Body) - is.NoError(err, "ReadAll should not return error") + require.NoError(t, err, "ReadAll should not return error") var resp []portainer.User err = json.Unmarshal(body, &resp) - is.NoError(err, "response should be list json") + require.NoError(t, err, "response should be list json") is.Len(resp, 1) if len(resp) == 1 { @@ -223,20 +224,20 @@ func Test_userList(t *testing.T) { // create a team including a user teamWithEndpointAccess := &portainer.Team{ID: 2, Name: "team-with-endpoint-access"} err = store.Team().Create(teamWithEndpointAccess) - is.NoError(err, "error creating team") + require.NoError(t, err, "error creating team") userUnderTeamWithEndpointAccess := &portainer.User{ID: 5, Username: "standard-user-under-team-with-endpoint-access", Role: portainer.StandardUserRole, PortainerAuthorizations: authorization.DefaultPortainerAuthorizations()} err = store.User().Create(userUnderTeamWithEndpointAccess) - is.NoError(err, "error creating user") + require.NoError(t, err, "error creating user") teamMembershipWithEndpointAccess := &portainer.TeamMembership{ID: 2, UserID: userUnderTeamWithEndpointAccess.ID, TeamID: teamWithEndpointAccess.ID} err = store.TeamMembership().Create(teamMembershipWithEndpointAccess) - is.NoError(err, "error creating team membership") + require.NoError(t, err, "error creating team membership") // Create environment group endpointGroupWithoutTeam := &portainer.EndpointGroup{ID: 4, Name: "endpoint-group-without-team"} err = store.EndpointGroup().Create(endpointGroupWithoutTeam) - is.NoError(err, "error creating endpoint group") + require.NoError(t, err, "error creating endpoint group") // Create endpoint and team access policies teamAccessPolicies := make(portainer.TeamAccessPolicies, 0) @@ -244,7 +245,7 @@ func Test_userList(t *testing.T) { endpointWithTeamAccessPolicy := &portainer.Endpoint{ID: 4, TeamAccessPolicies: teamAccessPolicies, GroupID: endpointGroupWithoutTeam.ID} err = store.Endpoint().Create(endpointWithTeamAccessPolicy) - is.NoError(err, "error creating endpoint") + require.NoError(t, err, "error creating endpoint") t.Run("admin user can list users who inherit endpoint access from a team", func(t *testing.T) { params := url.Values{} params.Add("environmentId", fmt.Sprintf("%d", endpointWithTeamAccessPolicy.ID)) @@ -257,11 +258,11 @@ func Test_userList(t *testing.T) { is.Equal(http.StatusOK, rr.Code) body, err := io.ReadAll(rr.Body) - is.NoError(err, "ReadAll should not return error") + require.NoError(t, err, "ReadAll should not return error") var resp []portainer.User err = json.Unmarshal(body, &resp) - is.NoError(err, "response should be list json") + require.NoError(t, err, "response should be list json") is.Len(resp, 1) if len(resp) == 1 { diff --git a/api/http/handler/users/user_remove_access_token_test.go b/api/http/handler/users/user_remove_access_token_test.go index 7534b2b5d..f0b2441d8 100644 --- a/api/http/handler/users/user_remove_access_token_test.go +++ b/api/http/handler/users/user_remove_access_token_test.go @@ -13,7 +13,9 @@ import ( "github.com/portainer/portainer/api/http/security" "github.com/portainer/portainer/api/internal/testhelpers" "github.com/portainer/portainer/api/jwt" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func Test_userRemoveAccessToken(t *testing.T) { @@ -24,15 +26,15 @@ func Test_userRemoveAccessToken(t *testing.T) { // create admin and standard user(s) adminUser := &portainer.User{ID: 1, Username: "admin", Role: portainer.AdministratorRole} err := store.User().Create(adminUser) - is.NoError(err, "error creating admin user") + require.NoError(t, err, "error creating admin user") user := &portainer.User{ID: 2, Username: "standard", Role: portainer.StandardUserRole} err = store.User().Create(user) - is.NoError(err, "error creating user") + require.NoError(t, err, "error creating user") // setup services jwtService, err := jwt.NewService("1h", store) - is.NoError(err, "Error initiating jwt service") + require.NoError(t, err, "Error initiating jwt service") apiKeyService := apikey.NewAPIKeyService(store.APIKeyRepository(), store.User()) requestBouncer := security.NewRequestBouncer(store, jwtService, apiKeyService) rateLimiter := security.NewRateLimiter(10, 1*time.Second, 1*time.Hour) @@ -48,7 +50,7 @@ func Test_userRemoveAccessToken(t *testing.T) { t.Run("standard user can successfully delete API key", func(t *testing.T) { is := assert.New(t) _, apiKey, err := apiKeyService.GenerateApiKey(*user, "test-delete-token") - is.NoError(err) + require.NoError(t, err) req := httptest.NewRequest(http.MethodDelete, fmt.Sprintf("%s/%d", "/users/2/tokens", apiKey.ID), nil) testhelpers.AddTestSecurityCookie(req, jwt) @@ -59,15 +61,15 @@ func Test_userRemoveAccessToken(t *testing.T) { is.Equal(http.StatusNoContent, rr.Code) keys, err := apiKeyService.GetAPIKeys(user.ID) - is.NoError(err) + require.NoError(t, err) - is.Equal(0, len(keys)) + require.Empty(t, keys) }) t.Run("admin can delete a standard user API Key", func(t *testing.T) { is := assert.New(t) _, apiKey, err := apiKeyService.GenerateApiKey(*user, "test-admin-delete-token") - is.NoError(err) + require.NoError(t, err) req := httptest.NewRequest(http.MethodDelete, fmt.Sprintf("%s/%d", "/users/2/tokens", apiKey.ID), nil) testhelpers.AddTestSecurityCookie(req, adminJWT) @@ -78,15 +80,15 @@ func Test_userRemoveAccessToken(t *testing.T) { is.Equal(http.StatusNoContent, rr.Code) keys, err := apiKeyService.GetAPIKeys(user.ID) - is.NoError(err) + require.NoError(t, err) - is.Equal(0, len(keys)) + is.Empty(keys) }) t.Run("user can delete API Key using api-key auth", func(t *testing.T) { is := assert.New(t) rawAPIKey, apiKey, err := apiKeyService.GenerateApiKey(*user, "test-api-key-auth-deletion") - is.NoError(err) + require.NoError(t, err) req := httptest.NewRequest(http.MethodDelete, fmt.Sprintf("%s/%d", "/users/2/tokens", apiKey.ID), nil) req.Header.Add("x-api-key", rawAPIKey) @@ -97,17 +99,17 @@ func Test_userRemoveAccessToken(t *testing.T) { is.Equal(http.StatusNoContent, rr.Code) keys, err := apiKeyService.GetAPIKeys(user.ID) - is.NoError(err) + require.NoError(t, err) - is.Equal(0, len(keys)) + is.Empty(keys) }) t.Run("user cannot delete another users API Keys using api-key auth", func(t *testing.T) { _, adminAPIKey, err := apiKeyService.GenerateApiKey(*adminUser, "admin-key") - is.NoError(err) + require.NoError(t, err) rawAPIKey, _, err := apiKeyService.GenerateApiKey(*user, "user-key") - is.NoError(err) + require.NoError(t, err) req := httptest.NewRequest(http.MethodDelete, fmt.Sprintf("/users/%d/tokens/%d", user.ID, adminAPIKey.ID), nil) req.Header.Add("x-api-key", rawAPIKey) @@ -118,7 +120,7 @@ func Test_userRemoveAccessToken(t *testing.T) { is.Equal(http.StatusForbidden, rr.Code) adminKeyGot, err := apiKeyService.GetAPIKey(adminAPIKey.ID) - is.NoError(err) + require.NoError(t, err) is.Equal(adminAPIKey, adminKeyGot) }) diff --git a/api/http/handler/users/user_update_test.go b/api/http/handler/users/user_update_test.go index 17eb231c6..47114feff 100644 --- a/api/http/handler/users/user_update_test.go +++ b/api/http/handler/users/user_update_test.go @@ -11,7 +11,9 @@ import ( "github.com/portainer/portainer/api/datastore" "github.com/portainer/portainer/api/http/security" "github.com/portainer/portainer/api/jwt" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func Test_updateUserRemovesAccessTokens(t *testing.T) { @@ -22,11 +24,11 @@ func Test_updateUserRemovesAccessTokens(t *testing.T) { // Create standard user user := &portainer.User{ID: 2, Username: "standard", Role: portainer.StandardUserRole} err := store.User().Create(user) - is.NoError(err, "error creating user") + require.NoError(t, err, "error creating user") // Setup services jwtService, err := jwt.NewService("1h", store) - is.NoError(err, "Error initiating jwt service") + require.NoError(t, err, "Error initiating jwt service") apiKeyService := apikey.NewAPIKeyService(store.APIKeyRepository(), store.User()) requestBouncer := security.NewRequestBouncer(store, jwtService, apiKeyService) rateLimiter := security.NewRateLimiter(10, 1*time.Second, 1*time.Hour) @@ -37,10 +39,10 @@ func Test_updateUserRemovesAccessTokens(t *testing.T) { t.Run("standard user deletion removes all associated access tokens", func(t *testing.T) { _, _, err := apiKeyService.GenerateApiKey(*user, "test-user-token") - is.NoError(err) + require.NoError(t, err) keys, err := apiKeyService.GetAPIKeys(user.ID) - is.NoError(err) + require.NoError(t, err) is.Len(keys, 1) rr := httptest.NewRecorder() @@ -50,7 +52,7 @@ func Test_updateUserRemovesAccessTokens(t *testing.T) { is.Equal(http.StatusNoContent, rr.Code) keys, err = apiKeyService.GetAPIKeys(user.ID) - is.NoError(err) - is.Equal(0, len(keys)) + require.NoError(t, err) + is.Empty(keys) }) } diff --git a/api/http/proxy/factory/kubernetes/transport_test.go b/api/http/proxy/factory/kubernetes/transport_test.go index 54f7f9822..868ee052e 100644 --- a/api/http/proxy/factory/kubernetes/transport_test.go +++ b/api/http/proxy/factory/kubernetes/transport_test.go @@ -11,6 +11,7 @@ import ( "github.com/portainer/portainer/api/datastore" "github.com/portainer/portainer/api/http/security" "github.com/portainer/portainer/api/jwt" + "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) @@ -23,8 +24,10 @@ type MockJWTService struct { func (m *MockJWTService) GenerateToken(data *portainer.TokenData) (string, time.Time, error) { if m.generateTokenFunc != nil { token, err := m.generateTokenFunc(data) + return token, time.Now().Add(24 * time.Hour), err } + return "mock-token", time.Now().Add(24 * time.Hour), nil } @@ -32,6 +35,7 @@ func (m *MockJWTService) GenerateTokenForKubeconfig(data *portainer.TokenData) ( if m.generateTokenFunc != nil { return m.generateTokenFunc(data) } + return "mock-kubeconfig-token", nil } @@ -104,7 +108,7 @@ func TestBaseTransport_AddTokenForExec(t *testing.T) { token := authHeader[7:] // Remove "Bearer " prefix parsedTokenData, _, _, err := jwtService.ParseAndVerifyToken(token) - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, tokenData.ID, parsedTokenData.ID) assert.Equal(t, tokenData.Username, parsedTokenData.Username) assert.Equal(t, tokenData.Role, parsedTokenData.Role) @@ -132,7 +136,7 @@ func TestBaseTransport_AddTokenForExec(t *testing.T) { token := authHeader[7:] // Remove "Bearer " prefix parsedTokenData, _, _, err := jwtService.ParseAndVerifyToken(token) - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, tokenData.ID, parsedTokenData.ID) assert.Equal(t, tokenData.Username, parsedTokenData.Username) assert.Equal(t, tokenData.Role, parsedTokenData.Role) @@ -193,7 +197,6 @@ func TestBaseTransport_AddTokenForExec(t *testing.T) { token := authHeader[7:] // Remove "Bearer " prefix assert.NotEmpty(t, token) - assert.Greater(t, len(token), 0, "Token should not be empty") }, }, { @@ -211,6 +214,7 @@ func TestBaseTransport_AddTokenForExec(t *testing.T) { })) // Set an existing Authorization header req.Header.Set("Authorization", "Bearer old-token") + return req }, expectError: false, @@ -221,7 +225,7 @@ func TestBaseTransport_AddTokenForExec(t *testing.T) { token := authHeader[7:] // Remove "Bearer " prefix parsedTokenData, _, _, err := jwtService.ParseAndVerifyToken(token) - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, tokenData.ID, parsedTokenData.ID) }, }, @@ -255,12 +259,12 @@ func TestBaseTransport_AddTokenForExec(t *testing.T) { // Check results if tt.expectError { - assert.Error(t, err) + require.Error(t, err) if tt.errorMsg != "" { assert.Contains(t, err.Error(), tt.errorMsg) } } else { - assert.NoError(t, err) + require.NoError(t, err) if tt.verifyResponse != nil { tt.verifyResponse(t, request, tt.tokenData) } diff --git a/api/http/security/bouncer_test.go b/api/http/security/bouncer_test.go index a1b29ea74..935b0e89b 100644 --- a/api/http/security/bouncer_test.go +++ b/api/http/security/bouncer_test.go @@ -1,7 +1,6 @@ package security import ( - "fmt" "net/http" "net/http/httptest" "testing" @@ -42,7 +41,7 @@ func Test_mwAuthenticateFirst(t *testing.T) { _, store := datastore.MustNewTestStore(t, true, true) jwtService, err := jwt.NewService("1h", store) - assert.NoError(t, err, "failed to create a copy of service") + require.NoError(t, err, "failed to create a copy of service") apiKeyService := apikey.NewAPIKeyService(nil, nil) @@ -109,7 +108,7 @@ func Test_mwAuthenticateFirst(t *testing.T) { h := bouncer.mwAuthenticateFirst(tt.verificationMiddlwares, testHandler200) h.ServeHTTP(rr, req) - is.Equal(tt.wantStatusCode, rr.Code, fmt.Sprintf("Status should be %d", tt.wantStatusCode)) + is.Equal(tt.wantStatusCode, rr.Code, "Status should be %d", tt.wantStatusCode) }) } } @@ -144,10 +143,10 @@ func Test_extractKeyFromCookie(t *testing.T) { apiKey, err := extractKeyFromCookie(req) is.Equal(test.token, apiKey) if !test.succeeds { - is.Error(err, "Should return error") + require.Error(t, err, "Should return error") is.ErrorIs(err, http.ErrNoCookie) } else { - is.NoError(err) + require.NoError(t, err) } } } @@ -311,18 +310,19 @@ func Test_apiKeyLookup(t *testing.T) { // create standard user user := &portainer.User{ID: 2, Username: "standard", Role: portainer.StandardUserRole} err := store.User().Create(user) - is.NoError(err, "error creating user") + require.NoError(t, err, "error creating user") // setup services jwtService, err := jwt.NewService("1h", store) - is.NoError(err, "Error initiating jwt service") + require.NoError(t, err, "Error initiating jwt service") apiKeyService := apikey.NewAPIKeyService(store.APIKeyRepository(), store.User()) bouncer := NewRequestBouncer(store, jwtService, apiKeyService) t.Run("missing x-api-key header fails api-key lookup", func(t *testing.T) { req := httptest.NewRequest(http.MethodGet, "/", nil) // testhelpers.AddTestSecurityCookie(req, jwt) - token, _ := bouncer.apiKeyLookup(req) + token, err := bouncer.apiKeyLookup(req) + require.NoError(t, err) is.Nil(token) }) @@ -331,12 +331,12 @@ func Test_apiKeyLookup(t *testing.T) { req.Header.Add("x-api-key", "random-failing-api-key") token, err := bouncer.apiKeyLookup(req) is.Nil(token) - is.Error(err) + require.Error(t, err) }) t.Run("valid x-api-key header succeeds api-key lookup", func(t *testing.T) { rawAPIKey, _, err := apiKeyService.GenerateApiKey(*user, "test") - is.NoError(err) + require.NoError(t, err) req := httptest.NewRequest(http.MethodGet, "/", nil) req.Header.Add("x-api-key", rawAPIKey) @@ -350,7 +350,7 @@ func Test_apiKeyLookup(t *testing.T) { t.Run("valid x-api-key header succeeds api-key lookup", func(t *testing.T) { rawAPIKey, apiKey, err := apiKeyService.GenerateApiKey(*user, "test") - is.NoError(err) + require.NoError(t, err) defer apiKeyService.DeleteAPIKey(apiKey.ID) req := httptest.NewRequest(http.MethodGet, "/", nil) @@ -365,7 +365,7 @@ func Test_apiKeyLookup(t *testing.T) { t.Run("successful api-key lookup updates token last used time", func(t *testing.T) { rawAPIKey, apiKey, err := apiKeyService.GenerateApiKey(*user, "test") - is.NoError(err) + require.NoError(t, err) defer apiKeyService.DeleteAPIKey(apiKey.ID) req := httptest.NewRequest(http.MethodGet, "/", nil) @@ -378,9 +378,9 @@ func Test_apiKeyLookup(t *testing.T) { is.Equal(expectedToken, token) _, apiKeyUpdated, err := apiKeyService.GetDigestUserAndKey(apiKey.Digest) - is.NoError(err) + require.NoError(t, err) - is.True(apiKeyUpdated.LastUsed > apiKey.LastUsed) + is.Greater(apiKeyUpdated.LastUsed, apiKey.LastUsed) }) } @@ -452,9 +452,9 @@ func Test_ShouldSkipCSRFCheck(t *testing.T) { result, err := ShouldSkipCSRFCheck(req, test.isDockerDesktopExtension) is.Equal(test.expectedResult, result) if test.expectedError { - is.Error(err) + require.Error(t, err) } else { - is.NoError(err) + require.NoError(t, err) } }) } diff --git a/api/http/utils/filters/filters_test.go b/api/http/utils/filters/filters_test.go index 0b0780fdf..021a723b2 100644 --- a/api/http/utils/filters/filters_test.go +++ b/api/http/utils/filters/filters_test.go @@ -82,7 +82,7 @@ func TestSearchOrderAndPaginate(t *testing.T) { result := SearchOrderAndPaginate(users, params, userConfig) - require.Equal(t, 5, len(result.Items), "Should return all items when no filters applied") + require.Len(t, result.Items, 5, "Should return all items when no filters applied") require.Equal(t, 5, result.TotalCount, "TotalCount should equal filtered items") require.Equal(t, 5, result.TotalAvailable, "TotalAvailable should equal original items") require.Equal(t, users, result.Items, "Items should be unchanged") @@ -97,7 +97,7 @@ func TestSearchOrderAndPaginate(t *testing.T) { result := SearchOrderAndPaginate(users, params, userConfig) - require.Equal(t, 1, len(result.Items), "Should find one user matching 'alice'") + require.Len(t, result.Items, 1, "Should find one user matching 'alice'") require.Equal(t, 1, result.TotalCount, "TotalCount should reflect filtered items") require.Equal(t, 5, result.TotalAvailable, "TotalAvailable should be original count") require.Equal(t, "Alice Johnson", result.Items[0].Name, "Should return Alice") @@ -112,7 +112,7 @@ func TestSearchOrderAndPaginate(t *testing.T) { result := SearchOrderAndPaginate(users, params, userConfig) - require.Equal(t, 1, len(result.Items), "Search should be case insensitive") + require.Len(t, result.Items, 1, "Search should be case insensitive") require.Equal(t, "Alice Johnson", result.Items[0].Name, "Should return Alice") }) @@ -125,7 +125,7 @@ func TestSearchOrderAndPaginate(t *testing.T) { result := SearchOrderAndPaginate(users, params, userConfig) - require.Equal(t, 1, len(result.Items), "Should find user by email") + require.Len(t, result.Items, 1, "Should find user by email") require.Equal(t, "Bob Smith", result.Items[0].Name, "Should return Bob") }) @@ -138,7 +138,7 @@ func TestSearchOrderAndPaginate(t *testing.T) { result := SearchOrderAndPaginate(users, params, userConfig) - require.Equal(t, 0, len(result.Items), "Should return empty when no matches") + require.Empty(t, result.Items, "Should return empty when no matches") require.Equal(t, 0, result.TotalCount, "TotalCount should be 0") require.Equal(t, 5, result.TotalAvailable, "TotalAvailable should remain original count") }) @@ -152,7 +152,7 @@ func TestSearchOrderAndPaginate(t *testing.T) { result := SearchOrderAndPaginate(users, params, userConfig) - require.Equal(t, 1, len(result.Items), "Should trim whitespace from search") + require.Len(t, result.Items, 1, "Should trim whitespace from search") require.Equal(t, "Alice Johnson", result.Items[0].Name, "Should return Alice") }) @@ -165,7 +165,7 @@ func TestSearchOrderAndPaginate(t *testing.T) { result := SearchOrderAndPaginate(users, params, userConfig) - require.Equal(t, 5, len(result.Items), "Should return all items") + require.Len(t, result.Items, 5, "Should return all items") require.Equal(t, "Alice Johnson", result.Items[0].Name, "First should be Alice") require.Equal(t, "Eve Adams", result.Items[4].Name, "Last should be Eve") }) @@ -179,7 +179,7 @@ func TestSearchOrderAndPaginate(t *testing.T) { result := SearchOrderAndPaginate(users, params, userConfig) - require.Equal(t, 5, len(result.Items), "Should return all items") + require.Len(t, result.Items, 5, "Should return all items") require.Equal(t, "Eve Adams", result.Items[0].Name, "First should be Eve (desc order)") require.Equal(t, "Alice Johnson", result.Items[4].Name, "Last should be Alice (desc order)") }) @@ -193,7 +193,7 @@ func TestSearchOrderAndPaginate(t *testing.T) { result := SearchOrderAndPaginate(users, params, userConfig) - require.Equal(t, 5, len(result.Items), "Should return all items") + require.Len(t, result.Items, 5, "Should return all items") require.Equal(t, 22, result.Items[0].Age, "First should be youngest (22)") require.Equal(t, 35, result.Items[4].Age, "Last should be oldest (35)") }) @@ -207,7 +207,7 @@ func TestSearchOrderAndPaginate(t *testing.T) { result := SearchOrderAndPaginate(users, params, userConfig) - require.Equal(t, 5, len(result.Items), "Should return all items") + require.Len(t, result.Items, 5, "Should return all items") // Items should remain in original order since no valid sort key require.Equal(t, users, result.Items, "Should maintain original order with invalid sort key") }) @@ -221,7 +221,7 @@ func TestSearchOrderAndPaginate(t *testing.T) { result := SearchOrderAndPaginate(users, params, userConfig) - require.Equal(t, 2, len(result.Items), "Should return 2 items") + require.Len(t, result.Items, 2, "Should return 2 items") require.Equal(t, 5, result.TotalCount, "TotalCount should be all items") require.Equal(t, 5, result.TotalAvailable, "TotalAvailable should be original count") require.Equal(t, users[1], result.Items[0], "Should start from index 1") @@ -237,7 +237,7 @@ func TestSearchOrderAndPaginate(t *testing.T) { result := SearchOrderAndPaginate(users, params, userConfig) - require.Equal(t, 5, len(result.Items), "Should return all items when limit is 0") + require.Len(t, result.Items, 5, "Should return all items when limit is 0") require.Equal(t, users, result.Items, "Should return all original items") }) @@ -250,7 +250,7 @@ func TestSearchOrderAndPaginate(t *testing.T) { result := SearchOrderAndPaginate(users, params, userConfig) - require.Equal(t, 5, len(result.Items), "Should return all items when limit is negative") + require.Len(t, result.Items, 5, "Should return all items when limit is negative") }) t.Run("pagination start beyond length", func(t *testing.T) { @@ -262,7 +262,7 @@ func TestSearchOrderAndPaginate(t *testing.T) { result := SearchOrderAndPaginate(users, params, userConfig) - require.Equal(t, 0, len(result.Items), "Should return empty slice when start is beyond length") + require.Empty(t, result.Items, "Should return empty slice when start is beyond length") require.Equal(t, 5, result.TotalCount, "TotalCount should still be original count") }) @@ -275,7 +275,7 @@ func TestSearchOrderAndPaginate(t *testing.T) { result := SearchOrderAndPaginate(users, params, userConfig) - require.Equal(t, 2, len(result.Items), "Should return 2 items starting from 0") + require.Len(t, result.Items, 2, "Should return 2 items starting from 0") require.Equal(t, users[0], result.Items[0], "Should start from index 0") require.Equal(t, users[1], result.Items[1], "Should include index 1") }) @@ -292,7 +292,7 @@ func TestSearchOrderAndPaginate(t *testing.T) { // All users have "example.com" in email, so all 5 should match search // Then sorted by age: Eve(22), Alice(25), Diana(28), Bob(30), Charlie(35) // Then paginated: start=1, limit=2 should give Alice(25), Diana(28) - require.Equal(t, 2, len(result.Items), "Should return 2 items after pagination") + require.Len(t, result.Items, 2, "Should return 2 items after pagination") require.Equal(t, 5, result.TotalCount, "TotalCount should be all filtered items") require.Equal(t, 5, result.TotalAvailable, "TotalAvailable should be original count") require.Equal(t, 25, result.Items[0].Age, "First item should be Alice (age 25)") @@ -310,7 +310,7 @@ func TestSearchOrderAndPaginate(t *testing.T) { // Should find 3 electronics, sorted by price: Mouse(29.99), Keyboard(129.99), Laptop(999.99) // Paginated to first 2: Mouse, Keyboard - require.Equal(t, 2, len(result.Items), "Should return 2 items") + require.Len(t, result.Items, 2, "Should return 2 items") require.Equal(t, 3, result.TotalCount, "Should find 3 electronics items") require.Equal(t, 5, result.TotalAvailable, "Should have 5 total products") require.Equal(t, "Mouse", result.Items[0].Name, "First should be Mouse (cheapest)") @@ -327,7 +327,7 @@ func TestSearchOrderAndPaginate(t *testing.T) { result := SearchOrderAndPaginate(emptyUsers, params, userConfig) - require.Equal(t, 0, len(result.Items), "Should return empty slice") + require.Empty(t, result.Items, "Should return empty slice") require.Equal(t, 0, result.TotalCount, "TotalCount should be 0") require.Equal(t, 0, result.TotalAvailable, "TotalAvailable should be 0") }) @@ -354,7 +354,7 @@ func TestSearchOrderAndPaginateWithErrors(t *testing.T) { result := SearchOrderAndPaginate(users, params, errorConfig) // Should still find Alice through the working accessor - require.Equal(t, 1, len(result.Items), "Should find user despite error in first accessor") + require.Len(t, result.Items, 1, "Should find user despite error in first accessor") require.Equal(t, "Alice Johnson", result.Items[0].Name, "Should return Alice") }) } diff --git a/api/http/utils/filters/query_params_test.go b/api/http/utils/filters/query_params_test.go index b95293030..c75a796e4 100644 --- a/api/http/utils/filters/query_params_test.go +++ b/api/http/utils/filters/query_params_test.go @@ -199,27 +199,23 @@ func TestExtractListModifiersQueryParams(t *testing.T) { } func TestSortOrderConstants(t *testing.T) { - t.Run("sort order constants", func(t *testing.T) { - require.Equal(t, SortOrder("asc"), SortAsc, "SortAsc constant should equal 'asc'") - require.Equal(t, SortOrder("desc"), SortDesc, "SortDesc constant should equal 'desc'") - }) + require.Equal(t, SortAsc, SortOrder("asc"), "SortAsc constant should equal 'asc'") + require.Equal(t, SortDesc, SortOrder("desc"), "SortDesc constant should equal 'desc'") } func TestQueryParamsStructEmbedding(t *testing.T) { - t.Run("struct embedding", func(t *testing.T) { - qp := QueryParams{ - SearchQueryParams: SearchQueryParams{search: "test"}, - SortQueryParams: SortQueryParams{sort: "name", order: SortAsc}, - PaginationQueryParams: PaginationQueryParams{start: 10, limit: 20}, - } + qp := QueryParams{ + SearchQueryParams: SearchQueryParams{search: "test"}, + SortQueryParams: SortQueryParams{sort: "name", order: SortAsc}, + PaginationQueryParams: PaginationQueryParams{start: 10, limit: 20}, + } - // Test that embedded fields are accessible - require.Equal(t, "test", qp.search, "Embedded search field should be accessible") - require.Equal(t, "name", qp.sort, "Embedded sort field should be accessible") - require.Equal(t, SortAsc, qp.order, "Embedded order field should be accessible") - require.Equal(t, 10, qp.start, "Embedded start field should be accessible") - require.Equal(t, 20, qp.limit, "Embedded limit field should be accessible") - }) + // Test that embedded fields are accessible + require.Equal(t, "test", qp.search, "Embedded search field should be accessible") + require.Equal(t, "name", qp.sort, "Embedded sort field should be accessible") + require.Equal(t, SortAsc, qp.order, "Embedded order field should be accessible") + require.Equal(t, 10, qp.start, "Embedded start field should be accessible") + require.Equal(t, 20, qp.limit, "Embedded limit field should be accessible") } func TestExtractListModifiersQueryParamsEdgeCases(t *testing.T) { diff --git a/api/http/utils/filters/sort_test.go b/api/http/utils/filters/sort_test.go index 44f4c5d72..66145fc1a 100644 --- a/api/http/utils/filters/sort_test.go +++ b/api/http/utils/filters/sort_test.go @@ -233,10 +233,10 @@ func TestReverseSortFn(t *testing.T) { userB := User{Name: "Bob", Age: 30} // Original function: A < B (returns negative) - require.Less(t, originalFn(userA, userB), 0) + require.Negative(t, originalFn(userA, userB)) // Reversed function: A > B (returns positive) - require.Greater(t, reversedFn(userA, userB), 0) + require.Positive(t, reversedFn(userA, userB)) // Test symmetry require.Equal(t, -originalFn(userA, userB), reversedFn(userA, userB)) diff --git a/api/internal/edge/edgestacks/service_test.go b/api/internal/edge/edgestacks/service_test.go index de211b32e..4e507fc77 100644 --- a/api/internal/edge/edgestacks/service_test.go +++ b/api/internal/edge/edgestacks/service_test.go @@ -7,6 +7,7 @@ import ( "github.com/portainer/portainer/api/internal/testhelpers" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func Test_updateEndpointRelation_successfulRuns(t *testing.T) { @@ -26,8 +27,7 @@ func Test_updateEndpointRelation_successfulRuns(t *testing.T) { service := NewService(dataStore) err := service.updateEndpointRelations(dataStore, edgeStackID, relatedIds) - - assert.NoError(t, err, "updateEndpointRelations should not fail") + require.NoError(t, err, "updateEndpointRelations should not fail") relatedSet := map[portainer.EndpointID]bool{} for _, relationID := range relatedIds { diff --git a/api/internal/endpointutils/endpoint_test.go b/api/internal/endpointutils/endpoint_test.go index 93e5db3f4..fd6a1e71b 100644 --- a/api/internal/endpointutils/endpoint_test.go +++ b/api/internal/endpointutils/endpoint_test.go @@ -97,7 +97,7 @@ func Test_FilterByExcludeIDs(t *testing.T) { portainer.EndpointID(2), }, asserts: func(t *testing.T, output []portainer.Endpoint) { - assert.Equal(t, 0, len(output)) + assert.Empty(t, output) }, }, { @@ -108,7 +108,7 @@ func Test_FilterByExcludeIDs(t *testing.T) { }, inputExcludeIDs: []portainer.EndpointID{}, asserts: func(t *testing.T, output []portainer.Endpoint) { - assert.Equal(t, 2, len(output)) + assert.Len(t, output, 2) }, }, } diff --git a/api/internal/randomstring/random_string_test.go b/api/internal/randomstring/random_string_test.go index 371374b5a..d6f640ee4 100644 --- a/api/internal/randomstring/random_string_test.go +++ b/api/internal/randomstring/random_string_test.go @@ -37,7 +37,7 @@ func TestRandomString(t *testing.T) { for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { result := RandomString(tc.length) - require.Equal(t, tc.expected, len(result)) + require.Len(t, result, tc.expected) // Verify all characters are from the expected alphabet for _, char := range result { @@ -56,7 +56,7 @@ func TestRandomStringUniqueness(t *testing.T) { for range numStrings { str := RandomString(stringLength) - require.Equal(t, stringLength, len(str)) + require.Len(t, str, stringLength) // Check if we've seen this string before (very unlikely for random strings) require.False(t, generated[str], "Generated duplicate random string: %s", str) diff --git a/api/jwt/jwt_kubeconfig_test.go b/api/jwt/jwt_kubeconfig_test.go index 8f79aaa60..648bfea3d 100644 --- a/api/jwt/jwt_kubeconfig_test.go +++ b/api/jwt/jwt_kubeconfig_test.go @@ -9,13 +9,14 @@ import ( "github.com/golang-jwt/jwt/v4" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func TestService_GenerateTokenForKubeconfig(t *testing.T) { _, store := datastore.MustNewTestStore(t, true, false) err := store.User().Create(&portainer.User{ID: 1}) - assert.NoError(t, err) + require.NoError(t, err) type fields struct { userSessionTimeout string @@ -27,12 +28,12 @@ func TestService_GenerateTokenForKubeconfig(t *testing.T) { } settings, err := store.Settings().Settings() - assert.NoError(t, err) + require.NoError(t, err) settings.KubeconfigExpiry = "0" err = store.Settings().UpdateSettings(settings) - assert.NoError(t, err) + require.NoError(t, err) myFields := fields{ userSessionTimeout: "24h", @@ -68,7 +69,7 @@ func TestService_GenerateTokenForKubeconfig(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { service, err := NewService(tt.fields.userSessionTimeout, tt.fields.dataStore) - assert.NoError(t, err, "failed to create a copy of service") + require.NoError(t, err, "failed to create a copy of service") got, err := service.GenerateTokenForKubeconfig(tt.args.data) if (err != nil) != tt.wantErr { @@ -77,15 +78,15 @@ func TestService_GenerateTokenForKubeconfig(t *testing.T) { } _, _, _, err = service.ParseAndVerifyToken(got) - assert.NoError(t, err) + require.NoError(t, err) parsedToken, err := jwt.ParseWithClaims(got, &claims{}, func(token *jwt.Token) (any, error) { return service.secrets[kubeConfigScope], nil }) - assert.NoError(t, err, "failed to parse generated token") + require.NoError(t, err, "failed to parse generated token") tokenClaims, ok := parsedToken.Claims.(*claims) - assert.Equal(t, true, ok, "failed to claims out of generated ticket") + assert.True(t, ok, "failed to claims out of generated ticket") assert.Equal(t, myTokenData.Username, tokenClaims.Username) assert.Equal(t, int(myTokenData.ID), tokenClaims.UserID) diff --git a/api/jwt/jwt_test.go b/api/jwt/jwt_test.go index ba79b8ef2..d48458e41 100644 --- a/api/jwt/jwt_test.go +++ b/api/jwt/jwt_test.go @@ -16,7 +16,7 @@ import ( func TestGenerateSignedToken(t *testing.T) { dataStore := testhelpers.NewDatastore(testhelpers.WithSettingsService(&portainer.Settings{})) svc, err := NewService("24h", dataStore) - assert.NoError(t, err, "failed to create a copy of service") + require.NoError(t, err, "failed to create a copy of service") token := &portainer.TokenData{ Username: "Joe", @@ -26,15 +26,15 @@ func TestGenerateSignedToken(t *testing.T) { expiresAt := time.Now().Add(1 * time.Hour) generatedToken, err := svc.generateSignedToken(token, expiresAt, defaultScope) - assert.NoError(t, err, "failed to generate a signed token") + require.NoError(t, err, "failed to generate a signed token") parsedToken, err := jwt.ParseWithClaims(generatedToken, &claims{}, func(token *jwt.Token) (any, error) { return svc.secrets[defaultScope], nil }) - assert.NoError(t, err, "failed to parse generated token") + require.NoError(t, err, "failed to parse generated token") tokenClaims, ok := parsedToken.Claims.(*claims) - assert.Equal(t, true, ok, "failed to claims out of generated ticket") + assert.True(t, ok, "failed to claims out of generated ticket") assert.Equal(t, token.Username, tokenClaims.Username) assert.Equal(t, int(token.ID), tokenClaims.UserID) @@ -45,7 +45,7 @@ func TestGenerateSignedToken(t *testing.T) { func TestGenerateSignedToken_InvalidScope(t *testing.T) { dataStore := testhelpers.NewDatastore(testhelpers.WithSettingsService(&portainer.Settings{})) svc, err := NewService("24h", dataStore) - assert.NoError(t, err, "failed to create a copy of service") + require.NoError(t, err, "failed to create a copy of service") token := &portainer.TokenData{ Username: "Joe", @@ -55,7 +55,7 @@ func TestGenerateSignedToken_InvalidScope(t *testing.T) { expiresAt := time.Now().Add(1 * time.Hour) _, err = svc.generateSignedToken(token, expiresAt, "testing") - assert.Error(t, err) + require.Error(t, err) assert.Equal(t, "invalid scope: testing", err.Error()) } diff --git a/api/kubernetes/cli/access_test.go b/api/kubernetes/cli/access_test.go index 09bb28d9e..7eca9adb2 100644 --- a/api/kubernetes/cli/access_test.go +++ b/api/kubernetes/cli/access_test.go @@ -6,6 +6,7 @@ import ( portainer "github.com/portainer/portainer/api" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ktypes "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" kfake "k8s.io/client-go/kubernetes/fake" @@ -50,17 +51,18 @@ func Test_NamespaceAccessPoliciesDeleteNamespace_updatesPortainerConfig_whenConf "NamespaceAccessPolicies": `{"ns1":{"UserAccessPolicies":{"2":{"RoleId":0}}}, "ns2":{"UserAccessPolicies":{"2":{"RoleId":0}}}}`, }, } + _, err := k.cli.CoreV1().ConfigMaps(portainerNamespace).Create(context.Background(), config, metav1.CreateOptions{}) - assert.NoError(t, err, "failed to create a portainer config") + require.NoError(t, err, "failed to create a portainer config") defer func() { k.cli.CoreV1().ConfigMaps(portainerNamespace).Delete(context.Background(), portainerConfigMapName, metav1.DeleteOptions{}) }() err = k.NamespaceAccessPoliciesDeleteNamespace(test.namespaceToDelete) - assert.NoError(t, err, "failed to delete namespace") + require.NoError(t, err, "failed to delete namespace") policies, err := k.GetNamespaceAccessPolicies() - assert.NoError(t, err, "failed to fetch policies") + require.NoError(t, err, "failed to fetch policies") assert.Equal(t, test.expectedConfig, policies) }) } diff --git a/api/kubernetes/cli/applications_test.go b/api/kubernetes/cli/applications_test.go index 81a5cfb71..d5b4402d4 100644 --- a/api/kubernetes/cli/applications_test.go +++ b/api/kubernetes/cli/applications_test.go @@ -5,7 +5,9 @@ import ( "testing" models "github.com/portainer/portainer/api/http/models/kubernetes" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" appsv1 "k8s.io/api/apps/v1" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -241,70 +243,70 @@ func TestGetApplications(t *testing.T) { // 1. Deployment with pods deployWithPods := createTestDeployment("deploy-with-pods", namespace, 2) _, err := fakeClient.AppsV1().Deployments(namespace).Create(context.TODO(), deployWithPods, metav1.CreateOptions{}) - assert.NoError(t, err) + require.NoError(t, err) replicaSet := createTestReplicaSet("rs-deploy-with-pods", namespace, "deploy-with-pods") _, err = fakeClient.AppsV1().ReplicaSets(namespace).Create(context.TODO(), replicaSet, metav1.CreateOptions{}) - assert.NoError(t, err) + require.NoError(t, err) pod1 := createTestPod("pod1-deploy", namespace, "ReplicaSet", "rs-deploy-with-pods", true) _, err = fakeClient.CoreV1().Pods(namespace).Create(context.TODO(), pod1, metav1.CreateOptions{}) - assert.NoError(t, err) + require.NoError(t, err) pod2 := createTestPod("pod2-deploy", namespace, "ReplicaSet", "rs-deploy-with-pods", true) _, err = fakeClient.CoreV1().Pods(namespace).Create(context.TODO(), pod2, metav1.CreateOptions{}) - assert.NoError(t, err) + require.NoError(t, err) // 2. Deployment without pods (scaled to 0) deployNoPods := createTestDeployment("deploy-no-pods", namespace, 0) _, err = fakeClient.AppsV1().Deployments(namespace).Create(context.TODO(), deployNoPods, metav1.CreateOptions{}) - assert.NoError(t, err) + require.NoError(t, err) // 3. StatefulSet with pods stsWithPods := createTestStatefulSet("sts-with-pods", namespace, 1) _, err = fakeClient.AppsV1().StatefulSets(namespace).Create(context.TODO(), stsWithPods, metav1.CreateOptions{}) - assert.NoError(t, err) + require.NoError(t, err) pod3 := createTestPod("pod1-sts", namespace, "StatefulSet", "sts-with-pods", true) _, err = fakeClient.CoreV1().Pods(namespace).Create(context.TODO(), pod3, metav1.CreateOptions{}) - assert.NoError(t, err) + require.NoError(t, err) // 4. StatefulSet without pods stsNoPods := createTestStatefulSet("sts-no-pods", namespace, 0) _, err = fakeClient.AppsV1().StatefulSets(namespace).Create(context.TODO(), stsNoPods, metav1.CreateOptions{}) - assert.NoError(t, err) + require.NoError(t, err) // 5. DaemonSet with pods dsWithPods := createTestDaemonSet("ds-with-pods", namespace) _, err = fakeClient.AppsV1().DaemonSets(namespace).Create(context.TODO(), dsWithPods, metav1.CreateOptions{}) - assert.NoError(t, err) + require.NoError(t, err) pod4 := createTestPod("pod1-ds", namespace, "DaemonSet", "ds-with-pods", true) _, err = fakeClient.CoreV1().Pods(namespace).Create(context.TODO(), pod4, metav1.CreateOptions{}) - assert.NoError(t, err) + require.NoError(t, err) pod5 := createTestPod("pod2-ds", namespace, "DaemonSet", "ds-with-pods", true) _, err = fakeClient.CoreV1().Pods(namespace).Create(context.TODO(), pod5, metav1.CreateOptions{}) - assert.NoError(t, err) + require.NoError(t, err) // 6. Naked Pod (no owner reference) nakedPod := createTestPod("naked-pod", namespace, "", "", true) _, err = fakeClient.CoreV1().Pods(namespace).Create(context.TODO(), nakedPod, metav1.CreateOptions{}) - assert.NoError(t, err) + require.NoError(t, err) // 7. Resources in another namespace deployOtherNs := createTestDeployment("deploy-other-ns", defaultNamespace, 1) _, err = fakeClient.AppsV1().Deployments(defaultNamespace).Create(context.TODO(), deployOtherNs, metav1.CreateOptions{}) - assert.NoError(t, err) + require.NoError(t, err) podOtherNs := createTestPod("pod-other-ns", defaultNamespace, "Deployment", "deploy-other-ns", true) _, err = fakeClient.CoreV1().Pods(defaultNamespace).Create(context.TODO(), podOtherNs, metav1.CreateOptions{}) - assert.NoError(t, err) + require.NoError(t, err) // 8. Add a service (dependency) service := createTestService("svc-deploy", namespace, map[string]string{"app": "deploy-with-pods"}) _, err = fakeClient.CoreV1().Services(namespace).Create(context.TODO(), service, metav1.CreateOptions{}) - assert.NoError(t, err) + require.NoError(t, err) // Create the KubeClient with admin privileges kubeClient := &KubeClient{ @@ -318,11 +320,11 @@ func TestGetApplications(t *testing.T) { // 1. All resources, no filtering t.Run("All resources with dependencies", func(t *testing.T) { apps, err := kubeClient.GetApplications("", "") - assert.NoError(t, err) + require.NoError(t, err) // We expect 7 resources: 2 deployments + 2 statefulsets + 1 daemonset + 1 naked pod + 1 deployment in other namespace // Note: Each controller with pods should count once, not per pod - assert.Equal(t, 7, len(apps)) + assert.Len(t, apps, 7) // Verify one of the deployments has services attached appsWithServices := []models.K8sApplication{} @@ -331,17 +333,17 @@ func TestGetApplications(t *testing.T) { appsWithServices = append(appsWithServices, app) } } - assert.Equal(t, 1, len(appsWithServices)) + assert.Len(t, appsWithServices, 1) assert.Equal(t, "deploy-with-pods", appsWithServices[0].Name) }) // 2. Filter by namespace t.Run("Filter by namespace", func(t *testing.T) { apps, err := kubeClient.GetApplications(namespace, "") - assert.NoError(t, err) + require.NoError(t, err) // We expect 6 resources in the test namespace - assert.Equal(t, 6, len(apps)) + assert.Len(t, apps, 6) // Verify resources from other namespaces are not included for _, app := range apps { @@ -361,25 +363,25 @@ func TestGetApplications(t *testing.T) { // Create resources in the allowed namespace sts1 := createTestStatefulSet("sts-allowed", namespace1, 1) _, err := fakeClient.AppsV1().StatefulSets(namespace1).Create(context.TODO(), sts1, metav1.CreateOptions{}) - assert.NoError(t, err) + require.NoError(t, err) pod1 := createTestPod("pod-allowed", namespace1, "StatefulSet", "sts-allowed", true) _, err = fakeClient.CoreV1().Pods(namespace1).Create(context.TODO(), pod1, metav1.CreateOptions{}) - assert.NoError(t, err) + require.NoError(t, err) // Add a StatefulSet without pods in the allowed namespace stsNoPods := createTestStatefulSet("sts-no-pods-allowed", namespace1, 0) _, err = fakeClient.AppsV1().StatefulSets(namespace1).Create(context.TODO(), stsNoPods, metav1.CreateOptions{}) - assert.NoError(t, err) + require.NoError(t, err) // Create resources in the restricted namespace sts2 := createTestStatefulSet("sts-restricted", namespace2, 1) _, err = fakeClient.AppsV1().StatefulSets(namespace2).Create(context.TODO(), sts2, metav1.CreateOptions{}) - assert.NoError(t, err) + require.NoError(t, err) pod2 := createTestPod("pod-restricted", namespace2, "StatefulSet", "sts-restricted", true) _, err = fakeClient.CoreV1().Pods(namespace2).Create(context.TODO(), pod2, metav1.CreateOptions{}) - assert.NoError(t, err) + require.NoError(t, err) // Create the KubeClient with non-admin privileges (only allowed namespace1) kubeClient := &KubeClient{ @@ -391,10 +393,10 @@ func TestGetApplications(t *testing.T) { // Test that only resources from allowed namespace are returned apps, err := kubeClient.GetApplications("", "") - assert.NoError(t, err) + require.NoError(t, err) // We expect 2 resources from the allowed namespace (1 sts with pod + 1 sts without pod) - assert.Equal(t, 2, len(apps)) + assert.Len(t, apps, 2) // Verify resources are from the allowed namespace for _, app := range apps { @@ -423,23 +425,23 @@ func TestGetApplications(t *testing.T) { // Create a deployment with pods on specific node deploy := createTestDeployment("node-deploy", namespace, 2) _, err := fakeClient.AppsV1().Deployments(namespace).Create(context.TODO(), deploy, metav1.CreateOptions{}) - assert.NoError(t, err) + require.NoError(t, err) // Create ReplicaSet for the deployment rs := createTestReplicaSet("rs-node-deploy", namespace, "node-deploy") _, err = fakeClient.AppsV1().ReplicaSets(namespace).Create(context.TODO(), rs, metav1.CreateOptions{}) - assert.NoError(t, err) + require.NoError(t, err) // Create 2 pods, one on the specified node, one on a different node pod1 := createTestPod("pod-on-node", namespace, "ReplicaSet", "rs-node-deploy", true) pod1.Spec.NodeName = nodeName _, err = fakeClient.CoreV1().Pods(namespace).Create(context.TODO(), pod1, metav1.CreateOptions{}) - assert.NoError(t, err) + require.NoError(t, err) pod2 := createTestPod("pod-other-node", namespace, "ReplicaSet", "rs-node-deploy", true) pod2.Spec.NodeName = "worker-node-2" _, err = fakeClient.CoreV1().Pods(namespace).Create(context.TODO(), pod2, metav1.CreateOptions{}) - assert.NoError(t, err) + require.NoError(t, err) // Create the KubeClient kubeClient := &KubeClient{ @@ -450,10 +452,10 @@ func TestGetApplications(t *testing.T) { // Test filtering by node name apps, err := kubeClient.GetApplications(namespace, nodeName) - assert.NoError(t, err) + require.NoError(t, err) // We expect to find only the pod on the specified node - assert.Equal(t, 1, len(apps)) + assert.Len(t, apps, 1) if len(apps) > 0 { assert.Equal(t, "node-deploy", apps[0].Name) } diff --git a/api/kubernetes/cli/event_test.go b/api/kubernetes/cli/event_test.go index 926928317..2fac7620b 100644 --- a/api/kubernetes/cli/event_test.go +++ b/api/kubernetes/cli/event_test.go @@ -21,6 +21,7 @@ func TestGetEvents(t *testing.T) { instanceID: "instance", IsKubeAdmin: true, } + event := corev1.Event{ InvolvedObject: corev1.ObjectReference{UID: "resourceId"}, Action: "something", @@ -29,18 +30,15 @@ func TestGetEvents(t *testing.T) { Type: "warning", Message: "This event has a very serious warning", } + _, err := kcl.cli.CoreV1().Events("default").Create(context.TODO(), &event, metav1.CreateOptions{}) - if err != nil { - t.Fatalf("Failed to create Event: %v", err) - } + require.NoError(t, err, "Failed to create Event") events, err := kcl.GetEvents("default", "resourceId") + require.NoError(t, err, "Failed to fetch Events") - if err != nil { - t.Fatalf("Failed to fetch Cron Jobs: %v", err) - } t.Logf("Fetched Events: %v", events) - require.Equal(t, 1, len(events), "Expected to return 1 event") + require.Len(t, events, 1, "Expected to return 1 event") assert.Equal(t, event.Message, events[0].Message, "Expected Message to be equal to event message created") assert.Equal(t, event.Type, events[0].Type, "Expected Type to be equal to event type created") assert.Equal(t, event.EventTime.UTC(), events[0].EventTime, "Expected EventTime to be saved as a string from event time created") @@ -52,6 +50,7 @@ func TestGetEvents(t *testing.T) { IsKubeAdmin: false, NonAdminNamespaces: []string{"nonAdmin"}, } + event := corev1.Event{ InvolvedObject: corev1.ObjectReference{UID: "resourceId"}, Action: "something", @@ -60,18 +59,15 @@ func TestGetEvents(t *testing.T) { Type: "warning", Message: "This event has a very serious warning", } + _, err := kcl.cli.CoreV1().Events("nonAdmin").Create(context.TODO(), &event, metav1.CreateOptions{}) - if err != nil { - t.Fatalf("Failed to create Event: %v", err) - } + require.NoError(t, err, "Failed to create Event") events, err := kcl.GetEvents("nonAdmin", "resourceId") + require.NoError(t, err, "Failed to fetch Cron Jobs") - if err != nil { - t.Fatalf("Failed to fetch Cron Jobs: %v", err) - } t.Logf("Fetched Events: %v", events) - require.Equal(t, 1, len(events), "Expected to return 1 event") + require.Len(t, events, 1, "Expected to return 1 event") assert.Equal(t, event.Message, events[0].Message, "Expected Message to be equal to event message created") assert.Equal(t, event.Type, events[0].Type, "Expected Type to be equal to event type created") assert.Equal(t, event.EventTime.UTC(), events[0].EventTime, "Expected EventTime to be saved as a string from event time created") @@ -84,6 +80,7 @@ func TestGetEvents(t *testing.T) { IsKubeAdmin: false, NonAdminNamespaces: []string{"nonAdmin"}, } + event := corev1.Event{ InvolvedObject: corev1.ObjectReference{UID: "resourceId"}, Action: "something", @@ -92,17 +89,13 @@ func TestGetEvents(t *testing.T) { Type: "warning", Message: "This event has a very serious warning", } + _, err := kcl.cli.CoreV1().Events("admin").Create(context.TODO(), &event, metav1.CreateOptions{}) - if err != nil { - t.Fatalf("Failed to create Event: %v", err) - } + require.NoError(t, err, "Failed to create Event") events, err := kcl.GetEvents("admin", "resourceId") - - if err != nil { - t.Fatalf("Failed to fetch Cron Jobs: %v", err) - } + require.NoError(t, err, "Failed to fetch Cron Jobs") t.Logf("Fetched Events: %v", events) - assert.Equal(t, 0, len(events), "Expected to return 0 events") + assert.Empty(t, events, "Expected to return 0 events") }) } diff --git a/api/kubernetes/cli/namespace_test.go b/api/kubernetes/cli/namespace_test.go index d3d25a4d0..2a0701d99 100644 --- a/api/kubernetes/cli/namespace_test.go +++ b/api/kubernetes/cli/namespace_test.go @@ -6,7 +6,9 @@ import ( "testing" portainer "github.com/portainer/portainer/api" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" core "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" kfake "k8s.io/client-go/kubernetes/fake" @@ -21,10 +23,10 @@ func Test_ToggleSystemState(t *testing.T) { } err := kcl.ToggleSystemState(nsName, true) - assert.NoError(t, err) + require.NoError(t, err) ns, err := kcl.cli.CoreV1().Namespaces().Get(context.Background(), nsName, metav1.GetOptions{}) - assert.NoError(t, err) + require.NoError(t, err) _, exists := ns.Labels[systemNamespaceLabel] assert.False(t, exists, "system label should not exists") @@ -38,7 +40,7 @@ func Test_ToggleSystemState(t *testing.T) { } err := kcl.ToggleSystemState(nsName, true) - assert.Error(t, err) + require.Error(t, err) }) t.Run("if called with the same state, should skip (exit without error)", func(t *testing.T) { @@ -60,10 +62,10 @@ func Test_ToggleSystemState(t *testing.T) { } err := kcl.ToggleSystemState(nsName, test.isSystem) - assert.NoError(t, err) + require.NoError(t, err) ns, err := kcl.cli.CoreV1().Namespaces().Get(context.Background(), nsName, metav1.GetOptions{}) - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, test.isSystem, isSystemNamespace(ns)) }) @@ -89,10 +91,10 @@ func Test_ToggleSystemState(t *testing.T) { } err := kcl.ToggleSystemState(nsName, true) - assert.NoError(t, err) + require.NoError(t, err) ns, err := kcl.cli.CoreV1().Namespaces().Get(context.Background(), nsName, metav1.GetOptions{}) - assert.NoError(t, err) + require.NoError(t, err) labelValue, exists := ns.Labels[systemNamespaceLabel] assert.True(t, exists, "system label should exists") @@ -109,10 +111,10 @@ func Test_ToggleSystemState(t *testing.T) { } err := kcl.ToggleSystemState(nsName, false) - assert.NoError(t, err) + require.NoError(t, err) ns, err := kcl.cli.CoreV1().Namespaces().Get(context.Background(), nsName, metav1.GetOptions{}) - assert.NoError(t, err) + require.NoError(t, err) labelValue, exists := ns.Labels[systemNamespaceLabel] assert.True(t, exists, "system label should exists") @@ -131,10 +133,10 @@ func Test_ToggleSystemState(t *testing.T) { } err := kcl.ToggleSystemState(nsName, false) - assert.NoError(t, err) + require.NoError(t, err) ns, err := kcl.cli.CoreV1().Namespaces().Get(context.Background(), nsName, metav1.GetOptions{}) - assert.NoError(t, err) + require.NoError(t, err) labelValue, exists := ns.Labels[systemNamespaceLabel] assert.True(t, exists, "system label should exists") @@ -164,10 +166,10 @@ func Test_ToggleSystemState(t *testing.T) { } err := kcl.ToggleSystemState(nsName, true) - assert.NoError(t, err) + require.NoError(t, err) ns, err := kcl.cli.CoreV1().Namespaces().Get(context.Background(), nsName, metav1.GetOptions{}) - assert.NoError(t, err) + require.NoError(t, err) labelValue, exists := ns.Labels[systemNamespaceLabel] assert.True(t, exists, "system label should exists") @@ -177,7 +179,7 @@ func Test_ToggleSystemState(t *testing.T) { "ns2": {UserAccessPolicies: portainer.UserAccessPolicies{2: {RoleID: 0}}}, } actualPolicies, err := kcl.GetNamespaceAccessPolicies() - assert.NoError(t, err, "failed to fetch policies") + require.NoError(t, err, "failed to fetch policies") assert.Equal(t, expectedPolicies, actualPolicies) }) } diff --git a/api/kubernetes/kubeclusteraccess_service_test.go b/api/kubernetes/kubeclusteraccess_service_test.go index 706b13849..f92b99d60 100644 --- a/api/kubernetes/kubeclusteraccess_service_test.go +++ b/api/kubernetes/kubeclusteraccess_service_test.go @@ -3,10 +3,10 @@ package kubernetes import ( "fmt" "os" - "strings" "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) // TLS certificate can be generated using: @@ -66,9 +66,9 @@ func Test_getCertificateAuthorityData(t *testing.T) { filePath := createTempFile("valid-cert.crt", certData, t) certificateAuthorityData, err := getCertificateAuthorityData(filePath) - is.NoError(err, "getCertificateAuthorityData succeed with valid cert; err=%w", errTLSCertIncorrectType) + require.NoError(t, err, "getCertificateAuthorityData succeed with valid cert; err=%w", errTLSCertIncorrectType) - is.Equal(certificateAuthorityData, certDataString, "returned certificateAuthorityData should be %s", certDataString) + is.Equal(certDataString, certificateAuthorityData, "returned certificateAuthorityData should be %s", certDataString) }) } @@ -94,13 +94,13 @@ func TestKubeClusterAccessService_GetKubeConfigInternal(t *testing.T) { t.Run("GetClusterDetails contains host address", func(t *testing.T) { kcs := NewKubeClusterAccessService("/", "", "") clusterAccessDetails := kcs.GetClusterDetails("mysite.com", 1, true) - is.True(strings.Contains(clusterAccessDetails.ClusterServerURL, "https://mysite.com"), "should contain host address") + is.Contains(clusterAccessDetails.ClusterServerURL, "https://mysite.com", "should contain host address") }) t.Run("GetClusterDetails contains environment proxy url", func(t *testing.T) { kcs := NewKubeClusterAccessService("/", "", "") clusterAccessDetails := kcs.GetClusterDetails("mysite.com", 100, true) - is.True(strings.Contains(clusterAccessDetails.ClusterServerURL, "api/endpoints/100/kubernetes"), "should contain environment proxy url") + is.Contains(clusterAccessDetails.ClusterServerURL, "api/endpoints/100/kubernetes", "should contain environment proxy url") }) t.Run("GetClusterDetails returns insecure cluster access config", func(t *testing.T) { diff --git a/api/kubernetes/yaml_test.go b/api/kubernetes/yaml_test.go index 80deef978..9b68353f3 100644 --- a/api/kubernetes/yaml_test.go +++ b/api/kubernetes/yaml_test.go @@ -4,6 +4,7 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func Test_AddAppLabels(t *testing.T) { @@ -420,7 +421,7 @@ spec: for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { result, err := AddAppLabels([]byte(tt.input), labels.ToMap()) - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, tt.wantOutput, string(result)) }) } @@ -584,7 +585,7 @@ spec: for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { result, err := AddAppLabels([]byte(tt.input), labels) - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, tt.wantOutput, string(result)) }) } @@ -633,7 +634,7 @@ metadata: io.portainer.kubernetes.application.stackid: "123" ` result, err := AddAppLabels([]byte(input), labels.ToMap()) - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, expected, string(result)) } @@ -664,7 +665,7 @@ kind: Namespace for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { result, err := GetNamespace([]byte(tt.input)) - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, tt.want, result) }) } @@ -704,7 +705,8 @@ kind: Namespace for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { results, err := ExtractDocuments([]byte(tt.input), nil) - assert.NoError(t, err) + require.NoError(t, err) + for i := range results { assert.Equal(t, tt.want[i], string(results[i])) } diff --git a/api/oauth/oauth_test.go b/api/oauth/oauth_test.go index 6083ec773..d57132021 100644 --- a/api/oauth/oauth_test.go +++ b/api/oauth/oauth_test.go @@ -7,6 +7,7 @@ import ( "github.com/portainer/portainer/api/oauth/oauthtest" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "golang.org/x/oauth2" ) @@ -80,8 +81,8 @@ func Test_getIdToken(t *testing.T) { } result, err := GetIdToken(token) - assert.Equal(t, err, tc.expectedError) - assert.Equal(t, result, tc.expectedResult) + require.ErrorIs(t, err, tc.expectedError) + assert.Equal(t, tc.expectedResult, result) }) } } diff --git a/api/pendingactions/pendingactions_test.go b/api/pendingactions/pendingactions_test.go index b572ede38..89e3e98ca 100644 --- a/api/pendingactions/pendingactions_test.go +++ b/api/pendingactions/pendingactions_test.go @@ -6,6 +6,7 @@ import ( portainer "github.com/portainer/portainer/api" "github.com/portainer/portainer/api/internal/testhelpers" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func TestExecute(t *testing.T) { @@ -78,11 +79,13 @@ func TestExecute(t *testing.T) { service.execute(tt.endpoint.ID) // Verify expectations - pendingActions, _ := store.PendingActions().ReadAll() + pendingActions, err := store.PendingActions().ReadAll() + require.NoError(t, err) + if tt.shouldExecute { - assert.Equal(t, len(tt.pendingActions)-1, len(pendingActions)) + assert.Len(t, pendingActions, len(tt.pendingActions)-1) } else { - assert.Equal(t, len(tt.pendingActions), len(pendingActions)) + assert.Len(t, pendingActions, len(tt.pendingActions)) } }) } diff --git a/api/roar/roar_test.go b/api/roar/roar_test.go index ed5103ad5..b9a25dd63 100644 --- a/api/roar/roar_test.go +++ b/api/roar/roar_test.go @@ -45,7 +45,7 @@ func TestRoar(t *testing.T) { }) rSlice := r.ToSlice() - require.EqualValues(t, []int{2, 3, 4, 5}, rSlice) + require.Equal(t, []int{2, 3, 4, 5}, rSlice) r.Intersection(FromSlice([]int{4})) require.Equal(t, 1, r.Len()) diff --git a/api/stacks/deployments/deploy_test.go b/api/stacks/deployments/deploy_test.go index b7015be01..86adcb3a6 100644 --- a/api/stacks/deployments/deploy_test.go +++ b/api/stacks/deployments/deploy_test.go @@ -156,7 +156,7 @@ func Test_redeployWhenChanged_FailsWhenCannotFindStack(t *testing.T) { _, store := datastore.MustNewTestStore(t, true, true) err := RedeployWhenChanged(1, nil, store, nil) - assert.Error(t, err) + require.Error(t, err) assert.Truef(t, strings.HasPrefix(err.Error(), "failed to get the stack"), "it isn't an error we expected: %v", err.Error()) } @@ -165,13 +165,13 @@ func Test_redeployWhenChanged_DoesNothingWhenNotAGitBasedStack(t *testing.T) { admin := &portainer.User{ID: 1, Username: "admin"} err := store.User().Create(admin) - assert.NoError(t, err, "error creating an admin") + require.NoError(t, err, "error creating an admin") err = store.Stack().Create(&portainer.Stack{ID: 1, CreatedBy: "admin"}) - assert.NoError(t, err, "failed to create a test stack") + require.NoError(t, err, "failed to create a test stack") err = RedeployWhenChanged(1, nil, store, testhelpers.NewGitService(nil, "")) - assert.NoError(t, err) + require.NoError(t, err) } func Test_redeployWhenChanged_DoesNothingWhenNoGitChanges(t *testing.T) { @@ -181,12 +181,12 @@ func Test_redeployWhenChanged_DoesNothingWhenNoGitChanges(t *testing.T) { admin := &portainer.User{ID: 1, Username: "admin"} err := store.User().Create(admin) - assert.NoError(t, err, "error creating an admin") + require.NoError(t, err, "error creating an admin") err = store.Endpoint().Create(&portainer.Endpoint{ ID: 0, }) - assert.NoError(t, err, "error creating environment") + require.NoError(t, err, "error creating environment") err = store.Stack().Create(&portainer.Stack{ ID: 1, @@ -197,10 +197,10 @@ func Test_redeployWhenChanged_DoesNothingWhenNoGitChanges(t *testing.T) { ReferenceName: "ref", ConfigHash: "oldHash", }}) - assert.NoError(t, err, "failed to create a test stack") + require.NoError(t, err, "failed to create a test stack") err = RedeployWhenChanged(1, nil, store, testhelpers.NewGitService(nil, "oldHash")) - assert.NoError(t, err) + require.NoError(t, err) } func Test_redeployWhenChanged_FailsWhenCannotClone(t *testing.T) { @@ -211,7 +211,7 @@ func Test_redeployWhenChanged_FailsWhenCannotClone(t *testing.T) { admin := &portainer.User{ID: 1, Username: "admin"} err := store.User().Create(admin) - assert.NoError(t, err, "error creating an admin") + require.NoError(t, err, "error creating an admin") err = store.Endpoint().Create(&portainer.Endpoint{ ID: 0, @@ -221,7 +221,7 @@ func Test_redeployWhenChanged_FailsWhenCannotClone(t *testing.T) { TLSSkipVerify: true, }, }) - assert.NoError(t, err, "error creating environment") + require.NoError(t, err, "error creating environment") err = store.Stack().Create(&portainer.Stack{ ID: 1, @@ -231,11 +231,11 @@ func Test_redeployWhenChanged_FailsWhenCannotClone(t *testing.T) { ReferenceName: "ref", ConfigHash: "oldHash", }}) - assert.NoError(t, err, "failed to create a test stack") + require.NoError(t, err, "failed to create a test stack") err = RedeployWhenChanged(1, nil, store, testhelpers.NewGitService(cloneErr, "newHash")) - assert.Error(t, err) - assert.ErrorIs(t, err, cloneErr, "should failed to clone but didn't, check test setup") + require.Error(t, err) + require.ErrorIs(t, err, cloneErr, "should failed to clone but didn't, check test setup") } func Test_redeployWhenChanged(t *testing.T) { @@ -244,11 +244,11 @@ func Test_redeployWhenChanged(t *testing.T) { tmpDir := t.TempDir() err := store.Endpoint().Create(&portainer.Endpoint{ID: 1}) - assert.NoError(t, err, "error creating environment") + require.NoError(t, err, "error creating environment") username := "user" err = store.User().Create(&portainer.User{Username: username, Role: portainer.AdministratorRole}) - assert.NoError(t, err, "error creating a user") + require.NoError(t, err, "error creating a user") stack := portainer.Stack{ ID: 1, @@ -263,14 +263,14 @@ func Test_redeployWhenChanged(t *testing.T) { } err = store.Stack().Create(&stack) - assert.NoError(t, err, "failed to create a test stack") + require.NoError(t, err, "failed to create a test stack") t.Run("can deploy docker compose stack", func(t *testing.T) { stack.Type = portainer.DockerComposeStack store.Stack().Update(stack.ID, &stack) err = RedeployWhenChanged(1, noopDeployer{}, store, testhelpers.NewGitService(nil, "newHash")) - assert.NoError(t, err) + require.NoError(t, err) }) t.Run("can deploy docker swarm stack", func(t *testing.T) { @@ -278,7 +278,7 @@ func Test_redeployWhenChanged(t *testing.T) { store.Stack().Update(stack.ID, &stack) err = RedeployWhenChanged(1, noopDeployer{}, store, testhelpers.NewGitService(nil, "newHash")) - assert.NoError(t, err) + require.NoError(t, err) }) t.Run("can deploy kube app", func(t *testing.T) { @@ -286,7 +286,7 @@ func Test_redeployWhenChanged(t *testing.T) { store.Stack().Update(stack.ID, &stack) err = RedeployWhenChanged(1, noopDeployer{}, store, testhelpers.NewGitService(nil, "newHash")) - assert.NoError(t, err) + require.NoError(t, err) }) } @@ -297,11 +297,11 @@ func Test_getUserRegistries(t *testing.T) { admin := &portainer.User{ID: 1, Username: "admin", Role: portainer.AdministratorRole} err := store.User().Create(admin) - assert.NoError(t, err, "error creating an admin") + require.NoError(t, err, "error creating an admin") user := &portainer.User{ID: 2, Username: "user", Role: portainer.StandardUserRole} err = store.User().Create(user) - assert.NoError(t, err, "error creating a user") + require.NoError(t, err, "error creating a user") team := portainer.Team{ID: 1, Name: "team"} @@ -324,7 +324,7 @@ func Test_getUserRegistries(t *testing.T) { }, } err = store.Registry().Create(®istryReachableByUser) - assert.NoError(t, err, "couldn't create a registry") + require.NoError(t, err, "couldn't create a registry") registryReachableByTeam := portainer.Registry{ ID: 2, @@ -338,7 +338,7 @@ func Test_getUserRegistries(t *testing.T) { }, } err = store.Registry().Create(®istryReachableByTeam) - assert.NoError(t, err, "couldn't create a registry") + require.NoError(t, err, "couldn't create a registry") registryRestricted := portainer.Registry{ ID: 3, @@ -352,17 +352,17 @@ func Test_getUserRegistries(t *testing.T) { }, } err = store.Registry().Create(®istryRestricted) - assert.NoError(t, err, "couldn't create a registry") + require.NoError(t, err, "couldn't create a registry") t.Run("admin should has access to all registries", func(t *testing.T) { registries, err := getUserRegistries(store, admin, portainer.EndpointID(endpointID)) - assert.NoError(t, err) + require.NoError(t, err) assert.ElementsMatch(t, []portainer.Registry{registryReachableByUser, registryReachableByTeam, registryRestricted}, registries) }) t.Run("regular user has access to registries allowed to him and/or his team", func(t *testing.T) { registries, err := getUserRegistries(store, user, portainer.EndpointID(endpointID)) - assert.NoError(t, err) + require.NoError(t, err) assert.ElementsMatch(t, []portainer.Registry{registryReachableByUser, registryReachableByTeam}, registries) }) } diff --git a/pkg/edge/utils_test.go b/pkg/edge/utils_test.go index ffecf73ee..c53daee72 100644 --- a/pkg/edge/utils_test.go +++ b/pkg/edge/utils_test.go @@ -4,6 +4,7 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func TestGetPortainerURLFromEdgeKey(t *testing.T) { @@ -22,7 +23,7 @@ func TestGetPortainerURLFromEdgeKey(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { result, err := GetPortainerURLFromEdgeKey(tt.edgeKey) - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, tt.expected, result) }) } diff --git a/pkg/libhelm/sdk/chartsources_test.go b/pkg/libhelm/sdk/chartsources_test.go index 20b6ef397..1802242d7 100644 --- a/pkg/libhelm/sdk/chartsources_test.go +++ b/pkg/libhelm/sdk/chartsources_test.go @@ -1,14 +1,16 @@ package sdk import ( + "errors" "strings" "testing" - "github.com/pkg/errors" portainer "github.com/portainer/portainer/api" "github.com/portainer/portainer/pkg/fips" helmregistrycache "github.com/portainer/portainer/pkg/libhelm/cache" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "helm.sh/helm/v3/pkg/action" "helm.sh/helm/v3/pkg/registry" ) @@ -41,8 +43,7 @@ func TestParseHTTPRepoChartRef(t *testing.T) { is := assert.New(t) chartRef, repoURL, err := parseHTTPRepoChartRef("my-chart", "https://my.repo/charts") - - is.NoError(err) + require.NoError(t, err) is.Equal("my-chart", chartRef) is.Equal("https://my.repo/charts", repoURL) } @@ -58,8 +59,7 @@ func TestParseOCIChartRef(t *testing.T) { } chartRef, repoURL, err := parseOCIChartRef("my-chart", registry) - - is.NoError(err) + require.NoError(t, err) is.Equal("oci://my-registry.io/my-namespace/my-chart", chartRef) is.Equal("my-registry.io/my-namespace", repoURL) } @@ -81,8 +81,7 @@ func TestParseOCIChartRef_GitLab(t *testing.T) { } chartRef, repoURL, err := parseOCIChartRef("my-chart", registry) - - is.NoError(err) + require.NoError(t, err) is.Equal("oci://registry.gitlab.com/my-chart", chartRef) is.Equal("registry.gitlab.com", repoURL) } @@ -92,8 +91,7 @@ func TestParseChartRef(t *testing.T) { is := assert.New(t) chartRef, repoURL, err := parseChartRef("my-chart", "https://my.repo/charts", nil) - - is.NoError(err) + require.NoError(t, err) is.Equal("my-chart", chartRef) is.Equal("https://my.repo/charts", repoURL) }) @@ -109,8 +107,7 @@ func TestParseChartRef(t *testing.T) { } chartRef, repoURL, err := parseChartRef("my-chart", "", registry) - - is.NoError(err) + require.NoError(t, err) is.Equal("oci://my-registry.io/my-namespace/my-chart", chartRef) is.Equal("my-registry.io/my-namespace", repoURL) }) @@ -163,8 +160,7 @@ func TestConfigureChartPathOptions(t *testing.T) { chartPathOptions := &action.ChartPathOptions{} err := configureChartPathOptions(chartPathOptions, "1.0.0", "https://my.repo/charts", nil) - - is.NoError(err) + require.NoError(t, err) is.Equal("https://my.repo/charts", chartPathOptions.RepoURL) is.Equal("1.0.0", chartPathOptions.Version) }) @@ -182,7 +178,7 @@ func TestConfigureChartPathOptions(t *testing.T) { err := configureChartPathOptions(chartPathOptions, "1.0.0", "", registry) - is.NoError(err) + require.NoError(t, err) is.Equal("user", chartPathOptions.Username) is.Equal("pass", chartPathOptions.Password) is.Equal("1.0.0", chartPathOptions.Version) @@ -194,7 +190,7 @@ func TestLoginToOCIRegistry(t *testing.T) { t.Run("should return nil for HTTP repository (nil registry)", func(t *testing.T) { client, err := createOCIRegistryClient(nil) - is.NoError(err) + require.NoError(t, err) is.Nil(client) }) @@ -204,7 +200,7 @@ func TestLoginToOCIRegistry(t *testing.T) { Authentication: false, } client, err := createOCIRegistryClient(registry) - is.NoError(err) + require.NoError(t, err) is.NotNil(client) // Now returns a client even without auth for potential TLS configuration }) @@ -223,9 +219,10 @@ func TestLoginToOCIRegistry(t *testing.T) { }, }, } + client, err := createOCIRegistryClient(registry) // Should succeed even without cert files when they're empty strings - is.NoError(err) + require.NoError(t, err) is.NotNil(client) // Should get a client configured for TLS }) @@ -235,8 +232,9 @@ func TestLoginToOCIRegistry(t *testing.T) { Authentication: true, Username: " ", } + client, err := createOCIRegistryClient(registry) - is.Error(err) + require.Error(t, err) is.Nil(client) // The error might be a validation error or a login error, both are acceptable is.True(err.Error() == "username is required when registry authentication is enabled" || @@ -254,7 +252,7 @@ func TestLoginToOCIRegistry(t *testing.T) { // this will fail because it can't connect to the registry, // but it proves that the loginToOCIRegistry function is calling the login function. client, err := createOCIRegistryClient(registry) - is.Error(err) + require.Error(t, err) is.Nil(client) is.Contains(err.Error(), "failed to login to registry") }) @@ -276,7 +274,7 @@ func TestLoginToOCIRegistry(t *testing.T) { // this will fail because it can't connect to the registry, // but it proves that the loginToOCIRegistry function is calling the login function. client, err := createOCIRegistryClient(registry) - is.Error(err) + require.Error(t, err) is.Nil(client) is.Contains(err.Error(), "failed to login to registry") }) @@ -287,7 +285,7 @@ func TestAuthenticateChartSource(t *testing.T) { is := assert.New(t) actionConfig := &action.Configuration{} err := authenticateChartSource(actionConfig, nil) - is.NoError(err) + require.NoError(t, err) is.Nil(actionConfig.RegistryClient) }) @@ -306,32 +304,32 @@ func TestAuthenticateChartSource(t *testing.T) { } err := authenticateChartSource(actionConfig, registry) - is.NoError(err) + require.NoError(t, err) is.Equal(existingClient, actionConfig.RegistryClient) }) t.Run("should authenticate OCI registry when registry is provided", func(t *testing.T) { - is := assert.New(t) actionConfig := &action.Configuration{} registry := &portainer.Registry{ ID: 123, Authentication: false, } + err := authenticateChartSource(actionConfig, registry) - is.NoError(err) + require.NoError(t, err) }) t.Run("should return error for invalid registry credentials", func(t *testing.T) { - is := assert.New(t) actionConfig := &action.Configuration{} registry := &portainer.Registry{ ID: 123, Authentication: true, Username: " ", // Invalid username } + err := authenticateChartSource(actionConfig, registry) - is.Error(err) - is.Contains(err.Error(), "registry credential validation failed") + require.Error(t, err) + require.Contains(t, err.Error(), "registry credential validation failed") }) } @@ -341,6 +339,7 @@ func TestGetRegistryClientFromCache(t *testing.T) { if err != nil { t.Fatalf("Failed to initialize cache: %v", err) } + // Clear cache before each test helmregistrycache.FlushAll() @@ -380,6 +379,7 @@ func TestSetRegistryClientInCache(t *testing.T) { if err != nil { t.Fatalf("Failed to initialize cache: %v", err) } + // Clear cache before each test helmregistrycache.FlushAll() @@ -433,6 +433,7 @@ func TestFlushRegistryCache(t *testing.T) { if err != nil { t.Fatalf("Failed to initialize cache: %v", err) } + // Clear cache before test helmregistrycache.FlushAll() @@ -643,12 +644,12 @@ func TestValidateRegistryCredentials(t *testing.T) { err := validateRegistryCredentials(tt.registry) if tt.expectError { - assert.Error(t, err) + require.Error(t, err) if err != nil { assert.Equal(t, tt.errorMsg, err.Error()) } } else { - assert.NoError(t, err) + require.NoError(t, err) } }) } diff --git a/pkg/libhelm/sdk/client_test.go b/pkg/libhelm/sdk/client_test.go index 88974bfea..298f6d3c3 100644 --- a/pkg/libhelm/sdk/client_test.go +++ b/pkg/libhelm/sdk/client_test.go @@ -6,13 +6,13 @@ import ( "github.com/portainer/portainer/pkg/libhelm/options" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "helm.sh/helm/v3/pkg/action" "k8s.io/client-go/tools/clientcmd" "k8s.io/client-go/tools/clientcmd/api" ) func Test_InitActionConfig(t *testing.T) { - is := assert.New(t) hspm := NewHelmSDKPackageManager() t.Run("with nil k8sAccess should use default kubeconfig", func(t *testing.T) { @@ -20,7 +20,7 @@ func Test_InitActionConfig(t *testing.T) { err := hspm.initActionConfig(actionConfig, "default", nil) // The function should not fail by design, even when not running in a k8s environment - is.NoError(err, "should not return error when not in k8s environment") + require.NoError(t, err, "should not return error when not in k8s environment") }) t.Run("with k8sAccess should create in-memory config", func(t *testing.T) { @@ -32,7 +32,7 @@ func Test_InitActionConfig(t *testing.T) { // The function should not fail by design err := hspm.initActionConfig(actionConfig, "default", k8sAccess) - is.NoError(err, "should not return error when using in-memory config") + require.NoError(t, err, "should not return error when using in-memory config") }) t.Run("with k8sAccess and CA file should create config with CA", func(t *testing.T) { @@ -45,7 +45,7 @@ func Test_InitActionConfig(t *testing.T) { // The function should not fail by design err := hspm.initActionConfig(actionConfig, "default", k8sAccess) - is.NoError(err, "should not return error when using in-memory config with CA") + require.NoError(t, err, "should not return error when using in-memory config with CA") }) } @@ -80,23 +80,23 @@ func Test_ClientConfigGetter(t *testing.T) { // Create client config getter clientGetter, err := newRESTClientGetter(clientConfig, "default") - is.NoError(err, "should not return error when creating client getter") + require.NoError(t, err, "should not return error when creating client getter") // Test ToRESTConfig restConfig, err := clientGetter.ToRESTConfig() - is.NoError(err, "should not return error when creating REST config") + require.NoError(t, err, "should not return error when creating REST config") is.NotNil(restConfig, "should return non-nil REST config") is.Equal("https://kubernetes.default.svc", restConfig.Host, "host should be https://kubernetes.default.svc") is.Equal("test-token", restConfig.BearerToken, "bearer token should be test-token") // Test ToDiscoveryClient discoveryClient, err := clientGetter.ToDiscoveryClient() - is.NoError(err, "should not return error when creating discovery client") + require.NoError(t, err, "should not return error when creating discovery client") is.NotNil(discoveryClient, "should return non-nil discovery client") // Test ToRESTMapper restMapper, err := clientGetter.ToRESTMapper() - is.NoError(err, "should not return error when creating REST mapper") + require.NoError(t, err, "should not return error when creating REST mapper") is.NotNil(restMapper, "should return non-nil REST mapper") // Test ToRawKubeConfigLoader @@ -119,18 +119,18 @@ resources: memory: 128Mi `) values, err := hspm.parseValues(yamlData) - is.NoError(err, "should parse valid YAML without error") + require.NoError(t, err, "should parse valid YAML without error") is.NotNil(values, "should return non-nil values") // Verify structure - service, ok := values["service"].(map[string]interface{}) + service, ok := values["service"].(map[string]any) is.True(ok, "service should be a map") is.Equal("ClusterIP", service["type"], "service type should be ClusterIP") - is.Equal(float64(80), service["port"], "service port should be 80") + is.Equal(80, int(service["port"].(float64)), "service port should be 80") - resources, ok := values["resources"].(map[string]interface{}) + resources, ok := values["resources"].(map[string]any) is.True(ok, "resources should be a map") - limits, ok := resources["limits"].(map[string]interface{}) + limits, ok := resources["limits"].(map[string]any) is.True(ok, "limits should be a map") is.Equal("100m", limits["cpu"], "cpu limit should be 100m") is.Equal("128Mi", limits["memory"], "memory limit should be 128Mi") @@ -144,14 +144,14 @@ service: invalid yaml `) _, err := hspm.parseValues(yamlData) - is.Error(err, "should return error for invalid YAML") + require.Error(t, err, "should return error for invalid YAML") }) t.Run("should handle empty YAML", func(t *testing.T) { yamlData := []byte(``) values, err := hspm.parseValues(yamlData) - is.NoError(err, "should not return error for empty YAML") + require.NoError(t, err, "should not return error for empty YAML") is.NotNil(values, "should return non-nil values for empty YAML") - is.Len(values, 0, "should return empty map for empty YAML") + is.Empty(values, "should return empty map for empty YAML") }) } diff --git a/pkg/libhelm/sdk/install_test.go b/pkg/libhelm/sdk/install_test.go index 5b24c5221..bad4a286d 100644 --- a/pkg/libhelm/sdk/install_test.go +++ b/pkg/libhelm/sdk/install_test.go @@ -30,7 +30,7 @@ func Test_Install(t *testing.T) { }) release, err := hspm.Upgrade(installOpts) - is.NoError(err, "should successfully install release") + require.NoError(t, err, "should successfully install release") is.NotNil(release, "should return non-nil release") defer hspm.Uninstall(options.UninstallOptions{ Name: installOpts.Name, @@ -44,7 +44,7 @@ func Test_Install(t *testing.T) { t.Run("successfully installs nginx with values", func(t *testing.T) { // SDK equivalent of: helm install test-nginx-2 --repo https://kubernetes.github.io/ingress-nginx nginx --values /tmp/helm-values3161785816 values, err := test.CreateValuesFile("service:\n port: 8081") - is.NoError(err, "should create a values file") + require.NoError(t, err, "should create a values file") defer os.Remove(values) installOpts := options.InstallOptions{ @@ -59,7 +59,7 @@ func Test_Install(t *testing.T) { }) release, err := hspm.Upgrade(installOpts) - is.NoError(err, "should successfully install release") + require.NoError(t, err, "should successfully install release") is.NotNil(release, "should return non-nil release") defer hspm.Uninstall(options.UninstallOptions{ Name: installOpts.Name, @@ -83,7 +83,7 @@ func Test_Install(t *testing.T) { }) release, err := hspm.Upgrade(installOpts) - is.NoError(err, "should successfully install release") + require.NoError(t, err, "should successfully install release") is.NotNil(release, "should return non-nil release") defer hspm.Uninstall(options.UninstallOptions{ Name: installOpts.Name, @@ -97,7 +97,7 @@ func Test_Install(t *testing.T) { t.Run("install with values as string", func(t *testing.T) { // First create a values file since InstallOptions doesn't support values as string directly values, err := test.CreateValuesFile("service:\n port: 8082") - is.NoError(err, "should create a values file") + require.NoError(t, err, "should create a values file") defer os.Remove(values) // Install with values file @@ -113,7 +113,7 @@ func Test_Install(t *testing.T) { }) release, err := hspm.Upgrade(installOpts) - is.NoError(err, "should successfully install release") + require.NoError(t, err, "should successfully install release") is.NotNil(release, "should return non-nil release") defer hspm.Uninstall(options.UninstallOptions{ Name: installOpts.Name, @@ -136,7 +136,7 @@ func Test_Install(t *testing.T) { }) release, err := hspm.Upgrade(installOpts) - is.NoError(err, "should successfully install release") + require.NoError(t, err, "should successfully install release") is.NotNil(release, "should return non-nil release") defer hspm.Uninstall(options.UninstallOptions{ Name: installOpts.Name, @@ -158,7 +158,7 @@ func Test_Install(t *testing.T) { _, err := hspm.Upgrade(installOpts) - is.Error(err, "should return an error when name is not provided") + require.Error(t, err, "should return an error when name is not provided") // is.Equal(err.Error(), "name is required for helm release installation") }) @@ -170,7 +170,7 @@ func Test_Install(t *testing.T) { Repo: "https://kubernetes.github.io/ingress-nginx", } _, err := hspm.Upgrade(installOpts) - is.Error(err, "should return error when chart doesn't exist") + require.Error(t, err, "should return error when chart doesn't exist") }) t.Run("install with invalid repo", func(t *testing.T) { @@ -186,6 +186,6 @@ func Test_Install(t *testing.T) { }) _, err := hspm.Upgrade(installOpts) - is.Error(err, "should return error when repo doesn't exist") + require.Error(t, err, "should return error when repo doesn't exist") }) } diff --git a/pkg/libhelm/sdk/resources_test.go b/pkg/libhelm/sdk/resources_test.go index 8bd3b8c21..0adb30bb3 100644 --- a/pkg/libhelm/sdk/resources_test.go +++ b/pkg/libhelm/sdk/resources_test.go @@ -4,6 +4,7 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/runtime" @@ -30,8 +31,8 @@ func TestParseResources(t *testing.T) { } got, err := parseResources(resourceTypesLists) - assert.NoError(t, err) - assert.Equal(t, 1, len(got)) + require.NoError(t, err) + assert.Len(t, got, 1) // Check resource metadata assert.Equal(t, "test-pod", got[0].GetName()) @@ -81,8 +82,8 @@ func TestParseResources(t *testing.T) { } got, err := parseResources(resourceTypesLists) - assert.NoError(t, err) - assert.Equal(t, 2, len(got)) + require.NoError(t, err) + assert.Len(t, got, 2) // Check first resource assert.Equal(t, "test-pod-1", got[0].GetName()) diff --git a/pkg/libhelm/sdk/rollback_test.go b/pkg/libhelm/sdk/rollback_test.go index 31932ffc7..c86009c0b 100644 --- a/pkg/libhelm/sdk/rollback_test.go +++ b/pkg/libhelm/sdk/rollback_test.go @@ -6,6 +6,7 @@ import ( "github.com/portainer/portainer/pkg/libhelm/options" "github.com/portainer/portainer/pkg/libhelm/test" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func TestRollback(t *testing.T) { @@ -22,7 +23,7 @@ func TestRollback(t *testing.T) { _, err := hspm.Rollback(rollbackOpts) - is.Error(err, "should return an error when name is not provided") + require.Error(t, err, "should return an error when name is not provided") is.Equal("name is required for helm release rollback", err.Error(), "should return correct error message") }) @@ -34,7 +35,7 @@ func TestRollback(t *testing.T) { _, err := hspm.Rollback(rollbackOpts) - is.Error(err, "should return an error when release doesn't exist") + require.Error(t, err, "should return an error when release doesn't exist") }) t.Run("should successfully rollback to previous revision", func(t *testing.T) { @@ -53,12 +54,12 @@ func TestRollback(t *testing.T) { // Install first version release, err := hspm.Upgrade(installOpts) - is.NoError(err, "should successfully install release") + require.NoError(t, err, "should successfully install release") is.Equal(1, release.Version, "first version should be 1") // Upgrade to second version _, err = hspm.Upgrade(installOpts) - is.NoError(err, "should successfully upgrade release") + require.NoError(t, err, "should successfully upgrade release") // Rollback to first version rollbackOpts := options.RollbackOptions{ @@ -72,7 +73,7 @@ func TestRollback(t *testing.T) { Name: installOpts.Name, }) - is.NoError(err, "should successfully rollback release") + require.NoError(t, err, "should successfully rollback release") is.NotNil(rolledBackRelease, "should return non-nil release") is.Equal(3, rolledBackRelease.Version, "version should be incremented to 3") }) @@ -93,16 +94,16 @@ func TestRollback(t *testing.T) { // Install first version release, err := hspm.Upgrade(installOpts) - is.NoError(err, "should successfully install release") + require.NoError(t, err, "should successfully install release") is.Equal(1, release.Version, "first version should be 1") // Upgrade to second version _, err = hspm.Upgrade(installOpts) - is.NoError(err, "should successfully upgrade release") + require.NoError(t, err, "should successfully upgrade release") // Upgrade to third version _, err = hspm.Upgrade(installOpts) - is.NoError(err, "should successfully upgrade release again") + require.NoError(t, err, "should successfully upgrade release again") // Rollback to first version rollbackOpts := options.RollbackOptions{ @@ -116,7 +117,7 @@ func TestRollback(t *testing.T) { Name: installOpts.Name, }) - is.NoError(err, "should successfully rollback to specific revision") + require.NoError(t, err, "should successfully rollback to specific revision") is.NotNil(rolledBackRelease, "should return non-nil release") is.Equal(4, rolledBackRelease.Version, "version should be incremented to 4") }) diff --git a/pkg/libhelm/sdk/search_repo_test.go b/pkg/libhelm/sdk/search_repo_test.go index bb30b8468..9afa22c00 100644 --- a/pkg/libhelm/sdk/search_repo_test.go +++ b/pkg/libhelm/sdk/search_repo_test.go @@ -5,7 +5,9 @@ import ( "testing" "github.com/portainer/portainer/pkg/libhelm/options" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) type testCase struct { @@ -33,9 +35,9 @@ func Test_SearchRepo(t *testing.T) { t.Parallel() response, err := hspm.SearchRepo(options.SearchRepoOptions{Repo: tc.url}) if tc.invalid { - is.Errorf(err, "error expected: %s", tc.url) + require.Error(t, err, "error expected: %s", tc.url) } else { - is.NoError(err, "no error expected: %s", tc.url) + require.NoError(t, err, "no error expected: %s", tc.url) } if err == nil { @@ -53,14 +55,14 @@ func Test_SearchRepo(t *testing.T) { responseBytes, err := hspm.SearchRepo(searchOpts) // The function should not fail by design, even when not running in a k8s environment - is.NoError(err, "should not return error when not in k8s environment") + require.NoError(t, err, "should not return error when not in k8s environment") is.NotNil(responseBytes, "should return non-nil response") is.NotEmpty(responseBytes, "should return non-empty response") // Parse the ext response var repoIndex RepoIndex err = json.Unmarshal(responseBytes, &repoIndex) - is.NoError(err, "should parse JSON response without error") + require.NoError(t, err, "should parse JSON response without error") is.NotEmpty(repoIndex, "should have at least one chart") // Verify charts structure apiVersion, entries, generated @@ -69,7 +71,7 @@ func Test_SearchRepo(t *testing.T) { is.NotEmpty(repoIndex.Generated, "generated should not be empty") // there should be at least one chart - is.Greater(len(repoIndex.Entries), 0, "should have at least one chart") + is.NotEmpty(repoIndex.Entries, "should have at least one chart") }) t.Run("search repo with empty repo URL", func(t *testing.T) { @@ -78,6 +80,6 @@ func Test_SearchRepo(t *testing.T) { Repo: "", } _, err := hspm.SearchRepo(searchOpts) - is.Error(err, "should return error when repo URL is empty") + require.Error(t, err, "should return error when repo URL is empty") }) } diff --git a/pkg/libhelm/sdk/show_test.go b/pkg/libhelm/sdk/show_test.go index 26801eb93..306d3b7c6 100644 --- a/pkg/libhelm/sdk/show_test.go +++ b/pkg/libhelm/sdk/show_test.go @@ -6,6 +6,7 @@ import ( "github.com/portainer/portainer/pkg/libhelm/options" "github.com/portainer/portainer/pkg/libhelm/test" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func Test_Show(t *testing.T) { @@ -35,7 +36,7 @@ func Test_Show(t *testing.T) { OutputFormat: "", } _, err := hspm.Show(showOpts) - is.Error(err, "should return error when required options are missing") + require.Error(t, err, "should return error when required options are missing") is.Contains(err.Error(), "chart, output format and either repo or registry are required", "error message should indicate required options") }) @@ -47,7 +48,7 @@ func Test_Show(t *testing.T) { } values, err := hspm.Show(showOpts) - is.NoError(err, "should not return error when not in k8s environment") + require.NoError(t, err, "should not return error when not in k8s environment") is.NotEmpty(values, "should return non-empty values") }) @@ -59,7 +60,7 @@ func Test_Show(t *testing.T) { } readme, err := hspm.Show(showOpts) - is.NoError(err, "should not return error when not in k8s environment") + require.NoError(t, err, "should not return error when not in k8s environment") is.NotEmpty(readme, "should return non-empty readme") }) @@ -71,7 +72,7 @@ func Test_Show(t *testing.T) { } chart, err := hspm.Show(showOpts) - is.NoError(err, "should not return error when not in k8s environment") + require.NoError(t, err, "should not return error when not in k8s environment") is.NotNil(chart, "should return non-nil chart definition") }) @@ -83,7 +84,7 @@ func Test_Show(t *testing.T) { } info, err := hspm.Show(showOpts) - is.NoError(err, "should not return error when not in k8s environment") + require.NoError(t, err, "should not return error when not in k8s environment") is.NotEmpty(info, "should return non-empty chart info") }) @@ -96,7 +97,7 @@ func Test_Show(t *testing.T) { } _, err := hspm.Show(showOpts) - is.Error(err, "should return error with invalid output format") + require.Error(t, err, "should return error with invalid output format") is.Contains(err.Error(), "unsupported output format", "error message should indicate invalid output format") }) } diff --git a/pkg/libhelm/sdk/uninstall_test.go b/pkg/libhelm/sdk/uninstall_test.go index 684be1780..85251cfde 100644 --- a/pkg/libhelm/sdk/uninstall_test.go +++ b/pkg/libhelm/sdk/uninstall_test.go @@ -6,6 +6,7 @@ import ( "github.com/portainer/portainer/pkg/libhelm/options" "github.com/portainer/portainer/pkg/libhelm/test" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func Test_Uninstall(t *testing.T) { @@ -21,7 +22,7 @@ func Test_Uninstall(t *testing.T) { Name: "", } err := hspm.Uninstall(uninstallOpts) - is.Error(err, "should return error when release name is empty") + require.Error(t, err, "should return error when release name is empty") is.Contains(err.Error(), "release name is required", "error message should indicate release name is required") }) @@ -34,7 +35,7 @@ func Test_Uninstall(t *testing.T) { // The function should not fail by design, even when not running in a k8s environment // However, it should return an error for a non-existent release - is.Error(err, "should return error when release doesn't exist") + require.Error(t, err, "should return error when release doesn't exist") is.Contains(err.Error(), "not found", "error message should indicate release not found") }) @@ -60,6 +61,6 @@ func Test_Uninstall(t *testing.T) { Name: "test-uninstall", } err = hspm.Uninstall(uninstallOpts) - is.NoError(err, "should successfully uninstall release") + require.NoError(t, err, "should successfully uninstall release") }) } diff --git a/pkg/libhelm/sdk/upgrade_test.go b/pkg/libhelm/sdk/upgrade_test.go index bd1d48616..f708abcb8 100644 --- a/pkg/libhelm/sdk/upgrade_test.go +++ b/pkg/libhelm/sdk/upgrade_test.go @@ -31,7 +31,7 @@ func TestUpgrade(t *testing.T) { }) release, err := hspm.Upgrade(upgradeOpts) - is.NoError(err, "should successfully install release via upgrade") + require.NoError(t, err, "should successfully install release via upgrade") is.NotNil(release, "should return non-nil release") defer hspm.Uninstall(options.UninstallOptions{ Name: upgradeOpts.Name, @@ -62,7 +62,7 @@ func TestUpgrade(t *testing.T) { }) release, err := hspm.Upgrade(installOpts) - is.NoError(err, "should successfully install release") + require.NoError(t, err, "should successfully install release") is.NotNil(release, "should return non-nil release") defer hspm.Uninstall(options.UninstallOptions{ Name: installOpts.Name, @@ -71,7 +71,7 @@ func TestUpgrade(t *testing.T) { // Upgrade the release with the same options upgradedRelease, err := hspm.Upgrade(installOpts) - is.NoError(err, "should successfully upgrade release") + require.NoError(t, err, "should successfully upgrade release") is.NotNil(upgradedRelease, "should return non-nil release") is.Equal("test-upgrade-nginx", upgradedRelease.Name, "release name should match") is.Equal(2, upgradedRelease.Version, "release version should be incremented to 2") @@ -93,7 +93,7 @@ func TestUpgrade(t *testing.T) { }) release, err := hspm.Upgrade(installOpts) // Cleanup - is.NoError(err, "should successfully install release") + require.NoError(t, err, "should successfully install release") is.NotNil(release, "should return non-nil release") defer hspm.Uninstall(options.UninstallOptions{ Name: installOpts.Name, @@ -101,7 +101,7 @@ func TestUpgrade(t *testing.T) { // Create values file values, err := test.CreateValuesFile("service:\n port: 8083") - is.NoError(err, "should create a values file") + require.NoError(t, err, "should create a values file") defer os.Remove(values) // Now upgrade with values @@ -115,7 +115,7 @@ func TestUpgrade(t *testing.T) { upgradedRelease, err := hspm.Upgrade(upgradeOpts) - is.NoError(err, "should successfully upgrade release with values") + require.NoError(t, err, "should successfully upgrade release with values") is.NotNil(upgradedRelease, "should return non-nil release") is.Equal("test-values-nginx", upgradedRelease.Name, "release name should match") is.Equal(2, upgradedRelease.Version, "release version should be incremented to 2") @@ -137,7 +137,7 @@ func TestUpgrade(t *testing.T) { }) release, err := hspm.Upgrade(installOpts) - is.NoError(err, "should successfully install release") + require.NoError(t, err, "should successfully install release") is.NotNil(release, "should return non-nil release") defer hspm.Uninstall(options.UninstallOptions{ Name: installOpts.Name, @@ -145,7 +145,7 @@ func TestUpgrade(t *testing.T) { // Create invalid values file values, err := test.CreateValuesFile("this is not valid yaml") - is.NoError(err, "should create a values file") + require.NoError(t, err, "should create a values file") defer os.Remove(values) // Now upgrade with invalid values @@ -159,7 +159,7 @@ func TestUpgrade(t *testing.T) { _, err = hspm.Upgrade(upgradeOpts) - is.Error(err, "should return error with invalid values") + require.Error(t, err, "should return error with invalid values") }) t.Run("should return error when name is not provided", func(t *testing.T) { @@ -171,7 +171,7 @@ func TestUpgrade(t *testing.T) { _, err := hspm.Upgrade(upgradeOpts) - is.Error(err, "should return an error when name is not provided") + require.Error(t, err, "should return an error when name is not provided") is.Equal("name is required for helm release upgrade", err.Error(), "should return correct error message") }) } diff --git a/pkg/libhelm/validate_repo_test.go b/pkg/libhelm/validate_repo_test.go index 5b9f6cd09..414400a91 100644 --- a/pkg/libhelm/validate_repo_test.go +++ b/pkg/libhelm/validate_repo_test.go @@ -6,13 +6,11 @@ import ( "testing" "github.com/portainer/portainer/pkg/libhelm/test" - "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) func Test_ValidateHelmRepositoryURL(t *testing.T) { test.EnsureIntegrationTest(t) - is := assert.New(t) type testCase struct { name string @@ -44,9 +42,9 @@ func Test_ValidateHelmRepositoryURL(t *testing.T) { t.Parallel() err := ValidateHelmRepositoryURL(tc.url, nil) if tc.invalid { - is.Errorf(err, "error expected: %s", tc.url) + require.Error(t, err, "error expected: %s", tc.url) } else { - is.NoError(err, "no error expected: %s", tc.url) + require.NoError(t, err, "no error expected: %s", tc.url) } }) }(test) diff --git a/pkg/libhttp/response/response_test.go b/pkg/libhttp/response/response_test.go index e79aa09c2..a501c9d5b 100644 --- a/pkg/libhttp/response/response_test.go +++ b/pkg/libhttp/response/response_test.go @@ -7,6 +7,7 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func TestJSONWithStatus(t *testing.T) { @@ -44,7 +45,7 @@ func TestJSONWithStatus(t *testing.T) { var response TestData err := json.Unmarshal(recorder.Body.Bytes(), &response) - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, test.data, response) }) } @@ -79,7 +80,7 @@ func TestJSON(t *testing.T) { var response TestData err := json.Unmarshal(recorder.Body.Bytes(), &response) - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, test.data, response) }) } diff --git a/pkg/liboras/registry_test.go b/pkg/liboras/registry_test.go index e9b9f8b7c..8fe502dec 100644 --- a/pkg/liboras/registry_test.go +++ b/pkg/liboras/registry_test.go @@ -4,7 +4,9 @@ import ( "testing" portainer "github.com/portainer/portainer/api" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "oras.land/oras-go/v2/registry/remote/auth" "oras.land/oras-go/v2/registry/remote/retry" ) @@ -127,7 +129,7 @@ func TestCreateClient_AuthenticationScenarios(t *testing.T) { t.Run(tt.name, func(t *testing.T) { client, err := CreateClient(tt.registry) - assert.NoError(t, err, "CreateClient should not return an error") + require.NoError(t, err, "CreateClient should not return an error") assert.NotNil(t, client, "Client should not be nil") // Check if the client has authentication configured @@ -178,7 +180,7 @@ func TestCreateClient_RegistryTypes(t *testing.T) { client, err := CreateClient(registry) - assert.NoError(t, err, "CreateClient should not return an error") + require.NoError(t, err, "CreateClient should not return an error") assert.NotNil(t, client, "Client should not be nil") // Verify that getRegistryTypeName returns the expected name @@ -248,10 +250,10 @@ func TestCreateClient_ErrorHandling(t *testing.T) { client, err := CreateClient(tt.registry) if tt.expectError { - assert.Error(t, err, "Expected an error but got none") + require.Error(t, err, "Expected an error but got none") assert.Nil(t, client, "Client should be nil when error occurs") } else { - assert.NoError(t, err, "Expected no error but got: %v", err) + require.NoError(t, err, "Expected no error but got: %v", err) assert.NotNil(t, client, "Client should not be nil") } }) diff --git a/pkg/libstack/compose/composeplugin_test.go b/pkg/libstack/compose/composeplugin_test.go index 6f5ed0948..6668ec1e6 100644 --- a/pkg/libstack/compose/composeplugin_test.go +++ b/pkg/libstack/compose/composeplugin_test.go @@ -564,7 +564,7 @@ func Test_DeployWithIgnoreOrphans(t *testing.T) { require.Equal(t, libstack.StatusCompleted, waitResult.Status) logString := logOutput.String() - require.False(t, strings.Contains(logString, "Found orphan containers ([compose_ignore_orphans_test-service-1-1])")) + require.NotContains(t, logString, "Found orphan containers ([compose_ignore_orphans_test-service-1-1])") } func Test_MaxConcurrency(t *testing.T) { @@ -597,7 +597,7 @@ func Test_MaxConcurrency(t *testing.T) { w.withComposeService(ctx, filepaths, options, func(service api.Service, _ *types.Project) error { if mockS, ok := service.(*mockComposeService); ok { - require.Equal(t, mockS.maxConcurrency, expectedMaxConcurrency) + require.Equal(t, expectedMaxConcurrency, mockS.maxConcurrency) } else { t.Fatalf("Expected mockComposeService but got %T", service) } diff --git a/pkg/registryhttp/client_test.go b/pkg/registryhttp/client_test.go index bf1fa53a1..41cfe6f60 100644 --- a/pkg/registryhttp/client_test.go +++ b/pkg/registryhttp/client_test.go @@ -7,6 +7,7 @@ import ( portainer "github.com/portainer/portainer/api" "github.com/portainer/portainer/pkg/fips" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "oras.land/oras-go/v2/registry/remote/retry" ) @@ -88,12 +89,12 @@ func TestCreateClient(t *testing.T) { client, usePlainHTTP, err := CreateClient(tt.registry) if tt.expectError { - assert.Error(t, err) + require.Error(t, err) assert.Nil(t, client) return } - assert.NoError(t, err) + require.NoError(t, err) assert.NotNil(t, client) assert.Equal(t, tt.expectedUsePlainHTTP, usePlainHTTP) @@ -137,7 +138,7 @@ func TestCreateClient_CloudRegistries(t *testing.T) { client, usePlainHTTP, err := CreateClient(registry) - assert.NoError(t, err) + require.NoError(t, err) assert.NotNil(t, client) assert.False(t, usePlainHTTP, "Cloud registries should use HTTPS") assert.Equal(t, retry.DefaultClient, client, "Cloud registries should use default retry client") @@ -160,7 +161,7 @@ func TestCreateClient_CustomTLSConfiguration(t *testing.T) { client, usePlainHTTP, err := CreateClient(registry) - assert.NoError(t, err) + require.NoError(t, err) assert.NotNil(t, client) assert.False(t, usePlainHTTP, "TLS enabled registries should use HTTPS") assert.NotEqual(t, retry.DefaultClient, client, "Custom TLS should create new client") @@ -180,7 +181,7 @@ func TestCreateClient_CustomTLSConfiguration(t *testing.T) { client, usePlainHTTP, err := CreateClient(registry) - assert.NoError(t, err) + require.NoError(t, err) assert.NotNil(t, client) assert.True(t, usePlainHTTP, "TLS disabled should use plain HTTP") assert.Equal(t, retry.DefaultClient, client, "No TLS should use default client") @@ -195,7 +196,7 @@ func TestCreateClient_CustomTLSConfiguration(t *testing.T) { client, usePlainHTTP, err := CreateClient(registry) - assert.NoError(t, err) + require.NoError(t, err) assert.NotNil(t, client) assert.True(t, usePlainHTTP, "No management config should use plain HTTP") assert.Equal(t, retry.DefaultClient, client, "No management config should use default client") diff --git a/pkg/snapshot/kubernetes_test.go b/pkg/snapshot/kubernetes_test.go index 83d51230b..6cd39169e 100644 --- a/pkg/snapshot/kubernetes_test.go +++ b/pkg/snapshot/kubernetes_test.go @@ -267,7 +267,7 @@ func TestCalculateNodeMetrics(t *testing.T) { metrics := calculateNodeMetrics(nodeStats, node) require.NotNil(t, metrics) - require.Equal(t, float64(50), metrics.CPUUsage) // 2/4 = 50% + require.Equal(t, 50, int(metrics.CPUUsage)) // 2/4 = 50% }) t.Run("CalculatesCorrectMemoryPercentage", func(t *testing.T) { @@ -280,7 +280,7 @@ func TestCalculateNodeMetrics(t *testing.T) { metrics := calculateNodeMetrics(nodeStats, node) require.NotNil(t, metrics) - require.Equal(t, float64(50), metrics.MemoryUsage) // 4GB/8GB = 50% + require.Equal(t, 50, int(metrics.MemoryUsage)) // 4GB/8GB = 50% }) t.Run("CalculatesCorrectNetworkUsage", func(t *testing.T) { @@ -297,7 +297,7 @@ func TestCalculateNodeMetrics(t *testing.T) { metrics := calculateNodeMetrics(nodeStats, node) require.NotNil(t, metrics) - require.Equal(t, float64(2048), metrics.NetworkUsage) // 2GB = 2048MB + require.Equal(t, 2048, int(metrics.NetworkUsage)) // 2GB = 2048MB }) t.Run("HandlesEmptyStats", func(t *testing.T) { @@ -317,8 +317,8 @@ func TestCalculateNodeMetrics(t *testing.T) { metrics := calculateNodeMetrics(nodeStats, node) require.NotNil(t, metrics) - require.Equal(t, float64(25), metrics.CPUUsage) // 1/4 = 25% - require.Equal(t, float64(0), metrics.MemoryUsage) - require.Equal(t, float64(0), metrics.NetworkUsage) + require.Equal(t, 25, int(metrics.CPUUsage)) // 1/4 = 25% + require.Equal(t, 0, int(metrics.MemoryUsage)) + require.Equal(t, 0, int(metrics.NetworkUsage)) }) }