mirror of
https://github.com/ash-project/ash_state_machine.git
synced 2024-09-17 03:43:11 +12:00
chore: fsm -> state_machine, event -> transition
This commit is contained in:
parent
6d0fa817a2
commit
06871a9977
15 changed files with 120 additions and 112 deletions
|
@ -1,8 +1,8 @@
|
|||
spark_locals_without_parens = [
|
||||
default_initial_state: 1,
|
||||
deprecated_states: 1,
|
||||
event: 1,
|
||||
event: 2,
|
||||
transition: 1,
|
||||
transition: 2,
|
||||
from: 1,
|
||||
initial_states: 1,
|
||||
state_attribute: 1,
|
||||
|
|
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -20,7 +20,7 @@ erl_crash.dump
|
|||
*.ez
|
||||
|
||||
# Ignore package tarball (built via "mix hex.build").
|
||||
ash_fsm-*.tar
|
||||
ash_state_machine-*.tar
|
||||
|
||||
# Temporary files, for example, from tests.
|
||||
/tmp/
|
||||
|
|
|
@ -1,21 +1,21 @@
|
|||
# AshFsm
|
||||
# AshStateMachine
|
||||
|
||||
**TODO: Add description**
|
||||
|
||||
## Installation
|
||||
|
||||
If [available in Hex](https://hex.pm/docs/publish), the package can be installed
|
||||
by adding `ash_fsm` to your list of dependencies in `mix.exs`:
|
||||
by adding `ash_state_machine` to your list of dependencies in `mix.exs`:
|
||||
|
||||
```elixir
|
||||
def deps do
|
||||
[
|
||||
{:ash_fsm, "~> 0.1.0"}
|
||||
{:ash_state_machine, "~> 0.1.0"}
|
||||
]
|
||||
end
|
||||
```
|
||||
|
||||
Documentation can be generated with [ExDoc](https://github.com/elixir-lang/ex_doc)
|
||||
and published on [HexDocs](https://hexdocs.pm). Once published, the docs can
|
||||
be found at <https://hexdocs.pm/ash_fsm>.
|
||||
be found at <https://hexdocs.pm/ash_state_machine>.
|
||||
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
defmodule AshFsm do
|
||||
defmodule AshStateMachine do
|
||||
@moduledoc """
|
||||
Documentation for `AshFsm`.
|
||||
Documentation for `AshStateMachine`.
|
||||
"""
|
||||
|
||||
defmodule Event do
|
||||
defmodule Transition do
|
||||
@moduledoc """
|
||||
The configuration for an event.
|
||||
The configuration for an transition.
|
||||
"""
|
||||
@type t :: %__MODULE__{
|
||||
action: atom,
|
||||
|
@ -16,15 +16,15 @@ defmodule AshFsm do
|
|||
defstruct [:action, :from, :to]
|
||||
end
|
||||
|
||||
@event %Spark.Dsl.Entity{
|
||||
name: :event,
|
||||
target: Event,
|
||||
@transition %Spark.Dsl.Entity{
|
||||
name: :transition,
|
||||
target: Transition,
|
||||
args: [:action],
|
||||
identifier: :action,
|
||||
schema: [
|
||||
action: [
|
||||
type: :atom,
|
||||
doc: "The corresponding action that is invoked for the event."
|
||||
doc: "The corresponding action that is invoked for the transition."
|
||||
],
|
||||
from: [
|
||||
type: {:or, [{:list, :atom}, :atom]},
|
||||
|
@ -39,23 +39,23 @@ defmodule AshFsm do
|
|||
]
|
||||
}
|
||||
|
||||
@events %Spark.Dsl.Section{
|
||||
name: :events,
|
||||
@transitions %Spark.Dsl.Section{
|
||||
name: :transitions,
|
||||
entities: [
|
||||
@event
|
||||
@transition
|
||||
]
|
||||
}
|
||||
|
||||
@fsm %Spark.Dsl.Section{
|
||||
name: :fsm,
|
||||
@state_machine %Spark.Dsl.Section{
|
||||
name: :state_machine,
|
||||
schema: [
|
||||
deprecated_states: [
|
||||
type: {:list, :atom},
|
||||
doc: """
|
||||
A list of states that have been deprecated.
|
||||
The list of states is derived from the events normally.
|
||||
The list of states is derived from the transitions normally.
|
||||
Use this option to express that certain types should still
|
||||
be included even though no events go to/from that state anymore.
|
||||
be included even though no transitions go to/from that state anymore.
|
||||
"""
|
||||
],
|
||||
state_attribute: [
|
||||
|
@ -74,44 +74,46 @@ defmodule AshFsm do
|
|||
]
|
||||
],
|
||||
sections: [
|
||||
@events
|
||||
@transitions
|
||||
]
|
||||
}
|
||||
|
||||
use Spark.Dsl.Extension,
|
||||
sections: [@fsm],
|
||||
sections: [@state_machine],
|
||||
transformers: [
|
||||
AshFsm.Transformers.FillInEventDefaults,
|
||||
AshFsm.Transformers.AddState,
|
||||
AshFsm.Transformers.EnsureStateSelected
|
||||
AshStateMachine.Transformers.FillInTransitionDefaults,
|
||||
AshStateMachine.Transformers.AddState,
|
||||
AshStateMachine.Transformers.EnsureStateSelected
|
||||
],
|
||||
verifiers: [
|
||||
AshFsm.Verifiers.VerifyEventActions,
|
||||
AshFsm.Verifiers.VerifyDefaultInitialState
|
||||
AshStateMachine.Verifiers.VerifyTransitionActions,
|
||||
AshStateMachine.Verifiers.VerifyDefaultInitialState
|
||||
],
|
||||
imports: [
|
||||
AshFsm.BuiltinChanges
|
||||
AshStateMachine.BuiltinChanges
|
||||
]
|
||||
|
||||
def transition_state(%{action_type: :update} = changeset, target) do
|
||||
events = AshFsm.Info.fsm_events(changeset.resource, changeset.action.name)
|
||||
attribute = AshFsm.Info.fsm_state_attribute!(changeset.resource)
|
||||
transitions =
|
||||
AshStateMachine.Info.state_machine_transitions(changeset.resource, changeset.action.name)
|
||||
|
||||
attribute = AshStateMachine.Info.state_machine_state_attribute!(changeset.resource)
|
||||
old_state = Map.get(changeset.data, attribute)
|
||||
|
||||
case Enum.find(events, fn event ->
|
||||
old_state in List.wrap(event.from) and target in List.wrap(event.to)
|
||||
case Enum.find(transitions, fn transition ->
|
||||
old_state in List.wrap(transition.from) and target in List.wrap(transition.to)
|
||||
end) do
|
||||
nil ->
|
||||
Ash.Changeset.add_error(
|
||||
changeset,
|
||||
AshFsm.Errors.NoMatchingEvent.exception(
|
||||
AshStateMachine.Errors.NoMatchingTransition.exception(
|
||||
from: old_state,
|
||||
target: target,
|
||||
action: changeset.action.name
|
||||
)
|
||||
)
|
||||
|
||||
_event ->
|
||||
_transition ->
|
||||
Ash.Changeset.force_change_attribute(changeset, attribute, target)
|
||||
end
|
||||
end
|
|
@ -1,12 +1,12 @@
|
|||
defmodule AshFsm.BuiltinChanges do
|
||||
defmodule AshStateMachine.BuiltinChanges do
|
||||
@moduledoc """
|
||||
Changes for working with AshFsm resources.
|
||||
Changes for working with AshStateMachine resources.
|
||||
"""
|
||||
|
||||
@doc """
|
||||
Changes the state to the target state, validating the transition
|
||||
"""
|
||||
def transition_state(target) do
|
||||
{AshFsm.BuiltinChanges.TransitionState, target: target}
|
||||
{AshStateMachine.BuiltinChanges.TransitionState, target: target}
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
defmodule AshFsm.BuiltinChanges.TransitionState do
|
||||
defmodule AshStateMachine.BuiltinChanges.TransitionState do
|
||||
use Ash.Resource.Change
|
||||
|
||||
def change(changeset, opts, _) do
|
||||
AshFsm.transition_state(changeset, opts[:target])
|
||||
AshStateMachine.transition_state(changeset, opts[:target])
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
defmodule AshFsm.Errors.NoMatchingEvent do
|
||||
@moduledoc "Used when a state change occurs in an action with no matching event"
|
||||
defmodule AshStateMachine.Errors.NoMatchingTransition do
|
||||
@moduledoc "Used when a state change occurs in an action with no matching transition"
|
||||
use Ash.Error.Exception
|
||||
|
||||
def_ash_error([:action, :target, :old_state], class: :invalid)
|
||||
|
@ -7,11 +7,11 @@ defmodule AshFsm.Errors.NoMatchingEvent do
|
|||
defimpl Ash.ErrorKind do
|
||||
def id(_), do: Ash.UUID.generate()
|
||||
|
||||
def code(_), do: "no_matching_event"
|
||||
def code(_), do: "no_matching_transition"
|
||||
|
||||
def message(error) do
|
||||
"""
|
||||
Attempted to change state from #{error.old_state} to #{error.target} in action #{error.action}, but no matching event was configured.
|
||||
Attempted to change state from #{error.old_state} to #{error.target} in action #{error.action}, but no matching transition was configured.
|
||||
"""
|
||||
end
|
||||
end
|
||||
|
|
17
lib/info.ex
17
lib/info.ex
|
@ -1,15 +1,16 @@
|
|||
defmodule AshFsm.Info do
|
||||
use Spark.InfoGenerator, extension: AshFsm, sections: [:fsm]
|
||||
defmodule AshStateMachine.Info do
|
||||
use Spark.InfoGenerator, extension: AshStateMachine, sections: [:state_machine]
|
||||
|
||||
@spec fsm_events(Ash.Resource.record() | map(), name :: atom) :: list(AshFsm.Event.t())
|
||||
def fsm_events(resource_or_dsl, name) do
|
||||
@spec state_machine_transitions(Ash.Resource.record() | map(), name :: atom) ::
|
||||
list(AshStateMachine.Transition.t())
|
||||
def state_machine_transitions(resource_or_dsl, name) do
|
||||
resource_or_dsl
|
||||
|> fsm_events()
|
||||
|> state_machine_transitions()
|
||||
|> Enum.filter(&(&1.action == name))
|
||||
end
|
||||
|
||||
@spec fsm_all_states(Ash.Resource.record() | map()) :: list(atom)
|
||||
def fsm_all_states(resource_or_dsl) do
|
||||
Spark.Dsl.Extension.get_persisted(resource_or_dsl, :all_fsm_states, [])
|
||||
@spec state_machine_all_states(Ash.Resource.record() | map()) :: list(atom)
|
||||
def state_machine_all_states(resource_or_dsl) do
|
||||
Spark.Dsl.Extension.get_persisted(resource_or_dsl, :all_state_machine_states, [])
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
defmodule AshFsm.Transformers.AddState do
|
||||
defmodule AshStateMachine.Transformers.AddState do
|
||||
use Spark.Dsl.Transformer
|
||||
alias Spark.Dsl.Transformer
|
||||
|
||||
|
@ -6,19 +6,21 @@ defmodule AshFsm.Transformers.AddState do
|
|||
|
||||
def transform(dsl_state) do
|
||||
deprecated_states =
|
||||
case AshFsm.Info.fsm_deprecated_states(dsl_state) do
|
||||
case AshStateMachine.Info.state_machine_deprecated_states(dsl_state) do
|
||||
{:ok, value} -> value || []
|
||||
_ -> []
|
||||
end
|
||||
|
||||
all_states = Enum.uniq(AshFsm.Info.fsm_all_states(dsl_state) ++ deprecated_states)
|
||||
attribute_name = AshFsm.Info.fsm_state_attribute!(dsl_state)
|
||||
all_states =
|
||||
Enum.uniq(AshStateMachine.Info.state_machine_all_states(dsl_state) ++ deprecated_states)
|
||||
|
||||
attribute_name = AshStateMachine.Info.state_machine_state_attribute!(dsl_state)
|
||||
module = Transformer.get_persisted(dsl_state, :module)
|
||||
|
||||
case Ash.Resource.Info.attribute(dsl_state, attribute_name) do
|
||||
nil ->
|
||||
default =
|
||||
case AshFsm.Info.fsm_default_initial_state(dsl_state) do
|
||||
case AshStateMachine.Info.state_machine_default_initial_state(dsl_state) do
|
||||
{:ok, value} ->
|
||||
value
|
||||
|
||||
|
@ -42,7 +44,7 @@ defmodule AshFsm.Transformers.AddState do
|
|||
{attribute.type, attribute.constraints}
|
||||
end
|
||||
|
||||
case AshFsm.Info.fsm_default_initial_state(dsl_state) do
|
||||
case AshStateMachine.Info.state_machine_default_initial_state(dsl_state) do
|
||||
{:ok, default} ->
|
||||
if attribute.default != default do
|
||||
raise Spark.Error.DslError,
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
defmodule AshFsm.Transformers.EnsureStateSelected do
|
||||
defmodule AshStateMachine.Transformers.EnsureStateSelected do
|
||||
use Spark.Dsl.Transformer
|
||||
|
||||
def transform(dsl_state) do
|
||||
|
@ -6,7 +6,7 @@ defmodule AshFsm.Transformers.EnsureStateSelected do
|
|||
dsl_state,
|
||||
{Ash.Resource.Preparation.Build,
|
||||
ensure_selected: [
|
||||
AshFsm.Info.fsm_state_attribute(dsl_state)
|
||||
AshStateMachine.Info.state_machine_state_attribute(dsl_state)
|
||||
]}
|
||||
)
|
||||
end
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
defmodule AshFsm.Transformers.FillInEventDefaults do
|
||||
defmodule AshStateMachine.Transformers.FillInTransitionDefaults do
|
||||
use Spark.Dsl.Transformer
|
||||
alias Spark.Dsl.Transformer
|
||||
@moduledoc false
|
||||
|
||||
def transform(dsl_state) do
|
||||
initial_states =
|
||||
case AshFsm.Info.fsm_initial_states(dsl_state) do
|
||||
case AshStateMachine.Info.state_machine_initial_states(dsl_state) do
|
||||
{:ok, value} -> List.wrap(value)
|
||||
_ -> []
|
||||
end
|
||||
|
@ -13,7 +13,7 @@ defmodule AshFsm.Transformers.FillInEventDefaults do
|
|||
initial_states =
|
||||
case initial_states do
|
||||
[] ->
|
||||
case AshFsm.Info.fsm_default_initial_state(dsl_state) do
|
||||
case AshStateMachine.Info.state_machine_default_initial_state(dsl_state) do
|
||||
{:ok, value} when not is_nil(value) ->
|
||||
[value]
|
||||
|
||||
|
@ -25,36 +25,36 @@ defmodule AshFsm.Transformers.FillInEventDefaults do
|
|||
initial_states
|
||||
end
|
||||
|
||||
events =
|
||||
transitions =
|
||||
dsl_state
|
||||
|> AshFsm.Info.fsm_events()
|
||||
|> AshStateMachine.Info.state_machine_transitions()
|
||||
|
||||
all_states =
|
||||
events
|
||||
|> Enum.flat_map(fn event ->
|
||||
List.wrap(event.from) ++ List.wrap(event.to)
|
||||
transitions
|
||||
|> Enum.flat_map(fn transition ->
|
||||
List.wrap(transition.from) ++ List.wrap(transition.to)
|
||||
end)
|
||||
|> Enum.concat(List.wrap(initial_states))
|
||||
|> Enum.uniq()
|
||||
|
||||
dsl_state =
|
||||
case AshFsm.Info.fsm_initial_states(dsl_state) do
|
||||
case AshStateMachine.Info.state_machine_initial_states(dsl_state) do
|
||||
{:ok, value} when not is_nil(value) and value != [] ->
|
||||
dsl_state
|
||||
|
||||
_ ->
|
||||
Transformer.set_option(dsl_state, [:fsm], :initial_states, all_states)
|
||||
Transformer.set_option(dsl_state, [:state_machine], :initial_states, all_states)
|
||||
end
|
||||
|
||||
{:ok,
|
||||
events
|
||||
|> Enum.reduce(dsl_state, fn event, dsl_state ->
|
||||
Transformer.replace_entity(dsl_state, [:fsm], %{
|
||||
event
|
||||
| from: event.from || all_states,
|
||||
to: event.to || all_states
|
||||
transitions
|
||||
|> Enum.reduce(dsl_state, fn transition, dsl_state ->
|
||||
Transformer.replace_entity(dsl_state, [:state_machine], %{
|
||||
transition
|
||||
| from: transition.from || all_states,
|
||||
to: transition.to || all_states
|
||||
})
|
||||
end)
|
||||
|> Transformer.persist(:all_fsm_states, all_states)}
|
||||
|> Transformer.persist(:all_state_machine_states, all_states)}
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,15 +1,18 @@
|
|||
defmodule AshFsm.Verifiers.VerifyDefaultInitialState do
|
||||
defmodule AshStateMachine.Verifiers.VerifyDefaultInitialState do
|
||||
use Spark.Dsl.Verifier
|
||||
|
||||
def verify(dsl_state) do
|
||||
module = Spark.Dsl.Verifier.get_persisted(dsl_state, :module)
|
||||
|
||||
attribute =
|
||||
Ash.Resource.Info.attribute(dsl_state, AshFsm.Info.fsm_state_attribute!(dsl_state))
|
||||
Ash.Resource.Info.attribute(
|
||||
dsl_state,
|
||||
AshStateMachine.Info.state_machine_state_attribute!(dsl_state)
|
||||
)
|
||||
|
||||
case AshFsm.Info.fsm_default_initial_state(dsl_state) do
|
||||
case AshStateMachine.Info.state_machine_default_initial_state(dsl_state) do
|
||||
{:ok, initial} when not is_nil(initial) ->
|
||||
initial_states = AshFsm.Info.fsm_initial_states!(dsl_state)
|
||||
initial_states = AshStateMachine.Info.state_machine_initial_states!(dsl_state)
|
||||
|
||||
unless initial in initial_states do
|
||||
raise Spark.Error.DslError,
|
||||
|
|
|
@ -1,18 +1,18 @@
|
|||
defmodule AshFsm.Verifiers.VerifyEventActions do
|
||||
defmodule AshStateMachine.Verifiers.VerifyTransitionActions do
|
||||
use Spark.Dsl.Verifier
|
||||
|
||||
def verify(dsl_state) do
|
||||
dsl_state
|
||||
|> AshFsm.Info.fsm_events()
|
||||
|> Enum.each(fn event ->
|
||||
action = Ash.Resource.Info.action(dsl_state, event.action)
|
||||
|> AshStateMachine.Info.state_machine_transitions()
|
||||
|> Enum.each(fn transition ->
|
||||
action = Ash.Resource.Info.action(dsl_state, transition.action)
|
||||
|
||||
unless action && action.type == :update do
|
||||
raise Spark.Error.DslError,
|
||||
module: Spark.Dsl.Verifier.get_persisted(dsl_state, :module),
|
||||
path: [:fsm, :events, :event, event.action],
|
||||
path: [:state_machine, :transitions, :transition, transition.action],
|
||||
message: """
|
||||
Event configured with action `:#{event.action}` but no such update action is defined.
|
||||
Transition configured with action `:#{transition.action}` but no such update action is defined.
|
||||
"""
|
||||
end
|
||||
end)
|
||||
|
|
22
mix.exs
22
mix.exs
|
@ -1,4 +1,4 @@
|
|||
defmodule AshFsm.MixProject do
|
||||
defmodule AshStateMachine.MixProject do
|
||||
use Mix.Project
|
||||
|
||||
@version "0.1.0"
|
||||
|
@ -9,7 +9,7 @@ defmodule AshFsm.MixProject do
|
|||
|
||||
def project do
|
||||
[
|
||||
app: :ash_fsm,
|
||||
app: :ash_state_machine,
|
||||
version: @version,
|
||||
elixir: "~> 1.14",
|
||||
start_permanent: Mix.env() == :prod,
|
||||
|
@ -20,19 +20,19 @@ defmodule AshFsm.MixProject do
|
|||
dialyzer: [plt_add_apps: [:ash]],
|
||||
docs: docs(),
|
||||
description: @description,
|
||||
source_url: "https://github.com/ash-project/ash_fsm",
|
||||
homepage_url: "https://github.com/ash-project/ash_fsm"
|
||||
source_url: "https://github.com/ash-project/ash_state_machine",
|
||||
homepage_url: "https://github.com/ash-project/ash_state_machine"
|
||||
]
|
||||
end
|
||||
|
||||
defp package do
|
||||
[
|
||||
name: :ash_fsm,
|
||||
name: :ash_state_machine,
|
||||
licenses: ["MIT"],
|
||||
files: ~w(lib .formatter.exs mix.exs README* LICENSE*
|
||||
CHANGELOG* documentation),
|
||||
links: %{
|
||||
GitHub: "https://github.com/ash-project/ash_fsm"
|
||||
GitHub: "https://github.com/ash-project/ash_state_machine"
|
||||
}
|
||||
]
|
||||
end
|
||||
|
@ -87,17 +87,17 @@ defmodule AshFsm.MixProject do
|
|||
|
||||
defp docs do
|
||||
[
|
||||
main: "AshFsm",
|
||||
main: "AshStateMachine",
|
||||
source_ref: "v#{@version}",
|
||||
logo: "logos/small-logo.png",
|
||||
extra_section: "GUIDES",
|
||||
spark: [
|
||||
extensions: [
|
||||
%{
|
||||
module: AshFsm,
|
||||
name: "AshFsm",
|
||||
module: AshStateMachine,
|
||||
name: "AshStateMachine",
|
||||
target: "Ash.Resource",
|
||||
type: "Fsm Resource"
|
||||
type: "StateMachine Resource"
|
||||
},
|
||||
%{
|
||||
module: AshGraphql.Api,
|
||||
|
@ -147,7 +147,7 @@ defmodule AshFsm.MixProject do
|
|||
sobelow: "sobelow --skip",
|
||||
credo: "credo --strict",
|
||||
docs: ["docs", "ash.replace_doc_links"],
|
||||
"spark.formatter": "spark.formatter --extensions AshFsm"
|
||||
"spark.formatter": "spark.formatter --extensions AshStateMachine"
|
||||
]
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,18 +1,18 @@
|
|||
defmodule AshFsmTest do
|
||||
defmodule AshStateMachineTest do
|
||||
use ExUnit.Case
|
||||
doctest AshFsm
|
||||
doctest AshStateMachine
|
||||
|
||||
defmodule ThreeStates do
|
||||
use Ash.Resource,
|
||||
data_layer: Ash.DataLayer.Ets,
|
||||
extensions: [AshFsm]
|
||||
extensions: [AshStateMachine]
|
||||
|
||||
fsm do
|
||||
state_machine do
|
||||
default_initial_state :pending
|
||||
|
||||
events do
|
||||
event :begin, from: :pending, to: :executing
|
||||
event :complete, from: :executing, to: :complete
|
||||
transitions do
|
||||
transition(:begin, from: :pending, to: :executing)
|
||||
transition(:complete, from: :executing, to: :complete)
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -37,7 +37,7 @@ defmodule AshFsmTest do
|
|||
end
|
||||
|
||||
code_interface do
|
||||
define_for AshFsmTest.Api
|
||||
define_for AshStateMachineTest.Api
|
||||
define :create
|
||||
define :begin
|
||||
define :complete
|
||||
|
@ -54,7 +54,7 @@ defmodule AshFsmTest do
|
|||
|
||||
describe "transformers" do
|
||||
test "infers all states" do
|
||||
assert Enum.sort(AshFsm.Info.fsm_all_states(ThreeStates)) ==
|
||||
assert Enum.sort(AshStateMachine.Info.state_machine_all_states(ThreeStates)) ==
|
||||
Enum.sort([:executing, :pending, :complete])
|
||||
end
|
||||
end
|
||||
|
@ -65,15 +65,15 @@ defmodule AshFsmTest do
|
|||
end
|
||||
|
||||
test "it transitions to the appropriate state" do
|
||||
fsm = ThreeStates.create!()
|
||||
state_machine = ThreeStates.create!()
|
||||
|
||||
assert ThreeStates.begin!(fsm).state == :executing
|
||||
assert ThreeStates.begin!(state_machine).state == :executing
|
||||
end
|
||||
|
||||
test "it transitions again to the appropriate state" do
|
||||
fsm = ThreeStates.create!() |> ThreeStates.begin!()
|
||||
state_machine = ThreeStates.create!() |> ThreeStates.begin!()
|
||||
|
||||
assert ThreeStates.complete!(fsm).state == :complete
|
||||
assert ThreeStates.complete!(state_machine).state == :complete
|
||||
end
|
||||
end
|
||||
end
|
Loading…
Reference in a new issue