Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
83 changes: 9 additions & 74 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,86 +22,32 @@ def current_time():

@pytest.fixture()
def campaign_machine():
"Define a new class for each test"
from statemachine import State
from statemachine import StateChart

class CampaignMachine(StateChart):
"A workflow machine"

draft = State(initial=True)
producing = State("Being produced")
closed = State(final=True)

add_job = draft.to(draft) | producing.to(producing)
produce = draft.to(producing)
deliver = producing.to(closed)
from tests.machines.workflow.campaign_machine import CampaignMachine

return CampaignMachine


@pytest.fixture()
def campaign_machine_with_validator():
"Define a new class for each test"
from statemachine import State
from statemachine import StateChart

class CampaignMachine(StateChart):
"A workflow machine"

draft = State(initial=True)
producing = State("Being produced")
closed = State(final=True)

add_job = draft.to(draft) | producing.to(producing)
produce = draft.to(producing, validators="can_produce")
deliver = producing.to(closed)
from tests.machines.workflow.campaign_machine_with_validator import (
CampaignMachineWithValidator,
)

def can_produce(*args, **kwargs):
if "goods" not in kwargs:
raise LookupError("Goods not found.")

return CampaignMachine
return CampaignMachineWithValidator


@pytest.fixture()
def campaign_machine_with_final_state():
"Define a new class for each test"
from statemachine import State
from statemachine import StateChart

class CampaignMachine(StateChart):
"A workflow machine"

draft = State(initial=True)
producing = State("Being produced")
closed = State(final=True)

add_job = draft.to(draft) | producing.to(producing)
produce = draft.to(producing)
deliver = producing.to(closed)
from tests.machines.workflow.campaign_machine import CampaignMachine

return CampaignMachine


@pytest.fixture()
def campaign_machine_with_values():
"Define a new class for each test"
from statemachine import State
from statemachine import StateChart

class CampaignMachineWithKeys(StateChart):
"A workflow machine"

draft = State(initial=True, value=1)
producing = State("Being produced", value=2)
closed = State(value=3, final=True)

add_job = draft.to(draft) | producing.to(producing)
produce = draft.to(producing)
deliver = producing.to(closed)
from tests.machines.workflow.campaign_machine_with_values import CampaignMachineWithValues

return CampaignMachineWithKeys
return CampaignMachineWithValues


@pytest.fixture()
Expand Down Expand Up @@ -153,18 +99,7 @@ def classic_traffic_light_machine_allow_event(classic_traffic_light_machine):

@pytest.fixture()
def reverse_traffic_light_machine():
from statemachine import State
from statemachine import StateChart

class ReverseTrafficLightMachine(StateChart):
"A traffic light machine"

green = State(initial=True)
yellow = State()
red = State()

stop = red.from_(yellow, green, red)
cycle = green.from_(red) | yellow.from_(green) | red.from_(yellow) | red.from_.itself()
from tests.machines.workflow.reverse_traffic_light import ReverseTrafficLightMachine

return ReverseTrafficLightMachine

Expand Down
Empty file.
25 changes: 25 additions & 0 deletions tests/machines/compound/middle_earth_journey.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
from statemachine import State
from statemachine import StateChart


class MiddleEarthJourney(StateChart):
class rivendell(State.Compound):
council = State(initial=True)
preparing = State()

get_ready = council.to(preparing)

class moria(State.Compound):
gates = State(initial=True)
bridge = State(final=True)

cross = gates.to(bridge)

class lothlorien(State.Compound):
mirror = State(initial=True)
departure = State(final=True)

leave = mirror.to(departure)

march_to_moria = rivendell.to(moria)
march_to_lorien = moria.to(lothlorien)
18 changes: 18 additions & 0 deletions tests/machines/compound/middle_earth_journey_two_compounds.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
from statemachine import State
from statemachine import StateChart


class MiddleEarthJourneyTwoCompounds(StateChart):
class rivendell(State.Compound):
council = State(initial=True)
preparing = State()

get_ready = council.to(preparing)

class moria(State.Compound):
gates = State(initial=True)
bridge = State(final=True)

cross = gates.to(bridge)

march_to_moria = rivendell.to(moria)
25 changes: 25 additions & 0 deletions tests/machines/compound/middle_earth_journey_with_finals.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
from statemachine import State
from statemachine import StateChart


class MiddleEarthJourneyWithFinals(StateChart):
class rivendell(State.Compound):
council = State(initial=True)
preparing = State(final=True)

get_ready = council.to(preparing)

class moria(State.Compound):
gates = State(initial=True)
bridge = State(final=True)

cross = gates.to(bridge)

class lothlorien(State.Compound):
mirror = State(initial=True)
departure = State(final=True)

leave = mirror.to(departure)

march_to_moria = rivendell.to(moria)
march_to_lorien = moria.to(lothlorien)
15 changes: 15 additions & 0 deletions tests/machines/compound/moria_expedition.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
from statemachine import State
from statemachine import StateChart


class MoriaExpedition(StateChart):
class moria(State.Compound):
class upper_halls(State.Compound):
entrance = State(initial=True)
bridge = State(final=True)

cross = entrance.to(bridge)

assert isinstance(upper_halls, State)
depths = State(final=True)
descend = upper_halls.to(depths)
18 changes: 18 additions & 0 deletions tests/machines/compound/moria_expedition_with_escape.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
from statemachine import State
from statemachine import StateChart


