Packages
finitomata
0.24.2
0.41.0
0.40.0
0.35.0
0.34.0
0.33.0
0.32.0
0.31.1
0.30.3
0.30.2
0.30.1
0.30.0
0.29.10
0.29.9
0.29.8
0.29.7
0.29.6
0.29.5
0.29.4
0.29.3
0.29.2
0.29.1
0.29.0
0.28.1
0.28.0
0.27.1
0.27.0
0.26.4
0.26.3
0.26.2
0.26.1
0.26.0
0.25.0
0.24.4
0.24.3
0.24.2
0.24.1
0.24.0
0.23.7
0.23.6
0.23.5
0.23.4
0.23.3
0.23.2
0.23.1
0.23.0
0.22.1
0.22.0
0.21.4
0.21.3
0.21.2
0.21.1
0.21.0
0.20.2
0.20.1
0.20.0
0.19.6
0.19.5
0.19.4
0.19.3
0.19.2
0.19.1
0.19.0
0.18.4
0.18.3
0.18.2
0.18.1
0.18.0
0.17.1
0.17.0
0.16.0
0.15.1
0.15.0
0.14.6
0.14.5
0.14.4
0.14.3
0.14.2
0.14.1
0.14.0
0.13.0
0.12.1
0.12.0
0.11.3
0.11.2
0.11.1
0.11.0
0.10.0
0.9.1
0.9.0
0.8.2
0.8.1
0.8.0
0.7.2
0.7.1
0.7.0
0.6.3
0.6.2
0.6.1
0.6.0
0.5.2
0.5.1
0.5.0
0.4.0
0.3.0
0.2.0
0.1.1
0.1.0
The FSM implementation generated from PlantUML textual representation.
Current section
Files
Jump to
Current section
Files
lib/mix/tasks/finitomata_generate_test.ex
defmodule Mix.Tasks.Finitomata.Generate.Test do
@shortdoc "Generates the test scaffold for the `Finitomata` instance"
@moduledoc """
Mix task to generate the `Finitomata.ExUnit` test scaffold.
"""
use Mix.Task
@finitomata_tests_path "test/finitomata"
@impl Mix.Task
@doc false
def run(args) do
Mix.Task.run("compile")
Finitomata.Mix.load_app()
{opts, _pass_thru, []} =
OptionParser.parse(args, strict: [module: :string, file: :string, dir: :string])
module = Keyword.fetch!(opts, :module)
test_dir = Keyword.get(opts, :dir, @finitomata_tests_path)
module = Module.concat([module])
test_file =
Keyword.get(
opts,
:file,
module |> Module.split() |> List.last() |> Macro.underscore() |> Kernel.<>("_test.exs")
)
if module?(module) do
paths =
module.fsm()
|> Finitomata.Transition.paths()
|> Enum.map(&{&1, transform_path(module.__config__(:auto_terminate), &1)})
test_module = Module.concat([module, "Test"])
target_file = Path.join(test_dir, test_file)
Mix.Generator.copy_template(
Path.expand("test_template.eex", __DIR__),
target_file,
module: module,
test_module: test_module,
paths: paths
)
File.write!(target_file, Code.format_file!(target_file))
Mix.shell().info([
[:bright, :blue, "* #{inspect(test_module)}", :reset],
" has been created for ",
[:blue, inspect(module), :reset],
", do not forget to:\n",
" ▹ amend assertions to fit your business logic\n",
" ▹ add `listener: :mox` (or actual listener) to `Finitomata` declaration"
])
end
end
@doc false
defp transform_path(auto_terminate?, %Finitomata.Transition.Path{path: path}),
do: transform_path(auto_terminate?, path)
defp transform_path(auto_terminate?, path) do
path
|> Enum.reduce([], fn
{event, state}, [] ->
[[{event, state}]]
{event, state}, [curr | rest] ->
if event |> to_string() |> String.ends_with?("!"),
do: [curr ++ [{event, state}] | rest],
else: [[{event, state}], curr | rest]
end)
|> then(&maybe_join_ending(auto_terminate?, &1))
|> Enum.reverse()
end
defp maybe_join_ending(false, path), do: path
defp maybe_join_ending(true, [[{:__end__, :*}] = last, prev | rest]), do: [prev ++ last | rest]
defp module?(module) do
with {:module, ^module} <- Code.ensure_compiled(module),
true <- function_exported?(module, :fsm, 0) do
true
else
_ ->
Mix.shell().error([
:yellow,
"* #{inspect(module)}",
:reset,
" is not found or is not a `Finitomata` instance"
])
false
end
end
end