mirror of
https://github.com/go-task/task.git
synced 2025-06-23 00:38:19 +02:00
feat: decoding improvements (#2068)
* refactor: moved/simplified snippets into its own file with tests * refactor: move snippet to taskfile package * feat: support snippets with line/col = 0 * feat: functional options for snippets * feat: added option to hide snippet indicators * feat: store raw lines for length calculations * feat: add debug function for TaskfileDecodeError * fix: decode errors from commands * fix: schema for defer cmd calls * fix: linting issues * refactor: split var and vars into different files like other structures
This commit is contained in:
289
taskfile/snippet_test.go
Normal file
289
taskfile/snippet_test.go
Normal file
@ -0,0 +1,289 @@
|
||||
package taskfile
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
const sample = `version: 3
|
||||
|
||||
tasks:
|
||||
default:
|
||||
vars:
|
||||
FOO: foo
|
||||
BAR: bar
|
||||
cmds:
|
||||
- echo "{{.FOO}}"
|
||||
- echo "{{.BAR}}"
|
||||
`
|
||||
|
||||
func TestNewSnippet(t *testing.T) {
|
||||
t.Parallel()
|
||||
tests := []struct {
|
||||
name string
|
||||
b []byte
|
||||
opts []SnippetOption
|
||||
want *Snippet
|
||||
}{
|
||||
{
|
||||
name: "first line, first column",
|
||||
b: []byte(sample),
|
||||
opts: []SnippetOption{
|
||||
SnippetWithLine(1),
|
||||
SnippetWithColumn(1),
|
||||
},
|
||||
want: &Snippet{
|
||||
linesRaw: []string{
|
||||
"version: 3",
|
||||
},
|
||||
linesHighlighted: []string{
|
||||
"\x1b[33mversion\x1b[0m\x1b[1m\x1b[30m:\x1b[0m\x1b[1m\x1b[30m \x1b[0m\x1b[36m3\x1b[0m\x1b[1m\x1b[30m\x1b[0m",
|
||||
},
|
||||
start: 1,
|
||||
end: 1,
|
||||
line: 1,
|
||||
column: 1,
|
||||
padding: 0,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "first line, first column, padding=2",
|
||||
b: []byte(sample),
|
||||
opts: []SnippetOption{
|
||||
SnippetWithLine(1),
|
||||
SnippetWithColumn(1),
|
||||
SnippetWithPadding(2),
|
||||
},
|
||||
want: &Snippet{
|
||||
linesRaw: []string{
|
||||
"version: 3",
|
||||
"",
|
||||
"tasks:",
|
||||
},
|
||||
linesHighlighted: []string{
|
||||
"\x1b[33mversion\x1b[0m\x1b[1m\x1b[30m:\x1b[0m\x1b[1m\x1b[30m \x1b[0m\x1b[36m3\x1b[0m\x1b[1m\x1b[30m\x1b[0m",
|
||||
"\x1b[1m\x1b[30m\x1b[0m",
|
||||
"\x1b[33mtasks\x1b[0m\x1b[1m\x1b[30m:\x1b[0m\x1b[1m\x1b[30m\x1b[0m",
|
||||
},
|
||||
start: 1,
|
||||
end: 3,
|
||||
line: 1,
|
||||
column: 1,
|
||||
padding: 2,
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
got := NewSnippet(tt.b, tt.opts...)
|
||||
require.Equal(t, tt.want, got)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestSnippetString(t *testing.T) {
|
||||
t.Parallel()
|
||||
tests := []struct {
|
||||
name string
|
||||
b []byte
|
||||
opts []SnippetOption
|
||||
want string
|
||||
}{
|
||||
{
|
||||
name: "empty",
|
||||
b: []byte{},
|
||||
opts: []SnippetOption{
|
||||
SnippetWithLine(1),
|
||||
SnippetWithColumn(1),
|
||||
},
|
||||
want: "",
|
||||
},
|
||||
{
|
||||
name: "0th line, 0th column (no indicators)",
|
||||
b: []byte(sample),
|
||||
want: "",
|
||||
},
|
||||
{
|
||||
name: "1st line, 0th column (line indicator only)",
|
||||
b: []byte(sample),
|
||||
opts: []SnippetOption{
|
||||
SnippetWithLine(1),
|
||||
},
|
||||
want: "> 1 | \x1b[33mversion\x1b[0m\x1b[1m\x1b[30m:\x1b[0m\x1b[1m\x1b[30m \x1b[0m\x1b[36m3\x1b[0m\x1b[1m\x1b[30m\x1b[0m",
|
||||
},
|
||||
{
|
||||
name: "0th line, 1st column (column indicator only)",
|
||||
b: []byte(sample),
|
||||
opts: []SnippetOption{
|
||||
SnippetWithColumn(1),
|
||||
},
|
||||
want: "",
|
||||
},
|
||||
{
|
||||
name: "0th line, 1st column, padding=2 (column indicator only)",
|
||||
b: []byte(sample),
|
||||
opts: []SnippetOption{
|
||||
SnippetWithColumn(1),
|
||||
SnippetWithPadding(2),
|
||||
},
|
||||
want: " 1 | \x1b[33mversion\x1b[0m\x1b[1m\x1b[30m:\x1b[0m\x1b[1m\x1b[30m \x1b[0m\x1b[36m3\x1b[0m\x1b[1m\x1b[30m\x1b[0m\n 2 | \x1b[1m\x1b[30m\x1b[0m\n | ^",
|
||||
},
|
||||
{
|
||||
name: "1st line, 1st column",
|
||||
b: []byte(sample),
|
||||
opts: []SnippetOption{
|
||||
SnippetWithLine(1),
|
||||
SnippetWithColumn(1),
|
||||
},
|
||||
want: "> 1 | \x1b[33mversion\x1b[0m\x1b[1m\x1b[30m:\x1b[0m\x1b[1m\x1b[30m \x1b[0m\x1b[36m3\x1b[0m\x1b[1m\x1b[30m\x1b[0m\n | ^",
|
||||
},
|
||||
{
|
||||
name: "1st line, 10th column",
|
||||
b: []byte(sample),
|
||||
opts: []SnippetOption{
|
||||
SnippetWithLine(1),
|
||||
SnippetWithColumn(10),
|
||||
},
|
||||
want: "> 1 | \x1b[33mversion\x1b[0m\x1b[1m\x1b[30m:\x1b[0m\x1b[1m\x1b[30m \x1b[0m\x1b[36m3\x1b[0m\x1b[1m\x1b[30m\x1b[0m\n | ^",
|
||||
},
|
||||
{
|
||||
name: "1st line, 1st column, padding=2",
|
||||
b: []byte(sample),
|
||||
opts: []SnippetOption{
|
||||
SnippetWithLine(1),
|
||||
SnippetWithColumn(1),
|
||||
SnippetWithPadding(2),
|
||||
},
|
||||
want: "> 1 | \x1b[33mversion\x1b[0m\x1b[1m\x1b[30m:\x1b[0m\x1b[1m\x1b[30m \x1b[0m\x1b[36m3\x1b[0m\x1b[1m\x1b[30m\x1b[0m\n | ^\n 2 | \x1b[1m\x1b[30m\x1b[0m\n 3 | \x1b[33mtasks\x1b[0m\x1b[1m\x1b[30m:\x1b[0m\x1b[1m\x1b[30m\x1b[0m",
|
||||
},
|
||||
{
|
||||
name: "1st line, 10th column, padding=2",
|
||||
b: []byte(sample),
|
||||
opts: []SnippetOption{
|
||||
SnippetWithLine(1),
|
||||
SnippetWithColumn(10),
|
||||
SnippetWithPadding(2),
|
||||
},
|
||||
want: "> 1 | \x1b[33mversion\x1b[0m\x1b[1m\x1b[30m:\x1b[0m\x1b[1m\x1b[30m \x1b[0m\x1b[36m3\x1b[0m\x1b[1m\x1b[30m\x1b[0m\n | ^\n 2 | \x1b[1m\x1b[30m\x1b[0m\n 3 | \x1b[33mtasks\x1b[0m\x1b[1m\x1b[30m:\x1b[0m\x1b[1m\x1b[30m\x1b[0m",
|
||||
},
|
||||
{
|
||||
name: "5th line, 1st column",
|
||||
b: []byte(sample),
|
||||
opts: []SnippetOption{
|
||||
SnippetWithLine(5),
|
||||
SnippetWithColumn(1),
|
||||
},
|
||||
want: "> 5 | \x1b[1m\x1b[30m \x1b[0m\x1b[33mvars\x1b[0m\x1b[1m\x1b[30m:\x1b[0m\x1b[1m\x1b[30m\x1b[0m\n | ^",
|
||||
},
|
||||
{
|
||||
name: "5th line, 5th column",
|
||||
b: []byte(sample),
|
||||
opts: []SnippetOption{
|
||||
SnippetWithLine(5),
|
||||
SnippetWithColumn(5),
|
||||
},
|
||||
want: "> 5 | \x1b[1m\x1b[30m \x1b[0m\x1b[33mvars\x1b[0m\x1b[1m\x1b[30m:\x1b[0m\x1b[1m\x1b[30m\x1b[0m\n | ^",
|
||||
},
|
||||
{
|
||||
name: "5th line, 5th column, padding=2",
|
||||
b: []byte(sample),
|
||||
opts: []SnippetOption{
|
||||
SnippetWithLine(5),
|
||||
SnippetWithColumn(5),
|
||||
SnippetWithPadding(2),
|
||||
},
|
||||
want: " 3 | \x1b[33mtasks\x1b[0m\x1b[1m\x1b[30m:\x1b[0m\x1b[1m\x1b[30m\x1b[0m\n 4 | \x1b[1m\x1b[30m \x1b[0m\x1b[33mdefault\x1b[0m\x1b[1m\x1b[30m:\x1b[0m\x1b[1m\x1b[30m\x1b[0m\n> 5 | \x1b[1m\x1b[30m \x1b[0m\x1b[33mvars\x1b[0m\x1b[1m\x1b[30m:\x1b[0m\x1b[1m\x1b[30m\x1b[0m\n | ^\n 6 | \x1b[1m\x1b[30m \x1b[0m\x1b[33mFOO\x1b[0m\x1b[1m\x1b[30m:\x1b[0m\x1b[1m\x1b[30m \x1b[0m\x1b[36mfoo\x1b[0m\x1b[1m\x1b[30m\x1b[0m\n 7 | \x1b[1m\x1b[30m \x1b[0m\x1b[33mBAR\x1b[0m\x1b[1m\x1b[30m:\x1b[0m\x1b[1m\x1b[30m \x1b[0m\x1b[36mbar\x1b[0m\x1b[1m\x1b[30m\x1b[0m",
|
||||
},
|
||||
{
|
||||
name: "5th line, 5th column, padding=2, no indicators",
|
||||
b: []byte(sample),
|
||||
opts: []SnippetOption{
|
||||
SnippetWithLine(5),
|
||||
SnippetWithColumn(5),
|
||||
SnippetWithPadding(2),
|
||||
SnippetWithNoIndicators(),
|
||||
},
|
||||
want: " 3 | \x1b[33mtasks\x1b[0m\x1b[1m\x1b[30m:\x1b[0m\x1b[1m\x1b[30m\x1b[0m\n 4 | \x1b[1m\x1b[30m \x1b[0m\x1b[33mdefault\x1b[0m\x1b[1m\x1b[30m:\x1b[0m\x1b[1m\x1b[30m\x1b[0m\n 5 | \x1b[1m\x1b[30m \x1b[0m\x1b[33mvars\x1b[0m\x1b[1m\x1b[30m:\x1b[0m\x1b[1m\x1b[30m\x1b[0m\n 6 | \x1b[1m\x1b[30m \x1b[0m\x1b[33mFOO\x1b[0m\x1b[1m\x1b[30m:\x1b[0m\x1b[1m\x1b[30m \x1b[0m\x1b[36mfoo\x1b[0m\x1b[1m\x1b[30m\x1b[0m\n 7 | \x1b[1m\x1b[30m \x1b[0m\x1b[33mBAR\x1b[0m\x1b[1m\x1b[30m:\x1b[0m\x1b[1m\x1b[30m \x1b[0m\x1b[36mbar\x1b[0m\x1b[1m\x1b[30m\x1b[0m",
|
||||
},
|
||||
{
|
||||
name: "10th line, 1st column",
|
||||
b: []byte(sample),
|
||||
opts: []SnippetOption{
|
||||
SnippetWithLine(10),
|
||||
SnippetWithColumn(1),
|
||||
},
|
||||
want: "> 10 | \x1b[1m\x1b[30m \x1b[0m\x1b[1m\x1b[30m- \x1b[0m\x1b[36mecho \"{{.BAR}}\"\x1b[0m\x1b[1m\x1b[30m\x1b[0m\n | ^",
|
||||
},
|
||||
{
|
||||
name: "10th line, 23rd column",
|
||||
b: []byte(sample),
|
||||
opts: []SnippetOption{
|
||||
SnippetWithLine(10),
|
||||
SnippetWithColumn(23),
|
||||
},
|
||||
want: "> 10 | \x1b[1m\x1b[30m \x1b[0m\x1b[1m\x1b[30m- \x1b[0m\x1b[36mecho \"{{.BAR}}\"\x1b[0m\x1b[1m\x1b[30m\x1b[0m\n | ^",
|
||||
},
|
||||
{
|
||||
name: "10th line, 24th column (out of bounds)",
|
||||
b: []byte(sample),
|
||||
opts: []SnippetOption{
|
||||
SnippetWithLine(10),
|
||||
SnippetWithColumn(24),
|
||||
},
|
||||
want: "> 10 | \x1b[1m\x1b[30m \x1b[0m\x1b[1m\x1b[30m- \x1b[0m\x1b[36mecho \"{{.BAR}}\"\x1b[0m\x1b[1m\x1b[30m\x1b[0m",
|
||||
},
|
||||
{
|
||||
name: "10th line, 23rd column, padding=2",
|
||||
b: []byte(sample),
|
||||
opts: []SnippetOption{
|
||||
SnippetWithLine(10),
|
||||
SnippetWithColumn(23),
|
||||
SnippetWithPadding(2),
|
||||
},
|
||||
want: " 8 | \x1b[1m\x1b[30m \x1b[0m\x1b[33mcmds\x1b[0m\x1b[1m\x1b[30m:\x1b[0m\x1b[1m\x1b[30m\x1b[0m\n 9 | \x1b[1m\x1b[30m \x1b[0m\x1b[1m\x1b[30m- \x1b[0m\x1b[36mecho \"{{.FOO}}\"\x1b[0m\x1b[1m\x1b[30m\x1b[0m\n> 10 | \x1b[1m\x1b[30m \x1b[0m\x1b[1m\x1b[30m- \x1b[0m\x1b[36mecho \"{{.BAR}}\"\x1b[0m\x1b[1m\x1b[30m\x1b[0m\n | ^",
|
||||
},
|
||||
{
|
||||
name: "5th line, 5th column, padding=100",
|
||||
b: []byte(sample),
|
||||
opts: []SnippetOption{
|
||||
SnippetWithLine(5),
|
||||
SnippetWithColumn(5),
|
||||
SnippetWithPadding(100),
|
||||
},
|
||||
want: " 1 | \x1b[33mversion\x1b[0m\x1b[1m\x1b[30m:\x1b[0m\x1b[1m\x1b[30m \x1b[0m\x1b[36m3\x1b[0m\x1b[1m\x1b[30m\x1b[0m\n 2 | \x1b[1m\x1b[30m\x1b[0m\n 3 | \x1b[33mtasks\x1b[0m\x1b[1m\x1b[30m:\x1b[0m\x1b[1m\x1b[30m\x1b[0m\n 4 | \x1b[1m\x1b[30m \x1b[0m\x1b[33mdefault\x1b[0m\x1b[1m\x1b[30m:\x1b[0m\x1b[1m\x1b[30m\x1b[0m\n> 5 | \x1b[1m\x1b[30m \x1b[0m\x1b[33mvars\x1b[0m\x1b[1m\x1b[30m:\x1b[0m\x1b[1m\x1b[30m\x1b[0m\n | ^\n 6 | \x1b[1m\x1b[30m \x1b[0m\x1b[33mFOO\x1b[0m\x1b[1m\x1b[30m:\x1b[0m\x1b[1m\x1b[30m \x1b[0m\x1b[36mfoo\x1b[0m\x1b[1m\x1b[30m\x1b[0m\n 7 | \x1b[1m\x1b[30m \x1b[0m\x1b[33mBAR\x1b[0m\x1b[1m\x1b[30m:\x1b[0m\x1b[1m\x1b[30m \x1b[0m\x1b[36mbar\x1b[0m\x1b[1m\x1b[30m\x1b[0m\n 8 | \x1b[1m\x1b[30m \x1b[0m\x1b[33mcmds\x1b[0m\x1b[1m\x1b[30m:\x1b[0m\x1b[1m\x1b[30m\x1b[0m\n 9 | \x1b[1m\x1b[30m \x1b[0m\x1b[1m\x1b[30m- \x1b[0m\x1b[36mecho \"{{.FOO}}\"\x1b[0m\x1b[1m\x1b[30m\x1b[0m\n 10 | \x1b[1m\x1b[30m \x1b[0m\x1b[1m\x1b[30m- \x1b[0m\x1b[36mecho \"{{.BAR}}\"\x1b[0m\x1b[1m\x1b[30m\x1b[0m",
|
||||
},
|
||||
{
|
||||
name: "11th line (out of bounds), 1st column",
|
||||
b: []byte(sample),
|
||||
opts: []SnippetOption{
|
||||
SnippetWithLine(11),
|
||||
SnippetWithColumn(1),
|
||||
},
|
||||
want: "",
|
||||
},
|
||||
{
|
||||
name: "11th line (out of bounds), 1st column, padding=2",
|
||||
b: []byte(sample),
|
||||
opts: []SnippetOption{
|
||||
SnippetWithLine(11),
|
||||
SnippetWithColumn(1),
|
||||
SnippetWithPadding(2),
|
||||
},
|
||||
want: " 9 | \x1b[1m\x1b[30m \x1b[0m\x1b[1m\x1b[30m- \x1b[0m\x1b[36mecho \"{{.FOO}}\"\x1b[0m\x1b[1m\x1b[30m\x1b[0m\n 10 | \x1b[1m\x1b[30m \x1b[0m\x1b[1m\x1b[30m- \x1b[0m\x1b[36mecho \"{{.BAR}}\"\x1b[0m\x1b[1m\x1b[30m\x1b[0m",
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
snippet := NewSnippet(tt.b, tt.opts...)
|
||||
got := snippet.String()
|
||||
if strings.Contains(got, "\t") {
|
||||
t.Fatalf("tab character found in snippet - check the sample string")
|
||||
}
|
||||
require.Equal(t, tt.want, got)
|
||||
})
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user