local scan = require "plenary.scandir" local mock = require "luassert.mock" local stub = require "luassert.stub" local eq = assert.are.same local contains = function(tbl, str) for _, v in ipairs(tbl) do if v == str then return true end end return false end local contains_match = function(tbl, str) for _, v in ipairs(tbl) do if v:match(str) then return true end end return false end describe("scandir", function() describe("can list all files recursive", function() it("with cwd", function() local dirs = scan.scan_dir "." eq("table", type(dirs)) eq(true, contains(dirs, "./CHANGELOG.md")) eq(true, contains(dirs, "./LICENSE")) eq(true, contains(dirs, "./lua/plenary/job.lua")) eq(false, contains(dirs, "./asdf/asdf/adsf.lua")) end) it("and callback gets called for each entry", function() local count = 0 local dirs = scan.scan_dir(".", { on_insert = function() count = count + 1 end, }) eq("table", type(dirs)) eq(true, contains(dirs, "./CHANGELOG.md")) eq(true, contains(dirs, "./LICENSE")) eq(true, contains(dirs, "./lua/plenary/job.lua")) eq(false, contains(dirs, "./asdf/asdf/adsf.lua")) eq(count, #dirs) end) it("with multiple paths", function() local dirs = scan.scan_dir { "./lua", "./tests" } eq("table", type(dirs)) eq(true, contains(dirs, "./lua/say.lua")) eq(true, contains(dirs, "./lua/plenary/job.lua")) eq(true, contains(dirs, "./tests/plenary/scandir_spec.lua")) eq(false, contains(dirs, "./asdf/asdf/adsf.lua")) end) it("with hidden files", function() local dirs = scan.scan_dir(".", { hidden = true }) eq("table", type(dirs)) eq(true, contains(dirs, "./CHANGELOG.md")) eq(true, contains(dirs, "./lua/plenary/job.lua")) eq(true, contains(dirs, "./.gitignore")) eq(false, contains(dirs, "./asdf/asdf/adsf.lua")) end) it("with add directories", function() local dirs = scan.scan_dir(".", { add_dirs = true }) eq("table", type(dirs)) eq(true, contains(dirs, "./CHANGELOG.md")) eq(true, contains(dirs, "./lua/plenary/job.lua")) eq(true, contains(dirs, "./lua")) eq(true, contains(dirs, "./tests")) eq(false, contains(dirs, "./asdf/asdf/adsf.lua")) end) it("with only directories", function() local dirs = scan.scan_dir(".", { only_dirs = true }) eq("table", type(dirs)) eq(false, contains(dirs, "./CHANGELOG.md")) eq(false, contains(dirs, "./lua/plenary/job.lua")) eq(true, contains(dirs, "./lua")) eq(true, contains(dirs, "./tests")) eq(false, contains(dirs, "./asdf/asdf/adsf.lua")) end) it("until depth 1 is reached", function() local dirs = scan.scan_dir(".", { depth = 1 }) eq("table", type(dirs)) eq(true, contains(dirs, "./CHANGELOG.md")) eq(true, contains(dirs, "./README.md")) eq(false, contains(dirs, "./lua")) eq(false, contains(dirs, "./lua/say.lua")) eq(false, contains(dirs, "./lua/plenary/job.lua")) eq(false, contains(dirs, "./asdf/asdf/adsf.lua")) end) it("until depth 1 is reached and with directories", function() local dirs = scan.scan_dir(".", { depth = 1, add_dirs = true }) eq("table", type(dirs)) eq(true, contains(dirs, "./CHANGELOG.md")) eq(true, contains(dirs, "./README.md")) eq(true, contains(dirs, "./lua")) eq(false, contains(dirs, "./lua/say.lua")) eq(false, contains(dirs, "./lua/plenary/job.lua")) eq(false, contains(dirs, "./asdf/asdf/adsf.lua")) end) it("until depth 2 is reached", function() local dirs = scan.scan_dir(".", { depth = 2 }) eq("table", type(dirs)) eq(true, contains(dirs, "./CHANGELOG.md")) eq(true, contains(dirs, "./README.md")) eq(true, contains(dirs, "./lua/say.lua")) eq(false, contains(dirs, "./lua/plenary/job.lua")) eq(false, contains(dirs, "./asdf/asdf/adsf.lua")) end) it("with respect_gitignore", function() vim.cmd ":silent !touch lua/test.so" local dirs = scan.scan_dir(".", { respect_gitignore = true }) vim.cmd ":silent !rm lua/test.so" eq("table", type(dirs)) eq(true, contains(dirs, "./CHANGELOG.md")) eq(true, contains(dirs, "./LICENSE")) eq(true, contains(dirs, "./lua/plenary/job.lua")) eq(false, contains(dirs, "./lua/test.so")) eq(false, contains(dirs, "./asdf/asdf/adsf.lua")) end) it("with search pattern", function() local dirs = scan.scan_dir(".", { search_pattern = "filetype" }) eq("table", type(dirs)) eq(true, contains(dirs, "./scripts/update_filetypes_from_github.lua")) eq(true, contains(dirs, "./lua/plenary/filetype.lua")) eq(true, contains(dirs, "./tests/plenary/filetype_spec.lua")) eq(true, contains(dirs, "./data/plenary/filetypes/base.lua")) eq(true, contains(dirs, "./data/plenary/filetypes/builtin.lua")) eq(false, contains(dirs, "./README.md")) end) it("with callback search pattern", function() local dirs = scan.scan_dir(".", { search_pattern = function(entry) return entry:match "filetype" end, }) eq("table", type(dirs)) eq(true, contains(dirs, "./scripts/update_filetypes_from_github.lua")) eq(true, contains(dirs, "./lua/plenary/filetype.lua")) eq(true, contains(dirs, "./tests/plenary/filetype_spec.lua")) eq(true, contains(dirs, "./data/plenary/filetypes/base.lua")) eq(true, contains(dirs, "./data/plenary/filetypes/builtin.lua")) eq(false, contains(dirs, "./README.md")) end) end) describe("gitignore", function() local Path = require "plenary.path" local mock_path, mock_gitignore before_each(function() mock_path = { exists = stub.new().returns(true), iter = function() local i = 0 local n = table.getn(mock_gitignore) return function() i = i + 1 if i <= n then return mock_gitignore[i] end end end, } Path.new = stub.new().returns(mock_path) end) after_each(function() Path.new:revert() end) describe("ignores path", function() it("when path matches pattern exactly", function() mock_gitignore = { "ignored.txt" } local should_add = scan.__make_gitignore { "path" } eq(false, should_add({ "path" }, "./path/ignored.txt")) end) it("when path matches * pattern", function() mock_gitignore = { "*.txt" } local should_add = scan.__make_gitignore { "path" } eq(false, should_add({ "path" }, "./path/dir/ignored.txt")) end) it("when path matches leading ** pattern", function() mock_gitignore = { "**/ignored.txt" } local should_add = scan.__make_gitignore { "path" } eq(false, should_add({ "path" }, "./path/dir/subdir/ignored.txt")) end) it("when path matches trailing ** pattern", function() mock_gitignore = { "/dir/**" } local should_add = scan.__make_gitignore { "path" } eq(false, should_add({ "path" }, "./path/dir/subdir/ignored.txt")) end) it("when path matches ? pattern", function() mock_gitignore = { "ignore?.txt" } local should_add = scan.__make_gitignore { "path" } eq(false, should_add({ "path" }, "./path/ignored.txt")) end) end) describe("does not ignore path", function() it("when path does not match", function() mock_gitignore = { "ignored.txt" } local should_add = scan.__make_gitignore { "path" } eq(true, should_add({ "path" }, "./path/ok.txt")) end) it("when path is negated", function() mock_gitignore = { "*.txt", "!ok.txt" } local should_add = scan.__make_gitignore { "path" } eq(true, should_add({ "path" }, "./path/ok.txt")) end) end) end) describe("ls", function() it("works for cwd", function() local dirs = scan.ls "." eq("table", type(dirs)) eq(true, contains_match(dirs, "CHANGELOG.md")) eq(true, contains_match(dirs, "LICENSE")) eq(true, contains_match(dirs, "README.md")) eq(true, contains_match(dirs, "lua")) eq(false, contains_match(dirs, "%.git$")) end) it("works for another directory", function() local dirs = scan.ls "./lua" eq("table", type(dirs)) eq(true, contains_match(dirs, "luassert")) eq(true, contains_match(dirs, "plenary")) eq(true, contains_match(dirs, "say.lua")) eq(false, contains_match(dirs, "README.md")) end) it("works with opts.hidden for cwd", function() local dirs = scan.ls(".", { hidden = true }) eq("table", type(dirs)) eq(true, contains_match(dirs, "CHANGELOG.md")) eq(true, contains_match(dirs, "LICENSE")) eq(true, contains_match(dirs, "README.md")) eq(true, contains_match(dirs, "lua")) eq(true, contains_match(dirs, "%.git$")) end) end) end)