Skip to content

Conversation

@yacosta738
Copy link
Contributor

@yacosta738 yacosta738 commented Jun 18, 2025

This commit introduces Behavior-Driven Development (BDD) to the HatchGrid backend using Cucumber and Gherkin.

Key changes include:

  • Added Cucumber dependencies to server/thryve/thryve.gradle.kts.
  • Configured JUnit Platform to run Cucumber tests.
  • Created user_registration.feature with Gherkin scenarios for user registration.
  • Implemented UserRegistrationSteps.kt with step definitions for the feature file.

The BDD tests cover scenarios for:

  • Successful user registration.
  • User registration with an existing email.
  • User registration with an invalid email format.

All tests, including the new BDD tests, pass successfully. A minor fix was applied to UserRegistrationSteps.kt to correctly access the error message from ApiDataResponse.

Summary by CodeRabbit

  • New Features
    • Introduced behavior-driven (BDD) tests for user registration, covering successful registration, duplicate email, and invalid email scenarios.
  • Chores
    • Added Cucumber testing dependencies and configuration to the build system.
    • Included a new feature file outlining user registration scenarios for automated testing.

This commit introduces Behavior-Driven Development (BDD) to the HatchGrid backend using Cucumber and Gherkin.

Key changes include:
- Added Cucumber dependencies to `server/thryve/thryve.gradle.kts`.
- Configured JUnit Platform to run Cucumber tests.
- Created `user_registration.feature` with Gherkin scenarios for user registration.
- Implemented `UserRegistrationSteps.kt` with step definitions for the feature file.

The BDD tests cover scenarios for:
- Successful user registration.
- User registration with an existing email.
- User registration with an invalid email format.

All tests, including the new BDD tests, pass successfully. A minor fix was applied to `UserRegistrationSteps.kt` to correctly access the error message from `ApiDataResponse`.
Copilot AI review requested due to automatic review settings June 18, 2025 16:44
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jun 18, 2025

Walkthrough

These changes introduce Cucumber-based BDD testing for user registration in the Thryve server module. They add a Kotlin step definition class, a feature file outlining registration scenarios, and update the build script to support Cucumber tests. The new tests cover successful registration, duplicate email, and invalid email format cases.

Changes

File(s) Change Summary
.../users/infrastructure/http/steps/UserRegistrationSteps.kt Added a Kotlin Cucumber step definition class for user registration BDD tests, covering various scenarios.
.../resources/features/user_registration.feature Added a Cucumber feature file defining scenarios for user registration success and failure cases.
.../thryve.gradle.kts Updated build script: added Cucumber dependencies and configured test task to use Cucumber engine.

Sequence Diagram(s)

sequenceDiagram
    participant Tester as Cucumber Test
    participant Steps as UserRegistrationSteps
    participant Controller as UserRegisterController
    participant Service as UserRegistrator (Mock)

    Tester->>Steps: Run Given/When/Then steps
    Steps->>Service: (Given) Mock registration behavior
    Steps->>Controller: (When) POST /register with user data
    Controller->>Service: Register user (mocked)
    Service-->>Controller: Return registration result
    Controller-->>Steps: HTTP response
    Steps->>Tester: (Then) Assert response and results
Loading

Poem

In the meadow of tests, a new feature takes root,
Cucumber steps hopping in their BDD suit.
With emails both valid and slyly askew,
The rabbits check errors and confirmations too.
Now registration is covered, from start to the end—
🥕 Here’s to new features, my testing friend!

✨ Finishing Touches
  • 📝 Generate Docstrings

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@cloudflare-workers-and-pages
Copy link

Deploying hatchgrid with  Cloudflare Pages  Cloudflare Pages

Latest commit: 63500c2
Status: ✅  Deploy successful!
Preview URL: https://1239bdaa.hatchgrid.pages.dev
Branch Preview URL: https://feature-bdd-cucumber-gherkin.hatchgrid.pages.dev

View logs

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR integrates Behavior-Driven Development (BDD) into HatchGrid’s backend using Cucumber and Gherkin, adding dependencies, configuring the test task, and providing a user registration feature with matching step definitions.

  • Added Cucumber dependencies and configured the JUnit Platform to run Cucumber tests
  • Created user_registration.feature with scenarios for user registration
  • Implemented UserRegistrationSteps.kt to define and execute the Gherkin steps

