Exemplo n.º 1
0
def test_compare_template():
    with patch('notifications_utils.template_change.TemplateChange.__init__',
               return_value=None) as mocked:
        old_template = Template({'content': 'faked', 'template_type': 'sms'})
        new_template = Template({'content': 'faked', 'template_type': 'sms'})
        template_changes = old_template.compare_to(new_template)
        mocked.assert_called_once_with(old_template, new_template)
Exemplo n.º 2
0
def test_include_placeholder_in_missing_data_if_placeholder_is_conditional(
        personalisation):

    template = Template({"content": "((has_name??hello!))"})

    template.values = personalisation
    assert template.missing_data == ['has_name']
Exemplo n.º 3
0
def edit_service_template(service_id, template_id):
    template = service_api_client.get_service_template(service_id,
                                                       template_id)['data']
    template['template_content'] = template['content']
    form = form_objects[template['template_type']](**template)

    if form.validate_on_submit():
        subject = form.subject.data if hasattr(form, 'subject') else None
        new_template = Template({
            'name': form.name.data,
            'content': form.template_content.data,
            'subject': subject,
            'template_type': template['template_type'],
            'id': template['id']
        })
        template_change = Template(template).compare_to(new_template)
        if template_change.has_different_placeholders and not request.form.get(
                'confirm'):
            return render_template(
                'views/templates/breaking-change.html',
                template_change=template_change,
                new_template=new_template,
                column_headings=list(
                    ascii_uppercase[:len(new_template.placeholders) + 1]),
                example_rows=[
                    [first_column_heading[new_template.template_type]] +
                    list(new_template.placeholders),
                    get_example_csv_rows(new_template),
                    get_example_csv_rows(new_template)
                ],
                form=form)
        try:
            service_api_client.update_service_template(
                template_id, form.name.data, template['template_type'],
                form.template_content.data, service_id, subject)
        except HTTPError as e:
            if e.status_code == 400:
                if 'content' in e.message and any([
                        'character count greater than' in x
                        for x in e.message['content']
                ]):
                    form.template_content.errors.extend(e.message['content'])
                else:
                    raise e
            else:
                raise e
        else:
            return redirect(
                url_for('.view_template',
                        service_id=service_id,
                        template_id=template_id))
    return render_template('views/edit-{}-template.html'.format(
        template['template_type']),
                           form=form,
                           template_id=template_id,
                           template_type=template['template_type'],
                           heading_action='Edit')
Exemplo n.º 4
0
def test_random_variable_retrieve():
    template = Template({
        'content': 'content',
        'template_type': 'sms',
        'created_by': "now"
    })
    assert template.get_raw('created_by') == "now"
    assert template.get_raw('missing', default='random') == 'random'
    assert template.get_raw('missing') is None
Exemplo n.º 5
0
def view_template_versions(service_id, template_id):
    return render_template(
        'views/templates/choose_history.html',
        template=Template(service_api_client.get_service_template(
            service_id, template_id)['data'],
                          prefix=current_service['name']),
        versions=[
            Template(template, prefix=current_service['name'])
            for template in service_api_client.get_service_template_versions(
                service_id, template_id)['data']
        ])
Exemplo n.º 6
0
def test_matches_keys_to_placeholder_names():

    template = Template({"content": "hello ((name))"})

    template.values = {'NAME': 'Chris'}
    assert template.values == {'name': 'Chris'}

    template.values = {'NAME': 'Chris', 'Town': 'London'}
    assert template.values == {'name': 'Chris', 'Town': 'London'}
    assert template.additional_data == {'Town'}

    template.values = None
    assert template.missing_data == ['name']
Exemplo n.º 7
0
def add_preview_of_content_to_notifications(notifications):

    for notification in notifications:

        if notification['template'].get('redact_personalisation'):
            notification['personalisation'] = {}

        if notification['template']['template_type'] == 'sms':
            yield dict(preview_of_content=str(
                Template(
                    notification['template'],
                    notification['personalisation'],
                    redact_missing_personalisation=True,
                )),
                       **notification)
        else:
            if notification['template']['is_precompiled_letter']:
                notification['template']['subject'] = notification[
                    'client_reference']
            yield dict(preview_of_content=(WithSubjectTemplate(
                notification['template'],
                notification['personalisation'],
                redact_missing_personalisation=True,
            ).subject),
                       **notification)
