Skip to content

Commit

Permalink
get language from file name
Browse files Browse the repository at this point in the history
  • Loading branch information
Dmitrii Malinovskii committed Jun 19, 2024
1 parent 98fd2e6 commit ef24c9f
Show file tree
Hide file tree
Showing 8 changed files with 145 additions and 33 deletions.
83 changes: 50 additions & 33 deletions internal/app/app.feature
Original file line number Diff line number Diff line change
@@ -1,55 +1,56 @@
Feature: Application command line tool

Scenario Outline: User wants to generate the output in given format
When <format> is given
And <feature> is provided
Then the output should be generated
Examples:
| <feature> | <format> | <assertion> |
| app.feature | go | does |
| app.feature | json | does |
| app.feature | raw | does |
| app.feature | invalid | does not |
| notfound.feature | raw | does not |
| <feature> | <format> | <assertion> |
| app.feature | go | does |
| app.feature | json | does |
| app.feature | raw | does |
| app.feature | invalid | does not |
| notfound.feature | raw | does not |

Scenario Outline: User wants to see usage information
When <flag> is provided
Then usage should be printed
Examples:
| <flag> |
| --help |
| <flag> |
| --help |

Scenario Outline: User wants to list built-in templates
When <flag> is provided
Then templates should be printed
Examples:
| <flag> |
| --list |
| <flag> |
| --list |

Scenario Outline: User wants to use custom template
When <template> is provided
And <feature> is provided
Then the output should be generated
Examples:
| <feature> | <template> |
| app.feature | ../assets/std.simple.v1.go.tmpl |
| app.feature | @/std.simple.v1.go.tmpl |
| <feature> | <template> |
| app.feature | ../assets/std.simple.v1.go.tmpl |
| app.feature | @/std.simple.v1.go.tmpl |

Scenario Outline: User wants to set custom package
When <package> is provided
Then the output should contain <package>
Examples:
| <package> |
| app_test |
| example_test |
| <package> |
| app_test |
| example_test |

Scenario Outline: User wants to generate a permanent json output
When -format is json
And -permanent-ids is <TheSameIDs>
Then calling generation twice will produce the same output <TheSameIDs>
Examples:
| <TheSameIDs> |
| true |
| false |
| <TheSameIDs> |
| true |
| false |

Scenario: User provides an invalid flag
When flag -invalid is provided
Expand All @@ -59,17 +60,17 @@ Feature: Application command line tool
When <flag> is provided
Then version is printed
Examples:
| <flag> |
| --version |
| -version |
| <flag> |
| --version |
| -version |

Scenario Outline: User specifies a file, but the file is not found
When inexistent <template> is provided
And <feature> is provided
Then the user receives an error
Examples:
| <feature> | <template> |
| app.feature | not_found |
| <feature> | <template> |
| app.feature | not_found |

Scenario: User wants to run tests in parallel
When `scenario.feature` is given
Expand All @@ -85,19 +86,35 @@ Feature: Application command line tool
And the <feature> is provided
Then the output should be generated
Examples:
| <language> | <feature> | assertion |
| en | ../generator/examples/simple.feature | does |
| en-pirate | ../generator/examples/simple.en-pirate.feature | does |
| unsupported | app.feature | does not |
| <language> | <feature> | assertion |
| en | ../generator/examples/simple.feature | does |
| en-pirate | ../generator/examples/simple.en-pirate.feature | does |
| unsupported | app.feature | does not |

Scenario Outline: User wants to see all supported natural languages
When the <flag> is provided
Then the list of supported natural languages should be printed
Examples:
| <flag> |
| -languages |
| --languages |
| <flag> |
| -languages |
| --languages |

Scenario: User wants to see consistent supported natural languages output
When the user lists supported natural languages several times
Then the output is the same

Scenario Outline: User wants to be able to specify the natural language of a feature in its file name
When the <language> is specified by the flag
And the <feature> is given
Then the output should be generated
Examples:
| <language> | <feature> | assertion |
| en-pirate | ./testdata/pirate.feature | does |
| | ./testdata/pirate.feature | does not |
| | ./testdata/pirate.sample.en-pirate.feature | does |
| wrong | ./testdata/pirate.sample.en-pirate.feature | does not |
| en | ./testdata/english.feature | does |
| | ./testdata/english.feature | does |
| | ./testdata/english.sample.en.feature | does |
| wrong | ./testdata/english.sample.en.feature | does not |
| | app.feature | does |
9 changes: 9 additions & 0 deletions internal/app/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"flag"
"io"
"math/rand"
"slices"
"strings"
"time"

Expand All @@ -22,6 +23,8 @@ const (
)

