fuzzyworld

template / commit

Adding tests and a few small changes:

da15cf493e7348feea17bb9bef1608aa070eceb7 · Pavel Safronov · 2022-09-23 11:37:12 -0700 · parents 3f79b1f77615

Adding tests and a few small changes:
- added basic tests for func createNewName
- Path is now optional for profiles, new objects are created in cwd
- added profile "note" that creates a note in cwd
- removed all instances of "name", using explicit projectName and profileName now
 .vscode/launch.json | 15 ++++++++++++--
 config.go           | 24 ++++++++++++++++++----
 new.go              | 47 +++++++++++++++++++++++--------------------
 new_test.go         | 57 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 116 insertions(+), 27 deletions(-)

diff --git a/.vscode/launch.json b/.vscode/launch.json
index 7820d09..c3f50c6 100644
--- a/.vscode/launch.json
+++ b/.vscode/launch.json
@@ -46,7 +46,7 @@
             ]
         },
         {
-            "name": "Run: template --profile work --name testProj",
+            "name": "Run: template --profile work --project testProj",
             "type": "go",
             "request": "launch",
             "mode": "auto",
@@ -54,9 +54,20 @@
             "args": [
                 "--profile",
                 "work",
-                "--name",
+                "--project",
                 "testProj"
             ]
+        },
+        {
+            "name": "Run: template note whoa",
+            "type": "go",
+            "request": "launch",
+            "mode": "auto",
+            "program": ".",
+            "args": [
+                "note",
+                "whoa"
+            ]
         }
     ]
 }
