95b6ed57c2
ISSUES CLOSED: #303
264 lines
13 KiB
Gherkin
264 lines
13 KiB
Gherkin
Feature: Diff review artifacts
|
|
As a developer reviewing plan changes
|
|
I want to build diff review artifacts from changesets
|
|
So that I can inspect changes before applying them
|
|
|
|
Background:
|
|
Given a plan ID "01PLAN000000000000000001"
|
|
And an empty changeset for the plan
|
|
|
|
Scenario: Empty changeset produces empty review artifact
|
|
When I build a review artifact from the changeset
|
|
Then the review artifact should have 0 total changes
|
|
And the review artifact should have 0 groups
|
|
And the review artifact should not be truncated
|
|
|
|
Scenario: Single CREATE change produces a diff entry
|
|
Given a change entry with operation "create" for path "src/main.py" in resource "RES001"
|
|
And after content for "src/main.py" is "print('hello')\n"
|
|
When I build a review artifact from the changeset
|
|
Then the review artifact should have 1 total changes
|
|
And the review artifact should have 1 groups
|
|
And group 0 should have 1 entries
|
|
And entry 0 in group 0 should have change type "create"
|
|
And entry 0 in group 0 should have path "src/main.py"
|
|
|
|
Scenario: MODIFY change generates unified diff
|
|
Given a change entry with operation "modify" for path "src/app.py" in resource "RES001"
|
|
And before content for "src/app.py" is "x = 1\ny = 2\n"
|
|
And after content for "src/app.py" is "x = 1\ny = 3\n"
|
|
When I build a review artifact from the changeset
|
|
Then entry 0 in group 0 should have change type "modify"
|
|
And the diff text in entry 0 of group 0 should contain "---"
|
|
And the diff text in entry 0 of group 0 should contain "+++"
|
|
|
|
Scenario: DELETE change entry
|
|
Given a change entry with operation "delete" for path "old.txt" in resource "RES001"
|
|
And before content for "old.txt" is "old content\n"
|
|
When I build a review artifact from the changeset
|
|
Then entry 0 in group 0 should have change type "delete"
|
|
And the diff text in entry 0 of group 0 should contain "---"
|
|
|
|
Scenario: Multiple changes across different resources
|
|
Given a change entry with operation "create" for path "a.py" in resource "RES001"
|
|
And a change entry with operation "modify" for path "b.py" in resource "RES002"
|
|
And after content for "a.py" is "new\n"
|
|
And before content for "b.py" is "old\n"
|
|
And after content for "b.py" is "new\n"
|
|
When I build a review artifact from the changeset
|
|
Then the review artifact should have 2 total changes
|
|
And the review artifact should have 2 groups
|
|
|
|
Scenario: Changes grouped by resource
|
|
Given a change entry with operation "create" for path "a.py" in resource "RES001"
|
|
And a change entry with operation "modify" for path "b.py" in resource "RES001"
|
|
And after content for "a.py" is "new\n"
|
|
And before content for "b.py" is "old\n"
|
|
And after content for "b.py" is "new\n"
|
|
When I build a review artifact from the changeset
|
|
Then the review artifact should have 1 groups
|
|
And group 0 should have 2 entries
|
|
|
|
Scenario: Binary file detection
|
|
Given a change entry with operation "create" for path "image.bin" in resource "RES001"
|
|
And after content for "image.bin" is "binary\x00data"
|
|
When I build a review artifact from the changeset
|
|
Then entry 0 in group 0 should be binary
|
|
And the diff text in entry 0 of group 0 should contain "[binary file]"
|
|
|
|
Scenario: Rename detection with matching content hash
|
|
Given a delete entry for path "old/file.py" in resource "RES001" with before_hash "abc123"
|
|
And a create entry for path "new/file.py" in resource "RES001" with after_hash "abc123"
|
|
When I build a review artifact from the changeset
|
|
Then the review artifact should have 1 groups
|
|
And group 0 should have 1 entries
|
|
And entry 0 in group 0 should be a rename
|
|
And entry 0 in group 0 rename should be from "old/file.py" to "new/file.py"
|
|
And group 0 should have 1 renamed
|
|
|
|
Scenario: Rename not detected when hashes differ
|
|
Given a delete entry for path "old/file.py" in resource "RES001" with before_hash "abc123"
|
|
And a create entry for path "new/file.py" in resource "RES001" with after_hash "xyz789"
|
|
When I build a review artifact from the changeset
|
|
Then group 0 should have 2 entries
|
|
And entry 0 in group 0 should not be a rename
|
|
|
|
Scenario: Max diff size truncation
|
|
Given a change entry with operation "create" for path "big.py" in resource "RES001"
|
|
And after content for "big.py" is a string of 100000 characters
|
|
When I build a review artifact with max diff size 100
|
|
Then the review artifact should be truncated
|
|
And entry 0 in group 0 should be truncated
|
|
|
|
Scenario: Stable ordering by resource then path
|
|
Given a change entry with operation "create" for path "z.py" in resource "RES002"
|
|
And a change entry with operation "create" for path "a.py" in resource "RES001"
|
|
And after content for "z.py" is "z\n"
|
|
And after content for "a.py" is "a\n"
|
|
When I build a review artifact from the changeset
|
|
Then group 0 should have resource id "RES001"
|
|
And group 1 should have resource id "RES002"
|
|
|
|
Scenario: Before and after content hashes in metadata
|
|
Given a hashed change entry "modify" path "f.py" resource "RES001" before_hash "hash1" after_hash "hash2"
|
|
And before content for "f.py" is "old\n"
|
|
And after content for "f.py" is "new\n"
|
|
When I build a review artifact from the changeset
|
|
Then entry 0 in group 0 should have before hash "hash1"
|
|
And entry 0 in group 0 should have after hash "hash2"
|
|
|
|
Scenario: File mode in metadata
|
|
Given a moded change entry "modify" path "script.sh" resource "RES001" after_mode 0o755
|
|
And before content for "script.sh" is "#!/bin/sh\n"
|
|
And after content for "script.sh" is "#!/bin/bash\n"
|
|
When I build a review artifact from the changeset
|
|
Then entry 0 in group 0 should have file mode 493
|
|
|
|
Scenario: Serialize to plain text
|
|
Given a change entry with operation "create" for path "new.py" in resource "RES001"
|
|
And after content for "new.py" is "hello\n"
|
|
And resource name "RES001" is "my-resource"
|
|
When I build a review artifact from the changeset
|
|
And I serialize the artifact to plain text
|
|
Then the plain text should contain "my-resource"
|
|
And the plain text should contain "new.py"
|
|
And the plain text should contain "Total changes: 1"
|
|
|
|
Scenario: Serialize to JSON
|
|
Given a change entry with operation "create" for path "new.py" in resource "RES001"
|
|
And after content for "new.py" is "hello\n"
|
|
When I build a review artifact from the changeset
|
|
And I serialize the artifact to JSON
|
|
Then the JSON output should be valid JSON
|
|
And the JSON output should contain key "total_changes"
|
|
And the JSON output should contain key "groups"
|
|
|
|
Scenario: Serialize to rich format
|
|
Given a change entry with operation "create" for path "new.py" in resource "RES001"
|
|
And after content for "new.py" is "hello\n"
|
|
When I build a review artifact from the changeset
|
|
And I serialize the artifact to rich format
|
|
Then the rich text should contain "[bold]"
|
|
And the rich text should contain "new.py"
|
|
|
|
Scenario: ResourceDiffGroup summary counts
|
|
Given a change entry with operation "create" for path "a.py" in resource "RES001"
|
|
And a change entry with operation "modify" for path "b.py" in resource "RES001"
|
|
And a change entry with operation "delete" for path "c.py" in resource "RES001"
|
|
And after content for "a.py" is "new\n"
|
|
And before content for "b.py" is "old\n"
|
|
And after content for "b.py" is "new\n"
|
|
And before content for "c.py" is "old\n"
|
|
When I build a review artifact from the changeset
|
|
Then group 0 should have 1 added
|
|
And group 0 should have 1 modified
|
|
And group 0 should have 1 deleted
|
|
|
|
Scenario: ReviewArtifact has plan and changeset IDs
|
|
When I build a review artifact from the changeset
|
|
Then the review artifact plan ID should match the changeset plan ID
|
|
And the review artifact changeset ID should match the changeset ID
|
|
|
|
Scenario: Empty content produces empty diff
|
|
Given a change entry with operation "modify" for path "empty.py" in resource "RES001"
|
|
When I build a review artifact from the changeset
|
|
Then the diff text in entry 0 of group 0 should be empty
|
|
|
|
Scenario: Multiple entries in same resource sorted by path
|
|
Given a change entry with operation "create" for path "z.py" in resource "RES001"
|
|
And a change entry with operation "create" for path "a.py" in resource "RES001"
|
|
And after content for "z.py" is "z\n"
|
|
And after content for "a.py" is "a\n"
|
|
When I build a review artifact from the changeset
|
|
Then entry 0 in group 0 should have path "a.py"
|
|
And entry 1 in group 0 should have path "z.py"
|
|
|
|
Scenario: Second entry fully truncated when budget exhausted
|
|
Given a change entry with operation "create" for path "a.py" in resource "RES001"
|
|
And a change entry with operation "create" for path "b.py" in resource "RES001"
|
|
And after content for "a.py" is a string of 1000 characters
|
|
And after content for "b.py" is a string of 1000 characters
|
|
When I build a review artifact with max diff size 50
|
|
Then the review artifact should be truncated
|
|
And entry 1 in group 0 should be truncated
|
|
And the diff text in entry 1 of group 0 should contain "[truncated]"
|
|
|
|
Scenario: JSON serialization includes hashes and file mode
|
|
Given a hashed change entry "modify" path "f.py" resource "RES001" before_hash "aaa" after_hash "bbb"
|
|
And a moded change entry "modify" path "g.py" resource "RES001" after_mode 0o644
|
|
And before content for "f.py" is "old\n"
|
|
And after content for "f.py" is "new\n"
|
|
And before content for "g.py" is "a\n"
|
|
And after content for "g.py" is "b\n"
|
|
When I build a review artifact from the changeset
|
|
And I serialize the artifact to JSON
|
|
Then the JSON output should be valid JSON
|
|
And the JSON output should have entry with before hash "aaa"
|
|
And the JSON output should have entry with after hash "bbb"
|
|
And the JSON output should have entry with file mode
|
|
|
|
Scenario: JSON serialization includes rename fields
|
|
Given a delete entry for path "old/r.py" in resource "RES001" with before_hash "h1"
|
|
And a create entry for path "new/r.py" in resource "RES001" with after_hash "h1"
|
|
When I build a review artifact from the changeset
|
|
And I serialize the artifact to JSON
|
|
Then the JSON output should be valid JSON
|
|
And the JSON output should have entry with rename from "old/r.py"
|
|
|
|
Scenario: Rich format shows truncation warning
|
|
Given a change entry with operation "create" for path "big.py" in resource "RES001"
|
|
And after content for "big.py" is a string of 100000 characters
|
|
When I build a review artifact with max diff size 100
|
|
And I serialize the artifact to rich format
|
|
Then the rich text should contain "[yellow]"
|
|
And the rich text should contain "truncated"
|
|
|
|
Scenario: Rich format shows binary marker
|
|
Given a change entry with operation "create" for path "bin.dat" in resource "RES001"
|
|
And after content for "bin.dat" is "binary\x00data"
|
|
When I build a review artifact from the changeset
|
|
And I serialize the artifact to rich format
|
|
Then the rich text should contain "[binary]"
|
|
|
|
Scenario: Rich format colorizes diff lines
|
|
Given a change entry with operation "modify" for path "c.py" in resource "RES001"
|
|
And before content for "c.py" is "old\n"
|
|
And after content for "c.py" is "new\n"
|
|
When I build a review artifact from the changeset
|
|
And I serialize the artifact to rich format
|
|
Then the rich text should contain "[green]"
|
|
And the rich text should contain "[red]"
|
|
|
|
Scenario: Cross-resource delete and create are not renamed
|
|
Given a delete entry for path "old/x.py" in resource "RES001" with before_hash "same"
|
|
And a create entry for path "new/x.py" in resource "RES002" with after_hash "same"
|
|
When I build a review artifact from the changeset
|
|
Then the review artifact should have 2 groups
|
|
And entry 0 in group 0 should not be a rename
|
|
And entry 0 in group 1 should not be a rename
|
|
|
|
Scenario: Multiple renames consume creates only once
|
|
Given a delete entry for path "old/a.py" in resource "RES001" with before_hash "h1"
|
|
And a delete entry for path "old/b.py" in resource "RES001" with before_hash "h1"
|
|
And a create entry for path "new/a.py" in resource "RES001" with after_hash "h1"
|
|
When I build a review artifact from the changeset
|
|
Then group 0 should have 2 entries
|
|
|
|
Scenario: Rename entry truncated when budget exhausted
|
|
Given a change entry with operation "create" for path "a.py" in resource "RES001"
|
|
And after content for "a.py" is a string of 1000 characters
|
|
And a delete entry for path "old/r.py" in resource "RES001" with before_hash "rh1"
|
|
And a create entry for path "new/r.py" in resource "RES001" with after_hash "rh1"
|
|
When I build a review artifact with max diff size 50
|
|
Then the review artifact should be truncated
|
|
And entry 1 in group 0 should be a rename
|
|
And entry 1 in group 0 should be truncated
|
|
And the diff text in entry 1 of group 0 should contain "[truncated]"
|
|
|
|
Scenario: Plain serialization shows binary marker
|
|
Given a change entry with operation "create" for path "img.png" in resource "RES001"
|
|
And after content for "img.png" is "png\x00header"
|
|
When I build a review artifact from the changeset
|
|
And I serialize the artifact to plain text
|
|
Then the plain text should contain "[binary file]"
|