-
Notifications
You must be signed in to change notification settings - Fork 13
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
BE-636-domain-packages | Add number package, introduce http helper (#572
- Loading branch information
1 parent
0500a54
commit 022c635
Showing
9 changed files
with
292 additions
and
59 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
package http | ||
|
||
import ( | ||
"strconv" | ||
|
||
"github.com/labstack/echo/v4" | ||
) | ||
|
||
// ParseBooleanQueryParam parses a boolean query parameter. | ||
// Returns false if the parameter is not present. | ||
// Errors if the value is not a valid boolean. | ||
// Returns the boolean value and an error if any. | ||
func ParseBooleanQueryParam(c echo.Context, paramName string) (paramValue bool, err error) { | ||
paramValueStr := c.QueryParam(paramName) | ||
if paramValueStr != "" { | ||
paramValue, err = strconv.ParseBool(paramValueStr) | ||
if err != nil { | ||
return false, err | ||
} | ||
} | ||
|
||
return paramValue, nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
package http | ||
|
||
import ( | ||
"net/http" | ||
"net/http/httptest" | ||
"testing" | ||
|
||
"github.com/labstack/echo/v4" | ||
"github.com/stretchr/testify/require" | ||
) | ||
|
||
func TestParseBooleanQueryParam(t *testing.T) { | ||
tests := []struct { | ||
name string | ||
queryParam string | ||
expectedValue bool | ||
expectedError bool | ||
}{ | ||
{"True value", "param=true", true, false}, | ||
{"False value", "param=false", false, false}, | ||
{"1 as true", "param=1", true, false}, | ||
{"0 as false", "param=0", false, false}, | ||
{"Empty value", "", false, false}, | ||
{"Invalid value", "param=invalid", false, true}, | ||
} | ||
|
||
for _, tt := range tests { | ||
t.Run(tt.name, func(t *testing.T) { | ||
// Setup | ||
e := echo.New() | ||
req := httptest.NewRequest(http.MethodGet, "/?"+tt.queryParam, nil) | ||
rec := httptest.NewRecorder() | ||
c := e.NewContext(req, rec) | ||
|
||
// Test | ||
value, err := ParseBooleanQueryParam(c, "param") | ||
|
||
// Assert | ||
if tt.expectedError { | ||
require.Error(t, err) | ||
} else { | ||
require.NoError(t, err) | ||
require.Equal(t, tt.expectedValue, value) | ||
} | ||
}) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
// Package number provides utility functions for working with numbers. | ||
package number | ||
|
||
import ( | ||
"strconv" | ||
"strings" | ||
) | ||
|
||
// ParseNumbers parses a comma-separated list of numbers into a slice of unit64. | ||
func ParseNumbers(numbersParam string) ([]uint64, error) { | ||
var numbers []uint64 | ||
numStrings := splitAndTrim(numbersParam, ",") | ||
|
||
for _, numStr := range numStrings { | ||
num, err := strconv.ParseUint(numStr, 10, 64) | ||
if err != nil { | ||
return nil, err | ||
} | ||
numbers = append(numbers, num) | ||
} | ||
|
||
return numbers, nil | ||
} | ||
|
||
// ParseNumberType parses a comma-separated list of numbers into a slice of the specified type. | ||
func ParseNumberType[T any](numbersParam string, parseFn func(s string) (T, error)) ([]T, error) { | ||
numStrings := splitAndTrim(numbersParam, ",") | ||
|
||
var numbers []T | ||
for _, numStr := range numStrings { | ||
num, err := parseFn(numStr) | ||
if err != nil { | ||
return nil, err | ||
} | ||
numbers = append(numbers, num) | ||
} | ||
|
||
return numbers, nil | ||
} | ||
|
||
// splitAndTrim splits a string by a separator and trims the resulting strings. | ||
func splitAndTrim(s, sep string) []string { | ||
var result []string | ||
for _, val := range strings.Split(s, sep) { | ||
trimmed := strings.TrimSpace(val) | ||
if trimmed != "" { | ||
result = append(result, trimmed) | ||
} | ||
} | ||
return result | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,159 @@ | ||
package number | ||
|
||
import ( | ||
"strconv" | ||
"testing" | ||
|
||
"github.com/stretchr/testify/require" | ||
) | ||
|
||
func TestParseNumbers(t *testing.T) { | ||
tests := []struct { | ||
name string | ||
input string | ||
want []uint64 | ||
wantErr bool | ||
}{ | ||
{ | ||
name: "valid numbers", | ||
input: "1, 2, 3, 4, 5", | ||
want: []uint64{1, 2, 3, 4, 5}, | ||
}, | ||
{ | ||
name: "single number", | ||
input: "42", | ||
want: []uint64{42}, | ||
}, | ||
{ | ||
name: "large numbers", | ||
input: "1000000, 2000000, 3000000", | ||
want: []uint64{1000000, 2000000, 3000000}, | ||
}, | ||
{ | ||
name: "invalid number", | ||
input: "1, 2, 3, abc, 5", | ||
wantErr: true, | ||
}, | ||
{ | ||
name: "numbers with extra spaces", | ||
input: " 1 , 2 , 3 ", | ||
want: []uint64{1, 2, 3}, | ||
}, | ||
{ | ||
name: "empty input", | ||
input: "", | ||
want: nil, | ||
}, | ||
{ | ||
name: "only commas", | ||
input: ",,,", | ||
want: nil, | ||
}, | ||
} | ||
|
||
for _, tt := range tests { | ||
t.Run(tt.name, func(t *testing.T) { | ||
got, err := ParseNumbers(tt.input) | ||
if tt.wantErr { | ||
require.Error(t, err) | ||
} else { | ||
require.NoError(t, err) | ||
require.Equal(t, tt.want, got) | ||
} | ||
}) | ||
} | ||
} | ||
|
||
func TestParseNumberType(t *testing.T) { | ||
tests := []struct { | ||
name string | ||
input string | ||
parseFunc func(string) (any, error) | ||
expected any | ||
expectError bool | ||
}{ | ||
{ | ||
name: "Parse uint64 numbers", | ||
input: "1, 2, 3", | ||
parseFunc: func(s string) (any, error) { | ||
return strconv.ParseUint(s, 10, 64) | ||
}, | ||
expected: []uint64{1, 2, 3}, | ||
expectError: false, | ||
}, | ||
{ | ||
name: "Parse int numbers", | ||
input: "-1, 0, 1", | ||
parseFunc: func(s string) (any, error) { | ||
return strconv.Atoi(s) | ||
}, | ||
expected: []int{-1, 0, 1}, | ||
expectError: false, | ||
}, | ||
{ | ||
name: "Parse float64 numbers", | ||
input: "1.1, 2.2, 3.3", | ||
parseFunc: func(s string) (any, error) { | ||
return strconv.ParseFloat(s, 64) | ||
}, | ||
expected: []float64{1.1, 2.2, 3.3}, | ||
expectError: false, | ||
}, | ||
{ | ||
name: "Invalid input for uint64", | ||
input: "1, 2, -3", | ||
parseFunc: func(s string) (any, error) { | ||
return strconv.ParseUint(s, 10, 64) | ||
}, | ||
expected: []uint64{}, | ||
expectError: true, | ||
}, | ||
{ | ||
name: "Empty input", | ||
input: "", | ||
parseFunc: func(s string) (any, error) { | ||
return strconv.Atoi(s) | ||
}, | ||
expected: nil, | ||
expectError: false, | ||
}, | ||
{ | ||
name: "Input with spaces", | ||
input: " 1 , 2 , 3 ", | ||
parseFunc: func(s string) (any, error) { | ||
return strconv.Atoi(s) | ||
}, | ||
expected: []int{1, 2, 3}, | ||
expectError: false, | ||
}, | ||
} | ||
|
||
for _, tt := range tests { | ||
t.Run(tt.name, func(t *testing.T) { | ||
var result any | ||
var err error | ||
|
||
switch tt.expected.(type) { | ||
case []uint64: | ||
result, err = ParseNumberType(tt.input, func(s string) (uint64, error) { | ||
return strconv.ParseUint(s, 10, 64) | ||
}) | ||
case []int: | ||
result, err = ParseNumberType(tt.input, func(s string) (int, error) { | ||
return strconv.Atoi(s) | ||
}) | ||
case []float64: | ||
result, err = ParseNumberType(tt.input, func(s string) (float64, error) { | ||
return strconv.ParseFloat(s, 64) | ||
}) | ||
} | ||
|
||
if tt.expectError { | ||
require.Error(t, err) | ||
} else { | ||
require.NoError(t, err) | ||
require.Equal(t, tt.expected, result) | ||
} | ||
}) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.