From 6fd424c6680c311e0aedaa31d876ded915f722f0 Mon Sep 17 00:00:00 2001 From: Mitchell Hanberg Date: Mon, 7 Aug 2023 17:23:35 -0400 Subject: [PATCH] test: organize tests into separate files --- mix.exs | 2 +- mix.lock | 2 +- test/next_ls/diagnostics_test.exs | 117 ++++++++++++++++++++ test/next_ls_test.exs | 178 +++++++----------------------- test/support/utils.ex | 62 +++++++++++ 5 files changed, 220 insertions(+), 141 deletions(-) create mode 100644 test/next_ls/diagnostics_test.exs diff --git a/mix.exs b/mix.exs index 6548516c..56ebc3e8 100644 --- a/mix.exs +++ b/mix.exs @@ -56,7 +56,7 @@ defmodule NextLS.MixProject do # Run "mix help deps" to learn about dependencies. defp deps do [ - {:gen_lsp, "~> 0.5"}, + {:gen_lsp, "~> 0.6"}, {:exqlite, "~> 0.13.14"}, {:styler, "~> 0.8", only: :dev}, {:ex_doc, ">= 0.0.0", only: :dev}, diff --git a/mix.lock b/mix.lock index b2e2e5cf..6ffe8485 100644 --- a/mix.lock +++ b/mix.lock @@ -10,7 +10,7 @@ "ex_doc": {:hex, :ex_doc, "0.29.4", "6257ecbb20c7396b1fe5accd55b7b0d23f44b6aa18017b415cb4c2b91d997729", [:mix], [{:earmark_parser, "~> 1.4.31", [hex: :earmark_parser, repo: "hexpm", optional: false]}, {:makeup_elixir, "~> 0.14", [hex: :makeup_elixir, repo: "hexpm", optional: false]}, {:makeup_erlang, "~> 0.1", [hex: :makeup_erlang, repo: "hexpm", optional: false]}], "hexpm", "2c6699a737ae46cb61e4ed012af931b57b699643b24dabe2400a8168414bc4f5"}, "exqlite": {:hex, :exqlite, "0.13.14", "acd8b58c2245c6aa611262a887509c6aa862a05bfeb174faf348375bd9fc7edb", [:make, :mix], [{:cc_precompiler, "~> 0.1", [hex: :cc_precompiler, repo: "hexpm", optional: false]}, {:db_connection, "~> 2.1", [hex: :db_connection, repo: "hexpm", optional: false]}, {:elixir_make, "~> 0.7", [hex: :elixir_make, repo: "hexpm", optional: false]}, {:table, "~> 0.1.0", [hex: :table, repo: "hexpm", optional: true]}], "hexpm", "e81cd9b811e70a43b8d2d4ee76d3ce57ff349890ec4182f8f5223ead38ac4996"}, "finch": {:hex, :finch, "0.16.0", "40733f02c89f94a112518071c0a91fe86069560f5dbdb39f9150042f44dcfb1a", [:mix], [{:castore, "~> 0.1 or ~> 1.0", [hex: :castore, repo: "hexpm", optional: false]}, {:mime, "~> 1.0 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:mint, "~> 1.3", [hex: :mint, repo: "hexpm", optional: false]}, {:nimble_options, "~> 0.4 or ~> 1.0", [hex: :nimble_options, repo: "hexpm", optional: false]}, {:nimble_pool, "~> 0.2.6 or ~> 1.0", [hex: :nimble_pool, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "f660174c4d519e5fec629016054d60edd822cdfe2b7270836739ac2f97735ec5"}, - "gen_lsp": {:hex, :gen_lsp, "0.5.0", "463d25c2b81f64b95667e1e6fa9bf2a4ed00896f5e9abe2965bc50edeebae747", [:mix], [{:jason, "~> 1.3", [hex: :jason, repo: "hexpm", optional: false]}, {:nimble_options, "~> 0.5 or ~> 1.0", [hex: :nimble_options, repo: "hexpm", optional: false]}, {:schematic, "~> 0.2.1", [hex: :schematic, repo: "hexpm", optional: false]}, {:typed_struct, "~> 0.3.0", [hex: :typed_struct, repo: "hexpm", optional: false]}], "hexpm", "6d40e2315bd2206cb0e40e93c5d58b28ab15787214fea1066f6561df783ef7c9"}, + "gen_lsp": {:hex, :gen_lsp, "0.6.0", "6292627ec3e18a6cb026d00a1c63db3548ac4afc37d04018ea28fb621a69d0a7", [:mix], [{:jason, "~> 1.3", [hex: :jason, repo: "hexpm", optional: false]}, {:nimble_options, "~> 0.5 or ~> 1.0", [hex: :nimble_options, repo: "hexpm", optional: false]}, {:schematic, "~> 0.2.1", [hex: :schematic, repo: "hexpm", optional: false]}, {:typed_struct, "~> 0.3.0", [hex: :typed_struct, repo: "hexpm", optional: false]}], "hexpm", "676c3e1a442f3ea5fba94e67ea798a595385280dc99d509f695a78f45df515d4"}, "hpax": {:hex, :hpax, "0.1.2", "09a75600d9d8bbd064cdd741f21fc06fc1f4cf3d0fcc335e5aa19be1a7235c84", [:mix], [], "hexpm", "2c87843d5a23f5f16748ebe77969880e29809580efdaccd615cd3bed628a8c13"}, "jason": {:hex, :jason, "1.4.1", "af1504e35f629ddcdd6addb3513c3853991f694921b1b9368b0bd32beb9f1b63", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "fbb01ecdfd565b56261302f7e1fcc27c4fb8f32d56eab74db621fc154604a7a1"}, "makeup": {:hex, :makeup, "1.1.0", "6b67c8bc2882a6b6a445859952a602afc1a41c2e08379ca057c0f525366fc3ca", [:mix], [{:nimble_parsec, "~> 1.2.2 or ~> 1.3", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "0a45ed501f4a8897f580eabf99a2e5234ea3e75a4373c8a52824f6e873be57a6"}, diff --git a/test/next_ls/diagnostics_test.exs b/test/next_ls/diagnostics_test.exs new file mode 100644 index 00000000..271c5903 --- /dev/null +++ b/test/next_ls/diagnostics_test.exs @@ -0,0 +1,117 @@ +defmodule NextLS.DiagnosticsTest do + use ExUnit.Case, async: true + + import GenLSP.Test + import NextLS.Support.Utils + + @moduletag :tmp_dir + @moduletag root_paths: ["my_proj"] + setup %{tmp_dir: tmp_dir} do + File.mkdir_p!(Path.join(tmp_dir, "my_proj/lib")) + File.write!(Path.join(tmp_dir, "my_proj/mix.exs"), mix_exs()) + [cwd: tmp_dir] + end + + setup %{tmp_dir: tmp_dir} do + File.write!(Path.join(tmp_dir, "my_proj/lib/bar.ex"), """ + defmodule Bar do + defstruct [:foo] + + def foo(arg1) do + end + end + """) + + File.write!(Path.join(tmp_dir, "my_proj/lib/code_action.ex"), """ + defmodule Foo.CodeAction do + # some comment + + defmodule NestedMod do + def foo do + :ok + end + end + end + """) + + File.write!(Path.join(tmp_dir, "my_proj/lib/foo.ex"), """ + defmodule Foo do + end + """) + + File.write!(Path.join(tmp_dir, "my_proj/lib/project.ex"), """ + defmodule Project do + def hello do + :world + end + end + """) + + File.rm_rf!(Path.join(tmp_dir, ".elixir-tools")) + + :ok + end + + setup :with_lsp + + test "publishes diagnostics once the client has initialized", %{client: client, cwd: cwd} = context do + assert :ok == notify(client, %{method: "initialized", jsonrpc: "2.0", params: %{}}) + assert_request(client, "client/registerCapability", fn _params -> nil end) + + assert_notification "window/logMessage", %{ + "message" => "[NextLS] NextLS v" <> _, + "type" => 4 + } + + title = "Initializing NextLS runtime for folder #{context.module}-my_proj..." + + assert_notification "$/progress", %{ + "value" => %{"kind" => "begin", "title" => ^title} + } + + message = "NextLS runtime for folder #{context.module}-my_proj has initialized!" + + assert_notification "$/progress", %{ + "value" => %{ + "kind" => "end", + "message" => ^message + } + } + + assert_notification "$/progress", %{"value" => %{"kind" => "begin", "title" => "Compiling..."}} + + assert_notification "$/progress", %{ + "value" => %{ + "kind" => "end", + "message" => "Compiled!" + } + } + + for file <- ["bar.ex"] do + uri = + to_string(%URI{ + host: "", + scheme: "file", + path: Path.join([cwd, "my_proj/lib", file]) + }) + + char = if Version.match?(System.version(), ">= 1.15.0"), do: 10, else: 0 + + assert_notification "textDocument/publishDiagnostics", %{ + "uri" => ^uri, + "diagnostics" => [ + %{ + "source" => "Elixir", + "severity" => 2, + "message" => + "variable \"arg1\" is unused (if the variable is not meant to be used, prefix it with an underscore)", + "range" => %{ + "start" => %{"line" => 3, "character" => ^char}, + "end" => %{"line" => 3, "character" => 999} + } + } + ] + } + end + end +end diff --git a/test/next_ls_test.exs b/test/next_ls_test.exs index 99e2f6f6..b8bdd25e 100644 --- a/test/next_ls_test.exs +++ b/test/next_ls_test.exs @@ -60,11 +60,11 @@ defmodule NextLSTest do assert alive?(server) end - test "responds correctly to a shutdown request", %{client: client} do + test "responds correctly to a shutdown request", %{client: client} = context do assert :ok == notify(client, %{method: "initialized", jsonrpc: "2.0", params: %{}}) assert_request(client, "client/registerCapability", fn _params -> nil end) - assert_notification "window/logMessage", %{"message" => "[NextLS] Runtime for folder my_proj is ready..."} + assert_is_ready(context, "my_proj") assert :ok == request(client, %{ @@ -116,64 +116,7 @@ defmodule NextLSTest do } end - test "publishes diagnostics once the client has initialized", %{client: client, cwd: cwd} do - assert :ok == notify(client, %{method: "initialized", jsonrpc: "2.0", params: %{}}) - assert_request(client, "client/registerCapability", fn _params -> nil end) - - assert_notification "window/logMessage", %{ - "message" => "[NextLS] NextLS v" <> _, - "type" => 4 - } - - assert_notification "$/progress", %{ - "value" => %{"kind" => "begin", "title" => "Initializing NextLS runtime for folder my_proj..."} - } - - assert_notification "$/progress", %{ - "value" => %{ - "kind" => "end", - "message" => "NextLS runtime for folder my_proj has initialized!" - } - } - - assert_notification "$/progress", %{"value" => %{"kind" => "begin", "title" => "Compiling..."}} - - assert_notification "$/progress", %{ - "value" => %{ - "kind" => "end", - "message" => "Compiled!" - } - } - - for file <- ["bar.ex"] do - uri = - to_string(%URI{ - host: "", - scheme: "file", - path: Path.join([cwd, "my_proj/lib", file]) - }) - - char = if Version.match?(System.version(), ">= 1.15.0"), do: 10, else: 0 - - assert_notification "textDocument/publishDiagnostics", %{ - "uri" => ^uri, - "diagnostics" => [ - %{ - "source" => "Elixir", - "severity" => 2, - "message" => - "variable \"arg1\" is unused (if the variable is not meant to be used, prefix it with an underscore)", - "range" => %{ - "start" => %{"line" => 3, "character" => ^char}, - "end" => %{"line" => 3, "character" => 999} - } - } - ] - } - end - end - - test "formats", %{client: client, cwd: cwd} do + test "formats", %{client: client, cwd: cwd} = context do assert :ok == notify(client, %{method: "initialized", jsonrpc: "2.0", params: %{}}) assert_request(client, "client/registerCapability", fn _params -> nil end) @@ -215,7 +158,7 @@ defmodule NextLSTest do assert_result 2, nil - assert_notification "window/logMessage", %{"message" => "[NextLS] Runtime for folder my_proj is ready..."} + assert_is_ready(context, "my_proj") request client, %{ method: "textDocument/formatting", @@ -248,7 +191,7 @@ defmodule NextLSTest do ] end - test "formatting gracefully handles files with syntax errors", %{client: client, cwd: cwd} do + test "formatting gracefully handles files with syntax errors", %{client: client, cwd: cwd} = context do assert :ok == notify(client, %{method: "initialized", jsonrpc: "2.0", params: %{}}) assert_request(client, "client/registerCapability", fn _params -> nil end) @@ -272,7 +215,7 @@ defmodule NextLSTest do } } - assert_notification "window/logMessage", %{"message" => "[NextLS] Runtime for folder my_proj is ready..."} + assert_is_ready(context, "my_proj") request client, %{ method: "textDocument/formatting", @@ -292,11 +235,11 @@ defmodule NextLSTest do assert_result 2, nil end - test "workspace symbols", %{client: client, cwd: cwd} do + test "workspace symbols", %{client: client, cwd: cwd} = context do assert :ok == notify(client, %{method: "initialized", jsonrpc: "2.0", params: %{}}) assert_request(client, "client/registerCapability", fn _params -> nil end) - assert_notification "window/logMessage", %{"message" => "[NextLS] Runtime for folder my_proj is ready..."} + assert_is_ready(context, "my_proj") assert_notification "window/logMessage", %{"message" => "[NextLS] Compiled!"} request client, %{ @@ -383,11 +326,11 @@ defmodule NextLSTest do } in symbols end - test "workspace symbols with query", %{client: client, cwd: cwd} do + test "workspace symbols with query", %{client: client, cwd: cwd} = context do assert :ok == notify(client, %{method: "initialized", jsonrpc: "2.0", params: %{}}) assert_request(client, "client/registerCapability", fn _params -> nil end) - assert_notification "window/logMessage", %{"message" => "[NextLS] Runtime for folder my_proj is ready..."} + assert_is_ready(context, "my_proj") assert_notification "window/logMessage", %{"message" => "[NextLS] Compiled!"} request client, %{ @@ -439,11 +382,11 @@ defmodule NextLSTest do ] == symbols end - test "deletes symbols when a file is deleted", %{client: client, cwd: cwd} do + test "deletes symbols when a file is deleted", %{client: client, cwd: cwd} = context do assert :ok == notify(client, %{method: "initialized", jsonrpc: "2.0", params: %{}}) assert_request(client, "client/registerCapability", fn _params -> nil end) - assert_notification "window/logMessage", %{"message" => "[NextLS] Runtime for folder my_proj is ready..."} + assert_is_ready(context, "my_proj") assert_notification "window/logMessage", %{"message" => "[NextLS] Compiled!"} request client, %{method: "workspace/symbol", id: 2, jsonrpc: "2.0", params: %{query: ""}} @@ -542,11 +485,11 @@ defmodule NextLSTest do setup :with_lsp - test "go to local function definition", %{client: client, bar: bar} do + test "go to local function definition", %{client: client, bar: bar} = context do assert :ok == notify(client, %{method: "initialized", jsonrpc: "2.0", params: %{}}) assert_request(client, "client/registerCapability", fn _params -> nil end) - assert_notification "window/logMessage", %{"message" => "[NextLS] Runtime for folder my_proj is ready..."} + assert_is_ready(context, "my_proj") assert_notification "window/logMessage", %{"message" => "[NextLS] Compiled!"} uri = uri(bar) @@ -576,11 +519,11 @@ defmodule NextLSTest do } end - test "go to imported function definition", %{client: client, bar: bar, imported: imported} do + test "go to imported function definition", %{client: client, bar: bar, imported: imported} = context do assert :ok == notify(client, %{method: "initialized", jsonrpc: "2.0", params: %{}}) assert_request(client, "client/registerCapability", fn _params -> nil end) - assert_notification "window/logMessage", %{"message" => "[NextLS] Runtime for folder my_proj is ready..."} + assert_is_ready(context, "my_proj") assert_notification "window/logMessage", %{"message" => "[NextLS] Compiled!"} uri = uri(bar) @@ -612,11 +555,11 @@ defmodule NextLSTest do } end - test "go to remote function definition", %{client: client, bar: bar, remote: remote} do + test "go to remote function definition", %{client: client, bar: bar, remote: remote} = context do assert :ok == notify(client, %{method: "initialized", jsonrpc: "2.0", params: %{}}) assert_request(client, "client/registerCapability", fn _params -> nil end) - assert_notification "window/logMessage", %{"message" => "[NextLS] Runtime for folder my_proj is ready..."} + assert_is_ready(context, "my_proj") assert_notification "window/logMessage", %{"message" => "[NextLS] Compiled!"} uri = uri(bar) @@ -742,11 +685,11 @@ defmodule NextLSTest do } end - test "go to imported macro definition", %{client: client, bar: bar, imported: imported} do + test "go to imported macro definition", %{client: client, bar: bar, imported: imported} = context do assert :ok == notify(client, %{method: "initialized", jsonrpc: "2.0", params: %{}}) assert_request(client, "client/registerCapability", fn _params -> nil end) - assert_notification "window/logMessage", %{"message" => "[NextLS] Runtime for folder my_proj is ready..."} + assert_is_ready(context, "my_proj") assert_notification "window/logMessage", %{"message" => "[NextLS] Compiled!"} uri = uri(bar) @@ -778,11 +721,11 @@ defmodule NextLSTest do } end - test "go to remote macro definition", %{client: client, bar: bar, remote: remote} do + test "go to remote macro definition", %{client: client, bar: bar, remote: remote} = context do assert :ok == notify(client, %{method: "initialized", jsonrpc: "2.0", params: %{}}) assert_request(client, "client/registerCapability", fn _params -> nil end) - assert_notification "window/logMessage", %{"message" => "[NextLS] Runtime for folder my_proj is ready..."} + assert_is_ready(context, "my_proj") assert_notification "window/logMessage", %{"message" => "[NextLS] Compiled!"} uri = uri(bar) @@ -850,10 +793,10 @@ defmodule NextLSTest do setup :with_lsp - test "go to module definition", %{client: client, bar: bar, peace: peace} do + test "go to module definition", %{client: client, bar: bar, peace: peace} = context do assert :ok == notify(client, %{method: "initialized", jsonrpc: "2.0", params: %{}}) assert_request(client, "client/registerCapability", fn _params -> nil end) - assert_notification "window/logMessage", %{"message" => "[NextLS] Runtime for folder my_proj is ready..."} + assert_is_ready(context, "my_proj") assert_notification "window/logMessage", %{"message" => "[NextLS] Compiled!"} uri = uri(bar) @@ -1022,10 +965,10 @@ defmodule NextLSTest do setup :with_lsp @tag root_paths: ["proj_one"] - test "starts a new runtime when you add a workspace folder", %{client: client, cwd: cwd} do + test "starts a new runtime when you add a workspace folder", %{client: client, cwd: cwd} = context do assert :ok == notify(client, %{method: "initialized", jsonrpc: "2.0", params: %{}}) assert_request(client, "client/registerCapability", fn _params -> nil end) - assert_notification "window/logMessage", %{"message" => "[NextLS] Runtime for folder proj_one is ready..."} + assert_is_ready(context, "proj_one") assert_notification "window/logMessage", %{"message" => "[NextLS] Compiled!"} notify(client, %{ @@ -1034,23 +977,23 @@ defmodule NextLSTest do params: %{ event: %{ added: [ - %{name: "proj_two", uri: "file://#{Path.join(cwd, "proj_two")}"} + %{name: "#{context.module}-proj_two", uri: "file://#{Path.join(cwd, "proj_two")}"} ], removed: [] } } }) - assert_notification "window/logMessage", %{"message" => "[NextLS] Runtime for folder proj_two is ready..."} + assert_is_ready(context, "proj_two") assert_notification "window/logMessage", %{"message" => "[NextLS] Compiled!"} end @tag root_paths: ["proj_one", "proj_two"] - test "stops the runtime when you remove a workspace folder", %{client: client, cwd: cwd} do + test "stops the runtime when you remove a workspace folder", %{client: client, cwd: cwd} = context do assert :ok == notify(client, %{method: "initialized", jsonrpc: "2.0", params: %{}}) assert_request(client, "client/registerCapability", fn _params -> nil end) - assert_notification "window/logMessage", %{"message" => "[NextLS] Runtime for folder proj_one is ready..."} - assert_notification "window/logMessage", %{"message" => "[NextLS] Runtime for folder proj_two is ready..."} + assert_is_ready(context, "proj_one") + assert_is_ready(context, "proj_two") assert_notification "window/logMessage", %{"message" => "[NextLS] Compiled!"} assert_notification "window/logMessage", %{"message" => "[NextLS] Compiled!"} @@ -1061,19 +1004,21 @@ defmodule NextLSTest do event: %{ added: [], removed: [ - %{name: "proj_two", uri: "file://#{Path.join(cwd, "proj_two")}"} + %{name: "#{context.module}-proj_two", uri: "file://#{Path.join(cwd, "proj_two")}"} ] } } }) + message = "[NextLS] The runtime for #{context.module}-proj_two has successfully shutdown." + assert_notification "window/logMessage", %{ - "message" => "[NextLS] The runtime for proj_two has successfully shutdown." + "message" => ^message } end @tag root_paths: ["proj_one"] - test "can register for workspace/didChangedWatchedFiles", %{client: client} do + test "can register for workspace/didChangedWatchedFiles", %{client: client} = context do assert :ok == notify(client, %{method: "initialized", jsonrpc: "2.0", params: %{}}) assert_request(client, "client/registerCapability", fn params -> @@ -1099,17 +1044,17 @@ defmodule NextLSTest do nil end) - assert_notification "window/logMessage", %{"message" => "[NextLS] Runtime for folder proj_one is ready..."} + assert_is_ready(context, "proj_one") assert_notification "window/logMessage", %{"message" => "[NextLS] Compiled!"} end @tag root_paths: ["proj_one"] - test "can receive workspace/didChangeWatchedFiles notification", %{client: client, cwd: cwd} do + test "can receive workspace/didChangeWatchedFiles notification", %{client: client, cwd: cwd} = context do assert :ok == notify(client, %{method: "initialized", jsonrpc: "2.0", params: %{}}) assert_request(client, "client/registerCapability", fn _params -> nil end) - assert_notification "window/logMessage", %{"message" => "[NextLS] Runtime for folder proj_one is ready..."} + assert_is_ready(context, "proj_one") assert_notification "window/logMessage", %{"message" => "[NextLS] Compiled!"} notify(client, %{ @@ -1120,51 +1065,6 @@ defmodule NextLSTest do end end - defp with_lsp(%{tmp_dir: tmp_dir} = context) do - root_paths = - for path <- context[:root_paths] || [""] do - Path.absname(Path.join(tmp_dir, path)) - end - - tvisor = start_supervised!(Supervisor.child_spec(Task.Supervisor, id: :one)) - r_tvisor = start_supervised!(Supervisor.child_spec(Task.Supervisor, id: :two)) - rvisor = start_supervised!({DynamicSupervisor, [strategy: :one_for_one]}) - start_supervised!({Registry, [keys: :duplicate, name: Registry.NextLSTest.Registry]}) - extensions = [NextLS.ElixirExtension] - cache = start_supervised!(NextLS.DiagnosticCache) - - server = - server(NextLS, - task_supervisor: tvisor, - runtime_task_supervisor: r_tvisor, - dynamic_supervisor: rvisor, - registry: Registry.NextLSTest.Registry, - extensions: extensions, - cache: cache - ) - - Process.link(server.lsp) - - client = client(server) - - assert :ok == - request(client, %{ - method: "initialize", - id: 1, - jsonrpc: "2.0", - params: %{ - capabilities: %{ - workspace: %{ - workspaceFolders: true - } - }, - workspaceFolders: for(path <- root_paths, do: %{uri: "file://#{path}", name: Path.basename(path)}) - } - }) - - [server: server, client: client] - end - defp uri(path) when is_binary(path) do URI.to_string(%URI{ scheme: "file", diff --git a/test/support/utils.ex b/test/support/utils.ex index 99426482..d6b7f8a0 100644 --- a/test/support/utils.ex +++ b/test/support/utils.ex @@ -1,4 +1,9 @@ defmodule NextLS.Support.Utils do + @moduledoc false + import ExUnit.Assertions + import ExUnit.Callbacks + import GenLSP.Test + def mix_exs do """ defmodule Project.MixProject do @@ -28,4 +33,61 @@ defmodule NextLS.Support.Utils do end """ end + + def with_lsp(%{tmp_dir: tmp_dir} = context) do + root_paths = + for path <- context[:root_paths] || [""] do + Path.absname(Path.join(tmp_dir, path)) + end + + tvisor = start_supervised!(Supervisor.child_spec(Task.Supervisor, id: :one)) + r_tvisor = start_supervised!(Supervisor.child_spec(Task.Supervisor, id: :two)) + rvisor = start_supervised!({DynamicSupervisor, [strategy: :one_for_one]}) + start_supervised!({Registry, [keys: :duplicate, name: context.module]}) + extensions = [NextLS.ElixirExtension] + cache = start_supervised!(NextLS.DiagnosticCache) + + server = + server(NextLS, + task_supervisor: tvisor, + runtime_task_supervisor: r_tvisor, + dynamic_supervisor: rvisor, + registry: context.module, + extensions: extensions, + cache: cache + ) + + Process.link(server.lsp) + + client = client(server) + + assert :ok == + request(client, %{ + method: "initialize", + id: 1, + jsonrpc: "2.0", + params: %{ + capabilities: %{ + workspace: %{ + workspaceFolders: true + } + }, + workspaceFolders: + for( + path <- root_paths, + do: %{uri: "file://#{path}", name: "#{context.module}-#{Path.basename(path)}"} + ) + } + }) + + [server: server, client: client] + end + + defmacro assert_is_ready(context, name) do + quote do + message = "[NextLS] Runtime for folder #{unquote(context).module}-#{unquote(name)} is ready..." + + assert_notification "window/logMessage", %{"message" => ^message} + end + end end