Skip to content

Commit

Permalink
added slugify method and tests
Browse files Browse the repository at this point in the history
  • Loading branch information
rozdolsky33 committed Sep 27, 2024
1 parent 1d11118 commit 8f7925a
Show file tree
Hide file tree
Showing 3 changed files with 53 additions and 1 deletion.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ The included tools are:
- [X] Get a random string of length n
- [ ] Post JSON to a remote service
- [X] Create a directory, including all parent directories, if it does not already exist
- [ ] Create a URL safe slug from a string
- [X] Create a URL safe slug from a string

## Installation

Expand Down
20 changes: 20 additions & 0 deletions tools.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,11 @@ import (
"net/http"
"os"
"path/filepath"
"regexp"
"strings"
)

// randomStringSource defines the character set used for generating random strings.
const randomStringSource = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVXWYZ0123456789_+"

// Tools is the type used to instantiate this module. Any variable of this type will have access to all the methods with the receiver *Tools.
Expand Down Expand Up @@ -54,6 +56,8 @@ func (t *Tools) UploadOneFile(r *http.Request, uploadDir string, rename ...bool)
return files[0], nil
}

// UploadFiles uploads multiple files from the provided HTTP request, storing them in the specified directory.
// If the optional rename argument is true or not provided, the files will be renamed.
func (t *Tools) UploadFiles(r *http.Request, uploadDir string, rename ...bool) ([]*UploadedFile, error) {
renameFile := true
if len(rename) > 0 {
Expand Down Expand Up @@ -151,3 +155,19 @@ func (t *Tools) CreateDirIfNotExist(dir string) error {
}
return nil
}

// Slugify transforms an input string into a URL-friendly slug by replacing non-alphanumeric characters with hyphens.
func (t *Tools) Slugify(s string) (string, error) {
if s == "" {
return "", errors.New("empty string not permitted")
}
var regEx = regexp.MustCompile(`[^a-z\d]+`)

slug := strings.Trim(regEx.ReplaceAllString(strings.ToLower(s), "-"), "-")

if len(slug) == 0 {
return "", errors.New("after removing characters, slug is zero length")
}

return slug, nil
}
32 changes: 32 additions & 0 deletions tools_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (
"testing"
)

// TestTools_RandomString verifies that the RandomString method returns a string of the correct length.
func TestTools_RandomString(t *testing.T) {
var testTools Tools
s := testTools.RandomString(10)
Expand All @@ -33,6 +34,7 @@ var uploadTests = []struct {
{name: "not allowed", allowedTypes: []string{"image/jpeg"}, renameFile: false, errorExpected: true},
}

// TestTools_UploadFiles tests the file upload functionality via multipart form-data with various scenarios and configurations.
func TestTools_UploadFiles(t *testing.T) {
for _, e := range uploadTests {
//set up a pipe to avoid buffering
Expand Down Expand Up @@ -92,6 +94,7 @@ func TestTools_UploadFiles(t *testing.T) {
}
}

// TestTools_UploadOneFile tests the UploadOneFile method to ensure a file can be uploaded, stored, and verified correctly.
func TestTools_UploadOneFile(t *testing.T) {
//set up a pipe to avoid buffering
pr, pw := io.Pipe()
Expand Down Expand Up @@ -158,3 +161,32 @@ func TestTools_CreateDirIfNotExist(t *testing.T) {
_ = os.Remove(fmt.Sprintf("./testdata/myDir"))

}

var slugTests = []struct {
name string
s string
expected string
errorExpected bool
}{
{name: "valid string", s: "Hello World", expected: "hello-world", errorExpected: false},
{name: "empty string", s: "", expected: "", errorExpected: true},
{name: "complex string", s: "Now is the time for all GOOD men! + fish & such &^123", expected: "now-is-the-time-for-all-good-men-fish-such-123", errorExpected: false},
{name: " japanese string", s: "こんにちは世界", expected: "", errorExpected: true},
{name: " japanese string and roman characters", s: "hello world こんにちは世界", expected: "hello-world", errorExpected: false},
}

func TestTools_Slugify(t *testing.T) {
var testTools Tools

for _, test := range slugTests {
slug, err := testTools.Slugify(test.s)
if err != nil && !test.errorExpected {
t.Errorf("%s: error received but none expected: %s", test.name, err.Error())
}

if !test.errorExpected && slug != test.expected {
t.Errorf("%s: wrong slug retrned; expected %s but got %s", test.name, test.expected, slug)
}
}

}

0 comments on commit 8f7925a

Please sign in to comment.