Files
cleveragents-core/features/steps/cloud_features_steps.py
T
2025-11-24 20:04:18 -05:00

288 lines
10 KiB
Python

"""Step definitions for cloud features identification."""
import json
from pathlib import Path
from behave import given, then, when
from cleveragents.discovery.cloud_features import CloudFeaturesExtractor
@given("the cloud features extractor is initialized")
def step_init_cloud_extractor(context):
"""Initialize the cloud features extractor."""
plandex_dir = Path(__file__).parent.parent.parent / "plandex"
context.cloud_extractor = CloudFeaturesExtractor(plandex_dir)
@when("I run the cloud features extraction")
def step_run_cloud_extraction(context):
"""Run the cloud features extraction."""
context.cloud_results = context.cloud_extractor.extract_all()
@when("I scan for billing features")
def step_scan_billing_features(context):
"""Scan for billing features."""
context.cloud_extractor._scan_billing_features()
context.billing_features = {
k: v
for k, v in context.cloud_extractor.cloud_features.items()
if v.get("category") == "billing"
}
@when("I scan for telemetry features")
def step_scan_telemetry_features(context):
"""Scan for telemetry features."""
context.cloud_extractor._scan_telemetry_features()
context.telemetry_features = {
k: v
for k, v in context.cloud_extractor.cloud_features.items()
if v.get("category") == "telemetry"
}
@when("I scan for managed auth features")
def step_scan_auth_features(context):
"""Scan for managed authentication features."""
context.cloud_extractor._scan_auth_features()
context.auth_features = {
k: v
for k, v in context.cloud_extractor.cloud_features.items()
if v.get("category") == "managed_auth"
}
@when("I extract cloud features and generate strategies")
def step_extract_and_generate_strategies(context):
"""Extract features and generate replacement strategies."""
context.cloud_results = context.cloud_extractor.extract_all()
context.replacement_strategies = context.cloud_results["replacements"]
@when("I extract all cloud features")
def step_extract_all_cloud_features(context):
"""Extract all cloud features."""
context.cloud_results = context.cloud_extractor.extract_all()
@given("I have identified cloud features")
def step_have_cloud_features(context):
"""Ensure cloud features are identified."""
if not hasattr(context, "cloud_results"):
context.cloud_results = context.cloud_extractor.extract_all()
@when("I save the cloud features results")
def step_save_cloud_results(context):
"""Save cloud features results."""
output_dir = Path("build/test_output/cloud")
context.json_file, context.yaml_file = context.cloud_extractor.save_results(
output_dir
)
@then("I should identify features in all categories")
def step_check_cloud_categories(context):
"""Check that features are found in multiple categories."""
features = context.cloud_results["cloud_features"]
categories = set(f.get("category") for f in features.values())
assert len(categories) >= 5, f"Expected multiple categories, got {categories}"
@then("each feature should have an action specified")
def step_check_feature_actions(context):
"""Check that each feature has an action."""
features = context.cloud_results["cloud_features"]
for feat_id, feature in features.items():
assert "action" in feature, f"Missing action in {feat_id}"
assert feature["action"] in ["remove", "replace", "defer"], (
f"Invalid action in {feat_id}"
)
@then("each feature should have a priority assigned")
def step_check_feature_priorities(context):
"""Check that each feature has a priority."""
features = context.cloud_results["cloud_features"]
for feat_id, feature in features.items():
assert "priority" in feature, f"Missing priority in {feat_id}"
assert feature["priority"] in ["high", "medium", "low"], (
f"Invalid priority in {feat_id}"
)
@then("the statistics should include feature counts")
def step_check_cloud_statistics(context):
"""Check cloud feature statistics."""
stats = context.cloud_results["statistics"]
assert "total_features" in stats
assert stats["total_features"] > 0
assert "by_category" in stats
assert "by_action" in stats
assert "by_priority" in stats
@then("I should find {feature_id} feature")
def step_find_cloud_feature(context, feature_id):
"""Check that a specific feature exists."""
# Try to find the feature in the appropriate context attribute
if hasattr(context, "billing_features") and feature_id in context.billing_features:
return
if (
hasattr(context, "telemetry_features")
and feature_id in context.telemetry_features
):
return
if hasattr(context, "auth_features") and feature_id in context.auth_features:
return
# If not found in any specific category, check all features
if hasattr(context, "cloud_extractor"):
features = context.cloud_extractor.cloud_features
assert feature_id in features, f"Feature {feature_id} not found"
else:
raise AssertionError(f"Feature {feature_id} not found in any category")
@then("each billing feature should have replacement strategy")
def step_check_billing_replacements(context):
"""Check billing features have replacements."""
for feat_id, feature in context.billing_features.items():
assert "replacement" in feature, f"Missing replacement in {feat_id}"
@then("telemetry should default to opt-in local alternatives")
def step_check_telemetry_opt_in(context):
"""Check telemetry is opt-in."""
for feat_id, feature in context.telemetry_features.items():
if "replacement" in feature:
replacement = feature["replacement"].lower()
assert "opt-in" in replacement or "local" in replacement, (
f"Telemetry {feat_id} should be opt-in/local"
)
@then("auth features should have local replacements")
def step_check_auth_replacements(context):
"""Check auth features have local replacements."""
for feat_id, feature in context.auth_features.items():
assert "replacement" in feature, f"Missing replacement in {feat_id}"
assert "local" in feature["replacement"].lower(), (
f"Auth feature {feat_id} should have local replacement"
)
@then("features should be categorized by action")
def step_check_action_categories(context):
"""Check features are categorized by action."""
assert "remove" in context.replacement_strategies
assert "replace" in context.replacement_strategies
@then("remove features should be listed")
def step_check_remove_features(context):
"""Check remove features are listed."""
remove_list = context.replacement_strategies["remove"]
assert isinstance(remove_list, list)
# We should have at least some features to remove
assert len(remove_list) > 0
@then("replace features should have alternatives")
def step_check_replace_alternatives(context):
"""Check replace features have alternatives."""
replace_list = context.replacement_strategies["replace"]
for item in replace_list:
assert "replacement" in item
assert item["replacement"] != "None"
@then("strategies should be sorted by priority")
def step_check_strategy_sorting(context):
"""Check strategies are sorted by priority."""
for action_list in context.replacement_strategies.values():
if len(action_list) > 1:
priorities = {"high": 0, "medium": 1, "low": 2}
prev_priority = -1
for item in action_list:
curr_priority = priorities.get(item["priority"], 3)
assert curr_priority >= prev_priority, (
"Strategies not sorted by priority"
)
prev_priority = curr_priority
@then("a JSON file should be created with feature data")
def step_check_cloud_json_file(context):
"""Check JSON file creation."""
assert context.json_file.exists()
with open(context.json_file) as f:
data = json.load(f)
assert "cloud_features" in data
assert "replacements" in data
@then("a YAML file should be created with feature data")
def step_check_cloud_yaml_file(context):
"""Check YAML file creation."""
assert context.yaml_file.exists()
@then("a cloud features Markdown documentation should be generated")
def step_check_cloud_markdown_doc(context):
"""Check Markdown documentation."""
md_file = context.json_file.parent / "cloud_features.md"
assert md_file.exists(), f"Markdown file {md_file} does not exist"
content = md_file.read_text()
assert "# Cloud-Only Features Analysis" in content
@then("the documentation should include replacement strategies")
def step_check_cloud_doc_strategies(context):
"""Check documentation includes strategies."""
md_file = context.json_file.parent / "cloud_features.md"
assert md_file.exists()
content = md_file.read_text()
assert "Replacement Strategies" in content
@then("the statistics should include total features")
def step_check_total_features(context):
"""Check total features statistic."""
stats = context.cloud_results["statistics"]
assert stats["total_features"] > 0
@then("the statistics should count features by category")
def step_check_features_by_category(context):
"""Check features by category statistic."""
stats = context.cloud_results["statistics"]
assert len(stats["by_category"]) > 0
@then("the statistics should count features by action")
def step_check_features_by_action(context):
"""Check features by action statistic."""
stats = context.cloud_results["statistics"]
assert stats["by_action"]["remove"] >= 0
assert stats["by_action"]["replace"] >= 0
@then("the statistics should count features by priority")
def step_check_features_by_priority(context):
"""Check features by priority statistic."""
stats = context.cloud_results["statistics"]
assert stats["by_priority"]["high"] >= 0
assert stats["by_priority"]["medium"] >= 0
assert stats["by_priority"]["low"] >= 0
@then("the statistics should count affected Go files")
def step_check_affected_files(context):
"""Check affected Go files statistic."""
stats = context.cloud_results["statistics"]
assert "go_files_affected" in stats
assert stats["go_files_affected"] > 0