"""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