fuzzyworld

template / commit

Added tests for findProfile, as well as:

55d96f9cc510e3f933b7be0ed9f59f0ab9dd4872 · Pavel Safronov · 2022-09-23 13:12:43 -0700 · parents da15cf493e73

Added tests for findProfile, as well as:
- profiles are no longer stored as a map, it's a list now, and we can have multiple profiles with the same name
- started adding basic config validation
- still trying to figure out how to do installation stuff, might need to start using Make or something
 .vscode/launch.json |  7 +++++++
 config.go           | 41 +++++++++++++++++++++++++++++++++++------
 main.go             |  6 ++++++
 new.go              | 12 ++++++------
 new_test.go         | 35 +++++++++++++++++++++++++++++++++++
 5 files changed, 89 insertions(+), 12 deletions(-)

diff --git a/.vscode/launch.json b/.vscode/launch.json
index c3f50c6..8f03d80 100644
--- a/.vscode/launch.json
+++ b/.vscode/launch.json
@@ -18,6 +18,13 @@
             "script": "go install",
             "cwd": "${workspaceFolder}"
         },
+        {
+            "name": "Refresh install: install and delete config",
+            "type": "PowerShell",
+            "request": "launch",
+            "script": "go install; Remove-Item ~/.template.yaml -ErrorAction SilentlyContinue",
+            "cwd": "${workspaceFolder}"
+        },
         {
             "name": "Run: template",
             "type": "go",
diff --git a/config.go b/config.go
index bccb10e..7f9a6cd 100644
--- a/config.go
+++ b/config.go
@@ -1,6 +1,7 @@
 package main
 
 import (
+	"fmt"
 	"os"
 
 	"gopkg.in/yaml.v3"
@@ -23,6 +24,7 @@ const (
 
 type Profile struct {
 	IsDefault    bool
+	Name         string
 	Path         string
 	Type         ProfileType
 	NamePatterns []string
@@ -34,13 +36,14 @@ type Profile struct {
 }
 
 type Config struct {
-	Profiles map[string]Profile
+	Profiles []Profile
 }
 
 func defaultConfig() Config {
 	return Config{
-		Profiles: map[string]Profile{
-			"daily": {
+		Profiles: []Profile{
+			{
+				Name: "daily",
 				OS:   "Windows",
 				Path: "C:\\work\\daily-notes",
 				Type: FileType,
@@ -57,7 +60,8 @@ func defaultConfig() Config {
 					"{{.Path}}",
 				},
 			},
-			"note": {
+			{
+				Name:      "note",
 				OS:        "All",
 				IsDefault: true,
 				Type:      FileType,
@@ -74,7 +78,8 @@ func defaultConfig() Config {
 					"{{.Path}}",
 				},
 			},
-			"blog": {
+			{
+				Name: "blog",
 				OS:   "All",
 				Path: "~/Dropbox/Blog",
 				Type: FileType,
@@ -92,7 +97,8 @@ func defaultConfig() Config {
 					"{{.Name}}",
 				},
 			},
-			"work": {
+			{
+				Name: "work",
 				OS:   "Windows",
 				Path: "C:/work",
 				Type: FolderType,
@@ -112,6 +118,29 @@ func defaultConfig() Config {
 	}
 }
 
+func validateConfig(config Config) error {
+	if config.Profiles == nil || len(config.Profiles) == 0 {
+		return fmt.Errorf("No profiles found")
+	}
+
+	foundDefault := false
+	for _, profile := range config.Profiles {
+		if profile.IsDefault {
+			if foundDefault {
+				return fmt.Errorf("Multiple default profiles found")
+			}
+			foundDefault = true
+		}
+		if profile.NamePatterns == nil || len(profile.NamePatterns) == 0 {
+			return fmt.Errorf("No name patterns found for profile %s", profile.Name)
+		}
+		if profile.Type == "" || (profile.Type != FileType && profile.Type != FolderType) {
+			return fmt.Errorf("Invalid profile type %s for profile %s", profile.Type, profile.Name)
+		}
+	}
+	return nil
+}
+
 func loadConfig(path string) (Config, error) {
 	file, error := os.ReadFile(path)
 	if error != nil {
diff --git a/main.go b/main.go
index a7cb46a..19cd09e 100644
--- a/main.go
+++ b/main.go
@@ -58,6 +58,12 @@ func main() {
 				fmt.Printf("Config loaded from '%v'\n", configFilePath)
 			}
 
+			// validate config
+			err = validateConfig(config)
+			if err != nil {
+				processError(err, "Invalid config")
+			}
+
 			// read args
 			args := context.Args()
 
diff --git a/new.go b/new.go
index a6b4411..ad8f208 100644
--- a/new.go
+++ b/new.go
@@ -16,7 +16,7 @@ import (
 
 func findProfile(config Config, profileName string) (Profile, error) {
 	if profileName == "" {
-		// use default profile
+		// find default profile
 		for _, p := range config.Profiles {
 			if p.IsDefault {
 				return p, nil
@@ -24,12 +24,12 @@ func findProfile(config Config, profileName string) (Profile, error) {
 		}
 	} else {
 		// find profile by name
-		profile, ok := config.Profiles[profileName]
-		if ok {
-			return profile, nil
-		} else {
-			return Profile{}, fmt.Errorf("Unable to find profile '%v'", profileName)
+		for _, p := range config.Profiles {
+			if p.Name == profileName {
+				return p, nil
+			}
 		}
+		return Profile{}, fmt.Errorf("Unable to find profile '%v'", profileName)
 	}
 	return Profile{}, errors.New("Couldn't find profile")
 }
diff --git a/new_test.go b/new_test.go
index 7540c4a..c383e76 100644
--- a/new_test.go
+++ b/new_test.go
@@ -5,6 +5,41 @@ import (
 	"time"
 )
 
+func TestFindProfile(t *testing.T) {
+	config := Config{
+		Profiles: []Profile{
+			{
+				Name: "daily",
+			},
+			{
+				IsDefault: true,
+				Name:      "notes",
+			},
+		},
+	}
+	testSuccess := func(profileName string, expectedProfileName string) {
+		profile, err := findProfile(config, profileName)
+		if err != nil {
+			t.Errorf("Failed to find profile '%v': %v", profileName, err)
+		}
+		if profile.Name != expectedProfileName {
+			t.Errorf("Asked for profile '%v', expected '%v', got '%v'", profileName, expectedProfileName, profile.Name)
+		}
+	}
+	testFailure := func(profileName string) {
+		_, err := findProfile(config, profileName)
+		if err == nil {
+			t.Errorf("Expected to fail to find profile '%v', but succeeded", profileName)
+		}
+	}
+
+	testSuccess("", "notes")
+	testSuccess("daily", "daily")
+	testSuccess("notes", "notes")
+
+	testFailure("non-existent")
+}
+
 func TestCreateNewName(t *testing.T) {
 	// setup code