Files
fleet/pkg/str/str_test.go
T
Juan Fernandez 5368b99636 Policy status page: automation activity history, reset endpoint, and details UI
Resolves #38670 

Adds the backend and frontend for the Policy status page — a historical, per-host view of policy automation outcomes — plus a way to reset a policy's results.
2026-06-19 12:13:36 -04:00

223 lines
5.1 KiB
Go

package str
import (
"strings"
"testing"
"unicode/utf8"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestSplitAndTrim(t *testing.T) {
tests := []struct {
name string
testString string
delimiter string
removeEmpty bool
expected []string
}{
{
name: "basic comma split",
testString: "a,b,c",
delimiter: ",",
removeEmpty: false,
expected: []string{"a", "b", "c"},
},
{
name: "trims whitespace",
testString: " a , b , c ",
delimiter: ",",
removeEmpty: false,
expected: []string{"a", "b", "c"},
},
{
name: "keeps empty parts when removeEmpty is false",
testString: "a,,b,,c",
delimiter: ",",
removeEmpty: false,
expected: []string{"a", "", "b", "", "c"},
},
{
name: "removes empty parts when removeEmpty is true",
testString: "a,,b,,c",
delimiter: ",",
removeEmpty: true,
expected: []string{"a", "b", "c"},
},
{
name: "removes whitespace-only parts when removeEmpty is true",
testString: "a, ,b, ,c",
delimiter: ",",
removeEmpty: true,
expected: []string{"a", "b", "c"},
},
{
name: "empty string",
testString: "",
delimiter: ",",
removeEmpty: true,
expected: []string{},
},
{
name: "empty string without removeEmpty",
testString: "",
delimiter: ",",
removeEmpty: false,
expected: []string{""},
},
{
name: "no delimiter found",
testString: "abc",
delimiter: ",",
removeEmpty: false,
expected: []string{"abc"},
},
{
name: "multi-char delimiter",
testString: "a::b::c",
delimiter: "::",
removeEmpty: false,
expected: []string{"a", "b", "c"},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
result := SplitAndTrim(tt.testString, tt.delimiter, tt.removeEmpty)
assert.Equal(t, tt.expected, result)
})
}
}
func TestParseUintList(t *testing.T) {
tests := []struct {
name string
input string
expected []uint
}{
{
name: "empty string returns nil",
input: "",
expected: nil,
},
{
name: "single value",
input: "42",
expected: []uint{42},
},
{
name: "multiple values",
input: "1,2,3",
expected: []uint{1, 2, 3},
},
{
name: "trims whitespace",
input: " 1 , 2 , 3 ",
expected: []uint{1, 2, 3},
},
{
name: "skips non-numeric values",
input: "1,abc,2,,3",
expected: []uint{1, 2, 3},
},
{
name: "skips negative values",
input: "1,-2,3",
expected: []uint{1, 3},
},
{
name: "all invalid returns empty slice",
input: "a,b,c",
expected: []uint{},
},
{
name: "zero is valid",
input: "0,1",
expected: []uint{0, 1},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
result := ParseUintList(tt.input)
assert.Equal(t, tt.expected, result)
})
}
}
func TestTruncateErrorResponse(t *testing.T) {
t.Run("short string passes through unchanged", func(t *testing.T) {
require.Equal(t, "hello", TruncateErrorResponse("hello"))
})
t.Run("exactly at limit passes through unchanged", func(t *testing.T) {
s := strings.Repeat("x", MaxErrorResponseBytes)
result := TruncateErrorResponse(s)
require.Equal(t, s, result)
require.False(t, strings.HasSuffix(result, " [truncated]"))
})
t.Run("one byte over limit is truncated", func(t *testing.T) {
s := strings.Repeat("x", MaxErrorResponseBytes+1)
result := TruncateErrorResponse(s)
require.True(t, strings.HasSuffix(result, " [truncated]"))
require.LessOrEqual(t, len(result), MaxErrorResponseBytes+len(" [truncated]"))
})
t.Run("result is always valid UTF-8", func(t *testing.T) {
// Build a string that is over the limit and ends with a partial multi-byte rune
// at the cut point. U+1F600 (😀) encodes as 4 bytes; place it straddling the limit.
prefix := strings.Repeat("a", MaxErrorResponseBytes-1)
s := prefix + "😀" + strings.Repeat("b", 100)
result := TruncateErrorResponse(s)
assert.True(t, utf8.ValidString(result), "result must be valid UTF-8")
assert.True(t, strings.HasSuffix(result, " [truncated]"))
})
t.Run("empty string passes through unchanged", func(t *testing.T) {
require.Empty(t, TruncateErrorResponse(""))
})
}
func TestParseStringList(t *testing.T) {
tests := []struct {
name string
input string
expected []string
}{
{
name: "empty string returns nil",
input: "",
expected: nil,
},
{
name: "single value",
input: "foo",
expected: []string{"foo"},
},
{
name: "multiple values",
input: "foo,bar,baz",
expected: []string{"foo", "bar", "baz"},
},
{
name: "trims whitespace",
input: " foo , bar , baz ",
expected: []string{"foo", "bar", "baz"},
},
{
name: "drops empty values",
input: "foo,,bar, ,baz",
expected: []string{"foo", "bar", "baz"},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
result := ParseStringList(tt.input)
assert.Equal(t, tt.expected, result)
})
}
}