def test_models_person_title_fields_abbreviation_length(self): """ The `abbreviation` field should be limited to 10 characters """ PersonTitleFactory(abbreviation="a" * 10) with self.assertRaises(DataError) as context: PersonTitleFactory(abbreviation="b" * 11) self.assertTrue(context.exception.args[0].startswith( "value too long for type character varying(10)\n"))
def test_cms_wizards_person_submit_form_slug_too_long(self): """ Trying to set a slug that is too long should make the form invalid """ # A parent page should pre-exist create_page("Persons", "richie/fullwidth.html", "en", reverse_id=Person.ROOT_REVERSE_ID) person_title = PersonTitleFactory() # Submit a slug that is too long and a title that is ok invalid_data = { "title": "t" * 255, "slug": "s" * 201, "person_title": person_title.id, "first_name": "First name", "last_name": "Last name", } form = PersonWizardForm(data=invalid_data) self.assertFalse(form.is_valid()) # Check that the slug being too long is a cause for the invalid form self.assertEqual( form.errors["slug"], ["Ensure this value has at most 200 characters (it has 201)."], )
def test_cms_wizards_person_submit_form(self): """ Submitting a valid PersonWizardForm should create a Person page extension and its related page. """ # A parent page should pre-exist create_page("Persons", "richie/fullwidth.html", "en", reverse_id=Person.ROOT_REVERSE_ID) # create a PersonTitle object person_title = PersonTitleFactory() form = PersonWizardForm( data={ "title": "A person", "person_title": person_title.id, "first_name": "First name", "last_name": "Last name", }) self.assertTrue(form.is_valid()) page = form.save() # Related page should have been created as draft Page.objects.drafts().get(id=page.id) Person.objects.get(id=page.person.id, extended_object=page) self.assertEqual(page.get_title(), "A person") # The slug should have been automatically set self.assertEqual(page.get_slug(), "a-person")
def test_models_person_title_str(self): """ The string representation should be built with models name, `title` and `abbreviation` fields """ person_title = PersonTitleFactory(title="Madam", abbreviation="Mme") self.assertEqual(str(person_title), "Person Title: Madam (Mme)")
def test_cms_wizards_person_submit_form_max_lengths(self): """ Check that the form correctly raises an error when the slug is too long. The path built by combining the slug of the page with the slug of its parent page, should not exceed 255 characters in length. """ # A parent page with a very long slug create_page("y" * 200, "richie/fullwidth.html", "en", reverse_id=Person.ROOT_REVERSE_ID) person_title = PersonTitleFactory() # A person with a slug at the limit length should work form = PersonWizardForm( data={ "title": "t" * 255, "slug": "s" * 54, "person_title": person_title.id, "first_name": "First name", "last_name": "Last name", }) self.assertTrue(form.is_valid()) form.save() # A person with a slug too long with regards to the parent's one should raise an error form = PersonWizardForm(data={"title": "t" * 255, "slug": "s" * 55}) self.assertFalse(form.is_valid()) self.assertEqual( form.errors["slug"][0], ("This slug is too long. The length of the path built by prepending the slug of " "the parent page would be 256 characters long and it should be less than 255" ), )
def test_models_person_title_fields_abbreviation_length(self): """ The `abbreviation` field should be limited to 10 characters """ PersonTitleFactory(translation__abbreviation="a" * 10) with self.assertRaises(ValidationError) as context: PersonTitleFactory(translation__abbreviation="b" * 11) self.assertEqual( context.exception.message_dict, { "abbreviation": [ "Ensure this value has at most 10 characters (it has 11)." ] }, )
def test_admin_person_change_view_post(self): """ Validate that the person can be updated via the admin. """ user = UserFactory(is_staff=True, is_superuser=True) self.client.login(username=user.username, password="******") # Create a person, title will automaticaly be created person = PersonFactory() # create a new title new_title = PersonTitleFactory() # Get the admin change view url = reverse("admin:persons_person_change", args=[person.id]) data = { "person_title": new_title.id, "first_name": "New First Name", "last_name": "New Last Name", } response = self.client.post(url, data) self.assertEqual(response.status_code, 302) # Check that the person was updated as expected person.refresh_from_db() self.assertEqual(person.person_title, new_title) self.assertEqual(person.first_name, "New First Name") self.assertEqual(person.last_name, "New Last Name")
def test_models_person_title_fields_title_required(self): """ The `title` field should be required """ with self.assertRaises(IntegrityError) as context: PersonTitleFactory(title=None) self.assertTrue(context.exception.args[0].startswith( 'null value in column "title" violates not-null constraint'))
def test_models_person_title_fields_title_required(self): """ The `title` field should be required """ with self.assertRaises(ValidationError) as context: PersonTitleFactory(translation__title=None, translation__abbreviation="M") self.assertEqual( context.exception.message_dict, {"title": ["This field cannot be null."]} )
def test_models_person_get_full_name(self): """ The get_full_name method should return title, first name and last name separated by space. No SQL query should be generated. """ person_title = PersonTitleFactory(title="Madam", abbreviation="Mme") person = PersonFactory( first_name="Louise", last_name="Dupont", person_title=person_title ) with self.assertNumQueries(0): self.assertEqual(person.get_full_name(), "Madam Louise Dupont")
def test_person_title_list_view(self): """ The admin list view of person titles should display title and abbreviation """ user = UserFactory(is_staff=True, is_superuser=True) self.client.login(username=user.username, password="******") # Create a person linked to a page person_title = PersonTitleFactory() # Get the admin list view url = reverse("admin:persons_persontitle_changelist") response = self.client.get(url) # Check that the page includes all our fields self.assertContains(response, person_title.title, status_code=200) self.assertContains(response, person_title.abbreviation)
def test_person_title_change_view_get(self): """ The admin change view should include the editable and readonly fields as expected. """ user = UserFactory(is_staff=True, is_superuser=True) self.client.login(username=user.username, password="******") # Create a person title person_title = PersonTitleFactory() # Get the admin change view url = reverse("admin:persons_persontitle_change", args=[person_title.id]) response = self.client.get(url) # Check that the page includes all our fields self.assertContains(response, person_title.title) self.assertContains(response, person_title.abbreviation)
def test_models_person_str(self): """ The string representation should be built with the page `title` and all person fields. Only 1 query to the associated page should be generated. """ page = create_page( "Page of Lady Louise Dupont", "persons/cms/person_detail.html", "en" ) person_title = PersonTitleFactory(title="Madam", abbreviation="Mme") person = PersonFactory( first_name="Louise", last_name="Dupont", person_title=person_title, extended_object=page, ) with self.assertNumQueries(1): self.assertEqual( str(person), "Person: Page of Lady Louise Dupont (Madam Louise Dupont)" )
def test_person_change_view_post(self): """ Validate that the person title can be updated via the admin. """ user = UserFactory(is_staff=True, is_superuser=True) self.client.login(username=user.username, password="******") # Create a person, title will automaticaly be created person_title = PersonTitleFactory(title="Mister", abbreviation="Mr.") # Get the admin change view url = reverse("admin:persons_persontitle_change", args=[person_title.id]) data = {"title": "Madam", "abbreviation": "Mm."} response = self.client.post(url, data) self.assertEqual(response.status_code, 302) # Check that the person title was updated as expected person_title = PersonTitle.objects.get(id=person_title.id) self.assertEqual(person_title.title, "Madam") self.assertEqual(person_title.abbreviation, "Mm.")
def test_cms_wizards_person_parent_page_should_exist(self): """ We should not be able to create a person page if the parent page does not exist """ person_title = PersonTitleFactory() form = PersonWizardForm( data={ "title": "A person", "person_title": person_title.id, "first_name": "First name", "last_name": "Last name", }) self.assertFalse(form.is_valid()) self.assertEqual( form.errors, { "slug": [ "You must first create a parent page and set its `reverse_id` to `persons`." ] }, )
def test_cms_wizards_person_submit_form_last_name_required(self): """ The `last_name` field should be required """ # A parent page should pre-exist create_page("Persons", "richie/fullwidth.html", "en", reverse_id=Person.ROOT_REVERSE_ID) person_title = PersonTitleFactory() invalid_data = { "title": "A person", "person_title": person_title.id, "first_name": "First name", } form = PersonWizardForm(data=invalid_data) self.assertFalse(form.is_valid()) # Check that missing last_name field is a cause for the invalid form self.assertEqual(form.errors["last_name"], ["This field is required."])
def test_cms_wizards_person_submit_form_slugify_long_title(self): """ When generating the slug from the title, we should respect the slug's "max_length" """ # A parent page should pre-exist create_page("Persons", "richie/fullwidth.html", "en", reverse_id=Person.ROOT_REVERSE_ID) person_title = PersonTitleFactory() # Submit a title at max length data = { "title": "t" * 255, "person_title": person_title.id, "first_name": "First name", "last_name": "Last name", } form = PersonWizardForm(data=data) self.assertTrue(form.is_valid()) page = form.save() # Check that the slug has been truncated self.assertEqual(page.get_slug(), "t" * 200)
def create_demo_site(): """ Create a simple site tree structure for developpers to work in realistic environment. We create multilingual pages, add organizations under the related page and add plugins to each page. """ site = Site.objects.get(id=1) # Create pages as described in PAGES_INFOS pages_created = recursive_page_creation(site, PAGE_INFOS) # Create some licences licences = LicenceFactory.create_batch(NB_LICENCES) # Create organizations under the `Organizations` page organizations = OrganizationFactory.create_batch( NB_ORGANIZATIONS, page_in_navigation=True, page_languages=["en", "fr"], page_parent=pages_created["organizations"], fill_banner=True, fill_description=True, fill_logo=True, should_publish=True, ) # Generate each category tree and return a list of the leaf categories levels = list(create_categories(LEVELS_INFO, pages_created["categories"])) subjects = list( create_categories(SUBJECTS_INFO, pages_created["categories"])) title = PersonTitleFactory(translation=None) PersonTitleTranslationFactory(master=title, language_code="en", title="Doctor", abbreviation="Dr.") PersonTitleTranslationFactory(master=title, language_code="fr", title="Docteur", abbreviation="Dr.") # Create persons under the `persons` page persons = PersonFactory.create_batch( NB_PERSONS, page_in_navigation=True, page_languages=["en", "fr"], page_parent=pages_created["persons"], person_title=random.choice([title, None]), fill_portrait=True, fill_resume=True, should_publish=True, ) # Create courses under the `Course` page with categories and organizations # relations courses = [] for _ in range(NB_COURSES): video_sample = random.choice(VIDEO_SAMPLE_LINKS) course = CourseFactory( page_in_navigation=True, page_languages=["en", "fr"], page_parent=pages_created["courses"], fill_licences=[ ("course_license_content", random.choice(licences)), ("course_license_participation", random.choice(licences)), ], fill_team=random.sample(persons, NB_COURSES_PERSONS_PLUGINS), fill_teaser=video_sample, fill_cover=video_sample.image, fill_categories=[ *random.sample( subjects, random.randint(1, NB_COURSES_SUBJECT_RELATIONS)), random.choice(levels), ], fill_organizations=random.sample( organizations, NB_COURSES_ORGANIZATION_RELATIONS), fill_texts=[ "course_syllabus", "course_format", "course_prerequisites", "course_plan", # "course_license_content", # "course_license_participation", ], should_publish=True, ) courses.append(course) # Add a random number of course runs to the course nb_course_runs = get_number_of_course_runs() # 1) Make sure we have one course run open for enrollment now = timezone.now() CourseRunFactory( __sequence=nb_course_runs, page_in_navigation=False, page_parent=course.extended_object, start=now + timedelta(days=1), enrollment_start=now - timedelta(days=5), enrollment_end=now + timedelta(days=5), should_publish=True, ) # 2) Add more random course runs for i in range(nb_course_runs - 1, 0, -1): CourseRunFactory( __sequence=i, page_in_navigation=False, page_languages=["en", "fr"], page_parent=course.extended_object, should_publish=True, ) # Once everything has been created, use some content to create a homepage placeholder = pages_created["home"].placeholders.get(slot="maincontent") # - Get a banner image banner_file = file_getter("banner")() wrapped_banner = File(banner_file, banner_file.name) banner = Image.objects.create(file=wrapped_banner) # - Get a logo image logo_file = file_getter("logo")() wrapped_logo = File(logo_file, logo_file.name) logo = Image.objects.create(file=wrapped_logo) # - Create the home page in each language for language, content in HOMEPAGE_CONTENT.items(): # Add a banner add_plugin( language=language, placeholder=placeholder, plugin_type="LargeBannerPlugin", title=content["banner_title"], background_image=banner, logo=logo, logo_alt_text="logo", content=content["banner_content"], template=content["banner_template"], ) # Add highlighted courses courses_section = add_plugin( language=language, placeholder=placeholder, plugin_type="SectionPlugin", title=content["courses_title"], template=content["section_template"], ) for course in random.sample(courses, NB_HOME_HIGHLIGHTED_COURSES): add_plugin( language=language, placeholder=placeholder, plugin_type="CoursePlugin", target=courses_section, page=course.extended_object, ) # Add highlighted organizations organizations_section = add_plugin( language=language, placeholder=placeholder, plugin_type="SectionPlugin", title=content["organizations_title"], template=content["section_template"], ) for organization in random.sample(organizations, NB_HOME_HIGHLIGHTED_ORGANIZATIONS): add_plugin( language=language, placeholder=placeholder, plugin_type="OrganizationPlugin", target=organizations_section, page=organization.extended_object, ) # Add highlighted subjects subjects_section = add_plugin( language=language, placeholder=placeholder, plugin_type="SectionPlugin", title=content["subjects_title"], template=content["section_template"], ) for subject in random.sample(subjects, NB_HOME_HIGHLIGHTED_SUBJECTS): add_plugin( language=language, placeholder=placeholder, plugin_type="CategoryPlugin", target=subjects_section, page=subject.extended_object, ) # Add highlighted persons persons_section = add_plugin( language=language, placeholder=placeholder, plugin_type="SectionPlugin", title=content["persons_title"], template=content["section_template"], ) for person in random.sample(persons, NB_HOME_HIGHLIGHTED_PERSONS): add_plugin( language=language, placeholder=placeholder, plugin_type="PersonPlugin", target=persons_section, page=person.extended_object, ) # Once content has been added we must publish again homepage in every # edited Languages pages_created["home"].publish("en") pages_created["home"].publish("fr")