<commit_before># -*- coding: utf-8 -*-
from django.contrib.auth import get_user_model
from django.db.models import Min
from django.test import TestCase
from django.urls import reverse
from django.utils.html import escape
from djiffy.models import Manifest
import json

from derrida.people.models import Person
from derrida.books.models import Instance, Work, Reference, DerridaWorkSection
from derrida.interventions.models import Intervention, INTERVENTION_TYPES


class TestInstanceViews(TestCase):
    fixtures = ['sample_work_data.json']

    def setUp(self):
        la_vie = Instance.objects.get(work__primary_title__icontains='la vie')
        for i in range(1, 20):
            la_vie.pk = None
            la_vie.save()

    def test_instance_detail_view(self):
        # get one of the la_vie copies
        la_vie = Instance.objects.filter(work__primary_title__icontains='la vie')[3]
        # pass its pk to detail view
        detail_view_url = reverse('books:detail', kwargs={'pk': la_vie.pk})
        response = self.client.get(detail_view_url)
        # doesn't have a manifest, should 404
        # should return a response
        assert response.status_code == 404

        # make a manifest and associate it
        manif = Manifest.objects.create()
        la_vie.digital_edition = manif
        la_vie.save()

        response = self.client.get(detail_view_url)
        # should return correctly
        assert response.status_code == 200
        # should have a context object called instance that's a copy of Instance
        assert 'instance' in response.context
        # it should be the copy of la_view we looked up
        assert response.context['instance'] == la_vie

    def test_instance_list_view(self):
        list_view_url = reverse('books:list')
        # an anonymous user can see the view
        response = self.client.get(list_view_url)
        assert response.status_code == 200
        # an object list is returned
        assert 'object_list' in response.context
        # Should find 16 objects and a paginator in context
        assert len(response.context['object_list']) == 16
        assert 'page_obj' in response.context
        page_obj = response.context['page_obj']
        assert page_obj
        # Paginator 1 indexes this rather than 0, it's 2 pages!
        assert page_obj.paginator.page_range == range(1, 3)
        assert page_obj.number == 1

        # - testing that query set is alpha by author of work
        # Make one more work, and give it an author
        testwork = Work.objects.create(
            primary_title="Un livre d'unittest",
            short_title="Un livre"
        )
        # author starts with 'a' so it should come first
        pers = Person.objects.create(authorized_name='Adespota', birth=1800,
            death=1845)
        testwork.authors.add(pers)
        testwork.save()
        # make an instance from that work
        inst = Instance.objects.create(work=testwork)
        # check the context to ensure it is there and firstß
        response = self.client.get(list_view_url)
        assert response.status_code == 200
        assert 'object_list' in response.context
        assert response.context['object_list'][0] == inst
        # still 16 items
        assert len(response.context['object_list']) == 16
        # still page 1
        page_obj = response.context['page_obj']
        assert page_obj
        assert page_obj.paginator.page_range == range(1, 3)
        assert page_obj.number == 1
        # now pick a different page via query string
        response = self.client.get(list_view_url, {'page': 2})
        assert response.status_code == 200
        page_obj = response.context['page_obj']
        assert page_obj
        assert page_obj.paginator.page_range == range(1, 3)
        assert page_obj.number == 2
        # only 5 of 21 items on pg. 2
        assert len(response.context['object_list']) == 5