Exemplo n.º 8
0
def add_preview_of_content_to_notifications(notifications):

    for notification in notifications:

        if notification["template"].get("redact_personalisation"):
            notification["personalisation"] = {}

        if notification["template"]["template_type"] == "sms":
            yield dict(
                preview_of_content=str(
                    Template(
                        notification["template"],
                        notification["personalisation"],
                        redact_missing_personalisation=True,
                    )),
                **notification,
            )
        else:
            if notification["template"]["is_precompiled_letter"]:
                notification["template"]["subject"] = "Provided as PDF"
            yield dict(
                preview_of_content=(WithSubjectTemplate(
                    notification["template"],
                    notification["personalisation"],
                    redact_missing_personalisation=True,
                ).subject),
                **notification,
            )
Exemplo n.º 9
0
def send_from_api(service_id, template_id):
    return render_template('views/send-from-api.html',
                           template=Template(
                               service_api_client.get_service_template(
                                   service_id, template_id)['data'],
                               prefix=current_service['name'],
                               sms_sender=current_service['sms_sender']))
Exemplo n.º 10
0
def styleguide():

    if not current_app.config['SHOW_STYLEGUIDE']:
        abort(404)

    class FormExamples(Form):
        username = StringField(u'Username')
        password = PasswordField(u'Password', [validators.required()])
        code = StringField('Enter code')
        message = TextAreaField(u'Message')
        file_upload = FileField('Upload a CSV file to add your recipients’ details')

    sms = "Your vehicle tax for ((registration number)) is due on ((date)). Renew online at www.gov.au/vehicle-tax"

    form = FormExamples()
    form.message.data = sms
    form.validate()

    template = Template({'content': sms})

    return render_template(
        'views/styleguide.html',
        form=form,
        template=template
    )
def test_pass_through_renderer():
    message = '''
        the
        quick brown
        fox
    '''
    assert str(Template({'content': message})) == message
Exemplo n.º 12
0
def test_passes_through_template_attributes():
    assert Template({"content": ''}).name is None
    assert Template({"content": '', 'name': 'Two week reminder'}).name == 'Two week reminder'
    assert Template({"content": ''}).id is None
    assert Template({"content": '', 'id': '1234'}).id == '1234'
    assert Template({"content": ''}).template_type is None
    assert Template({"content": '', 'template_type': 'sms'}).template_type is 'sms'
    assert not hasattr(Template({"content": ''}), 'subject')
def test_basic_templates_return_markup():

    template_dict = {'content': 'content', 'subject': 'subject'}

    for output in [
        str(Template(template_dict)),
        str(WithSubjectTemplate(template_dict)),
        WithSubjectTemplate(template_dict).subject,
    ]:
        assert isinstance(output, Markup)
Exemplo n.º 14
0
def get_example_csv(service_id, template_id):
    template = Template(
        service_api_client.get_service_template(service_id,
                                                template_id)['data'])
    return Spreadsheet.from_rows(
        [[first_column_heading[template.template_type]] +
         list(template.placeholders),
         get_example_csv_rows(template)]).as_csv_data, 200, {
             'Content-Type': 'text/csv; charset=utf-8',
             'Content-Disposition':
             'inline; filename="{}.csv"'.format(template.name)
         }
Exemplo n.º 15
0
def choose_template(service_id, template_type):
    if template_type not in ['email', 'sms']:
        abort(404)
    return render_template(
        'views/templates/choose.html',
        templates=[
            Template(template,
                     prefix=current_service['name'],
                     sms_sender=current_service['sms_sender']) for template in
            service_api_client.get_service_templates(service_id)['data']
            if template['template_type'] == template_type
        ],
        template_type=template_type,
        page_heading=get_page_headings(template_type))
