diff --git a/app/main/views/dashboard.py b/app/main/views/dashboard.py
index def963624..5b9c6988d 100644
--- a/app/main/views/dashboard.py
+++ b/app/main/views/dashboard.py
@@ -1,6 +1,4 @@
from datetime import datetime, timedelta
-from collections import namedtuple
-from itertools import groupby
import dateutil
from flask import (
@@ -20,7 +18,7 @@ from app import (
service_api_client,
template_statistics_client
)
-from app.statistics_utils import add_rates_to, get_formatted_percentage, add_rate_to_jobs
+from app.statistics_utils import get_formatted_percentage, add_rate_to_job
from app.utils import user_has_permissions
@@ -117,20 +115,21 @@ def aggregate_usage(template_statistics):
def get_dashboard_partials(service_id):
+ # all but scheduled and cancelled
+ statuses_to_display = job_api_client.JOB_STATUSES - {'scheduled', 'cancelled'}
template_statistics = aggregate_usage(
template_statistics_client.get_template_statistics_for_service(service_id, limit_days=7)
)
- jobs = add_rate_to_jobs([
- job for job in job_api_client.get_job(service_id, limit_days=7)['data']
- if job['original_file_name'] != current_app.config['TEST_MESSAGE_FILENAME']
- ])
- scheduled_jobs = sorted([
- job for job in jobs if job['job_status'] == 'scheduled'
- ], key=lambda job: job['scheduled_for'])
+ scheduled_jobs = sorted(
+ job_api_client.get_jobs(service_id, statuses=['scheduled'])['data'],
+ key=lambda job: job['scheduled_for']
+ )
immediate_jobs = [
- job for job in jobs if job['job_status'] not in ['scheduled', 'cancelled']
+ add_rate_to_job(job)
+ for job in job_api_client.get_jobs(service_id, statuses=statuses_to_display)['data']
+ if job['original_file_name'] != current_app.config['TEST_MESSAGE_FILENAME']
]
service = service_api_client.get_detailed_service(service_id)
diff --git a/app/main/views/jobs.py b/app/main/views/jobs.py
index 756394bcc..9cdf91824 100644
--- a/app/main/views/jobs.py
+++ b/app/main/views/jobs.py
@@ -1,8 +1,6 @@
# -*- coding: utf-8 -*-
import ago
-import time
import dateutil
-import json
from orderedset import OrderedSet
from datetime import datetime, timedelta, timezone
from itertools import chain
@@ -29,11 +27,13 @@ from app import (
from app.main import main
from app.utils import (
get_page_from_request,
- generate_previous_next_dict,
+ generate_next_dict,
+ generate_previous_dict,
user_has_permissions,
- generate_notifications_csv)
-from app.statistics_utils import add_rate_to_jobs
-from app.utils import get_help_argument
+ generate_notifications_csv,
+ get_help_argument
+)
+from app.statistics_utils import add_rate_to_job
def _parse_filter_args(filter_dict):
@@ -65,12 +65,28 @@ def _set_status_filters(filter_args):
@login_required
@user_has_permissions('view_activity', admin_override=True)
def view_jobs(service_id):
+ page = int(request.args.get('page', 1))
+ # all but scheduled and cancelled
+ statuses_to_display = job_api_client.JOB_STATUSES - {'scheduled', 'cancelled'}
+ jobs_response = job_api_client.get_jobs(service_id, statuses=statuses_to_display, page=page)
+ jobs = [
+ add_rate_to_job(job) for job in jobs_response['data']
+ if job['original_file_name'] != current_app.config['TEST_MESSAGE_FILENAME']
+ ]
+
+ prev_page = None
+ if jobs_response['links'].get('prev', None):
+ prev_page = generate_previous_dict('main.view_jobs', service_id, page)
+ next_page = None
+ if jobs_response['links'].get('next', None):
+ next_page = generate_next_dict('main.view_jobs', service_id, page)
+
return render_template(
'views/jobs/jobs.html',
- jobs=add_rate_to_jobs([
- job for job in job_api_client.get_job(service_id)['data']
- if job['job_status'] not in ['scheduled', 'cancelled']
- ])
+ jobs=jobs,
+ page=page,
+ prev_page=prev_page,
+ next_page=next_page,
)
@@ -205,28 +221,18 @@ def get_notifications(service_id, message_type, status_override=None):
template_type=[message_type],
status=filter_args.get('status'),
limit_days=current_app.config['ACTIVITY_STATS_LIMIT_DAYS'])
- view_dict = dict(
- message_type=message_type,
- status=request.args.get('status')
- )
+
+ url_args = {
+ 'message_type': message_type,
+ 'status': request.args.get('status')
+ }
prev_page = None
if notifications['links'].get('prev', None):
- prev_page = generate_previous_next_dict(
- 'main.view_notifications',
- service_id,
- view_dict,
- page - 1,
- 'Previous page',
- 'page {}'.format(page - 1))
+ prev_page = generate_previous_dict('main.view_notifications', service_id, page, url_args=url_args)
next_page = None
if notifications['links'].get('next', None):
- next_page = generate_previous_next_dict(
- 'main.view_notifications',
- service_id,
- view_dict,
- page + 1,
- 'Next page',
- 'page {}'.format(page + 1))
+ next_page = generate_next_dict('main.view_notifications', service_id, page, url_args)
+
if request.path.endswith('csv'):
csv_content = generate_notifications_csv(
notification_api_client.get_notifications_for_service(
diff --git a/app/notify_client/job_api_client.py b/app/notify_client/job_api_client.py
index 614a01560..4ec07bc8f 100644
--- a/app/notify_client/job_api_client.py
+++ b/app/notify_client/job_api_client.py
@@ -5,6 +5,16 @@ from app.notify_client import _attach_current_user
class JobApiClient(BaseAPIClient):
+
+ JOB_STATUSES = {
+ 'scheduled',
+ 'pending',
+ 'in progress',
+ 'finished',
+ 'cancelled',
+ 'sending limits exceeded',
+ }
+
def __init__(self):
super().__init__("a", "b", "c")
@@ -26,24 +36,24 @@ class JobApiClient(BaseAPIClient):
results['requested'] += outcome['count']
return results
- def get_job(self, service_id, job_id=None, limit_days=None, status=None):
- if job_id:
- params = {}
- if status is not None:
- params['status'] = status
- job = self.get(url='/service/{}/job/{}'.format(service_id, job_id), params=params)
-
- stats = self.__convert_statistics(job['data'])
- job['data']['notifications_sent'] = stats['delivered'] + stats['failed']
- job['data']['notifications_delivered'] = stats['delivered']
- job['data']['notifications_failed'] = stats['failed']
- job['data']['notifications_requested'] = stats['requested']
-
- return job
-
+ def get_job(self, service_id, job_id):
params = {}
+ job = self.get(url='/service/{}/job/{}'.format(service_id, job_id), params=params)
+
+ stats = self.__convert_statistics(job['data'])
+ job['data']['notifications_sent'] = stats['delivered'] + stats['failed']
+ job['data']['notifications_delivered'] = stats['delivered']
+ job['data']['notifications_failed'] = stats['failed']
+ job['data']['notifications_requested'] = stats['requested']
+
+ return job
+
+ def get_jobs(self, service_id, limit_days=None, statuses=None, page=1):
+ params = {'page': page}
if limit_days is not None:
params['limit_days'] = limit_days
+ if statuses is not None:
+ params['statuses'] = ','.join(statuses)
jobs = self.get(url='/service/{}/job'.format(service_id), params=params)
for job in jobs['data']:
diff --git a/app/statistics_utils.py b/app/statistics_utils.py
index 4581e069d..c9a08992e 100644
--- a/app/statistics_utils.py
+++ b/app/statistics_utils.py
@@ -74,17 +74,15 @@ def statistics_by_state(statistics):
def get_failure_rate_for_job(job):
if not job.get('notifications_delivered'):
- if job.get('notifications_failed'):
- return 1
- return 0
+ return 1 if job.get('notifications_failed') else 0
return (
job.get('notifications_failed', 0) /
(job.get('notifications_failed', 0) + job.get('notifications_delivered', 0))
)
-def add_rate_to_jobs(jobs):
- return [dict(
+def add_rate_to_job(job):
+ return dict(
failure_rate=(get_failure_rate_for_job(job)) * 100,
**job
- ) for job in jobs]
+ )
diff --git a/app/templates/components/previous-next-navigation.html b/app/templates/components/previous-next-navigation.html
index 9704ea939..525555396 100644
--- a/app/templates/components/previous-next-navigation.html
+++ b/app/templates/components/previous-next-navigation.html
@@ -8,7 +8,7 @@
- {% endif %}
+ {% endif %}
{% if next_page %}
@@ -19,4 +19,4 @@
{% endif %}
-{% endmacro %}
\ No newline at end of file
+{% endmacro %}
diff --git a/app/templates/views/jobs/jobs.html b/app/templates/views/jobs/jobs.html
index 7745a241b..8c9441c20 100644
--- a/app/templates/views/jobs/jobs.html
+++ b/app/templates/views/jobs/jobs.html
@@ -1,3 +1,4 @@
+{% from "components/previous-next-navigation.html" import previous_next_navigation %}
{% extends "withnav_template.html" %}
{% block page_title %}
@@ -8,5 +9,6 @@
Uploaded files
{% include 'views/dashboard/_jobs.html' %}
+ {{ previous_next_navigation(prev_page, next_page) }}
{% endblock %}
diff --git a/app/utils.py b/app/utils.py
index 98178fd7f..4c8750f39 100644
--- a/app/utils.py
+++ b/app/utils.py
@@ -118,21 +118,26 @@ def get_page_from_request():
return 1
-def generate_previous_next_dict(view, service_id, view_dict, page, title, label):
- if 'page' in view_dict:
- view_dict.pop('page')
- if 'service_id' in view_dict:
- view_dict.pop('service_id')
+def generate_previous_dict(view, service_id, page, url_args=None):
+ return generate_previous_next_dict(view, service_id, page - 1, 'Previous page', url_args or {})
+
+
+def generate_next_dict(view, service_id, page, url_args=None):
+ return generate_previous_next_dict(view, service_id, page + 1, 'Next page', url_args or {})
+
+
+def generate_previous_next_dict(view, service_id, page, title, url_args):
return {
- 'url': url_for(view, service_id=service_id, page=page, **view_dict),
+ 'url': url_for(view, service_id=service_id, page=page, **url_args),
'title': title,
- 'label': label
+ 'label': 'page {}'.format(page)
}
def email_safe(string):
return "".join([
- character.lower() if character.isalnum() or character == "." else "" for character in re.sub("\s+", ".", string.strip()) # noqa
+ character.lower() if character.isalnum() or character == "." else ""
+ for character in re.sub(r"\s+", ".", string.strip())
])
diff --git a/tests/__init__.py b/tests/__init__.py
index ff56bce5a..e23f597b5 100644
--- a/tests/__init__.py
+++ b/tests/__init__.py
@@ -159,7 +159,7 @@ def job_json(
notification_count=1,
notifications_sent=1,
notifications_requested=1,
- job_status='Delivered',
+ job_status='finished',
scheduled_for=''
):
if job_id is None:
diff --git a/tests/app/main/views/test_dashboard.py b/tests/app/main/views/test_dashboard.py
index 8b3a008a9..8a1d8ae88 100644
--- a/tests/app/main/views/test_dashboard.py
+++ b/tests/app/main/views/test_dashboard.py
@@ -182,7 +182,10 @@ def test_should_show_upcoming_jobs_on_dashboard(
client.login(api_user_active)
response = client.get(url_for('main.service_dashboard', service_id=SERVICE_ONE_ID))
- mock_get_jobs.assert_called_once_with(SERVICE_ONE_ID, limit_days=7)
+ first_call = mock_get_jobs.call_args_list[0]
+ assert first_call[0] == (SERVICE_ONE_ID,)
+ assert first_call[1]['statuses'] == ['scheduled']
+
assert response.status_code == 200
page = BeautifulSoup(response.data.decode('utf-8'), 'html.parser')
@@ -218,7 +221,10 @@ def test_should_show_recent_jobs_on_dashboard(
client.login(api_user_active)
response = client.get(url_for('main.service_dashboard', service_id=SERVICE_ONE_ID))
- mock_get_jobs.assert_called_once_with(SERVICE_ONE_ID, limit_days=7)
+ second_call = mock_get_jobs.call_args_list[1]
+ assert second_call[0] == (SERVICE_ONE_ID,)
+ assert 'scheduled' not in second_call[1]['statuses']
+
assert response.status_code == 200
page = BeautifulSoup(response.data.decode('utf-8'), 'html.parser')
diff --git a/tests/app/main/views/test_jobs.py b/tests/app/main/views/test_jobs.py
index 2abbc9634..0f6d2146e 100644
--- a/tests/app/main/views/test_jobs.py
+++ b/tests/app/main/views/test_jobs.py
@@ -12,21 +12,38 @@ from tests import notification_json
from freezegun import freeze_time
-def test_should_return_list_of_all_jobs(app_,
- service_one,
- active_user_with_permissions,
- mock_get_jobs,
- mocker):
- with app_.test_request_context():
- with app_.test_client() as client:
- client.login(active_user_with_permissions, mocker, service_one)
- response = client.get(url_for('main.view_jobs', service_id=service_one['id']))
+def test_get_jobs_should_return_list_of_all_real_jobs(
+ client,
+ service_one,
+ active_user_with_permissions,
+ mock_get_jobs,
+ mocker
+):
+ client.login(active_user_with_permissions, mocker, service_one)
+ response = client.get(url_for('main.view_jobs', service_id=service_one['id']))
- assert response.status_code == 200
- page = BeautifulSoup(response.data.decode('utf-8'), 'html.parser')
- assert page.h1.string == 'Uploaded files'
- jobs = page.tbody.find_all('tr')
- assert len(jobs) == 5
+ assert response.status_code == 200
+ page = BeautifulSoup(response.data.decode('utf-8'), 'html.parser')
+ assert page.h1.string == 'Uploaded files'
+ jobs = [x.text for x in page.tbody.find_all('a', {'class': 'file-list-filename'})]
+ assert len(jobs) == 4
+ assert 'Test message' not in jobs
+
+
+def test_get_jobs_shows_page_links(
+ client,
+ service_one,
+ active_user_with_permissions,
+ mock_get_jobs,
+ mocker
+):
+ client.login(active_user_with_permissions, mocker, service_one)
+ response = client.get(url_for('main.view_jobs', service_id=service_one['id']))
+
+ assert response.status_code == 200
+ page = BeautifulSoup(response.data.decode('utf-8'), 'html.parser')
+ assert 'Next page' in page.find('li', {'class': 'next-page'}).text
+ assert 'Previous page' in page.find('li', {'class': 'previous-page'}).text
@pytest.mark.parametrize(
diff --git a/tests/app/notify_client/test_job_client.py b/tests/app/notify_client/test_job_client.py
index fe70f5809..02e6f740a 100644
--- a/tests/app/notify_client/test_job_client.py
+++ b/tests/app/notify_client/test_job_client.py
@@ -1,3 +1,6 @@
+import uuid
+from unittest.mock import ANY
+
from app.notify_client.job_api_client import JobApiClient
@@ -51,8 +54,6 @@ def test_client_schedules_job(mocker, fake_uuid):
def test_client_gets_job_by_service_and_job(mocker):
- mocker.patch('app.notify_client.current_user', id='1')
-
service_id = 'service_id'
job_id = 'job_id'
@@ -66,40 +67,24 @@ def test_client_gets_job_by_service_and_job(mocker):
mock_get.assert_called_once_with(url=expected_url, params={})
-def test_client_gets_job_by_service_and_job_filtered_by_status(mocker):
- mocker.patch('app.notify_client.current_user', id='1')
+def test_client_gets_jobs_with_status_filter(mocker):
+ mock_get = mocker.patch('app.notify_client.job_api_client.JobApiClient.get')
- service_id = 'service_id'
- job_id = 'job_id'
+ JobApiClient().get_jobs(uuid.uuid4(), statuses=['foo', 'bar'])
- expected_url = '/service/{}/job/{}'.format(service_id, job_id)
+ mock_get.assert_called_once_with(url=ANY, params={'page': 1, 'statuses': 'foo,bar'})
+
+def test_client_gets_jobs_with_page_parameter(mocker):
client = JobApiClient()
mock_get = mocker.patch('app.notify_client.job_api_client.JobApiClient.get')
- client.get_job(service_id, job_id, limit_days=1, status='failed')
+ client.get_jobs('foo', page=2)
- mock_get.assert_called_once_with(url=expected_url, params={'status': 'failed'})
-
-
-def test_client_gets_job_by_service_filtered_by_status(mocker):
- mocker.patch('app.notify_client.current_user', id='1')
-
- service_id = 'service_id'
-
- expected_url = '/service/{}/job'.format(service_id)
-
- client = JobApiClient()
- mock_get = mocker.patch('app.notify_client.job_api_client.JobApiClient.get')
-
- client.get_job(service_id, limit_days=1, status='failed')
-
- mock_get.assert_called_once_with(url=expected_url, params={'limit_days': 1})
+ mock_get.assert_called_once_with(url=ANY, params={'page': 2})
def test_client_parses_job_stats(mocker):
- mocker.patch('app.notify_client.current_user', id='1')
-
service_id = 'service_id'
job_id = 'job_id'
expected_data = {'data': {
@@ -145,8 +130,6 @@ def test_client_parses_job_stats(mocker):
def test_client_parses_empty_job_stats(mocker):
- mocker.patch('app.notify_client.current_user', id='1')
-
service_id = 'service_id'
job_id = 'job_id'
expected_data = {'data': {
@@ -183,8 +166,6 @@ def test_client_parses_empty_job_stats(mocker):
def test_client_parses_job_stats_for_service(mocker):
- mocker.patch('app.notify_client.current_user', id='1')
-
service_id = 'service_id'
job_1_id = 'job_id_1'
job_2_id = 'job_id_2'
@@ -247,9 +228,9 @@ def test_client_parses_job_stats_for_service(mocker):
client = JobApiClient()
mock_get = mocker.patch('app.notify_client.job_api_client.JobApiClient.get', return_value=expected_data)
- result = client.get_job(service_id)
+ result = client.get_jobs(service_id)
- mock_get.assert_called_once_with(url=expected_url, params={})
+ mock_get.assert_called_once_with(url=expected_url, params={'page': 1})
assert result['data'][0]['id'] == job_1_id
assert result['data'][0]['notifications_requested'] == 80
assert result['data'][0]['notifications_sent'] == 50
@@ -263,8 +244,6 @@ def test_client_parses_job_stats_for_service(mocker):
def test_client_parses_empty_job_stats_for_service(mocker):
- mocker.patch('app.notify_client.current_user', id='1')
-
service_id = 'service_id'
job_1_id = 'job_id_1'
job_2_id = 'job_id_2'
@@ -309,9 +288,9 @@ def test_client_parses_empty_job_stats_for_service(mocker):
client = JobApiClient()
mock_get = mocker.patch('app.notify_client.job_api_client.JobApiClient.get', return_value=expected_data)
- result = client.get_job(service_id)
+ result = client.get_jobs(service_id)
- mock_get.assert_called_once_with(url=expected_url, params={})
+ mock_get.assert_called_once_with(url=expected_url, params={'page': 1})
assert result['data'][0]['id'] == job_1_id
assert result['data'][0]['notifications_requested'] == 0
assert result['data'][0]['notifications_sent'] == 0
@@ -325,7 +304,6 @@ def test_client_parses_empty_job_stats_for_service(mocker):
def test_cancel_job(mocker):
-
mock_post = mocker.patch('app.notify_client.job_api_client.JobApiClient.post')
JobApiClient().cancel_job('service_id', 'job_id')
diff --git a/tests/app/test_statistics_utils.py b/tests/app/test_statistics_utils.py
index cb6b27db8..167ca8b15 100644
--- a/tests/app/test_statistics_utils.py
+++ b/tests/app/test_statistics_utils.py
@@ -1,6 +1,6 @@
import pytest
-from app.statistics_utils import sum_of_statistics, add_rates_to, add_rate_to_jobs, statistics_by_state
+from app.statistics_utils import sum_of_statistics, add_rates_to, add_rate_to_job, statistics_by_state
@pytest.mark.parametrize('delivery_statistics', [
@@ -118,20 +118,29 @@ def test_service_statistics_by_state():
@pytest.mark.parametrize('failed, delivered, expected_failure_rate', [
(0, 0, 0),
(0, 1, 0),
+ (1, 1, 50),
(1, 0, 100),
(1, 4, 20)
])
-def test_add_rate_to_jobs(failed, delivered, expected_failure_rate):
- resp = add_rate_to_jobs([
+def test_add_rate_to_job_calculates_rate(failed, delivered, expected_failure_rate):
+ resp = add_rate_to_job(
{
'notifications_failed': failed,
- 'notifications_delivered': delivered
- },
- {
- 'notifications_failed': 1,
- 'notifications_delivered': 1
+ 'notifications_delivered': delivered,
+ 'id': 'foo'
}
- ])
+ )
- assert resp[0]['failure_rate'] == expected_failure_rate
- assert resp[1]['failure_rate'] == 50
+ assert resp['failure_rate'] == expected_failure_rate
+
+
+def test_add_rate_to_job_preserves_initial_fields():
+ resp = add_rate_to_job(
+ {
+ 'notifications_failed': 0,
+ 'notifications_delivered': 0,
+ 'id': 'foo'
+ }
+ )
+
+ assert set(resp.keys()) == {'notifications_failed', 'notifications_delivered', 'id', 'failure_rate'}
diff --git a/tests/app/test_utils.py b/tests/app/test_utils.py
index dda4cfa0b..14495ab2d 100644
--- a/tests/app/test_utils.py
+++ b/tests/app/test_utils.py
@@ -1,6 +1,6 @@
import pytest
from io import StringIO
-from app.utils import email_safe, generate_notifications_csv
+from app.utils import email_safe, generate_notifications_csv, generate_previous_dict, generate_next_dict
from csv import DictReader
from freezegun import freeze_time
@@ -48,3 +48,22 @@ def test_generate_csv_from_notifications(
for row in DictReader(StringIO(csv_content)):
assert row['Time'] == 'Friday 01 January 2016 at 15:09'
assert row['Status'] == expected_status
+
+
+def test_generate_previous_dict(client):
+ ret = generate_previous_dict('main.view_jobs', 'foo', 2, {})
+ assert 'page=1' in ret['url']
+ assert ret['title'] == 'Previous page'
+ assert ret['label'] == 'page 1'
+
+
+def test_generate_next_dict(client):
+ ret = generate_next_dict('main.view_jobs', 'foo', 2, {})
+ assert 'page=3' in ret['url']
+ assert ret['title'] == 'Next page'
+ assert ret['label'] == 'page 3'
+
+
+def test_generate_previous_next_dict_adds_other_url_args(client):
+ ret = generate_next_dict('main.view_notifications', 'foo', 2, {'message_type': 'blah'})
+ assert 'notifications/blah' in ret['url']
diff --git a/tests/conftest.py b/tests/conftest.py
index 7ec1ba9f2..d43e7d2b2 100644
--- a/tests/conftest.py
+++ b/tests/conftest.py
@@ -901,8 +901,11 @@ def mock_get_job_in_progress(mocker, api_user_active):
@pytest.fixture(scope='function')
def mock_get_jobs(mocker, api_user_active):
- def _get_jobs(service_id, limit_days=None):
- return {"data": [
+ def _get_jobs(service_id, limit_days=None, statuses=None, page=1):
+ if statuses is None:
+ statuses = ['', 'scheduled', 'pending', 'cancelled']
+
+ jobs = [
job_json(
service_id,
api_user_active,
@@ -911,19 +914,25 @@ def mock_get_jobs(mocker, api_user_active):
job_status=job_status
)
for filename, scheduled_for, job_status in (
- ("Test message", '', ''),
- ("Test message", '2016-01-01 11:09:00.061258', 'scheduled'),
- ("export 1/1/2016.xls", '', ''),
- ("all email addresses.xlsx", '', 'pending'),
- ("applicants.ods", '', ''),
- ("thisisatest.csv", '', ''),
- ("send_me_later.csv", '2016-01-01 11:09:00.061258', 'scheduled'),
- ("even_later.csv", '2016-01-01 23:09:00.061258', 'scheduled'),
- ("full_of_regret.csv", '2016-01-01 23:09:00.061258', 'cancelled')
+ ('Test message', '', 'finished'),
+ ('export 1/1/2016.xls', '', 'finished'),
+ ('all email addresses.xlsx', '', 'pending'),
+ ('applicants.ods', '', 'finished'),
+ ('thisisatest.csv', '', 'finished'),
+ ('send_me_later.csv', '2016-01-01 11:09:00.061258', 'scheduled'),
+ ('even_later.csv', '2016-01-01 23:09:00.061258', 'scheduled'),
+ ('full_of_regret.csv', '2016-01-01 23:09:00.061258', 'cancelled')
)
- ]}
+ ]
+ return {
+ 'data': [job for job in jobs if job['job_status'] in statuses],
+ 'links': {
+ 'prev': 'services/{}/jobs?page={}'.format(service_id, page - 1),
+ 'next': 'services/{}/jobs?page={}'.format(service_id, page + 1)
+ }
+ }
- return mocker.patch('app.job_api_client.get_job', side_effect=_get_jobs)
+ return mocker.patch('app.job_api_client.get_jobs', side_effect=_get_jobs)
@pytest.fixture(scope='function')