Skip to content

Commit

Permalink
commands: Add CLI tests
Browse files Browse the repository at this point in the history
  • Loading branch information
bep committed Apr 11, 2018
1 parent 4d32f2f commit e8d6ca9
Show file tree
Hide file tree
Showing 10 changed files with 199 additions and 71 deletions.
3 changes: 1 addition & 2 deletions commands/benchmark.go
Expand Up @@ -45,8 +45,6 @@ creating a benchmark.`,
cmd.Flags().StringVar(&c.memProfileFile, "memprofile", "", "path/filename for the memory profile file")
cmd.Flags().IntVarP(&c.benchmarkTimes, "count", "n", 13, "number of times to build the site")

cmd.Flags().Bool("renderToMemory", false, "render to memory (only useful for benchmark testing)")

cmd.RunE = c.benchmark

return c
Expand All @@ -56,6 +54,7 @@ func (c *benchmarkCmd) benchmark(cmd *cobra.Command, args []string) error {
cfgInit := func(c *commandeer) error {
return nil
}

comm, err := initializeConfig(false, &c.hugoBuilderCommon, c, cfgInit)
if err != nil {
return err
Expand Down
4 changes: 2 additions & 2 deletions commands/commandeer.go
Expand Up @@ -40,7 +40,7 @@ import (
type commandeer struct {
*deps.DepsCfg

h *hugoBuilderCommon
h *hugoBuilderCommon
ftch flagsToConfigHandler

pathSpec *helpers.PathSpec
Expand Down Expand Up @@ -109,7 +109,7 @@ func newCommandeer(running bool, h *hugoBuilderCommon, f flagsToConfigHandler, d

c := &commandeer{
h: h,
ftch: f,
ftch: f,
doWithCommandeer: doWithCommandeer,
visitedURLs: types.NewEvictingStringQueue(10),
debounce: rebuildDebouncer,
Expand Down
133 changes: 133 additions & 0 deletions commands/commands_test.go
@@ -0,0 +1,133 @@
// Copyright 2018 The Hugo Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package commands

import (
"fmt"
"io/ioutil"
"os"
"path/filepath"
"testing"

"github.com/stretchr/testify/require"
)

func TestCommands(t *testing.T) {

assert := require.New(t)

dir, err := createSimpleTestSite(t)
assert.NoError(err)

dirOut, err := ioutil.TempDir("", "hugo-cli-out")
assert.NoError(err)

defer func() {
os.RemoveAll(dir)
os.RemoveAll(dirOut)
}()

sourceFlag := fmt.Sprintf("-s=%s", dir)

tests := []struct {
commands []string
flags []string
}{
{[]string{"check", "ulimit"}, nil},
{[]string{"env"}, nil},
{[]string{"version"}, nil},
// no args = hugo build
{nil, []string{sourceFlag}},
// TODO(bep) cli refactor remove the HugoSites global and enable the below
//{nil, []string{sourceFlag, "--renderToMemory"}},
{[]string{"benchmark"}, []string{sourceFlag, "-n=1"}},
{[]string{"convert", "toTOML"}, []string{sourceFlag, "-o=" + filepath.Join(dirOut, "toml")}},
{[]string{"convert", "toYAML"}, []string{sourceFlag, "-o=" + filepath.Join(dirOut, "yaml")}},
{[]string{"convert", "toJSON"}, []string{sourceFlag, "-o=" + filepath.Join(dirOut, "json")}},
{[]string{"gen", "autocomplete"}, []string{"--completionfile=" + filepath.Join(dirOut, "autocomplete.txt")}},
{[]string{"gen", "chromastyles"}, []string{"--style=manni"}},
{[]string{"gen", "doc"}, []string{"--dir=" + filepath.Join(dirOut, "doc")}},
{[]string{"gen", "man"}, []string{"--dir=" + filepath.Join(dirOut, "man")}},
{[]string{"list", "drafts"}, []string{sourceFlag}},
{[]string{"list", "expired"}, []string{sourceFlag}},
{[]string{"list", "future"}, []string{sourceFlag}},
{[]string{"new", "new-page.md"}, []string{sourceFlag}},
{[]string{"new", "site", filepath.Join(dirOut, "new-site")}, nil},
// TODO(bep) cli refactor fix https://github.com/gohugoio/hugo/issues/4450
//{[]string{"new", "theme", filepath.Join(dirOut, "new-theme")}, nil},
}

for _, test := range tests {

hugoCmd := newHugoCompleteCmd()
test.flags = append(test.flags, "--quiet")
hugoCmd.SetArgs(append(test.commands, test.flags...))

// TODO(bep) capture output and add some simple asserts

assert.NoError(hugoCmd.Execute(), fmt.Sprintf("%v", test.commands))
}

}

func createSimpleTestSite(t *testing.T) (string, error) {
d, e := ioutil.TempDir("", "hugo-cli")
if e != nil {
return "", e
}

// Just the basic. These are for CLI tests, not site testing.
writeFile(t, filepath.Join(d, "config.toml"), `
baseURL = "https://example.org"
title = "Hugo Commands"
`)

writeFile(t, filepath.Join(d, "content", "p1.md"), `
---
title: "P1"
weight: 1
---
Content
`)

writeFile(t, filepath.Join(d, "layouts", "_default", "single.html"), `
Single: {{ .Title }}
`)

writeFile(t, filepath.Join(d, "layouts", "_default", "list.html"), `
List: {{ .Title }}
`)

return d, nil

}

func writeFile(t *testing.T, filename, content string) {
must(t, os.MkdirAll(filepath.Dir(filename), os.FileMode(0755)))
must(t, ioutil.WriteFile(filename, []byte(content), os.FileMode(0755)))
}

func must(t *testing.T, err error) {
if err != nil {
t.Fatal(err)
}
}
27 changes: 13 additions & 14 deletions commands/convert.go
Expand Up @@ -32,17 +32,17 @@ var (
_ cmder = (*convertCmd)(nil)
)

// TODO(bep) cli refactor
var outputDir string
var unsafe bool

type convertCmd struct {
outputDir string
unsafe bool

*baseBuilderCmd
}

func newConvertCmd() *convertCmd {
cc := &convertCmd{}

// TODO(bep) cli refactor this is more than it had
cc.baseBuilderCmd = newBuilderCmd(&cobra.Command{
Use: "convert",
Short: "Convert your content to different formats",
Expand Down Expand Up @@ -82,17 +82,16 @@ to use YAML for the front matter.`,
},
)

