Project

General

Profile

0002-tests-separate-statistics-API-tests-57663.patch

Benjamin Dauvergne, 06 October 2021 10:17 PM

Download (20.8 KB)

View differences:

Subject: [PATCH 2/3] tests: separate statistics API tests (#57663)

 tests/api/test_misc.py       | 230 --------------------------------
 tests/api/test_statistics.py | 252 +++++++++++++++++++++++++++++++++++
 2 files changed, 252 insertions(+), 230 deletions(-)
 create mode 100644 tests/api/test_statistics.py
tests/api/test_misc.py
from django.utils.encoding import force_text
from django.utils.text import slugify
from requests.models import Response
from rest_framework import VERSION as drf_version
from authentic2.a2_rbac.models import Role
from authentic2.a2_rbac.utils import get_default_ou
from authentic2.apps.journal.models import Event, EventType
from authentic2.models import Attribute, AttributeValue, AuthorizedRole, Service
from authentic2.utils.misc import good_next_url
from django_rbac.models import SEARCH_OP
......
assert_event('manager.user.deletion', user=admin, api=True)
@pytest.mark.skipif(drf_version.startswith('3.4'), reason='no support for old django rest framework')
def test_api_statistics_list(app, admin):
OU = get_ou_model()
headers = basic_authorization_header(admin)
resp = app.get('/api/statistics/', headers=headers)
assert len(resp.json['data']) == 6
login_stats = {
'name': 'Login count by authentication type',
'url': 'http://testserver/api/statistics/login/',
'id': 'login',
'filters': [
{
"id": "time_interval",
"label": "Time interval",
"options": [
{"id": "day", "label": "Day"},
{"id": "month", "label": "Month"},
{"id": "year", "label": "Year"},
],
"required": True,
"default": "month",
},
{'id': 'service', 'label': 'Service', 'options': []},
],
}
assert login_stats in resp.json['data']
assert {
'name': 'Login count by service',
'url': 'http://testserver/api/statistics/service_login/',
'id': 'service-login',
'filters': [
{
"id": "time_interval",
"label": "Time interval",
"options": [
{"id": "day", "label": "Day"},
{"id": "month", "label": "Month"},
{"id": "year", "label": "Year"},
],
"required": True,
"default": "month",
},
],
} in resp.json['data']
service = Service.objects.create(name='Service1', slug='service1', ou=get_default_ou())
service = Service.objects.create(name='Service2', slug='service2', ou=get_default_ou())
login_stats['filters'][1]['options'].append({'id': 'service1 default', 'label': 'Service1'})
login_stats['filters'][1]['options'].append({'id': 'service2 default', 'label': 'Service2'})
resp = app.get('/api/statistics/', headers=headers)
assert login_stats in resp.json['data']
# adding second ou doesn't change anything
ou = OU.objects.create(name='Second OU', slug='second')
resp = app.get('/api/statistics/', headers=headers)
assert login_stats in resp.json['data']
# if there are services in two differents OUs, filter is shown
service.ou = ou
service.save()
login_stats['filters'][1]['options'][1]['id'] = 'service2 second'
login_stats['filters'].append(
{
'id': 'services_ou',
'label': 'Services organizational unit',
'options': [
{'id': 'default', 'label': 'Default organizational unit'},
{'id': 'second', 'label': 'Second OU'},
],
}
)
resp = app.get('/api/statistics/', headers=headers)
assert login_stats in resp.json['data']
# same goes with users
User.objects.create(username='john.doe', email='john.doe@example.com', ou=ou)
login_stats['filters'].append(
{
'id': 'users_ou',
'label': 'Users organizational unit',
'options': [
{'id': 'default', 'label': 'Default organizational unit'},
{'id': 'second', 'label': 'Second OU'},
],
}
)
resp = app.get('/api/statistics/', headers=headers)
assert login_stats in resp.json['data']
@pytest.mark.skipif(drf_version.startswith('3.4'), reason='no support for old django rest framework')
@pytest.mark.parametrize(
'event_type_name,event_name', [('user.login', 'login'), ('user.registration', 'registration')]
)
def test_api_statistics(app, admin, freezer, event_type_name, event_name):
OU = get_ou_model()
headers = basic_authorization_header(admin)
resp = app.get('/api/statistics/login/?time_interval=month', headers=headers)
assert resp.json == {"data": {"series": [], "x_labels": []}, "err": 0}
user = User.objects.create(username='john.doe', email='john.doe@example.com', ou=get_default_ou())
ou = OU.objects.create(name='Second OU', slug='second')
portal = Service.objects.create(name='portal', slug='portal', ou=ou)
agendas = Service.objects.create(name='agendas', slug='agendas', ou=get_default_ou())
method = {'how': 'password-on-https'}
method2 = {'how': 'fc'}
event_type = EventType.objects.get_for_name(event_type_name)
freezer.move_to('2020-02-03 12:00')
Event.objects.create(type=event_type, references=[portal], data=method)
Event.objects.create(type=event_type, references=[agendas, user], user=user, data=method)
freezer.move_to('2020-03-04 13:00')
Event.objects.create(type=event_type, references=[agendas], data=method)
Event.objects.create(type=event_type, references=[portal], data=method2)
resp = app.get('/api/statistics/%s/?time_interval=month' % event_name, headers=headers)
data = resp.json['data']
data['series'].sort(key=lambda x: x['label'])
assert data == {
'x_labels': ['2020-02', '2020-03'],
'series': [{'label': 'FranceConnect', 'data': [None, 1]}, {'label': 'password', 'data': [2, 1]}],
}
# default time interval is 'month'
month_data = data
resp = app.get('/api/statistics/%s/' % event_name, headers=headers)
data = resp.json['data']
data['series'].sort(key=lambda x: x['label'])
assert month_data == data
resp = app.get(
'/api/statistics/%s/?time_interval=month&services_ou=default' % event_name, headers=headers
)
data = resp.json['data']
data['series'].sort(key=lambda x: x['label'])
assert data == {
'x_labels': ['2020-02', '2020-03'],
'series': [{'label': 'password', 'data': [1, 1]}],
}
# legacy way to filter by service OU
services_ou_data = data
resp = app.get('/api/statistics/%s/?time_interval=month&ou=default' % event_name, headers=headers)
data = resp.json['data']
data['series'].sort(key=lambda x: x['label'])
assert services_ou_data == data
resp = app.get(
'/api/statistics/%s/?time_interval=month&users_ou=default&service=agendas default' % event_name,
headers=headers,
)
data = resp.json['data']
assert data == {
'x_labels': ['2020-02'],
'series': [{'label': 'password', 'data': [1]}],
}
resp = app.get('/api/statistics/%s/?time_interval=month&users_ou=default' % event_name, headers=headers)
data = resp.json['data']
assert data == {'x_labels': ['2020-02'], 'series': [{'label': 'password', 'data': [1]}]}
resp = app.get(
'/api/statistics/%s/?time_interval=month&service=agendas default' % event_name, headers=headers
)
data = resp.json['data']
assert data == {'x_labels': ['2020-02', '2020-03'], 'series': [{'label': 'password', 'data': [1, 1]}]}
resp = app.get(
'/api/statistics/%s/?time_interval=month&start=2020-03-01T01:01' % event_name, headers=headers
)
data = resp.json['data']
data['series'].sort(key=lambda x: x['label'])
assert data == {
'x_labels': ['2020-03'],
'series': [{'label': 'FranceConnect', 'data': [1]}, {'label': 'password', 'data': [1]}],
}
resp = app.get(
'/api/statistics/%s/?time_interval=month&end=2020-03-01T01:01' % event_name, headers=headers
)
data = resp.json['data']
assert data == {'x_labels': ['2020-02'], 'series': [{'label': 'password', 'data': [2]}]}
resp = app.get('/api/statistics/%s/?time_interval=month&end=2020-03-01' % event_name, headers=headers)
data = resp.json['data']
assert data == {'x_labels': ['2020-02'], 'series': [{'label': 'password', 'data': [2]}]}
resp = app.get(
'/api/statistics/%s/?time_interval=year&service=portal second' % event_name, headers=headers
)
data = resp.json['data']
data['series'].sort(key=lambda x: x['label'])
assert data == {
'x_labels': ['2020'],
'series': [{'label': 'FranceConnect', 'data': [1]}, {'label': 'password', 'data': [1]}],
}
resp = app.get('/api/statistics/service_%s/?time_interval=month' % event_name, headers=headers)
data = resp.json['data']
data['series'].sort(key=lambda x: x['label'])
assert data == {
'x_labels': ['2020-02', '2020-03'],
'series': [{'label': 'agendas', 'data': [1, 1]}, {'label': 'portal', 'data': [1, 1]}],
}
resp = app.get('/api/statistics/service_ou_%s/?time_interval=month' % event_name, headers=headers)
data = resp.json['data']
data['series'].sort(key=lambda x: x['label'])
assert data == {
'x_labels': ['2020-02', '2020-03'],
'series': [
{'label': 'Default organizational unit', 'data': [1, 1]},
{'label': 'Second OU', 'data': [1, 1]},
],
}
def test_api_statistics_no_crash_older_drf(app, admin):
headers = basic_authorization_header(admin)
expected_status = 200 if drf_version > '3.9' else 404
app.get('/api/statistics/login/?time_interval=month', headers=headers, status=expected_status)
def test_find_duplicates_put(app, admin, settings):
app.authorization = ('Basic', (admin.username, admin.username))
app.put_json(
tests/api/test_statistics.py
# authentic2 - versatile identity manager
# Copyright (C) 2010-2019 Entr'ouvert
#
# This program is free software: you can redistribute it and/or modify it
# under the terms of the GNU Affero General Public License as published
# by the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import pytest
from rest_framework import VERSION as drf_version
from authentic2.a2_rbac.models import OrganizationalUnit as OU
from authentic2.a2_rbac.utils import get_default_ou
from authentic2.apps.journal.models import Event, EventType
from authentic2.custom_user.models import User
from authentic2.models import Service
from tests.utils import basic_authorization_header
@pytest.mark.skipif(drf_version.startswith('3.4'), reason='no support for old django rest framework')
def test_api_statistics_list(app, admin):
headers = basic_authorization_header(admin)
resp = app.get('/api/statistics/', headers=headers)
assert len(resp.json['data']) == 6
login_stats = {
'name': 'Login count by authentication type',
'url': 'http://testserver/api/statistics/login/',
'id': 'login',
'filters': [
{
"id": "time_interval",
"label": "Time interval",
"options": [
{"id": "day", "label": "Day"},
{"id": "month", "label": "Month"},
{"id": "year", "label": "Year"},
],
"required": True,
"default": "month",
},
{'id': 'service', 'label': 'Service', 'options': []},
],
}
assert login_stats in resp.json['data']
assert {
'name': 'Login count by service',
'url': 'http://testserver/api/statistics/service_login/',
'id': 'service-login',
'filters': [
{
"id": "time_interval",
"label": "Time interval",
"options": [
{"id": "day", "label": "Day"},
{"id": "month", "label": "Month"},
{"id": "year", "label": "Year"},
],
"required": True,
"default": "month",
},
],
} in resp.json['data']
service = Service.objects.create(name='Service1', slug='service1', ou=get_default_ou())
service = Service.objects.create(name='Service2', slug='service2', ou=get_default_ou())
login_stats['filters'][1]['options'].append({'id': 'service1 default', 'label': 'Service1'})
login_stats['filters'][1]['options'].append({'id': 'service2 default', 'label': 'Service2'})
resp = app.get('/api/statistics/', headers=headers)
assert login_stats in resp.json['data']
# adding second ou doesn't change anything
ou = OU.objects.create(name='Second OU', slug='second')
resp = app.get('/api/statistics/', headers=headers)
assert login_stats in resp.json['data']
# if there are services in two differents OUs, filter is shown
service.ou = ou
service.save()
login_stats['filters'][1]['options'][1]['id'] = 'service2 second'
login_stats['filters'].append(
{
'id': 'services_ou',
'label': 'Services organizational unit',
'options': [
{'id': 'default', 'label': 'Default organizational unit'},
{'id': 'second', 'label': 'Second OU'},
],
}
)
resp = app.get('/api/statistics/', headers=headers)
assert login_stats in resp.json['data']
# same goes with users
User.objects.create(username='john.doe', email='john.doe@example.com', ou=ou)
login_stats['filters'].append(
{
'id': 'users_ou',
'label': 'Users organizational unit',
'options': [
{'id': 'default', 'label': 'Default organizational unit'},
{'id': 'second', 'label': 'Second OU'},
],
}
)
resp = app.get('/api/statistics/', headers=headers)
assert login_stats in resp.json['data']
@pytest.mark.skipif(drf_version.startswith('3.4'), reason='no support for old django rest framework')
@pytest.mark.parametrize(
'event_type_name,event_name', [('user.login', 'login'), ('user.registration', 'registration')]
)
def test_api_statistics(app, admin, freezer, event_type_name, event_name):
headers = basic_authorization_header(admin)
resp = app.get('/api/statistics/login/?time_interval=month', headers=headers)
assert resp.json == {"data": {"series": [], "x_labels": []}, "err": 0}
user = User.objects.create(username='john.doe', email='john.doe@example.com', ou=get_default_ou())
ou = OU.objects.create(name='Second OU', slug='second')
portal = Service.objects.create(name='portal', slug='portal', ou=ou)
agendas = Service.objects.create(name='agendas', slug='agendas', ou=get_default_ou())
method = {'how': 'password-on-https'}
method2 = {'how': 'fc'}
event_type = EventType.objects.get_for_name(event_type_name)
freezer.move_to('2020-02-03 12:00')
Event.objects.create(type=event_type, references=[portal], data=method)
Event.objects.create(type=event_type, references=[agendas, user], user=user, data=method)
freezer.move_to('2020-03-04 13:00')
Event.objects.create(type=event_type, references=[agendas], data=method)
Event.objects.create(type=event_type, references=[portal], data=method2)
resp = app.get('/api/statistics/%s/?time_interval=month' % event_name, headers=headers)
data = resp.json['data']
data['series'].sort(key=lambda x: x['label'])
assert data == {
'x_labels': ['2020-02', '2020-03'],
'series': [{'label': 'FranceConnect', 'data': [None, 1]}, {'label': 'password', 'data': [2, 1]}],
}
# default time interval is 'month'
month_data = data
resp = app.get('/api/statistics/%s/' % event_name, headers=headers)
data = resp.json['data']
data['series'].sort(key=lambda x: x['label'])
assert month_data == data
resp = app.get(
'/api/statistics/%s/?time_interval=month&services_ou=default' % event_name, headers=headers
)
data = resp.json['data']
data['series'].sort(key=lambda x: x['label'])
assert data == {
'x_labels': ['2020-02', '2020-03'],
'series': [{'label': 'password', 'data': [1, 1]}],
}
# legacy way to filter by service OU
services_ou_data = data
resp = app.get('/api/statistics/%s/?time_interval=month&ou=default' % event_name, headers=headers)
data = resp.json['data']
data['series'].sort(key=lambda x: x['label'])
assert services_ou_data == data
resp = app.get(
'/api/statistics/%s/?time_interval=month&users_ou=default&service=agendas default' % event_name,
headers=headers,
)
data = resp.json['data']
assert data == {
'x_labels': ['2020-02'],
'series': [{'label': 'password', 'data': [1]}],
}
resp = app.get('/api/statistics/%s/?time_interval=month&users_ou=default' % event_name, headers=headers)
data = resp.json['data']
assert data == {'x_labels': ['2020-02'], 'series': [{'label': 'password', 'data': [1]}]}
resp = app.get(
'/api/statistics/%s/?time_interval=month&service=agendas default' % event_name, headers=headers
)
data = resp.json['data']
assert data == {'x_labels': ['2020-02', '2020-03'], 'series': [{'label': 'password', 'data': [1, 1]}]}
resp = app.get(
'/api/statistics/%s/?time_interval=month&start=2020-03-01T01:01' % event_name, headers=headers
)
data = resp.json['data']
data['series'].sort(key=lambda x: x['label'])
assert data == {
'x_labels': ['2020-03'],
'series': [{'label': 'FranceConnect', 'data': [1]}, {'label': 'password', 'data': [1]}],
}
resp = app.get(
'/api/statistics/%s/?time_interval=month&end=2020-03-01T01:01' % event_name, headers=headers
)
data = resp.json['data']
assert data == {'x_labels': ['2020-02'], 'series': [{'label': 'password', 'data': [2]}]}
resp = app.get('/api/statistics/%s/?time_interval=month&end=2020-03-01' % event_name, headers=headers)
data = resp.json['data']
assert data == {'x_labels': ['2020-02'], 'series': [{'label': 'password', 'data': [2]}]}
resp = app.get(
'/api/statistics/%s/?time_interval=year&service=portal second' % event_name, headers=headers
)
data = resp.json['data']
data['series'].sort(key=lambda x: x['label'])
assert data == {
'x_labels': ['2020'],
'series': [{'label': 'FranceConnect', 'data': [1]}, {'label': 'password', 'data': [1]}],
}
resp = app.get('/api/statistics/service_%s/?time_interval=month' % event_name, headers=headers)
data = resp.json['data']
data['series'].sort(key=lambda x: x['label'])
assert data == {
'x_labels': ['2020-02', '2020-03'],
'series': [{'label': 'agendas', 'data': [1, 1]}, {'label': 'portal', 'data': [1, 1]}],
}
resp = app.get('/api/statistics/service_ou_%s/?time_interval=month' % event_name, headers=headers)
data = resp.json['data']
data['series'].sort(key=lambda x: x['label'])
assert data == {
'x_labels': ['2020-02', '2020-03'],
'series': [
{'label': 'Default organizational unit', 'data': [1, 1]},
{'label': 'Second OU', 'data': [1, 1]},
],
}
def test_api_statistics_no_crash_older_drf(app, admin):
headers = basic_authorization_header(admin)
expected_status = 200 if drf_version > '3.9' else 404
app.get('/api/statistics/login/?time_interval=month', headers=headers, status=expected_status)