Add ConfigCommand test #58

- Includes refactoring of existing packages to enable testing of commands
This commit is contained in:
Michael Mayer 2018-11-17 13:57:19 +01:00
parent 86a6dda0e0
commit 9872cfaa50
21 changed files with 168 additions and 55 deletions

View file

@ -7,13 +7,13 @@ import (
"github.com/urfave/cli"
)
// Prints current configuration
var ConfigCommand = cli.Command{
Name: "config",
Usage: "Displays global configuration values",
Action: configAction,
}
// Prints current configuration; called by ConfigCommand
func configAction(ctx *cli.Context) error {
conf := context.NewConfig(ctx)

View file

@ -0,0 +1,34 @@
package commands
import (
"testing"
"github.com/photoprism/photoprism/internal/test"
"github.com/stretchr/testify/assert"
)
func TestConfigCommand(t *testing.T) {
var err error
ctx := test.CliContext()
output := test.Capture(func() {
err = ConfigCommand.Run(ctx)
})
expected := `NAME VALUE
debug false
config-file /go/src/github.com/photoprism/photoprism/configs/photoprism.yml
darktable-cli /usr/bin/darktable-cli
originals-path /go/src/github.com/photoprism/photoprism/assets/testdata/originals
import-path /srv/photoprism/photos/import
export-path /srv/photoprism/photos/export
cache-path /srv/photoprism/cache
assets-path /go/src/github.com/photoprism/photoprism/assets
database-driver mysql
database-dsn photoprism:photoprism@tcp(database:3306)/photoprism?parseTime=true
`
assert.Equal(t, expected, output)
assert.Nil(t, err)
}

View file

@ -9,13 +9,13 @@ import (
"github.com/urfave/cli"
)
// Converts RAW files to JPEG images, if no JPEG already exists
var ConvertCommand = cli.Command{
Name: "convert",
Usage: "Converts RAW originals to JPEG",
Action: convertAction,
}
// Converts images to JPEG; called by ConvertCommand
func convertAction(ctx *cli.Context) error {
conf := context.NewConfig(ctx)

View file

@ -1,5 +1,5 @@
/*
This package contains commands and flags to be used by the main application.
This package contains commands and flags used by the photoprism application.
Additional information concerning the command-line interface can be found in our Developer Guide:

View file

@ -10,6 +10,7 @@ import (
"github.com/urfave/cli"
)
// Exports photos as JPEG thumbnails (resized)
var ExportCommand = cli.Command{
Name: "export",
Usage: "Exports photos as JPEG",
@ -37,7 +38,6 @@ var exportFlags = []cli.Flag{
},
}
// Exports photos as JPEG; called by ExportCommand and uses exportFlags
func exportAction(ctx *cli.Context) error {
conf := context.NewConfig(ctx)

View file

@ -2,6 +2,7 @@ package commands
import "github.com/urfave/cli"
// Global CLI flags
var GlobalFlags = []cli.Flag{
cli.BoolFlag{
Name: "debug",

View file

@ -9,13 +9,13 @@ import (
"github.com/urfave/cli"
)
// Imports photos from path defined in command-line args
var ImportCommand = cli.Command{
Name: "import",
Usage: "Imports photos",
Action: importAction,
}
// Imports photos from path defined in ctx arg; called by ImportCommand;
func importAction(ctx *cli.Context) error {
conf := context.NewConfig(ctx)

View file

@ -9,13 +9,13 @@ import (
"github.com/urfave/cli"
)
// Re-indexes all photos in originals directory (photo library)
var IndexCommand = cli.Command{
Name: "index",
Usage: "Re-indexes all originals",
Action: indexAction,
}
// Indexes original photos; called by IndexCommand
func indexAction(ctx *cli.Context) error {
conf := context.NewConfig(ctx)

View file

@ -7,13 +7,13 @@ import (
"github.com/urfave/cli"
)
// Automatically migrates / initializes database
var MigrateCommand = cli.Command{
Name: "migrate",
Usage: "Automatically migrates / initializes database",
Action: migrateAction,
}
// Automatically migrates / initializes database; called by MigrateCommand
func migrateAction(ctx *cli.Context) error {
conf := context.NewConfig(ctx)

View file

@ -9,6 +9,7 @@ import (
"github.com/urfave/cli"
)
// Starts web server (user interface)
var StartCommand = cli.Command{
Name: "start",
Usage: "Starts web server",
@ -37,7 +38,6 @@ var startFlags = []cli.Flag{
},
}
// Starts web serve using startFlags; called by startCommand
func startAction(ctx *cli.Context) error {
conf := context.NewConfig(ctx)

View file

@ -9,9 +9,10 @@ import (
"github.com/urfave/cli"
)
// Pre-renders thumbnails
var ThumbnailsCommand = cli.Command{
Name: "thumbnails",
Usage: "Creates thumbnails",
Usage: "Pre-renders thumbnails",
Flags: []cli.Flag{
cli.IntSliceFlag{
Name: "size, s",
@ -29,7 +30,6 @@ var ThumbnailsCommand = cli.Command{
Action: thumbnailsAction,
}
// Creates thumbnail; called by ThumbnailsCommand
func thumbnailsAction(ctx *cli.Context) error {
conf := context.NewConfig(ctx)

View file

@ -9,6 +9,7 @@ import (
_ "github.com/jinzhu/gorm/dialects/mysql"
_ "github.com/jinzhu/gorm/dialects/sqlite"
"github.com/kylelemons/go-gypsy/yaml"
"github.com/photoprism/photoprism/internal/frontend"
"github.com/photoprism/photoprism/internal/fsutil"
"github.com/photoprism/photoprism/internal/models"
"github.com/urfave/cli"
@ -42,8 +43,6 @@ type Config struct {
db *gorm.DB
}
type ClientConfig map[string]interface{}
// NewConfig() creates a new configuration entity by using two methods:
//
// 1. SetValuesFromFile: This will initialize values from a yaml config file.
@ -386,7 +385,7 @@ func (c *Config) MigrateDb() {
}
// GetClientConfig returns a loaded and set configuration entity.
func (c *Config) GetClientConfig() map[string]interface{} {
func (c *Config) GetClientConfig() frontend.Config {
db := c.GetDb()
var cameras []*models.Camera
@ -405,7 +404,7 @@ func (c *Config) GetClientConfig() map[string]interface{} {
jsHash := fsutil.Hash(c.GetPublicBuildPath() + "/app.js")
cssHash := fsutil.Hash(c.GetPublicBuildPath() + "/app.css")
result := ClientConfig{
result := frontend.Config{
"appName": c.GetAppName(),
"appVersion": c.GetAppVersion(),
"debug": c.IsDebug(),

View file

@ -1,46 +1,16 @@
package context
import (
"flag"
"testing"
"github.com/photoprism/photoprism/internal/fsutil"
"github.com/photoprism/photoprism/internal/test"
"github.com/stretchr/testify/assert"
"github.com/urfave/cli"
)
const testDataPath = "testdata"
const testConfigFile = "../../configs/photoprism.yml"
var darktableCli = "/usr/bin/darktable-cli"
var assetsPath = fsutil.ExpandedFilename("../../assets")
var originalsPath = fsutil.ExpandedFilename(testDataPath + "/originals")
var databaseDriver = "mysql"
var databaseDsn = "photoprism:photoprism@tcp(database:3306)/photoprism?parseTime=true"
func getTestCliContext() *cli.Context {
globalSet := flag.NewFlagSet("test", 0)
globalSet.Bool("debug", false, "doc")
globalSet.String("config-file", testConfigFile, "doc")
globalSet.String("assets-path", assetsPath, "doc")
globalSet.String("originals-path", originalsPath, "doc")
globalSet.String("darktable-cli", darktableCli, "doc")
app := cli.NewApp()
c := cli.NewContext(app, globalSet, nil)
c.Set("config-file", testConfigFile)
c.Set("assets-path", assetsPath)
c.Set("originals-path", originalsPath)
c.Set("darktable-cli", darktableCli)
return c
}
func TestNewConfig(t *testing.T) {
ctx := getTestCliContext()
ctx := test.CliContext()
assert.True(t, ctx.IsSet("assets-path"))
assert.False(t, ctx.Bool("debug"))
@ -49,14 +19,14 @@ func TestNewConfig(t *testing.T) {
assert.IsType(t, new(Config), c)
assert.Equal(t, assetsPath, c.GetAssetsPath())
assert.Equal(t, fsutil.ExpandedFilename("../../assets"), c.GetAssetsPath())
assert.False(t, c.IsDebug())
}
func TestConfig_SetValuesFromFile(t *testing.T) {
c := NewConfig(getTestCliContext())
c := NewConfig(test.CliContext())
c.SetValuesFromFile(fsutil.ExpandedFilename(testConfigFile))
c.SetValuesFromFile(fsutil.ExpandedFilename("../../configs/photoprism.yml"))
assert.Equal(t, "/srv/photoprism", c.GetAssetsPath())
assert.Equal(t, "/srv/photoprism/cache", c.GetCachePath())
@ -64,6 +34,6 @@ func TestConfig_SetValuesFromFile(t *testing.T) {
assert.Equal(t, "/srv/photoprism/photos/originals", c.GetOriginalsPath())
assert.Equal(t, "/srv/photoprism/photos/import", c.GetImportPath())
assert.Equal(t, "/srv/photoprism/photos/export", c.GetExportPath())
assert.Equal(t, databaseDriver, c.GetDatabaseDriver())
assert.Equal(t, databaseDsn, c.GetDatabaseDsn())
assert.Equal(t, "mysql", c.GetDatabaseDriver())
assert.Equal(t, "photoprism:photoprism@tcp(database:3306)/photoprism?parseTime=true", c.GetDatabaseDsn())
}

View file

@ -0,0 +1,4 @@
package frontend
// Config values for Web frontend
type Config map[string]interface{}

8
internal/frontend/doc.go Normal file
View file

@ -0,0 +1,8 @@
/*
Package frontend contains user interface related code.
Additional information can be found in our Developer Guide:
https://github.com/photoprism/photoprism/wiki
*/
package frontend

View file

@ -4,14 +4,16 @@ import (
"github.com/jinzhu/gorm"
_ "github.com/jinzhu/gorm/dialects/mysql"
_ "github.com/jinzhu/gorm/dialects/sqlite"
"github.com/photoprism/photoprism/internal/frontend"
)
// Todo: Remove Get prefix, see https://golang.org/doc/effective_go.html#Getters
type Config interface {
CreateDirectories() error
MigrateDb()
GetDb() *gorm.DB
GetClientConfig() map[string]interface{}
GetClientConfig() frontend.Config
GetConfigFile() string
GetAppName() string

35
internal/test/capture.go Normal file
View file

@ -0,0 +1,35 @@
package test
import (
"bytes"
"io"
"os"
)
// Returns output to stdout and stderr for testing
func Capture(f func()) string {
r, w, err := os.Pipe()
if err != nil {
panic(err)
}
stdout := os.Stdout
os.Stdout = w
defer func() {
os.Stdout = stdout
}()
stderr := os.Stderr
os.Stderr = w
defer func() {
os.Stderr = stderr
}()
f()
w.Close()
var buf bytes.Buffer
io.Copy(&buf, r)
return buf.String()
}

View file

@ -0,0 +1,18 @@
package test
import (
"fmt"
"os"
"testing"
"github.com/stretchr/testify/assert"
)
func TestCapture(t *testing.T) {
result := Capture(func() {
fmt.Fprint(os.Stdout, "foo")
fmt.Fprint(os.Stderr, "bar")
})
assert.Equal(t, "foobar", result)
}

View file

@ -10,7 +10,7 @@ import (
"github.com/jinzhu/gorm"
_ "github.com/jinzhu/gorm/dialects/mysql"
_ "github.com/jinzhu/gorm/dialects/sqlite"
"github.com/photoprism/photoprism/internal/context"
"github.com/photoprism/photoprism/internal/frontend"
"github.com/photoprism/photoprism/internal/fsutil"
"github.com/photoprism/photoprism/internal/models"
)
@ -296,7 +296,7 @@ func (c *Config) MigrateDb() {
}
// GetClientConfig returns a loaded and set configuration entity.
func (c *Config) GetClientConfig() map[string]interface{} {
func (c *Config) GetClientConfig() frontend.Config {
db := c.GetDb()
var cameras []*models.Camera
@ -315,7 +315,7 @@ func (c *Config) GetClientConfig() map[string]interface{} {
jsHash := fsutil.Hash(c.GetPublicBuildPath() + "/app.js")
cssHash := fsutil.Hash(c.GetPublicBuildPath() + "/app.css")
result := context.ClientConfig{
result := frontend.Config{
"appName": c.GetAppName(),
"appVersion": c.GetAppVersion(),
"debug": c.IsDebug(),

28
internal/test/context.go Normal file
View file

@ -0,0 +1,28 @@
package test
import (
"flag"
"github.com/urfave/cli"
)
// Returns example cli context for testing
func CliContext() *cli.Context {
globalSet := flag.NewFlagSet("test", 0)
globalSet.Bool("debug", false, "doc")
globalSet.String("config-file", ConfigFile, "doc")
globalSet.String("assets-path", AssetsPath, "doc")
globalSet.String("originals-path", OriginalsPath, "doc")
globalSet.String("darktable-cli", DarktableCli, "doc")
app := cli.NewApp()
c := cli.NewContext(app, globalSet, nil)
c.Set("config-file", ConfigFile)
c.Set("assets-path", AssetsPath)
c.Set("originals-path", OriginalsPath)
c.Set("darktable-cli", DarktableCli)
return c
}

View file

@ -0,0 +1,14 @@
package test
import (
"testing"
"github.com/stretchr/testify/assert"
"github.com/urfave/cli"
)
func TestCliContext(t *testing.T) {
result := CliContext()
assert.IsType(t, new(cli.Context), result)
}