Packages
mneme
0.9.0-alpha.0
0.10.2
0.10.1
0.10.0
0.9.4
0.9.3
0.9.2
0.9.1
0.9.0
0.9.0-alpha.1
0.9.0-alpha.0
0.8.2
0.8.1
0.8.0
0.7.0
0.6.1
0.6.0
0.5.1
0.5.0
0.4.3
0.4.2
0.4.1
0.4.0
0.3.5
0.3.4
0.3.3
0.3.2
0.3.1
0.3.0
0.3.0-rc.1
0.3.0-rc.0
0.2.7
0.2.6
0.2.5
0.2.4
0.2.3
0.2.2
0.2.1
0.2.0
0.1.6
0.1.5
0.1.4
0.1.3
0.1.2
0.1.1
0.1.0
0.0.5
0.0.4
0.0.3
0.0.2
0.0.1
Snapshot testing tool using familiar assertions
Current section
Files
Jump to
Current section
Files
lib/mneme/watch/test_runner.ex
defmodule Mneme.Watch.TestRunner do
@moduledoc false
use GenServer
defstruct [:cli_args, :testing, paths: [], about_to_save: []]
@doc false
def start_link(opts) do
GenServer.start_link(__MODULE__, opts, name: __MODULE__)
end
@doc """
Notify the test runner of files about to be saved so that they can
be ignored in the next files changed event.
"""
def notify_about_to_save(paths) when is_list(paths) do
case GenServer.whereis(__MODULE__) do
nil -> :ok
test_runner -> GenServer.cast(test_runner, {:notify_about_to_save, paths})
end
end
@impl GenServer
def init(opts) do
Code.compiler_options(ignore_module_conflict: true)
:ok = Mneme.Watch.ElixirFiles.watch!()
state = struct(__MODULE__, Keyword.validate!(opts, [:cli_args]))
{:ok, state, {:continue, :force_schedule_tests}}
end
@impl GenServer
def handle_continue(:force_schedule_tests, state) do
{:noreply, %{state | testing: run_tests_async(state.cli_args)}}
end
def handle_continue(:maybe_schedule_tests, %{testing: %Task{}} = state) do
{:noreply, state}
end
def handle_continue(:maybe_schedule_tests, %{paths: []} = state) do
{:noreply, state}
end
def handle_continue(:maybe_schedule_tests, state) do
IO.write("\r\n")
state.paths
|> Enum.uniq()
|> Enum.sort()
|> Enum.each(fn path ->
Owl.IO.puts([Owl.Data.tag("reloading: ", :cyan), path])
end)
IO.write("\n")
state = %{state | testing: run_tests_async(state.cli_args), paths: []}
{:noreply, state}
end
@impl GenServer
def handle_info({:files_changed, paths}, state) do
relevant_paths = paths -- state.about_to_save
state =
state
|> Map.put(:about_to_save, [])
|> Map.update!(:paths, &(relevant_paths ++ &1))
if state.testing do
Mneme.Server.skip_all()
end
{:noreply, state, {:continue, :maybe_schedule_tests}}
end
def handle_info({ref, _}, %{testing: %Task{ref: ref}} = state) do
{:noreply, %{state | testing: nil}, {:continue, :maybe_schedule_tests}}
end
def handle_info({:DOWN, _ref, :process, _pid, _reason}, state) do
{:noreply, state}
end
@impl GenServer
def handle_cast({:notify_about_to_save, paths}, state) do
{:noreply, put_in(state.about_to_save, paths)}
end
defp run_tests_async(cli_args) do
Task.async(fn -> run_tests(cli_args) end)
end
defp run_tests(cli_args) do
Code.unrequire_files(Code.required_files())
recompile()
Mix.Task.reenable(:test)
Mix.Task.run(:test, cli_args)
end
@dialyzer {:nowarn_function, recompile: 0}
defp recompile do
IEx.Helpers.recompile()
end
end