mirror of
https://github.com/GSA/notifications-admin.git
synced 2026-08-24 16:24:08 -04:00
Feedback page working with all tests passing.
Updated to include team id. Give Feedback -> Give feedback
This commit is contained in:
@@ -306,3 +306,10 @@ class CreateKeyForm(Form):
|
|||||||
def validate_key_name(self, key_name):
|
def validate_key_name(self, key_name):
|
||||||
if key_name.data.lower() in self.existing_key_names:
|
if key_name.data.lower() in self.existing_key_names:
|
||||||
raise ValidationError('A key with this name already exists')
|
raise ValidationError('A key with this name already exists')
|
||||||
|
|
||||||
|
|
||||||
|
class Feedback(Form):
|
||||||
|
|
||||||
|
name = StringField('Name')
|
||||||
|
email_address = StringField('Email address')
|
||||||
|
feedback = TextAreaField(u'', validators=[DataRequired(message="Can’t be empty")])
|
||||||
|
|||||||
@@ -1,8 +1,11 @@
|
|||||||
import markdown
|
import markdown
|
||||||
import os
|
import os
|
||||||
from flask import render_template, url_for, redirect, Markup
|
import requests
|
||||||
|
import json
|
||||||
|
from flask import (render_template, url_for, redirect, Markup, flash, current_app, abort)
|
||||||
from app.main import main
|
from app.main import main
|
||||||
from flask_login import login_required
|
from flask_login import login_required
|
||||||
|
from app.main.forms import Feedback
|
||||||
|
|
||||||
from flask.ext.login import current_user
|
from flask.ext.login import current_user
|
||||||
from mdx_gfm import GithubFlavoredMarkdownExtension
|
from mdx_gfm import GithubFlavoredMarkdownExtension
|
||||||
@@ -41,6 +44,40 @@ def terms():
|
|||||||
return render_template('views/terms-of-use.html')
|
return render_template('views/terms-of-use.html')
|
||||||
|
|
||||||
|
|
||||||
|
@main.route('/feedback', methods=['GET', 'POST'])
|
||||||
|
def feedback():
|
||||||
|
form = Feedback()
|
||||||
|
if form.validate_on_submit():
|
||||||
|
data = {
|
||||||
|
'person_email': current_app.config.get('DESKPRO_PERSON_EMAIL'),
|
||||||
|
'agent_team_id': current_app.config.get('DESKPRO_TEAM_ID'),
|
||||||
|
'subject': 'Notify feedback',
|
||||||
|
'message': '{}\n{}\n{}'.format(
|
||||||
|
form.name.data,
|
||||||
|
form.email_address.data,
|
||||||
|
form.feedback.data)
|
||||||
|
}
|
||||||
|
headers = {
|
||||||
|
"X-DeskPRO-API-Key": current_app.config.get('DESKPRO_API_KEY'),
|
||||||
|
'Content-Type': "application/x-www-form-urlencoded"
|
||||||
|
}
|
||||||
|
resp = requests.post(
|
||||||
|
current_app.config.get('DESKPRO_API_HOST') + '/api/tickets',
|
||||||
|
data=data,
|
||||||
|
headers=headers)
|
||||||
|
if resp.status_code != 201:
|
||||||
|
current_app.logger.error(
|
||||||
|
"Deskpro create ticket request failed with {} '{}'".format(
|
||||||
|
resp.status_code,
|
||||||
|
resp.json())
|
||||||
|
)
|
||||||
|
abort(500, "Feedback submission failed")
|
||||||
|
flash("Your feedback has been submitted")
|
||||||
|
return redirect(url_for('.feedback'))
|
||||||
|
|
||||||
|
return render_template('views/feedback.html', form=form)
|
||||||
|
|
||||||
|
|
||||||
@main.route('/documentation')
|
@main.route('/documentation')
|
||||||
def documentation():
|
def documentation():
|
||||||
curr_dir = os.path.dirname(os.path.realpath(__file__))
|
curr_dir = os.path.dirname(os.path.realpath(__file__))
|
||||||
|
|||||||
@@ -78,7 +78,7 @@
|
|||||||
<div class="column-one-third">
|
<div class="column-one-third">
|
||||||
<h2>Contact</h2>
|
<h2>Contact</h2>
|
||||||
<ul>
|
<ul>
|
||||||
<li><a href="https://docs.google.com/forms/d/1AL8U-xJX_HAFEiQiJszGQw0PcEaEUnYATSntEghNDGo/viewform">Support and feedback</a></li>
|
<li><a href="{{ url_for('main.feedback') }}">Support and feedback</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<div class="column-one-third">
|
<div class="column-one-third">
|
||||||
|
|||||||
28
app/templates/views/feedback.html
Normal file
28
app/templates/views/feedback.html
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
{% extends "withoutnav_template.html" %}
|
||||||
|
{% from "components/textbox.html" import textbox %}
|
||||||
|
{% from "components/page-footer.html" import page_footer %}
|
||||||
|
|
||||||
|
{% block page_title %}
|
||||||
|
Feedback – GOV.UK Notify
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block maincolumn_content %}
|
||||||
|
|
||||||
|
<h1 class="heading-large">
|
||||||
|
Give feedback
|
||||||
|
</h1>
|
||||||
|
<div class="grid-row">
|
||||||
|
<div class="column-two-thirds">
|
||||||
|
<p>What went wrong, if anything? What went well? How could we improve this service?</p>
|
||||||
|
<form method="post">
|
||||||
|
{{ textbox(form.feedback, width='1-1', hint='', rows=10) }}
|
||||||
|
<h3 class="heading-medium">Do you want a reply?</h3>
|
||||||
|
<p>Leave your details below if you'd like a response.</p>
|
||||||
|
{{ textbox(form.name, width='1-1') }}
|
||||||
|
{{ textbox(form.email_address, width='1-1') }}
|
||||||
|
{{ page_footer('Send') }}
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{% endblock %}
|
||||||
@@ -36,6 +36,10 @@ class Config(object):
|
|||||||
TOKEN_MAX_AGE_SECONDS = 3600
|
TOKEN_MAX_AGE_SECONDS = 3600
|
||||||
WTF_CSRF_ENABLED = True
|
WTF_CSRF_ENABLED = True
|
||||||
CSV_UPLOAD_BUCKET_NAME = 'local-notifications-csv-upload'
|
CSV_UPLOAD_BUCKET_NAME = 'local-notifications-csv-upload'
|
||||||
|
DESKPRO_API_HOST = os.environ['DESKPRO_API_HOST']
|
||||||
|
DESKPRO_API_KEY = os.environ['DESKPRO_API_KEY']
|
||||||
|
DESKPRO_PERSON_EMAIL = os.environ['DESKPRO_PERSON_EMAIL']
|
||||||
|
DESKPRO_TEAM_ID = os.environ['DESKPRO_TEAM_ID']
|
||||||
|
|
||||||
EMAIL_DOMAIN_REGEXES = [
|
EMAIL_DOMAIN_REGEXES = [
|
||||||
"gov\.uk",
|
"gov\.uk",
|
||||||
|
|||||||
@@ -4,3 +4,7 @@ export ADMIN_CLIENT_USER_NAME='dev-notify-admin'
|
|||||||
export API_HOST_NAME='http://localhost:6311'
|
export API_HOST_NAME='http://localhost:6311'
|
||||||
export DANGEROUS_SALT='dev-notify-salt'
|
export DANGEROUS_SALT='dev-notify-salt'
|
||||||
export SECRET_KEY='dev-notify-secret-key'
|
export SECRET_KEY='dev-notify-secret-key'
|
||||||
|
export DESKPRO_API_HOST=""
|
||||||
|
export DESKPRO_API_KEY=""
|
||||||
|
export DESKPRO_PERSON_EMAIL=""
|
||||||
|
export DESKPRO_TEAM_ID=""
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
from flask import url_for
|
from flask import url_for
|
||||||
|
|
||||||
from bs4 import BeautifulSoup
|
from bs4 import BeautifulSoup
|
||||||
|
from unittest.mock import ANY
|
||||||
|
|
||||||
import app
|
import app
|
||||||
|
|
||||||
@@ -255,7 +256,6 @@ def test_new_user_accept_invite_completes_new_registration_redirects_to_verify(a
|
|||||||
assert response.status_code == 302
|
assert response.status_code == 302
|
||||||
assert response.location == expected_redirect_location
|
assert response.location == expected_redirect_location
|
||||||
|
|
||||||
from unittest.mock import ANY
|
|
||||||
mock_send_verify_code.assert_called_once_with(ANY, 'sms', data['mobile_number'])
|
mock_send_verify_code.assert_called_once_with(ANY, 'sms', data['mobile_number'])
|
||||||
|
|
||||||
mock_register_user.assert_called_with(data['name'],
|
mock_register_user.assert_called_with(data['name'],
|
||||||
|
|||||||
@@ -1,4 +1,7 @@
|
|||||||
from flask import url_for
|
import pytest
|
||||||
|
from flask import (url_for, current_app)
|
||||||
|
from werkzeug.exceptions import InternalServerError
|
||||||
|
from unittest.mock import Mock, ANY
|
||||||
|
|
||||||
|
|
||||||
def test_logged_in_user_redirects_to_choose_service(app_,
|
def test_logged_in_user_redirects_to_choose_service(app_,
|
||||||
@@ -14,3 +17,85 @@ def test_logged_in_user_redirects_to_choose_service(app_,
|
|||||||
|
|
||||||
response = client.get(url_for('main.sign_in', follow_redirects=True))
|
response = client.get(url_for('main.sign_in', follow_redirects=True))
|
||||||
assert response.location == url_for('main.choose_service', _external=True)
|
assert response.location == url_for('main.choose_service', _external=True)
|
||||||
|
|
||||||
|
|
||||||
|
def test_get_feedback_page(app_):
|
||||||
|
with app_.test_request_context():
|
||||||
|
with app_.test_client() as client:
|
||||||
|
resp = client.get(url_for('main.feedback'))
|
||||||
|
assert resp.status_code == 200
|
||||||
|
|
||||||
|
|
||||||
|
def test_post_feedback_with_no_name_email(app_, mocker):
|
||||||
|
mock_post = mocker.patch(
|
||||||
|
'app.main.views.index.requests.post',
|
||||||
|
return_value=Mock(status_code=201))
|
||||||
|
with app_.test_request_context():
|
||||||
|
with app_.test_client() as client:
|
||||||
|
resp = client.post(url_for('main.feedback'), data={'feedback': "blah"})
|
||||||
|
assert resp.status_code == 302
|
||||||
|
|
||||||
|
|
||||||
|
def test_post_feedback_with_no_name_email(app_, mocker):
|
||||||
|
mock_post = mocker.patch(
|
||||||
|
'app.main.views.index.requests.post',
|
||||||
|
return_value=Mock(status_code=201))
|
||||||
|
with app_.test_request_context():
|
||||||
|
with app_.test_client() as client:
|
||||||
|
resp = client.post(url_for('main.feedback'), data={'feedback': "blah"})
|
||||||
|
assert resp.status_code == 302
|
||||||
|
mock_post.assert_called_with(
|
||||||
|
ANY,
|
||||||
|
data={
|
||||||
|
'agent_team_id': ANY,
|
||||||
|
'subject': 'Notify feedback',
|
||||||
|
'message': '\n\nblah',
|
||||||
|
'person_email': ANY},
|
||||||
|
headers=ANY)
|
||||||
|
|
||||||
|
|
||||||
|
def test_post_feedback_with_name_email(app_, mocker):
|
||||||
|
mock_post = mocker.patch(
|
||||||
|
'app.main.views.index.requests.post',
|
||||||
|
return_value=Mock(status_code=201))
|
||||||
|
with app_.test_request_context():
|
||||||
|
with app_.test_client() as client:
|
||||||
|
resp = client.post(
|
||||||
|
url_for('main.feedback'),
|
||||||
|
data={'feedback': "blah", 'name': "Steve Irwin", 'email_address': 'rip@gmail.com'})
|
||||||
|
assert resp.status_code == 302
|
||||||
|
mock_post.assert_called_with(
|
||||||
|
ANY,
|
||||||
|
data={
|
||||||
|
'subject': 'Notify feedback',
|
||||||
|
'agent_team_id': ANY,
|
||||||
|
'message': 'Steve Irwin\nrip@gmail.com\nblah',
|
||||||
|
'person_email': ANY},
|
||||||
|
headers=ANY)
|
||||||
|
|
||||||
|
|
||||||
|
def test_log_error_on_post(app_, mocker):
|
||||||
|
mock_post = mocker.patch(
|
||||||
|
'app.main.views.index.requests.post',
|
||||||
|
return_value=Mock(
|
||||||
|
status_code=401,
|
||||||
|
json=lambda: {
|
||||||
|
'error_code': 'invalid_auth',
|
||||||
|
'error_message': 'Please provide a valid API key or token'}))
|
||||||
|
with app_.test_request_context():
|
||||||
|
mock_logger = mocker.patch.object(app_.logger, 'error')
|
||||||
|
with app_.test_client() as client:
|
||||||
|
with pytest.raises(InternalServerError):
|
||||||
|
resp = client.post(
|
||||||
|
url_for('main.feedback'),
|
||||||
|
data={'feedback': "blah", 'name': "Steve Irwin", 'email_address': 'rip@gmail.com'})
|
||||||
|
mock_post.assert_called_with(
|
||||||
|
ANY,
|
||||||
|
data={
|
||||||
|
'subject': 'Notify feedback',
|
||||||
|
'agent_team_id': ANY,
|
||||||
|
'message': 'Steve Irwin\nrip@gmail.com\nblah',
|
||||||
|
'person_email': ANY},
|
||||||
|
headers=ANY)
|
||||||
|
mock_logger.assert_called_with(
|
||||||
|
"Deskpro create ticket request failed with {} '{}'".format(mock_post().status_code, mock_post().json()))
|
||||||
|
|||||||
Reference in New Issue
Block a user