|
| 1 | +--- Integration Tests: Snacks without Telescope installed |
| 2 | +--- Verifies that the Snacks adapter works when telescope.nvim is not available |
| 3 | +--- Regression test for GitHub issue #40 |
| 4 | + |
| 5 | +local has_snacks = pcall(require, 'snacks') |
| 6 | +if not has_snacks then |
| 7 | + return |
| 8 | +end |
| 9 | + |
| 10 | +local helpers = require('spec.e2e.adapters.helpers') |
| 11 | +local e2e_helpers = require('spec.helpers.e2e_helpers') |
| 12 | + |
| 13 | +--- Temporarily block all telescope modules from being required |
| 14 | +--- @return function restore Call to restore telescope availability |
| 15 | +local function block_telescope() |
| 16 | + local blocked = {} |
| 17 | + local saved = {} |
| 18 | + |
| 19 | + -- Save and remove all loaded telescope modules |
| 20 | + for key, value in pairs(package.loaded) do |
| 21 | + if key:match('^telescope') then |
| 22 | + saved[key] = value |
| 23 | + package.loaded[key] = nil |
| 24 | + end |
| 25 | + end |
| 26 | + |
| 27 | + -- Also clear telescope-orgmode adapter cache so it reloads cleanly |
| 28 | + package.loaded['telescope-orgmode.adapters.telescope'] = nil |
| 29 | + |
| 30 | + -- Install a loader that blocks telescope requires |
| 31 | + -- LuaJIT/Lua 5.1 uses package.loaders, Lua 5.2+ uses package.searchers |
| 32 | + local searchers = package.searchers or package.loaders |
| 33 | + local function blocker(modname) |
| 34 | + if modname:match('^telescope%.') or modname == 'telescope' then |
| 35 | + return function() |
| 36 | + error('telescope is not installed (blocked by test)') |
| 37 | + end |
| 38 | + end |
| 39 | + end |
| 40 | + table.insert(searchers, 1, blocker) |
| 41 | + |
| 42 | + -- Return restore function |
| 43 | + return function() |
| 44 | + -- Remove blocker |
| 45 | + for i, s in ipairs(searchers) do |
| 46 | + if s == blocker then |
| 47 | + table.remove(searchers, i) |
| 48 | + break |
| 49 | + end |
| 50 | + end |
| 51 | + |
| 52 | + -- Restore saved modules |
| 53 | + for key, value in pairs(saved) do |
| 54 | + package.loaded[key] = value |
| 55 | + end |
| 56 | + end |
| 57 | +end |
| 58 | + |
| 59 | +describe('[Integration: Snacks without Telescope]', function() |
| 60 | + local restore_telescope |
| 61 | + |
| 62 | + before_each(function() |
| 63 | + e2e_helpers.create_test_org_files() |
| 64 | + e2e_helpers.setup_orgmode_with_test_files() |
| 65 | + -- Reset telescope-orgmode module cache to force fresh adapter loading |
| 66 | + package.loaded['telescope-orgmode'] = nil |
| 67 | + package.loaded['telescope-orgmode.adapters.snacks'] = nil |
| 68 | + package.loaded['telescope-orgmode.entry_maker.headlines'] = nil |
| 69 | + package.loaded['telescope-orgmode.entry_maker.orgfiles'] = nil |
| 70 | + restore_telescope = block_telescope() |
| 71 | + end) |
| 72 | + |
| 73 | + after_each(function() |
| 74 | + -- Clean up pickers first (before restoring telescope) |
| 75 | + pcall(function() |
| 76 | + local picker = e2e_helpers.get_current_picker_snacks() |
| 77 | + if picker then |
| 78 | + e2e_helpers.close_picker_snacks(picker) |
| 79 | + end |
| 80 | + end) |
| 81 | + helpers.close_all_pickers() |
| 82 | + helpers.close_all_buffers() |
| 83 | + |
| 84 | + -- Restore telescope availability for other tests |
| 85 | + if restore_telescope then |
| 86 | + restore_telescope() |
| 87 | + end |
| 88 | + end) |
| 89 | + |
| 90 | + describe('module loading', function() |
| 91 | + it('should load entry_maker/headlines without telescope', function() |
| 92 | + assert.has_no.errors(function() |
| 93 | + require('telescope-orgmode.entry_maker.headlines') |
| 94 | + end) |
| 95 | + end) |
| 96 | + |
| 97 | + it('should load entry_maker/orgfiles without telescope', function() |
| 98 | + assert.has_no.errors(function() |
| 99 | + require('telescope-orgmode.entry_maker.orgfiles') |
| 100 | + end) |
| 101 | + end) |
| 102 | + |
| 103 | + it('should load snacks adapter without telescope', function() |
| 104 | + assert.has_no.errors(function() |
| 105 | + require('telescope-orgmode.adapters.snacks') |
| 106 | + end) |
| 107 | + end) |
| 108 | + end) |
| 109 | + |
| 110 | + describe('data pipeline', function() |
| 111 | + it('should load headlines via get_entries without telescope', function() |
| 112 | + local headlines = require('telescope-orgmode.entry_maker.headlines') |
| 113 | + local results, widths = headlines.get_entries({}) |
| 114 | + assert.is_table(results) |
| 115 | + assert.is_true(#results > 0, 'should return headlines from test org files') |
| 116 | + assert.is_table(widths) |
| 117 | + |
| 118 | + -- Verify entry structure |
| 119 | + local entry = results[1] |
| 120 | + assert.is_string(entry.filename) |
| 121 | + assert.is_table(entry.headline) |
| 122 | + end) |
| 123 | + |
| 124 | + it('should load orgfiles via get_entries without telescope', function() |
| 125 | + local orgfiles = require('telescope-orgmode.entry_maker.orgfiles') |
| 126 | + local results = orgfiles.get_entries({}) |
| 127 | + assert.is_table(results) |
| 128 | + assert.is_true(#results > 0, 'should return org files from test setup') |
| 129 | + |
| 130 | + -- Verify entry structure |
| 131 | + local entry = results[1] |
| 132 | + assert.is_string(entry.filename) |
| 133 | + end) |
| 134 | + |
| 135 | + it('should format headline segments for snacks display without telescope', function() |
| 136 | + local headlines = require('telescope-orgmode.entry_maker.headlines') |
| 137 | + local highlight_lib = require('telescope-orgmode.lib.highlights') |
| 138 | + |
| 139 | + local results, widths = headlines.get_entries({}) |
| 140 | + assert.is_true(#results > 0) |
| 141 | + |
| 142 | + -- This is what the snacks adapter calls for each entry |
| 143 | + local opts = { widths = widths, show_location = true, show_tags = true } |
| 144 | + local segments, text = highlight_lib.get_headline_segments(results[1].headline, results[1].filename, opts) |
| 145 | + assert.is_table(segments) |
| 146 | + assert.is_true(#segments > 0, 'should produce display segments') |
| 147 | + assert.is_string(text) |
| 148 | + assert.is_true(#text > 0, 'should produce search text') |
| 149 | + end) |
| 150 | + end) |
| 151 | + |
| 152 | + describe('picker creation', function() |
| 153 | + it('should open search_headings picker without telescope', function() |
| 154 | + local tom = require('telescope-orgmode') |
| 155 | + tom.setup({ adapter = 'snacks' }) |
| 156 | + |
| 157 | + local ok, err = pcall(tom.search_headings) |
| 158 | + assert.is_true(ok, 'search_headings should work without telescope: ' .. tostring(err)) |
| 159 | + |
| 160 | + pcall(function() |
| 161 | + local picker = e2e_helpers.get_current_picker_snacks() |
| 162 | + if picker then |
| 163 | + e2e_helpers.close_picker_snacks(picker) |
| 164 | + end |
| 165 | + end) |
| 166 | + end) |
| 167 | + |
| 168 | + it('should open refile_heading picker without telescope', function() |
| 169 | + local tom = require('telescope-orgmode') |
| 170 | + tom.setup({ adapter = 'snacks' }) |
| 171 | + |
| 172 | + local ok, err = pcall(tom.refile_heading) |
| 173 | + assert.is_true(ok, 'refile_heading should work without telescope: ' .. tostring(err)) |
| 174 | + |
| 175 | + pcall(function() |
| 176 | + local picker = e2e_helpers.get_current_picker_snacks() |
| 177 | + if picker then |
| 178 | + e2e_helpers.close_picker_snacks(picker) |
| 179 | + end |
| 180 | + end) |
| 181 | + end) |
| 182 | + |
| 183 | + it('should open insert_link picker without telescope', function() |
| 184 | + vim.cmd('new') |
| 185 | + local tom = require('telescope-orgmode') |
| 186 | + tom.setup({ adapter = 'snacks' }) |
| 187 | + |
| 188 | + local ok, err = pcall(tom.insert_link) |
| 189 | + assert.is_true(ok, 'insert_link should work without telescope: ' .. tostring(err)) |
| 190 | + |
| 191 | + pcall(function() |
| 192 | + local picker = e2e_helpers.get_current_picker_snacks() |
| 193 | + if picker then |
| 194 | + e2e_helpers.close_picker_snacks(picker) |
| 195 | + end |
| 196 | + end) |
| 197 | + vim.cmd('bdelete!') |
| 198 | + end) |
| 199 | + end) |
| 200 | + |
| 201 | + describe('error handling', function() |
| 202 | + it('should show clear error when adapter fails and telescope unavailable', function() |
| 203 | + local tom = require('telescope-orgmode') |
| 204 | + tom.setup({ adapter = 'nonexistent' }) |
| 205 | + |
| 206 | + local ok, err = pcall(tom.search_headings) |
| 207 | + assert.is_false(ok, 'should error for invalid adapter without telescope fallback') |
| 208 | + assert.matches('not available', tostring(err)) |
| 209 | + end) |
| 210 | + end) |
| 211 | +end) |
0 commit comments