1# -*- coding: utf-8 -*- 2import json 3import datetime 4 5from djangocms_text_ckeditor.cms_plugins import TextPlugin 6from djangocms_text_ckeditor.models import Text 7from django.contrib import admin 8from django.contrib.admin.models import LogEntry 9from django.contrib.admin.sites import site 10from django.contrib.auth import get_user_model 11from django.contrib.auth.models import Permission 12from django.contrib.sites.models import Site 13from django.urls import reverse 14from django.http import (Http404, HttpResponseBadRequest, 15 HttpResponseNotFound) 16from django.utils.encoding import force_text, smart_str 17from django.utils import timezone 18 19from cms import api 20from cms.api import create_page, create_title, add_plugin, publish_page 21from cms.admin.pageadmin import PageAdmin 22from cms.constants import TEMPLATE_INHERITANCE_MAGIC 23from cms.models import StaticPlaceholder 24from cms.models.pagemodel import Page, PageType 25from cms.models.permissionmodels import GlobalPagePermission, PagePermission 26from cms.models.placeholdermodel import Placeholder 27from cms.models.pluginmodel import CMSPlugin 28from cms.models.titlemodels import Title 29from cms.test_utils import testcases as base 30from cms.test_utils.testcases import ( 31 CMSTestCase, URL_CMS_PAGE_DELETE, URL_CMS_PAGE,URL_CMS_TRANSLATION_DELETE, 32 URL_CMS_PAGE_CHANGE_LANGUAGE, URL_CMS_PAGE_CHANGE, 33 URL_CMS_PAGE_PUBLISHED, 34) 35from cms.utils.conf import get_cms_setting 36from cms.utils.urlutils import admin_reverse 37 38 39class AdminTestsBase(CMSTestCase): 40 @property 41 def admin_class(self): 42 return site._registry[Page] 43 44 def _get_guys(self, admin_only=False, use_global_permissions=True): 45 admin_user = self.get_superuser() 46 47 if admin_only: 48 return admin_user 49 staff_user = self._get_staff_user(use_global_permissions) 50 return admin_user, staff_user 51 52 def _get_staff_user(self, use_global_permissions=True): 53 USERNAME = 'test' 54 55 if get_user_model().USERNAME_FIELD == 'email': 56 normal_guy = get_user_model().objects.create_user(USERNAME, 'test@test.com', 'test@test.com') 57 else: 58 normal_guy = get_user_model().objects.create_user(USERNAME, 'test@test.com', USERNAME) 59 60 normal_guy.is_staff = True 61 normal_guy.is_active = True 62 perms = Permission.objects.filter( 63 codename__in=['change_page', 'change_title', 'add_page', 'add_title', 'delete_page', 'delete_title'] 64 ) 65 normal_guy.save() 66 normal_guy.user_permissions.set(perms) 67 if use_global_permissions: 68 gpp = GlobalPagePermission.objects.create( 69 user=normal_guy, 70 can_change=True, 71 can_delete=True, 72 can_change_advanced_settings=False, 73 can_publish=True, 74 can_change_permissions=False, 75 can_move_page=True, 76 ) 77 gpp.sites.set(Site.objects.all()) 78 return normal_guy 79 80 81class AdminTestCase(AdminTestsBase): 82 83 def test_extension_not_in_admin(self): 84 admin_user, staff = self._get_guys() 85 with self.login_user_context(admin_user): 86 request = self.get_request(URL_CMS_PAGE_CHANGE % 1, 'en',) 87 response = site.index(request) 88 self.assertNotContains(response, '/mytitleextension/') 89 self.assertNotContains(response, '/mypageextension/') 90 91 def test_2apphooks_with_same_namespace(self): 92 PAGE1 = 'Test Page' 93 PAGE2 = 'Test page 2' 94 APPLICATION_URLS = 'project.sampleapp.urls' 95 96 admin_user, normal_guy = self._get_guys() 97 98 current_site = Site.objects.get(pk=1) 99 100 # The admin creates the page 101 page = create_page(PAGE1, "nav_playground.html", "en", 102 site=current_site, created_by=admin_user) 103 page2 = create_page(PAGE2, "nav_playground.html", "en", 104 site=current_site, created_by=admin_user) 105 106 page.application_urls = APPLICATION_URLS 107 page.application_namespace = "space1" 108 page.save() 109 page2.application_urls = APPLICATION_URLS 110 page2.save() 111 112 # The admin edits the page (change the page name for ex.) 113 page_data = { 114 'title': PAGE2, 115 'slug': page2.get_slug(), 116 'template': page2.template, 117 'application_urls': 'SampleApp', 118 'application_namespace': 'space1', 119 } 120 121 with self.login_user_context(admin_user): 122 resp = self.client.post(base.URL_CMS_PAGE_ADVANCED_CHANGE % page.pk, page_data) 123 self.assertEqual(resp.status_code, 302) 124 self.assertEqual(Page.objects.filter(application_namespace="space1").count(), 1) 125 resp = self.client.post(base.URL_CMS_PAGE_ADVANCED_CHANGE % page2.pk, page_data) 126 self.assertEqual(resp.status_code, 200) 127 page_data['application_namespace'] = 'space2' 128 resp = self.client.post(base.URL_CMS_PAGE_ADVANCED_CHANGE % page2.pk, page_data) 129 self.assertEqual(resp.status_code, 302) 130 131 def test_delete(self): 132 admin_user = self.get_superuser() 133 create_page("home", "nav_playground.html", "en", 134 created_by=admin_user, published=True) 135 page = create_page("delete-page", "nav_playground.html", "en", 136 created_by=admin_user, published=True) 137 create_page('child-page', "nav_playground.html", "en", 138 created_by=admin_user, published=True, parent=page) 139 body = page.placeholders.get(slot='body') 140 add_plugin(body, 'TextPlugin', 'en', body='text') 141 page.publish('en') 142 with self.login_user_context(admin_user): 143 data = {'post': 'yes'} 144 response = self.client.post(URL_CMS_PAGE_DELETE % page.pk, data) 145 self.assertRedirects(response, URL_CMS_PAGE) 146 147 def test_delete_diff_language(self): 148 admin_user = self.get_superuser() 149 create_page("home", "nav_playground.html", "en", 150 created_by=admin_user, published=True) 151 page = create_page("delete-page", "nav_playground.html", "en", 152 created_by=admin_user, published=True) 153 create_page('child-page', "nav_playground.html", "de", 154 created_by=admin_user, published=True, parent=page) 155 body = page.placeholders.get(slot='body') 156 add_plugin(body, 'TextPlugin', 'en', body='text') 157 page.publish('en') 158 with self.login_user_context(admin_user): 159 data = {'post': 'yes'} 160 response = self.client.post(URL_CMS_PAGE_DELETE % page.pk, data) 161 self.assertRedirects(response, URL_CMS_PAGE) 162 163 def test_search_fields(self): 164 superuser = self.get_superuser() 165 from django.contrib.admin import site 166 167 with self.login_user_context(superuser): 168 for model, admin_instance in site._registry.items(): 169 if model._meta.app_label != 'cms': 170 continue 171 if not admin_instance.search_fields: 172 continue 173 url = admin_reverse('cms_%s_changelist' % model._meta.model_name) 174 response = self.client.get('%s?q=1' % url) 175 errmsg = response.content 176 self.assertEqual(response.status_code, 200, errmsg) 177 178 def test_pagetree_filtered(self): 179 superuser = self.get_superuser() 180 create_page("root-page", "nav_playground.html", "en", 181 created_by=superuser, published=True) 182 with self.login_user_context(superuser): 183 url = admin_reverse('cms_page_changelist') 184 response = self.client.get('%s?template__exact=nav_playground.html' % url) 185 errmsg = response.content 186 self.assertEqual(response.status_code, 200, errmsg) 187 188 def test_delete_translation(self): 189 admin_user = self.get_superuser() 190 page = create_page("delete-page-translation", "nav_playground.html", "en", 191 created_by=admin_user, published=True) 192 create_title("de", "delete-page-translation-2", page, slug="delete-page-translation-2") 193 create_title("es-mx", "delete-page-translation-es", page, slug="delete-page-translation-es") 194 with self.login_user_context(admin_user): 195 response = self.client.get(URL_CMS_TRANSLATION_DELETE % page.pk, {'language': 'de'}) 196 self.assertEqual(response.status_code, 200) 197 response = self.client.post(URL_CMS_TRANSLATION_DELETE % page.pk, {'language': 'de'}) 198 self.assertRedirects(response, URL_CMS_PAGE) 199 response = self.client.get(URL_CMS_TRANSLATION_DELETE % page.pk, {'language': 'es-mx'}) 200 self.assertEqual(response.status_code, 200) 201 response = self.client.post(URL_CMS_TRANSLATION_DELETE % page.pk, {'language': 'es-mx'}) 202 self.assertRedirects(response, URL_CMS_PAGE) 203 204 def test_change_dates(self): 205 admin_user, staff = self._get_guys() 206 207 with self.settings(USE_TZ=False, TIME_ZONE='UTC'): 208 209 page = create_page('test-page', 'nav_playground.html', 'en') 210 page.publish('en') 211 draft = page.get_draft_object() 212 213 original_date = draft.publication_date 214 original_end_date = draft.publication_end_date 215 new_date = timezone.now() - datetime.timedelta(days=1) 216 new_end_date = timezone.now() + datetime.timedelta(days=1) 217 url = admin_reverse('cms_page_dates', args=(draft.pk,)) 218 with self.login_user_context(admin_user): 219 response = self.client.post(url, { 220 'publication_date_0': new_date.date(), 221 'publication_date_1': new_date.strftime("%H:%M:%S"), 222 'publication_end_date_0': new_end_date.date(), 223 'publication_end_date_1': new_end_date.strftime("%H:%M:%S"), 224 }) 225 self.assertEqual(response.status_code, 302) 226 draft = Page.objects.get(pk=draft.pk) 227 self.assertNotEqual(draft.publication_date.timetuple(), original_date.timetuple()) 228 self.assertEqual(draft.publication_date.timetuple(), new_date.timetuple()) 229 self.assertEqual(draft.publication_end_date.timetuple(), new_end_date.timetuple()) 230 if original_end_date: 231 self.assertNotEqual(draft.publication_end_date.timetuple(), original_end_date.timetuple()) 232 233 with self.settings(USE_TZ=True, TIME_ZONE='UTC'): 234 235 page = create_page('test-page-2', 'nav_playground.html', 'en') 236 page.publish('en') 237 draft = page.get_draft_object() 238 239 original_date = draft.publication_date 240 original_end_date = draft.publication_end_date 241 new_date = timezone.localtime(timezone.now()) - datetime.timedelta(days=1) 242 new_end_date = timezone.localtime(timezone.now()) + datetime.timedelta(days=1) 243 url = admin_reverse('cms_page_dates', args=(draft.pk,)) 244 with self.login_user_context(admin_user): 245 response = self.client.post(url, { 246 'language': 'en', 247 'publication_date_0': new_date.date(), 248 'publication_date_1': new_date.strftime("%H:%M:%S"), 249 'publication_end_date_0': new_end_date.date(), 250 'publication_end_date_1': new_end_date.strftime("%H:%M:%S"), 251 }) 252 self.assertEqual(response.status_code, 302) 253 draft = Page.objects.get(pk=draft.pk) 254 self.assertNotEqual(draft.publication_date.timetuple(), original_date.timetuple()) 255 self.assertEqual(timezone.localtime(draft.publication_date).timetuple(), new_date.timetuple()) 256 self.assertEqual(timezone.localtime(draft.publication_end_date).timetuple(), new_end_date.timetuple()) 257 if original_end_date: 258 self.assertNotEqual(draft.publication_end_date.timetuple(), original_end_date.timetuple()) 259 260 def test_change_template(self): 261 template = get_cms_setting('TEMPLATES')[0][0] 262 admin_user, staff = (self.get_superuser(), self.get_staff_user_with_no_permissions()) 263 264 with self.login_user_context(admin_user): 265 response = self.client.post( 266 self.get_admin_url(Page, 'change_template', 1), 267 {'template': template} 268 ) 269 self.assertEqual(response.status_code, 404) 270 271 with self.login_user_context(staff): 272 response = self.client.post( 273 self.get_admin_url(Page, 'change_template', 1), 274 {'template': template} 275 ) 276 self.assertEqual(response.status_code, 403) 277 278 page = create_page('test-page', template, 'en') 279 280 with self.login_user_context(staff): 281 response = self.client.post( 282 self.get_admin_url(Page, 'change_template', page.pk), 283 {'template': template} 284 ) 285 self.assertEqual(response.status_code, 403) 286 287 with self.login_user_context(admin_user): 288 response = self.client.post( 289 self.get_admin_url(Page, 'change_template', page.pk), 290 {'template': 'doesntexist'} 291 ) 292 self.assertEqual(response.status_code, 400) 293 response = self.client.post( 294 self.get_admin_url(Page, 'change_template', page.pk), 295 {'template': template} 296 ) 297 self.assertEqual(response.status_code, 200) 298 299 def test_changelist_items(self): 300 admin_user = self.get_superuser() 301 first_level_page = create_page('level1', 'nav_playground.html', 'en') 302 second_level_page_top = create_page('level21', "nav_playground.html", "en", 303 created_by=admin_user, published=True, parent=first_level_page) 304 second_level_page_bottom = create_page('level22', "nav_playground.html", "en", 305 created_by=admin_user, published=True, 306 parent=self.reload(first_level_page)) 307 third_level_page = create_page('level3', "nav_playground.html", "en", 308 created_by=admin_user, published=True, parent=second_level_page_top) 309 self.assertEqual(Page.objects.all().count(), 4) 310 311 with self.login_user_context(admin_user): 312 response = self.client.get(self.get_admin_url(Page, 'changelist')) 313 cms_page_nodes = response.context_data['tree']['items'] 314 self.assertEqual(cms_page_nodes[0], first_level_page) 315 self.assertEqual(cms_page_nodes[1], second_level_page_top) 316 self.assertEqual(cms_page_nodes[2], third_level_page) 317 self.assertEqual(cms_page_nodes[3], second_level_page_bottom) 318 319 def test_changelist_get_results(self): 320 admin_user = self.get_superuser() 321 first_level_page = create_page('level1', 'nav_playground.html', 'en', published=True) 322 second_level_page_top = create_page('level21', "nav_playground.html", "en", 323 created_by=admin_user, published=True, 324 parent=first_level_page) 325 second_level_page_bottom = create_page('level22', "nav_playground.html", "en", # nopyflakes 326 created_by=admin_user, published=True, 327 parent=self.reload(first_level_page)) 328 third_level_page = create_page('level3', "nav_playground.html", "en", # nopyflakes 329 created_by=admin_user, published=True, 330 parent=second_level_page_top) 331 fourth_level_page = create_page('level23', "nav_playground.html", "en", # nopyflakes 332 created_by=admin_user, 333 parent=self.reload(first_level_page)) 334 self.assertEqual(Page.objects.all().count(), 9) 335 endpoint = self.get_admin_url(Page, 'changelist') 336 337 with self.login_user_context(admin_user): 338 response = self.client.get(endpoint) 339 self.assertEqual(response.context_data['tree']['items'].count(), 5) 340 341 with self.login_user_context(admin_user): 342 response = self.client.get(endpoint + '?q=level23') 343 self.assertEqual(response.context_data['tree']['items'].count(), 1) 344 345 with self.login_user_context(admin_user): 346 response = self.client.get(endpoint + '?q=level2') 347 self.assertEqual(response.context_data['tree']['items'].count(), 3) 348 349 def test_unihandecode_doesnt_break_404_in_admin(self): 350 self.get_superuser() 351 352 if get_user_model().USERNAME_FIELD == 'email': 353 self.client.login(username='admin@django-cms.org', password='admin@django-cms.org') 354 else: 355 self.client.login(username='admin', password='admin') 356 357 response = self.client.get(URL_CMS_PAGE_CHANGE_LANGUAGE % (1, 'en')) 358 self.assertEqual(response.status_code, 404) 359 360 def test_empty_placeholder_with_nested_plugins(self): 361 # It's important that this test clears a placeholder 362 # which only has nested plugins. 363 # This allows us to catch a strange bug that happened 364 # under these conditions with the new related name handling. 365 page_en = create_page("EmptyPlaceholderTestPage (EN)", "nav_playground.html", "en") 366 ph = page_en.placeholders.get(slot="body") 367 368 column_wrapper = add_plugin(ph, "MultiColumnPlugin", "en") 369 370 add_plugin(ph, "ColumnPlugin", "en", parent=column_wrapper) 371 add_plugin(ph, "ColumnPlugin", "en", parent=column_wrapper) 372 373 # before cleaning the de placeholder 374 self.assertEqual(ph.get_plugins('en').count(), 3) 375 376 admin_user, staff = self._get_guys() 377 endpoint = self.get_clear_placeholder_url(ph, language='en') 378 379 with self.login_user_context(admin_user): 380 response = self.client.post(endpoint, {'test': 0}) 381 382 self.assertEqual(response.status_code, 302) 383 384 # After cleaning the de placeholder, en placeholder must still have all the plugins 385 self.assertEqual(ph.get_plugins('en').count(), 0) 386 387 def test_empty_placeholder_in_correct_language(self): 388 """ 389 Test that Cleaning a placeholder only affect current language contents 390 """ 391 # create some objects 392 page_en = create_page("EmptyPlaceholderTestPage (EN)", "nav_playground.html", "en") 393 ph = page_en.placeholders.get(slot="body") 394 395 # add the text plugin to the en version of the page 396 add_plugin(ph, "TextPlugin", "en", body="Hello World EN 1") 397 add_plugin(ph, "TextPlugin", "en", body="Hello World EN 2") 398 399 # creating a de title of the page and adding plugins to it 400 create_title("de", page_en.get_title(), page_en, slug=page_en.get_slug()) 401 add_plugin(ph, "TextPlugin", "de", body="Hello World DE") 402 add_plugin(ph, "TextPlugin", "de", body="Hello World DE 2") 403 add_plugin(ph, "TextPlugin", "de", body="Hello World DE 3") 404 405 # before cleaning the de placeholder 406 self.assertEqual(ph.get_plugins('en').count(), 2) 407 self.assertEqual(ph.get_plugins('de').count(), 3) 408 409 admin_user, staff = self._get_guys() 410 endpoint = self.get_clear_placeholder_url(ph, language='de') 411 412 with self.login_user_context(admin_user): 413 response = self.client.post(endpoint, {'test': 0}) 414 415 self.assertEqual(response.status_code, 302) 416 417 # After cleaning the de placeholder, en placeholder must still have all the plugins 418 self.assertEqual(ph.get_plugins('en').count(), 2) 419 self.assertEqual(ph.get_plugins('de').count(), 0) 420 421 422class AdminTests(AdminTestsBase): 423 # TODO: needs tests for actual permissions, not only superuser/normaluser 424 425 def setUp(self): 426 self.page = create_page("testpage", "nav_playground.html", "en") 427 428 def get_admin(self): 429 User = get_user_model() 430 431 fields = dict(email="admin@django-cms.org", is_staff=True, is_superuser=True) 432 433 if (User.USERNAME_FIELD != 'email'): 434 fields[User.USERNAME_FIELD] = "admin" 435 436 usr = User(**fields) 437 usr.set_password(getattr(usr, User.USERNAME_FIELD)) 438 usr.save() 439 return usr 440 441 def get_permless(self): 442 User = get_user_model() 443 444 fields = dict(email="permless@django-cms.org", is_staff=True) 445 446 if (User.USERNAME_FIELD != 'email'): 447 fields[User.USERNAME_FIELD] = "permless" 448 449 usr = User(**fields) 450 usr.set_password(getattr(usr, User.USERNAME_FIELD)) 451 usr.save() 452 return usr 453 454 def get_page(self): 455 return self.page 456 457 def test_change_publish_unpublish(self): 458 page = self.get_page() 459 permless = self.get_permless() 460 with self.login_user_context(permless): 461 request = self.get_request() 462 response = self.admin_class.publish_page(request, page.pk, "en") 463 self.assertEqual(response.status_code, 405) 464 page = self.reload(page) 465 self.assertFalse(page.is_published('en')) 466 467 request = self.get_request(post_data={'no': 'data'}) 468 response = self.admin_class.publish_page(request, page.pk, "en") 469 self.assertEqual(response.status_code, 403) 470 page = self.reload(page) 471 self.assertFalse(page.is_published('en')) 472 473 admin_user = self.get_admin() 474 with self.login_user_context(admin_user): 475 request = self.get_request(post_data={'no': 'data'}) 476 response = self.admin_class.publish_page(request, page.pk, "en") 477 self.assertEqual(response.status_code, 302) 478 479 page = self.reload(page) 480 self.assertTrue(page.is_published('en')) 481 482 response = self.admin_class.unpublish(request, page.pk, "en") 483 self.assertEqual(response.status_code, 302) 484 485 page = self.reload(page) 486 self.assertFalse(page.is_published('en')) 487 488 def test_change_status_adds_log_entry(self): 489 page = self.get_page() 490 admin_user = self.get_admin() 491 with self.login_user_context(admin_user): 492 request = self.get_request(post_data={'no': 'data'}) 493 self.assertFalse(LogEntry.objects.count()) 494 response = self.admin_class.publish_page(request, page.pk, "en") 495 self.assertEqual(response.status_code, 302) 496 self.assertEqual(1, LogEntry.objects.count()) 497 self.assertEqual(page.pk, int(LogEntry.objects.all()[0].object_id)) 498 499 def test_change_innavigation(self): 500 page = self.get_page() 501 permless = self.get_permless() 502 admin_user = self.get_admin() 503 with self.login_user_context(permless): 504 request = self.get_request() 505 response = self.admin_class.change_innavigation(request, page.pk) 506 self.assertEqual(response.status_code, 405) 507 with self.login_user_context(permless): 508 request = self.get_request(post_data={'no': 'data'}) 509 response = self.admin_class.change_innavigation(request, page.pk) 510 self.assertEqual(response.status_code, 403) 511 with self.login_user_context(permless): 512 request = self.get_request(post_data={'no': 'data'}) 513 self.assertEqual(response.status_code, 403) 514 with self.login_user_context(admin_user): 515 request = self.get_request(post_data={'no': 'data'}) 516 self.assertRaises(Http404, self.admin_class.change_innavigation, 517 request, page.pk + 100) 518 with self.login_user_context(permless): 519 request = self.get_request(post_data={'no': 'data'}) 520 response = self.admin_class.change_innavigation(request, page.pk) 521 self.assertEqual(response.status_code, 403) 522 with self.login_user_context(admin_user): 523 request = self.get_request(post_data={'no': 'data'}) 524 old = page.in_navigation 525 response = self.admin_class.change_innavigation(request, page.pk) 526 self.assertEqual(response.status_code, 204) 527 page = self.reload(page) 528 self.assertEqual(old, not page.in_navigation) 529 530 def test_publish_page_requires_perms(self): 531 permless = self.get_permless() 532 with self.login_user_context(permless): 533 request = self.get_request() 534 request.method = "POST" 535 response = self.admin_class.publish_page(request, Page.objects.drafts().first().pk, "en") 536 self.assertEqual(response.status_code, 403) 537 538 def test_remove_plugin_requires_post(self): 539 ph = self.page.placeholders.all()[0] 540 plugin = add_plugin(ph, 'TextPlugin', 'en', body='test') 541 admin_user = self.get_admin() 542 with self.login_user_context(admin_user): 543 endpoint = self.get_delete_plugin_uri(plugin, container=self.page) 544 response = self.client.get(endpoint) 545 self.assertEqual(response.status_code, 200) 546 547 def test_move_language(self): 548 page = self.get_page() 549 source, target = list(page.placeholders.all())[:2] 550 col = add_plugin(source, 'MultiColumnPlugin', 'en') 551 sub_col = add_plugin(source, 'ColumnPlugin', 'en', target=col) 552 col2 = add_plugin(source, 'MultiColumnPlugin', 'de') 553 554 admin_user = self.get_admin() 555 with self.login_user_context(admin_user): 556 data = { 557 'plugin_id': sub_col.pk, 558 'placeholder_id': source.id, 559 'plugin_parent': col2.pk, 560 'target_language': 'de' 561 } 562 endpoint = self.get_move_plugin_uri(sub_col) 563 response = self.client.post(endpoint, data) 564 self.assertEqual(response.status_code, 200) 565 sub_col = CMSPlugin.objects.get(pk=sub_col.pk) 566 self.assertEqual(sub_col.language, "de") 567 self.assertEqual(sub_col.parent_id, col2.pk) 568 569 def test_preview_page(self): 570 permless = self.get_permless() 571 with self.login_user_context(permless): 572 request = self.get_request() 573 self.assertRaises(Http404, self.admin_class.preview_page, request, 404, "en") 574 page = self.get_page() 575 page.publish("en") 576 page.set_as_homepage() 577 578 new_site = Site.objects.create(id=2, domain='django-cms.org', name='django-cms') 579 new_page = create_page("testpage", "nav_playground.html", "fr", site=new_site, published=True) 580 581 base_url = page.get_absolute_url() 582 with self.login_user_context(permless): 583 request = self.get_request('/?public=true') 584 response = self.admin_class.preview_page(request, page.pk, 'en') 585 self.assertEqual(response.status_code, 302) 586 self.assertEqual(response['Location'], '%s?%s&language=en' % (base_url, get_cms_setting('CMS_TOOLBAR_URL__EDIT_ON'))) 587 request = self.get_request() 588 response = self.admin_class.preview_page(request, page.pk, 'en') 589 self.assertEqual(response.status_code, 302) 590 self.assertEqual(response['Location'], '%s?%s&language=en' % (base_url, get_cms_setting('CMS_TOOLBAR_URL__EDIT_ON'))) 591 592 # Switch active site 593 request.session['cms_admin_site'] = new_site.pk 594 595 # Preview page attached to active site but not to current site 596 response = self.admin_class.preview_page(request, new_page.pk, 'fr') 597 self.assertEqual(response.status_code, 302) 598 self.assertEqual(response['Location'], 599 'http://django-cms.org/fr/testpage/?%s&language=fr' % get_cms_setting('CMS_TOOLBAR_URL__EDIT_ON')) 600 601 def test_too_many_plugins_global(self): 602 conf = { 603 'body': { 604 'limits': { 605 'global': 1, 606 }, 607 }, 608 } 609 admin_user = self.get_admin() 610 url = admin_reverse('cms_page_add_plugin') 611 with self.settings(CMS_PERMISSION=False, CMS_PLACEHOLDER_CONF=conf): 612 page = create_page('somepage', 'nav_playground.html', 'en') 613 body = page.placeholders.get(slot='body') 614 add_plugin(body, 'TextPlugin', 'en', body='text') 615 with self.login_user_context(admin_user): 616 data = { 617 'plugin_type': 'TextPlugin', 618 'placeholder_id': body.pk, 619 'target_language': 'en', 620 } 621 response = self.client.post(url, data) 622 self.assertEqual(response.status_code, HttpResponseBadRequest.status_code) 623 624 def test_too_many_plugins_type(self): 625 conf = { 626 'body': { 627 'limits': { 628 'TextPlugin': 1, 629 }, 630 }, 631 } 632 admin_user = self.get_admin() 633 url = admin_reverse('cms_page_add_plugin') 634 with self.settings(CMS_PERMISSION=False, CMS_PLACEHOLDER_CONF=conf): 635 page = create_page('somepage', 'nav_playground.html', 'en') 636 body = page.placeholders.get(slot='body') 637 add_plugin(body, 'TextPlugin', 'en', body='text') 638 with self.login_user_context(admin_user): 639 data = { 640 'plugin_type': 'TextPlugin', 641 'placeholder_id': body.pk, 642 'target_language': 'en', 643 'plugin_parent': '', 644 } 645 response = self.client.post(url, data) 646 self.assertEqual(response.status_code, HttpResponseBadRequest.status_code) 647 648 def test_edit_title_dirty_bit(self): 649 language = "en" 650 admin_user = self.get_admin() 651 page = create_page('A', 'nav_playground.html', language) 652 page_admin = PageAdmin(Page, None) 653 page_admin._current_page = page 654 page.publish("en") 655 draft_page = page.get_draft_object() 656 admin_url = reverse("admin:cms_page_edit_title_fields", args=( 657 draft_page.pk, language 658 )) 659 660 post_data = { 661 'title': "A Title" 662 } 663 with self.login_user_context(admin_user): 664 self.client.post(admin_url, post_data) 665 draft_page = Page.objects.get(pk=page.pk).get_draft_object() 666 self.assertTrue(draft_page.is_dirty('en')) 667 668 def test_edit_title_languages(self): 669 language = "en" 670 admin_user = self.get_admin() 671 page = create_page('A', 'nav_playground.html', language) 672 page_admin = PageAdmin(Page, None) 673 page_admin._current_page = page 674 page.publish("en") 675 draft_page = page.get_draft_object() 676 admin_url = reverse("admin:cms_page_edit_title_fields", args=( 677 draft_page.pk, language 678 )) 679 680 post_data = { 681 'title': "A Title" 682 } 683 with self.login_user_context(admin_user): 684 self.client.post(admin_url, post_data) 685 draft_page = Page.objects.get(pk=page.pk).get_draft_object() 686 self.assertTrue(draft_page.is_dirty('en')) 687 688 689class NoDBAdminTests(CMSTestCase): 690 @property 691 def admin_class(self): 692 return site._registry[Page] 693 694 def test_lookup_allowed_site__exact(self): 695 self.assertTrue(self.admin_class.lookup_allowed('site__exact', '1')) 696 697 def test_lookup_allowed_published(self): 698 self.assertTrue(self.admin_class.lookup_allowed('published', value='1')) 699 700 701class PluginPermissionTests(AdminTestsBase): 702 def setUp(self): 703 self._page = create_page('test page', 'nav_playground.html', 'en') 704 self._placeholder = self._page.placeholders.all()[0] 705 706 def _get_admin(self): 707 User = get_user_model() 708 709 fields = dict(email="admin@django-cms.org", is_staff=True, is_active=True) 710 711 if (User.USERNAME_FIELD != 'email'): 712 fields[User.USERNAME_FIELD] = "admin" 713 714 admin_user = User(**fields) 715 716 admin_user.set_password('admin') 717 admin_user.save() 718 return admin_user 719 720 def _get_page_admin(self): 721 return admin.site._registry[Page] 722 723 def _give_permission(self, user, model, permission_type, save=True): 724 codename = '%s_%s' % (permission_type, model._meta.object_name.lower()) 725 user.user_permissions.add(Permission.objects.get(codename=codename)) 726 727 def _give_page_permission_rights(self, user): 728 self._give_permission(user, PagePermission, 'add') 729 self._give_permission(user, PagePermission, 'change') 730 self._give_permission(user, PagePermission, 'delete') 731 732 def _get_change_page_request(self, user, page): 733 return type('Request', (object,), { 734 'user': user, 735 'path': base.URL_CMS_PAGE_CHANGE % page.pk 736 }) 737 738 def _give_cms_permissions(self, user, save=True): 739 for perm_type in ['add', 'change', 'delete']: 740 for model in [Page, Title]: 741 self._give_permission(user, model, perm_type, False) 742 gpp = GlobalPagePermission.objects.create( 743 user=user, 744 can_change=True, 745 can_delete=True, 746 can_change_advanced_settings=False, 747 can_publish=True, 748 can_change_permissions=False, 749 can_move_page=True, 750 ) 751 gpp.sites = Site.objects.all() 752 if save: 753 user.save() 754 755 def _create_plugin(self): 756 plugin = add_plugin(self._placeholder, 'TextPlugin', 'en') 757 return plugin 758 759 def test_plugin_edit_wrong_url(self): 760 """User tries to edit a plugin using a random url. 404 response returned""" 761 plugin = self._create_plugin() 762 _, normal_guy = self._get_guys() 763 764 if get_user_model().USERNAME_FIELD == 'email': 765 self.client.login(username='test@test.com', password='test@test.com') 766 else: 767 self.client.login(username='test', password='test') 768 769 self._give_permission(normal_guy, Text, 'change') 770 url = '%s/edit-plugin/%s/' % (admin_reverse('cms_page_edit_plugin', args=[plugin.id]), plugin.id) 771 response = self.client.post(url, dict()) 772 self.assertEqual(response.status_code, HttpResponseNotFound.status_code) 773 self.assertTrue("Plugin not found" in force_text(response.content)) 774 775 776class AdminFormsTests(AdminTestsBase): 777 def test_clean_overwrite_url(self): 778 """ 779 A manual path needs to be stripped from leading and trailing slashes. 780 """ 781 superuser = self.get_superuser() 782 cms_page = create_page('test page', 'nav_playground.html', 'en') 783 page_data = { 784 'overwrite_url': '/overwrite/url/', 785 'template': cms_page.template, 786 } 787 endpoint = self.get_admin_url(Page, 'advanced', cms_page.pk) 788 789 with self.login_user_context(superuser): 790 response = self.client.post(endpoint, page_data) 791 self.assertRedirects(response, URL_CMS_PAGE) 792 self.assertSequenceEqual( 793 cms_page.title_set.values_list('path', 'has_url_overwrite'), 794 [('overwrite/url', True)], 795 ) 796 797 def test_missmatching_site_parent_dotsite(self): 798 superuser = self.get_superuser() 799 new_site = Site.objects.create(id=2, domain='foo.com', name='foo.com') 800 parent_page = api.create_page("test", get_cms_setting('TEMPLATES')[0][0], "fr", site=new_site) 801 new_page_data = { 802 'title': 'Title', 803 'slug': 'slug', 804 'parent_node': parent_page.node.pk, 805 } 806 with self.login_user_context(superuser): 807 # Invalid parent 808 response = self.client.post(self.get_admin_url(Page, 'add'), new_page_data) 809 expected_error = ( 810 '<ul class="errorlist">' 811 '<li>Site doesn't match the parent's page site</li></ul>' 812 ) 813 self.assertEqual(response.status_code, 200) 814 self.assertContains(response, expected_error, html=True) 815 816 def test_form_errors(self): 817 superuser = self.get_superuser() 818 site0 = Site.objects.create(id=2, domain='foo.com', name='foo.com') 819 page1 = api.create_page("test", get_cms_setting('TEMPLATES')[0][0], "fr", site=site0) 820 821 new_page_data = { 822 'title': 'Title', 823 'slug': 'home', 824 'parent_node': page1.node.pk, 825 } 826 827 with self.login_user_context(superuser): 828 # Invalid parent 829 response = self.client.post(self.get_admin_url(Page, 'add'), new_page_data) 830 expected_error = ( 831 '<ul class="errorlist">' 832 '<li>Site doesn't match the parent's page site</li></ul>' 833 ) 834 self.assertEqual(response.status_code, 200) 835 self.assertContains(response, expected_error, html=True) 836 837 new_page_data = { 838 'title': 'Title', 839 'slug': '#', 840 } 841 842 with self.login_user_context(superuser): 843 # Invalid slug 844 response = self.client.post(self.get_admin_url(Page, 'add'), new_page_data) 845 expected_error = '<ul class="errorlist"><li>Slug must not be empty.</li></ul>' 846 self.assertEqual(response.status_code, 200) 847 self.assertContains(response, expected_error, html=True) 848 849 page2 = api.create_page("test", get_cms_setting('TEMPLATES')[0][0], "en") 850 new_page_data = { 851 'title': 'Title', 852 'slug': 'test', 853 } 854 855 with self.login_user_context(superuser): 856 # Duplicate slug / path 857 response = self.client.post(self.get_admin_url(Page, 'add'), new_page_data) 858 expected_error = ( 859 '<ul class="errorlist"><li>Page ' 860 '<a href="{}" target="_blank">test</a> ' 861 'has the same url \'test\' as current page.</li></ul>' 862 ).format(self.get_admin_url(Page, 'change', page2.pk)) 863 self.assertEqual(response.status_code, 200) 864 self.assertContains(response, expected_error, html=True) 865 866 def test_reverse_id_error_location(self): 867 superuser = self.get_superuser() 868 create_page('Page 1', 'nav_playground.html', 'en', reverse_id='p1') 869 page2 = create_page('Page 2', 'nav_playground.html', 'en') 870 page2_endpoint = self.get_admin_url(Page, 'advanced', page2.pk) 871 872 # Assemble a bunch of data to test the page form 873 page2_data = { 874 'reverse_id': 'p1', 875 'template': 'col_two.html', 876 } 877 878 with self.login_user_context(superuser): 879 response = self.client.post(page2_endpoint, page2_data) 880 expected_error = ( 881 '<ul class="errorlist">' 882 '<li>A page with this reverse URL id exists already.</li></ul>' 883 ) 884 self.assertEqual(response.status_code, 200) 885 self.assertContains(response, expected_error.format(page2.pk), html=True) 886 887 def test_advanced_settings_endpoint(self): 888 admin_user = self.get_superuser() 889 site = Site.objects.get_current() 890 page = create_page('Page 1', 'nav_playground.html', 'en') 891 page_data = { 892 'language': 'en', 893 'site': site.pk, 894 'template': 'col_two.html', 895 } 896 path = admin_reverse('cms_page_advanced', args=(page.pk,)) 897 898 with self.login_user_context(admin_user): 899 en_path = path + u"?language=en" 900 redirect_path = admin_reverse('cms_page_changelist') + '?language=en' 901 response = self.client.post(en_path, page_data) 902 self.assertRedirects(response, redirect_path) 903 self.assertEqual(Page.objects.get(pk=page.pk).template, 'col_two.html') 904 905 # Now switch it up by adding german as the current language 906 # Note that german has not been created as page translation. 907 page_data['language'] = 'de' 908 page_data['template'] = 'nav_playground.html' 909 910 with self.login_user_context(admin_user): 911 de_path = path + u"?language=de" 912 redirect_path = admin_reverse('cms_page_change', args=(page.pk,)) + '?language=de' 913 response = self.client.post(de_path, page_data) 914 # Assert user is redirected to basic settings. 915 self.assertRedirects(response, redirect_path) 916 # Make sure no change was made 917 self.assertEqual(Page.objects.get(pk=page.pk).template, 'col_two.html') 918 919 de_translation = create_title('de', title='Page 1', page=page.reload()) 920 de_translation.slug = '' 921 de_translation.save() 922 923 # Now try again but slug is set to empty string. 924 page_data['language'] = 'de' 925 page_data['template'] = 'nav_playground.html' 926 927 with self.login_user_context(admin_user): 928 de_path = path + u"?language=de" 929 response = self.client.post(de_path, page_data) 930 # Assert user is not redirected because there was a form error 931 self.assertEqual(response.status_code, 200) 932 # Make sure no change was made 933 self.assertEqual(Page.objects.get(pk=page.pk).template, 'col_two.html') 934 935 de_translation.slug = 'someslug' 936 de_translation.save() 937 938 # Now try again but with the title having a slug. 939 page_data['language'] = 'de' 940 page_data['template'] = 'nav_playground.html' 941 942 with self.login_user_context(admin_user): 943 en_path = path + u"?language=de" 944 redirect_path = admin_reverse('cms_page_changelist') + '?language=de' 945 response = self.client.post(en_path, page_data) 946 self.assertRedirects(response, redirect_path) 947 self.assertEqual(Page.objects.get(pk=page.pk).template, 'nav_playground.html') 948 949 def test_advanced_settings_endpoint_fails_gracefully(self): 950 admin_user = self.get_superuser() 951 page = create_page('Page 1', 'nav_playground.html', 'en') 952 page_data = { 953 'language': 'en', 954 'template': 'col_two.html', 955 } 956 path = admin_reverse('cms_page_advanced', args=(page.pk,)) 957 958 # It's important to test fields that are validated 959 # automatically by Django vs fields that are validated 960 # via the clean() method by us. 961 # Fields validated by Django will not be in cleaned data 962 # if they have an error so if we rely on these in the clean() 963 # method then an error will be raised. 964 965 # So test that the form short circuits if there's errors. 966 page_data['application_urls'] = 'TestApp' 967 968 with self.login_user_context(admin_user): 969 response = self.client.post(path, page_data) 970 # Assert user is not redirected because there was a form error 971 self.assertEqual(response.status_code, 200) 972 973 page = page.reload() 974 # Make sure no change was made 975 self.assertEqual(page.application_urls, None) 976 977 def test_create_page_type(self): 978 page = create_page('Test', 'static.html', 'en', published=True, reverse_id="home") 979 for placeholder in page.placeholders.all(): 980 add_plugin(placeholder, TextPlugin, 'en', body='<b>Test</b>') 981 page.publish('en') 982 self.assertEqual(Page.objects.count(), 2) 983 self.assertEqual(CMSPlugin.objects.count(), 4) 984 superuser = self.get_superuser() 985 with self.login_user_context(superuser): 986 # source is hidden because there's no page-types 987 response = self.client.get(self.get_admin_url(Page, 'add')) 988 self.assertContains(response, '<input id="id_source" name="source" type="hidden" />', html=True) 989 # create our first page type 990 page_data = {'source': page.pk, 'title': 'type1', 'slug': 'type1', '_save': 1} 991 response = self.client.post( 992 self.get_admin_url(PageType, 'add'), 993 data=page_data, 994 ) 995 self.assertEqual(response.status_code, 302) 996 self.assertEqual(Page.objects.count(), 4) 997 self.assertEqual(Page.objects.filter(is_page_type=True).count(), 2) 998 self.assertEqual(CMSPlugin.objects.count(), 6) 999 new_page_id = Page.objects.filter(is_page_type=True).only('pk').latest('id').pk 1000 response = self.client.get(admin_reverse('cms_page_add')) 1001 expected_field = ( 1002 '<select id="id_source" name="source">' 1003 '<option value="" selected="selected">---------</option>' 1004 '<option value="{}">type1</option></select>' 1005 ).format(new_page_id) 1006 self.assertContains(response, expected_field, html=True) 1007 # source is hidden when adding a page-type 1008 response = self.client.get(self.get_admin_url(PageType, 'add')) 1009 self.assertContains(response, '<input id="id_source" name="source" type="hidden" />', html=True) 1010 1011 def test_render_edit_mode(self): 1012 from django.core.cache import cache 1013 1014 cache.clear() 1015 1016 homepage = create_page('Test', 'static.html', 'en', published=True) 1017 homepage.set_as_homepage() 1018 1019 for placeholder in Placeholder.objects.all(): 1020 add_plugin(placeholder, TextPlugin, 'en', body='<b>Test</b>') 1021 1022 user = self.get_superuser() 1023 self.assertEqual(Placeholder.objects.all().count(), 4) 1024 with self.login_user_context(user): 1025 output = force_text( 1026 self.client.get( 1027 '/en/?%s' % get_cms_setting('CMS_TOOLBAR_URL__EDIT_ON') 1028 ).content 1029 ) 1030 self.assertIn('<b>Test</b>', output) 1031 self.assertEqual(Placeholder.objects.all().count(), 9) 1032 self.assertEqual(StaticPlaceholder.objects.count(), 2) 1033 for placeholder in Placeholder.objects.all(): 1034 add_plugin(placeholder, TextPlugin, 'en', body='<b>Test</b>') 1035 output = force_text( 1036 self.client.get( 1037 '/en/?%s' % get_cms_setting('CMS_TOOLBAR_URL__EDIT_ON') 1038 ).content 1039 ) 1040 self.assertIn('<b>Test</b>', output) 1041 1042 def test_tree_view_queries(self): 1043 from django.core.cache import cache 1044 1045 cache.clear() 1046 for i in range(10): 1047 create_page('Test%s' % i, 'col_two.html', 'en', published=True) 1048 for placeholder in Placeholder.objects.all(): 1049 add_plugin(placeholder, TextPlugin, 'en', body='<b>Test</b>') 1050 1051 user = self.get_superuser() 1052 with self.login_user_context(user): 1053 with self.assertNumQueries(9): 1054 force_text(self.client.get(self.get_admin_url(Page, 'changelist'))) 1055 1056 def test_smart_link_published_pages(self): 1057 admin, staff_guy = self._get_guys() 1058 page_url = URL_CMS_PAGE_PUBLISHED # Not sure how to achieve this with reverse... 1059 create_page('home', 'col_two.html', 'en', published=True) 1060 1061 with self.login_user_context(staff_guy): 1062 multi_title_page = create_page('main_title', 'col_two.html', 'en', published=True, 1063 overwrite_url='overwritten_url', 1064 menu_title='menu_title') 1065 1066 title = multi_title_page.get_title_obj() 1067 title.page_title = 'page_title' 1068 title.save() 1069 1070 multi_title_page.save() 1071 publish_page(multi_title_page, admin, 'en') 1072 1073 # Non ajax call should return a 403 as this page shouldn't be accessed by anything else but ajax queries 1074 self.assertEqual(403, self.client.get(page_url).status_code) 1075 1076 self.assertEqual(200, 1077 self.client.get(page_url, HTTP_X_REQUESTED_WITH='XMLHttpRequest').status_code 1078 ) 1079 1080 # Test that the query param is working as expected. 1081 self.assertEqual(1, len(json.loads(self.client.get(page_url, {'q':'main_title'}, 1082 HTTP_X_REQUESTED_WITH='XMLHttpRequest').content.decode("utf-8")))) 1083 1084 self.assertEqual(1, len(json.loads(self.client.get(page_url, {'q':'menu_title'}, 1085 HTTP_X_REQUESTED_WITH='XMLHttpRequest').content.decode("utf-8")))) 1086 1087 self.assertEqual(1, len(json.loads(self.client.get(page_url, {'q':'overwritten_url'}, 1088 HTTP_X_REQUESTED_WITH='XMLHttpRequest').content.decode("utf-8")))) 1089 1090 self.assertEqual(1, len(json.loads(self.client.get(page_url, {'q':'page_title'}, 1091 HTTP_X_REQUESTED_WITH='XMLHttpRequest').content.decode("utf-8")))) 1092 1093 1094class AdminPageEditContentSizeTests(AdminTestsBase): 1095 """ 1096 System user count influences the size of the page edit page, 1097 but the users are only 2 times present on the page 1098 1099 The test relates to extra=0 1100 at PagePermissionInlineAdminForm and ViewRestrictionInlineAdmin 1101 """ 1102 1103 def test_editpage_contentsize(self): 1104 """ 1105 Expected a username only 2 times in the content, but a relationship 1106 between usercount and pagesize 1107 """ 1108 with self.settings(CMS_PERMISSION=True): 1109 admin_user = self.get_superuser() 1110 PAGE_NAME = 'TestPage' 1111 USER_NAME = 'test_size_user_0' 1112 current_site = Site.objects.get(pk=1) 1113 page = create_page(PAGE_NAME, "nav_playground.html", "en", site=current_site, created_by=admin_user) 1114 page.save() 1115 self._page = page 1116 with self.login_user_context(admin_user): 1117 url = base.URL_CMS_PAGE_PERMISSION_CHANGE % self._page.pk 1118 response = self.client.get(url) 1119 self.assertEqual(response.status_code, 200) 1120 old_response_size = len(response.content) 1121 old_user_count = get_user_model().objects.count() 1122 # create additionals user and reload the page 1123 get_user_model().objects.create_user(username=USER_NAME, email=USER_NAME + '@django-cms.org', 1124 password=USER_NAME) 1125 user_count = get_user_model().objects.count() 1126 more_users_in_db = old_user_count < user_count 1127 # we have more users 1128 self.assertTrue(more_users_in_db, "New users got NOT created") 1129 response = self.client.get(url) 1130 new_response_size = len(response.content) 1131 page_size_grown = old_response_size < new_response_size 1132 # expect that the pagesize gets influenced by the useramount of the system 1133 self.assertTrue(page_size_grown, "Page size has not grown after user creation") 1134 # usernames are only 2 times in content 1135 text = smart_str(response.content, response.charset) 1136 foundcount = text.count(USER_NAME) 1137 # 2 forms contain usernames as options 1138 self.assertEqual(foundcount, 2, 1139 "Username %s appeared %s times in response.content, expected 2 times" % ( 1140 USER_NAME, foundcount)) 1141 1142 1143class AdminPageTreeTests(AdminTestsBase): 1144 1145 def test_move_node(self): 1146 admin_user, staff = self._get_guys() 1147 page_admin = self.admin_class 1148 1149 alpha = create_page('Alpha', 'nav_playground.html', 'en', published=True) 1150 beta = create_page('Beta', TEMPLATE_INHERITANCE_MAGIC, 'en', published=True) 1151 gamma = create_page('Gamma', TEMPLATE_INHERITANCE_MAGIC, 'en', published=True) 1152 delta = create_page('Delta', TEMPLATE_INHERITANCE_MAGIC, 'en', published=True) 1153 1154 # Current structure: 1155 # <root> 1156 # ⊢ Alpha 1157 # ⊢ Beta 1158 # ⊢ Gamma 1159 # ⊢ Delta 1160 1161 # Move Beta to be a child of Alpha 1162 data = { 1163 'id': beta.pk, 1164 'position': 0, 1165 'target': alpha.pk, 1166 } 1167 1168 with self.login_user_context(admin_user): 1169 request = self.get_request(post_data=data) 1170 response = page_admin.move_page(request, page_id=beta.pk) 1171 data = json.loads(response.content.decode('utf8')) 1172 1173 self.assertEqual(response.status_code, 200) 1174 self.assertEqual(data['status'], 200) 1175 self.assertEqual(alpha.node._reload().get_descendants().count(), 1) 1176 1177 # Current structure: 1178 # <root> 1179 # ⊢ Alpha 1180 # ⊢ Beta 1181 # ⊢ Gamma 1182 # ⊢ Delta 1183 1184 # Move Gamma to be a child of Beta 1185 data = { 1186 'id': gamma.pk, 1187 'position': 0, 1188 'target': beta.pk, 1189 } 1190 1191 with self.login_user_context(admin_user): 1192 request = self.get_request(post_data=data) 1193 response = page_admin.move_page(request, page_id=gamma.pk) 1194 data = json.loads(response.content.decode('utf8')) 1195 1196 self.assertEqual(response.status_code, 200) 1197 self.assertEqual(data['status'], 200) 1198 self.assertEqual(alpha.node._reload().get_descendants().count(), 2) 1199 self.assertEqual(beta.node._reload().get_descendants().count(), 1) 1200 1201 # Current structure: 1202 # <root> 1203 # ⊢ Alpha 1204 # ⊢ Beta 1205 # ⊢ Gamma 1206 # ⊢ Delta 1207 1208 # Move Delta to be a child of Beta 1209 data = { 1210 'id': delta.pk, 1211 'position': 0, 1212 'target': gamma.pk, 1213 } 1214 1215 with self.login_user_context(admin_user): 1216 request = self.get_request(post_data=data) 1217 response = page_admin.move_page(request, page_id=delta.pk) 1218 data = json.loads(response.content.decode('utf8')) 1219 1220 self.assertEqual(response.status_code, 200) 1221 self.assertEqual(data['status'], 200) 1222 self.assertEqual(alpha.node._reload().get_descendants().count(), 3) 1223 self.assertEqual(beta.node._reload().get_descendants().count(), 2) 1224 self.assertEqual(gamma.node._reload().get_descendants().count(), 1) 1225 1226 # Current structure: 1227 # <root> 1228 # ⊢ Alpha 1229 # ⊢ Beta 1230 # ⊢ Gamma 1231 # ⊢ Delta 1232 1233 # Move Beta to the root as node #1 (positions are 0-indexed) 1234 data = { 1235 'id': beta.pk, 1236 'position': 1, 1237 } 1238 1239 with self.login_user_context(admin_user): 1240 request = self.get_request(post_data=data) 1241 response = page_admin.move_page(request, page_id=beta.pk) 1242 data = json.loads(response.content.decode('utf8')) 1243 1244 self.assertEqual(response.status_code, 200) 1245 self.assertEqual(data['status'], 200) 1246 self.assertEqual(alpha.node._reload().get_descendants().count(), 0) 1247 self.assertEqual(beta.node._reload().get_descendants().count(), 2) 1248 self.assertEqual(gamma.node._reload().get_descendants().count(), 1) 1249 1250 # Current structure: 1251 # <root> 1252 # ⊢ Alpha 1253 # ⊢ Beta 1254 # ⊢ Gamma 1255 # ⊢ Delta 1256 1257 # Move Beta to be a child of Alpha again 1258 data = { 1259 'id': beta.pk, 1260 'position': 0, 1261 'target': alpha.pk, 1262 } 1263 1264 with self.login_user_context(admin_user): 1265 request = self.get_request(post_data=data) 1266 response = page_admin.move_page(request, page_id=beta.pk) 1267 data = json.loads(response.content.decode('utf8')) 1268 1269 self.assertEqual(response.status_code, 200) 1270 self.assertEqual(data['status'], 200) 1271 self.assertEqual(alpha.node._reload().get_descendants().count(), 3) 1272 self.assertEqual(beta.node._reload().get_descendants().count(), 2) 1273 self.assertEqual(gamma.node._reload().get_descendants().count(), 1) 1274 1275 # Current structure: 1276 # <root> 1277 # ⊢ Alpha 1278 # ⊢ Beta 1279 # ⊢ Gamma 1280 # ⊢ Delta 1281 1282 # Move Gamma to the root as node #1 (positions are 0-indexed) 1283 data = { 1284 'id': gamma.pk, 1285 'position': 1, 1286 } 1287 1288 with self.login_user_context(admin_user): 1289 request = self.get_request(post_data=data) 1290 response = page_admin.move_page(request, page_id=gamma.pk) 1291 data = json.loads(response.content.decode('utf8')) 1292 1293 self.assertEqual(response.status_code, 200) 1294 self.assertEqual(data['status'], 200) 1295 self.assertEqual(alpha.node._reload().get_descendants().count(), 1) 1296 self.assertEqual(beta.node._reload().get_descendants().count(), 0) 1297 self.assertEqual(gamma.node._reload().get_descendants().count(), 1) 1298 1299 # Current structure: 1300 # <root> 1301 # ⊢ Alpha 1302 # ⊢ Beta 1303 # ⊢ Gamma 1304 # ⊢ Delta 1305 1306 # Move Delta to the root as node #1 (positions are 0-indexed) 1307 data = { 1308 'id': delta.pk, 1309 'position': 1, 1310 } 1311 1312 with self.login_user_context(admin_user): 1313 request = self.get_request(post_data=data) 1314 response = page_admin.move_page(request, page_id=delta.pk) 1315 data = json.loads(response.content.decode('utf8')) 1316 1317 self.assertEqual(response.status_code, 200) 1318 self.assertEqual(data['status'], 200) 1319 self.assertEqual(alpha.node._reload().get_descendants().count(), 1) 1320 self.assertEqual(beta.node._reload().get_descendants().count(), 0) 1321 self.assertEqual(gamma.node._reload().get_descendants().count(), 0) 1322 1323 # Current structure: 1324 # <root> 1325 # ⊢ Alpha 1326 # ⊢ Beta 1327 # ⊢ Delta 1328 # ⊢ Gamma 1329 1330 # Move Gamma to be a child of Delta 1331 data = { 1332 'id': gamma.pk, 1333 'position': 1, 1334 'target': delta.pk, 1335 } 1336 1337 with self.login_user_context(admin_user): 1338 request = self.get_request(post_data=data) 1339 response = page_admin.move_page(request, page_id=gamma.pk) 1340 data = json.loads(response.content.decode('utf8')) 1341 1342 self.assertEqual(response.status_code, 200) 1343 self.assertEqual(data['status'], 200) 1344 self.assertEqual(alpha.node._reload().get_descendants().count(), 1) 1345 self.assertEqual(beta.node._reload().get_descendants().count(), 0) 1346 self.assertEqual(gamma.node._reload().get_descendants().count(), 0) 1347 self.assertEqual(delta.node._reload().get_descendants().count(), 1) 1348 1349 # Final structure: 1350 # <root> 1351 # ⊢ Alpha 1352 # ⊢ Beta 1353 # ⊢ Delta 1354 # ⊢ Gamma 1355