\ No newline at end of file
diff --git a/config.go b/config.go
index 3f01dfa..bccb10e 100644
--- a/config.go
+++ b/config.go
@@ -41,10 +41,9 @@ func defaultConfig() Config {
 	return Config{
 		Profiles: map[string]Profile{
 			"daily": {
-				IsDefault: true,
-				OS:        "Windows",
-				Path:      "C:\\work\\daily-notes",
-				Type:      FileType,
+				OS:   "Windows",
+				Path: "C:\\work\\daily-notes",
+				Type: FileType,
 				NamePatterns: []string{
 					"{{$version := getVersion}}" +
 						"{{.Year}}-{{.Month}}-{{.Day}}" +
@@ -58,6 +57,23 @@ func defaultConfig() Config {
 					"{{.Path}}",
 				},
 			},
+			"note": {
+				OS:        "All",
+				IsDefault: true,
+				Type:      FileType,
+				NamePatterns: []string{
+					"{{$version := getVersion}}" +
+						"{{.Year}}-{{.Month}}-{{.Day}}" +
+						"{{if .ProjectName}}-{{.ProjectName}}{{end}}" +
+						"{{if (gt $version 1)}}n{{$version}}{{end}}" +
+						".md",
+				},
+				ScriptShell: "pwsh",
+				PostScript: []string{
+					"code",
+					"{{.Path}}",
+				},
+			},
 			"blog": {
 				OS:   "All",
 				Path: "~/Dropbox/Blog",
diff --git a/new.go b/new.go
index 734391d..a6b4411 100644
--- a/new.go
+++ b/new.go
@@ -14,8 +14,8 @@ import (
 	"golang.org/x/exp/slices"
 )
 
-func findProfile(config Config, name string) (Profile, error) {
-	if name == "" {
+func findProfile(config Config, profileName string) (Profile, error) {
+	if profileName == "" {
 		// use default profile
 		for _, p := range config.Profiles {
 			if p.IsDefault {
@@ -24,22 +24,23 @@ func findProfile(config Config, name string) (Profile, error) {
 		}
 	} else {
 		// find profile by name
-		profile, ok := config.Profiles[name]
+		profile, ok := config.Profiles[profileName]
 		if ok {
 			return profile, nil
 		} else {
-			return Profile{}, fmt.Errorf("Unable to find profile '%v'", name)
+			return Profile{}, fmt.Errorf("Unable to find profile '%v'", profileName)
 		}
 	}
 	return Profile{}, errors.New("Couldn't find profile")
 }
 
-func processProfile(profile Profile, name string) error {
+func processProfile(profile Profile, projectName string) error {
 	// validate profile
 	if profile.NamePatterns == nil || len(profile.NamePatterns) == 0 {
 		return errors.New("No name patterns specified")
 	}
 
+	// decide if the profile should run on this OS
 	profileOs := profile.OS
 	isWindows := runtime.GOOS == "windows"
 	shouldRun := profileOs == "All" ||
@@ -50,13 +51,19 @@ func processProfile(profile Profile, name string) error {
 		return nil
 	}
 
-	// change cwd
-	path := getFullPath(profile.Path)
-	err := os.Chdir(path)
+	cwd, err := os.Getwd()
 	if err != nil {
-		processError(err, fmt.Sprintf("Error while changing directory to '%v'", path))
+		processError(err, "Unable to get current working directory")
+	}
+	if profile.Path != "" {
+		// change cwd to the profile's path, if one is specified
+		path := getFullPath(profile.Path)
+		err := os.Chdir(path)
+		if err != nil {
+			processError(err, fmt.Sprintf("Error while changing directory to '%v'", path))
+		}
+		cwd = path
 	}
-	cwd := path
 
 	// get all entities in current directory
 	files, err := os.ReadDir(cwd)
@@ -84,8 +91,9 @@ func processProfile(profile Profile, name string) error {
 		}
 	}
 
-	// generate a new name based on profile and existing entities
-	newName, err := createNewName(name, profile, entities)
+	// generate a new name based on time, profile, and existing entities
+	now := time.Now()
+	newName, err := createNewName(now, projectName, profile, entities)
 	if err != nil {
 		return err
 	}
@@ -131,16 +139,14 @@ func processProfile(profile Profile, name string) error {
 type NamePatternData struct {
 	Year, Month, Day, Hour, Minute, Second string
 	ProjectName                            string
-	Index                                  int
 }
 type PostScriptPatternData struct {
 	Name string
 	Path string
 }
 
-func createNewName(name string, profile Profile, existingEntities []string) (string, error) {
-	now := time.Now()
-	patternInfo := createNamePatternData(now, name)
+func createNewName(now time.Time, projectName string, profile Profile, existingEntities []string) (string, error) {
+	patternInfo := createNamePatternData(now, projectName)
 	newName, err := createNewNameForProfile(profile, patternInfo, existingEntities)
 	if err != nil {
 		return "", err
@@ -158,7 +164,6 @@ func createNamePatternData(now time.Time, projectName string) NamePatternData {
 		Minute:      now.Format("04"),
 		Second:      now.Format("05"),
 		ProjectName: projectName,
-		Index:       0,
 	}
 
 	return patternInfo
@@ -216,7 +221,7 @@ func createNewNameForProfile(profile Profile, patternData NamePatternData, exist
 	return "", errors.New("Couldn't find a new name")
 }
 
-func createPostScriptArray(profile Profile, name string, path string) ([]string, error) {
+func createPostScriptArray(profile Profile, newName string, fullPath string) ([]string, error) {
 	array := make([]string, 0)
 
 	if profile.PostScript == nil || len(profile.PostScript) == 0 {
@@ -224,13 +229,13 @@ func createPostScriptArray(profile Profile, name string, path string) ([]string,
 	}
 
 	patternData := PostScriptPatternData{
-		Name: name,
-		Path: path,
+		Name: newName,
+		Path: fullPath,
 	}
 
 	for _, postScriptPattern := range profile.PostScript {
 
-		template, err := template.New("template-name").Parse(postScriptPattern)
+		template, err := template.New("postscript").Parse(postScriptPattern)
 		if err != nil {
 			return nil, err
 		}
diff --git a/new_test.go b/new_test.go
new file mode 100644
index 0000000..7540c4a
--- /dev/null
+++ b/new_test.go
@@ -0,0 +1,57 @@
+package main
+
+import (
+	"testing"
+	"time"
+)
+
+func TestCreateNewName(t *testing.T) {
+	// setup code
+
+	// Mon Jan 2 15:04:05 MST 2006
+	now := time.Date(2006, 1, 2, 15, 4, 5, 0, time.UTC)
+	profile := Profile{
+		IsDefault: true,
+		Type:      FileType,
+		NamePatterns: []string{
+			"{{.Year}}-{{.Month}}-{{.Day}}{{if .ProjectName}}-{{.ProjectName}}{{end}}.txt",
+			"{{.Year}}-{{.Month}}-{{.Day}}-{{.Hour}}{{if .ProjectName}}-{{.ProjectName}}{{end}}.txt",
+			"{{.Year}}-{{.Month}}-{{.Day}}-{{.Hour}}-{{.Minute}}-{{.Second}}-{{.ProjectName}}.txt",
+		},
+	}
+	newName1 := "2006-01-02-test-project.txt"
+	newName2 := "2006-01-02-15-test-project.txt"
+	newName3 := "2006-01-02-15-04-05-test-project.txt"
+
+	testHappyPath := func(projectName string, expectedName string, existingEntities []string) func(t *testing.T) {
+		return func(t *testing.T) {
+			newName, err := createNewName(now, projectName, profile, existingEntities)
+			if err != nil {
+				t.Error("Error creating new name: ", err)
+			}
+			if newName != expectedName {
+				t.Error("Expected name to be ", expectedName, " but got ", newName)
+			}
+		}
+	}
+	testErrorPath := func(projectName string, existingEntities []string) func(t *testing.T) {
+		return func(t *testing.T) {
+			_, err := createNewName(now, projectName, profile, existingEntities)
+			if err == nil {
+				t.Error("Expected error but got none")
+			}
+		}
+	}
+
+	// test code
+
+	// happy path
+	t.Run("createNewName - happy path", testHappyPath("test-project", newName1, []string{}))
+	t.Run("createNewName - use second pattern", testHappyPath("test-project", newName2, []string{newName1}))
+	t.Run("createNewName - use third pattern", testHappyPath("test-project", newName3, []string{newName1, newName2}))
+
+	// error path
+	t.Run("createNewName - error path - collision", testErrorPath("test-project", []string{newName1, newName2, newName3}))
+
+	// teardown code
+}