예제 #1
0
    def test_scheduled_json_report_action(self):
        """Create a scheduled send report action and execute it."""

        token = 'false token'
        settings.EXECUTE_ACTION_JSON_TRANSFER = False
        OnTaskSharedState.json_outbox = []

        user = get_user_model().objects.get(email='*****@*****.**')

        # User must exist
        self.assertIsNotNone(user, 'User [email protected] not found')
        action = models.Action.objects.get(name='send json report')

        now = datetime.now(pytz.timezone(settings.TIME_ZONE))
        scheduled_item = models.ScheduledOperation(
            user=user,
            operation_type=models.Log.ACTION_RUN_JSON_REPORT,
            name='JSON Report scheduled action',
            workflow=action.workflow,
            action=action,
            execute=now + timedelta(minutes=2),
            status=models.scheduler.STATUS_PENDING,
            payload={'token': token})
        scheduled_item.save()

        # Execute the scheduler
        tasks.execute_scheduled_operation(scheduled_item.id)

        json_outbox = OnTaskSharedState.json_outbox
        scheduled_item.refresh_from_db()
        assert scheduled_item.status == models.scheduler.STATUS_DONE
        assert len(json_outbox) == 1
        assert all(token in item['auth'] for item in json_outbox)
예제 #2
0
    def test_scheduled_email_report(self):
        """Create a scheduled send report action and execute it."""

        user = get_user_model().objects.get(email='*****@*****.**')

        # User must exist
        self.assertIsNotNone(user, 'User [email protected] not found')
        action = models.Action.objects.get(name='send list')

        now = datetime.now(pytz.timezone(settings.TIME_ZONE))
        scheduled_item = models.ScheduledOperation(
            user=user,
            operation_type=models.Log.ACTION_RUN_EMAIL_REPORT,
            name='send list scheduled action',
            workflow=action.workflow,
            action=action,
            execute=now + self.tdelta,
            status=models.scheduler.STATUS_PENDING,
            payload={
                'email_to': '*****@*****.**',
                'subject': 'Action subject',
                'cc_email': '',
                'bcc_email': ''
            })
        scheduled_item.save()

        # Execute the scheduler
        tasks.execute_scheduled_operation(scheduled_item.id)

        scheduled_item.refresh_from_db()
        assert scheduled_item.status == models.scheduler.STATUS_DONE
        assert len(mail.outbox) == 1
        assert ('*****@*****.**' in mail.outbox[0].body)
        assert ('*****@*****.**' in mail.outbox[0].body)
예제 #3
0
    def test_scheduled_json_action(self):
        """Create a scheduled send list action and execute it."""
        token = 'fake token'

        OnTaskSharedState.json_outbox = []
        settings.EXECUTE_ACTION_JSON_TRANSFER = False

        user = get_user_model().objects.get(email='*****@*****.**')

        # User must exist
        self.assertIsNotNone(user, 'User [email protected] not found')
        action = models.Action.objects.get(name='send json')

        now = datetime.now(pytz.timezone(settings.TIME_ZONE))
        scheduled_item = models.ScheduledOperation(
            user=user,
            operation_type=models.Log.ACTION_RUN_PERSONALIZED_JSON,
            name='JSON scheduled action',
            workflow=action.workflow,
            action=action,
            execute=now + self.tdelta,
            status=models.scheduler.STATUS_PENDING,
            payload={
                'item_column': action.workflow.columns.get(name='email').id,
                'token': token
            })
        scheduled_item.save()

        # Execute the scheduler
        tasks.execute_scheduled_operation(scheduled_item.id)

        scheduled_item.refresh_from_db()
        json_outbox = OnTaskSharedState.json_outbox
        assert scheduled_item.status == models.scheduler.STATUS_DONE
        assert len(json_outbox) == 3
        assert all(item['target'] == action.target_url for item in json_outbox)
        assert all(token in item['auth'] for item in json_outbox)
