diff --git a/.github/workflows/golangci-lint.yaml b/.github/workflows/golangci-lint.yaml deleted file mode 100644 index 254eeb9..0000000 --- a/.github/workflows/golangci-lint.yaml +++ /dev/null @@ -1,38 +0,0 @@ -name: lint -on: - push: - tags: - - v* - branches: - - master - - main - pull_request: -jobs: - golangci: - name: golangci-lint - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v2 - - name: golangci-lint - uses: golangci/golangci-lint-action@v2.5.2 - with: - # Required: the version of golangci-lint is required and must be specified without patch version: we always use the latest patch version. - version: v1.42.0 - - # Optional: working directory, useful for monorepos - # working-directory: somedir - - # Optional: golangci-lint command line arguments. - # args: --issues-exit-code=0 - - # Optional: show only new issues if it's a pull request. The default value is `false`. - # only-new-issues: true - - # Optional: if set to true then the action will use pre-installed Go. - # skip-go-installation: true - - # Optional: if set to true then the action don't cache or restore ~/go/pkg. - # skip-pkg-cache: true - - # Optional: if set to true then the action don't cache or restore ~/.cache/go-build. - # skip-build-cache: true diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml deleted file mode 100644 index 42456e3..0000000 --- a/.github/workflows/test.yaml +++ /dev/null @@ -1,60 +0,0 @@ -name: test - -on: - push: - branches: - - master - pull_request: - -env: - GO111MODULE: "on" - GO_LATEST_VERSION: "1.17.x" - -jobs: - test: - strategy: - fail-fast: false - matrix: - os: [ ubuntu-latest, macos-latest ] - go-version: [ 1.16.x, 1.17.x ] - runs-on: ${{ matrix.os }} - steps: - - name: Install Go - uses: actions/setup-go@v2 - with: - go-version: ${{ matrix.go-version }} - - - name: Checkout code - uses: actions/checkout@v2 - - - name: Go cache - uses: actions/cache@v2 - with: - # In order: - # * Module download cache - # * Build cache (Linux) - path: | - ~/go/pkg/mod - ~/.cache/go-build - key: ${{ runner.os }}-go-${{ matrix.go-version }}-cache-${{ hashFiles('**/go.sum') }} - restore-keys: | - ${{ runner.os }}-go-${{ matrix.go-version }}-cache - - - name: Test - id: test - run: | - make test - - - name: Upload code coverage (unit) - if: matrix.go-version == env.GO_LATEST_VERSION - uses: codecov/codecov-action@v1 - with: - file: ./unit.coverprofile - flags: unittests-${{ runner.os }} - - - name: Upload code coverage (features) - if: matrix.go-version == env.GO_LATEST_VERSION - uses: codecov/codecov-action@v1 - with: - file: ./features.coverprofile - flags: featurestests-${{ runner.os }} diff --git a/Makefile b/Makefile deleted file mode 100644 index 18629a4..0000000 --- a/Makefile +++ /dev/null @@ -1,25 +0,0 @@ -VENDOR_DIR = vendor - -GO ?= go -GOLANGCI_LINT ?= golangci-lint - -.PHONY: $(VENDOR_DIR) lint test test-unit - -$(VENDOR_DIR): - @mkdir -p $(VENDOR_DIR) - @$(GO) mod vendor - @$(GO) mod tidy - -lint: - @$(GOLANGCI_LINT) run - -test: test-unit test-integration - -## Run unit tests -test-unit: - @echo ">> unit test" - @$(GO) test -gcflags=-l -coverprofile=unit.coverprofile -covermode=atomic -race ./... - -test-integration: - @echo ">> integration test" - @$(GO) test ./features/... -gcflags=-l -coverprofile=features.coverprofile -coverpkg ./... -race -v --godog diff --git a/README.md b/README.md index 4171bd1..69efe0b 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,10 @@ +> ⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️ +> +> This module is deprecated. Use `github.com/godogx/expandvars` instead. + # Variables Expander for Cucumber Steps [![GitHub Releases](https://img.shields.io/github/v/release/nhatthm/expandog)](https://github.com/nhatthm/expandog/releases/latest) -[![Build Status](https://github.com/nhatthm/expandog/actions/workflows/test.yaml/badge.svg)](https://github.com/nhatthm/expandog/actions/workflows/test.yaml) [![codecov](https://codecov.io/gh/nhatthm/expandog/branch/master/graph/badge.svg?token=eTdAgDE2vR)](https://codecov.io/gh/nhatthm/expandog) [![Go Report Card](https://goreportcard.com/badge/github.com/nhatthm/expandog)](https://goreportcard.com/report/github.com/nhatthm/expandog) [![GoDevDoc](https://img.shields.io/badge/dev-doc-00ADD8?logo=go)](https://pkg.go.dev/github.com/nhatthm/expandog) diff --git a/doc.go b/doc.go index f7c65e5..e36cf31 100644 --- a/doc.go +++ b/doc.go @@ -1,2 +1,4 @@ // Package expandog provides functionalities to expand variables in cucumber steps. +// +// Deprecated: Use github.com/godogx/expandvars instead. package expandog diff --git a/expander.go b/expander.go index 1ed12d3..c58bef7 100644 --- a/expander.go +++ b/expander.go @@ -1,100 +1,37 @@ package expandog import ( - "errors" - "fmt" - "os" - "strings" + "github.com/godogx/expandvars" ) -const varDelimiter = "$" - // ErrUnsupportedExpander indicates that the provided expander is not supported. -var ErrUnsupportedExpander = errors.New("unsupported expander") +// +// Deprecated: Use expandvars.ErrUnsupportedExpander instead. +var ErrUnsupportedExpander = expandvars.ErrUnsupportedExpander // EnvExpander expands variables using env vars. -var EnvExpander Expander = os.ExpandEnv +// +// Deprecated: Use expandvars.EnvExpander instead. +var EnvExpander = expandvars.EnvExpander // Pairs is a pair of old and new to be replaced. -type Pairs = map[string]string +// +// Deprecated: Use expandvars.Pairs instead. +type Pairs = expandvars.Pairs // Expander expands the variables in a string. -type Expander func(string) string +// +// Deprecated: Use expandvars.Expander instead. +type Expander = expandvars.Expander // Replacer replace string. -type Replacer interface { - Replace(string) string -} +// +// Deprecated: Use expandvars.Replacer instead. +type Replacer = expandvars.Replacer // BeforeScenario expands variables from a provider that will be called only once before every scenario. +// +// Deprecated: Use expandvars.BeforeScenario instead. func BeforeScenario(provide func() Pairs) func() Expander { - return func() Expander { - return mapExpander(provide()) - } -} - -func placeholder(name string) string { - return fmt.Sprintf("%s%s", varDelimiter, name) -} - -// runtimeExpander expands variables from a provider. -func runtimeExpander(provide func() Pairs) Expander { - return func(s string) string { - return mapExpander(provide())(s) - } -} - -// mapExpander initiates a new variable expander from a map of values. -func mapExpander(pairs Pairs) Expander { - oldNew := make([]string, 0, 2*len(pairs)) - - for k, v := range pairs { - oldNew = append(oldNew, placeholder(k), v) - } - - return strings.NewReplacer(oldNew...).Replace -} - -func chainExpanders(expanders ...interface{}) Expander { - l := make([]Expander, 0, len(expanders)) - - for _, e := range expanders { - l = append(l, newExpander(e)) - } - - return func(s string) string { - for _, expand := range l { - s = expand(s) - } - - return s - } -} - -func newExpander(e interface{}) Expander { - switch e := e.(type) { - case Pairs: - return mapExpander(e) - - case func() Pairs: - return runtimeExpander(e) - - case func() Expander: - return e() - - case Replacer: - return e.Replace - - case Expander: - return e - - case func(string) string: - return e - } - - panic(fmt.Errorf("%w: got %T", ErrUnsupportedExpander, e)) -} - -func doExpand(expand Expander, s string) string { - return expand(s) + return expandvars.BeforeScenario(provide) } diff --git a/expander_internal_test.go b/expander_internal_test.go deleted file mode 100644 index fa21885..0000000 --- a/expander_internal_test.go +++ /dev/null @@ -1,104 +0,0 @@ -package expandog - -import ( - "os" - "strings" - "testing" - - "github.com/stretchr/testify/assert" -) - -func TestPlaceholder(t *testing.T) { - t.Parallel() - - actual := placeholder("VAR") - expected := "$VAR" - - assert.Equal(t, expected, actual) -} - -func TestRuntimeExpander(t *testing.T) { - t.Parallel() - - expand := runtimeExpander(func() Pairs { - return Pairs{ - "HUSBAND": "John", - "WIFE": "Jane", - } - }) - - content := "$HUSBAND & $WIFE" - actual := expand(content) - expected := "John & Jane" - - assert.Equal(t, expected, actual) -} - -func TestMapExpander(t *testing.T) { - t.Parallel() - - expand := mapExpander(Pairs{ - "HUSBAND": "John", - "WIFE": "Jane", - }) - - content := "$HUSBAND & $WIFE" - actual := expand(content) - expected := "John & Jane" - - assert.Equal(t, expected, actual) -} - -func TestChainExpanders(t *testing.T) { - t.Parallel() - - expand := chainExpanders( - // Raw replacer. - strings.NewReplacer("$TO", "Berlin"), - // Our expanders. - Pairs{ - "HUSBAND": "John", - }, - func() Pairs { - return Pairs{ - "WIFE": "Jane", - } - }, - func() Expander { - return func(s string) string { - return strings.ReplaceAll(s, "$DURATION", "and stay there for 3 days") - } - }, - func(s string) string { - return strings.ReplaceAll(s, "$FROM", "Paris") - }, - Expander(func(s string) string { - return strings.ReplaceAll(s, "$TRANSPORT", "by bus") - }), - // Os. - EnvExpander, - ) - - // Set os env. - assert.NoError(t, os.Setenv("DATE", "Thursday")) - - defer func() { - _ = os.Unsetenv("DATE") // nolint:errcheck - }() - - content := "On $DATE, $HUSBAND & $WIFE are going from $FROM to $TO $TRANSPORT $DURATION" - actual := expand(content) - expected := "On Thursday, John & Jane are going from Paris to Berlin by bus and stay there for 3 days" - - assert.Equal(t, expected, actual) -} - -func TestChainExpanders_UnsupportedType(t *testing.T) { - t.Parallel() - - assert.PanicsWithError(t, "unsupported expander: got int", func() { - chainExpanders(Pairs{ - "HUSBAND": "John", - }, 42) - }) -} diff --git a/features/bootstrap/godog_test.go b/features/bootstrap/godog_test.go deleted file mode 100644 index a639df1..0000000 --- a/features/bootstrap/godog_test.go +++ /dev/null @@ -1,114 +0,0 @@ -package bootstrap - -import ( - "bytes" - "flag" - "fmt" - "io/ioutil" - "os" - "path/filepath" - "strings" - "testing" - "time" - - "github.com/cucumber/godog" - "github.com/spf13/pflag" - "github.com/stretchr/testify/assert" - - "github.com/nhatthm/expandog" -) - -// Used by init(). -// -//nolint:gochecknoglobals -var ( - runGoDogTests bool - - out = new(bytes.Buffer) - opt = godog.Options{ - Strict: true, - Output: out, - } -) - -// This has to run on init to define -godog flag, otherwise "undefined flag" error happens. -// -//nolint:gochecknoinits -func init() { - flag.BoolVar(&runGoDogTests, "godog", false, "Set this flag is you want to run godog BDD tests") - godog.BindCommandLineFlags("godog.", &opt) -} - -func TestMain(m *testing.M) { - flag.Parse() - pflag.Parse() - - os.Exit(m.Run()) -} - -func TestIntegration(t *testing.T) { - if !runGoDogTests { - t.Skip(`Missing "--godog" flag, skipping integration test.`) - } - - stepExpander := expandog.NewStepExpander( - expandog.Pairs{"NAME": "John"}, - expandog.BeforeScenario(func() expandog.Pairs { - return expandog.Pairs{ - "TIMESTAMP": fmt.Sprintf("%d", time.Now().UnixNano()), - } - }), - expandog.EnvExpander, - ) - - err := os.Setenv("FOOBAR", "foobar") - assert.NoError(t, err) - - stepCtx := newStepCtx() - - RunSuite(t, "..", func(t *testing.T, ctx *godog.ScenarioContext) { - t.Helper() - - stepExpander.RegisterContext(ctx) - stepCtx.RegisterContext(t, ctx) - }) -} - -func RunSuite(t *testing.T, path string, featureContext func(t *testing.T, ctx *godog.ScenarioContext)) { - t.Helper() - - var paths []string - - files, err := ioutil.ReadDir(filepath.Clean(path)) - assert.NoError(t, err) - - paths = make([]string, 0, len(files)) - - for _, f := range files { - if strings.HasSuffix(f.Name(), ".feature") { - paths = append(paths, filepath.Join(path, f.Name())) - } - } - - for _, path := range paths { - path := path - - t.Run(path, func(t *testing.T) { - opt.Paths = []string{path} - suite := godog.TestSuite{ - Name: "Integration", - TestSuiteInitializer: nil, - ScenarioInitializer: func(s *godog.ScenarioContext) { - featureContext(t, s) - }, - Options: &opt, - } - status := suite.Run() - - if status != 0 { - fmt.Println(out.String()) - assert.Failf(t, "one or more scenarios failed in feature: %s", path) - } - }) - } -} diff --git a/features/bootstrap/step_test.go b/features/bootstrap/step_test.go deleted file mode 100644 index 5f71a0d..0000000 --- a/features/bootstrap/step_test.go +++ /dev/null @@ -1,87 +0,0 @@ -package bootstrap - -import ( - "context" - "testing" - - "github.com/cucumber/godog" - "github.com/stretchr/testify/assert" -) - -type stepCtx struct { - test *testing.T - stepText string - stepArgument interface{} - timestamp string -} - -var doNothing = func() error { return nil } - -func (s *stepCtx) RegisterContext(t *testing.T, sc *godog.ScenarioContext) { - t.Helper() - - s.test = t - - sc.StepContext().After(func(_ context.Context, st *godog.Step, _ godog.StepResultStatus, _ error) (context.Context, error) { - s.stepText = st.Text - - if st.Argument == nil { - return nil, nil - } - - if st.Argument.DocString != nil { - s.stepArgument = st.Argument.DocString.Content - } - - if st.Argument.DataTable != nil { - s.stepArgument = st.Argument.DataTable - } - - return nil, nil - }) - - sc.Step("step text is:", s.assertStepText) - sc.Step("step argument is a string:", s.assertStepArgumentString) - sc.Step("step argument is a table:", s.assertStepArgumentTable) - sc.Step(`current timestamp is "([^"]*)"`, s.setCurrentTimestamp) - sc.Step(`timestamp = "([^"]*)"`, s.assertTimestamp) - sc.Step(".*", doNothing) -} - -func (s *stepCtx) assertStepText(text *godog.DocString) error { - assert.Equal(s.test, text.Content, s.stepText) - - return nil -} - -func (s *stepCtx) assertStepArgumentString(text *godog.DocString) error { - assert.Equal(s.test, text.Content, s.stepArgument) - - return nil -} - -func (s *stepCtx) assertStepArgumentTable(text *godog.Table) error { - assert.Equal(s.test, text, s.stepArgument) - - return nil -} - -func (s *stepCtx) setCurrentTimestamp(timestamp string) error { - assert.NotEqual(s.test, "$TIMESTAMP", timestamp) - assert.NotEqual(s.test, s.timestamp, timestamp) - - s.timestamp = timestamp - - return nil -} - -func (s *stepCtx) assertTimestamp(timestamp string) error { - assert.NotEqual(s.test, "$TIMESTAMP", timestamp) - assert.Equal(s.test, s.timestamp, timestamp) - - return nil -} - -func newStepCtx() *stepCtx { - return &stepCtx{} -} diff --git a/features/expand.feature b/features/expand.feature deleted file mode 100644 index d2f308e..0000000 --- a/features/expand.feature +++ /dev/null @@ -1,66 +0,0 @@ -Feature: - Expand variables - - Scenario: Env var is replaced - Given env var FOOBAR is replaced in step text: $FOOBAR - - Then step text is: - """ - env var FOOBAR is replaced in step text: foobar - """ - - Given env var FOOBAR is replaced in step argument (string) - """ - FOOBAR=$FOOBAR - """ - - Then step argument is a string: - """ - FOOBAR=foobar - """ - - Given env var FOOBAR is replaced in step argument (table) - | col 1 | col 2 | col 3 | - | value 1 | $FOOBAR | value 3 | - - Then step argument is a table: - | col 1 | col 2 | col 3 | - | value 1 | foobar | value 3 | - - Scenario: Map var is replaced - Given map var NAME is replaced in step text: $NAME - - Then step text is: - """ - map var NAME is replaced in step text: John - """ - - Given map var NAME is replaced in step argument (string) - """ - NAME=$NAME - """ - - Then step argument is a string: - """ - NAME=John - """ - - Given map var NAME is replaced in step argument (table) - | col 1 | col 2 | col 3 | - | value 1 | $NAME | value 3 | - - Then step argument is a table: - | col 1 | col 2 | col 3 | - | value 1 | John | value 3 | - - Scenario: Scenario Provider runs only once every scenario - Given current timestamp is "$TIMESTAMP" - - Then First call, timestamp = "$TIMESTAMP" - Then Second call, timestamp = "$TIMESTAMP" - - Scenario: Scenario Provider runs once again in another scenario - Given current timestamp is "$TIMESTAMP" - - Then First call, timestamp = "$TIMESTAMP" - Then Second call, timestamp = "$TIMESTAMP" diff --git a/go.mod b/go.mod index 18df531..ce076cf 100644 --- a/go.mod +++ b/go.mod @@ -1,10 +1,11 @@ +// Deprecated: Use github.com/godogx/expandvars instead. module github.com/nhatthm/expandog go 1.17 require ( github.com/cucumber/godog v0.12.1 - github.com/spf13/pflag v1.0.5 + github.com/godogx/expandvars v0.1.0 github.com/stretchr/testify v1.7.0 ) @@ -18,5 +19,6 @@ require ( github.com/hashicorp/golang-lru v0.5.4 // indirect github.com/kr/text v0.2.0 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect + github.com/spf13/pflag v1.0.5 // indirect gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776 // indirect ) diff --git a/go.sum b/go.sum index e0fb948..b7bcfee 100644 --- a/go.sum +++ b/go.sum @@ -52,6 +52,8 @@ github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2 github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= +github.com/godogx/expandvars v0.1.0 h1:msk+LqBDgtckUIwn37mhE4e+k7n+44wZZN8BpFTYWMI= +github.com/godogx/expandvars v0.1.0/go.mod h1:50+yWZ9Z9ueaisxOQz4AwaLjzf0XwdcEHYcIB/JYdrc= github.com/gofrs/uuid v4.0.0+incompatible h1:1SD/1F5pU8p29ybwgQSwpQk+mwdRrXCYuPhW6m+TnJw= github.com/gofrs/uuid v4.0.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= diff --git a/step.go b/step.go index 0214c93..b60ff39 100644 --- a/step.go +++ b/step.go @@ -1,66 +1,25 @@ package expandog import ( - "context" - "github.com/cucumber/godog" + "github.com/godogx/expandvars" ) // StepExpander expands variables in cucumber steps. -type StepExpander struct { - expanders []interface{} - expand Expander -} - -// RegisterExpander registers only the expander to the test suite to let it work. -// There will be no registration of step definition in this method. -func (m *StepExpander) RegisterExpander(s *godog.ScenarioContext) { - s.Before(func(ctx context.Context, sc *godog.Scenario) (context.Context, error) { - m.expand = chainExpanders(m.expanders...) - - return nil, nil - }) - - s.StepContext().Before(func(_ context.Context, st *godog.Step) (context.Context, error) { - expandStep(st, m.expand) - - return nil, nil - }) -} - -// RegisterContext register everything to the test suite. -func (m *StepExpander) RegisterContext(s *godog.ScenarioContext) { - m.RegisterExpander(s) -} +// +// Deprecated: Use expandvars.StepExpander instead. +type StepExpander = expandvars.StepExpander // NewStepExpander initiates a new variable expanders for cucumber steps. +// +// Deprecated: Use expandvars.NewStepExpander instead. func NewStepExpander(expanders ...interface{}) *StepExpander { - return &StepExpander{ - expanders: expanders, - } + return expandvars.NewStepExpander(expanders...) } // ExpandStep expands variables in the step definition using an expander. +// +// Deprecated: Use expandvars.ExpandStep instead. func ExpandStep(st *godog.Step, expanders ...interface{}) { - expandStep(st, chainExpanders(expanders...)) -} - -func expandStep(st *godog.Step, expand Expander) { - st.Text = doExpand(expand, st.Text) - - if st.Argument == nil { - return - } - - if st.Argument.DocString != nil { - st.Argument.DocString.Content = doExpand(expand, st.Argument.DocString.Content) - } - - if st.Argument.DataTable != nil { - for _, row := range st.Argument.DataTable.Rows { - for _, cell := range row.Cells { - cell.Value = doExpand(expand, cell.Value) - } - } - } + expandvars.ExpandStep(st, expanders...) } diff --git a/step_test.go b/step_test.go deleted file mode 100644 index 54cddac..0000000 --- a/step_test.go +++ /dev/null @@ -1,57 +0,0 @@ -package expandog_test - -import ( - "os" - "strings" - "testing" - - "github.com/cucumber/godog" - "github.com/stretchr/testify/assert" - - "github.com/nhatthm/expandog" -) - -func TestExpandStep(t *testing.T) { - t.Parallel() - - expanders := []interface{}{ - // Raw replacer. - strings.NewReplacer("$TO", "Berlin"), - // Our expanders. - expandog.Pairs{ - "HUSBAND": "John", - }, - func() expandog.Pairs { - return expandog.Pairs{ - "WIFE": "Jane", - } - }, - func() expandog.Expander { - return func(s string) string { - return strings.ReplaceAll(s, "$DURATION", "and stay there for 3 days") - } - }, - func(s string) string { - return strings.ReplaceAll(s, "$FROM", "Paris") - }, - expandog.Expander(func(s string) string { - return strings.ReplaceAll(s, "$TRANSPORT", "by bus") - }), - // Os. - expandog.EnvExpander, - } - - // Set os env. - assert.NoError(t, os.Setenv("GREETINGS", "Hi Dave")) - - defer func() { - _ = os.Unsetenv("GREETINGS") // nolint:errcheck - }() - - step := &godog.Step{Text: "$GREETINGS, $HUSBAND & $WIFE are going from $FROM to $TO $TRANSPORT $DURATION"} - expected := "Hi Dave, John & Jane are going from Paris to Berlin by bus and stay there for 3 days" - - expandog.ExpandStep(step, expanders...) - - assert.Equal(t, expected, step.Text) -}