Reviewed Changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 3 comments.

File Description
server/thryve/thryve.gradle.kts Added Cucumber dependencies and configured the test engine
server/thryve/src/test/resources/features/user_registration.feature Added Gherkin scenarios covering user registration cases
server/thryve/src/test/kotlin/com/hatchgrid/thryve/users/infrastructure/http/steps/UserRegistrationSteps.kt Implemented step definitions for the BDD scenarios

tasks.withType<Test> {
useJUnitPlatform()
useJUnitPlatform {
includeEngines("cucumber")
Copy link

Copilot AI Jun 18, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

By specifying only the Cucumber engine here, other JUnit tests (e.g. unit tests) may be excluded. Consider including both 'junit-jupiter' and 'cucumber' engines or using the default configuration alongside a separate Cucumber test task.

Suggested change
includeEngines("cucumber")
includeEngines("junit-jupiter", "cucumber")

Copilot uses AI. Check for mistakes.
coEvery { mockUserRegistrator.registerNewUser(any()) } returns ApiDataResponse.success(UserResponse(email, email, firstName, lastName))
}

@When("the user attempts to register")
Copy link

Copilot AI Jun 18, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The second scenario uses 'When the new user attempts to register', which doesn’t match this step definition. Either add a second @when annotation for that phrase or unify the Gherkin step text.

Suggested change
@When("the user attempts to register")
@When("the user attempts to register")
@When("the new user attempts to register")

Copilot uses AI. Check for mistakes.
Comment on lines +56 to +64
assert(apiDataResponse?.status == ApiResponseStatus.SUCCESS)
assert(apiDataResponse?.data?.email == email)
}

