示例#1
0
class StateTestCase(TestCase):
    def setUp(self) -> None:
        self.state = State(Invoice.objects.create(status='draft'), 'status')

    def test_hash_remains_the_same(self):
        self.assertEqual(self.state._get_hash(), self.state._get_hash())

    def test_get_db_state(self):
        self.assertEqual(self.state.get_db_state(), 'draft')

    def test_lock(self):
        self.assertFalse(self.state.is_locked())
        self.state.lock()
        self.assertTrue(self.state.is_locked())

        # nothing should happen
        self.state.lock()
        self.assertTrue(self.state.is_locked())

        self.state.unlock()
        self.assertFalse(self.state.is_locked())

    def test_set_state(self):
        self.state.set_state('void')
        self.assertEqual(self.state.instance.status, 'void')
        # make sure it was saved to db
        self.state.instance.refresh_from_db()
        self.assertEqual(self.state.instance.status, 'void')
示例#2
0
 def complete_transition(self, state: State, **kwargs):
     """
     It completes the transition process for provided state.
     The instance will be unlocked and callbacks executed
     :param state: State object
     """
     state.set_state(self.target)
     logging.info(f'{state.instance_key} state changed to {self.target}')
     state.unlock()
     logging.info(f'{state.instance_key} has been unlocked')
     self.callbacks.execute(state, **kwargs)
示例#3
0
 def fail_transition(self, state: State, exception: Exception, **kwargs):
     """
     It triggers fail transition in case of any failure during the side effects execution.
     :param state: State object
     :param exception: Exception that caused transition failure
     """
     if self.failed_state:
         state.set_state(self.failed_state)
         logging.info(
             f'{state.instance_key} state changed to {self.failed_state}')
     state.unlock()
     logging.info(f'{state.instance_key} has been unlocked')
     self.failure_callbacks.execute(state, exception=exception, **kwargs)
示例#4
0
    def change_state(self, state: State, **kwargs):
        """
        This method changes a state by the following algorithm:
        - Lock state
        - Change state to `in progress` if such exists
        - Run side effects which should run `complete_transition` in case of success
        or `fail_transition` in case of failure.
        :param state: State object
        """
        if state.is_locked():
            logging.info(f'{state.instance_key} is locked')
            raise TransitionNotAllowed("State is locked")

        state.lock()
        logging.info(f'{state.instance_key} has been locked')
        if self.in_progress_state:
            state.set_state(self.in_progress_state)
            logging.info(
                f'{state.instance_key} state changed to {self.in_progress_state}'
            )
        self.side_effects.execute(state, **kwargs)