예제 #4
0
    def test_scheduled_email_action(self):
        """Create a scheduled send email action and execute it."""

        user = get_user_model().objects.get(email='*****@*****.**')

        # User must exist
        self.assertIsNotNone(user, 'User [email protected] not found')
        action = models.Action.objects.get(name='send email')

        now = datetime.now(pytz.timezone(settings.TIME_ZONE))
        scheduled_item = models.ScheduledOperation(
            user=user,
            operation_type=models.Log.ACTION_RUN_PERSONALIZED_EMAIL,
            name='send email action',
            workflow=action.workflow,
            action=action,
            execute=now + self.tdelta,
            status=models.scheduler.STATUS_PENDING,
            payload={
                'item_column': action.workflow.columns.get(name='email').id,
                'subject': 'Email subject',
                'cc_email': '',
                'bcc_email': '',
                'send_confirmation': False,
                'track_read': False
            })

        scheduled_item.save()

        # Execute the scheduler
        tasks.execute_scheduled_operation(scheduled_item.id)

        scheduled_item.refresh_from_db()
        assert scheduled_item.status == models.scheduler.STATUS_DONE
        assert len(mail.outbox) == 2
        assert 'Hi Student Two' in mail.outbox[0].body
        assert 'Hi Student Three' in mail.outbox[1].body
예제 #5
0
    def test_scheduled_incremental_email(self):
        """Test an incremental scheduled action."""
        # Modify the data table so that initially all records have registered
        # equal to alse
        workflow = models.Workflow.objects.all().first()
        with connection.cursor() as cursor:
            query = sql.SQL('UPDATE {0} SET {1} = false').format(
                sql.Identifier(workflow.get_data_frame_table_name()),
                sql.Identifier('registered'))
            cursor.execute(query)

        user = get_user_model().objects.get(email='*****@*****.**')

        # User must exist
        self.assertIsNotNone(user, 'User [email protected] not found')
        action = models.Action.objects.get(name='send email incrementally')

        now = datetime.now(pytz.timezone(settings.TIME_ZONE))
        scheduled_item = models.ScheduledOperation(
            user=user,
            operation_type=models.Log.ACTION_RUN_PERSONALIZED_EMAIL,
            name='send email action incrementally',
            workflow=action.workflow,
            action=action,
            execute=now,
            frequency='* * * * *',
            execute_until=now + timedelta(hours=1),
            status=models.scheduler.STATUS_PENDING,
            payload={
                'item_column': action.workflow.columns.get(name='email').id,
                'exclude_values': [],
                'subject': 'Email subject',
                'cc_email': '',
                'bcc_email': '',
                'send_confirmation': False,
                'track_read': False
            })
        scheduled_item.save()

        # Execute the scheduler for the first time
        tasks.execute_scheduled_operation(scheduled_item.id)

        # Event still pending, with no values in exclude values
        scheduled_item.refresh_from_db()
        assert scheduled_item.status == models.scheduler.STATUS_PENDING
        assert scheduled_item.payload.get('exclude_values', []) == []

        # Modify one of the values in the matrix
        with connection.cursor() as cursor:
            query = sql.SQL(
                'UPDATE {0} SET {1} = true WHERE {2} = {3}').format(
                    sql.Identifier(workflow.get_data_frame_table_name()),
                    sql.Identifier('registered'), sql.Identifier('email'),
                    sql.Placeholder())
            cursor.execute(query, ['*****@*****.**'])

        # Execute the scheduler for the first time
        tasks.execute_scheduled_operation(scheduled_item.id)

        # Event still pending, with one values in exclude values
        scheduled_item.refresh_from_db()
        assert scheduled_item.status == models.scheduler.STATUS_PENDING
        assert scheduled_item.payload['exclude_values'] == [
            '*****@*****.**'
        ]

        # Modify one of the values in the matrix
        with connection.cursor() as cursor:
            query = sql.SQL(
                'UPDATE {0} SET {1} = true WHERE {2} = {3}').format(
                    sql.Identifier(workflow.get_data_frame_table_name()),
                    sql.Identifier('registered'), sql.Identifier('email'),
                    sql.Placeholder())
            cursor.execute(query, ['*****@*****.**'])

        # Execute the scheduler for the first time
        tasks.execute_scheduled_operation(scheduled_item.id)

        # Event still pending, with two values in exclude values
        scheduled_item.refresh_from_db()
        assert scheduled_item.status == models.scheduler.STATUS_PENDING
        assert scheduled_item.payload['exclude_values'] == [
            '*****@*****.**', '*****@*****.**'
        ]

        # Modify one of the values in the matrix
        with connection.cursor() as cursor:
            query = sql.SQL(
                'UPDATE {0} SET {1} = true WHERE {2} = {3}').format(
                    sql.Identifier(workflow.get_data_frame_table_name()),
                    sql.Identifier('registered'), sql.Identifier('email'),
                    sql.Placeholder())
            cursor.execute(query, ['*****@*****.**'])

        # Execute the scheduler for the first time
        tasks.execute_scheduled_operation(scheduled_item.id)

        # Event still pending, with three values in exclude values
        scheduled_item.refresh_from_db()
        assert scheduled_item.status == models.scheduler.STATUS_PENDING
        assert scheduled_item.payload['exclude_values'] == [
            '*****@*****.**', '*****@*****.**', '*****@*****.**'
        ]

        # Execute the scheduler for the first time
        tasks.execute_scheduled_operation(scheduled_item.id)

        # Event still pending, with no values in exclude values
        scheduled_item.refresh_from_db()
        assert scheduled_item.status == models.scheduler.STATUS_PENDING
        assert scheduled_item.payload['exclude_values'] == [
            '*****@*****.**', '*****@*****.**', '*****@*****.**'
        ]
