示例#1
0
 def test_tagged_tree_extract(self):
     midsize = PublishableContentFactory(author_list=[self.user_author])
     midsize_draft = midsize.load_version()
     first_container = ContainerFactory(parent=midsize_draft, db_object=midsize)
     second_container = ContainerFactory(parent=midsize_draft, db_object=midsize)
     first_extract = ExtractFactory(container=first_container, db_object=midsize)
     second_extract = ExtractFactory(container=second_container, db_object=midsize)
     tagged_tree = get_target_tagged_tree_for_extract(first_extract, midsize_draft)
     paths = {i[0]: i[3] for i in tagged_tree}
     self.assertTrue(paths[second_extract.get_full_slug()])
     self.assertFalse(paths[second_container.get_path(True)])
     self.assertFalse(paths[first_container.get_path(True)])
示例#2
0
 def test_tagged_tree_extract(self):
     midsize = PublishableContentFactory(author_list=[self.user_author])
     midsize_draft = midsize.load_version()
     first_container = ContainerFactory(parent=midsize_draft, db_object=midsize)
     second_container = ContainerFactory(parent=midsize_draft, db_object=midsize)
     first_extract = ExtractFactory(container=first_container, db_object=midsize)
     second_extract = ExtractFactory(container=second_container, db_object=midsize)
     tagged_tree = get_target_tagged_tree_for_extract(first_extract, midsize_draft)
     paths = {i[0]: i[3] for i in tagged_tree}
     self.assertTrue(paths[second_extract.get_full_slug()])
     self.assertFalse(paths[second_container.get_path(True)])
     self.assertFalse(paths[first_container.get_path(True)])
示例#3
0
    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")
示例#4
0
    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')
示例#5
0
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
示例#6
0
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
示例#7
0
    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))
示例#8
0
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
示例#9
0
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
示例#10
0
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()))
示例#11
0
    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))
示例#12
0
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()))
示例#13
0
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
示例#14
0
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