LazyVim + neotest-mocha and overcoming `No test found`

LazyVim + neotest-mocha and overcoming `No test found`

I began to have issues with AstoVim setup and decided to slim down and build a LazyVim config to cover my needs. I will admit that debugging NeoVim and Lua is still a bit difficult for me to grok. I read a lot of bug reports and reached out to some people but I believe I got my answers.

So I installed LazyVim and fired up :Mason and installed the following:

  • bash-language-server
  • eslint_d
  • gitui
  • js-debug-adapter
  • lua-language-server
  • marksman
  • prettierd
  • shellcheck
  • shfmt
  • sqlfluff
  • stylua
  • typescript-language-server
  • vtsls

I went into Lazy Extras (just open nvim and hit x on the menu) and loaded

  • dap.core
  • dap.nlua
  • editor.inc-rename
  • editor.neo-tree
  • formatting.prettier
  • linting.eslint
  • lsp.none-ls
  • test.core
  • util.gitui
  • vscode

Finally I add the following config file ~/.config/nvim/lua/plugins/neotest

return {
  "nvim-neotest/neotest",
  dependencies = {
    "nvim-neotest/nvim-nio",
    "nvim-lua/plenary.nvim",
    "antoinemadec/FixCursorHold.nvim",
    "nvim-treesitter/nvim-treesitter",
    "adrigzr/neotest-mocha",
  },
  opts = {
    adapters = {
      ["neotest-mocha"] = {
        log_level = vim.log.levels.DEBUG,
        command = "npx mocha --",
        command_args = function(context)
          -- The context contains:
          --   results_path: The file that json results are written to
          --   test_name_pattern: The generated pattern for the test
          --   path: The path to the test file
          --
          -- It should return a string array of arguments
          --
          -- Not specifying 'command_args' will use the defaults below
          local relative_path = vim.fn.fnamemodify(context.path, ":.")
          return {
            "--full-trace",
            "--reporter=json",
            "--reporter-options=output=" .. context.results_path,
            "--grep=" .. context.test_name_pattern,
            relative_path,
          }
        end,
        env = { CI = true },
        cwd = function()
          return vim.fn.getcwd()
        end,
      },
    },
    --    consumers = {
    --      overseer = require("neotest.consumers.overseer"),
    --    },
    config = function(_, opts)
      local neotest_ns = vim.api.nvim_create_namespace("neotest")
      vim.diagnostic.config({
        virtual_text = {
          format = function(diagnostic)
            -- Replace newline and tab characters with space for more compact diagnostics
            local message = diagnostic.message:gsub("\n", " "):gsub("\t", " "):gsub("%s+", " "):gsub("^%s+", "")
            return message
          end,
        },
      }, neotest_ns)

      if opts.adapters then
        local adapters = {}
        for name, config in pairs(opts.adapters or {}) do
          if type(name) == "number" then
            if type(config) == "string" then
              config = require(config)
            end
            adapters[#adapters + 1] = config
          elseif config ~= false then
            local adapter = require(name)
            if type(config) == "table" and not vim.tbl_isempty(config) then
              local meta = getmetatable(adapter)
              if adapter.setup then
                adapter.setup(config)
              elseif adapter.adapter then
                adapter.adapter(config)
                adapter = adapter.adapter
              elseif meta and meta.__call then
                adapter = adapter(config)
              else
                error("Adapter " .. name .. " does not support setup")
              end
            end
            adapters[#adapters + 1] = adapter
          end
        end
        opts.adapters = adapters
      end
      require("neotest").setup(opts)
    end,
  },
}

:q

The last step is in your project to setup .mocharc.json file

Now some mocha project would error on No tests found and it took me some time to figure out why because it isn't obvious. Neotest looks for files that match its discovery regex (*_test.js*.spec.js*.test.js, …). If your files are named differently, they won’t be picked up.

You can override file discovery in the opt section

opts = {
  adapters = {
    ["neotest-mocha"] = {
      -- existing keys …
      -- Add a custom pattern (Lua pattern, not glob):
      discover_files = function(path)
        return vim.fn.globpath(path, "**/*_spec.js", false, true) -- adjust as needed
      end,
    },
  },
}

I hope this helps with anyone that encounters No tests found with neotest.