class TestReferenceViews(TestCase):
    fixtures = ['test_references.json']

    def test_reference_list(self):
        reference_list_url = reverse('books:reference-list')
        response = self.client.get(reference_list_url)
        assert response.status_code == 200
        assert 'object_list' in response.context
        assert isinstance(response.context['object_list'][0], Reference)
        self.assertTemplateUsed(response, 'books/reference_list.html')
        self.assertTemplateUsed(response, 'components/citation-list-item.html')
        self.assertTemplateUsed(response, 'components/page-pagination.html')

        # fixme: is total displayed anywhere?

        # reference details that should be present in the template
        ref = Reference.objects.first()
        # spot check template (tested more thoroughly in reference detail below)
        self.assertContains(response, 'p. %s' % ref.book_page,
            msg_prefix='reference detail should include book page number')
        self.assertContains(response, escape(ref.instance.display_title()),
            msg_prefix='reference detail should include book title')

        # pagination: link to page two
        # FIXME: should this include current page url?
        # will eventually need to include sort/filter options
        self.assertContains(response, '?page=2',
            msg_prefix='should include link to next page of results')

        # test non-paginated results
        # - remove all but five references
        keep_ids = Reference.objects.values_list('id', flat=True)[:5]
        Reference.objects.exclude(id__in=keep_ids).delete()
        response = self.client.get(reference_list_url)
        assert response.status_code == 200
        self.assertTemplateNotUsed(response, 'components/page-pagination.html')

        # todo: test no results display?

    def test_reference_detail(self):
        ref = Reference.objects.exclude(book_page='').first()
        response = self.client.get(ref.get_absolute_url())
        assert response.status_code == 200
        self.assertTemplateUsed('components/citation-list-item.html')
        # check for details that should be displayed
        # - reference type
        self.assertContains(response, ref.reference_type.name,
            msg_prefix='should display reference type')
        # - link to cited book
        self.assertContains(response, ref.instance.get_absolute_url(),
            msg_prefix='should include link to work instance detail page')
        # - cited book title
        self.assertContains(response, escape(ref.instance.display_title()),
            msg_prefix='should include work instance title')
        # - work instance authors
        self.assertContains(response,
            '; '.join([a.authorized_name for a in ref.instance.work.authors.all()]),
            msg_prefix='should display all author names')
        # - instance copyright year
        self.assertContains(response, ref.instance.copyright_year,
            msg_prefix='should include work instance copyright year')<commit_msg>Update test to MySQL query<commit_after># -*- coding: utf-8 -*-
from django.contrib.auth import get_user_model
from django.db.models import Min
from django.db.transaction import atomic
from django.test import TestCase
from django.urls import reverse
from django.utils.html import escape
from djiffy.models import Manifest
import json

from derrida.people.models import Person
from derrida.books.models import Instance, Work, Reference, DerridaWorkSection
from derrida.interventions.models import Intervention, INTERVENTION_TYPES


class TestInstanceViews(TestCase):
    fixtures = ['sample_work_data.json']

    def setUp(self):
        la_vie = Instance.objects.get(work__primary_title__icontains='la vie')
        for i in range(1, 20):
            la_vie.pk = None
            la_vie.save()

    def test_instance_detail_view(self):
        # get one of the la_vie copies
        la_vie = Instance.objects.filter(work__primary_title__icontains='la vie')[3]
        # pass its pk to detail view
        detail_view_url = reverse('books:detail', kwargs={'pk': la_vie.pk})
        response = self.client.get(detail_view_url)
        # doesn't have a manifest, should 404
        # should return a response
        assert response.status_code == 404

        # make a manifest and associate it
        manif = Manifest.objects.create()
        la_vie.digital_edition = manif
        la_vie.save()

        response = self.client.get(detail_view_url)
        # should return correctly
        assert response.status_code == 200
        # should have a context object called instance that's a copy of Instance
        assert 'instance' in response.context
        # it should be the copy of la_view we looked up
        assert response.context['instance'] == la_vie

    def test_instance_list_view(self):
        list_view_url = reverse('books:list')
        # an anonymous user can see the view
        response = self.client.get(list_view_url)
        assert response.status_code == 200
        # an object list is returned
        assert 'object_list' in response.context
        # Should find 16 objects and a paginator in context
        assert len(response.context['object_list']) == 16
        assert 'page_obj' in response.context
        page_obj = response.context['page_obj']
        assert page_obj
        # Paginator 1 indexes this rather than 0, it's 2 pages!
        assert page_obj.paginator.page_range == range(1, 3)
        assert page_obj.number == 1

        # - testing that query set is alpha by author of work
        # Make one more work, and give it an author
        testwork = Work.objects.create(
            primary_title="Un livre d'unittest",
            short_title="Un livre"
        )
        # author starts with 'a' so it should come first
        pers = Person.objects.create(authorized_name='Adespota', birth=1800,
            death=1845)
        testwork.authors.add(pers)
        testwork.save()
        # make an instance from that work
        inst = Instance.objects.create(work=testwork)
        # check the context to ensure it is there and firstß
        response = self.client.get(list_view_url)
        assert response.status_code == 200
        assert 'object_list' in response.context
        assert response.context['object_list'][0] == inst
        # still 16 items
        assert len(response.context['object_list']) == 16
        # still page 1
        page_obj = response.context['page_obj']
        assert page_obj
        assert page_obj.paginator.page_range == range(1, 3)
        assert page_obj.number == 1
        # now pick a different page via query string
        response = self.client.get(list_view_url, {'page': 2})
        assert response.status_code == 200
        page_obj = response.context['page_obj']
        assert page_obj
        assert page_obj.paginator.page_range == range(1, 3)
        assert page_obj.number == 2
        # only 5 of 21 items on pg. 2
        assert len(response.context['object_list']) == 5


