src/notes/tests/api/session.py
author ymh <ymh.work@gmail.com>
Tue, 29 Mar 2022 11:23:56 +0200
changeset 211 244a90638e80
parent 142 56850f5c73f6
permissions -rw-r--r--
Added tag 0.2.3 for changeset 3de92ddba2de

"""
Tests the core api for sessions
"""
import datetime
import logging
from unittest import skip
from uuid import uuid4

from django.contrib.auth import get_user_model
from django.contrib.auth.models import Group
from django.urls import reverse
from django.utils import timezone
from rest_framework import status
from rest_framework.test import APITransactionTestCase

from notes import constants
from notes.models import GroupProfile, Note, Session

logger = logging.getLogger(__name__)

class SessionApiTests(APITransactionTestCase):

    def setUp(self):
        User = get_user_model()
        self.user1 = User.objects.create_user(
            username='test_user1',
            email='test_user@emial.com',
            password='top_secret'
        )
        self.user2 = User.objects.create_user(
            username='test_user2',
            email='test_user@emial.com',
            password='top_secret'
        )
        user3 = User.objects.create_user(
            username='test_user3',
            email='test_user@emial.com',
            password='top_secret'
        )

        self.group1 = Group(name='group1')
        self.group1.save()
        self.group1.user_set.add(self.user1)
        self.group1.user_set.add(self.user2)
        self.group1.profile.owner = self.user1
        self.group1.profile.description = "This is the group 1"
        self.group1.profile.save()

        self.user2.profile.default_group = self.group1
        self.user2.profile.save()

        self.session1 = Session.objects.create(
            title="a new session 1",
            description="Description 1",
            group=self.user1.profile.default_group,
            owner=self.user1
        )

        self.session2 = Session.objects.create(
            title="a new session 2",
            description="Description 2",
            group=self.user2.profile.default_group,
            owner=self.user2
        )

        self.session3 = Session.objects.create(
            title="a new session 3",
            description="Description 3",
            group=user3.profile.default_group,
            owner=user3
        )

        self.session4 = Session.objects.create(
            title="a new session 4",
            description="Description 4",
            group=user3.profile.default_group,
            owner=user3
        )

        Note.objects.create(
            tc_start=timezone.now(),
            tc_end=timezone.now(),
            session=self.session1,
            plain="example note 1",
            html="<i>example note 1</i>",
            raw="<i>example note 1</i>",
            margin_note="margin note 1",
            categorization="[]"
        )

        Note.objects.create(
            tc_start=timezone.now(),
            tc_end=timezone.now(),
            session=self.session2,
            plain="example note 2",
            html="<i>example note</i>",
            raw="<i>example note</i>",
            margin_note="margin note",
            categorization="[]"
        )


    def test_list_session_no_user(self):
        url = reverse('notes:session-list')
        response = self.client.post(url)
        self.assertEqual(response.status_code, status.HTTP_401_UNAUTHORIZED)


    def test_list_session(self):
        url = reverse('notes:session-list')
        self.client.login(username='test_user1', password='top_secret')
        response = self.client.get(url)
        self.assertEqual(response.status_code, status.HTTP_200_OK)
        json = response.json()
        self.assertIn('results', json, "must have results")
        self.assertIn('count', json, "must have count")
        self.assertEqual(json['count'], 1, "must have one session")
        self.assertEqual(len(json['results']), 1, "must have one session")

        for session in json['results']:
            self.assertEqual(session['owner'], 'test_user1')


    def test_list_session_filter(self):
        url = reverse('notes:session-list')
        self.client.login(username='test_user1', password='top_secret')
        response = self.client.get(url, {"ext_id__in": ",".join([str(self.session1.ext_id)])})
        self.assertEqual(response.status_code, status.HTTP_200_OK)
        json = response.json()
        self.assertIn('results', json, "must have results")
        self.assertIn('count', json, "must have count")
        self.assertEqual(json['count'], 1, "must have one session")
        self.assertEqual(len(json['results']), 1, "must have one session")

        for session in json['results']:
            self.assertEqual(session['owner'], 'test_user1')


    def test_list_session_filter_bad(self):
        url = reverse('notes:session-list')
        self.client.login(username='test_user1', password='top_secret')
        response = self.client.get(url, {"ext_id__in": ",".join([str(uuid4())])})
        self.assertEqual(response.status_code, status.HTTP_200_OK)
        json = response.json()
        self.assertIn('results', json, "must have results")
        self.assertIn('count', json, "must have count")
        self.assertEqual(json['count'], 0, "must have no session")
        self.assertEqual(len(json['results']), 0, "must have no session")

    def test_create_session_no_user(self):
        url = reverse('notes:session-list')
        response = self.client.post(url, {
            'title': "a new session",
            'description': "description of the session",
            'protocol': "[]"
        }, format='json')

        self.assertEqual(response.status_code, status.HTTP_401_UNAUTHORIZED)


    def test_create_session(self):
        url = reverse('notes:session-list')
        self.client.login(username='test_user1', password='top_secret')
        response = self.client.post(url, {
            'title': "a new session",
            'description': "description of the session",
            'group': 'group1'
        }, format='json')

        self.assertEqual(response.status_code, status.HTTP_201_CREATED, "error msg: %r" % response.content)
        json = response.json()
        self.assertIn('ext_id', json)

        session = Session.objects.get(ext_id=json['ext_id'])
        self.assertIsNotNone(session)
        self.assertEqual(self.group1, session.group)
        self.assertEqual(self.group1.profile.protocol, session.protocol)


    def test_create_session_protocol(self):
        url = reverse('notes:session-list')
        self.client.login(username='test_user1', password='top_secret')
        response = self.client.post(url, {
            'title': "a new session",
            'description': "description of the session",
            'group': 'group1',
            'protocol': {}
        }, format='json')

        self.assertEqual(response.status_code, status.HTTP_201_CREATED, response.json())
        json = response.json()
        self.assertIn('ext_id', json)

        session = Session.objects.get(ext_id=json['ext_id'])
        self.assertIsNotNone(session)
        self.assertEqual(self.group1, session.group)
        self.assertNotEqual(self.group1.profile.protocol, session.protocol)


    def test_create_session_protocol_as_str(self):
        url = reverse('notes:session-list')
        self.client.login(username='test_user1', password='top_secret')
        group1 = Group.objects.get(id=self.group1.id)
        response = self.client.post(url, {
            'title': "a new session",
            'description': "description of the session",
            'group': 'group1',
            'protocol': group1.profile.protocol
        }, format='json')

        self.assertEqual(response.status_code, status.HTTP_201_CREATED, response.json())
        json = response.json()
        self.assertIn('ext_id', json)

        session = Session.objects.get(ext_id=json['ext_id'])
        self.assertIsNotNone(session)
        self.assertEqual(self.group1, session.group)
        self.assertEqual(self.group1.profile.protocol, session.protocol)


    def test_create_session_protocol_as_str_unknown(self):
        url = reverse('notes:session-list')
        self.client.login(username='test_user1', password='top_secret')
        group1 = Group.objects.get(id=self.group1.id)
        response = self.client.post(url, {
            'title': "a new session",
            'description': "description of the session",
            'group': 'group1',
            'protocol': constants.PROTOCOL_URN_PREFIX + str(uuid4()) + ".1"
        }, format='json')

        self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST, response.json())
        json = response.json()
        self.assertIn('protocol', json)
        self.assertIn('Incorrect protocol', json['protocol'][0])
        self.assertIn('does not exists', json['protocol'][0])


    def test_create_session_protocol_as_str_bad(self):
        url = reverse('notes:session-list')
        self.client.login(username='test_user1', password='top_secret')
        group1 = Group.objects.get(id=self.group1.id)
        response = self.client.post(url, {
            'title': "a new session",
            'description': "description of the session",
            'group': 'group1',
            'protocol': constants.PROTOCOL_URN_PREFIX + "foo"
        }, format='json')

        self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST, response.json())
        json = response.json()
        self.assertIn('protocol', json)
        self.assertEqual('Incorrect format. Expected `urn:protocol:<ext_id>.<version>`.', json['protocol'][0])


    def test_create_session_protocol_as_other_type_bad(self):
        url = reverse('notes:session-list')
        self.client.login(username='test_user1', password='top_secret')
        group1 = Group.objects.get(id=self.group1.id)
        response = self.client.post(url, {
            'title': "a new session",
            'description': "description of the session",
            'group': 'group1',
            'protocol': True
        }, format='json')

        self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST, response.json())
        json = response.json()
        self.assertIn('protocol', json)
        self.assertEqual('Incorrect format. Expected `urn:protocol:<ext_id>.<version>` or dict.', json['protocol'][0])


    def test_create_session_no_group(self):
        url = reverse('notes:session-list')
        self.client.login(username='test_user1', password='top_secret')
        response = self.client.post(url, {
            'title': "a new session",
            'description': "description of the session"
        }, format='json')

        self.assertEqual(response.status_code, status.HTTP_201_CREATED, "Error when creating session %r" % response.json())
        json = response.json()
        self.assertIn('ext_id', json)

        session = Session.objects.get(ext_id=json['ext_id'])
        self.assertIsNotNone(session)
        user1_personal_group = Group.objects.get(profile__owner_personal=self.user1)
        self.assertEqual(user1_personal_group, session.group)
        self.assertEqual(user1_personal_group.profile.protocol, session.protocol)

    def test_create_session_no_group_default(self):
        url = reverse('notes:session-list')
        self.client.login(username='test_user2', password='top_secret')
        response = self.client.post(url, {
            'title': "a new session",
            'description': "description of the session"
        }, format='json')

        self.assertEqual(response.status_code, status.HTTP_201_CREATED, "Error when creating session %r" % response.json())
        json = response.json()
        self.assertIn('ext_id', json)

        session = Session.objects.get(ext_id=json['ext_id'])
        self.assertIsNotNone(session)
        self.assertEqual(self.group1, session.group)


    def test_create_session_bad_group(self):
        url = reverse('notes:session-list')
        self.client.login(username='test_user3', password='top_secret')
        response = self.client.post(url, {
            'title': "a new session",
            'description': "description of the session",
            'protocol': { 'owner': 'group1' },
            'group': "group1"
        }, format='json')

        self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
        json = response.json()
        self.assertIn('non_field_errors', json)
        self.assertIn('Owner must be in group', json['non_field_errors'])


    def test_create_session_with_ext_id(self):
        url = reverse('notes:session-list')
        self.client.login(username='test_user1', password='top_secret')
        ext_id = str(uuid4())
        response = self.client.post(url, {
            'ext_id': ext_id,
            'title': "a new session",
            'description': "description of the session",
            'group': 'group1'
        }, format='json')

        self.assertEqual(response.status_code, status.HTTP_201_CREATED, "response content: %r" % response.content)
        json = response.json()
        self.assertIn('ext_id', json)
        self.assertEqual(json['ext_id'], ext_id)


    def test_detail_session(self):
        url = reverse('notes:session-detail', kwargs={'ext_id':str(self.session1.ext_id)})
        self.client.login(username='test_user1', password='top_secret')
        response = self.client.get(url, format='json')
        self.assertEqual(response.status_code, status.HTTP_200_OK)

    def test_list_notes(self):
        url = reverse('notes:notes-session-list', kwargs={'session_ext_id':str(self.session1.ext_id)})
        self.client.login(username='test_user1', password='top_secret')
        response = self.client.get(url, format='json')
        self.assertEqual(response.status_code, status.HTTP_200_OK)

    def test_detail_session_bad(self):
        url = reverse('notes:session-detail', kwargs={'ext_id':str(self.session2.ext_id)})
        self.client.login(username='test_user1', password='top_secret')
        response = self.client.get(url, format='json')
        self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)

    def test_list_notes_bad(self):
        url = reverse('notes:notes-session-list', kwargs={'session_ext_id':str(self.session2.ext_id)})
        self.client.login(username='test_user1', password='top_secret')
        response = self.client.get(url, format='json')
        self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)

    def test_filter_modified_since(self):
        url = reverse('notes:session-list')
        self.client.login(username='test_user3', password='top_secret')
        nexthour = \
            datetime.datetime.utcnow().replace(tzinfo=timezone.utc) +\
            datetime.timedelta(hours=1)
        Session.objects.filter(pk=self.session4.id).update(updated=nexthour)

        response = self.client.get(
            url,
            {'modified_since': (nexthour - datetime.timedelta(minutes=30)).timestamp()},
            format='json'
        )

        self.assertEqual(response.status_code, status.HTTP_200_OK)
        json = response.json()
        self.assertIn('results', json, "must have results")
        self.assertIn('count', json, "must have count")
        self.assertEqual(json['count'], 1, "must have one session")
        self.assertEqual(len(json['results']), 1, "must have one session")

        self.assertEqual(json['results'][0].get('title'), "a new session 4")


    def test_filter_modified_since_zero(self):
        url = reverse('notes:session-list')
        self.client.login(username='test_user3', password='top_secret')

        response = self.client.get(url, {'modified_since': 0}, format='json')

        self.assertEqual(response.status_code, status.HTTP_200_OK)
        json = response.json()
        self.assertIn('results', json, "must have results")
        self.assertIn('count', json, "must have count")
        self.assertEqual(json['count'], 2, "must have two sessions")
        self.assertEqual(len(json['results']), 2, "must have two sessions")

        for session_json in json['results']:
            self.assertIn(session_json.get('title'), ['a new session 3', 'a new session 4'])


    def test_filter_modified_seconds(self):
        url = reverse('notes:session-list')
        self.client.login(username='test_user3', password='top_secret')

        prevmoment = \
            datetime.datetime.utcnow().replace(tzinfo=timezone.utc) -\
            datetime.timedelta(seconds=5)

        response = self.client.get(url, {'modified_since': prevmoment.timestamp()}, format='json')

        self.assertEqual(response.status_code, status.HTTP_200_OK)
        json = response.json()
        self.assertIn('results', json, "must have results")
        self.assertIn('count', json, "must have count")
        self.assertEqual(json['count'], 2, "must have two sessions")
        self.assertEqual(len(json['results']), 2, "must have two sessions")
        for session_json in json['results']:
            self.assertIn(session_json.get('title'), ['a new session 3', 'a new session 4'])

    def test_update_session(self):
        url = reverse('notes:session-detail', kwargs={'ext_id': self.session1.ext_id})

        self.client.login(username='test_user1', password='top_secret')
        response = self.client.put(url, {
            'title': "a new session",
            'description': "description of the session",
            'group': 'group1'
        }, format='json')

        self.assertEqual(response.status_code, status.HTTP_200_OK, "response content: %r" % response.content)
        json = response.json()
        self.assertIn('ext_id', json)

        session = Session.objects.get(ext_id=json['ext_id'])
        self.assertIsNotNone(session)
        self.assertEqual(self.group1, session.group)
        self.assertEqual(self.group1.profile.protocol, session.protocol)

    @skip("Protocol update not yet implemented")
    def test_update_session_protocol(self):
        url = reverse('notes:session-detail', kwargs={'ext_id': self.session1.ext_id})

        self.client.login(username='test_user1', password='top_secret')
        response = self.client.put(url, {
            'title': "an updated session",
            'description': "description of the session",
            'group': 'group1',
            'protocol': "urn:protocol:845ac623-b85a-4ddd-91ee-a2deb1a9b54f.3"
        }, format='json')

        json = response.json()
        # self.assertIn('ext_id', json)
        session = Session.objects.get(ext_id=self.session1.ext_id)
        self.assertEqual(response.status_code, status.HTTP_200_OK, "response content: %r" % response.content)


        # session = Session.objects.get(ext_id=json['ext_id'])
        # self.assertIsNotNone(session)
        # self.assertEqual(self.group1, session.group)
        # self.assertEqual(self.group1.profile.protocol, session.protocol)