aboutsummaryrefslogtreecommitdiffstats
path: root/tests/core/managers
diff options
context:
space:
mode:
authorWilliam Boman <william@redwill.se>2022-03-26 13:41:50 +0100
committerGitHub <noreply@github.com>2022-03-26 13:41:50 +0100
commit212d17a039da449043b67529c29851db37acc236 (patch)
tree38411b14487895cef0d7648e198b79fd28793fe6 /tests/core/managers
parentrun autogen_metadata.lua (diff)
downloadmason-212d17a039da449043b67529c29851db37acc236.tar
mason-212d17a039da449043b67529c29851db37acc236.tar.gz
mason-212d17a039da449043b67529c29851db37acc236.tar.bz2
mason-212d17a039da449043b67529c29851db37acc236.tar.lz
mason-212d17a039da449043b67529c29851db37acc236.tar.xz
mason-212d17a039da449043b67529c29851db37acc236.tar.zst
mason-212d17a039da449043b67529c29851db37acc236.zip
add async managers (#536)
Diffstat (limited to 'tests/core/managers')
-rw-r--r--tests/core/managers/cargo_spec.lua210
-rw-r--r--tests/core/managers/composer_spec.lua188
-rw-r--r--tests/core/managers/dotnet_spec.lua47
-rw-r--r--tests/core/managers/gem_spec.lua226
-rw-r--r--tests/core/managers/git_spec.lua179
-rw-r--r--tests/core/managers/go_spec.lua187
-rw-r--r--tests/core/managers/npm_spec.lua205
-rw-r--r--tests/core/managers/opam_spec.lua64
-rw-r--r--tests/core/managers/pip3_spec.lua253
9 files changed, 1559 insertions, 0 deletions
diff --git a/tests/core/managers/cargo_spec.lua b/tests/core/managers/cargo_spec.lua
new file mode 100644
index 00000000..303bf5d0
--- /dev/null
+++ b/tests/core/managers/cargo_spec.lua
@@ -0,0 +1,210 @@
+local spy = require "luassert.spy"
+local match = require "luassert.match"
+local mock = require "luassert.mock"
+local Optional = require "nvim-lsp-installer.core.optional"
+local cargo = require "nvim-lsp-installer.core.managers.cargo"
+local Result = require "nvim-lsp-installer.core.result"
+local spawn = require "nvim-lsp-installer.core.spawn"
+
+describe("cargo manager", function()
+ ---@type InstallContext
+ local ctx
+ before_each(function()
+ ctx = InstallContextGenerator {
+ spawn = mock.new {
+ cargo = mockx.returns {},
+ },
+ }
+ end)
+
+ it(
+ "should call cargo install",
+ async_test(function()
+ ctx.requested_version = Optional.of "42.13.37"
+ cargo.crate "my-crate"(ctx)
+ assert.spy(ctx.spawn.cargo).was_called(1)
+ assert.spy(ctx.spawn.cargo).was_called_with {
+ "install",
+ "--root",
+ ".",
+ "--locked",
+ { "--version", "42.13.37" },
+ vim.NIL, -- --features
+ "my-crate",
+ }
+ end)
+ )
+
+ it(
+ "should call cargo install with git source",
+ async_test(function()
+ cargo.crate("https://my-crate.git", { git = true })(ctx)
+ assert.spy(ctx.spawn.cargo).was_called(1)
+ assert.spy(ctx.spawn.cargo).was_called_with {
+ "install",
+ "--root",
+ ".",
+ "--locked",
+ vim.NIL,
+ vim.NIL, -- --features
+ { "--git", "https://my-crate.git" },
+ }
+ end)
+ )
+
+ it(
+ "should respect options",
+ async_test(function()
+ ctx.requested_version = Optional.of "42.13.37"
+ cargo.crate("my-crate", {
+ features = "lsp",
+ })(ctx)
+ assert.spy(ctx.spawn.cargo).was_called(1)
+ assert.spy(ctx.spawn.cargo).was_called_with {
+ "install",
+ "--root",
+ ".",
+ "--locked",
+ { "--version", "42.13.37" },
+ { "--features", "lsp" },
+ "my-crate",
+ }
+ end)
+ )
+
+ it(
+ "should not allow combining version with git crate",
+ async_test(function()
+ ctx.requested_version = Optional.of "42.13.37"
+ local err = assert.has_error(function()
+ cargo.crate("my-crate", {
+ git = true,
+ })(ctx)
+ end)
+ assert.equals("Providing a version when installing a git crate is not allowed.", err)
+ assert.spy(ctx.spawn.cargo).was_called(0)
+ end)
+ )
+
+ it(
+ "should provide receipt information",
+ async_test(function()
+ cargo.crate "main-package"(ctx)
+ assert.equals(
+ vim.inspect {
+ type = "cargo",
+ package = "main-package",
+ },
+ vim.inspect(ctx.receipt.primary_source)
+ )
+ end)
+ )
+end)
+
+describe("cargo version check", function()
+ it("parses cargo installed packages output", function()
+ assert.equal(
+ vim.inspect {
+ ["bat"] = "0.18.3",
+ ["exa"] = "0.10.1",
+ ["git-select-branch"] = "0.1.1",
+ ["hello_world"] = "0.0.1",
+ ["rust-analyzer"] = "0.0.0",
+ ["stylua"] = "0.11.2",
+ ["zoxide"] = "0.5.0",
+ },
+ vim.inspect(cargo.parse_installed_crates [[bat v0.18.3:
+ bat
+exa v0.10.1:
+ exa
+git-select-branch v0.1.1:
+ git-select-branch
+hello_world v0.0.1 (/private/var/folders/ky/s6yyhm_d24d0jsrql4t8k4p40000gn/T/tmp.LGbguATJHj):
+ hello_world
+rust-analyzer v0.0.0 (/private/var/folders/ky/s6yyhm_d24d0jsrql4t8k4p40000gn/T/tmp.YlsHeA9JVL/crates/rust-analyzer):
+ rust-analyzer
+stylua v0.11.2:
+ stylua
+zoxide v0.5.0:
+ zoxide
+]])
+ )
+ end)
+
+ it(
+ "should return current version",
+ async_test(function()
+ spawn.cargo = spy.new(function()
+ return Result.success {
+ stdout = [[flux-lsp v0.8.8 (https://github.com/influxdata/flux-lsp#4e452f07):
+ flux-lsp
+]],
+ }
+ end)
+
+ local result = cargo.get_installed_primary_package_version(
+ mock.new {
+ primary_source = mock.new {
+ type = "cargo",
+ package = "https://github.com/influxdata/flux-lsp",
+ },
+ },
+ "/tmp/install/dir"
+ )
+
+ assert.spy(spawn.cargo).was_called(1)
+ assert.spy(spawn.cargo).was_called_with(match.tbl_containing {
+ "install",
+ "--list",
+ "--root",
+ ".",
+ cwd = "/tmp/install/dir",
+ })
+ assert.is_true(result:is_success())
+ assert.equals("0.8.8", result:get_or_nil())
+
+ spawn.cargo = nil
+ end)
+ )
+
+ -- XXX: This test will actually send http request to crates.io's API. It's not mocked.
+ it(
+ "should return outdated primary package",
+ async_test(function()
+ spawn.cargo = spy.new(function()
+ return Result.success {
+ stdout = [[lelwel v0.4.0:
+ lelwel-ls
+]],
+ }
+ end)
+
+ local result = cargo.check_outdated_primary_package(
+ mock.new {
+ primary_source = mock.new {
+ type = "cargo",
+ package = "lelwel",
+ },
+ },
+ "/tmp/install/dir"
+ )
+
+ assert.spy(spawn.cargo).was_called(1)
+ assert.spy(spawn.cargo).was_called_with(match.tbl_containing {
+ "install",
+ "--list",
+ "--root",
+ ".",
+ cwd = "/tmp/install/dir",
+ })
+ assert.is_true(result:is_success())
+ assert.is_true(match.tbl_containing {
+ current_version = "0.4.0",
+ latest_version = match.matches "%d.%d.%d",
+ name = "lelwel",
+ }(result:get_or_nil()))
+
+ spawn.cargo = nil
+ end)
+ )
+end)
diff --git a/tests/core/managers/composer_spec.lua b/tests/core/managers/composer_spec.lua
new file mode 100644
index 00000000..caa0721e
--- /dev/null
+++ b/tests/core/managers/composer_spec.lua
@@ -0,0 +1,188 @@
+local spy = require "luassert.spy"
+local mock = require "luassert.mock"
+local Optional = require "nvim-lsp-installer.core.optional"
+local composer = require "nvim-lsp-installer.core.managers.composer"
+local Result = require "nvim-lsp-installer.core.result"
+local spawn = require "nvim-lsp-installer.core.spawn"
+
+describe("composer manager", function()
+ ---@type InstallContext
+ local ctx
+ before_each(function()
+ ctx = InstallContextGenerator {
+ spawn = mock.new {
+ composer = mockx.returns {},
+ },
+ }
+ end)
+
+ it(
+ "should call composer require",
+ async_test(function()
+ ctx.fs.file_exists = mockx.returns(false)
+ ctx.requested_version = Optional.of "42.13.37"
+ composer.require { "main-package", "supporting-package", "supporting-package2" }(ctx)
+ assert.spy(ctx.spawn.composer).was_called(2)
+ assert.spy(ctx.spawn.composer).was_called_with {
+ "init",
+ "--no-interaction",
+ "--stability=stable",
+ }
+ assert.spy(ctx.spawn.composer).was_called_with {
+ "require",
+ {
+ "main-package:42.13.37",
+ "supporting-package",
+ "supporting-package2",
+ },
+ }
+ end)
+ )
+
+ it(
+ "should provide receipt information",
+ async_test(function()
+ ctx.requested_version = Optional.of "42.13.37"
+ composer.require { "main-package", "supporting-package", "supporting-package2" }(ctx)
+ assert.equals(
+ vim.inspect {
+ type = "composer",
+ package = "main-package",
+ },
+ vim.inspect(ctx.receipt.primary_source)
+ )
+ assert.equals(
+ vim.inspect {
+ {
+ type = "composer",
+ package = "supporting-package",
+ },
+ {
+ type = "composer",
+ package = "supporting-package2",
+ },
+ },
+ vim.inspect(ctx.receipt.secondary_sources)
+ )
+ end)
+ )
+end)
+
+describe("composer version check", function()
+ it(
+ "should return current version",
+ async_test(function()
+ spawn.composer = spy.new(function()
+ return Result.success {
+ stdout = [[
+{
+ "name": "vimeo/psalm",
+ "versions": [
+ "4.0.0"
+ ]
+}
+]],
+ }
+ end)
+
+ local result = composer.get_installed_primary_package_version(
+ mock.new {
+ primary_source = mock.new {
+ type = "composer",
+ package = "vimeo/psalm",
+ },
+ },
+ "/tmp/install/dir"
+ )
+
+ assert.spy(spawn.composer).was_called(1)
+ assert.spy(spawn.composer).was_called_with {
+ "info",
+ "--format=json",
+ "vimeo/psalm",
+ cwd = "/tmp/install/dir",
+ }
+ assert.is_true(result:is_success())
+ assert.equals("4.0.0", result:get_or_nil())
+
+ spawn.composer = nil
+ end)
+ )
+
+ it(
+ "should return outdated primary package",
+ async_test(function()
+ spawn.composer = spy.new(function()
+ return Result.success {
+ stdout = [[
+{
+ "installed": [
+ {
+ "name": "vimeo/psalm",
+ "version": "4.0.0",
+ "latest": "4.22.0",
+ "latest-status": "semver-safe-update",
+ "description": "A static analysis tool for finding errors in PHP applications"
+ }
+ ]
+}
+]],
+ }
+ end)
+
+ local result = composer.check_outdated_primary_package(
+ mock.new {
+ primary_source = mock.new {
+ type = "composer",
+ package = "vimeo/psalm",
+ },
+ },
+ "/tmp/install/dir"
+ )
+
+ assert.spy(spawn.composer).was_called(1)
+ assert.spy(spawn.composer).was_called_with {
+ "outdated",
+ "--no-interaction",
+ "--format=json",
+ cwd = "/tmp/install/dir",
+ }
+ assert.is_true(result:is_success())
+ assert.equals(
+ vim.inspect {
+ name = "vimeo/psalm",
+ current_version = "4.0.0",
+ latest_version = "4.22.0",
+ },
+ vim.inspect(result:get_or_nil())
+ )
+
+ spawn.composer = nil
+ end)
+ )
+
+ it(
+ "should return failure if primary package is not outdated",
+ async_test(function()
+ spawn.composer = spy.new(function()
+ return Result.success {
+ stdout = [[{"installed": []}]],
+ }
+ end)
+
+ local result = composer.check_outdated_primary_package(
+ mock.new {
+ primary_source = mock.new {
+ type = "composer",
+ package = "vimeo/psalm",
+ },
+ },
+ "/tmp/install/dir"
+ )
+
+ assert.is_true(result:is_failure())
+ assert.equals("Primary package is not outdated.", result:err_or_nil())
+ spawn.composer = nil
+ end)
+ )
+end)
diff --git a/tests/core/managers/dotnet_spec.lua b/tests/core/managers/dotnet_spec.lua
new file mode 100644
index 00000000..4a6887da
--- /dev/null
+++ b/tests/core/managers/dotnet_spec.lua
@@ -0,0 +1,47 @@
+local mock = require "luassert.mock"
+local Optional = require "nvim-lsp-installer.core.optional"
+local dotnet = require "nvim-lsp-installer.core.managers.dotnet"
+
+describe("dotnet manager", function()
+ ---@type InstallContext
+ local ctx
+ before_each(function()
+ ctx = InstallContextGenerator {
+ spawn = mock.new {
+ dotnet = mockx.returns {},
+ },
+ }
+ end)
+
+ it(
+ "should call dotnet tool update",
+ async_test(function()
+ ctx.requested_version = Optional.of "42.13.37"
+ dotnet.package "main-package"(ctx)
+ assert.spy(ctx.spawn.dotnet).was_called(1)
+ assert.spy(ctx.spawn.dotnet).was_called_with {
+ "tool",
+ "update",
+ "--tool-path",
+ ".",
+ { "--version", "42.13.37" },
+ "main-package",
+ }
+ end)
+ )
+
+ it(
+ "should provide receipt information",
+ async_test(function()
+ ctx.requested_version = Optional.of "42.13.37"
+ dotnet.package "main-package"(ctx)
+ assert.equals(
+ vim.inspect {
+ type = "dotnet",
+ package = "main-package",
+ },
+ vim.inspect(ctx.receipt.primary_source)
+ )
+ end)
+ )
+end)
diff --git a/tests/core/managers/gem_spec.lua b/tests/core/managers/gem_spec.lua
new file mode 100644
index 00000000..e258c65b
--- /dev/null
+++ b/tests/core/managers/gem_spec.lua
@@ -0,0 +1,226 @@
+local spy = require "luassert.spy"
+local match = require "luassert.match"
+local mock = require "luassert.mock"
+local Optional = require "nvim-lsp-installer.core.optional"
+local gem = require "nvim-lsp-installer.core.managers.gem"
+local Result = require "nvim-lsp-installer.core.result"
+local spawn = require "nvim-lsp-installer.core.spawn"
+
+describe("gem manager", function()
+ ---@type InstallContext
+ local ctx
+ before_each(function()
+ ctx = InstallContextGenerator {
+ spawn = mock.new {
+ gem = mockx.returns {},
+ },
+ }
+ end)
+
+ it(
+ "should call gem install",
+ async_test(function()
+ ctx.requested_version = Optional.of "42.13.37"
+ gem.packages { "main-package", "supporting-package", "supporting-package2" }(ctx)
+ assert.spy(ctx.spawn.gem).was_called(1)
+ assert.spy(ctx.spawn.gem).was_called_with(match.tbl_containing {
+ "install",
+ "--no-user-install",
+ "--install-dir=.",
+ "--bindir=bin",
+ "--no-document",
+ match.tbl_containing {
+ "main-package:42.13.37",
+ "supporting-package",
+ "supporting-package2",
+ },
+ })
+ end)
+ )
+
+ it(
+ "should provide receipt information",
+ async_test(function()
+ ctx.requested_version = Optional.of "42.13.37"
+ gem.packages { "main-package", "supporting-package", "supporting-package2" }(ctx)
+ assert.equals(
+ vim.inspect {
+ type = "gem",
+ package = "main-package",
+ },
+ vim.inspect(ctx.receipt.primary_source)
+ )
+ assert.equals(
+ vim.inspect {
+ {
+ type = "gem",
+ package = "supporting-package",
+ },
+ {
+ type = "gem",
+ package = "supporting-package2",
+ },
+ },
+ vim.inspect(ctx.receipt.secondary_sources)
+ )
+ end)
+ )
+end)
+
+describe("gem version check", function()
+ it(
+ "should return current version",
+ async_test(function()
+ spawn.gem = spy.new(function()
+ return Result.success {
+ stdout = [[shellwords (default: 0.1.0)
+singleton (default: 0.1.1)
+solargraph (0.44.0)
+stringio (default: 3.0.1)
+strscan (default: 3.0.1)
+]],
+ }
+ end)
+
+ local result = gem.get_installed_primary_package_version(
+ mock.new {
+ primary_source = mock.new {
+ type = "gem",
+ package = "solargraph",
+ },
+ },
+ "/tmp/install/dir"
+ )
+
+ assert.spy(spawn.gem).was_called(1)
+ assert.spy(spawn.gem).was_called_with(match.tbl_containing {
+ "list",
+ cwd = "/tmp/install/dir",
+ env = match.all_of(
+ match.list_containing "GEM_HOME=/tmp/install/dir",
+ match.list_containing "GEM_PATH=/tmp/install/dir"
+ ),
+ })
+ assert.is_true(result:is_success())
+ assert.equals("0.44.0", result:get_or_nil())
+
+ spawn.gem = nil
+ end)
+ )
+
+ it(
+ "should return outdated primary package",
+ async_test(function()
+ spawn.gem = spy.new(function()
+ return Result.success {
+ stdout = [[bigdecimal (3.1.1 < 3.1.2)
+cgi (0.3.1 < 0.3.2)
+logger (1.5.0 < 1.5.1)
+ostruct (0.5.2 < 0.5.3)
+reline (0.3.0 < 0.3.1)
+securerandom (0.1.1 < 0.2.0)
+solargraph (0.44.0 < 0.44.3)
+]],
+ }
+ end)
+
+ local result = gem.check_outdated_primary_package(
+ mock.new {
+ primary_source = mock.new {
+ type = "gem",
+ package = "solargraph",
+ },
+ },
+ "/tmp/install/dir"
+ )
+
+ assert.spy(spawn.gem).was_called(1)
+ assert.spy(spawn.gem).was_called_with(match.tbl_containing {
+ "outdated",
+ cwd = "/tmp/install/dir",
+ env = match.all_of(
+ match.list_containing "GEM_HOME=/tmp/install/dir",
+ match.list_containing "GEM_PATH=/tmp/install/dir"
+ ),
+ })
+ assert.is_true(result:is_success())
+ assert.equals(
+ vim.inspect {
+ name = "solargraph",
+ current_version = "0.44.0",
+ latest_version = "0.44.3",
+ },
+ vim.inspect(result:get_or_nil())
+ )
+
+ spawn.gem = nil
+ end)
+ )
+
+ it(
+ "should return failure if primary package is not outdated",
+ async_test(function()
+ spawn.gem = spy.new(function()
+ return Result.success {
+ stdout = "",
+ }
+ end)
+
+ local result = gem.check_outdated_primary_package(
+ mock.new {
+ primary_source = mock.new {
+ type = "gem",
+ package = "solargraph",
+ },
+ },
+ "/tmp/install/dir"
+ )
+
+ assert.is_true(result:is_failure())
+ assert.equals("Primary package is not outdated.", result:err_or_nil())
+ spawn.gem = nil
+ end)
+ )
+
+ it("parses outdated gem output", function()
+ local normalize = gem.parse_outdated_gem
+ assert.equal(
+ vim.inspect {
+ name = "solargraph",
+ current_version = "0.42.2",
+ latest_version = "0.44.2",
+ },
+ vim.inspect(normalize [[solargraph (0.42.2 < 0.44.2)]])
+ )
+ assert.equal(
+ vim.inspect {
+ name = "sorbet-runtime",
+ current_version = "0.5.9307",
+ latest_version = "0.5.9468",
+ },
+ vim.inspect(normalize [[sorbet-runtime (0.5.9307 < 0.5.9468)]])
+ )
+ end)
+
+ it("returns nil when unable to parse outdated gem", function()
+ assert.is_nil(gem.parse_outdated_gem "a whole bunch of gibberish!")
+ assert.is_nil(gem.parse_outdated_gem "")
+ end)
+
+ it("should parse gem list output", function()
+ assert.equals(
+ vim.inspect {
+ ["solargraph"] = "0.44.3",
+ ["unicode-display_width"] = "2.1.0",
+ },
+ vim.inspect(gem.parse_gem_list_output [[
+
+*** LOCAL GEMS ***
+
+nokogiri (1.13.3 arm64-darwin)
+solargraph (0.44.3)
+unicode-display_width (2.1.0)
+]])
+ )
+ end)
+end)
diff --git a/tests/core/managers/git_spec.lua b/tests/core/managers/git_spec.lua
new file mode 100644
index 00000000..2f6c6ace
--- /dev/null
+++ b/tests/core/managers/git_spec.lua
@@ -0,0 +1,179 @@
+local spy = require "luassert.spy"
+local mock = require "luassert.mock"
+local spawn = require "nvim-lsp-installer.core.spawn"
+local Result = require "nvim-lsp-installer.core.result"
+
+local git = require "nvim-lsp-installer.core.managers.git"
+local Optional = require "nvim-lsp-installer.core.optional"
+
+describe("git manager", function()
+ ---@type InstallContext
+ local ctx
+ before_each(function()
+ ctx = InstallContextGenerator {
+ spawn = mock.new {
+ git = mockx.returns {},
+ },
+ }
+ end)
+
+ it(
+ "should fail if no git repo provided",
+ async_test(function()
+ local err = assert.has_errors(function()
+ git.clone {}(ctx)
+ end)
+ assert.equals("No git URL provided.", err)
+ assert.spy(ctx.spawn.git).was_not_called()
+ end)
+ )
+
+ it(
+ "should clone provided repo",
+ async_test(function()
+ git.clone { "https://github.com/williamboman/nvim-lsp-installer.git" }(ctx)
+ assert.spy(ctx.spawn.git).was_called(1)
+ assert.spy(ctx.spawn.git).was_called_with {
+ "clone",
+ "--depth",
+ "1",
+ "https://github.com/williamboman/nvim-lsp-installer.git",
+ ".",
+ }
+ end)
+ )
+
+ it(
+ "should fetch and checkout revision if requested",
+ async_test(function()
+ ctx.requested_version = Optional.of "1337"
+ git.clone { "https://github.com/williamboman/nvim-lsp-installer.git" }(ctx)
+ assert.spy(ctx.spawn.git).was_called(3)
+ assert.spy(ctx.spawn.git).was_called_with {
+ "clone",
+ "--depth",
+ "1",
+ "https://github.com/williamboman/nvim-lsp-installer.git",
+ ".",
+ }
+ assert.spy(ctx.spawn.git).was_called_with {
+ "fetch",
+ "--depth",
+ "1",
+ "origin",
+ "1337",
+ }
+ assert.spy(ctx.spawn.git).was_called_with { "checkout", "FETCH_HEAD" }
+ end)
+ )
+
+ it(
+ "should provide receipt information",
+ async_test(function()
+ git.clone { "https://github.com/williamboman/nvim-lsp-installer.git" }(ctx)
+ assert.equals(
+ vim.inspect {
+ type = "git",
+ remote = "https://github.com/williamboman/nvim-lsp-installer.git",
+ },
+ vim.inspect(ctx.receipt.primary_source)
+ )
+ assert.is_true(#ctx.receipt.secondary_sources == 0)
+ end)
+ )
+end)
+
+describe("git version check", function()
+ it(
+ "should return current version",
+ async_test(function()
+ spawn.git = spy.new(function()
+ return Result.success {
+ stdout = [[19c668c]],
+ }
+ end)
+
+ local result = git.get_installed_revision "/tmp/install/dir"
+
+ assert.spy(spawn.git).was_called(1)
+ assert.spy(spawn.git).was_called_with { "rev-parse", "--short", "HEAD", cwd = "/tmp/install/dir" }
+ assert.is_true(result:is_success())
+ assert.equals("19c668c", result:get_or_nil())
+
+ spawn.git = nil
+ end)
+ )
+
+ it(
+ "should check for outdated git clone",
+ async_test(function()
+ spawn.git = spy.new(function()
+ return Result.success {
+ stdout = [[728307a74cd5f2dec7ca2ca164785c25673d6328
+19c668cd10695b243b09452f0dfd53570c1a2e7d]],
+ }
+ end)
+
+ local result = git.check_outdated_git_clone(
+ mock.new {
+ primary_source = mock.new {
+ type = "git",
+ remote = "https://github.com/williamboman/nvim-lsp-installer.git",
+ },
+ },
+ "/tmp/install/dir"
+ )
+
+ assert.spy(spawn.git).was_called(2)
+ assert.spy(spawn.git).was_called_with {
+ "fetch",
+ "origin",
+ "HEAD",
+ cwd = "/tmp/install/dir",
+ }
+ assert.spy(spawn.git).was_called_with {
+ "rev-parse",
+ "FETCH_HEAD",
+ "HEAD",
+ cwd = "/tmp/install/dir",
+ }
+ assert.is_true(result:is_success())
+ assert.equals(
+ vim.inspect {
+ name = "https://github.com/williamboman/nvim-lsp-installer.git",
+ current_version = "19c668cd10695b243b09452f0dfd53570c1a2e7d",
+ latest_version = "728307a74cd5f2dec7ca2ca164785c25673d6328",
+ },
+ vim.inspect(result:get_or_nil())
+ )
+
+ spawn.git = nil
+ end)
+ )
+
+ it(
+ "should return failure if clone is not outdated",
+ async_test(function()
+ spawn.git = spy.new(function()
+ return Result.success {
+ stdout = [[19c668cd10695b243b09452f0dfd53570c1a2e7d
+19c668cd10695b243b09452f0dfd53570c1a2e7d]],
+ }
+ end)
+
+ local result = git.check_outdated_git_clone(
+ mock.new {
+ primary_source = mock.new {
+ type = "git",
+ remote = "https://github.com/williamboman/nvim-lsp-installer.git",
+ },
+ },
+ "/tmp/install/dir"
+ )
+
+ assert.is_true(result:is_failure())
+ assert.equals("Git clone is up to date.", result:err_or_nil())
+ spawn.git = nil
+ end)
+ )
+end)
diff --git a/tests/core/managers/go_spec.lua b/tests/core/managers/go_spec.lua
new file mode 100644
index 00000000..4152d671
--- /dev/null
+++ b/tests/core/managers/go_spec.lua
@@ -0,0 +1,187 @@
+local match = require "luassert.match"
+local mock = require "luassert.mock"
+local stub = require "luassert.stub"
+local spy = require "luassert.spy"
+local Optional = require "nvim-lsp-installer.core.optional"
+local Result = require "nvim-lsp-installer.core.result"
+local go = require "nvim-lsp-installer.core.managers.go"
+local spawn = require "nvim-lsp-installer.core.spawn"
+
+describe("go manager", function()
+ ---@type InstallContext
+ local ctx
+ before_each(function()
+ ctx = InstallContextGenerator {
+ spawn = mock.new {
+ go = mockx.returns {},
+ },
+ }
+ end)
+
+ it(
+ "should call go install",
+ async_test(function()
+ ctx.requested_version = Optional.of "42.13.37"
+ go.packages { "main-package", "supporting-package", "supporting-package2" }(ctx)
+ assert.spy(ctx.spawn.go).was_called(3)
+ assert.spy(ctx.spawn.go).was_called_with(match.tbl_containing {
+ "install",
+ "-v",
+ "main-package@42.13.37",
+ env = match.list_containing "GOBIN=/tmp/install-dir",
+ })
+ assert.spy(ctx.spawn.go).was_called_with(match.tbl_containing {
+ "install",
+ "-v",
+ "supporting-package@latest",
+ env = match.list_containing "GOBIN=/tmp/install-dir",
+ })
+ assert.spy(ctx.spawn.go).was_called_with(match.tbl_containing {
+ "install",
+ "-v",
+ "supporting-package2@latest",
+ env = match.list_containing "GOBIN=/tmp/install-dir",
+ })
+ end)
+ )
+
+ it(
+ "should provide receipt information",
+ async_test(function()
+ ctx.requested_version = Optional.of "42.13.37"
+ go.packages { "main-package", "supporting-package", "supporting-package2" }(ctx)
+ assert.equals(
+ vim.inspect {
+ type = "go",
+ package = "main-package",
+ },
+ vim.inspect(ctx.receipt.primary_source)
+ )
+ assert.equals(
+ vim.inspect {
+ {
+ type = "go",
+ package = "supporting-package",
+ },
+ {
+ type = "go",
+ package = "supporting-package2",
+ },
+ },
+ vim.inspect(ctx.receipt.secondary_sources)
+ )
+ end)
+ )
+end)
+
+describe("go version check", function()
+ local go_version_output = [[
+gopls: go1.18
+ path golang.org/x/tools/gopls
+ mod golang.org/x/tools/gopls v0.8.1 h1:q5nDpRopYrnF4DN/1o8ZQ7Oar4Yd4I5OtGMx5RyV2/8=
+ dep github.com/google/go-cmp v0.5.7 h1:81/ik6ipDQS2aGcBfIN5dHDB36BwrStyeAQquSYCV4o=
+ dep mvdan.cc/xurls/v2 v2.4.0 h1:tzxjVAj+wSBmDcF6zBB7/myTy3gX9xvi8Tyr28AuQgc=
+ build -compiler=gc
+ build GOOS=darwin
+]]
+
+ it("should parse go version output", function()
+ local parsed = go.parse_mod_version_output(go_version_output)
+ assert.equals(
+ vim.inspect {
+ path = { ["golang.org/x/tools/gopls"] = "" },
+ mod = { ["golang.org/x/tools/gopls"] = "v0.8.1" },
+ dep = { ["github.com/google/go-cmp"] = "v0.5.7", ["mvdan.cc/xurls/v2"] = "v2.4.0" },
+ build = { ["-compiler=gc"] = "", ["GOOS=darwin"] = "" },
+ },
+ vim.inspect(parsed)
+ )
+ end)
+
+ it(
+ "should return current version",
+ async_test(function()
+ spawn.go = spy.new(function()
+ return Result.success { stdout = go_version_output }
+ end)
+
+ local result = go.get_installed_primary_package_version(
+ mock.new {
+ primary_source = mock.new {
+ type = "go",
+ package = "golang.org/x/tools/gopls",
+ },
+ },
+ "/tmp/install/dir"
+ )
+
+ assert.spy(spawn.go).was_called(1)
+ assert.spy(spawn.go).was_called_with {
+ "version",
+ "-m",
+ "gopls",
+ cwd = "/tmp/install/dir",
+ }
+ assert.is_true(result:is_success())
+ assert.equals("v0.8.1", result:get_or_nil())
+
+ spawn.go = nil
+ end)
+ )
+
+ it(
+ "should return outdated primary package",
+ async_test(function()
+ stub(spawn, "go")
+ spawn.go.on_call_with({
+ "list",
+ "-json",
+ "-m",
+ "-versions",
+ "golang.org/x/tools/gopls",
+ cwd = "/tmp/install/dir",
+ }).returns(Result.success {
+ stdout = [[
+ {
+ "Path": "/tmp/install/dir",
+ "Versions": [
+ "v1.0.0",
+ "v1.0.1",
+ "v2.0.0"
+ ]
+ }
+ ]],
+ })
+ spawn.go.on_call_with({
+ "version",
+ "-m",
+ "gopls",
+ cwd = "/tmp/install/dir",
+ }).returns(Result.success {
+ stdout = go_version_output,
+ })
+
+ local result = go.check_outdated_primary_package(
+ mock.new {
+ primary_source = mock.new {
+ type = "go",
+ package = "golang.org/x/tools/gopls",
+ },
+ },
+ "/tmp/install/dir"
+ )
+
+ assert.is_true(result:is_success())
+ assert.equals(
+ vim.inspect {
+ name = "golang.org/x/tools/gopls",
+ current_version = "v0.8.1",
+ latest_version = "v2.0.0",
+ },
+ vim.inspect(result:get_or_nil())
+ )
+
+ spawn.go = nil
+ end)
+ )
+end)
diff --git a/tests/core/managers/npm_spec.lua b/tests/core/managers/npm_spec.lua
new file mode 100644
index 00000000..c5e2b2b9
--- /dev/null
+++ b/tests/core/managers/npm_spec.lua
@@ -0,0 +1,205 @@
+local spy = require "luassert.spy"
+local match = require "luassert.match"
+local mock = require "luassert.mock"
+local Optional = require "nvim-lsp-installer.core.optional"
+local npm = require "nvim-lsp-installer.core.managers.npm"
+local Result = require "nvim-lsp-installer.core.result"
+local spawn = require "nvim-lsp-installer.core.spawn"
+
+describe("npm manager", function()
+ ---@type InstallContext
+ local ctx
+ before_each(function()
+ ctx = InstallContextGenerator {
+ spawn = mock.new {
+ npm = mockx.returns {},
+ },
+ }
+ end)
+
+ it(
+ "should call npm install",
+ async_test(function()
+ ctx.requested_version = Optional.of "42.13.37"
+ npm.packages { "main-package", "supporting-package", "supporting-package2" }(ctx)
+ assert.spy(ctx.spawn.npm).was_called(1)
+ assert.spy(ctx.spawn.npm).was_called_with(match.tbl_containing {
+ "install",
+ match.tbl_containing {
+ "main-package@42.13.37",
+ "supporting-package",
+ "supporting-package2",
+ },
+ })
+ end)
+ )
+
+ it(
+ "should call npm init if node_modules and package.json doesnt exist",
+ async_test(function()
+ ctx.fs.file_exists = mockx.returns(false)
+ ctx.fs.dir_exists = mockx.returns(false)
+ npm.install { "main-package", "supporting-package", "supporting-package2" }(ctx)
+ assert.spy(ctx.spawn.npm).was_called_with {
+ "init",
+ "--yes",
+ "--scope=lsp-installer",
+ }
+ end)
+ )
+
+ it(
+ "should append .npmrc file",
+ async_test(function()
+ ctx.requested_version = Optional.of "42.13.37"
+ npm.packages { "main-package", "supporting-package", "supporting-package2" }(ctx)
+ assert.spy(ctx.fs.append_file).was_called(1)
+ assert.spy(ctx.fs.append_file).was_called_with(ctx.fs, ".npmrc", "global-style=true")
+ end)
+ )
+
+ it(
+ "should provide receipt information",
+ async_test(function()
+ ctx.requested_version = Optional.of "42.13.37"
+ npm.packages { "main-package", "supporting-package", "supporting-package2" }(ctx)
+ assert.equals(
+ vim.inspect {
+ type = "npm",
+ package = "main-package",
+ },
+ vim.inspect(ctx.receipt.primary_source)
+ )
+ assert.equals(
+ vim.inspect {
+ {
+ type = "npm",
+ package = "supporting-package",
+ },
+ {
+ type = "npm",
+ package = "supporting-package2",
+ },
+ },
+ vim.inspect(ctx.receipt.secondary_sources)
+ )
+ end)
+ )
+end)
+
+describe("npm version check", function()
+ it(
+ "should return current version",
+ async_test(function()
+ spawn.npm = spy.new(function()
+ return Result.success {
+ stdout = [[
+ {
+ "name": "bash",
+ "dependencies": {
+ "bash-language-server": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/bash-language-server/-/bash-language-server-2.0.0.tgz"
+ }
+ }
+ }
+ ]],
+ }
+ end)
+
+ local result = npm.get_installed_primary_package_version(
+ mock.new {
+ primary_source = mock.new {
+ type = "npm",
+ package = "bash-language-server",
+ },
+ },
+ "/tmp/install/dir"
+ )
+
+ assert.spy(spawn.npm).was_called(1)
+ assert.spy(spawn.npm).was_called_with { "ls", "--json", cwd = "/tmp/install/dir" }
+ assert.is_true(result:is_success())
+ assert.equals("2.0.0", result:get_or_nil())
+
+ spawn.npm = nil
+ end)
+ )
+
+ it(
+ "should return outdated primary package",
+ async_test(function()
+ spawn.npm = spy.new(function()
+ -- npm outdated returns with exit code 1 if outdated packages are found!
+ return Result.failure {
+ exit_code = 1,
+ stdout = [[
+ {
+ "bash-language-server": {
+ "current": "1.17.0",
+ "wanted": "1.17.0",
+ "latest": "2.0.0",
+ "dependent": "bash",
+ "location": "/tmp/install/dir"
+ }
+ }
+ ]],
+ }
+ end)
+
+ local result = npm.check_outdated_primary_package(
+ mock.new {
+ primary_source = mock.new {
+ type = "npm",
+ package = "bash-language-server",
+ },
+ },
+ "/tmp/install/dir"
+ )
+
+ assert.spy(spawn.npm).was_called(1)
+ assert.spy(spawn.npm).was_called_with {
+ "outdated",
+ "--json",
+ "bash-language-server",
+ cwd = "/tmp/install/dir",
+ }
+ assert.is_true(result:is_success())
+ assert.equals(
+ vim.inspect {
+ name = "bash-language-server",
+ current_version = "1.17.0",
+ latest_version = "2.0.0",
+ },
+ vim.inspect(result:get_or_nil())
+ )
+
+ spawn.npm = nil
+ end)
+ )
+
+ it(
+ "should return failure if primary package is not outdated",
+ async_test(function()
+ spawn.npm = spy.new(function()
+ return Result.success {
+ stdout = "{}",
+ }
+ end)
+
+ local result = npm.check_outdated_primary_package(
+ mock.new {
+ primary_source = mock.new {
+ type = "npm",
+ package = "bash-language-server",
+ },
+ },
+ "/tmp/install/dir"
+ )
+
+ assert.is_true(result:is_failure())
+ assert.equals("Primary package is not outdated.", result:err_or_nil())
+ spawn.npm = nil
+ end)
+ )
+end)
diff --git a/tests/core/managers/opam_spec.lua b/tests/core/managers/opam_spec.lua
new file mode 100644
index 00000000..0ec003ec
--- /dev/null
+++ b/tests/core/managers/opam_spec.lua
@@ -0,0 +1,64 @@
+local match = require "luassert.match"
+local mock = require "luassert.mock"
+local Optional = require "nvim-lsp-installer.core.optional"
+local opam = require "nvim-lsp-installer.core.managers.opam"
+
+describe("opam manager", function()
+ ---@type InstallContext
+ local ctx
+ before_each(function()
+ ctx = InstallContextGenerator {
+ spawn = mock.new {
+ opam = mockx.returns {},
+ },
+ }
+ end)
+
+ it(
+ "should call opam install",
+ async_test(function()
+ ctx.requested_version = Optional.of "42.13.37"
+ opam.packages { "main-package", "supporting-package", "supporting-package2" }(ctx)
+ assert.spy(ctx.spawn.opam).was_called(1)
+ assert.spy(ctx.spawn.opam).was_called_with(match.tbl_containing {
+ "install",
+ "--destdir=.",
+ "--yes",
+ "--verbose",
+ match.tbl_containing {
+ "main-package.42.13.37",
+ "supporting-package",
+ "supporting-package2",
+ },
+ })
+ end)
+ )
+
+ it(
+ "should provide receipt information",
+ async_test(function()
+ ctx.requested_version = Optional.of "42.13.37"
+ opam.packages { "main-package", "supporting-package", "supporting-package2" }(ctx)
+ assert.equals(
+ vim.inspect {
+ type = "opam",
+ package = "main-package",
+ },
+ vim.inspect(ctx.receipt.primary_source)
+ )
+ assert.equals(
+ vim.inspect {
+ {
+ type = "opam",
+ package = "supporting-package",
+ },
+ {
+ type = "opam",
+ package = "supporting-package2",
+ },
+ },
+ vim.inspect(ctx.receipt.secondary_sources)
+ )
+ end)
+ )
+end)
diff --git a/tests/core/managers/pip3_spec.lua b/tests/core/managers/pip3_spec.lua
new file mode 100644
index 00000000..704a32e8
--- /dev/null
+++ b/tests/core/managers/pip3_spec.lua
@@ -0,0 +1,253 @@
+local mock = require "luassert.mock"
+local spy = require "luassert.spy"
+local match = require "luassert.match"
+
+local pip3 = require "nvim-lsp-installer.core.managers.pip3"
+local Optional = require "nvim-lsp-installer.core.optional"
+local Result = require "nvim-lsp-installer.core.result"
+local settings = require "nvim-lsp-installer.settings"
+local spawn = require "nvim-lsp-installer.core.spawn"
+
+describe("pip3 manager", function()
+ ---@type InstallContext
+ local ctx
+ before_each(function()
+ ctx = InstallContextGenerator {
+ spawn = mock.new {
+ python3 = mockx.returns {},
+ },
+ }
+ end)
+
+ it("normalizes pip3 packages", function()
+ local normalize = pip3.normalize_package
+ assert.equal("python-lsp-server", normalize "python-lsp-server[all]")
+ assert.equal("python-lsp-server", normalize "python-lsp-server[]")
+ assert.equal("python-lsp-server", normalize "python-lsp-server[[]]")
+ end)
+
+ it(
+ "should create venv and call pip3 install",
+ async_test(function()
+ ctx.requested_version = Optional.of "42.13.37"
+ pip3.packages { "main-package", "supporting-package", "supporting-package2" }(ctx)
+ assert.spy(ctx.promote_cwd).was_called(1)
+ assert.spy(ctx.spawn.python3).was_called(2)
+ assert.spy(ctx.spawn.python3).was_called_with {
+ "-m",
+ "venv",
+ "venv",
+ }
+ assert.spy(ctx.spawn.python3).was_called_with(match.tbl_containing {
+ "-m",
+ "pip",
+ "install",
+ "-U",
+ match.table(),
+ match.tbl_containing {
+ "main-package==42.13.37",
+ "supporting-package",
+ "supporting-package2",
+ },
+ env = match.is_table(),
+ })
+ end)
+ )
+
+ it(
+ "should exhaust python3 executable candidates if all fail",
+ async_test(function()
+ vim.g.python3_host_prog = "/my/python3"
+ ctx.spawn = mock.new {
+ python3 = mockx.throws(),
+ python = mockx.throws(),
+ [vim.g.python3_host_prog] = mockx.throws(),
+ }
+ local err = assert.has_error(function()
+ pip3.packages { "package" }(ctx)
+ end)
+ vim.g.python3_host_prog = nil
+
+ assert.equals("Unable to create python3 venv environment.", err)
+ assert.spy(ctx.spawn["/my/python3"]).was_called(1)
+ assert.spy(ctx.spawn.python3).was_called(1)
+ assert.spy(ctx.spawn.python).was_called(1)
+ end)
+ )
+
+ it(
+ "should not exhaust python3 executable if one succeeds",
+ async_test(function()
+ vim.g.python3_host_prog = "/my/python3"
+ ctx.spawn = mock.new {
+ python3 = mockx.throws(),
+ python = mockx.throws(),
+ [vim.g.python3_host_prog] = mockx.returns {},
+ }
+ pip3.packages { "package" }(ctx)
+ vim.g.python3_host_prog = nil
+ assert.spy(ctx.spawn.python3).was_called(0)
+ assert.spy(ctx.spawn.python).was_called(0)
+ assert.spy(ctx.spawn["/my/python3"]).was_called()
+ end)
+ )
+
+ it(
+ "should use install_args from settings",
+ async_test(function()
+ settings.set {
+ pip = {
+ install_args = { "--proxy", "http://localhost:8080" },
+ },
+ }
+ pip3.packages { "package" }(ctx)
+ settings.set(settings._DEFAULT_SETTINGS)
+ assert.spy(ctx.spawn.python3).was_called_with(match.tbl_containing {
+ "-m",
+ "pip",
+ "install",
+ "-U",
+ match.tbl_containing { "--proxy", "http://localhost:8080" },
+ match.tbl_containing { "package" },
+ env = match.is_table(),
+ })
+ end)
+ )
+
+ it(
+ "should provide receipt information",
+ async_test(function()
+ ctx.requested_version = Optional.of "42.13.37"
+ pip3.packages { "main-package", "supporting-package", "supporting-package2" }(ctx)
+ assert.equals(
+ vim.inspect {
+ type = "pip3",
+ package = "main-package",
+ },
+ vim.inspect(ctx.receipt.primary_source)
+ )
+ assert.equals(
+ vim.inspect {
+ {
+ type = "pip3",
+ package = "supporting-package",
+ },
+ {
+ type = "pip3",
+ package = "supporting-package2",
+ },
+ },
+ vim.inspect(ctx.receipt.secondary_sources)
+ )
+ end)
+ )
+end)
+
+describe("pip3 version check", function()
+ it(
+ "should return current version",
+ async_test(function()
+ spawn.python = spy.new(function()
+ return Result.success {
+ stdout = [[
+ [{"name": "astroid", "version": "2.9.3"}, {"name": "mccabe", "version": "0.6.1"}, {"name": "python-lsp-server", "version": "1.3.0", "latest_version": "1.4.0", "latest_filetype": "wheel"}, {"name": "wrapt", "version": "1.13.3", "latest_version": "1.14.0", "latest_filetype": "wheel"}]
+ ]],
+ }
+ end)
+
+ local result = pip3.get_installed_primary_package_version(
+ mock.new {
+ primary_source = mock.new {
+ type = "pip3",
+ package = "python-lsp-server",
+ },
+ },
+ "/tmp/install/dir"
+ )
+
+ assert.spy(spawn.python).was_called(1)
+ assert.spy(spawn.python).was_called_with(match.tbl_containing {
+ "-m",
+ "pip",
+ "list",
+ "--format=json",
+ cwd = "/tmp/install/dir",
+ env = match.table(),
+ })
+ assert.is_true(result:is_success())
+ assert.equals("1.3.0", result:get_or_nil())
+
+ spawn.python = nil
+ end)
+ )
+
+ it(
+ "should return outdated primary package",
+ async_test(function()
+ spawn.python = spy.new(function()
+ return Result.success {
+ stdout = [[
+[{"name": "astroid", "version": "2.9.3", "latest_version": "2.11.0", "latest_filetype": "wheel"}, {"name": "mccabe", "version": "0.6.1", "latest_version": "0.7.0", "latest_filetype": "wheel"}, {"name": "python-lsp-server", "version": "1.3.0", "latest_version": "1.4.0", "latest_filetype": "wheel"}, {"name": "wrapt", "version": "1.13.3", "latest_version": "1.14.0", "latest_filetype": "wheel"}]
+ ]],
+ }
+ end)
+
+ local result = pip3.check_outdated_primary_package(
+ mock.new {
+ primary_source = mock.new {
+ type = "pip3",
+ package = "python-lsp-server",
+ },
+ },
+ "/tmp/install/dir"
+ )
+
+ assert.spy(spawn.python).was_called(1)
+ assert.spy(spawn.python).was_called_with(match.tbl_containing {
+ "-m",
+ "pip",
+ "list",
+ "--outdated",
+ "--format=json",
+ cwd = "/tmp/install/dir",
+ env = match.table(),
+ })
+ assert.is_true(result:is_success())
+ assert.equals(
+ vim.inspect {
+ name = "python-lsp-server",
+ current_version = "1.3.0",
+ latest_version = "1.4.0",
+ },
+ vim.inspect(result:get_or_nil())
+ )
+
+ spawn.python = nil
+ end)
+ )
+
+ it(
+ "should return failure if primary package is not outdated",
+ async_test(function()
+ spawn.python = spy.new(function()
+ return Result.success {
+ stdout = "[]",
+ }
+ end)
+
+ local result = pip3.check_outdated_primary_package(
+ mock.new {
+ primary_source = mock.new {
+ type = "pip3",
+ package = "python-lsp-server",
+ },
+ },
+ "/tmp/install/dir"
+ )
+
+ assert.is_true(result:is_failure())
+ assert.equals("Primary package is not outdated.", result:err_or_nil())
+ spawn.python = nil
+ end)
+ )
+end)