Current section
Files
Jump to
Current section
Files
lib/feature_case.ex
defmodule FeatureCase do
defmacro __using__(options) do
quote do
use ExUnit.Case, unquote(options)
import FeatureCase
setup do
{:ok, _} = Agent.start(fn -> %{} end, name: FeatureCase.agent_name())
:ok
end
defp save(key, value) do
Agent.update(FeatureCase.agent_name(), fn state ->
Map.put(state, key, value)
end)
end
defp get(key) do
Agent.get(FeatureCase.agent_name(), fn state -> state[key] end)
end
def step(step) do
{label, args} = parse_step(step)
step(label, args)
end
defdelegate given_(step), to: __MODULE__, as: :step
defdelegate when_(step), to: __MODULE__, as: :step
defdelegate then_(step), to: __MODULE__, as: :step
end
end
def agent_name, do: {:global, {__MODULE__, :state, self()}}
defmacro defgiven(step, do: block), do: define_step(step, block)
defmacro defwhen(step, do: block), do: define_step(step, block)
defmacro defthen(step, do: block), do: define_step(step, block)
defp define_step(step, block) do
case FeatureCase.parse_step(step) do
{label, []} ->
quote do
def step(unquote(label), _values), do: unquote(block)
end
{label, var_names} ->
quote do
def step(unquote(label), values) do
var!(args) =
unquote(var_names)
|> Enum.map(&String.to_atom/1)
|> Enum.zip(values)
|> Enum.into(%{})
unquote(block)
end
end
end
end
def parse_step(step) do
with {vars, label_chunks} <-
step
|> String.split(~r/\{.*?\}/, include_captures: true, trim: true)
|> Enum.split_with(fn s -> s =~ ~r/\{.*\}/ end),
label <- label_chunks |> Enum.join("{}"),
args <- vars |> Enum.map(fn a -> String.replace(a, ~r/\{(.*)\}/, "\\1") end) do
{label, args}
end
end
end