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 = Action.objects.get(name='send json')

        scheduled_item = ScheduledOperation(
            user=user,
            name='JSON scheduled action',
            action=action,
            execute=datetime.now(pytz.timezone(settings.TIME_ZONE)).replace(
                second=0),
            status=ScheduledOperation.STATUS_PENDING,
            item_column=action.workflow.columns.get(name='email'),
            payload={'token': token})
        scheduled_item.save()

        # Execute the scheduler
        tasks.execute_scheduled_actions_task(True)

        scheduled_item.refresh_from_db()
        json_outbox = OnTaskSharedState.json_outbox
        assert scheduled_item.status == ScheduledOperation.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)
    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 = Action.objects.get(name='send email')

        scheduled_item = ScheduledOperation(
            user=user,
            name='send email action',
            action=action,
            execute=datetime.now(pytz.timezone(settings.TIME_ZONE)).replace(
                second=0),
            status=ScheduledOperation.STATUS_PENDING,
            item_column=action.workflow.columns.get(name='email'),
            payload={
                'subject': 'Email subject',
                'cc_email': '',
                'bcc_email': '',
                'send_confirmation': False,
                'track_read': False})

        scheduled_item.save()

        # Execute the scheduler
        tasks.execute_scheduled_actions_task(True)

        scheduled_item.refresh_from_db()
        assert scheduled_item.status == ScheduledOperation.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
    def test_scheduled_send_list_action(self):
        """Create a scheduled send list action and execute it."""

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

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

        scheduled_item = ScheduledOperation(
            user=user,
            name='send list scheduled action',
            action=action,
            execute=datetime.now(pytz.timezone(settings.TIME_ZONE)).replace(
                second=0),
            status=ScheduledOperation.STATUS_PENDING,
            payload={
                'email_to': '*****@*****.**',
                'subject': 'Action subject',
                'cc_email': '',
                'bcc_email': ''})
        scheduled_item.save()

        # Execute the scheduler
        tasks.execute_scheduled_actions_task(True)

        scheduled_item.refresh_from_db()
        assert scheduled_item.status == ScheduledOperation.STATUS_DONE
        assert len(mail.outbox) == 1
        assert (
            '[email protected], [email protected]' in mail.outbox[0].body)
    def test_scheduled_incremental_email_action(self):
        """Test an incremental scheduled action."""
        # Modify the data table so that initially all records have registered
        # equal to alse
        workflow = 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 = Action.objects.get(name='send email incrementally')

        now = datetime.now(pytz.timezone(settings.TIME_ZONE)).replace(second=0)
        scheduled_item = ScheduledOperation(
            user=user,
            name='send email action incrementally',
            action=action,
            execute=now,
            execute_until=now + timedelta(hours=1),
            status=ScheduledOperation.STATUS_PENDING,
            item_column=action.workflow.columns.get(name='email'),
            payload={
                '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_actions_task(True)

        # Event stil pending, with no values in exclude values
        scheduled_item.refresh_from_db()
        assert scheduled_item.status == ScheduledOperation.STATUS_PENDING
        assert scheduled_item.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_actions_task(True)

        # Event stil pending, with no values in exclude values
        scheduled_item.refresh_from_db()
        assert scheduled_item.status == ScheduledOperation.STATUS_PENDING
        assert scheduled_item.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_actions_task(True)

        # Event stil pending, with no values in exclude values
        scheduled_item.refresh_from_db()
        assert scheduled_item.status == ScheduledOperation.STATUS_PENDING
        assert scheduled_item.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_actions_task(True)

        # Event stil pending, with no values in exclude values
        scheduled_item.refresh_from_db()
        assert scheduled_item.status == ScheduledOperation.STATUS_PENDING
        assert scheduled_item.exclude_values == [
            '*****@*****.**',
            '*****@*****.**',
            '*****@*****.**']

        # Execute the scheduler for the first time
        tasks.execute_scheduled_actions_task(True)

        # Event stil pending, with no values in exclude values
        scheduled_item.refresh_from_db()
        assert scheduled_item.status == ScheduledOperation.STATUS_PENDING
        assert scheduled_item.exclude_values == [
            '*****@*****.**',
            '*****@*****.**',
            '*****@*****.**']