def testParseBadManifest(self): base_content = PublishableContentFactory(author_list=[self.user_author]) versioned = base_content.load_version() versioned.add_container(Container('un peu plus près de 42')) versioned.dump_json() manifest = os.path.join(versioned.get_path(), 'manifest.json') dictionary = json_handler.load(open(manifest)) old_title = dictionary['title'] # first bad title dictionary['title'] = 81 * ['a'] self.assertRaises(BadManifestError, get_content_from_json, dictionary, None, '', max_title_len=PublishableContent._meta.get_field('title').max_length) dictionary['title'] = ''.join(dictionary['title']) self.assertRaises(BadManifestError, get_content_from_json, dictionary, None, '', max_title_len=PublishableContent._meta.get_field('title').max_length) dictionary['title'] = '...' self.assertRaises(InvalidSlugError, get_content_from_json, dictionary, None, '', max_title_len=PublishableContent._meta.get_field('title').max_length) dictionary['title'] = old_title dictionary['children'][0]['title'] = 81 * ['a'] self.assertRaises(BadManifestError, get_content_from_json, dictionary, None, '', max_title_len=PublishableContent._meta.get_field('title').max_length) dictionary['children'][0]['title'] = 'bla' dictionary['children'][0]['slug'] = '...' self.assertRaises(InvalidSlugError, get_content_from_json, dictionary, None, '', max_title_len=PublishableContent._meta.get_field('title').max_length)
def test_opinion_publication_guest(self): """ Test the publication of PublishableContent where type is OPINION (with guest => 403). """ text_publication = 'Aussi tôt dit, aussi tôt fait !' opinion = PublishableContentFactory(type='OPINION') opinion.authors.add(self.user_author) UserGalleryFactory(gallery=opinion.gallery, user=self.user_author, mode='W') opinion.licence = self.licence opinion.save() opinion_draft = opinion.load_version() ExtractFactory(container=opinion_draft, db_object=opinion) ExtractFactory(container=opinion_draft, db_object=opinion) self.assertEqual( self.client.login( username=self.user_guest.username, password='******'), True) result = self.client.post( reverse('validation:publish-opinion', kwargs={'pk': opinion.pk, 'slug': opinion.slug}), { 'text': text_publication, 'source': '', 'version': opinion_draft.current_version }, follow=False) self.assertEqual(result.status_code, 403) self.assertEqual(PublishedContent.objects.count(), 0)
def test_get_tuto_count(self): # Start with 0 self.assertEqual(self.user1.get_tuto_count(), 0) # Create Tuto ! minituto = PublishableContentFactory(type='TUTORIAL') minituto.authors.add(self.user1.user) minituto.gallery = GalleryFactory() minituto.save() # Should be 1 self.assertEqual(self.user1.get_tuto_count(), 1)
def test_get_draft_articles(self): # Start with 0 self.assertEqual(len(self.user1.get_draft_articles()), 0) # Create article ! article = PublishableContentFactory(type='ARTICLE') article.authors.add(self.user1.user) article.save() # Should be 1 articles = self.user1.get_draft_articles() self.assertEqual(len(articles), 1) self.assertEqual(article, articles[0])
def test_get_validate_tutos(self): # Start with 0 self.assertEqual(len(self.user1.get_validate_tutos()), 0) # Create Tuto ! validatetuto = PublishableContentFactory(type='TUTORIAL', author_list=[self.user1.user]) validatetuto.sha_validation = 'whatever' validatetuto.save() # Should be 1 validatetutos = self.user1.get_validate_tutos() self.assertEqual(len(validatetutos), 1) self.assertEqual(validatetuto, validatetutos[0])
def test_get_draft_tutos(self): # Start with 0 self.assertEqual(len(self.user1.get_draft_tutos()), 0) # Create Tuto ! drafttuto = PublishableContentFactory(type='TUTORIAL') drafttuto.authors.add(self.user1.user) drafttuto.gallery = GalleryFactory() drafttuto.save() # Should be 1 drafttutos = self.user1.get_draft_tutos() self.assertEqual(len(drafttutos), 1) self.assertEqual(drafttuto, drafttutos[0])
def test_tagged_tree_extract(self): midsize = PublishableContentFactory(author_list=[self.user_author]) midsize_draft = midsize.load_version() first_container = ContainerFactory(parent=midsize_draft, db_object=midsize) second_container = ContainerFactory(parent=midsize_draft, db_object=midsize) first_extract = ExtractFactory(container=first_container, db_object=midsize) second_extract = ExtractFactory(container=second_container, db_object=midsize) tagged_tree = get_target_tagged_tree_for_extract(first_extract, midsize_draft) paths = {i[0]: i[3] for i in tagged_tree} self.assertTrue(paths[second_extract.get_full_slug()]) self.assertFalse(paths[second_container.get_path(True)]) self.assertFalse(paths[first_container.get_path(True)])
def test_publish_content_article(self): """test and ensure the behavior of ``publish_content()`` and ``unpublish_content()``""" # 1. Article: article = PublishableContentFactory(type='ARTICLE') article.authors.add(self.user_author) UserGalleryFactory(gallery=article.gallery, user=self.user_author, mode='W') article.licence = self.licence article.save() # populate the article article_draft = article.load_version() ExtractFactory(container=article_draft, db_object=article) ExtractFactory(container=article_draft, db_object=article) self.assertEqual(len(article_draft.children), 2) # publish ! article = PublishableContent.objects.get(pk=article.pk) published = publish_content(article, article_draft) self.assertEqual(published.content, article) self.assertEqual(published.content_pk, article.pk) self.assertEqual(published.content_type, article.type) self.assertEqual(published.content_public_slug, article_draft.slug) self.assertEqual(published.sha_public, article.sha_draft) public = article.load_version(sha=published.sha_public, public=published) self.assertIsNotNone(public) self.assertTrue(public.PUBLIC) # it's a PublicContent object self.assertEqual(public.type, published.content_type) self.assertEqual(public.current_version, published.sha_public) # test object created in database self.assertEqual(PublishedContent.objects.filter(content=article).count(), 1) published = PublishedContent.objects.filter(content=article).last() self.assertEqual(published.content_pk, article.pk) self.assertEqual(published.content_public_slug, article_draft.slug) self.assertEqual(published.content_type, article.type) self.assertEqual(published.sha_public, public.current_version) # test creation of files: self.assertTrue(os.path.isdir(published.get_prod_path())) self.assertTrue(os.path.isfile(os.path.join(published.get_prod_path(), 'manifest.json'))) prod_path = public.get_prod_path() self.assertTrue(prod_path.endswith('.html'), prod_path) self.assertTrue(os.path.isfile(prod_path), prod_path) # normally, an HTML file should exists self.assertIsNone(public.introduction) # since all is in the HTML file, introduction does not exists anymore self.assertIsNone(public.conclusion) article.public_version = published article.save() # depublish it ! unpublish_content(article) self.assertEqual(PublishedContent.objects.filter(content=article).count(), 0) # published object disappear self.assertFalse(os.path.exists(public.get_prod_path())) # article was removed
def test_get_beta_tutos(self): # Start with 0 self.assertEqual(len(self.user1.get_beta_tutos()), 0) # Create Tuto ! betatetuto = PublishableContentFactory(type='TUTORIAL') betatetuto.authors.add(self.user1.user) betatetuto.gallery = GalleryFactory() betatetuto.sha_beta = 'whatever' betatetuto.save() # Should be 1 betatetutos = self.user1.get_beta_tutos() self.assertEqual(len(betatetutos), 1) self.assertEqual(betatetuto, betatetutos[0])
def test_get_public_tutos(self): # Start with 0 self.assertEqual(len(self.user1.get_public_tutos()), 0) # Create Tuto ! publictuto = PublishableContentFactory(type='TUTORIAL') publictuto.authors.add(self.user1.user) publictuto.gallery = GalleryFactory() publictuto.sha_public = 'whatever' publictuto.save() # Should be 0 because publication was not used publictutos = self.user1.get_public_tutos() self.assertEqual(len(publictutos), 0) PublishedContentFactory(author_list=[self.user1.user]) self.assertEqual(len(self.user1.get_public_tutos()), 1)
def test_get_public_articles(self): # Start with 0 self.assertEqual(len(self.user1.get_public_articles()), 0) # Create article ! article = PublishableContentFactory(type='ARTICLE') article.authors.add(self.user1.user) article.sha_public = 'whatever' article.save() # Should be 0 articles = self.user1.get_public_articles() self.assertEqual(len(articles), 0) # Should be 1 PublishedContentFactory(author_list=[self.user1.user], type='ARTICLE') self.assertEqual(len(self.user1.get_public_articles()), 1) self.assertEqual(len(self.user1.get_public_tutos()), 0)
def setUp(self): self.mas = ProfileFactory().user self.overridden_zds_app['member']['bot_account'] = self.mas.username self.licence = LicenceFactory() self.user_author = ProfileFactory().user self.staff = StaffProfileFactory().user self.tuto = PublishableContentFactory(type='TUTORIAL') self.tuto.authors.add(self.user_author) UserGalleryFactory(gallery=self.tuto.gallery, user=self.user_author, mode='W') self.tuto.licence = self.licence self.tuto.save() self.tuto_draft = self.tuto.load_version() self.part1 = ContainerFactory(parent=self.tuto_draft, db_object=self.tuto) self.chapter1 = ContainerFactory(parent=self.part1, db_object=self.tuto) self.old_registry = {key: value for key, value in PublicatorRegistry.get_all_registered()} class TestPdfPublicator(Publicator): def publish(self, md_file_path, base_name, **kwargs): with Path(base_name + '.pdf').open('w') as f: f.write('bla') shutil.copy2(str(Path(base_name + '.pdf')), str(Path(md_file_path.replace('__building', '')).parent)) PublicatorRegistry.registry['pdf'] = TestPdfPublicator()
def setUp(self): # don't build PDF to speed up the tests self.user1 = ProfileFactory().user self.user2 = ProfileFactory().user # create a tutorial self.tuto = PublishableContentFactory(type='TUTORIAL') self.tuto.authors.add(self.user1) UserGalleryFactory(gallery=self.tuto.gallery, user=self.user1, mode='W') self.tuto.licence = LicenceFactory() self.tuto.subcategory.add(SubCategoryFactory()) self.tuto.save() tuto_draft = self.tuto.load_version() # then, publish it ! version = tuto_draft.current_version self.published = publish_content(self.tuto, tuto_draft, is_major_update=True) self.tuto.sha_public = version self.tuto.sha_draft = version self.tuto.public_version = self.published self.tuto.save() self.assertTrue(self.client.login(username=self.user1.username, password='******'))
def setUp(self): self.licence = LicenceFactory() self.subcategory = SubCategoryFactory() self.author = ProfileFactory() self.user = ProfileFactory() self.staff = StaffProfileFactory() self.tuto = PublishableContentFactory(type='TUTORIAL') self.tuto.authors.add(self.author.user) self.tuto.licence = self.licence self.tuto.subcategory.add(self.subcategory) self.tuto.save() self.validation = Validation( content=self.tuto, version=self.tuto.sha_draft, comment_authors='bla', date_proposition=datetime.now(), ) self.validation.save() self.topic = send_mp(author=self.author.user, users=[], title='Title', text='Testing', subtitle='', leave=False) self.topic.participants.add(self.user.user) send_message_mp(self.user.user, self.topic, 'Testing') # humane_delta test periods = ((1, 0), (2, 1), (3, 7), (4, 30), (5, 360)) cont = dict() cont['date_today'] = periods[0][0] cont['date_yesterday'] = periods[1][0] cont['date_last_week'] = periods[2][0] cont['date_last_month'] = periods[3][0] cont['date_last_year'] = periods[4][0] self.context = Context(cont)
def setUp(self): self.staff = StaffProfileFactory().user settings.EMAIL_BACKEND = 'django.core.mail.backends.locmem.EmailBackend' self.mas = ProfileFactory().user self.overridden_zds_app['member']['bot_account'] = self.mas.username self.licence = LicenceFactory() self.subcategory = SubCategoryFactory() self.user_author = ProfileFactory().user self.user_staff = StaffProfileFactory().user self.user_guest = ProfileFactory().user self.tuto = PublishableContentFactory(type='TUTORIAL') self.tuto.authors.add(self.user_author) UserGalleryFactory(gallery=self.tuto.gallery, user=self.user_author, mode='W') self.tuto.licence = self.licence self.tuto.subcategory.add(self.subcategory) self.tuto.save() self.beta_forum = ForumFactory( pk=self.overridden_zds_app['forum']['beta_forum_id'], category=CategoryFactory(position=1), position_in_category=1) # ensure that the forum, for the beta versions, is created self.tuto_draft = self.tuto.load_version() self.part1 = ContainerFactory(parent=self.tuto_draft, db_object=self.tuto) self.chapter1 = ContainerFactory(parent=self.part1, db_object=self.tuto) self.extract1 = ExtractFactory(container=self.chapter1, db_object=self.tuto) bot = Group(name=self.overridden_zds_app['member']['bot_group']) bot.save()
def test_char_count_after_publication(self): """Test the ``get_char_count()`` function. Special care should be taken with this function, since: - The username of the author is, by default "Firmxxx" where "xxx" depends on the tests before ; - The titles (!) also contains a number that also depends on the number of tests before ; - The date is ``datetime.now()`` and contains the months, which is never a fixed number of letters. """ author = ProfileFactory().user author.username = '******' author.save() len_date_now = len(date(datetime.now(), 'd F Y')) article = PublishedContentFactory(type='ARTICLE', author_list=[author], title='Un titre') published = PublishedContent.objects.filter(content=article).first() self.assertEqual(published.get_char_count(), 160 + len_date_now) tuto = PublishableContentFactory(type='TUTORIAL', author_list=[author], title='Un titre') # add a chapter, so it becomes a middle tutorial tuto_draft = tuto.load_version() chapter1 = ContainerFactory(parent=tuto_draft, db_object=tuto, title='Un chapitre') ExtractFactory(container=chapter1, db_object=tuto, title='Un extrait') published = publish_content(tuto, tuto_draft, is_major_update=True) tuto.sha_public = tuto_draft.current_version tuto.sha_draft = tuto_draft.current_version tuto.public_version = published tuto.save() published = PublishedContent.objects.filter(content=tuto).first() self.assertEqual(published.get_char_count(), 335 + len_date_now)
def test_content_ordering(self): category_1 = ContentCategoryFactory() category_2 = ContentCategoryFactory() subcategory_1 = SubCategoryFactory(category=category_1) subcategory_1.position = 5 subcategory_1.save() subcategory_2 = SubCategoryFactory(category=category_1) subcategory_2.position = 1 subcategory_2.save() subcategory_3 = SubCategoryFactory(category=category_2) tuto_1 = PublishableContentFactory(type='TUTORIAL') tuto_1.subcategory.add(subcategory_1) tuto_1_draft = tuto_1.load_version() publish_content(tuto_1, tuto_1_draft, is_major_update=True) top_categories_tuto = topbar_publication_categories('TUTORIAL').get('categories') expected = [(subcategory_1.title, subcategory_1.slug, category_1.slug)] self.assertEqual(top_categories_tuto[category_1.title], expected) tuto_2 = PublishableContentFactory(type='TUTORIAL') tuto_2.subcategory.add(subcategory_2) tuto_2_draft = tuto_2.load_version() publish_content(tuto_2, tuto_2_draft, is_major_update=True) top_categories_tuto = topbar_publication_categories('TUTORIAL').get('categories') # New subcategory is now first is the list expected.insert(0, (subcategory_2.title, subcategory_2.slug, category_1.slug)) self.assertEqual(top_categories_tuto[category_1.title], expected) article_1 = PublishableContentFactory(type='TUTORIAL') article_1.subcategory.add(subcategory_3) article_1_draft = tuto_2.load_version() publish_content(article_1, article_1_draft, is_major_update=True) # New article has no impact top_categories_tuto = topbar_publication_categories('TUTORIAL').get('categories') self.assertEqual(top_categories_tuto[category_1.title], expected) top_categories_contents = topbar_publication_categories(['TUTORIAL', 'ARTICLE']).get('categories') expected_2 = [(subcategory_3.title, subcategory_3.slug, category_2.slug)] self.assertEqual(top_categories_contents[category_1.title], expected) self.assertEqual(top_categories_contents[category_2.title], expected_2)
def setUp(self): self.overridden_zds_app = overridden_zds_app # don't build PDF to speed up the tests overridden_zds_app['content']['build_pdf_when_published'] = False self.staff = StaffProfileFactory().user settings.EMAIL_BACKEND = 'django.core.mail.backends.locmem.EmailBackend' self.mas = ProfileFactory().user overridden_zds_app['member']['bot_account'] = self.mas.username bot = Group(name=overridden_zds_app['member']['bot_group']) bot.save() self.external = UserFactory( username=overridden_zds_app['member']['external_account'], password='******') self.beta_forum = ForumFactory( pk=overridden_zds_app['forum']['beta_forum_id'], category=CategoryFactory(position=1), position_in_category=1) # ensure that the forum, for the beta versions, is created self.licence = LicenceFactory() self.subcategory = SubCategoryFactory() self.user_author = ProfileFactory().user self.user_staff = StaffProfileFactory().user self.user_guest = ProfileFactory().user # create a tutorial self.tuto = PublishableContentFactory(type='TUTORIAL') self.tuto.authors.add(self.user_author) UserGalleryFactory(gallery=self.tuto.gallery, user=self.user_author, mode='W') self.tuto.licence = self.licence self.tuto.subcategory.add(self.subcategory) self.tuto.save() # fill it with one part, containing one chapter, containing one extract self.tuto_draft = self.tuto.load_version() self.part1 = ContainerFactory(parent=self.tuto_draft, db_object=self.tuto) self.chapter1 = ContainerFactory(parent=self.part1, db_object=self.tuto) self.extract1 = ExtractFactory(container=self.chapter1, db_object=self.tuto) # then, publish it ! version = self.tuto_draft.current_version self.published = publish_content(self.tuto, self.tuto_draft, is_major_update=True) self.tuto.sha_public = version self.tuto.sha_draft = version self.tuto.public_version = self.published self.tuto.save() self.tutofeed = LastTutorialsFeedRSS()
def test_ensure_slug_stay(self): """This test ensures that slugs are not modified when coming from a manifest""" tuto = PublishableContentFactory(type='TUTORIAL') versioned = tuto.load_version() random = 'Non, piti bug, tu ne reviendras plus !!!' title = "N'importe quel titre" # add three container with the same title versioned.repo_add_container(title, random, random) # x versioned.repo_add_container(title, random, random) # x-1 version = versioned.repo_add_container(title, random, random) # x-2 self.assertEqual(len(versioned.children), 3) current = tuto.load_version(sha=version) self.assertEqual(len(current.children), 3) for index, child in enumerate(current.children): self.assertEqual(child.slug, versioned.children[index].slug) # same order # then, delete the second one: last_slug = versioned.children[2].slug version = versioned.children[1].repo_delete() self.assertEqual(len(versioned.children), 2) self.assertEqual(versioned.children[1].slug, last_slug) current = tuto.load_version(sha=version) self.assertEqual(len(current.children), 2) for index, child in enumerate(current.children): self.assertEqual(child.slug, versioned.children[index].slug) # slug remains # same test with extracts chapter = versioned.children[0] chapter.repo_add_extract(title, random) # x chapter.repo_add_extract(title, random) # x-1 version = chapter.repo_add_extract(title, random) # x-2 self.assertEqual(len(chapter.children), 3) current = tuto.load_version(sha=version) self.assertEqual(len(current.children[0].children), 3) for index, child in enumerate(current.children[0].children): self.assertEqual(child.slug, chapter.children[index].slug) # slug remains # delete the second one! last_slug = chapter.children[2].slug version = chapter.children[1].repo_delete() self.assertEqual(len(chapter.children), 2) self.assertEqual(chapter.children[1].slug, last_slug) current = tuto.load_version(sha=version) self.assertEqual(len(current.children[0].children), 2) for index, child in enumerate(current.children[0].children): self.assertEqual(child.slug, chapter.children[index].slug) # slug remains for extract as well!
def test_publish_content_big_tuto(self): # 4. Big tutorial: bigtuto = PublishableContentFactory(type='TUTORIAL') bigtuto.authors.add(self.user_author) UserGalleryFactory(gallery=bigtuto.gallery, user=self.user_author, mode='W') bigtuto.licence = self.licence bigtuto.save() # populate with 2 part (1 chapter with 1 extract each) bigtuto_draft = bigtuto.load_version() part1 = ContainerFactory(parent=bigtuto_draft, db_objet=bigtuto) chapter1 = ContainerFactory(parent=part1, db_objet=bigtuto) ExtractFactory(container=chapter1, db_object=bigtuto) part2 = ContainerFactory(parent=bigtuto_draft, db_objet=bigtuto) chapter2 = ContainerFactory(parent=part2, db_objet=bigtuto) ExtractFactory(container=chapter2, db_object=bigtuto) # publish it bigtuto = PublishableContent.objects.get(pk=bigtuto.pk) published = publish_content(bigtuto, bigtuto_draft) self.assertEqual(published.content, bigtuto) self.assertEqual(published.content_pk, bigtuto.pk) self.assertEqual(published.content_type, bigtuto.type) self.assertEqual(published.content_public_slug, bigtuto_draft.slug) self.assertEqual(published.sha_public, bigtuto.sha_draft) public = bigtuto.load_version(sha=published.sha_public, public=published) self.assertIsNotNone(public) self.assertTrue(public.PUBLIC) # it's a PublicContent object self.assertEqual(public.type, published.content_type) self.assertEqual(public.current_version, published.sha_public) # test creation of files: self.assertTrue(os.path.isdir(published.get_prod_path())) self.assertTrue(os.path.isfile(os.path.join(published.get_prod_path(), 'manifest.json'))) self.assertTrue(os.path.isfile(os.path.join(public.get_prod_path(), public.introduction))) self.assertTrue(os.path.isfile(os.path.join(public.get_prod_path(), public.conclusion))) self.assertEqual(len(public.children), 2) for part in public.children: self.assertTrue(os.path.isdir(part.get_prod_path())) # a directory for each part # ... and an HTML file for introduction and conclusion self.assertTrue(os.path.isfile(os.path.join(public.get_prod_path(), part.introduction))) self.assertTrue(os.path.isfile(os.path.join(public.get_prod_path(), part.conclusion))) self.assertEqual(len(part.children), 1) for chapter in part.children: # the HTML file is located in the good directory: self.assertEqual(part.get_prod_path(), os.path.dirname(chapter.get_prod_path())) self.assertTrue(os.path.isfile(chapter.get_prod_path())) # an HTML file for each chapter self.assertIsNone(chapter.introduction) self.assertIsNone(chapter.conclusion)
def test_image_with_non_ascii_chars(self): """seen on #4144""" article = PublishableContentFactory(type='article', author_list=[self.user_author]) image_string = '![Portrait de Richard Stallman en 2014. [Source](https://commons.wikimedia.org/wiki/' \ 'File:Richard_Stallman_-_Fête_de_l%27Humanité_2014_-_010.jpg).]' \ '(/media/galleries/4410/c1016bf1-a1de-48a1-9ef1-144308e8725d.jpg)' article.sha_draft = article.load_version().repo_update(article.title, image_string, '', update_slug=False) article.save(force_slug_update=False) publish_content(article, article.load_version()) self.assertTrue(PublishedContent.objects.filter(content_id=article.pk).exists())
def create_multiple_tags(self, number_of_tags=REST_PAGE_SIZE): tags = [] for tag in range(0, number_of_tags): tags.append('number' + str(tag)) # Prepare content containing all the tags content = PublishableContentFactory(type='TUTORIAL') content.add_tags(tags) content.save() content_draft = content.load_version() # then, publish it ! publish_content(content, content_draft)
def setUp(self): settings.EMAIL_BACKEND = 'django.core.mail.backends.locmem.EmailBackend' self.mas = ProfileFactory().user self.overridden_zds_app['member']['bot_account'] = self.mas.username self.licence = LicenceFactory() self.user_author = ProfileFactory().user self.staff = StaffProfileFactory().user self.tuto = PublishableContentFactory(type='TUTORIAL') self.tuto.authors.add(self.user_author) UserGalleryFactory(gallery=self.tuto.gallery, user=self.user_author, mode='W') self.tuto.licence = self.licence self.tuto.save() self.tuto_draft = self.tuto.load_version() self.part1 = ContainerFactory(parent=self.tuto_draft, db_object=self.tuto) self.chapter1 = ContainerFactory(parent=self.part1, db_object=self.tuto) self.extract1 = ExtractFactory(container=self.chapter1, db_object=self.tuto)
def setUp(self): self.overridden_zds_app = overridden_zds_app # don't build PDF to speed up the tests overridden_zds_app['content']['build_pdf_when_published'] = False self.staff = StaffProfileFactory().user settings.EMAIL_BACKEND = 'django.core.mail.backends.locmem.EmailBackend' self.mas = ProfileFactory().user overridden_zds_app['member']['bot_account'] = self.mas.username self.licence = LicenceFactory() self.subcategory = SubCategoryFactory() self.user_author = ProfileFactory().user self.user_staff = StaffProfileFactory().user self.user_guest = ProfileFactory().user self.content = PublishableContentFactory(author_list=[self.user_author], light=False) self.part_published = ContainerFactory(db_object=self.content, light=False, parent=self.content.load_version()) self.ignored_part = ContainerFactory(db_object=self.content, light=False, parent=self.content.load_version()) ExtractFactory(db_object=self.content, container=self.part_published, light=False) ExtractFactory(db_object=self.content, container=self.ignored_part, light=False)
def test_extract_is_none(self): """Test the case of a null extract""" article = PublishableContentFactory(type='ARTICLE') versioned = article.load_version() given_title = 'Peu importe, en fait, ça compte peu' some_text = 'Disparaitra aussi vite que possible' # add a new extract with `None` for text version = versioned.repo_add_extract(given_title, None) # check on the model: new_extract = versioned.children[-1] self.assertIsNone(new_extract.text) # it remains when loading the manifest! versioned2 = article.load_version(sha=version) self.assertIsNotNone(versioned2) self.assertIsNone(versioned.children[-1].text) version = new_extract.repo_update(given_title, None) self.assertIsNone(new_extract.text) # it remains versioned2 = article.load_version(sha=version) self.assertIsNotNone(versioned2) self.assertIsNone(versioned.children[-1].text) version = new_extract.repo_update(given_title, some_text) self.assertIsNotNone(new_extract.text) self.assertEqual(some_text, new_extract.get_text()) # now it changes versioned2 = article.load_version(sha=version) self.assertIsNotNone(versioned2) self.assertIsNotNone(versioned.children[-1].text) # ... and lets go back version = new_extract.repo_update(given_title, None) self.assertIsNone(new_extract.text) # it has changed versioned2 = article.load_version(sha=version) self.assertIsNotNone(versioned2) self.assertIsNone(versioned.children[-1].text)
def test_publish_content_medium_tuto(self): # 3. Medium-size tutorial midsize_tuto = PublishableContentFactory(type='TUTORIAL') midsize_tuto.authors.add(self.user_author) UserGalleryFactory(gallery=midsize_tuto.gallery, user=self.user_author, mode='W') midsize_tuto.licence = self.licence midsize_tuto.save() # populate with 2 chapters (1 extract each) midsize_tuto_draft = midsize_tuto.load_version() chapter1 = ContainerFactory(parent=midsize_tuto_draft, db_objet=midsize_tuto) ExtractFactory(container=chapter1, db_object=midsize_tuto) chapter2 = ContainerFactory(parent=midsize_tuto_draft, db_objet=midsize_tuto) ExtractFactory(container=chapter2, db_object=midsize_tuto) # publish it midsize_tuto = PublishableContent.objects.get(pk=midsize_tuto.pk) published = publish_content(midsize_tuto, midsize_tuto_draft) self.assertEqual(published.content, midsize_tuto) self.assertEqual(published.content_pk, midsize_tuto.pk) self.assertEqual(published.content_type, midsize_tuto.type) self.assertEqual(published.content_public_slug, midsize_tuto_draft.slug) self.assertEqual(published.sha_public, midsize_tuto.sha_draft) public = midsize_tuto.load_version(sha=published.sha_public, public=published) self.assertIsNotNone(public) self.assertTrue(public.PUBLIC) # it's a PublicContent object self.assertEqual(public.type, published.content_type) self.assertEqual(public.current_version, published.sha_public) # test creation of files: self.assertTrue(Path(published.get_prod_path()).is_dir()) self.assertTrue(Path(published.get_prod_path(), 'manifest.json').is_file()) self.assertTrue(Path(public.get_prod_path(), public.introduction).is_file()) self.assertTrue(Path(public.get_prod_path(), public.conclusion).is_file()) self.assertEqual(len(public.children), 2) for child in public.children: self.assertTrue(os.path.isfile(child.get_prod_path())) # an HTML file for each chapter self.assertIsNone(child.introduction) self.assertIsNone(child.conclusion)
def test_indexation(self): """test the indexation and deletion of the different documents""" if not self.manager.connected_to_es: return # create a topic with a post topic = TopicFactory(forum=self.forum, author=self.user) post = PostFactory(topic=topic, author=self.user, position=1) topic = Topic.objects.get(pk=topic.pk) post = Post.objects.get(pk=post.pk) self.assertFalse(topic.es_already_indexed) self.assertTrue(topic.es_flagged) self.assertFalse(post.es_already_indexed) self.assertTrue(post.es_flagged) # create a middle-tutorial and publish it tuto = PublishableContentFactory(type='TUTORIAL') tuto.authors.add(self.user) tuto.save() tuto_draft = tuto.load_version() chapter1 = ContainerFactory(parent=tuto_draft, db_object=tuto) ExtractFactory(container=chapter1, db_object=tuto) published = publish_content(tuto, tuto_draft, is_major_update=True) tuto.sha_public = tuto_draft.current_version tuto.sha_draft = tuto_draft.current_version tuto.public_version = published tuto.save() published = PublishedContent.objects.get(content_pk=tuto.pk) self.assertFalse(published.es_already_indexed) self.assertTrue(published.es_flagged) # 1. index all for model in self.indexable: if model is FakeChapter: continue self.manager.es_bulk_indexing_of_model(model, force_reindexing=False) self.manager.refresh_index() topic = Topic.objects.get(pk=topic.pk) post = Post.objects.get(pk=post.pk) self.assertTrue(topic.es_already_indexed) self.assertFalse(topic.es_flagged) self.assertTrue(post.es_already_indexed) self.assertFalse(post.es_flagged) published = PublishedContent.objects.get(content_pk=tuto.pk) self.assertTrue(published.es_already_indexed) self.assertFalse(published.es_flagged) s = Search() s.query(MatchAll()) results = self.manager.setup_search(s).execute() self.assertEqual(len(results), 4) # get 4 results, one of each type must_contain = {'post': False, 'topic': False, 'publishedcontent': False, 'chapter': False} id_must_be = { 'post': str(post.pk), 'topic': str(topic.pk), 'publishedcontent': str(published.pk), 'chapter': tuto.slug + '__' + chapter1.slug } for hit in results: doc_type = hit.meta.doc_type must_contain[doc_type] = True self.assertEqual(hit.meta.id, id_must_be[doc_type]) self.assertTrue(all(must_contain)) # 2. Test what reindexation will do: new_topic = TopicFactory(forum=self.forum, author=self.user) new_post = PostFactory(topic=new_topic, author=self.user, position=1) pk_of_topics_to_reindex = [] for item in Topic.get_es_indexable(force_reindexing=False): pk_of_topics_to_reindex.append(item.pk) pk_of_posts_to_reindex = [] for item in Post.get_es_indexable(force_reindexing=False): pk_of_posts_to_reindex.append(item.pk) self.assertTrue(topic.pk not in pk_of_topics_to_reindex) self.assertTrue(new_topic.pk in pk_of_topics_to_reindex) self.assertTrue(post.pk not in pk_of_posts_to_reindex) self.assertTrue(new_post.pk in pk_of_posts_to_reindex) for model in self.indexable: # ok, so let's index that if model is FakeChapter: continue self.manager.es_bulk_indexing_of_model(model, force_reindexing=False) self.manager.refresh_index() s = Search() s.query(MatchAll()) results = self.manager.setup_search(s).execute() self.assertEqual(len(results), 6) # good! # 3. Test single deletion: new_post = Post.objects.get(pk=new_post.pk) self.manager.delete_document(new_post) self.manager.refresh_index() s = Search() s.query(MatchAll()) results = self.manager.setup_search(s).execute() self.assertEqual(len(results), 5) # one is missing for hit in results: self.assertTrue(hit.meta.doc_type != Post.get_es_document_type() or hit.meta.id != new_post.es_id) # 4. Test "delete_by_query_deletion": topic = Topic.objects.get(pk=topic.pk) new_topic = Topic.objects.get(pk=new_topic.pk) self.manager.delete_by_query(Topic.get_es_document_type(), MatchAll()) # the two topic are deleted self.manager.refresh_index() s = Search() s.query(MatchAll()) results = self.manager.setup_search(s).execute() self.assertEqual(len(results), 3) for hit in results: self.assertTrue(hit.meta.doc_type != Topic.get_es_document_type() or hit.meta.id != new_topic.es_id) self.assertTrue(hit.meta.doc_type != Topic.get_es_document_type() or hit.meta.id != topic.es_id) # 5. Test that the deletion of an object also triggers its deletion in ES post = Post.objects.get(pk=post.pk) post.delete() self.manager.refresh_index() s = Search() s.query(MatchAll()) results = self.manager.setup_search(s).execute() self.assertEqual(len(results), 2) for hit in results: self.assertTrue(hit.meta.doc_type != Post.get_es_document_type() or hit.meta.id != post.es_id) # 6. Test full desindexation: for model in self.indexable: if model is FakeChapter: continue self.manager.clear_indexing_of_model(model) # note "topic" is gone since "post" is gone, due to relationships at the Django level new_topic = Topic.objects.get(pk=new_topic.pk) new_post = Post.objects.get(pk=new_post.pk) self.assertFalse(new_topic.es_already_indexed) self.assertTrue(new_topic.es_flagged) self.assertFalse(new_post.es_already_indexed) self.assertTrue(new_post.es_flagged) published = PublishedContent.objects.get(content_pk=tuto.pk) self.assertFalse(published.es_already_indexed) self.assertTrue(published.es_flagged)
def test_opinion_conversion(self): """ Test the conversion of PublishableContent with type=OPINION to PublishableContent with type=ARTICLE """ text_publication = 'Aussi tôt dit, aussi tôt fait !' opinion = PublishableContentFactory(type='OPINION') opinion.authors.add(self.user_author) UserGalleryFactory(gallery=opinion.gallery, user=self.user_author, mode='W') opinion.licence = self.licence opinion.save() opinion_draft = opinion.load_version() ExtractFactory(container=opinion_draft, db_object=opinion) ExtractFactory(container=opinion_draft, db_object=opinion) self.assertEqual( self.client.login(username=self.user_author.username, password='******'), True) # publish result = self.client.post(reverse('validation:publish-opinion', kwargs={ 'pk': opinion.pk, 'slug': opinion.slug }), { 'text': text_publication, 'source': '', 'version': opinion_draft.current_version }, follow=False) self.assertEqual(result.status_code, 302) self.assertEqual(PublishedContent.objects.count(), 1) opinion = PublishableContent.objects.get(pk=opinion.pk) self.assertIsNotNone(opinion.public_version) self.assertEqual(opinion.public_version.sha_public, opinion_draft.current_version) # valid with author => 403 result = self.client.post(reverse('validation:promote-opinion', kwargs={ 'pk': opinion.pk, 'slug': opinion.slug }), { 'source': '', 'version': opinion_draft.current_version }, follow=False) self.assertEqual(result.status_code, 403) self.assertEqual( self.client.login(username=self.user_staff.username, password='******'), True) # valid with staff result = self.client.post(reverse('validation:promote-opinion', kwargs={ 'pk': opinion.pk, 'slug': opinion.slug }), { 'source': '', 'version': opinion_draft.current_version }, follow=False) self.assertEqual(result.status_code, 302)
def test_validation_list(self): """ensure the behavior of the `validation:list` page (with filters)""" text = 'Ceci est un éléphant' tuto_not_reserved = PublishableContentFactory( type='TUTORIAL', author_list=[self.user_author]) tuto_reserved = PublishableContentFactory( type='TUTORIAL', author_list=[self.user_author]) article_not_reserved = PublishableContentFactory( type='ARTICLE', author_list=[self.user_author]) article_reserved = PublishableContentFactory( type='ARTICLE', author_list=[self.user_author]) all_contents = [ tuto_not_reserved, tuto_reserved, article_not_reserved, article_reserved ] reserved_contents = [tuto_reserved, article_reserved] # apply a filter to test category filter subcat = SubCategoryFactory() article_reserved.subcategory.add(subcat) article_reserved.save() # send in validation for content in all_contents: v = ValidationFactory(content=content, status='PENDING') v.date_proposition = datetime.datetime.now() v.version = content.sha_draft v.comment_authors = text if content in reserved_contents: v.validator = self.user_staff v.date_reserve = datetime.datetime.now() v.status = 'PENDING_V' v.save() # first, test access for public result = self.client.get(reverse('validation:list'), follow=False) self.assertEqual(result.status_code, 302) # get 302 → redirection to login # connect with author: self.assertEqual( self.client.login(username=self.user_author.username, password='******'), True) result = self.client.get(reverse('validation:list'), follow=False) self.assertEqual(result.status_code, 403) # get 403 not allowed self.client.logout() # connect with staff: self.assertEqual( self.client.login(username=self.user_staff.username, password='******'), True) response = self.client.get(reverse('validation:list'), follow=False) self.assertEqual(response.status_code, 200) # OK validations = response.context['validations'] self.assertEqual(len(validations), 4) # a total of 4 contents in validation # test filters response = self.client.get(reverse('validation:list') + '?type=article', follow=False) self.assertEqual(response.status_code, 200) # OK validations = response.context['validations'] self.assertEqual(len(validations), 2) # 2 articles response = self.client.get(reverse('validation:list') + '?type=tuto', follow=False) self.assertEqual(response.status_code, 200) # OK validations = response.context['validations'] self.assertEqual(len(validations), 2) # 2 articles response = self.client.get(reverse('validation:list') + '?type=orphan', follow=False) self.assertEqual(response.status_code, 200) # OK validations = response.context['validations'] self.assertEqual(len(validations), 2) # 2 not-reserved content for validation in validations: self.assertFalse(validation.content in reserved_contents) response = self.client.get(reverse('validation:list') + '?type=reserved', follow=False) self.assertEqual(response.status_code, 200) # OK validations = response.context['validations'] self.assertEqual(len(validations), 2) # 2 reserved content for validation in validations: self.assertTrue(validation.content in reserved_contents) response = self.client.get(reverse('validation:list') + '?subcategory={}'.format(subcat.pk), follow=False) self.assertEqual(response.status_code, 200) # OK validations = response.context['validations'] self.assertEqual(len(validations), 1) # 1 content with this category self.assertEqual(validations[0].content, article_reserved) # the right content
def test_ignore_opinion(self): opinion = PublishableContentFactory(type='OPINION') opinion.authors.add(self.user_author) UserGalleryFactory(gallery=opinion.gallery, user=self.user_author, mode='W') opinion.licence = self.licence opinion.save() opinion_draft = opinion.load_version() ExtractFactory(container=opinion_draft, db_object=opinion) ExtractFactory(container=opinion_draft, db_object=opinion) self.assertEqual( self.client.login(username=self.user_author.username, password='******'), True) # publish result = self.client.post(reverse('validation:publish-opinion', kwargs={ 'pk': opinion.pk, 'slug': opinion.slug }), { 'source': '', 'version': opinion_draft.current_version }, follow=False) self.assertEqual(result.status_code, 302) # ignore with author => 403 result = self.client.post(reverse('validation:ignore-opinion', kwargs={ 'pk': opinion.pk, 'slug': opinion.slug }), { 'operation': 'NO_PICK', }, follow=False) self.assertEqual(result.status_code, 403) # now, login as staff self.assertEqual( self.client.login(username=self.user_staff.username, password='******'), True) # check that the opinion is displayed result = self.client.get(reverse('validation:list-opinion')) self.assertContains(result, opinion.title) # ignore the opinion result = self.client.post(reverse('validation:ignore-opinion', kwargs={ 'pk': opinion.pk, 'slug': opinion.slug }), { 'operation': 'NO_PICK', }, follow=False) self.assertEqual(result.status_code, 200) # check that the opinion is not displayed result = self.client.get(reverse('validation:list-opinion')) self.assertNotContains(result, opinion.title) # publish the opinion again result = self.client.post(reverse('validation:publish-opinion', kwargs={ 'pk': opinion.pk, 'slug': opinion.slug }), { 'source': '', 'version': opinion_draft.current_version }, follow=False) self.assertEqual(result.status_code, 302) # check that the opinion is displayed result = self.client.get(reverse('validation:list-opinion')) self.assertContains(result, opinion.title) # reject it result = self.client.post(reverse('validation:ignore-opinion', kwargs={ 'pk': opinion.pk, 'slug': opinion.slug }), { 'operation': 'REJECT', }, follow=False) self.assertEqual(result.status_code, 200) # publish again result = self.client.post(reverse('validation:publish-opinion', kwargs={ 'pk': opinion.pk, 'slug': opinion.slug }), { 'source': '', 'version': opinion_draft.current_version }, follow=False) self.assertEqual(result.status_code, 302) # check that the opinion is not displayed result = self.client.get(reverse('validation:list-opinion')) self.assertNotContains(result, opinion.title)
def test_defenitely_unpublish_alerted_opinion(self): opinion = PublishableContentFactory(type='OPINION') opinion.authors.add(self.user_author) UserGalleryFactory(gallery=opinion.gallery, user=self.user_author, mode='W') opinion.licence = self.licence opinion.save() opinion_draft = opinion.load_version() ExtractFactory(container=opinion_draft, db_object=opinion) ExtractFactory(container=opinion_draft, db_object=opinion) self.assertEqual( self.client.login(username=self.user_author.username, password='******'), True) # publish result = self.client.post(reverse('validation:publish-opinion', kwargs={ 'pk': opinion.pk, 'slug': opinion.slug }), { 'source': '', 'version': opinion_draft.current_version }, follow=False) self.assertEqual(result.status_code, 302) # login as staff self.assertEqual( self.client.login(username=self.user_staff.username, password='******'), True) alerter = ProfileFactory().user Alert.objects.create( author=alerter, scope='CONTENT', content=opinion, pubdate=datetime.datetime.now(), text="J'ai un probleme avec cette opinion : c'est pas la mienne.") # unpublish opinion result = self.client.post(reverse('validation:ignore-opinion', kwargs={ 'pk': opinion.pk, 'slug': opinion.slug }), { 'operation': 'REMOVE_PUB', }, follow=False) self.assertEqual(result.status_code, 200) # refresh opinion = PublishableContent.objects.get(pk=opinion.pk) # check that the opinion is not published self.assertFalse(opinion.in_public()) # check that it's impossible to publish the opinion again result = self.client.get(opinion.get_absolute_url()) self.assertContains(result, _('Billet modéré')) # front result = self.client.post(reverse('validation:publish-opinion', kwargs={ 'pk': opinion.pk, 'slug': opinion.slug }), { 'source': '', 'version': opinion_draft.current_version }, follow=False) self.assertEqual(result.status_code, 403) # back self.assertTrue(Alert.objects.filter(content=opinion).last().solved) # check alert page is still accessible and our alert is well displayed resp = self.client.get(reverse('pages-alerts')) self.assertEqual(200, resp.status_code) self.assertEqual(0, len(resp.context['alerts'])) self.assertEqual(1, len(resp.context['solved']))
class ContentNotification(TestCase, TutorialTestMixin): def setUp(self): # don't build PDF to speed up the tests overridden_zds_app['content']['build_pdf_when_published'] = False self.overridden_zds_app = overridden_zds_app self.user1 = ProfileFactory().user self.user2 = ProfileFactory().user # create a tutorial self.tuto = PublishableContentFactory(type='TUTORIAL') self.tuto.authors.add(self.user1) UserGalleryFactory(gallery=self.tuto.gallery, user=self.user1, mode='W') self.tuto.licence = LicenceFactory() self.tuto.subcategory.add(SubCategoryFactory()) self.tuto.save() tuto_draft = self.tuto.load_version() # then, publish it ! version = tuto_draft.current_version self.published = publish_content(self.tuto, tuto_draft, is_major_update=True) self.tuto.sha_public = version self.tuto.sha_draft = version self.tuto.public_version = self.published self.tuto.save() self.assertTrue( self.client.login(username=self.user1.username, password='******')) def test_no_persistant_notif_on_revoke(self): from zds.tutorialv2.publication_utils import unpublish_content NewPublicationSubscription.objects.get_or_create_active( self.user1, self.user2) content = PublishedContentFactory(author_list=[self.user2]) notif_signals.new_content.send(sender=self.tuto.__class__, instance=content, by_email=False) self.assertEqual( 1, len(Notification.objects.get_notifications_of(self.user1))) unpublish_content(content) self.assertEqual( 0, len(Notification.objects.get_notifications_of(self.user1))) def test_only_one_notif_on_update(self): NewPublicationSubscription.objects.get_or_create_active( self.user1, self.user2) content = PublishedContentFactory(author_list=[self.user2]) notify_update(content, False, True) versioned = content.load_version() content.sha_draft = versioned.repo_update(introduction='new intro', conclusion='new conclusion', title=versioned.title) content.save(force_slug_update=False) publish_content(content, content.load_version(), True) notify_update(content, True, False) notifs = interventions_topics(self.user1) self.assertEqual(1, len(notifs), str(notifs)) def test_only_one_notif_on_major_update(self): NewPublicationSubscription.objects.get_or_create_active( self.user1, self.user2) content = PublishedContentFactory(author_list=[self.user2]) notify_update(content, False, True) versioned = content.load_version() content.sha_draft = versioned.repo_update(introduction='new intro', conclusion='new conclusion', title=versioned.title) content.save(force_slug_update=False) publish_content(content, content.load_version(), True) notify_update(content, True, True) notifs = interventions_topics(self.user1) self.assertEqual(1, len(notifs), str(notifs))
def test_unregister(self): """ To test that unregistering user is working. """ # test not logged user can't unregister. self.client.logout() result = self.client.post( reverse('member-unregister'), follow=False) self.assertEqual(result.status_code, 302) # test logged user can register. user = ProfileFactory() login_check = self.client.login( username=user.user.username, password='******') self.assertEqual(login_check, True) result = self.client.post( reverse('member-unregister'), follow=False) self.assertEqual(result.status_code, 302) self.assertEqual(User.objects.filter(username=user.user.username).count(), 0) # Attach a user at tutorials, articles, topics and private topics. After that, # unregister this user and check that he is well removed in all contents. user = ProfileFactory() user2 = ProfileFactory() alone_gallery = GalleryFactory() UserGalleryFactory(gallery=alone_gallery, user=user.user) shared_gallery = GalleryFactory() UserGalleryFactory(gallery=shared_gallery, user=user.user) UserGalleryFactory(gallery=shared_gallery, user=user2.user) # first case : a published tutorial with only one author published_tutorial_alone = PublishedContentFactory(type='TUTORIAL') published_tutorial_alone.authors.add(user.user) published_tutorial_alone.save() # second case : a published tutorial with two authors published_tutorial_2 = PublishedContentFactory(type='TUTORIAL') published_tutorial_2.authors.add(user.user) published_tutorial_2.authors.add(user2.user) published_tutorial_2.save() # third case : a private tutorial with only one author writing_tutorial_alone = PublishableContentFactory(type='TUTORIAL') writing_tutorial_alone.authors.add(user.user) writing_tutorial_alone.save() writing_tutorial_alone_galler_path = writing_tutorial_alone.gallery.get_gallery_path() # fourth case : a private tutorial with at least two authors writing_tutorial_2 = PublishableContentFactory(type='TUTORIAL') writing_tutorial_2.authors.add(user.user) writing_tutorial_2.authors.add(user2.user) writing_tutorial_2.save() self.client.login(username=self.staff.username, password="******") # same thing for articles published_article_alone = PublishedContentFactory(type='ARTICLE') published_article_alone.authors.add(user.user) published_article_alone.save() published_article_2 = PublishedContentFactory(type='ARTICLE') published_article_2.authors.add(user.user) published_article_2.authors.add(user2.user) published_article_2.save() writing_article_alone = PublishableContentFactory(type='ARTICLE') writing_article_alone.authors.add(user.user) writing_article_alone.save() writing_article_2 = PublishableContentFactory(type='ARTICLE') writing_article_2.authors.add(user.user) writing_article_2.authors.add(user2.user) writing_article_2.save() # beta content beta_forum = ForumFactory(category=CategoryFactory()) beta_content = BetaContentFactory(author_list=[user.user], forum=beta_forum) beta_content_2 = BetaContentFactory(author_list=[user.user, user2.user], forum=beta_forum) # about posts and topics authored_topic = TopicFactory(author=user.user, forum=self.forum11) answered_topic = TopicFactory(author=user2.user, forum=self.forum11) PostFactory(topic=answered_topic, author=user.user, position=2) edited_answer = PostFactory(topic=answered_topic, author=user.user, position=3) edited_answer.editor = user.user edited_answer.save() upvoted_answer = PostFactory(topic=answered_topic, author=user2.user, position=4) upvoted_answer.like += 1 upvoted_answer.save() CommentVote.objects.create(user=user.user, comment=upvoted_answer, positive=True) private_topic = PrivateTopicFactory(author=user.user) private_topic.participants.add(user2.user) private_topic.save() PrivatePostFactory(author=user.user, privatetopic=private_topic, position_in_topic=1) # login and unregister: login_check = self.client.login( username=user.user.username, password='******') self.assertEqual(login_check, True) result = self.client.post( reverse('member-unregister'), follow=False) self.assertEqual(result.status_code, 302) # check that the bot have taken authorship of tutorial: self.assertEqual(published_tutorial_alone.authors.count(), 1) self.assertEqual(published_tutorial_alone.authors.first().username, settings.ZDS_APP["member"]["external_account"]) self.assertFalse(os.path.exists(writing_tutorial_alone_galler_path)) self.assertEqual(published_tutorial_2.authors.count(), 1) self.assertEqual(published_tutorial_2.authors .filter(username=settings.ZDS_APP["member"]["external_account"]) .count(), 0) # check that published tutorials remain published and accessible self.assertIsNotNone(published_tutorial_2.public_version.get_prod_path()) self.assertTrue(os.path.exists(published_tutorial_2.public_version.get_prod_path())) self.assertIsNotNone(published_tutorial_alone.public_version.get_prod_path()) self.assertTrue(os.path.exists(published_tutorial_alone.public_version.get_prod_path())) self.assertEqual(self.client.get( reverse('tutorial:view', args=[ published_tutorial_alone.pk, published_tutorial_alone.slug]), follow=False).status_code, 200) self.assertEqual(self.client.get( reverse('tutorial:view', args=[ published_tutorial_2.pk, published_tutorial_2.slug]), follow=False).status_code, 200) # test that published articles remain accessible self.assertTrue(os.path.exists(published_article_alone.public_version.get_prod_path())) self.assertEqual(self.client.get( reverse( 'article:view', args=[ published_article_alone.pk, published_article_alone.slug]), follow=True).status_code, 200) self.assertEqual(self.client.get( reverse( 'article:view', args=[ published_article_2.pk, published_article_2.slug]), follow=True).status_code, 200) # check that the tutorial for which the author was alone does not exists anymore self.assertEqual(PublishableContent.objects.filter(pk=writing_tutorial_alone.pk).count(), 0) self.assertFalse(os.path.exists(writing_tutorial_alone.get_repo_path())) # check that bot haven't take the authorship of the tuto with more than one author self.assertEqual(writing_tutorial_2.authors.count(), 1) self.assertEqual(writing_tutorial_2.authors .filter(username=settings.ZDS_APP["member"]["external_account"]) .count(), 0) # authorship for the article for which user was the only author self.assertEqual(published_article_alone.authors.count(), 1) self.assertEqual(published_article_alone.authors .first().username, settings.ZDS_APP["member"]["external_account"]) self.assertEqual(published_article_2.authors.count(), 1) self.assertEqual(PublishableContent.objects.filter(pk=writing_article_alone.pk).count(), 0) self.assertFalse(os.path.exists(writing_article_alone.get_repo_path())) # not bot if another author: self.assertEqual(published_article_2.authors .filter(username=settings.ZDS_APP["member"]["external_account"]).count(), 0) self.assertEqual(writing_article_2.authors.count(), 1) self.assertEqual(writing_article_2.authors .filter(username=settings.ZDS_APP["member"]["external_account"]).count(), 0) # topics, gallery and PMs: self.assertEqual(Topic.objects.filter(author__username=user.user.username).count(), 0) self.assertEqual(Post.objects.filter(author__username=user.user.username).count(), 0) self.assertEqual(Post.objects.filter(editor__username=user.user.username).count(), 0) self.assertEqual(PrivatePost.objects.filter(author__username=user.user.username).count(), 0) self.assertEqual(PrivateTopic.objects.filter(author__username=user.user.username).count(), 0) self.assertIsNotNone(Topic.objects.get(pk=authored_topic.pk)) self.assertIsNotNone(PrivateTopic.objects.get(pk=private_topic.pk)) self.assertIsNotNone(Gallery.objects.get(pk=alone_gallery.pk)) self.assertEquals(alone_gallery.get_linked_users().count(), 1) self.assertEquals(shared_gallery.get_linked_users().count(), 1) self.assertEquals(UserGallery.objects.filter(user=user.user).count(), 0) self.assertEquals(CommentVote.objects.filter(user=user.user, positive=True).count(), 0) self.assertEquals(Post.objects.filter(pk=upvoted_answer.id).first().like, 0) # zep 12, published contents and beta self.assertIsNotNone(PublishedContent.objects.filter(content__pk=published_tutorial_alone.pk).first()) self.assertIsNotNone(PublishedContent.objects.filter(content__pk=published_tutorial_2.pk).first()) self.assertTrue(Topic.objects.get(pk=beta_content.beta_topic.pk).is_locked) self.assertFalse(Topic.objects.get(pk=beta_content_2.beta_topic.pk).is_locked)
class InterventionsTest(TestCase): """ This test uses quite complicated paths to check number of notifications: 1. Create private topics and do stuff with them 2. User signs in 3. Render the home page 4. Check the number of unread private messages on home page source code This because a correct test of this function requires a complete context (or it behaves strangely) """ def setUp(self): self.licence = LicenceFactory() self.subcategory = SubCategoryFactory() self.author = ProfileFactory() self.user = ProfileFactory() self.staff = StaffProfileFactory() self.tuto = PublishableContentFactory(type='TUTORIAL') self.tuto.authors.add(self.author.user) self.tuto.licence = self.licence self.tuto.subcategory.add(self.subcategory) self.tuto.save() self.validation = Validation( content=self.tuto, version=self.tuto.sha_draft, comment_authors='bla', date_proposition=datetime.now(), ) self.validation.save() self.topic = send_mp(author=self.author.user, users=[], title='Title', text='Testing', subtitle='', leave=False) self.topic.participants.add(self.user.user) send_message_mp(self.user.user, self.topic, 'Testing') # humane_delta test periods = ((1, 0), (2, 1), (3, 7), (4, 30), (5, 360)) cont = dict() cont['date_today'] = periods[0][0] cont['date_yesterday'] = periods[1][0] cont['date_last_week'] = periods[2][0] cont['date_last_month'] = periods[3][0] cont['date_last_year'] = periods[4][0] self.context = Context(cont) def test_interventions_privatetopics(self): self.assertTrue( self.client.login(username=self.author.user.username, password='******')) response = self.client.post(reverse('homepage')) self.assertEqual(200, response.status_code) self.assertContains(response, '<span class="notif-count">1</span>', html=True) self.client.logout() self.assertTrue( self.client.login(username=self.user.user.username, password='******')) response = self.client.post(reverse('homepage')) self.assertEqual(200, response.status_code) self.assertContains(response, '<span class="notif-count">1</span>', html=True) def test_interventions_privatetopics_author_leave(self): # profile1 (author) leave topic move = self.topic.participants.first() self.topic.author = move self.topic.participants.remove(move) self.topic.save() self.assertTrue( self.client.login(username=self.user.user.username, password='******')) response = self.client.post(reverse('homepage')) self.assertEqual(200, response.status_code) self.assertContains(response, '<span class="notif-count">1</span>', html=True) def test_interventions_waiting_contents(self): # Login as staff self.assertTrue( self.client.login(username=self.staff.user.username, password='******')) # check that the number of waiting tutorials is correct response = self.client.post(reverse('homepage')) self.assertEqual(200, response.status_code) self.assertContains(response, '(1)') # Mark the content as reserved self.validation.status = 'PENDING_V' self.validation.save() # and check that the count was removed response = self.client.post(reverse('homepage')) self.assertEqual(200, response.status_code) self.assertNotContains(response, '(1)') def test_interventions_humane_delta(self): tr = Template('{% load interventions %}' '{{ date_today|humane_delta }}').render(self.context) self.assertEqual('Aujourd'hui', tr) tr = Template('{% load interventions %}' '{{ date_yesterday|humane_delta }}').render(self.context) self.assertEqual('Hier', tr) tr = Template('{% load interventions %}' '{{ date_last_week|humane_delta }}').render(self.context) self.assertEqual('Les 7 derniers jours', tr) tr = Template('{% load interventions %}' '{{ date_last_month|humane_delta }}').render( self.context) self.assertEqual('Les 30 derniers jours', tr) tr = Template('{% load interventions %}' '{{ date_last_year|humane_delta }}').render(self.context) self.assertEqual('Plus ancien', tr)
class ContentTests(TestCase): def setUp(self): # don't build PDF to speed up the tests overridden_zds_app['content']['build_pdf_when_published'] = False settings.EMAIL_BACKEND = 'django.core.mail.backends.locmem.EmailBackend' self.mas = ProfileFactory().user overridden_zds_app['member']['bot_account'] = self.mas.username self.licence = LicenceFactory() self.user_author = ProfileFactory().user self.staff = StaffProfileFactory().user self.tuto = PublishableContentFactory(type='TUTORIAL') self.tuto.authors.add(self.user_author) UserGalleryFactory(gallery=self.tuto.gallery, user=self.user_author, mode='W') self.tuto.licence = self.licence self.tuto.save() self.tuto_draft = self.tuto.load_version() self.part1 = ContainerFactory(parent=self.tuto_draft, db_object=self.tuto) self.chapter1 = ContainerFactory(parent=self.part1, db_object=self.tuto) self.extract1 = ExtractFactory(container=self.chapter1, db_object=self.tuto) def test_workflow_content(self): """ General tests for a content """ # ensure the usability of manifest versioned = self.tuto.load_version() self.assertEqual(self.tuto_draft.title, versioned.title) self.assertEqual(self.part1.title, versioned.children[0].title) self.assertEqual(self.extract1.title, versioned.children[0].children[0].children[0].title) # ensure url resolution project using dictionary: self.assertTrue(self.part1.slug in list(versioned.children_dict.keys())) self.assertTrue(self.chapter1.slug in versioned.children_dict[self.part1.slug].children_dict) def test_slug_pool(self): versioned = self.tuto.load_version() for i in [1, 2, 3]: slug = 'introduction-' + str(i) self.assertEqual(slug, versioned.get_unique_slug('introduction')) self.assertTrue(slug in versioned.slug_pool) def test_ensure_unique_slug(self): """ Ensure that slugs for a container or extract are always unique """ # get draft version versioned = self.tuto.load_version() # forbidden slugs: slug_to_test = ['introduction', 'conclusion'] for slug in slug_to_test: new_slug = versioned.get_unique_slug(slug) self.assertNotEqual(slug, new_slug) self.assertTrue(new_slug in versioned.slug_pool) # ensure new slugs are in slug pool # then test with 'real' containers and extracts: new_chapter_1 = ContainerFactory(title='aa', parent=versioned, db_object=self.tuto) new_chapter_2 = ContainerFactory(title='aa', parent=versioned, db_object=self.tuto) self.assertNotEqual(new_chapter_1.slug, new_chapter_2.slug) new_extract_1 = ExtractFactory(title='aa', container=new_chapter_1, db_object=self.tuto) self.assertEqual(new_extract_1.slug, new_chapter_1.slug) # different level can have the same slug! new_extract_2 = ExtractFactory(title='aa', container=new_chapter_2, db_object=self.tuto) self.assertEqual(new_extract_2.slug, new_extract_1.slug) # not the same parent, so allowed new_extract_3 = ExtractFactory(title='aa', container=new_chapter_1, db_object=self.tuto) self.assertNotEqual(new_extract_3.slug, new_extract_1.slug) # same parent, forbidden def test_ensure_unique_slug_2(self): """This test is an extension of the previous one, with the manifest reloaded each time""" title = "Il existe des gens que la ZEP-12 n'aime pas" random = "... Mais c'est pas censé arriver, donc on va tout faire pour que ça disparaisse !" # get draft version versioned = self.tuto.load_version() # add containers version = versioned.repo_add_container(title, random, random) new_version = self.tuto.load_version(sha=version) self.assertEqual(new_version.children[-1].slug, versioned.children[-1].slug) slugs = [new_version.children[-1].slug] for i in range(0, 2): # will add 3 new container version = versioned.repo_add_container(title, random, random) new_version = self.tuto.load_version(sha=version) self.assertEqual(new_version.children[-1].slug, versioned.children[-1].slug) self.assertTrue(new_version.children[-1].slug not in slugs) # slug is different self.assertTrue(versioned.children[-1].slug not in slugs) slugs.append(new_version.children[-1].slug) # add extracts extract_title = "On va changer de titre (parce qu'on sais jamais) !" chapter = versioned.children[-1] # for this second test, the last chapter will be used version = chapter.repo_add_extract(extract_title, random) new_version = self.tuto.load_version(sha=version) self.assertEqual(new_version.children[-1].children[-1].slug, chapter.children[-1].slug) slugs = [new_version.children[-1].children[-1].slug] for i in range(0, 2): # will add 3 new extracts with the same title version = chapter.repo_add_extract(extract_title, random) new_version = self.tuto.load_version(sha=version) self.assertTrue(new_version.children[-1].children[-1].slug not in slugs) self.assertTrue(chapter.children[-1].slug not in slugs) slugs.append(new_version.children[-1].children[-1].slug) def test_workflow_repository(self): """ Test to ensure the behavior of repo_*() functions: - if they change the filesystem as they are suppose to ; - if they change the `self.sha_*` as they are suppose to. """ new_title = 'Un nouveau titre' other_new_title = 'Un titre différent' random_text = "J'ai faim!" other_random_text = 'Oh, du chocolat <3' versioned = self.tuto.load_version() current_version = versioned.current_version slug_repository = versioned.slug_repository # VersionedContent: old_path = versioned.get_path() self.assertTrue(os.path.isdir(old_path)) new_slug = versioned.get_unique_slug(new_title) # normally, you get a new slug by asking database! versioned.repo_update_top_container(new_title, new_slug, random_text, random_text) self.assertNotEqual(versioned.sha_draft, current_version) self.assertNotEqual(versioned.current_version, current_version) self.assertEqual(versioned.current_version, versioned.sha_draft) current_version = versioned.current_version new_path = versioned.get_path() self.assertNotEqual(old_path, new_path) self.assertTrue(os.path.isdir(new_path)) self.assertFalse(os.path.isdir(old_path)) self.assertNotEqual(slug_repository, versioned.slug_repository) # if this test fail, you're in trouble # Container: # 1. add new part: versioned.repo_add_container(new_title, random_text, random_text) self.assertNotEqual(versioned.sha_draft, current_version) self.assertNotEqual(versioned.current_version, current_version) self.assertEqual(versioned.current_version, versioned.sha_draft) current_version = versioned.current_version part = versioned.children[-1] old_path = part.get_path() self.assertTrue(os.path.isdir(old_path)) self.assertTrue(os.path.exists(os.path.join(versioned.get_path(), part.introduction))) self.assertTrue(os.path.exists(os.path.join(versioned.get_path(), part.conclusion))) self.assertEqual(part.get_introduction(), random_text) self.assertEqual(part.get_conclusion(), random_text) # 2. update the part part.repo_update(other_new_title, other_random_text, other_random_text) self.assertNotEqual(versioned.sha_draft, current_version) self.assertNotEqual(versioned.current_version, current_version) self.assertEqual(versioned.current_version, versioned.sha_draft) current_version = versioned.current_version new_path = part.get_path() self.assertNotEqual(old_path, new_path) self.assertTrue(os.path.isdir(new_path)) self.assertFalse(os.path.isdir(old_path)) self.assertEqual(part.get_introduction(), other_random_text) self.assertEqual(part.get_conclusion(), other_random_text) # 3. delete it part.repo_delete() # boom! self.assertNotEqual(versioned.sha_draft, current_version) self.assertNotEqual(versioned.current_version, current_version) self.assertEqual(versioned.current_version, versioned.sha_draft) current_version = versioned.current_version self.assertFalse(os.path.isdir(new_path)) # Extract: # 1. add new extract versioned.repo_add_container(new_title, random_text, random_text) # need to add a new part before part = versioned.children[-1] part.repo_add_extract(new_title, random_text) self.assertNotEqual(versioned.sha_draft, current_version) self.assertNotEqual(versioned.current_version, current_version) self.assertEqual(versioned.current_version, versioned.sha_draft) current_version = versioned.current_version extract = part.children[-1] old_path = extract.get_path() self.assertTrue(os.path.isfile(old_path)) self.assertEqual(extract.get_text(), random_text) # 2. update extract extract.repo_update(other_new_title, other_random_text) self.assertNotEqual(versioned.sha_draft, current_version) self.assertNotEqual(versioned.current_version, current_version) self.assertEqual(versioned.current_version, versioned.sha_draft) current_version = versioned.current_version new_path = extract.get_path() self.assertNotEqual(old_path, new_path) self.assertTrue(os.path.isfile(new_path)) self.assertFalse(os.path.isfile(old_path)) self.assertEqual(extract.get_text(), other_random_text) # 3. update parent and see if it still works: part.repo_update(other_new_title, other_random_text, other_random_text) old_path = new_path new_path = extract.get_path() self.assertNotEqual(old_path, new_path) self.assertTrue(os.path.isfile(new_path)) self.assertFalse(os.path.isfile(old_path)) self.assertEqual(extract.get_text(), other_random_text) # 4. Boom, no more extract extract.repo_delete() self.assertNotEqual(versioned.sha_draft, current_version) self.assertNotEqual(versioned.current_version, current_version) self.assertEqual(versioned.current_version, versioned.sha_draft) self.assertFalse(os.path.exists(new_path)) def test_if_none(self): """Test the case where introduction and conclusion are `None`""" given_title = "La vie secrète de Clem'" some_text = 'Tous ces secrets (ou pas)' versioned = self.tuto.load_version() # add a new part with `None` for intro and conclusion version = versioned.repo_add_container(given_title, None, None) # check on the model: new_part = versioned.children[-1] self.assertIsNone(new_part.introduction) self.assertIsNone(new_part.conclusion) # it remains when loading the manifest! versioned2 = self.tuto.load_version(sha=version) self.assertIsNotNone(versioned2) self.assertIsNone(versioned.children[-1].introduction) self.assertIsNone(versioned.children[-1].conclusion) version = new_part.repo_update(given_title, None, None) # still `None` self.assertIsNone(new_part.introduction) self.assertIsNone(new_part.conclusion) # does it still remains? versioned2 = self.tuto.load_version(sha=version) self.assertIsNotNone(versioned2) self.assertIsNone(versioned.children[-1].introduction) self.assertIsNone(versioned.children[-1].conclusion) new_part.repo_update(given_title, some_text, some_text) self.assertIsNotNone(new_part.introduction) # now, value given self.assertIsNotNone(new_part.conclusion) old_intro = new_part.introduction old_conclu = new_part.conclusion self.assertTrue(os.path.isfile(os.path.join(versioned.get_path(), old_intro))) self.assertTrue(os.path.isfile(os.path.join(versioned.get_path(), old_conclu))) # when loaded the manifest, not None, this time versioned2 = self.tuto.load_version(sha=version) self.assertIsNotNone(versioned2) self.assertIsNotNone(versioned.children[-1].introduction) self.assertIsNotNone(versioned.children[-1].conclusion) version = new_part.repo_update(given_title, None, None) # and we go back to `None` self.assertIsNone(new_part.introduction) self.assertIsNone(new_part.conclusion) self.assertFalse(os.path.isfile(os.path.join(versioned.get_path(), old_intro))) # introduction is deleted self.assertFalse(os.path.isfile(os.path.join(versioned.get_path(), old_conclu))) # does it go back to None? versioned2 = self.tuto.load_version(sha=version) self.assertIsNotNone(versioned2) self.assertIsNone(versioned.children[-1].introduction) self.assertIsNone(versioned.children[-1].conclusion) new_part.repo_update(given_title, '', '') # '' is not None self.assertIsNotNone(new_part.introduction) self.assertIsNotNone(new_part.conclusion) def test_extract_is_none(self): """Test the case of a null extract""" article = PublishableContentFactory(type='ARTICLE') versioned = article.load_version() given_title = 'Peu importe, en fait, ça compte peu' some_text = 'Disparaitra aussi vite que possible' # add a new extract with `None` for text version = versioned.repo_add_extract(given_title, None) # check on the model: new_extract = versioned.children[-1] self.assertIsNone(new_extract.text) # it remains when loading the manifest! versioned2 = article.load_version(sha=version) self.assertIsNotNone(versioned2) self.assertIsNone(versioned.children[-1].text) version = new_extract.repo_update(given_title, None) self.assertIsNone(new_extract.text) # it remains versioned2 = article.load_version(sha=version) self.assertIsNotNone(versioned2) self.assertIsNone(versioned.children[-1].text) version = new_extract.repo_update(given_title, some_text) self.assertIsNotNone(new_extract.text) self.assertEqual(some_text, new_extract.get_text()) # now it changes versioned2 = article.load_version(sha=version) self.assertIsNotNone(versioned2) self.assertIsNotNone(versioned.children[-1].text) # ... and lets go back version = new_extract.repo_update(given_title, None) self.assertIsNone(new_extract.text) # it has changed versioned2 = article.load_version(sha=version) self.assertIsNotNone(versioned2) self.assertIsNone(versioned.children[-1].text) def test_ensure_slug_stay(self): """This test ensures that slugs are not modified when coming from a manifest""" tuto = PublishableContentFactory(type='TUTORIAL') versioned = tuto.load_version() random = 'Non, piti bug, tu ne reviendras plus !!!' title = "N'importe quel titre" # add three container with the same title versioned.repo_add_container(title, random, random) # x versioned.repo_add_container(title, random, random) # x-1 version = versioned.repo_add_container(title, random, random) # x-2 self.assertEqual(len(versioned.children), 3) current = tuto.load_version(sha=version) self.assertEqual(len(current.children), 3) for index, child in enumerate(current.children): self.assertEqual(child.slug, versioned.children[index].slug) # same order # then, delete the second one: last_slug = versioned.children[2].slug version = versioned.children[1].repo_delete() self.assertEqual(len(versioned.children), 2) self.assertEqual(versioned.children[1].slug, last_slug) current = tuto.load_version(sha=version) self.assertEqual(len(current.children), 2) for index, child in enumerate(current.children): self.assertEqual(child.slug, versioned.children[index].slug) # slug remains # same test with extracts chapter = versioned.children[0] chapter.repo_add_extract(title, random) # x chapter.repo_add_extract(title, random) # x-1 version = chapter.repo_add_extract(title, random) # x-2 self.assertEqual(len(chapter.children), 3) current = tuto.load_version(sha=version) self.assertEqual(len(current.children[0].children), 3) for index, child in enumerate(current.children[0].children): self.assertEqual(child.slug, chapter.children[index].slug) # slug remains # delete the second one! last_slug = chapter.children[2].slug version = chapter.children[1].repo_delete() self.assertEqual(len(chapter.children), 2) self.assertEqual(chapter.children[1].slug, last_slug) current = tuto.load_version(sha=version) self.assertEqual(len(current.children[0].children), 2) for index, child in enumerate(current.children[0].children): self.assertEqual(child.slug, chapter.children[index].slug) # slug remains for extract as well! def test_publication_and_attributes_consistency(self): pubdate = datetime.now() - timedelta(days=1) article = PublishedContentFactory(type='ARTICLE', author_list=[self.user_author]) public_version = article.public_version public_version.publication_date = pubdate public_version.save() # everything must come from database to have good datetime comparison article = PublishableContent.objects.get(pk=article.pk) article.public_version.load_public_version() old_date = article.public_version.publication_date old_title = article.public_version.title() old_description = article.public_version.description() article.licence = LicenceFactory() article.save() self.assertEqual( self.client.login( username=self.user_author.username, password='******'), True) self.client.post(reverse('content:edit', args=[article.pk, article.slug]), { 'title': old_title + 'bla', 'description': old_description + 'bla', 'type': 'ARTICLE', 'licence': article.licence.pk, 'subcategory': SubCategoryFactory().pk, 'last_hash': article.sha_draft }) article = PublishableContent.objects.prefetch_related('public_version').get(pk=article.pk) article.public_version.load_public_version() self.assertEqual(old_title, article.public_version.title()) self.assertEqual(old_description, article.public_version.description()) self.assertEqual(old_date, article.public_version.publication_date) publish_content(article, article.load_version(), False) article = PublishableContent.objects.get(pk=article.pk) article.public_version.load_public_version() self.assertEqual(old_date, article.public_version.publication_date) self.assertNotEqual(old_date, article.public_version.update_date) def test_add_tags(self): tuto = self.tuto tags_len = len(Tag.objects.all()) tuto_tags_len = len(tuto.tags.all()) # add 3 tags tags = ['a', 'b', 'c'] tuto.add_tags(tags) tags_len += 3 tuto_tags_len += 3 self.assertEqual(tags_len, len(Tag.objects.all())) self.assertEqual(tuto_tags_len, len(tuto.tags.all())) # add the same tags (nothing append) tags = ['a', 'b', 'c'] tuto.add_tags(tags) self.assertEqual(tags_len, len(Tag.objects.all())) self.assertEqual(tuto_tags_len, len(tuto.tags.all())) # add 2 more tags = ['d', 'e'] tuto.add_tags(tags) tags_len += 2 tuto_tags_len += 2 self.assertEqual(tags_len, len(Tag.objects.all())) self.assertEqual(tuto_tags_len, len(tuto.tags.all())) # add 3 with invalid content (only 2 valid) tags = ['f', 'g', ' '] tuto.add_tags(tags) tags_len += 2 tuto_tags_len += 2 self.assertEqual(tags_len, Tag.objects.count(), 'all tags are "{}"'.format('","'.join([str(t) for t in Tag.objects.all()]))) self.assertEqual(tuto_tags_len, len(tuto.tags.all())) # test space in tags (first and last space deleted) tags = ['foo bar', ' azerty', 'qwerty ', ' another tag '] tuto.add_tags(tags) tuto_tags_list = [tag['title'] for tag in tuto.tags.values('title')] self.assertIn('foo bar', tuto_tags_list) self.assertNotIn(' azerty', tuto_tags_list) self.assertIn('azerty', tuto_tags_list) self.assertNotIn('qwerty ', tuto_tags_list) self.assertIn('qwerty', tuto_tags_list) self.assertNotIn(' another tag', tuto_tags_list) self.assertIn('another tag', tuto_tags_list) @unittest.skip('The test seems to be incorrect in its way to count chars') def test_char_count_after_publication(self): """Test the ``get_char_count()`` function. Special care should be taken with this function, since: - The username of the author is, by default "Firmxxx" where "xxx" depends on the tests before ; - The titles (!) also contains a number that also depends on the number of tests before ; - The date is ``datetime.now()`` and contains the months, which is never a fixed number of letters. """ author = ProfileFactory().user author.username = '******' author.save() len_date_now = len(date(datetime.now(), 'd F Y')) article = PublishedContentFactory(type='ARTICLE', author_list=[author], title='Un titre') published = PublishedContent.objects.filter(content=article).first() self.assertEqual(published.get_char_count(), 160 + len_date_now) tuto = PublishableContentFactory(type='TUTORIAL', author_list=[author], title='Un titre') # add a chapter, so it becomes a middle tutorial tuto_draft = tuto.load_version() chapter1 = ContainerFactory(parent=tuto_draft, db_object=tuto, title='Un chapitre') ExtractFactory(container=chapter1, db_object=tuto, title='Un extrait') published = publish_content(tuto, tuto_draft, is_major_update=True) tuto.sha_public = tuto_draft.current_version tuto.sha_draft = tuto_draft.current_version tuto.public_version = published tuto.save() published = PublishedContent.objects.filter(content=tuto).first() self.assertEqual(published.get_char_count(), 335 + len_date_now) def test_ensure_gallery(self): content = PublishedContentFactory() content.authors.add(ProfileFactory().user) content.authors.add(ProfileFactory().user) content.save() content.ensure_author_gallery() self.assertEqual(UserGallery.objects.filter(gallery__pk=content.gallery.pk).count(), content.authors.count()) content.authors.add(ProfileFactory().user) content.save() content.ensure_author_gallery() self.assertEqual(UserGallery.objects.filter(gallery__pk=content.gallery.pk).count(), content.authors.count()) def tearDown(self): if os.path.isdir(overridden_zds_app['content']['repo_private_path']): shutil.rmtree(overridden_zds_app['content']['repo_private_path']) if os.path.isdir(overridden_zds_app['content']['repo_public_path']): shutil.rmtree(overridden_zds_app['content']['repo_public_path']) if os.path.isdir(settings.MEDIA_ROOT): shutil.rmtree(settings.MEDIA_ROOT)
def _create_and_publish_type_in_subcategory(self, content_type, subcategory): tuto_1 = PublishableContentFactory(type=content_type, author_list=[self.user_author]) tuto_1.subcategory.add(subcategory) tuto_1.save() tuto_1_draft = tuto_1.load_version() publish_content(tuto_1, tuto_1_draft, is_major_update=True)
class ContentTests(TutorialTestMixin, TestCase): def setUp(self): self.staff = StaffProfileFactory().user settings.EMAIL_BACKEND = "django.core.mail.backends.locmem.EmailBackend" self.mas = ProfileFactory().user self.overridden_zds_app["member"]["bot_account"] = self.mas.username self.licence = LicenceFactory() self.subcategory = SubCategoryFactory() self.user_author = ProfileFactory().user self.user_staff = StaffProfileFactory().user self.user_guest = ProfileFactory().user self.tuto = PublishableContentFactory(type="TUTORIAL") self.tuto.authors.add(self.user_author) UserGalleryFactory(gallery=self.tuto.gallery, user=self.user_author, mode="W") self.tuto.licence = self.licence self.tuto.subcategory.add(self.subcategory) self.tuto.save() self.beta_forum = ForumFactory( pk=self.overridden_zds_app["forum"]["beta_forum_id"], category=ForumCategoryFactory(position=1), position_in_category=1, ) # ensure that the forum, for the beta versions, is created self.tuto_draft = self.tuto.load_version() self.part1 = ContainerFactory(parent=self.tuto_draft, db_object=self.tuto) self.chapter1 = ContainerFactory(parent=self.part1, db_object=self.tuto) self.extract1 = ExtractFactory(container=self.chapter1, db_object=self.tuto) bot = Group(name=self.overridden_zds_app["member"]["bot_group"]) bot.save() self.external = UserFactory( username=self.overridden_zds_app["member"]["external_account"], password="******") def test_public_lists(self): tutorial = PublishedContentFactory(author_list=[self.user_author]) tutorial_unpublished = PublishableContentFactory( author_list=[self.user_author]) article = PublishedContentFactory(author_list=[self.user_author], type="ARTICLE") article_unpublished = PublishableContentFactory( author_list=[self.user_author], type="ARTICLE") self.client.logout() resp = self.client.get(reverse("publication:list") + "?type=tutorial") self.assertContains(resp, tutorial.title) self.assertNotContains(resp, tutorial_unpublished.title) resp = self.client.get(reverse("publication:list") + "?type=article") self.assertContains(resp, article.title) self.assertNotContains(resp, article_unpublished.title) resp = self.client.get( reverse("tutorial:find-tutorial", args=[self.user_author.username]) + "?filter=public") self.assertContains(resp, tutorial.title) self.assertNotContains(resp, tutorial_unpublished.title) resp = self.client.get( reverse("tutorial:find-tutorial", args=[self.user_author.username]) + "?filter=redaction") self.assertEqual(resp.status_code, 403) resp = self.client.get( reverse("article:find-article", args=[self.user_author.username]) + "?filter=public") self.assertContains(resp, article.title) self.assertNotContains(resp, article_unpublished.title) resp = self.client.get( reverse("article:find-article", args=[self.user_author.username]) + "?filter=redaction") self.assertEqual(resp.status_code, 403) resp = self.client.get( reverse("article:find-article", args=[self.user_author.username]) + "?filter=chuck-norris") self.assertEqual(resp.status_code, 404) def _create_and_publish_type_in_subcategory(self, content_type, subcategory): tuto_1 = PublishableContentFactory(type=content_type, author_list=[self.user_author]) tuto_1.subcategory.add(subcategory) tuto_1.save() tuto_1_draft = tuto_1.load_version() tuto_1.public_version = publish_content(tuto_1, tuto_1_draft, is_major_update=True) tuto_1.save() def test_list_categories(self): category_1 = ContentCategoryFactory() subcategory_1 = SubCategoryFactory(category=category_1) subcategory_2 = SubCategoryFactory(category=category_1) # Not in context if nothing published inside this subcategory SubCategoryFactory(category=category_1) for _ in range(5): self._create_and_publish_type_in_subcategory( "TUTORIAL", subcategory_1) self._create_and_publish_type_in_subcategory( "ARTICLE", subcategory_2) self.client.logout() resp = self.client.get(reverse("publication:list")) context_categories = list(resp.context_data["categories"]) self.assertEqual(context_categories[0].contents_count, 10) self.assertEqual(context_categories[0].subcategories, [subcategory_1, subcategory_2]) self.assertEqual(context_categories, [category_1]) def test_private_lists(self): tutorial = PublishedContentFactory(author_list=[self.user_author]) tutorial_unpublished = PublishableContentFactory( author_list=[self.user_author]) article = PublishedContentFactory(author_list=[self.user_author], type="ARTICLE") article_unpublished = PublishableContentFactory( author_list=[self.user_author], type="ARTICLE") self.client.login(username=self.user_author.username, password="******") resp = self.client.get( reverse("tutorial:find-tutorial", args=[self.user_author.username])) self.assertContains(resp, tutorial.title) self.assertContains(resp, tutorial_unpublished.title) self.assertContains(resp, "content-illu") resp = self.client.get( reverse("article:find-article", args=[self.user_author.username])) self.assertContains(resp, article.title) self.assertContains(resp, article_unpublished.title) self.assertContains(resp, "content-illu") def test_validation_list(self): """ensure the behavior of the `validation:list` page (with filters)""" text = "Ceci est un éléphant" tuto_not_reserved = PublishableContentFactory( type="TUTORIAL", author_list=[self.user_author]) tuto_reserved = PublishableContentFactory( type="TUTORIAL", author_list=[self.user_author]) article_not_reserved = PublishableContentFactory( type="ARTICLE", author_list=[self.user_author]) article_reserved = PublishableContentFactory( type="ARTICLE", author_list=[self.user_author]) all_contents = [ tuto_not_reserved, tuto_reserved, article_not_reserved, article_reserved ] reserved_contents = [tuto_reserved, article_reserved] # apply a filter to test category filter subcat = SubCategoryFactory() article_reserved.subcategory.add(subcat) article_reserved.save() # send in validation for content in all_contents: v = ValidationFactory(content=content, status="PENDING") v.date_proposition = datetime.datetime.now() v.version = content.sha_draft v.comment_authors = text if content in reserved_contents: v.validator = self.user_staff v.date_reserve = datetime.datetime.now() v.status = "PENDING_V" v.save() # first, test access for public result = self.client.get(reverse("validation:list"), follow=False) self.assertEqual(result.status_code, 302) # get 302 → redirection to login # connect with author: self.assertEqual( self.client.login(username=self.user_author.username, password="******"), True) result = self.client.get(reverse("validation:list"), follow=False) self.assertEqual(result.status_code, 403) # get 403 not allowed self.client.logout() # connect with staff: self.assertEqual( self.client.login(username=self.user_staff.username, password="******"), True) response = self.client.get(reverse("validation:list"), follow=False) self.assertEqual(response.status_code, 200) # OK validations = response.context["validations"] self.assertEqual(len(validations), 4) # a total of 4 contents in validation # test filters response = self.client.get(reverse("validation:list") + "?type=article", follow=False) self.assertEqual(response.status_code, 200) # OK validations = response.context["validations"] self.assertEqual(len(validations), 2) # 2 articles response = self.client.get(reverse("validation:list") + "?type=tuto", follow=False) self.assertEqual(response.status_code, 200) # OK validations = response.context["validations"] self.assertEqual(len(validations), 2) # 2 articles response = self.client.get(reverse("validation:list") + "?type=orphan", follow=False) self.assertEqual(response.status_code, 200) # OK validations = response.context["validations"] self.assertEqual(len(validations), 2) # 2 not-reserved content for validation in validations: self.assertFalse(validation.content in reserved_contents) response = self.client.get(reverse("validation:list") + "?type=reserved", follow=False) self.assertEqual(response.status_code, 200) # OK validations = response.context["validations"] self.assertEqual(len(validations), 2) # 2 reserved content for validation in validations: self.assertTrue(validation.content in reserved_contents) response = self.client.get(reverse("validation:list") + "?subcategory={}".format(subcat.pk), follow=False) self.assertEqual(response.status_code, 200) # OK validations = response.context["validations"] self.assertEqual(len(validations), 1) # 1 content with this category self.assertEqual(validations[0].content, article_reserved) # the right content
class LastTutorialsFeedRSSTest(TutorialTestMixin, TestCase): def setUp(self): self.overridden_zds_app = overridden_zds_app # don't build PDF to speed up the tests overridden_zds_app["content"]["build_pdf_when_published"] = False self.staff = StaffProfileFactory().user settings.EMAIL_BACKEND = "django.core.mail.backends.locmem.EmailBackend" self.mas = ProfileFactory().user overridden_zds_app["member"]["bot_account"] = self.mas.username bot = Group(name=overridden_zds_app["member"]["bot_group"]) bot.save() self.external = UserFactory( username=overridden_zds_app["member"]["external_account"], password="******") self.beta_forum = ForumFactory( pk=overridden_zds_app["forum"]["beta_forum_id"], category=ForumCategoryFactory(position=1), position_in_category=1, ) # ensure that the forum, for the beta versions, is created self.licence = LicenceFactory() self.subcategory = SubCategoryFactory() self.tag = TagFactory() self.user_author = ProfileFactory().user self.user_staff = StaffProfileFactory().user self.user_guest = ProfileFactory().user # create a tutorial self.tuto = PublishableContentFactory(type="TUTORIAL") self.tuto.authors.add(self.user_author) UserGalleryFactory(gallery=self.tuto.gallery, user=self.user_author, mode="W") self.tuto.licence = self.licence self.tuto.subcategory.add(self.subcategory) self.tuto.tags.add(self.tag) self.tuto.save() # fill it with one part, containing one chapter, containing one extract self.tuto_draft = self.tuto.load_version() self.part1 = ContainerFactory(parent=self.tuto_draft, db_object=self.tuto) self.chapter1 = ContainerFactory(parent=self.part1, db_object=self.tuto) self.extract1 = ExtractFactory(container=self.chapter1, db_object=self.tuto) # then, publish it ! version = self.tuto_draft.current_version self.published = publish_content(self.tuto, self.tuto_draft, is_major_update=True) self.tuto.sha_public = version self.tuto.sha_draft = version self.tuto.public_version = self.published self.tuto.save() self.tutofeed = LastTutorialsFeedRSS() def test_is_well_setup(self): """ Test that base parameters are Ok """ self.assertEqual(self.tutofeed.link, "/tutoriels/") reftitle = "Tutoriels sur {}".format( overridden_zds_app["site"]["literal_name"]) self.assertEqual(self.tutofeed.title, reftitle) refdescription = "Les derniers tutoriels parus sur {}.".format( overridden_zds_app["site"]["literal_name"]) self.assertEqual(self.tutofeed.description, refdescription) atom = LastTutorialsFeedATOM() self.assertEqual(atom.subtitle, refdescription) def test_get_items(self): """ basic test sending back the tutorial """ ret = list(self.tutofeed.items()) self.assertEqual(ret[0].content, self.tuto) def test_get_pubdate(self): """ test the return value of pubdate """ ref = PublishedContent.objects.get( content__pk=self.tuto.pk).publication_date tuto = list(self.tutofeed.items())[0] ret = self.tutofeed.item_pubdate(item=tuto) self.assertEqual(ret.date(), ref.date()) def test_get_title(self): """ test the return value of title """ ref = self.tuto.title tuto = list(self.tutofeed.items())[0] ret = self.tutofeed.item_title(item=tuto) self.assertEqual(ret, ref) def test_get_description(self): """ test the return value of description """ ref = self.tuto.description tuto = list(self.tutofeed.items())[0] ret = self.tutofeed.item_description(item=tuto) self.assertEqual(ret, ref) def test_get_author_name(self): """ test the return value of author name """ ref = self.user_author.username tuto = list(self.tutofeed.items())[0] ret = self.tutofeed.item_author_name(item=tuto) self.assertEqual(ret, ref) def test_get_item_link(self): """ test the return value of item link """ ref = self.tuto.get_absolute_url_online() tuto = list(self.tutofeed.items())[0] ret = self.tutofeed.item_link(item=tuto) self.assertEqual(ret, ref) def test_filters(self): """ Test filtering by category & tag """ subcategory2 = SubCategoryFactory() subcategory3 = SubCategoryFactory() tag2 = TagFactory() tag3 = TagFactory() # Add a new tuto & publish it tuto2 = PublishableContentFactory(type="TUTORIAL") tuto2.authors.add(self.user_author) tuto2.licence = self.licence tuto2.subcategory.add(subcategory2) tuto2.tags.add(self.tag) tuto2.tags.add(tag2) tuto2.save() tuto2_draft = tuto2.load_version() tuto2.sha_public = tuto2.sha_draft = tuto2_draft.current_version tuto2.public_version = publish_content(tuto2, tuto2_draft, is_major_update=True) tuto2.save() # Default view ret = [item.content for item in self.tutofeed.items()] self.assertEqual(ret, [tuto2, self.tuto]) # Filter by subcategory self.tutofeed.query_params = {"subcategory": self.subcategory.slug} ret = [item.content for item in self.tutofeed.items()] self.assertEqual(ret, [self.tuto]) self.tutofeed.query_params = { "subcategory": f" {self.subcategory.slug} " } ret = [item.content for item in self.tutofeed.items()] self.assertEqual(ret, [self.tuto]) self.tutofeed.query_params = {"subcategory": subcategory2.slug} ret = [item.content for item in self.tutofeed.items()] self.assertEqual(ret, [tuto2]) self.tutofeed.query_params = {"subcategory": subcategory3.slug} ret = [item.content for item in self.tutofeed.items()] self.assertEqual(ret, []) self.tutofeed.query_params = {"subcategory": "invalid"} self.assertRaises(Http404, self.tutofeed.items) # Filter by tag self.tutofeed.query_params = {"tag": self.tag.slug} ret = [item.content for item in self.tutofeed.items()] self.assertEqual(ret, [tuto2, self.tuto]) self.tutofeed.query_params = {"tag": tag2.slug} ret = [item.content for item in self.tutofeed.items()] self.assertEqual(ret, [tuto2]) self.tutofeed.query_params = {"tag": f" {tag2.slug} "} ret = [item.content for item in self.tutofeed.items()] self.assertEqual(ret, [tuto2]) self.tutofeed.query_params = {"tag": tag3.slug} ret = [item.content for item in self.tutofeed.items()] self.assertEqual(ret, []) self.tutofeed.query_params = {"tag": "invalid"} self.assertRaises(Http404, self.tutofeed.items)
def test_ensure_slug_stay(self): """This test ensure that slug are not modified when coming from a manifest""" tuto = PublishableContentFactory(type='TUTORIAL') versioned = tuto.load_version() random = u'Non, piti bug, tu ne reviendra plus !!!' title = u'N\'importe quel titre' # add three container with the same title versioned.repo_add_container(title, random, random) # x versioned.repo_add_container(title, random, random) # x-1 version = versioned.repo_add_container(title, random, random) # x-2 self.assertEqual(len(versioned.children), 3) current = tuto.load_version(sha=version) self.assertEqual(len(current.children), 3) for index, child in enumerate(current.children): self.assertEqual(child.slug, versioned.children[index].slug) # same order # then, delete the second one: last_slug = versioned.children[2].slug version = versioned.children[1].repo_delete() self.assertEqual(len(versioned.children), 2) self.assertEqual(versioned.children[1].slug, last_slug) current = tuto.load_version(sha=version) self.assertEqual(len(current.children), 2) for index, child in enumerate(current.children): self.assertEqual(child.slug, versioned.children[index].slug) # slug remains # same test with extracts chapter = versioned.children[0] chapter.repo_add_extract(title, random) # x chapter.repo_add_extract(title, random) # x-1 version = chapter.repo_add_extract(title, random) # x-2 self.assertEqual(len(chapter.children), 3) current = tuto.load_version(sha=version) self.assertEqual(len(current.children[0].children), 3) for index, child in enumerate(current.children[0].children): self.assertEqual(child.slug, chapter.children[index].slug) # slug remains # delete the second one ! last_slug = chapter.children[2].slug version = chapter.children[1].repo_delete() self.assertEqual(len(chapter.children), 2) self.assertEqual(chapter.children[1].slug, last_slug) current = tuto.load_version(sha=version) self.assertEqual(len(current.children[0].children), 2) for index, child in enumerate(current.children[0].children): self.assertEqual(child.slug, chapter.children[index].slug ) # slug remains for extract as well !
class ContentTests(TestCase): def setUp(self): # don't build PDF to speed up the tests settings.ZDS_APP['content']['build_pdf_when_published'] = False settings.EMAIL_BACKEND = 'django.core.mail.backends.locmem.EmailBackend' self.mas = ProfileFactory().user settings.ZDS_APP['member']['bot_account'] = self.mas.username self.licence = LicenceFactory() self.user_author = ProfileFactory().user self.staff = StaffProfileFactory().user self.tuto = PublishableContentFactory(type='TUTORIAL') self.tuto.authors.add(self.user_author) UserGalleryFactory(gallery=self.tuto.gallery, user=self.user_author, mode='W') self.tuto.licence = self.licence self.tuto.save() self.tuto_draft = self.tuto.load_version() self.part1 = ContainerFactory(parent=self.tuto_draft, db_object=self.tuto) self.chapter1 = ContainerFactory(parent=self.part1, db_object=self.tuto) self.extract1 = ExtractFactory(container=self.chapter1, db_object=self.tuto) def test_workflow_content(self): """ General tests for a content """ # ensure the usability of manifest versioned = self.tuto.load_version() self.assertEqual(self.tuto_draft.title, versioned.title) self.assertEqual(self.part1.title, versioned.children[0].title) self.assertEqual(self.extract1.title, versioned.children[0].children[0].children[0].title) # ensure url resolution project using dictionary : self.assertTrue(self.part1.slug in versioned.children_dict.keys()) self.assertTrue(self.chapter1.slug in versioned.children_dict[ self.part1.slug].children_dict) def test_ensure_unique_slug(self): """ Ensure that slugs for a container or extract are always unique """ # get draft version versioned = self.tuto.load_version() # forbidden slugs : slug_to_test = ['introduction', 'conclusion'] for slug in slug_to_test: new_slug = versioned.get_unique_slug(slug) self.assertNotEqual(slug, new_slug) self.assertTrue( new_slug in versioned.slug_pool) # ensure new slugs are in slug pool # then test with "real" containers and extracts : new_chapter_1 = ContainerFactory(title='aa', parent=versioned, db_object=self.tuto) new_chapter_2 = ContainerFactory(title='aa', parent=versioned, db_object=self.tuto) self.assertNotEqual(new_chapter_1.slug, new_chapter_2.slug) new_extract_1 = ExtractFactory(title='aa', container=new_chapter_1, db_object=self.tuto) self.assertEqual( new_extract_1.slug, new_chapter_1.slug) # different level can have the same slug ! new_extract_2 = ExtractFactory(title='aa', container=new_chapter_2, db_object=self.tuto) self.assertEqual(new_extract_2.slug, new_extract_1.slug) # not the same parent, so allowed new_extract_3 = ExtractFactory(title='aa', container=new_chapter_1, db_object=self.tuto) self.assertNotEqual(new_extract_3.slug, new_extract_1.slug) # same parent, forbidden def test_ensure_unique_slug_2(self): """This text is an extension of the previous one, with the manifest re-loaded each time""" title = u'Il existe des gens que la ZEP-12 n\'aime pas' random = u'... Mais c\'est pas sencé arriver, donc on va tout faire pour que ça disparaisse !' # get draft version versioned = self.tuto.load_version() # add containers version = versioned.repo_add_container(title, random, random) new_version = self.tuto.load_version(sha=version) self.assertEqual(new_version.children[-1].slug, versioned.children[-1].slug) slugs = [new_version.children[-1].slug] for i in range(0, 2): # will add 3 new container version = versioned.repo_add_container(title, random, random) new_version = self.tuto.load_version(sha=version) self.assertEqual(new_version.children[-1].slug, versioned.children[-1].slug) self.assertTrue(new_version.children[-1].slug not in slugs) # slug is different self.assertTrue(versioned.children[-1].slug not in slugs) slugs.append(new_version.children[-1].slug) # add extracts extract_title = u'On va changer de titre (parce qu\'on sais jamais) !' chapter = versioned.children[ -1] # for this second test, the last chapter will be used version = chapter.repo_add_extract(extract_title, random) new_version = self.tuto.load_version(sha=version) self.assertEqual(new_version.children[-1].children[-1].slug, chapter.children[-1].slug) slugs = [new_version.children[-1].children[-1].slug] for i in range(0, 2): # will add 3 new extracts with the same title version = chapter.repo_add_extract(extract_title, random) new_version = self.tuto.load_version(sha=version) self.assertTrue( new_version.children[-1].children[-1].slug not in slugs) self.assertTrue(chapter.children[-1].slug not in slugs) slugs.append(new_version.children[-1].children[-1].slug) def test_workflow_repository(self): """ Test to ensure the behavior of repo_*() functions : - if they change the filesystem as they are suppose to ; - if they change the `self.sha_*` as they are suppose to. """ new_title = u'Un nouveau titre' other_new_title = u'Un titre différent' random_text = u'J\'ai faim!' other_random_text = u'Oh, du chocolat <3' versioned = self.tuto.load_version() current_version = versioned.current_version slug_repository = versioned.slug_repository # VersionedContent: old_path = versioned.get_path() self.assertTrue(os.path.isdir(old_path)) new_slug = versioned.get_unique_slug( new_title) # normally, you get a new slug by asking database ! versioned.repo_update_top_container(new_title, new_slug, random_text, random_text) self.assertNotEqual(versioned.sha_draft, current_version) self.assertNotEqual(versioned.current_version, current_version) self.assertEqual(versioned.current_version, versioned.sha_draft) current_version = versioned.current_version new_path = versioned.get_path() self.assertNotEqual(old_path, new_path) self.assertTrue(os.path.isdir(new_path)) self.assertFalse(os.path.isdir(old_path)) self.assertNotEqual( slug_repository, versioned.slug_repository) # if this test fail, you're in trouble # Container: # 1. add new part: versioned.repo_add_container(new_title, random_text, random_text) self.assertNotEqual(versioned.sha_draft, current_version) self.assertNotEqual(versioned.current_version, current_version) self.assertEqual(versioned.current_version, versioned.sha_draft) current_version = versioned.current_version part = versioned.children[-1] old_path = part.get_path() self.assertTrue(os.path.isdir(old_path)) self.assertTrue( os.path.exists( os.path.join(versioned.get_path(), part.introduction))) self.assertTrue( os.path.exists(os.path.join(versioned.get_path(), part.conclusion))) self.assertEqual(part.get_introduction(), random_text) self.assertEqual(part.get_conclusion(), random_text) # 2. update the part part.repo_update(other_new_title, other_random_text, other_random_text) self.assertNotEqual(versioned.sha_draft, current_version) self.assertNotEqual(versioned.current_version, current_version) self.assertEqual(versioned.current_version, versioned.sha_draft) current_version = versioned.current_version new_path = part.get_path() self.assertNotEqual(old_path, new_path) self.assertTrue(os.path.isdir(new_path)) self.assertFalse(os.path.isdir(old_path)) self.assertEqual(part.get_introduction(), other_random_text) self.assertEqual(part.get_conclusion(), other_random_text) # 3. delete it part.repo_delete() # boom ! self.assertNotEqual(versioned.sha_draft, current_version) self.assertNotEqual(versioned.current_version, current_version) self.assertEqual(versioned.current_version, versioned.sha_draft) current_version = versioned.current_version self.assertFalse(os.path.isdir(new_path)) # Extract : # 1. add new extract versioned.repo_add_container( new_title, random_text, random_text) # need to add a new part before part = versioned.children[-1] part.repo_add_extract(new_title, random_text) self.assertNotEqual(versioned.sha_draft, current_version) self.assertNotEqual(versioned.current_version, current_version) self.assertEqual(versioned.current_version, versioned.sha_draft) current_version = versioned.current_version extract = part.children[-1] old_path = extract.get_path() self.assertTrue(os.path.isfile(old_path)) self.assertEqual(extract.get_text(), random_text) # 2. update extract extract.repo_update(other_new_title, other_random_text) self.assertNotEqual(versioned.sha_draft, current_version) self.assertNotEqual(versioned.current_version, current_version) self.assertEqual(versioned.current_version, versioned.sha_draft) current_version = versioned.current_version new_path = extract.get_path() self.assertNotEqual(old_path, new_path) self.assertTrue(os.path.isfile(new_path)) self.assertFalse(os.path.isfile(old_path)) self.assertEqual(extract.get_text(), other_random_text) # 3. update parent and see if it still works: part.repo_update(other_new_title, other_random_text, other_random_text) old_path = new_path new_path = extract.get_path() self.assertNotEqual(old_path, new_path) self.assertTrue(os.path.isfile(new_path)) self.assertFalse(os.path.isfile(old_path)) self.assertEqual(extract.get_text(), other_random_text) # 4. Boom, no more extract extract.repo_delete() self.assertNotEqual(versioned.sha_draft, current_version) self.assertNotEqual(versioned.current_version, current_version) self.assertEqual(versioned.current_version, versioned.sha_draft) self.assertFalse(os.path.exists(new_path)) def test_if_none(self): """Test the case where introduction and conclusion are `None`""" given_title = u'La vie secrète de Clem\'' some_text = u'Tous ces secrets (ou pas)' versioned = self.tuto.load_version() # add a new part with `None` for intro and conclusion version = versioned.repo_add_container(given_title, None, None) # check on the model : new_part = versioned.children[-1] self.assertIsNone(new_part.introduction) self.assertIsNone(new_part.conclusion) # it remains when loading the manifest ! versioned2 = self.tuto.load_version(sha=version) self.assertIsNotNone(versioned2) self.assertIsNone(versioned.children[-1].introduction) self.assertIsNone(versioned.children[-1].conclusion) version = new_part.repo_update(given_title, None, None) # still `None` self.assertIsNone(new_part.introduction) self.assertIsNone(new_part.conclusion) # does it still remains ? versioned2 = self.tuto.load_version(sha=version) self.assertIsNotNone(versioned2) self.assertIsNone(versioned.children[-1].introduction) self.assertIsNone(versioned.children[-1].conclusion) new_part.repo_update(given_title, some_text, some_text) self.assertIsNotNone(new_part.introduction) # now, value given self.assertIsNotNone(new_part.conclusion) old_intro = new_part.introduction old_conclu = new_part.conclusion self.assertTrue( os.path.isfile(os.path.join(versioned.get_path(), old_intro))) self.assertTrue( os.path.isfile(os.path.join(versioned.get_path(), old_conclu))) # when loaded the manifest, not None, this time versioned2 = self.tuto.load_version(sha=version) self.assertIsNotNone(versioned2) self.assertIsNotNone(versioned.children[-1].introduction) self.assertIsNotNone(versioned.children[-1].conclusion) version = new_part.repo_update(given_title, None, None) # and we go back to `None` self.assertIsNone(new_part.introduction) self.assertIsNone(new_part.conclusion) self.assertFalse( os.path.isfile(os.path.join(versioned.get_path(), old_intro))) # introduction is deleted self.assertFalse( os.path.isfile(os.path.join(versioned.get_path(), old_conclu))) # does it go back to None ? versioned2 = self.tuto.load_version(sha=version) self.assertIsNotNone(versioned2) self.assertIsNone(versioned.children[-1].introduction) self.assertIsNone(versioned.children[-1].conclusion) new_part.repo_update(given_title, '', '') # empty string != `None` self.assertIsNotNone(new_part.introduction) self.assertIsNotNone(new_part.conclusion) def test_extract_is_none(self): """Test the case of a null extract""" article = PublishableContentFactory(type="ARTICLE") versioned = article.load_version() given_title = u'Peu importe, en fait, ça compte peu' some_text = u'Disparaitra aussi vite que possible' # add a new extract with `None` for text version = versioned.repo_add_extract(given_title, None) # check on the model : new_extract = versioned.children[-1] self.assertIsNone(new_extract.text) # it remains when loading the manifest ! versioned2 = article.load_version(sha=version) self.assertIsNotNone(versioned2) self.assertIsNone(versioned.children[-1].text) version = new_extract.repo_update(given_title, None) self.assertIsNone(new_extract.text) # it remains versioned2 = article.load_version(sha=version) self.assertIsNotNone(versioned2) self.assertIsNone(versioned.children[-1].text) version = new_extract.repo_update(given_title, some_text) self.assertIsNotNone(new_extract.text) self.assertEqual(some_text, new_extract.get_text()) # now it change versioned2 = article.load_version(sha=version) self.assertIsNotNone(versioned2) self.assertIsNotNone(versioned.children[-1].text) # ... and lets go back version = new_extract.repo_update(given_title, None) self.assertIsNone(new_extract.text) # it has changed versioned2 = article.load_version(sha=version) self.assertIsNotNone(versioned2) self.assertIsNone(versioned.children[-1].text) def test_ensure_slug_stay(self): """This test ensure that slug are not modified when coming from a manifest""" tuto = PublishableContentFactory(type='TUTORIAL') versioned = tuto.load_version() random = u'Non, piti bug, tu ne reviendra plus !!!' title = u'N\'importe quel titre' # add three container with the same title versioned.repo_add_container(title, random, random) # x versioned.repo_add_container(title, random, random) # x-1 version = versioned.repo_add_container(title, random, random) # x-2 self.assertEqual(len(versioned.children), 3) current = tuto.load_version(sha=version) self.assertEqual(len(current.children), 3) for index, child in enumerate(current.children): self.assertEqual(child.slug, versioned.children[index].slug) # same order # then, delete the second one: last_slug = versioned.children[2].slug version = versioned.children[1].repo_delete() self.assertEqual(len(versioned.children), 2) self.assertEqual(versioned.children[1].slug, last_slug) current = tuto.load_version(sha=version) self.assertEqual(len(current.children), 2) for index, child in enumerate(current.children): self.assertEqual(child.slug, versioned.children[index].slug) # slug remains # same test with extracts chapter = versioned.children[0] chapter.repo_add_extract(title, random) # x chapter.repo_add_extract(title, random) # x-1 version = chapter.repo_add_extract(title, random) # x-2 self.assertEqual(len(chapter.children), 3) current = tuto.load_version(sha=version) self.assertEqual(len(current.children[0].children), 3) for index, child in enumerate(current.children[0].children): self.assertEqual(child.slug, chapter.children[index].slug) # slug remains # delete the second one ! last_slug = chapter.children[2].slug version = chapter.children[1].repo_delete() self.assertEqual(len(chapter.children), 2) self.assertEqual(chapter.children[1].slug, last_slug) current = tuto.load_version(sha=version) self.assertEqual(len(current.children[0].children), 2) for index, child in enumerate(current.children[0].children): self.assertEqual(child.slug, chapter.children[index].slug ) # slug remains for extract as well ! def test_publication_and_attributes_consistency(self): pubdate = datetime.now() - timedelta(days=1) article = PublishedContentFactory(type="ARTILCE", author_list=[self.user_author]) public_version = article.public_version public_version.publication_date = pubdate public_version.save() # everything must come from database to have good datetime comparison article = PublishableContent.objects.get(pk=article.pk) article.public_version.load_public_version() old_date = article.public_version.publication_date old_title = article.public_version.title() old_description = article.public_version.description() article.licence = LicenceFactory() article.save() self.assertEqual( self.client.login(username=self.user_author.username, password='******'), True) self.client.post( reverse("content:edit", args=[article.pk, article.slug]), { "title": old_title + "bla", "description": old_description + "bla", "type": "ARTICLE", "licence": article.licence.pk, "subcategory": SubCategoryFactory().pk, "last_hash": article.sha_draft }) article = PublishableContent.objects.prefetch_related( "public_version").get(pk=article.pk) article.public_version.load_public_version() self.assertEqual(old_title, article.public_version.title()) self.assertEqual(old_description, article.public_version.description()) self.assertEqual(old_date, article.public_version.publication_date) publish_content(article, article.load_version(), False) article = PublishableContent.objects.get(pk=article.pk) article.public_version.load_public_version() self.assertEqual(old_date, article.public_version.publication_date) self.assertNotEqual(old_date, article.public_version.update_date) def tearDown(self): if os.path.isdir(settings.ZDS_APP['content']['repo_private_path']): shutil.rmtree(settings.ZDS_APP['content']['repo_private_path']) if os.path.isdir(settings.ZDS_APP['content']['repo_public_path']): shutil.rmtree(settings.ZDS_APP['content']['repo_public_path']) if os.path.isdir(settings.MEDIA_ROOT): shutil.rmtree(settings.MEDIA_ROOT) # re-active PDF build settings.ZDS_APP['content']['build_pdf_when_published'] = True
class ContentNotification(TestCase, TutorialTestMixin): def setUp(self): # don't build PDF to speed up the tests self.user1 = ProfileFactory().user self.user2 = ProfileFactory().user # create a tutorial self.tuto = PublishableContentFactory(type='TUTORIAL') self.tuto.authors.add(self.user1) UserGalleryFactory(gallery=self.tuto.gallery, user=self.user1, mode='W') self.tuto.licence = LicenceFactory() self.tuto.subcategory.add(SubCategoryFactory()) self.tuto.save() tuto_draft = self.tuto.load_version() # then, publish it ! version = tuto_draft.current_version self.published = publish_content(self.tuto, tuto_draft, is_major_update=True) self.tuto.sha_public = version self.tuto.sha_draft = version self.tuto.public_version = self.published self.tuto.save() self.assertTrue(self.client.login(username=self.user1.username, password='******')) def test_no_persistant_notif_on_revoke(self): from zds.tutorialv2.publication_utils import unpublish_content NewPublicationSubscription.objects.get_or_create_active(self.user1, self.user2) content = PublishedContentFactory(author_list=[self.user2]) notif_signals.new_content.send(sender=self.tuto.__class__, instance=content, by_email=False) self.assertEqual(1, len(Notification.objects.get_notifications_of(self.user1))) unpublish_content(content) self.assertEqual(0, len(Notification.objects.get_notifications_of(self.user1))) def test_no_persistant_comment_notif_on_revoke(self): from zds.tutorialv2.publication_utils import unpublish_content content = PublishedContentFactory(author_list=[self.user2]) ContentReactionAnswerSubscription.objects.get_or_create_active(self.user1, content) ContentReactionFactory(related_content=content, author=self.user2, position=1) self.assertEqual(1, len(Notification.objects.get_unread_notifications_of(self.user1))) unpublish_content(content, moderator=self.user2) self.assertEqual(0, len(Notification.objects.get_unread_notifications_of(self.user1))) def test_only_one_notif_on_update(self): NewPublicationSubscription.objects.get_or_create_active(self.user1, self.user2) content = PublishedContentFactory(author_list=[self.user2]) notify_update(content, False, True) versioned = content.load_version() content.sha_draft = versioned.repo_update(introduction='new intro', conclusion='new conclusion', title=versioned.title) content.save(force_slug_update=False) publish_content(content, content.load_version(), True) notify_update(content, True, False) notifs = get_header_notifications(self.user1)['general_notifications']['list'] self.assertEqual(1, len(notifs), str(notifs)) def test_only_one_notif_on_major_update(self): NewPublicationSubscription.objects.get_or_create_active(self.user1, self.user2) content = PublishedContentFactory(author_list=[self.user2]) notify_update(content, False, True) versioned = content.load_version() content.sha_draft = versioned.repo_update(introduction='new intro', conclusion='new conclusion', title=versioned.title) content.save(force_slug_update=False) publish_content(content, content.load_version(), True) notify_update(content, True, True) notifs = get_header_notifications(self.user1)['general_notifications']['list'] self.assertEqual(1, len(notifs), str(notifs))
def load_contents(cli, size, fake, _type, *_, **__): """Create v2 contents""" nb_contents = size * 10 percent_contents_in_validation = 0.2 percent_contents_with_validator = 0.1 percent_contents_public = 0.6 percent_mini = 0.5 percent_medium = 0.3 percent_big = 0.2 nb_avg_containers_in_content = size nb_avg_extracts_in_content = size is_articles = _type == "ARTICLE" is_tutorials = _type == "TUTORIAL" is_opinion = _type == "OPINION" textual_type = "article" if is_tutorials: textual_type = "tutoriel" elif is_opinion: textual_type = "billet" # small introduction cli.stdout.write("À créer: {:d} {}s".format(nb_contents, textual_type), ending="") if is_tutorials: cli.stdout.write(" ({:g} petits, {:g} moyens et {:g} grands)".format( nb_contents * percent_mini, nb_contents * percent_medium, nb_contents * percent_big)) else: cli.stdout.write("") cli.stdout.write(" - {:g} en brouillon".format( nb_contents * (1 - percent_contents_public - percent_contents_in_validation - percent_contents_with_validator))) if is_opinion: cli.stdout.write( " - {:g} publiés et {:g} approuvés en page d'accueil".format( nb_contents * (percent_contents_in_validation + percent_contents_with_validator), nb_contents * percent_contents_with_validator, )) else: cli.stdout.write(" - {:g} en validation (dont {:g} réservés)".format( nb_contents * (percent_contents_in_validation + percent_contents_with_validator), nb_contents * percent_contents_with_validator, )) cli.stdout.write(" - {:g} publiés".format(nb_contents * percent_contents_public)) tps1 = time.time() # create tables with 0=draft, 1=in validation, 2=reserved, 3=published what_to_do = [] for created_content_index in range(nb_contents): what = 0 # in draft if created_content_index < percent_contents_public * nb_contents: what = 3 elif created_content_index < ( percent_contents_public + percent_contents_with_validator) * nb_contents: what = 2 elif created_content_index >= ( 1 - percent_contents_in_validation) * nb_contents: what = 1 what_to_do.append(what) # create a table with 0=mini, 1=medium, 2=big content_sizes = [] for created_content_index in range(nb_contents): sz = 0 if created_content_index < percent_big * nb_contents: sz = 2 elif created_content_index >= (1 - percent_medium) * nb_contents: sz = 1 content_sizes.append(sz) # shuffle the whole thing random.shuffle(what_to_do) random.shuffle(content_sizes) # checks that everything is ok users = list(Profile.objects.all()) nb_users = len(users) sub_categories = list(SubCategory.objects.all()) nb_sub_categories = len(sub_categories) if nb_users == 0: cli.stdout.write( "Il n'y a aucun membre actuellement. " "Vous devez rajouter les membre dans vos fixtures (member)") return if nb_sub_categories == 0: cli.stdout.write( "Il n'y a aucune catégories actuellement." "Vous devez rajouter les catégories dans vos fixtures (category_content)" ) return perms = list( Permission.objects.filter(codename__startswith="change_").all()) staffs = list(User.objects.filter(groups__permissions__in=perms).all()) nb_staffs = len(staffs) if nb_staffs == 0: cli.stdout.write( "Il n'y a aucun staff actuellement." "Vous devez rajouter les staffs dans vos fixtures (staff)") return licenses = list(Licence.objects.all()) nb_licenses = len(licenses) if nb_licenses == 0: cli.stdout.write( "Il n'y a aucune licence actuellement." "Vous devez rajouter les licences dans vos fixtures (category_content)" ) return # create and so all: for created_content_index in range(nb_contents): sys.stdout.write("Création {} : {}/{} \r".format( textual_type, created_content_index + 1, nb_contents)) current_size = content_sizes[created_content_index] action_flag = what_to_do[created_content_index] # creation: content = PublishableContentFactory(type=_type, title=fake.text(max_nb_chars=60), description=fake.sentence( nb_words=15, variable_nb_words=True)) versioned = content.load_version() generate_text_for_content( current_size, fake, is_articles, is_opinion, nb_avg_containers_in_content, nb_avg_extracts_in_content, versioned, ) # add some informations: author = users[random.randint(0, nb_users - 1)].user content.authors.add(author) UserGalleryFactory(gallery=content.gallery, mode="W", user=author) content.licence = licenses[random.randint(0, nb_licenses - 1)] content.sha_draft = versioned.sha_draft content.subcategory.add(sub_categories[random.randint( 0, nb_sub_categories - 1)]) content.save() # then, validation if needed: if action_flag > 0: if is_opinion: publish_opinion(content, action_flag, versioned) else: validate_edited_content(content, fake, nb_staffs, staffs, action_flag, versioned) sys.stdout.flush() tps2 = time.time() cli.stdout.write("\nFait en {:.3f} sec".format(tps2 - tps1))
def setUp(self): self.overridden_zds_app = overridden_zds_app # don't build PDF to speed up the tests overridden_zds_app["content"]["build_pdf_when_published"] = False self.staff = StaffProfileFactory().user settings.EMAIL_BACKEND = "django.core.mail.backends.locmem.EmailBackend" self.mas = ProfileFactory().user overridden_zds_app["member"]["bot_account"] = self.mas.username bot = Group(name=overridden_zds_app["member"]["bot_group"]) bot.save() self.external = UserFactory( username=overridden_zds_app["member"]["external_account"], password="******") self.beta_forum = ForumFactory( pk=overridden_zds_app["forum"]["beta_forum_id"], category=ForumCategoryFactory(position=1), position_in_category=1, ) # ensure that the forum, for the beta versions, is created self.licence = LicenceFactory() self.subcategory = SubCategoryFactory() self.tag = TagFactory() self.user_author = ProfileFactory().user self.user_staff = StaffProfileFactory().user self.user_guest = ProfileFactory().user # create a tutorial self.tuto = PublishableContentFactory(type="TUTORIAL") self.tuto.authors.add(self.user_author) UserGalleryFactory(gallery=self.tuto.gallery, user=self.user_author, mode="W") self.tuto.licence = self.licence self.tuto.subcategory.add(self.subcategory) self.tuto.tags.add(self.tag) self.tuto.save() # fill it with one part, containing one chapter, containing one extract self.tuto_draft = self.tuto.load_version() self.part1 = ContainerFactory(parent=self.tuto_draft, db_object=self.tuto) self.chapter1 = ContainerFactory(parent=self.part1, db_object=self.tuto) self.extract1 = ExtractFactory(container=self.chapter1, db_object=self.tuto) # then, publish it ! version = self.tuto_draft.current_version self.published = publish_content(self.tuto, self.tuto_draft, is_major_update=True) self.tuto.sha_public = version self.tuto.sha_draft = version self.tuto.public_version = self.published self.tuto.save() self.tutofeed = LastTutorialsFeedRSS()
def test_publish_content_article(self): """test and ensure the behavior of ``publish_content()`` and ``unpublish_content()``""" # 1. Article: article = PublishableContentFactory(type='ARTICLE') article.authors.add(self.user_author) UserGalleryFactory(gallery=article.gallery, user=self.user_author, mode='W') article.licence = self.licence article.save() # populate the article article_draft = article.load_version() ExtractFactory(container=article_draft, db_object=article) ExtractFactory(container=article_draft, db_object=article) self.assertEqual(len(article_draft.children), 2) # publish ! article = PublishableContent.objects.get(pk=article.pk) published = publish_content(article, article_draft) self.assertEqual(published.content, article) self.assertEqual(published.content_pk, article.pk) self.assertEqual(published.content_type, article.type) self.assertEqual(published.content_public_slug, article_draft.slug) self.assertEqual(published.sha_public, article.sha_draft) public = article.load_version(sha=published.sha_public, public=published) self.assertIsNotNone(public) self.assertTrue(public.PUBLIC) # it's a PublicContent object self.assertEqual(public.type, published.content_type) self.assertEqual(public.current_version, published.sha_public) # test object created in database self.assertEqual( PublishedContent.objects.filter(content=article).count(), 1) published = PublishedContent.objects.filter(content=article).last() self.assertEqual(published.content_pk, article.pk) self.assertEqual(published.content_public_slug, article_draft.slug) self.assertEqual(published.content_type, article.type) self.assertEqual(published.sha_public, public.current_version) # test creation of files: self.assertTrue(os.path.isdir(published.get_prod_path())) self.assertTrue( os.path.isfile( os.path.join(published.get_prod_path(), 'manifest.json'))) prod_path = public.get_prod_path() self.assertTrue(prod_path.endswith('.html'), prod_path) self.assertTrue(os.path.isfile(prod_path), prod_path) # normally, an HTML file should exists self.assertIsNone( public.introduction ) # since all is in the HTML file, introduction does not exists anymore self.assertIsNone(public.conclusion) article.public_version = published article.save() # depublish it ! unpublish_content(article) self.assertEqual( PublishedContent.objects.filter(content=article).count(), 0) # published object disappear self.assertFalse(os.path.exists( public.get_prod_path())) # article was removed
class EditContentTagsFunctionalTests(TutorialTestMixin, TestCase): """Test the detailed behavior of the feature, such as updates of the database or repositories.""" def setUp(self): # Create a user self.author = ProfileFactory() # Create tags self.tag_0 = TagFactory() self.tag_1 = TagFactory() self.tag_from_other_content = TagFactory() self.tags_name = [self.tag_0.title, self.tag_1.title, self.tag_from_other_content.title] # Create contents self.content = PublishableContentFactory(author_list=[self.author.user]) self.other_content = PublishableContentFactory(author_list=[self.author.user]) self.other_content.tags.add(self.tag_from_other_content) self.other_content.save() # Get information to be reused in tests self.form_url = reverse("content:edit-tags", kwargs={"pk": self.content.pk}) # Log in with an authorized user (e.g the author of the content) to perform the tests self.client.force_login(self.author.user) def test_form_function(self): """Test many use cases for the form.""" test_cases = self.get_test_cases() for case_name, case in test_cases.items(): with self.subTest(msg=case_name): self.enforce_preconditions(case["preconditions"]) self.post_form(case["inputs"]) self.check_effects(case["expected_outputs"]) def get_test_cases(self): """List test cases for the license editing form.""" new_tag_name = "new_tag_for_sure" return { "nothing": { "preconditions": {"all_tags": self.tags_name, "content_tags": []}, "inputs": {"tags": ""}, "expected_outputs": {"all_tags": self.tags_name, "content_tags": []}, }, "existing_tag": { "preconditions": {"all_tags": self.tags_name, "content_tags": []}, "inputs": {"tags": self.tag_1.title}, "expected_outputs": {"all_tags": self.tags_name, "content_tags": [self.tag_1.title]}, }, "new_tag": { "preconditions": {"all_tags": self.tags_name, "content_tags": []}, "inputs": {"tags": new_tag_name}, "expected_outputs": {"all_tags": self.tags_name + [new_tag_name], "content_tags": [new_tag_name]}, }, } def enforce_preconditions(self, preconditions): """Prepare the test environment to match given preconditions""" tags = [] for t in preconditions["content_tags"]: tags.append(Tag.objects.get(title=t)) self.content.tags.set(tags) self.assertEqual(list(self.content.tags.values_list("title")), preconditions["content_tags"]) def post_form(self, inputs): """Post the form with given inputs.""" form_data = {"tags": inputs["tags"]} self.client.post(self.form_url, form_data) def check_effects(self, expected_outputs): """Check the effects of having sent the form.""" updated_content = PublishableContent.objects.get(pk=self.content.pk) content_tags_as_string = [tag.title for tag in updated_content.tags.all()] all_tags_as_string = [tag.title for tag in Tag.objects.all()] self.assertEqual(content_tags_as_string, expected_outputs["content_tags"]) self.assertEqual(all_tags_as_string, expected_outputs["all_tags"])
def test_publish_content_big_tuto(self): # 4. Big tutorial: bigtuto = PublishableContentFactory(type='TUTORIAL') bigtuto.authors.add(self.user_author) UserGalleryFactory(gallery=bigtuto.gallery, user=self.user_author, mode='W') bigtuto.licence = self.licence bigtuto.save() # populate with 2 part (1 chapter with 1 extract each) bigtuto_draft = bigtuto.load_version() part1 = ContainerFactory(parent=bigtuto_draft, db_objet=bigtuto) chapter1 = ContainerFactory(parent=part1, db_objet=bigtuto) ExtractFactory(container=chapter1, db_object=bigtuto) part2 = ContainerFactory(parent=bigtuto_draft, db_objet=bigtuto) chapter2 = ContainerFactory(parent=part2, db_objet=bigtuto) ExtractFactory(container=chapter2, db_object=bigtuto) # publish it bigtuto = PublishableContent.objects.get(pk=bigtuto.pk) published = publish_content(bigtuto, bigtuto_draft) self.assertEqual(published.content, bigtuto) self.assertEqual(published.content_pk, bigtuto.pk) self.assertEqual(published.content_type, bigtuto.type) self.assertEqual(published.content_public_slug, bigtuto_draft.slug) self.assertEqual(published.sha_public, bigtuto.sha_draft) public = bigtuto.load_version(sha=published.sha_public, public=published) self.assertIsNotNone(public) self.assertTrue(public.PUBLIC) # it's a PublicContent object self.assertEqual(public.type, published.content_type) self.assertEqual(public.current_version, published.sha_public) # test creation of files: self.assertTrue(os.path.isdir(published.get_prod_path())) self.assertTrue( os.path.isfile( os.path.join(published.get_prod_path(), 'manifest.json'))) self.assertTrue( os.path.isfile( os.path.join(public.get_prod_path(), public.introduction))) self.assertTrue( os.path.isfile( os.path.join(public.get_prod_path(), public.conclusion))) self.assertEqual(len(public.children), 2) for part in public.children: self.assertTrue(os.path.isdir( part.get_prod_path())) # a directory for each part # ... and an HTML file for introduction and conclusion self.assertTrue( os.path.isfile( os.path.join(public.get_prod_path(), part.introduction))) self.assertTrue( os.path.isfile( os.path.join(public.get_prod_path(), part.conclusion))) self.assertEqual(len(part.children), 1) for chapter in part.children: # the HTML file is located in the good directory: self.assertEqual(part.get_prod_path(), os.path.dirname(chapter.get_prod_path())) self.assertTrue(os.path.isfile( chapter.get_prod_path())) # an HTML file for each chapter self.assertIsNone(chapter.introduction) self.assertIsNone(chapter.conclusion)
def test_opinion_validation(self): """ Test the validation of PublishableContent where type is OPINION. """ text_publication = 'Aussi tôt dit, aussi tôt fait !' opinion = PublishableContentFactory(type='OPINION') opinion.authors.add(self.user_author) UserGalleryFactory(gallery=opinion.gallery, user=self.user_author, mode='W') opinion.licence = self.licence opinion.save() opinion_draft = opinion.load_version() ExtractFactory(container=opinion_draft, db_object=opinion) ExtractFactory(container=opinion_draft, db_object=opinion) self.assertEqual( self.client.login(username=self.user_author.username, password='******'), True) # publish result = self.client.post(reverse('validation:publish-opinion', kwargs={ 'pk': opinion.pk, 'slug': opinion.slug }), { 'text': text_publication, 'source': '', 'version': opinion_draft.current_version }, follow=False) self.assertEqual(result.status_code, 302) self.assertEqual(PublishedContent.objects.count(), 1) opinion = PublishableContent.objects.get(pk=opinion.pk) self.assertIsNotNone(opinion.public_version) self.assertEqual(opinion.public_version.sha_public, opinion_draft.current_version) # valid with author => 403 opinion = PublishableContent.objects.get(pk=opinion.pk) opinion_draft = opinion.load_version() result = self.client.post(reverse('validation:pick-opinion', kwargs={ 'pk': opinion.pk, 'slug': opinion.slug }), { 'source': '', 'version': opinion_draft.current_version }, follow=False) self.assertEqual(result.status_code, 403) opinion = PublishableContent.objects.get(pk=opinion.pk) self.assertIsNone(opinion.sha_picked) self.assertIsNone(opinion.picked_date) self.assertEqual( self.client.login(username=self.user_staff.username, password='******'), True) # valid with staff result = self.client.post(reverse('validation:pick-opinion', kwargs={ 'pk': opinion.pk, 'slug': opinion.slug }), { 'source': '', 'version': opinion_draft.current_version }, follow=False) self.assertEqual(result.status_code, 302) opinion = PublishableContent.objects.get(pk=opinion.pk) self.assertEqual(opinion.sha_picked, opinion_draft.current_version) self.assertIsNotNone(opinion.picked_date) # invalid with author => 403 self.assertEqual( self.client.login(username=self.user_author.username, password='******'), True) result = self.client.post(reverse('validation:unpick-opinion', kwargs={ 'pk': opinion.pk, 'slug': opinion.slug }), { 'text': 'Parce que je veux', 'version': opinion_draft.current_version }, follow=False) self.assertEqual(result.status_code, 403) opinion = PublishableContent.objects.get(pk=opinion.pk) self.assertEqual(opinion.sha_picked, opinion_draft.current_version) # invalid with staff self.assertEqual( self.client.login(username=self.user_staff.username, password='******'), True) result = self.client.post(reverse('validation:unpick-opinion', kwargs={ 'pk': opinion.pk, 'slug': opinion.slug }), { 'text': 'Parce que je peux !', 'version': opinion_draft.current_version }, follow=False) self.assertEqual(result.status_code, 302) opinion = PublishableContent.objects.get(pk=opinion.pk) self.assertIsNone(opinion.sha_picked) # double invalidation wont work result = self.client.post(reverse('validation:unpick-opinion', kwargs={ 'pk': opinion.pk, 'slug': opinion.slug }), { 'text': 'Parce que je peux toujours ...', 'version': opinion_draft.current_version }, follow=False) self.assertEqual(result.status_code, 403)
class UtilsTests(TutorialTestMixin, TestCase): def setUp(self): self.mas = ProfileFactory().user self.overridden_zds_app['member']['bot_account'] = self.mas.username self.licence = LicenceFactory() self.user_author = ProfileFactory().user self.staff = StaffProfileFactory().user self.tuto = PublishableContentFactory(type='TUTORIAL') self.tuto.authors.add(self.user_author) UserGalleryFactory(gallery=self.tuto.gallery, user=self.user_author, mode='W') self.tuto.licence = self.licence self.tuto.save() self.tuto_draft = self.tuto.load_version() self.part1 = ContainerFactory(parent=self.tuto_draft, db_object=self.tuto) self.chapter1 = ContainerFactory(parent=self.part1, db_object=self.tuto) self.old_registry = { key: value for key, value in PublicatorRegistry.get_all_registered() } class TestPdfPublicator(Publicator): def publish(self, md_file_path, base_name, **kwargs): with Path(base_name + '.pdf').open('w') as f: f.write('bla') shutil.copy2( str(Path(base_name + '.pdf')), str(Path(md_file_path.replace('__building', '')).parent)) PublicatorRegistry.registry['pdf'] = TestPdfPublicator() def test_get_target_tagged_tree_for_container(self): part2 = ContainerFactory(parent=self.tuto_draft, db_object=self.tuto, title='part2') part3 = ContainerFactory(parent=self.tuto_draft, db_object=self.tuto, title='part3') tagged_tree = get_target_tagged_tree_for_container( self.part1, self.tuto_draft) self.assertEqual(4, len(tagged_tree)) paths = {i[0]: i[3] for i in tagged_tree} self.assertTrue(part2.get_path(True) in paths) self.assertTrue(part3.get_path(True) in paths) self.assertTrue(self.chapter1.get_path(True) in paths) self.assertTrue(self.part1.get_path(True) in paths) self.assertFalse(self.tuto_draft.get_path(True) in paths) self.assertFalse(paths[self.chapter1.get_path(True)], "can't be moved to a too deep container") self.assertFalse(paths[self.part1.get_path(True)], "can't be moved after or before himself") self.assertTrue(paths[part2.get_path(True)], 'can be moved after or before part2') self.assertTrue(paths[part3.get_path(True)], 'can be moved after or before part3') tagged_tree = get_target_tagged_tree_for_container( part3, self.tuto_draft) self.assertEqual(4, len(tagged_tree)) paths = {i[0]: i[3] for i in tagged_tree} self.assertTrue(part2.get_path(True) in paths) self.assertTrue(part3.get_path(True) in paths) self.assertTrue(self.chapter1.get_path(True) in paths) self.assertTrue(self.part1.get_path(True) in paths) self.assertFalse(self.tuto_draft.get_path(True) in paths) self.assertTrue(paths[self.chapter1.get_path(True)], "can't be moved to a too deep container") self.assertTrue(paths[self.part1.get_path(True)], "can't be moved after or before himself") self.assertTrue(paths[part2.get_path(True)], 'can be moved after or before part2') self.assertFalse(paths[part3.get_path(True)], 'can be moved after or before part3') def test_publish_content_article(self): """test and ensure the behavior of ``publish_content()`` and ``unpublish_content()``""" # 1. Article: article = PublishableContentFactory(type='ARTICLE') article.authors.add(self.user_author) UserGalleryFactory(gallery=article.gallery, user=self.user_author, mode='W') article.licence = self.licence article.save() # populate the article article_draft = article.load_version() ExtractFactory(container=article_draft, db_object=article) ExtractFactory(container=article_draft, db_object=article) self.assertEqual(len(article_draft.children), 2) # publish ! article = PublishableContent.objects.get(pk=article.pk) published = publish_content(article, article_draft) self.assertEqual(published.content, article) self.assertEqual(published.content_pk, article.pk) self.assertEqual(published.content_type, article.type) self.assertEqual(published.content_public_slug, article_draft.slug) self.assertEqual(published.sha_public, article.sha_draft) public = article.load_version(sha=published.sha_public, public=published) self.assertIsNotNone(public) self.assertTrue(public.PUBLIC) # it's a PublicContent object self.assertEqual(public.type, published.content_type) self.assertEqual(public.current_version, published.sha_public) # test object created in database self.assertEqual( PublishedContent.objects.filter(content=article).count(), 1) published = PublishedContent.objects.filter(content=article).last() self.assertEqual(published.content_pk, article.pk) self.assertEqual(published.content_public_slug, article_draft.slug) self.assertEqual(published.content_type, article.type) self.assertEqual(published.sha_public, public.current_version) # test creation of files: self.assertTrue(os.path.isdir(published.get_prod_path())) self.assertTrue( os.path.isfile( os.path.join(published.get_prod_path(), 'manifest.json'))) prod_path = public.get_prod_path() self.assertTrue(prod_path.endswith('.html'), prod_path) self.assertTrue(os.path.isfile(prod_path), prod_path) # normally, an HTML file should exists self.assertIsNone( public.introduction ) # since all is in the HTML file, introduction does not exists anymore self.assertIsNone(public.conclusion) article.public_version = published article.save() # depublish it ! unpublish_content(article) self.assertEqual( PublishedContent.objects.filter(content=article).count(), 0) # published object disappear self.assertFalse(os.path.exists( public.get_prod_path())) # article was removed # ... For the next tests, I will assume that the unpublication works. def test_publish_content_medium_tuto(self): # 3. Medium-size tutorial midsize_tuto = PublishableContentFactory(type='TUTORIAL') midsize_tuto.authors.add(self.user_author) UserGalleryFactory(gallery=midsize_tuto.gallery, user=self.user_author, mode='W') midsize_tuto.licence = self.licence midsize_tuto.save() # populate with 2 chapters (1 extract each) midsize_tuto_draft = midsize_tuto.load_version() chapter1 = ContainerFactory(parent=midsize_tuto_draft, db_objet=midsize_tuto) ExtractFactory(container=chapter1, db_object=midsize_tuto) chapter2 = ContainerFactory(parent=midsize_tuto_draft, db_objet=midsize_tuto) ExtractFactory(container=chapter2, db_object=midsize_tuto) # publish it midsize_tuto = PublishableContent.objects.get(pk=midsize_tuto.pk) published = publish_content(midsize_tuto, midsize_tuto_draft) self.assertEqual(published.content, midsize_tuto) self.assertEqual(published.content_pk, midsize_tuto.pk) self.assertEqual(published.content_type, midsize_tuto.type) self.assertEqual(published.content_public_slug, midsize_tuto_draft.slug) self.assertEqual(published.sha_public, midsize_tuto.sha_draft) public = midsize_tuto.load_version(sha=published.sha_public, public=published) self.assertIsNotNone(public) self.assertTrue(public.PUBLIC) # it's a PublicContent object self.assertEqual(public.type, published.content_type) self.assertEqual(public.current_version, published.sha_public) # test creation of files: self.assertTrue(Path(published.get_prod_path()).is_dir()) self.assertTrue( Path(published.get_prod_path(), 'manifest.json').is_file()) self.assertTrue( Path(public.get_prod_path(), public.introduction).is_file()) self.assertTrue( Path(public.get_prod_path(), public.conclusion).is_file()) self.assertEqual(len(public.children), 2) for child in public.children: self.assertTrue(os.path.isfile( child.get_prod_path())) # an HTML file for each chapter self.assertIsNone(child.introduction) self.assertIsNone(child.conclusion) def test_publish_content_big_tuto(self): # 4. Big tutorial: bigtuto = PublishableContentFactory(type='TUTORIAL') bigtuto.authors.add(self.user_author) UserGalleryFactory(gallery=bigtuto.gallery, user=self.user_author, mode='W') bigtuto.licence = self.licence bigtuto.save() # populate with 2 part (1 chapter with 1 extract each) bigtuto_draft = bigtuto.load_version() part1 = ContainerFactory(parent=bigtuto_draft, db_objet=bigtuto) chapter1 = ContainerFactory(parent=part1, db_objet=bigtuto) ExtractFactory(container=chapter1, db_object=bigtuto) part2 = ContainerFactory(parent=bigtuto_draft, db_objet=bigtuto) chapter2 = ContainerFactory(parent=part2, db_objet=bigtuto) ExtractFactory(container=chapter2, db_object=bigtuto) # publish it bigtuto = PublishableContent.objects.get(pk=bigtuto.pk) published = publish_content(bigtuto, bigtuto_draft) self.assertEqual(published.content, bigtuto) self.assertEqual(published.content_pk, bigtuto.pk) self.assertEqual(published.content_type, bigtuto.type) self.assertEqual(published.content_public_slug, bigtuto_draft.slug) self.assertEqual(published.sha_public, bigtuto.sha_draft) public = bigtuto.load_version(sha=published.sha_public, public=published) self.assertIsNotNone(public) self.assertTrue(public.PUBLIC) # it's a PublicContent object self.assertEqual(public.type, published.content_type) self.assertEqual(public.current_version, published.sha_public) # test creation of files: self.assertTrue(os.path.isdir(published.get_prod_path())) self.assertTrue( os.path.isfile( os.path.join(published.get_prod_path(), 'manifest.json'))) self.assertTrue( os.path.isfile( os.path.join(public.get_prod_path(), public.introduction))) self.assertTrue( os.path.isfile( os.path.join(public.get_prod_path(), public.conclusion))) self.assertEqual(len(public.children), 2) for part in public.children: self.assertTrue(os.path.isdir( part.get_prod_path())) # a directory for each part # ... and an HTML file for introduction and conclusion self.assertTrue( os.path.isfile( os.path.join(public.get_prod_path(), part.introduction))) self.assertTrue( os.path.isfile( os.path.join(public.get_prod_path(), part.conclusion))) self.assertEqual(len(part.children), 1) for chapter in part.children: # the HTML file is located in the good directory: self.assertEqual(part.get_prod_path(), os.path.dirname(chapter.get_prod_path())) self.assertTrue(os.path.isfile( chapter.get_prod_path())) # an HTML file for each chapter self.assertIsNone(chapter.introduction) self.assertIsNone(chapter.conclusion) def test_tagged_tree_extract(self): midsize = PublishableContentFactory(author_list=[self.user_author]) midsize_draft = midsize.load_version() first_container = ContainerFactory(parent=midsize_draft, db_object=midsize) second_container = ContainerFactory(parent=midsize_draft, db_object=midsize) first_extract = ExtractFactory(container=first_container, db_object=midsize) second_extract = ExtractFactory(container=second_container, db_object=midsize) tagged_tree = get_target_tagged_tree_for_extract( first_extract, midsize_draft) paths = {i[0]: i[3] for i in tagged_tree} self.assertTrue(paths[second_extract.get_full_slug()]) self.assertFalse(paths[second_container.get_path(True)]) self.assertFalse(paths[first_container.get_path(True)]) def test_update_manifest(self): opts = {} path_manifest1 = settings.BASE_DIR / 'fixtures' / 'tuto' / 'balise_audio' / 'manifest.json' path_manifest2 = settings.BASE_DIR / 'fixtures' / 'tuto' / 'balise_audio' / 'manifest2.json' args = [str(path_manifest2)] shutil.copy(path_manifest1, path_manifest2) LicenceFactory(code='CC BY') call_command('upgrade_manifest_to_v2', *args, **opts) manifest = path_manifest2.open('r') json = json_handler.loads(manifest.read()) self.assertTrue('version' in json) self.assertTrue('licence' in json) self.assertTrue('children' in json) self.assertEqual(len(json['children']), 3) self.assertEqual(json['children'][0]['object'], 'extract') os.unlink(args[0]) path_manifest1 = settings.BASE_DIR / 'fixtures' / 'tuto' / 'big_tuto_v1' / 'manifest.json' path_manifest2 = settings.BASE_DIR / 'fixtures' / 'tuto' / 'big_tuto_v1' / 'manifest2.json' args = [str(path_manifest2)] shutil.copy(path_manifest1, path_manifest2) call_command('upgrade_manifest_to_v2', *args, **opts) manifest = path_manifest2.open('r') json = json_handler.loads(manifest.read()) os.unlink(args[0]) self.assertTrue('version' in json) self.assertTrue('licence' in json) self.assertTrue('children' in json) self.assertEqual(len(json['children']), 5) self.assertEqual(json['children'][0]['object'], 'container') self.assertEqual(len(json['children'][0]['children']), 3) self.assertEqual(len(json['children'][0]['children'][0]['children']), 3) path_manifest1 = settings.BASE_DIR / 'fixtures' / 'tuto' / 'article_v1' / 'manifest.json' path_manifest2 = settings.BASE_DIR / 'fixtures' / 'tuto' / 'article_v1' / 'manifest2.json' args = [path_manifest2] shutil.copy(path_manifest1, path_manifest2) call_command('upgrade_manifest_to_v2', *args, **opts) manifest = path_manifest2.open('r') json = json_handler.loads(manifest.read()) self.assertTrue('version' in json) self.assertTrue('licence' in json) self.assertTrue('children' in json) self.assertEqual(len(json['children']), 1) os.unlink(args[0]) def test_generate_markdown(self): tuto = PublishedContentFactory( type='TUTORIAL') # generate and publish a tutorial published = PublishedContent.objects.get(content_pk=tuto.pk) tuto2 = PublishedContentFactory( type='TUTORIAL') # generate and publish a second tutorial published2 = PublishedContent.objects.get(content_pk=tuto2.pk) self.assertTrue(published.has_md()) self.assertTrue(published2.has_md()) os.remove( str( Path(published.get_extra_contents_directory(), published.content_public_slug + '.md'))) os.remove( str( Path(published2.get_extra_contents_directory(), published2.content_public_slug + '.md'))) self.assertFalse(published.has_md()) self.assertFalse(published2.has_md()) # test command with param call_command('generate_markdown', published.content.pk) self.assertTrue(published.has_md()) self.assertFalse(published2.has_md()) os.remove( str( Path(published.get_extra_contents_directory(), published.content_public_slug + '.md'))) # test command without param call_command('generate_markdown') self.assertTrue(published.has_md()) self.assertTrue(published2.has_md()) def test_generate_pdf(self): """ensure the behavior of the `python manage.py generate_pdf` commmand""" self.overridden_zds_app['content'][ 'build_pdf_when_published'] = True # this test need PDF build, if any tuto = PublishedContentFactory( type='TUTORIAL') # generate and publish a tutorial published = PublishedContent.objects.get(content_pk=tuto.pk) tuto2 = PublishedContentFactory( type='TUTORIAL') # generate and publish a second tutorial published2 = PublishedContent.objects.get(content_pk=tuto2.pk) # ensure that PDF exists in the first place self.assertTrue(published.has_pdf()) self.assertTrue(published2.has_pdf()) pdf_path = os.path.join(published.get_extra_contents_directory(), published.content_public_slug + '.pdf') pdf_path2 = os.path.join(published2.get_extra_contents_directory(), published2.content_public_slug + '.pdf') self.assertTrue(os.path.exists(pdf_path)) self.assertTrue(os.path.exists(pdf_path2)) # 1. re-generate (all) PDFs os.remove(pdf_path) os.remove(pdf_path2) self.assertFalse(os.path.exists(pdf_path)) self.assertFalse(os.path.exists(pdf_path2)) call_command('generate_pdf') self.assertTrue(os.path.exists(pdf_path)) self.assertTrue(os.path.exists(pdf_path2)) # both PDFs are generated # 2. re-generate a given PDF os.remove(pdf_path) os.remove(pdf_path2) self.assertFalse(os.path.exists(pdf_path)) self.assertFalse(os.path.exists(pdf_path2)) call_command('generate_pdf', 'id={}'.format(tuto.pk)) self.assertTrue(os.path.exists(pdf_path)) self.assertFalse( os.path.exists(pdf_path2)) # only the first PDF is generated # 3. re-generate a given PDF with a wrong id os.remove(pdf_path) self.assertFalse(os.path.exists(pdf_path)) self.assertFalse(os.path.exists(pdf_path2)) call_command('generate_pdf', 'id=-1') # There is no content with pk=-1 self.assertFalse(os.path.exists(pdf_path)) self.assertFalse(os.path.exists(pdf_path2)) # so no PDF is generated ! def test_last_participation_is_old(self): article = PublishedContentFactory(author_list=[self.user_author], type='ARTICLE') new_user = ProfileFactory().user reac = ContentReaction(author=self.user_author, position=1, related_content=article) reac.update_content('I will find you.') reac.save() article.last_note = reac article.save() self.assertFalse(last_participation_is_old(article, new_user)) ContentRead(user=self.user_author, note=reac, content=article).save() reac = ContentReaction(author=new_user, position=2, related_content=article) reac.update_content('I will find you.') reac.save() article.last_note = reac article.save() ContentRead(user=new_user, note=reac, content=article).save() self.assertFalse(last_participation_is_old(article, new_user)) self.assertTrue(last_participation_is_old(article, self.user_author)) def testParseBadManifest(self): base_content = PublishableContentFactory( author_list=[self.user_author]) versioned = base_content.load_version() versioned.add_container(Container('un peu plus près de 42')) versioned.dump_json() manifest = os.path.join(versioned.get_path(), 'manifest.json') dictionary = json_handler.load(open(manifest)) old_title = dictionary['title'] # first bad title dictionary['title'] = 81 * ['a'] self.assertRaises(BadManifestError, get_content_from_json, dictionary, None, '', max_title_len=PublishableContent._meta.get_field( 'title').max_length) dictionary['title'] = ''.join(dictionary['title']) self.assertRaises(BadManifestError, get_content_from_json, dictionary, None, '', max_title_len=PublishableContent._meta.get_field( 'title').max_length) dictionary['title'] = '...' self.assertRaises(InvalidSlugError, get_content_from_json, dictionary, None, '', max_title_len=PublishableContent._meta.get_field( 'title').max_length) dictionary['title'] = old_title dictionary['children'][0]['title'] = 81 * ['a'] self.assertRaises(BadManifestError, get_content_from_json, dictionary, None, '', max_title_len=PublishableContent._meta.get_field( 'title').max_length) dictionary['children'][0]['title'] = 'bla' dictionary['children'][0]['slug'] = '...' self.assertRaises(InvalidSlugError, get_content_from_json, dictionary, None, '', max_title_len=PublishableContent._meta.get_field( 'title').max_length) def test_get_commit_author(self): """Ensure the behavior of `get_commit_author()` : - `git.Actor` use the pk of the bot account when no one is connected - `git.Actor` use the pk (and the email) of the connected account when available (Implementation of `git.Actor` is there : https://github.com/gitpython-developers/GitPython/blob/master/git/util.py#L312) """ # 1. With user connected self.assertEqual( self.client.login(username=self.user_author.username, password='******'), True) # go to whatever page, if not, `get_current_user()` does not work at all result = self.client.get(reverse('pages-index')) self.assertEqual(result.status_code, 200) actor = get_commit_author() self.assertEqual(actor['committer'].name, str(self.user_author.pk)) self.assertEqual(actor['author'].name, str(self.user_author.pk)) self.assertEqual(actor['committer'].email, self.user_author.email) self.assertEqual(actor['author'].email, self.user_author.email) def test_get_commit_author_not_auth(self): result = self.client.get(reverse('pages-index')) self.assertEqual(result.status_code, 200) actor = get_commit_author() self.assertEqual(actor['committer'].name, str(self.mas.pk)) self.assertEqual(actor['author'].name, str(self.mas.pk)) def invalid_slug_is_invalid(self): """ensure that an exception is raised when it should""" # exception are raised when title are invalid invalid_titles = [ '-', '_', '__', '-_-', '$', '@', '&', '{}', ' ', '...' ] for t in invalid_titles: self.assertRaises(InvalidSlugError, slugify_raise_on_invalid, t) # Those slugs are recognized as wrong slug invalid_slugs = [ '', # empty '----', # empty '___', # empty '-_-', # empty (!) '&;', # invalid characters '!{', # invalid characters '@', # invalid character 'a ' # space ! ] for s in invalid_slugs: self.assertFalse(check_slug(s)) # too long slugs are forbidden : too_damn_long_slug = 'a' * ( self.overridden_zds_app['content']['maximum_slug_size'] + 1) self.assertFalse(check_slug(too_damn_long_slug)) def test_adjust_char_count(self): """Test the `adjust_char_count` command""" article = PublishedContentFactory(type='ARTICLE', author_list=[self.user_author]) published = PublishedContent.objects.filter(content=article).first() published.char_count = None published.save() call_command('adjust_char_count') published = PublishedContent.objects.get(pk=published.pk) self.assertEqual(published.char_count, published.get_char_count()) def test_image_with_non_ascii_chars(self): """seen on #4144""" article = PublishableContentFactory(type='article', author_list=[self.user_author]) image_string = '![Portrait de Richard Stallman en 2014. [Source](https://commons.wikimedia.org/wiki/' \ 'File:Richard_Stallman_-_Fête_de_l%27Humanité_2014_-_010.jpg).]' \ '(/media/galleries/4410/c1016bf1-a1de-48a1-9ef1-144308e8725d.jpg)' article.sha_draft = article.load_version().repo_update( article.title, image_string, '', update_slug=False) article.save(force_slug_update=False) publish_content(article, article.load_version()) self.assertTrue( PublishedContent.objects.filter(content_id=article.pk).exists()) def test_no_alert_on_unpublish(self): """related to #4860""" published = PublishedContentFactory(type='OPINION', author_list=[self.user_author]) reaction = ContentReactionFactory(related_content=published, author=ProfileFactory().user, position=1, pubdate=datetime.datetime.now()) Alert.objects.create(scope='CONTENT', comment=reaction, text='a text', author=ProfileFactory().user, pubdate=datetime.datetime.now(), content=published) staff = StaffProfileFactory().user self.assertEqual(1, get_header_notifications(staff)['alerts']['total']) unpublish_content(published, staff) self.assertEqual(0, get_header_notifications(staff)['alerts']['total']) def tearDown(self): super().tearDown() PublicatorRegistry.registry = self.old_registry
def test_permanently_unpublish_opinion(self): opinion = PublishableContentFactory(type='OPINION') opinion.authors.add(self.user_author) UserGalleryFactory(gallery=opinion.gallery, user=self.user_author, mode='W') opinion.licence = self.licence opinion.save() opinion_draft = opinion.load_version() ExtractFactory(container=opinion_draft, db_object=opinion) ExtractFactory(container=opinion_draft, db_object=opinion) self.assertEqual( self.client.login(username=self.user_author.username, password='******'), True) # publish result = self.client.post(reverse('validation:publish-opinion', kwargs={ 'pk': opinion.pk, 'slug': opinion.slug }), { 'source': '', 'version': opinion_draft.current_version }, follow=False) self.assertEqual(result.status_code, 302) # login as staff self.assertEqual( self.client.login(username=self.user_staff.username, password='******'), True) # unpublish opinion result = self.client.post(reverse('validation:ignore-opinion', kwargs={ 'pk': opinion.pk, 'slug': opinion.slug }), { 'operation': 'REMOVE_PUB', }, follow=False) self.assertEqual(result.status_code, 200) # refresh opinion = PublishableContent.objects.get(pk=opinion.pk) # check that the opinion is not published self.assertFalse(opinion.in_public()) # check that it's impossible to publish the opinion again result = self.client.get(opinion.get_absolute_url()) self.assertContains(result, _('Billet modéré')) # front result = self.client.post(reverse('validation:publish-opinion', kwargs={ 'pk': opinion.pk, 'slug': opinion.slug }), { 'source': '', 'version': opinion_draft.current_version }, follow=False) self.assertEqual(result.status_code, 403) # back
def test_publish_content(self): """test and ensure the behavior of ``publish_content()`` and ``unpublish_content()``""" # 1. Article: article = PublishableContentFactory(type='ARTICLE') article.authors.add(self.user_author) UserGalleryFactory(gallery=article.gallery, user=self.user_author, mode='W') article.licence = self.licence article.save() # populate the article article_draft = article.load_version() ExtractFactory(container=article_draft, db_object=article) ExtractFactory(container=article_draft, db_object=article) self.assertEqual(len(article_draft.children), 2) # publish ! article = PublishableContent.objects.get(pk=article.pk) published = publish_content(article, article_draft) self.assertEqual(published.content, article) self.assertEqual(published.content_pk, article.pk) self.assertEqual(published.content_type, article.type) self.assertEqual(published.content_public_slug, article_draft.slug) self.assertEqual(published.sha_public, article.sha_draft) public = article.load_version(sha=published.sha_public, public=published) self.assertIsNotNone(public) self.assertTrue(public.PUBLIC) # its a PublicContent object ! self.assertEqual(public.type, published.content_type) self.assertEqual(public.current_version, published.sha_public) # test object created in database self.assertEqual( PublishedContent.objects.filter(content=article).count(), 1) published = PublishedContent.objects.filter(content=article).last() self.assertEqual(published.content_pk, article.pk) self.assertEqual(published.content_public_slug, article_draft.slug) self.assertEqual(published.content_type, article.type) self.assertEqual(published.sha_public, public.current_version) # test creation of files: self.assertTrue(os.path.isdir(published.get_prod_path())) self.assertTrue( os.path.isfile( os.path.join(published.get_prod_path(), 'manifest.json'))) self.assertTrue(os.path.isfile( public.get_prod_path())) # normally, an HTML file should exists self.assertIsNone( public.introduction ) # since all is in the HTML file, introduction does not exists anymore self.assertIsNone(public.conclusion) article.public_version = published article.save() # depublish it ! unpublish_content(article) self.assertEqual( PublishedContent.objects.filter(content=article).count(), 0) # published object disappear self.assertFalse(os.path.exists( public.get_prod_path())) # article was removed # ... For the next tests, I will assume that the unpublication works. # 2. Mini-tutorial → Not tested, because at this point, it's the same as an article (with a different metadata) # 3. Medium-size tutorial midsize_tuto = PublishableContentFactory(type='TUTORIAL') midsize_tuto.authors.add(self.user_author) UserGalleryFactory(gallery=midsize_tuto.gallery, user=self.user_author, mode='W') midsize_tuto.licence = self.licence midsize_tuto.save() # populate with 2 chapters (1 extract each) midsize_tuto_draft = midsize_tuto.load_version() chapter1 = ContainerFactory(parent=midsize_tuto_draft, db_objet=midsize_tuto) ExtractFactory(container=chapter1, db_object=midsize_tuto) chapter2 = ContainerFactory(parent=midsize_tuto_draft, db_objet=midsize_tuto) ExtractFactory(container=chapter2, db_object=midsize_tuto) # publish it midsize_tuto = PublishableContent.objects.get(pk=midsize_tuto.pk) published = publish_content(midsize_tuto, midsize_tuto_draft) self.assertEqual(published.content, midsize_tuto) self.assertEqual(published.content_pk, midsize_tuto.pk) self.assertEqual(published.content_type, midsize_tuto.type) self.assertEqual(published.content_public_slug, midsize_tuto_draft.slug) self.assertEqual(published.sha_public, midsize_tuto.sha_draft) public = midsize_tuto.load_version(sha=published.sha_public, public=published) self.assertIsNotNone(public) self.assertTrue(public.PUBLIC) # its a PublicContent object self.assertEqual(public.type, published.content_type) self.assertEqual(public.current_version, published.sha_public) # test creation of files: self.assertTrue(os.path.isdir(published.get_prod_path())) self.assertTrue( os.path.isfile( os.path.join(published.get_prod_path(), 'manifest.json'))) self.assertTrue( os.path.isfile( os.path.join(public.get_prod_path(), public.introduction))) self.assertTrue( os.path.isfile( os.path.join(public.get_prod_path(), public.conclusion))) self.assertEqual(len(public.children), 2) for child in public.children: self.assertTrue(os.path.isfile( child.get_prod_path())) # an HTML file for each chapter self.assertIsNone(child.introduction) self.assertIsNone(child.conclusion) # 4. Big tutorial: bigtuto = PublishableContentFactory(type='TUTORIAL') bigtuto.authors.add(self.user_author) UserGalleryFactory(gallery=bigtuto.gallery, user=self.user_author, mode='W') bigtuto.licence = self.licence bigtuto.save() # populate with 2 part (1 chapter with 1 extract each) bigtuto_draft = bigtuto.load_version() part1 = ContainerFactory(parent=bigtuto_draft, db_objet=bigtuto) chapter1 = ContainerFactory(parent=part1, db_objet=bigtuto) ExtractFactory(container=chapter1, db_object=bigtuto) part2 = ContainerFactory(parent=bigtuto_draft, db_objet=bigtuto) chapter2 = ContainerFactory(parent=part2, db_objet=bigtuto) ExtractFactory(container=chapter2, db_object=bigtuto) # publish it bigtuto = PublishableContent.objects.get(pk=bigtuto.pk) published = publish_content(bigtuto, bigtuto_draft) self.assertEqual(published.content, bigtuto) self.assertEqual(published.content_pk, bigtuto.pk) self.assertEqual(published.content_type, bigtuto.type) self.assertEqual(published.content_public_slug, bigtuto_draft.slug) self.assertEqual(published.sha_public, bigtuto.sha_draft) public = bigtuto.load_version(sha=published.sha_public, public=published) self.assertIsNotNone(public) self.assertTrue(public.PUBLIC) # its a PublicContent object self.assertEqual(public.type, published.content_type) self.assertEqual(public.current_version, published.sha_public) # test creation of files: self.assertTrue(os.path.isdir(published.get_prod_path())) self.assertTrue( os.path.isfile( os.path.join(published.get_prod_path(), 'manifest.json'))) self.assertTrue( os.path.isfile( os.path.join(public.get_prod_path(), public.introduction))) self.assertTrue( os.path.isfile( os.path.join(public.get_prod_path(), public.conclusion))) self.assertEqual(len(public.children), 2) for part in public.children: self.assertTrue(os.path.isdir( part.get_prod_path())) # a directory for each part # ... and an HTML file for introduction and conclusion self.assertTrue( os.path.isfile( os.path.join(public.get_prod_path(), part.introduction))) self.assertTrue( os.path.isfile( os.path.join(public.get_prod_path(), part.conclusion))) self.assertEqual(len(part.children), 1) for chapter in part.children: # the HTML file is located in the good directory: self.assertEqual(part.get_prod_path(), os.path.dirname(chapter.get_prod_path())) self.assertTrue(os.path.isfile( chapter.get_prod_path())) # an HTML file for each chapter self.assertIsNone(chapter.introduction) self.assertIsNone(chapter.conclusion)
def test_cancel_pick_operation(self): opinion = PublishableContentFactory(type='OPINION') opinion.authors.add(self.user_author) UserGalleryFactory(gallery=opinion.gallery, user=self.user_author, mode='W') opinion.licence = self.licence opinion.save() opinion_draft = opinion.load_version() ExtractFactory(container=opinion_draft, db_object=opinion) ExtractFactory(container=opinion_draft, db_object=opinion) self.assertEqual( self.client.login(username=self.user_author.username, password='******'), True) # publish result = self.client.post(reverse('validation:publish-opinion', kwargs={ 'pk': opinion.pk, 'slug': opinion.slug }), { 'source': '', 'version': opinion_draft.current_version }, follow=False) self.assertEqual(result.status_code, 302) # login as staff self.assertEqual( self.client.login(username=self.user_staff.username, password='******'), True) # PICK result = self.client.post(reverse('validation:pick-opinion', kwargs={ 'pk': opinion.pk, 'slug': opinion.slug }), { 'source': '', 'version': opinion_draft.current_version }, follow=False) self.assertEqual(result.status_code, 302) # cancel the operation operation = PickListOperation.objects.latest('operation_date') result = self.client.post(reverse('validation:revoke-ignore-opinion', kwargs={'pk': operation.pk}), follow=False) self.assertEqual(result.status_code, 200) # refresh operation = PickListOperation.objects.get(pk=operation.pk) opinion = PublishableContent.objects.get(pk=opinion.pk) self.assertFalse(operation.is_effective) self.assertEqual(self.user_staff, operation.canceler_user) self.assertIsNone(opinion.sha_picked) # NO_PICK result = self.client.post(reverse('validation:ignore-opinion', kwargs={ 'pk': opinion.pk, 'slug': opinion.slug }), { 'operation': 'NO_PICK', }, follow=False) self.assertEqual(result.status_code, 200) # cancel the operation operation = PickListOperation.objects.latest('operation_date') result = self.client.post(reverse('validation:revoke-ignore-opinion', kwargs={'pk': operation.pk}), follow=False) self.assertEqual(result.status_code, 200) # check that the opinion is displayed on validation page result = self.client.get(reverse('validation:list-opinion')) self.assertContains(result, opinion.title) # REMOVE_PUB result = self.client.post(reverse('validation:ignore-opinion', kwargs={ 'pk': opinion.pk, 'slug': opinion.slug }), { 'operation': 'REMOVE_PUB', }, follow=False) self.assertEqual(result.status_code, 200) # cancel the operation operation = PickListOperation.objects.latest('operation_date') result = self.client.post(reverse('validation:revoke-ignore-opinion', kwargs={'pk': operation.pk}), follow=False) self.assertEqual(result.status_code, 200) # check that the opinion can be published again result = self.client.post(reverse('validation:publish-opinion', kwargs={ 'pk': opinion.pk, 'slug': opinion.slug }), { 'source': '', 'version': opinion_draft.current_version }, follow=False) self.assertEqual(result.status_code, 302)
class UtilsTests(TestCase): def setUp(self): # don't build PDF to speed up the tests settings.ZDS_APP['content']['build_pdf_when_published'] = False settings.EMAIL_BACKEND = 'django.core.mail.backends.locmem.EmailBackend' self.mas = ProfileFactory().user settings.ZDS_APP['member']['bot_account'] = self.mas.username self.licence = LicenceFactory() self.user_author = ProfileFactory().user self.staff = StaffProfileFactory().user self.tuto = PublishableContentFactory(type='TUTORIAL') self.tuto.authors.add(self.user_author) UserGalleryFactory(gallery=self.tuto.gallery, user=self.user_author, mode='W') self.tuto.licence = self.licence self.tuto.save() self.tuto_draft = self.tuto.load_version() self.part1 = ContainerFactory(parent=self.tuto_draft, db_object=self.tuto) self.chapter1 = ContainerFactory(parent=self.part1, db_object=self.tuto) def test_get_target_tagged_tree_for_container(self): part2 = ContainerFactory(parent=self.tuto_draft, db_object=self.tuto, title="part2") part3 = ContainerFactory(parent=self.tuto_draft, db_object=self.tuto, title="part3") tagged_tree = get_target_tagged_tree_for_container( self.part1, self.tuto_draft) self.assertEqual(4, len(tagged_tree)) paths = {i[0]: i[3] for i in tagged_tree} self.assertTrue(part2.get_path(True) in paths) self.assertTrue(part3.get_path(True) in paths) self.assertTrue(self.chapter1.get_path(True) in paths) self.assertTrue(self.part1.get_path(True) in paths) self.assertFalse(self.tuto_draft.get_path(True) in paths) self.assertFalse(paths[self.chapter1.get_path(True)], "can't be moved to a too deep container") self.assertFalse(paths[self.part1.get_path(True)], "can't be moved after or before himself") self.assertTrue(paths[part2.get_path(True)], "can be moved after or before part2") self.assertTrue(paths[part3.get_path(True)], "can be moved after or before part3") tagged_tree = get_target_tagged_tree_for_container( part3, self.tuto_draft) self.assertEqual(4, len(tagged_tree)) paths = {i[0]: i[3] for i in tagged_tree} self.assertTrue(part2.get_path(True) in paths) self.assertTrue(part3.get_path(True) in paths) self.assertTrue(self.chapter1.get_path(True) in paths) self.assertTrue(self.part1.get_path(True) in paths) self.assertFalse(self.tuto_draft.get_path(True) in paths) self.assertTrue(paths[self.chapter1.get_path(True)], "can't be moved to a too deep container") self.assertTrue(paths[self.part1.get_path(True)], "can't be moved after or before himself") self.assertTrue(paths[part2.get_path(True)], "can be moved after or before part2") self.assertFalse(paths[part3.get_path(True)], "can be moved after or before part3") def test_publish_content(self): """test and ensure the behavior of ``publish_content()`` and ``unpublish_content()``""" # 1. Article: article = PublishableContentFactory(type='ARTICLE') article.authors.add(self.user_author) UserGalleryFactory(gallery=article.gallery, user=self.user_author, mode='W') article.licence = self.licence article.save() # populate the article article_draft = article.load_version() ExtractFactory(container=article_draft, db_object=article) ExtractFactory(container=article_draft, db_object=article) self.assertEqual(len(article_draft.children), 2) # publish ! article = PublishableContent.objects.get(pk=article.pk) published = publish_content(article, article_draft) self.assertEqual(published.content, article) self.assertEqual(published.content_pk, article.pk) self.assertEqual(published.content_type, article.type) self.assertEqual(published.content_public_slug, article_draft.slug) self.assertEqual(published.sha_public, article.sha_draft) public = article.load_version(sha=published.sha_public, public=published) self.assertIsNotNone(public) self.assertTrue(public.PUBLIC) # its a PublicContent object ! self.assertEqual(public.type, published.content_type) self.assertEqual(public.current_version, published.sha_public) # test object created in database self.assertEqual( PublishedContent.objects.filter(content=article).count(), 1) published = PublishedContent.objects.filter(content=article).last() self.assertEqual(published.content_pk, article.pk) self.assertEqual(published.content_public_slug, article_draft.slug) self.assertEqual(published.content_type, article.type) self.assertEqual(published.sha_public, public.current_version) # test creation of files: self.assertTrue(os.path.isdir(published.get_prod_path())) self.assertTrue( os.path.isfile( os.path.join(published.get_prod_path(), 'manifest.json'))) self.assertTrue(os.path.isfile( public.get_prod_path())) # normally, an HTML file should exists self.assertIsNone( public.introduction ) # since all is in the HTML file, introduction does not exists anymore self.assertIsNone(public.conclusion) article.public_version = published article.save() # depublish it ! unpublish_content(article) self.assertEqual( PublishedContent.objects.filter(content=article).count(), 0) # published object disappear self.assertFalse(os.path.exists( public.get_prod_path())) # article was removed # ... For the next tests, I will assume that the unpublication works. # 2. Mini-tutorial → Not tested, because at this point, it's the same as an article (with a different metadata) # 3. Medium-size tutorial midsize_tuto = PublishableContentFactory(type='TUTORIAL') midsize_tuto.authors.add(self.user_author) UserGalleryFactory(gallery=midsize_tuto.gallery, user=self.user_author, mode='W') midsize_tuto.licence = self.licence midsize_tuto.save() # populate with 2 chapters (1 extract each) midsize_tuto_draft = midsize_tuto.load_version() chapter1 = ContainerFactory(parent=midsize_tuto_draft, db_objet=midsize_tuto) ExtractFactory(container=chapter1, db_object=midsize_tuto) chapter2 = ContainerFactory(parent=midsize_tuto_draft, db_objet=midsize_tuto) ExtractFactory(container=chapter2, db_object=midsize_tuto) # publish it midsize_tuto = PublishableContent.objects.get(pk=midsize_tuto.pk) published = publish_content(midsize_tuto, midsize_tuto_draft) self.assertEqual(published.content, midsize_tuto) self.assertEqual(published.content_pk, midsize_tuto.pk) self.assertEqual(published.content_type, midsize_tuto.type) self.assertEqual(published.content_public_slug, midsize_tuto_draft.slug) self.assertEqual(published.sha_public, midsize_tuto.sha_draft) public = midsize_tuto.load_version(sha=published.sha_public, public=published) self.assertIsNotNone(public) self.assertTrue(public.PUBLIC) # its a PublicContent object self.assertEqual(public.type, published.content_type) self.assertEqual(public.current_version, published.sha_public) # test creation of files: self.assertTrue(os.path.isdir(published.get_prod_path())) self.assertTrue( os.path.isfile( os.path.join(published.get_prod_path(), 'manifest.json'))) self.assertTrue( os.path.isfile( os.path.join(public.get_prod_path(), public.introduction))) self.assertTrue( os.path.isfile( os.path.join(public.get_prod_path(), public.conclusion))) self.assertEqual(len(public.children), 2) for child in public.children: self.assertTrue(os.path.isfile( child.get_prod_path())) # an HTML file for each chapter self.assertIsNone(child.introduction) self.assertIsNone(child.conclusion) # 4. Big tutorial: bigtuto = PublishableContentFactory(type='TUTORIAL') bigtuto.authors.add(self.user_author) UserGalleryFactory(gallery=bigtuto.gallery, user=self.user_author, mode='W') bigtuto.licence = self.licence bigtuto.save() # populate with 2 part (1 chapter with 1 extract each) bigtuto_draft = bigtuto.load_version() part1 = ContainerFactory(parent=bigtuto_draft, db_objet=bigtuto) chapter1 = ContainerFactory(parent=part1, db_objet=bigtuto) ExtractFactory(container=chapter1, db_object=bigtuto) part2 = ContainerFactory(parent=bigtuto_draft, db_objet=bigtuto) chapter2 = ContainerFactory(parent=part2, db_objet=bigtuto) ExtractFactory(container=chapter2, db_object=bigtuto) # publish it bigtuto = PublishableContent.objects.get(pk=bigtuto.pk) published = publish_content(bigtuto, bigtuto_draft) self.assertEqual(published.content, bigtuto) self.assertEqual(published.content_pk, bigtuto.pk) self.assertEqual(published.content_type, bigtuto.type) self.assertEqual(published.content_public_slug, bigtuto_draft.slug) self.assertEqual(published.sha_public, bigtuto.sha_draft) public = bigtuto.load_version(sha=published.sha_public, public=published) self.assertIsNotNone(public) self.assertTrue(public.PUBLIC) # its a PublicContent object self.assertEqual(public.type, published.content_type) self.assertEqual(public.current_version, published.sha_public) # test creation of files: self.assertTrue(os.path.isdir(published.get_prod_path())) self.assertTrue( os.path.isfile( os.path.join(published.get_prod_path(), 'manifest.json'))) self.assertTrue( os.path.isfile( os.path.join(public.get_prod_path(), public.introduction))) self.assertTrue( os.path.isfile( os.path.join(public.get_prod_path(), public.conclusion))) self.assertEqual(len(public.children), 2) for part in public.children: self.assertTrue(os.path.isdir( part.get_prod_path())) # a directory for each part # ... and an HTML file for introduction and conclusion self.assertTrue( os.path.isfile( os.path.join(public.get_prod_path(), part.introduction))) self.assertTrue( os.path.isfile( os.path.join(public.get_prod_path(), part.conclusion))) self.assertEqual(len(part.children), 1) for chapter in part.children: # the HTML file is located in the good directory: self.assertEqual(part.get_prod_path(), os.path.dirname(chapter.get_prod_path())) self.assertTrue(os.path.isfile( chapter.get_prod_path())) # an HTML file for each chapter self.assertIsNone(chapter.introduction) self.assertIsNone(chapter.conclusion) def test_tagged_tree_extract(self): midsize = PublishableContentFactory(author_list=[self.user_author]) midsize_draft = midsize.load_version() first_container = ContainerFactory(parent=midsize_draft, db_object=midsize) second_container = ContainerFactory(parent=midsize_draft, db_object=midsize) first_extract = ExtractFactory(container=first_container, db_object=midsize) second_extract = ExtractFactory(container=second_container, db_object=midsize) tagged_tree = get_target_tagged_tree_for_extract( first_extract, midsize_draft) paths = {i[0]: i[3] for i in tagged_tree} self.assertTrue(paths[second_extract.get_full_slug()]) self.assertFalse(paths[second_container.get_path(True)]) self.assertFalse(paths[first_container.get_path(True)]) def test_update_manifest(self): opts = {} shutil.copy( os.path.join(BASE_DIR, "fixtures", "tuto", "balise_audio", "manifest.json"), os.path.join(BASE_DIR, "fixtures", "tuto", "balise_audio", "manifest2.json")) LicenceFactory(code="CC BY") args = [ os.path.join(BASE_DIR, "fixtures", "tuto", "balise_audio", "manifest2.json") ] call_command('upgrade_manifest_to_v2', *args, **opts) manifest = open( os.path.join(BASE_DIR, "fixtures", "tuto", "balise_audio", "manifest2.json"), 'r') json = json_reader.loads(manifest.read()) self.assertTrue(u"version" in json) self.assertTrue(u"licence" in json) self.assertTrue(u"children" in json) self.assertEqual(len(json[u"children"]), 3) self.assertEqual(json[u"children"][0][u"object"], u"extract") os.unlink(args[0]) args = [ os.path.join(BASE_DIR, "fixtures", "tuto", "big_tuto_v1", "manifest2.json") ] shutil.copy( os.path.join(BASE_DIR, "fixtures", "tuto", "big_tuto_v1", "manifest.json"), os.path.join(BASE_DIR, "fixtures", "tuto", "big_tuto_v1", "manifest2.json")) call_command('upgrade_manifest_to_v2', *args, **opts) manifest = open( os.path.join(BASE_DIR, "fixtures", "tuto", "big_tuto_v1", "manifest2.json"), 'r') json = json_reader.loads(manifest.read()) os.unlink(args[0]) self.assertTrue(u"version" in json) self.assertTrue(u"licence" in json) self.assertTrue(u"children" in json) self.assertEqual(len(json[u"children"]), 5) self.assertEqual(json[u"children"][0][u"object"], u"container") self.assertEqual(len(json[u"children"][0][u"children"]), 3) self.assertEqual( len(json[u"children"][0][u"children"][0][u"children"]), 3) args = [ os.path.join(BASE_DIR, "fixtures", "tuto", "article_v1", "manifest2.json") ] shutil.copy( os.path.join(BASE_DIR, "fixtures", "tuto", "article_v1", "manifest.json"), os.path.join(BASE_DIR, "fixtures", "tuto", "article_v1", "manifest2.json")) call_command('upgrade_manifest_to_v2', *args, **opts) manifest = open( os.path.join(BASE_DIR, "fixtures", "tuto", "article_v1", "manifest2.json"), 'r') json = json_reader.loads(manifest.read()) self.assertTrue(u"version" in json) self.assertTrue(u"licence" in json) self.assertTrue(u"children" in json) self.assertEqual(len(json[u"children"]), 1) os.unlink(args[0]) def test_retrieve_images(self): """test the ``retrieve_and_update_images_links()`` function. NOTE: this test require an working internet connection to succeed Also, it was implemented with small images on highly responsive server(s), to make it quick ! """ tempdir = os.path.join(tempfile.gettempdir(), 'test_retrieve_imgs') os.makedirs(tempdir) # image which exists, or not test_images = [ # PNG: ('http://upload.wikimedia.org/wikipedia/en/9/9d/Commons-logo-31px.png', 'Commons-logo-31px.png'), # JPEG: ('http://upload.wikimedia.org/wikipedia/commons/6/6b/01Aso.jpg', '01Aso.jpg'), # Image which does not exists: ('http://test.com/test idiot.png', 'test_idiot.png' ), # NOTE: space changed into `_` ! # SVG (will be converted to png): ('http://upload.wikimedia.org/wikipedia/commons/f/f9/10DF.svg', '10DF.png'), # GIF (will be converted to png): ('http://upload.wikimedia.org/wikipedia/commons/2/27/AnimatedStar.gif', 'AnimatedStar.png'), # local image: ('fixtures/image_test.jpg', 'image_test.jpg') ] # for each of these images, test that the url (and only that) is changed for url, filename in test_images: random_thing = str(datetime.datetime.now( )) # will be used as legend, to ensure that this part remains an_image_link = '![{}]({})'.format(random_thing, url) new_image_url = 'images/{}'.format(filename) new_image_link = '![{}]({})'.format(random_thing, new_image_url) new_md = retrieve_and_update_images_links(an_image_link, tempdir) self.assertTrue( os.path.isfile(os.path.join( tempdir, new_image_url))) # image was retrieved self.assertEqual(new_image_link, new_md) # link was updated # then, ensure that 3 times the same images link make the code use three times the same image ! link = '![{}](http://upload.wikimedia.org/wikipedia/commons/5/56/Asteroid_icon.jpg)' new_link = '![{}](images/Asteroid_icon.jpg)' three_times = ' '.join([link.format(i) for i in range(0, 2)]) three_times_updated = ' '.join( [new_link.format(i) for i in range(0, 2)]) new_md = retrieve_and_update_images_links(three_times, tempdir) self.assertEqual(three_times_updated, new_md) # ensure that the original file is deleted if any another_svg = '![](http://upload.wikimedia.org/wikipedia/commons/3/32/Arrow.svg)' new_md = retrieve_and_update_images_links(another_svg, tempdir) self.assertEqual('![](images/Arrow.png)', new_md) self.assertTrue( os.path.isfile(os.path.join( tempdir, 'images/Arrow.png'))) # image was converted in PNG self.assertFalse( os.path.isfile(os.path.join( tempdir, 'images/Arrow.svg'))) # and the original SVG was deleted # finally, clean up: shutil.rmtree(tempdir) def test_migrate_zep12(self): private_mini_tuto = MiniTutorialFactory(title="Private Mini tuto") private_mini_tuto.authors.add(self.user_author) private_mini_tuto.save() multi_author_tuto = MiniTutorialFactory(title="Multi User Tuto") multi_author_tuto.authors.add(self.user_author) multi_author_tuto.authors.add(self.staff) multi_author_tuto.save() public_mini_tuto = PublishedMiniTutorial(title="Public Mini Tuto") public_mini_tuto.authors.add(self.user_author) public_mini_tuto.save() OldTutoValidation( tutorial=public_mini_tuto, version=public_mini_tuto.sha_public, date_proposition=datetime.datetime.now(), comment_authors=u"La vie est belle, le destin s'en écarte.", comment_validator=u"Personne ne joue avec les mêmes cartes.", validator=self.staff, status="ACCEPT", date_reserve=datetime.datetime.now(), date_validation=datetime.datetime.now()).save() staff_note = NoteFactory(tutorial=public_mini_tuto, position=1, author=self.staff) liked_note = NoteFactory(tutorial=public_mini_tuto, position=2, author=self.user_author) t_read = TutorialRead() t_read.tutorial = public_mini_tuto t_read.user = self.staff t_read.note = staff_note t_read.save() like = CommentLike() like.comments = liked_note like.user = self.staff like.save() big_tuto = BigTutorialFactory(title="Big tuto") big_tuto.authors.add(self.user_author) big_tuto.save() public_big_tuto = PublishedBigTutorial(light=False, title="Public Big Tuto") public_big_tuto.authors.add(self.user_author) public_big_tuto.save() private_article = ArticleFactory(title="Private Article") private_article.authors.add(self.user_author) private_article.save() multi_author_article = ArticleFactory(title="Multi Author Article") multi_author_article.authors.add(self.user_author) multi_author_article.authors.add(self.staff) multi_author_article.save() public_article = PublishedArticleFactory(title="Public Article") public_article.authors.add(self.user_author) public_article.save() OldArticleValidation( article=public_article, version=public_article.sha_public, date_proposition=datetime.datetime.now(), comment_authors=u"Pourquoi fortune et infortune?", comment_validator=u"Pourquoi suis-je né les poches vides?", validator=self.staff, status="ACCEPT", date_reserve=datetime.datetime.now(), date_validation=datetime.datetime.now()).save() staff_note = ReactionFactory(article=public_article, position=1, author=self.staff) liked_reaction = ReactionFactory(article=public_article, position=2, author=self.user_author) a_read = ArticleRead() a_read.article = public_article a_read.user = self.staff a_read.reaction = staff_note a_read.save() like = CommentLike() like.comments = liked_reaction like.user = self.staff like.save() category1 = CategoryFactory(position=1) forum11 = ForumFactory(category=category1, position_in_category=1) beta_tuto = BetaMiniTutorialFactory(title=u"Beta Tuto", forum=forum11, author=self.user_author) beta_tuto.authors.add(self.user_author) beta_tuto.save() call_command('migrate_to_zep12') # 1 tuto in setup, 4 mini tutos, 1 big tuto, 3 articles self.assertEqual( PublishableContent.objects.filter( authors__pk__in=[self.user_author.pk]).count(), 10) # if we had n published content we must have 2 * n PublishedContent entities to handle redirections. self.assertEqual( PublishedContent.objects.filter( content__authors__pk__in=[self.user_author.pk]).count(), 2 * 3) self.assertEqual( ContentReaction.objects.filter(author__pk=self.staff.pk).count(), 2) migrated_pulished_article = PublishableContent.objects.filter( authors__in=[self.user_author], title=public_article.title, type="ARTICLE").first() self.assertIsNotNone(migrated_pulished_article) self.assertIsNotNone(migrated_pulished_article.last_note) self.assertEqual( 2, ContentReaction.objects.filter( related_content=migrated_pulished_article).count()) self.assertEqual( 1, ContentRead.objects.filter( content=migrated_pulished_article).count()) self.assertTrue( migrated_pulished_article.is_public( migrated_pulished_article.sha_public)) self.assertTrue( migrated_pulished_article.load_version( migrated_pulished_article.sha_public).has_extracts()) self.assertEqual( len( migrated_pulished_article.load_version( migrated_pulished_article.sha_public).children), 2) migrated_pulished_tuto = PublishableContent.objects.filter( authors__in=[self.user_author], title=public_mini_tuto.title, type="TUTORIAL").first() self.assertIsNotNone(migrated_pulished_tuto) self.assertIsNotNone(migrated_pulished_tuto.last_note) self.assertEqual( 2, ContentReaction.objects.filter( related_content=migrated_pulished_tuto).count()) self.assertEqual( 1, ContentRead.objects.filter(content=migrated_pulished_tuto).count()) self.assertTrue( migrated_pulished_tuto.is_public( migrated_pulished_tuto.sha_public)) beta_content = PublishableContent.objects.filter( title=beta_tuto.title).first() self.assertIsNotNone(beta_content) self.assertEqual(beta_content.sha_beta, beta_tuto.sha_beta) self.assertEqual( Topic.objects.filter(key=beta_tuto.pk).first().pk, beta_content.beta_topic.pk) multi_author_content = PublishableContent.objects.filter(type="TUTORIAL", title=multi_author_tuto.title)\ .first() self.assertIsNotNone(multi_author_content) self.assertEqual(multi_author_content.authors.count(), multi_author_tuto.authors.count()) multi_author_content = PublishableContent.objects.filter(type="ARTICLE", title=multi_author_article.title)\ .first() self.assertIsNotNone(multi_author_content) self.assertEqual(multi_author_content.authors.count(), multi_author_article.authors.count()) old_tutorial_module_prefix = "oldtutoriels" old_article_module_prefix = "oldarticles" new_tutorial_module_prefix = "tutoriels" new_article_module_prefix = "articles" public_article_url = public_article.get_absolute_url_online()\ .replace(old_article_module_prefix, new_article_module_prefix) public_tutorial_url = public_mini_tuto.get_absolute_url_online()\ .replace(old_tutorial_module_prefix, new_tutorial_module_prefix) self.assertEqual(301, self.client.get(public_article_url).status_code) self.assertEqual(301, self.client.get(public_tutorial_url).status_code) public_chapter = Chapter.objects.filter( part__tutorial__pk=public_big_tuto.pk).first() self.assertIsNotNone(public_chapter) public_chapter_url = public_chapter.get_absolute_url_online() public_chapter_url = public_chapter_url.replace( old_tutorial_module_prefix, new_tutorial_module_prefix) self.assertEqual(301, self.client.get(public_chapter_url).status_code) self.assertEqual( 200, self.client.get(public_chapter_url, follow=True).status_code) self.assertEqual( 200, self.client.get(public_article_url, follow=True).status_code) self.assertEqual( 200, self.client.get(public_tutorial_url, follow=True).status_code) tuto_validation = Validation.objects.filter( content__pk=migrated_pulished_tuto.pk).first() self.assertIsNotNone(tuto_validation) self.assertEqual(tuto_validation.status, "ACCEPT") self.assertEqual(tuto_validation.validator.pk, self.staff.pk) article_validation = Validation.objects.filter( content__pk=migrated_pulished_article.pk).first() self.assertIsNotNone(article_validation) self.assertEqual(article_validation.status, "ACCEPT") self.assertEqual(article_validation.validator.pk, self.staff.pk) def test_generate_pdf(self): """ensure the behavior of the `python manage.py generate_pdf` commmand""" settings.ZDS_APP['content'][ 'build_pdf_when_published'] = True # this test need PDF build, if any tuto = PublishedContentFactory( type='TUTORIAL') # generate and publish a tutorial published = PublishedContent.objects.get(content_pk=tuto.pk) tuto2 = PublishedContentFactory( type='TUTORIAL') # generate and publish a second tutorial published2 = PublishedContent.objects.get(content_pk=tuto2.pk) # ensure that PDF exists in the first place self.assertTrue(published.have_pdf()) self.assertTrue(published2.have_pdf()) pdf_path = os.path.join(published.get_extra_contents_directory(), published.content_public_slug + '.pdf') pdf_path2 = os.path.join(published2.get_extra_contents_directory(), published2.content_public_slug + '.pdf') self.assertTrue(os.path.exists(pdf_path)) self.assertTrue(os.path.exists(pdf_path2)) # 1. re-generate (all) PDFs os.remove(pdf_path) os.remove(pdf_path2) self.assertFalse(os.path.exists(pdf_path)) self.assertFalse(os.path.exists(pdf_path2)) call_command('generate_pdf') self.assertTrue(os.path.exists(pdf_path)) self.assertTrue(os.path.exists(pdf_path2)) # both PDFs are generated # 2. re-generate a given PDF os.remove(pdf_path) os.remove(pdf_path2) self.assertFalse(os.path.exists(pdf_path)) self.assertFalse(os.path.exists(pdf_path2)) call_command('generate_pdf', 'id={}'.format(tuto.pk)) self.assertTrue(os.path.exists(pdf_path)) self.assertFalse( os.path.exists(pdf_path2)) # only the first PDF is generated # 3. re-generate a given PDF with a wrong id os.remove(pdf_path) self.assertFalse(os.path.exists(pdf_path)) self.assertFalse(os.path.exists(pdf_path2)) call_command('generate_pdf', 'id=-1') # There is no content with pk=-1 self.assertFalse(os.path.exists(pdf_path)) self.assertFalse(os.path.exists(pdf_path2)) # so no PDF is generated ! def tearDown(self): if os.path.isdir(settings.ZDS_APP['content']['repo_private_path']): shutil.rmtree(settings.ZDS_APP['content']['repo_private_path']) if os.path.isdir(settings.ZDS_APP['content']['repo_public_path']): shutil.rmtree(settings.ZDS_APP['content']['repo_public_path']) if os.path.isdir(settings.MEDIA_ROOT): shutil.rmtree(settings.MEDIA_ROOT) if os.path.isdir(settings.ZDS_APP['tutorial']['repo_path']): shutil.rmtree(settings.ZDS_APP['tutorial']['repo_path']) if os.path.isdir(settings.ZDS_APP['tutorial']['repo_public_path']): shutil.rmtree(settings.ZDS_APP['tutorial']['repo_public_path']) if os.path.isdir(settings.ZDS_APP['article']['repo_path']): shutil.rmtree(settings.ZDS_APP['article']['repo_path']) # re-active PDF build settings.ZDS_APP['content']['build_pdf_when_published'] = True
def test_opinion_alert(self): """Test content alert""" text_publication = 'Aussi tôt dit, aussi tôt fait !' opinion = PublishableContentFactory(type='OPINION') opinion.authors.add(self.user_author) UserGalleryFactory(gallery=opinion.gallery, user=self.user_author, mode='W') opinion.licence = self.licence opinion.save() opinion_draft = opinion.load_version() ExtractFactory(container=opinion_draft, db_object=opinion) ExtractFactory(container=opinion_draft, db_object=opinion) self.assertEqual( self.client.login(username=self.user_author.username, password='******'), True) result = self.client.post(reverse('validation:publish-opinion', kwargs={ 'pk': opinion.pk, 'slug': opinion.slug }), { 'text': text_publication, 'source': '', 'version': opinion_draft.current_version }, follow=False) self.assertEqual(result.status_code, 302) self.assertEqual(PublishedContent.objects.count(), 1) opinion = PublishableContent.objects.get(pk=opinion.pk) self.assertIsNotNone(opinion.public_version) self.assertEqual(opinion.public_version.sha_public, opinion_draft.current_version) # Alert content random_user = ProfileFactory().user self.assertEqual( self.client.login(username=random_user.username, password='******'), True) result = self.client.post(reverse('content:alert-content', kwargs={'pk': opinion.pk}), {'signal_text': 'Yeurk !'}, follow=False) self.assertEqual(result.status_code, 302) self.assertIsNotNone( Alert.objects.filter(author__pk=random_user.pk, content__pk=opinion.pk).first()) alert = Alert.objects.filter(author__pk=random_user.pk, content__pk=opinion.pk).first() self.assertFalse(alert.solved) result = self.client.post(reverse('content:resolve-content', kwargs={'pk': opinion.pk}), { 'alert_pk': alert.pk, 'text': 'Je peux ?' }, follow=False) self.assertEqual(result.status_code, 403) # solving the alert by yourself wont work alert = Alert.objects.get(pk=alert.pk) self.assertFalse(alert.solved) self.assertEqual( self.client.login(username=self.user_staff.username, password='******'), True) result = self.client.post(reverse('content:resolve-content', kwargs={'pk': opinion.pk}), { 'alert_pk': alert.pk, 'text': 'Anéfé!' }, follow=False) self.assertEqual(result.status_code, 302) alert = Alert.objects.get(pk=alert.pk) self.assertTrue(alert.solved)
def test_move_extract_before(self): # test 1 : move extract after a sibling # login with author self.assertEqual( self.client.login( username=self.user_author.username, password='******'), True) tuto = PublishableContent.objects.get(pk=self.tuto.pk) self.extract2 = ExtractFactory(container=self.chapter1, db_object=self.tuto) self.extract3 = ExtractFactory(container=self.chapter1, db_object=self.tuto) old_sha = tuto.sha_draft # test moving smoothly result = self.client.post( reverse('content:move-element'), { 'child_slug': self.extract1.slug, 'container_slug': self.chapter1.slug, 'first_level_slug': self.part1.slug, 'moving_method': 'before:' + self.extract3.get_path(True)[:-3], 'pk': tuto.pk }, follow=True) self.assertEqual(200, result.status_code) self.assertNotEqual(old_sha, PublishableContent.objects.get(pk=tuto.pk).sha_draft) versioned = PublishableContent.objects.get(pk=tuto.pk).load_version() extract = versioned.children_dict[self.part1.slug].children_dict[self.chapter1.slug].children[0] self.assertEqual(self.extract2.slug, extract.slug) tuto = PublishableContent.objects.get(pk=self.tuto.pk) old_sha = tuto.sha_draft # test changing parent for extract (smoothly) self.chapter2 = ContainerFactory(parent=self.part1, db_object=self.tuto) self.extract4 = ExtractFactory(container=self.chapter2, db_object=self.tuto) result = self.client.post( reverse('content:move-element'), { 'child_slug': self.extract1.slug, 'container_slug': self.chapter1.slug, 'first_level_slug': self.part1.slug, 'moving_method': 'before:' + self.extract4.get_full_slug(), 'pk': tuto.pk }, follow=True) self.assertEqual(200, result.status_code) self.assertNotEqual(old_sha, PublishableContent.objects.get(pk=tuto.pk).sha_draft) versioned = PublishableContent.objects.get(pk=tuto.pk).load_version() extract = versioned.children_dict[self.part1.slug].children_dict[self.chapter2.slug].children[0] self.assertEqual(self.extract1.slug, extract.slug) extract = versioned.children_dict[self.part1.slug].children_dict[self.chapter2.slug].children[1] self.assertEqual(self.extract4.slug, extract.slug) self.assertEqual(2, len(versioned.children_dict[self.part1.slug].children_dict[self.chapter1.slug].children)) # test changing parents on a 'midsize content' (i.e depth of 1) midsize = PublishableContentFactory(author_list=[self.user_author]) midsize_draft = midsize.load_version() first_container = ContainerFactory(parent=midsize_draft, db_object=midsize) second_container = ContainerFactory(parent=midsize_draft, db_object=midsize) first_extract = ExtractFactory(container=first_container, db_object=midsize) second_extract = ExtractFactory(container=second_container, db_object=midsize) result = self.client.post( reverse('content:move-element'), { 'child_slug': first_extract.slug, 'container_slug': first_container.get_path(True), 'first_level_slug': '', 'moving_method': 'before:' + second_extract.get_full_slug(), 'pk': midsize.pk }, follow=True) self.assertEqual(result.status_code, 200) self.assertFalse(isfile(first_extract.get_path(True))) midsize = PublishableContent.objects.filter(pk=midsize.pk).first() midsize_draft = midsize.load_version() second_container_draft = midsize_draft.children[1] self.assertEqual(second_container_draft.children[0].title, first_extract.title) self.assertTrue(second_container_draft.children[0].get_path(False)) # test try to move to a container that can't get extract tuto = PublishableContent.objects.get(pk=self.tuto.pk) old_sha = tuto.sha_draft result = self.client.post( reverse('content:move-element'), { 'child_slug': self.extract1.slug, 'container_slug': self.chapter2.slug, 'first_level_slug': self.part1.slug, 'moving_method': 'before:' + self.chapter1.get_path(True), 'pk': tuto.pk }, follow=True) self.assertEqual(200, result.status_code) self.assertEqual(old_sha, PublishableContent.objects.get(pk=tuto.pk).sha_draft) versioned = PublishableContent.objects.get(pk=tuto.pk).load_version() extract = versioned.children_dict[self.part1.slug].children_dict[self.chapter2.slug].children[0] self.assertEqual(self.extract1.slug, extract.slug) extract = versioned.children_dict[self.part1.slug].children_dict[self.chapter2.slug].children[1] self.assertEqual(self.extract4.slug, extract.slug) self.assertEqual(2, len(versioned.children_dict[self.part1.slug].children_dict[self.chapter1.slug].children)) # test try to move near an extract that does not exist tuto = PublishableContent.objects.get(pk=self.tuto.pk) old_sha = tuto.sha_draft result = self.client.post( reverse('content:move-element'), { 'child_slug': self.extract1.slug, 'container_slug': self.chapter2.slug, 'first_level_slug': self.part1.slug, 'moving_method': 'before:' + self.chapter1.get_path(True) + '/un-mauvais-extrait', 'pk': tuto.pk }, follow=True) self.assertEqual(404, result.status_code) self.assertEqual(old_sha, PublishableContent.objects.get(pk=tuto.pk).sha_draft) versioned = PublishableContent.objects.get(pk=tuto.pk).load_version() extract = versioned.children_dict[self.part1.slug].children_dict[self.chapter2.slug].children[0] self.assertEqual(self.extract1.slug, extract.slug) extract = versioned.children_dict[self.part1.slug].children_dict[self.chapter2.slug].children[1] self.assertEqual(self.extract4.slug, extract.slug) self.assertEqual(2, len(versioned.children_dict[self.part1.slug].children_dict[self.chapter1.slug].children))
def test_category_and_subcategory_impact_search(self): """If two contents do not belong to the same (sub)category""" if not self.manager.connected_to_es: return text = 'Did you ever hear the tragedy of Darth Plagueis The Wise?' # 1. Create two contents with different subcategories category_1 = 'category 1' subcategory_1 = SubCategoryFactory(title=category_1) category_2 = 'category 2' subcategory_2 = SubCategoryFactory(title=category_2) tuto_1 = PublishableContentFactory(type='TUTORIAL') tuto_1_draft = tuto_1.load_version() tuto_1.title = text tuto_1.authors.add(self.user) tuto_1.subcategory.add(subcategory_1) tuto_1.save() tuto_1_draft.description = text tuto_1_draft.repo_update_top_container(text, tuto_1.slug, text, text) chapter_1 = ContainerFactory(parent=tuto_1_draft, db_object=tuto_1) extract_1 = ExtractFactory(container=chapter_1, db_object=tuto_1) extract_1.repo_update(text, text) published_1 = publish_content(tuto_1, tuto_1_draft, is_major_update=True) tuto_1.sha_public = tuto_1_draft.current_version tuto_1.sha_draft = tuto_1_draft.current_version tuto_1.public_version = published_1 tuto_1.save() tuto_2 = PublishableContentFactory(type='TUTORIAL') tuto_2_draft = tuto_2.load_version() tuto_2.title = text tuto_2.authors.add(self.user) tuto_2.subcategory.add(subcategory_2) tuto_2.save() tuto_2_draft.description = text tuto_2_draft.repo_update_top_container(text, tuto_2.slug, text, text) chapter_2 = ContainerFactory(parent=tuto_2_draft, db_object=tuto_2) extract_2 = ExtractFactory(container=chapter_2, db_object=tuto_2) extract_2.repo_update(text, text) published_2 = publish_content(tuto_2, tuto_2_draft, is_major_update=True) tuto_2.sha_public = tuto_2_draft.current_version tuto_2.sha_draft = tuto_2_draft.current_version tuto_2.public_version = published_2 tuto_2.save() # 2. Index: self.assertEqual(len(self.manager.setup_search(Search().query(MatchAll())).execute()), 0) # index for model in self.indexable: if model is FakeChapter: continue self.manager.es_bulk_indexing_of_model(model) self.manager.refresh_index() result = self.client.get(reverse('search:query') + '?q=' + text, follow=False) self.assertEqual(result.status_code, 200) response = result.context['object_list'].execute() self.assertEqual(response.hits.total, 4) # Ok # 3. Test result = self.client.get( reverse('search:query') + '?q=' + text + '&model=content&subcategory=' + subcategory_1.slug, follow=False) self.assertEqual(result.status_code, 200) response = result.context['object_list'].execute() self.assertEqual(response.hits.total, 2) self.assertEqual([int(r.meta.id) for r in response if r.meta.doc_type == 'publishedcontent'][0], published_1.pk) self.assertEqual( [r.meta.id for r in response if r.meta.doc_type == 'chapter'][0], tuto_1.slug + '__' + chapter_1.slug) result = self.client.get( reverse('search:query') + '?q=' + text + '&model=content&subcategory=' + subcategory_2.slug, follow=False) self.assertEqual(result.status_code, 200) response = result.context['object_list'].execute() self.assertEqual(response.hits.total, 2) self.assertEqual([int(r.meta.id) for r in response if r.meta.doc_type == 'publishedcontent'][0], published_2.pk) self.assertEqual( [r.meta.id for r in response if r.meta.doc_type == 'chapter'][0], tuto_2.slug + '__' + chapter_2.slug)
class ContentMoveTests(TutorialTestMixin, TestCase): def setUp(self): self.staff = StaffProfileFactory().user settings.EMAIL_BACKEND = 'django.core.mail.backends.locmem.EmailBackend' self.mas = ProfileFactory().user self.overridden_zds_app['member']['bot_account'] = self.mas.username self.licence = LicenceFactory() self.subcategory = SubCategoryFactory() self.user_author = ProfileFactory().user self.user_staff = StaffProfileFactory().user self.user_guest = ProfileFactory().user self.tuto = PublishableContentFactory(type='TUTORIAL') self.tuto.authors.add(self.user_author) UserGalleryFactory(gallery=self.tuto.gallery, user=self.user_author, mode='W') self.tuto.licence = self.licence self.tuto.subcategory.add(self.subcategory) self.tuto.save() self.beta_forum = ForumFactory( pk=self.overridden_zds_app['forum']['beta_forum_id'], category=CategoryFactory(position=1), position_in_category=1) # ensure that the forum, for the beta versions, is created self.tuto_draft = self.tuto.load_version() self.part1 = ContainerFactory(parent=self.tuto_draft, db_object=self.tuto) self.chapter1 = ContainerFactory(parent=self.part1, db_object=self.tuto) self.extract1 = ExtractFactory(container=self.chapter1, db_object=self.tuto) bot = Group(name=self.overridden_zds_app['member']['bot_group']) bot.save() def test_move_up_extract(self): # login with author self.assertEqual( self.client.login( username=self.user_author.username, password='******'), True) tuto = PublishableContent.objects.get(pk=self.tuto.pk) self.extract2 = ExtractFactory(container=self.chapter1, db_object=self.tuto) old_sha = tuto.sha_draft # test moving up smoothly result = self.client.post( reverse('content:move-element'), { 'child_slug': self.extract2.slug, 'container_slug': self.chapter1.slug, 'first_level_slug': self.part1.slug, 'moving_method': 'up', 'pk': tuto.pk }, follow=True) self.assertEqual(200, result.status_code) self.assertNotEqual(old_sha, PublishableContent.objects.get(pk=tuto.pk).sha_draft) versioned = PublishableContent.objects.get(pk=tuto.pk).load_version() extract = versioned.children_dict[self.part1.slug].children_dict[self.chapter1.slug].children[0] self.assertEqual(self.extract2.slug, extract.slug) # test moving up the first element tuto = PublishableContent.objects.get(pk=self.tuto.pk) old_sha = tuto.sha_draft result = self.client.post( reverse('content:move-element'), { 'child_slug': self.extract2.slug, 'container_slug': self.chapter1.slug, 'first_level_slug': self.part1.slug, 'moving_method': 'up', 'pk': tuto.pk }, follow=True) self.assertEqual(200, result.status_code) self.assertEqual(old_sha, PublishableContent.objects.get(pk=tuto.pk).sha_draft) versioned = PublishableContent.objects.get(pk=tuto.pk).load_version() extract = versioned.children_dict[self.part1.slug]\ .children_dict[self.chapter1.slug].children_dict[self.extract2.slug] self.assertEqual(1, extract.position_in_parent) # test moving without permission self.client.logout() self.assertEqual( self.client.login( username=self.user_guest.username, password='******'), True) result = self.client.post( reverse('content:move-element'), { 'child_slug': self.extract2.slug, 'container_slug': self.chapter1.slug, 'first_level_slug': self.part1.slug, 'moving_method': 'up', 'pk': tuto.pk }, follow=False) self.assertEqual(result.status_code, 403) def test_move_extract_before(self): # test 1 : move extract after a sibling # login with author self.assertEqual( self.client.login( username=self.user_author.username, password='******'), True) tuto = PublishableContent.objects.get(pk=self.tuto.pk) self.extract2 = ExtractFactory(container=self.chapter1, db_object=self.tuto) self.extract3 = ExtractFactory(container=self.chapter1, db_object=self.tuto) old_sha = tuto.sha_draft # test moving smoothly result = self.client.post( reverse('content:move-element'), { 'child_slug': self.extract1.slug, 'container_slug': self.chapter1.slug, 'first_level_slug': self.part1.slug, 'moving_method': 'before:' + self.extract3.get_path(True)[:-3], 'pk': tuto.pk }, follow=True) self.assertEqual(200, result.status_code) self.assertNotEqual(old_sha, PublishableContent.objects.get(pk=tuto.pk).sha_draft) versioned = PublishableContent.objects.get(pk=tuto.pk).load_version() extract = versioned.children_dict[self.part1.slug].children_dict[self.chapter1.slug].children[0] self.assertEqual(self.extract2.slug, extract.slug) tuto = PublishableContent.objects.get(pk=self.tuto.pk) old_sha = tuto.sha_draft # test changing parent for extract (smoothly) self.chapter2 = ContainerFactory(parent=self.part1, db_object=self.tuto) self.extract4 = ExtractFactory(container=self.chapter2, db_object=self.tuto) result = self.client.post( reverse('content:move-element'), { 'child_slug': self.extract1.slug, 'container_slug': self.chapter1.slug, 'first_level_slug': self.part1.slug, 'moving_method': 'before:' + self.extract4.get_full_slug(), 'pk': tuto.pk }, follow=True) self.assertEqual(200, result.status_code) self.assertNotEqual(old_sha, PublishableContent.objects.get(pk=tuto.pk).sha_draft) versioned = PublishableContent.objects.get(pk=tuto.pk).load_version() extract = versioned.children_dict[self.part1.slug].children_dict[self.chapter2.slug].children[0] self.assertEqual(self.extract1.slug, extract.slug) extract = versioned.children_dict[self.part1.slug].children_dict[self.chapter2.slug].children[1] self.assertEqual(self.extract4.slug, extract.slug) self.assertEqual(2, len(versioned.children_dict[self.part1.slug].children_dict[self.chapter1.slug].children)) # test changing parents on a 'midsize content' (i.e depth of 1) midsize = PublishableContentFactory(author_list=[self.user_author]) midsize_draft = midsize.load_version() first_container = ContainerFactory(parent=midsize_draft, db_object=midsize) second_container = ContainerFactory(parent=midsize_draft, db_object=midsize) first_extract = ExtractFactory(container=first_container, db_object=midsize) second_extract = ExtractFactory(container=second_container, db_object=midsize) result = self.client.post( reverse('content:move-element'), { 'child_slug': first_extract.slug, 'container_slug': first_container.get_path(True), 'first_level_slug': '', 'moving_method': 'before:' + second_extract.get_full_slug(), 'pk': midsize.pk }, follow=True) self.assertEqual(result.status_code, 200) self.assertFalse(isfile(first_extract.get_path(True))) midsize = PublishableContent.objects.filter(pk=midsize.pk).first() midsize_draft = midsize.load_version() second_container_draft = midsize_draft.children[1] self.assertEqual(second_container_draft.children[0].title, first_extract.title) self.assertTrue(second_container_draft.children[0].get_path(False)) # test try to move to a container that can't get extract tuto = PublishableContent.objects.get(pk=self.tuto.pk) old_sha = tuto.sha_draft result = self.client.post( reverse('content:move-element'), { 'child_slug': self.extract1.slug, 'container_slug': self.chapter2.slug, 'first_level_slug': self.part1.slug, 'moving_method': 'before:' + self.chapter1.get_path(True), 'pk': tuto.pk }, follow=True) self.assertEqual(200, result.status_code) self.assertEqual(old_sha, PublishableContent.objects.get(pk=tuto.pk).sha_draft) versioned = PublishableContent.objects.get(pk=tuto.pk).load_version() extract = versioned.children_dict[self.part1.slug].children_dict[self.chapter2.slug].children[0] self.assertEqual(self.extract1.slug, extract.slug) extract = versioned.children_dict[self.part1.slug].children_dict[self.chapter2.slug].children[1] self.assertEqual(self.extract4.slug, extract.slug) self.assertEqual(2, len(versioned.children_dict[self.part1.slug].children_dict[self.chapter1.slug].children)) # test try to move near an extract that does not exist tuto = PublishableContent.objects.get(pk=self.tuto.pk) old_sha = tuto.sha_draft result = self.client.post( reverse('content:move-element'), { 'child_slug': self.extract1.slug, 'container_slug': self.chapter2.slug, 'first_level_slug': self.part1.slug, 'moving_method': 'before:' + self.chapter1.get_path(True) + '/un-mauvais-extrait', 'pk': tuto.pk }, follow=True) self.assertEqual(404, result.status_code) self.assertEqual(old_sha, PublishableContent.objects.get(pk=tuto.pk).sha_draft) versioned = PublishableContent.objects.get(pk=tuto.pk).load_version() extract = versioned.children_dict[self.part1.slug].children_dict[self.chapter2.slug].children[0] self.assertEqual(self.extract1.slug, extract.slug) extract = versioned.children_dict[self.part1.slug].children_dict[self.chapter2.slug].children[1] self.assertEqual(self.extract4.slug, extract.slug) self.assertEqual(2, len(versioned.children_dict[self.part1.slug].children_dict[self.chapter1.slug].children)) def test_move_container_before(self): # login with author self.assertEqual( self.client.login( username=self.user_author.username, password='******'), True) tuto = PublishableContent.objects.get(pk=self.tuto.pk) self.chapter2 = ContainerFactory(parent=self.part1, db_object=self.tuto) self.chapter3 = ContainerFactory(parent=self.part1, db_object=self.tuto) self.part2 = ContainerFactory(parent=self.tuto_draft, db_object=self.tuto) self.chapter4 = ContainerFactory(parent=self.part2, db_object=self.tuto) self.extract5 = ExtractFactory(container=self.chapter3, db_object=self.tuto) tuto = PublishableContent.objects.get(pk=self.tuto.pk) old_sha = tuto.sha_draft # test changing parent for container (smoothly) result = self.client.post( reverse('content:move-element'), { 'child_slug': self.chapter3.slug, 'container_slug': self.part1.slug, 'first_level_slug': '', 'moving_method': 'before:' + self.chapter4.get_path(True), 'pk': tuto.pk }, follow=True) self.assertEqual(200, result.status_code) self.assertNotEqual(old_sha, PublishableContent.objects.get(pk=tuto.pk).sha_draft) versioned = PublishableContent.objects.get(pk=tuto.pk).load_version() self.assertEqual(2, len(versioned.children_dict[self.part2.slug].children)) chapter = versioned.children_dict[self.part2.slug].children[0] self.assertTrue(isdir(chapter.get_path())) self.assertEqual(1, len(chapter.children)) self.assertTrue(isfile(chapter.children[0].get_path())) self.assertEqual(self.extract5.slug, chapter.children[0].slug) self.assertEqual(self.chapter3.slug, chapter.slug) chapter = versioned.children_dict[self.part2.slug].children[1] self.assertEqual(self.chapter4.slug, chapter.slug) # test changing parent for too deep container tuto = PublishableContent.objects.get(pk=self.tuto.pk) old_sha = tuto.sha_draft result = self.client.post( reverse('content:move-element'), { 'child_slug': self.part1.slug, 'container_slug': self.tuto.slug, 'first_level_slug': '', 'moving_method': 'before:' + self.chapter4.get_path(True), 'pk': tuto.pk }, follow=True) self.assertEqual(200, result.status_code) self.assertEqual(old_sha, PublishableContent.objects.get(pk=tuto.pk).sha_draft) versioned = PublishableContent.objects.get(pk=tuto.pk).load_version() self.assertEqual(2, len(versioned.children_dict[self.part2.slug].children)) chapter = versioned.children_dict[self.part2.slug].children[0] self.assertEqual(self.chapter3.slug, chapter.slug) chapter = versioned.children_dict[self.part2.slug].children[1] self.assertEqual(self.chapter4.slug, chapter.slug) # test moving before the root tuto = PublishableContent.objects.get(pk=self.tuto.pk) old_sha = tuto.sha_draft result = self.client.post( reverse('content:move-element'), { 'child_slug': self.part1.slug, 'container_slug': self.tuto.slug, 'first_level_slug': '', 'moving_method': 'before:' + self.tuto.load_version().get_path(), 'pk': tuto.pk }, follow=True) self.assertEqual(404, result.status_code) self.assertEqual(old_sha, PublishableContent.objects.get(pk=tuto.pk).sha_draft) versioned = PublishableContent.objects.get(pk=tuto.pk).load_version() self.assertEqual(2, len(versioned.children_dict[self.part2.slug].children)) chapter = versioned.children_dict[self.part2.slug].children[0] self.assertEqual(self.chapter3.slug, chapter.slug) chapter = versioned.children_dict[self.part2.slug].children[1] self.assertEqual(self.chapter4.slug, chapter.slug) # test moving without permission self.client.logout() self.assertEqual( self.client.login( username=self.user_guest.username, password='******'), True) result = self.client.post( reverse('content:move-element'), { 'child_slug': self.chapter2.slug, 'container_slug': self.chapter1.slug, 'first_level_slug': self.part1.slug, 'moving_method': 'up', 'pk': tuto.pk }, follow=False) self.assertEqual(result.status_code, 403) def test_move_extract_after(self): # test 1 : move extract after a sibling # login with author self.assertEqual( self.client.login( username=self.user_author.username, password='******'), True) tuto = PublishableContent.objects.get(pk=self.tuto.pk) self.extract2 = ExtractFactory(container=self.chapter1, db_object=self.tuto) self.extract3 = ExtractFactory(container=self.chapter1, db_object=self.tuto) old_sha = tuto.sha_draft # test moving smoothly result = self.client.post( reverse('content:move-element'), { 'child_slug': self.extract1.slug, 'container_slug': self.chapter1.slug, 'first_level_slug': self.part1.slug, 'moving_method': 'after:' + self.extract3.get_path(True)[:-3], 'pk': tuto.pk }, follow=True) self.assertEqual(200, result.status_code) self.assertNotEqual(old_sha, PublishableContent.objects.get(pk=tuto.pk).sha_draft) versioned = PublishableContent.objects.get(pk=tuto.pk).load_version() extract = versioned.children_dict[self.part1.slug].children_dict[self.chapter1.slug].children[0] self.assertEqual(self.extract2.slug, extract.slug) extract = versioned.children_dict[self.part1.slug].children_dict[self.chapter1.slug].children[1] self.assertEqual(self.extract3.slug, extract.slug) tuto = PublishableContent.objects.get(pk=self.tuto.pk) old_sha = tuto.sha_draft # test changing parent for extract (smoothly) self.chapter2 = ContainerFactory(parent=self.part1, db_object=self.tuto) self.extract4 = ExtractFactory(container=self.chapter2, db_object=self.tuto) result = self.client.post( reverse('content:move-element'), { 'child_slug': self.extract1.slug, 'container_slug': self.chapter1.slug, 'first_level_slug': self.part1.slug, 'moving_method': 'after:' + self.extract4.get_path(True)[:-3], 'pk': tuto.pk }, follow=True) self.assertEqual(200, result.status_code) self.assertNotEqual(old_sha, PublishableContent.objects.get(pk=tuto.pk).sha_draft) versioned = PublishableContent.objects.get(pk=tuto.pk).load_version() extract = versioned.children_dict[self.part1.slug].children_dict[self.chapter2.slug].children[1] self.assertEqual(self.extract1.slug, extract.slug) extract = versioned.children_dict[self.part1.slug].children_dict[self.chapter2.slug].children[0] self.assertEqual(self.extract4.slug, extract.slug) self.assertEqual(2, len(versioned.children_dict[self.part1.slug].children_dict[self.chapter1.slug].children)) # test try to move to a container that can't get extract tuto = PublishableContent.objects.get(pk=self.tuto.pk) old_sha = tuto.sha_draft result = self.client.post( reverse('content:move-element'), { 'child_slug': self.extract1.slug, 'container_slug': self.chapter2.slug, 'first_level_slug': self.part1.slug, 'moving_method': 'after:' + self.chapter1.get_path(True), 'pk': tuto.pk }, follow=True) self.assertEqual(200, result.status_code) self.assertEqual(old_sha, PublishableContent.objects.get(pk=tuto.pk).sha_draft) versioned = PublishableContent.objects.get(pk=tuto.pk).load_version() extract = versioned.children_dict[self.part1.slug].children_dict[self.chapter2.slug].children[1] self.assertEqual(self.extract1.slug, extract.slug) extract = versioned.children_dict[self.part1.slug].children_dict[self.chapter2.slug].children[0] self.assertEqual(self.extract4.slug, extract.slug) self.assertEqual(2, len(versioned.children_dict[self.part1.slug].children_dict[self.chapter1.slug].children)) # test try to move near an extract that does not exist tuto = PublishableContent.objects.get(pk=self.tuto.pk) old_sha = tuto.sha_draft result = self.client.post( reverse('content:move-element'), { 'child_slug': self.extract1.slug, 'container_slug': self.chapter2.slug, 'first_level_slug': self.part1.slug, 'moving_method': 'after:' + self.chapter1.get_path(True) + '/un-mauvais-extrait', 'pk': tuto.pk }, follow=True) self.assertEqual(404, result.status_code) self.assertEqual(old_sha, PublishableContent.objects.get(pk=tuto.pk).sha_draft) versioned = PublishableContent.objects.get(pk=tuto.pk).load_version() extract = versioned.children_dict[self.part1.slug].children_dict[self.chapter2.slug].children[1] self.assertEqual(self.extract1.slug, extract.slug) extract = versioned.children_dict[self.part1.slug].children_dict[self.chapter2.slug].children[0] self.assertEqual(self.extract4.slug, extract.slug) self.assertEqual(2, len(versioned.children_dict[self.part1.slug].children_dict[self.chapter1.slug].children)) def test_move_container_after(self): # login with author self.assertEqual( self.client.login( username=self.user_author.username, password='******'), True) tuto = PublishableContent.objects.get(pk=self.tuto.pk) self.chapter2 = ContainerFactory(parent=self.part1, db_object=self.tuto) self.chapter3 = ContainerFactory(parent=self.part1, db_object=self.tuto) self.part2 = ContainerFactory(parent=self.tuto_draft, db_object=self.tuto) self.extract5 = ExtractFactory(container=self.chapter3, db_object=self.tuto) self.chapter4 = ContainerFactory(parent=self.part2, db_object=self.tuto) tuto = PublishableContent.objects.get(pk=self.tuto.pk) old_sha = tuto.sha_draft # test changing parent for container (smoothly) result = self.client.post( reverse('content:move-element'), { 'child_slug': self.chapter3.slug, 'container_slug': self.part1.slug, 'first_level_slug': '', 'moving_method': 'after:' + self.chapter4.get_path(True), 'pk': tuto.pk }, follow=True) self.assertEqual(200, result.status_code) self.assertNotEqual(old_sha, PublishableContent.objects.get(pk=tuto.pk).sha_draft) versioned = PublishableContent.objects.get(pk=tuto.pk).load_version() self.assertEqual(2, len(versioned.children_dict[self.part2.slug].children)) chapter = versioned.children_dict[self.part2.slug].children[1] self.assertEqual(1, len(chapter.children)) self.assertTrue(isfile(chapter.children[0].get_path())) self.assertEqual(self.extract5.slug, chapter.children[0].slug) self.assertEqual(self.chapter3.slug, chapter.slug) chapter = versioned.children_dict[self.part2.slug].children[0] self.assertEqual(self.chapter4.slug, chapter.slug) # test changing parent for too deep container tuto = PublishableContent.objects.get(pk=self.tuto.pk) old_sha = tuto.sha_draft result = self.client.post( reverse('content:move-element'), { 'child_slug': self.part1.slug, 'container_slug': self.tuto.slug, 'first_level_slug': '', 'moving_method': 'after:' + self.chapter4.get_path(True), 'pk': tuto.pk }, follow=True) self.assertEqual(200, result.status_code) self.assertEqual(old_sha, PublishableContent.objects.get(pk=tuto.pk).sha_draft) versioned = PublishableContent.objects.get(pk=tuto.pk).load_version() self.assertEqual(2, len(versioned.children_dict[self.part2.slug].children)) chapter = versioned.children_dict[self.part2.slug].children[1] self.assertEqual(self.chapter3.slug, chapter.slug) chapter = versioned.children_dict[self.part2.slug].children[0] self.assertEqual(self.chapter4.slug, chapter.slug) def test_move_no_slug_update(self): """ this test comes from issue #3328 (https://github.com/zestedesavoir/zds-site/issues/3328) telling it is tricky is kind of euphemism. :return: """ LicenceFactory(code='CC BY') self.assertEqual( self.client.login( username=self.user_author.username, password='******'), True) draft_zip_path = join(dirname(__file__), 'fake_lasynchrone-et-le-multithread-en-net.zip') result = self.client.post( reverse('content:import-new'), { 'archive': open(draft_zip_path, 'rb'), 'subcategory': self.subcategory.pk }, follow=False ) self.assertEqual(result.status_code, 302) tuto = PublishableContent.objects.last() published = publish_content(tuto, tuto.load_version(), True) tuto.sha_public = tuto.sha_draft tuto.public_version = published tuto.save() extract1 = tuto.load_version().children[0] # test moving up smoothly result = self.client.post( reverse('content:move-element'), { 'child_slug': extract1.slug, 'first_level_slug': '', 'container_slug': tuto.slug, 'moving_method': 'down', 'pk': tuto.pk }, follow=True) self.assertEqual(200, result.status_code) self.assertTrue(isdir(tuto.get_repo_path()))
def test_special_case_of_contents(self): """test that the old publishedcontent does not stay when a new one is created""" if not self.manager.connected_to_es: return # 1. Create a middle-tutorial, publish it, then index it tuto = PublishableContentFactory(type='TUTORIAL') tuto.authors.add(self.user) tuto.save() tuto_draft = tuto.load_version() chapter1 = ContainerFactory(parent=tuto_draft, db_object=tuto) ExtractFactory(container=chapter1, db_object=tuto) published = publish_content(tuto, tuto_draft, is_major_update=True) tuto.sha_public = tuto_draft.current_version tuto.sha_draft = tuto_draft.current_version tuto.public_version = published tuto.save() self.manager.es_bulk_indexing_of_model(PublishedContent, force_reindexing=True) # index self.manager.refresh_index() first_publication = PublishedContent.objects.get(content_pk=tuto.pk) self.assertTrue(first_publication.es_already_indexed) self.assertFalse(first_publication.es_flagged) s = Search() s.query(MatchAll()) results = self.manager.setup_search(s).execute() self.assertEqual(len(results), 2) # get 2 results, one for the content and one for the chapter self.assertEqual(PublishedContent.objects.count(), 1) # 2. Change thet title, which will trigger a change in the slug tuto = PublishableContent.objects.get(pk=tuto.pk) versioned = tuto.load_version(sha=tuto.sha_draft) tuto.title = 'un titre complètement différent!' tuto.save() versioned.repo_update_top_container(tuto.title, tuto.slug, 'osef', 'osef') second_publication = publish_content(tuto, versioned, True) tuto.sha_public = versioned.current_version tuto.sha_draft = versioned.current_version tuto.public_version = second_publication tuto.save() self.assertEqual(PublishedContent.objects.count(), 2) # now there is two objects ... first_publication = PublishedContent.objects.get(pk=first_publication.pk) self.assertTrue(first_publication.must_redirect) # .. including the first one, for redirection self.manager.refresh_index() s = Search() s.query(MatchAll()) results = self.manager.setup_search(s).execute() self.assertEqual(len(results), 0) # the old one is gone (and we need to reindex to get the new one) # 3. Check if indexation brings the new one, and not the old one self.manager.es_bulk_indexing_of_model(PublishedContent, force_reindexing=True) # index self.manager.refresh_index() first_publication = PublishedContent.objects.get(pk=first_publication.pk) second_publication = PublishedContent.objects.get(pk=second_publication.pk) s = Search() s.query(MatchAll()) results = self.manager.setup_search(s).execute() self.assertEqual(len(results), 2) # Still 2, not 4 ! found_old = False found_new = False for hit in results: if hit.meta.doc_type == PublishedContent.get_es_document_type(): if hit.meta.id == first_publication.es_id: found_old = True if hit.meta.id == second_publication.es_id: found_new = True self.assertTrue(found_new) self.assertFalse(found_old)
class ContentNotification(TestCase, TutorialTestMixin): def setUp(self): # don't build PDF to speed up the tests self.user1 = ProfileFactory().user self.user2 = ProfileFactory().user # create a tutorial self.tuto = PublishableContentFactory(type="TUTORIAL") self.tuto.authors.add(self.user1) UserGalleryFactory(gallery=self.tuto.gallery, user=self.user1, mode="W") self.tuto.licence = LicenceFactory() self.tuto.subcategory.add(SubCategoryFactory()) self.tuto.save() tuto_draft = self.tuto.load_version() # then, publish it ! version = tuto_draft.current_version self.published = publish_content(self.tuto, tuto_draft, is_major_update=True) self.tuto.sha_public = version self.tuto.sha_draft = version self.tuto.public_version = self.published self.tuto.save() self.client.force_login(self.user1) def test_no_persistant_notif_on_revoke(self): from zds.tutorialv2.publication_utils import unpublish_content NewPublicationSubscription.objects.get_or_create_active( self.user1, self.user2) content = PublishedContentFactory(author_list=[self.user2]) signals.content_published.send(sender=self.tuto.__class__, instance=content, by_email=False) self.assertEqual( 1, len(Notification.objects.get_notifications_of(self.user1))) unpublish_content(content) self.assertEqual( 0, len(Notification.objects.get_notifications_of(self.user1))) def test_no_persistant_comment_notif_on_revoke(self): from zds.tutorialv2.publication_utils import unpublish_content content = PublishedContentFactory(author_list=[self.user2]) ContentReactionAnswerSubscription.objects.get_or_create_active( self.user1, content) ContentReactionFactory(related_content=content, author=self.user2, position=1) self.assertEqual( 1, len(Notification.objects.get_unread_notifications_of(self.user1))) unpublish_content(content, moderator=self.user2) self.assertEqual( 0, len(Notification.objects.get_unread_notifications_of(self.user1))) def test_only_one_notif_on_update(self): NewPublicationSubscription.objects.get_or_create_active( self.user1, self.user2) content = PublishedContentFactory(author_list=[self.user2]) notify_update(content, False, True) versioned = content.load_version() content.sha_draft = versioned.repo_update(introduction="new intro", conclusion="new conclusion", title=versioned.title) content.save() publish_content(content, content.load_version(), True) notify_update(content, True, False) notifs = get_header_notifications( self.user1)["general_notifications"]["list"] self.assertEqual(1, len(notifs), str(notifs)) def test_only_one_notif_on_major_update(self): NewPublicationSubscription.objects.get_or_create_active( self.user1, self.user2) content = PublishedContentFactory(author_list=[self.user2]) notify_update(content, False, True) versioned = content.load_version() content.sha_draft = versioned.repo_update(introduction="new intro", conclusion="new conclusion", title=versioned.title) content.save() publish_content(content, content.load_version(), True) notify_update(content, True, True) notifs = get_header_notifications( self.user1)["general_notifications"]["list"] self.assertEqual(1, len(notifs), str(notifs))
class NotificationPublishableContentTest(TestCase): def setUp(self): self.user1 = ProfileFactory().user self.user2 = ProfileFactory().user # create a tutorial self.tuto = PublishableContentFactory(type='TUTORIAL') self.tuto.authors.add(self.user1) UserGalleryFactory(gallery=self.tuto.gallery, user=self.user1, mode='W') self.tuto.licence = LicenceFactory() self.tuto.subcategory.add(SubCategoryFactory()) self.tuto.save() tuto_draft = self.tuto.load_version() # then, publish it ! version = tuto_draft.current_version self.published = publish_content(self.tuto, tuto_draft, is_major_update=True) self.tuto.sha_public = version self.tuto.sha_draft = version self.tuto.public_version = self.published self.tuto.save() self.assertTrue( self.client.login(username=self.user1.username, password='******')) def test_follow_content_at_publication(self): """ When a content is published, authors automatically follow it. """ subscription = ContentReactionAnswerSubscription.objects.get_existing( user=self.user1, content_object=self.tuto) self.assertIsNone(subscription) # Signal call by the view at the publication. signals.new_content.send(sender=self.tuto.__class__, instance=self.tuto, by_email=False) subscription = ContentReactionAnswerSubscription.objects.get_existing( user=self.user1, content_object=self.tuto) self.assertTrue(subscription.is_active) def test_follow_content_from_view(self): """ Allows a user to follow (or not) a content from the view. """ subscription = ContentReactionAnswerSubscription.objects.get_existing( user=self.user1, content_object=self.tuto) self.assertIsNone(subscription) result = self.client.post( reverse('content:follow-reactions', args=[self.tuto.pk]), {'follow': 1}) self.assertEqual(result.status_code, 302) subscription = ContentReactionAnswerSubscription.objects.get_existing( user=self.user1, content_object=self.tuto) self.assertTrue(subscription.is_active) def test_answer_subscription(self): """ When a user posts on a publishable content, the user gets subscribed. """ subscription = ContentReactionAnswerSubscription.objects.get_existing( user=self.user1, content_object=self.tuto) self.assertIsNone(subscription) result = self.client.post(reverse('content:add-reaction') + '?pk={}'.format(self.tuto.pk), { 'text': 'message', 'last_note': '0' }, follow=True) self.assertEqual(result.status_code, 200) subscription = ContentReactionAnswerSubscription.objects.get_existing( user=self.user1, content_object=self.tuto) self.assertTrue(subscription.is_active) def test_notification_read(self): """ When the notification is a reaction, it is marked as read when the corresponding content is displayed to the user. """ ContentReactionFactory(related_content=self.tuto, author=self.user1, position=1) last_note = ContentReactionFactory(related_content=self.tuto, author=self.user2, position=2) self.tuto.last_note = last_note self.tuto.save() notification = Notification.objects.get(subscription__user=self.user1) self.assertFalse(notification.is_read) result = self.client.get(reverse('tutorial:view', args=[self.tuto.pk, self.tuto.slug]), follow=False) self.assertEqual(result.status_code, 200) notification = Notification.objects.get(subscription__user=self.user1) self.assertTrue(notification.is_read) def test_subscription_to_new_publications_from_user(self): """ Any user may subscribe to new publications from a user. """ result = self.client.post(reverse('content:follow', args=[self.user1.pk]), follow=False) self.assertEqual(result.status_code, 403) self.client.logout() self.assertTrue( self.client.login(username=self.user2.username, password='******'), True) result = self.client.post(reverse('content:follow', args=[self.user1.pk]), {'follow': 1}, follow=False, HTTP_X_REQUESTED_WITH='XMLHttpRequest') self.assertEqual(result.status_code, 200) subscription = NewPublicationSubscription.objects.get_existing( user=self.user2, content_object=self.user1) self.assertTrue(subscription.is_active) result = self.client.post(reverse('content:follow', args=[self.user1.pk]), {'email': 1}, follow=False, HTTP_X_REQUESTED_WITH='XMLHttpRequest') self.assertEqual(result.status_code, 200) subscription = NewPublicationSubscription.objects.get_existing( user=self.user2, content_object=self.user1) self.assertTrue(subscription.is_active) self.assertTrue(subscription.by_email) def test_notification_generated_when_a_tuto_is_published(self): """ When a user subscribe to new publications from a user, a notification is generated when a publication is published. """ subscription = NewPublicationSubscription.objects.toggle_follow( self.user1, self.user2) signals.new_content.send(sender=self.tuto.__class__, instance=self.tuto, by_email=False) notifications = Notification.objects.filter(subscription=subscription, is_read=False).all() self.assertEqual(1, len(notifications)) signals.content_read.send(sender=self.tuto.__class__, instance=self.tuto, user=self.user2, target=ContentReaction) notifications = Notification.objects.filter(subscription=subscription, is_read=False).all() self.assertEqual(1, len(notifications)) signals.content_read.send(sender=self.tuto.__class__, instance=self.tuto, user=self.user2, target=PublishableContent) notifications = Notification.objects.filter(subscription=subscription, is_read=False).all() self.assertEqual(0, len(notifications)) def test_no_error_on_multiple_subscription(self): subscription = NewPublicationSubscription.objects.toggle_follow( self.user1, self.user2) signals.new_content.send(sender=self.tuto.__class__, instance=self.tuto, by_email=False) subscription1 = Notification.objects.filter(subscription=subscription, is_read=False).first() subscription2 = copy.copy(subscription1) subscription2.save() subscription.mark_notification_read(self.tuto) subscription1 = Notification.objects.filter(subscription=subscription, is_read=False).first() self.assertIsNone(subscription1) self.assertEqual( 1, Notification.objects.filter(subscription=subscription, is_read=True).count())
def test_filters(self): """ Test filtering by category & tag """ subcategory2 = SubCategoryFactory() subcategory3 = SubCategoryFactory() tag2 = TagFactory() tag3 = TagFactory() # Add a new tuto & publish it article2 = PublishableContentFactory(type="ARTICLE") article2.authors.add(self.user_author) article2.licence = self.licence article2.subcategory.add(subcategory2) article2.tags.add(self.tag) article2.tags.add(tag2) article2.save() article2_draft = article2.load_version() article2.sha_public = article2.sha_draft = article2_draft.current_version article2.public_version = publish_content(article2, article2_draft, is_major_update=True) article2.save() # Default view ret = [item.content for item in self.articlefeed.items()] self.assertEqual(ret, [article2, self.article]) # Filter by subcategory self.articlefeed.query_params = {"subcategory": self.subcategory.slug} ret = [item.content for item in self.articlefeed.items()] self.assertEqual(ret, [self.article]) self.articlefeed.query_params = { "subcategory": f" {self.subcategory.slug} " } ret = [item.content for item in self.articlefeed.items()] self.assertEqual(ret, [self.article]) self.articlefeed.query_params = {"subcategory": subcategory2.slug} ret = [item.content for item in self.articlefeed.items()] self.assertEqual(ret, [article2]) self.articlefeed.query_params = {"subcategory": subcategory3.slug} ret = [item.content for item in self.articlefeed.items()] self.assertEqual(ret, []) self.articlefeed.query_params = {"subcategory": "invalid"} self.assertRaises(Http404, self.articlefeed.items) # Filter by tag self.articlefeed.query_params = {"tag": self.tag.slug} ret = [item.content for item in self.articlefeed.items()] self.assertEqual(ret, [article2, self.article]) self.articlefeed.query_params = {"tag": tag2.slug} ret = [item.content for item in self.articlefeed.items()] self.assertEqual(ret, [article2]) self.articlefeed.query_params = {"tag": f" {tag2.slug} "} ret = [item.content for item in self.articlefeed.items()] self.assertEqual(ret, [article2]) self.articlefeed.query_params = {"tag": tag3.slug} ret = [item.content for item in self.articlefeed.items()] self.assertEqual(ret, []) self.articlefeed.query_params = {"tag": "invalid"} self.assertRaises(Http404, self.articlefeed.items)