1import datetime
2
3from io import BytesIO
4
5from django.conf import settings
6from django.test import TestCase
7from django.urls import reverse
8from django.utils import timezone
9from openpyxl import load_workbook
10
11from wagtail.core.models import Page, PageLogEntry
12from wagtail.tests.utils import WagtailTestUtils
13
14
15class TestLockedPagesView(TestCase, WagtailTestUtils):
16    def setUp(self):
17        self.user = self.login()
18
19    def get(self, params={}):
20        return self.client.get(reverse('wagtailadmin_reports:locked_pages'), params)
21
22    def test_simple(self):
23        response = self.get()
24        self.assertEqual(response.status_code, 200)
25        self.assertTemplateUsed(response, 'wagtailadmin/reports/locked_pages.html')
26
27        # Initially there should be no locked pages
28        self.assertContains(response, "No locked pages found.")
29
30        self.page = Page.objects.first()
31        self.page.locked = True
32        self.page.locked_by = self.user
33        self.page.locked_at = timezone.now()
34        self.page.save()
35
36        # Now the listing should contain our locked page
37        response = self.get()
38        self.assertEqual(response.status_code, 200)
39        self.assertTemplateUsed(response, 'wagtailadmin/reports/locked_pages.html')
40        self.assertNotContains(response, "No locked pages found.")
41        self.assertContains(response, self.page.title)
42
43    def test_csv_export(self):
44
45        self.page = Page.objects.first()
46        self.page.locked = True
47        self.page.locked_by = self.user
48        if settings.USE_TZ:
49            # 12:00 UTC
50            self.page.locked_at = '2013-02-01T12:00:00.000Z'
51            self.page.latest_revision_created_at = '2013-01-01T12:00:00.000Z'
52        else:
53            # 12:00 in no specific timezone
54            self.page.locked_at = '2013-02-01T12:00:00'
55            self.page.latest_revision_created_at = '2013-01-01T12:00:00'
56        self.page.save()
57
58        response = self.get(params={'export': 'csv'})
59
60        # Check response
61        self.assertEqual(response.status_code, 200)
62        data_lines = response.getvalue().decode().split("\n")
63        self.assertEqual(data_lines[0], 'Title,Updated,Status,Type,Locked At,Locked By\r')
64        if settings.USE_TZ:
65            self.assertEqual(data_lines[1], 'Root,2013-01-01 12:00:00+00:00,live,Page,2013-02-01 12:00:00+00:00,test@email.com\r')
66        else:
67            self.assertEqual(data_lines[1], 'Root,2013-01-01 12:00:00,live,Page,2013-02-01 12:00:00,test@email.com\r')
68
69    def test_xlsx_export(self):
70
71        self.page = Page.objects.first()
72        self.page.locked = True
73        self.page.locked_by = self.user
74        if settings.USE_TZ:
75            # 12:00 UTC
76            self.page.locked_at = '2013-02-01T12:00:00.000Z'
77            self.page.latest_revision_created_at = '2013-01-01T12:00:00.000Z'
78        else:
79            # 12:00 in no specific timezone
80            self.page.locked_at = '2013-02-01T12:00:00'
81            self.page.latest_revision_created_at = '2013-01-01T12:00:00'
82        self.page.save()
83
84        response = self.get(params={'export': 'xlsx'})
85
86        # Check response - the locked page info should be in it
87        self.assertEqual(response.status_code, 200)
88        workbook_data = response.getvalue()
89        worksheet = load_workbook(filename=BytesIO(workbook_data))['Sheet1']
90        cell_array = [[cell.value for cell in row] for row in worksheet.rows]
91        self.assertEqual(cell_array[0], ['Title', 'Updated', 'Status', 'Type', 'Locked At', 'Locked By'])
92        self.assertEqual(cell_array[1], ['Root', datetime.datetime(2013, 1, 1, 12, 0), 'live', 'Page', datetime.datetime(2013, 2, 1, 12, 0), 'test@email.com'])
93        self.assertEqual(len(cell_array), 2)
94
95
96class TestFilteredLockedPagesView(TestCase, WagtailTestUtils):
97    fixtures = ['test.json']
98
99    def setUp(self):
100        self.user = self.login()
101        self.unpublished_page = Page.objects.get(url_path='/home/events/tentative-unpublished-event/')
102        self.unpublished_page.locked = True
103        self.unpublished_page.locked_by = self.user
104        self.unpublished_page.locked_at = timezone.now()
105        self.unpublished_page.save()
106
107    def get(self, params={}):
108        return self.client.get(reverse('wagtailadmin_reports:locked_pages'), params)
109
110    def test_filter_by_live(self):
111        response = self.get(params={'live': 'true'})
112        self.assertEqual(response.status_code, 200)
113        self.assertNotContains(response, "Tentative Unpublished Event")
114        self.assertContains(response, "My locked page")
115
116        response = self.get(params={'live': 'false'})
117        self.assertEqual(response.status_code, 200)
118        self.assertContains(response, "Tentative Unpublished Event")
119        self.assertNotContains(response, "My locked page")
120
121    def test_filter_by_user(self):
122        response = self.get(params={'locked_by': self.user.pk})
123        self.assertEqual(response.status_code, 200)
124        self.assertContains(response, "Tentative Unpublished Event")
125        self.assertNotContains(response, "My locked page")
126
127
128class TestFilteredLogEntriesView(TestCase, WagtailTestUtils):
129    fixtures = ['test.json']
130
131    def setUp(self):
132        self.user = self.login()
133        self.home_page = Page.objects.get(url_path='/home/')
134
135        self.create_log = PageLogEntry.objects.log_action(self.home_page, 'wagtail.create')
136        self.edit_log_1 = PageLogEntry.objects.log_action(self.home_page, 'wagtail.edit')
137        self.edit_log_2 = PageLogEntry.objects.log_action(self.home_page, 'wagtail.edit')
138        self.edit_log_3 = PageLogEntry.objects.log_action(self.home_page, 'wagtail.edit')
139
140        self.create_comment_log = PageLogEntry.objects.log_action(self.home_page, 'wagtail.comments.create', data={
141            'comment': {
142                'contentpath': 'title',
143                'text': 'Foo',
144            }
145        })
146        self.edit_comment_log = PageLogEntry.objects.log_action(self.home_page, 'wagtail.comments.edit', data={
147            'comment': {
148                'contentpath': 'title',
149                'text': 'Edited',
150            }
151        })
152        self.create_reply_log = PageLogEntry.objects.log_action(self.home_page, 'wagtail.comments.create_reply', data={
153            'comment': {
154                'contentpath': 'title',
155                'text': 'Foo',
156            }
157        })
158
159    def get(self, params={}):
160        return self.client.get(reverse('wagtailadmin_reports:site_history'), params)
161
162    def assert_log_entries(self, response, expected):
163        actual = set(response.context['object_list'])
164        self.assertSetEqual(actual, set(expected))
165
166    def test_unfiltered(self):
167        response = self.get()
168        self.assertEqual(response.status_code, 200)
169        self.assert_log_entries(response, [
170            self.create_log,
171            self.edit_log_1,
172            self.edit_log_2,
173            self.edit_log_3,
174            self.create_comment_log,
175            self.edit_comment_log,
176            self.create_reply_log,
177        ])
178
179    def test_filter_by_action(self):
180        response = self.get(params={'action': 'wagtail.edit'})
181        self.assertEqual(response.status_code, 200)
182        self.assert_log_entries(response, [
183            self.edit_log_1,
184            self.edit_log_2,
185            self.edit_log_3,
186        ])
187
188    def test_hide_commenting_actions(self):
189        response = self.get(params={'hide_commenting_actions': 'on'})
190        self.assertEqual(response.status_code, 200)
191        self.assert_log_entries(response, [
192            self.create_log,
193            self.edit_log_1,
194            self.edit_log_2,
195            self.edit_log_3,
196        ])
197