Files
cleveragents-core/features/devcontainer_handler_protocol_methods.feature
freemo ee980ee117
CI / benchmark-publish (push) Has been cancelled
CI / integration_tests (push) Has been cancelled
CI / lint (push) Has been cancelled
CI / typecheck (push) Has been cancelled
CI / security (push) Has been cancelled
CI / build (push) Has been cancelled
CI / unit_tests (push) Has been cancelled
CI / quality (push) Has been cancelled
CI / helm (push) Has been cancelled
CI / e2e_tests (push) Has been cancelled
CI / status-check (push) Has been cancelled
CI / coverage (push) Has been cancelled
CI / benchmark-regression (push) Has been cancelled
CI / docker (push) Has been cancelled
feat(resource): implement DevcontainerHandler missing protocol methods (#1286)
Implements the four missing protocol methods on DevcontainerHandler required by Epic #825 (ResourceHandler Protocol Completion):

- delete(): uses 'devcontainer exec rm -rf' to delete files/dirs inside the container; returns DeleteResult(success=False) for missing/stopped containers rather than raising.
- list_children(): uses 'devcontainer exec ls -1' to enumerate workspace entries; returns an empty list on container failure.
- diff(): compares content hashes between the devcontainer workspace and another filesystem location; uses EMPTY_CONTENT_HASH sentinel to treat both-absent as no-change.
- create_sandbox(): delegates to BaseResourceHandler.create_sandbox with lazy activation (same DETECTED/STOPPED/FAILED guard as resolve()).

All methods raise ValueError for resources with no location.

Adds 18 Behave BDD scenarios covering success paths, failure/stopped-container paths, empty-path edge cases, and ValueError guards.

ISSUES CLOSED: #1242

Co-authored-by: Jeffrey Phillips Freeman <the@jeffreyfreeman.me>
Co-committed-by: Jeffrey Phillips Freeman <the@jeffreyfreeman.me>
2026-04-02 17:08:52 +00:00

151 lines
8.2 KiB
Gherkin

Feature: DevcontainerHandler missing protocol methods
As a developer using DevcontainerHandler
I want delete(), list_children(), diff(), and create_sandbox() to be implemented
So that the handler satisfies the full ResourceHandler protocol (issue #1242)
# delete() method
Scenario: dcproto delete file successfully from devcontainer
Given dcproto a devcontainer handler
And dcproto a devcontainer-instance resource with location "/ws/project"
And dcproto subprocess returns successful rm output
When dcproto I delete path "src/old_file.py" from the resource
Then dcproto the delete should succeed
And dcproto the delete message should contain "src/old_file.py"
And dcproto the subprocess should have been called with "rm" and "src/old_file.py"
Scenario: dcproto delete with empty path targets workspace root
Given dcproto a devcontainer handler
And dcproto a devcontainer-instance resource with location "/ws/project"
And dcproto subprocess returns successful rm output
When dcproto I delete with empty path from the resource
Then dcproto the delete should succeed
And dcproto the subprocess should have been called with "rm" and "."
Scenario: dcproto delete fails when container is stopped
Given dcproto a devcontainer handler
And dcproto a devcontainer-instance resource with location "/ws/project"
And dcproto subprocess returns failed rm output with stderr "container not running"
When dcproto I delete path "file.txt" from the resource
Then dcproto the delete should fail
And dcproto the delete failure message should contain "container not running"
Scenario: dcproto delete from resource with no location raises ValueError
Given dcproto a devcontainer handler
And dcproto a devcontainer-instance resource with no location
When dcproto I delete path "any/file.txt" from the resource
Then dcproto the delete should raise ValueError containing "no location"
# ── list_children() method ───────────────────────────────────
Scenario: dcproto list_children returns sorted names from devcontainer
Given dcproto a devcontainer handler
And dcproto a devcontainer-instance resource with location "/ws/project"
And dcproto subprocess returns successful ls listing "src\ntests\nREADME.md"
When dcproto I list children of the resource
Then dcproto the children list should have 3 entries
And dcproto the children list should be "README.md,src,tests"
Scenario: dcproto list_children returns empty list when container is stopped
Given dcproto a devcontainer handler
And dcproto a devcontainer-instance resource with location "/ws/project"
And dcproto subprocess returns failed ls output
When dcproto I list children of the resource
Then dcproto the children list should have 0 entries
Scenario: dcproto list_children filters blank lines from ls output
Given dcproto a devcontainer handler
And dcproto a devcontainer-instance resource with location "/ws/project"
And dcproto subprocess returns successful ls listing "alpha\n\n\nbeta\n"
When dcproto I list children of the resource
Then dcproto the children list should have 2 entries
And dcproto the children list should be "alpha,beta"
Scenario: dcproto list_children from resource with no location raises ValueError
Given dcproto a devcontainer handler
And dcproto a devcontainer-instance resource with no location
When dcproto I list children of the resource
Then dcproto the list children should raise ValueError containing "no location"
Scenario: dcproto list_children uses devcontainer exec ls command
Given dcproto a devcontainer handler
And dcproto a devcontainer-instance resource with location "/ws/project"
And dcproto subprocess returns successful ls listing "main.py"
When dcproto I list children of the resource
Then dcproto the subprocess should have been called with "ls" and "--workspace-folder"
# ── diff() method ────────────────────────────────────────────
Scenario: dcproto diff detects changes when hashes differ
Given dcproto a devcontainer handler
And dcproto a devcontainer-instance resource with location "/ws/project"
And dcproto the container content hash is "aabbccdd"
And dcproto a temporary directory with a different file
When dcproto I diff the resource against the temporary directory
Then dcproto the diff should report has_changes true
And dcproto the diff files_changed should be 1
Scenario: dcproto diff reports no changes when hashes match
Given dcproto a devcontainer handler
And dcproto a devcontainer-instance resource with location "/ws/project"
And dcproto the container content hash matches the other location
When dcproto I diff the resource against the same location
Then dcproto the diff should report has_changes false
And dcproto the diff files_changed should be 0
Scenario: dcproto diff reports no changes when both sides are absent
Given dcproto a devcontainer handler
And dcproto a devcontainer-instance resource with location "/nonexistent/path"
When dcproto I diff the resource against "/another/nonexistent/path"
Then dcproto the diff should report has_changes false
Scenario: dcproto diff from resource with no location raises ValueError
Given dcproto a devcontainer handler
And dcproto a devcontainer-instance resource with no location
When dcproto I diff the resource against "/some/path"
Then dcproto the diff should raise ValueError containing "no location"
Scenario: dcproto diff unified_diff is always empty string
Given dcproto a devcontainer handler
And dcproto a devcontainer-instance resource with location "/ws/project"
And dcproto the container content hash is "aabbccdd"
And dcproto a temporary directory with a different file
When dcproto I diff the resource against the temporary directory
Then dcproto the diff unified_diff should be empty
# ── create_sandbox() method ──────────────────────────────────
Scenario: dcproto create_sandbox delegates to base class for running container
Given dcproto a devcontainer handler
And dcproto a devcontainer-instance resource with location "/ws/project"
And dcproto the container is in RUNNING state
And dcproto a mock sandbox manager that returns a valid sandbox
When dcproto I create a sandbox for the resource with plan "plan-001"
Then dcproto the sandbox result should have strategy "none"
And dcproto the sandbox result should have a sandbox path
Scenario: dcproto create_sandbox activates container when in DETECTED state
Given dcproto a devcontainer handler
And dcproto a devcontainer-instance resource with location "/ws/project"
And dcproto the container is in DETECTED state
And dcproto a mock sandbox manager that returns a valid sandbox
And dcproto activate_container is mocked to succeed
When dcproto I create a sandbox for the resource with plan "plan-002"
Then dcproto activate_container should have been called
Scenario: dcproto create_sandbox activates container when in STOPPED state
Given dcproto a devcontainer handler
And dcproto a devcontainer-instance resource with location "/ws/project"
And dcproto the container is in STOPPED state
And dcproto a mock sandbox manager that returns a valid sandbox
And dcproto activate_container is mocked to succeed
When dcproto I create a sandbox for the resource with plan "plan-003"
Then dcproto activate_container should have been called
Scenario: dcproto create_sandbox raises ValueError for resource with no location
Given dcproto a devcontainer handler
And dcproto a devcontainer-instance resource with no location
And dcproto a mock sandbox manager that returns a valid sandbox
When dcproto I create a sandbox for the resource with plan "plan-004"
Then dcproto the create_sandbox should raise ValueError containing "no location"