Skip to content

Commit 02a2802

Browse files
committed
tests
1 parent 460dd41 commit 02a2802

File tree

6 files changed

+118
-5
lines changed

6 files changed

+118
-5
lines changed

completion/all.go

+23-4
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import (
1616
type Shell interface {
1717
Name() string
1818
InstallPath() (string, error)
19+
UsesOwnFile() bool
1920
WriteCompletion(io.Writer) error
2021
}
2122

@@ -102,13 +103,31 @@ func generateCompletion(
102103
func InstallShellCompletion(shell Shell) error {
103104
path, err := shell.InstallPath()
104105
if err != nil {
105-
return fmt.Errorf("get install path: %w", err)
106+
return fmt.Errorf("failed to get install path: %w", err)
106107
}
107-
f, err := os.OpenFile(path, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0o644)
108+
109+
err = os.MkdirAll(filepath.Dir(path), 0o755)
108110
if err != nil {
109-
return fmt.Errorf("create and append to file: %w", err)
111+
return fmt.Errorf("failed to create directories: %w", err)
112+
}
113+
114+
if shell.UsesOwnFile() {
115+
err := os.WriteFile(path, nil, 0o644)
116+
if err != nil {
117+
return fmt.Errorf("failed to create or truncate file: %w", err)
118+
}
119+
}
120+
121+
f, err := os.OpenFile(path, os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0o644)
122+
if err != nil {
123+
return fmt.Errorf("failed to open file for appending: %w", err)
110124
}
111125
defer f.Close()
112126

113-
return shell.WriteCompletion(f)
127+
err = shell.WriteCompletion(f)
128+
if err != nil {
129+
return fmt.Errorf("failed to write completion script: %w", err)
130+
}
131+
132+
return nil
114133
}

completion/bash.go

+7
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,11 @@ func (b *bash) Name() string {
2323
return "bash"
2424
}
2525

26+
// UsesOwnFile implements Shell.
27+
func (b *bash) UsesOwnFile() bool {
28+
return false
29+
}
30+
2631
// InstallPath implements Shell.
2732
func (b *bash) InstallPath() (string, error) {
2833
homeDir, err := home.Dir()
@@ -41,6 +46,7 @@ func (b *bash) WriteCompletion(w io.Writer) error {
4146
}
4247

4348
const bashCompletionTemplate = `
49+
4450
# === BEGIN {{.Name}} COMPLETION ===
4551
_generate_{{.Name}}_completions() {
4652
# Capture the line excluding the command, and everything after the current word
@@ -60,4 +66,5 @@ _generate_{{.Name}}_completions() {
6066
# Setup Bash to use the function for completions for '{{.Name}}'
6167
complete -F _generate_{{.Name}}_completions {{.Name}}
6268
# === END {{.Name}} COMPLETION ===
69+
6370
`

completion/fish.go

+5
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,11 @@ func Fish(goos string, programName string) Shell {
1818
return &fish{goos: goos, programName: programName}
1919
}
2020

21+
// UsesOwnFile implements Shell.
22+
func (f *fish) UsesOwnFile() bool {
23+
return true
24+
}
25+
2126
// Name implements Shell.
2227
func (f *fish) Name() string {
2328
return "fish"

completion/powershell.go

+9-1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package completion
33
import (
44
"io"
55
"os/exec"
6+
"strings"
67
)
78

89
type powershell struct {
@@ -19,6 +20,11 @@ func Powershell(goos string, programName string) Shell {
1920
return &powershell{goos: goos, programName: programName}
2021
}
2122

23+
// UsesOwnFile implements Shell.
24+
func (p *powershell) UsesOwnFile() bool {
25+
return false
26+
}
27+
2228
// InstallPath implements Shell.
2329
func (p *powershell) InstallPath() (string, error) {
2430
var (
@@ -34,7 +40,7 @@ func (p *powershell) InstallPath() (string, error) {
3440
if err != nil {
3541
return "", err
3642
}
37-
return string(path), nil
43+
return strings.TrimSpace(string(path)), nil
3844
}
3945

4046
// WriteCompletion implements Shell.
@@ -45,6 +51,7 @@ func (p *powershell) WriteCompletion(w io.Writer) error {
4551
var _ Shell = &powershell{}
4652

4753
const pshCompletionTemplate = `
54+
4855
# === BEGIN {{.Name}} COMPLETION ===
4956
# Escaping output sourced from:
5057
# https://github.com/spf13/cobra/blob/e94f6d0dd9a5e5738dca6bce03c4b1207ffbc0ec/powershell_completions.go#L47
@@ -83,4 +90,5 @@ $_{{.Name}}_completions = {
8390
}
8491
Register-ArgumentCompleter -CommandName {{.Name}} -ScriptBlock $_{{.Name}}_completions
8592
# === END {{.Name}} COMPLETION ===
93+
8694
`

completion/zsh.go

+7
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,11 @@ func (z *zsh) Name() string {
2323
return "zsh"
2424
}
2525

26+
// UsesOwnFile implements Shell.
27+
func (z *zsh) UsesOwnFile() bool {
28+
return false
29+
}
30+
2631
// InstallPath implements Shell.
2732
func (z *zsh) InstallPath() (string, error) {
2833
homeDir, err := home.Dir()
@@ -38,6 +43,7 @@ func (z *zsh) WriteCompletion(w io.Writer) error {
3843
}
3944

4045
const zshCompletionTemplate = `
46+
4147
# === BEGIN {{.Name}} COMPLETION ===
4248
_{{.Name}}_completions() {
4349
local -a args completions
@@ -47,4 +53,5 @@ _{{.Name}}_completions() {
4753
}
4854
compdef _{{.Name}}_completions {{.Name}}
4955
# === END {{.Name}} COMPLETION ===
56+
5057
`

completion_test.go

+67
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,14 @@ package serpent_test
22

33
import (
44
"fmt"
5+
"io"
56
"os"
7+
"path/filepath"
68
"strings"
79
"testing"
810

911
serpent "github.com/coder/serpent"
12+
"github.com/coder/serpent/completion"
1013
"github.com/stretchr/testify/require"
1114
)
1215

@@ -231,3 +234,67 @@ func TestFileCompletion(t *testing.T) {
231234
})
232235
}
233236
}
237+
238+
func TestCompletionInstall(t *testing.T) {
239+
t.Parallel()
240+
241+
t.Run("InstallingAppend", func(t *testing.T) {
242+
dir := t.TempDir()
243+
path := filepath.Join(dir, "fake.sh")
244+
f, err := os.Create(path)
245+
require.NoError(t, err)
246+
f.Write([]byte("FAKE_SCRIPT"))
247+
f.Close()
248+
249+
shell := &fakeShell{baseInstallDir: dir, useOwn: false}
250+
err = completion.InstallShellCompletion(shell)
251+
require.NoError(t, err)
252+
contents, err := os.ReadFile(path)
253+
require.NoError(t, err)
254+
require.Equal(t, "FAKE_SCRIPTFAKE_COMPLETION", string(contents))
255+
})
256+
257+
t.Run("InstallReplace", func(t *testing.T) {
258+
dir := t.TempDir()
259+
path := filepath.Join(dir, "fake.sh")
260+
f, err := os.Create(path)
261+
require.NoError(t, err)
262+
f.Write([]byte("FAKE_SCRIPT"))
263+
f.Close()
264+
265+
shell := &fakeShell{baseInstallDir: dir, useOwn: true}
266+
err = completion.InstallShellCompletion(shell)
267+
require.NoError(t, err)
268+
contents, err := os.ReadFile(path)
269+
require.NoError(t, err)
270+
require.Equal(t, "FAKE_COMPLETION", string(contents))
271+
})
272+
}
273+
274+
type fakeShell struct {
275+
baseInstallDir string
276+
useOwn bool
277+
}
278+
279+
var _ completion.Shell = &fakeShell{}
280+
281+
// InstallPath implements completion.Shell.
282+
func (f *fakeShell) InstallPath() (string, error) {
283+
return filepath.Join(f.baseInstallDir, "fake.sh"), nil
284+
}
285+
286+
// Name implements completion.Shell.
287+
func (f *fakeShell) Name() string {
288+
return "fake"
289+
}
290+
291+
// UsesOwnFile implements completion.Shell.
292+
func (f *fakeShell) UsesOwnFile() bool {
293+
return f.useOwn
294+
}
295+
296+
// WriteCompletion implements completion.Shell.
297+
func (f *fakeShell) WriteCompletion(w io.Writer) error {
298+
_, err := w.Write([]byte("FAKE_COMPLETION"))
299+
return err
300+
}

0 commit comments

Comments
 (0)