lib/runbox/scenario.ex

defmodule Runbox.Scenario do
  @moduledoc """
  Holds information about scenario.

  Instances of this struct are created internally by Runbox. It is documented only because
  other public APIs may optionally consume this struct.
  """
  alias Runbox.Scenario.Type

  defstruct [:manifest, :opts, :templates]

  @type t :: %__MODULE__{
          manifest: Runbox.Scenario.Manifest.t(),
          opts: map(),
          templates: [Runbox.ScenarioTemplate.t()]
        }

  @type component_def :: %{id: term(), mod: module(), fun: atom(), args: map}

  @spec manifest_module?(module()) :: boolean()
  def manifest_module?(module) do
    behaviours =
      :attributes
      |> module.module_info()
      |> Keyword.get_values(:behaviour)
      |> List.flatten()

    Enum.member?(behaviours, Runbox.Scenario.Manifest)
  end

  @spec template_module?(module(), module()) :: boolean()
  def template_module?(module, manifest_module) do
    module |> Module.split() |> prefixed?(scenario_prefix(manifest_module))
  end

  @stage Type.stage()
  @simple Type.simple()
  @spec get_impl_for(Type.t()) :: %{template_inspector: module()}
  def get_impl_for(@stage) do
    %{template_inspector: Runbox.Scenario.Template.StageBased}
  end

  def get_impl_for(@simple) do
    %{template_inspector: Runbox.Scenario.Template.Simple}
  end

  defp scenario_prefix(manifest_module) do
    Module.split(manifest_module)
  end

  defp prefixed?(module_parts, prefix) do
    List.starts_with?(module_parts, prefix)
  end
end