예제 #1
0
    def test_delete_ignores_other_workflows(self):
        workflow = Workflow.create_and_init()
        workflow2 = Workflow.create_and_init()

        # Create a delta we want to delete
        delta = self.run_with_async_db(
            ChangeWorkflowTitleCommand.create(workflow=workflow,
                                              new_value="1"))

        # Create deltas on workflow2 that we _don't_ want to delete
        delta2 = self.run_with_async_db(
            ChangeWorkflowTitleCommand.create(workflow=workflow2,
                                              new_value="1"))

        self.run_with_async_db(delta.backward())  # fix workflow.last_delta_id
        delta.delete_with_successors()
        workflow.delete_orphan_soft_deleted_models()

        delta2.refresh_from_db()  # do not crash
예제 #2
0
    def test_delete_orphans(self):
        workflow = Workflow.create_and_init()

        self.run_with_async_db(
            ChangeWorkflowTitleCommand.create(workflow=workflow,
                                              new_value="1"))
        delta2 = self.run_with_async_db(
            ChangeWorkflowTitleCommand.create(workflow=workflow,
                                              new_value="2"))
        delta3 = self.run_with_async_db(
            ChangeWorkflowTitleCommand.create(workflow=workflow,
                                              new_value="3"))
        self.run_with_async_db(delta3.backward())
        self.run_with_async_db(delta2.backward())
        # Create a new delta ... making delta2 and delta3 obsolete
        self.run_with_async_db(
            ChangeWorkflowTitleCommand.create(workflow=workflow,
                                              new_value="4"))

        with self.assertRaises(Delta.DoesNotExist):
            delta2.refresh_from_db()
        with self.assertRaises(Delta.DoesNotExist):
            delta3.refresh_from_db()
예제 #3
0
 def test_delete_deltas_without_init_delta(self):
     workflow = Workflow.objects.create(name='A')
     tab = workflow.tabs.create(position=0)
     self.run_with_async_db(
         ChangeWorkflowTitleCommand.create(workflow=workflow,
                                           new_value='B'))
     ModuleVersion.create_or_replace_from_spec({
         'id_name': 'x',
         'name': 'x',
         'category': 'Clean',
         'parameters': [],
     })
     self.run_with_async_db(
         AddModuleCommand.create(workflow=workflow,
                                 tab=tab,
                                 module_id_name='x',
                                 position=0,
                                 param_values={}))
     self.run_with_async_db(
         ChangeWorkflowTitleCommand.create(workflow=workflow,
                                           new_value='C'))
     workflow.delete()
     self.assertTrue(True)  # no crash
예제 #4
0
    def test_delete_deletes_soft_deleted_wfmodule(self):
        workflow = Workflow.create_and_init()
        # Here's a soft-deleted module
        wf_module = workflow.tabs.first().wf_modules.create(
            order=0, slug="step-1", module_id_name="foo", is_deleted=True)

        delta = self.run_with_async_db(
            ChangeWorkflowTitleCommand.create(workflow=workflow,
                                              new_value="1"))
        self.run_with_async_db(delta.backward())  # fix workflow.last_delta_id
        delta.delete_with_successors()
        workflow.delete_orphan_soft_deleted_models()

        with self.assertRaises(WfModule.DoesNotExist):
            wf_module.refresh_from_db()
예제 #5
0
    def test_delete_protects_non_deleted_wfmodule(self):
        workflow = Workflow.create_and_init()
        # Here's a soft-deleted module
        wf_module = workflow.tabs.first().wf_modules.create(
            order=0, slug="step-1", module_id_name="foo", is_deleted=False)

        # delete a delta
        delta = self.run_with_async_db(
            ChangeWorkflowTitleCommand.create(workflow=workflow,
                                              new_value="1"))
        self.run_with_async_db(delta.backward())  # fix workflow.last_delta_id
        delta.delete_with_successors()
        workflow.delete_orphan_soft_deleted_models()

        wf_module.refresh_from_db()  # no DoesNotExist: it's not deleted
예제 #6
0
 def test_delete_deltas_without_init_delta(self):
     workflow = Workflow.objects.create(name="A")
     tab = workflow.tabs.create(position=0)
     self.run_with_async_db(
         ChangeWorkflowTitleCommand.create(workflow=workflow, new_value="B")
     )
     ModuleVersion.create_or_replace_from_spec(
         {"id_name": "x", "name": "x", "category": "Clean", "parameters": []}
     )
     self.run_with_async_db(
         AddModuleCommand.create(
             workflow=workflow,
             tab=tab,
             slug="step-1",
             module_id_name="x",
             position=0,
             param_values={},
         )
     )
     self.run_with_async_db(
         ChangeWorkflowTitleCommand.create(workflow=workflow, new_value="C")
     )
     workflow.delete()
     self.assertTrue(True)  # no crash
