mirror of
https://github.com/jesseduffield/lazygit.git
synced 2026-09-12 16:46:25 -04:00
JumpToBlock is special: each of its 5 elements is the binding for one side window (status / files / branches / commits / stash), not an alternate for a single command. Change the field from []string to []Keybinding so each window slot can have alternates of its own. The schema becomes "an array of 5 keybindings, each itself a string or array of strings", which falls out cleanly from how the Keybinding type inlines into the generated schema. Existing configs (a flat array of 5 strings) keep validating because each element is unmarshalled through Keybinding's scalar-or-sequence decoder.
198 lines
4 KiB
Go
198 lines
4 KiB
Go
package config
|
|
|
|
import (
|
|
"encoding/json"
|
|
"testing"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
"gopkg.in/yaml.v3"
|
|
)
|
|
|
|
func TestKeybindingUnmarshalYAML(t *testing.T) {
|
|
scenarios := []struct {
|
|
name string
|
|
input string
|
|
expected Keybinding
|
|
wantErr bool
|
|
}{
|
|
{
|
|
name: "scalar string",
|
|
input: `q`,
|
|
expected: Keybinding{"q"},
|
|
},
|
|
{
|
|
name: "scalar with special characters",
|
|
input: `<esc>`,
|
|
expected: Keybinding{"<esc>"},
|
|
},
|
|
{
|
|
name: "sequence with one element",
|
|
input: `[q]`,
|
|
expected: Keybinding{"q"},
|
|
},
|
|
{
|
|
name: "sequence with multiple elements",
|
|
input: `["q", "<esc>"]`,
|
|
expected: Keybinding{"q", "<esc>"},
|
|
},
|
|
{
|
|
name: "empty sequence",
|
|
input: `[]`,
|
|
expected: Keybinding{},
|
|
},
|
|
{
|
|
name: "scalar <disabled> decodes to empty",
|
|
input: `<disabled>`,
|
|
expected: Keybinding{},
|
|
},
|
|
{
|
|
name: "scalar empty string decodes to empty",
|
|
input: `""`,
|
|
expected: Keybinding{},
|
|
},
|
|
{
|
|
name: "<disabled> entries are filtered out of a sequence",
|
|
input: `["q", "<disabled>", "<esc>"]`,
|
|
expected: Keybinding{"q", "<esc>"},
|
|
},
|
|
{
|
|
name: "mapping is rejected",
|
|
input: `{key: q}`,
|
|
wantErr: true,
|
|
},
|
|
}
|
|
|
|
for _, s := range scenarios {
|
|
t.Run(s.name, func(t *testing.T) {
|
|
var k Keybinding
|
|
err := yaml.Unmarshal([]byte(s.input), &k)
|
|
if s.wantErr {
|
|
assert.Error(t, err)
|
|
return
|
|
}
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, s.expected, k)
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestKeybindingMarshalYAML(t *testing.T) {
|
|
scenarios := []struct {
|
|
name string
|
|
input Keybinding
|
|
expected string
|
|
}{
|
|
{
|
|
name: "single key emits a scalar",
|
|
input: Keybinding{"q"},
|
|
expected: "q\n",
|
|
},
|
|
{
|
|
name: "multiple keys emit a flow sequence",
|
|
input: Keybinding{"q", "<esc>"},
|
|
expected: "[q, <esc>]\n",
|
|
},
|
|
{
|
|
name: "empty keybinding emits an empty sequence",
|
|
input: Keybinding{},
|
|
expected: "[]\n",
|
|
},
|
|
}
|
|
|
|
for _, s := range scenarios {
|
|
t.Run(s.name, func(t *testing.T) {
|
|
out, err := yaml.Marshal(s.input)
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, s.expected, string(out))
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestKeybindingMarshalJSON(t *testing.T) {
|
|
scenarios := []struct {
|
|
name string
|
|
input Keybinding
|
|
expected string
|
|
}{
|
|
{
|
|
name: "single key emits a string",
|
|
input: Keybinding{"q"},
|
|
expected: `"q"`,
|
|
},
|
|
{
|
|
name: "multiple keys emit an array",
|
|
input: Keybinding{"q", "esc"},
|
|
expected: `["q","esc"]`,
|
|
},
|
|
}
|
|
|
|
for _, s := range scenarios {
|
|
t.Run(s.name, func(t *testing.T) {
|
|
out, err := json.Marshal(s.input)
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, s.expected, string(out))
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestKeybindingYAMLRoundTrip(t *testing.T) {
|
|
scenarios := []Keybinding{
|
|
{"q"},
|
|
{"q", "<esc>"},
|
|
{"<ctrl+c>", "<ctrl+d>", "<esc>"},
|
|
}
|
|
for _, original := range scenarios {
|
|
out, err := yaml.Marshal(original)
|
|
assert.NoError(t, err)
|
|
var decoded Keybinding
|
|
assert.NoError(t, yaml.Unmarshal(out, &decoded))
|
|
assert.Equal(t, original, decoded)
|
|
}
|
|
}
|
|
|
|
func TestKeybindingConfigYAMLAcceptsBothForms(t *testing.T) {
|
|
scenarios := []struct {
|
|
name string
|
|
yaml string
|
|
expected Keybinding
|
|
}{
|
|
{
|
|
name: "scalar form",
|
|
yaml: "quit: q\n",
|
|
expected: Keybinding{"q"},
|
|
},
|
|
{
|
|
name: "sequence form",
|
|
yaml: "quit: [q, <esc>]\n",
|
|
expected: Keybinding{"q", "<esc>"},
|
|
},
|
|
{
|
|
name: "block sequence form",
|
|
yaml: "quit:\n - q\n - <esc>\n",
|
|
expected: Keybinding{"q", "<esc>"},
|
|
},
|
|
}
|
|
for _, s := range scenarios {
|
|
t.Run(s.name, func(t *testing.T) {
|
|
var cfg KeybindingUniversalConfig
|
|
assert.NoError(t, yaml.Unmarshal([]byte(s.yaml), &cfg))
|
|
assert.Equal(t, s.expected, cfg.Quit)
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestJumpToBlockYAMLAcceptsMixedForms(t *testing.T) {
|
|
yamlInput := `
|
|
jumpToBlock:
|
|
- "1"
|
|
- ["2", "@"]
|
|
- "3"
|
|
- "4"
|
|
- "5"
|
|
`
|
|
var cfg KeybindingUniversalConfig
|
|
assert.NoError(t, yaml.Unmarshal([]byte(yamlInput), &cfg))
|
|
expected := []Keybinding{{"1"}, {"2", "@"}, {"3"}, {"4"}, {"5"}}
|
|
assert.Equal(t, expected, cfg.JumpToBlock)
|
|
}
|