Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 16 additions & 2 deletions cmd/builder/command.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,16 @@ type Runner interface {
LookPath() error
}

// Command interface comprehends bot Runner and Builder interfaces
// Parser holds available methods for parse commands
type Parser interface {
Parse(string) error
}

// Command interface comprehends bot Runner, Builder, Parser interfaces
type Command interface {
Builder
Runner
Parser
}

// NewCommand Create a new command.
Expand All @@ -51,7 +57,6 @@ func ParseCommand(line string) (command *DefaultCommand, err error) {
}

command = &DefaultCommand{parsed[0], parsed[1:]}

return
}

Expand Down Expand Up @@ -94,3 +99,12 @@ func (c *DefaultCommand) Exec(args ...string) (outStr string, err error) {
outStr, err = shell.Exec(c.command, finalArgs...)
return
}

// Parse calls the ParseCommand function
func (c *DefaultCommand) Parse(line string) (err error) {
if parsed, err := ParseCommand(line); err == nil {
*c = *parsed
}

return
}
16 changes: 16 additions & 0 deletions cmd/builder/command_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -204,3 +204,19 @@ func TestInteractiveArgs(t *testing.T) {
t.Errorf("Interactive failed; expected output 'x', got '%s'", output)
}
}

func TestParse(t *testing.T) {
line := "echo 'xxx'"

cmd := NewCommand("")
err := cmd.Parse(line)

if err != nil {
t.Errorf("failed to parse proper command line onto Command; error: %s", err)
return
}

if len(cmd.args) != 1 || cmd.command != "echo" || cmd.args[0] != "xxx" {
t.Errorf("ParseCommand failed; given %s got %v", line, cmd.String())
}
}
24 changes: 16 additions & 8 deletions cmd/builder/fake_command.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,15 @@ package builder