예제 #7
0
    def test_delete_scopes_tab_delete_by_workflow(self):
        workflow = Workflow.create_and_init()
        workflow2 = Workflow.create_and_init()
        # Here's a soft-deleted module on workflow2. Nothing references it. It
        # "shouldn't" exist.
        tab = workflow2.tabs.create(position=1)

        # now delete a delta on workflow1
        delta = self.run_with_async_db(
            ChangeWorkflowTitleCommand.create(workflow=workflow,
                                              new_value="1"))
        self.run_with_async_db(delta.backward())  # fix workflow.last_delta_id
        delta.delete_with_successors()
        workflow.delete_orphan_soft_deleted_models()

        tab.refresh_from_db()  # no DoesNotExist: leave workflow2 alone
예제 #8
0
    def test_delete_scopes_wf_module_delete_by_workflow(self):
        workflow = Workflow.create_and_init()
        workflow2 = Workflow.create_and_init()
        # Here's a soft-deleted module on workflow2. Nothing references it. It
        # "shouldn't" exist.
        wf_module = workflow2.tabs.first().wf_modules.create(
            order=0, slug="step-1", module_id_name="foo", is_deleted=True)

        # now delete a delta on workflow1
        delta = self.run_with_async_db(
            ChangeWorkflowTitleCommand.create(workflow=workflow,
                                              new_value="1"))
        self.run_with_async_db(delta.backward())  # fix workflow.last_delta_id
        delta.delete_with_successors()
        workflow.delete_orphan_soft_deleted_models()

        wf_module.refresh_from_db()  # no DoesNotExist: leave workflow2 alone
예제 #9
0
    def test_delete_deletes_soft_deleted_tab(self):
        workflow = Workflow.create_and_init()
        tab = workflow.tabs.create(position=1, is_deleted=True)
        # create a wf_module -- it needs to be deleted, too!
        wf_module = tab.wf_modules.create(order=0,
                                          module_id_name='foo',
                                          is_deleted=True)

        delta = self.run_with_async_db(
            ChangeWorkflowTitleCommand.create(workflow=workflow,
                                              new_value='1'))
        self.run_with_async_db(delta.backward())  # fix workflow.last_delta_id
        delta.delete_with_successors()
        workflow.delete_orphan_soft_deleted_models()

        with self.assertRaises(WfModule.DoesNotExist):
            wf_module.refresh_from_db()
        with self.assertRaises(Tab.DoesNotExist):
            tab.refresh_from_db()
예제 #10
0
    def test_delete_protects_soft_deleted_wfmodule_with_reference(self):
        workflow = Workflow.create_and_init()
        # Here's a soft-deleted module
        wf_module = workflow.tabs.first().wf_modules.create(
            order=0, slug="step-1", module_id_name="foo", is_deleted=True)

        # "protect" it: here's a delta we _aren't_ deleting
        self.run_with_async_db(
            ChangeWfModuleNotesCommand.create(workflow=workflow,
                                              wf_module=wf_module,
                                              new_value="1"))

        # now delete a delta
        delta = self.run_with_async_db(
            ChangeWorkflowTitleCommand.create(workflow=workflow,
                                              new_value="1"))
        self.run_with_async_db(delta.backward())  # fix workflow.last_delta_id
        delta.delete_with_successors()
        workflow.delete_orphan_soft_deleted_models()

        wf_module.refresh_from_db()  # no DoesNotExist -- a delta depends on it
    def test_change_title(self):
        workflow = Workflow.create_and_init(name="title1")

        # Change back to second title, see if it saved
        cmd = self.run_with_async_db(
            ChangeWorkflowTitleCommand.create(workflow=workflow,
                                              new_value="title2"))
        self.assertEqual(workflow.name, "title2")  # test var change
        workflow.refresh_from_db()
        self.assertEqual(workflow.name, "title2")  # test DB change

        # undo
        self.run_with_async_db(cmd.backward())
        self.assertEqual(workflow.name, "title1")  # test var change
        workflow.refresh_from_db()
        self.assertEqual(workflow.name, "title1")  # test DB change

        # redo
        self.run_with_async_db(cmd.forward())
        self.assertEqual(workflow.name, "title2")
        workflow.refresh_from_db()
        self.assertEqual(workflow.name, "title2")