class MoriaExpeditionWithEscape(StateChart):
class moria(State.Compound):
class upper_halls(State.Compound):
entrance = State(initial=True)
bridge = State()

cross = entrance.to(bridge)

assert isinstance(upper_halls, State)
depths = State(final=True)
descend = upper_halls.to(depths)

daylight = State(final=True)
escape = moria.to(daylight)
13 changes: 13 additions & 0 deletions tests/machines/compound/quest_for_erebor.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
from statemachine import State
from statemachine import StateChart


class QuestForErebor(StateChart):
class lonely_mountain(State.Compound):
approach = State(initial=True)
inside = State(final=True)

enter_mountain = approach.to(inside)

victory = State(final=True)
done_state_lonely_mountain = lonely_mountain.to(victory)
13 changes: 13 additions & 0 deletions tests/machines/compound/shire_to_rivendell.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
from statemachine import State
from statemachine import StateChart


class ShireToRivendell(StateChart):
class shire(State.Compound):
bag_end = State(initial=True)
green_dragon = State()

visit_pub = bag_end.to(green_dragon)

road = State(final=True)
depart = shire.to(road)
Empty file.
20 changes: 20 additions & 0 deletions tests/machines/donedata/destroy_the_ring.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
from statemachine import Event
from statemachine import State
from statemachine import StateChart


class DestroyTheRing(StateChart):
class quest(State.Compound):
traveling = State(initial=True)
completed = State(final=True, donedata="get_quest_result")

finish = traveling.to(completed)

def get_quest_result(self):
return {"ring_destroyed": True, "hero": "frodo"}

epilogue = State(final=True)
done_state_quest = Event(quest.to(epilogue, on="capture_result")) # type: ignore[arg-type]

def capture_result(self, ring_destroyed=None, hero=None, **kwargs):
self.received = {"ring_destroyed": ring_destroyed, "hero": hero}
17 changes: 17 additions & 0 deletions tests/machines/donedata/destroy_the_ring_simple.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
from statemachine import Event
from statemachine import State
from statemachine import StateChart


class DestroyTheRingSimple(StateChart):
class quest(State.Compound):
traveling = State(initial=True)
completed = State(final=True, donedata="get_result")

finish = traveling.to(completed)

def get_result(self):
return {"outcome": "victory"}

celebration = State(final=True)
done_state_quest = Event(quest.to(celebration)) # type: ignore[arg-type]
22 changes: 22 additions & 0 deletions tests/machines/donedata/nested_quest_donedata.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
from statemachine import Event
from statemachine import State
from statemachine import StateChart


class NestedQuestDoneData(StateChart):
class outer(State.Compound):
class inner(State.Compound):
start = State(initial=True)
end = State(final=True, donedata="inner_result")

go = start.to(end)

def inner_result(self):
return {"level": "inner"}

assert isinstance(inner, State)
after_inner = State(final=True)
done_state_inner = Event(inner.to(after_inner)) # type: ignore[arg-type]

final = State(final=True)
done_state_outer = Event(outer.to(final)) # type: ignore[arg-type]
13 changes: 13 additions & 0 deletions tests/machines/donedata/quest_for_erebor_done_convention.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
from statemachine import State
from statemachine import StateChart


class QuestForEreborDoneConvention(StateChart):
class quest(State.Compound):
traveling = State(initial=True)
arrived = State(final=True)

finish = traveling.to(arrived)

celebration = State(final=True)
done_state_quest = quest.to(celebration)
14 changes: 14 additions & 0 deletions tests/machines/donedata/quest_for_erebor_explicit_id.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
from statemachine import Event
from statemachine import State
from statemachine import StateChart


class QuestForEreborExplicitId(StateChart):
class quest(State.Compound):
traveling = State(initial=True)
arrived = State(final=True)

finish = traveling.to(arrived)

celebration = State(final=True)
done_state_quest = Event(quest.to(celebration), id="done.state.quest") # type: ignore[arg-type]
13 changes: 13 additions & 0 deletions tests/machines/donedata/quest_for_erebor_multi_word.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
from statemachine import State
from statemachine import StateChart


class QuestForEreborMultiWord(StateChart):
class lonely_mountain(State.Compound):
approach = State(initial=True)
inside = State(final=True)

enter_mountain = approach.to(inside)

victory = State(final=True)
done_state_lonely_mountain = lonely_mountain.to(victory)
14 changes: 14 additions & 0 deletions tests/machines/donedata/quest_for_erebor_with_event.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
from statemachine import Event
from statemachine import State
from statemachine import StateChart


class QuestForEreborWithEvent(StateChart):
class quest(State.Compound):
traveling = State(initial=True)
arrived = State(final=True)

finish = traveling.to(arrived)

celebration = State(final=True)
done_state_quest = Event(quest.to(celebration)) # type: ignore[arg-type]
Empty file.
16 changes: 16 additions & 0 deletions tests/machines/error/error_convention_event.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
from statemachine import Event
from statemachine import State
from statemachine import StateChart


class ErrorConventionEventSC(StateChart):
"""Using Event without explicit id with error_ prefix auto-registers dot notation."""

s1 = State("s1", initial=True)
error_state = State("error_state", final=True)

go = s1.to(s1, on="bad_action")
error_execution = Event(s1.to(error_state))

def bad_action(self):
raise RuntimeError("action failed")
Loading
Loading