forked from cleveragents/cleveragents-core
fe69d132f1
ISSUES CLOSED: #178
186 lines
8.0 KiB
Gherkin
186 lines
8.0 KiB
Gherkin
Feature: Definition-of-Done gating
|
|
As a plan executor
|
|
I want apply to be blocked unless all DoD criteria are met
|
|
So that only plans meeting completion criteria are committed
|
|
|
|
Background:
|
|
Given a definition of done test environment
|
|
|
|
# -- DoD parsing ---------------------------------------------------------
|
|
|
|
Scenario: Parse DoD text into criteria
|
|
When I parse the DoD text "All tests pass\nNo lint errors\nCoverage above 90%"
|
|
Then there should be 3 criteria parsed
|
|
And criterion 0 text should be "All tests pass"
|
|
And criterion 1 text should be "No lint errors"
|
|
|
|
Scenario: Parse DoD with bullet points
|
|
When I parse the DoD text "- Tests pass\n- No errors\n* Coverage ok"
|
|
Then there should be 3 criteria parsed
|
|
And criterion 0 text should be "Tests pass"
|
|
|
|
Scenario: Parse DoD with numbered items
|
|
When I parse the DoD text "1. Tests pass\n2. No errors"
|
|
Then there should be 2 criteria parsed
|
|
And criterion 0 text should be "Tests pass"
|
|
And criterion 1 text should be "No errors"
|
|
|
|
Scenario: Parse empty DoD returns no criteria
|
|
When I parse an empty DoD text
|
|
Then there should be 0 criteria parsed
|
|
|
|
# -- Template rendering --------------------------------------------------
|
|
|
|
Scenario: Render DoD template with plan arguments
|
|
When I render the DoD template "Tests for {module} must pass" with argument "module" as "auth"
|
|
Then the rendered DoD should be "Tests for auth must pass"
|
|
|
|
Scenario: Render DoD template preserves unmatched placeholders
|
|
When I render the DoD template "Deploy {service} to {env}" with argument "service" as "api"
|
|
Then the rendered DoD should contain "{env}"
|
|
|
|
# -- Text match evaluation -----------------------------------------------
|
|
|
|
Scenario: TextMatchEvaluator passes when context contains criterion text
|
|
Given DoD criteria from "All tests pass"
|
|
And evaluation context with key "status" value "all tests pass"
|
|
When I evaluate the criteria with TextMatchEvaluator
|
|
Then all criteria should have passed
|
|
|
|
Scenario: TextMatchEvaluator fails when context lacks criterion text
|
|
Given DoD criteria from "All tests pass"
|
|
And evaluation context with key "status" value "3 tests failed"
|
|
When I evaluate the criteria with TextMatchEvaluator
|
|
Then criterion 0 should have status "failed"
|
|
|
|
Scenario: TextMatchEvaluator with regex pattern passes on match
|
|
Given a DoD criterion with text "Coverage check" and pattern "coverage.*9[0-9]"
|
|
And evaluation context with key "coverage" value "coverage=95%"
|
|
When I evaluate the criteria with TextMatchEvaluator
|
|
Then all criteria should have passed
|
|
|
|
Scenario: TextMatchEvaluator with regex pattern fails on no match
|
|
Given a DoD criterion with text "Coverage check" and pattern "coverage.*9[0-9]"
|
|
And evaluation context with key "coverage" value "coverage=80%"
|
|
When I evaluate the criteria with TextMatchEvaluator
|
|
Then criterion 0 should have status "failed"
|
|
|
|
Scenario: TextMatchEvaluator skips when context is empty
|
|
Given DoD criteria from "All tests pass"
|
|
And an empty evaluation context
|
|
When I evaluate the criteria with TextMatchEvaluator
|
|
Then criterion 0 should have status "skipped"
|
|
|
|
Scenario: TextMatchEvaluator handles invalid regex gracefully
|
|
Given a DoD criterion with text "Bad regex" and pattern "[invalid"
|
|
And evaluation context with key "data" value "anything"
|
|
When I evaluate the criteria with TextMatchEvaluator
|
|
Then criterion 0 should have status "failed"
|
|
And criterion 0 reasoning should contain "Invalid regex"
|
|
|
|
# -- DoDSummary model ----------------------------------------------------
|
|
|
|
Scenario: DoDSummary reports all_passed when no failures
|
|
Given a DoDSummary with 2 passed and 0 failed
|
|
Then the summary should report all passed
|
|
And the DoD summary total should be 2
|
|
|
|
Scenario: DoDSummary reports not all passed when failures exist
|
|
Given a DoDSummary with 1 passed and 1 failed
|
|
Then the summary should not report all passed
|
|
And the summary failed count should be 1
|
|
|
|
Scenario: DoDSummary empty check
|
|
Given an empty DoDSummary
|
|
Then the summary should be empty
|
|
And the summary should not report all passed
|
|
|
|
Scenario: DoDSummary to_cli_dict has expected fields
|
|
Given a DoDSummary with 1 passed and 0 failed
|
|
Then the summary CLI dict should have key "total"
|
|
And the summary CLI dict should have key "all_passed"
|
|
And the summary CLI dict should have key "criteria"
|
|
|
|
Scenario: DoDSummary to_validation_summary is compatible
|
|
Given a DoDSummary with 2 passed and 1 failed
|
|
Then the validation summary should have required_passed 2
|
|
And the validation summary should have required_failed 1
|
|
And the validation summary should have dod_evaluated true
|
|
|
|
# -- Evaluation context matching -----------------------------------------
|
|
|
|
Scenario: TextMatchEvaluator matches criterion text in context keys
|
|
Given DoD criteria from "lint_errors"
|
|
And evaluation context with key "lint_errors" value "0"
|
|
When I evaluate the criteria with TextMatchEvaluator
|
|
Then all criteria should have passed
|
|
|
|
Scenario: Multiple criteria with mixed results
|
|
Given DoD criteria from "tests pass\nlint errors"
|
|
And evaluation context with key "result" value "tests pass, no issues"
|
|
When I evaluate the criteria with TextMatchEvaluator
|
|
Then criterion 0 should have status "passed"
|
|
And criterion 1 should have status "failed"
|
|
|
|
# -- Coverage: edge cases ------------------------------------------------
|
|
|
|
Scenario: Parse DoD with blank lines between criteria
|
|
When I parse the DoD text "Tests pass\n\nNo errors"
|
|
Then there should be 2 criteria parsed
|
|
|
|
Scenario: Parse DoD with whitespace only line
|
|
When I parse the DoD text " \n- Tests pass"
|
|
Then there should be 1 criteria parsed
|
|
And criterion 0 text should be "Tests pass"
|
|
|
|
Scenario: TextMatchEvaluator matches via individual key lookup
|
|
Given DoD criteria from "all_tests_passed"
|
|
And evaluation context with key "all_tests_passed" value "true"
|
|
When I evaluate the criteria with TextMatchEvaluator
|
|
Then all criteria should have passed
|
|
|
|
# -- T1: all-SKIPPED summary gate behavior --------------------------------
|
|
|
|
Scenario: DoDSummary all_passed is false when all criteria skipped
|
|
Given a DoDSummary with all criteria skipped
|
|
Then the summary should not report all passed
|
|
And the summary skipped count should be 2
|
|
|
|
# -- T2: bullet prefix yielding empty text --------------------------------
|
|
|
|
Scenario: Parse DoD with bullet prefix but no text
|
|
When I parse the DoD text "- \n- Tests pass"
|
|
Then there should be 1 criteria parsed
|
|
And criterion 0 text should be "Tests pass"
|
|
|
|
# -- T5: multi-argument template rendering --------------------------------
|
|
|
|
Scenario: Render DoD template with multiple arguments
|
|
When I render the DoD template "{svc} in {env} OK" with arguments "svc"="api" and "env"="prod"
|
|
Then the rendered DoD should be "api in prod OK"
|
|
|
|
Scenario: Render DoD template prevents injection via values
|
|
When I render the DoD template "Test {name}" with argument "name" as "{secret}"
|
|
Then the rendered DoD should be "Test {secret}"
|
|
|
|
# -- S3: length limit on template -----------------------------------------
|
|
|
|
Scenario: Render DoD rejects oversized template
|
|
Given a DoD template that is 11000 characters long
|
|
When I render the oversized DoD template with argument "x" as "y"
|
|
Then the DoD render should fail with "exceeds maximum"
|
|
|
|
Scenario: Render DoD rejects oversized output
|
|
Given a short DoD template with a huge argument value
|
|
When I render the DoD template that produces oversized output
|
|
Then the DoD render should fail with "exceeds maximum"
|
|
|
|
# -- S2: ReDoS protection -------------------------------------------------
|
|
|
|
Scenario: TextMatchEvaluator rejects oversized regex pattern
|
|
Given a DoD criterion with text "long regex" and pattern that is 600 chars
|
|
And evaluation context with key "data" value "anything"
|
|
When I evaluate the criteria with TextMatchEvaluator
|
|
Then criterion 0 should have status "failed"
|
|
And criterion 0 reasoning should contain "exceeds maximum"
|