// Run the application.
//
//nolint:cyclop // Looks fine to me.
func Run(arguments []string, out io.Writer, version string) (err error) {
flagSet := flag.NewFlagSet(flag.CommandLine.Name(), flag.ContinueOnError)
flagSet.SetOutput(out)
Expand Down Expand Up @@ -98,6 +101,12 @@ func Run(arguments []string, out io.Writer, version string) (err error) {
inputFile = flagSet.Args()[0]
}

if !slices.Contains(arguments, "-language") {
if hint := tryFromFileName(inputFile); hint != "" {
*language = hint
}
}

switch {
case *versionCmd:
return runVersion(out, version)
Expand Down
42 changes: 42 additions & 0 deletions internal/app/app_test.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
//nolint:goconst // These are auto generated tests.
package app_test

import (
Expand Down Expand Up @@ -201,6 +202,47 @@ func TestApplicationCommandLineTool(t *testing.T) {
// Then the output is the same.
assert.Equal(t, out1, out2)
})

t.Run("User wants to be able to specify the natural language of a feature in its file name", func(t *testing.T) {
t.Parallel()

type testCase struct {
Language string `field:"<language>"`
Feature string `field:"<feature>"`
Assertion string `field:"assertion"`
}

testCases := map[string]testCase{
"en-pirate_./testdata/pirate.feature_does": {"en-pirate", "./testdata/pirate.feature", "does"},
"_./testdata/pirate.feature_does_not": {"", "./testdata/pirate.feature", "does not"},
"_./testdata/pirate.sample.en-pirate.feature_does": {"", "./testdata/pirate.sample.en-pirate.feature", "does"},
"wrong_./testdata/pirate.sample.en-pirate.feature_does_not": {"wrong", "./testdata/pirate.sample.en-pirate.feature", "does not"},
"en_./testdata/english.feature_does": {"en", "./testdata/english.feature", "does"},
"_./testdata/english.feature_does": {"", "./testdata/english.feature", "does"},
"_./testdata/english.sample.en.feature_does": {"", "./testdata/english.sample.en.feature", "does"},
"wrong_./testdata/english.sample.en.feature_does_not": {"wrong", "./testdata/english.sample.en.feature", "does not"},
"_app.feature_does": {"", "app.feature", "does"},
}

for name, testCase := range testCases {
t.Run(name, func(t *testing.T) {
t.Parallel()

var arguments []string

// When the <language> is specified by the flag.
if testCase.Language != "" {
arguments = append(arguments, "-language", testCase.Language)
}

// And the <feature> is given.
arguments = append(arguments, testCase.Feature)

// Then the output should be generated.
runApp(t, arguments, testCase.Assertion == "does")
})
}
})
}

func TestApplicationCommandLineToolCustom(t *testing.T) {
Expand Down
14 changes: 14 additions & 0 deletions internal/app/languages.go → internal/app/language.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,3 +51,17 @@ func featureLanguages() ([]*gherkin.Dialect, error) {

return dialects, nil
}

func tryFromFileName(fileName string) string {
i := strings.LastIndexAny(fileName, "/\\")

lastPart := fileName[i+1:]

parts := strings.Split(lastPart, ".")

if len(parts) <= 2 {
return ""
}

return parts[len(parts)-2]
}
7 changes: 7 additions & 0 deletions internal/app/testdata/english.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
Feature: Guess the word

The word guess game is a turn-based game for two players.
The Maker makes a word for the Breaker to guess. The game
is over when the Breaker guesses the Maker's word.

Example: Maker starts a game
7 changes: 7 additions & 0 deletions internal/app/testdata/english.sample.en.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
Feature: Guess the word

The word guess game is a turn-based game for two players.
The Maker makes a word for the Breaker to guess. The game
is over when the Breaker guesses the Maker's word.

Example: Maker starts a game
8 changes: 8 additions & 0 deletions internal/app/testdata/pirate.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
Ahoy matey!: Guessin' the Word!

This be a game o' guessin' words, turn-based and for two scallywags only!
The Maker, a cunning buccaneer, chooses a secret word for the Breaker to decipher.
The Breaker, a sharp wit, tries to guess the Maker's hidden word.
The game be done when the Breaker shouts out the right word!

Heave to: The Maker starts a game!
8 changes: 8 additions & 0 deletions internal/app/testdata/pirate.sample.en-pirate.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
Ahoy matey!: Guessin' the Word!

This be a game o' guessin' words, turn-based and for two scallywags only!
The Maker, a cunning buccaneer, chooses a secret word for the Breaker to decipher.
The Breaker, a sharp wit, tries to guess the Maker's hidden word.
The game be done when the Breaker shouts out the right word!

Heave to: The Maker starts a game!

0 comments on commit ef24c9f

Please sign in to comment.