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')
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)