forked from HAL9000/cleveragents-core
4b9798bc40
- Implemented branch naming change in GitWorktreeSandbox.create() from sandbox/<plan_id> to cleveragents/plan-<plan_id>, located in src/cleveragents/infrastructure/sandbox/git_worktree.py
- Updated the create() method docstring to reflect the new branch naming convention
- Updated test fixtures:
- features/steps/git_worktree_coverage_boost_steps.py: sandbox/test -> cleveragents/plan-test, sandbox/cleanup-test -> cleveragents/plan-cleanup-test, sandbox/branch-delete-fail -> cleveragents/plan-branch-delete-fail
- Updated scenario:
- features/garbage_collection.feature: sandbox/test-plan -> cleveragents/plan-test-plan
- Design rationale:
- Adopted the spec-required format: cleveragents/plan-{safe_plan_id} to align with the spec-defined namespace for all CleverAgents-managed git branches
- Ensures consistent branch naming across code, tests, and features for easier policy enforcement and maintainability
ISSUES CLOSED: #2601
578 lines
20 KiB
Python
578 lines
20 KiB
Python
"""Step definitions for git worktree sandbox coverage boost.
|
|
|
|
All steps use the ``gwtcb`` prefix to avoid collisions with existing steps.
|
|
These scenarios target uncovered lines and branches in git_worktree.py.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import os
|
|
import subprocess
|
|
import tempfile
|
|
from unittest.mock import MagicMock, patch
|
|
|
|
from behave import given, then, when
|
|
from behave.runner import Context
|
|
|
|
from cleveragents.infrastructure.sandbox.git_worktree import (
|
|
GitWorktreeSandbox,
|
|
_sanitise_branch_name,
|
|
)
|
|
from cleveragents.infrastructure.sandbox.protocol import (
|
|
SandboxCommitError,
|
|
SandboxCreationError,
|
|
SandboxRollbackError,
|
|
SandboxStateError,
|
|
SandboxStatus,
|
|
)
|
|
|
|
_MODULE = "cleveragents.infrastructure.sandbox.git_worktree"
|
|
|
|
|
|
def _make_sandbox(original_path: str) -> GitWorktreeSandbox:
|
|
"""Helper: create a GitWorktreeSandbox with sensible defaults."""
|
|
return GitWorktreeSandbox(
|
|
resource_id="res-cov-001",
|
|
original_path=original_path,
|
|
git_timeout=10,
|
|
)
|
|
|
|
|
|
def _init_test_repo() -> str:
|
|
"""Create a temporary git repo with an initial commit."""
|
|
repo_dir = tempfile.mkdtemp(prefix="gwtcb-test-repo-")
|
|
subprocess.run(["git", "init"], cwd=repo_dir, capture_output=True, check=True)
|
|
subprocess.run(
|
|
["git", "config", "user.email", "test@test.com"],
|
|
cwd=repo_dir,
|
|
capture_output=True,
|
|
check=True,
|
|
)
|
|
subprocess.run(
|
|
["git", "config", "user.name", "Test"],
|
|
cwd=repo_dir,
|
|
capture_output=True,
|
|
check=True,
|
|
)
|
|
subprocess.run(
|
|
["git", "config", "commit.gpgSign", "false"],
|
|
cwd=repo_dir,
|
|
capture_output=True,
|
|
check=True,
|
|
)
|
|
readme = os.path.join(repo_dir, "README.md")
|
|
with open(readme, "w") as f:
|
|
f.write("# Test Repo\n")
|
|
subprocess.run(["git", "add", "."], cwd=repo_dir, capture_output=True, check=True)
|
|
subprocess.run(
|
|
["git", "commit", "-m", "Initial commit"],
|
|
cwd=repo_dir,
|
|
capture_output=True,
|
|
check=True,
|
|
)
|
|
return repo_dir
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# _sanitise_branch_name
|
|
# ---------------------------------------------------------------------------
|
|
|
|
|
|
@when('gwtcb _sanitise_branch_name is called with "{raw}"')
|
|
def step_gwtcb_sanitise(ctx: Context, raw: str) -> None:
|
|
ctx.gwtcb_result = _sanitise_branch_name(raw)
|
|
ctx.gwtcb_error = None
|
|
|
|
|
|
@then('gwtcb the result should be "{expected}"')
|
|
def step_gwtcb_sanitise_result(ctx: Context, expected: str) -> None:
|
|
assert ctx.gwtcb_result == expected, (
|
|
f"Expected '{expected}', got '{ctx.gwtcb_result}'"
|
|
)
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# create: path is not repo root
|
|
# ---------------------------------------------------------------------------
|
|
|
|
|
|
@given("a gwtcb sandbox pointed at a non-root subdirectory")
|
|
def step_gwtcb_non_root_subdir(ctx: Context) -> None:
|
|
repo_dir = _init_test_repo()
|
|
# Create a subdirectory inside the repo
|
|
subdir = os.path.join(repo_dir, "subdir")
|
|
os.makedirs(subdir, exist_ok=True)
|
|
ctx.gwtcb_sandbox = _make_sandbox(subdir)
|
|
ctx.gwtcb_error = None
|
|
|
|
|
|
@when('gwtcb create is called for plan "{plan_id}"')
|
|
def step_gwtcb_create(ctx: Context, plan_id: str) -> None:
|
|
try:
|
|
ctx.gwtcb_sandbox.create(plan_id)
|
|
except (SandboxCreationError, SandboxStateError, ValueError) as exc:
|
|
ctx.gwtcb_error = exc
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# create: timeout
|
|
# ---------------------------------------------------------------------------
|
|
|
|
|
|
@given("a gwtcb sandbox with mocked _run_git that times out")
|
|
def step_gwtcb_create_timeout_setup(ctx: Context) -> None:
|
|
repo_dir = _init_test_repo()
|
|
ctx.gwtcb_sandbox = _make_sandbox(repo_dir)
|
|
ctx.gwtcb_error = None
|
|
|
|
# Patch _run_git to raise TimeoutExpired on first call
|
|
patcher = patch(
|
|
f"{_MODULE}._run_git",
|
|
side_effect=subprocess.TimeoutExpired(cmd="git", timeout=10),
|
|
)
|
|
ctx.gwtcb_patcher = patcher
|
|
patcher.start()
|
|
|
|
|
|
@when("gwtcb create is called expecting a timeout error")
|
|
def step_gwtcb_create_timeout(ctx: Context) -> None:
|
|
try:
|
|
ctx.gwtcb_sandbox.create("plan-timeout")
|
|
except SandboxCreationError as exc:
|
|
ctx.gwtcb_error = exc
|
|
finally:
|
|
if hasattr(ctx, "gwtcb_patcher"):
|
|
ctx.gwtcb_patcher.stop()
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# get_path: worktree_path is None
|
|
# ---------------------------------------------------------------------------
|
|
|
|
|
|
@given("a gwtcb sandbox in CREATED state with None worktree_path")
|
|
def step_gwtcb_created_none_path(ctx: Context) -> None:
|
|
repo_dir = _init_test_repo()
|
|
ctx.gwtcb_sandbox = _make_sandbox(repo_dir)
|
|
ctx.gwtcb_error = None
|
|
# Force internal state: CREATED with worktree_path = None
|
|
ctx.gwtcb_sandbox._status = SandboxStatus.CREATED
|
|
ctx.gwtcb_sandbox._worktree_path = None
|
|
|
|
|
|
@when('gwtcb get_path is called with "{path}"')
|
|
def step_gwtcb_get_path(ctx: Context, path: str) -> None:
|
|
try:
|
|
ctx.gwtcb_sandbox.get_path(path)
|
|
except SandboxStateError as exc:
|
|
ctx.gwtcb_error = exc
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# commit: worktree not initialised
|
|
# ---------------------------------------------------------------------------
|
|
|
|
|
|
@given("a gwtcb sandbox in ACTIVE state with no worktree or branch")
|
|
def step_gwtcb_active_no_worktree(ctx: Context) -> None:
|
|
repo_dir = _init_test_repo()
|
|
ctx.gwtcb_sandbox = _make_sandbox(repo_dir)
|
|
ctx.gwtcb_error = None
|
|
# Force ACTIVE with None worktree and branch to hit line 344-345
|
|
ctx.gwtcb_sandbox._status = SandboxStatus.ACTIVE
|
|
ctx.gwtcb_sandbox._worktree_path = None
|
|
ctx.gwtcb_sandbox._branch_name = None
|
|
|
|
|
|
@when('gwtcb commit is called with message "{message}"')
|
|
def step_gwtcb_commit(ctx: Context, message: str) -> None:
|
|
try:
|
|
ctx.gwtcb_commit_result = ctx.gwtcb_sandbox.commit(message)
|
|
except (SandboxStateError, SandboxCommitError) as exc:
|
|
ctx.gwtcb_error = exc
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# commit: modified files in diff output
|
|
# ---------------------------------------------------------------------------
|
|
|
|
|
|
@given("a gwtcb sandbox ready to commit with modified-file diff output")
|
|
def step_gwtcb_commit_modified_diff(ctx: Context) -> None:
|
|
repo_dir = _init_test_repo()
|
|
ctx.gwtcb_sandbox = _make_sandbox(repo_dir)
|
|
ctx.gwtcb_error = None
|
|
ctx.gwtcb_commit_result = None
|
|
|
|
# Set sandbox to ACTIVE with valid worktree/branch
|
|
ctx.gwtcb_sandbox._status = SandboxStatus.ACTIVE
|
|
ctx.gwtcb_sandbox._worktree_path = repo_dir
|
|
ctx.gwtcb_sandbox._branch_name = "cleveragents/plan-test"
|
|
ctx.gwtcb_sandbox._base_commit = "abc123"
|
|
ctx.gwtcb_sandbox._original_branch = "main"
|
|
|
|
# Prepare the diff output including M (modified), A (added), D (deleted)
|
|
diff_output = "M\tsrc/modified.py\nA\tsrc/new.py\nD\tsrc/old.py\n"
|
|
|
|
# Mock _run_git for add, commit, rev-parse, merge
|
|
def mock_run_git(args, cwd, timeout=10):
|
|
result = MagicMock()
|
|
result.stdout = "abc456\n"
|
|
result.stderr = ""
|
|
return result
|
|
|
|
ctx.gwtcb_run_git_patcher = patch(f"{_MODULE}._run_git", side_effect=mock_run_git)
|
|
ctx.gwtcb_run_git_patcher.start()
|
|
|
|
# Mock subprocess.run for diff --cached --name-status
|
|
real_subprocess_run = subprocess.run
|
|
|
|
def mock_subprocess_run(cmd, **kwargs):
|
|
if isinstance(cmd, list) and "diff" in cmd and "--name-status" in cmd:
|
|
result = MagicMock()
|
|
result.stdout = diff_output
|
|
result.stderr = ""
|
|
result.returncode = 0
|
|
return result
|
|
return real_subprocess_run(cmd, **kwargs)
|
|
|
|
ctx.gwtcb_subprocess_patcher = patch(
|
|
"subprocess.run", side_effect=mock_subprocess_run
|
|
)
|
|
ctx.gwtcb_subprocess_patcher.start()
|
|
|
|
|
|
@then('the gwtcb commit result should include changed file "{filename}"')
|
|
def step_gwtcb_commit_changed_file(ctx: Context, filename: str) -> None:
|
|
if hasattr(ctx, "gwtcb_run_git_patcher"):
|
|
ctx.gwtcb_run_git_patcher.stop()
|
|
if hasattr(ctx, "gwtcb_subprocess_patcher"):
|
|
ctx.gwtcb_subprocess_patcher.stop()
|
|
assert ctx.gwtcb_commit_result is not None, "Expected a commit result"
|
|
assert filename in ctx.gwtcb_commit_result.changed_files, (
|
|
f"Expected '{filename}' in changed_files, got {ctx.gwtcb_commit_result.changed_files}"
|
|
)
|
|
|
|
|
|
@then('the gwtcb commit result should include added file "{filename}"')
|
|
def step_gwtcb_commit_added_file(ctx: Context, filename: str) -> None:
|
|
assert ctx.gwtcb_commit_result is not None, "Expected a commit result"
|
|
assert filename in ctx.gwtcb_commit_result.added_files, (
|
|
f"Expected '{filename}' in added_files, got {ctx.gwtcb_commit_result.added_files}"
|
|
)
|
|
|
|
|
|
@then('the gwtcb commit result should include deleted file "{filename}"')
|
|
def step_gwtcb_commit_deleted_file(ctx: Context, filename: str) -> None:
|
|
assert ctx.gwtcb_commit_result is not None, "Expected a commit result"
|
|
assert filename in ctx.gwtcb_commit_result.deleted_files, (
|
|
f"Expected '{filename}' in deleted_files, got {ctx.gwtcb_commit_result.deleted_files}"
|
|
)
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# commit: timeout and CalledProcessError
|
|
# ---------------------------------------------------------------------------
|
|
|
|
|
|
@given("a gwtcb sandbox in ACTIVE state ready to commit")
|
|
def step_gwtcb_active_ready_commit(ctx: Context) -> None:
|
|
repo_dir = _init_test_repo()
|
|
ctx.gwtcb_sandbox = _make_sandbox(repo_dir)
|
|
ctx.gwtcb_error = None
|
|
ctx.gwtcb_commit_result = None
|
|
|
|
ctx.gwtcb_sandbox._status = SandboxStatus.ACTIVE
|
|
ctx.gwtcb_sandbox._worktree_path = repo_dir
|
|
ctx.gwtcb_sandbox._branch_name = "cleveragents/plan-test"
|
|
ctx.gwtcb_sandbox._base_commit = "abc123"
|
|
ctx.gwtcb_sandbox._original_branch = "main"
|
|
|
|
|
|
@given("gwtcb _run_git is mocked to raise TimeoutExpired on commit")
|
|
def step_gwtcb_mock_commit_timeout(ctx: Context) -> None:
|
|
patcher = patch(
|
|
f"{_MODULE}._run_git",
|
|
side_effect=subprocess.TimeoutExpired(cmd="git", timeout=10),
|
|
)
|
|
ctx.gwtcb_patcher = patcher
|
|
patcher.start()
|
|
|
|
|
|
@when("gwtcb commit is called expecting a timeout error")
|
|
def step_gwtcb_commit_timeout(ctx: Context) -> None:
|
|
try:
|
|
ctx.gwtcb_commit_result = ctx.gwtcb_sandbox.commit("timeout commit")
|
|
except SandboxCommitError as exc:
|
|
ctx.gwtcb_error = exc
|
|
finally:
|
|
if hasattr(ctx, "gwtcb_patcher"):
|
|
ctx.gwtcb_patcher.stop()
|
|
|
|
|
|
@given("gwtcb _run_git is mocked to raise CalledProcessError on commit")
|
|
def step_gwtcb_mock_commit_process_error(ctx: Context) -> None:
|
|
patcher = patch(
|
|
f"{_MODULE}._run_git",
|
|
side_effect=subprocess.CalledProcessError(
|
|
returncode=1,
|
|
cmd="git commit",
|
|
stderr="commit failed",
|
|
),
|
|
)
|
|
ctx.gwtcb_patcher = patcher
|
|
patcher.start()
|
|
|
|
|
|
@when("gwtcb commit is called expecting a process error")
|
|
def step_gwtcb_commit_process_error(ctx: Context) -> None:
|
|
try:
|
|
ctx.gwtcb_commit_result = ctx.gwtcb_sandbox.commit("error commit")
|
|
except SandboxCommitError as exc:
|
|
ctx.gwtcb_error = exc
|
|
finally:
|
|
if hasattr(ctx, "gwtcb_patcher"):
|
|
ctx.gwtcb_patcher.stop()
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# rollback: worktree not initialised
|
|
# ---------------------------------------------------------------------------
|
|
|
|
|
|
@given("a gwtcb sandbox in ACTIVE state with no worktree or base commit")
|
|
def step_gwtcb_active_no_worktree_rollback(ctx: Context) -> None:
|
|
repo_dir = _init_test_repo()
|
|
ctx.gwtcb_sandbox = _make_sandbox(repo_dir)
|
|
ctx.gwtcb_error = None
|
|
# Force ACTIVE with None worktree and base_commit to hit line 472-473
|
|
ctx.gwtcb_sandbox._status = SandboxStatus.ACTIVE
|
|
ctx.gwtcb_sandbox._worktree_path = None
|
|
ctx.gwtcb_sandbox._base_commit = None
|
|
|
|
|
|
@when("gwtcb rollback is called expecting a state error")
|
|
def step_gwtcb_rollback_state_error(ctx: Context) -> None:
|
|
try:
|
|
ctx.gwtcb_sandbox.rollback()
|
|
except SandboxStateError as exc:
|
|
ctx.gwtcb_error = exc
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# rollback: timeout and CalledProcessError
|
|
# ---------------------------------------------------------------------------
|
|
|
|
|
|
@given("a gwtcb sandbox in ACTIVE state ready to rollback")
|
|
def step_gwtcb_active_ready_rollback(ctx: Context) -> None:
|
|
repo_dir = _init_test_repo()
|
|
ctx.gwtcb_sandbox = _make_sandbox(repo_dir)
|
|
ctx.gwtcb_error = None
|
|
|
|
ctx.gwtcb_sandbox._status = SandboxStatus.ACTIVE
|
|
ctx.gwtcb_sandbox._worktree_path = repo_dir
|
|
ctx.gwtcb_sandbox._base_commit = "abc123"
|
|
|
|
|
|
@given("gwtcb _run_git is mocked to raise TimeoutExpired on rollback")
|
|
def step_gwtcb_mock_rollback_timeout(ctx: Context) -> None:
|
|
patcher = patch(
|
|
f"{_MODULE}._run_git",
|
|
side_effect=subprocess.TimeoutExpired(cmd="git", timeout=10),
|
|
)
|
|
ctx.gwtcb_patcher = patcher
|
|
patcher.start()
|
|
|
|
|
|
@when("gwtcb rollback is called expecting a timeout error")
|
|
def step_gwtcb_rollback_timeout(ctx: Context) -> None:
|
|
try:
|
|
ctx.gwtcb_sandbox.rollback()
|
|
except SandboxRollbackError as exc:
|
|
ctx.gwtcb_error = exc
|
|
finally:
|
|
if hasattr(ctx, "gwtcb_patcher"):
|
|
ctx.gwtcb_patcher.stop()
|
|
|
|
|
|
@given("gwtcb _run_git is mocked to raise CalledProcessError on rollback")
|
|
def step_gwtcb_mock_rollback_process_error(ctx: Context) -> None:
|
|
patcher = patch(
|
|
f"{_MODULE}._run_git",
|
|
side_effect=subprocess.CalledProcessError(
|
|
returncode=1,
|
|
cmd="git reset",
|
|
stderr="rollback failed",
|
|
),
|
|
)
|
|
ctx.gwtcb_patcher = patcher
|
|
patcher.start()
|
|
|
|
|
|
@when("gwtcb rollback is called expecting a process error")
|
|
def step_gwtcb_rollback_process_error(ctx: Context) -> None:
|
|
try:
|
|
ctx.gwtcb_sandbox.rollback()
|
|
except SandboxRollbackError as exc:
|
|
ctx.gwtcb_error = exc
|
|
finally:
|
|
if hasattr(ctx, "gwtcb_patcher"):
|
|
ctx.gwtcb_patcher.stop()
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# cleanup: worktree remove failure (fallback to shutil)
|
|
# ---------------------------------------------------------------------------
|
|
|
|
|
|
@given("a gwtcb sandbox with a worktree directory that exists")
|
|
def step_gwtcb_cleanup_worktree_exists(ctx: Context) -> None:
|
|
repo_dir = _init_test_repo()
|
|
ctx.gwtcb_sandbox = _make_sandbox(repo_dir)
|
|
ctx.gwtcb_error = None
|
|
|
|
# Create a real temp dir to act as the worktree path
|
|
worktree_dir = tempfile.mkdtemp(prefix="gwtcb-worktree-")
|
|
ctx.gwtcb_sandbox._status = SandboxStatus.ACTIVE
|
|
ctx.gwtcb_sandbox._worktree_path = worktree_dir
|
|
ctx.gwtcb_sandbox._branch_name = "cleveragents/plan-cleanup-test"
|
|
|
|
|
|
@given("gwtcb _run_git is mocked to fail on worktree remove")
|
|
def step_gwtcb_mock_worktree_remove_fail(ctx: Context) -> None:
|
|
call_count = {"n": 0}
|
|
|
|
def mock_run_git(args, cwd, timeout=10):
|
|
call_count["n"] += 1
|
|
if args and args[0] == "worktree" and "remove" in args:
|
|
raise subprocess.CalledProcessError(
|
|
returncode=1,
|
|
cmd="git worktree remove",
|
|
stderr="worktree remove failed",
|
|
)
|
|
# Let branch -D and worktree prune succeed
|
|
result = MagicMock()
|
|
result.stdout = ""
|
|
result.stderr = ""
|
|
return result
|
|
|
|
patcher = patch(f"{_MODULE}._run_git", side_effect=mock_run_git)
|
|
ctx.gwtcb_patcher = patcher
|
|
patcher.start()
|
|
|
|
|
|
@when("gwtcb cleanup is called")
|
|
def step_gwtcb_cleanup(ctx: Context) -> None:
|
|
try:
|
|
ctx.gwtcb_sandbox.cleanup()
|
|
except Exception as exc:
|
|
ctx.gwtcb_error = exc
|
|
finally:
|
|
if hasattr(ctx, "gwtcb_patcher"):
|
|
ctx.gwtcb_patcher.stop()
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# cleanup: branch delete failure
|
|
# ---------------------------------------------------------------------------
|
|
|
|
|
|
@given("a gwtcb sandbox with a branch name set but no worktree directory")
|
|
def step_gwtcb_cleanup_no_worktree_dir(ctx: Context) -> None:
|
|
repo_dir = _init_test_repo()
|
|
ctx.gwtcb_sandbox = _make_sandbox(repo_dir)
|
|
ctx.gwtcb_error = None
|
|
|
|
# Set branch name but worktree_path to a non-existent path
|
|
# so the worktree removal block is skipped
|
|
ctx.gwtcb_sandbox._status = SandboxStatus.ACTIVE
|
|
ctx.gwtcb_sandbox._worktree_path = "/tmp/nonexistent-gwtcb-worktree"
|
|
ctx.gwtcb_sandbox._branch_name = "cleveragents/plan-branch-delete-fail"
|
|
|
|
|
|
@given("gwtcb _run_git is mocked to fail on branch delete")
|
|
def step_gwtcb_mock_branch_delete_fail(ctx: Context) -> None:
|
|
|
|
def mock_run_git(args, cwd, timeout=10):
|
|
if args and args[0] == "branch" and "-D" in args:
|
|
raise subprocess.CalledProcessError(
|
|
returncode=1,
|
|
cmd="git branch -D",
|
|
stderr="branch delete failed",
|
|
)
|
|
# Let worktree prune succeed
|
|
result = MagicMock()
|
|
result.stdout = ""
|
|
result.stderr = ""
|
|
return result
|
|
|
|
patcher = patch(f"{_MODULE}._run_git", side_effect=mock_run_git)
|
|
ctx.gwtcb_patcher = patcher
|
|
patcher.start()
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Then - common assertions
|
|
# ---------------------------------------------------------------------------
|
|
|
|
|
|
@then('the gwtcb sandbox should be in the "{status}" state')
|
|
def step_gwtcb_check_status(ctx: Context, status: str) -> None:
|
|
expected = SandboxStatus(status)
|
|
assert ctx.gwtcb_sandbox.status == expected, (
|
|
f"Expected status {expected}, got {ctx.gwtcb_sandbox.status}"
|
|
)
|
|
|
|
|
|
@then("a gwtcb SandboxCreationError should be raised")
|
|
def step_gwtcb_creation_error(ctx: Context) -> None:
|
|
assert ctx.gwtcb_error is not None, "Expected an error but none occurred"
|
|
assert isinstance(ctx.gwtcb_error, SandboxCreationError), (
|
|
f"Expected SandboxCreationError, got {type(ctx.gwtcb_error).__name__}: {ctx.gwtcb_error}"
|
|
)
|
|
|
|
|
|
@then('a gwtcb SandboxCreationError should be raised with message "{msg}"')
|
|
def step_gwtcb_creation_error_msg(ctx: Context, msg: str) -> None:
|
|
assert ctx.gwtcb_error is not None, "Expected an error but none occurred"
|
|
assert isinstance(ctx.gwtcb_error, SandboxCreationError), (
|
|
f"Expected SandboxCreationError, got {type(ctx.gwtcb_error).__name__}"
|
|
)
|
|
assert msg in str(ctx.gwtcb_error), (
|
|
f"Expected '{msg}' in error message, got: {ctx.gwtcb_error}"
|
|
)
|
|
|
|
|
|
@then('a gwtcb SandboxStateError should be raised with message "{msg}"')
|
|
def step_gwtcb_state_error_msg(ctx: Context, msg: str) -> None:
|
|
assert ctx.gwtcb_error is not None, "Expected an error but none occurred"
|
|
assert isinstance(ctx.gwtcb_error, SandboxStateError), (
|
|
f"Expected SandboxStateError, got {type(ctx.gwtcb_error).__name__}: {ctx.gwtcb_error}"
|
|
)
|
|
assert msg in str(ctx.gwtcb_error), (
|
|
f"Expected '{msg}' in error message, got: {ctx.gwtcb_error}"
|
|
)
|
|
|
|
|
|
@then('a gwtcb SandboxCommitError should be raised with message "{msg}"')
|
|
def step_gwtcb_commit_error_msg(ctx: Context, msg: str) -> None:
|
|
assert ctx.gwtcb_error is not None, "Expected an error but none occurred"
|
|
assert isinstance(ctx.gwtcb_error, SandboxCommitError), (
|
|
f"Expected SandboxCommitError, got {type(ctx.gwtcb_error).__name__}: {ctx.gwtcb_error}"
|
|
)
|
|
assert msg in str(ctx.gwtcb_error), (
|
|
f"Expected '{msg}' in error message, got: {ctx.gwtcb_error}"
|
|
)
|
|
|
|
|
|
@then('a gwtcb SandboxRollbackError should be raised with message "{msg}"')
|
|
def step_gwtcb_rollback_error_msg(ctx: Context, msg: str) -> None:
|
|
assert ctx.gwtcb_error is not None, "Expected an error but none occurred"
|
|
assert isinstance(ctx.gwtcb_error, SandboxRollbackError), (
|
|
f"Expected SandboxRollbackError, got {type(ctx.gwtcb_error).__name__}: {ctx.gwtcb_error}"
|
|
)
|
|
assert msg in str(ctx.gwtcb_error), (
|
|
f"Expected '{msg}' in error message, got: {ctx.gwtcb_error}"
|
|
)
|