Merge pull request #32294 from mmorel-35/testifylint

chore: fix several checks issues from testifylint
pull/32172/merge
Terry Howe 1 day ago committed by GitHub
commit 50fb6ff85b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -139,16 +139,6 @@ linters:
- models
testifylint:
disable:
- encoded-compare
- equal-values
- expected-actual
- float-compare
- go-require
- nil-compare
- require-error
- suite-dont-use-pkg
- suite-extra-assert-call
# Intentionally enable all testifylint rules so new checks are adopted automatically.
enable-all: true

@ -22,6 +22,7 @@ import (
"time"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"helm.sh/helm/v4/internal/chart/v3/lint/support"
chartutil "helm.sh/helm/v4/internal/chart/v3/util"
@ -126,7 +127,7 @@ func TestBadCrdFileV3(t *testing.T) {
var values map[string]any
m := RunAll(badCrdFileDir, values, namespace).Messages
assert.Lenf(t, m, 2, "All didn't fail with expected errors, got %#v", m)
assert.ErrorContains(t, m[0].Err, "apiVersion is not in 'apiextensions.k8s.io'")
require.ErrorContains(t, m[0].Err, "apiVersion is not in 'apiextensions.k8s.io'")
assert.ErrorContains(t, m[1].Err, "object kind is not 'CustomResourceDefinition'")
}

@ -92,11 +92,7 @@ func TestValidateValuesFileSchemaFailure(t *testing.T) {
valfile := filepath.Join(tmpdir, "values.yaml")
err := validateValuesFile(valfile, map[string]any{}, false)
if err == nil {
t.Fatal("expected values file to fail parsing")
}
assert.Contains(t, err.Error(), "- at '/username': got number, want string")
assert.ErrorContains(t, err, "- at '/username': got number, want string")
}
func TestValidateValuesFileSchemaFailureButWithSkipSchemaValidation(t *testing.T) {
@ -167,7 +163,7 @@ func TestValidateValuesFile(t *testing.T) {
case err == nil && tt.errorMessage != "":
t.Error("expected values file to fail parsing")
case err != nil && tt.errorMessage != "":
assert.Contains(t, err.Error(), tt.errorMessage, "Failed with unexpected error")
assert.ErrorContains(t, err, tt.errorMessage, "Failed with unexpected error")
}
})
}