// FakeCommand implements the Command interface and is used for mocking on testing scenarios
type FakeCommand struct {
ArgsAppend []string
ArgsInteractive []string
ArgsExec []string
CalledAppendArgs bool
CalledString bool
CalledLookPath bool
CalledInteractive bool
CalledExec bool
ArgsAppend []string
ArgsInteractive []string
ArgsExec []string
CalledAppendArgs bool
CalledString bool
CalledLookPath bool
CalledInteractive bool
CalledExec bool
CalledParseCommand bool

MockExecOut string
MockError error
Expand Down Expand Up @@ -51,3 +52,10 @@ func (f *FakeCommand) Exec(args ...string) (outStr string, err error) {
err = f.MockError
return
}

// Parse call the ParseCommand function
func (f *FakeCommand) Parse(line string) (err error) {
f.CalledParseCommand = true
err = f.MockError
return
}
86 changes: 86 additions & 0 deletions cmd/create.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
package cmd

import (
"fmt"
"kool-dev/kool/cmd/builder"
"kool-dev/kool/cmd/presets"
"os"

"github.com/spf13/cobra"
)

// KoolCreate holds handlers and functions to implement the preset command logic
type KoolCreate struct {
DefaultKoolService
parser presets.Parser
createCommand builder.Command
KoolPreset
}

func init() {
var (
create = NewKoolCreate()
createCmd = NewCreateCommand(create)
)

rootCmd.AddCommand(createCmd)
}

// NewKoolCreate creates a new handler for create logic
func NewKoolCreate() *KoolCreate {
return &KoolCreate{
*newDefaultKoolService(),
&presets.DefaultParser{},
&builder.DefaultCommand{},
*NewKoolPreset(),
}
}

// Execute runs the create logic with incoming arguments.
func (c *KoolCreate) Execute(originalArgs []string) (err error) {
preset := originalArgs[0]
dir := originalArgs[1]

c.parser.LoadPresets(presets.GetAll())

if !c.parser.Exists(preset) {
Comment thread
fabriciojs marked this conversation as resolved.
err = fmt.Errorf("Unknown preset %s", preset)
return
}

createCmd, err := c.parser.GetCreateCommand(preset)

if err != nil {
return
}

err = c.createCommand.Parse(createCmd)

if err != nil {
return
}

err = c.createCommand.Interactive(dir)

if err != nil {
return
}

_ = os.Chdir(dir)

err = c.KoolPreset.Execute([]string{preset})

return
}

// NewCreateCommand initializes new kool create command
func NewCreateCommand(create *KoolCreate) (createCmd *cobra.Command) {
createCmd = &cobra.Command{
Use: "create [preset] [project]",
Short: "Create a new project using preset",
Args: cobra.ExactArgs(2),
Run: DefaultCommandRunFunction(create),
}

return
}
126 changes: 126 additions & 0 deletions cmd/create_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
package cmd

import (
"bytes"
"kool-dev/kool/cmd/builder"
"kool-dev/kool/cmd/presets"
"kool-dev/kool/cmd/shell"
"testing"
)

func newFakeKoolCreate() *KoolCreate {
return &KoolCreate{
*newFakeKoolService(),
&presets.FakeParser{},
&builder.FakeCommand{},
*newFakeKoolPreset(),
}
}

func TestNewKoolCreate(t *testing.T) {
k := NewKoolCreate()

if _, ok := k.DefaultKoolService.out.(*shell.DefaultOutputWriter); !ok {
t.Errorf("unexpected shell.OutputWriter on default KoolCreate instance")
}

if _, ok := k.DefaultKoolService.exiter.(*shell.DefaultExiter); !ok {
t.Errorf("unexpected shell.Exiter on default KoolCreate instance")
}

if _, ok := k.DefaultKoolService.in.(*shell.DefaultInputReader); !ok {
t.Errorf("unexpected shell.InputReader on default KoolCreate instance")
}

if _, ok := k.createCommand.(*builder.DefaultCommand); !ok {
t.Errorf("unexpected builder.Command on default KoolCreate instance")
}

if _, ok := k.parser.(*presets.DefaultParser); !ok {
t.Errorf("unexpected presets.Parser on default KoolCreate instance")
}
}

func TestNewKoolCreateCommand(t *testing.T) {
f := newFakeKoolCreate()

f.parser.(*presets.FakeParser).MockExists = true
f.KoolPreset.parser.(*presets.FakeParser).MockExists = true
f.parser.(*presets.FakeParser).MockCreateCommand = "kool docker create command"

cmd := NewCreateCommand(f)
cmd.SetArgs([]string{"laravel", "my-app"})

if err := cmd.Execute(); err != nil {
t.Errorf("unexpected error executing create command; error: %v", err)
}

if !f.parser.(*presets.FakeParser).CalledLoadPresets {
t.Error("did not call parser.LoadPresets")
}

if !f.parser.(*presets.FakeParser).CalledExists {
t.Error("did not call parser.Exists")
}

if !f.parser.(*presets.FakeParser).CalledGetCreateCommand {
t.Error("did not call parser.GetCreateCommand")
}

if !f.createCommand.(*builder.FakeCommand).CalledParseCommand {
t.Error("did not call Parse on KoolCreate.createCommand Command")
}

if !f.createCommand.(*builder.FakeCommand).CalledInteractive {
t.Error("did not call Interactive on KoolCreate.createCommand Command")
}

if !f.out.(*shell.FakeOutputWriter).CalledSetWriter {
t.Error("did not call SetWriter")
}
}

func TestInvalidPresetCreateCommand(t *testing.T) {
f := newFakeKoolCreate()
cmd := NewCreateCommand(f)

cmd.SetArgs([]string{"invalid", "my-app"})

if err := cmd.Execute(); err != nil {
t.Errorf("unexpected error executing preset command; error: %v", err)
}

if !f.parser.(*presets.FakeParser).CalledLoadPresets {
t.Error("did not call parser.LoadPresets")
}

if !f.parser.(*presets.FakeParser).CalledExists {
t.Error("did not call parser.Exists")
}

if !f.out.(*shell.FakeOutputWriter).CalledError {
t.Error("did not call Error")
}

expected := "Unknown preset invalid"
output := f.out.(*shell.FakeOutputWriter).Err.Error()

if expected != output {
t.Errorf("expecting error '%s', got '%s'", expected, output)
}

if !f.exiter.(*shell.FakeExiter).Exited() {
t.Error("did not call Exit")
}
}

func TestNoArgsNewCreateCommand(t *testing.T) {
f := newFakeKoolCreate()

cmd := NewCreateCommand(f)
cmd.SetOut(bytes.NewBufferString(""))

if err := cmd.Execute(); err == nil {
t.Error("expecting no arguments error executing create command")
}
}
4 changes: 3 additions & 1 deletion cmd/preset.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ func NewKoolPreset() *KoolPreset {
return &KoolPreset{
*newDefaultKoolService(),
&KoolPresetFlags{false},
&presets.DefaultParser{Presets: presets.GetAll()},
&presets.DefaultParser{},
shell.NewTerminalChecker(),
shell.NewPromptSelect(),
}
Expand All @@ -67,6 +67,8 @@ func (p *KoolPreset) Execute(args []string) (err error) {
preset = args[0]
}

p.parser.LoadPresets(presets.GetAll())

if !p.parser.Exists(preset) {
err = fmt.Errorf("Unknown preset %s", preset)
return
Expand Down
29 changes: 22 additions & 7 deletions cmd/presets/fake_parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,16 @@ package presets

// FakeParser implements all fake behaviors for using parser in tests.
type FakeParser struct {
CalledExists, CalledLookUpFiles, CalledWriteFiles, CalledGetPresets, CalledGetLanguages bool
CalledExists, CalledLookUpFiles, CalledWriteFiles, CalledGetCreateCommand, CalledGetPresets, CalledGetLanguages, CalledLoadPresets bool

MockExists bool
MockFoundFiles []string
MockFileError string
MockError error
MockLanguages []string
MockPresets []string
MockExists bool
MockFoundFiles []string
MockFileError string
MockError error
MockCreateCommand string
MockLanguages []string
MockPresets []string
MockAllPresets map[string]map[string]string
}

// Exists check if preset exists
Expand All @@ -19,6 +21,13 @@ func (f *FakeParser) Exists(preset string) (exists bool) {
return
}

// GetCreateCommand gets the command to create a new project
func (f *FakeParser) GetCreateCommand(preset string) (cmd string, err error) {
Comment thread
fabriciojs marked this conversation as resolved.
f.CalledGetCreateCommand = true
cmd = f.MockCreateCommand
return
}

// GetLanguages get all presets languages
func (f *FakeParser) GetLanguages() (languages []string) {
f.CalledGetLanguages = true
Expand Down Expand Up @@ -47,3 +56,9 @@ func (f *FakeParser) WriteFiles(preset string) (fileError string, err error) {
err = f.MockError
return
}

//LoadPresets loads all presets
func (f *FakeParser) LoadPresets(presets map[string]map[string]string) {
f.CalledLoadPresets = true
f.MockAllPresets = presets
}
7 changes: 7 additions & 0 deletions cmd/presets/fake_parser_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,4 +43,11 @@ func TestFakeParser(t *testing.T) {
if !f.CalledGetLanguages || len(languages) != 1 || languages[0] != "php" {
t.Error("failed to use mocked GetPresets function on FakeParser")
}

f.MockCreateCommand = "create"
createCommand, _ := f.GetCreateCommand("")

if !f.CalledGetCreateCommand || createCommand == "" || createCommand != "create" {
t.Error("failed to use mocked GetCreateCommand function on FakeParser")
}
}
Loading