@@ -115,6 +115,26 @@ def mock_adversarial_target() -> PromptTarget:
115115FIXTURES = ["patch_central_database" , "mock_runtime_env" ]
116116
117117
118+ class TestScamStrategyEnum :
119+ """Aggregate expansion for ScamStrategy (DEFAULT curation)."""
120+
121+ def test_default_expands_to_single_turn_only (self ):
122+ members = {m .value for m in ScamStrategy .expand ({ScamStrategy .DEFAULT })}
123+ assert members == {"context_compliance" , "role_play" }
124+
125+ def test_default_excludes_persuasive_rta (self ):
126+ members = {m .value for m in ScamStrategy .expand ({ScamStrategy .DEFAULT })}
127+ assert "persuasive_rta" not in members
128+
129+ def test_all_includes_persuasive_rta (self ):
130+ members = {m .value for m in ScamStrategy .expand ({ScamStrategy .ALL })}
131+ assert members == {"context_compliance" , "role_play" , "persuasive_rta" }
132+
133+ def test_default_is_aggregate (self ):
134+ assert "default" in ScamStrategy .get_aggregate_tags ()
135+ assert ScamStrategy .DEFAULT in ScamStrategy .get_aggregate_strategies ()
136+
137+
118138@pytest .mark .usefixtures (* FIXTURES )
119139class TestScamInitialization :
120140 """Tests for Scam initialization."""
@@ -134,7 +154,11 @@ def test_init_with_default_objectives(
134154 scenario = Scam (objective_scorer = mock_objective_scorer )
135155
136156 assert scenario .name == "Scam"
137- assert scenario .VERSION == 1
157+ assert scenario .VERSION == 2
158+
159+ def test_default_strategy_is_default (self , mock_objective_scorer ) -> None :
160+ scenario = Scam (objective_scorer = mock_objective_scorer )
161+ assert scenario ._default_strategy == ScamStrategy .DEFAULT
138162
139163 def test_init_with_default_scorer (self , mock_memory_seed_groups ) -> None :
140164 """Test initialization with default scorer."""
@@ -219,7 +243,7 @@ class TestScamAttackGeneration:
219243 async def test_attack_generation_for_all (
220244 self , mock_objective_target , mock_objective_scorer , mock_memory_seed_groups , mock_dataset_config
221245 ):
222- """Test that _get_atomic_attacks_async returns atomic attacks ."""
246+ """ALL runs every technique, including the multi-turn PersuasiveRedTeamingAttack ."""
223247 with patch .object (
224248 Scam ,
225249 "_resolve_seed_groups_by_dataset_async" ,
@@ -228,11 +252,41 @@ async def test_attack_generation_for_all(
228252 ):
229253 scenario = Scam (objective_scorer = mock_objective_scorer )
230254
231- await scenario .initialize_async (objective_target = mock_objective_target , dataset_config = mock_dataset_config )
255+ await scenario .initialize_async (
256+ objective_target = mock_objective_target ,
257+ scenario_strategies = [ScamStrategy .ALL ],
258+ dataset_config = mock_dataset_config ,
259+ include_baseline = False ,
260+ )
261+ atomic_attacks = scenario ._atomic_attacks
262+
263+ assert len (atomic_attacks ) == 3
264+ attack_types = {type (run .attack_technique .attack ) for run in atomic_attacks }
265+ assert attack_types == {ContextComplianceAttack , RolePlayAttack , RedTeamingAttack }
266+
267+ async def test_default_run_yields_single_turn_only (
268+ self , mock_objective_target , mock_objective_scorer , mock_memory_seed_groups , mock_dataset_config
269+ ):
270+ """No explicit strategies -> DEFAULT -> only the two single-turn techniques, no persuasive_rta."""
271+ with patch .object (
272+ Scam ,
273+ "_resolve_seed_groups_by_dataset_async" ,
274+ new_callable = AsyncMock ,
275+ return_value = {"memory" : mock_memory_seed_groups },
276+ ):
277+ scenario = Scam (objective_scorer = mock_objective_scorer )
278+
279+ await scenario .initialize_async (
280+ objective_target = mock_objective_target ,
281+ dataset_config = mock_dataset_config ,
282+ include_baseline = False ,
283+ )
232284 atomic_attacks = scenario ._atomic_attacks
233285
234- assert len (atomic_attacks ) > 0
235- assert all (run .attack_technique is not None for run in atomic_attacks )
286+ assert len (atomic_attacks ) == 2
287+ attack_types = {type (run .attack_technique .attack ) for run in atomic_attacks }
288+ assert attack_types == {ContextComplianceAttack , RolePlayAttack }
289+ assert RedTeamingAttack not in attack_types
236290
237291 async def test_attack_generation_for_singleturn_async (
238292 self ,
@@ -429,7 +483,7 @@ def test_scenario_version_is_set(
429483 objective_scorer = mock_objective_scorer ,
430484 )
431485
432- assert scenario .VERSION == 1
486+ assert scenario .VERSION == 2
433487
434488 async def test_no_target_duplication_async (
435489 self ,
0 commit comments