1import json
2
3from django.contrib.auth import get_user_model
4from django.test import TestCase
5from django.urls import reverse
6from django.utils.http import urlencode
7
8from wagtail.admin.views.chooser import can_choose_page
9from wagtail.core.models import Page, UserPagePermissionsProxy
10from wagtail.tests.testapp.models import EventIndex, EventPage, SimplePage, SingleEventPage
11from wagtail.tests.utils import WagtailTestUtils
12
13
14class TestChooserBrowse(TestCase, WagtailTestUtils):
15    def setUp(self):
16        self.root_page = Page.objects.get(id=2)
17
18        # Add child page
19        self.child_page = SimplePage(title="foobarbaz", content="hello")
20        self.root_page.add_child(instance=self.child_page)
21
22        self.login()
23
24    def get(self, params={}):
25        return self.client.get(reverse('wagtailadmin_choose_page'), params)
26
27    def test_simple(self):
28        response = self.get()
29        self.assertEqual(response.status_code, 200)
30        self.assertTemplateUsed(response, 'wagtailadmin/chooser/browse.html')
31
32    def test_construct_queryset_hook(self):
33        page = SimplePage(title="Test shown", content="hello")
34        Page.get_first_root_node().add_child(instance=page)
35
36        page_not_shown = SimplePage(title="Test not shown", content="hello")
37        Page.get_first_root_node().add_child(instance=page_not_shown)
38
39        def filter_pages(pages, request):
40            return pages.filter(id=page.id)
41
42        with self.register_hook('construct_page_chooser_queryset', filter_pages):
43            response = self.get()
44        self.assertEqual(len(response.context['pages']), 1)
45        self.assertEqual(response.context['pages'][0].specific, page)
46
47
48class TestCanChooseRootFlag(TestCase, WagtailTestUtils):
49    def setUp(self):
50        self.login()
51
52    def get(self, params={}):
53        return self.client.get(reverse('wagtailadmin_choose_page'), params)
54
55    def test_cannot_choose_root_by_default(self):
56        response = self.get()
57        self.assertNotContains(response, '/admin/pages/1/edit/')
58
59    def test_can_choose_root(self):
60        response = self.get({'can_choose_root': 'true'})
61        self.assertContains(response, '/admin/pages/1/edit/')
62
63
64class TestChooserBrowseChild(TestCase, WagtailTestUtils):
65    def setUp(self):
66        self.root_page = Page.objects.get(id=2)
67
68        # Add child page
69        self.child_page = SimplePage(title="foobarbaz", content="hello")
70        self.root_page.add_child(instance=self.child_page)
71
72        self.login()
73
74    def get(self, params={}):
75        return self.client.get(reverse('wagtailadmin_choose_page_child',
76                                       args=(self.root_page.id,)), params)
77
78    def get_invalid(self, params={}):
79        return self.client.get(reverse('wagtailadmin_choose_page_child',
80                                       args=(9999999,)), params)
81
82    def test_simple(self):
83        response = self.get()
84        self.assertEqual(response.status_code, 200)
85        self.assertTemplateUsed(response, 'wagtailadmin/chooser/browse.html')
86
87    def test_get_invalid(self):
88        self.assertEqual(self.get_invalid().status_code, 404)
89
90    def test_with_page_type(self):
91        # Add a page that is not a SimplePage
92        event_page = EventPage(
93            title="event",
94            location='the moon', audience='public',
95            cost='free', date_from='2001-01-01',
96        )
97        self.root_page.add_child(instance=event_page)
98
99        # Add a page with a child page
100        event_index_page = EventIndex(
101            title="events",
102        )
103        self.root_page.add_child(instance=event_index_page)
104        event_index_page.add_child(instance=EventPage(
105            title="other event",
106            location='the moon', audience='public',
107            cost='free', date_from='2001-01-01',
108        ))
109
110        # Send request
111        response = self.get({'page_type': 'tests.simplepage'})
112        self.assertEqual(response.status_code, 200)
113        self.assertTemplateUsed(response, 'wagtailadmin/chooser/browse.html')
114        self.assertEqual(response.context['page_type_string'], 'tests.simplepage')
115
116        pages = {
117            page.id: page
118            for page in response.context['pages'].object_list
119        }
120
121        # Child page is a simple page directly underneath root
122        # so should appear in the list
123        self.assertIn(self.child_page.id, pages)
124        self.assertTrue(pages[self.child_page.id].can_choose)
125        self.assertFalse(pages[self.child_page.id].can_descend)
126
127        # Event page is not a simple page and is not descendable either
128        # so should not appear in the list
129        self.assertNotIn(event_page.id, pages)
130
131        # Event index page is not a simple page but has a child and is therefore descendable
132        # so should appear in the list
133        self.assertIn(event_index_page.id, pages)
134        self.assertFalse(pages[event_index_page.id].can_choose)
135        self.assertTrue(pages[event_index_page.id].can_descend)
136
137    def test_with_url_extended_page_type(self):
138        # Add a page that overrides the url path
139        single_event_page = SingleEventPage(
140            title="foo",
141            location='the moon', audience='public',
142            cost='free', date_from='2001-01-01',
143        )
144        self.root_page.add_child(instance=single_event_page)
145
146        # Send request
147        response = self.get()
148        self.assertEqual(response.status_code, 200)
149        self.assertTemplateUsed(response, 'wagtailadmin/chooser/browse.html')
150
151        page_urls = [
152            page.url
153            for page in response.context['pages']
154        ]
155
156        self.assertIn('/foo/pointless-suffix/', page_urls)
157
158    def test_with_blank_page_type(self):
159        # a blank page_type parameter should be equivalent to an absent parameter
160        # (or an explicit page_type of wagtailcore.page)
161        response = self.get({'page_type': ''})
162        self.assertEqual(response.status_code, 200)
163        self.assertTemplateUsed(response, 'wagtailadmin/chooser/browse.html')
164
165    def test_with_multiple_page_types(self):
166        # Add a page that is not a SimplePage
167        event_page = EventPage(
168            title="event",
169            location='the moon', audience='public',
170            cost='free', date_from='2001-01-01',
171        )
172        self.root_page.add_child(instance=event_page)
173
174        # Send request
175        response = self.get({'page_type': 'tests.simplepage,tests.eventpage'})
176        self.assertEqual(response.status_code, 200)
177        self.assertTemplateUsed(response, 'wagtailadmin/chooser/browse.html')
178        self.assertEqual(response.context['page_type_string'], 'tests.simplepage,tests.eventpage')
179
180        pages = {
181            page.id: page
182            for page in response.context['pages'].object_list
183        }
184
185        # Simple page in results, as before
186        self.assertIn(self.child_page.id, pages)
187        self.assertTrue(pages[self.child_page.id].can_choose)
188
189        # Event page should now also be choosable
190        self.assertIn(event_page.id, pages)
191        self.assertTrue(pages[self.child_page.id].can_choose)
192
193    def test_with_unknown_page_type(self):
194        response = self.get({'page_type': 'foo.bar'})
195        self.assertEqual(response.status_code, 404)
196
197    def test_with_bad_page_type(self):
198        response = self.get({'page_type': 'wagtailcore.site'})
199        self.assertEqual(response.status_code, 404)
200
201    def test_with_invalid_page_type(self):
202        response = self.get({'page_type': 'foo'})
203        self.assertEqual(response.status_code, 404)
204
205    def test_with_admin_display_title(self):
206        # Check the display of the child page title when it's a child
207        response = self.get({'page_type': 'wagtailcore.Page'})
208        self.assertEqual(response.status_code, 200)
209        self.assertTemplateUsed(response, 'wagtailadmin/chooser/browse.html')
210
211        html = response.json().get('html')
212        self.assertInHTML("foobarbaz (simple page)", html)
213
214        # The data-title attribute should not use the custom admin display title,
215        # because JS code that uses that attribute (e.g. the rich text editor)
216        # should use the real page title.
217        self.assertIn('data-title="foobarbaz"', html)
218
219    def test_parent_with_admin_display_title(self):
220        # Add another child under child_page so it renders a chooser list
221        leaf_page = SimplePage(title="quux", content="goodbye")
222        self.child_page.add_child(instance=leaf_page)
223
224        # Use the child page as the chooser parent
225        response = self.client.get(
226            reverse('wagtailadmin_choose_page_child', args=(self.child_page.id,)),
227            params={'page_type': 'wagtailcore.Page'}
228        )
229        self.assertEqual(response.status_code, 200)
230        self.assertTemplateUsed(response, 'wagtailadmin/chooser/browse.html')
231
232        self.assertInHTML("foobarbaz (simple page)", response.json().get('html'))
233        self.assertInHTML("quux (simple page)", response.json().get('html'))
234
235    def test_admin_display_title_breadcrumb(self):
236        # Add another child under child_page so we get breadcrumbs
237        leaf_page = SimplePage(title="quux", content="goodbye")
238        self.child_page.add_child(instance=leaf_page)
239
240        # Use the leaf page as the chooser parent, so child is in the breadcrumbs
241        response = self.client.get(
242            reverse('wagtailadmin_choose_page_child', args=(leaf_page.id,))
243        )
244        self.assertEqual(response.status_code, 200)
245        self.assertTemplateUsed(response, 'wagtailadmin/chooser/browse.html')
246
247        # Look for a link element in the breadcrumbs with the admin title
248        self.assertTagInHTML(
249            '<li><a href="/admin/choose-page/{page_id}/?" class="navigate-pages">{page_title}</a></li>'.format(
250                page_id=self.child_page.id,
251                page_title="foobarbaz (simple page)",
252            ),
253            response.json().get('html')
254        )
255
256    def setup_pagination_test_data(self):
257        # Create lots of pages
258        for i in range(100):
259            new_page = SimplePage(
260                title="foobarbaz",
261                slug="foobarbaz-%d" % i,
262                content="hello",
263            )
264            self.root_page.add_child(instance=new_page)
265
266    def test_pagination_basic(self):
267        self.setup_pagination_test_data()
268
269        response = self.get()
270        self.assertEqual(response.context['pages'].paginator.num_pages, 5)
271        self.assertEqual(response.context['pages'].number, 1)
272
273    def test_pagination_another_page(self):
274        self.setup_pagination_test_data()
275
276        response = self.get({'p': 2})
277        self.assertEqual(response.context['pages'].number, 2)
278
279    def test_pagination_invalid_page(self):
280        self.setup_pagination_test_data()
281
282        response = self.get({'p': 'foo'})
283        self.assertEqual(response.context['pages'].number, 1)
284
285    def test_pagination_out_of_range_page(self):
286        self.setup_pagination_test_data()
287
288        response = self.get({'p': 100})
289        self.assertEqual(response.context['pages'].number, 5)
290
291
292class TestChooserSearch(TestCase, WagtailTestUtils):
293    def setUp(self):
294        self.root_page = Page.objects.get(id=2)
295
296        # Add child page
297        self.child_page = SimplePage(title="foobarbaz", content="hello")
298        self.root_page.add_child(instance=self.child_page)
299
300        self.login()
301
302    def get(self, params=None):
303        return self.client.get(reverse('wagtailadmin_choose_page_search'), params or {})
304
305    def test_simple(self):
306        response = self.get({'q': "foobarbaz"})
307        self.assertEqual(response.status_code, 200)
308        self.assertTemplateUsed(response, 'wagtailadmin/chooser/_search_results.html')
309        self.assertContains(response, "There is 1 match")
310        self.assertContains(response, "foobarbaz")
311
312    def test_result_uses_custom_admin_display_title(self):
313        single_event_page = SingleEventPage(
314            title="Lunar event",
315            location='the moon', audience='public',
316            cost='free', date_from='2001-01-01',
317        )
318        self.root_page.add_child(instance=single_event_page)
319
320        response = self.get({'q': "lunar"})
321        self.assertEqual(response.status_code, 200)
322        self.assertTemplateUsed(response, 'wagtailadmin/chooser/_search_results.html')
323        self.assertContains(response, "Lunar event (single event)")
324
325    def test_search_no_results(self):
326        response = self.get({'q': "quux"})
327        self.assertEqual(response.status_code, 200)
328        self.assertContains(response, "There are 0 matches")
329
330    def test_with_page_type(self):
331        # Add a page that is not a SimplePage
332        event_page = EventPage(
333            title="foo",
334            location='the moon', audience='public',
335            cost='free', date_from='2001-01-01',
336        )
337        self.root_page.add_child(instance=event_page)
338
339        # Send request
340        response = self.get({'q': "foo", 'page_type': 'tests.simplepage'})
341        self.assertEqual(response.status_code, 200)
342        self.assertTemplateUsed(response, 'wagtailadmin/chooser/_search_results.html')
343        self.assertEqual(response.context['page_type_string'], 'tests.simplepage')
344
345        pages = {
346            page.id: page
347            for page in response.context['pages']
348        }
349
350        self.assertIn(self.child_page.id, pages)
351
352        # Not a simple page
353        self.assertNotIn(event_page.id, pages)
354
355    def test_with_blank_page_type(self):
356        # a blank page_type parameter should be equivalent to an absent parameter
357        # (or an explicit page_type of wagtailcore.page)
358        response = self.get({'q': "foobarbaz", 'page_type': ''})
359        self.assertEqual(response.status_code, 200)
360        self.assertTemplateUsed(response, 'wagtailadmin/chooser/_search_results.html')
361        self.assertContains(response, "There is 1 match")
362        self.assertContains(response, "foobarbaz")
363
364    def test_with_multiple_page_types(self):
365        # Add a page that is not a SimplePage
366        event_page = EventPage(
367            title="foo",
368            location='the moon', audience='public',
369            cost='free', date_from='2001-01-01',
370        )
371        self.root_page.add_child(instance=event_page)
372
373        # Send request
374        response = self.get({'q': "foo", 'page_type': 'tests.simplepage,tests.eventpage'})
375        self.assertEqual(response.status_code, 200)
376        self.assertTemplateUsed(response, 'wagtailadmin/chooser/_search_results.html')
377        self.assertEqual(response.context['page_type_string'], 'tests.simplepage,tests.eventpage')
378
379        pages = {
380            page.id: page
381            for page in response.context['pages']
382        }
383
384        # Simple page in results, as before
385        self.assertIn(self.child_page.id, pages)
386
387        # Event page should now also be choosable
388        self.assertIn(event_page.id, pages)
389
390    def test_with_unknown_page_type(self):
391        response = self.get({'page_type': 'foo.bar'})
392        self.assertEqual(response.status_code, 404)
393
394    def test_with_bad_page_type(self):
395        response = self.get({'page_type': 'wagtailcore.site'})
396        self.assertEqual(response.status_code, 404)
397
398    def test_with_invalid_page_type(self):
399        response = self.get({'page_type': 'foo'})
400        self.assertEqual(response.status_code, 404)
401
402    def test_construct_queryset_hook(self):
403        page = SimplePage(title="Test shown", content="hello")
404        self.root_page.add_child(instance=page)
405
406        page_not_shown = SimplePage(title="Test not shown", content="hello")
407        self.root_page.add_child(instance=page_not_shown)
408
409        def filter_pages(pages, request):
410            return pages.filter(id=page.id)
411
412        with self.register_hook('construct_page_chooser_queryset', filter_pages):
413            response = self.get({'q': 'Test'})
414        self.assertEqual(len(response.context['pages']), 1)
415        self.assertEqual(response.context['pages'][0].specific, page)
416
417
418class TestAutomaticRootPageDetection(TestCase, WagtailTestUtils):
419    def setUp(self):
420        self.tree_root = Page.objects.get(id=1)
421        self.home_page = Page.objects.get(id=2)
422
423        self.about_page = self.home_page.add_child(instance=SimplePage(
424            title='About', content='About Foo'))
425        self.contact_page = self.about_page.add_child(instance=SimplePage(
426            title='Contact', content='Content Foo'))
427        self.people_page = self.about_page.add_child(instance=SimplePage(
428            title='People', content='The people of Foo'))
429
430        self.event_index = self.make_event_section('Events')
431
432        self.login()
433
434    def make_event_section(self, name):
435        event_index = self.home_page.add_child(instance=EventIndex(
436            title=name))
437        event_index.add_child(instance=EventPage(
438            title='First Event',
439            location='Bar', audience='public',
440            cost='free', date_from='2001-01-01'))
441        event_index.add_child(instance=EventPage(
442            title='Second Event',
443            location='Baz', audience='public',
444            cost='free', date_from='2001-01-01'))
445        return event_index
446
447    def get_best_root(self, params={}):
448        response = self.client.get(reverse('wagtailadmin_choose_page'), params)
449        return response.context['parent_page'].specific
450
451    def test_no_type_filter(self):
452        self.assertEqual(self.get_best_root(), self.tree_root)
453
454    def test_type_page(self):
455        self.assertEqual(
456            self.get_best_root({'page_type': 'wagtailcore.Page'}),
457            self.tree_root)
458
459    def test_type_eventpage(self):
460        """
461        The chooser should start at the EventIndex that holds all the
462        EventPages.
463        """
464        self.assertEqual(
465            self.get_best_root({'page_type': 'tests.EventPage'}),
466            self.event_index)
467
468    def test_type_eventpage_two_indexes(self):
469        """
470        The chooser should start at the home page, as there are two
471        EventIndexes with EventPages.
472        """
473        self.make_event_section('Other events')
474        self.assertEqual(
475            self.get_best_root({'page_type': 'tests.EventPage'}),
476            self.home_page)
477
478    def test_type_simple_page(self):
479        """
480        The chooser should start at the home page, as all SimplePages are
481        directly under it
482        """
483        self.assertEqual(
484            self.get_best_root({'page_type': 'tests.BusinessIndex'}),
485            self.tree_root)
486
487    def test_type_missing(self):
488        """
489        The chooser should start at the root, as there are no BusinessIndexes
490        """
491        self.assertEqual(
492            self.get_best_root({'page_type': 'tests.BusinessIndex'}),
493            self.tree_root)
494
495
496class TestChooserExternalLink(TestCase, WagtailTestUtils):
497    def setUp(self):
498        self.login()
499
500    def get(self, params={}):
501        return self.client.get(reverse('wagtailadmin_choose_page_external_link'), params)
502
503    def post(self, post_data={}, url_params={}):
504        url = reverse('wagtailadmin_choose_page_external_link')
505        if url_params:
506            url += '?' + urlencode(url_params)
507        return self.client.post(url, post_data)
508
509    def test_simple(self):
510        response = self.get()
511        self.assertEqual(response.status_code, 200)
512        self.assertTemplateUsed(response, 'wagtailadmin/chooser/external_link.html')
513
514    def test_prepopulated_form(self):
515        response = self.get({'link_text': 'Torchbox', 'link_url': 'https://torchbox.com/'})
516        self.assertEqual(response.status_code, 200)
517        self.assertContains(response, 'Torchbox')
518        self.assertContains(response, 'https://torchbox.com/')
519
520    def test_create_link(self):
521        response = self.post({'external-link-chooser-url': 'http://www.example.com/', 'external-link-chooser-link_text': 'example'})
522        self.assertEqual(response.status_code, 200)
523        response_json = json.loads(response.content.decode())
524        self.assertEqual(response_json['step'], 'external_link_chosen')
525        self.assertEqual(response_json['result']['url'], "http://www.example.com/")
526        self.assertEqual(response_json['result']['title'], "example")  # When link text is given, it is used
527        self.assertEqual(response_json['result']['prefer_this_title_as_link_text'], True)
528
529    def test_create_link_without_text(self):
530        response = self.post({'external-link-chooser-url': 'http://www.example.com/'})
531        self.assertEqual(response.status_code, 200)
532        response_json = json.loads(response.content.decode())
533        self.assertEqual(response_json['step'], 'external_link_chosen')
534        self.assertEqual(response_json['result']['url'], "http://www.example.com/")
535        self.assertEqual(response_json['result']['title'], "http://www.example.com/")  # When no text is given, it uses the url
536        self.assertEqual(response_json['result']['prefer_this_title_as_link_text'], False)
537
538    def test_notice_changes_to_link_text(self):
539        response = self.post(
540            {'external-link-chooser-url': 'http://www.example.com/', 'external-link-chooser-link_text': 'example'},  # POST data
541            {'link_url': 'http://old.example.com/', 'link_text': 'example'}  # GET params - initial data
542        )
543        result = json.loads(response.content.decode())['result']
544        self.assertEqual(result['url'], "http://www.example.com/")
545        self.assertEqual(result['title'], "example")
546        # no change to link text, so prefer the existing link/selection content where available
547        self.assertEqual(result['prefer_this_title_as_link_text'], False)
548
549        response = self.post(
550            {'external-link-chooser-url': 'http://www.example.com/', 'external-link-chooser-link_text': 'new example'},  # POST data
551            {'link_url': 'http://old.example.com/', 'link_text': 'example'}  # GET params - initial data
552        )
553        result = json.loads(response.content.decode())['result']
554        self.assertEqual(result['url'], "http://www.example.com/")
555        self.assertEqual(result['title'], "new example")
556        # link text has changed, so tell the caller to use it
557        self.assertEqual(result['prefer_this_title_as_link_text'], True)
558
559    def test_invalid_url(self):
560        response = self.post({'external-link-chooser-url': 'ntp://www.example.com', 'external-link-chooser-link_text': 'example'})
561        self.assertEqual(response.status_code, 200)
562        response_json = json.loads(response.content.decode())
563        self.assertEqual(response_json['step'], 'external_link')  # indicates failure / show error message
564        self.assertContains(response, "Enter a valid URL.")
565
566    def test_allow_local_url(self):
567        response = self.post({'external-link-chooser-url': '/admin/', 'external-link-chooser-link_text': 'admin'})
568        self.assertEqual(response.status_code, 200)
569        response_json = json.loads(response.content.decode())
570        self.assertEqual(response_json['step'], 'external_link_chosen')  # indicates success / post back to calling page
571        self.assertEqual(response_json['result']['url'], "/admin/")
572        self.assertEqual(response_json['result']['title'], "admin")
573
574
575class TestChooserAnchorLink(TestCase, WagtailTestUtils):
576    def setUp(self):
577        self.login()
578
579    def get(self, params={}):
580        return self.client.get(reverse('wagtailadmin_choose_page_anchor_link'), params)
581
582    def post(self, post_data={}, url_params={}):
583        url = reverse('wagtailadmin_choose_page_anchor_link')
584        if url_params:
585            url += '?' + urlencode(url_params)
586        return self.client.post(url, post_data)
587
588    def test_simple(self):
589        response = self.get()
590        self.assertEqual(response.status_code, 200)
591        self.assertTemplateUsed(response, 'wagtailadmin/chooser/anchor_link.html')
592
593    def test_prepopulated_form(self):
594        response = self.get({'link_text': 'Example Anchor Text', 'link_url': 'exampleanchor'})
595        self.assertEqual(response.status_code, 200)
596        self.assertContains(response, 'Example Anchor Text')
597        self.assertContains(response, 'exampleanchor')
598
599    def test_create_link(self):
600        response = self.post({'anchor-link-chooser-url': 'exampleanchor', 'anchor-link-chooser-link_text': 'Example Anchor Text'})
601        result = json.loads(response.content.decode())['result']
602        self.assertEqual(result['url'], "#exampleanchor")
603        self.assertEqual(result['title'], "Example Anchor Text")  # When link text is given, it is used
604        self.assertEqual(result['prefer_this_title_as_link_text'], True)
605
606    def test_create_link_without_text(self):
607        response = self.post({'anchor-link-chooser-url': 'exampleanchor'})
608        result = json.loads(response.content.decode())['result']
609        self.assertEqual(result['url'], "#exampleanchor")
610        self.assertEqual(result['title'], "exampleanchor")  # When no link text is given, it uses anchor
611        self.assertEqual(result['prefer_this_title_as_link_text'], False)
612
613    def test_notice_changes_to_link_text(self):
614        response = self.post(
615            {'anchor-link-chooser-url': 'exampleanchor2', 'email-link-chooser-link_text': 'Example Text'},  # POST data
616            {'link_url': 'exampleanchor2', 'link_text': 'Example Text'}  # GET params - initial data
617        )
618        result = json.loads(response.content.decode())['result']
619        self.assertEqual(result['url'], "#exampleanchor2")
620        self.assertEqual(result['title'], "exampleanchor2")
621        # no change to link text, so prefer the existing link/selection content where available
622        self.assertEqual(result['prefer_this_title_as_link_text'], True)
623
624        response = self.post(
625            {'anchor-link-chooser-url': 'exampleanchor2', 'anchor-link-chooser-link_text': 'Example Anchor Test 2.1'},  # POST data
626            {'link_url': 'exampleanchor', 'link_text': 'Example Anchor Text'}  # GET params - initial data
627        )
628        result = json.loads(response.content.decode())['result']
629        self.assertEqual(result['url'], "#exampleanchor2")
630        self.assertEqual(result['title'], "Example Anchor Test 2.1")
631        # link text has changed, so tell the caller to use it
632        self.assertEqual(result['prefer_this_title_as_link_text'], True)
633
634
635class TestChooserEmailLink(TestCase, WagtailTestUtils):
636    def setUp(self):
637        self.login()
638
639    def get(self, params={}):
640        return self.client.get(reverse('wagtailadmin_choose_page_email_link'), params)
641
642    def post(self, post_data={}, url_params={}):
643        url = reverse('wagtailadmin_choose_page_email_link')
644        if url_params:
645            url += '?' + urlencode(url_params)
646        return self.client.post(url, post_data)
647
648    def test_simple(self):
649        response = self.get()
650        self.assertEqual(response.status_code, 200)
651        self.assertTemplateUsed(response, 'wagtailadmin/chooser/email_link.html')
652
653    def test_prepopulated_form(self):
654        response = self.get({'link_text': 'Example', 'link_url': 'example@example.com'})
655        self.assertEqual(response.status_code, 200)
656        self.assertContains(response, 'Example')
657        self.assertContains(response, 'example@example.com')
658
659    def test_create_link(self):
660        response = self.post({'email-link-chooser-email_address': 'example@example.com', 'email-link-chooser-link_text': 'contact'})
661        result = json.loads(response.content.decode())['result']
662        self.assertEqual(result['url'], "mailto:example@example.com")
663        self.assertEqual(result['title'], "contact")  # When link text is given, it is used
664        self.assertEqual(result['prefer_this_title_as_link_text'], True)
665
666    def test_create_link_without_text(self):
667        response = self.post({'email-link-chooser-email_address': 'example@example.com'})
668        result = json.loads(response.content.decode())['result']
669        self.assertEqual(result['url'], "mailto:example@example.com")
670        self.assertEqual(result['title'], "example@example.com")  # When no link text is given, it uses the email
671        self.assertEqual(result['prefer_this_title_as_link_text'], False)
672
673    def test_notice_changes_to_link_text(self):
674        response = self.post(
675            {'email-link-chooser-email_address': 'example2@example.com', 'email-link-chooser-link_text': 'example'},  # POST data
676            {'link_url': 'example@example.com', 'link_text': 'example'}  # GET params - initial data
677        )
678        result = json.loads(response.content.decode())['result']
679        self.assertEqual(result['url'], "mailto:example2@example.com")
680        self.assertEqual(result['title'], "example")
681        # no change to link text, so prefer the existing link/selection content where available
682        self.assertEqual(result['prefer_this_title_as_link_text'], False)
683
684        response = self.post(
685            {'email-link-chooser-email_address': 'example2@example.com', 'email-link-chooser-link_text': 'new example'},  # POST data
686            {'link_url': 'example@example.com', 'link_text': 'example'}  # GET params - initial data
687        )
688        result = json.loads(response.content.decode())['result']
689        self.assertEqual(result['url'], "mailto:example2@example.com")
690        self.assertEqual(result['title'], "new example")
691        # link text has changed, so tell the caller to use it
692        self.assertEqual(result['prefer_this_title_as_link_text'], True)
693
694
695class TestChooserPhoneLink(TestCase, WagtailTestUtils):
696    def setUp(self):
697        self.login()
698
699    def get(self, params={}):
700        return self.client.get(reverse('wagtailadmin_choose_page_phone_link'), params)
701
702    def post(self, post_data={}, url_params={}):
703        url = reverse('wagtailadmin_choose_page_phone_link')
704        if url_params:
705            url += '?' + urlencode(url_params)
706        return self.client.post(url, post_data)
707
708    def test_simple(self):
709        response = self.get()
710        self.assertEqual(response.status_code, 200)
711        self.assertTemplateUsed(response, 'wagtailadmin/chooser/phone_link.html')
712
713    def test_prepopulated_form(self):
714        response = self.get({'link_text': 'Example', 'link_url': '+123456789'})
715        self.assertEqual(response.status_code, 200)
716        self.assertContains(response, 'Example')
717        self.assertContains(response, '+123456789')
718
719    def test_create_link(self):
720        response = self.post({'phone-link-chooser-phone_number': '+123456789', 'phone-link-chooser-link_text': 'call'})
721        result = json.loads(response.content.decode())['result']
722        self.assertEqual(result['url'], "tel:+123456789")
723        self.assertEqual(result['title'], "call")
724        self.assertEqual(result['prefer_this_title_as_link_text'], True)
725
726    def test_create_link_without_text(self):
727        response = self.post({'phone-link-chooser-phone_number': '+123456789'})
728        result = json.loads(response.content.decode())['result']
729        self.assertEqual(result['url'], "tel:+123456789")
730        self.assertEqual(result['title'], "+123456789")  # When no link text is given, it uses the phone number
731        self.assertEqual(result['prefer_this_title_as_link_text'], False)
732
733    def test_notice_changes_to_link_text(self):
734        response = self.post(
735            {'phone-link-chooser-phone_number': '+222222222', 'phone-link-chooser-link_text': 'example'},  # POST data
736            {'link_url': '+111111111', 'link_text': 'example'}  # GET params - initial data
737        )
738        result = json.loads(response.content.decode())['result']
739        self.assertEqual(result['url'], "tel:+222222222")
740        self.assertEqual(result['title'], "example")
741        # no change to link text, so prefer the existing link/selection content where available
742        self.assertEqual(result['prefer_this_title_as_link_text'], False)
743
744        response = self.post(
745            {'phone-link-chooser-phone_number': '+222222222', 'phone-link-chooser-link_text': 'new example'},  # POST data
746            {'link_url': '+111111111', 'link_text': 'example'}  # GET params - initial data
747        )
748        result = json.loads(response.content.decode())['result']
749        self.assertEqual(result['url'], "tel:+222222222")
750        self.assertEqual(result['title'], "new example")
751        # link text has changed, so tell the caller to use it
752        self.assertEqual(result['prefer_this_title_as_link_text'], True)
753
754
755class TestCanChoosePage(TestCase, WagtailTestUtils):
756    fixtures = ['test.json']
757
758    def setUp(self):
759        self.user = self.login()
760        self.permission_proxy = UserPagePermissionsProxy(self.user)
761        self.desired_classes = (Page, )
762
763    def test_can_choose_page(self):
764        homepage = Page.objects.get(url_path='/home/')
765        result = can_choose_page(homepage, self.permission_proxy, self.desired_classes)
766        self.assertTrue(result)
767
768    def test_with_user_no_permission(self):
769        homepage = Page.objects.get(url_path='/home/')
770        # event editor does not have permissions on homepage
771        event_editor = get_user_model().objects.get(email='eventeditor@example.com')
772        permission_proxy = UserPagePermissionsProxy(event_editor)
773        result = can_choose_page(homepage, permission_proxy, self.desired_classes, user_perm='copy_to')
774        self.assertFalse(result)
775
776    def test_with_can_choose_root(self):
777        root = Page.objects.get(url_path='/')
778        result = can_choose_page(root, self.permission_proxy, self.desired_classes, can_choose_root=True)
779        self.assertTrue(result)
780
781    def test_with_can_not_choose_root(self):
782        root = Page.objects.get(url_path='/')
783        result = can_choose_page(root, self.permission_proxy, self.desired_classes, can_choose_root=False)
784        self.assertFalse(result)
785