@ -38,7 +38,7 @@ func TestAtomicWriteFile(t *testing.T) {
mode := os.FileMode(0o644)
err := AtomicWriteFile(testpath, reader, mode)
assert.NoError(t, err)
require.NoError(t, err)
got, err := os.ReadFile(testpath)
require.NoError(t, err)
@ -71,7 +71,7 @@ func TestAtomicWriteFile_EmptyContent(t *testing.T) {
mode := os.FileMode(0o644)
err := AtomicWriteFile(testpath, reader, mode)
assert.NoError(t, err, "AtomicWriteFile error with empty content")
require.NoError(t, err, "AtomicWriteFile error with empty content")
got, err := os.ReadFile(testpath)
require.NoError(t, err)
@ -90,7 +90,7 @@ func TestAtomicWriteFile_LargeContent(t *testing.T) {
mode := os.FileMode(0o644)
err := AtomicWriteFile(testpath, reader, mode)
assert.NoError(t, err, "AtomicWriteFile error with large content")
require.NoError(t, err, "AtomicWriteFile error with large content")
got, err := os.ReadFile(testpath)
require.NoError(t, err)

@ -24,6 +24,7 @@ import (
"time"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestLogHolder_Logger(t *testing.T) {
@ -198,7 +199,7 @@ func TestDebugCheckHandler_Handle(t *testing.T) {
record := slog.NewRecord(time.Now(), slog.LevelInfo, "test message", 0)
err := handler.Handle(t.Context(), record)
assert.NoError(t, err)
require.NoError(t, err)
assert.Contains(t, buf.String(), "test message")
})
@ -215,7 +216,7 @@ func TestDebugCheckHandler_Handle(t *testing.T) {
record := slog.NewRecord(time.Now(), slog.LevelInfo, "context test", 0)
err := handler.Handle(ctx, record)
assert.NoError(t, err)
require.NoError(t, err)
assert.Contains(t, buf.String(), "context test")
})
}

@ -49,8 +49,7 @@ func TestUnmarshaConfig(t *testing.T) {
config, err := unmarshalConfig("cli/v1", map[string]any{
"invalid field": "foo",
})
require.Error(t, err)
assert.Contains(t, err.Error(), "field not found")
require.ErrorContains(t, err, "field not found")
assert.Nil(t, config)
}
}

@ -118,7 +118,7 @@ func TestLoadDir(t *testing.T) {
require.NoError(t, err, "error loading plugin from %s", tc.dirname)
assert.Equal(t, tc.dirname, plug.Dir())
assert.EqualValues(t, tc.expect, plug.Metadata())
assert.Equal(t, tc.expect, plug.Metadata())
})
}
}
@ -295,8 +295,7 @@ command: echo test`,
m, err := loadMetadataLegacy([]byte(tc.yaml))
if tc.expectError {
require.Error(t, err)
assert.Contains(t, err.Error(), tc.errorContains)
require.ErrorContains(t, err, tc.errorContains)
t.Logf("Legacy error (validation catches empty name): %v", err)
if tc.logNote != "" {
t.Log(tc.logNote)
@ -342,8 +341,7 @@ runtime: subprocess
m, err := loadMetadataV1([]byte(tc.yaml))
if tc.expectError {
require.Error(t, err)
assert.Contains(t, err.Error(), tc.errorContains)
require.ErrorContains(t, err, tc.errorContains)
t.Logf("V1 error (strict unmarshalling): %v", err)
} else {
require.NoError(t, err)

@ -78,8 +78,7 @@ func TestMetadataV1ValidateVersion(t *testing.T) {
m := base()
m.Version = tc.version
err := m.Validate()
assert.Error(t, err)
assert.Contains(t, err.Error(), tc.errMsg)
assert.ErrorContains(t, err, tc.errMsg)
})
}
}

@ -71,7 +71,7 @@ func TestRuntimeExtismV1InvokePlugin(t *testing.T) {
p, err := r.CreatePlugin(pr.Dir, &pr.Metadata)
assert.NoError(t, err, "expected no error creating plugin")
require.NoError(t, err, "expected no error creating plugin")
assert.NotNil(t, p, "expected plugin to be created")
output, err := p.Invoke(t.Context(), &Input{

@ -23,6 +23,7 @@ import (
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
batchv1 "k8s.io/api/batch/v1"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@ -107,9 +108,9 @@ func TestJobConditions(t *testing.T) {
t.Run(tc.name, func(t *testing.T) {
t.Parallel()
us, err := toUnstructured(t, tc.job)
assert.NoError(t, err)
require.NoError(t, err)
result, err := jobConditions(us)
assert.NoError(t, err)
require.NoError(t, err)
assert.Equal(t, tc.expectedStatus, result.Status)
})
}

@ -20,6 +20,7 @@ import (
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
v1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@ -102,9 +103,9 @@ func TestPodConditions(t *testing.T) {
t.Run(tc.name, func(t *testing.T) {
t.Parallel()
us, err := toUnstructured(t, tc.pod)
assert.NoError(t, err)
require.NoError(t, err)
result, err := podConditions(us)
assert.NoError(t, err)
require.NoError(t, err)
assert.Equal(t, tc.expectedStatus, result.Status)
})
}

@ -20,7 +20,6 @@ import (
"path/filepath"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
@ -51,7 +50,7 @@ func TestNewTLSConfig(t *testing.T) {
WithCertKeyPairFiles(certFile, keyFile),
WithCAFile(caCertFile),
)
assert.NoError(t, err)
require.NoError(t, err)
require.Len(t, cfg.Certificates, 1)
require.False(t, cfg.InsecureSkipVerify, "insecure skip verify mismatch, expecting false")
@ -62,7 +61,7 @@ func TestNewTLSConfig(t *testing.T) {
WithInsecureSkipVerify(insecureSkipTLSVerify),
WithCAFile(caCertFile),
)
assert.NoError(t, err)
require.NoError(t, err)
require.Empty(t, cfg.Certificates)
require.False(t, cfg.InsecureSkipVerify, "insecure skip verify mismatch, expecting false")
@ -74,7 +73,7 @@ func TestNewTLSConfig(t *testing.T) {
WithInsecureSkipVerify(insecureSkipTLSVerify),
WithCertKeyPairFiles(certFile, keyFile),
)
assert.NoError(t, err)
require.NoError(t, err)
require.Len(t, cfg.Certificates, 1)
require.False(t, cfg.InsecureSkipVerify, "insecure skip verify mismatch, expecting false")

@ -20,6 +20,7 @@ import (
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestURLJoin(t *testing.T) {
@ -36,7 +37,7 @@ func TestURLJoin(t *testing.T) {
for _, tt := range tests {
got, err := URLJoin(tt.url, tt.paths...)
assert.NoError(t, err, tt.name)
require.NoError(t, err, tt.name)
assert.Equal(t, tt.expect, got, tt.name)
}
}

@ -358,10 +358,9 @@ func TestConfiguration_Init(t *testing.T) {
actualErr := cfg.Init(nil, "default", tt.helmDriver)
if tt.expectErr {
assert.Error(t, actualErr)
assert.Contains(t, actualErr.Error(), tt.errMsg)
require.ErrorContains(t, actualErr, tt.errMsg)
} else {
assert.NoError(t, actualErr)
require.NoError(t, actualErr)
assert.IsType(t, tt.expectedDriverType, cfg.Releases.Driver)
}
})
@ -1575,10 +1574,9 @@ data:
merged, err := annotateAndMerge(tt.files)
if tt.expectedError != "" {
assert.Error(t, err)
assert.Contains(t, err.Error(), tt.expectedError)
assert.ErrorContains(t, err, tt.expectedError)
} else {
assert.NoError(t, err)
require.NoError(t, err)
assert.NotNil(t, merged)
assert.Equal(t, tt.expected, merged)
}
@ -1738,10 +1736,9 @@ data:
files, err := splitAndDeannotate(tt.input, "test")
if tt.expectedError != "" {
assert.Error(t, err)
assert.Contains(t, err.Error(), tt.expectedError)
require.ErrorContains(t, err, tt.expectedError)
} else {
assert.NoError(t, err)
require.NoError(t, err)
assert.Len(t, files, len(tt.expectedFiles))
for expectedFile, expectedContent := range tt.expectedFiles {
@ -1827,7 +1824,7 @@ func TestRenderResources_PostRenderer_Success(t *testing.T) {
mockPR, false, false, false, PostRenderStrategyCombined,
)
assert.NoError(t, err)
require.NoError(t, err)
assert.NotNil(t, hooks)
assert.NotNil(t, buf)
assert.Empty(t, notes)
@ -1874,8 +1871,7 @@ func TestRenderResources_PostRenderer_Error(t *testing.T) {
mockPR, false, false, false, PostRenderStrategyCombined,
)
assert.Error(t, err)
assert.Contains(t, err.Error(), "error while running post render on files")
assert.ErrorContains(t, err, "error while running post render on files")
}
func TestRenderResources_PostRenderer_MergeError(t *testing.T) {
@ -1902,8 +1898,8 @@ func TestRenderResources_PostRenderer_MergeError(t *testing.T) {
mockPR, false, false, false, PostRenderStrategyCombined,
)
assert.Error(t, err)
assert.Contains(t, err.Error(), "error merging manifests")
require.Error(t, err)
assert.ErrorContains(t, err, "error merging manifests")
}
func TestRenderResources_PostRenderer_SplitError(t *testing.T) {
@ -1924,8 +1920,7 @@ func TestRenderResources_PostRenderer_SplitError(t *testing.T) {
mockPR, false, false, false, PostRenderStrategyCombined,
)
assert.Error(t, err)
assert.Contains(t, err.Error(), "error while parsing post rendered output: error parsing YAML: MalformedYAMLError:")
assert.ErrorContains(t, err, "error while parsing post rendered output: error parsing YAML: MalformedYAMLError:")
}
func TestRenderResources_PostRenderer_Integration(t *testing.T) {
@ -1945,7 +1940,7 @@ func TestRenderResources_PostRenderer_Integration(t *testing.T) {
mockPR, false, false, false, PostRenderStrategyCombined,
)
assert.NoError(t, err)
require.NoError(t, err)
assert.NotNil(t, hooks)
assert.NotNil(t, buf)
assert.Empty(t, notes) // Notes should be empty for this test
@ -1984,7 +1979,7 @@ func TestRenderResources_NoPostRenderer(t *testing.T) {
nil, false, false, false, PostRenderStrategyCombined,
)
assert.NoError(t, err)
require.NoError(t, err)
assert.NotNil(t, hooks)
assert.NotNil(t, buf)
assert.Empty(t, notes)
@ -2045,7 +2040,7 @@ spec:
mockPR, false, false, false, PostRenderStrategySeparate,
)
assert.NoError(t, err)
require.NoError(t, err)
assert.Len(t, hooks, 1)
assert.Equal(t, "my-app", hooks[0].Name)
assert.Contains(t, buf.String(), "kind: Deployment")
@ -2087,7 +2082,7 @@ metadata:
mockPR, false, false, false, PostRenderStrategyCombined,
)
assert.NoError(t, err)
require.NoError(t, err)
assert.Equal(t, 1, calls, "combined strategy should invoke the post-renderer exactly once")
assert.Contains(t, lastInput, "hook-cm")
assert.Contains(t, lastInput, "template-cm")
@ -2123,7 +2118,7 @@ metadata:
mockPR, false, false, false, PostRenderStrategy(""),
)
assert.NoError(t, err)
require.NoError(t, err)
assert.Equal(t, 1, calls, "unset strategy must preserve backwards-compatible combined behavior")
}
@ -2157,7 +2152,7 @@ metadata:
mockPR, false, false, false, PostRenderStrategySeparate,
)
assert.NoError(t, err)
require.NoError(t, err)
assert.Len(t, inputs, 2, "separate strategy should invoke the post-renderer twice when both hooks and templates exist")
for _, in := range inputs {
hasHook := strings.Contains(in, "hook-cm")
@ -2191,7 +2186,7 @@ metadata:
mockPR, false, false, false, PostRenderStrategySeparate,
)
assert.NoError(t, err)
require.NoError(t, err)
assert.Equal(t, 1, calls, "separate strategy should skip the empty hook group and invoke the post-renderer only once")
}
@ -2225,7 +2220,7 @@ metadata:
mockPR, false, false, false, PostRenderStrategyNoHooks,
)
assert.NoError(t, err)
require.NoError(t, err)
assert.Len(t, inputs, 1, "nohooks strategy should invoke the post-renderer exactly once (for templates only)")
assert.NotContains(t, inputs[0], "hook-cm", "hooks must not be sent to the post-renderer")
assert.Contains(t, inputs[0], "template-cm", "templates must be sent to the post-renderer")
@ -2262,7 +2257,7 @@ metadata:
mockPR, false, false, false, PostRenderStrategyNoHooks,
)
assert.NoError(t, err)
require.NoError(t, err)
assert.Equal(t, 0, calls, "nohooks strategy should not invoke the post-renderer when the chart only has hooks")
}
@ -2284,9 +2279,8 @@ metadata:
mockPR, false, false, false, PostRenderStrategy("bogus"),
)
assert.Error(t, err)
assert.Contains(t, err.Error(), "unknown post-render strategy")
assert.Contains(t, err.Error(), "bogus")
require.ErrorContains(t, err, "unknown post-render strategy")
assert.ErrorContains(t, err, "bogus")
}
func TestDetermineReleaseSSAApplyMethod(t *testing.T) {

@ -23,6 +23,7 @@ import (
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"helm.sh/helm/v4/internal/test"
chart "helm.sh/helm/v4/pkg/chart/v2"
@ -118,13 +119,14 @@ func TestStatArchiveForStatus(t *testing.T) {
}
is := assert.New(t)
req := require.New(t)
lilithpath := filepath.Join(chartpath, "lilith-1.2.3.tgz")
is.Empty(statArchiveForStatus(lilithpath, dep))
// save the chart (version 0.1.0, because that is the default)
where, err := chartutil.Save(lilith, chartpath)
is.NoError(err)
req.NoError(err)
// Should get "wrong version" because we asked for 1.2.3 and got 0.1.0
is.Equal("wrong version", statArchiveForStatus(where, dep))

@ -443,8 +443,7 @@ func TestGetMetadata_Run_UnreachableKubeClient(t *testing.T) {
client := NewGetMetadata(cfg)
_, err := client.Run("test-release")
assert.Error(t, err)
assert.Contains(t, err.Error(), "connection refused")
assert.ErrorContains(t, err, "connection refused")
}
func TestGetMetadata_Run_ReleaseNotFound(t *testing.T) {
@ -452,8 +451,7 @@ func TestGetMetadata_Run_ReleaseNotFound(t *testing.T) {
client := NewGetMetadata(cfg)
_, err := client.Run("non-existent-release")
assert.Error(t, err)
assert.Contains(t, err.Error(), "not found")
assert.ErrorContains(t, err, "not found")
}
func TestGetMetadata_Run_EmptyAppVersion(t *testing.T) {
@ -648,10 +646,10 @@ func TestGetMetadata_Labels(t *testing.T) {
metaGetter := NewGetMetadata(actionConfigFixture(t))
err := metaGetter.cfg.Releases.Create(rel)
assert.NoError(t, err)
require.NoError(t, err)
metadata, err := metaGetter.Run(rel.Name)
assert.NoError(t, err)
require.NoError(t, err)
assert.Equal(t, metadata.Name, rel.Name)
assert.Equal(t, metadata.Labels, customLabels)

@ -177,8 +177,7 @@ func TestGetValues_Run_UnreachableKubeClient(t *testing.T) {
client := NewGetValues(cfg)
_, err := client.Run("test-release")
assert.Error(t, err)
assert.Contains(t, err.Error(), "connection refused")
assert.ErrorContains(t, err, "connection refused")
}
func TestGetValues_Run_ReleaseNotFound(t *testing.T) {
@ -186,8 +185,7 @@ func TestGetValues_Run_ReleaseNotFound(t *testing.T) {
client := NewGetValues(cfg)
_, err := client.Run("non-existent-release")
assert.Error(t, err)
assert.Contains(t, err.Error(), "not found")
assert.ErrorContains(t, err, "not found")
}
func TestGetValues_Run_NilConfig(t *testing.T) {

@ -28,6 +28,7 @@ import (
"time"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
v1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/util/yaml"
@ -177,6 +178,7 @@ func runInstallForHooksWithSuccess(t *testing.T, manifest, expectedNamespace str
expectedOutput = "attempted to output logs for namespace: " + expectedNamespace
}
is := assert.New(t)
req := require.New(t)
instAction := installAction(t)
instAction.ReleaseName = "failed-hooks"
outBuffer := &bytes.Buffer{}
@ -190,9 +192,9 @@ func runInstallForHooksWithSuccess(t *testing.T, manifest, expectedNamespace str
vals := map[string]any{}
resi, err := instAction.Run(buildChartWithTemplates(templates), vals)
is.NoError(err)
req.NoError(err)
res, err := releaserToV1Release(resi)
is.NoError(err)
req.NoError(err)
is.Equal(expectedOutput, outBuffer.String())
is.Equal(rcommon.StatusDeployed, res.Info.Status)
}
@ -204,6 +206,7 @@ func runInstallForHooksWithFailure(t *testing.T, manifest, expectedNamespace str
expectedOutput = "attempted to output logs for namespace: " + expectedNamespace
}
is := assert.New(t)
req := require.New(t)
instAction := installAction(t)
instAction.ReleaseName = "failed-hooks"
failingClient := instAction.cfg.KubeClient.(*kubefake.FailingKubeClient)
@ -220,9 +223,9 @@ func runInstallForHooksWithFailure(t *testing.T, manifest, expectedNamespace str
vals := map[string]any{}
resi, err := instAction.Run(buildChartWithTemplates(templates), vals)
is.Error(err)
req.Error(err)
res, err := releaserToV1Release(resi)
is.NoError(err)
req.NoError(err)
is.Contains(res.Info.Description, "failed pre-install")
is.Equal(expectedOutput, outBuffer.String())
is.Equal(rcommon.StatusFailed, res.Info.Status)
@ -447,6 +450,7 @@ func TestConfiguration_hookSetDeletePolicy(t *testing.T) {
func TestExecHook_WaitOptionsPassedDownstream(t *testing.T) {
is := assert.New(t)
req := require.New(t)
failer := &kubefake.FailingKubeClient{
PrintingKubeClient: kubefake.PrintingKubeClient{Out: io.Discard},
@ -487,7 +491,7 @@ data:
waitOptions := []kube.WaitOption{kube.WithWaitContext(ctx)}
err := configuration.execHook(rel, release.HookPreInstall, kube.StatusWatcherStrategy, waitOptions, 600, false)
is.NoError(err)
req.NoError(err)
// Verify that WaitOptions were passed to GetWaiter
is.NotEmpty(failer.RecordedWaitOptions, "WaitOptions should be passed to GetWaiter")

@ -189,25 +189,25 @@ func TestInstallRelease(t *testing.T) {
t.Fatalf("Failed install: %s", err)
}
res, err := releaserToV1Release(resi)
is.NoError(err)
is.Equal(res.Name, "test-install-release", "Expected release name.")
is.Equal(res.Namespace, "spaced")
req.NoError(err)
is.Equal("test-install-release", res.Name, "Expected release name.")
is.Equal("spaced", res.Namespace)
r, err := instAction.cfg.Releases.Get(res.Name, res.Version)
is.NoError(err)
req.NoError(err)
rel, err := releaserToV1Release(r)
is.NoError(err)
req.NoError(err)
is.Len(rel.Hooks, 1)
is.Equal(rel.Hooks[0].Manifest, manifestWithHook)
is.Equal(rel.Hooks[0].Events[0], release.HookPostInstall)
is.Equal(rel.Hooks[0].Events[1], release.HookPreDelete, "Expected event 0 is pre-delete")
is.Equal(manifestWithHook, rel.Hooks[0].Manifest)
is.Equal(release.HookPostInstall, rel.Hooks[0].Events[0])
is.Equal(release.HookPreDelete, rel.Hooks[0].Events[1], "Expected event 0 is pre-delete")
is.NotEmpty(res.Manifest)
is.NotEmpty(rel.Manifest)
is.Contains(rel.Manifest, "---\n# Source: hello/templates/hello\nhello: world")
is.Equal(rel.Info.Description, "Install complete")
is.Equal("Install complete", rel.Info.Description)
// Detecting previous bug where context termination after successful release
// caused release to fail.
@ -216,8 +216,8 @@ func TestInstallRelease(t *testing.T) {
lastRelease, err := instAction.cfg.Releases.Last(rel.Name)
req.NoError(err)
lrel, err := releaserToV1Release(lastRelease)
is.NoError(err)
is.Equal(lrel.Info.Status, rcommon.StatusDeployed)
req.NoError(err)
is.Equal(rcommon.StatusDeployed, lrel.Info.Status)
}
func TestInstallReleaseWithTakeOwnership_ResourceNotOwned(t *testing.T) {
@ -231,6 +231,7 @@ func TestInstallReleaseWithTakeOwnership_ResourceNotOwned(t *testing.T) {
// "Client{Namespace: namespace, kubeClient: k8sfake.NewClientset()}"
is := assert.New(t)
req := require.New(t)
// Resource list from cluster is NOT owned by helm chart
config := actionConfigFixtureWithDummyResources(t, createDummyResourceList(false))
@ -241,19 +242,20 @@ func TestInstallReleaseWithTakeOwnership_ResourceNotOwned(t *testing.T) {
t.Fatalf("Failed install: %s", err)
}
res, err := releaserToV1Release(resi)
is.NoError(err)
req.NoError(err)
r, err := instAction.cfg.Releases.Get(res.Name, res.Version)
is.NoError(err)
req.NoError(err)
rel, err := releaserToV1Release(r)
is.NoError(err)
req.NoError(err)
is.Equal(rel.Info.Description, "Install complete")
is.Equal("Install complete", rel.Info.Description)
}
func TestInstallReleaseWithTakeOwnership_ResourceOwned(t *testing.T) {
is := assert.New(t)
req := require.New(t)
// Resource list from cluster is owned by helm chart
config := actionConfigFixtureWithDummyResources(t, createDummyResourceList(true))
@ -264,29 +266,31 @@ func TestInstallReleaseWithTakeOwnership_ResourceOwned(t *testing.T) {
t.Fatalf("Failed install: %s", err)
}
res, err := releaserToV1Release(resi)
is.NoError(err)
req.NoError(err)
r, err := instAction.cfg.Releases.Get(res.Name, res.Version)
is.NoError(err)
req.NoError(err)
rel, err := releaserToV1Release(r)
is.NoError(err)
req.NoError(err)
is.Equal(rel.Info.Description, "Install complete")
is.Equal("Install complete", rel.Info.Description)
}
func TestInstallReleaseWithTakeOwnership_ResourceOwnedNoFlag(t *testing.T) {
is := assert.New(t)
req := require.New(t)
// Resource list from cluster is NOT owned by helm chart
config := actionConfigFixtureWithDummyResources(t, createDummyResourceList(false))
instAction := installActionWithConfig(config)
_, err := instAction.Run(buildChart(), nil)
is.Error(err)
req.Error(err)
is.Contains(err.Error(), "unable to continue with install")
}
func TestInstallReleaseWithValues(t *testing.T) {
is := assert.New(t)
req := require.New(t)
instAction := installAction(t)
userVals := map[string]any{
"nestedKey": map[string]any{
@ -303,20 +307,20 @@ func TestInstallReleaseWithValues(t *testing.T) {
t.Fatalf("Failed install: %s", err)
}
res, err := releaserToV1Release(resi)
is.NoError(err)
is.Equal(res.Name, "test-install-release", "Expected release name.")
is.Equal(res.Namespace, "spaced")
req.NoError(err)
is.Equal("test-install-release", res.Name, "Expected release name.")
is.Equal("spaced", res.Namespace)
r, err := instAction.cfg.Releases.Get(res.Name, res.Version)
is.NoError(err)
req.NoError(err)
rel, err := releaserToV1Release(r)
is.NoError(err)
req.NoError(err)
is.Len(rel.Hooks, 1)
is.Equal(rel.Hooks[0].Manifest, manifestWithHook)
is.Equal(rel.Hooks[0].Events[0], release.HookPostInstall)
is.Equal(rel.Hooks[0].Events[1], release.HookPreDelete, "Expected event 0 is pre-delete")
is.Equal(manifestWithHook, rel.Hooks[0].Manifest)
is.Equal(release.HookPostInstall, rel.Hooks[0].Events[0])
is.Equal(release.HookPreDelete, rel.Hooks[0].Events[1], "Expected event 0 is pre-delete")
is.NotEmpty(res.Manifest)
is.NotEmpty(rel.Manifest)
@ -330,14 +334,12 @@ func TestInstallRelease_NoName(t *testing.T) {
instAction.ReleaseName = ""
vals := map[string]any{}
_, err := instAction.Run(buildChart(), vals)
if err == nil {
t.Fatal("expected failure when no name is specified")
}
assert.Contains(t, err.Error(), "no name provided")
assert.ErrorContains(t, err, "no name provided")
}
func TestInstallRelease_WithNotes(t *testing.T) {
is := assert.New(t)
req := require.New(t)
instAction := installAction(t)
instAction.ReleaseName = "with-notes"
vals := map[string]any{}
@ -346,29 +348,30 @@ func TestInstallRelease_WithNotes(t *testing.T) {
t.Fatalf("Failed install: %s", err)
}
res, err := releaserToV1Release(resi)
is.NoError(err)
req.NoError(err)
is.Equal(res.Name, "with-notes")
is.Equal(res.Namespace, "spaced")
is.Equal("with-notes", res.Name)
is.Equal("spaced", res.Namespace)
r, err := instAction.cfg.Releases.Get(res.Name, res.Version)
is.NoError(err)
req.NoError(err)
rel, err := releaserToV1Release(r)
is.NoError(err)
req.NoError(err)
is.Len(rel.Hooks, 1)
is.Equal(rel.Hooks[0].Manifest, manifestWithHook)
is.Equal(rel.Hooks[0].Events[0], release.HookPostInstall)
is.Equal(rel.Hooks[0].Events[1], release.HookPreDelete, "Expected event 0 is pre-delete")
is.Equal(manifestWithHook, rel.Hooks[0].Manifest)
is.Equal(release.HookPostInstall, rel.Hooks[0].Events[0])
is.Equal(release.HookPreDelete, rel.Hooks[0].Events[1], "Expected event 0 is pre-delete")
is.NotEmpty(res.Manifest)
is.NotEmpty(rel.Manifest)
is.Contains(rel.Manifest, "---\n# Source: hello/templates/hello\nhello: world")
is.Equal(rel.Info.Description, "Install complete")
is.Equal("Install complete", rel.Info.Description)
is.Equal(rel.Info.Notes, "note here")
is.Equal("note here", rel.Info.Notes)
}
func TestInstallRelease_WithNotesRendered(t *testing.T) {
is := assert.New(t)
req := require.New(t)
instAction := installAction(t)
instAction.ReleaseName = "with-notes"
vals := map[string]any{}
@ -377,21 +380,22 @@ func TestInstallRelease_WithNotesRendered(t *testing.T) {
t.Fatalf("Failed install: %s", err)
}
res, err := releaserToV1Release(resi)
is.NoError(err)
req.NoError(err)
r, err := instAction.cfg.Releases.Get(res.Name, res.Version)
is.NoError(err)
req.NoError(err)
rel, err := releaserToV1Release(r)
is.NoError(err)
req.NoError(err)
expectedNotes := "got-" + res.Name
is.Equal(expectedNotes, rel.Info.Notes)
is.Equal(rel.Info.Description, "Install complete")
is.Equal("Install complete", rel.Info.Description)
}
func TestInstallRelease_WithChartAndDependencyParentNotes(t *testing.T) {
// Regression: Make sure that the child's notes don't override the parent's
is := assert.New(t)
req := require.New(t)
instAction := installAction(t)
instAction.ReleaseName = "with-notes"
vals := map[string]any{}
@ -400,20 +404,21 @@ func TestInstallRelease_WithChartAndDependencyParentNotes(t *testing.T) {
t.Fatalf("Failed install: %s", err)
}
res, err := releaserToV1Release(resi)
is.NoError(err)
req.NoError(err)
r, err := instAction.cfg.Releases.Get(res.Name, res.Version)
is.NoError(err)
req.NoError(err)
rel, err := releaserToV1Release(r)
is.NoError(err)
req.NoError(err)
is.Equal("with-notes", rel.Name)
is.Equal("parent", rel.Info.Notes)
is.Equal(rel.Info.Description, "Install complete")
is.Equal("Install complete", rel.Info.Description)
}
func TestInstallRelease_WithChartAndDependencyAllNotes(t *testing.T) {
// Regression: Make sure that the child's notes don't override the parent's
is := assert.New(t)
req := require.New(t)
instAction := installAction(t)
instAction.ReleaseName = "with-notes"
instAction.SubNotes = true
@ -423,23 +428,24 @@ func TestInstallRelease_WithChartAndDependencyAllNotes(t *testing.T) {
t.Fatalf("Failed install: %s", err)
}
res, err := releaserToV1Release(resi)
is.NoError(err)
req.NoError(err)
r, err := instAction.cfg.Releases.Get(res.Name, res.Version)
is.NoError(err)
req.NoError(err)
rel, err := releaserToV1Release(r)
is.NoError(err)
req.NoError(err)
is.Equal("with-notes", rel.Name)
// test run can return as either 'parent\nchild' or 'child\nparent'
if !strings.Contains(rel.Info.Notes, "parent") && !strings.Contains(rel.Info.Notes, "child") {
t.Fatalf("Expected 'parent\nchild' or 'child\nparent', got '%s'", rel.Info.Notes)
}
is.Equal(rel.Info.Description, "Install complete")
is.Equal("Install complete", rel.Info.Description)
}
func TestInstallRelease_DryRunClient(t *testing.T) {
for _, dryRunStrategy := range []DryRunStrategy{DryRunClient, DryRunServer} {
is := assert.New(t)
req := require.New(t)
instAction := installAction(t)
instAction.DryRunStrategy = dryRunStrategy
@ -449,7 +455,7 @@ func TestInstallRelease_DryRunClient(t *testing.T) {
t.Fatalf("Failed install: %s", err)
}
res, err := releaserToV1Release(resi)
is.NoError(err)
req.NoError(err)
is.Contains(res.Manifest, "---\n# Source: hello/templates/hello\nhello: world")
is.Contains(res.Manifest, "---\n# Source: hello/templates/goodbye\ngoodbye: world")
@ -458,15 +464,16 @@ func TestInstallRelease_DryRunClient(t *testing.T) {
is.NotContains(res.Manifest, "empty")
_, err = instAction.cfg.Releases.Get(res.Name, res.Version)
is.Error(err)
req.Error(err)
is.Len(res.Hooks, 1)
is.True(res.Hooks[0].LastRun.CompletedAt.IsZero(), "expect hook to not be marked as run")
is.Equal(res.Info.Description, "Dry run complete")
is.Equal("Dry run complete", res.Info.Description)
}
}
func TestInstallRelease_DryRunHiddenSecret(t *testing.T) {
is := assert.New(t)
req := require.New(t)
instAction := installAction(t)
// First perform a normal dry-run with the secret and confirm its presence.
@ -477,12 +484,12 @@ func TestInstallRelease_DryRunHiddenSecret(t *testing.T) {
t.Fatalf("Failed install: %s", err)
}
res, err := releaserToV1Release(resi)
is.NoError(err)
req.NoError(err)
is.Contains(res.Manifest, "---\n# Source: hello/templates/secret.yaml\napiVersion: v1\nkind: Secret")
_, err = instAction.cfg.Releases.Get(res.Name, res.Version)
is.Error(err)
is.Equal(res.Info.Description, "Dry run complete")
req.Error(err)
is.Equal("Dry run complete", res.Info.Description)
// Perform a dry-run where the secret should not be present
instAction.HideSecret = true
@ -492,13 +499,13 @@ func TestInstallRelease_DryRunHiddenSecret(t *testing.T) {
t.Fatalf("Failed install: %s", err)
}
res2, err := releaserToV1Release(res2i)
is.NoError(err)
req.NoError(err)
is.NotContains(res2.Manifest, "---\n# Source: hello/templates/secret.yaml\napiVersion: v1\nkind: Secret")
_, err = instAction.cfg.Releases.Get(res2.Name, res2.Version)
is.Error(err)
is.Equal(res2.Info.Description, "Dry run complete")
req.Error(err)
is.Equal("Dry run complete", res2.Info.Description)
// Ensure there is an error when HideSecret True but not in a dry-run mode
instAction.DryRunStrategy = DryRunNone
@ -512,6 +519,7 @@ func TestInstallRelease_DryRunHiddenSecret(t *testing.T) {
// Regression test for #7955
func TestInstallRelease_DryRun_Lookup(t *testing.T) {
is := assert.New(t)
req := require.New(t)
instAction := installAction(t)
instAction.DryRunStrategy = DryRunNone
vals := map[string]any{}
@ -528,7 +536,7 @@ func TestInstallRelease_DryRun_Lookup(t *testing.T) {
t.Fatalf("Failed install: %s", err)
}
res, err := releaserToV1Release(resi)
is.NoError(err)
req.NoError(err)
is.Contains(res.Manifest, "goodbye: map[]")
}
@ -550,6 +558,7 @@ func TestInstallReleaseIncorrectTemplate_DryRun(t *testing.T) {
func TestInstallRelease_NoHooks(t *testing.T) {
is := assert.New(t)
req := require.New(t)
instAction := installAction(t)
instAction.DisableHooks = true
instAction.ReleaseName = "no-hooks"
@ -561,13 +570,14 @@ func TestInstallRelease_NoHooks(t *testing.T) {
t.Fatalf("Failed install: %s", err)
}
res, err := releaserToV1Release(resi)
is.NoError(err)
req.NoError(err)
is.True(res.Hooks[0].LastRun.CompletedAt.IsZero(), "hooks should not run with no-hooks")
}
func TestInstallRelease_FailedHooks(t *testing.T) {
is := assert.New(t)
req := require.New(t)
instAction := installAction(t)
instAction.ReleaseName = "failed-hooks"
failer := instAction.cfg.KubeClient.(*kubefake.FailingKubeClient)
@ -578,9 +588,9 @@ func TestInstallRelease_FailedHooks(t *testing.T) {
vals := map[string]any{}
resi, err := instAction.Run(buildChart(), vals)
is.Error(err)
req.Error(err)
res, err := releaserToV1Release(resi)
is.NoError(err)
req.NoError(err)
is.Contains(res.Info.Description, "failed post-install")
is.Empty(outBuffer.String())
is.Equal(rcommon.StatusFailed, res.Info.Status)
@ -588,48 +598,51 @@ func TestInstallRelease_FailedHooks(t *testing.T) {
func TestInstallRelease_ReplaceRelease(t *testing.T) {
is := assert.New(t)
req := require.New(t)
instAction := installAction(t)
instAction.Replace = true
rel := releaseStub()
rel.Info.Status = rcommon.StatusUninstalled
require.NoError(t, instAction.cfg.Releases.Create(rel))
req.NoError(instAction.cfg.Releases.Create(rel))
instAction.ReleaseName = rel.Name
vals := map[string]any{}
resi, err := instAction.Run(buildChart(), vals)
is.NoError(err)
req.NoError(err)
res, err := releaserToV1Release(resi)
is.NoError(err)
req.NoError(err)
// This should have been auto-incremented
is.Equal(2, res.Version)
is.Equal(res.Name, rel.Name)
r, err := instAction.cfg.Releases.Get(rel.Name, res.Version)
is.NoError(err)
req.NoError(err)
getres, err := releaserToV1Release(r)
is.NoError(err)
is.Equal(getres.Info.Status, rcommon.StatusDeployed)
req.NoError(err)
is.Equal(rcommon.StatusDeployed, getres.Info.Status)
}
func TestInstallRelease_KubeVersion(t *testing.T) {
is := assert.New(t)
req := require.New(t)
instAction := installAction(t)
vals := map[string]any{}
_, err := instAction.Run(buildChart(withKube(">=0.0.0")), vals)
is.NoError(err)
req.NoError(err)
// This should fail for a few hundred years
instAction.ReleaseName = "should-fail"
vals = map[string]any{}
_, err = instAction.Run(buildChart(withKube(">=99.0.0")), vals)
is.Error(err)
req.Error(err)
is.Contains(err.Error(), "chart requires kubeVersion: >=99.0.0 which is incompatible with Kubernetes v1.20.")
}
func TestInstallRelease_Wait(t *testing.T) {
is := assert.New(t)
req := require.New(t)
instAction := installAction(t)
instAction.ReleaseName = "come-fail-away"
failer := instAction.cfg.KubeClient.(*kubefake.FailingKubeClient)
@ -641,16 +654,17 @@ func TestInstallRelease_Wait(t *testing.T) {
goroutines := instAction.getGoroutineCount()
resi, err := instAction.Run(buildChart(), vals)
is.Error(err)
req.Error(err)
res, err := releaserToV1Release(resi)
is.NoError(err)
req.NoError(err)
is.Contains(res.Info.Description, "I timed out")
is.Equal(res.Info.Status, rcommon.StatusFailed)
is.Equal(rcommon.StatusFailed, res.Info.Status)
is.Equal(goroutines, instAction.getGoroutineCount())
}
func TestInstallRelease_Wait_Interrupted(t *testing.T) {
is := assert.New(t)
req := require.New(t)
instAction := installAction(t)
instAction.ReleaseName = "interrupted-release"
failer := instAction.cfg.KubeClient.(*kubefake.FailingKubeClient)
@ -665,7 +679,7 @@ func TestInstallRelease_Wait_Interrupted(t *testing.T) {
goroutines := instAction.getGoroutineCount()
_, err := instAction.RunWithContext(ctx, buildChart(), vals)
is.Error(err)
req.Error(err)
is.Contains(err.Error(), "context canceled")
is.Equal(goroutines+1, instAction.getGoroutineCount()) // installation goroutine still is in background
@ -674,6 +688,7 @@ func TestInstallRelease_Wait_Interrupted(t *testing.T) {
}
func TestInstallRelease_WaitForJobs(t *testing.T) {
is := assert.New(t)
req := require.New(t)
instAction := installAction(t)
instAction.ReleaseName = "come-fail-away"
failer := instAction.cfg.KubeClient.(*kubefake.FailingKubeClient)
@ -684,17 +699,17 @@ func TestInstallRelease_WaitForJobs(t *testing.T) {
vals := map[string]any{}
resi, err := instAction.Run(buildChart(), vals)
is.Error(err)
req.Error(err)
res, err := releaserToV1Release(resi)
is.NoError(err)
req.NoError(err)
is.Contains(res.Info.Description, "I timed out")
is.Equal(res.Info.Status, rcommon.StatusFailed)
is.Equal(rcommon.StatusFailed, res.Info.Status)
}
func TestInstallRelease_RollbackOnFailure(t *testing.T) {
is := assert.New(t)
t.Run("rollback-on-failure uninstall succeeds", func(t *testing.T) {
is := assert.New(t)
req := require.New(t)
instAction := installAction(t)
instAction.ReleaseName = "come-fail-away"
failer := instAction.cfg.KubeClient.(*kubefake.FailingKubeClient)
@ -707,19 +722,21 @@ func TestInstallRelease_RollbackOnFailure(t *testing.T) {
vals := map[string]any{}
resi, err := instAction.Run(buildChart(), vals)
is.Error(err)
req.Error(err)
is.Contains(err.Error(), "I timed out")
is.Contains(err.Error(), "rollback-on-failure")
res, err := releaserToV1Release(resi)
is.NoError(err)
req.NoError(err)
// Now make sure it isn't in storage anymore
_, err = instAction.cfg.Releases.Get(res.Name, res.Version)
is.Error(err)
req.Error(err)
is.Equal(err, driver.ErrReleaseNotFound)
})
t.Run("rollback-on-failure uninstall fails", func(t *testing.T) {
is := assert.New(t)
req := require.New(t)
instAction := installAction(t)
instAction.ReleaseName = "come-fail-away-with-me"
failer := instAction.cfg.KubeClient.(*kubefake.FailingKubeClient)
@ -730,7 +747,7 @@ func TestInstallRelease_RollbackOnFailure(t *testing.T) {
vals := map[string]any{}
_, err := instAction.Run(buildChart(), vals)
is.Error(err)
req.Error(err)
is.Contains(err.Error(), "I timed out")
is.Contains(err.Error(), "uninstall fail")
is.Contains(err.Error(), "an error occurred while uninstalling the release")
@ -738,6 +755,7 @@ func TestInstallRelease_RollbackOnFailure(t *testing.T) {
}
func TestInstallRelease_RollbackOnFailure_Interrupted(t *testing.T) {
is := assert.New(t)
req := require.New(t)
instAction := installAction(t)
instAction.ReleaseName = "interrupted-release"
failer := instAction.cfg.KubeClient.(*kubefake.FailingKubeClient)
@ -752,16 +770,16 @@ func TestInstallRelease_RollbackOnFailure_Interrupted(t *testing.T) {
goroutines := instAction.getGoroutineCount()
resi, err := instAction.RunWithContext(ctx, buildChart(), vals)
is.Error(err)
req.Error(err)
is.Contains(err.Error(), "context canceled")
is.Contains(err.Error(), "rollback-on-failure")
is.Contains(err.Error(), "uninstalled")
res, err := releaserToV1Release(resi)
is.NoError(err)
req.NoError(err)
// Now make sure it isn't in storage anymore
_, err = instAction.cfg.Releases.Get(res.Name, res.Version)
is.Error(err)
req.Error(err)
is.Equal(err, driver.ErrReleaseNotFound)
is.Equal(goroutines+1, instAction.getGoroutineCount()) // installation goroutine still is in background
time.Sleep(10 * time.Second) // wait for goroutine to finish
@ -837,6 +855,7 @@ func TestNameTemplate(t *testing.T) {
func TestInstallReleaseOutputDir(t *testing.T) {
is := assert.New(t)
req := require.New(t)
instAction := installAction(t)
vals := map[string]any{}
@ -850,16 +869,16 @@ func TestInstallReleaseOutputDir(t *testing.T) {
}
_, err = os.Stat(filepath.Join(dir, "hello/templates/goodbye"))
is.NoError(err)
req.NoError(err)
_, err = os.Stat(filepath.Join(dir, "hello/templates/hello"))
is.NoError(err)
req.NoError(err)
_, err = os.Stat(filepath.Join(dir, "hello/templates/with-partials"))
is.NoError(err)
req.NoError(err)
_, err = os.Stat(filepath.Join(dir, "hello/templates/rbac"))
is.NoError(err)
req.NoError(err)
test.AssertGoldenFile(t, filepath.Join(dir, "hello/templates/rbac"), "rbac.txt")
@ -869,6 +888,7 @@ func TestInstallReleaseOutputDir(t *testing.T) {
func TestInstallOutputDirWithReleaseName(t *testing.T) {
is := assert.New(t)
req := require.New(t)
instAction := installAction(t)
vals := map[string]any{}
@ -886,16 +906,16 @@ func TestInstallOutputDirWithReleaseName(t *testing.T) {
}
_, err = os.Stat(filepath.Join(newDir, "hello/templates/goodbye"))
is.NoError(err)
req.NoError(err)
_, err = os.Stat(filepath.Join(newDir, "hello/templates/hello"))
is.NoError(err)
req.NoError(err)
_, err = os.Stat(filepath.Join(newDir, "hello/templates/with-partials"))
is.NoError(err)
req.NoError(err)
_, err = os.Stat(filepath.Join(newDir, "hello/templates/rbac"))
is.NoError(err)
req.NoError(err)
test.AssertGoldenFile(t, filepath.Join(newDir, "hello/templates/rbac"), "rbac.txt")
@ -1008,6 +1028,7 @@ func TestNameAndChartGenerateName(t *testing.T) {
func TestInstallWithLabels(t *testing.T) {
is := assert.New(t)
req := require.New(t)
instAction := installAction(t)
instAction.Labels = map[string]string{
"key1": "val1",
@ -1018,7 +1039,7 @@ func TestInstallWithLabels(t *testing.T) {
t.Fatalf("Failed install: %s", err)
}
res, err := releaserToV1Release(resi)
is.NoError(err)
req.NoError(err)
is.Equal(instAction.Labels, res.Labels)
}
@ -1275,6 +1296,7 @@ func TestInstallCRDs_CheckNilErrors(t *testing.T) {
func TestInstallRelease_WaitOptionsPassedDownstream(t *testing.T) {
is := assert.New(t)
req := require.New(t)
instAction := installAction(t)
instAction.ReleaseName = "wait-options-test"
@ -1289,7 +1311,7 @@ func TestInstallRelease_WaitOptionsPassedDownstream(t *testing.T) {
vals := map[string]any{}
_, err := instAction.Run(buildChart(), vals)
is.NoError(err)
req.NoError(err)
// Verify that WaitOptions were passed to GetWaiter
is.NotEmpty(failer.RecordedWaitOptions, "WaitOptions should be passed to GetWaiter")

@ -22,6 +22,7 @@ import (
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
kubefake "helm.sh/helm/v4/pkg/kube/fake"
ri "helm.sh/helm/v4/pkg/release"
@ -64,7 +65,7 @@ func TestListStates(t *testing.T) {
func TestList_Empty(t *testing.T) {
lister := NewList(actionConfigFixture(t))
list, err := lister.Run()
assert.NoError(t, err)
require.NoError(t, err)
assert.Empty(t, list)
}
@ -75,33 +76,36 @@ func newListFixture(t *testing.T) *List {
func TestList_OneNamespace(t *testing.T) {
is := assert.New(t)
req := require.New(t)
lister := newListFixture(t)
makeMeSomeReleases(t, lister.cfg.Releases)
list, err := lister.Run()
is.NoError(err)
req.NoError(err)
is.Len(list, 3)
}
func TestList_AllNamespaces(t *testing.T) {
is := assert.New(t)
req := require.New(t)
lister := newListFixture(t)
makeMeSomeReleases(t, lister.cfg.Releases)
lister.AllNamespaces = true
lister.SetStateMask()
list, err := lister.Run()
is.NoError(err)
req.NoError(err)
is.Len(list, 3)
}
func TestList_Sort(t *testing.T) {
is := assert.New(t)
req := require.New(t)
lister := newListFixture(t)
lister.Sort = ByNameDesc // Other sorts are tested elsewhere
makeMeSomeReleases(t, lister.cfg.Releases)
l, err := lister.Run()
is.NoError(err)
req.NoError(err)
list, err := releaseListToV1List(l)
is.NoError(err)
req.NoError(err)
is.Len(list, 3)
is.Equal("two", list[0].Name)
@ -111,13 +115,14 @@ func TestList_Sort(t *testing.T) {
func TestList_Limit(t *testing.T) {
is := assert.New(t)
req := require.New(t)
lister := newListFixture(t)
lister.Limit = 2
makeMeSomeReleases(t, lister.cfg.Releases)
l, err := lister.Run()
is.NoError(err)
req.NoError(err)
list, err := releaseListToV1List(l)
is.NoError(err)
req.NoError(err)
is.Len(list, 2)
// Lex order means one, three, two
is.Equal("one", list[0].Name)
@ -126,13 +131,14 @@ func TestList_Limit(t *testing.T) {
func TestList_BigLimit(t *testing.T) {
is := assert.New(t)
req := require.New(t)
lister := newListFixture(t)
lister.Limit = 20
makeMeSomeReleases(t, lister.cfg.Releases)
l, err := lister.Run()
is.NoError(err)
req.NoError(err)
list, err := releaseListToV1List(l)
is.NoError(err)
req.NoError(err)
is.Len(list, 3)
// Lex order means one, three, two
@ -143,14 +149,15 @@ func TestList_BigLimit(t *testing.T) {
func TestList_LimitOffset(t *testing.T) {
is := assert.New(t)
req := require.New(t)
lister := newListFixture(t)
lister.Limit = 2
lister.Offset = 1
makeMeSomeReleases(t, lister.cfg.Releases)
l, err := lister.Run()
is.NoError(err)
req.NoError(err)
list, err := releaseListToV1List(l)
is.NoError(err)
req.NoError(err)
is.Len(list, 2)
// Lex order means one, three, two
@ -160,27 +167,29 @@ func TestList_LimitOffset(t *testing.T) {
func TestList_LimitOffsetOutOfBounds(t *testing.T) {
is := assert.New(t)
req := require.New(t)
lister := newListFixture(t)
lister.Limit = 2
lister.Offset = 3 // Last item is index 2
makeMeSomeReleases(t, lister.cfg.Releases)
list, err := lister.Run()
is.NoError(err)
req.NoError(err)
is.Empty(list)
lister.Limit = 10
lister.Offset = 1
list, err = lister.Run()
is.NoError(err)
req.NoError(err)
is.Len(list, 2)
}
func TestList_StateMask(t *testing.T) {
is := assert.New(t)
req := require.New(t)
lister := newListFixture(t)
makeMeSomeReleases(t, lister.cfg.Releases)
oner, err := lister.cfg.Releases.Get("one", 1)
is.NoError(err)
req.NoError(err)
var one release.Release
switch v := oner.(type) {
@ -194,18 +203,18 @@ func TestList_StateMask(t *testing.T) {
one.SetStatus(common.StatusUninstalled, "uninstalled")
err = lister.cfg.Releases.Update(one)
is.NoError(err)
req.NoError(err)
res, err := lister.Run()
is.NoError(err)
req.NoError(err)
is.Len(res, 3)
ac0, err := ri.NewAccessor(res[0])
is.NoError(err)
req.NoError(err)
ac1, err := ri.NewAccessor(res[1])
is.NoError(err)
req.NoError(err)
ac2, err := ri.NewAccessor(res[2])
is.NoError(err)
req.NoError(err)
is.Equal("one", ac0.Name())
is.Equal("three", ac1.Name())
@ -213,20 +222,21 @@ func TestList_StateMask(t *testing.T) {
lister.StateMask = ListUninstalled
res, err = lister.Run()
is.NoError(err)
req.NoError(err)
is.Len(res, 1)
ac0, err = ri.NewAccessor(res[0])
is.NoError(err)
req.NoError(err)
is.Equal("one", ac0.Name())
lister.StateMask |= ListDeployed
res, err = lister.Run()
is.NoError(err)
req.NoError(err)
is.Len(res, 3)
}
func TestList_StateMaskWithStaleRevisions(t *testing.T) {
is := assert.New(t)
req := require.New(t)
lister := newListFixture(t)
lister.StateMask = ListFailed
@ -234,13 +244,13 @@ func TestList_StateMaskWithStaleRevisions(t *testing.T) {
res, err := lister.Run()
is.NoError(err)
req.NoError(err)
is.Len(res, 1)
// "dirty" release should _not_ be present as most recent
// release is deployed despite failed release in past
ac0, err := ri.NewAccessor(res[0])
is.NoError(err)
req.NoError(err)
is.Equal("failed", ac0.Name())
}
@ -273,21 +283,22 @@ func makeMeSomeReleasesWithStaleFailure(t *testing.T, store *storage.Storage) {
}
all, err := store.ListReleases()
assert.NoError(t, err)
require.NoError(t, err)
assert.Len(t, all, 5, "sanity test: five items added")
}
func TestList_Filter(t *testing.T) {
is := assert.New(t)
req := require.New(t)
lister := newListFixture(t)
lister.Filter = "th."
makeMeSomeReleases(t, lister.cfg.Releases)
res, err := lister.Run()
is.NoError(err)
req.NoError(err)
is.Len(res, 1)
ac0, err := ri.NewAccessor(res[0])
is.NoError(err)
req.NoError(err)
is.Equal("three", ac0.Name())
}
@ -323,7 +334,7 @@ func makeMeSomeReleases(t *testing.T, store *storage.Storage) {
}
all, err := store.ListReleases()
assert.NoError(t, err)
require.NoError(t, err)
assert.Len(t, all, 3, "sanity test: three items added")
}

@ -23,6 +23,7 @@ import (
"testing"
"github.com/Masterminds/semver/v3"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"helm.sh/helm/v4/internal/test/ensure"
@ -92,8 +93,8 @@ func TestPassphraseFileFetcher_WithStdinAndMultipleFetches(t *testing.T) {
passphrase := "secret-from-stdin"
go func() {
_, err = w.WriteString(passphrase + "\n")
require.NoError(t, err)
_, err := w.WriteString(passphrase + "\n")
assert.NoError(t, err)
}()
for range 4 {

@ -71,8 +71,8 @@ func startLocalServerForTests(t *testing.T, handler http.Handler) (*httptest.Ser
return nil, err
}
handler = http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) {
_, err = w.Write(fileBytes)
require.NoError(t, err)
_, err := w.Write(fileBytes)
assert.NoError(t, err)
})
}

@ -20,6 +20,7 @@ import (
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestNewRegistryLogin(t *testing.T) {
@ -37,7 +38,7 @@ func TestWithCertFile(t *testing.T) {
certFile := "testdata/cert.pem"
opt := WithCertFile(certFile)
assert.NoError(t, opt(client))
require.NoError(t, opt(client))
assert.Equal(t, certFile, client.certFile)
}
@ -47,7 +48,7 @@ func TestWithInsecure(t *testing.T) {
opt := WithInsecure(true)
assert.NoError(t, opt(client))
require.NoError(t, opt(client))
assert.True(t, client.insecure)
}
@ -58,7 +59,7 @@ func TestWithKeyFile(t *testing.T) {
keyFile := "testdata/key.pem"
opt := WithKeyFile(keyFile)
assert.NoError(t, opt(client))
require.NoError(t, opt(client))
assert.Equal(t, keyFile, client.keyFile)
}
@ -69,7 +70,7 @@ func TestWithCAFile(t *testing.T) {
caFile := "testdata/ca.pem"
opt := WithCAFile(caFile)
assert.NoError(t, opt(client))
require.NoError(t, opt(client))
assert.Equal(t, caFile, client.caFile)
}
@ -79,6 +80,6 @@ func TestWithPlainHTTPLogin(t *testing.T) {
opt := WithPlainHTTPLogin(true)
assert.NoError(t, opt(client))
require.NoError(t, opt(client))
assert.True(t, client.plainHTTP)
}

@ -147,6 +147,7 @@ func TestReleaseTestingGetPodLogs_SkipNonPodHooks(t *testing.T) {
func TestReleaseTesting_WaitOptionsPassedDownstream(t *testing.T) {
is := assert.New(t)
req := require.New(t)
config := actionConfigFixture(t)
// Create a release with a test hook
@ -165,7 +166,7 @@ func TestReleaseTesting_WaitOptionsPassedDownstream(t *testing.T) {
failer := config.KubeClient.(*kubefake.FailingKubeClient)
_, _, err := client.Run(rel.Name)
is.NoError(err)
req.NoError(err)
// Verify that WaitOptions were passed to GetWaiter
is.NotEmpty(failer.RecordedWaitOptions, "WaitOptions should be passed to GetWaiter")
@ -230,8 +231,7 @@ func TestGetContainerLogs_PodNotFound(t *testing.T) {
var buf bytes.Buffer
err := rt.getContainerLogs(&buf, client, "nonexistent-pod")
require.Error(t, err)
assert.Contains(t, err.Error(), "unable to get pod nonexistent-pod")
assert.ErrorContains(t, err, "unable to get pod nonexistent-pod")
}
func TestGetContainerLogs_OutputHeaderFormat(t *testing.T) {

@ -49,6 +49,7 @@ func TestRollbackRun_UnreachableKubeClient(t *testing.T) {
func TestRollback_WaitOptionsPassedDownstream(t *testing.T) {
is := assert.New(t)
req := require.New(t)
config := actionConfigFixture(t)
// Create a deployed release and a second version to roll back to
@ -78,7 +79,7 @@ func TestRollback_WaitOptionsPassedDownstream(t *testing.T) {
failer := config.KubeClient.(*kubefake.FailingKubeClient)
err := client.Run(rel.Name)
is.NoError(err)
req.NoError(err)
// Verify that WaitOptions were passed to GetWaiter
is.NotEmpty(failer.RecordedWaitOptions, "WaitOptions should be passed to GetWaiter")

@ -61,6 +61,7 @@ func TestUninstallRelease_ignoreNotFound(t *testing.T) {
}
func TestUninstallRelease_deleteRelease(t *testing.T) {
is := assert.New(t)
req := require.New(t)
unAction := uninstallAction(t)
unAction.DisableHooks = true
@ -83,9 +84,9 @@ func TestUninstallRelease_deleteRelease(t *testing.T) {
"password": "password"
}
}`
require.NoError(t, unAction.cfg.Releases.Create(rel))
req.NoError(unAction.cfg.Releases.Create(rel))
res, err := unAction.Run(rel.Name)
is.NoError(err)
req.NoError(err)
expected := `These resources were kept due to the resource policy:
[Secret] secret
`
@ -94,6 +95,7 @@ func TestUninstallRelease_deleteRelease(t *testing.T) {
func TestUninstallRelease_Wait(t *testing.T) {
is := assert.New(t)
req := require.New(t)
unAction := uninstallAction(t)
unAction.DisableHooks = true
@ -113,16 +115,16 @@ func TestUninstallRelease_Wait(t *testing.T) {
"password": "password"
}
}`
require.NoError(t, unAction.cfg.Releases.Create(rel))
req.NoError(unAction.cfg.Releases.Create(rel))
failer := unAction.cfg.KubeClient.(*kubefake.FailingKubeClient)
failer.WaitForDeleteError = errors.New("U timed out")
unAction.cfg.KubeClient = failer
resi, err := unAction.Run(rel.Name)
is.Error(err)
req.Error(err)
is.Contains(err.Error(), "U timed out")
res, err := releaserToV1Release(resi.Release)
is.NoError(err)
is.Equal(res.Info.Status, common.StatusUninstalled)
req.NoError(err)
is.Equal(common.StatusUninstalled, res.Info.Status)
}
func TestUninstallRelease_Cascade(t *testing.T) {
@ -180,6 +182,7 @@ func TestUninstallRun_UnreachableKubeClient(t *testing.T) {
func TestUninstallRelease_OwnershipVerification(t *testing.T) {
is := assert.New(t)
req := require.New(t)
// Create a buffer to capture log output
logBuffer := &bytes.Buffer{}
@ -207,7 +210,7 @@ metadata:
meta.helm.sh/release-namespace: default
data:
key: value`
require.NoError(t, config.Releases.Create(rel))
req.NoError(config.Releases.Create(rel))
// Create dummy resources with proper ownership metadata
labels := map[string]string{
@ -224,10 +227,10 @@ data:
failer.DummyResources = dummyResources
resi, err := unAction.Run(rel.Name)
is.NoError(err)
req.NoError(err)
is.NotNil(resi)
res, err := releaserToV1Release(resi.Release)
is.NoError(err)
req.NoError(err)
is.Equal(common.StatusUninstalled, res.Info.Status)
// Verify log contains debug message about deleting owned resource
@ -239,6 +242,7 @@ data:
func TestUninstallRelease_OwnershipVerification_WithKeepPolicy(t *testing.T) {
is := assert.New(t)
req := require.New(t)
// Create a buffer to capture log output
logBuffer := &bytes.Buffer{}
@ -280,7 +284,7 @@ metadata:
meta.helm.sh/release-namespace: default
data:
key: value`
require.NoError(t, config.Releases.Create(rel))
req.NoError(config.Releases.Create(rel))
// Create dummy resources - one unowned to test logging
dummyResources := kube.ResourceList{
@ -290,7 +294,7 @@ data:
failer.DummyResources = dummyResources
res, err := unAction.Run(rel.Name)
is.NoError(err)
req.NoError(err)
is.NotNil(res)
// Should contain info about kept resources
is.Contains(res.Info, "kept due to the resource policy")
@ -303,6 +307,7 @@ data:
func TestUninstallRelease_DryRun_OwnershipVerification(t *testing.T) {
is := assert.New(t)
req := require.New(t)
// Create a buffer to capture log output
logBuffer := &bytes.Buffer{}
@ -329,7 +334,7 @@ metadata:
meta.helm.sh/release-namespace: default
data:
key: value`
require.NoError(t, config.Releases.Create(rel))
req.NoError(config.Releases.Create(rel))
// Create dummy resources - one unowned to test dry-run logging
dummyResources := kube.ResourceList{
@ -339,11 +344,11 @@ data:
failer.DummyResources = dummyResources
resi, err := unAction.Run(rel.Name)
is.NoError(err)
req.NoError(err)
is.NotNil(resi)
is.NotNil(resi.Release)
res, err := releaserToV1Release(resi.Release)
is.NoError(err)
req.NoError(err)
is.Equal("dryrun-ownership", res.Name)
// Verify log contains dry-run warning about resources that would be skipped

@ -66,8 +66,8 @@ func TestUpgradeRelease_Success(t *testing.T) {
resi, err := upAction.RunWithContext(ctx, rel.Name, buildChart(), vals)
req.NoError(err)
res, err := releaserToV1Release(resi)
is.NoError(err)
is.Equal(res.Info.Status, common.StatusDeployed)
req.NoError(err)
is.Equal(common.StatusDeployed, res.Info.Status)
done()
// Detecting previous bug where context termination after successful release
@ -77,7 +77,7 @@ func TestUpgradeRelease_Success(t *testing.T) {
req.NoError(err)
lastRelease, err := releaserToV1Release(lastReleasei)
req.NoError(err)
is.Equal(lastRelease.Info.Status, common.StatusDeployed)
is.Equal(common.StatusDeployed, lastRelease.Info.Status)
}
func TestUpgradeRelease_Wait(t *testing.T) {
@ -99,9 +99,9 @@ func TestUpgradeRelease_Wait(t *testing.T) {
resi, err := upAction.Run(rel.Name, buildChart(), vals)
req.Error(err)
res, err := releaserToV1Release(resi)
is.NoError(err)
req.NoError(err)
is.Contains(res.Info.Description, "I timed out")
is.Equal(res.Info.Status, common.StatusFailed)
is.Equal(common.StatusFailed, res.Info.Status)
}
func TestUpgradeRelease_WaitForJobs(t *testing.T) {
@ -124,9 +124,9 @@ func TestUpgradeRelease_WaitForJobs(t *testing.T) {
resi, err := upAction.Run(rel.Name, buildChart(), vals)
req.Error(err)
res, err := releaserToV1Release(resi)
is.NoError(err)
req.NoError(err)
is.Contains(res.Info.Description, "I timed out")
is.Equal(res.Info.Status, common.StatusFailed)
is.Equal(common.StatusFailed, res.Info.Status)
}
func TestUpgradeRelease_CleanupOnFail(t *testing.T) {
@ -151,22 +151,21 @@ func TestUpgradeRelease_CleanupOnFail(t *testing.T) {
req.Error(err)
is.NotContains(err.Error(), "unable to cleanup resources")
res, err := releaserToV1Release(resi)
is.NoError(err)
req.NoError(err)
is.Contains(res.Info.Description, "I timed out")
is.Equal(res.Info.Status, common.StatusFailed)
is.Equal(common.StatusFailed, res.Info.Status)
}
func TestUpgradeRelease_RollbackOnFailure(t *testing.T) {
is := assert.New(t)
req := require.New(t)
t.Run("rollback-on-failure rollback succeeds", func(t *testing.T) {
is := assert.New(t)
req := require.New(t)
upAction := upgradeAction(t)
rel := releaseStub()
rel.Name = "nuketown"
rel.Info.Status = common.StatusDeployed
require.NoError(t, upAction.cfg.Releases.Create(rel))
req.NoError(upAction.cfg.Releases.Create(rel))
failer := upAction.cfg.KubeClient.(*kubefake.FailingKubeClient)
// We can't make Update error because then the rollback won't work
@ -180,18 +179,20 @@ func TestUpgradeRelease_RollbackOnFailure(t *testing.T) {
is.Contains(err.Error(), "arming key removed")
is.Contains(err.Error(), "rollback-on-failure")
res, err := releaserToV1Release(resi)
is.NoError(err)
req.NoError(err)
// Now make sure it is actually upgraded
updatedResi, err := upAction.cfg.Releases.Get(res.Name, 3)
is.NoError(err)
req.NoError(err)
updatedRes, err := releaserToV1Release(updatedResi)
is.NoError(err)
req.NoError(err)
// Should have rolled back to the previous
is.Equal(updatedRes.Info.Status, common.StatusDeployed)
is.Equal(common.StatusDeployed, updatedRes.Info.Status)
})
t.Run("rollback-on-failure uninstall fails", func(t *testing.T) {
is := assert.New(t)
req := require.New(t)
upAction := upgradeAction(t)
rel := releaseStub()
rel.Name = "fallout"
@ -212,9 +213,9 @@ func TestUpgradeRelease_RollbackOnFailure(t *testing.T) {
}
func TestUpgradeRelease_ReuseValues(t *testing.T) {
is := assert.New(t)
t.Run("reuse values should work with values", func(t *testing.T) {
is := assert.New(t)
req := require.New(t)
upAction := upgradeAction(t)
existingValues := map[string]any{
@ -240,31 +241,33 @@ func TestUpgradeRelease_ReuseValues(t *testing.T) {
rel.Config = existingValues
err := upAction.cfg.Releases.Create(rel)
is.NoError(err)
req.NoError(err)
upAction.ReuseValues = true
// setting newValues and upgrading
resi, err := upAction.Run(rel.Name, buildChart(), newValues)
is.NoError(err)
req.NoError(err)
res, err := releaserToV1Release(resi)
is.NoError(err)
req.NoError(err)
// Now make sure it is actually upgraded
updatedResi, err := upAction.cfg.Releases.Get(res.Name, 2)
is.NoError(err)
req.NoError(err)
if updatedResi == nil {
is.Fail("Updated Release is nil")
return
}
updatedRes, err := releaserToV1Release(updatedResi)
is.NoError(err)
req.NoError(err)
is.Equal(common.StatusDeployed, updatedRes.Info.Status)
is.Equal(expectedValues, updatedRes.Config)
})
t.Run("reuse values should not install disabled charts", func(t *testing.T) {
is := assert.New(t)
req := require.New(t)
upAction := upgradeAction(t)
chartDefaultValues := map[string]any{
"subchart": map[string]any{
@ -301,7 +304,7 @@ func TestUpgradeRelease_ReuseValues(t *testing.T) {
Version: 1,
}
err := upAction.cfg.Releases.Create(rel)
is.NoError(err)
req.NoError(err)
upAction.ReuseValues = true
sampleChartWithSubChart := buildChart(
@ -312,20 +315,20 @@ func TestUpgradeRelease_ReuseValues(t *testing.T) {
)
// reusing values and upgrading
resi, err := upAction.Run(rel.Name, sampleChartWithSubChart, map[string]any{})
is.NoError(err)
req.NoError(err)
res, err := releaserToV1Release(resi)
is.NoError(err)
req.NoError(err)
// Now get the upgraded release
updatedResi, err := upAction.cfg.Releases.Get(res.Name, 2)
is.NoError(err)
req.NoError(err)
if updatedResi == nil {
is.Fail("Updated Release is nil")
return
}
updatedRes, err := releaserToV1Release(updatedResi)
is.NoError(err)
req.NoError(err)
is.Equal(common.StatusDeployed, updatedRes.Info.Status)
is.Empty(updatedRes.Chart.Dependencies(), "expected 0 dependencies")
@ -340,9 +343,9 @@ func TestUpgradeRelease_ReuseValues(t *testing.T) {
}
func TestUpgradeRelease_ResetThenReuseValues(t *testing.T) {
is := assert.New(t)
t.Run("reset then reuse values should work with values", func(t *testing.T) {
is := assert.New(t)
req := require.New(t)
upAction := upgradeAction(t)
existingValues := map[string]any{
@ -371,25 +374,25 @@ func TestUpgradeRelease_ResetThenReuseValues(t *testing.T) {
rel.Config = existingValues
err := upAction.cfg.Releases.Create(rel)
is.NoError(err)
req.NoError(err)
upAction.ResetThenReuseValues = true
// setting newValues and upgrading
resi, err := upAction.Run(rel.Name, buildChart(withValues(newChartValues)), newValues)
is.NoError(err)
req.NoError(err)
res, err := releaserToV1Release(resi)
is.NoError(err)
req.NoError(err)
// Now make sure it is actually upgraded
updatedResi, err := upAction.cfg.Releases.Get(res.Name, 2)
is.NoError(err)
req.NoError(err)
if updatedResi == nil {
is.Fail("Updated Release is nil")
return
}
updatedRes, err := releaserToV1Release(updatedResi)
is.NoError(err)
req.NoError(err)
is.Equal(common.StatusDeployed, updatedRes.Info.Status)
is.Equal(expectedValues, updatedRes.Config)
@ -440,9 +443,9 @@ func TestUpgradeRelease_Interrupted_Wait(t *testing.T) {
req.Error(err)
res, err := releaserToV1Release(resi)
is.NoError(err)
req.NoError(err)
is.Contains(res.Info.Description, "Upgrade \"interrupted-release\" failed: context canceled")
is.Equal(res.Info.Status, common.StatusFailed)
is.Equal(common.StatusFailed, res.Info.Status)
}
func TestUpgradeRelease_Interrupted_RollbackOnFailure(t *testing.T) {
@ -453,7 +456,7 @@ func TestUpgradeRelease_Interrupted_RollbackOnFailure(t *testing.T) {
rel := releaseStub()
rel.Name = "interrupted-release"
rel.Info.Status = common.StatusDeployed
require.NoError(t, upAction.cfg.Releases.Create(rel))
req.NoError(upAction.cfg.Releases.Create(rel))
failer := upAction.cfg.KubeClient.(*kubefake.FailingKubeClient)
failer.WaitDuration = 5 * time.Second
@ -469,14 +472,14 @@ func TestUpgradeRelease_Interrupted_RollbackOnFailure(t *testing.T) {
req.Error(err)
is.Contains(err.Error(), "release interrupted-release failed, and has been rolled back due to rollback-on-failure being set: context canceled")
res, err := releaserToV1Release(resi)
is.NoError(err)
req.NoError(err)
// Now make sure it is actually upgraded
updatedResi, err := upAction.cfg.Releases.Get(res.Name, 3)
is.NoError(err)
req.NoError(err)
updatedRes, err := releaserToV1Release(updatedResi)
is.NoError(err)
req.NoError(err)
// Should have rolled back to the previous
is.Equal(updatedRes.Info.Status, common.StatusDeployed)
is.Equal(common.StatusDeployed, updatedRes.Info.Status)
}
func TestMergeCustomLabels(t *testing.T) {
@ -496,6 +499,7 @@ func TestMergeCustomLabels(t *testing.T) {
func TestUpgradeRelease_Labels(t *testing.T) {
is := assert.New(t)
req := require.New(t)
upAction := upgradeAction(t)
rel := releaseStub()
@ -508,7 +512,7 @@ func TestUpgradeRelease_Labels(t *testing.T) {
rel.Info.Status = common.StatusDeployed
err := upAction.cfg.Releases.Create(rel)
is.NoError(err)
req.NoError(err)
upAction.Labels = map[string]string{
"key1": "null",
@ -517,39 +521,40 @@ func TestUpgradeRelease_Labels(t *testing.T) {
}
// setting newValues and upgrading
resi, err := upAction.Run(rel.Name, buildChart(), nil)
is.NoError(err)
req.NoError(err)
res, err := releaserToV1Release(resi)
is.NoError(err)
req.NoError(err)
// Now make sure it is actually upgraded and labels were merged
updatedResi, err := upAction.cfg.Releases.Get(res.Name, 2)
is.NoError(err)
req.NoError(err)
if updatedResi == nil {
is.Fail("Updated Release is nil")
return
}
updatedRes, err := releaserToV1Release(updatedResi)
is.NoError(err)
req.NoError(err)
is.Equal(common.StatusDeployed, updatedRes.Info.Status)
is.Equal(mergeCustomLabels(rel.Labels, upAction.Labels), updatedRes.Labels)
// Now make sure it is suppressed release still contains original labels
initialResi, err := upAction.cfg.Releases.Get(res.Name, 1)
is.NoError(err)
req.NoError(err)
if initialResi == nil {
is.Fail("Updated Release is nil")
return
}
initialRes, err := releaserToV1Release(initialResi)
is.NoError(err)
is.Equal(initialRes.Info.Status, common.StatusSuperseded)
req.NoError(err)
is.Equal(common.StatusSuperseded, initialRes.Info.Status)
is.Equal(initialRes.Labels, rel.Labels)
}
func TestUpgradeRelease_SystemLabels(t *testing.T) {
is := assert.New(t)
req := require.New(t)
upAction := upgradeAction(t)
rel := releaseStub()
@ -562,7 +567,7 @@ func TestUpgradeRelease_SystemLabels(t *testing.T) {
rel.Info.Status = common.StatusDeployed
err := upAction.cfg.Releases.Create(rel)
is.NoError(err)
req.NoError(err)
upAction.Labels = map[string]string{
"key1": "null",
@ -596,7 +601,7 @@ func TestUpgradeRelease_DryRun(t *testing.T) {
done()
req.NoError(err)
res, err := releaserToV1Release(resi)
is.NoError(err)
req.NoError(err)
is.Equal(common.StatusPendingUpgrade, res.Info.Status)
is.Contains(res.Manifest, "kind: Secret")
@ -604,7 +609,7 @@ func TestUpgradeRelease_DryRun(t *testing.T) {
req.NoError(err)
lastRelease, err := releaserToV1Release(lastReleasei)
req.NoError(err)
is.Equal(lastRelease.Info.Status, common.StatusDeployed)
is.Equal(common.StatusDeployed, lastRelease.Info.Status)
is.Equal(1, lastRelease.Version)
// Test the case for hiding the secret to ensure it is not displayed
@ -616,7 +621,7 @@ func TestUpgradeRelease_DryRun(t *testing.T) {
done()
req.NoError(err)
res, err = releaserToV1Release(resi)
is.NoError(err)
req.NoError(err)
is.Equal(common.StatusPendingUpgrade, res.Info.Status)
is.NotContains(res.Manifest, "kind: Secret")
@ -624,7 +629,7 @@ func TestUpgradeRelease_DryRun(t *testing.T) {
req.NoError(err)
lastRelease, err = releaserToV1Release(lastReleasei)
req.NoError(err)
is.Equal(lastRelease.Info.Status, common.StatusDeployed)
is.Equal(common.StatusDeployed, lastRelease.Info.Status)
is.Equal(1, lastRelease.Version)
// Ensure in a dry run mode when using HideSecret
@ -715,7 +720,7 @@ func TestGetUpgradeServerSideValue(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
serverSideApply, err := getUpgradeServerSideValue(tt.actionServerSideOption, tt.releaseApplyMethod)
assert.NoError(t, err)
require.NoError(t, err)
assert.Equal(t, tt.expectedServerSideApply, serverSideApply)
})
}

@ -25,6 +25,7 @@ import (
"helm.sh/helm/v4/pkg/kube"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
appsv1 "k8s.io/api/apps/v1"
"k8s.io/apimachinery/pkg/api/meta"
@ -130,7 +131,7 @@ func TestRequireAdoption(t *testing.T) {
// Verify that a resource that lacks labels/annotations can be adopted
found, err := requireAdoption(resources)
assert.NoError(t, err)
require.NoError(t, err)
assert.Len(t, found, 1)
assert.Equal(t, found[0], existing)
assert.NotSame(t, found[0], existing)
@ -155,7 +156,7 @@ func TestExistingResourceConflict(t *testing.T) {
// Verify only existing resources are returned
found, err := existingResourceConflict(resources, releaseName, releaseNamespace)
assert.NoError(t, err)
require.NoError(t, err)
assert.Len(t, found, 1)
assert.Equal(t, found[0], existing)
assert.NotSame(t, found[0], existing)
@ -171,21 +172,21 @@ func TestCheckOwnership(t *testing.T) {
// Verify that a resource that lacks labels/annotations is not owned
err := checkOwnership(deployFoo.Object, "rel-a", "ns-a")
assert.EqualError(t, err, `invalid ownership metadata; label validation error: missing key "app.kubernetes.io/managed-by": must be set to "Helm"; annotation validation error: missing key "meta.helm.sh/release-name": must be set to "rel-a"; annotation validation error: missing key "meta.helm.sh/release-namespace": must be set to "ns-a"`)
require.EqualError(t, err, `invalid ownership metadata; label validation error: missing key "app.kubernetes.io/managed-by": must be set to "Helm"; annotation validation error: missing key "meta.helm.sh/release-name": must be set to "rel-a"; annotation validation error: missing key "meta.helm.sh/release-namespace": must be set to "ns-a"`)
// Set managed by label and verify annotation error message
_ = accessor.SetLabels(deployFoo.Object, map[string]string{
appManagedByLabel: appManagedByHelm,
})
err = checkOwnership(deployFoo.Object, "rel-a", "ns-a")
assert.EqualError(t, err, `invalid ownership metadata; annotation validation error: missing key "meta.helm.sh/release-name": must be set to "rel-a"; annotation validation error: missing key "meta.helm.sh/release-namespace": must be set to "ns-a"`)
require.EqualError(t, err, `invalid ownership metadata; annotation validation error: missing key "meta.helm.sh/release-name": must be set to "rel-a"; annotation validation error: missing key "meta.helm.sh/release-namespace": must be set to "ns-a"`)
// Set only the release name annotation and verify missing release namespace error message
_ = accessor.SetAnnotations(deployFoo.Object, map[string]string{
helmReleaseNameAnnotation: "rel-a",
})
err = checkOwnership(deployFoo.Object, "rel-a", "ns-a")
assert.EqualError(t, err, `invalid ownership metadata; annotation validation error: missing key "meta.helm.sh/release-namespace": must be set to "ns-a"`)
require.EqualError(t, err, `invalid ownership metadata; annotation validation error: missing key "meta.helm.sh/release-namespace": must be set to "ns-a"`)
// Set both release name and namespace annotations and verify no ownership errors
_ = accessor.SetAnnotations(deployFoo.Object, map[string]string{
@ -193,15 +194,15 @@ func TestCheckOwnership(t *testing.T) {
helmReleaseNamespaceAnnotation: "ns-a",
})
err = checkOwnership(deployFoo.Object, "rel-a", "ns-a")
assert.NoError(t, err)
require.NoError(t, err)
// Verify ownership error for wrong release name
err = checkOwnership(deployFoo.Object, "rel-b", "ns-a")
assert.EqualError(t, err, `invalid ownership metadata; annotation validation error: key "meta.helm.sh/release-name" must equal "rel-b": current value is "rel-a"`)
require.EqualError(t, err, `invalid ownership metadata; annotation validation error: key "meta.helm.sh/release-name" must equal "rel-b": current value is "rel-a"`)
// Verify ownership error for wrong release namespace
err = checkOwnership(deployFoo.Object, "rel-a", "ns-b")
assert.EqualError(t, err, `invalid ownership metadata; annotation validation error: key "meta.helm.sh/release-namespace" must equal "ns-b": current value is "ns-a"`)
require.EqualError(t, err, `invalid ownership metadata; annotation validation error: key "meta.helm.sh/release-namespace" must equal "ns-b": current value is "ns-a"`)
// Verify ownership error for wrong manager label
_ = accessor.SetLabels(deployFoo.Object, map[string]string{
@ -235,7 +236,7 @@ func TestVerifyOwnershipBeforeDelete(t *testing.T) {
resources := kube.ResourceList{owned1, owned2}
ownedList, unownedList, _, err := verifyOwnershipBeforeDelete(resources, releaseName, releaseNamespace)
assert.NoError(t, err)
require.NoError(t, err)
assert.Len(t, ownedList, 2)
assert.Empty(t, unownedList)
})
@ -247,7 +248,7 @@ func TestVerifyOwnershipBeforeDelete(t *testing.T) {
resources := kube.ResourceList{owned, unowned}
ownedList, unownedList, _, err := verifyOwnershipBeforeDelete(resources, releaseName, releaseNamespace)
assert.NoError(t, err)
require.NoError(t, err)
assert.Len(t, ownedList, 1)
assert.Len(t, unownedList, 1)
assert.Equal(t, "owned", ownedList[0].Name)
@ -260,7 +261,7 @@ func TestVerifyOwnershipBeforeDelete(t *testing.T) {
resources := kube.ResourceList{missing}
ownedList, unownedList, _, err := verifyOwnershipBeforeDelete(resources, releaseName, releaseNamespace)
assert.NoError(t, err)
require.NoError(t, err)
assert.Empty(t, ownedList)
assert.Empty(t, unownedList)
})
@ -271,7 +272,7 @@ func TestVerifyOwnershipBeforeDelete(t *testing.T) {
resources := kube.ResourceList{noMeta}
ownedList, unownedList, _, err := verifyOwnershipBeforeDelete(resources, releaseName, releaseNamespace)
assert.NoError(t, err)
require.NoError(t, err)
assert.Empty(t, ownedList)
assert.Len(t, unownedList, 1)
})
@ -282,7 +283,7 @@ func TestVerifyOwnershipBeforeDelete(t *testing.T) {
resources := kube.ResourceList{otherRelease}
ownedList, unownedList, _, err := verifyOwnershipBeforeDelete(resources, releaseName, releaseNamespace)
assert.NoError(t, err)
require.NoError(t, err)
assert.Empty(t, ownedList)
assert.Len(t, unownedList, 1)
})
@ -295,7 +296,7 @@ func TestVerifyOwnershipBeforeDelete(t *testing.T) {
resources := kube.ResourceList{owned, unowned, missing}
ownedList, unownedList, _, err := verifyOwnershipBeforeDelete(resources, releaseName, releaseNamespace)
assert.NoError(t, err)
require.NoError(t, err)
assert.Len(t, ownedList, 1)
assert.Len(t, unownedList, 1)
assert.Equal(t, "owned", ownedList[0].Name)
@ -313,25 +314,24 @@ func TestSetMetadataVisitor(t *testing.T) {
// Set release tracking metadata and verify no error
err = resources.Visit(setMetadataVisitor("rel-a", "ns-a", true))
assert.NoError(t, err)
require.NoError(t, err)
// Verify that release "b" cannot take ownership of "a"
err = resources.Visit(setMetadataVisitor("rel-b", "ns-a", false))
assert.Error(t, err)
require.Error(t, err)
// Force release "b" to take ownership
err = resources.Visit(setMetadataVisitor("rel-b", "ns-a", true))
assert.NoError(t, err)
require.NoError(t, err)
// Check that there is now no ownership error when setting metadata without force
err = resources.Visit(setMetadataVisitor("rel-b", "ns-a", false))
assert.NoError(t, err)
require.NoError(t, err)
// Add a new resource that is missing ownership metadata and verify error
resources.Append(newDeploymentResource("baz", "default", ""))
err = resources.Visit(setMetadataVisitor("rel-b", "ns-a", false))
assert.Error(t, err)
assert.Contains(t, err.Error(), `Deployment "baz" in namespace "" cannot be owned`)
assert.ErrorContains(t, err, `Deployment "baz" in namespace "" cannot be owned`)
}
func TestValidateNameAndGenerateName(t *testing.T) {
@ -368,10 +368,9 @@ func TestValidateNameAndGenerateName(t *testing.T) {
skip, err := validateNameAndGenerateName(tc.info)
if tc.wantErr {
assert.Error(t, err)
assert.Contains(t, err.Error(), tc.errContains)
require.ErrorContains(t, err, tc.errContains)
} else {
assert.NoError(t, err)
require.NoError(t, err)
}
assert.Equal(t, tc.wantSkip, skip)

@ -25,6 +25,7 @@ import (
"text/template"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"helm.sh/helm/v4/pkg/chart/common"
chart "helm.sh/helm/v4/pkg/chart/v2"
@ -734,6 +735,7 @@ func TestConcatPrefix(t *testing.T) {
// from issue #31643 where chart has data: {} and user provides data: {foo: bar, baz: ~}
func TestCoalesceValuesEmptyMapWithNils(t *testing.T) {
is := assert.New(t)
req := require.New(t)
c := &chart.Chart{
Metadata: &chart.Metadata{Name: "test"},
@ -750,7 +752,7 @@ func TestCoalesceValuesEmptyMapWithNils(t *testing.T) {
}
v, err := CoalesceValues(c, vals)
is.NoError(err)
req.NoError(err)
data, ok := v["data"].(map[string]any)
is.True(ok, "data is not a map")
@ -769,6 +771,7 @@ func TestCoalesceValuesEmptyMapWithNils(t *testing.T) {
// Regression test for issue #31919.
func TestCoalesceValuesSubchartDefaultNilsCleaned(t *testing.T) {
is := assert.New(t)
req := require.New(t)
// Subchart has a default with nil values (e.g. keyMapping: {password: null})
subchart := &chart.Chart{
@ -789,7 +792,7 @@ func TestCoalesceValuesSubchartDefaultNilsCleaned(t *testing.T) {
vals := map[string]any{}
v, err := CoalesceValues(parent, vals)
is.NoError(err)
req.NoError(err)
childVals, ok := v["child"].(map[string]any)
is.True(ok, "child values should be a map")
@ -807,6 +810,7 @@ func TestCoalesceValuesSubchartDefaultNilsCleaned(t *testing.T) {
// Regression test for issue #31919.
func TestCoalesceValuesUserNullErasesSubchartDefault(t *testing.T) {
is := assert.New(t)
req := require.New(t)
subchart := &chart.Chart{
Metadata: &chart.Metadata{Name: "child"},
@ -828,7 +832,7 @@ func TestCoalesceValuesUserNullErasesSubchartDefault(t *testing.T) {
}
v, err := CoalesceValues(parent, vals)
is.NoError(err)
req.NoError(err)
childVals, ok := v["child"].(map[string]any)
is.True(ok, "child values should be a map")
@ -843,6 +847,7 @@ func TestCoalesceValuesUserNullErasesSubchartDefault(t *testing.T) {
// Regression test for issue #31971.
func TestCoalesceValuesSubchartNilDoesNotShadowGlobal(t *testing.T) {
is := assert.New(t)
req := require.New(t)
subchart := &chart.Chart{
Metadata: &chart.Metadata{Name: "child"},
@ -868,7 +873,7 @@ func TestCoalesceValuesSubchartNilDoesNotShadowGlobal(t *testing.T) {
}
v, err := CoalesceValues(parent, vals)
is.NoError(err)
req.NoError(err)
childVals, ok := v["child"].(map[string]any)
is.True(ok, "child values should be a map")
@ -887,6 +892,7 @@ func TestCoalesceValuesSubchartNilDoesNotShadowGlobal(t *testing.T) {
// the same map. Regression test for the coalesceTablesFullKey merge path.
func TestCoalesceValuesSubchartNilCleanedWhenUserPartiallyOverrides(t *testing.T) {
is := assert.New(t)
req := require.New(t)
subchart := &chart.Chart{
Metadata: &chart.Metadata{Name: "child"},
@ -913,7 +919,7 @@ func TestCoalesceValuesSubchartNilCleanedWhenUserPartiallyOverrides(t *testing.T
}
v, err := CoalesceValues(parent, vals)
is.NoError(err)
req.NoError(err)
childVals, ok := v["child"].(map[string]any)
is.True(ok, "child values should be a map")

@ -22,6 +22,7 @@ import (
"time"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"helm.sh/helm/v4/pkg/chart/v2/lint/support"
chartutil "helm.sh/helm/v4/pkg/chart/v2/util"
@ -130,7 +131,7 @@ func TestBadCrdFile(t *testing.T) {
var values map[string]any
m := RunAll(badCrdFileDir, values, namespace).Messages
assert.Lenf(t, m, 2, "All didn't fail with expected errors, got %#v", m)
assert.ErrorContains(t, m[0].Err, "apiVersion is not in 'apiextensions.k8s.io'")
require.ErrorContains(t, m[0].Err, "apiVersion is not in 'apiextensions.k8s.io'")
assert.ErrorContains(t, m[1].Err, "object kind is not 'CustomResourceDefinition'")
}

@ -92,11 +92,7 @@ func TestValidateValuesFileSchemaFailure(t *testing.T) {
valfile := filepath.Join(tmpdir, "values.yaml")
err := validateValuesFile(valfile, map[string]any{}, false)
if err == nil {
t.Fatal("expected values file to fail parsing")
}
assert.Contains(t, err.Error(), "- at '/username': got number, want string")
assert.ErrorContains(t, err, "- at '/username': got number, want string")
}
func TestValidateValuesFileSchemaFailureButWithSkipSchemaValidation(t *testing.T) {
@ -167,7 +163,7 @@ func TestValidateValuesFile(t *testing.T) {
case err == nil && tt.errorMessage != "":
t.Error("expected values file to fail parsing")
case err != nil && tt.errorMessage != "":
assert.Contains(t, err.Error(), tt.errorMessage, "Failed with unexpected error")
assert.ErrorContains(t, err, tt.errorMessage, "Failed with unexpected error")
}
})
}

@ -224,7 +224,7 @@ func TestReadFile(t *testing.T) {
assert.Error(t, err)
return
}
assert.NoError(t, err)
require.NoError(t, err)
if tt.expectedData != nil {
assert.Equal(t, tt.expectedData, got)
@ -258,8 +258,7 @@ func TestReadFileErrorMessages(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
_, err := readFile(tt.filePath, tt.providers)
require.Error(t, err)
assert.Contains(t, err.Error(), tt.wantErr)
require.ErrorContains(t, err, tt.wantErr)
})
}
}

@ -286,9 +286,9 @@ func TestCmdGetDryRunFlagStrategy(t *testing.T) {
t.Run(name, func(t *testing.T) {
dryRunStrategy, err := cmdGetDryRunFlagStrategy(cmd, tc.IsTemplate)
if tc.ExpectedError {
assert.Error(t, err)
require.Error(t, err)
} else {
assert.NoError(t, err)
require.NoError(t, err)
assert.Equal(t, tc.ExpectedStrategy, dryRunStrategy)
}

@ -451,7 +451,7 @@ func TestReleaseInfoEmptyStringRoundTrip(t *testing.T) {
// Zero time value should be omitted
assert.NotContains(t, result, "updated")
assert.Equal(t, float64(1), result["revision"])
assert.InDelta(t, float64(1), result["revision"], 0.0)
assert.Equal(t, "deployed", result["status"])
assert.Equal(t, "mychart-1.0.0", result["chart"])
}

@ -94,7 +94,7 @@ func TestDiskCache_PutAndGet(t *testing.T) {
// Get should return ErrNotExist for empty files
_, err = cache.Get(emptyKey, CacheChart)
assert.ErrorIs(t, err, os.ErrNotExist, "Get for an empty file should return os.ErrNotExist")
require.ErrorIs(t, err, os.ErrNotExist, "Get for an empty file should return os.ErrNotExist")
// But the file should exist
_, err = os.Stat(path)

@ -26,6 +26,7 @@ import (
"time"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"sigs.k8s.io/yaml"
chart "helm.sh/helm/v4/pkg/chart/v2"
@ -679,7 +680,7 @@ func TestDedupeRepos(t *testing.T) {
func TestWriteLock(t *testing.T) {
fixedTime, err := time.Parse(time.RFC3339, "2025-07-04T00:00:00Z")
assert.NoError(t, err)
require.NoError(t, err)
lock := &chart.Lock{
Generated: fixedTime,
Digest: "sha256:12345",
@ -692,76 +693,75 @@ func TestWriteLock(t *testing.T) {
},
}
expectedContent, err := yaml.Marshal(lock)
assert.NoError(t, err)
require.NoError(t, err)
t.Run("v2 lock file", func(t *testing.T) {
dir := t.TempDir()
err := writeLock(dir, lock, false)
assert.NoError(t, err)
require.NoError(t, err)
lockfilePath := filepath.Join(dir, "Chart.lock")
_, err = os.Stat(lockfilePath)
assert.NoError(t, err, "Chart.lock should exist")
require.NoError(t, err, "Chart.lock should exist")
content, err := os.ReadFile(lockfilePath)
assert.NoError(t, err)
require.NoError(t, err)
assert.Equal(t, expectedContent, content)
// Check that requirements.lock does not exist
_, err = os.Stat(filepath.Join(dir, "requirements.lock"))
assert.Error(t, err)
require.Error(t, err)
assert.True(t, os.IsNotExist(err))
})
t.Run("v1 lock file", func(t *testing.T) {
dir := t.TempDir()
err := writeLock(dir, lock, true)
assert.NoError(t, err)
require.NoError(t, err)
lockfilePath := filepath.Join(dir, "requirements.lock")
_, err = os.Stat(lockfilePath)
assert.NoError(t, err, "requirements.lock should exist")
require.NoError(t, err, "requirements.lock should exist")
content, err := os.ReadFile(lockfilePath)
assert.NoError(t, err)
require.NoError(t, err)
assert.Equal(t, expectedContent, content)
// Check that Chart.lock does not exist
_, err = os.Stat(filepath.Join(dir, "Chart.lock"))
assert.Error(t, err)
require.Error(t, err)
assert.True(t, os.IsNotExist(err))
})
t.Run("overwrite existing lock file", func(t *testing.T) {
dir := t.TempDir()
lockfilePath := filepath.Join(dir, "Chart.lock")
assert.NoError(t, os.WriteFile(lockfilePath, []byte("old content"), 0o644))
require.NoError(t, os.WriteFile(lockfilePath, []byte("old content"), 0o644))
err = writeLock(dir, lock, false)
assert.NoError(t, err)
require.NoError(t, err)
content, err := os.ReadFile(lockfilePath)
assert.NoError(t, err)
require.NoError(t, err)
assert.Equal(t, expectedContent, content)
})
t.Run("lock file is a symlink", func(t *testing.T) {
dir := t.TempDir()
dummyFile := filepath.Join(dir, "dummy.txt")
assert.NoError(t, os.WriteFile(dummyFile, []byte("dummy"), 0o644))
require.NoError(t, os.WriteFile(dummyFile, []byte("dummy"), 0o644))
lockfilePath := filepath.Join(dir, "Chart.lock")
assert.NoError(t, os.Symlink(dummyFile, lockfilePath))
require.NoError(t, os.Symlink(dummyFile, lockfilePath))
err = writeLock(dir, lock, false)
assert.Error(t, err)
assert.Contains(t, err.Error(), "the Chart.lock file is a symlink to")
assert.ErrorContains(t, err, "the Chart.lock file is a symlink to")
})
t.Run("chart path is not a directory", func(t *testing.T) {
dir := t.TempDir()
filePath := filepath.Join(dir, "not-a-dir")
assert.NoError(t, os.WriteFile(filePath, []byte("file"), 0o644))
require.NoError(t, os.WriteFile(filePath, []byte("file"), 0o644))
err = writeLock(filePath, lock, false)
assert.Error(t, err)

@ -135,7 +135,7 @@ keyInElement1 = "valueInElement1"`,
for _, tt := range tests {
var b strings.Builder
err := template.Must(template.New("test").Funcs(funcMap()).Parse(tt.tpl)).Execute(&b, tt.vars)
assert.NoError(t, err)
require.NoError(t, err)
assert.Equal(t, tt.expect, b.String(), tt.tpl)
}
@ -187,7 +187,7 @@ keyInElement1 = "valueInElement1"`,
var b strings.Builder
err := template.Must(template.New("test").Funcs(funcMap()).Parse(tt.tpl)).Execute(&b, tt.vars)
if tt.expect != nil {
assert.NoError(t, err)
require.NoError(t, err)
assert.Equal(t, tt.expect, b.String(), tt.tpl)
} else {
assert.Error(t, err)
@ -475,7 +475,7 @@ func TestMerge(t *testing.T) {
tpl := `{{merge .dst .src1 .src2}}`
var b strings.Builder
err := template.Must(template.New("test").Funcs(funcMap()).Parse(tpl)).Execute(&b, dict)
assert.NoError(t, err)
require.NoError(t, err)
expected := map[string]any{
"a": "one", // key overridden

@ -539,8 +539,7 @@ func TestUpdate(t *testing.T) {
ClientUpdateOptionUpgradeClientSideFieldManager(true))
if tc.ExpectedError != "" {
require.Error(t, err)
require.Contains(t, err.Error(), tc.ExpectedError)
require.ErrorContains(t, err, tc.ExpectedError)
} else {
require.NoError(t, err)
}
@ -558,7 +557,7 @@ func TestUpdate(t *testing.T) {
if tc.ExpectedError != "" {
require.Error(t, err)
require.Contains(t, err.Error(), tc.ExpectedError)
require.ErrorContains(t, err, tc.ExpectedError)
} else {
require.NoError(t, err)
}
@ -968,7 +967,8 @@ func TestGetPodList(t *testing.T) {
podList, err := c.GetPodList(namespace, metav1.ListOptions{})
clientAssertions := assert.New(t)
clientAssertions.NoError(err)
req := require.New(t)
req.NoError(err)
podList.ResourceVersion = ""
clientAssertions.Equal(&responsePodList, podList)
}
@ -983,7 +983,8 @@ func TestOutputContainerLogsForPodList(t *testing.T) {
outBufferFunc := func(_, _, _ string) io.Writer { return outBuffer }
err := c.OutputContainerLogsForPodList(&somePodList, namespace, outBufferFunc)
clientAssertions := assert.New(t)
clientAssertions.NoError(err)
req := require.New(t)
req.NoError(err)
clientAssertions.Equal("fake logsfake logsfake logs", outBuffer.String())
}
@ -1937,7 +1938,7 @@ func TestClientWaitContextCancellationLegacy(t *testing.T) {
err = c.Wait(resources, time.Second*30)
require.Error(t, err)
assert.Contains(t, err.Error(), "context canceled", "expected context canceled error, got: %v", err)
assert.ErrorContains(t, err, "context canceled", "expected context canceled error, got: %v", err)
}
func TestClientWaitWithJobsContextCancellationLegacy(t *testing.T) {
@ -1991,8 +1992,7 @@ func TestClientWaitWithJobsContextCancellationLegacy(t *testing.T) {
assert.Len(t, result.Created, 1, "expected 1 resource created, got %d", len(result.Created))
err = c.WaitWithJobs(resources, time.Second*30)
require.Error(t, err)
assert.Contains(t, err.Error(), "context canceled", "expected context canceled error, got: %v", err)
assert.ErrorContains(t, err, "context canceled", "expected context canceled error, got: %v", err)
}
func TestClientWaitForDeleteContextCancellationLegacy(t *testing.T) {
@ -2056,8 +2056,7 @@ func TestClientWaitForDeleteContextCancellationLegacy(t *testing.T) {
}
err = c.WaitForDelete(resources, time.Second*30)
require.Error(t, err)
assert.Contains(t, err.Error(), "context canceled", "expected context canceled error, got: %v", err)
assert.ErrorContains(t, err, "context canceled", "expected context canceled error, got: %v", err)
}
func TestClientWaitContextNilDoesNotPanic(t *testing.T) {
@ -2164,8 +2163,7 @@ func TestClientWaitContextPreCancelledLegacy(t *testing.T) {
assert.Len(t, result.Created, 1, "expected 1 resource created, got %d", len(result.Created))
err = c.Wait(resources, time.Second*30)
require.Error(t, err)
assert.Contains(t, err.Error(), "context canceled", "expected context canceled error, got: %v", err)
assert.ErrorContains(t, err, "context canceled", "expected context canceled error, got: %v", err)
}
func TestClientWaitContextCancellationStatusWatcher(t *testing.T) {
@ -2191,8 +2189,7 @@ metadata:
cancel()
err = c.Wait(resources, time.Second*30)
require.Error(t, err)
assert.Contains(t, err.Error(), "context canceled", "expected context canceled error, got: %v", err)
assert.ErrorContains(t, err, "context canceled", "expected context canceled error, got: %v", err)
}
func TestClientWaitWithJobsContextCancellationStatusWatcher(t *testing.T) {
@ -2218,8 +2215,7 @@ metadata:
cancel()
err = c.WaitWithJobs(resources, time.Second*30)
require.Error(t, err)
assert.Contains(t, err.Error(), "context canceled", "expected context canceled error, got: %v", err)
assert.ErrorContains(t, err, "context canceled", "expected context canceled error, got: %v", err)
}
func TestClientWaitForDeleteContextCancellationStatusWatcher(t *testing.T) {
@ -2250,8 +2246,7 @@ status:
cancel()
err = c.WaitForDelete(resources, time.Second*30)
require.Error(t, err)
assert.Contains(t, err.Error(), "context canceled", "expected context canceled error, got: %v", err)
assert.ErrorContains(t, err, "context canceled", "expected context canceled error, got: %v", err)
}
// testStatusReader is a custom status reader for testing that returns a configurable status.

@ -273,7 +273,7 @@ func getRuntimeObjFromManifests(t *testing.T, manifests []string) []runtime.Obje
for _, manifest := range manifests {
m := make(map[string]any)
err := yaml.Unmarshal([]byte(manifest), &m)
assert.NoError(t, err)
require.NoError(t, err)
resource := &unstructured.Unstructured{Object: m}
objects = append(objects, resource)
}
@ -285,7 +285,7 @@ func getResourceListFromRuntimeObjs(t *testing.T, c *Client, objs []runtime.Obje
resourceList := ResourceList{}
for _, obj := range objs {
list, err := c.Build(objBody(obj), false)
assert.NoError(t, err)
require.NoError(t, err)
resourceList = append(resourceList, list...)
}
return resourceList
@ -333,7 +333,7 @@ func TestStatusWaitForDelete(t *testing.T) {
u := objToCreate.(*unstructured.Unstructured)
gvr := getGVR(t, fakeMapper, u)
err := fakeClient.Tracker().Create(gvr, u, u.GetNamespace())
assert.NoError(t, err)
require.NoError(t, err)
}
objsToDelete := getRuntimeObjFromManifests(t, tt.manifestsToDelete)
for _, objToDelete := range objsToDelete {
@ -350,7 +350,7 @@ func TestStatusWaitForDelete(t *testing.T) {
if tt.expectErrs != nil {
require.Error(t, err)
for _, expectedErrStr := range tt.expectErrs {
assert.Contains(t, err.Error(), expectedErrStr)
require.ErrorContains(t, err, expectedErrStr)
}
return
}
@ -434,14 +434,14 @@ func TestStatusWait(t *testing.T) {
u := obj.(*unstructured.Unstructured)
gvr := getGVR(t, fakeMapper, u)
err := fakeClient.Tracker().Create(gvr, u, u.GetNamespace())
assert.NoError(t, err)
require.NoError(t, err)
}
resourceList := getResourceListFromRuntimeObjs(t, c, objs)
err := statusWaiter.Wait(resourceList, time.Second*3)
if tt.expectErrStrs != nil {
require.Error(t, err)
for _, expectedErrStr := range tt.expectErrStrs {
assert.Contains(t, err.Error(), expectedErrStr)
require.ErrorContains(t, err, expectedErrStr)
}
return
}
@ -491,14 +491,14 @@ func TestWaitForJobComplete(t *testing.T) {
u := obj.(*unstructured.Unstructured)
gvr := getGVR(t, fakeMapper, u)
err := fakeClient.Tracker().Create(gvr, u, u.GetNamespace())
assert.NoError(t, err)
require.NoError(t, err)
}
resourceList := getResourceListFromRuntimeObjs(t, c, objs)
err := statusWaiter.WaitWithJobs(resourceList, time.Second*3)
if tt.expectErrStrs != nil {
require.Error(t, err)
for _, expectedErrStr := range tt.expectErrStrs {
assert.Contains(t, err.Error(), expectedErrStr)
require.ErrorContains(t, err, expectedErrStr)
}
return
}
@ -554,14 +554,14 @@ func TestWatchForReady(t *testing.T) {
u := obj.(*unstructured.Unstructured)
gvr := getGVR(t, fakeMapper, u)
err := fakeClient.Tracker().Create(gvr, u, u.GetNamespace())
assert.NoError(t, err)
require.NoError(t, err)
}
resourceList := getResourceListFromRuntimeObjs(t, c, objs)
err := statusWaiter.WatchUntilReady(resourceList, time.Second*3)
if tt.expectErrStrs != nil {
require.Error(t, err)
for _, expectedErrStr := range tt.expectErrStrs {
assert.Contains(t, err.Error(), expectedErrStr)
require.ErrorContains(t, err, expectedErrStr)
}
return
}
@ -658,7 +658,7 @@ func TestStatusWaitMultipleNamespaces(t *testing.T) {
u := obj.(*unstructured.Unstructured)
gvr := getGVR(t, fakeMapper, u)
err := fakeClient.Tracker().Create(gvr, u, u.GetNamespace())
assert.NoError(t, err)
require.NoError(t, err)
}
if strings.Contains(tt.name, "delete") {
@ -679,7 +679,7 @@ func TestStatusWaitMultipleNamespaces(t *testing.T) {
if tt.expectErrStrs != nil {
require.Error(t, err)
for _, expectedErrStr := range tt.expectErrStrs {
assert.Contains(t, err.Error(), expectedErrStr)
require.ErrorContains(t, err, expectedErrStr)
}
return
}
@ -840,7 +840,7 @@ func TestStatusWaitRestrictedRBAC(t *testing.T) {
u := obj.(*unstructured.Unstructured)
gvr := getGVR(t, fakeMapper, u)
err := baseFakeClient.Tracker().Create(gvr, u, u.GetNamespace())
assert.NoError(t, err)
require.NoError(t, err)
}
if strings.Contains(tt.name, "delet") {
@ -861,11 +861,11 @@ func TestStatusWaitRestrictedRBAC(t *testing.T) {
if tt.expectErrs != nil {
require.Error(t, err)
for _, expectedErr := range tt.expectErrs {
assert.Contains(t, err.Error(), expectedErr.Error())
require.ErrorContains(t, err, expectedErr.Error())
}
return
}
assert.NoError(t, err)
require.NoError(t, err)
assert.False(t, restrictedConfig.clusterScopedListAttempted)
})
}
@ -948,7 +948,7 @@ func TestStatusWaitMixedResources(t *testing.T) {
u := obj.(*unstructured.Unstructured)
gvr := getGVR(t, fakeMapper, u)
err := baseFakeClient.Tracker().Create(gvr, u, u.GetNamespace())
assert.NoError(t, err)
require.NoError(t, err)
}
if strings.Contains(tt.name, "delet") {
@ -969,11 +969,11 @@ func TestStatusWaitMixedResources(t *testing.T) {
if tt.expectErrs != nil {
require.Error(t, err)
for _, expectedErr := range tt.expectErrs {
assert.Contains(t, err.Error(), expectedErr.Error())
require.ErrorContains(t, err, expectedErr.Error())
}
return
}
assert.NoError(t, err)
require.NoError(t, err)
assert.False(t, restrictedConfig.clusterScopedListAttempted)
})
}
@ -1068,14 +1068,14 @@ func TestStatusWaitWithCustomReaders(t *testing.T) {
u := obj.(*unstructured.Unstructured)
gvr := getGVR(t, fakeMapper, u)
err := fakeClient.Tracker().Create(gvr, u, u.GetNamespace())
assert.NoError(t, err)
require.NoError(t, err)
}
resourceList := getResourceListFromRuntimeObjs(t, c, objs)
err := statusWaiter.Wait(resourceList, time.Second*3)
if tt.expectErrStrs != nil {
require.Error(t, err)
for _, expectedErrStr := range tt.expectErrStrs {
assert.Contains(t, err.Error(), expectedErrStr)
require.ErrorContains(t, err, expectedErrStr)
}
return
}
@ -1140,7 +1140,7 @@ func TestStatusWaitWithJobsAndCustomReaders(t *testing.T) {
u := obj.(*unstructured.Unstructured)
gvr := getGVR(t, fakeMapper, u)
err := fakeClient.Tracker().Create(gvr, u, u.GetNamespace())
assert.NoError(t, err)
require.NoError(t, err)
}
resourceList := getResourceListFromRuntimeObjs(t, c, objs)
err := statusWaiter.WaitWithJobs(resourceList, time.Second*3)
@ -1239,14 +1239,14 @@ func TestStatusWaitWithFailedResources(t *testing.T) {
u := obj.(*unstructured.Unstructured)
gvr := getGVR(t, fakeMapper, u)
err := fakeClient.Tracker().Create(gvr, u, u.GetNamespace())
assert.NoError(t, err)
require.NoError(t, err)
}
resourceList := getResourceListFromRuntimeObjs(t, c, objs)
err := tt.testFunc(&sw, resourceList, time.Second*3)
if tt.expectErrStrs != nil {
require.Error(t, err)
for _, expectedErrStr := range tt.expectErrStrs {
assert.Contains(t, err.Error(), expectedErrStr)
require.ErrorContains(t, err, expectedErrStr)
}
return
}
@ -1328,8 +1328,7 @@ func TestMethodSpecificContextCancellation(t *testing.T) {
err := sw.WatchUntilReady(resourceList, time.Second*3)
// Should fail due to cancelled method context
require.Error(t, err)
assert.Contains(t, err.Error(), "context canceled")
assert.ErrorContains(t, err, "context canceled")
})
t.Run("Wait uses method-specific context", func(t *testing.T) {
@ -1362,8 +1361,7 @@ func TestMethodSpecificContextCancellation(t *testing.T) {
err := sw.Wait(resourceList, time.Second*3)
// Should fail due to cancelled method context
require.Error(t, err)
assert.Contains(t, err.Error(), "context canceled")
assert.ErrorContains(t, err, "context canceled")
})
t.Run("WaitWithJobs uses method-specific context", func(t *testing.T) {
@ -1396,8 +1394,7 @@ func TestMethodSpecificContextCancellation(t *testing.T) {
err := sw.WaitWithJobs(resourceList, time.Second*3)
// Should fail due to cancelled method context
require.Error(t, err)
assert.Contains(t, err.Error(), "context canceled")
assert.ErrorContains(t, err, "context canceled")
})
t.Run("WaitForDelete uses method-specific context", func(t *testing.T) {
@ -1430,8 +1427,7 @@ func TestMethodSpecificContextCancellation(t *testing.T) {
err := sw.WaitForDelete(resourceList, time.Second*3)
// Should fail due to cancelled method context
require.Error(t, err)
assert.Contains(t, err.Error(), "context canceled")
assert.ErrorContains(t, err, "context canceled")
})
}
@ -1468,8 +1464,7 @@ func TestMethodContextFallbackToGeneralContext(t *testing.T) {
err := sw.WatchUntilReady(resourceList, time.Second*3)
// Should fail due to cancelled general context
require.Error(t, err)
assert.Contains(t, err.Error(), "context canceled")
assert.ErrorContains(t, err, "context canceled")
})
t.Run("Wait falls back to general context when method context is nil", func(t *testing.T) {
@ -1502,8 +1497,7 @@ func TestMethodContextFallbackToGeneralContext(t *testing.T) {
err := sw.Wait(resourceList, time.Second*3)
// Should fail due to cancelled general context
require.Error(t, err)
assert.Contains(t, err.Error(), "context canceled")
assert.ErrorContains(t, err, "context canceled")
})
t.Run("WaitWithJobs falls back to general context when method context is nil", func(t *testing.T) {
@ -1536,8 +1530,7 @@ func TestMethodContextFallbackToGeneralContext(t *testing.T) {
err := sw.WaitWithJobs(resourceList, time.Second*3)
// Should fail due to cancelled general context
require.Error(t, err)
assert.Contains(t, err.Error(), "context canceled")
assert.ErrorContains(t, err, "context canceled")
})
t.Run("WaitForDelete falls back to general context when method context is nil", func(t *testing.T) {
@ -1570,8 +1563,7 @@ func TestMethodContextFallbackToGeneralContext(t *testing.T) {
err := sw.WaitForDelete(resourceList, time.Second*3)
// Should fail due to cancelled general context
require.Error(t, err)
assert.Contains(t, err.Error(), "context canceled")
assert.ErrorContains(t, err, "context canceled")
})
}
@ -1788,14 +1780,14 @@ func TestWatchUntilReadyWithCustomReaders(t *testing.T) {
u := obj.(*unstructured.Unstructured)
gvr := getGVR(t, fakeMapper, u)
err := fakeClient.Tracker().Create(gvr, u, u.GetNamespace())
assert.NoError(t, err)
require.NoError(t, err)
}
resourceList := getResourceListFromRuntimeObjs(t, c, objs)
err := statusWaiter.WatchUntilReady(resourceList, time.Second*3)
if tt.expectErrStrs != nil {
require.Error(t, err)
for _, expectedErrStr := range tt.expectErrStrs {
assert.Contains(t, err.Error(), expectedErrStr)
require.ErrorContains(t, err, expectedErrStr)
}
return
}

@ -23,6 +23,7 @@ import (
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
appsv1 "k8s.io/api/apps/v1"
appsv1beta1 "k8s.io/api/apps/v1beta1"
appsv1beta2 "k8s.io/api/apps/v1beta2"
@ -227,10 +228,9 @@ func TestSelectorsForObject(t *testing.T) {
t.Run(tt.name, func(t *testing.T) {
selector, err := SelectorsForObject(tt.object.(runtime.Object))
if tt.expectError {
assert.Error(t, err)
assert.Contains(t, err.Error(), tt.errorContains)
require.ErrorContains(t, err, tt.errorContains)
} else {
assert.NoError(t, err)
require.NoError(t, err)
expected := labels.Set(tt.expectedLabels)
assert.True(t, selector.Matches(expected), "expected selector to match")
}

@ -50,15 +50,16 @@ func TestNewPostRenderPluginWithOneArgsRun(t *testing.T) {
t.Skip("skipping on windows")
}
is := assert.New(t)
req := require.New(t)
s := cli.New()
s.PluginsDirectory = "testdata/plugins"
name := "postrenderer-v1"
renderer, err := NewPostRendererPlugin(s, name, "ARG1")
require.NoError(t, err)
req.NoError(err)
output, err := renderer.Run(bytes.NewBufferString("FOOTEST"))
is.NoError(err)
req.NoError(err)
is.Contains(output.String(), "ARG1")
}
@ -68,14 +69,15 @@ func TestNewPostRenderPluginWithTwoArgsRun(t *testing.T) {
t.Skip("skipping on windows")
}
is := assert.New(t)
req := require.New(t)
s := cli.New()
s.PluginsDirectory = "testdata/plugins"
name := "postrenderer-v1"
renderer, err := NewPostRendererPlugin(s, name, "ARG1", "ARG2")
require.NoError(t, err)
req.NoError(err)
output, err := renderer.Run(bytes.NewBufferString("FOOTEST"))
is.NoError(err)
req.NoError(err)
is.Contains(output.String(), "ARG1 ARG2")
}

@ -237,7 +237,7 @@ func TestGenerateOCICreatedAnnotations(t *testing.T) {
// Verify value of created artifact in RFC3339 format
_, err := time.Parse(time.RFC3339, result[ocispec.AnnotationCreated])
assert.NoError(t, err, "%s annotation with value '%s' not in RFC3339 format", ocispec.AnnotationCreated, result[ocispec.AnnotationCreated])
require.NoError(t, err, "%s annotation with value '%s' not in RFC3339 format", ocispec.AnnotationCreated, result[ocispec.AnnotationCreated])
// Verify default creation time set
result = generateOCIAnnotations(testChart, "")

@ -59,7 +59,7 @@ func (suite *RegistryScopeTestSuite) Test_1_Check_Push_Request_Scope() {
})
lnCfg := net.ListenConfig{}
listener, err := lnCfg.Listen(suite.T().Context(), "tcp", suite.AuthServerHost)
suite.NoError(err, "no error creating server listener")
suite.Require().NoError(err, "no error creating server listener")
ts := httptest.NewUnstartedServer(handler)
ts.Listener = listener
@ -69,18 +69,18 @@ func (suite *RegistryScopeTestSuite) Test_1_Check_Push_Request_Scope() {
// basic push, good ref
testingChartCreationTime := "1977-09-02T22:04:05Z"
chartData, err := os.ReadFile("../downloader/testdata/local-subchart-0.1.0.tgz")
suite.NoError(err, "no error loading test chart")
suite.Require().NoError(err, "no error loading test chart")
meta, err := extractChartMeta(chartData)
suite.NoError(err, "no error extracting chart meta")
suite.Require().NoError(err, "no error extracting chart meta")
ref := fmt.Sprintf("%s/testrepo/%s:%s", suite.DockerRegistryHost, meta.Name, meta.Version)
_, err = suite.RegistryClient.Push(chartData, ref, PushOptCreationTime(testingChartCreationTime))
suite.Error(err, "error pushing good ref because auth server doesn't give proper token")
suite.Require().Error(err, "error pushing good ref because auth server doesn't give proper token")
//check the url that authentication server received
select {
case urlStr := <-requestURL:
u, err := url.Parse(urlStr)
suite.NoError(err, "no error parsing requested URL")
suite.Require().NoError(err, "no error parsing requested URL")
suite.Equal("/auth", u.Path)
suite.Equal("testservice", u.Query().Get("service"))
@ -105,7 +105,7 @@ func (suite *RegistryScopeTestSuite) Test_2_Check_Pull_Request_Scope() {
})
lnCfg := net.ListenConfig{}
listener, err := lnCfg.Listen(suite.T().Context(), "tcp", suite.AuthServerHost)
suite.NoError(err, "no error creating server listener")
suite.Require().NoError(err, "no error creating server listener")
ts := httptest.NewUnstartedServer(handler)
ts.Listener = listener
@ -115,18 +115,18 @@ func (suite *RegistryScopeTestSuite) Test_2_Check_Pull_Request_Scope() {
// Load test chart (to build ref pushed in previous test)
// Simple pull, chart only
chartData, err := os.ReadFile("../downloader/testdata/local-subchart-0.1.0.tgz")
suite.NoError(err, "no error loading test chart")
suite.Require().NoError(err, "no error loading test chart")
meta, err := extractChartMeta(chartData)
suite.NoError(err, "no error extracting chart meta")
suite.Require().NoError(err, "no error extracting chart meta")
ref := fmt.Sprintf("%s/testrepo/%s:%s", suite.DockerRegistryHost, meta.Name, meta.Version)
_, err = suite.RegistryClient.Pull(ref)
suite.Error(err, "error pulling a simple chart because auth server doesn't give proper token")
suite.Require().Error(err, "error pulling a simple chart because auth server doesn't give proper token")
//check the url that authentication server received
select {
case urlStr := <-requestURL:
u, err := url.Parse(urlStr)
suite.NoError(err, "no error parsing requested URL")
suite.Require().NoError(err, "no error parsing requested URL")
suite.Equal("/auth", u.Path)
suite.Equal("testservice", u.Query().Get("service"))

@ -20,6 +20,7 @@ import (
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func verify(t *testing.T, actual reference, registry, repository, tag, digest string) {
@ -45,30 +46,30 @@ func verify(t *testing.T, actual reference, registry, repository, tag, digest st
func TestNewReference(t *testing.T) {
actual, err := newReference("registry.example.com/repository:1.0@sha256:c6841b3a895f1444a6738b5d04564a57e860ce42f8519c3be807fb6d9bee7888")
assert.NoError(t, err)
require.NoError(t, err)
verify(t, actual, "registry.example.com", "repository", "1.0", "sha256:c6841b3a895f1444a6738b5d04564a57e860ce42f8519c3be807fb6d9bee7888")
actual, err = newReference("oci://registry.example.com/repository:1.0@sha256:c6841b3a895f1444a6738b5d04564a57e860ce42f8519c3be807fb6d9bee7888")
assert.NoError(t, err)
require.NoError(t, err)
verify(t, actual, "registry.example.com", "repository", "1.0", "sha256:c6841b3a895f1444a6738b5d04564a57e860ce42f8519c3be807fb6d9bee7888")
actual, err = newReference("a/b:1@c")
assert.NoError(t, err)
require.NoError(t, err)
verify(t, actual, "a", "b", "1", "c")
actual, err = newReference("a/b:@")
assert.NoError(t, err)
require.NoError(t, err)
verify(t, actual, "a", "b", "", "")
actual, err = newReference("registry.example.com/repository:1.0+001")
assert.NoError(t, err)
require.NoError(t, err)
verify(t, actual, "registry.example.com", "repository", "1.0_001", "")
actual, err = newReference("thing:1.0")
assert.Error(t, err)
require.Error(t, err)
verify(t, actual, "", "", "", "")
actual, err = newReference("registry.example.com/the/repository@sha256:c6841b3a895f1444a6738b5d04564a57e860ce42f8519c3be807fb6d9bee7888")
assert.NoError(t, err)
require.NoError(t, err)
verify(t, actual, "registry.example.com", "the/repository", "", "sha256:c6841b3a895f1444a6738b5d04564a57e860ce42f8519c3be807fb6d9bee7888")
}

@ -560,9 +560,9 @@ func testPull(suite *TestRegistry) {
suite.Equal(
"sha256:b0a02b7412f78ae93324d48df8fcc316d8482e5ad7827b5b238657a29a22f256",
result.Prov.Digest)
suite.Equal("{\"schemaVersion\":2,\"config\":{\"mediaType\":\"application/vnd.cncf.helm.config.v1+json\",\"digest\":\"sha256:8d17cb6bf6ccd8c29aace9a658495cbd5e2e87fc267876e86117c7db681c9580\",\"size\":99},\"layers\":[{\"mediaType\":\"application/vnd.cncf.helm.chart.provenance.v1.prov\",\"digest\":\"sha256:b0a02b7412f78ae93324d48df8fcc316d8482e5ad7827b5b238657a29a22f256\",\"size\":695},{\"mediaType\":\"application/vnd.cncf.helm.chart.content.v1.tar+gzip\",\"digest\":\"sha256:e5ef611620fb97704d8751c16bab17fedb68883bfb0edc76f78a70e9173f9b55\",\"size\":973}],\"annotations\":{\"org.opencontainers.image.created\":\"1977-09-02T22:04:05Z\",\"org.opencontainers.image.description\":\"A Helm chart for Kubernetes\",\"org.opencontainers.image.title\":\"signtest\",\"org.opencontainers.image.version\":\"0.1.0\"}}",
suite.JSONEq("{\"schemaVersion\":2,\"config\":{\"mediaType\":\"application/vnd.cncf.helm.config.v1+json\",\"digest\":\"sha256:8d17cb6bf6ccd8c29aace9a658495cbd5e2e87fc267876e86117c7db681c9580\",\"size\":99},\"layers\":[{\"mediaType\":\"application/vnd.cncf.helm.chart.provenance.v1.prov\",\"digest\":\"sha256:b0a02b7412f78ae93324d48df8fcc316d8482e5ad7827b5b238657a29a22f256\",\"size\":695},{\"mediaType\":\"application/vnd.cncf.helm.chart.content.v1.tar+gzip\",\"digest\":\"sha256:e5ef611620fb97704d8751c16bab17fedb68883bfb0edc76f78a70e9173f9b55\",\"size\":973}],\"annotations\":{\"org.opencontainers.image.created\":\"1977-09-02T22:04:05Z\",\"org.opencontainers.image.description\":\"A Helm chart for Kubernetes\",\"org.opencontainers.image.title\":\"signtest\",\"org.opencontainers.image.version\":\"0.1.0\"}}",
string(result.Manifest.Data))
suite.Equal("{\"name\":\"signtest\",\"version\":\"0.1.0\",\"description\":\"A Helm chart for Kubernetes\",\"apiVersion\":\"v1\"}",
suite.JSONEq("{\"name\":\"signtest\",\"version\":\"0.1.0\",\"description\":\"A Helm chart for Kubernetes\",\"apiVersion\":\"v1\"}",
string(result.Config.Data))
suite.Equal(chartData, result.Chart.Data)
suite.Equal(provData, result.Prov.Data)

@ -19,6 +19,7 @@ package registry
import (
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
@ -61,15 +62,14 @@ func TestGetTagMatchingVersionOrConstraint_InvalidConstraint(t *testing.T) {
func TestGetTagMatchingVersionOrConstraint_NoMatches(t *testing.T) {
tags := []string{"0.1.0", "0.2.0"}
_, err := GetTagMatchingVersionOrConstraint(tags, ">=1.0.0")
require.Error(t, err, "expected error when no tags match")
require.Contains(t, err.Error(), ">=1.0.0", "expected error to contain version string")
assert.ErrorContains(t, err, ">=1.0.0", "expected error to contain version string")
}
func TestGetTagMatchingVersionOrConstraint_SkipsNonSemverTags(t *testing.T) {
tags := []string{"alpha", "1.0.0", "beta", "1.1.0"}
got, err := GetTagMatchingVersionOrConstraint(tags, ">=1.0.0 <2.0.0")
require.NoError(t, err)
require.Equal(t, "1.0.0", got)
assert.Equal(t, "1.0.0", got)
}
func TestGetTagMatchingVersionOrConstraint_OrderMatters_FirstMatchReturned(t *testing.T) {
@ -77,7 +77,7 @@ func TestGetTagMatchingVersionOrConstraint_OrderMatters_FirstMatchReturned(t *te
tags := []string{"1.3.0", "1.2.0"}
got, err := GetTagMatchingVersionOrConstraint(tags, ">=1.2.0 <2.0.0")
require.NoError(t, err)
require.Equal(t, "1.3.0", got, "first satisfying tag")
assert.Equal(t, "1.3.0", got, "first satisfying tag")
}
func TestGetTagMatchingVersionOrConstraint_ExactMatchHasPrecedence(t *testing.T) {
@ -85,5 +85,5 @@ func TestGetTagMatchingVersionOrConstraint_ExactMatchHasPrecedence(t *testing.T)
tags := []string{"1.3.0", "1.2.3"}
got, err := GetTagMatchingVersionOrConstraint(tags, "1.2.3")
require.NoError(t, err)
require.Equal(t, "1.2.3", got, "expected exact match")
assert.Equal(t, "1.2.3", got, "expected exact match")
}

@ -21,6 +21,7 @@ import (
"time"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
v2release "helm.sh/helm/v4/internal/release/v2"
"helm.sh/helm/v4/pkg/release/common"
@ -31,6 +32,7 @@ func TestNewDefaultAccessor(t *testing.T) {
// Testing the default implementation rather than NewAccessor which can be
// overridden by developers.
is := assert.New(t)
req := require.New(t)
// Create release
info := &rspb.Info{Status: common.StatusDeployed, LastDeployed: time.Now().Add(1000)}
@ -55,7 +57,7 @@ func TestNewDefaultAccessor(t *testing.T) {
// can't be used with interfaces. The accessors enable access to the underlying data
// in a manner that works with Go interfaces.
accessor, err := newDefaultAccessor(rel)
is.NoError(err)
req.NoError(err)
// Verify information
is.Equal(rel.Name, accessor.Name())
@ -68,6 +70,7 @@ func TestNewDefaultAccessor(t *testing.T) {
func TestNewDefaultAccessorV2(t *testing.T) {
// Testing the default implementation for v2 releases (charts/v3)
is := assert.New(t)
req := require.New(t)
// Create v2 release
info := &v2release.Info{Status: common.StatusDeployed, LastDeployed: time.Now().Add(1000), Notes: "test notes"}
@ -93,7 +96,7 @@ func TestNewDefaultAccessorV2(t *testing.T) {
// Test accessor creation
accessor, err := newDefaultAccessor(rel)
is.NoError(err)
req.NoError(err)
// Verify all accessor methods return correct values
is.Equal(rel.Name, accessor.Name())
@ -112,7 +115,7 @@ func TestNewDefaultAccessorV2(t *testing.T) {
// Test hook accessor
hookAccessor, err := newDefaultHookAccessor(hooks[0])
is.NoError(err)
req.NoError(err)
is.Equal("templates/hook.yaml", hookAccessor.Path())
is.Equal("hook manifest", hookAccessor.Manifest())
}
@ -120,6 +123,7 @@ func TestNewDefaultAccessorV2(t *testing.T) {
func TestNewDefaultAccessorV2ByValue(t *testing.T) {
// Test that passing v2 release by value also works
is := assert.New(t)
req := require.New(t)
info := &v2release.Info{Status: common.StatusDeployed, LastDeployed: time.Now()}
rel := v2release.Release{
@ -130,6 +134,6 @@ func TestNewDefaultAccessorV2ByValue(t *testing.T) {
}
accessor, err := newDefaultAccessor(rel)
is.NoError(err)
req.NoError(err)
is.Equal("test-release", accessor.Name())
}

@ -21,7 +21,7 @@ import (
"reflect"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"helm.sh/helm/v4/pkg/release"
"helm.sh/helm/v4/pkg/release/common"
@ -296,7 +296,7 @@ func TestMemoryDelete(t *testing.T) {
t.Errorf("expected end to be %d instead of %d", startLen-2, endLen)
for _, ee := range end {
rac, err := release.NewAccessor(ee)
assert.NoError(t, err, "unable to get release accessor")
require.NoError(t, err, "unable to get release accessor")
t.Logf("Name: %s, Version: %d", rac.Name(), rac.Version())
}
}

@ -24,7 +24,7 @@ import (
"reflect"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"helm.sh/helm/v4/pkg/release"
"helm.sh/helm/v4/pkg/release/common"
@ -113,7 +113,7 @@ func TestStorageDelete(t *testing.T) {
}
rhist, err := releaseListToV1List(hist)
assert.NoError(t, err)
require.NoError(t, err)
// We have now deleted one of the two records.
if len(rhist) != 1 {
@ -204,7 +204,7 @@ func TestStorageDeployed(t *testing.T) {
}
rel, err := releaserToV1Release(rls)
assert.NoError(t, err)
require.NoError(t, err)
switch {
case rls == nil:
@ -247,7 +247,7 @@ func TestStorageDeployedWithCorruption(t *testing.T) {
}
rel, err := releaserToV1Release(rls)
assert.NoError(t, err)
require.NoError(t, err)
switch {
case rls == nil:
@ -387,12 +387,10 @@ func TestStorageRemoveLeastRecent(t *testing.T) {
// On inserting the 5th record, we expect two records to be pruned from history.
hist, err := storage.History(name)
assert.NoError(t, err)
require.NoError(t, err)
rhist, err := releaseListToV1List(hist)
assert.NoError(t, err)
if err != nil {
t.Fatal(err)
} else if len(rhist) != storage.MaxHistory {
require.NoError(t, err)
if len(rhist) != storage.MaxHistory {
for _, item := range rhist {
t.Logf("%s %v", item.Name, item.Version)
}
@ -440,7 +438,7 @@ func TestStorageDoNotDeleteDeployed(t *testing.T) {
t.Fatal(err)
} else if len(hist) != storage.MaxHistory {
rhist, err := releaseListToV1List(hist)
assert.NoError(t, err)
require.NoError(t, err)
for _, item := range rhist {
t.Logf("%s %v", item.Name, item.Version)
}
@ -454,7 +452,7 @@ func TestStorageDoNotDeleteDeployed(t *testing.T) {
}
rhist, err := releaseListToV1List(hist)
assert.NoError(t, err)
require.NoError(t, err)
for _, item := range rhist {
if !expectedVersions[item.Version] {
t.Errorf("Release version %d, found when not expected", item.Version)
@ -490,7 +488,7 @@ func TestStorageLast(t *testing.T) {
}
rel, err := releaserToV1Release(h)
assert.NoError(t, err)
require.NoError(t, err)
if rel.Version != 4 {
t.Errorf("Expected revision 4, got %d", rel.Version)
@ -544,7 +542,7 @@ func TestUpgradeInitiallyFailedReleaseWithHistoryLimit(t *testing.T) {
}
rhist, err := releaseListToV1List(hist)
assert.NoError(t, err)
require.NoError(t, err)
for i, rel := range rhist {
wantVersion := i + 2
if rel.Version != wantVersion {

@ -451,9 +451,7 @@ func TestParseLiteralNestedLevels(t *testing.T) {
if err != nil {
if tt.err {
if tt.errStr != "" {
if err.Error() != tt.errStr {
assert.Equal(t, tt.errStr, err.Error())
}
require.EqualError(t, err, tt.errStr)
}
continue
}
@ -468,9 +466,7 @@ func TestParseLiteralNestedLevels(t *testing.T) {
require.NoError(t, err)
y2, err := yaml.Marshal(got)
if err != nil {
require.NoError(t, err, "Error serializing parsed value")
}
require.NoError(t, err, "Error serializing parsed value")
if !bytes.Equal(y1, y2) {
assert.Equal(t, string(y1), string(y2), tt.str)

@ -779,9 +779,7 @@ func TestParseSetNestedLevels(t *testing.T) {
if err != nil {
if tt.err {
if tt.errStr != "" {
if err.Error() != tt.errStr {
assert.Equal(t, tt.errStr, err.Error())
}
require.EqualError(t, err, tt.errStr)
}
continue
}
@ -794,9 +792,7 @@ func TestParseSetNestedLevels(t *testing.T) {
y1, err := yaml.Marshal(tt.expect)
require.NoError(t, err)
y2, err := yaml.Marshal(got)
if err != nil {
require.NoError(t, err, "Error serializing parsed value")
}
require.NoError(t, err, "Error serializing parsed value")
if !bytes.Equal(y1, y2) {
assert.Equal(t, string(y1), string(y2), tt.str)

Loading…
Cancel
Save