diff --git a/chrono/agendas/models.py b/chrono/agendas/models.py index 68dff38a..4024dc14 100644 --- a/chrono/agendas/models.py +++ b/chrono/agendas/models.py @@ -585,7 +585,8 @@ class Agenda(WithSnapshotMixin, WithApplicationMixin, WithInspectMixin, models.M slug = data.pop('slug') qs_kwargs = {} if snapshot: - qs_kwargs = {'snapshot': snapshot} + qs_kwargs = {'snapshot': snapshot} # don't take slug from snapshot: it has to be unique ! + data['slug'] = str(uuid.uuid4()) # random slug else: qs_kwargs = {'slug': slug} agenda, created = cls.objects.update_or_create(defaults=data, **qs_kwargs) @@ -3018,7 +3019,8 @@ class EventsType(WithSnapshotMixin, WithApplicationMixin, WithInspectMixin, mode slug = data.pop('slug') qs_kwargs = {} if snapshot: - qs_kwargs = {'snapshot': snapshot} + qs_kwargs = {'snapshot': snapshot} # don't take slug from snapshot: it has to be unique ! + data['slug'] = str(uuid.uuid4()) # random slug else: qs_kwargs = {'slug': slug} events_type, created = cls.objects.update_or_create(defaults=data, **qs_kwargs) @@ -3648,7 +3650,8 @@ class Resource(WithSnapshotMixin, WithApplicationMixin, WithInspectMixin, models slug = data.pop('slug') qs_kwargs = {} if snapshot: - qs_kwargs = {'snapshot': snapshot} + qs_kwargs = {'snapshot': snapshot} # don't take slug from snapshot: it has to be unique ! + data['slug'] = str(uuid.uuid4()) # random slug else: qs_kwargs = {'slug': slug} resource, created = cls.objects.update_or_create(defaults=data, **qs_kwargs) @@ -3708,7 +3711,8 @@ class Category(WithSnapshotMixin, WithApplicationMixin, WithInspectMixin, models slug = data.pop('slug') qs_kwargs = {} if snapshot: - qs_kwargs = {'snapshot': snapshot} + qs_kwargs = {'snapshot': snapshot} # don't take slug from snapshot: it has to be unique ! + data['slug'] = str(uuid.uuid4()) # random slug else: qs_kwargs = {'slug': slug} category, created = cls.objects.update_or_create(defaults=data, **qs_kwargs) @@ -4106,7 +4110,8 @@ class UnavailabilityCalendar(WithSnapshotMixin, WithApplicationMixin, WithInspec slug = data.pop('slug') qs_kwargs = {} if snapshot: - qs_kwargs = {'snapshot': snapshot} + qs_kwargs = {'snapshot': snapshot} # don't take slug from snapshot: it has to be unique ! + data['slug'] = str(uuid.uuid4()) # random slug else: qs_kwargs = {'slug': slug} unavailability_calendar, created = cls.objects.update_or_create(defaults=data, **qs_kwargs) diff --git a/chrono/apps/snapshot/models.py b/chrono/apps/snapshot/models.py index 7254a3a0..6f78b811 100644 --- a/chrono/apps/snapshot/models.py +++ b/chrono/apps/snapshot/models.py @@ -79,9 +79,11 @@ class AbstractSnapshot(models.Model): def get_instance(self): try: # try reusing existing instance - return self.get_instance_model().snapshots.get(snapshot=self) + instance = self.get_instance_model().snapshots.get(snapshot=self) except self.get_instance_model().DoesNotExist: - return self.load_instance(self.serialization, snapshot=self) + instance = self.load_instance(self.serialization, snapshot=self) + instance.slug = self.serialization['slug'] # restore slug + return instance def load_instance(self, json_instance, snapshot=None): return self.get_instance_model().import_json(json_instance, snapshot=snapshot)[1] diff --git a/chrono/apps/snapshot/views.py b/chrono/apps/snapshot/views.py index 7a8d84ff..78c49b0c 100644 --- a/chrono/apps/snapshot/views.py +++ b/chrono/apps/snapshot/views.py @@ -16,13 +16,17 @@ import difflib import json +import re from django.http import Http404, HttpResponseRedirect from django.shortcuts import get_object_or_404, redirect +from django.template import loader from django.urls import reverse from django.utils.formats import date_format from django.utils.translation import gettext_lazy as _ from django.views.generic import DetailView, ListView +from lxml.html.diff import htmldiff +from pyquery import PyQuery as pq from chrono.utils.timezone import localtime @@ -65,7 +69,7 @@ class InstanceWithSnapshotHistoryCompareView(DetailView): kwargs[self.instance_context_key] = self.object mode = self.request.GET.get('mode') or 'json' - if mode not in ['json']: + if mode not in ['json', 'inspect']: raise Http404 snapshot1, snapshot2 = self.get_snapshots() @@ -90,6 +94,65 @@ class InstanceWithSnapshotHistoryCompareView(DetailView): return context return self.render_to_response(context) + def get_compare_inspect_context(self, snapshot1, snapshot2): + instance1 = snapshot1.get_instance() + instance2 = snapshot2.get_instance() + + def get_context(instance): + return { + 'object': instance, + } + + def fix_result(panel_diff): + if not panel_diff: + return panel_diff + panel = pq(panel_diff) + # remove "Link" added by htmldiff + for link in panel.find('a'): + d = pq(link) + text = d.html() + new_text = re.sub(r' Link: .*$', '', text) + d.html(new_text) + # remove empty ins and del tags + for elem in panel.find('ins, del'): + d = pq(elem) + if not (d.html() or '').strip(): + d.remove() + # prevent auto-closing behaviour of pyquery .html() method + for elem in panel.find('span, ul, div'): + d = pq(elem) + if not d.html(): + d.html(' ') + return panel.html() + + inspect1 = loader.render_to_string(self.inspect_template_name, get_context(instance1), self.request) + d1 = pq(str(inspect1)) + inspect2 = loader.render_to_string(self.inspect_template_name, get_context(instance2), self.request) + d2 = pq(str(inspect2)) + panels_attrs = [tab.attrib for tab in d1('[role="tabpanel"]')] + panels1 = list(d1('[role="tabpanel"]')) + panels2 = list(d2('[role="tabpanel"]')) + + # build tab list (merge version 1 and version2) + tabs1 = d1.find('[role="tab"]') + tabs2 = d2.find('[role="tab"]') + tabs_order = [t.get('id') for t in panels_attrs] + tabs = {} + for tab in tabs1 + tabs2: + tab_id = pq(tab).attr('aria-controls') + tabs[tab_id] = pq(tab).outer_html() + tabs = [tabs[k] for k in tabs_order if k in tabs] + + # build diff of each panel + panels_diff = list(map(htmldiff, panels1, panels2)) + panels_diff = [fix_result(t) for t in panels_diff] + + return { + 'tabs': tabs, + 'panels': zip(panels_attrs, panels_diff), + 'tab_class_names': d1('.pk-tabs').attr('class'), + } + def get_compare_json_context(self, snapshot1, snapshot2): s1 = json.dumps(snapshot1.serialization, sort_keys=True, indent=2) s2 = json.dumps(snapshot2.serialization, sort_keys=True, indent=2) diff --git a/chrono/manager/static/css/style.scss b/chrono/manager/static/css/style.scss index 273736a2..9928db6e 100644 --- a/chrono/manager/static/css/style.scss +++ b/chrono/manager/static/css/style.scss @@ -966,6 +966,33 @@ p.snapshot-description { margin: 0; } +div.diff { + margin: 1em 0; + h3 { + del, ins { + font-weight: bold; + background-color: transparent; + } + del { + color: #fbb6c2 !important; + } + ins { + color: #d4fcbc !important; + } + } +} + +ins { + text-decoration: none; + background-color: #d4fcbc; +} + +del { + text-decoration: line-through; + background-color: #fbb6c2; + color: #555; +} + table.diff { background: white; border: 1px solid #f3f3f3; diff --git a/chrono/manager/templates/chrono/manager_agenda_history_compare.html b/chrono/manager/templates/chrono/manager_agenda_history_compare.html index f0982f2a..ec52ff7a 100644 --- a/chrono/manager/templates/chrono/manager_agenda_history_compare.html +++ b/chrono/manager/templates/chrono/manager_agenda_history_compare.html @@ -3,6 +3,10 @@ {% block appbar %}

{% trans 'Compare snapshots' %} ({% if mode == 'json' %}{% trans "JSON" %}{% else %}{% trans "Inspect" %}{% endif %})

+ + {% trans "Compare inspect" %} + {% trans "Compare JSON" %} + {% endblock %} {% block breadcrumb %} diff --git a/chrono/manager/templates/chrono/manager_agenda_inspect.html b/chrono/manager/templates/chrono/manager_agenda_inspect.html index 46419061..0cbd2e42 100644 --- a/chrono/manager/templates/chrono/manager_agenda_inspect.html +++ b/chrono/manager/templates/chrono/manager_agenda_inspect.html @@ -12,314 +12,7 @@ {% block content %} -
-
- - - - {% if object.kind == 'events' %} - - - {% elif object.kind == 'meetings' %} - - - - {% elif object.kind == 'virtual' %} - - - {% endif %} -
-
- -
-
-
    - {% for label, value in object.get_inspect_fields %} -
  • - {% blocktrans %}{{ label }}:{% endblocktrans %} - {{ value }} -
  • - {% endfor %} -
-
-
- - - - - - {% if object.kind == 'events' %} - - - - - - {% elif object.kind == 'meetings' %} - - - - - - - - {% elif object.kind == "virtual" %} - - - - - - {% endif %} - -
-
+ {% include 'chrono/manager_agenda_inspect_fragment.html' %} {% endblock %} {% block sidebar %} diff --git a/chrono/manager/templates/chrono/manager_agenda_inspect_fragment.html b/chrono/manager/templates/chrono/manager_agenda_inspect_fragment.html new file mode 100644 index 00000000..b734a997 --- /dev/null +++ b/chrono/manager/templates/chrono/manager_agenda_inspect_fragment.html @@ -0,0 +1,309 @@ +{% load i18n %} +
+
+ + + + {% if object.kind == 'events' %} + + + {% elif object.kind == 'meetings' %} + + + + {% elif object.kind == 'virtual' %} + + + {% endif %} +
+
+ +
+
+
    + {% for label, value in object.get_inspect_fields %} +
  • + {% blocktrans %}{{ label }}:{% endblocktrans %} + {{ value }} +
  • + {% endfor %} +
+
+
+ + + + + + {% if object.kind == 'events' %} + + + + + + {% elif object.kind == 'meetings' %} + + + + + + + + {% elif object.kind == "virtual" %} + + + + + + {% endif %} + +
+
diff --git a/chrono/manager/templates/chrono/manager_category_history_compare.html b/chrono/manager/templates/chrono/manager_category_history_compare.html index fd7027df..2fa68ce9 100644 --- a/chrono/manager/templates/chrono/manager_category_history_compare.html +++ b/chrono/manager/templates/chrono/manager_category_history_compare.html @@ -3,6 +3,10 @@ {% block appbar %}

{% trans 'Compare snapshots' %} ({% if mode == 'json' %}{% trans "JSON" %}{% else %}{% trans "Inspect" %}{% endif %})

+ + {% trans "Compare inspect" %} + {% trans "Compare JSON" %} + {% endblock %} {% block breadcrumb %} diff --git a/chrono/manager/templates/chrono/manager_category_inspect.html b/chrono/manager/templates/chrono/manager_category_inspect.html index da6584cd..8d5bade6 100644 --- a/chrono/manager/templates/chrono/manager_category_inspect.html +++ b/chrono/manager/templates/chrono/manager_category_inspect.html @@ -11,26 +11,7 @@ {% endblock %} {% block content %} -
-
- -
-
- -
-
-
    - {% for label, value in object.get_inspect_fields %} -
  • - {% blocktrans %}{{ label }}:{% endblocktrans %} - {{ value }} -
  • - {% endfor %} -
-
-
-
-
+ {% include 'chrono/manager_category_inspect_fragment.html' %} {% endblock %} {% block sidebar %} diff --git a/chrono/manager/templates/chrono/manager_category_inspect_fragment.html b/chrono/manager/templates/chrono/manager_category_inspect_fragment.html new file mode 100644 index 00000000..869c12e2 --- /dev/null +++ b/chrono/manager/templates/chrono/manager_category_inspect_fragment.html @@ -0,0 +1,21 @@ +{% load i18n %} +
+
+ +
+
+ +
+
+
    + {% for label, value in object.get_inspect_fields %} +
  • + {% blocktrans %}{{ label }}:{% endblocktrans %} + {{ value }} +
  • + {% endfor %} +
+
+
+
+
diff --git a/chrono/manager/templates/chrono/manager_events_type_history_compare.html b/chrono/manager/templates/chrono/manager_events_type_history_compare.html index 80065547..4f228377 100644 --- a/chrono/manager/templates/chrono/manager_events_type_history_compare.html +++ b/chrono/manager/templates/chrono/manager_events_type_history_compare.html @@ -3,6 +3,10 @@ {% block appbar %}

{% trans 'Compare snapshots' %} ({% if mode == 'json' %}{% trans "JSON" %}{% else %}{% trans "Inspect" %}{% endif %})

+ + {% trans "Compare inspect" %} + {% trans "Compare JSON" %} + {% endblock %} {% block breadcrumb %} diff --git a/chrono/manager/templates/chrono/manager_events_type_inspect.html b/chrono/manager/templates/chrono/manager_events_type_inspect.html index 90ce07f4..4970c41c 100644 --- a/chrono/manager/templates/chrono/manager_events_type_inspect.html +++ b/chrono/manager/templates/chrono/manager_events_type_inspect.html @@ -11,52 +11,7 @@ {% endblock %} {% block content %} -
-
- - -
-
- -
-
-
    - {% for label, value in object.get_inspect_fields %} -
  • - {% blocktrans %}{{ label }}:{% endblocktrans %} - {{ value }} -
  • - {% endfor %} -
-
-
- - - -
-
+ {% include 'chrono/manager_events_type_inspect_fragment.html' %} {% endblock %} {% block sidebar %} diff --git a/chrono/manager/templates/chrono/manager_events_type_inspect_fragment.html b/chrono/manager/templates/chrono/manager_events_type_inspect_fragment.html new file mode 100644 index 00000000..2ad2facd --- /dev/null +++ b/chrono/manager/templates/chrono/manager_events_type_inspect_fragment.html @@ -0,0 +1,47 @@ +{% load i18n %} +
+
+ + +
+
+ +
+
+
    + {% for label, value in object.get_inspect_fields %} +
  • + {% blocktrans %}{{ label }}:{% endblocktrans %} + {{ value }} +
  • + {% endfor %} +
+
+
+ + + +
+
diff --git a/chrono/manager/templates/chrono/manager_resource_history_compare.html b/chrono/manager/templates/chrono/manager_resource_history_compare.html index db7b5433..4b4543e4 100644 --- a/chrono/manager/templates/chrono/manager_resource_history_compare.html +++ b/chrono/manager/templates/chrono/manager_resource_history_compare.html @@ -3,6 +3,10 @@ {% block appbar %}

{% trans 'Compare snapshots' %} ({% if mode == 'json' %}{% trans "JSON" %}{% else %}{% trans "Inspect" %}{% endif %})

+ + {% trans "Compare inspect" %} + {% trans "Compare JSON" %} + {% endblock %} {% block breadcrumb %} diff --git a/chrono/manager/templates/chrono/manager_resource_inspect.html b/chrono/manager/templates/chrono/manager_resource_inspect.html index 7e42ced0..009b814a 100644 --- a/chrono/manager/templates/chrono/manager_resource_inspect.html +++ b/chrono/manager/templates/chrono/manager_resource_inspect.html @@ -11,27 +11,7 @@ {% endblock %} {% block content %} -
-
- -
-
- -
-
-
    - {% for label, value in object.get_inspect_fields %} -
  • - {% blocktrans %}{{ label }}:{% endblocktrans %} - {{ value }} -
  • - {% endfor %} -
-
-
- -
-
+ {% include 'chrono/manager_resource_inspect_fragment.html' %} {% endblock %} {% block sidebar %} diff --git a/chrono/manager/templates/chrono/manager_resource_inspect_fragment.html b/chrono/manager/templates/chrono/manager_resource_inspect_fragment.html new file mode 100644 index 00000000..db6c45b2 --- /dev/null +++ b/chrono/manager/templates/chrono/manager_resource_inspect_fragment.html @@ -0,0 +1,22 @@ +{% load i18n %} +
+
+ +
+
+ +
+
+
    + {% for label, value in object.get_inspect_fields %} +
  • + {% blocktrans %}{{ label }}:{% endblocktrans %} + {{ value }} +
  • + {% endfor %} +
+
+
+ +
+
diff --git a/chrono/manager/templates/chrono/manager_unavailability_calendar_history_compare.html b/chrono/manager/templates/chrono/manager_unavailability_calendar_history_compare.html index c9e0550f..d04a18c6 100644 --- a/chrono/manager/templates/chrono/manager_unavailability_calendar_history_compare.html +++ b/chrono/manager/templates/chrono/manager_unavailability_calendar_history_compare.html @@ -3,6 +3,10 @@ {% block appbar %}

{% trans 'Compare snapshots' %} ({% if mode == 'json' %}{% trans "JSON" %}{% else %}{% trans "Inspect" %}{% endif %})

+ + {% trans "Compare inspect" %} + {% trans "Compare JSON" %} + {% endblock %} {% block breadcrumb %} diff --git a/chrono/manager/templates/chrono/manager_unavailability_calendar_inspect.html b/chrono/manager/templates/chrono/manager_unavailability_calendar_inspect.html index 9f02414d..ba54e363 100644 --- a/chrono/manager/templates/chrono/manager_unavailability_calendar_inspect.html +++ b/chrono/manager/templates/chrono/manager_unavailability_calendar_inspect.html @@ -11,58 +11,7 @@ {% endblock %} {% block content %} -
-
- - - -
-
- -
-
-
    - {% for label, value in object.get_inspect_fields %} -
  • - {% blocktrans %}{{ label }}:{% endblocktrans %} - {{ value }} -
  • - {% endfor %} -
-
-
- - - - - -
-
+ {% include 'chrono/manager_unavailability_calendar_inspect_fragment.html' %} {% endblock %} {% block sidebar %} diff --git a/chrono/manager/templates/chrono/manager_unavailability_calendar_inspect_fragment.html b/chrono/manager/templates/chrono/manager_unavailability_calendar_inspect_fragment.html new file mode 100644 index 00000000..47c6d46f --- /dev/null +++ b/chrono/manager/templates/chrono/manager_unavailability_calendar_inspect_fragment.html @@ -0,0 +1,53 @@ +{% load i18n %} +
+
+ + + +
+
+ +
+
+
    + {% for label, value in object.get_inspect_fields %} +
  • + {% blocktrans %}{{ label }}:{% endblocktrans %} + {{ value }} +
  • + {% endfor %} +
+
+
+ + + + + +
+
diff --git a/chrono/manager/views.py b/chrono/manager/views.py index f8f9621f..98ddc745 100644 --- a/chrono/manager/views.py +++ b/chrono/manager/views.py @@ -829,6 +829,7 @@ resource_history = ResourceHistoryView.as_view() class ResourceHistoryCompareView(InstanceWithSnapshotHistoryCompareView): template_name = 'chrono/manager_resource_history_compare.html' + inspect_template_name = 'chrono/manager_resource_inspect_fragment.html' model = Resource instance_context_key = 'resource' history_view = 'chrono-manager-resource-history' @@ -960,6 +961,7 @@ category_history = CategoryHistoryView.as_view() class CategoryHistoryCompareView(InstanceWithSnapshotHistoryCompareView): template_name = 'chrono/manager_category_history_compare.html' + inspect_template_name = 'chrono/manager_category_inspect_fragment.html' model = Category instance_context_key = 'category' history_view = 'chrono-manager-category-history' @@ -1148,6 +1150,7 @@ events_type_history = EventsTypeHistoryView.as_view() class EventsTypeHistoryCompareView(InstanceWithSnapshotHistoryCompareView): template_name = 'chrono/manager_events_type_history_compare.html' + inspect_template_name = 'chrono/manager_events_type_inspect_fragment.html' model = EventsType instance_context_key = 'events_type' history_view = 'chrono-manager-events-type-history' @@ -4209,9 +4212,12 @@ class AgendaInspectView(ManagedAgendaMixin, DetailView): 'desk_set', queryset=Desk.objects.prefetch_related( 'timeperiod_set', - 'timeperiodexception_set', 'timeperiodexceptionsource_set', 'unavailability_calendars', + Prefetch( + 'timeperiodexception_set', + queryset=TimePeriodException.objects.filter(source__isnull=True), + ), ), ), Prefetch('event_set', queryset=Event.objects.filter(primary_event__isnull=True)), @@ -4237,6 +4243,7 @@ agenda_history = AgendaHistoryView.as_view() class AgendaHistoryCompareView(ManagedAgendaMixin, InstanceWithSnapshotHistoryCompareView): template_name = 'chrono/manager_agenda_history_compare.html' + inspect_template_name = 'chrono/manager_agenda_inspect_fragment.html' model = Agenda instance_context_key = 'agenda' history_view = 'chrono-manager-agenda-history' @@ -4893,6 +4900,7 @@ class UnavailabilityCalendarHistoryCompareView( ManagedUnavailabilityCalendarMixin, InstanceWithSnapshotHistoryCompareView ): template_name = 'chrono/manager_unavailability_calendar_history_compare.html' + inspect_template_name = 'chrono/manager_unavailability_calendar_inspect_fragment.html' model = UnavailabilityCalendar instance_context_key = 'unavailability_calendar' history_view = 'chrono-manager-unavailability-calendar-history' diff --git a/debian/control b/debian/control index d5bbe97b..96e7cc34 100644 --- a/debian/control +++ b/debian/control @@ -14,6 +14,7 @@ Package: python3-chrono Architecture: all Depends: python3-django (>= 2:3.2), python3-gadjo, + python3-lxml, python3-publik-django-templatetags, python3-requests, python3-uwsgidecorators, diff --git a/pylint.rc b/pylint.rc index fe0e5bdd..147abf97 100644 --- a/pylint.rc +++ b/pylint.rc @@ -1,6 +1,7 @@ [MASTER] persistent=yes ignore=vendor,Bouncers,ezt.py +extension-pkg-allow-list=lxml [MESSAGES CONTROL] disable= diff --git a/setup.py b/setup.py index 7d1d869a..bf9c22ea 100644 --- a/setup.py +++ b/setup.py @@ -169,6 +169,7 @@ setup( 'workalendar', 'weasyprint', 'sorl-thumbnail', + 'lxml', ], zip_safe=False, cmdclass={ diff --git a/tests/manager/test_event.py b/tests/manager/test_event.py index 332159b3..68cdb80c 100644 --- a/tests/manager/test_event.py +++ b/tests/manager/test_event.py @@ -1026,7 +1026,7 @@ def test_import_events(app, admin_user): ) with CaptureQueriesContext(connection) as ctx: resp = resp.form.submit(status=302) - assert len(ctx.captured_queries) == 32 + assert len(ctx.captured_queries) == 31 assert Event.objects.count() == 5 assert set(Event.objects.values_list('slug', flat=True)) == { 'labelb', diff --git a/tests/manager/test_snapshot.py b/tests/manager/test_snapshot.py index b38fabfc..621c2fb5 100644 --- a/tests/manager/test_snapshot.py +++ b/tests/manager/test_snapshot.py @@ -44,15 +44,20 @@ def test_agenda_history(settings, app, admin_user): ] assert '(Version 42.0)' in resp.pyquery('tr:nth-child(1)').text() - resp = app.get( - '/manage/agendas/%s/history/compare/?version1=%s&version2=%s' - % (agenda.pk, snapshot1.pk, snapshot2.pk) - ) - assert 'Snapshot (%s)' % (snapshot1.pk) in resp - assert 'Snapshot (%s) - (Version 42.0)' % (snapshot2.pk) in resp - assert resp.text.count('diff_sub') == 1 - assert resp.text.count('diff_add') == 16 - assert resp.text.count('diff_chg') == 0 + for mode in ['json', 'inspect', '']: + resp = app.get( + '/manage/agendas/%s/history/compare/?version1=%s&version2=%s&mode=%s' + % (agenda.pk, snapshot1.pk, snapshot2.pk, mode) + ) + assert 'Snapshot (%s)' % (snapshot1.pk) in resp + assert 'Snapshot (%s) - (Version 42.0)' % (snapshot2.pk) in resp + if mode == 'inspect': + assert resp.text.count('') == 6 + assert resp.text.count('') == 0 + else: + assert resp.text.count('diff_sub') == 1 + assert resp.text.count('diff_add') == 16 + assert resp.text.count('diff_chg') == 0 resp = app.get( '/manage/agendas/%s/history/compare/?version1=%s&version2=%s' % (agenda.pk, snapshot2.pk, snapshot1.pk) @@ -112,15 +117,20 @@ def test_category_history(settings, app, admin_user): ] assert '(Version 42.0)' in resp.pyquery('tr:nth-child(1)').text() - resp = app.get( - '/manage/category/%s/history/compare/?version1=%s&version2=%s' - % (category.pk, snapshot1.pk, snapshot2.pk) - ) - assert 'Snapshot (%s)' % (snapshot1.pk) in resp - assert 'Snapshot (%s) - (Version 42.0)' % (snapshot2.pk) in resp - assert resp.text.count('diff_sub') == 0 - assert resp.text.count('diff_add') == 0 - assert resp.text.count('diff_chg') == 2 + for mode in ['json', 'inspect', '']: + resp = app.get( + '/manage/category/%s/history/compare/?version1=%s&version2=%s&mode=%s' + % (category.pk, snapshot1.pk, snapshot2.pk, mode) + ) + assert 'Snapshot (%s)' % (snapshot1.pk) in resp + assert 'Snapshot (%s) - (Version 42.0)' % (snapshot2.pk) in resp + if mode == 'inspect': + assert resp.text.count('') == 1 + assert resp.text.count('') == 1 + else: + assert resp.text.count('diff_sub') == 0 + assert resp.text.count('diff_add') == 0 + assert resp.text.count('diff_chg') == 2 resp = app.get( '/manage/category/%s/history/compare/?version1=%s&version2=%s' % (category.pk, snapshot2.pk, snapshot1.pk) @@ -154,15 +164,20 @@ def test_events_type_history(settings, app, admin_user): ] assert '(Version 42.0)' in resp.pyquery('tr:nth-child(1)').text() - resp = app.get( - '/manage/events-type/%s/history/compare/?version1=%s&version2=%s' - % (events_type.pk, snapshot1.pk, snapshot2.pk) - ) - assert 'Snapshot (%s)' % (snapshot1.pk) in resp - assert 'Snapshot (%s) - (Version 42.0)' % (snapshot2.pk) in resp - assert resp.text.count('diff_sub') == 0 - assert resp.text.count('diff_add') == 0 - assert resp.text.count('diff_chg') == 2 + for mode in ['json', 'inspect', '']: + resp = app.get( + '/manage/events-type/%s/history/compare/?version1=%s&version2=%s&mode=%s' + % (events_type.pk, snapshot1.pk, snapshot2.pk, mode) + ) + assert 'Snapshot (%s)' % (snapshot1.pk) in resp + assert 'Snapshot (%s) - (Version 42.0)' % (snapshot2.pk) in resp + if mode == 'inspect': + assert resp.text.count('') == 1 + assert resp.text.count('') == 1 + else: + assert resp.text.count('diff_sub') == 0 + assert resp.text.count('diff_add') == 0 + assert resp.text.count('diff_chg') == 2 resp = app.get( '/manage/events-type/%s/history/compare/?version1=%s&version2=%s' % (events_type.pk, snapshot2.pk, snapshot1.pk) @@ -196,15 +211,20 @@ def test_resource_history(settings, app, admin_user): ] assert '(Version 42.0)' in resp.pyquery('tr:nth-child(1)').text() - resp = app.get( - '/manage/resource/%s/history/compare/?version1=%s&version2=%s' - % (resource.pk, snapshot1.pk, snapshot2.pk) - ) - assert 'Snapshot (%s)' % (snapshot1.pk) in resp - assert 'Snapshot (%s) - (Version 42.0)' % (snapshot2.pk) in resp - assert resp.text.count('diff_sub') == 0 - assert resp.text.count('diff_add') == 0 - assert resp.text.count('diff_chg') == 2 + for mode in ['json', 'inspect', '']: + resp = app.get( + '/manage/resource/%s/history/compare/?version1=%s&version2=%s&mode=%s' + % (resource.pk, snapshot1.pk, snapshot2.pk, mode) + ) + assert 'Snapshot (%s)' % (snapshot1.pk) in resp + assert 'Snapshot (%s) - (Version 42.0)' % (snapshot2.pk) in resp + if mode == 'inspect': + assert resp.text.count('') == 1 + assert resp.text.count('') == 1 + else: + assert resp.text.count('diff_sub') == 0 + assert resp.text.count('diff_add') == 0 + assert resp.text.count('diff_chg') == 2 resp = app.get( '/manage/resource/%s/history/compare/?version1=%s&version2=%s' % (resource.pk, snapshot2.pk, snapshot1.pk) @@ -238,15 +258,20 @@ def test_unavailability_calendar_history(settings, app, admin_user): ] assert '(Version 42.0)' in resp.pyquery('tr:nth-child(1)').text() - resp = app.get( - '/manage/unavailability-calendar/%s/history/compare/?version1=%s&version2=%s' - % (unavailability_calendar.pk, snapshot1.pk, snapshot2.pk) - ) - assert 'Snapshot (%s)' % (snapshot1.pk) in resp - assert 'Snapshot (%s) - (Version 42.0)' % (snapshot2.pk) in resp - assert resp.text.count('diff_sub') == 0 - assert resp.text.count('diff_add') == 0 - assert resp.text.count('diff_chg') == 2 + for mode in ['json', 'inspect', '']: + resp = app.get( + '/manage/unavailability-calendar/%s/history/compare/?version1=%s&version2=%s&mode=%s' + % (unavailability_calendar.pk, snapshot1.pk, snapshot2.pk, mode) + ) + assert 'Snapshot (%s)' % (snapshot1.pk) in resp + assert 'Snapshot (%s) - (Version 42.0)' % (snapshot2.pk) in resp + if mode == 'inspect': + assert resp.text.count('') == 1 + assert resp.text.count('') == 1 + else: + assert resp.text.count('diff_sub') == 0 + assert resp.text.count('diff_add') == 0 + assert resp.text.count('diff_chg') == 2 resp = app.get( '/manage/unavailability-calendar/%s/history/compare/?version1=%s&version2=%s' % (unavailability_calendar.pk, snapshot2.pk, snapshot1.pk) diff --git a/tox.ini b/tox.ini index b0aed5b9..efaa8edb 100644 --- a/tox.ini +++ b/tox.ini @@ -67,6 +67,7 @@ deps = psycopg2-binary<2.9 git+https://git.entrouvert.org/publik-django-templatetags.git responses + lxml commands = ./getlasso3.sh pylint: ./pylint.sh chrono/ tests/