mirror of
https://github.com/GSA/notifications-admin.git
synced 2026-04-06 18:41:25 -04:00
Merge branch 'master' into new-api-for-deleting-templates
This commit is contained in:
3
.gitignore
vendored
3
.gitignore
vendored
@@ -70,3 +70,6 @@ app/templates/govuk_template.html
|
||||
npm-debug.log
|
||||
|
||||
environment.sh
|
||||
.envrc
|
||||
|
||||
app/version.py
|
||||
|
||||
@@ -18,6 +18,7 @@ after_success:
|
||||
- coveralls
|
||||
- ./scripts/trigger-dependent-build.sh
|
||||
script:
|
||||
- make generate-version-file
|
||||
- npm run build
|
||||
- ./scripts/run_tests.sh
|
||||
notifications:
|
||||
@@ -88,7 +89,6 @@ deploy:
|
||||
region: eu-west-1
|
||||
on: *2
|
||||
before_deploy:
|
||||
- ./scripts/update_version_file.sh
|
||||
- rm -rf node_modules bower_components app/assets
|
||||
- zip -r --exclude=*__pycache__* notifications-admin *
|
||||
- mkdir -p dpl_cd_upload
|
||||
|
||||
128
Makefile
Normal file
128
Makefile
Normal file
@@ -0,0 +1,128 @@
|
||||
.DEFAULT_GOAL := help
|
||||
SHELL := /bin/bash
|
||||
DATE = $(shell date +%Y-%m-%d:%H:%M:%S)
|
||||
|
||||
PIP_ACCEL_CACHE ?= ${CURDIR}/cache/pip-accel
|
||||
APP_VERSION_FILE = app/version.py
|
||||
|
||||
GIT_BRANCH = $(shell git symbolic-ref --short HEAD 2> /dev/null || echo "detached")
|
||||
GIT_COMMIT ?= $(shell git rev-parse HEAD)
|
||||
|
||||
DOCKER_BUILDER_IMAGE_NAME = govuk/notify-admin-builder
|
||||
|
||||
BUILD_TAG ?= notifications-admin-manual
|
||||
BUILD_NUMBER ?= 0
|
||||
DEPLOY_BUILD_NUMBER ?= ${BUILD_NUMBER}
|
||||
BUILD_URL ?=
|
||||
|
||||
DOCKER_CONTAINER_PREFIX = ${USER}-${BUILD_TAG}
|
||||
|
||||
.PHONY: help
|
||||
help:
|
||||
@cat $(MAKEFILE_LIST) | grep -E '^[a-zA-Z_-]+:.*?## .*$$' | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}'
|
||||
|
||||
.PHONY: venv
|
||||
venv: venv/bin/activate ## Create virtualenv if it does not exist
|
||||
|
||||
venv/bin/activate:
|
||||
test -d venv || virtualenv venv
|
||||
./venv/bin/pip install pip-accel
|
||||
|
||||
.PHONY: check-env-vars
|
||||
check-env-vars: ## Check mandatory environment variables
|
||||
$(if ${DEPLOY_ENV},,$(error Must specify DEPLOY_ENV))
|
||||
$(if ${DNS_NAME},,$(error Must specify DNS_NAME))
|
||||
$(if ${AWS_ACCESS_KEY_ID},,$(error Must specify AWS_ACCESS_KEY_ID))
|
||||
$(if ${AWS_SECRET_ACCESS_KEY},,$(error Must specify AWS_SECRET_ACCESS_KEY))
|
||||
|
||||
.PHONY: development
|
||||
development: ## Set environment to development
|
||||
$(eval export DEPLOY_ENV=development)
|
||||
$(eval export DNS_NAME="notify.works")
|
||||
@true
|
||||
|
||||
.PHONY: staging
|
||||
staging: ## Set environment to staging
|
||||
$(eval export DEPLOY_ENV=staging)
|
||||
$(eval export DNS_NAME="staging-notify.works")
|
||||
@true
|
||||
|
||||
.PHONY: production
|
||||
production: ## Set environment to production
|
||||
$(eval export DEPLOY_ENV=production)
|
||||
$(eval export DNS_NAME="notifications.service.gov.uk")
|
||||
@true
|
||||
|
||||
.PHONY: dependencies
|
||||
dependencies: venv ## Install build dependencies
|
||||
npm set progress=false
|
||||
npm install
|
||||
npm rebuild node-sass
|
||||
mkdir -p ${PIP_ACCEL_CACHE}
|
||||
PIP_ACCEL_CACHE=${PIP_ACCEL_CACHE} ./venv/bin/pip-accel install -r requirements_for_test.txt
|
||||
|
||||
.PHONY: generate-version-file
|
||||
generate-version-file: ## Generates the app version file
|
||||
@echo -e "__travis_commit__ = \"${GIT_COMMIT}\"\n__time__ = \"${DATE}\"\n__travis_job_number__ = \"${BUILD_NUMBER}\"\n__travis_job_url__ = \"${BUILD_URL}\"" > ${APP_VERSION_FILE}
|
||||
|
||||
.PHONY: build
|
||||
build: dependencies generate-version-file ## Build project
|
||||
npm run build
|
||||
|
||||
.PHONY: build-codedeploy-artifact
|
||||
build-codedeploy-artifact: ## Build the deploy artifact for CodeDeploy
|
||||
mkdir -p target
|
||||
zip -r -x@deploy-exclude.lst target/notifications-admin.zip *
|
||||
|
||||
.PHONY: upload-codedeploy-artifact ## Upload the deploy artifact for CodeDeploy
|
||||
upload-codedeploy-artifact: check-env-vars
|
||||
aws s3 cp --region eu-west-1 target/notifications-admin.zip s3://${DNS_NAME}-codedeploy/notifications-admin-${DEPLOY_BUILD_NUMBER}.zip
|
||||
|
||||
.PHONY: test
|
||||
test: venv ## Run tests
|
||||
./scripts/run_tests.sh
|
||||
|
||||
.PHONY: deploy
|
||||
deploy: check-env-vars ## Upload deploy artifacts to S3 and trigger CodeDeploy
|
||||
aws deploy create-deployment --application-name notify-admin --deployment-config-name CodeDeployDefault.OneAtATime --deployment-group-name notify-admin --s3-location bucket=${DNS_NAME}-codedeploy,key=notifications-admin-${DEPLOY_BUILD_NUMBER}.zip,bundleType=zip --region eu-west-1
|
||||
|
||||
.PHONY: coverage
|
||||
coverage: venv ## Create coverage report
|
||||
./venv/bin/coveralls
|
||||
|
||||
.PHONY: prepare-docker-build-image
|
||||
prepare-docker-build-image: ## Prepare the Docker builder image
|
||||
mkdir -p ${PIP_ACCEL_CACHE}
|
||||
make -C docker build-build-image
|
||||
|
||||
.PHONY: build-with-docker
|
||||
build-with-docker: prepare-docker-build-image ## Build inside a Docker container
|
||||
docker run -i --rm \
|
||||
--name "${DOCKER_CONTAINER_PREFIX}-build" \
|
||||
-v `pwd`:/var/project \
|
||||
-v ${PIP_ACCEL_CACHE}:/var/project/cache/pip-accel \
|
||||
${DOCKER_BUILDER_IMAGE_NAME} \
|
||||
make build
|
||||
|
||||
.PHONY: test-with-docker
|
||||
test-with-docker: prepare-docker-build-image ## Run tests inside a Docker container
|
||||
docker run -i --rm \
|
||||
--name "${DOCKER_CONTAINER_PREFIX}-test" \
|
||||
-v `pwd`:/var/project \
|
||||
${DOCKER_BUILDER_IMAGE_NAME} \
|
||||
make test
|
||||
|
||||
.PHONY: coverage-with-docker
|
||||
coverage-with-docker: prepare-docker-build-image ## Generates coverage report inside a Docker container
|
||||
docker run -i --rm \
|
||||
--name "${DOCKER_CONTAINER_PREFIX}-coverage" \
|
||||
-v `pwd`:/var/project \
|
||||
${DOCKER_BUILDER_IMAGE_NAME} \
|
||||
make coverage
|
||||
|
||||
.PHONY: clean-docker-containers
|
||||
clean-docker-containers: ## Clean up any remaining docker containers
|
||||
docker rm -f $(shell docker ps -q -f "name=${DOCKER_CONTAINER_PREFIX}") 2> /dev/null || true
|
||||
|
||||
clean:
|
||||
rm -rf node_modules cache target venv .coverage
|
||||
@@ -337,7 +337,7 @@ class ServiceSmsSender(Form):
|
||||
def validate_sms_sender(form, field):
|
||||
import re
|
||||
if field.data and not re.match('^[a-zA-Z0-9\s]+$', field.data):
|
||||
raise ValidationError('Sms text message sender can only contain alpha-numeric characters')
|
||||
raise ValidationError('Text message sender can only contain alpha-numeric characters')
|
||||
|
||||
|
||||
class ServiceBrandingOrg(Form):
|
||||
|
||||
@@ -66,11 +66,12 @@ def template_history(service_id):
|
||||
template_statistics = aggregate_usage(
|
||||
template_statistics_client.get_template_statistics_for_service(service_id)
|
||||
)
|
||||
|
||||
return render_template(
|
||||
'views/dashboard/all-template-statistics.html',
|
||||
template_statistics=template_statistics,
|
||||
most_used_template_count=max(
|
||||
[row['usage_count'] for row in template_statistics] or [0]
|
||||
[row['count'] for row in template_statistics] or [0]
|
||||
)
|
||||
)
|
||||
|
||||
@@ -98,31 +99,9 @@ def weekly(service_id):
|
||||
|
||||
|
||||
def aggregate_usage(template_statistics):
|
||||
|
||||
immutable_template = namedtuple('Template', ['template_type', 'name', 'id'])
|
||||
|
||||
# grouby requires the list to be sorted by template first
|
||||
statistics_sorted_by_template = sorted(
|
||||
(
|
||||
(
|
||||
immutable_template(**row['template']),
|
||||
row['usage_count']
|
||||
)
|
||||
for row in template_statistics
|
||||
),
|
||||
key=lambda items: items[0]
|
||||
)
|
||||
|
||||
# then group and sort the result by usage
|
||||
return sorted(
|
||||
(
|
||||
{
|
||||
'usage_count': sum(usage[1] for usage in usages),
|
||||
'template': template
|
||||
}
|
||||
for template, usages in groupby(statistics_sorted_by_template, lambda items: items[0])
|
||||
),
|
||||
key=lambda row: row['usage_count'],
|
||||
template_statistics,
|
||||
key=lambda template_statistic: template_statistic['count'],
|
||||
reverse=True
|
||||
)
|
||||
|
||||
@@ -149,7 +128,7 @@ def get_dashboard_partials(service_id):
|
||||
'views/dashboard/template-statistics.html',
|
||||
template_statistics=template_statistics,
|
||||
most_used_template_count=max(
|
||||
[row['usage_count'] for row in template_statistics] or [0]
|
||||
[row['count'] for row in template_statistics] or [0]
|
||||
),
|
||||
),
|
||||
'has_template_statistics': bool(template_statistics),
|
||||
|
||||
@@ -16,12 +16,14 @@ class TemplateStatisticsApiClient(BaseAPIClient):
|
||||
params = {}
|
||||
if limit_days is not None:
|
||||
params['limit_days'] = limit_days
|
||||
|
||||
return self.get(
|
||||
url='/service/{}/template-statistics'.format(service_id),
|
||||
params=params
|
||||
)['data']
|
||||
|
||||
def get_template_statistics_for_template(self, service_id, template_id):
|
||||
|
||||
return self.get(
|
||||
url='/service/{}/template-statistics/{}'.format(service_id, template_id)
|
||||
)['data']
|
||||
|
||||
@@ -10,9 +10,6 @@
|
||||
<div class="column-half">
|
||||
<h2 class="heading-large">Templates sent</h2>
|
||||
</div>
|
||||
<div class="column-half">
|
||||
<span class="align-with-heading-copy">1 April 2016 to date</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% include 'views/dashboard/template-statistics.html' %}
|
||||
|
||||
@@ -17,18 +17,18 @@
|
||||
) %}
|
||||
{% call row_heading() %}
|
||||
<span class="spark-bar-label">
|
||||
<a href="{{ url_for('.view_template', service_id=current_service.id, template_id=item.template.id) }}">{{ item.template.name }}</a>
|
||||
<a href="{{ url_for('.view_template', service_id=current_service.id, template_id=item.template_id) }}">{{ item.template_name }}</a>
|
||||
<span class="file-list-hint">
|
||||
{{ message_count_label(1, item.template.template_type, suffix='template')|capitalize }}
|
||||
{{ message_count_label(1, item.template_type, suffix='template')|capitalize }}
|
||||
</span>
|
||||
</span>
|
||||
{% endcall %}
|
||||
{% call field() %}
|
||||
{% if template_statistics|length > 1 %}
|
||||
<span class="spark-bar">
|
||||
<span style="width: {{ item.usage_count / most_used_template_count * 100 }}%">
|
||||
<span style="width: {{ item.count / most_used_template_count * 100 }}%">
|
||||
{{ big_number(
|
||||
item.usage_count,
|
||||
item.count,
|
||||
smallest=True
|
||||
) }}
|
||||
</span>
|
||||
@@ -36,7 +36,7 @@
|
||||
{% else %}
|
||||
<span class="heading-small">
|
||||
{{ big_number(
|
||||
item.usage_count,
|
||||
item.count,
|
||||
smallest=True
|
||||
) }}
|
||||
</span>
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
{% block maincolumn_content %}
|
||||
|
||||
<h1 class="heading-large">Check your email</h1>
|
||||
<p>We’ve sent an email to {{ session['user_details']['email'] }}.</p>
|
||||
<p>An email has been sent to {{ session['user_details']['email'] }}.</p>
|
||||
<p>Click the link in the email to continue your registration.</p>
|
||||
|
||||
{% endblock %}
|
||||
|
||||
@@ -12,7 +12,7 @@ Check your mobile number – GOV.UK Notify
|
||||
<div class="column-two-thirds">
|
||||
<h1 class="heading-large">Check your mobile number</h1>
|
||||
|
||||
<p>Check your mobile phone number is correct and then resend the confirmation code.</p>
|
||||
<p>Check your mobile phone number is correct and then resend the security code.</p>
|
||||
|
||||
<p>
|
||||
<label class="form-label" for="mobile">Mobile phone number</label>
|
||||
@@ -21,7 +21,7 @@ Check your mobile number – GOV.UK Notify
|
||||
|
||||
|
||||
<p>
|
||||
<a class="button" href="verify-mobile" role="button">Resend confirmation code</a>
|
||||
<a class="button" href="verify-mobile" role="button">Resend security code</a>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -12,11 +12,11 @@ Check your mobile number – GOV.UK Notify
|
||||
<div class="column-two-thirds">
|
||||
<h1 class="heading-large">Check your mobile number</h1>
|
||||
|
||||
<p>Check your mobile phone number is correct and then resend the confirmation code.</p>
|
||||
<p>Check your mobile phone number is correct and then resend the security code.</p>
|
||||
|
||||
<form autocomplete="off" method="post">
|
||||
{{ textbox(form.mobile_number) }}
|
||||
{{ page_footer("Resend confirmation code") }}
|
||||
{{ page_footer("Resend security code") }}
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -13,7 +13,7 @@ GOV.UK Notify | Service settings
|
||||
<div class="grid-row">
|
||||
<div class="column-three-quarters">
|
||||
<p>
|
||||
We’ve sent a code to your new {{ thing }}.
|
||||
We’ve sent a security code to your new {{ thing }}.
|
||||
</p>
|
||||
<form method="post">
|
||||
{{ textbox(form_field) }}
|
||||
|
||||
@@ -10,7 +10,7 @@ Confirm your mobile number – GOV.UK Notify
|
||||
<div class="column-two-thirds">
|
||||
<h1 class="heading-large">Confirm your mobile number</h1>
|
||||
|
||||
<p>We’ve sent you a security code by text message.</p>
|
||||
<p>We’ve sent you a security code by text message.</p>
|
||||
|
||||
<p>
|
||||
<label class="form-label" for="email">Enter security code<br>
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
__travis_commit__ = ""
|
||||
__time__ = "2016-07-05:14:44:52"
|
||||
__time__ = ""
|
||||
__travis_job_number__ = ""
|
||||
__travis_job_url__ = ""
|
||||
16
appspec.yml
16
appspec.yml
@@ -1,11 +1,11 @@
|
||||
---
|
||||
files:
|
||||
-
|
||||
---
|
||||
files:
|
||||
-
|
||||
destination: /home/notify-app/notifications-admin
|
||||
source: /
|
||||
hooks:
|
||||
AfterInstall:
|
||||
-
|
||||
hooks:
|
||||
AfterInstall:
|
||||
-
|
||||
location: scripts/aws_install_dependencies.sh
|
||||
runas: root
|
||||
timeout: 300
|
||||
@@ -27,11 +27,9 @@ hooks:
|
||||
location: scripts/deregister_from_elb.sh
|
||||
runas: ubuntu
|
||||
timeout: 300
|
||||
-
|
||||
-
|
||||
location: scripts/aws_stop_app.sh
|
||||
runas: root
|
||||
timeout: 300
|
||||
os: linux
|
||||
version: 0.0
|
||||
|
||||
|
||||
|
||||
9
deploy-exclude.lst
Normal file
9
deploy-exclude.lst
Normal file
@@ -0,0 +1,9 @@
|
||||
*__pycache__*
|
||||
*.git*
|
||||
*app/assets*
|
||||
*bower_components*
|
||||
*cache*
|
||||
*docker*
|
||||
*node_modules*
|
||||
*target*
|
||||
*venv*
|
||||
36
docker/Dockerfile-build
Normal file
36
docker/Dockerfile-build
Normal file
@@ -0,0 +1,36 @@
|
||||
FROM python:3.4-slim
|
||||
|
||||
ENV PYTHONUNBUFFERED=1 \
|
||||
DEBIAN_FRONTEND=noninteractive \
|
||||
NODEJS_VERSION=6.3.1-1nodesource1~jessie1
|
||||
|
||||
RUN \
|
||||
echo "Install base packages" \
|
||||
&& apt-get update \
|
||||
&& apt-get install -y --no-install-recommends \
|
||||
apt-transport-https \
|
||||
make \
|
||||
curl \
|
||||
git \
|
||||
build-essential \
|
||||
libxml2-dev \
|
||||
libxslt-dev \
|
||||
zlib1g-dev \
|
||||
zip \
|
||||
rlwrap \
|
||||
|
||||
&& echo "Install nodejs" \
|
||||
&& cd /tmp \
|
||||
&& curl -sSLO https://deb.nodesource.com/node_6.x/pool/main/n/nodejs/nodejs_${NODEJS_VERSION}_amd64.deb \
|
||||
&& dpkg -i /tmp/nodejs_${NODEJS_VERSION}_amd64.deb \
|
||||
|
||||
&& echo "Clean up" \
|
||||
&& rm -rf /var/lib/apt/lists/* /tmp/*
|
||||
|
||||
RUN \
|
||||
echo "Install global pip packages" \
|
||||
&& pip install \
|
||||
virtualenv \
|
||||
awscli
|
||||
|
||||
WORKDIR /var/project
|
||||
10
docker/Makefile
Normal file
10
docker/Makefile
Normal file
@@ -0,0 +1,10 @@
|
||||
.DEFAULT_GOAL := help
|
||||
SHELL := /bin/bash
|
||||
|
||||
.PHONY: help
|
||||
help:
|
||||
@cat $(MAKEFILE_LIST) | grep -E '^[a-zA-Z_-]+:.*?## .*$$' | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}'
|
||||
|
||||
.PHONY: build-build-image
|
||||
build-build-image:
|
||||
docker build -f Dockerfile-build -t govuk/notify-admin-builder .
|
||||
@@ -183,7 +183,7 @@ get_instance_health_elb() {
|
||||
;;
|
||||
*)
|
||||
msg "Instance '$instance_id' not part of ELB '$elb_name'"
|
||||
return 0
|
||||
return 1
|
||||
esac
|
||||
fi
|
||||
}
|
||||
@@ -345,3 +345,40 @@ get_instance_id() {
|
||||
curl -s http://169.254.169.254/latest/meta-data/instance-id
|
||||
return $?
|
||||
}
|
||||
|
||||
# Usage: get_instance_name_from_tags <instance_id>
|
||||
#
|
||||
# Looks up tags for the given instance, extracting the 'name'
|
||||
# returns <name> or error_exit
|
||||
get_instance_name_from_tags() {
|
||||
local instance_id=$1
|
||||
|
||||
local instance_name=$($AWS_CLI ec2 describe-tags \
|
||||
--filters "Name=resource-id,Values=${instance_id}" \
|
||||
--query Tags[0].Value \
|
||||
--output text)
|
||||
if [ $? != 0 ]; then
|
||||
error_exit "Couldn't get instance name for '$instance_id'"
|
||||
fi
|
||||
echo $instance_name
|
||||
return $?
|
||||
}
|
||||
|
||||
ELB_NAME=""
|
||||
|
||||
get_elb_name_for_instance_name() {
|
||||
local instance_name=$1
|
||||
|
||||
declare -A elb_to_instance_mapping
|
||||
|
||||
elb_to_instance_mapping['notify-admin']='notify-admin'
|
||||
|
||||
elb_to_instance_mapping['notify_admin']='notify-admin-elb'
|
||||
|
||||
local elb_name=${elb_to_instance_mapping[${instance_name}]}
|
||||
if [ -z $elb_name ]; then
|
||||
msg "No ELB for instance ${instance_name}"
|
||||
else
|
||||
ELB_NAME=$elb_name
|
||||
fi
|
||||
}
|
||||
|
||||
@@ -28,7 +28,9 @@ msg "Started $(basename $0) at $(/bin/date "+%F %T")"
|
||||
start_sec=$(/bin/date +%s.%N)
|
||||
|
||||
msg "Getting relevant load balancer"
|
||||
get_elb_list $INSTANCE_ID "notify-admin-elb"
|
||||
INSTANCE_NAME=$(get_instance_name_from_tags $INSTANCE_ID)
|
||||
get_elb_name_for_instance_name $INSTANCE_NAME
|
||||
get_elb_list $INSTANCE_ID $ELB_NAME
|
||||
|
||||
msg "Checking that user set at least one load balancer"
|
||||
if test -z "$ELB_LIST"; then
|
||||
|
||||
@@ -28,8 +28,10 @@ msg "Started $(basename $0) at $(/bin/date "+%F %T")"
|
||||
start_sec=$(/bin/date +%s.%N)
|
||||
|
||||
msg "Getting relevant load balancer"
|
||||
get_elb_list $INSTANCE_ID "notify-admin-elb"
|
||||
|
||||
INSTANCE_NAME=$(get_instance_name_from_tags $INSTANCE_ID)
|
||||
get_elb_name_for_instance_name $INSTANCE_NAME
|
||||
ELB_LIST=$ELB_NAME
|
||||
get_elb_list $INSTANCE_ID $ELB_NAME
|
||||
|
||||
msg "Checking that user set at least one load balancer"
|
||||
if test -z "$ELB_LIST"; then
|
||||
|
||||
@@ -24,6 +24,9 @@ function display_result {
|
||||
fi
|
||||
}
|
||||
|
||||
if [ -d venv ]; then
|
||||
source ./venv/bin/activate
|
||||
fi
|
||||
pep8 .
|
||||
display_result $? 1 "Code style check"
|
||||
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
#!/bin/bash
|
||||
#
|
||||
# Update the version file of the project from the Travis build details
|
||||
#
|
||||
sed -i -e "s/__travis_commit__ =.*/__travis_commit__ = \"$TRAVIS_COMMIT\"/g" ./app/version.py
|
||||
sed -i -e "s/__travis_job_number__ =.*/__travis_job_number__ = \"$TRAVIS_BUILD_NUMBER\"/g" ./app/version.py
|
||||
sed -i -e "s/__time__ =.*/__time__ = \"$(date +%Y-%m-%d:%H:%M:%S)\"/g" ./app/version.py
|
||||
@@ -141,4 +141,4 @@ def test_sms_sender_form_validation(app_, mock_get_user_by_email):
|
||||
|
||||
form.sms_sender.data = '###########'
|
||||
form.validate()
|
||||
assert 'Sms text message sender can only contain alpha-numeric characters' == form.errors['sms_sender'][0]
|
||||
assert 'Text message sender can only contain alpha-numeric characters' == form.errors['sms_sender'][0]
|
||||
|
||||
@@ -66,7 +66,7 @@ def test_should_render_correct_resend_template_for_pending_user(app_,
|
||||
page = BeautifulSoup(response.data.decode('utf-8'), 'html.parser')
|
||||
assert page.h1.string == 'Check your mobile number'
|
||||
|
||||
expected = 'Check your mobile phone number is correct and then resend the confirmation code.'
|
||||
expected = 'Check your mobile phone number is correct and then resend the security code.'
|
||||
message = page.find_all('p')[1].text
|
||||
assert message == expected
|
||||
assert page.find('form').input['value'] == api_user_pending.mobile_number
|
||||
|
||||
@@ -11,70 +11,36 @@ from app.main.views.dashboard import get_dashboard_totals, format_weekly_stats_t
|
||||
from tests import validate_route_permission
|
||||
from tests.conftest import SERVICE_ONE_ID
|
||||
|
||||
|
||||
stub_template_stats = [
|
||||
{
|
||||
'template': {
|
||||
'name': 'Brine Shrimp',
|
||||
'template_type': 'sms',
|
||||
'id': 1
|
||||
},
|
||||
'id': '6005e192-4738-4962-beec-ebd982d0b03f',
|
||||
'day': '2016-04-06',
|
||||
'usage_count': 6,
|
||||
'service': '1491b86f-c950-48f5-bed1-2a55df027ecb'
|
||||
'template_type': 'sms',
|
||||
'template_name': 'one',
|
||||
'template_id': 'id-1',
|
||||
'count': 100
|
||||
},
|
||||
{
|
||||
'template': {
|
||||
'name': 'Pickle feet',
|
||||
'template_type': 'sms',
|
||||
'id': 2
|
||||
},
|
||||
'id': '0bd529cd-a0fd-43e5-80ee-b95ef6b0d51f',
|
||||
'day': '2016-04-06',
|
||||
'usage_count': 6,
|
||||
'service': '1491b86f-c950-48f5-bed1-2a55df027ecb'
|
||||
},
|
||||
{
|
||||
'template': {
|
||||
'name': 'Brine Shrimp',
|
||||
'template_type': 'sms',
|
||||
'id': 1
|
||||
},
|
||||
'id': '24531628-ffff-4082-a443-9f6db5af83d9',
|
||||
'day': '2016-04-05',
|
||||
'usage_count': 7,
|
||||
'service': '1491b86f-c950-48f5-bed1-2a55df027ecb'
|
||||
},
|
||||
{
|
||||
'template': {
|
||||
'name': 'Pickle feet',
|
||||
'template_type': 'sms',
|
||||
'id': 2
|
||||
},
|
||||
'id': '0bd529cd-a0fd-43e5-80ee-b95ef6b0d51f',
|
||||
'day': '2016-03-06',
|
||||
'usage_count': 200,
|
||||
'service': '1491b86f-c950-48f5-bed1-2a55df027ecb'
|
||||
},
|
||||
'template_type': 'email',
|
||||
'template_name': 'two',
|
||||
'template_id': 'id-2',
|
||||
'count': 200
|
||||
}
|
||||
]
|
||||
|
||||
|
||||
def test_get_started(
|
||||
app_,
|
||||
mocker,
|
||||
api_user_active,
|
||||
mock_get_service,
|
||||
mock_get_service_templates_when_no_templates_exist,
|
||||
mock_get_user,
|
||||
mock_get_user_by_email,
|
||||
mock_login,
|
||||
mock_get_jobs,
|
||||
mock_has_permissions,
|
||||
mock_get_detailed_service,
|
||||
mock_get_usage
|
||||
app_,
|
||||
mocker,
|
||||
api_user_active,
|
||||
mock_get_service,
|
||||
mock_get_service_templates_when_no_templates_exist,
|
||||
mock_get_user,
|
||||
mock_get_user_by_email,
|
||||
mock_login,
|
||||
mock_get_jobs,
|
||||
mock_has_permissions,
|
||||
mock_get_detailed_service,
|
||||
mock_get_usage
|
||||
):
|
||||
|
||||
mock_template_stats = mocker.patch('app.template_statistics_client.get_template_statistics_for_service',
|
||||
return_value=copy.deepcopy(stub_template_stats))
|
||||
|
||||
@@ -83,24 +49,23 @@ def test_get_started(
|
||||
response = client.get(url_for('main.service_dashboard', service_id=SERVICE_ONE_ID))
|
||||
|
||||
# mock_get_service_templates_when_no_templates_exist.assert_called_once_with(SERVICE_ONE_ID)
|
||||
print(response.get_data(as_text=True))
|
||||
assert response.status_code == 200
|
||||
assert 'Get started' in response.get_data(as_text=True)
|
||||
|
||||
|
||||
def test_get_started_is_hidden_once_templates_exist(
|
||||
app_,
|
||||
mocker,
|
||||
api_user_active,
|
||||
mock_get_service,
|
||||
mock_get_service_templates,
|
||||
mock_get_user,
|
||||
mock_get_user_by_email,
|
||||
mock_login,
|
||||
mock_get_jobs,
|
||||
mock_has_permissions,
|
||||
mock_get_detailed_service,
|
||||
mock_get_usage
|
||||
app_,
|
||||
mocker,
|
||||
api_user_active,
|
||||
mock_get_service,
|
||||
mock_get_service_templates,
|
||||
mock_get_user,
|
||||
mock_get_user_by_email,
|
||||
mock_login,
|
||||
mock_get_jobs,
|
||||
mock_has_permissions,
|
||||
mock_get_detailed_service,
|
||||
mock_get_usage
|
||||
):
|
||||
mock_template_stats = mocker.patch('app.template_statistics_client.get_template_statistics_for_service',
|
||||
return_value=copy.deepcopy(stub_template_stats))
|
||||
@@ -125,7 +90,6 @@ def test_should_show_recent_templates_on_dashboard(app_,
|
||||
mock_has_permissions,
|
||||
mock_get_detailed_service,
|
||||
mock_get_usage):
|
||||
|
||||
mock_template_stats = mocker.patch('app.template_statistics_client.get_template_statistics_for_service',
|
||||
return_value=copy.deepcopy(stub_template_stats))
|
||||
|
||||
@@ -147,28 +111,27 @@ def test_should_show_recent_templates_on_dashboard(app_,
|
||||
|
||||
assert len(table_rows) == 2
|
||||
|
||||
assert 'Pickle feet' in table_rows[0].find_all('th')[0].text
|
||||
assert 'Text message template' in table_rows[0].find_all('th')[0].text
|
||||
assert '206' in table_rows[0].find_all('td')[0].text
|
||||
assert 'two' in table_rows[0].find_all('th')[0].text
|
||||
assert 'Email template' in table_rows[0].find_all('th')[0].text
|
||||
assert '200' in table_rows[0].find_all('td')[0].text
|
||||
|
||||
assert 'Brine Shrimp' in table_rows[1].find_all('th')[0].text
|
||||
assert 'one' in table_rows[1].find_all('th')[0].text
|
||||
assert 'Text message template' in table_rows[1].find_all('th')[0].text
|
||||
assert '13' in table_rows[1].find_all('td')[0].text
|
||||
assert '100' in table_rows[1].find_all('td')[0].text
|
||||
|
||||
|
||||
def test_should_show_all_templates_on_template_statistics_page(
|
||||
app_,
|
||||
mocker,
|
||||
api_user_active,
|
||||
mock_get_service,
|
||||
mock_get_service_templates,
|
||||
mock_get_user,
|
||||
mock_get_user_by_email,
|
||||
mock_login,
|
||||
mock_get_jobs,
|
||||
mock_has_permissions
|
||||
app_,
|
||||
mocker,
|
||||
api_user_active,
|
||||
mock_get_service,
|
||||
mock_get_service_templates,
|
||||
mock_get_user,
|
||||
mock_get_user_by_email,
|
||||
mock_login,
|
||||
mock_get_jobs,
|
||||
mock_has_permissions
|
||||
):
|
||||
|
||||
mock_template_stats = mocker.patch('app.template_statistics_client.get_template_statistics_for_service',
|
||||
return_value=copy.deepcopy(stub_template_stats))
|
||||
|
||||
@@ -186,32 +149,31 @@ def test_should_show_all_templates_on_template_statistics_page(
|
||||
|
||||
assert len(table_rows) == 2
|
||||
|
||||
assert 'Pickle feet' in table_rows[0].find_all('th')[0].text
|
||||
assert 'Text message template' in table_rows[0].find_all('th')[0].text
|
||||
assert '206' in table_rows[0].find_all('td')[0].text
|
||||
assert 'two' in table_rows[0].find_all('th')[0].text
|
||||
assert 'Email template' in table_rows[0].find_all('th')[0].text
|
||||
assert '200' in table_rows[0].find_all('td')[0].text
|
||||
|
||||
assert 'Brine Shrimp' in table_rows[1].find_all('th')[0].text
|
||||
assert 'one' in table_rows[1].find_all('th')[0].text
|
||||
assert 'Text message template' in table_rows[1].find_all('th')[0].text
|
||||
assert '13' in table_rows[1].find_all('td')[0].text
|
||||
assert '100' in table_rows[1].find_all('td')[0].text
|
||||
|
||||
|
||||
@freeze_time("2016-01-01 11:09:00.061258")
|
||||
def test_should_show_recent_jobs_on_dashboard(
|
||||
app_,
|
||||
mocker,
|
||||
api_user_active,
|
||||
mock_get_service,
|
||||
mock_get_service_templates,
|
||||
mock_get_user,
|
||||
mock_get_user_by_email,
|
||||
mock_login,
|
||||
mock_get_template_statistics,
|
||||
mock_get_detailed_service,
|
||||
mock_get_jobs,
|
||||
mock_has_permissions,
|
||||
mock_get_usage
|
||||
app_,
|
||||
mocker,
|
||||
api_user_active,
|
||||
mock_get_service,
|
||||
mock_get_service_templates,
|
||||
mock_get_user,
|
||||
mock_get_user_by_email,
|
||||
mock_login,
|
||||
mock_get_template_statistics,
|
||||
mock_get_detailed_service,
|
||||
mock_get_jobs,
|
||||
mock_has_permissions,
|
||||
mock_get_usage
|
||||
):
|
||||
|
||||
with app_.test_request_context(), app_.test_client() as client:
|
||||
client.login(api_user_active)
|
||||
response = client.get(url_for('main.service_dashboard', service_id=SERVICE_ONE_ID))
|
||||
@@ -226,10 +188,10 @@ def test_should_show_recent_jobs_on_dashboard(
|
||||
assert len(table_rows) == 4
|
||||
|
||||
for index, filename in enumerate((
|
||||
"export 1/1/2016.xls",
|
||||
"all email addresses.xlsx",
|
||||
"applicants.ods",
|
||||
"thisisatest.csv",
|
||||
"export 1/1/2016.xls",
|
||||
"all email addresses.xlsx",
|
||||
"applicants.ods",
|
||||
"thisisatest.csv",
|
||||
)):
|
||||
assert filename in table_rows[index].find_all('th')[0].text
|
||||
assert 'Uploaded 1 January at 11:09' in table_rows[index].find_all('th')[0].text
|
||||
@@ -259,7 +221,6 @@ def test_menu_send_messages(mocker,
|
||||
mock_get_template_statistics,
|
||||
mock_get_detailed_service,
|
||||
mock_get_usage):
|
||||
|
||||
with app_.test_request_context():
|
||||
resp = _test_dashboard_menu(
|
||||
mocker,
|
||||
@@ -271,11 +232,11 @@ def test_menu_send_messages(mocker,
|
||||
assert url_for(
|
||||
'main.choose_template',
|
||||
service_id=service_one['id'],
|
||||
template_type='email')in page
|
||||
template_type='email') in page
|
||||
assert url_for(
|
||||
'main.choose_template',
|
||||
service_id=service_one['id'],
|
||||
template_type='sms')in page
|
||||
template_type='sms') in page
|
||||
assert url_for('main.manage_users', service_id=service_one['id']) in page
|
||||
|
||||
assert url_for('main.service_settings', service_id=service_one['id']) not in page
|
||||
@@ -408,11 +369,14 @@ def test_aggregate_template_stats():
|
||||
expected = aggregate_usage(copy.deepcopy(stub_template_stats))
|
||||
|
||||
assert len(expected) == 2
|
||||
for item in expected:
|
||||
if item['template'].id == 1:
|
||||
assert item['usage_count'] == 13
|
||||
elif item['template'].id == 2:
|
||||
assert item['usage_count'] == 206
|
||||
assert expected[0]['template_name'] == 'two'
|
||||
assert expected[0]['count'] == 200
|
||||
assert expected[0]['template_id'] == 'id-2'
|
||||
assert expected[0]['template_type'] == 'email'
|
||||
assert expected[1]['template_name'] == 'one'
|
||||
assert expected[1]['count'] == 100
|
||||
assert expected[1]['template_id'] == 'id-1'
|
||||
assert expected[1]['template_type'] == 'sms'
|
||||
|
||||
|
||||
def test_service_dashboard_updates_gets_dashboard_totals(mocker,
|
||||
|
||||
@@ -1068,16 +1068,11 @@ def mock_remove_user_from_service(mocker):
|
||||
def mock_get_template_statistics(mocker, service_one, fake_uuid):
|
||||
template = template_json(service_one['id'], fake_uuid, "Test template", "sms", "Something very interesting")
|
||||
data = {
|
||||
"usage_count": 1,
|
||||
"template": {
|
||||
"name": template['name'],
|
||||
"template_type": template['template_type'],
|
||||
"id": template['id']
|
||||
},
|
||||
"service": template['service'],
|
||||
"id": str(generate_uuid()),
|
||||
"day": "2016-04-04",
|
||||
"updated_at": "2016-04-04T12:00:00.000000+00:00"
|
||||
"count": 1,
|
||||
"template_name": template['name'],
|
||||
"template_type": template['template_type'],
|
||||
"template_id": template['id'],
|
||||
"day": "2016-04-04"
|
||||
}
|
||||
|
||||
def _get_stats(service_id, limit_days=None):
|
||||
|
||||
Reference in New Issue
Block a user