Skip to content
Closed
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
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
go-blueprint
site

.idea
55 changes: 30 additions & 25 deletions cmd/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -196,35 +196,32 @@ var createCmd = &cobra.Command{
}
}

if flagAdvanced {

featureFlags := cmd.Flag("feature").Value.String()
// Process feature flags (can be used independently of --advanced flag)
featureFlags := cmd.Flag("feature").Value.String()

if featureFlags != "" {
featuresFlagValues := strings.Split(featureFlags, ",")
for _, key := range featuresFlagValues {
project.AdvancedOptions[key] = true
}
} else {
isInteractive = true
step := steps.Steps["advanced"]
tprogram = tea.NewProgram((multiSelect.InitialModelMultiSelect(step.Options, options.Advanced, step.Headers, project)))
if _, err := tprogram.Run(); err != nil {
cobra.CheckErr(textinput.CreateErrorInputModel(err).Err())
}
project.ExitCLI(tprogram)
for key, opt := range options.Advanced.Choices {
project.AdvancedOptions[strings.ToLower(key)] = opt
err := cmd.Flag("feature").Value.Set(strings.ToLower(key))
if err != nil {
log.Fatal("failed to set the feature flag value", err)
}
}
if featureFlags != "" {
featuresFlagValues := strings.Split(featureFlags, ",")
for _, key := range featuresFlagValues {
project.AdvancedOptions[key] = true
}
} else if flagAdvanced {
isInteractive = true
step := steps.Steps["advanced"]
tprogram = tea.NewProgram((multiSelect.InitialModelMultiSelect(step.Options, options.Advanced, step.Headers, project)))
if _, err := tprogram.Run(); err != nil {
cobra.CheckErr(textinput.CreateErrorInputModel(err).Err())
}
project.ExitCLI(tprogram)
for key, opt := range options.Advanced.Choices {
project.AdvancedOptions[strings.ToLower(key)] = opt
err := cmd.Flag("feature").Value.Set(strings.ToLower(key))
if err != nil {
log.Fatal("failed to set the htmx option", err)
log.Fatal("failed to set the feature flag value", err)
}
}

if err != nil {
log.Fatal("failed to set the htmx option", err)
}
}

if project.GitOptions == "" {
Expand Down Expand Up @@ -305,6 +302,14 @@ var createCmd = &cobra.Command{
fmt.Println(endingMsgStyle.Render("• Generate templ function files by running `templ generate`\n"))
}

if options.Advanced.Choices["Kafka"] {
fmt.Println(endingMsgStyle.Render("• Configure Kafka broker settings in the .env file\n"))
fmt.Println(endingMsgStyle.Render("• Build the consumer binary: `go build -o consumer ./cmd/consumer`\n"))
fmt.Println(endingMsgStyle.Render("• Run the consumer: `./consumer` or `go run ./cmd/consumer`\n"))
fmt.Println(endingMsgStyle.Render("• Implementation in pkg/kafka/segmentio/, example in integration_example.go\n"))
fmt.Println(endingMsgStyle.Render("• Customize message processing in pkg/kafka/segmentio/consumer.go\n"))
}

if isInteractive {
nonInteractiveCommand := utils.NonInteractiveCommand(cmd.Use, cmd.Flags())
fmt.Println(tipMsgStyle.Render("Tip: Repeat the equivalent Blueprint with the following non-interactive command:"))
Expand Down
4 changes: 3 additions & 1 deletion cmd/flags/advancedFeatures.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,11 @@ const (
Tailwind string = "tailwind"
React string = "react"
Docker string = "docker"
Kafka string = "kafka"
Worker string = "worker"
)

var AllowedAdvancedFeatures = []string{string(React), string(Htmx), string(GoProjectWorkflow), string(Websocket), string(Tailwind), string(Docker)}
var AllowedAdvancedFeatures = []string{string(React), string(Htmx), string(GoProjectWorkflow), string(Websocket), string(Tailwind), string(Docker), string(Kafka), string(Worker)}

func (f AdvancedFeatures) String() string {
return strings.Join(f, ",")
Expand Down
145 changes: 145 additions & 0 deletions cmd/flags/advancedFeatures_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
package flags

import (
"testing"
)

func TestAdvancedFeaturesWorker(t *testing.T) {
// Test that Worker constant is properly defined
if Worker != "worker" {
t.Errorf("Worker constant expected 'worker', got '%s'", Worker)
}
}

func TestAllowedAdvancedFeaturesContainsWorker(t *testing.T) {
// Test that Worker is included in AllowedAdvancedFeatures
found := false
for _, feature := range AllowedAdvancedFeatures {
if feature == Worker {
found = true
break
}
}
if !found {
t.Errorf("Worker feature not found in AllowedAdvancedFeatures slice")
}
}

func TestAdvancedFeaturesSetWorker(t *testing.T) {
var features AdvancedFeatures

// Test valid worker feature
err := features.Set("worker")
if err != nil {
t.Errorf("Expected no error when setting 'worker' feature, got: %v", err)
}

// Check if worker was added to the slice
found := false
for _, feature := range features {
if feature == "worker" {
found = true
break
}
}
if !found {
t.Errorf("Worker feature was not added to the AdvancedFeatures slice")
}
}

func TestAdvancedFeaturesSetInvalidFeature(t *testing.T) {
var features AdvancedFeatures

// Test invalid feature
err := features.Set("invalid-feature")
if err == nil {
t.Errorf("Expected error when setting invalid feature, got nil")
}

// Check that the error message contains the allowed values
expectedSubstring := "advanced Feature to use. Allowed values:"
if err != nil && !contains(err.Error(), expectedSubstring) {
t.Errorf("Error message should contain '%s', got: %s", expectedSubstring, err.Error())
}
}

func TestAdvancedFeaturesSetMultipleFeatures(t *testing.T) {
var features AdvancedFeatures

// Test setting multiple features including worker
testFeatures := []string{"worker", "docker", "htmx"}

for _, feature := range testFeatures {
err := features.Set(feature)
if err != nil {
t.Errorf("Expected no error when setting '%s' feature, got: %v", feature, err)
}
}

// Verify all features were added
if len(features) != len(testFeatures) {
t.Errorf("Expected %d features, got %d", len(testFeatures), len(features))
}

// Verify worker is in the list
found := false
for _, feature := range features {
if feature == "worker" {
found = true
break
}
}
if !found {
t.Errorf("Worker feature not found in the features list after setting multiple features")
}
}

func TestAdvancedFeaturesString(t *testing.T) {
var features AdvancedFeatures

// Test empty features
result := features.String()
if result != "" {
t.Errorf("Expected empty string for empty features, got: '%s'", result)
}

// Test with worker feature
features.Set("worker")

Check failure on line 107 in cmd/flags/advancedFeatures_test.go

View workflow job for this annotation

GitHub Actions / lint

Error return value of `features.Set` is not checked (errcheck)
result = features.String()
if result != "worker" {
t.Errorf("Expected 'worker' for single feature, got: '%s'", result)
}

// Test with multiple features
features.Set("docker")

Check failure on line 114 in cmd/flags/advancedFeatures_test.go

View workflow job for this annotation

GitHub Actions / lint

Error return value of `features.Set` is not checked (errcheck)
result = features.String()
expected := "worker,docker"
if result != expected {
t.Errorf("Expected '%s' for multiple features, got: '%s'", expected, result)
}
}

func TestAdvancedFeaturesType(t *testing.T) {
var features AdvancedFeatures

// Test Type method
result := features.Type()
expected := "AdvancedFeatures"
if result != expected {
t.Errorf("Expected '%s' from Type(), got: '%s'", expected, result)
}
}

// Helper function to check if a string contains a substring
func contains(s, substr string) bool {
return len(s) >= len(substr) && (len(substr) == 0 || findSubstring(s, substr))
}

func findSubstring(s, substr string) bool {
for i := 0; i <= len(s)-len(substr); i++ {
if s[i:i+len(substr)] == substr {
return true
}
}
return false
}
Loading
Loading