zk/internal/core/config_test.go

550 lines
13 KiB
Go
Raw Normal View History

package core
2020-12-25 19:25:52 +00:00
import (
2020-12-31 12:44:17 +00:00
"fmt"
2020-12-25 19:25:52 +00:00
"testing"
2020-12-31 12:44:17 +00:00
"github.com/google/go-cmp/cmp"
"github.com/mickael-menu/zk/internal/util/opt"
"github.com/mickael-menu/zk/internal/util/test/assert"
2020-12-25 19:25:52 +00:00
)
2020-12-31 12:44:17 +00:00
func TestParseDefaultConfig(t *testing.T) {
2021-03-17 17:04:27 +00:00
conf, err := ParseConfig([]byte(""), ".zk/config.toml", NewDefaultConfig())
2020-12-25 19:25:52 +00:00
assert.Nil(t, err)
2021-03-17 17:04:27 +00:00
assert.Equal(t, conf, Config{
2021-02-13 21:16:11 +00:00
Note: NoteConfig{
2020-12-31 12:44:17 +00:00
FilenameTemplate: "{{id}}",
Extension: "md",
2020-12-31 12:44:17 +00:00
BodyTemplatePath: opt.NullString,
IDOptions: IDOptions{
Length: 4,
2020-12-31 12:44:17 +00:00
Charset: CharsetAlphanum,
Case: CaseLower,
},
DefaultTitle: "Untitled",
Lang: "en",
Ignore: []string{},
2020-12-31 12:44:17 +00:00
},
Groups: make(map[string]GroupConfig),
Format: FormatConfig{
Markdown: MarkdownConfig{
2021-04-18 14:37:54 +00:00
Hashtags: true,
ColonTags: false,
MultiwordTags: false,
LinkFormat: "markdown",
LinkEncodePath: true,
LinkDropExtension: true,
},
},
2021-02-13 21:16:11 +00:00
Tool: ToolConfig{
Editor: opt.NullString,
Pager: opt.NullString,
FzfPreview: opt.NullString,
FzfLine: opt.NullString,
},
LSP: LSPConfig{
Diagnostics: LSPDiagnosticConfig{
WikiTitle: LSPDiagnosticNone,
DeadLink: LSPDiagnosticError,
},
},
Filters: make(map[string]string),
Aliases: make(map[string]string),
Extra: make(map[string]string),
2020-12-31 12:44:17 +00:00
})
}
func TestParseInvalidConfig(t *testing.T) {
2021-03-17 17:04:27 +00:00
_, err := ParseConfig([]byte(`;`), ".zk/config.toml", NewDefaultConfig())
2020-12-31 12:44:17 +00:00
assert.NotNil(t, err)
2020-12-25 19:25:52 +00:00
}
func TestParseComplete(t *testing.T) {
2020-12-31 12:44:17 +00:00
conf, err := ParseConfig([]byte(`
# Comment
2021-02-13 21:16:11 +00:00
[note]
2020-12-29 17:13:46 +00:00
filename = "{{id}}.note"
extension = "txt"
2020-12-25 19:25:52 +00:00
template = "default.note"
language = "fr"
default-title = "Sans titre"
2021-02-13 21:16:11 +00:00
id-charset = "alphanum"
id-length = 4
id-case = "lower"
ignore = ["ignored", ".git"]
[format.markdown]
hashtags = false
colon-tags = true
multiword-tags = true
2021-04-18 14:37:54 +00:00
link-format = "custom"
link-encode-path = true
link-drop-extension = false
2021-02-13 21:16:11 +00:00
[tool]
editor = "vim"
pager = "less"
fzf-preview = "bat {1}"
fzf-line = "{{title}}"
[extra]
hello = "world"
salut = "le monde"
2021-03-24 20:06:32 +00:00
[filter]
recents = "--created-after '2 weeks ago'"
journal = "journal --sort created"
[alias]
ls = "zk list $@"
ed = "zk edit $@"
[group.log]
paths = ["journal/daily", "journal/weekly"]
[group.log.note]
filename = "{{date}}.md"
extension = "note"
template = "log.md"
language = "de"
default-title = "Ohne Titel"
2021-02-13 21:16:11 +00:00
id-charset = "letters"
id-length = 8
id-case = "mixed"
ignore = ["new-ignored"]
[group.log.extra]
log-ext = "value"
[group.ref.note]
filename = "{{slug title}}.md"
[group."without path"]
paths = []
[lsp.diagnostics]
wiki-title = "hint"
dead-link = "none"
2021-03-17 17:04:27 +00:00
`), ".zk/config.toml", NewDefaultConfig())
2020-12-25 19:25:52 +00:00
assert.Nil(t, err)
2021-03-17 17:04:27 +00:00
assert.Equal(t, conf, Config{
2021-02-13 21:16:11 +00:00
Note: NoteConfig{
2020-12-31 12:44:17 +00:00
FilenameTemplate: "{{id}}.note",
Extension: "txt",
2020-12-31 12:44:17 +00:00
BodyTemplatePath: opt.NewString("default.note"),
IDOptions: IDOptions{
Length: 4,
Charset: CharsetAlphanum,
Case: CaseLower,
},
Lang: "fr",
DefaultTitle: "Sans titre",
Ignore: []string{"ignored", ".git"},
2020-12-25 19:25:52 +00:00
},
Groups: map[string]GroupConfig{
2020-12-31 12:44:17 +00:00
"log": {
Paths: []string{"journal/daily", "journal/weekly"},
2021-02-13 21:16:11 +00:00
Note: NoteConfig{
FilenameTemplate: "{{date}}.md",
Extension: "note",
BodyTemplatePath: opt.NewString("log.md"),
IDOptions: IDOptions{
Length: 8,
Charset: CharsetLetters,
Case: CaseMixed,
},
Lang: "de",
DefaultTitle: "Ohne Titel",
Ignore: []string{"ignored", ".git", "new-ignored"},
2020-12-31 12:44:17 +00:00
},
Extra: map[string]string{
"hello": "world",
"salut": "le monde",
"log-ext": "value",
},
},
"ref": {
Paths: []string{"ref"},
2021-02-13 21:16:11 +00:00
Note: NoteConfig{
FilenameTemplate: "{{slug title}}.md",
Extension: "txt",
BodyTemplatePath: opt.NewString("default.note"),
IDOptions: IDOptions{
Length: 4,
Charset: CharsetAlphanum,
Case: CaseLower,
},
Lang: "fr",
DefaultTitle: "Sans titre",
Ignore: []string{"ignored", ".git"},
2020-12-26 13:49:20 +00:00
},
2020-12-31 12:44:17 +00:00
Extra: map[string]string{
"hello": "world",
"salut": "le monde",
},
},
"without path": {
Paths: []string{},
Note: NoteConfig{
FilenameTemplate: "{{id}}.note",
Extension: "txt",
BodyTemplatePath: opt.NewString("default.note"),
IDOptions: IDOptions{
Length: 4,
Charset: CharsetAlphanum,
Case: CaseLower,
},
Lang: "fr",
DefaultTitle: "Sans titre",
Ignore: []string{"ignored", ".git"},
},
Extra: map[string]string{
"hello": "world",
"salut": "le monde",
},
},
2020-12-31 12:44:17 +00:00
},
Format: FormatConfig{
Markdown: MarkdownConfig{
2021-04-18 14:37:54 +00:00
Hashtags: false,
ColonTags: true,
MultiwordTags: true,
LinkFormat: "custom",
LinkEncodePath: true,
LinkDropExtension: false,
},
},
2021-02-13 21:16:11 +00:00
Tool: ToolConfig{
Editor: opt.NewString("vim"),
Pager: opt.NewString("less"),
FzfPreview: opt.NewString("bat {1}"),
FzfLine: opt.NewString("{{title}}"),
},
LSP: LSPConfig{
Diagnostics: LSPDiagnosticConfig{
WikiTitle: LSPDiagnosticHint,
DeadLink: LSPDiagnosticNone,
},
},
2021-03-24 20:06:32 +00:00
Filters: map[string]string{
"recents": "--created-after '2 weeks ago'",
"journal": "journal --sort created",
},
2021-01-24 11:10:13 +00:00
Aliases: map[string]string{
"ls": "zk list $@",
"ed": "zk edit $@",
},
2021-02-13 21:16:11 +00:00
Extra: map[string]string{
"hello": "world",
"salut": "le monde",
},
2020-12-31 12:44:17 +00:00
})
}
func TestParseMergesGroupConfig(t *testing.T) {
2020-12-31 12:44:17 +00:00
conf, err := ParseConfig([]byte(`
2021-02-13 21:16:11 +00:00
[note]
2020-12-31 12:44:17 +00:00
filename = "root-filename"
extension = "txt"
2020-12-31 12:44:17 +00:00
template = "root-template"
language = "fr"
default-title = "Sans titre"
2021-02-13 21:16:11 +00:00
id-charset = "letters"
id-length = 42
id-case = "upper"
ignore = ["ignored", ".git"]
[extra]
hello = "world"
salut = "le monde"
[group.log.note]
filename = "log-filename"
template = "log-template"
2021-02-13 21:16:11 +00:00
id-charset = "numbers"
id-length = 8
id-case = "mixed"
[group.log.extra]
hello = "override"
log-ext = "value"
[group.inherited]
2021-03-17 17:04:27 +00:00
`), ".zk/config.toml", NewDefaultConfig())
2020-12-31 12:44:17 +00:00
assert.Nil(t, err)
2021-03-17 17:04:27 +00:00
assert.Equal(t, conf, Config{
2021-02-13 21:16:11 +00:00
Note: NoteConfig{
2020-12-31 12:44:17 +00:00
FilenameTemplate: "root-filename",
Extension: "txt",
2020-12-31 12:44:17 +00:00
BodyTemplatePath: opt.NewString("root-template"),
IDOptions: IDOptions{
Length: 42,
Charset: CharsetLetters,
Case: CaseUpper,
},
Lang: "fr",
DefaultTitle: "Sans titre",
Ignore: []string{"ignored", ".git"},
2020-12-25 19:25:52 +00:00
},
Groups: map[string]GroupConfig{
2020-12-31 12:44:17 +00:00
"log": {
Paths: []string{"log"},
2021-02-13 21:16:11 +00:00
Note: NoteConfig{
FilenameTemplate: "log-filename",
Extension: "txt",
BodyTemplatePath: opt.NewString("log-template"),
IDOptions: IDOptions{
Length: 8,
Charset: CharsetNumbers,
Case: CaseMixed,
},
Lang: "fr",
DefaultTitle: "Sans titre",
Ignore: []string{"ignored", ".git"},
2020-12-31 12:44:17 +00:00
},
Extra: map[string]string{
"hello": "override",
"salut": "le monde",
"log-ext": "value",
},
},
"inherited": {
Paths: []string{"inherited"},
2021-02-13 21:16:11 +00:00
Note: NoteConfig{
FilenameTemplate: "root-filename",
Extension: "txt",
BodyTemplatePath: opt.NewString("root-template"),
IDOptions: IDOptions{
Length: 42,
Charset: CharsetLetters,
Case: CaseUpper,
},
Lang: "fr",
DefaultTitle: "Sans titre",
Ignore: []string{"ignored", ".git"},
2020-12-31 12:44:17 +00:00
},
Extra: map[string]string{
"hello": "world",
"salut": "le monde",
},
},
2020-12-25 19:25:52 +00:00
},
Format: FormatConfig{
Markdown: MarkdownConfig{
2021-04-18 14:37:54 +00:00
Hashtags: true,
ColonTags: false,
MultiwordTags: false,
LinkFormat: "markdown",
LinkEncodePath: true,
LinkDropExtension: true,
},
},
LSP: LSPConfig{
Diagnostics: LSPDiagnosticConfig{
WikiTitle: LSPDiagnosticNone,
DeadLink: LSPDiagnosticError,
},
},
2021-03-24 20:06:32 +00:00
Filters: make(map[string]string),
2021-01-24 11:10:13 +00:00
Aliases: make(map[string]string),
2021-02-13 21:16:11 +00:00
Extra: map[string]string{
"hello": "world",
"salut": "le monde",
},
2020-12-28 13:25:35 +00:00
})
2020-12-25 19:25:52 +00:00
}
// Some properties like `pager` and `fzf.preview` differentiate between not
// being set and an empty string.
func TestParsePreservePropertiesAllowingEmptyValues(t *testing.T) {
conf, err := ParseConfig([]byte(`
2021-02-13 21:16:11 +00:00
[tool]
pager = ""
2021-02-13 21:16:11 +00:00
fzf-preview = ""
2021-03-17 17:04:27 +00:00
`), ".zk/config.toml", NewDefaultConfig())
assert.Nil(t, err)
2021-02-13 21:16:11 +00:00
assert.Equal(t, conf.Tool.Pager.IsNull(), false)
assert.Equal(t, conf.Tool.Pager, opt.NewString(""))
assert.Equal(t, conf.Tool.FzfPreview.IsNull(), false)
assert.Equal(t, conf.Tool.FzfPreview, opt.NewString(""))
}
2020-12-31 12:44:17 +00:00
func TestParseIDCharset(t *testing.T) {
test := func(charset string, expected Charset) {
toml := fmt.Sprintf(`
2021-02-13 21:16:11 +00:00
[note]
id-charset = "%v"
`, charset)
2021-03-17 17:04:27 +00:00
conf, err := ParseConfig([]byte(toml), ".zk/config.toml", NewDefaultConfig())
2020-12-31 12:44:17 +00:00
assert.Nil(t, err)
2021-02-13 21:16:11 +00:00
if !cmp.Equal(conf.Note.IDOptions.Charset, expected) {
2020-12-31 12:44:17 +00:00
t.Errorf("Didn't parse ID charset `%v` as expected", charset)
}
}
2020-12-25 19:25:52 +00:00
2020-12-31 12:44:17 +00:00
test("alphanum", CharsetAlphanum)
test("hex", CharsetHex)
test("letters", CharsetLetters)
test("numbers", CharsetNumbers)
test("HEX", []rune("HEX")) // case sensitive
test("custom", []rune("custom"))
}
func TestParseIDCase(t *testing.T) {
test := func(letterCase string, expected Case) {
toml := fmt.Sprintf(`
2021-02-13 21:16:11 +00:00
[note]
id-case = "%v"
`, letterCase)
2021-03-17 17:04:27 +00:00
conf, err := ParseConfig([]byte(toml), ".zk/config.toml", NewDefaultConfig())
2020-12-31 12:44:17 +00:00
assert.Nil(t, err)
2021-02-13 21:16:11 +00:00
if !cmp.Equal(conf.Note.IDOptions.Case, expected) {
2020-12-31 12:44:17 +00:00
t.Errorf("Didn't parse ID case `%v` as expected", letterCase)
}
}
test("lower", CaseLower)
test("upper", CaseUpper)
test("mixed", CaseMixed)
test("unknown", CaseLower)
}
2021-04-18 14:37:54 +00:00
// If link-encode-path is not set explicitly, it defaults to true for
// "markdown" format and false for anything else.
func TestParseMarkdownLinkEncodePath(t *testing.T) {
test := func(format string, expected bool) {
toml := fmt.Sprintf(`
[format.markdown]
link-format = "%s"
`, format)
conf, err := ParseConfig([]byte(toml), ".zk/config.toml", NewDefaultConfig())
assert.Nil(t, err)
assert.Equal(t, conf.Format.Markdown.LinkEncodePath, expected)
}
test("", true)
test("markdown", true)
test("wiki", false)
test("custom", false)
}
func TestParseLSPDiagnosticsSeverity(t *testing.T) {
test := func(value string, expected LSPDiagnosticSeverity) {
toml := fmt.Sprintf(`
[lsp.diagnostics]
wiki-title = "%s"
dead-link = "%s"
`, value, value)
conf, err := ParseConfig([]byte(toml), ".zk/config.toml", NewDefaultConfig())
assert.Nil(t, err)
assert.Equal(t, conf.LSP.Diagnostics.WikiTitle, expected)
assert.Equal(t, conf.LSP.Diagnostics.DeadLink, expected)
}
test("", LSPDiagnosticNone)
test("none", LSPDiagnosticNone)
test("error", LSPDiagnosticError)
test("warning", LSPDiagnosticWarning)
test("info", LSPDiagnosticInfo)
test("hint", LSPDiagnosticHint)
toml := `
[lsp.diagnostics]
wiki-title = "foobar"
`
_, err := ParseConfig([]byte(toml), ".zk/config.toml", NewDefaultConfig())
assert.Err(t, err, "foobar: unknown LSP diagnostic severity - may be none, hint, info, warning or error")
}
func TestGroupConfigIgnoreGlobs(t *testing.T) {
// empty globs
config := GroupConfig{
Paths: []string{"path"},
Note: NoteConfig{Ignore: []string{}},
}
assert.Equal(t, config.IgnoreGlobs(), []string{})
// empty paths
config = GroupConfig{
Paths: []string{},
Note: NoteConfig{
Ignore: []string{"ignored", ".git"},
},
}
assert.Equal(t, config.IgnoreGlobs(), []string{"ignored", ".git"})
// several paths
config = GroupConfig{
Paths: []string{"log", "drafts"},
Note: NoteConfig{
Ignore: []string{"ignored", "*.git"},
},
}
assert.Equal(t, config.IgnoreGlobs(), []string{"log/ignored", "log/*.git", "drafts/ignored", "drafts/*.git"})
}
func TestGroupConfigClone(t *testing.T) {
original := GroupConfig{
Paths: []string{"original"},
2021-02-13 21:16:11 +00:00
Note: NoteConfig{
FilenameTemplate: "{{id}}.note",
Extension: "md",
BodyTemplatePath: opt.NewString("default.note"),
IDOptions: IDOptions{
Length: 4,
Charset: CharsetAlphanum,
Case: CaseLower,
},
Lang: "fr",
DefaultTitle: "Sans titre",
Ignore: []string{"ignored", ".git"},
2020-12-31 14:54:39 +00:00
},
Extra: map[string]string{
"hello": "world",
},
}
clone := original.Clone()
// Check that the clone is equivalent
assert.Equal(t, clone, original)
clone.Paths = []string{"cloned"}
2021-02-13 21:16:11 +00:00
clone.Note.FilenameTemplate = "modified"
clone.Note.Extension = "txt"
clone.Note.BodyTemplatePath = opt.NewString("modified")
clone.Note.IDOptions.Length = 41
clone.Note.IDOptions.Charset = CharsetNumbers
clone.Note.IDOptions.Case = CaseUpper
clone.Note.Lang = "de"
clone.Note.DefaultTitle = "Ohne Titel"
clone.Note.Ignore = []string{"other-ignored"}
2020-12-31 14:54:39 +00:00
clone.Extra["test"] = "modified"
// Check that we didn't modify the original
assert.Equal(t, original, GroupConfig{
Paths: []string{"original"},
2021-02-13 21:16:11 +00:00
Note: NoteConfig{
FilenameTemplate: "{{id}}.note",
Extension: "md",
BodyTemplatePath: opt.NewString("default.note"),
IDOptions: IDOptions{
Length: 4,
Charset: CharsetAlphanum,
Case: CaseLower,
},
Lang: "fr",
DefaultTitle: "Sans titre",
Ignore: []string{"ignored", ".git"},
2020-12-31 14:54:39 +00:00
},
Extra: map[string]string{
"hello": "world",
},
})
}