LCOV - code coverage report
Current view: top level - /lua/yoda - picker_handler.lua (source / functions) Coverage Total Hit
Test: lcov.info Lines: 100.0 % 117 117
Test Date: 2026-04-14 10:33:13 Functions: - 0 0

            Line data    Source code
       1              : -- lua/yoda/picker_handler.lua
       2              : -- Test picker UI handling - Wizard pattern with low complexity
       3              : -- All functions refactored to have cyclomatic complexity ≤ 7
       4              : 
       5            1 : local M = {}
       6              : 
       7              : -- ============================================================================
       8              : -- Constants
       9              : -- ============================================================================
      10              : 
      11            1 : local DEFAULT_MARKERS = {
      12              :   "bdd",
      13              :   "unit",
      14              :   "functional",
      15              :   "smoke",
      16              :   "critical",
      17              :   "performance",
      18              :   "regression",
      19              :   "integration",
      20              : }
      21              : 
      22            1 : local ALLURE_OPTIONS = {
      23              :   "Yes, open Allure report",
      24              :   "No, skip Allure report",
      25              : }
      26              : 
      27            2 : local CACHE_FILE_PATH = vim.fn.stdpath("cache") .. "/yoda_testpicker_marker.json"
      28              : 
      29              : -- ============================================================================
      30              : -- Cache Management (Extracted for DRY)
      31              : -- ============================================================================
      32              : 
      33              : --- Load cached test configuration
      34              : --- Complexity: 1
      35              : --- @return table Cached configuration
      36              : local function load_cached_config()
      37           23 :   local config_loader = require("yoda.config_loader")
      38           23 :   return config_loader.load_marker(CACHE_FILE_PATH)
      39            1 : end
      40              : 
      41              : --- Save test configuration to cache
      42              : --- Complexity: 1
      43              : --- @param env string Environment
      44              : --- @param region string Region
      45              : --- @param markers string Markers
      46              : --- @param open_allure boolean Allure preference
      47              : local function save_cached_config(env, region, markers, open_allure)
      48            5 :   local config_loader = require("yoda.config_loader")
      49            5 :   config_loader.save_marker(CACHE_FILE_PATH, env, region, markers, open_allure)
      50            6 : end
      51              : 
      52              : -- ============================================================================
      53              : -- Reordering Logic (Extracted for DRY - Used in 5 places!)
      54              : -- ============================================================================
      55              : 
      56              : --- Reorder items to show default first
      57              : --- Complexity: 4 (1 if + 1 insert + 1 loop + 1 conditional insert)
      58              : --- @param items table Array of items
      59              : --- @param default any Default item to show first
      60              : --- @return table Reordered items
      61              : local function reorder_with_default_first(items, default)
      62           23 :   if not default then
      63            1 :     return items
      64              :   end
      65              : 
      66           22 :   local reordered = { default }
      67           57 :   for _, item in ipairs(items) do
      68           35 :     if item ~= default then
      69           13 :       table.insert(reordered, item)
      70              :     end
      71              :   end
      72           22 :   return reordered
      73            1 : end
      74              : 
      75              : -- ============================================================================
      76              : -- Picker Wrapper (Extracted for DRY)
      77              : -- ============================================================================
      78              : 
      79              : --- Safe picker selection with cancellation handling
      80              : --- Complexity: 2 (1 if + callback)
      81              : --- @param items table Items to select from
      82              : --- @param options table Picker options
      83              : --- @param callback function Callback function
      84              : local function safe_picker_select(items, options, callback)
      85           23 :   local picker = require("snacks.picker")
      86           46 :   picker.select(items, options, function(selection)
      87           23 :     if not selection then
      88            3 :       callback(nil)
      89            3 :       return
      90              :     end
      91           20 :     callback(selection)
      92           43 :   end)
      93           24 : end
      94              : 
      95              : -- ============================================================================
      96              : -- Data Extraction Helpers
      97              : -- ============================================================================
      98              : 
      99              : --- Extract environment names from configuration
     100              : --- Complexity: 3 (1 if + 1 loop + 1 sort)
     101              : --- @param env_region table Environment configuration
     102              : --- @return table Sorted list of environment names
     103              : local function extract_env_names(env_region)
     104            7 :   if env_region.env_order then
     105            7 :     return env_region.env_order
     106              :   end
     107              : 
     108              :   local env_names = {}
     109              :   for env_name, _ in pairs(env_region.environments or env_region) do
     110              :     table.insert(env_names, env_name)
     111              :   end
     112              :   table.sort(env_names)
     113              :   return env_names
     114            1 : end
     115              : 
     116              : --- Parse environment and region from combined label
     117              : --- @param label string Label in format "env (region)"
     118              : --- @return string|nil, string|nil Environment and region
     119              : local function parse_env_region_label(label)
     120            4 :   return label:match("^(.+)%s+%((.+)%)$")
     121            1 : end
     122              : 
     123              : --- Determine Allure preference from selection
     124              : --- Complexity: 2 (1 if + 1 comparison)
     125              : --- @param selection string|nil Selected option
     126              : --- @param default boolean Default preference
     127              : --- @return boolean Whether to open Allure
     128              : local function determine_allure_preference(selection, default)
     129            5 :   if selection == nil then
     130              :     return default
     131              :   end
     132            5 :   return selection == ALLURE_OPTIONS[1]
     133            1 : end
     134              : 
     135              : --- Generate environment-region combination labels
     136              : --- Complexity: 2 (2 nested loops)
     137              : --- @param env_region table Environment and region configuration
     138              : --- @return table List of formatted labels
     139              : local function generate_env_region_labels(env_region)
     140            5 :   local items = {}
     141           11 :   for _, env in ipairs(env_region.environments) do
     142           14 :     for _, region in ipairs(env_region.regions) do
     143            8 :       table.insert(items, env .. " (" .. region .. ")")
     144              :     end
     145              :   end
     146            5 :   return items
     147            1 : end
     148              : 
     149              : -- ============================================================================
     150              : -- Wizard Steps (Each step is now a focused function)
     151              : -- ============================================================================
     152              : 
     153              : --- Wizard Step 1: Select Environment
     154              : --- Complexity: 4 (1 load + 1 reorder + 1 picker + 1 callback check)
     155              : --- @param env_names table Available environments
     156              : --- @param callback function Callback(selected_env)
     157              : local function wizard_step_select_environment(env_names, callback)
     158            7 :   local cached = load_cached_config()
     159            7 :   local reordered = reorder_with_default_first(env_names, cached.environment)
     160              : 
     161           14 :   safe_picker_select(reordered, { prompt = "Select Environment:" }, function(selected_env)
     162            7 :     if not selected_env then
     163            1 :       callback(nil)
     164            1 :       return
     165              :     end
     166            6 :     callback(selected_env)
     167           13 :   end)
     168            8 : end
     169              : 
     170              : --- Wizard Step 2: Select Region
     171              : --- Complexity: 5 (1 lookup + 1 check + 1 load + 1 reorder + 1 picker)
     172              : --- @param env_region table Environment configuration
     173              : --- @param selected_env string Selected environment
     174              : --- @param callback function Callback(selected_region)
     175              : local function wizard_step_select_region(env_region, selected_env, callback)
     176            6 :   local regions = (env_region.environments or env_region)[selected_env]
     177              : 
     178            6 :   if not regions or #regions == 0 then
     179              :     vim.notify("No regions found for environment: " .. selected_env, vim.log.levels.WARN)
     180              :     callback(nil)
     181              :     return
     182              :   end
     183              : 
     184            6 :   local cached = load_cached_config()
     185            6 :   local reordered = reorder_with_default_first(regions, cached.region)
     186              : 
     187           12 :   safe_picker_select(reordered, {
     188            6 :     prompt = "Select Region for " .. selected_env .. ":",
     189            6 :   }, callback)
     190            7 : end
     191              : 
     192              : --- Wizard Step 3: Select Markers (multiselect)
     193              : --- Complexity: 4 (1 load + 1 check + 1 picker)
     194              : --- @param callback function Callback(selected_markers)
     195              : local function wizard_step_select_markers(callback)
     196            5 :   local picker = require("yoda-adapters.picker")
     197              : 
     198           10 :   picker.multiselect(DEFAULT_MARKERS, {
     199              :     prompt = "Select Test Markers (Tab to toggle selection, Enter to confirm):",
     200              :   }, function(selected)
     201            5 :     if not selected or #selected == 0 then
     202              :       callback(nil)
     203              :       return
     204              :     end
     205              :     -- Join markers with comma for storage
     206            5 :     local markers_str = table.concat(selected, ",")
     207            5 :     callback(markers_str)
     208           10 :   end)
     209            6 : end
     210              : 
     211              : --- Wizard Step 4: Select Allure Preference
     212              : --- Complexity: 3 (1 load + 1 reorder + 1 picker)
     213              : --- @param callback function Callback(open_allure)
     214              : local function wizard_step_select_allure(callback)
     215            5 :   local cached = load_cached_config()
     216            5 :   local default_allure = cached.open_allure or false
     217            5 :   local default_text = default_allure and ALLURE_OPTIONS[1] or ALLURE_OPTIONS[2]
     218              : 
     219            5 :   local reordered = reorder_with_default_first(ALLURE_OPTIONS, default_text)
     220              : 
     221           10 :   safe_picker_select(reordered, {
     222              :     prompt = "Generate Allure Report?",
     223              :   }, function(selected)
     224            5 :     if not selected then
     225              :       callback(nil)
     226              :       return
     227              :     end
     228           10 :     callback(determine_allure_preference(selected, default_allure))
     229           10 :   end)
     230            6 : end
     231              : 
     232              : -- ============================================================================
     233              : -- Configuration Display and Command Generation
     234              : -- ============================================================================
     235              : 
     236              : -- NOTE: Pytest command generation functions have been moved to pytest-atlas.nvim plugin
     237              : 
     238              : -- ============================================================================
     239              : -- Wizard Orchestration (Chain of wizard steps)
     240              : -- ============================================================================
     241              : 
     242              : --- Execute YAML-based multi-step wizard
     243              : --- Complexity: 2 (1 extract + 1 step1 call)
     244              : --- @param env_region table Environment to regions mapping
     245              : --- @param callback function Callback function
     246            1 : function M.handle_yaml_selection(env_region, callback)
     247            7 :   local env_names = extract_env_names(env_region)
     248              : 
     249              :   -- Chain wizard steps using extracted functions
     250           14 :   wizard_step_select_environment(env_names, function(selected_env)
     251            7 :     if not selected_env then
     252            1 :       callback(nil)
     253            1 :       return
     254              :     end
     255              : 
     256           12 :     wizard_step_select_region(env_region, selected_env, function(selected_region)
     257            6 :       if not selected_region then
     258            1 :         callback(nil)
     259            1 :         return
     260              :       end
     261              : 
     262           10 :       wizard_step_select_markers(function(markers_to_use)
     263            5 :         if not markers_to_use then
     264              :           callback(nil)
     265              :           return
     266              :         end
     267              : 
     268           10 :         wizard_step_select_allure(function(open_allure)
     269            5 :           if open_allure == nil then
     270              :             callback(nil)
     271              :             return
     272              :           end
     273              : 
     274              :           -- Save and return results
     275            5 :           save_cached_config(selected_env, selected_region, markers_to_use, open_allure)
     276              : 
     277              :           -- NOTE: Configuration preview moved to pytest-atlas.nvim plugin
     278              : 
     279           10 :           callback({
     280            5 :             environment = selected_env,
     281            5 :             region = selected_region,
     282            5 :             markers = markers_to_use,
     283            5 :             open_allure = open_allure,
     284              :           })
     285           10 :         end)
     286           10 :       end)
     287           11 :     end)
     288           13 :   end)
     289            8 : end
     290              : 
     291              : --- Handle JSON/fallback single-step selection
     292              : --- Complexity: 6 (1 generate + 1 load + 1 if + 1 reorder + 1 picker + 1 parse check)
     293              : --- @param env_region table Environment and region configuration
     294              : --- @param callback function Callback function
     295            1 : function M.handle_json_selection(env_region, callback)
     296            5 :   local items = generate_env_region_labels(env_region)
     297            5 :   local cached = load_cached_config()
     298              : 
     299            5 :   local default_label = nil
     300            5 :   if cached.environment and cached.region then
     301            5 :     default_label = cached.environment .. " (" .. cached.region .. ")"
     302              :   end
     303              : 
     304            5 :   local reordered = reorder_with_default_first(items, default_label)
     305              : 
     306           10 :   safe_picker_select(reordered, { prompt = "Select Test Environment:" }, function(choice)
     307            5 :     if not choice then
     308            1 :       callback(nil)
     309            1 :       return
     310              :     end
     311              : 
     312            4 :     local env, region = parse_env_region_label(choice)
     313            4 :     if env and region then
     314            6 :       callback({ environment = env, region = region })
     315              :     else
     316            1 :       vim.notify("Failed to parse environment and region from selection", vim.log.levels.ERROR)
     317            1 :       callback(nil)
     318              :     end
     319            9 :   end)
     320            6 : end
     321              : 
     322              : -- ============================================================================
     323              : -- Public API
     324              : -- ============================================================================
     325              : 
     326              : -- NOTE: Test configuration display and command generation functions have been moved to pytest-atlas.nvim plugin
     327              : 
     328            1 : return M
        

Generated by: LCOV version 2.0-1