package steps import ( "dance-lessons-coach/pkg/bdd/testserver" "fmt" "strings" "github.com/cucumber/godog" ) // StepContext holds the test client and implements all step definitions type StepContext struct { client *testserver.Client } // NewStepContext creates a new step context func NewStepContext(client *testserver.Client) *StepContext { return &StepContext{client: client} } // InitializeAllSteps registers all step definitions for the BDD tests func InitializeAllSteps(ctx *godog.ScenarioContext, client *testserver.Client) { sc := NewStepContext(client) ctx.Step(`^I request a greeting for "([^"]*)"$`, sc.iRequestAGreetingFor) ctx.Step(`^I request the default greeting$`, sc.iRequestTheDefaultGreeting) ctx.Step(`^I request the health endpoint$`, sc.iRequestTheHealthEndpoint) ctx.Step(`^the response should be "{\\"([^"]*)":\\"([^"]*)"}"$`, sc.theResponseShouldBe) ctx.Step(`^the server is running$`, sc.theServerIsRunning) ctx.Step(`^the server is running with v2 enabled$`, sc.theServerIsRunningWithV2Enabled) ctx.Step(`^I send a POST request to v2 greet with name "([^"]*)"$`, sc.iSendPOSTRequestToV2GreetWithName) ctx.Step(`^I send a POST request to v2 greet with invalid JSON "([^"]*)"$`, sc.iSendPOSTRequestToV2GreetWithInvalidJSON) ctx.Step(`^the response should contain error "([^"]*)"$`, sc.theResponseShouldContainError) } func (sc *StepContext) iRequestAGreetingFor(name string) error { return sc.client.Request("GET", fmt.Sprintf("/api/v1/greet/%s", name), nil) } func (sc *StepContext) iRequestTheDefaultGreeting() error { return sc.client.Request("GET", "/api/v1/greet/", nil) } func (sc *StepContext) iRequestTheHealthEndpoint() error { return sc.client.Request("GET", "/api/health", nil) } func (sc *StepContext) theResponseShouldBe(arg1, arg2 string) error { // The regex captures the full JSON from the feature file, including quotes // We need to extract just the key and value without the surrounding quotes and backslashes // Remove the surrounding quotes and backslashes cleanArg1 := strings.Trim(arg1, `"\`) cleanArg2 := strings.Trim(arg2, `"\`) // Build the expected JSON string expected := fmt.Sprintf(`{"%s":"%s"}`, cleanArg1, cleanArg2) return sc.client.ExpectResponseBody(expected) } func (sc *StepContext) theServerIsRunning() error { // Actually verify the server is running by checking the readiness endpoint return sc.client.Request("GET", "/api/ready", nil) } func (sc *StepContext) theServerIsRunningWithV2Enabled() error { // Verify the server is running and v2 is enabled by checking v2 endpoint exists // First check server is running if err := sc.client.Request("GET", "/api/ready", nil); err != nil { return err } // Check if v2 endpoint is available (should return 405 Method Not Allowed for GET, which means endpoint exists) // If v2 is disabled, this will return 404 resp, err := sc.client.CustomRequest("GET", "/api/v2/greet", nil) if err != nil { return err } defer resp.Body.Close() // If we get 405, v2 is enabled (endpoint exists but doesn't allow GET) // If we get 404, v2 is disabled if resp.StatusCode == 404 { return fmt.Errorf("v2 endpoint not available - v2 feature flag not enabled") } return nil } func (sc *StepContext) iSendPOSTRequestToV2GreetWithName(name string) error { // Create JSON request body requestBody := map[string]string{"name": name} return sc.client.Request("POST", "/api/v2/greet", requestBody) } func (sc *StepContext) iSendPOSTRequestToV2GreetWithInvalidJSON(invalidJSON string) error { // Send raw invalid JSON return sc.client.Request("POST", "/api/v2/greet", invalidJSON) } func (sc *StepContext) theResponseShouldContainError(expectedError string) error { // Check if the response contains the expected error body := string(sc.client.GetLastBody()) if !strings.Contains(body, expectedError) { return fmt.Errorf("expected response to contain error %q, got %q", expectedError, body) } return nil }