@@ -264,8 +264,9 @@ def test_kdma_combination_default_value_issue(page, real_data_test_server):
264264 scenario_values = [opt .get_attribute ("value" ) for opt in scenario_options if opt .get_attribute ("value" )]
265265 print (f"Available scenarios: { scenario_values } " )
266266
267- # Find a June2025-AF-train scenario
267+ # Find a June2025-AF-train scenario (required for this test)
268268 june_scenarios = [s for s in scenario_values if "June2025-AF-train" in s ]
269+ assert len (june_scenarios ) > 0 , f"June2025-AF-train scenarios required for this test, but only found: { scenario_values } "
269270
270271 scenario_select .select_option (june_scenarios [0 ])
271272 # Wait for scenario selection to take effect
@@ -282,6 +283,9 @@ def test_kdma_combination_default_value_issue(page, real_data_test_server):
282283 # Look for "Add KDMA" button
283284 add_kdma_button = page .locator (".add-kdma-btn" )
284285
286+ # This test requires the ability to add a second KDMA
287+ assert add_kdma_button .count () > 0 , "Add KDMA button must be available for this test"
288+
285289 # Click Add KDMA button
286290 add_kdma_button .click ()
287291
@@ -322,3 +326,90 @@ def test_kdma_combination_default_value_issue(page, real_data_test_server):
322326 assert scenario_select_value != "" , "Scenario select should not go blank after adding KDMA"
323327 assert "June2025-AF-train" in scenario_select_value , "Should still have June2025-AF-train scenario selected"
324328
329+
330+ def test_kdma_delete_button_enabled_after_adding_second_kdma (page , real_data_test_server ):
331+ """Test that KDMA delete buttons become enabled after adding a second KDMA when valid single-KDMA experiments exist."""
332+ page .goto (real_data_test_server )
333+
334+ # Wait for table to load
335+ page .wait_for_selector (".comparison-table" , timeout = 10000 )
336+ page .wait_for_function (
337+ "document.querySelectorAll('.table-adm-select').length > 0" , timeout = 10000
338+ )
339+
340+ # Select pipeline_baseline ADM to enable KDMA functionality
341+ adm_select = page .locator (".table-adm-select" ).first
342+ adm_select .select_option ("pipeline_baseline" )
343+ page .wait_for_load_state ("networkidle" )
344+
345+ # Select June2025-AF-train scenario to get multi-KDMA support
346+ scenario_select = page .locator (".table-scenario-select" ).first
347+
348+ # Check what scenarios are available
349+ scenario_options = scenario_select .locator ("option" ).all ()
350+ scenario_values = [opt .get_attribute ("value" ) for opt in scenario_options if opt .get_attribute ("value" )]
351+
352+ # Find a June2025-AF-train scenario (required for this test)
353+ june_scenarios = [s for s in scenario_values if "June2025-AF-train" in s ]
354+ assert len (june_scenarios ) > 0 , f"June2025-AF-train scenarios required for this test, but only found: { scenario_values } "
355+
356+ scenario_select .select_option (june_scenarios [0 ])
357+ page .wait_for_load_state ("networkidle" )
358+
359+ # Check initial KDMA delete buttons - should be disabled with single KDMA
360+ initial_delete_buttons = page .locator (".table-kdma-remove-btn" )
361+ initial_delete_count = initial_delete_buttons .count ()
362+
363+ # This test requires at least one initial delete button
364+ assert initial_delete_count > 0 , "Should have at least one delete button with initial KDMA"
365+
366+ initial_button = initial_delete_buttons .first
367+ initial_disabled = initial_button .is_disabled ()
368+ print (f"Initial delete button disabled: { initial_disabled } " )
369+
370+ # With single KDMA, delete button should be disabled (can't remove all KDMAs)
371+ assert initial_disabled , "Delete button should be disabled with single KDMA"
372+
373+ # Look for "Add KDMA" button
374+ add_kdma_button = page .locator (".add-kdma-btn" )
375+
376+ # This test requires the ability to add a second KDMA
377+ assert add_kdma_button .count () > 0 , "Add KDMA button must be available for this test"
378+
379+ # Click Add KDMA button to add second KDMA
380+ add_kdma_button .click ()
381+
382+ # Wait for new KDMA slider to be added
383+ page .wait_for_function (
384+ "document.querySelectorAll('.table-kdma-value-slider').length > 1" ,
385+ timeout = 5000
386+ )
387+
388+ # Now check delete buttons after adding second KDMA
389+ updated_delete_buttons = page .locator (".table-kdma-remove-btn" )
390+ updated_delete_count = updated_delete_buttons .count ()
391+
392+ assert updated_delete_count > 1 , "Should have delete buttons for multiple KDMAs"
393+
394+ # Check delete button states for asymmetric KDMA deletion
395+ # With two KDMAs (affiliation + merit) for June2025-AF-train scenario:
396+ # - affiliation alone: experiments exist for this scenario ✅
397+ # - merit alone: experiments DON'T exist for this scenario (they exist for June2025-MF-train) ❌
398+ # Therefore: only merit KDMA should be deletable (leaving affiliation alone)
399+ all_delete_buttons = updated_delete_buttons .all ()
400+ assert len (all_delete_buttons ) == 2 , f"Should have exactly 2 delete buttons for 2 KDMAs, got { len (all_delete_buttons )} "
401+
402+ disabled_states = [btn .is_disabled () for btn in all_delete_buttons ]
403+ print (f"Delete buttons disabled states: { disabled_states } " )
404+
405+ # Expected behavior: exactly one delete button enabled, one disabled
406+ # The merit KDMA should be deletable (disabled=False, leaving affiliation alone)
407+ # The affiliation KDMA should NOT be deletable (disabled=True, merit alone doesn't exist for this scenario)
408+ enabled_count = sum (1 for disabled in disabled_states if not disabled )
409+ disabled_count = sum (1 for disabled in disabled_states if disabled )
410+
411+ assert enabled_count == 1 , f"Expected exactly 1 enabled delete button for June2025-AF-train scenario, but got { enabled_count } enabled buttons: { disabled_states } "
412+ assert disabled_count == 1 , f"Expected exactly 1 disabled delete button for June2025-AF-train scenario, but got { disabled_count } disabled buttons: { disabled_states } "
413+
414+ print ("✓ Correctly identified asymmetric KDMA deletion: one deletable, one not" )
415+
0 commit comments