run_features.lua
1 #!/usr/bin/env lua 2 -- Run all .feature files with byfeature-style output (Feature:/Scenario:/steps with ✓/✗ and colors). 3 -- Usage: from repo root, lua tests/run_features.lua 4 -- Step definitions must be required before running (they register with the runner). 5 6 local repo_root = os.getenv('DOTFILES_HOME') or (os.getenv('HOME') and (os.getenv('HOME') .. '/.dotfiles')) or '.' 7 package.path = package.path .. ';' .. repo_root .. '/?.lua;' .. repo_root .. '/tests/?.lua' 8 9 local runner = require('tests.runner.feature_runner') 10 local lfs = require('lfs') 11 local colors = require('tests.runner.colors') 12 13 -- Load step definitions (they register with runner when required) 14 local step_dir = repo_root .. '/tests/step_definitions' 15 for name in lfs.dir(step_dir) do 16 if name:match('%.lua$') then 17 local mod = name:gsub('%.lua$', '') 18 pcall(require, 'tests.step_definitions.' .. mod) 19 end 20 end 21 22 local features_dir = repo_root .. '/tests/features' 23 local total_passed, total_failed = 0, 0 24 local all_errors = {} 25 26 -- Skip feature files that have no step definitions yet (e.g. nvim_keymaps) 27 local skip_features = { ['nvim_keymaps.feature'] = true } 28 29 print(colors.blue('=== RUN Lua/Features')) 30 print('') 31 32 for name in lfs.dir(features_dir) do 33 if name:match('%.feature$') and not skip_features[name] then 34 local path = features_dir .. '/' .. name 35 local p, f, errs = runner.run_feature_file_byfeature(path, {}) 36 total_passed = total_passed + p 37 total_failed = total_failed + f 38 for _, e in ipairs(errs or {}) do table.insert(all_errors, e) end 39 end 40 end 41 42 -- Summary 43 print('') 44 if #all_errors > 0 then 45 print('--- ' .. colors.red('Failed steps:') .. '') 46 print('') 47 for _, e in ipairs(all_errors) do 48 print(' ' .. e) 49 end 50 print('') 51 end 52 53 print('--- Summary') 54 local total = total_passed + total_failed 55 if total == 0 then 56 print('No scenarios') 57 else 58 local parts = {} 59 if total_passed > 0 then table.insert(parts, colors.green(total_passed .. ' passed')) end 60 if total_failed > 0 then table.insert(parts, colors.red(total_failed .. ' failed')) end 61 print(total .. ' scenarios (' .. table.concat(parts, ', ') .. ')') 62 end 63 64 if total_failed > 0 then 65 os.exit(1) 66 end 67 os.exit(0)