예제 #6
0
    def test_sql_update_create(self):
        """Create a new SQL Scheduled operation."""

        initial_df = self.workflow.data_frame()

        # Create the new table in the DB for the scheduled operation
        with connection.connection.cursor() as cursor:
            # Add the extra table to the database for the merge
            for query, fields in SQL_QUERIES:
                cursor.execute(query, fields)

        # Save some current variables for future checks
        current_ops = models.ScheduledOperation.objects.count()
        current_tasks = PeriodicTask.objects.count()
        current_nrows = self.workflow.nrows
        current_columns = self.workflow.ncols

        # Index page should be ok
        resp = self.get_response('scheduler:index')
        self.assertTrue(status.is_success(resp.status_code))

        # GET the page to select the SQL connection
        resp = self.get_response('scheduler:select_sql')
        self.assertTrue(status.is_success(resp.status_code))
        for sql_conn in models.SQLConnection.objects.all():
            self.assertTrue(sql_conn.name in str(resp.content))

        # Get the connection pointing to localhost
        sql_conn = models.SQLConnection.objects.get(name='remote server 2')

        # Modify connection to point to the test DB
        sql_conn.db_name = settings.DATABASE_URL['NAME']
        sql_conn.save()

        # GET the form to create the scheduled SQL operation
        resp = self.get_response('scheduler:sqlupload',
                                 {'pk': str(sql_conn.id)})
        self.assertTrue(status.is_success(resp.status_code))

        # POST incorrect form without a dst key
        resp = self.get_response('scheduler:sqlupload',
                                 {'pk': str(sql_conn.id)},
                                 method='POST',
                                 req_params={
                                     'name': 'schedule sql upload',
                                     'execute': '05/31/2999 14:35',
                                     'src_key': 'email',
                                     'how_merge': 'outer',
                                     'db_password': '******'
                                 })
        self.assertTrue(status.is_success(resp.status_code))
        self.assertIn('operation requires the names', str(resp.content))

        # POST incorrect form without a src key
        resp = self.get_response('scheduler:sqlupload',
                                 {'pk': str(sql_conn.id)},
                                 method='POST',
                                 req_params={
                                     'name': 'schedule sql upload',
                                     'execute': '05/31/2999 14:35',
                                     'dst_key': 'email',
                                     'how_merge': 'outer',
                                     'db_password': '******'
                                 })
        self.assertTrue(status.is_success(resp.status_code))
        self.assertIn('operation requires the names', str(resp.content))

        # POST incorrect form without a non-existent dst_key
        resp = self.get_response('scheduler:sqlupload',
                                 {'pk': str(sql_conn.id)},
                                 method='POST',
                                 req_params={
                                     'name': 'schedule sql upload',
                                     'execute': '05/31/2999 14:35',
                                     'dst_key': 'INCORRECT NAME',
                                     'src_key': 'email',
                                     'how_merge': 'outer',
                                     'db_password': '******'
                                 })
        self.assertTrue(status.is_success(resp.status_code))
        self.assertIn('is not a key column', str(resp.content))

        # POST incorrect form without an incorrect dst_key
        resp = self.get_response('scheduler:sqlupload',
                                 {'pk': str(sql_conn.id)},
                                 method='POST',
                                 req_params={
                                     'name': 'schedule sql upload',
                                     'execute': '05/31/2999 14:35',
                                     'dst_key': 'Gender',
                                     'src_key': 'email',
                                     'how_merge': 'outer',
                                     'db_password': '******'
                                 })
        self.assertTrue(status.is_success(resp.status_code))
        self.assertIn('is not a key column', str(resp.content))

        # POST incorrect form without a merge method
        resp = self.get_response('scheduler:sqlupload',
                                 {'pk': str(sql_conn.id)},
                                 method='POST',
                                 req_params={
                                     'name': 'schedule sql upload',
                                     'execute': '05/31/2999 14:35',
                                     'dst_key': 'Gender',
                                     'src_key': 'email',
                                     'db_password': '******'
                                 })
        self.assertTrue(status.is_success(resp.status_code))
        self.assertIn('requires a merge method', str(resp.content))

        # POST the correct form to create the SQL operation
        resp = self.get_response('scheduler:sqlupload',
                                 {'pk': str(sql_conn.id)},
                                 method='POST',
                                 req_params={
                                     'name': 'schedule sql upload',
                                     'execute': '05/31/2999 14:35',
                                     'dst_key': 'email',
                                     'src_key': 'email',
                                     'how_merge': 'outer',
                                     'db_password': '******'
                                 })
        self.assertTrue(status.is_success(resp.status_code))
        self.assertEqual(current_ops + 1,
                         models.ScheduledOperation.objects.count())

        # Execute the operation
        s_item = self.workflow.scheduled_operations.get(
            name='schedule sql upload')
        tasks.execute_scheduled_operation(s_item.id)

        # Verify the result of the operation
        s_item.refresh_from_db()
        self.workflow.refresh_from_db()

        # Identical number of tasks pending than at the start
        self.assertEqual(current_tasks + 1, PeriodicTask.objects.count())

        # Operation must have status equal to DONE
        self.assertEqual(s_item.status, models.scheduler.STATUS_DONE)

        # Operation execution time must be reflected in the log field
        self.assertIsNotNone(s_item.last_executed_log)

        # Number of rows and columns in workflow has changed
        self.assertEqual(self.workflow.nrows, current_nrows + 3)
        self.assertEqual(self.workflow.ncols, current_columns + 1)

        # New column with the right name and type
        new_column = self.workflow.columns.filter(name='NEW COLUMN').first()
        self.assertIsNotNone(new_column)
        self.assertEqual(new_column.data_type, 'double')
        result_df = self.workflow.data_frame()

        # New rows with the right email
        email_values = list(result_df['email'])
        self.assertIn('*****@*****.**', email_values)
        self.assertIn('*****@*****.**', email_values)
        self.assertIn('*****@*****.**', email_values)

        # Columns with the right value
        old_hecs_count = initial_df['Enrolment Type'].loc[
            initial_df['Enrolment Type'] == 'Local'].count()
        new_hecs_count = result_df['Enrolment Type'].loc[
            result_df['Enrolment Type'] == 'Local'].count()
        self.assertEqual(old_hecs_count + 6, new_hecs_count)
        self.assertEqual(result_df['NEW COLUMN'].count(), 6)