예제 #12
0
    def test_undo_redo(self):
        ModuleVersion.create_or_replace_from_spec({
            'id_name':
            'pastecsv',
            'name':
            'pastecsv',
            'category':
            'Clean',
            'parameters': [
                {
                    'id_name': 'csv',
                    'type': 'string'
                },
            ]
        })

        workflow = Workflow.create_and_init()
        tab = workflow.tabs.first()

        all_modules = tab.live_wf_modules  # beginning state: nothing

        v0 = workflow.last_delta_id

        # Test undoing nothing at all. Should NOP
        self.run_with_async_db(WorkflowUndo(workflow))
        workflow.refresh_from_db()
        self.assertEqual(workflow.last_delta_id, v0)
        self.assertEqual(all_modules.count(), 0)
        self.assertEqual(workflow.last_delta_id, v0)

        # Add a module
        cmd1 = self.run_with_async_db(
            AddModuleCommand.create(workflow=workflow,
                                    tab=tab,
                                    module_id_name='pastecsv',
                                    position=0,
                                    param_values={}))
        v1 = cmd1.id
        workflow.refresh_from_db()
        self.assertEqual(all_modules.count(), 1)
        self.assertGreater(v1, v0)
        self.assertEqual(workflow.last_delta_id, v1)
        self.assertWfModuleVersions(tab, [v1])

        # Undo, ensure we are back at start
        self.run_with_async_db(WorkflowUndo(workflow))
        workflow.refresh_from_db()
        self.assertEqual(all_modules.count(), 0)
        self.assertEqual(workflow.last_delta_id, v0)
        self.assertWfModuleVersions(tab, [])

        # Redo, ensure we are back at v1
        self.run_with_async_db(WorkflowRedo(workflow))
        workflow.refresh_from_db()
        self.assertEqual(all_modules.count(), 1)
        self.assertEqual(workflow.last_delta_id, v1)
        self.assertWfModuleVersions(tab, [v1])

        # Change a parameter
        cmd2 = self.run_with_async_db(
            ChangeParametersCommand.create(
                workflow=workflow,
                wf_module=tab.live_wf_modules.first(),
                new_values={'csv': 'some value'}))
        v2 = cmd2.id
        workflow.refresh_from_db()
        self.assertEqual(tab.live_wf_modules.first().params['csv'],
                         'some value')
        self.assertEqual(workflow.last_delta_id, v2)
        self.assertGreater(v2, v1)
        self.assertWfModuleVersions(tab, [v2])

        # Undo parameter change
        self.run_with_async_db(WorkflowUndo(workflow))
        workflow.refresh_from_db()
        self.assertEqual(workflow.last_delta_id, v1)
        self.assertEqual(tab.live_wf_modules.first().params['csv'], '')
        self.assertWfModuleVersions(tab, [v1])

        # Redo
        self.run_with_async_db(WorkflowRedo(workflow))
        workflow.refresh_from_db()
        self.assertEqual(workflow.last_delta_id, v2)
        self.assertEqual(tab.live_wf_modules.first().params['csv'],
                         'some value')
        self.assertWfModuleVersions(tab, [v2])

        # Redo again should do nothing
        self.run_with_async_db(WorkflowRedo(workflow))
        workflow.refresh_from_db()
        self.assertEqual(workflow.last_delta_id, v2)
        self.assertEqual(tab.live_wf_modules.first().params['csv'],
                         'some value')
        self.assertWfModuleVersions(tab, [v2])

        # Add one more command so the stack is 3 deep
        cmd3 = self.run_with_async_db(
            ChangeWorkflowTitleCommand.create(workflow=workflow,
                                              new_value='New Title'))
        v3 = cmd3.id
        self.assertGreater(v3, v2)
        self.assertWfModuleVersions(tab, [v2])

        # Undo twice
        self.run_with_async_db(WorkflowUndo(workflow))
        workflow.refresh_from_db()
        self.assertEqual(workflow.last_delta, cmd2)
        self.assertWfModuleVersions(tab, [v2])
        self.run_with_async_db(WorkflowUndo(workflow))
        workflow.refresh_from_db()
        self.assertEqual(workflow.last_delta, cmd1)
        self.assertWfModuleVersions(tab, [v1])

        # Redo twice
        self.run_with_async_db(WorkflowRedo(workflow))
        workflow.refresh_from_db()
        self.assertEqual(workflow.last_delta, cmd2)
        self.assertWfModuleVersions(tab, [v2])
        self.run_with_async_db(WorkflowRedo(workflow))
        workflow.refresh_from_db()
        self.assertEqual(workflow.last_delta, cmd3)
        self.assertWfModuleVersions(tab, [v2])

        # Undo again to get to a place where we have two commands to redo
        self.run_with_async_db(WorkflowUndo(workflow))
        self.run_with_async_db(WorkflowUndo(workflow))
        workflow.refresh_from_db()
        self.assertEqual(workflow.last_delta, cmd1)

        # Now add a new command. It should remove cmd2, cmd3 from the redo
        # stack and delete them from the db
        wfm = all_modules.first()
        cmd4 = self.run_with_async_db(
            ChangeWfModuleNotesCommand.create(workflow=workflow,
                                              wf_module=wfm,
                                              new_value='Note of no note'))
        v4 = cmd4.id
        workflow.refresh_from_db()
        self.assertEqual(workflow.last_delta_id, v4)
        self.assertEqual(set(Delta.objects.values_list('id', flat=True)),
                         {v0, v1, v4})  # v2, v3 deleted

        # Undo back to start, then add a command, ensure it deletes dangling
        # commands (tests an edge case in Delta.save)
        self.run_with_async_db(WorkflowUndo(workflow))
        workflow.refresh_from_db()
        self.assertEqual(workflow.last_delta_id, v1)
        cmd5 = self.run_with_async_db(
            ChangeWfModuleNotesCommand.create(workflow=workflow,
                                              wf_module=cmd1.wf_module,
                                              new_value='Note of some note'))
        v5 = cmd5.id
        workflow.refresh_from_db()
        self.assertEqual(workflow.last_delta_id, v5)
        self.assertEqual(set(Delta.objects.values_list('id', flat=True)),
                         {v0, v1, v5})  # v1, v4 deleted
        self.assertWfModuleVersions(tab, [v1])