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_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_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')
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) self.old_registry = {key: value for key, value in PublicatorRegistery.get_all_registered()} 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_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 test_last_participation_is_old(self): article = PublishedContentFactory(author_list=[self.user_author], type="ARTICLE") newUser = ProfileFactory().user reac = ContentReaction(author=self.user_author, position=1, related_content=article) reac.update_content("I will find you. And I Will Kill you.") reac.save() article.last_note = reac article.save() self.assertFalse(last_participation_is_old(article, newUser)) ContentRead(user=self.user_author, note=reac, content=article).save() reac = ContentReaction(author=newUser, position=2, related_content=article) reac.update_content("I will find you. And I Will Kill you.") reac.save() article.last_note = reac article.save() ContentRead(user=newUser, note=reac, content=article).save() self.assertFalse(last_participation_is_old(article, newUser)) 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(u"un peu plus près de 42")) versioned.dump_json() manifest = os.path.join(versioned.get_path(), "manifest.json") dictionary = json_reader.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('zds.pages.views.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) # 2. Without connected user self.client.logout() # as above ... result = self.client.get(reverse('zds.pages.views.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 = [u'-', u'_', u'__', u'-_-', u'$', u'@', u'&', u'{}', u' ', u'...'] for t in invalid_titles: self.assertRaises(InvalidSlugError, slugify_raise_on_invalid, t) # Those slugs are recognized as wrong slug invalid_slugs = [ u'', # empty u'----', # empty u'___', # empty u'-_-', # empty (!) u'&;', # invalid characters u'!{', # invalid characters u'@', # invalid character u'a ' # space ! ] for s in invalid_slugs: self.assertFalse(check_slug(s)) # too long slugs are forbidden : too_damn_long_slug = 'a' * (settings.ZDS_APP['content']['maximum_slug_size'] + 1) self.assertFalse(check_slug(too_damn_long_slug)) def test_watchdog(self): PublicatorRegistery.unregister("pdf") PublicatorRegistery.unregister("epub") PublicatorRegistery.unregister("html") with open("path", "w") as f: f.write("my_content;/path/to/markdown.md") @PublicatorRegistery.register("test", "", "") class TestPublicator(Publicator): def __init__(self, *__): pass PublicatorRegistery.get("test").publish = Mock() event = FileCreatedEvent("path") handler = TutorialIsPublished() handler.prepare_generation = Mock() handler.finish_generation = Mock() handler.on_created(event) self.assertTrue(PublicatorRegistery.get("test").publish.called) handler.finish_generation.assert_called_with("/path/to", "path") handler.prepare_generation.assert_called_with("/path/to") 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['content']['extra_content_watchdog_dir']): shutil.rmtree(settings.ZDS_APP['content']['extra_content_watchdog_dir']) # re-active PDF build settings.ZDS_APP['content']['build_pdf_when_published'] = True PublicatorRegistery.registry = self.old_registry
class ContentMoveTests(TestCase): def setUp(self): # don't build PDF to speed up the tests settings.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 settings.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=settings.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=settings.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), '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 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-activate PDF build settings.ZDS_APP['content']['build_pdf_when_published'] = True
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))
class UtilsTests(TestCase, TutorialTestMixin): def setUp(self): self.overridden_zds_app = overridden_zds_app 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.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 = {} 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_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]) 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_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) 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_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_pdf(self): """ensure the behavior of the `python manage.py generate_pdf` commmand""" 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' * ( overridden_zds_app['content']['maximum_slug_size'] + 1) self.assertFalse(check_slug(too_damn_long_slug)) def test_watchdog(self): PublicatorRegistry.unregister('pdf') PublicatorRegistry.unregister('printable-pdf') PublicatorRegistry.unregister('epub') PublicatorRegistry.unregister('html') with open('path', 'w') as f: f.write('my_content;/path/to/markdown.md') @PublicatorRegistry.register('test', '', '') class TestPublicator(Publicator): def __init__(self, *__): pass PublicatorRegistry.get('test').publish = Mock() event = FileCreatedEvent('path') handler = TutorialIsPublished() handler.prepare_generation = Mock() handler.finish_generation = Mock() handler.on_created(event) self.assertTrue(PublicatorRegistry.get('test').publish.called) handler.finish_generation.assert_called_with('/path/to', 'path') handler.prepare_generation.assert_called_with('/path/to') os.remove('path') 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
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
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()))
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=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() def test_move_up_extract(self): # login with author self.client.force_login(self.user_author) 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.client.force_login(self.user_guest) 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.client.force_login(self.user_author) 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.client.force_login(self.user_author) 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.client.force_login(self.user_guest) 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.client.force_login(self.user_author) 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.client.force_login(self.user_author) 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.client.force_login(self.user_author) 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()))
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_object=midsize_tuto) ExtractFactory(container=chapter1, db_object=midsize_tuto) chapter2 = ContainerFactory(parent=midsize_tuto_draft, db_object=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_object=bigtuto) chapter1 = ContainerFactory(parent=part1, db_object=bigtuto) ExtractFactory(container=chapter1, db_object=bigtuto) part2 = ContainerFactory(parent=bigtuto_draft, db_object=bigtuto) chapter2 = ContainerFactory(parent=part2, db_object=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", f"id={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.client.force_login(self.user_author) # 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() 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
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 = {} shutil.copy( os.path.join(settings.BASE_DIR, 'fixtures', 'tuto', 'balise_audio', 'manifest.json'), os.path.join(settings.BASE_DIR, 'fixtures', 'tuto', 'balise_audio', 'manifest2.json') ) LicenceFactory(code='CC BY') args = [os.path.join(settings.BASE_DIR, 'fixtures', 'tuto', 'balise_audio', 'manifest2.json')] call_command('upgrade_manifest_to_v2', *args, **opts) manifest = open(os.path.join(settings.BASE_DIR, 'fixtures', 'tuto', 'balise_audio', 'manifest2.json'), '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]) args = [os.path.join(settings.BASE_DIR, 'fixtures', 'tuto', 'big_tuto_v1', 'manifest2.json')] shutil.copy( os.path.join(settings.BASE_DIR, 'fixtures', 'tuto', 'big_tuto_v1', 'manifest.json'), os.path.join(settings.BASE_DIR, 'fixtures', 'tuto', 'big_tuto_v1', 'manifest2.json') ) call_command('upgrade_manifest_to_v2', *args, **opts) manifest = open(os.path.join(settings.BASE_DIR, 'fixtures', 'tuto', 'big_tuto_v1', 'manifest2.json'), '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) args = [os.path.join(settings.BASE_DIR, 'fixtures', 'tuto', 'article_v1', 'manifest2.json')] shutil.copy( os.path.join(settings.BASE_DIR, 'fixtures', 'tuto', 'article_v1', 'manifest.json'), os.path.join(settings.BASE_DIR, 'fixtures', 'tuto', 'article_v1', 'manifest2.json') ) call_command('upgrade_manifest_to_v2', *args, **opts) manifest = open(os.path.join(settings.BASE_DIR, 'fixtures', 'tuto', 'article_v1', 'manifest2.json'), '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_watchdog(self): PublicatorRegistry.unregister('pdf') PublicatorRegistry.unregister('printable-pdf') PublicatorRegistry.unregister('epub') PublicatorRegistry.unregister('html') with open('path', 'w') as f: f.write('my_content;/path/to/markdown.md') @PublicatorRegistry.register('test', '', '') class TestPublicator(Publicator): def __init__(self, *__): pass PublicatorRegistry.get('test').publish = Mock() event = FileCreatedEvent('path') handler = TutorialIsPublished() handler.prepare_generation = Mock() handler.finish_generation = Mock() handler.on_created(event) self.assertTrue(PublicatorRegistry.get('test').publish.called) handler.finish_generation.assert_called_with('/path/to', 'path') handler.prepare_generation.assert_called_with('/path/to') os.remove('path') 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