Exemplo n.º 16
0
def send_test(service_id, template_id):

    file_name = current_app.config['TEST_MESSAGE_FILENAME']

    template = Template(service_api_client.get_service_template(
        service_id, template_id)['data'],
                        prefix=current_service['name'],
                        sms_sender=current_service['sms_sender'])

    if len(template.placeholders) == 0 or request.method == 'POST':
        upload_id = s3upload(
            service_id, {
                'file_name':
                file_name,
                'data':
                Spreadsheet.from_rows([
                    [first_column_heading[template.template_type]] +
                    list(template.placeholders),
                    get_example_csv_rows(template,
                                         use_example_as_example=False,
                                         submitted_fields=request.form)
                ]).as_csv_data
            }, current_app.config['AWS_REGION'])
        session['upload_data'] = {
            "template_id": template_id,
            "original_file_name": file_name
        }
        return redirect(
            url_for('.check_messages',
                    upload_id=upload_id,
                    service_id=service_id,
                    template_type=template.template_type,
                    from_test=True,
                    help=2 if request.args.get('help') else 0))

    return render_template(
        'views/send-test.html',
        template=template,
        recipient_column=first_column_heading[template.template_type],
        example=[get_example_csv_rows(template, use_example_as_example=False)],
        help=get_help_argument())
Exemplo n.º 17
0
def view_job(service_id, job_id):
    job = job_api_client.get_job(service_id, job_id)['data']

    if job['job_status'] == 'cancelled':
        abort(404)

    filter_args = _parse_filter_args(request.args)
    filter_args['status'] = _set_status_filters(filter_args)

    total_notifications = job.get('notification_count', 0)
    processed_notifications = job.get('notifications_delivered', 0) + job.get('notifications_failed', 0)

    return render_template(
        'views/jobs/job.html',
        finished=(total_notifications == processed_notifications),
        uploaded_file_name=job['original_file_name'],
        template=Template(
            service_api_client.get_service_template(
                service_id=service_id,
                template_id=job['template'],
                version=job['template_version']
            )['data'],
            prefix=current_service['name'],
            sms_sender=current_service['sms_sender']
        ),
        status=request.args.get('status', ''),
        updates_url=url_for(
            ".view_job_updates",
            service_id=service_id,
            job_id=job['id'],
            status=request.args.get('status', ''),
            help=get_help_argument()
        ),
        partials=get_job_partials(job),
        help=get_help_argument()
    )
Exemplo n.º 18
0
def send_messages(service_id, template_id):
    template = Template(service_api_client.get_service_template(
        service_id, template_id)['data'],
                        prefix=current_service['name'],
                        sms_sender=current_service['sms_sender'])

    form = CsvUploadForm()
    if form.validate_on_submit():
        try:
            upload_id = s3upload(
                service_id,
                Spreadsheet.from_file(
                    form.file.data, filename=form.file.data.filename).as_dict,
                current_app.config['AWS_REGION'])
            session['upload_data'] = {
                "template_id": template_id,
                "original_file_name": form.file.data.filename
            }
            return redirect(
                url_for('.check_messages',
                        service_id=service_id,
                        upload_id=upload_id,
                        template_type=template.template_type))
        except (UnicodeDecodeError, BadZipFile, XLRDError):
            flash(
                'Couldn’t read {}. Try using a different file format.'.format(
                    form.file.data.filename))

    return render_template(
        'views/send.html',
        template=template,
        column_headings=list(ascii_uppercase[:len(template.placeholders) + 1]),
        example=[[first_column_heading[template.template_type]] +
                 list(template.placeholders),
                 get_example_csv_rows(template)],
        form=form)
Exemplo n.º 19
0
def styleguide():

    if not current_app.config["SHOW_STYLEGUIDE"]:
        abort(404)

    class FormExamples(Form):
        username = StringField("Username")
        password = PasswordField("Password", [validators.required()])
        code = StringField("Enter code")
        message = TextAreaField("Message")
        file_upload = FileField(
            "Upload a CSV file to add your recipients’ details")

    sms = "Your vehicle tax for ((registration number)) is due on ((date)). Renew online at www.gov.uk/vehicle-tax"

    form = FormExamples()
    form.message.data = sms
    form.validate()

    template = Template({"content": sms})

    return render_template("views/styleguide.html",
                           form=form,
                           template=template)
Exemplo n.º 20
0
import pytest
from notifications_utils.template import Template
from notifications_utils.template_change import TemplateChange