class TestReferenceViews(TestCase):
    fixtures = ['test_references.json']

    def test_reference_list(self):
        reference_list_url = reverse('books:reference-list')
        response = self.client.get(reference_list_url)
        assert response.status_code == 200
        assert 'object_list' in response.context
        assert isinstance(response.context['object_list'][0], Reference)
        self.assertTemplateUsed(response, 'books/reference_list.html')
        self.assertTemplateUsed(response, 'components/citation-list-item.html')
        self.assertTemplateUsed(response, 'components/page-pagination.html')

        # fixme: is total displayed anywhere?

        # reference details that should be present in the template
        ref = Reference.objects.first()
        # spot check template (tested more thoroughly in reference detail below)
        self.assertContains(response, 'p. %s' % ref.book_page,
            msg_prefix='reference detail should include book page number')
        self.assertContains(response, escape(ref.instance.display_title()),
            msg_prefix='reference detail should include book title')

        # pagination: link to page two
        # FIXME: should this include current page url?
        # will eventually need to include sort/filter options
        self.assertContains(response, '?page=2',
            msg_prefix='should include link to next page of results')

        # test non-paginated results
        # - remove all but five references
        # Done as three steps to avoid a MySQL subquery issue (LIMIT + IN/ANY/ALL)
        keep_ids = Reference.objects.all()[:5]
        Reference.objects.all().delete()
        
        @atomic
        def save_keeps(qs):
            '''Wrap the save of all 5 as one commit to keep the test zippier'''
            for item in qs:
                item.save()
        save_keeps(keep_ids)
        response = self.client.get(reference_list_url)
        assert response.status_code == 200
        self.assertTemplateNotUsed(response, 'components/page-pagination.html')

        # todo: test no results display?

    def test_reference_detail(self):
        ref = Reference.objects.exclude(book_page='').first()
        response = self.client.get(ref.get_absolute_url())
        assert response.status_code == 200
        self.assertTemplateUsed('components/citation-list-item.html')
        # check for details that should be displayed
        # - reference type
        self.assertContains(response, ref.reference_type.name,
            msg_prefix='should display reference type')
        # - link to cited book
        self.assertContains(response, ref.instance.get_absolute_url(),
            msg_prefix='should include link to work instance detail page')
        # - cited book title
        self.assertContains(response, escape(ref.instance.display_title()),
            msg_prefix='should include work instance title')
        # - work instance authors
        self.assertContains(response,
            '; '.join([a.authorized_name for a in ref.instance.work.authors.all()]),
            msg_prefix='should display all author names')
        # - instance copyright year
        self.assertContains(response, ref.instance.copyright_year,
            msg_prefix='should include work instance copyright year')
{'fraction_non_alphanumeric': 0.08661858413276381, 'fraction_numerical': 0.010013304390448848, 'mean_word_length': 2.7183025253840145, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5265560', 'n_tokens_mistral': 3924, 'n_tokens_neox': 3748, 'n_words': 1109}