diff --git a/jupyterhub/tests/test_api.py b/jupyterhub/tests/test_api.py index 735f8a39..b02f6fec 100644 --- a/jupyterhub/tests/test_api.py +++ b/jupyterhub/tests/test_api.py @@ -1,24 +1,21 @@ """Tests for the REST API.""" +from datetime import datetime from concurrent.futures import Future import json -import time +import re import sys from unittest import mock from urllib.parse import urlparse, quote import uuid -import pytest from pytest import mark -import requests from tornado import gen import jupyterhub from .. import orm -from ..user import User from ..utils import url_path_join as ujoin -from . import mocking from .mocking import public_host, public_url from .utils import async_requests @@ -187,6 +184,48 @@ def test_referer_check(app): # User API tests # -------------- +def normalize_timestamp(ts): + """Normalize a timestamp + + For easier comparison + """ + if ts is None: + return + return re.sub('\d(\.\d+)?', '0', ts) + +def normalize_user(user): + """Normalize a user model for comparison + + smooths out user model with things like timestamps + for easier comparison + """ + for key in ('created', 'last_activity', 'started'): + user[key] = normalize_timestamp(user[key]) + if 'servers' in user: + for server in user['servers'].values(): + for key in ('started', 'last_activity'): + server[key] = normalize_timestamp(server[key]) + return user + +def fill_user(model): + """Fill a default user model + + Any unspecified fields will be filled with the defaults + """ + model.setdefault('server', None) + model.setdefault('kind', 'user') + model.setdefault('groups', []) + model.setdefault('admin', False) + model.setdefault('server', None) + model.setdefault('pending', None) + model.setdefault('created', TIMESTAMP) + model.setdefault('last_activity', TIMESTAMP) + model.setdefault('started', None) + return model + + +TIMESTAMP = normalize_timestamp(datetime.now().isoformat() + 'Z') + @mark.user @mark.gen_test def test_get_users(app): @@ -195,25 +234,17 @@ def test_get_users(app): assert r.status_code == 200 users = sorted(r.json(), key=lambda d: d['name']) - for u in users: - u.pop('last_activity') + users = [ normalize_user(u) for u in users ] assert users == [ - { - 'kind': 'user', + fill_user({ 'name': 'admin', - 'groups': [], 'admin': True, - 'server': None, - 'pending': None, - }, - { - 'kind': 'user', + }), + fill_user({ 'name': 'user', - 'groups': [], 'admin': False, - 'server': None, - 'pending': None, - } + 'last_activity': None, + }), ] r = yield api_request(app, 'users', @@ -275,18 +306,9 @@ def test_get_user(app): name = 'user' r = yield api_request(app, 'users', name) assert r.status_code == 200 - user = r.json() - user.pop('last_activity') - assert user == { - 'kind': 'user', - 'name': name, - 'groups': [], - 'admin': False, - 'server': None, - 'pending': None, - # auth state is present because requestor is an admin - 'auth_state': None - } + + user = normalize_user(r.json()) + assert user == fill_user({'name': name, 'auth_state': None}) @mark.user diff --git a/jupyterhub/tests/test_named_servers.py b/jupyterhub/tests/test_named_servers.py index a2511cd5..78b1aa51 100644 --- a/jupyterhub/tests/test_named_servers.py +++ b/jupyterhub/tests/test_named_servers.py @@ -5,7 +5,7 @@ import pytest from ..utils import url_path_join -from .test_api import api_request, add_user +from .test_api import api_request, add_user, fill_user, normalize_user, TIMESTAMP from .mocking import public_url from .utils import async_requests @@ -28,23 +28,23 @@ def test_default_server(app, named_servers): r = yield api_request(app, 'users', username) r.raise_for_status() - user_model = r.json() - user_model.pop('last_activity') - assert user_model == { + user_model = normalize_user(r.json()) + print(user_model) + assert user_model == fill_user({ 'name': username, - 'groups': [], - 'kind': 'user', - 'admin': False, - 'pending': None, 'auth_state': None, 'server': user.url, + 'started': TIMESTAMP, 'servers': { '': { 'name': '', + 'started': TIMESTAMP, + 'last_activity': TIMESTAMP, 'url': user.url, }, }, - } + }) + # now stop the server r = yield api_request(app, 'users', username, 'server', method='delete') @@ -54,19 +54,12 @@ def test_default_server(app, named_servers): r = yield api_request(app, 'users', username) r.raise_for_status() - user_model = r.json() - user_model.pop('last_activity') - assert user_model == { + user_model = normalize_user(r.json()) + assert user_model == fill_user({ 'name': username, - 'groups': [], - 'kind': 'user', - 'admin': False, - 'pending': None, - 'server': None, 'servers': {}, 'auth_state': None, - } - + }) @pytest.mark.gen_test @@ -93,24 +86,20 @@ def test_create_named_server(app, named_servers): r = yield api_request(app, 'users', username) r.raise_for_status() - user_model = r.json() - user_model.pop('last_activity') - assert user_model == { + user_model = normalize_user(r.json()) + assert user_model == fill_user({ 'name': username, - 'groups': [], - 'kind': 'user', - 'admin': False, - 'pending': None, 'auth_state': None, - 'server': None, 'servers': { servername: { 'name': name, + 'started': TIMESTAMP, + 'last_activity': TIMESTAMP, 'url': url_path_join(user.url, name, '/'), } for name in [servername] }, - } + }) @pytest.mark.gen_test @@ -131,16 +120,10 @@ def test_delete_named_server(app, named_servers): r = yield api_request(app, 'users', username) r.raise_for_status() - user_model = r.json() - user_model.pop('last_activity') - assert user_model == { + user_model = normalize_user(r.json()) + assert user_model == fill_user({ 'name': username, - 'groups': [], - 'kind': 'user', - 'admin': False, - 'pending': None, 'auth_state': None, - 'server': None, 'servers': { name: { 'name': name, @@ -148,7 +131,7 @@ def test_delete_named_server(app, named_servers): } for name in [] }, - } + }) @pytest.mark.gen_test def test_named_server_disabled(app):