@pytest.mark.parametrize("old_template, new_template, should_differ", [
    (Template({'content': '((1)) ((2)) ((3))'
               }), Template({'content': '((1)) ((2)) ((3))'}), False),
    (Template({'content': '((1)) ((2)) ((3))'
               }), Template({'content': '((3)) ((2)) ((1))'}), False),
    (Template({'content': '((1)) ((2)) ((3))'}),
     Template({'content': '((1)) ((1)) ((2)) ((2)) ((3)) ((3))'}), False),
    (Template({'content': '((1))'}), Template({'content': '((1)) ((2))'
                                               }), True),
    (Template({'content': '((1)) ((2))'}), Template({'content': '((1))'
                                                     }), True),
    (Template({'content': '((a)) ((b))'
               }), Template({'content': '((A)) (( B_ ))'}), False),
])
def test_checking_for_difference_between_templates(old_template, new_template,
                                                   should_differ):
    assert TemplateChange(
        old_template, new_template).has_different_placeholders == should_differ


@pytest.mark.parametrize("old_template, new_template, placeholders_added", [
    (Template({'content': '((1)) ((2)) ((3))'
               }), Template({'content': '((1)) ((2)) ((3))'}), set()),
    (Template({'content': '((1)) ((2)) ((3))'}),
     Template({'content': '((1)) ((1)) ((2)) ((2)) ((3)) ((3))'}), set()),
    (Template({'content': '((1)) ((2)) ((3))'}), Template({'content': '((1))'
Exemplo n.º 21
0
def test_errors_for_missing_template_content():
    with pytest.raises(KeyError):
        Template({})
Exemplo n.º 22
0
def test_errors_for_invalid_template_types(template):
    with pytest.raises(TypeError):
        Template(template)
Exemplo n.º 23
0
def check_messages(service_id, template_type, upload_id):

    if not session.get('upload_data'):
        return redirect(
            url_for('main.choose_template',
                    service_id=service_id,
                    template_type=template_type))

    users = user_api_client.get_users_for_service(service_id=service_id)

    statistics = service_api_client.get_detailed_service_for_today(
        service_id)['data']['statistics']
    remaining_messages = (current_service['message_limit'] -
                          sum(stat['requested']
                              for stat in statistics.values()))

    contents = s3download(service_id, upload_id)
    if not contents:
        flash('There was a problem reading your upload file')

    template = Template(service_api_client.get_service_template(
        service_id, session['upload_data'].get('template_id'))['data'],
                        prefix=current_service['name'],
                        sms_sender=current_service['sms_sender'])

    recipients = RecipientCSV(
        contents,
        template_type=template.template_type,
        placeholders=template.placeholders,
        max_initial_rows_shown=50,
        max_errors_shown=50,
        whitelist=itertools.chain.from_iterable(
            [user.mobile_number, user.email_address]
            for user in users) if current_service['restricted'] else None,
        remaining_messages=remaining_messages)

    if request.args.get('from_test'):
        extra_args = {
            'help': 1
        } if request.args.get('help', '0') != '0' else {}
        if len(template.placeholders):
            back_link = url_for('.send_test',
                                service_id=service_id,
                                template_id=template.id,
                                **extra_args)
        else:
            back_link = url_for('.choose_template',
                                service_id=service_id,
                                template_type=template.template_type,
                                **extra_args)
        choose_time_form = None
    else:
        back_link = url_for('.send_messages',
                            service_id=service_id,
                            template_id=template.id)
        choose_time_form = ChooseTimeForm()

    with suppress(StopIteration):
        template.values = next(recipients.rows)
        first_recipient = template.values.get(
            recipients.recipient_column_header, '')

    session['upload_data']['notification_count'] = len(list(recipients.rows))
    session['upload_data']['valid'] = not recipients.has_errors
    return render_template(
        'views/check.html',
        recipients=recipients,
        first_recipient=first_recipient,
        template=template,
        errors=recipients.has_errors,
        row_errors=get_errors_for_csv(recipients, template.template_type),
        count_of_recipients=session['upload_data']['notification_count'],
        count_of_displayed_recipients=(
            len(list(recipients.initial_annotated_rows_with_errors))
            if any(recipients.rows_with_errors)
            and not recipients.missing_column_headers else len(
                list(recipients.initial_annotated_rows))),
        original_file_name=session['upload_data'].get('original_file_name'),
        upload_id=upload_id,
        form=CsvUploadForm(),
        remaining_messages=remaining_messages,
        choose_time_form=choose_time_form,
        back_link=back_link,
        help=get_help_argument())
Exemplo n.º 24
0
def test_errors_for_invalid_values(values):
    with pytest.raises(TypeError):
        Template({"content": ''}, values)
Exemplo n.º 25
0
def test_class():
    assert repr(Template({"content": "hello ((name))"
                          })) == 'Template("hello ((name))", {})'
Exemplo n.º 26
0
 def __call__(self, form, field):
     if ',' in ''.join(Template({'content': field.data}).placeholders):
         raise ValidationError(self.message)
Exemplo n.º 27
0
def test_random_variable_retrieve():
    template = Template({"content": "content", "template_type": "sms", "created_by": "now"})
    assert template.get_raw("created_by") == "now"
    assert template.get_raw("missing", default="random") == "random"
    assert template.get_raw("missing") is None
Exemplo n.º 28
0
def test_compare_template():
    with patch("notifications_utils.template.TemplateChange.__init__", return_value=None) as mocked:
        old_template = Template({"content": "faked", "template_type": "sms"})
        new_template = Template({"content": "faked", "template_type": "sms"})
        template_changes = old_template.compare_to(new_template)
        mocked.assert_called_once_with(old_template, new_template)
Exemplo n.º 29
0
def view_template_version(service_id, template_id, version):
    return render_template('views/templates/template_history.html',
                           template=Template(
                               service_api_client.get_service_template(
                                   service_id, template_id, version)['data'],
                               prefix=current_service['name']))
Exemplo n.º 30
0
def view_template(service_id, template_id):
    return render_template('views/templates/template.html',
                           template=Template(
                               service_api_client.get_service_template(
                                   service_id, template_id)['data'],
                               prefix=current_service['name']))
Exemplo n.º 31
0
def check_messages(service_id, template_type, upload_id):

    if not session.get('upload_data'):
        return redirect(url_for('main.choose_template', service_id=service_id, template_type=template_type))

    users = user_api_client.get_users_for_service(service_id=service_id)
    today = datetime.utcnow().date().strftime('%Y-%m-%d')

    statistics = statistics_api_client.get_statistics_for_service_for_day(service_id, today)
    if not statistics:
        statistics = {}

    contents = s3download(service_id, upload_id)
    if not contents:
        flash('There was a problem reading your upload file')

    template = service_api_client.get_service_template(
        service_id,
        session['upload_data'].get('template_id')
    )['data']

    template = Template(
        template,
        prefix=current_service['name']
    )

    recipients = RecipientCSV(
        contents,
        template_type=template.template_type,
        placeholders=template.placeholders,
        max_initial_rows_shown=50,
        max_errors_shown=50,
        whitelist=itertools.chain.from_iterable(
            [user.mobile_number, user.email_address] for user in users
        ) if current_service['restricted'] else None
    )

    if request.args.get('from_test'):
        extra_args = {'help': 1} if request.args.get('help', '0') != '0' else {}
        if len(template.placeholders):
            back_link = url_for(
                '.send_test', service_id=service_id, template_id=template.id, **extra_args
            )
        else:
            back_link = url_for(
                '.choose_template', service_id=service_id, template_type=template.template_type, **extra_args
            )
    else:
        back_link = url_for('.send_messages', service_id=service_id, template_id=template.id)

    with suppress(StopIteration):
        template.values = next(recipients.rows)
        first_recipient = template.values.get(recipients.recipient_column_header, '')

    session['upload_data']['notification_count'] = len(list(recipients.rows))
    session['upload_data']['valid'] = not recipients.has_errors
    return render_template(
        'views/check.html',
        recipients=recipients,
        first_recipient=first_recipient,
        template=template,
        errors=recipients.has_errors,
        row_errors=get_errors_for_csv(recipients, template.template_type),
        count_of_recipients=session['upload_data']['notification_count'],
        count_of_displayed_recipients=(
            len(list(recipients.initial_annotated_rows_with_errors))
            if any(recipients.rows_with_errors) and not recipients.missing_column_headers else
            len(list(recipients.initial_annotated_rows))
        ),
        original_file_name=session['upload_data'].get('original_file_name'),
        upload_id=upload_id,
        form=CsvUploadForm(),
        statistics=statistics,
        back_link=back_link,
        help=get_help_argument()
    )