@Then("the user should receive a confirmation")
fun the_user_should_receive_a_confirmation() {
// This step would typically involve checking an email or a notification service.
// For this example, we\'ll assume the successful creation implies confirmation.
assert(apiDataResponse?.status == ApiResponseStatus.SUCCESS)
Copy link

Copilot AI Jun 18, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Kotlin's built-in assert is disabled by default at runtime. Switch to a JUnit assertion (e.g., Assertions.assertEquals) or WebTestClient’s expectBody checks to ensure failures are reported.

Suggested change
assert(apiDataResponse?.status == ApiResponseStatus.SUCCESS)
assert(apiDataResponse?.data?.email == email)
}
@Then("the user should receive a confirmation")
fun the_user_should_receive_a_confirmation() {
// This step would typically involve checking an email or a notification service.
// For this example, we\'ll assume the successful creation implies confirmation.
assert(apiDataResponse?.status == ApiResponseStatus.SUCCESS)
assertEquals(ApiResponseStatus.SUCCESS, apiDataResponse?.status)
assertEquals(email, apiDataResponse?.data?.email)
}
@Then("the user should receive a confirmation")
fun the_user_should_receive_a_confirmation() {
// This step would typically involve checking an email or a notification service.
// For this example, we\'ll assume the successful creation implies confirmation.
assertEquals(ApiResponseStatus.SUCCESS, apiDataResponse?.status)

Copilot uses AI. Check for mistakes.
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🧹 Nitpick comments (2)
server/thryve/thryve.gradle.kts (1)

97-101: Missing runtime dependency & Kotlin flavour

  1. cucumber-junit-platform-engine is required at runtime; placing it in testImplementation drags it transitively, but Gradle’s dependency insight often flags it as unused. For clarity add:
testRuntimeOnly("io.cucumber:cucumber-junit-platform-engine:${libs.versions.cucumber.get()}")
  1. Step definitions are written in Kotlin yet only cucumber-java is added. While it works, cucumber-kotlin offers better lambda / default parameter support and avoids reflexive edge-cases. Consider:
testImplementation("io.cucumber:cucumber-kotlin:${libs.versions.cucumber.get()}")
server/thryve/src/test/resources/features/user_registration.feature (1)

12-17: Scenario wording causes duplicate action – consider removing the extra Given

And a new user attempts to register with the same email duplicates the subsequent When the new user attempts to register step and does not add pre-conditions.
Dropping the redundant line streamlines the scenario without changing intent.

-    And a new user attempts to register with the same email
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between fe19b9d and 63500c2.

📒 Files selected for processing (3)
  • server/thryve/src/test/kotlin/com/hatchgrid/thryve/users/infrastructure/http/steps/UserRegistrationSteps.kt (1 hunks)
  • server/thryve/src/test/resources/features/user_registration.feature (1 hunks)
  • server/thryve/thryve.gradle.kts (2 hunks)
⏰ Context from checks skipped due to timeout of 90000ms (6)
  • GitHub Check: Lint with Detekt
  • GitHub Check: Build and Test
  • GitHub Check: Analyze (javascript-typescript)
  • GitHub Check: Analyze (actions)
  • GitHub Check: Analyze (java-kotlin)
  • GitHub Check: Cloudflare Pages
🔇 Additional comments (1)
server/thryve/src/test/kotlin/com/hatchgrid/thryve/users/infrastructure/http/steps/UserRegistrationSteps.kt (1)

19-31: Un-used cucumber-spring – wire Spring context or drop the dependency

cucumber-spring is included but the step class is instantiated manually (not Spring-managed).
If full Spring context is desired, annotate with @SpringBootTest / @ContextConfiguration and let Cucumber autowire beans; otherwise remove the dependency to keep the test class lightweight.

Comment on lines +118 to +120
useJUnitPlatform {
includeEngines("cucumber")
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Restricting to only the cucumber engine hides the rest of your JUnit‐Jupiter suite

includeEngines("cucumber") means only the Cucumber engine will be executed; all classic JUnit-Jupiter tests (junit-jupiter) and any property-based tests (junit-quickcheck, etc.) are silently skipped.
Unless that is intentional, extend – rather than replace – the engine list:

-useJUnitPlatform {
-    includeEngines("cucumber")
-}
+useJUnitPlatform {
+    includeEngines("cucumber", "junit-jupiter")
+}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
useJUnitPlatform {
includeEngines("cucumber")
}
useJUnitPlatform {
includeEngines("cucumber", "junit-jupiter")
}
🤖 Prompt for AI Agents
In server/thryve/thryve.gradle.kts around lines 118 to 120, the current
configuration restricts test execution to only the Cucumber engine by using
includeEngines("cucumber"), which causes all other JUnit-Jupiter tests to be
skipped. To fix this, modify the configuration to include the Cucumber engine
alongside the default engines instead of replacing them, ensuring that all test
engines run as intended.

Comment on lines +55 to +58
fun the_user_account_should_be_created_successfully() {
assert(apiDataResponse?.status == ApiResponseStatus.SUCCESS)
assert(apiDataResponse?.data?.email == email)
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

kotlin.assert() is ignored unless JVM is run with -ea – replace with test asserts

Gradle’s Test task does not enable assertions by default, so these checks are currently no-ops.
Swap them for JUnit/Jupiter or Kotlin-test assertions:

-assert(apiDataResponse?.status == ApiResponseStatus.SUCCESS)
+assertEquals(ApiResponseStatus.SUCCESS, apiDataResponse?.status)

-assert(apiDataResponse?.error == "Email already in use")
+assertEquals("Email already in use", apiDataResponse?.error)

Repeat for all similar lines.

Also applies to: 61-65, 84-86, 88-91, 104-106

🤖 Prompt for AI Agents
In
server/thryve/src/test/kotlin/com/hatchgrid/thryve/users/infrastructure/http/steps/UserRegistrationSteps.kt
around lines 55 to 58, replace the kotlin.assert() calls with proper JUnit or
Kotlin-test assertion methods because kotlin.assert() is ignored unless JVM is
run with -ea, making these checks ineffective. Use assertions like assertEquals
or assertTrue from the testing framework to ensure the tests actually validate
the conditions. Apply the same replacement for all similar assertions in lines
61-65, 84-86, 88-91, and 104-106.

Comment on lines +45 to +51
apiDataResponse = webTestClient.post().uri("/api/register")
.contentType(MediaType.APPLICATION_JSON)
.bodyValue(request)
.exchange()
.expectStatus().isCreated
.expectBody(ApiDataResponse::class.java)
.returnResult().responseBody as ApiDataResponse<UserResponse>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Hard-coding isCreated makes failing scenarios pass or break unexpectedly

All scenarios reuse this @When step, yet expectStatus().isCreated asserts HTTP 201 even for error paths (duplicate/invalid email).
Either parameterise the expected status or assert by scenario in the corresponding @Then.

-expectStatus().isCreated
+expectStatus().satisfies {
+    // 201 for success, 4xx for validations – we’ll verify later
+}

Alternatively split the When step into success/failure variants.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
apiDataResponse = webTestClient.post().uri("/api/register")
.contentType(MediaType.APPLICATION_JSON)
.bodyValue(request)
.exchange()
.expectStatus().isCreated
.expectBody(ApiDataResponse::class.java)
.returnResult().responseBody as ApiDataResponse<UserResponse>
apiDataResponse = webTestClient.post().uri("/api/register")
.contentType(MediaType.APPLICATION_JSON)
.bodyValue(request)
.exchange()
.expectStatus().satisfies {
// 201 for success, 4xx for validations – we’ll verify later
}
.expectBody(ApiDataResponse::class.java)
.returnResult().responseBody as ApiDataResponse<UserResponse>
🤖 Prompt for AI Agents
In
server/thryve/src/test/kotlin/com/hatchgrid/thryve/users/infrastructure/http/steps/UserRegistrationSteps.kt
around lines 45 to 51, the test step hard-codes the expected HTTP status as 201
Created, which causes failure scenarios to pass or break incorrectly. To fix
this, modify the step to accept the expected HTTP status as a parameter or
remove the status assertion from the When step and instead assert the status
explicitly in the Then step for each scenario. Alternatively, split the When
step into separate success and failure variants with appropriate status
assertions.

@github-actions
Copy link
Contributor

Test Results

 37 files   - 106   37 suites   - 106   24s ⏱️ -35s
146 tests  - 335  146 ✅  - 335  0 💤 ±0  0 ❌ ±0 
146 runs   - 339  146 ✅  - 339  0 💤 ±0  0 ❌ ±0 

Results for commit 63500c2. ± Comparison against base commit fe19b9d.

This pull request removes 339 and adds 4 tests. Note that renamed tests count towards both.
com.hatchgrid.ApplicationStartupTracesTest ‑ init the application with incompatible profiles
com.hatchgrid.ApplicationStartupTracesTest ‑ should build trace for application with web configuration
com.hatchgrid.ApplicationStartupTracesTest ‑ should build trace for empty non web environment
com.hatchgrid.ApplicationStartupTracesTest ‑ should build trace for empty web environment
com.hatchgrid.ApplicationStartupTracesTest ‑ should build trace for environment with application name
com.hatchgrid.ApplicationStartupTracesTest ‑ should use https when ssl bundle is configured
com.hatchgrid.ArchTest ‑ application should not depend on infrastructure
com.hatchgrid.ArchTest ‑ domain should not depend on application or infrastructure
com.hatchgrid.common.domain.bus.MediatorBuilderTest ‑ [1] com.hatchgrid.common.domain.bus.ContinueOnExceptionPublishStrategy@79f2b72
com.hatchgrid.common.domain.bus.MediatorBuilderTest ‑ [2] com.hatchgrid.common.domain.bus.ParallelNoWaitPublishStrategy@46e48aaf
…
com.hatchgrid.common.domain.bus.MediatorBuilderTest ‑ [1] com.hatchgrid.common.domain.bus.ContinueOnExceptionPublishStrategy@655c30fc
com.hatchgrid.common.domain.bus.MediatorBuilderTest ‑ [2] com.hatchgrid.common.domain.bus.ParallelNoWaitPublishStrategy@7eafc362
com.hatchgrid.common.domain.bus.MediatorBuilderTest ‑ [3] com.hatchgrid.common.domain.bus.ParallelWhenAllPublishStrategy@109eb6d3
com.hatchgrid.common.domain.bus.MediatorBuilderTest ‑ [4] com.hatchgrid.common.domain.bus.StopOnExceptionPublishStrategy@648cfca5

@github-actions
Copy link
Contributor

github-actions bot commented Aug 9, 2025

This PR was marked as stale due to inactivity. It will be closed automatically in 7 days if there are no updates.

@github-actions github-actions bot added the stale label Aug 9, 2025
@yacosta738
Copy link
Contributor Author

WIP 👍

@github-actions github-actions bot removed the stale label Aug 11, 2025
@github-actions
Copy link
Contributor

This PR was marked as stale due to inactivity. It will be closed automatically in 60 days if there are no updates.

@github-actions github-actions bot added the stale label Dec 11, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Setup BDD framework with Cucumber and implement scenarios for all core use cases

2 participants