// TODO(bep) cli refactor
// cmd.PersistentFlags().StringVarP(&outputDir, "output", "o", "", "filesystem path to write files to")
// cmd.PersistentFlags().StringVarP(&source, "source", "s", "", "filesystem path to read files relative from")
// cmd.PersistentFlags().BoolVar(&unsafe, "unsafe", false, "enable less safe operations, please backup first")
cc.cmd.PersistentFlags().StringVarP(&cc.outputDir, "output", "o", "", "filesystem path to write files to")
cc.cmd.PersistentFlags().StringVarP(&cc.source, "source", "s", "", "filesystem path to read files relative from")
cc.cmd.PersistentFlags().BoolVar(&cc.unsafe, "unsafe", false, "enable less safe operations, please backup first")
cc.cmd.PersistentFlags().SetAnnotation("source", cobra.BashCompSubdirsInDir, []string{})

return cc
}

func (cc *convertCmd) convertContents(mark rune) error {
if outputDir == "" && !unsafe {
if cc.outputDir == "" && !cc.unsafe {
return newUserError("Unsafe operation not allowed, use --unsafe or set a different output path")
}

Expand All @@ -114,17 +113,17 @@ func (cc *convertCmd) convertContents(mark rune) error {

site.Log.FEEDBACK.Println("processing", len(site.AllPages), "content files")
for _, p := range site.AllPages {
if err := convertAndSavePage(p, site, mark); err != nil {
if err := cc.convertAndSavePage(p, site, mark); err != nil {
return err
}
}
return nil
}

func convertAndSavePage(p *hugolib.Page, site *hugolib.Site, mark rune) error {
func (cc *convertCmd) convertAndSavePage(p *hugolib.Page, site *hugolib.Site, mark rune) error {
// The resources are not in .Site.AllPages.
for _, r := range p.Resources.ByType("page") {
if err := convertAndSavePage(r.(*hugolib.Page), site, mark); err != nil {
if err := cc.convertAndSavePage(r.(*hugolib.Page), site, mark); err != nil {
return err
}
}
Expand Down Expand Up @@ -182,8 +181,8 @@ func convertAndSavePage(p *hugolib.Page, site *hugolib.Site, mark rune) error {
}

newFilename := p.Filename()
if outputDir != "" {
newFilename = filepath.Join(outputDir, p.Dir(), newPage.LogicalName())
if cc.outputDir != "" {
newFilename = filepath.Join(cc.outputDir, p.Dir(), newPage.LogicalName())
}

if err = newPage.SaveSourceAs(newFilename); err != nil {
Expand Down
33 changes: 16 additions & 17 deletions commands/hugo.go
Expand Up @@ -141,6 +141,9 @@ Complete documentation is available at http://gohugo.io/.`,
// Set bash-completion
_ = cc.cmd.PersistentFlags().SetAnnotation("logFile", cobra.BashCompFilenameExt, []string{})

cc.cmd.SetGlobalNormalizationFunc(helpers.NormalizeHugoFlags)
cc.cmd.SilenceUsage = true

return cc
}

Expand Down Expand Up @@ -191,6 +194,7 @@ func (cc *hugoBuilderCommon) handleFlags(cmd *cobra.Command) {
cmd.Flags().BoolP("noTimes", "", false, "don't sync modification time of files")
cmd.Flags().BoolP("noChmod", "", false, "don't sync permission mode of files")
cmd.Flags().BoolP("i18n-warnings", "", false, "print missing translations")
cmd.Flags().Bool("renderToMemory", false, "render to memory (only useful for benchmark testing)")

cmd.Flags().StringSlice("disableKinds", []string{}, "disable different kind of pages (home, RSS etc.)")

Expand All @@ -214,23 +218,11 @@ func Reset() error {
return nil
}

var (
hugoCommand = newHugoCmd()

// HugoCmd is Hugo's root command.
// Every other command attached to HugoCmd is a child command to it.
HugoCmd = hugoCommand.getCommand()
)

// Execute adds all child commands to the root command HugoCmd and sets flags appropriately.
func Execute() {
HugoCmd.SetGlobalNormalizationFunc(helpers.NormalizeHugoFlags)
hugoCmd := newHugoCompleteCmd()

HugoCmd.SilenceUsage = true

addAllCommands()

if c, err := HugoCmd.ExecuteC(); err != nil {
if c, err := hugoCmd.ExecuteC(); err != nil {
if isUserError(err) {
c.Println("")
c.Println(c.UsageString())
Expand All @@ -240,9 +232,16 @@ func Execute() {
}
}

func newHugoCompleteCmd() *cobra.Command {
hugoCmd := newHugoCmd().getCommand()
addAllCommands(hugoCmd)
return hugoCmd
}

// addAllCommands adds child commands to the root command HugoCmd.
func addAllCommands() {
func addAllCommands(root *cobra.Command) {
addCommands(
root,
newServerCmd(),
newVersionCmd(),
newEnvCmd(),
Expand All @@ -257,9 +256,9 @@ func addAllCommands() {
)
}

func addCommands(commands ...cmder) {
func addCommands(root *cobra.Command, commands ...cmder) {
for _, command := range commands {
HugoCmd.AddCommand(command.getCommand())
root.AddCommand(command.getCommand())
}
}

Expand Down
2 changes: 1 addition & 1 deletion commands/list.go
Expand Up @@ -151,7 +151,7 @@ expired.`,
)

// TODO(bep) cli refactor
// cc.cmd.PersistentFlags().StringVarP(&source, "source", "s", "", "filesystem path to read files relative from")
cc.cmd.PersistentFlags().StringVarP(&cc.source, "source", "s", "", "filesystem path to read files relative from")
cc.cmd.PersistentFlags().SetAnnotation("source", cobra.BashCompSubdirsInDir, []string{})

return cc
Expand Down
27 changes: 13 additions & 14 deletions commands/new.go
Expand Up @@ -30,15 +30,16 @@ import (
var _ cmder = (*newCmd)(nil)

type newCmd struct {
hugoBuilderCommon
contentEditor string
contentType string

*baseCmd
}

func newNewCmd() *newCmd {
ccmd := &newCmd{baseCmd: newBaseCmd(nil)}
cmd := &cobra.Command{
cc := &newCmd{}
cc.baseCmd = newBaseCmd(&cobra.Command{
Use: "new [path]",
Short: "Create new content for your site",
Long: `Create a new content file and automatically set the date and title.
Expand All @@ -48,21 +49,19 @@ You can also specify the kind with ` + "`-k KIND`" + `.
If archetypes are provided in your theme or site, they will be used.`,

RunE: ccmd.newContent,
}
RunE: cc.newContent,
})

cmd.Flags().StringVarP(&ccmd.contentType, "kind", "k", "", "content type to create")
cc.cmd.Flags().StringVarP(&cc.contentType, "kind", "k", "", "content type to create")
// TODO(bep) cli refactor
// cmd.PersistentFlags().StringVarP(&source, "source", "s", "", "filesystem path to read files relative from")
cmd.PersistentFlags().SetAnnotation("source", cobra.BashCompSubdirsInDir, []string{})
cmd.Flags().StringVar(&ccmd.contentEditor, "editor", "", "edit new content with this editor, if provided")

cmd.AddCommand(newNewSiteCmd().getCommand())
cmd.AddCommand(newNewThemeCmd().getCommand())
cc.cmd.PersistentFlags().StringVarP(&cc.source, "source", "s", "", "filesystem path to read files relative from")
cc.cmd.PersistentFlags().SetAnnotation("source", cobra.BashCompSubdirsInDir, []string{})
cc.cmd.Flags().StringVar(&cc.contentEditor, "editor", "", "edit new content with this editor, if provided")

ccmd.cmd = cmd
cc.cmd.AddCommand(newNewSiteCmd().getCommand())
cc.cmd.AddCommand(newNewThemeCmd().getCommand())

return ccmd
return cc
}

func (n *newCmd) newContent(cmd *cobra.Command, args []string) error {
Expand All @@ -73,7 +72,7 @@ func (n *newCmd) newContent(cmd *cobra.Command, args []string) error {
return nil
}

c, err := initializeConfig(false, nil, n, cfgInit)
c, err := initializeConfig(false, &n.hugoBuilderCommon, n, cfgInit)

if err != nil {
return err
Expand Down

0 comments on commit e8d6ca9

Please sign in to comment.