Example #1
0
    def testParseBadManifest(self):
        base_content = PublishableContentFactory(author_list=[self.user_author])
        versioned = base_content.load_version()
        versioned.add_container(Container('un peu plus près de 42'))
        versioned.dump_json()
        manifest = os.path.join(versioned.get_path(), 'manifest.json')
        dictionary = json_handler.load(open(manifest))

        old_title = dictionary['title']

        # first bad title
        dictionary['title'] = 81 * ['a']
        self.assertRaises(BadManifestError,
                          get_content_from_json, dictionary, None, '',
                          max_title_len=PublishableContent._meta.get_field('title').max_length)
        dictionary['title'] = ''.join(dictionary['title'])
        self.assertRaises(BadManifestError,
                          get_content_from_json, dictionary, None, '',
                          max_title_len=PublishableContent._meta.get_field('title').max_length)
        dictionary['title'] = '...'
        self.assertRaises(InvalidSlugError,
                          get_content_from_json, dictionary, None, '',
                          max_title_len=PublishableContent._meta.get_field('title').max_length)

        dictionary['title'] = old_title
        dictionary['children'][0]['title'] = 81 * ['a']
        self.assertRaises(BadManifestError,
                          get_content_from_json, dictionary, None, '',
                          max_title_len=PublishableContent._meta.get_field('title').max_length)

        dictionary['children'][0]['title'] = 'bla'
        dictionary['children'][0]['slug'] = '...'
        self.assertRaises(InvalidSlugError,
                          get_content_from_json, dictionary, None, '',
                          max_title_len=PublishableContent._meta.get_field('title').max_length)
    def test_opinion_publication_guest(self):
        """
        Test the publication of PublishableContent where type is OPINION (with guest => 403).
        """

        text_publication = 'Aussi tôt dit, aussi tôt fait !'

        opinion = PublishableContentFactory(type='OPINION')

        opinion.authors.add(self.user_author)
        UserGalleryFactory(gallery=opinion.gallery, user=self.user_author, mode='W')
        opinion.licence = self.licence
        opinion.save()

        opinion_draft = opinion.load_version()
        ExtractFactory(container=opinion_draft, db_object=opinion)
        ExtractFactory(container=opinion_draft, db_object=opinion)

        self.assertEqual(
            self.client.login(
                username=self.user_guest.username,
                password='******'),
            True)

        result = self.client.post(
            reverse('validation:publish-opinion', kwargs={'pk': opinion.pk, 'slug': opinion.slug}),
            {
                'text': text_publication,
                'source': '',
                'version': opinion_draft.current_version
            },
            follow=False)
        self.assertEqual(result.status_code, 403)

        self.assertEqual(PublishedContent.objects.count(), 0)
Example #3
0
 def test_get_tuto_count(self):
     # Start with 0
     self.assertEqual(self.user1.get_tuto_count(), 0)
     # Create Tuto !
     minituto = PublishableContentFactory(type='TUTORIAL')
     minituto.authors.add(self.user1.user)
     minituto.gallery = GalleryFactory()
     minituto.save()
     # Should be 1
     self.assertEqual(self.user1.get_tuto_count(), 1)
Example #4
0
 def test_get_draft_articles(self):
     # Start with 0
     self.assertEqual(len(self.user1.get_draft_articles()), 0)
     # Create article !
     article = PublishableContentFactory(type='ARTICLE')
     article.authors.add(self.user1.user)
     article.save()
     # Should be 1
     articles = self.user1.get_draft_articles()
     self.assertEqual(len(articles), 1)
     self.assertEqual(article, articles[0])
Example #5
0
 def test_get_validate_tutos(self):
     # Start with 0
     self.assertEqual(len(self.user1.get_validate_tutos()), 0)
     # Create Tuto !
     validatetuto = PublishableContentFactory(type='TUTORIAL', author_list=[self.user1.user])
     validatetuto.sha_validation = 'whatever'
     validatetuto.save()
     # Should be 1
     validatetutos = self.user1.get_validate_tutos()
     self.assertEqual(len(validatetutos), 1)
     self.assertEqual(validatetuto, validatetutos[0])
Example #6
0
 def test_get_draft_tutos(self):
     # Start with 0
     self.assertEqual(len(self.user1.get_draft_tutos()), 0)
     # Create Tuto !
     drafttuto = PublishableContentFactory(type='TUTORIAL')
     drafttuto.authors.add(self.user1.user)
     drafttuto.gallery = GalleryFactory()
     drafttuto.save()
     # Should be 1
     drafttutos = self.user1.get_draft_tutos()
     self.assertEqual(len(drafttutos), 1)
     self.assertEqual(drafttuto, drafttutos[0])
Example #7
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)])
Example #8
0
    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
Example #9
0
 def test_get_beta_tutos(self):
     # Start with 0
     self.assertEqual(len(self.user1.get_beta_tutos()), 0)
     # Create Tuto !
     betatetuto = PublishableContentFactory(type='TUTORIAL')
     betatetuto.authors.add(self.user1.user)
     betatetuto.gallery = GalleryFactory()
     betatetuto.sha_beta = 'whatever'
     betatetuto.save()
     # Should be 1
     betatetutos = self.user1.get_beta_tutos()
     self.assertEqual(len(betatetutos), 1)
     self.assertEqual(betatetuto, betatetutos[0])
Example #10
0
 def test_get_public_tutos(self):
     # Start with 0
     self.assertEqual(len(self.user1.get_public_tutos()), 0)
     # Create Tuto !
     publictuto = PublishableContentFactory(type='TUTORIAL')
     publictuto.authors.add(self.user1.user)
     publictuto.gallery = GalleryFactory()
     publictuto.sha_public = 'whatever'
     publictuto.save()
     # Should be 0 because publication was not used
     publictutos = self.user1.get_public_tutos()
     self.assertEqual(len(publictutos), 0)
     PublishedContentFactory(author_list=[self.user1.user])
     self.assertEqual(len(self.user1.get_public_tutos()), 1)
Example #11
0
 def test_get_public_articles(self):
     # Start with 0
     self.assertEqual(len(self.user1.get_public_articles()), 0)
     # Create article !
     article = PublishableContentFactory(type='ARTICLE')
     article.authors.add(self.user1.user)
     article.sha_public = 'whatever'
     article.save()
     # Should be 0
     articles = self.user1.get_public_articles()
     self.assertEqual(len(articles), 0)
     # Should be 1
     PublishedContentFactory(author_list=[self.user1.user], type='ARTICLE')
     self.assertEqual(len(self.user1.get_public_articles()), 1)
     self.assertEqual(len(self.user1.get_public_tutos()), 0)
Example #12
0
    def setUp(self):
        self.mas = ProfileFactory().user
        self.overridden_zds_app['member']['bot_account'] = self.mas.username

        self.licence = LicenceFactory()

        self.user_author = ProfileFactory().user
        self.staff = StaffProfileFactory().user

        self.tuto = PublishableContentFactory(type='TUTORIAL')
        self.tuto.authors.add(self.user_author)
        UserGalleryFactory(gallery=self.tuto.gallery, user=self.user_author, mode='W')
        self.tuto.licence = self.licence
        self.tuto.save()

        self.tuto_draft = self.tuto.load_version()
        self.part1 = ContainerFactory(parent=self.tuto_draft, db_object=self.tuto)
        self.chapter1 = ContainerFactory(parent=self.part1, db_object=self.tuto)
        self.old_registry = {key: value for key, value in PublicatorRegistry.get_all_registered()}

        class TestPdfPublicator(Publicator):
            def publish(self, md_file_path, base_name, **kwargs):
                with Path(base_name + '.pdf').open('w') as f:
                    f.write('bla')
                shutil.copy2(str(Path(base_name + '.pdf')),
                             str(Path(md_file_path.replace('__building', '')).parent))
        PublicatorRegistry.registry['pdf'] = TestPdfPublicator()
Example #13
0
    def setUp(self):

        # don't build PDF to speed up the tests
        self.user1 = ProfileFactory().user
        self.user2 = ProfileFactory().user

        # create a tutorial
        self.tuto = PublishableContentFactory(type='TUTORIAL')
        self.tuto.authors.add(self.user1)
        UserGalleryFactory(gallery=self.tuto.gallery, user=self.user1, mode='W')
        self.tuto.licence = LicenceFactory()
        self.tuto.subcategory.add(SubCategoryFactory())
        self.tuto.save()
        tuto_draft = self.tuto.load_version()

        # then, publish it !
        version = tuto_draft.current_version
        self.published = publish_content(self.tuto, tuto_draft, is_major_update=True)

        self.tuto.sha_public = version
        self.tuto.sha_draft = version
        self.tuto.public_version = self.published
        self.tuto.save()

        self.assertTrue(self.client.login(username=self.user1.username, password='******'))
Example #14
0
    def setUp(self):
        self.licence = LicenceFactory()
        self.subcategory = SubCategoryFactory()

        self.author = ProfileFactory()
        self.user = ProfileFactory()
        self.staff = StaffProfileFactory()

        self.tuto = PublishableContentFactory(type='TUTORIAL')
        self.tuto.authors.add(self.author.user)
        self.tuto.licence = self.licence
        self.tuto.subcategory.add(self.subcategory)
        self.tuto.save()

        self.validation = Validation(
            content=self.tuto,
            version=self.tuto.sha_draft,
            comment_authors='bla',
            date_proposition=datetime.now(),
        )
        self.validation.save()

        self.topic = send_mp(author=self.author.user, users=[], title='Title', text='Testing', subtitle='', leave=False)
        self.topic.participants.add(self.user.user)
        send_message_mp(self.user.user, self.topic, 'Testing')

        # humane_delta test
        periods = ((1, 0), (2, 1), (3, 7), (4, 30), (5, 360))
        cont = dict()
        cont['date_today'] = periods[0][0]
        cont['date_yesterday'] = periods[1][0]
        cont['date_last_week'] = periods[2][0]
        cont['date_last_month'] = periods[3][0]
        cont['date_last_year'] = periods[4][0]
        self.context = Context(cont)
Example #15
0
    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()
Example #16
0
    def test_char_count_after_publication(self):
        """Test the ``get_char_count()`` function.

        Special care should be taken with this function, since:

        - The username of the author is, by default "Firmxxx" where "xxx" depends on the tests before ;
        - The titles (!) also contains a number that also depends on the number of tests before ;
        - The date is ``datetime.now()`` and contains the months, which is never a fixed number of letters.
        """

        author = ProfileFactory().user
        author.username = '******'
        author.save()

        len_date_now = len(date(datetime.now(), 'd F Y'))

        article = PublishedContentFactory(type='ARTICLE', author_list=[author], title='Un titre')
        published = PublishedContent.objects.filter(content=article).first()
        self.assertEqual(published.get_char_count(), 160 + len_date_now)

        tuto = PublishableContentFactory(type='TUTORIAL', author_list=[author], title='Un titre')

        # add a chapter, so it becomes a middle tutorial
        tuto_draft = tuto.load_version()
        chapter1 = ContainerFactory(parent=tuto_draft, db_object=tuto, title='Un chapitre')
        ExtractFactory(container=chapter1, db_object=tuto, title='Un extrait')
        published = publish_content(tuto, tuto_draft, is_major_update=True)

        tuto.sha_public = tuto_draft.current_version
        tuto.sha_draft = tuto_draft.current_version
        tuto.public_version = published
        tuto.save()

        published = PublishedContent.objects.filter(content=tuto).first()
        self.assertEqual(published.get_char_count(), 335 + len_date_now)
Example #17
0
    def test_content_ordering(self):
        category_1 = ContentCategoryFactory()
        category_2 = ContentCategoryFactory()
        subcategory_1 = SubCategoryFactory(category=category_1)
        subcategory_1.position = 5
        subcategory_1.save()
        subcategory_2 = SubCategoryFactory(category=category_1)
        subcategory_2.position = 1
        subcategory_2.save()
        subcategory_3 = SubCategoryFactory(category=category_2)

        tuto_1 = PublishableContentFactory(type='TUTORIAL')
        tuto_1.subcategory.add(subcategory_1)
        tuto_1_draft = tuto_1.load_version()
        publish_content(tuto_1, tuto_1_draft, is_major_update=True)

        top_categories_tuto = topbar_publication_categories('TUTORIAL').get('categories')
        expected = [(subcategory_1.title, subcategory_1.slug, category_1.slug)]
        self.assertEqual(top_categories_tuto[category_1.title], expected)

        tuto_2 = PublishableContentFactory(type='TUTORIAL')
        tuto_2.subcategory.add(subcategory_2)
        tuto_2_draft = tuto_2.load_version()
        publish_content(tuto_2, tuto_2_draft, is_major_update=True)

        top_categories_tuto = topbar_publication_categories('TUTORIAL').get('categories')
        # New subcategory is now first is the list
        expected.insert(0, (subcategory_2.title, subcategory_2.slug, category_1.slug))
        self.assertEqual(top_categories_tuto[category_1.title], expected)

        article_1 = PublishableContentFactory(type='TUTORIAL')
        article_1.subcategory.add(subcategory_3)
        article_1_draft = tuto_2.load_version()
        publish_content(article_1, article_1_draft, is_major_update=True)

        # New article has no impact
        top_categories_tuto = topbar_publication_categories('TUTORIAL').get('categories')
        self.assertEqual(top_categories_tuto[category_1.title], expected)

        top_categories_contents = topbar_publication_categories(['TUTORIAL', 'ARTICLE']).get('categories')
        expected_2 = [(subcategory_3.title, subcategory_3.slug, category_2.slug)]
        self.assertEqual(top_categories_contents[category_1.title], expected)
        self.assertEqual(top_categories_contents[category_2.title], expected_2)
Example #18
0
    def setUp(self):
        self.overridden_zds_app = overridden_zds_app
        # don't build PDF to speed up the tests
        overridden_zds_app['content']['build_pdf_when_published'] = False

        self.staff = StaffProfileFactory().user

        settings.EMAIL_BACKEND = 'django.core.mail.backends.locmem.EmailBackend'
        self.mas = ProfileFactory().user
        overridden_zds_app['member']['bot_account'] = self.mas.username

        bot = Group(name=overridden_zds_app['member']['bot_group'])
        bot.save()
        self.external = UserFactory(
            username=overridden_zds_app['member']['external_account'],
            password='******')

        self.beta_forum = ForumFactory(
            pk=overridden_zds_app['forum']['beta_forum_id'],
            category=CategoryFactory(position=1),
            position_in_category=1)  # ensure that the forum, for the beta versions, is created

        self.licence = LicenceFactory()
        self.subcategory = SubCategoryFactory()

        self.user_author = ProfileFactory().user
        self.user_staff = StaffProfileFactory().user
        self.user_guest = ProfileFactory().user

        # create a tutorial
        self.tuto = PublishableContentFactory(type='TUTORIAL')
        self.tuto.authors.add(self.user_author)
        UserGalleryFactory(gallery=self.tuto.gallery, user=self.user_author, mode='W')
        self.tuto.licence = self.licence
        self.tuto.subcategory.add(self.subcategory)
        self.tuto.save()

        # fill it with one part, containing one chapter, containing one extract
        self.tuto_draft = self.tuto.load_version()
        self.part1 = ContainerFactory(parent=self.tuto_draft, db_object=self.tuto)
        self.chapter1 = ContainerFactory(parent=self.part1, db_object=self.tuto)
        self.extract1 = ExtractFactory(container=self.chapter1, db_object=self.tuto)

        # then, publish it !
        version = self.tuto_draft.current_version
        self.published = publish_content(self.tuto, self.tuto_draft, is_major_update=True)

        self.tuto.sha_public = version
        self.tuto.sha_draft = version
        self.tuto.public_version = self.published
        self.tuto.save()

        self.tutofeed = LastTutorialsFeedRSS()
Example #19
0
    def test_ensure_slug_stay(self):
        """This test ensures that slugs are not modified when coming from a manifest"""

        tuto = PublishableContentFactory(type='TUTORIAL')
        versioned = tuto.load_version()

        random = 'Non, piti bug, tu ne reviendras plus !!!'
        title = "N'importe quel titre"

        # add three container with the same title
        versioned.repo_add_container(title, random, random)  # x
        versioned.repo_add_container(title, random, random)  # x-1
        version = versioned.repo_add_container(title, random, random)  # x-2
        self.assertEqual(len(versioned.children), 3)

        current = tuto.load_version(sha=version)
        self.assertEqual(len(current.children), 3)

        for index, child in enumerate(current.children):
            self.assertEqual(child.slug, versioned.children[index].slug)  # same order

        # then, delete the second one:
        last_slug = versioned.children[2].slug
        version = versioned.children[1].repo_delete()
        self.assertEqual(len(versioned.children), 2)
        self.assertEqual(versioned.children[1].slug, last_slug)

        current = tuto.load_version(sha=version)
        self.assertEqual(len(current.children), 2)

        for index, child in enumerate(current.children):
            self.assertEqual(child.slug, versioned.children[index].slug)  # slug remains

        # same test with extracts
        chapter = versioned.children[0]
        chapter.repo_add_extract(title, random)  # x
        chapter.repo_add_extract(title, random)  # x-1
        version = chapter.repo_add_extract(title, random)  # x-2
        self.assertEqual(len(chapter.children), 3)

        current = tuto.load_version(sha=version)
        self.assertEqual(len(current.children[0].children), 3)

        for index, child in enumerate(current.children[0].children):
            self.assertEqual(child.slug, chapter.children[index].slug)  # slug remains

        # delete the second one!
        last_slug = chapter.children[2].slug
        version = chapter.children[1].repo_delete()
        self.assertEqual(len(chapter.children), 2)
        self.assertEqual(chapter.children[1].slug, last_slug)

        current = tuto.load_version(sha=version)
        self.assertEqual(len(current.children[0].children), 2)

        for index, child in enumerate(current.children[0].children):
            self.assertEqual(child.slug, chapter.children[index].slug)  # slug remains for extract as well!
Example #20
0
    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)
Example #21
0
 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())
Example #22
0
    def create_multiple_tags(self, number_of_tags=REST_PAGE_SIZE):
        tags = []
        for tag in range(0, number_of_tags):
            tags.append('number' + str(tag))

        # Prepare content containing all the tags
        content = PublishableContentFactory(type='TUTORIAL')
        content.add_tags(tags)
        content.save()
        content_draft = content.load_version()

        # then, publish it !
        publish_content(content, content_draft)
Example #23
0
    def setUp(self):
        settings.EMAIL_BACKEND = 'django.core.mail.backends.locmem.EmailBackend'
        self.mas = ProfileFactory().user
        self.overridden_zds_app['member']['bot_account'] = self.mas.username

        self.licence = LicenceFactory()

        self.user_author = ProfileFactory().user
        self.staff = StaffProfileFactory().user

        self.tuto = PublishableContentFactory(type='TUTORIAL')
        self.tuto.authors.add(self.user_author)
        UserGalleryFactory(gallery=self.tuto.gallery, user=self.user_author, mode='W')
        self.tuto.licence = self.licence
        self.tuto.save()

        self.tuto_draft = self.tuto.load_version()
        self.part1 = ContainerFactory(parent=self.tuto_draft, db_object=self.tuto)
        self.chapter1 = ContainerFactory(parent=self.part1, db_object=self.tuto)

        self.extract1 = ExtractFactory(container=self.chapter1, db_object=self.tuto)
Example #24
0
    def setUp(self):
        self.overridden_zds_app = overridden_zds_app
        # don't build PDF to speed up the tests
        overridden_zds_app['content']['build_pdf_when_published'] = False

        self.staff = StaffProfileFactory().user

        settings.EMAIL_BACKEND = 'django.core.mail.backends.locmem.EmailBackend'
        self.mas = ProfileFactory().user
        overridden_zds_app['member']['bot_account'] = self.mas.username

        self.licence = LicenceFactory()
        self.subcategory = SubCategoryFactory()

        self.user_author = ProfileFactory().user
        self.user_staff = StaffProfileFactory().user
        self.user_guest = ProfileFactory().user
        self.content = PublishableContentFactory(author_list=[self.user_author], light=False)
        self.part_published = ContainerFactory(db_object=self.content, light=False, parent=self.content.load_version())
        self.ignored_part = ContainerFactory(db_object=self.content, light=False, parent=self.content.load_version())
        ExtractFactory(db_object=self.content, container=self.part_published, light=False)
        ExtractFactory(db_object=self.content, container=self.ignored_part, light=False)
Example #25
0
    def test_extract_is_none(self):
        """Test the case of a null extract"""

        article = PublishableContentFactory(type='ARTICLE')
        versioned = article.load_version()

        given_title = 'Peu importe, en fait, ça compte peu'
        some_text = 'Disparaitra aussi vite que possible'

        # add a new extract with `None` for text
        version = versioned.repo_add_extract(given_title, None)

        # check on the model:
        new_extract = versioned.children[-1]
        self.assertIsNone(new_extract.text)

        # it remains when loading the manifest!
        versioned2 = article.load_version(sha=version)
        self.assertIsNotNone(versioned2)
        self.assertIsNone(versioned.children[-1].text)

        version = new_extract.repo_update(given_title, None)
        self.assertIsNone(new_extract.text)

        # it remains
        versioned2 = article.load_version(sha=version)
        self.assertIsNotNone(versioned2)
        self.assertIsNone(versioned.children[-1].text)

        version = new_extract.repo_update(given_title, some_text)
        self.assertIsNotNone(new_extract.text)
        self.assertEqual(some_text, new_extract.get_text())

        # now it changes
        versioned2 = article.load_version(sha=version)
        self.assertIsNotNone(versioned2)
        self.assertIsNotNone(versioned.children[-1].text)

        # ... and lets go back
        version = new_extract.repo_update(given_title, None)
        self.assertIsNone(new_extract.text)

        # it has changed
        versioned2 = article.load_version(sha=version)
        self.assertIsNotNone(versioned2)
        self.assertIsNone(versioned.children[-1].text)
Example #26
0
    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)
Example #27
0
    def test_indexation(self):
        """test the indexation and deletion of the different documents"""

        if not self.manager.connected_to_es:
            return

        # create a topic with a post
        topic = TopicFactory(forum=self.forum, author=self.user)
        post = PostFactory(topic=topic, author=self.user, position=1)

        topic = Topic.objects.get(pk=topic.pk)
        post = Post.objects.get(pk=post.pk)

        self.assertFalse(topic.es_already_indexed)
        self.assertTrue(topic.es_flagged)
        self.assertFalse(post.es_already_indexed)
        self.assertTrue(post.es_flagged)

        # create a middle-tutorial and publish it
        tuto = PublishableContentFactory(type='TUTORIAL')
        tuto.authors.add(self.user)
        tuto.save()

        tuto_draft = tuto.load_version()
        chapter1 = ContainerFactory(parent=tuto_draft, db_object=tuto)
        ExtractFactory(container=chapter1, db_object=tuto)
        published = publish_content(tuto, tuto_draft, is_major_update=True)

        tuto.sha_public = tuto_draft.current_version
        tuto.sha_draft = tuto_draft.current_version
        tuto.public_version = published
        tuto.save()

        published = PublishedContent.objects.get(content_pk=tuto.pk)
        self.assertFalse(published.es_already_indexed)
        self.assertTrue(published.es_flagged)

        # 1. index all
        for model in self.indexable:
            if model is FakeChapter:
                continue
            self.manager.es_bulk_indexing_of_model(model, force_reindexing=False)
            self.manager.refresh_index()

        topic = Topic.objects.get(pk=topic.pk)
        post = Post.objects.get(pk=post.pk)

        self.assertTrue(topic.es_already_indexed)
        self.assertFalse(topic.es_flagged)
        self.assertTrue(post.es_already_indexed)
        self.assertFalse(post.es_flagged)

        published = PublishedContent.objects.get(content_pk=tuto.pk)
        self.assertTrue(published.es_already_indexed)
        self.assertFalse(published.es_flagged)

        s = Search()
        s.query(MatchAll())
        results = self.manager.setup_search(s).execute()
        self.assertEqual(len(results), 4)  # get 4 results, one of each type

        must_contain = {'post': False, 'topic': False, 'publishedcontent': False, 'chapter': False}
        id_must_be = {
            'post': str(post.pk),
            'topic': str(topic.pk),
            'publishedcontent': str(published.pk),
            'chapter': tuto.slug + '__' + chapter1.slug
        }

        for hit in results:
            doc_type = hit.meta.doc_type
            must_contain[doc_type] = True
            self.assertEqual(hit.meta.id, id_must_be[doc_type])

        self.assertTrue(all(must_contain))

        # 2. Test what reindexation will do:
        new_topic = TopicFactory(forum=self.forum, author=self.user)
        new_post = PostFactory(topic=new_topic, author=self.user, position=1)

        pk_of_topics_to_reindex = []
        for item in Topic.get_es_indexable(force_reindexing=False):
            pk_of_topics_to_reindex.append(item.pk)

        pk_of_posts_to_reindex = []
        for item in Post.get_es_indexable(force_reindexing=False):
            pk_of_posts_to_reindex.append(item.pk)

        self.assertTrue(topic.pk not in pk_of_topics_to_reindex)
        self.assertTrue(new_topic.pk in pk_of_topics_to_reindex)
        self.assertTrue(post.pk not in pk_of_posts_to_reindex)
        self.assertTrue(new_post.pk in pk_of_posts_to_reindex)

        for model in self.indexable:  # ok, so let's index that
            if model is FakeChapter:
                continue
            self.manager.es_bulk_indexing_of_model(model, force_reindexing=False)
        self.manager.refresh_index()

        s = Search()
        s.query(MatchAll())
        results = self.manager.setup_search(s).execute()
        self.assertEqual(len(results), 6)  # good!

        # 3. Test single deletion:
        new_post = Post.objects.get(pk=new_post.pk)

        self.manager.delete_document(new_post)
        self.manager.refresh_index()

        s = Search()
        s.query(MatchAll())
        results = self.manager.setup_search(s).execute()
        self.assertEqual(len(results), 5)  # one is missing

        for hit in results:
            self.assertTrue(hit.meta.doc_type != Post.get_es_document_type() or hit.meta.id != new_post.es_id)

        # 4. Test "delete_by_query_deletion":
        topic = Topic.objects.get(pk=topic.pk)
        new_topic = Topic.objects.get(pk=new_topic.pk)

        self.manager.delete_by_query(Topic.get_es_document_type(), MatchAll())  # the two topic are deleted
        self.manager.refresh_index()

        s = Search()
        s.query(MatchAll())
        results = self.manager.setup_search(s).execute()
        self.assertEqual(len(results), 3)

        for hit in results:
            self.assertTrue(hit.meta.doc_type != Topic.get_es_document_type() or hit.meta.id != new_topic.es_id)
            self.assertTrue(hit.meta.doc_type != Topic.get_es_document_type() or hit.meta.id != topic.es_id)

        # 5. Test that the deletion of an object also triggers its deletion in ES
        post = Post.objects.get(pk=post.pk)
        post.delete()
        self.manager.refresh_index()

        s = Search()
        s.query(MatchAll())
        results = self.manager.setup_search(s).execute()
        self.assertEqual(len(results), 2)

        for hit in results:
            self.assertTrue(hit.meta.doc_type != Post.get_es_document_type() or hit.meta.id != post.es_id)

        # 6. Test full desindexation:
        for model in self.indexable:
            if model is FakeChapter:
                continue
            self.manager.clear_indexing_of_model(model)

        # note "topic" is gone since "post" is gone, due to relationships at the Django level
        new_topic = Topic.objects.get(pk=new_topic.pk)
        new_post = Post.objects.get(pk=new_post.pk)

        self.assertFalse(new_topic.es_already_indexed)
        self.assertTrue(new_topic.es_flagged)
        self.assertFalse(new_post.es_already_indexed)
        self.assertTrue(new_post.es_flagged)

        published = PublishedContent.objects.get(content_pk=tuto.pk)
        self.assertFalse(published.es_already_indexed)
        self.assertTrue(published.es_flagged)
Example #28
0
    def test_opinion_conversion(self):
        """
        Test the conversion of PublishableContent with type=OPINION
        to PublishableContent with type=ARTICLE
        """

        text_publication = 'Aussi tôt dit, aussi tôt fait !'

        opinion = PublishableContentFactory(type='OPINION')

        opinion.authors.add(self.user_author)
        UserGalleryFactory(gallery=opinion.gallery,
                           user=self.user_author,
                           mode='W')
        opinion.licence = self.licence
        opinion.save()

        opinion_draft = opinion.load_version()
        ExtractFactory(container=opinion_draft, db_object=opinion)
        ExtractFactory(container=opinion_draft, db_object=opinion)

        self.assertEqual(
            self.client.login(username=self.user_author.username,
                              password='******'), True)

        # publish
        result = self.client.post(reverse('validation:publish-opinion',
                                          kwargs={
                                              'pk': opinion.pk,
                                              'slug': opinion.slug
                                          }),
                                  {
                                      'text': text_publication,
                                      'source': '',
                                      'version': opinion_draft.current_version
                                  },
                                  follow=False)
        self.assertEqual(result.status_code, 302)

        self.assertEqual(PublishedContent.objects.count(), 1)

        opinion = PublishableContent.objects.get(pk=opinion.pk)
        self.assertIsNotNone(opinion.public_version)
        self.assertEqual(opinion.public_version.sha_public,
                         opinion_draft.current_version)

        # valid with author => 403
        result = self.client.post(reverse('validation:promote-opinion',
                                          kwargs={
                                              'pk': opinion.pk,
                                              'slug': opinion.slug
                                          }),
                                  {
                                      'source': '',
                                      'version': opinion_draft.current_version
                                  },
                                  follow=False)
        self.assertEqual(result.status_code, 403)

        self.assertEqual(
            self.client.login(username=self.user_staff.username,
                              password='******'), True)

        # valid with staff
        result = self.client.post(reverse('validation:promote-opinion',
                                          kwargs={
                                              'pk': opinion.pk,
                                              'slug': opinion.slug
                                          }),
                                  {
                                      'source': '',
                                      'version': opinion_draft.current_version
                                  },
                                  follow=False)
        self.assertEqual(result.status_code, 302)
Example #29
0
    def test_validation_list(self):
        """ensure the behavior of the `validation:list` page (with filters)"""

        text = 'Ceci est un éléphant'

        tuto_not_reserved = PublishableContentFactory(
            type='TUTORIAL', author_list=[self.user_author])
        tuto_reserved = PublishableContentFactory(
            type='TUTORIAL', author_list=[self.user_author])
        article_not_reserved = PublishableContentFactory(
            type='ARTICLE', author_list=[self.user_author])
        article_reserved = PublishableContentFactory(
            type='ARTICLE', author_list=[self.user_author])

        all_contents = [
            tuto_not_reserved, tuto_reserved, article_not_reserved,
            article_reserved
        ]
        reserved_contents = [tuto_reserved, article_reserved]

        # apply a filter to test category filter
        subcat = SubCategoryFactory()
        article_reserved.subcategory.add(subcat)
        article_reserved.save()

        # send in validation
        for content in all_contents:
            v = ValidationFactory(content=content, status='PENDING')
            v.date_proposition = datetime.datetime.now()
            v.version = content.sha_draft
            v.comment_authors = text

            if content in reserved_contents:
                v.validator = self.user_staff
                v.date_reserve = datetime.datetime.now()
                v.status = 'PENDING_V'

            v.save()

        # first, test access for public
        result = self.client.get(reverse('validation:list'), follow=False)
        self.assertEqual(result.status_code,
                         302)  # get 302 → redirection to login

        # connect with author:
        self.assertEqual(
            self.client.login(username=self.user_author.username,
                              password='******'), True)

        result = self.client.get(reverse('validation:list'), follow=False)
        self.assertEqual(result.status_code, 403)  # get 403 not allowed

        self.client.logout()

        # connect with staff:
        self.assertEqual(
            self.client.login(username=self.user_staff.username,
                              password='******'), True)

        response = self.client.get(reverse('validation:list'), follow=False)
        self.assertEqual(response.status_code, 200)  # OK

        validations = response.context['validations']
        self.assertEqual(len(validations),
                         4)  # a total of 4 contents in validation

        # test filters
        response = self.client.get(reverse('validation:list') +
                                   '?type=article',
                                   follow=False)
        self.assertEqual(response.status_code, 200)  # OK
        validations = response.context['validations']
        self.assertEqual(len(validations), 2)  # 2 articles

        response = self.client.get(reverse('validation:list') + '?type=tuto',
                                   follow=False)
        self.assertEqual(response.status_code, 200)  # OK
        validations = response.context['validations']
        self.assertEqual(len(validations), 2)  # 2 articles

        response = self.client.get(reverse('validation:list') + '?type=orphan',
                                   follow=False)
        self.assertEqual(response.status_code, 200)  # OK
        validations = response.context['validations']
        self.assertEqual(len(validations), 2)  # 2 not-reserved content

        for validation in validations:
            self.assertFalse(validation.content in reserved_contents)

        response = self.client.get(reverse('validation:list') +
                                   '?type=reserved',
                                   follow=False)
        self.assertEqual(response.status_code, 200)  # OK
        validations = response.context['validations']
        self.assertEqual(len(validations), 2)  # 2 reserved content

        for validation in validations:
            self.assertTrue(validation.content in reserved_contents)

        response = self.client.get(reverse('validation:list') +
                                   '?subcategory={}'.format(subcat.pk),
                                   follow=False)
        self.assertEqual(response.status_code, 200)  # OK
        validations = response.context['validations']
        self.assertEqual(len(validations), 1)  # 1 content with this category

        self.assertEqual(validations[0].content,
                         article_reserved)  # the right content
Example #30
0
    def test_ignore_opinion(self):
        opinion = PublishableContentFactory(type='OPINION')

        opinion.authors.add(self.user_author)
        UserGalleryFactory(gallery=opinion.gallery,
                           user=self.user_author,
                           mode='W')
        opinion.licence = self.licence
        opinion.save()

        opinion_draft = opinion.load_version()
        ExtractFactory(container=opinion_draft, db_object=opinion)
        ExtractFactory(container=opinion_draft, db_object=opinion)

        self.assertEqual(
            self.client.login(username=self.user_author.username,
                              password='******'), True)

        # publish
        result = self.client.post(reverse('validation:publish-opinion',
                                          kwargs={
                                              'pk': opinion.pk,
                                              'slug': opinion.slug
                                          }),
                                  {
                                      'source': '',
                                      'version': opinion_draft.current_version
                                  },
                                  follow=False)
        self.assertEqual(result.status_code, 302)

        # ignore with author => 403
        result = self.client.post(reverse('validation:ignore-opinion',
                                          kwargs={
                                              'pk': opinion.pk,
                                              'slug': opinion.slug
                                          }), {
                                              'operation': 'NO_PICK',
                                          },
                                  follow=False)
        self.assertEqual(result.status_code, 403)

        # now, login as staff
        self.assertEqual(
            self.client.login(username=self.user_staff.username,
                              password='******'), True)

        # check that the opinion is displayed
        result = self.client.get(reverse('validation:list-opinion'))
        self.assertContains(result, opinion.title)

        # ignore the opinion
        result = self.client.post(reverse('validation:ignore-opinion',
                                          kwargs={
                                              'pk': opinion.pk,
                                              'slug': opinion.slug
                                          }), {
                                              'operation': 'NO_PICK',
                                          },
                                  follow=False)
        self.assertEqual(result.status_code, 200)

        # check that the opinion is not displayed
        result = self.client.get(reverse('validation:list-opinion'))
        self.assertNotContains(result, opinion.title)

        # publish the opinion again
        result = self.client.post(reverse('validation:publish-opinion',
                                          kwargs={
                                              'pk': opinion.pk,
                                              'slug': opinion.slug
                                          }),
                                  {
                                      'source': '',
                                      'version': opinion_draft.current_version
                                  },
                                  follow=False)
        self.assertEqual(result.status_code, 302)

        # check that the opinion is displayed
        result = self.client.get(reverse('validation:list-opinion'))
        self.assertContains(result, opinion.title)

        # reject it
        result = self.client.post(reverse('validation:ignore-opinion',
                                          kwargs={
                                              'pk': opinion.pk,
                                              'slug': opinion.slug
                                          }), {
                                              'operation': 'REJECT',
                                          },
                                  follow=False)
        self.assertEqual(result.status_code, 200)

        # publish again
        result = self.client.post(reverse('validation:publish-opinion',
                                          kwargs={
                                              'pk': opinion.pk,
                                              'slug': opinion.slug
                                          }),
                                  {
                                      'source': '',
                                      'version': opinion_draft.current_version
                                  },
                                  follow=False)
        self.assertEqual(result.status_code, 302)

        # check that the opinion is not displayed
        result = self.client.get(reverse('validation:list-opinion'))
        self.assertNotContains(result, opinion.title)
Example #31
0
    def test_defenitely_unpublish_alerted_opinion(self):
        opinion = PublishableContentFactory(type='OPINION')

        opinion.authors.add(self.user_author)
        UserGalleryFactory(gallery=opinion.gallery,
                           user=self.user_author,
                           mode='W')
        opinion.licence = self.licence
        opinion.save()

        opinion_draft = opinion.load_version()
        ExtractFactory(container=opinion_draft, db_object=opinion)
        ExtractFactory(container=opinion_draft, db_object=opinion)

        self.assertEqual(
            self.client.login(username=self.user_author.username,
                              password='******'), True)

        # publish
        result = self.client.post(reverse('validation:publish-opinion',
                                          kwargs={
                                              'pk': opinion.pk,
                                              'slug': opinion.slug
                                          }),
                                  {
                                      'source': '',
                                      'version': opinion_draft.current_version
                                  },
                                  follow=False)
        self.assertEqual(result.status_code, 302)

        # login as staff
        self.assertEqual(
            self.client.login(username=self.user_staff.username,
                              password='******'), True)
        alerter = ProfileFactory().user
        Alert.objects.create(
            author=alerter,
            scope='CONTENT',
            content=opinion,
            pubdate=datetime.datetime.now(),
            text="J'ai un probleme avec cette opinion : c'est pas la mienne.")
        # unpublish opinion
        result = self.client.post(reverse('validation:ignore-opinion',
                                          kwargs={
                                              'pk': opinion.pk,
                                              'slug': opinion.slug
                                          }), {
                                              'operation': 'REMOVE_PUB',
                                          },
                                  follow=False)
        self.assertEqual(result.status_code, 200)

        # refresh
        opinion = PublishableContent.objects.get(pk=opinion.pk)

        # check that the opinion is not published
        self.assertFalse(opinion.in_public())

        # check that it's impossible to publish the opinion again
        result = self.client.get(opinion.get_absolute_url())
        self.assertContains(result, _('Billet modéré'))  # front

        result = self.client.post(reverse('validation:publish-opinion',
                                          kwargs={
                                              'pk': opinion.pk,
                                              'slug': opinion.slug
                                          }),
                                  {
                                      'source': '',
                                      'version': opinion_draft.current_version
                                  },
                                  follow=False)
        self.assertEqual(result.status_code, 403)  # back
        self.assertTrue(Alert.objects.filter(content=opinion).last().solved)
        # check alert page is still accessible and our alert is well displayed
        resp = self.client.get(reverse('pages-alerts'))
        self.assertEqual(200, resp.status_code)
        self.assertEqual(0, len(resp.context['alerts']))
        self.assertEqual(1, len(resp.context['solved']))
Example #32
0
class ContentNotification(TestCase, TutorialTestMixin):
    def setUp(self):

        # don't build PDF to speed up the tests
        overridden_zds_app['content']['build_pdf_when_published'] = False
        self.overridden_zds_app = overridden_zds_app
        self.user1 = ProfileFactory().user
        self.user2 = ProfileFactory().user

        # create a tutorial
        self.tuto = PublishableContentFactory(type='TUTORIAL')
        self.tuto.authors.add(self.user1)
        UserGalleryFactory(gallery=self.tuto.gallery,
                           user=self.user1,
                           mode='W')
        self.tuto.licence = LicenceFactory()
        self.tuto.subcategory.add(SubCategoryFactory())
        self.tuto.save()
        tuto_draft = self.tuto.load_version()

        # then, publish it !
        version = tuto_draft.current_version
        self.published = publish_content(self.tuto,
                                         tuto_draft,
                                         is_major_update=True)

        self.tuto.sha_public = version
        self.tuto.sha_draft = version
        self.tuto.public_version = self.published
        self.tuto.save()

        self.assertTrue(
            self.client.login(username=self.user1.username,
                              password='******'))

    def test_no_persistant_notif_on_revoke(self):
        from zds.tutorialv2.publication_utils import unpublish_content
        NewPublicationSubscription.objects.get_or_create_active(
            self.user1, self.user2)
        content = PublishedContentFactory(author_list=[self.user2])

        notif_signals.new_content.send(sender=self.tuto.__class__,
                                       instance=content,
                                       by_email=False)
        self.assertEqual(
            1, len(Notification.objects.get_notifications_of(self.user1)))
        unpublish_content(content)
        self.assertEqual(
            0, len(Notification.objects.get_notifications_of(self.user1)))

    def test_only_one_notif_on_update(self):
        NewPublicationSubscription.objects.get_or_create_active(
            self.user1, self.user2)
        content = PublishedContentFactory(author_list=[self.user2])
        notify_update(content, False, True)
        versioned = content.load_version()
        content.sha_draft = versioned.repo_update(introduction='new intro',
                                                  conclusion='new conclusion',
                                                  title=versioned.title)
        content.save(force_slug_update=False)
        publish_content(content, content.load_version(), True)
        notify_update(content, True, False)
        notifs = interventions_topics(self.user1)
        self.assertEqual(1, len(notifs), str(notifs))

    def test_only_one_notif_on_major_update(self):
        NewPublicationSubscription.objects.get_or_create_active(
            self.user1, self.user2)
        content = PublishedContentFactory(author_list=[self.user2])
        notify_update(content, False, True)
        versioned = content.load_version()
        content.sha_draft = versioned.repo_update(introduction='new intro',
                                                  conclusion='new conclusion',
                                                  title=versioned.title)
        content.save(force_slug_update=False)
        publish_content(content, content.load_version(), True)
        notify_update(content, True, True)
        notifs = interventions_topics(self.user1)
        self.assertEqual(1, len(notifs), str(notifs))
Example #33
0
    def test_unregister(self):
        """
        To test that unregistering user is working.
        """

        # test not logged user can't unregister.
        self.client.logout()
        result = self.client.post(
            reverse('member-unregister'),
            follow=False)
        self.assertEqual(result.status_code, 302)

        # test logged user can register.
        user = ProfileFactory()
        login_check = self.client.login(
            username=user.user.username,
            password='******')
        self.assertEqual(login_check, True)
        result = self.client.post(
            reverse('member-unregister'),
            follow=False)
        self.assertEqual(result.status_code, 302)
        self.assertEqual(User.objects.filter(username=user.user.username).count(), 0)

        # Attach a user at tutorials, articles, topics and private topics. After that,
        # unregister this user and check that he is well removed in all contents.
        user = ProfileFactory()
        user2 = ProfileFactory()
        alone_gallery = GalleryFactory()
        UserGalleryFactory(gallery=alone_gallery, user=user.user)
        shared_gallery = GalleryFactory()
        UserGalleryFactory(gallery=shared_gallery, user=user.user)
        UserGalleryFactory(gallery=shared_gallery, user=user2.user)
        # first case : a published tutorial with only one author
        published_tutorial_alone = PublishedContentFactory(type='TUTORIAL')
        published_tutorial_alone.authors.add(user.user)
        published_tutorial_alone.save()
        # second case : a published tutorial with two authors
        published_tutorial_2 = PublishedContentFactory(type='TUTORIAL')
        published_tutorial_2.authors.add(user.user)
        published_tutorial_2.authors.add(user2.user)
        published_tutorial_2.save()
        # third case : a private tutorial with only one author
        writing_tutorial_alone = PublishableContentFactory(type='TUTORIAL')
        writing_tutorial_alone.authors.add(user.user)
        writing_tutorial_alone.save()
        writing_tutorial_alone_galler_path = writing_tutorial_alone.gallery.get_gallery_path()
        # fourth case : a private tutorial with at least two authors
        writing_tutorial_2 = PublishableContentFactory(type='TUTORIAL')
        writing_tutorial_2.authors.add(user.user)
        writing_tutorial_2.authors.add(user2.user)
        writing_tutorial_2.save()
        self.client.login(username=self.staff.username, password="******")
        # same thing for articles
        published_article_alone = PublishedContentFactory(type='ARTICLE')
        published_article_alone.authors.add(user.user)
        published_article_alone.save()
        published_article_2 = PublishedContentFactory(type='ARTICLE')
        published_article_2.authors.add(user.user)
        published_article_2.authors.add(user2.user)
        published_article_2.save()
        writing_article_alone = PublishableContentFactory(type='ARTICLE')
        writing_article_alone.authors.add(user.user)
        writing_article_alone.save()
        writing_article_2 = PublishableContentFactory(type='ARTICLE')
        writing_article_2.authors.add(user.user)
        writing_article_2.authors.add(user2.user)
        writing_article_2.save()
        # beta content
        beta_forum = ForumFactory(category=CategoryFactory())
        beta_content = BetaContentFactory(author_list=[user.user], forum=beta_forum)
        beta_content_2 = BetaContentFactory(author_list=[user.user, user2.user], forum=beta_forum)
        # about posts and topics
        authored_topic = TopicFactory(author=user.user, forum=self.forum11)
        answered_topic = TopicFactory(author=user2.user, forum=self.forum11)
        PostFactory(topic=answered_topic, author=user.user, position=2)
        edited_answer = PostFactory(topic=answered_topic, author=user.user, position=3)
        edited_answer.editor = user.user
        edited_answer.save()

        upvoted_answer = PostFactory(topic=answered_topic, author=user2.user, position=4)
        upvoted_answer.like += 1
        upvoted_answer.save()
        CommentVote.objects.create(user=user.user, comment=upvoted_answer, positive=True)

        private_topic = PrivateTopicFactory(author=user.user)
        private_topic.participants.add(user2.user)
        private_topic.save()
        PrivatePostFactory(author=user.user, privatetopic=private_topic, position_in_topic=1)

        # login and unregister:
        login_check = self.client.login(
            username=user.user.username,
            password='******')
        self.assertEqual(login_check, True)
        result = self.client.post(
            reverse('member-unregister'),
            follow=False)
        self.assertEqual(result.status_code, 302)

        # check that the bot have taken authorship of tutorial:
        self.assertEqual(published_tutorial_alone.authors.count(), 1)
        self.assertEqual(published_tutorial_alone.authors.first().username,
                         settings.ZDS_APP["member"]["external_account"])
        self.assertFalse(os.path.exists(writing_tutorial_alone_galler_path))
        self.assertEqual(published_tutorial_2.authors.count(), 1)
        self.assertEqual(published_tutorial_2.authors
                         .filter(username=settings.ZDS_APP["member"]["external_account"])
                         .count(), 0)

        # check that published tutorials remain published and accessible
        self.assertIsNotNone(published_tutorial_2.public_version.get_prod_path())
        self.assertTrue(os.path.exists(published_tutorial_2.public_version.get_prod_path()))
        self.assertIsNotNone(published_tutorial_alone.public_version.get_prod_path())
        self.assertTrue(os.path.exists(published_tutorial_alone.public_version.get_prod_path()))
        self.assertEqual(self.client.get(
            reverse('tutorial:view', args=[
                    published_tutorial_alone.pk,
                    published_tutorial_alone.slug]), follow=False).status_code, 200)
        self.assertEqual(self.client.get(
            reverse('tutorial:view', args=[
                    published_tutorial_2.pk,
                    published_tutorial_2.slug]), follow=False).status_code, 200)

        # test that published articles remain accessible
        self.assertTrue(os.path.exists(published_article_alone.public_version.get_prod_path()))
        self.assertEqual(self.client.get(
            reverse(
                'article:view',
                args=[
                    published_article_alone.pk,
                    published_article_alone.slug]),
            follow=True).status_code, 200)
        self.assertEqual(self.client.get(
            reverse(
                'article:view',
                args=[
                    published_article_2.pk,
                    published_article_2.slug]),
            follow=True).status_code, 200)

        # check that the tutorial for which the author was alone does not exists anymore
        self.assertEqual(PublishableContent.objects.filter(pk=writing_tutorial_alone.pk).count(), 0)
        self.assertFalse(os.path.exists(writing_tutorial_alone.get_repo_path()))

        # check that bot haven't take the authorship of the tuto with more than one author
        self.assertEqual(writing_tutorial_2.authors.count(), 1)
        self.assertEqual(writing_tutorial_2.authors
                         .filter(username=settings.ZDS_APP["member"]["external_account"])
                         .count(), 0)

        # authorship for the article for which user was the only author
        self.assertEqual(published_article_alone.authors.count(), 1)
        self.assertEqual(published_article_alone.authors
                         .first().username, settings.ZDS_APP["member"]["external_account"])
        self.assertEqual(published_article_2.authors.count(), 1)

        self.assertEqual(PublishableContent.objects.filter(pk=writing_article_alone.pk).count(), 0)
        self.assertFalse(os.path.exists(writing_article_alone.get_repo_path()))

        # not bot if another author:
        self.assertEqual(published_article_2.authors
                         .filter(username=settings.ZDS_APP["member"]["external_account"]).count(), 0)
        self.assertEqual(writing_article_2.authors.count(), 1)
        self.assertEqual(writing_article_2.authors
                         .filter(username=settings.ZDS_APP["member"]["external_account"]).count(), 0)

        # topics, gallery and PMs:
        self.assertEqual(Topic.objects.filter(author__username=user.user.username).count(), 0)
        self.assertEqual(Post.objects.filter(author__username=user.user.username).count(), 0)
        self.assertEqual(Post.objects.filter(editor__username=user.user.username).count(), 0)
        self.assertEqual(PrivatePost.objects.filter(author__username=user.user.username).count(), 0)
        self.assertEqual(PrivateTopic.objects.filter(author__username=user.user.username).count(), 0)

        self.assertIsNotNone(Topic.objects.get(pk=authored_topic.pk))
        self.assertIsNotNone(PrivateTopic.objects.get(pk=private_topic.pk))
        self.assertIsNotNone(Gallery.objects.get(pk=alone_gallery.pk))
        self.assertEquals(alone_gallery.get_linked_users().count(), 1)
        self.assertEquals(shared_gallery.get_linked_users().count(), 1)
        self.assertEquals(UserGallery.objects.filter(user=user.user).count(), 0)
        self.assertEquals(CommentVote.objects.filter(user=user.user, positive=True).count(), 0)
        self.assertEquals(Post.objects.filter(pk=upvoted_answer.id).first().like, 0)

        # zep 12, published contents and beta
        self.assertIsNotNone(PublishedContent.objects.filter(content__pk=published_tutorial_alone.pk).first())
        self.assertIsNotNone(PublishedContent.objects.filter(content__pk=published_tutorial_2.pk).first())
        self.assertTrue(Topic.objects.get(pk=beta_content.beta_topic.pk).is_locked)
        self.assertFalse(Topic.objects.get(pk=beta_content_2.beta_topic.pk).is_locked)
Example #34
0
class InterventionsTest(TestCase):
    """
    This test uses quite complicated paths to check number of notifications:
    1. Create private topics and do stuff with them
    2. User signs in
    3. Render the home page
    4. Check the number of unread private messages on home page source code
    This because a correct test of this function requires a complete context (or it behaves strangely)
    """
    def setUp(self):
        self.licence = LicenceFactory()
        self.subcategory = SubCategoryFactory()

        self.author = ProfileFactory()
        self.user = ProfileFactory()
        self.staff = StaffProfileFactory()

        self.tuto = PublishableContentFactory(type='TUTORIAL')
        self.tuto.authors.add(self.author.user)
        self.tuto.licence = self.licence
        self.tuto.subcategory.add(self.subcategory)
        self.tuto.save()

        self.validation = Validation(
            content=self.tuto,
            version=self.tuto.sha_draft,
            comment_authors='bla',
            date_proposition=datetime.now(),
        )
        self.validation.save()

        self.topic = send_mp(author=self.author.user,
                             users=[],
                             title='Title',
                             text='Testing',
                             subtitle='',
                             leave=False)
        self.topic.participants.add(self.user.user)
        send_message_mp(self.user.user, self.topic, 'Testing')

        # humane_delta test
        periods = ((1, 0), (2, 1), (3, 7), (4, 30), (5, 360))
        cont = dict()
        cont['date_today'] = periods[0][0]
        cont['date_yesterday'] = periods[1][0]
        cont['date_last_week'] = periods[2][0]
        cont['date_last_month'] = periods[3][0]
        cont['date_last_year'] = periods[4][0]
        self.context = Context(cont)

    def test_interventions_privatetopics(self):

        self.assertTrue(
            self.client.login(username=self.author.user.username,
                              password='******'))
        response = self.client.post(reverse('homepage'))
        self.assertEqual(200, response.status_code)
        self.assertContains(response,
                            '<span class="notif-count">1</span>',
                            html=True)

        self.client.logout()

        self.assertTrue(
            self.client.login(username=self.user.user.username,
                              password='******'))
        response = self.client.post(reverse('homepage'))
        self.assertEqual(200, response.status_code)
        self.assertContains(response,
                            '<span class="notif-count">1</span>',
                            html=True)

    def test_interventions_privatetopics_author_leave(self):

        # profile1 (author) leave topic
        move = self.topic.participants.first()
        self.topic.author = move
        self.topic.participants.remove(move)
        self.topic.save()

        self.assertTrue(
            self.client.login(username=self.user.user.username,
                              password='******'))
        response = self.client.post(reverse('homepage'))
        self.assertEqual(200, response.status_code)
        self.assertContains(response,
                            '<span class="notif-count">1</span>',
                            html=True)

    def test_interventions_waiting_contents(self):
        # Login as staff
        self.assertTrue(
            self.client.login(username=self.staff.user.username,
                              password='******'))

        # check that the number of waiting tutorials is correct
        response = self.client.post(reverse('homepage'))
        self.assertEqual(200, response.status_code)
        self.assertContains(response, '(1)')

        # Mark the content as reserved
        self.validation.status = 'PENDING_V'
        self.validation.save()

        # and check that the count was removed
        response = self.client.post(reverse('homepage'))
        self.assertEqual(200, response.status_code)
        self.assertNotContains(response, '(1)')

    def test_interventions_humane_delta(self):
        tr = Template('{% load interventions %}'
                      '{{ date_today|humane_delta }}').render(self.context)
        self.assertEqual('Aujourd&#39;hui', tr)

        tr = Template('{% load interventions %}'
                      '{{ date_yesterday|humane_delta }}').render(self.context)
        self.assertEqual('Hier', tr)

        tr = Template('{% load interventions %}'
                      '{{ date_last_week|humane_delta }}').render(self.context)
        self.assertEqual('Les 7 derniers jours', tr)

        tr = Template('{% load interventions %}'
                      '{{ date_last_month|humane_delta }}').render(
                          self.context)
        self.assertEqual('Les 30 derniers jours', tr)

        tr = Template('{% load interventions %}'
                      '{{ date_last_year|humane_delta }}').render(self.context)
        self.assertEqual('Plus ancien', tr)
Example #35
0
class ContentTests(TestCase):

    def setUp(self):

        # don't build PDF to speed up the tests
        overridden_zds_app['content']['build_pdf_when_published'] = False

        settings.EMAIL_BACKEND = 'django.core.mail.backends.locmem.EmailBackend'
        self.mas = ProfileFactory().user
        overridden_zds_app['member']['bot_account'] = self.mas.username

        self.licence = LicenceFactory()

        self.user_author = ProfileFactory().user
        self.staff = StaffProfileFactory().user

        self.tuto = PublishableContentFactory(type='TUTORIAL')
        self.tuto.authors.add(self.user_author)
        UserGalleryFactory(gallery=self.tuto.gallery, user=self.user_author, mode='W')
        self.tuto.licence = self.licence
        self.tuto.save()

        self.tuto_draft = self.tuto.load_version()
        self.part1 = ContainerFactory(parent=self.tuto_draft, db_object=self.tuto)
        self.chapter1 = ContainerFactory(parent=self.part1, db_object=self.tuto)

        self.extract1 = ExtractFactory(container=self.chapter1, db_object=self.tuto)

    def test_workflow_content(self):
        """
        General tests for a content
        """
        # ensure the usability of manifest
        versioned = self.tuto.load_version()
        self.assertEqual(self.tuto_draft.title, versioned.title)
        self.assertEqual(self.part1.title, versioned.children[0].title)
        self.assertEqual(self.extract1.title, versioned.children[0].children[0].children[0].title)

        # ensure url resolution project using dictionary:
        self.assertTrue(self.part1.slug in list(versioned.children_dict.keys()))
        self.assertTrue(self.chapter1.slug in versioned.children_dict[self.part1.slug].children_dict)

    def test_slug_pool(self):
        versioned = self.tuto.load_version()

        for i in [1, 2, 3]:
            slug = 'introduction-' + str(i)
            self.assertEqual(slug, versioned.get_unique_slug('introduction'))
            self.assertTrue(slug in versioned.slug_pool)

    def test_ensure_unique_slug(self):
        """
        Ensure that slugs for a container or extract are always unique
        """
        # get draft version
        versioned = self.tuto.load_version()

        # forbidden slugs:
        slug_to_test = ['introduction', 'conclusion']

        for slug in slug_to_test:
            new_slug = versioned.get_unique_slug(slug)
            self.assertNotEqual(slug, new_slug)
            self.assertTrue(new_slug in versioned.slug_pool)  # ensure new slugs are in slug pool

        # then test with 'real' containers and extracts:
        new_chapter_1 = ContainerFactory(title='aa', parent=versioned, db_object=self.tuto)
        new_chapter_2 = ContainerFactory(title='aa', parent=versioned, db_object=self.tuto)
        self.assertNotEqual(new_chapter_1.slug, new_chapter_2.slug)
        new_extract_1 = ExtractFactory(title='aa', container=new_chapter_1, db_object=self.tuto)
        self.assertEqual(new_extract_1.slug, new_chapter_1.slug)  # different level can have the same slug!

        new_extract_2 = ExtractFactory(title='aa', container=new_chapter_2, db_object=self.tuto)
        self.assertEqual(new_extract_2.slug, new_extract_1.slug)  # not the same parent, so allowed

        new_extract_3 = ExtractFactory(title='aa', container=new_chapter_1, db_object=self.tuto)
        self.assertNotEqual(new_extract_3.slug, new_extract_1.slug)  # same parent, forbidden

    def test_ensure_unique_slug_2(self):
        """This test is an extension of the previous one, with the manifest reloaded each time"""

        title = "Il existe des gens que la ZEP-12 n'aime pas"
        random = "... Mais c'est pas censé arriver, donc on va tout faire pour que ça disparaisse !"

        # get draft version
        versioned = self.tuto.load_version()

        # add containers
        version = versioned.repo_add_container(title, random, random)
        new_version = self.tuto.load_version(sha=version)
        self.assertEqual(new_version.children[-1].slug, versioned.children[-1].slug)

        slugs = [new_version.children[-1].slug]

        for i in range(0, 2):  # will add 3 new container
            version = versioned.repo_add_container(title, random, random)
            new_version = self.tuto.load_version(sha=version)
            self.assertEqual(new_version.children[-1].slug, versioned.children[-1].slug)
            self.assertTrue(new_version.children[-1].slug not in slugs)  # slug is different
            self.assertTrue(versioned.children[-1].slug not in slugs)

            slugs.append(new_version.children[-1].slug)

        # add extracts
        extract_title = "On va changer de titre (parce qu'on sais jamais) !"

        chapter = versioned.children[-1]  # for this second test, the last chapter will be used
        version = chapter.repo_add_extract(extract_title, random)
        new_version = self.tuto.load_version(sha=version)
        self.assertEqual(new_version.children[-1].children[-1].slug, chapter.children[-1].slug)

        slugs = [new_version.children[-1].children[-1].slug]

        for i in range(0, 2):  # will add 3 new extracts with the same title
            version = chapter.repo_add_extract(extract_title, random)
            new_version = self.tuto.load_version(sha=version)
            self.assertTrue(new_version.children[-1].children[-1].slug not in slugs)
            self.assertTrue(chapter.children[-1].slug not in slugs)

            slugs.append(new_version.children[-1].children[-1].slug)

    def test_workflow_repository(self):
        """
        Test to ensure the behavior of repo_*() functions:
        - if they change the filesystem as they are suppose to ;
        - if they change the `self.sha_*` as they are suppose to.
        """

        new_title = 'Un nouveau titre'
        other_new_title = 'Un titre différent'
        random_text = "J'ai faim!"
        other_random_text = 'Oh, du chocolat <3'

        versioned = self.tuto.load_version()
        current_version = versioned.current_version
        slug_repository = versioned.slug_repository

        # VersionedContent:
        old_path = versioned.get_path()
        self.assertTrue(os.path.isdir(old_path))
        new_slug = versioned.get_unique_slug(new_title)  # normally, you get a new slug by asking database!

        versioned.repo_update_top_container(new_title, new_slug, random_text, random_text)
        self.assertNotEqual(versioned.sha_draft, current_version)
        self.assertNotEqual(versioned.current_version, current_version)
        self.assertEqual(versioned.current_version, versioned.sha_draft)
        current_version = versioned.current_version

        new_path = versioned.get_path()
        self.assertNotEqual(old_path, new_path)
        self.assertTrue(os.path.isdir(new_path))
        self.assertFalse(os.path.isdir(old_path))

        self.assertNotEqual(slug_repository, versioned.slug_repository)  # if this test fail, you're in trouble

        # Container:

        # 1. add new part:
        versioned.repo_add_container(new_title, random_text, random_text)
        self.assertNotEqual(versioned.sha_draft, current_version)
        self.assertNotEqual(versioned.current_version, current_version)
        self.assertEqual(versioned.current_version, versioned.sha_draft)
        current_version = versioned.current_version

        part = versioned.children[-1]
        old_path = part.get_path()
        self.assertTrue(os.path.isdir(old_path))
        self.assertTrue(os.path.exists(os.path.join(versioned.get_path(), part.introduction)))
        self.assertTrue(os.path.exists(os.path.join(versioned.get_path(), part.conclusion)))
        self.assertEqual(part.get_introduction(), random_text)
        self.assertEqual(part.get_conclusion(), random_text)

        # 2. update the part
        part.repo_update(other_new_title, other_random_text, other_random_text)
        self.assertNotEqual(versioned.sha_draft, current_version)
        self.assertNotEqual(versioned.current_version, current_version)
        self.assertEqual(versioned.current_version, versioned.sha_draft)
        current_version = versioned.current_version

        new_path = part.get_path()
        self.assertNotEqual(old_path, new_path)
        self.assertTrue(os.path.isdir(new_path))
        self.assertFalse(os.path.isdir(old_path))

        self.assertEqual(part.get_introduction(), other_random_text)
        self.assertEqual(part.get_conclusion(), other_random_text)

        # 3. delete it
        part.repo_delete()  # boom!
        self.assertNotEqual(versioned.sha_draft, current_version)
        self.assertNotEqual(versioned.current_version, current_version)
        self.assertEqual(versioned.current_version, versioned.sha_draft)
        current_version = versioned.current_version

        self.assertFalse(os.path.isdir(new_path))

        # Extract:

        # 1. add new extract
        versioned.repo_add_container(new_title, random_text, random_text)  # need to add a new part before
        part = versioned.children[-1]

        part.repo_add_extract(new_title, random_text)
        self.assertNotEqual(versioned.sha_draft, current_version)
        self.assertNotEqual(versioned.current_version, current_version)
        self.assertEqual(versioned.current_version, versioned.sha_draft)
        current_version = versioned.current_version

        extract = part.children[-1]
        old_path = extract.get_path()
        self.assertTrue(os.path.isfile(old_path))
        self.assertEqual(extract.get_text(), random_text)

        # 2. update extract
        extract.repo_update(other_new_title, other_random_text)
        self.assertNotEqual(versioned.sha_draft, current_version)
        self.assertNotEqual(versioned.current_version, current_version)
        self.assertEqual(versioned.current_version, versioned.sha_draft)
        current_version = versioned.current_version

        new_path = extract.get_path()
        self.assertNotEqual(old_path, new_path)
        self.assertTrue(os.path.isfile(new_path))
        self.assertFalse(os.path.isfile(old_path))

        self.assertEqual(extract.get_text(), other_random_text)

        # 3. update parent and see if it still works:
        part.repo_update(other_new_title, other_random_text, other_random_text)

        old_path = new_path
        new_path = extract.get_path()

        self.assertNotEqual(old_path, new_path)
        self.assertTrue(os.path.isfile(new_path))
        self.assertFalse(os.path.isfile(old_path))

        self.assertEqual(extract.get_text(), other_random_text)

        # 4. Boom, no more extract
        extract.repo_delete()
        self.assertNotEqual(versioned.sha_draft, current_version)
        self.assertNotEqual(versioned.current_version, current_version)
        self.assertEqual(versioned.current_version, versioned.sha_draft)

        self.assertFalse(os.path.exists(new_path))

    def test_if_none(self):
        """Test the case where introduction and conclusion are `None`"""

        given_title = "La vie secrète de Clem'"
        some_text = 'Tous ces secrets (ou pas)'
        versioned = self.tuto.load_version()
        # add a new part with `None` for intro and conclusion
        version = versioned.repo_add_container(given_title, None, None)

        # check on the model:
        new_part = versioned.children[-1]
        self.assertIsNone(new_part.introduction)
        self.assertIsNone(new_part.conclusion)

        # it remains when loading the manifest!
        versioned2 = self.tuto.load_version(sha=version)
        self.assertIsNotNone(versioned2)
        self.assertIsNone(versioned.children[-1].introduction)
        self.assertIsNone(versioned.children[-1].conclusion)

        version = new_part.repo_update(given_title, None, None)  # still `None`
        self.assertIsNone(new_part.introduction)
        self.assertIsNone(new_part.conclusion)

        # does it still remains?
        versioned2 = self.tuto.load_version(sha=version)
        self.assertIsNotNone(versioned2)
        self.assertIsNone(versioned.children[-1].introduction)
        self.assertIsNone(versioned.children[-1].conclusion)

        new_part.repo_update(given_title, some_text, some_text)
        self.assertIsNotNone(new_part.introduction)  # now, value given
        self.assertIsNotNone(new_part.conclusion)

        old_intro = new_part.introduction
        old_conclu = new_part.conclusion
        self.assertTrue(os.path.isfile(os.path.join(versioned.get_path(), old_intro)))
        self.assertTrue(os.path.isfile(os.path.join(versioned.get_path(), old_conclu)))

        # when loaded the manifest, not None, this time
        versioned2 = self.tuto.load_version(sha=version)
        self.assertIsNotNone(versioned2)
        self.assertIsNotNone(versioned.children[-1].introduction)
        self.assertIsNotNone(versioned.children[-1].conclusion)

        version = new_part.repo_update(given_title, None, None)  # and we go back to `None`
        self.assertIsNone(new_part.introduction)
        self.assertIsNone(new_part.conclusion)
        self.assertFalse(os.path.isfile(os.path.join(versioned.get_path(), old_intro)))  # introduction is deleted
        self.assertFalse(os.path.isfile(os.path.join(versioned.get_path(), old_conclu)))

        # does it go back to None?
        versioned2 = self.tuto.load_version(sha=version)
        self.assertIsNotNone(versioned2)
        self.assertIsNone(versioned.children[-1].introduction)
        self.assertIsNone(versioned.children[-1].conclusion)

        new_part.repo_update(given_title, '', '')  # '' is not None
        self.assertIsNotNone(new_part.introduction)
        self.assertIsNotNone(new_part.conclusion)

    def test_extract_is_none(self):
        """Test the case of a null extract"""

        article = PublishableContentFactory(type='ARTICLE')
        versioned = article.load_version()

        given_title = 'Peu importe, en fait, ça compte peu'
        some_text = 'Disparaitra aussi vite que possible'

        # add a new extract with `None` for text
        version = versioned.repo_add_extract(given_title, None)

        # check on the model:
        new_extract = versioned.children[-1]
        self.assertIsNone(new_extract.text)

        # it remains when loading the manifest!
        versioned2 = article.load_version(sha=version)
        self.assertIsNotNone(versioned2)
        self.assertIsNone(versioned.children[-1].text)

        version = new_extract.repo_update(given_title, None)
        self.assertIsNone(new_extract.text)

        # it remains
        versioned2 = article.load_version(sha=version)
        self.assertIsNotNone(versioned2)
        self.assertIsNone(versioned.children[-1].text)

        version = new_extract.repo_update(given_title, some_text)
        self.assertIsNotNone(new_extract.text)
        self.assertEqual(some_text, new_extract.get_text())

        # now it changes
        versioned2 = article.load_version(sha=version)
        self.assertIsNotNone(versioned2)
        self.assertIsNotNone(versioned.children[-1].text)

        # ... and lets go back
        version = new_extract.repo_update(given_title, None)
        self.assertIsNone(new_extract.text)

        # it has changed
        versioned2 = article.load_version(sha=version)
        self.assertIsNotNone(versioned2)
        self.assertIsNone(versioned.children[-1].text)

    def test_ensure_slug_stay(self):
        """This test ensures that slugs are not modified when coming from a manifest"""

        tuto = PublishableContentFactory(type='TUTORIAL')
        versioned = tuto.load_version()

        random = 'Non, piti bug, tu ne reviendras plus !!!'
        title = "N'importe quel titre"

        # add three container with the same title
        versioned.repo_add_container(title, random, random)  # x
        versioned.repo_add_container(title, random, random)  # x-1
        version = versioned.repo_add_container(title, random, random)  # x-2
        self.assertEqual(len(versioned.children), 3)

        current = tuto.load_version(sha=version)
        self.assertEqual(len(current.children), 3)

        for index, child in enumerate(current.children):
            self.assertEqual(child.slug, versioned.children[index].slug)  # same order

        # then, delete the second one:
        last_slug = versioned.children[2].slug
        version = versioned.children[1].repo_delete()
        self.assertEqual(len(versioned.children), 2)
        self.assertEqual(versioned.children[1].slug, last_slug)

        current = tuto.load_version(sha=version)
        self.assertEqual(len(current.children), 2)

        for index, child in enumerate(current.children):
            self.assertEqual(child.slug, versioned.children[index].slug)  # slug remains

        # same test with extracts
        chapter = versioned.children[0]
        chapter.repo_add_extract(title, random)  # x
        chapter.repo_add_extract(title, random)  # x-1
        version = chapter.repo_add_extract(title, random)  # x-2
        self.assertEqual(len(chapter.children), 3)

        current = tuto.load_version(sha=version)
        self.assertEqual(len(current.children[0].children), 3)

        for index, child in enumerate(current.children[0].children):
            self.assertEqual(child.slug, chapter.children[index].slug)  # slug remains

        # delete the second one!
        last_slug = chapter.children[2].slug
        version = chapter.children[1].repo_delete()
        self.assertEqual(len(chapter.children), 2)
        self.assertEqual(chapter.children[1].slug, last_slug)

        current = tuto.load_version(sha=version)
        self.assertEqual(len(current.children[0].children), 2)

        for index, child in enumerate(current.children[0].children):
            self.assertEqual(child.slug, chapter.children[index].slug)  # slug remains for extract as well!

    def test_publication_and_attributes_consistency(self):
        pubdate = datetime.now() - timedelta(days=1)
        article = PublishedContentFactory(type='ARTICLE', author_list=[self.user_author])
        public_version = article.public_version
        public_version.publication_date = pubdate
        public_version.save()
        # everything must come from database to have good datetime comparison
        article = PublishableContent.objects.get(pk=article.pk)
        article.public_version.load_public_version()
        old_date = article.public_version.publication_date
        old_title = article.public_version.title()
        old_description = article.public_version.description()
        article.licence = LicenceFactory()
        article.save()
        self.assertEqual(
            self.client.login(
                username=self.user_author.username,
                password='******'),
            True)
        self.client.post(reverse('content:edit', args=[article.pk, article.slug]), {
            'title': old_title + 'bla',
            'description': old_description + 'bla',
            'type': 'ARTICLE',
            'licence': article.licence.pk,
            'subcategory': SubCategoryFactory().pk,
            'last_hash': article.sha_draft
        })
        article = PublishableContent.objects.prefetch_related('public_version').get(pk=article.pk)
        article.public_version.load_public_version()
        self.assertEqual(old_title, article.public_version.title())
        self.assertEqual(old_description, article.public_version.description())
        self.assertEqual(old_date, article.public_version.publication_date)
        publish_content(article, article.load_version(), False)
        article = PublishableContent.objects.get(pk=article.pk)
        article.public_version.load_public_version()
        self.assertEqual(old_date, article.public_version.publication_date)
        self.assertNotEqual(old_date, article.public_version.update_date)

    def test_add_tags(self):
        tuto = self.tuto
        tags_len = len(Tag.objects.all())
        tuto_tags_len = len(tuto.tags.all())

        # add 3 tags
        tags = ['a', 'b', 'c']
        tuto.add_tags(tags)
        tags_len += 3
        tuto_tags_len += 3
        self.assertEqual(tags_len, len(Tag.objects.all()))
        self.assertEqual(tuto_tags_len, len(tuto.tags.all()))

        # add the same tags (nothing append)
        tags = ['a', 'b', 'c']
        tuto.add_tags(tags)
        self.assertEqual(tags_len, len(Tag.objects.all()))
        self.assertEqual(tuto_tags_len, len(tuto.tags.all()))

        # add 2 more
        tags = ['d', 'e']
        tuto.add_tags(tags)
        tags_len += 2
        tuto_tags_len += 2
        self.assertEqual(tags_len, len(Tag.objects.all()))
        self.assertEqual(tuto_tags_len, len(tuto.tags.all()))

        # add 3 with invalid content (only 2 valid)
        tags = ['f', 'g', ' ']
        tuto.add_tags(tags)
        tags_len += 2
        tuto_tags_len += 2
        self.assertEqual(tags_len, Tag.objects.count(),
                         'all tags are "{}"'.format('","'.join([str(t) for t in Tag.objects.all()])))
        self.assertEqual(tuto_tags_len, len(tuto.tags.all()))

        # test space in tags (first and last space deleted)
        tags = ['foo bar', ' azerty', 'qwerty ', ' another tag ']
        tuto.add_tags(tags)
        tuto_tags_list = [tag['title'] for tag in tuto.tags.values('title')]
        self.assertIn('foo bar', tuto_tags_list)
        self.assertNotIn(' azerty', tuto_tags_list)
        self.assertIn('azerty', tuto_tags_list)
        self.assertNotIn('qwerty ', tuto_tags_list)
        self.assertIn('qwerty', tuto_tags_list)
        self.assertNotIn(' another tag', tuto_tags_list)
        self.assertIn('another tag', tuto_tags_list)

    @unittest.skip('The test seems to be incorrect in its way to count chars')
    def test_char_count_after_publication(self):
        """Test the ``get_char_count()`` function.

        Special care should be taken with this function, since:

        - The username of the author is, by default "Firmxxx" where "xxx" depends on the tests before ;
        - The titles (!) also contains a number that also depends on the number of tests before ;
        - The date is ``datetime.now()`` and contains the months, which is never a fixed number of letters.
        """

        author = ProfileFactory().user
        author.username = '******'
        author.save()

        len_date_now = len(date(datetime.now(), 'd F Y'))

        article = PublishedContentFactory(type='ARTICLE', author_list=[author], title='Un titre')
        published = PublishedContent.objects.filter(content=article).first()
        self.assertEqual(published.get_char_count(), 160 + len_date_now)

        tuto = PublishableContentFactory(type='TUTORIAL', author_list=[author], title='Un titre')

        # add a chapter, so it becomes a middle tutorial
        tuto_draft = tuto.load_version()
        chapter1 = ContainerFactory(parent=tuto_draft, db_object=tuto, title='Un chapitre')
        ExtractFactory(container=chapter1, db_object=tuto, title='Un extrait')
        published = publish_content(tuto, tuto_draft, is_major_update=True)

        tuto.sha_public = tuto_draft.current_version
        tuto.sha_draft = tuto_draft.current_version
        tuto.public_version = published
        tuto.save()

        published = PublishedContent.objects.filter(content=tuto).first()
        self.assertEqual(published.get_char_count(), 335 + len_date_now)

    def test_ensure_gallery(self):
        content = PublishedContentFactory()
        content.authors.add(ProfileFactory().user)
        content.authors.add(ProfileFactory().user)
        content.save()
        content.ensure_author_gallery()
        self.assertEqual(UserGallery.objects.filter(gallery__pk=content.gallery.pk).count(), content.authors.count())
        content.authors.add(ProfileFactory().user)
        content.save()
        content.ensure_author_gallery()
        self.assertEqual(UserGallery.objects.filter(gallery__pk=content.gallery.pk).count(), content.authors.count())

    def tearDown(self):
        if os.path.isdir(overridden_zds_app['content']['repo_private_path']):
            shutil.rmtree(overridden_zds_app['content']['repo_private_path'])
        if os.path.isdir(overridden_zds_app['content']['repo_public_path']):
            shutil.rmtree(overridden_zds_app['content']['repo_public_path'])
        if os.path.isdir(settings.MEDIA_ROOT):
            shutil.rmtree(settings.MEDIA_ROOT)
Example #36
0
 def _create_and_publish_type_in_subcategory(self, content_type, subcategory):
     tuto_1 = PublishableContentFactory(type=content_type, author_list=[self.user_author])
     tuto_1.subcategory.add(subcategory)
     tuto_1.save()
     tuto_1_draft = tuto_1.load_version()
     publish_content(tuto_1, tuto_1_draft, is_major_update=True)
Example #37
0
class ContentTests(TutorialTestMixin, TestCase):
    def setUp(self):
        self.staff = StaffProfileFactory().user

        settings.EMAIL_BACKEND = "django.core.mail.backends.locmem.EmailBackend"
        self.mas = ProfileFactory().user
        self.overridden_zds_app["member"]["bot_account"] = self.mas.username

        self.licence = LicenceFactory()
        self.subcategory = SubCategoryFactory()

        self.user_author = ProfileFactory().user
        self.user_staff = StaffProfileFactory().user
        self.user_guest = ProfileFactory().user

        self.tuto = PublishableContentFactory(type="TUTORIAL")
        self.tuto.authors.add(self.user_author)
        UserGalleryFactory(gallery=self.tuto.gallery,
                           user=self.user_author,
                           mode="W")
        self.tuto.licence = self.licence
        self.tuto.subcategory.add(self.subcategory)
        self.tuto.save()

        self.beta_forum = ForumFactory(
            pk=self.overridden_zds_app["forum"]["beta_forum_id"],
            category=ForumCategoryFactory(position=1),
            position_in_category=1,
        )  # ensure that the forum, for the beta versions, is created

        self.tuto_draft = self.tuto.load_version()
        self.part1 = ContainerFactory(parent=self.tuto_draft,
                                      db_object=self.tuto)
        self.chapter1 = ContainerFactory(parent=self.part1,
                                         db_object=self.tuto)

        self.extract1 = ExtractFactory(container=self.chapter1,
                                       db_object=self.tuto)
        bot = Group(name=self.overridden_zds_app["member"]["bot_group"])
        bot.save()
        self.external = UserFactory(
            username=self.overridden_zds_app["member"]["external_account"],
            password="******")

    def test_public_lists(self):
        tutorial = PublishedContentFactory(author_list=[self.user_author])
        tutorial_unpublished = PublishableContentFactory(
            author_list=[self.user_author])
        article = PublishedContentFactory(author_list=[self.user_author],
                                          type="ARTICLE")
        article_unpublished = PublishableContentFactory(
            author_list=[self.user_author], type="ARTICLE")
        self.client.logout()

        resp = self.client.get(reverse("publication:list") + "?type=tutorial")
        self.assertContains(resp, tutorial.title)
        self.assertNotContains(resp, tutorial_unpublished.title)

        resp = self.client.get(reverse("publication:list") + "?type=article")
        self.assertContains(resp, article.title)
        self.assertNotContains(resp, article_unpublished.title)

        resp = self.client.get(
            reverse("tutorial:find-tutorial", args=[self.user_author.username])
            + "?filter=public")
        self.assertContains(resp, tutorial.title)
        self.assertNotContains(resp, tutorial_unpublished.title)

        resp = self.client.get(
            reverse("tutorial:find-tutorial", args=[self.user_author.username])
            + "?filter=redaction")
        self.assertEqual(resp.status_code, 403)

        resp = self.client.get(
            reverse("article:find-article", args=[self.user_author.username]) +
            "?filter=public")
        self.assertContains(resp, article.title)
        self.assertNotContains(resp, article_unpublished.title)

        resp = self.client.get(
            reverse("article:find-article", args=[self.user_author.username]) +
            "?filter=redaction")
        self.assertEqual(resp.status_code, 403)

        resp = self.client.get(
            reverse("article:find-article", args=[self.user_author.username]) +
            "?filter=chuck-norris")
        self.assertEqual(resp.status_code, 404)

    def _create_and_publish_type_in_subcategory(self, content_type,
                                                subcategory):
        tuto_1 = PublishableContentFactory(type=content_type,
                                           author_list=[self.user_author])
        tuto_1.subcategory.add(subcategory)
        tuto_1.save()
        tuto_1_draft = tuto_1.load_version()
        tuto_1.public_version = publish_content(tuto_1,
                                                tuto_1_draft,
                                                is_major_update=True)
        tuto_1.save()

    def test_list_categories(self):
        category_1 = ContentCategoryFactory()
        subcategory_1 = SubCategoryFactory(category=category_1)
        subcategory_2 = SubCategoryFactory(category=category_1)
        # Not in context if nothing published inside this subcategory
        SubCategoryFactory(category=category_1)

        for _ in range(5):
            self._create_and_publish_type_in_subcategory(
                "TUTORIAL", subcategory_1)
            self._create_and_publish_type_in_subcategory(
                "ARTICLE", subcategory_2)

        self.client.logout()
        resp = self.client.get(reverse("publication:list"))

        context_categories = list(resp.context_data["categories"])
        self.assertEqual(context_categories[0].contents_count, 10)
        self.assertEqual(context_categories[0].subcategories,
                         [subcategory_1, subcategory_2])
        self.assertEqual(context_categories, [category_1])

    def test_private_lists(self):
        tutorial = PublishedContentFactory(author_list=[self.user_author])
        tutorial_unpublished = PublishableContentFactory(
            author_list=[self.user_author])
        article = PublishedContentFactory(author_list=[self.user_author],
                                          type="ARTICLE")
        article_unpublished = PublishableContentFactory(
            author_list=[self.user_author], type="ARTICLE")
        self.client.login(username=self.user_author.username,
                          password="******")
        resp = self.client.get(
            reverse("tutorial:find-tutorial",
                    args=[self.user_author.username]))
        self.assertContains(resp, tutorial.title)
        self.assertContains(resp, tutorial_unpublished.title)
        self.assertContains(resp, "content-illu")
        resp = self.client.get(
            reverse("article:find-article", args=[self.user_author.username]))
        self.assertContains(resp, article.title)
        self.assertContains(resp, article_unpublished.title)
        self.assertContains(resp, "content-illu")

    def test_validation_list(self):
        """ensure the behavior of the `validation:list` page (with filters)"""

        text = "Ceci est un éléphant"

        tuto_not_reserved = PublishableContentFactory(
            type="TUTORIAL", author_list=[self.user_author])
        tuto_reserved = PublishableContentFactory(
            type="TUTORIAL", author_list=[self.user_author])
        article_not_reserved = PublishableContentFactory(
            type="ARTICLE", author_list=[self.user_author])
        article_reserved = PublishableContentFactory(
            type="ARTICLE", author_list=[self.user_author])

        all_contents = [
            tuto_not_reserved, tuto_reserved, article_not_reserved,
            article_reserved
        ]
        reserved_contents = [tuto_reserved, article_reserved]

        # apply a filter to test category filter
        subcat = SubCategoryFactory()
        article_reserved.subcategory.add(subcat)
        article_reserved.save()

        # send in validation
        for content in all_contents:
            v = ValidationFactory(content=content, status="PENDING")
            v.date_proposition = datetime.datetime.now()
            v.version = content.sha_draft
            v.comment_authors = text

            if content in reserved_contents:
                v.validator = self.user_staff
                v.date_reserve = datetime.datetime.now()
                v.status = "PENDING_V"

            v.save()

        # first, test access for public
        result = self.client.get(reverse("validation:list"), follow=False)
        self.assertEqual(result.status_code,
                         302)  # get 302 → redirection to login

        # connect with author:
        self.assertEqual(
            self.client.login(username=self.user_author.username,
                              password="******"), True)

        result = self.client.get(reverse("validation:list"), follow=False)
        self.assertEqual(result.status_code, 403)  # get 403 not allowed

        self.client.logout()

        # connect with staff:
        self.assertEqual(
            self.client.login(username=self.user_staff.username,
                              password="******"), True)

        response = self.client.get(reverse("validation:list"), follow=False)
        self.assertEqual(response.status_code, 200)  # OK

        validations = response.context["validations"]
        self.assertEqual(len(validations),
                         4)  # a total of 4 contents in validation

        # test filters
        response = self.client.get(reverse("validation:list") +
                                   "?type=article",
                                   follow=False)
        self.assertEqual(response.status_code, 200)  # OK
        validations = response.context["validations"]
        self.assertEqual(len(validations), 2)  # 2 articles

        response = self.client.get(reverse("validation:list") + "?type=tuto",
                                   follow=False)
        self.assertEqual(response.status_code, 200)  # OK
        validations = response.context["validations"]
        self.assertEqual(len(validations), 2)  # 2 articles

        response = self.client.get(reverse("validation:list") + "?type=orphan",
                                   follow=False)
        self.assertEqual(response.status_code, 200)  # OK
        validations = response.context["validations"]
        self.assertEqual(len(validations), 2)  # 2 not-reserved content

        for validation in validations:
            self.assertFalse(validation.content in reserved_contents)

        response = self.client.get(reverse("validation:list") +
                                   "?type=reserved",
                                   follow=False)
        self.assertEqual(response.status_code, 200)  # OK
        validations = response.context["validations"]
        self.assertEqual(len(validations), 2)  # 2 reserved content

        for validation in validations:
            self.assertTrue(validation.content in reserved_contents)

        response = self.client.get(reverse("validation:list") +
                                   "?subcategory={}".format(subcat.pk),
                                   follow=False)
        self.assertEqual(response.status_code, 200)  # OK
        validations = response.context["validations"]
        self.assertEqual(len(validations), 1)  # 1 content with this category

        self.assertEqual(validations[0].content,
                         article_reserved)  # the right content
Example #38
0
class LastTutorialsFeedRSSTest(TutorialTestMixin, TestCase):
    def setUp(self):
        self.overridden_zds_app = overridden_zds_app
        # don't build PDF to speed up the tests
        overridden_zds_app["content"]["build_pdf_when_published"] = False

        self.staff = StaffProfileFactory().user

        settings.EMAIL_BACKEND = "django.core.mail.backends.locmem.EmailBackend"
        self.mas = ProfileFactory().user
        overridden_zds_app["member"]["bot_account"] = self.mas.username

        bot = Group(name=overridden_zds_app["member"]["bot_group"])
        bot.save()
        self.external = UserFactory(
            username=overridden_zds_app["member"]["external_account"],
            password="******")

        self.beta_forum = ForumFactory(
            pk=overridden_zds_app["forum"]["beta_forum_id"],
            category=ForumCategoryFactory(position=1),
            position_in_category=1,
        )  # ensure that the forum, for the beta versions, is created

        self.licence = LicenceFactory()
        self.subcategory = SubCategoryFactory()
        self.tag = TagFactory()

        self.user_author = ProfileFactory().user
        self.user_staff = StaffProfileFactory().user
        self.user_guest = ProfileFactory().user

        # create a tutorial
        self.tuto = PublishableContentFactory(type="TUTORIAL")
        self.tuto.authors.add(self.user_author)
        UserGalleryFactory(gallery=self.tuto.gallery,
                           user=self.user_author,
                           mode="W")
        self.tuto.licence = self.licence
        self.tuto.subcategory.add(self.subcategory)
        self.tuto.tags.add(self.tag)
        self.tuto.save()

        # fill it with one part, containing one chapter, containing one extract
        self.tuto_draft = self.tuto.load_version()
        self.part1 = ContainerFactory(parent=self.tuto_draft,
                                      db_object=self.tuto)
        self.chapter1 = ContainerFactory(parent=self.part1,
                                         db_object=self.tuto)
        self.extract1 = ExtractFactory(container=self.chapter1,
                                       db_object=self.tuto)

        # then, publish it !
        version = self.tuto_draft.current_version
        self.published = publish_content(self.tuto,
                                         self.tuto_draft,
                                         is_major_update=True)

        self.tuto.sha_public = version
        self.tuto.sha_draft = version
        self.tuto.public_version = self.published
        self.tuto.save()

        self.tutofeed = LastTutorialsFeedRSS()

    def test_is_well_setup(self):
        """ Test that base parameters are Ok """

        self.assertEqual(self.tutofeed.link, "/tutoriels/")
        reftitle = "Tutoriels sur {}".format(
            overridden_zds_app["site"]["literal_name"])
        self.assertEqual(self.tutofeed.title, reftitle)
        refdescription = "Les derniers tutoriels parus sur {}.".format(
            overridden_zds_app["site"]["literal_name"])
        self.assertEqual(self.tutofeed.description, refdescription)

        atom = LastTutorialsFeedATOM()
        self.assertEqual(atom.subtitle, refdescription)

    def test_get_items(self):
        """ basic test sending back the tutorial """

        ret = list(self.tutofeed.items())
        self.assertEqual(ret[0].content, self.tuto)

    def test_get_pubdate(self):
        """ test the return value of pubdate """

        ref = PublishedContent.objects.get(
            content__pk=self.tuto.pk).publication_date
        tuto = list(self.tutofeed.items())[0]
        ret = self.tutofeed.item_pubdate(item=tuto)
        self.assertEqual(ret.date(), ref.date())

    def test_get_title(self):
        """ test the return value of title """

        ref = self.tuto.title
        tuto = list(self.tutofeed.items())[0]
        ret = self.tutofeed.item_title(item=tuto)
        self.assertEqual(ret, ref)

    def test_get_description(self):
        """ test the return value of description """

        ref = self.tuto.description
        tuto = list(self.tutofeed.items())[0]
        ret = self.tutofeed.item_description(item=tuto)
        self.assertEqual(ret, ref)

    def test_get_author_name(self):
        """ test the return value of author name """

        ref = self.user_author.username
        tuto = list(self.tutofeed.items())[0]
        ret = self.tutofeed.item_author_name(item=tuto)
        self.assertEqual(ret, ref)

    def test_get_item_link(self):
        """ test the return value of item link """

        ref = self.tuto.get_absolute_url_online()
        tuto = list(self.tutofeed.items())[0]
        ret = self.tutofeed.item_link(item=tuto)
        self.assertEqual(ret, ref)

    def test_filters(self):
        """ Test filtering by category & tag """
        subcategory2 = SubCategoryFactory()
        subcategory3 = SubCategoryFactory()
        tag2 = TagFactory()
        tag3 = TagFactory()

        # Add a new tuto & publish it

        tuto2 = PublishableContentFactory(type="TUTORIAL")
        tuto2.authors.add(self.user_author)
        tuto2.licence = self.licence
        tuto2.subcategory.add(subcategory2)
        tuto2.tags.add(self.tag)
        tuto2.tags.add(tag2)
        tuto2.save()

        tuto2_draft = tuto2.load_version()
        tuto2.sha_public = tuto2.sha_draft = tuto2_draft.current_version
        tuto2.public_version = publish_content(tuto2,
                                               tuto2_draft,
                                               is_major_update=True)
        tuto2.save()

        # Default view

        ret = [item.content for item in self.tutofeed.items()]
        self.assertEqual(ret, [tuto2, self.tuto])

        # Filter by subcategory

        self.tutofeed.query_params = {"subcategory": self.subcategory.slug}
        ret = [item.content for item in self.tutofeed.items()]
        self.assertEqual(ret, [self.tuto])

        self.tutofeed.query_params = {
            "subcategory": f" {self.subcategory.slug} "
        }
        ret = [item.content for item in self.tutofeed.items()]
        self.assertEqual(ret, [self.tuto])

        self.tutofeed.query_params = {"subcategory": subcategory2.slug}
        ret = [item.content for item in self.tutofeed.items()]
        self.assertEqual(ret, [tuto2])

        self.tutofeed.query_params = {"subcategory": subcategory3.slug}
        ret = [item.content for item in self.tutofeed.items()]
        self.assertEqual(ret, [])

        self.tutofeed.query_params = {"subcategory": "invalid"}
        self.assertRaises(Http404, self.tutofeed.items)

        # Filter by tag

        self.tutofeed.query_params = {"tag": self.tag.slug}
        ret = [item.content for item in self.tutofeed.items()]
        self.assertEqual(ret, [tuto2, self.tuto])

        self.tutofeed.query_params = {"tag": tag2.slug}
        ret = [item.content for item in self.tutofeed.items()]
        self.assertEqual(ret, [tuto2])

        self.tutofeed.query_params = {"tag": f" {tag2.slug} "}
        ret = [item.content for item in self.tutofeed.items()]
        self.assertEqual(ret, [tuto2])

        self.tutofeed.query_params = {"tag": tag3.slug}
        ret = [item.content for item in self.tutofeed.items()]
        self.assertEqual(ret, [])

        self.tutofeed.query_params = {"tag": "invalid"}
        self.assertRaises(Http404, self.tutofeed.items)
Example #39
0
    def test_ensure_slug_stay(self):
        """This test ensure that slug are not modified when coming from a manifest"""

        tuto = PublishableContentFactory(type='TUTORIAL')
        versioned = tuto.load_version()

        random = u'Non, piti bug, tu ne reviendra plus !!!'
        title = u'N\'importe quel titre'

        # add three container with the same title
        versioned.repo_add_container(title, random, random)  # x
        versioned.repo_add_container(title, random, random)  # x-1
        version = versioned.repo_add_container(title, random, random)  # x-2
        self.assertEqual(len(versioned.children), 3)

        current = tuto.load_version(sha=version)
        self.assertEqual(len(current.children), 3)

        for index, child in enumerate(current.children):
            self.assertEqual(child.slug,
                             versioned.children[index].slug)  # same order

        # then, delete the second one:
        last_slug = versioned.children[2].slug
        version = versioned.children[1].repo_delete()
        self.assertEqual(len(versioned.children), 2)
        self.assertEqual(versioned.children[1].slug, last_slug)

        current = tuto.load_version(sha=version)
        self.assertEqual(len(current.children), 2)

        for index, child in enumerate(current.children):
            self.assertEqual(child.slug,
                             versioned.children[index].slug)  # slug remains

        # same test with extracts
        chapter = versioned.children[0]
        chapter.repo_add_extract(title, random)  # x
        chapter.repo_add_extract(title, random)  # x-1
        version = chapter.repo_add_extract(title, random)  # x-2
        self.assertEqual(len(chapter.children), 3)

        current = tuto.load_version(sha=version)
        self.assertEqual(len(current.children[0].children), 3)

        for index, child in enumerate(current.children[0].children):
            self.assertEqual(child.slug,
                             chapter.children[index].slug)  # slug remains

        # delete the second one !
        last_slug = chapter.children[2].slug
        version = chapter.children[1].repo_delete()
        self.assertEqual(len(chapter.children), 2)
        self.assertEqual(chapter.children[1].slug, last_slug)

        current = tuto.load_version(sha=version)
        self.assertEqual(len(current.children[0].children), 2)

        for index, child in enumerate(current.children[0].children):
            self.assertEqual(child.slug, chapter.children[index].slug
                             )  # slug remains for extract as well !
Example #40
0
class ContentTests(TestCase):
    def setUp(self):

        # don't build PDF to speed up the tests
        settings.ZDS_APP['content']['build_pdf_when_published'] = False

        settings.EMAIL_BACKEND = 'django.core.mail.backends.locmem.EmailBackend'
        self.mas = ProfileFactory().user
        settings.ZDS_APP['member']['bot_account'] = self.mas.username

        self.licence = LicenceFactory()

        self.user_author = ProfileFactory().user
        self.staff = StaffProfileFactory().user

        self.tuto = PublishableContentFactory(type='TUTORIAL')
        self.tuto.authors.add(self.user_author)
        UserGalleryFactory(gallery=self.tuto.gallery,
                           user=self.user_author,
                           mode='W')
        self.tuto.licence = self.licence
        self.tuto.save()

        self.tuto_draft = self.tuto.load_version()
        self.part1 = ContainerFactory(parent=self.tuto_draft,
                                      db_object=self.tuto)
        self.chapter1 = ContainerFactory(parent=self.part1,
                                         db_object=self.tuto)

        self.extract1 = ExtractFactory(container=self.chapter1,
                                       db_object=self.tuto)

    def test_workflow_content(self):
        """
        General tests for a content
        """
        # ensure the usability of manifest
        versioned = self.tuto.load_version()
        self.assertEqual(self.tuto_draft.title, versioned.title)
        self.assertEqual(self.part1.title, versioned.children[0].title)
        self.assertEqual(self.extract1.title,
                         versioned.children[0].children[0].children[0].title)

        # ensure url resolution project using dictionary :
        self.assertTrue(self.part1.slug in versioned.children_dict.keys())
        self.assertTrue(self.chapter1.slug in versioned.children_dict[
            self.part1.slug].children_dict)

    def test_ensure_unique_slug(self):
        """
        Ensure that slugs for a container or extract are always unique
        """
        # get draft version
        versioned = self.tuto.load_version()

        # forbidden slugs :
        slug_to_test = ['introduction', 'conclusion']

        for slug in slug_to_test:
            new_slug = versioned.get_unique_slug(slug)
            self.assertNotEqual(slug, new_slug)
            self.assertTrue(
                new_slug
                in versioned.slug_pool)  # ensure new slugs are in slug pool

        # then test with "real" containers and extracts :
        new_chapter_1 = ContainerFactory(title='aa',
                                         parent=versioned,
                                         db_object=self.tuto)
        new_chapter_2 = ContainerFactory(title='aa',
                                         parent=versioned,
                                         db_object=self.tuto)
        self.assertNotEqual(new_chapter_1.slug, new_chapter_2.slug)
        new_extract_1 = ExtractFactory(title='aa',
                                       container=new_chapter_1,
                                       db_object=self.tuto)
        self.assertEqual(
            new_extract_1.slug,
            new_chapter_1.slug)  # different level can have the same slug !

        new_extract_2 = ExtractFactory(title='aa',
                                       container=new_chapter_2,
                                       db_object=self.tuto)
        self.assertEqual(new_extract_2.slug,
                         new_extract_1.slug)  # not the same parent, so allowed

        new_extract_3 = ExtractFactory(title='aa',
                                       container=new_chapter_1,
                                       db_object=self.tuto)
        self.assertNotEqual(new_extract_3.slug,
                            new_extract_1.slug)  # same parent, forbidden

    def test_ensure_unique_slug_2(self):
        """This text is an extension of the previous one, with the manifest re-loaded each time"""

        title = u'Il existe des gens que la ZEP-12 n\'aime pas'
        random = u'... Mais c\'est pas sencé arriver, donc on va tout faire pour que ça disparaisse !'

        # get draft version
        versioned = self.tuto.load_version()

        # add containers
        version = versioned.repo_add_container(title, random, random)
        new_version = self.tuto.load_version(sha=version)
        self.assertEqual(new_version.children[-1].slug,
                         versioned.children[-1].slug)

        slugs = [new_version.children[-1].slug]

        for i in range(0, 2):  # will add 3 new container
            version = versioned.repo_add_container(title, random, random)
            new_version = self.tuto.load_version(sha=version)
            self.assertEqual(new_version.children[-1].slug,
                             versioned.children[-1].slug)
            self.assertTrue(new_version.children[-1].slug
                            not in slugs)  # slug is different
            self.assertTrue(versioned.children[-1].slug not in slugs)

            slugs.append(new_version.children[-1].slug)

        # add extracts
        extract_title = u'On va changer de titre (parce qu\'on sais jamais) !'

        chapter = versioned.children[
            -1]  # for this second test, the last chapter will be used
        version = chapter.repo_add_extract(extract_title, random)
        new_version = self.tuto.load_version(sha=version)
        self.assertEqual(new_version.children[-1].children[-1].slug,
                         chapter.children[-1].slug)

        slugs = [new_version.children[-1].children[-1].slug]

        for i in range(0, 2):  # will add 3 new extracts with the same title
            version = chapter.repo_add_extract(extract_title, random)
            new_version = self.tuto.load_version(sha=version)
            self.assertTrue(
                new_version.children[-1].children[-1].slug not in slugs)
            self.assertTrue(chapter.children[-1].slug not in slugs)

            slugs.append(new_version.children[-1].children[-1].slug)

    def test_workflow_repository(self):
        """
        Test to ensure the behavior of repo_*() functions :
        - if they change the filesystem as they are suppose to ;
        - if they change the `self.sha_*` as they are suppose to.
        """

        new_title = u'Un nouveau titre'
        other_new_title = u'Un titre différent'
        random_text = u'J\'ai faim!'
        other_random_text = u'Oh, du chocolat <3'

        versioned = self.tuto.load_version()
        current_version = versioned.current_version
        slug_repository = versioned.slug_repository

        # VersionedContent:
        old_path = versioned.get_path()
        self.assertTrue(os.path.isdir(old_path))
        new_slug = versioned.get_unique_slug(
            new_title)  # normally, you get a new slug by asking database !

        versioned.repo_update_top_container(new_title, new_slug, random_text,
                                            random_text)
        self.assertNotEqual(versioned.sha_draft, current_version)
        self.assertNotEqual(versioned.current_version, current_version)
        self.assertEqual(versioned.current_version, versioned.sha_draft)
        current_version = versioned.current_version

        new_path = versioned.get_path()
        self.assertNotEqual(old_path, new_path)
        self.assertTrue(os.path.isdir(new_path))
        self.assertFalse(os.path.isdir(old_path))

        self.assertNotEqual(
            slug_repository,
            versioned.slug_repository)  # if this test fail, you're in trouble

        # Container:

        # 1. add new part:
        versioned.repo_add_container(new_title, random_text, random_text)
        self.assertNotEqual(versioned.sha_draft, current_version)
        self.assertNotEqual(versioned.current_version, current_version)
        self.assertEqual(versioned.current_version, versioned.sha_draft)
        current_version = versioned.current_version

        part = versioned.children[-1]
        old_path = part.get_path()
        self.assertTrue(os.path.isdir(old_path))
        self.assertTrue(
            os.path.exists(
                os.path.join(versioned.get_path(), part.introduction)))
        self.assertTrue(
            os.path.exists(os.path.join(versioned.get_path(),
                                        part.conclusion)))
        self.assertEqual(part.get_introduction(), random_text)
        self.assertEqual(part.get_conclusion(), random_text)

        # 2. update the part
        part.repo_update(other_new_title, other_random_text, other_random_text)
        self.assertNotEqual(versioned.sha_draft, current_version)
        self.assertNotEqual(versioned.current_version, current_version)
        self.assertEqual(versioned.current_version, versioned.sha_draft)
        current_version = versioned.current_version

        new_path = part.get_path()
        self.assertNotEqual(old_path, new_path)
        self.assertTrue(os.path.isdir(new_path))
        self.assertFalse(os.path.isdir(old_path))

        self.assertEqual(part.get_introduction(), other_random_text)
        self.assertEqual(part.get_conclusion(), other_random_text)

        # 3. delete it
        part.repo_delete()  # boom !
        self.assertNotEqual(versioned.sha_draft, current_version)
        self.assertNotEqual(versioned.current_version, current_version)
        self.assertEqual(versioned.current_version, versioned.sha_draft)
        current_version = versioned.current_version

        self.assertFalse(os.path.isdir(new_path))

        # Extract :

        # 1. add new extract
        versioned.repo_add_container(
            new_title, random_text,
            random_text)  # need to add a new part before
        part = versioned.children[-1]

        part.repo_add_extract(new_title, random_text)
        self.assertNotEqual(versioned.sha_draft, current_version)
        self.assertNotEqual(versioned.current_version, current_version)
        self.assertEqual(versioned.current_version, versioned.sha_draft)
        current_version = versioned.current_version

        extract = part.children[-1]
        old_path = extract.get_path()
        self.assertTrue(os.path.isfile(old_path))
        self.assertEqual(extract.get_text(), random_text)

        # 2. update extract
        extract.repo_update(other_new_title, other_random_text)
        self.assertNotEqual(versioned.sha_draft, current_version)
        self.assertNotEqual(versioned.current_version, current_version)
        self.assertEqual(versioned.current_version, versioned.sha_draft)
        current_version = versioned.current_version

        new_path = extract.get_path()
        self.assertNotEqual(old_path, new_path)
        self.assertTrue(os.path.isfile(new_path))
        self.assertFalse(os.path.isfile(old_path))

        self.assertEqual(extract.get_text(), other_random_text)

        # 3. update parent and see if it still works:
        part.repo_update(other_new_title, other_random_text, other_random_text)

        old_path = new_path
        new_path = extract.get_path()

        self.assertNotEqual(old_path, new_path)
        self.assertTrue(os.path.isfile(new_path))
        self.assertFalse(os.path.isfile(old_path))

        self.assertEqual(extract.get_text(), other_random_text)

        # 4. Boom, no more extract
        extract.repo_delete()
        self.assertNotEqual(versioned.sha_draft, current_version)
        self.assertNotEqual(versioned.current_version, current_version)
        self.assertEqual(versioned.current_version, versioned.sha_draft)

        self.assertFalse(os.path.exists(new_path))

    def test_if_none(self):
        """Test the case where introduction and conclusion are `None`"""

        given_title = u'La vie secrète de Clem\''
        some_text = u'Tous ces secrets (ou pas)'
        versioned = self.tuto.load_version()
        # add a new part with `None` for intro and conclusion
        version = versioned.repo_add_container(given_title, None, None)

        # check on the model :
        new_part = versioned.children[-1]
        self.assertIsNone(new_part.introduction)
        self.assertIsNone(new_part.conclusion)

        # it remains when loading the manifest !
        versioned2 = self.tuto.load_version(sha=version)
        self.assertIsNotNone(versioned2)
        self.assertIsNone(versioned.children[-1].introduction)
        self.assertIsNone(versioned.children[-1].conclusion)

        version = new_part.repo_update(given_title, None, None)  # still `None`
        self.assertIsNone(new_part.introduction)
        self.assertIsNone(new_part.conclusion)

        # does it still remains ?
        versioned2 = self.tuto.load_version(sha=version)
        self.assertIsNotNone(versioned2)
        self.assertIsNone(versioned.children[-1].introduction)
        self.assertIsNone(versioned.children[-1].conclusion)

        new_part.repo_update(given_title, some_text, some_text)
        self.assertIsNotNone(new_part.introduction)  # now, value given
        self.assertIsNotNone(new_part.conclusion)

        old_intro = new_part.introduction
        old_conclu = new_part.conclusion
        self.assertTrue(
            os.path.isfile(os.path.join(versioned.get_path(), old_intro)))
        self.assertTrue(
            os.path.isfile(os.path.join(versioned.get_path(), old_conclu)))

        # when loaded the manifest, not None, this time
        versioned2 = self.tuto.load_version(sha=version)
        self.assertIsNotNone(versioned2)
        self.assertIsNotNone(versioned.children[-1].introduction)
        self.assertIsNotNone(versioned.children[-1].conclusion)

        version = new_part.repo_update(given_title, None,
                                       None)  # and we go back to `None`
        self.assertIsNone(new_part.introduction)
        self.assertIsNone(new_part.conclusion)
        self.assertFalse(
            os.path.isfile(os.path.join(versioned.get_path(),
                                        old_intro)))  # introduction is deleted
        self.assertFalse(
            os.path.isfile(os.path.join(versioned.get_path(), old_conclu)))

        # does it go back to None ?
        versioned2 = self.tuto.load_version(sha=version)
        self.assertIsNotNone(versioned2)
        self.assertIsNone(versioned.children[-1].introduction)
        self.assertIsNone(versioned.children[-1].conclusion)

        new_part.repo_update(given_title, '', '')  # empty string != `None`
        self.assertIsNotNone(new_part.introduction)
        self.assertIsNotNone(new_part.conclusion)

    def test_extract_is_none(self):
        """Test the case of a null extract"""

        article = PublishableContentFactory(type="ARTICLE")
        versioned = article.load_version()

        given_title = u'Peu importe, en fait, ça compte peu'
        some_text = u'Disparaitra aussi vite que possible'

        # add a new extract with `None` for text
        version = versioned.repo_add_extract(given_title, None)

        # check on the model :
        new_extract = versioned.children[-1]
        self.assertIsNone(new_extract.text)

        # it remains when loading the manifest !
        versioned2 = article.load_version(sha=version)
        self.assertIsNotNone(versioned2)
        self.assertIsNone(versioned.children[-1].text)

        version = new_extract.repo_update(given_title, None)
        self.assertIsNone(new_extract.text)

        # it remains
        versioned2 = article.load_version(sha=version)
        self.assertIsNotNone(versioned2)
        self.assertIsNone(versioned.children[-1].text)

        version = new_extract.repo_update(given_title, some_text)
        self.assertIsNotNone(new_extract.text)
        self.assertEqual(some_text, new_extract.get_text())

        # now it change
        versioned2 = article.load_version(sha=version)
        self.assertIsNotNone(versioned2)
        self.assertIsNotNone(versioned.children[-1].text)

        # ... and lets go back
        version = new_extract.repo_update(given_title, None)
        self.assertIsNone(new_extract.text)

        # it has changed
        versioned2 = article.load_version(sha=version)
        self.assertIsNotNone(versioned2)
        self.assertIsNone(versioned.children[-1].text)

    def test_ensure_slug_stay(self):
        """This test ensure that slug are not modified when coming from a manifest"""

        tuto = PublishableContentFactory(type='TUTORIAL')
        versioned = tuto.load_version()

        random = u'Non, piti bug, tu ne reviendra plus !!!'
        title = u'N\'importe quel titre'

        # add three container with the same title
        versioned.repo_add_container(title, random, random)  # x
        versioned.repo_add_container(title, random, random)  # x-1
        version = versioned.repo_add_container(title, random, random)  # x-2
        self.assertEqual(len(versioned.children), 3)

        current = tuto.load_version(sha=version)
        self.assertEqual(len(current.children), 3)

        for index, child in enumerate(current.children):
            self.assertEqual(child.slug,
                             versioned.children[index].slug)  # same order

        # then, delete the second one:
        last_slug = versioned.children[2].slug
        version = versioned.children[1].repo_delete()
        self.assertEqual(len(versioned.children), 2)
        self.assertEqual(versioned.children[1].slug, last_slug)

        current = tuto.load_version(sha=version)
        self.assertEqual(len(current.children), 2)

        for index, child in enumerate(current.children):
            self.assertEqual(child.slug,
                             versioned.children[index].slug)  # slug remains

        # same test with extracts
        chapter = versioned.children[0]
        chapter.repo_add_extract(title, random)  # x
        chapter.repo_add_extract(title, random)  # x-1
        version = chapter.repo_add_extract(title, random)  # x-2
        self.assertEqual(len(chapter.children), 3)

        current = tuto.load_version(sha=version)
        self.assertEqual(len(current.children[0].children), 3)

        for index, child in enumerate(current.children[0].children):
            self.assertEqual(child.slug,
                             chapter.children[index].slug)  # slug remains

        # delete the second one !
        last_slug = chapter.children[2].slug
        version = chapter.children[1].repo_delete()
        self.assertEqual(len(chapter.children), 2)
        self.assertEqual(chapter.children[1].slug, last_slug)

        current = tuto.load_version(sha=version)
        self.assertEqual(len(current.children[0].children), 2)

        for index, child in enumerate(current.children[0].children):
            self.assertEqual(child.slug, chapter.children[index].slug
                             )  # slug remains for extract as well !

    def test_publication_and_attributes_consistency(self):
        pubdate = datetime.now() - timedelta(days=1)
        article = PublishedContentFactory(type="ARTILCE",
                                          author_list=[self.user_author])
        public_version = article.public_version
        public_version.publication_date = pubdate
        public_version.save()
        # everything must come from database to have good datetime comparison
        article = PublishableContent.objects.get(pk=article.pk)
        article.public_version.load_public_version()
        old_date = article.public_version.publication_date
        old_title = article.public_version.title()
        old_description = article.public_version.description()
        article.licence = LicenceFactory()
        article.save()
        self.assertEqual(
            self.client.login(username=self.user_author.username,
                              password='******'), True)
        self.client.post(
            reverse("content:edit", args=[article.pk, article.slug]), {
                "title": old_title + "bla",
                "description": old_description + "bla",
                "type": "ARTICLE",
                "licence": article.licence.pk,
                "subcategory": SubCategoryFactory().pk,
                "last_hash": article.sha_draft
            })
        article = PublishableContent.objects.prefetch_related(
            "public_version").get(pk=article.pk)
        article.public_version.load_public_version()
        self.assertEqual(old_title, article.public_version.title())
        self.assertEqual(old_description, article.public_version.description())
        self.assertEqual(old_date, article.public_version.publication_date)
        publish_content(article, article.load_version(), False)
        article = PublishableContent.objects.get(pk=article.pk)
        article.public_version.load_public_version()
        self.assertEqual(old_date, article.public_version.publication_date)
        self.assertNotEqual(old_date, article.public_version.update_date)

    def tearDown(self):
        if os.path.isdir(settings.ZDS_APP['content']['repo_private_path']):
            shutil.rmtree(settings.ZDS_APP['content']['repo_private_path'])
        if os.path.isdir(settings.ZDS_APP['content']['repo_public_path']):
            shutil.rmtree(settings.ZDS_APP['content']['repo_public_path'])
        if os.path.isdir(settings.MEDIA_ROOT):
            shutil.rmtree(settings.MEDIA_ROOT)

        # re-active PDF build
        settings.ZDS_APP['content']['build_pdf_when_published'] = True
Example #41
0
class ContentNotification(TestCase, TutorialTestMixin):
    def setUp(self):

        # don't build PDF to speed up the tests
        self.user1 = ProfileFactory().user
        self.user2 = ProfileFactory().user

        # create a tutorial
        self.tuto = PublishableContentFactory(type='TUTORIAL')
        self.tuto.authors.add(self.user1)
        UserGalleryFactory(gallery=self.tuto.gallery, user=self.user1, mode='W')
        self.tuto.licence = LicenceFactory()
        self.tuto.subcategory.add(SubCategoryFactory())
        self.tuto.save()
        tuto_draft = self.tuto.load_version()

        # then, publish it !
        version = tuto_draft.current_version
        self.published = publish_content(self.tuto, tuto_draft, is_major_update=True)

        self.tuto.sha_public = version
        self.tuto.sha_draft = version
        self.tuto.public_version = self.published
        self.tuto.save()

        self.assertTrue(self.client.login(username=self.user1.username, password='******'))

    def test_no_persistant_notif_on_revoke(self):
        from zds.tutorialv2.publication_utils import unpublish_content
        NewPublicationSubscription.objects.get_or_create_active(self.user1, self.user2)
        content = PublishedContentFactory(author_list=[self.user2])

        notif_signals.new_content.send(sender=self.tuto.__class__, instance=content, by_email=False)
        self.assertEqual(1, len(Notification.objects.get_notifications_of(self.user1)))
        unpublish_content(content)
        self.assertEqual(0, len(Notification.objects.get_notifications_of(self.user1)))

    def test_no_persistant_comment_notif_on_revoke(self):
        from zds.tutorialv2.publication_utils import unpublish_content
        content = PublishedContentFactory(author_list=[self.user2])
        ContentReactionAnswerSubscription.objects.get_or_create_active(self.user1, content)
        ContentReactionFactory(related_content=content, author=self.user2, position=1)
        self.assertEqual(1, len(Notification.objects.get_unread_notifications_of(self.user1)))
        unpublish_content(content, moderator=self.user2)
        self.assertEqual(0, len(Notification.objects.get_unread_notifications_of(self.user1)))

    def test_only_one_notif_on_update(self):
        NewPublicationSubscription.objects.get_or_create_active(self.user1, self.user2)
        content = PublishedContentFactory(author_list=[self.user2])
        notify_update(content, False, True)
        versioned = content.load_version()
        content.sha_draft = versioned.repo_update(introduction='new intro', conclusion='new conclusion',
                                                  title=versioned.title)
        content.save(force_slug_update=False)
        publish_content(content, content.load_version(), True)
        notify_update(content, True, False)
        notifs = get_header_notifications(self.user1)['general_notifications']['list']
        self.assertEqual(1, len(notifs), str(notifs))

    def test_only_one_notif_on_major_update(self):
        NewPublicationSubscription.objects.get_or_create_active(self.user1, self.user2)
        content = PublishedContentFactory(author_list=[self.user2])
        notify_update(content, False, True)
        versioned = content.load_version()
        content.sha_draft = versioned.repo_update(introduction='new intro', conclusion='new conclusion',
                                                  title=versioned.title)
        content.save(force_slug_update=False)
        publish_content(content, content.load_version(), True)
        notify_update(content, True, True)
        notifs = get_header_notifications(self.user1)['general_notifications']['list']
        self.assertEqual(1, len(notifs), str(notifs))
Example #42
0
def load_contents(cli, size, fake, _type, *_, **__):
    """Create v2 contents"""

    nb_contents = size * 10
    percent_contents_in_validation = 0.2
    percent_contents_with_validator = 0.1
    percent_contents_public = 0.6
    percent_mini = 0.5
    percent_medium = 0.3
    percent_big = 0.2
    nb_avg_containers_in_content = size
    nb_avg_extracts_in_content = size

    is_articles = _type == "ARTICLE"
    is_tutorials = _type == "TUTORIAL"
    is_opinion = _type == "OPINION"

    textual_type = "article"
    if is_tutorials:
        textual_type = "tutoriel"
    elif is_opinion:
        textual_type = "billet"

    # small introduction
    cli.stdout.write("À créer: {:d} {}s".format(nb_contents, textual_type),
                     ending="")

    if is_tutorials:
        cli.stdout.write(" ({:g} petits, {:g} moyens et {:g} grands)".format(
            nb_contents * percent_mini, nb_contents * percent_medium,
            nb_contents * percent_big))
    else:
        cli.stdout.write("")

    cli.stdout.write(" - {:g} en brouillon".format(
        nb_contents *
        (1 - percent_contents_public - percent_contents_in_validation -
         percent_contents_with_validator)))
    if is_opinion:
        cli.stdout.write(
            " - {:g} publiés et {:g} approuvés en page d'accueil".format(
                nb_contents * (percent_contents_in_validation +
                               percent_contents_with_validator),
                nb_contents * percent_contents_with_validator,
            ))
    else:
        cli.stdout.write(" - {:g} en validation (dont {:g} réservés)".format(
            nb_contents *
            (percent_contents_in_validation + percent_contents_with_validator),
            nb_contents * percent_contents_with_validator,
        ))
    cli.stdout.write(" - {:g} publiés".format(nb_contents *
                                              percent_contents_public))

    tps1 = time.time()

    # create tables with 0=draft, 1=in validation, 2=reserved, 3=published
    what_to_do = []
    for created_content_index in range(nb_contents):
        what = 0  # in draft
        if created_content_index < percent_contents_public * nb_contents:
            what = 3
        elif created_content_index < (
                percent_contents_public +
                percent_contents_with_validator) * nb_contents:
            what = 2
        elif created_content_index >= (
                1 - percent_contents_in_validation) * nb_contents:
            what = 1
        what_to_do.append(what)

    # create a table with 0=mini, 1=medium, 2=big
    content_sizes = []
    for created_content_index in range(nb_contents):
        sz = 0
        if created_content_index < percent_big * nb_contents:
            sz = 2
        elif created_content_index >= (1 - percent_medium) * nb_contents:
            sz = 1
        content_sizes.append(sz)

    # shuffle the whole thing
    random.shuffle(what_to_do)
    random.shuffle(content_sizes)

    # checks that everything is ok
    users = list(Profile.objects.all())
    nb_users = len(users)
    sub_categories = list(SubCategory.objects.all())
    nb_sub_categories = len(sub_categories)
    if nb_users == 0:
        cli.stdout.write(
            "Il n'y a aucun membre actuellement. "
            "Vous devez rajouter les membre dans vos fixtures (member)")
        return

    if nb_sub_categories == 0:
        cli.stdout.write(
            "Il n'y a aucune catégories actuellement."
            "Vous devez rajouter les catégories dans vos fixtures (category_content)"
        )
        return

    perms = list(
        Permission.objects.filter(codename__startswith="change_").all())
    staffs = list(User.objects.filter(groups__permissions__in=perms).all())
    nb_staffs = len(staffs)

    if nb_staffs == 0:
        cli.stdout.write(
            "Il n'y a aucun staff actuellement."
            "Vous devez rajouter les staffs dans vos fixtures (staff)")
        return

    licenses = list(Licence.objects.all())
    nb_licenses = len(licenses)

    if nb_licenses == 0:
        cli.stdout.write(
            "Il n'y a aucune licence actuellement."
            "Vous devez rajouter les licences dans vos fixtures (category_content)"
        )
        return

    # create and so all:
    for created_content_index in range(nb_contents):
        sys.stdout.write("Création {} : {}/{}  \r".format(
            textual_type, created_content_index + 1, nb_contents))

        current_size = content_sizes[created_content_index]
        action_flag = what_to_do[created_content_index]

        # creation:
        content = PublishableContentFactory(type=_type,
                                            title=fake.text(max_nb_chars=60),
                                            description=fake.sentence(
                                                nb_words=15,
                                                variable_nb_words=True))

        versioned = content.load_version()

        generate_text_for_content(
            current_size,
            fake,
            is_articles,
            is_opinion,
            nb_avg_containers_in_content,
            nb_avg_extracts_in_content,
            versioned,
        )
        # add some informations:
        author = users[random.randint(0, nb_users - 1)].user
        content.authors.add(author)
        UserGalleryFactory(gallery=content.gallery, mode="W", user=author)
        content.licence = licenses[random.randint(0, nb_licenses - 1)]
        content.sha_draft = versioned.sha_draft
        content.subcategory.add(sub_categories[random.randint(
            0, nb_sub_categories - 1)])
        content.save()

        # then, validation if needed:
        if action_flag > 0:
            if is_opinion:
                publish_opinion(content, action_flag, versioned)
            else:
                validate_edited_content(content, fake, nb_staffs, staffs,
                                        action_flag, versioned)

        sys.stdout.flush()

    tps2 = time.time()
    cli.stdout.write("\nFait en {:.3f} sec".format(tps2 - tps1))
Example #43
0
    def setUp(self):
        self.overridden_zds_app = overridden_zds_app
        # don't build PDF to speed up the tests
        overridden_zds_app["content"]["build_pdf_when_published"] = False

        self.staff = StaffProfileFactory().user

        settings.EMAIL_BACKEND = "django.core.mail.backends.locmem.EmailBackend"
        self.mas = ProfileFactory().user
        overridden_zds_app["member"]["bot_account"] = self.mas.username

        bot = Group(name=overridden_zds_app["member"]["bot_group"])
        bot.save()
        self.external = UserFactory(
            username=overridden_zds_app["member"]["external_account"],
            password="******")

        self.beta_forum = ForumFactory(
            pk=overridden_zds_app["forum"]["beta_forum_id"],
            category=ForumCategoryFactory(position=1),
            position_in_category=1,
        )  # ensure that the forum, for the beta versions, is created

        self.licence = LicenceFactory()
        self.subcategory = SubCategoryFactory()
        self.tag = TagFactory()

        self.user_author = ProfileFactory().user
        self.user_staff = StaffProfileFactory().user
        self.user_guest = ProfileFactory().user

        # create a tutorial
        self.tuto = PublishableContentFactory(type="TUTORIAL")
        self.tuto.authors.add(self.user_author)
        UserGalleryFactory(gallery=self.tuto.gallery,
                           user=self.user_author,
                           mode="W")
        self.tuto.licence = self.licence
        self.tuto.subcategory.add(self.subcategory)
        self.tuto.tags.add(self.tag)
        self.tuto.save()

        # fill it with one part, containing one chapter, containing one extract
        self.tuto_draft = self.tuto.load_version()
        self.part1 = ContainerFactory(parent=self.tuto_draft,
                                      db_object=self.tuto)
        self.chapter1 = ContainerFactory(parent=self.part1,
                                         db_object=self.tuto)
        self.extract1 = ExtractFactory(container=self.chapter1,
                                       db_object=self.tuto)

        # then, publish it !
        version = self.tuto_draft.current_version
        self.published = publish_content(self.tuto,
                                         self.tuto_draft,
                                         is_major_update=True)

        self.tuto.sha_public = version
        self.tuto.sha_draft = version
        self.tuto.public_version = self.published
        self.tuto.save()

        self.tutofeed = LastTutorialsFeedRSS()
Example #44
0
    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
Example #45
0
class EditContentTagsFunctionalTests(TutorialTestMixin, TestCase):
    """Test the detailed behavior of the feature, such as updates of the database or repositories."""

    def setUp(self):
        # Create a user
        self.author = ProfileFactory()

        # Create tags
        self.tag_0 = TagFactory()
        self.tag_1 = TagFactory()
        self.tag_from_other_content = TagFactory()
        self.tags_name = [self.tag_0.title, self.tag_1.title, self.tag_from_other_content.title]

        # Create contents
        self.content = PublishableContentFactory(author_list=[self.author.user])
        self.other_content = PublishableContentFactory(author_list=[self.author.user])
        self.other_content.tags.add(self.tag_from_other_content)
        self.other_content.save()

        # Get information to be reused in tests
        self.form_url = reverse("content:edit-tags", kwargs={"pk": self.content.pk})

        # Log in with an authorized user (e.g the author of the content) to perform the tests
        self.client.force_login(self.author.user)

    def test_form_function(self):
        """Test many use cases for the form."""
        test_cases = self.get_test_cases()
        for case_name, case in test_cases.items():
            with self.subTest(msg=case_name):
                self.enforce_preconditions(case["preconditions"])
                self.post_form(case["inputs"])
                self.check_effects(case["expected_outputs"])

    def get_test_cases(self):
        """List test cases for the license editing form."""
        new_tag_name = "new_tag_for_sure"
        return {
            "nothing": {
                "preconditions": {"all_tags": self.tags_name, "content_tags": []},
                "inputs": {"tags": ""},
                "expected_outputs": {"all_tags": self.tags_name, "content_tags": []},
            },
            "existing_tag": {
                "preconditions": {"all_tags": self.tags_name, "content_tags": []},
                "inputs": {"tags": self.tag_1.title},
                "expected_outputs": {"all_tags": self.tags_name, "content_tags": [self.tag_1.title]},
            },
            "new_tag": {
                "preconditions": {"all_tags": self.tags_name, "content_tags": []},
                "inputs": {"tags": new_tag_name},
                "expected_outputs": {"all_tags": self.tags_name + [new_tag_name], "content_tags": [new_tag_name]},
            },
        }

    def enforce_preconditions(self, preconditions):
        """Prepare the test environment to match given preconditions"""
        tags = []
        for t in preconditions["content_tags"]:
            tags.append(Tag.objects.get(title=t))
        self.content.tags.set(tags)
        self.assertEqual(list(self.content.tags.values_list("title")), preconditions["content_tags"])

    def post_form(self, inputs):
        """Post the form with given inputs."""
        form_data = {"tags": inputs["tags"]}
        self.client.post(self.form_url, form_data)

    def check_effects(self, expected_outputs):
        """Check the effects of having sent the form."""
        updated_content = PublishableContent.objects.get(pk=self.content.pk)
        content_tags_as_string = [tag.title for tag in updated_content.tags.all()]
        all_tags_as_string = [tag.title for tag in Tag.objects.all()]
        self.assertEqual(content_tags_as_string, expected_outputs["content_tags"])
        self.assertEqual(all_tags_as_string, expected_outputs["all_tags"])
Example #46
0
    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)
Example #47
0
    def test_opinion_validation(self):
        """
        Test the validation of PublishableContent where type is OPINION.
        """

        text_publication = 'Aussi tôt dit, aussi tôt fait !'

        opinion = PublishableContentFactory(type='OPINION')

        opinion.authors.add(self.user_author)
        UserGalleryFactory(gallery=opinion.gallery,
                           user=self.user_author,
                           mode='W')
        opinion.licence = self.licence
        opinion.save()

        opinion_draft = opinion.load_version()
        ExtractFactory(container=opinion_draft, db_object=opinion)
        ExtractFactory(container=opinion_draft, db_object=opinion)

        self.assertEqual(
            self.client.login(username=self.user_author.username,
                              password='******'), True)

        # publish
        result = self.client.post(reverse('validation:publish-opinion',
                                          kwargs={
                                              'pk': opinion.pk,
                                              'slug': opinion.slug
                                          }),
                                  {
                                      'text': text_publication,
                                      'source': '',
                                      'version': opinion_draft.current_version
                                  },
                                  follow=False)
        self.assertEqual(result.status_code, 302)

        self.assertEqual(PublishedContent.objects.count(), 1)

        opinion = PublishableContent.objects.get(pk=opinion.pk)
        self.assertIsNotNone(opinion.public_version)
        self.assertEqual(opinion.public_version.sha_public,
                         opinion_draft.current_version)

        # valid with author => 403
        opinion = PublishableContent.objects.get(pk=opinion.pk)
        opinion_draft = opinion.load_version()

        result = self.client.post(reverse('validation:pick-opinion',
                                          kwargs={
                                              'pk': opinion.pk,
                                              'slug': opinion.slug
                                          }),
                                  {
                                      'source': '',
                                      'version': opinion_draft.current_version
                                  },
                                  follow=False)
        self.assertEqual(result.status_code, 403)

        opinion = PublishableContent.objects.get(pk=opinion.pk)
        self.assertIsNone(opinion.sha_picked)
        self.assertIsNone(opinion.picked_date)

        self.assertEqual(
            self.client.login(username=self.user_staff.username,
                              password='******'), True)

        # valid with staff
        result = self.client.post(reverse('validation:pick-opinion',
                                          kwargs={
                                              'pk': opinion.pk,
                                              'slug': opinion.slug
                                          }),
                                  {
                                      'source': '',
                                      'version': opinion_draft.current_version
                                  },
                                  follow=False)
        self.assertEqual(result.status_code, 302)

        opinion = PublishableContent.objects.get(pk=opinion.pk)
        self.assertEqual(opinion.sha_picked, opinion_draft.current_version)
        self.assertIsNotNone(opinion.picked_date)

        # invalid with author => 403
        self.assertEqual(
            self.client.login(username=self.user_author.username,
                              password='******'), True)

        result = self.client.post(reverse('validation:unpick-opinion',
                                          kwargs={
                                              'pk': opinion.pk,
                                              'slug': opinion.slug
                                          }),
                                  {
                                      'text': 'Parce que je veux',
                                      'version': opinion_draft.current_version
                                  },
                                  follow=False)
        self.assertEqual(result.status_code, 403)

        opinion = PublishableContent.objects.get(pk=opinion.pk)
        self.assertEqual(opinion.sha_picked, opinion_draft.current_version)

        # invalid with staff
        self.assertEqual(
            self.client.login(username=self.user_staff.username,
                              password='******'), True)

        result = self.client.post(reverse('validation:unpick-opinion',
                                          kwargs={
                                              'pk': opinion.pk,
                                              'slug': opinion.slug
                                          }),
                                  {
                                      'text': 'Parce que je peux !',
                                      'version': opinion_draft.current_version
                                  },
                                  follow=False)
        self.assertEqual(result.status_code, 302)

        opinion = PublishableContent.objects.get(pk=opinion.pk)
        self.assertIsNone(opinion.sha_picked)

        # double invalidation wont work
        result = self.client.post(reverse('validation:unpick-opinion',
                                          kwargs={
                                              'pk': opinion.pk,
                                              'slug': opinion.slug
                                          }),
                                  {
                                      'text': 'Parce que je peux toujours ...',
                                      'version': opinion_draft.current_version
                                  },
                                  follow=False)
        self.assertEqual(result.status_code, 403)
Example #48
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 = {}
        path_manifest1 = settings.BASE_DIR / 'fixtures' / 'tuto' / 'balise_audio' / 'manifest.json'
        path_manifest2 = settings.BASE_DIR / 'fixtures' / 'tuto' / 'balise_audio' / 'manifest2.json'
        args = [str(path_manifest2)]
        shutil.copy(path_manifest1, path_manifest2)
        LicenceFactory(code='CC BY')
        call_command('upgrade_manifest_to_v2', *args, **opts)
        manifest = path_manifest2.open('r')
        json = json_handler.loads(manifest.read())

        self.assertTrue('version' in json)
        self.assertTrue('licence' in json)
        self.assertTrue('children' in json)
        self.assertEqual(len(json['children']), 3)
        self.assertEqual(json['children'][0]['object'], 'extract')
        os.unlink(args[0])
        path_manifest1 = settings.BASE_DIR / 'fixtures' / 'tuto' / 'big_tuto_v1' / 'manifest.json'
        path_manifest2 = settings.BASE_DIR / 'fixtures' / 'tuto' / 'big_tuto_v1' / 'manifest2.json'
        args = [str(path_manifest2)]
        shutil.copy(path_manifest1, path_manifest2)
        call_command('upgrade_manifest_to_v2', *args, **opts)
        manifest = path_manifest2.open('r')
        json = json_handler.loads(manifest.read())
        os.unlink(args[0])
        self.assertTrue('version' in json)
        self.assertTrue('licence' in json)
        self.assertTrue('children' in json)
        self.assertEqual(len(json['children']), 5)
        self.assertEqual(json['children'][0]['object'], 'container')
        self.assertEqual(len(json['children'][0]['children']), 3)
        self.assertEqual(len(json['children'][0]['children'][0]['children']),
                         3)
        path_manifest1 = settings.BASE_DIR / 'fixtures' / 'tuto' / 'article_v1' / 'manifest.json'
        path_manifest2 = settings.BASE_DIR / 'fixtures' / 'tuto' / 'article_v1' / 'manifest2.json'
        args = [path_manifest2]
        shutil.copy(path_manifest1, path_manifest2)
        call_command('upgrade_manifest_to_v2', *args, **opts)
        manifest = path_manifest2.open('r')
        json = json_handler.loads(manifest.read())

        self.assertTrue('version' in json)
        self.assertTrue('licence' in json)
        self.assertTrue('children' in json)
        self.assertEqual(len(json['children']), 1)
        os.unlink(args[0])

    def test_generate_markdown(self):
        tuto = PublishedContentFactory(
            type='TUTORIAL')  # generate and publish a tutorial
        published = PublishedContent.objects.get(content_pk=tuto.pk)

        tuto2 = PublishedContentFactory(
            type='TUTORIAL')  # generate and publish a second tutorial
        published2 = PublishedContent.objects.get(content_pk=tuto2.pk)

        self.assertTrue(published.has_md())
        self.assertTrue(published2.has_md())
        os.remove(
            str(
                Path(published.get_extra_contents_directory(),
                     published.content_public_slug + '.md')))
        os.remove(
            str(
                Path(published2.get_extra_contents_directory(),
                     published2.content_public_slug + '.md')))
        self.assertFalse(published.has_md())
        self.assertFalse(published2.has_md())
        # test command with param
        call_command('generate_markdown', published.content.pk)
        self.assertTrue(published.has_md())
        self.assertFalse(published2.has_md())
        os.remove(
            str(
                Path(published.get_extra_contents_directory(),
                     published.content_public_slug + '.md')))
        # test command without param
        call_command('generate_markdown')
        self.assertTrue(published.has_md())
        self.assertTrue(published2.has_md())

    def test_generate_pdf(self):
        """ensure the behavior of the `python manage.py generate_pdf` commmand"""

        self.overridden_zds_app['content'][
            'build_pdf_when_published'] = True  # this test need PDF build, if any

        tuto = PublishedContentFactory(
            type='TUTORIAL')  # generate and publish a tutorial
        published = PublishedContent.objects.get(content_pk=tuto.pk)

        tuto2 = PublishedContentFactory(
            type='TUTORIAL')  # generate and publish a second tutorial
        published2 = PublishedContent.objects.get(content_pk=tuto2.pk)

        # ensure that PDF exists in the first place
        self.assertTrue(published.has_pdf())
        self.assertTrue(published2.has_pdf())

        pdf_path = os.path.join(published.get_extra_contents_directory(),
                                published.content_public_slug + '.pdf')
        pdf_path2 = os.path.join(published2.get_extra_contents_directory(),
                                 published2.content_public_slug + '.pdf')
        self.assertTrue(os.path.exists(pdf_path))
        self.assertTrue(os.path.exists(pdf_path2))

        # 1. re-generate (all) PDFs
        os.remove(pdf_path)
        os.remove(pdf_path2)
        self.assertFalse(os.path.exists(pdf_path))
        self.assertFalse(os.path.exists(pdf_path2))
        call_command('generate_pdf')
        self.assertTrue(os.path.exists(pdf_path))
        self.assertTrue(os.path.exists(pdf_path2))  # both PDFs are generated

        # 2. re-generate a given PDF
        os.remove(pdf_path)
        os.remove(pdf_path2)
        self.assertFalse(os.path.exists(pdf_path))
        self.assertFalse(os.path.exists(pdf_path2))
        call_command('generate_pdf', 'id={}'.format(tuto.pk))
        self.assertTrue(os.path.exists(pdf_path))
        self.assertFalse(
            os.path.exists(pdf_path2))  # only the first PDF is generated

        # 3. re-generate a given PDF with a wrong id
        os.remove(pdf_path)
        self.assertFalse(os.path.exists(pdf_path))
        self.assertFalse(os.path.exists(pdf_path2))
        call_command('generate_pdf', 'id=-1')  # There is no content with pk=-1
        self.assertFalse(os.path.exists(pdf_path))
        self.assertFalse(os.path.exists(pdf_path2))  # so no PDF is generated !

    def test_last_participation_is_old(self):
        article = PublishedContentFactory(author_list=[self.user_author],
                                          type='ARTICLE')
        new_user = ProfileFactory().user
        reac = ContentReaction(author=self.user_author,
                               position=1,
                               related_content=article)
        reac.update_content('I will find you.')
        reac.save()
        article.last_note = reac
        article.save()

        self.assertFalse(last_participation_is_old(article, new_user))
        ContentRead(user=self.user_author, note=reac, content=article).save()
        reac = ContentReaction(author=new_user,
                               position=2,
                               related_content=article)
        reac.update_content('I will find you.')
        reac.save()
        article.last_note = reac
        article.save()
        ContentRead(user=new_user, note=reac, content=article).save()
        self.assertFalse(last_participation_is_old(article, new_user))
        self.assertTrue(last_participation_is_old(article, self.user_author))

    def testParseBadManifest(self):
        base_content = PublishableContentFactory(
            author_list=[self.user_author])
        versioned = base_content.load_version()
        versioned.add_container(Container('un peu plus près de 42'))
        versioned.dump_json()
        manifest = os.path.join(versioned.get_path(), 'manifest.json')
        dictionary = json_handler.load(open(manifest))

        old_title = dictionary['title']

        # first bad title
        dictionary['title'] = 81 * ['a']
        self.assertRaises(BadManifestError,
                          get_content_from_json,
                          dictionary,
                          None,
                          '',
                          max_title_len=PublishableContent._meta.get_field(
                              'title').max_length)
        dictionary['title'] = ''.join(dictionary['title'])
        self.assertRaises(BadManifestError,
                          get_content_from_json,
                          dictionary,
                          None,
                          '',
                          max_title_len=PublishableContent._meta.get_field(
                              'title').max_length)
        dictionary['title'] = '...'
        self.assertRaises(InvalidSlugError,
                          get_content_from_json,
                          dictionary,
                          None,
                          '',
                          max_title_len=PublishableContent._meta.get_field(
                              'title').max_length)

        dictionary['title'] = old_title
        dictionary['children'][0]['title'] = 81 * ['a']
        self.assertRaises(BadManifestError,
                          get_content_from_json,
                          dictionary,
                          None,
                          '',
                          max_title_len=PublishableContent._meta.get_field(
                              'title').max_length)

        dictionary['children'][0]['title'] = 'bla'
        dictionary['children'][0]['slug'] = '...'
        self.assertRaises(InvalidSlugError,
                          get_content_from_json,
                          dictionary,
                          None,
                          '',
                          max_title_len=PublishableContent._meta.get_field(
                              'title').max_length)

    def test_get_commit_author(self):
        """Ensure the behavior of `get_commit_author()` :
          - `git.Actor` use the pk of the bot account when no one is connected
          - `git.Actor` use the pk (and the email) of the connected account when available

        (Implementation of `git.Actor` is there :
        https://github.com/gitpython-developers/GitPython/blob/master/git/util.py#L312)
        """

        # 1. With user connected
        self.assertEqual(
            self.client.login(username=self.user_author.username,
                              password='******'), True)

        # go to whatever page, if not, `get_current_user()` does not work at all
        result = self.client.get(reverse('pages-index'))
        self.assertEqual(result.status_code, 200)

        actor = get_commit_author()
        self.assertEqual(actor['committer'].name, str(self.user_author.pk))
        self.assertEqual(actor['author'].name, str(self.user_author.pk))
        self.assertEqual(actor['committer'].email, self.user_author.email)
        self.assertEqual(actor['author'].email, self.user_author.email)

    def test_get_commit_author_not_auth(self):
        result = self.client.get(reverse('pages-index'))
        self.assertEqual(result.status_code, 200)

        actor = get_commit_author()
        self.assertEqual(actor['committer'].name, str(self.mas.pk))
        self.assertEqual(actor['author'].name, str(self.mas.pk))

    def invalid_slug_is_invalid(self):
        """ensure that an exception is raised when it should"""

        # exception are raised when title are invalid
        invalid_titles = [
            '-', '_', '__', '-_-', '$', '@', '&', '{}', '    ', '...'
        ]

        for t in invalid_titles:
            self.assertRaises(InvalidSlugError, slugify_raise_on_invalid, t)

        # Those slugs are recognized as wrong slug
        invalid_slugs = [
            '',  # empty
            '----',  # empty
            '___',  # empty
            '-_-',  # empty (!)
            '&;',  # invalid characters
            '!{',  # invalid characters
            '@',  # invalid character
            'a '  # space !
        ]

        for s in invalid_slugs:
            self.assertFalse(check_slug(s))

        # too long slugs are forbidden :
        too_damn_long_slug = 'a' * (
            self.overridden_zds_app['content']['maximum_slug_size'] + 1)
        self.assertFalse(check_slug(too_damn_long_slug))

    def test_adjust_char_count(self):
        """Test the `adjust_char_count` command"""

        article = PublishedContentFactory(type='ARTICLE',
                                          author_list=[self.user_author])
        published = PublishedContent.objects.filter(content=article).first()
        published.char_count = None
        published.save()

        call_command('adjust_char_count')

        published = PublishedContent.objects.get(pk=published.pk)
        self.assertEqual(published.char_count, published.get_char_count())

    def test_image_with_non_ascii_chars(self):
        """seen on #4144"""
        article = PublishableContentFactory(type='article',
                                            author_list=[self.user_author])
        image_string = '![Portrait de Richard Stallman en 2014. [Source](https://commons.wikimedia.org/wiki/' \
                       'File:Richard_Stallman_-_Fête_de_l%27Humanité_2014_-_010.jpg).]' \
                       '(/media/galleries/4410/c1016bf1-a1de-48a1-9ef1-144308e8725d.jpg)'
        article.sha_draft = article.load_version().repo_update(
            article.title, image_string, '', update_slug=False)
        article.save(force_slug_update=False)
        publish_content(article, article.load_version())
        self.assertTrue(
            PublishedContent.objects.filter(content_id=article.pk).exists())

    def test_no_alert_on_unpublish(self):
        """related to #4860"""
        published = PublishedContentFactory(type='OPINION',
                                            author_list=[self.user_author])
        reaction = ContentReactionFactory(related_content=published,
                                          author=ProfileFactory().user,
                                          position=1,
                                          pubdate=datetime.datetime.now())
        Alert.objects.create(scope='CONTENT',
                             comment=reaction,
                             text='a text',
                             author=ProfileFactory().user,
                             pubdate=datetime.datetime.now(),
                             content=published)
        staff = StaffProfileFactory().user
        self.assertEqual(1, get_header_notifications(staff)['alerts']['total'])
        unpublish_content(published, staff)
        self.assertEqual(0, get_header_notifications(staff)['alerts']['total'])

    def tearDown(self):
        super().tearDown()
        PublicatorRegistry.registry = self.old_registry
Example #49
0
    def test_permanently_unpublish_opinion(self):
        opinion = PublishableContentFactory(type='OPINION')

        opinion.authors.add(self.user_author)
        UserGalleryFactory(gallery=opinion.gallery,
                           user=self.user_author,
                           mode='W')
        opinion.licence = self.licence
        opinion.save()

        opinion_draft = opinion.load_version()
        ExtractFactory(container=opinion_draft, db_object=opinion)
        ExtractFactory(container=opinion_draft, db_object=opinion)

        self.assertEqual(
            self.client.login(username=self.user_author.username,
                              password='******'), True)

        # publish
        result = self.client.post(reverse('validation:publish-opinion',
                                          kwargs={
                                              'pk': opinion.pk,
                                              'slug': opinion.slug
                                          }),
                                  {
                                      'source': '',
                                      'version': opinion_draft.current_version
                                  },
                                  follow=False)
        self.assertEqual(result.status_code, 302)

        # login as staff
        self.assertEqual(
            self.client.login(username=self.user_staff.username,
                              password='******'), True)

        # unpublish opinion
        result = self.client.post(reverse('validation:ignore-opinion',
                                          kwargs={
                                              'pk': opinion.pk,
                                              'slug': opinion.slug
                                          }), {
                                              'operation': 'REMOVE_PUB',
                                          },
                                  follow=False)
        self.assertEqual(result.status_code, 200)

        # refresh
        opinion = PublishableContent.objects.get(pk=opinion.pk)

        # check that the opinion is not published
        self.assertFalse(opinion.in_public())

        # check that it's impossible to publish the opinion again
        result = self.client.get(opinion.get_absolute_url())
        self.assertContains(result, _('Billet modéré'))  # front

        result = self.client.post(reverse('validation:publish-opinion',
                                          kwargs={
                                              'pk': opinion.pk,
                                              'slug': opinion.slug
                                          }),
                                  {
                                      'source': '',
                                      'version': opinion_draft.current_version
                                  },
                                  follow=False)
        self.assertEqual(result.status_code, 403)  # back
Example #50
0
    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)
Example #51
0
    def test_cancel_pick_operation(self):
        opinion = PublishableContentFactory(type='OPINION')

        opinion.authors.add(self.user_author)
        UserGalleryFactory(gallery=opinion.gallery,
                           user=self.user_author,
                           mode='W')
        opinion.licence = self.licence
        opinion.save()

        opinion_draft = opinion.load_version()
        ExtractFactory(container=opinion_draft, db_object=opinion)
        ExtractFactory(container=opinion_draft, db_object=opinion)

        self.assertEqual(
            self.client.login(username=self.user_author.username,
                              password='******'), True)

        # publish
        result = self.client.post(reverse('validation:publish-opinion',
                                          kwargs={
                                              'pk': opinion.pk,
                                              'slug': opinion.slug
                                          }),
                                  {
                                      'source': '',
                                      'version': opinion_draft.current_version
                                  },
                                  follow=False)
        self.assertEqual(result.status_code, 302)

        # login as staff
        self.assertEqual(
            self.client.login(username=self.user_staff.username,
                              password='******'), True)

        # PICK
        result = self.client.post(reverse('validation:pick-opinion',
                                          kwargs={
                                              'pk': opinion.pk,
                                              'slug': opinion.slug
                                          }),
                                  {
                                      'source': '',
                                      'version': opinion_draft.current_version
                                  },
                                  follow=False)
        self.assertEqual(result.status_code, 302)

        # cancel the operation
        operation = PickListOperation.objects.latest('operation_date')
        result = self.client.post(reverse('validation:revoke-ignore-opinion',
                                          kwargs={'pk': operation.pk}),
                                  follow=False)
        self.assertEqual(result.status_code, 200)

        # refresh
        operation = PickListOperation.objects.get(pk=operation.pk)
        opinion = PublishableContent.objects.get(pk=opinion.pk)
        self.assertFalse(operation.is_effective)
        self.assertEqual(self.user_staff, operation.canceler_user)
        self.assertIsNone(opinion.sha_picked)

        # NO_PICK
        result = self.client.post(reverse('validation:ignore-opinion',
                                          kwargs={
                                              'pk': opinion.pk,
                                              'slug': opinion.slug
                                          }), {
                                              'operation': 'NO_PICK',
                                          },
                                  follow=False)
        self.assertEqual(result.status_code, 200)

        # cancel the operation
        operation = PickListOperation.objects.latest('operation_date')
        result = self.client.post(reverse('validation:revoke-ignore-opinion',
                                          kwargs={'pk': operation.pk}),
                                  follow=False)
        self.assertEqual(result.status_code, 200)

        # check that the opinion is displayed on validation page
        result = self.client.get(reverse('validation:list-opinion'))
        self.assertContains(result, opinion.title)

        # REMOVE_PUB
        result = self.client.post(reverse('validation:ignore-opinion',
                                          kwargs={
                                              'pk': opinion.pk,
                                              'slug': opinion.slug
                                          }), {
                                              'operation': 'REMOVE_PUB',
                                          },
                                  follow=False)
        self.assertEqual(result.status_code, 200)

        # cancel the operation
        operation = PickListOperation.objects.latest('operation_date')
        result = self.client.post(reverse('validation:revoke-ignore-opinion',
                                          kwargs={'pk': operation.pk}),
                                  follow=False)
        self.assertEqual(result.status_code, 200)

        # check that the opinion can be published again
        result = self.client.post(reverse('validation:publish-opinion',
                                          kwargs={
                                              'pk': opinion.pk,
                                              'slug': opinion.slug
                                          }),
                                  {
                                      'source': '',
                                      'version': opinion_draft.current_version
                                  },
                                  follow=False)
        self.assertEqual(result.status_code, 302)
Example #52
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
Example #53
0
    def test_opinion_alert(self):
        """Test content alert"""

        text_publication = 'Aussi tôt dit, aussi tôt fait !'

        opinion = PublishableContentFactory(type='OPINION')

        opinion.authors.add(self.user_author)
        UserGalleryFactory(gallery=opinion.gallery,
                           user=self.user_author,
                           mode='W')
        opinion.licence = self.licence
        opinion.save()

        opinion_draft = opinion.load_version()
        ExtractFactory(container=opinion_draft, db_object=opinion)
        ExtractFactory(container=opinion_draft, db_object=opinion)

        self.assertEqual(
            self.client.login(username=self.user_author.username,
                              password='******'), True)

        result = self.client.post(reverse('validation:publish-opinion',
                                          kwargs={
                                              'pk': opinion.pk,
                                              'slug': opinion.slug
                                          }),
                                  {
                                      'text': text_publication,
                                      'source': '',
                                      'version': opinion_draft.current_version
                                  },
                                  follow=False)
        self.assertEqual(result.status_code, 302)

        self.assertEqual(PublishedContent.objects.count(), 1)

        opinion = PublishableContent.objects.get(pk=opinion.pk)
        self.assertIsNotNone(opinion.public_version)
        self.assertEqual(opinion.public_version.sha_public,
                         opinion_draft.current_version)

        # Alert content
        random_user = ProfileFactory().user

        self.assertEqual(
            self.client.login(username=random_user.username,
                              password='******'), True)

        result = self.client.post(reverse('content:alert-content',
                                          kwargs={'pk': opinion.pk}),
                                  {'signal_text': 'Yeurk !'},
                                  follow=False)

        self.assertEqual(result.status_code, 302)
        self.assertIsNotNone(
            Alert.objects.filter(author__pk=random_user.pk,
                                 content__pk=opinion.pk).first())

        alert = Alert.objects.filter(author__pk=random_user.pk,
                                     content__pk=opinion.pk).first()
        self.assertFalse(alert.solved)

        result = self.client.post(reverse('content:resolve-content',
                                          kwargs={'pk': opinion.pk}), {
                                              'alert_pk': alert.pk,
                                              'text': 'Je peux ?'
                                          },
                                  follow=False)
        self.assertEqual(result.status_code,
                         403)  # solving the alert by yourself wont work

        alert = Alert.objects.get(pk=alert.pk)
        self.assertFalse(alert.solved)

        self.assertEqual(
            self.client.login(username=self.user_staff.username,
                              password='******'), True)

        result = self.client.post(reverse('content:resolve-content',
                                          kwargs={'pk': opinion.pk}), {
                                              'alert_pk': alert.pk,
                                              'text': 'Anéfé!'
                                          },
                                  follow=False)
        self.assertEqual(result.status_code, 302)

        alert = Alert.objects.get(pk=alert.pk)
        self.assertTrue(alert.solved)
Example #54
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))
Example #55
0
    def test_category_and_subcategory_impact_search(self):
        """If two contents do not belong to the same (sub)category"""

        if not self.manager.connected_to_es:
            return

        text = 'Did you ever hear the tragedy of Darth Plagueis The Wise?'

        # 1. Create two contents with different subcategories
        category_1 = 'category 1'
        subcategory_1 = SubCategoryFactory(title=category_1)
        category_2 = 'category 2'
        subcategory_2 = SubCategoryFactory(title=category_2)

        tuto_1 = PublishableContentFactory(type='TUTORIAL')
        tuto_1_draft = tuto_1.load_version()

        tuto_1.title = text
        tuto_1.authors.add(self.user)
        tuto_1.subcategory.add(subcategory_1)
        tuto_1.save()

        tuto_1_draft.description = text
        tuto_1_draft.repo_update_top_container(text, tuto_1.slug, text, text)

        chapter_1 = ContainerFactory(parent=tuto_1_draft, db_object=tuto_1)
        extract_1 = ExtractFactory(container=chapter_1, db_object=tuto_1)
        extract_1.repo_update(text, text)

        published_1 = publish_content(tuto_1, tuto_1_draft, is_major_update=True)

        tuto_1.sha_public = tuto_1_draft.current_version
        tuto_1.sha_draft = tuto_1_draft.current_version
        tuto_1.public_version = published_1
        tuto_1.save()

        tuto_2 = PublishableContentFactory(type='TUTORIAL')
        tuto_2_draft = tuto_2.load_version()

        tuto_2.title = text
        tuto_2.authors.add(self.user)
        tuto_2.subcategory.add(subcategory_2)
        tuto_2.save()

        tuto_2_draft.description = text
        tuto_2_draft.repo_update_top_container(text, tuto_2.slug, text, text)

        chapter_2 = ContainerFactory(parent=tuto_2_draft, db_object=tuto_2)
        extract_2 = ExtractFactory(container=chapter_2, db_object=tuto_2)
        extract_2.repo_update(text, text)

        published_2 = publish_content(tuto_2, tuto_2_draft, is_major_update=True)

        tuto_2.sha_public = tuto_2_draft.current_version
        tuto_2.sha_draft = tuto_2_draft.current_version
        tuto_2.public_version = published_2
        tuto_2.save()

        # 2. Index:
        self.assertEqual(len(self.manager.setup_search(Search().query(MatchAll())).execute()), 0)

        # index
        for model in self.indexable:
            if model is FakeChapter:
                continue
            self.manager.es_bulk_indexing_of_model(model)
        self.manager.refresh_index()

        result = self.client.get(reverse('search:query') + '?q=' + text, follow=False)
        self.assertEqual(result.status_code, 200)

        response = result.context['object_list'].execute()
        self.assertEqual(response.hits.total, 4)  # Ok

        # 3. Test
        result = self.client.get(
            reverse('search:query') + '?q=' + text + '&model=content&subcategory=' + subcategory_1.slug, follow=False)

        self.assertEqual(result.status_code, 200)

        response = result.context['object_list'].execute()
        self.assertEqual(response.hits.total, 2)

        self.assertEqual([int(r.meta.id) for r in response if r.meta.doc_type == 'publishedcontent'][0], published_1.pk)
        self.assertEqual(
            [r.meta.id for r in response if r.meta.doc_type == 'chapter'][0],
            tuto_1.slug + '__' + chapter_1.slug)

        result = self.client.get(
            reverse('search:query') + '?q=' + text + '&model=content&subcategory=' + subcategory_2.slug, follow=False)

        self.assertEqual(result.status_code, 200)

        response = result.context['object_list'].execute()
        self.assertEqual(response.hits.total, 2)

        self.assertEqual([int(r.meta.id) for r in response if r.meta.doc_type == 'publishedcontent'][0], published_2.pk)
        self.assertEqual(
            [r.meta.id for r in response if r.meta.doc_type == 'chapter'][0],
            tuto_2.slug + '__' + chapter_2.slug)
Example #56
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()))
Example #57
0
    def test_special_case_of_contents(self):
        """test that the old publishedcontent does not stay when a new one is created"""

        if not self.manager.connected_to_es:
            return

        # 1. Create a middle-tutorial, publish it, then index it
        tuto = PublishableContentFactory(type='TUTORIAL')
        tuto.authors.add(self.user)
        tuto.save()

        tuto_draft = tuto.load_version()
        chapter1 = ContainerFactory(parent=tuto_draft, db_object=tuto)
        ExtractFactory(container=chapter1, db_object=tuto)
        published = publish_content(tuto, tuto_draft, is_major_update=True)

        tuto.sha_public = tuto_draft.current_version
        tuto.sha_draft = tuto_draft.current_version
        tuto.public_version = published
        tuto.save()

        self.manager.es_bulk_indexing_of_model(PublishedContent, force_reindexing=True)  # index
        self.manager.refresh_index()

        first_publication = PublishedContent.objects.get(content_pk=tuto.pk)
        self.assertTrue(first_publication.es_already_indexed)
        self.assertFalse(first_publication.es_flagged)

        s = Search()
        s.query(MatchAll())
        results = self.manager.setup_search(s).execute()
        self.assertEqual(len(results), 2)  # get 2 results, one for the content and one for the chapter

        self.assertEqual(PublishedContent.objects.count(), 1)

        # 2. Change thet title, which will trigger a change in the slug
        tuto = PublishableContent.objects.get(pk=tuto.pk)
        versioned = tuto.load_version(sha=tuto.sha_draft)

        tuto.title = 'un titre complètement différent!'
        tuto.save()

        versioned.repo_update_top_container(tuto.title, tuto.slug, 'osef', 'osef')
        second_publication = publish_content(tuto, versioned, True)

        tuto.sha_public = versioned.current_version
        tuto.sha_draft = versioned.current_version
        tuto.public_version = second_publication
        tuto.save()

        self.assertEqual(PublishedContent.objects.count(), 2)  # now there is two objects ...
        first_publication = PublishedContent.objects.get(pk=first_publication.pk)
        self.assertTrue(first_publication.must_redirect)  # .. including the first one, for redirection

        self.manager.refresh_index()

        s = Search()
        s.query(MatchAll())
        results = self.manager.setup_search(s).execute()
        self.assertEqual(len(results), 0)  # the old one is gone (and we need to reindex to get the new one)

        # 3. Check if indexation brings the new one, and not the old one
        self.manager.es_bulk_indexing_of_model(PublishedContent, force_reindexing=True)  # index
        self.manager.refresh_index()

        first_publication = PublishedContent.objects.get(pk=first_publication.pk)
        second_publication = PublishedContent.objects.get(pk=second_publication.pk)

        s = Search()
        s.query(MatchAll())
        results = self.manager.setup_search(s).execute()
        self.assertEqual(len(results), 2)  # Still 2, not 4 !

        found_old = False
        found_new = False

        for hit in results:
            if hit.meta.doc_type == PublishedContent.get_es_document_type():
                if hit.meta.id == first_publication.es_id:
                    found_old = True
                if hit.meta.id == second_publication.es_id:
                    found_new = True

        self.assertTrue(found_new)
        self.assertFalse(found_old)
Example #58
0
class ContentNotification(TestCase, TutorialTestMixin):
    def setUp(self):

        # don't build PDF to speed up the tests
        self.user1 = ProfileFactory().user
        self.user2 = ProfileFactory().user

        # create a tutorial
        self.tuto = PublishableContentFactory(type="TUTORIAL")
        self.tuto.authors.add(self.user1)
        UserGalleryFactory(gallery=self.tuto.gallery,
                           user=self.user1,
                           mode="W")
        self.tuto.licence = LicenceFactory()
        self.tuto.subcategory.add(SubCategoryFactory())
        self.tuto.save()
        tuto_draft = self.tuto.load_version()

        # then, publish it !
        version = tuto_draft.current_version
        self.published = publish_content(self.tuto,
                                         tuto_draft,
                                         is_major_update=True)

        self.tuto.sha_public = version
        self.tuto.sha_draft = version
        self.tuto.public_version = self.published
        self.tuto.save()

        self.client.force_login(self.user1)

    def test_no_persistant_notif_on_revoke(self):
        from zds.tutorialv2.publication_utils import unpublish_content

        NewPublicationSubscription.objects.get_or_create_active(
            self.user1, self.user2)
        content = PublishedContentFactory(author_list=[self.user2])

        signals.content_published.send(sender=self.tuto.__class__,
                                       instance=content,
                                       by_email=False)
        self.assertEqual(
            1, len(Notification.objects.get_notifications_of(self.user1)))
        unpublish_content(content)
        self.assertEqual(
            0, len(Notification.objects.get_notifications_of(self.user1)))

    def test_no_persistant_comment_notif_on_revoke(self):
        from zds.tutorialv2.publication_utils import unpublish_content

        content = PublishedContentFactory(author_list=[self.user2])
        ContentReactionAnswerSubscription.objects.get_or_create_active(
            self.user1, content)
        ContentReactionFactory(related_content=content,
                               author=self.user2,
                               position=1)
        self.assertEqual(
            1,
            len(Notification.objects.get_unread_notifications_of(self.user1)))
        unpublish_content(content, moderator=self.user2)
        self.assertEqual(
            0,
            len(Notification.objects.get_unread_notifications_of(self.user1)))

    def test_only_one_notif_on_update(self):
        NewPublicationSubscription.objects.get_or_create_active(
            self.user1, self.user2)
        content = PublishedContentFactory(author_list=[self.user2])
        notify_update(content, False, True)
        versioned = content.load_version()
        content.sha_draft = versioned.repo_update(introduction="new intro",
                                                  conclusion="new conclusion",
                                                  title=versioned.title)
        content.save()
        publish_content(content, content.load_version(), True)
        notify_update(content, True, False)
        notifs = get_header_notifications(
            self.user1)["general_notifications"]["list"]
        self.assertEqual(1, len(notifs), str(notifs))

    def test_only_one_notif_on_major_update(self):
        NewPublicationSubscription.objects.get_or_create_active(
            self.user1, self.user2)
        content = PublishedContentFactory(author_list=[self.user2])
        notify_update(content, False, True)
        versioned = content.load_version()
        content.sha_draft = versioned.repo_update(introduction="new intro",
                                                  conclusion="new conclusion",
                                                  title=versioned.title)
        content.save()
        publish_content(content, content.load_version(), True)
        notify_update(content, True, True)
        notifs = get_header_notifications(
            self.user1)["general_notifications"]["list"]
        self.assertEqual(1, len(notifs), str(notifs))
Example #59
0
class NotificationPublishableContentTest(TestCase):
    def setUp(self):
        self.user1 = ProfileFactory().user
        self.user2 = ProfileFactory().user

        # create a tutorial
        self.tuto = PublishableContentFactory(type='TUTORIAL')
        self.tuto.authors.add(self.user1)
        UserGalleryFactory(gallery=self.tuto.gallery,
                           user=self.user1,
                           mode='W')
        self.tuto.licence = LicenceFactory()
        self.tuto.subcategory.add(SubCategoryFactory())
        self.tuto.save()
        tuto_draft = self.tuto.load_version()

        # then, publish it !
        version = tuto_draft.current_version
        self.published = publish_content(self.tuto,
                                         tuto_draft,
                                         is_major_update=True)

        self.tuto.sha_public = version
        self.tuto.sha_draft = version
        self.tuto.public_version = self.published
        self.tuto.save()

        self.assertTrue(
            self.client.login(username=self.user1.username,
                              password='******'))

    def test_follow_content_at_publication(self):
        """
        When a content is published, authors automatically follow it.
        """
        subscription = ContentReactionAnswerSubscription.objects.get_existing(
            user=self.user1, content_object=self.tuto)
        self.assertIsNone(subscription)

        # Signal call by the view at the publication.
        signals.new_content.send(sender=self.tuto.__class__,
                                 instance=self.tuto,
                                 by_email=False)

        subscription = ContentReactionAnswerSubscription.objects.get_existing(
            user=self.user1, content_object=self.tuto)
        self.assertTrue(subscription.is_active)

    def test_follow_content_from_view(self):
        """
        Allows a user to follow (or not) a content from the view.
        """
        subscription = ContentReactionAnswerSubscription.objects.get_existing(
            user=self.user1, content_object=self.tuto)
        self.assertIsNone(subscription)

        result = self.client.post(
            reverse('content:follow-reactions', args=[self.tuto.pk]),
            {'follow': 1})
        self.assertEqual(result.status_code, 302)

        subscription = ContentReactionAnswerSubscription.objects.get_existing(
            user=self.user1, content_object=self.tuto)
        self.assertTrue(subscription.is_active)

    def test_answer_subscription(self):
        """
        When a user posts on a publishable content, the user gets subscribed.
        """
        subscription = ContentReactionAnswerSubscription.objects.get_existing(
            user=self.user1, content_object=self.tuto)
        self.assertIsNone(subscription)

        result = self.client.post(reverse('content:add-reaction') +
                                  '?pk={}'.format(self.tuto.pk), {
                                      'text': 'message',
                                      'last_note': '0'
                                  },
                                  follow=True)
        self.assertEqual(result.status_code, 200)

        subscription = ContentReactionAnswerSubscription.objects.get_existing(
            user=self.user1, content_object=self.tuto)
        self.assertTrue(subscription.is_active)

    def test_notification_read(self):
        """
        When the notification is a reaction, it is marked as read
        when the corresponding content is displayed to the user.
        """
        ContentReactionFactory(related_content=self.tuto,
                               author=self.user1,
                               position=1)
        last_note = ContentReactionFactory(related_content=self.tuto,
                                           author=self.user2,
                                           position=2)
        self.tuto.last_note = last_note
        self.tuto.save()

        notification = Notification.objects.get(subscription__user=self.user1)
        self.assertFalse(notification.is_read)

        result = self.client.get(reverse('tutorial:view',
                                         args=[self.tuto.pk, self.tuto.slug]),
                                 follow=False)
        self.assertEqual(result.status_code, 200)

        notification = Notification.objects.get(subscription__user=self.user1)
        self.assertTrue(notification.is_read)

    def test_subscription_to_new_publications_from_user(self):
        """
        Any user may subscribe to new publications from a user.
        """
        result = self.client.post(reverse('content:follow',
                                          args=[self.user1.pk]),
                                  follow=False)
        self.assertEqual(result.status_code, 403)

        self.client.logout()
        self.assertTrue(
            self.client.login(username=self.user2.username,
                              password='******'), True)

        result = self.client.post(reverse('content:follow',
                                          args=[self.user1.pk]), {'follow': 1},
                                  follow=False,
                                  HTTP_X_REQUESTED_WITH='XMLHttpRequest')
        self.assertEqual(result.status_code, 200)

        subscription = NewPublicationSubscription.objects.get_existing(
            user=self.user2, content_object=self.user1)
        self.assertTrue(subscription.is_active)

        result = self.client.post(reverse('content:follow',
                                          args=[self.user1.pk]), {'email': 1},
                                  follow=False,
                                  HTTP_X_REQUESTED_WITH='XMLHttpRequest')
        self.assertEqual(result.status_code, 200)

        subscription = NewPublicationSubscription.objects.get_existing(
            user=self.user2, content_object=self.user1)
        self.assertTrue(subscription.is_active)
        self.assertTrue(subscription.by_email)

    def test_notification_generated_when_a_tuto_is_published(self):
        """
        When a user subscribe to new publications from a user, a notification is generated when a publication is
        published.
        """
        subscription = NewPublicationSubscription.objects.toggle_follow(
            self.user1, self.user2)

        signals.new_content.send(sender=self.tuto.__class__,
                                 instance=self.tuto,
                                 by_email=False)

        notifications = Notification.objects.filter(subscription=subscription,
                                                    is_read=False).all()
        self.assertEqual(1, len(notifications))

        signals.content_read.send(sender=self.tuto.__class__,
                                  instance=self.tuto,
                                  user=self.user2,
                                  target=ContentReaction)

        notifications = Notification.objects.filter(subscription=subscription,
                                                    is_read=False).all()
        self.assertEqual(1, len(notifications))

        signals.content_read.send(sender=self.tuto.__class__,
                                  instance=self.tuto,
                                  user=self.user2,
                                  target=PublishableContent)

        notifications = Notification.objects.filter(subscription=subscription,
                                                    is_read=False).all()
        self.assertEqual(0, len(notifications))

    def test_no_error_on_multiple_subscription(self):
        subscription = NewPublicationSubscription.objects.toggle_follow(
            self.user1, self.user2)

        signals.new_content.send(sender=self.tuto.__class__,
                                 instance=self.tuto,
                                 by_email=False)

        subscription1 = Notification.objects.filter(subscription=subscription,
                                                    is_read=False).first()
        subscription2 = copy.copy(subscription1)
        subscription2.save()
        subscription.mark_notification_read(self.tuto)
        subscription1 = Notification.objects.filter(subscription=subscription,
                                                    is_read=False).first()
        self.assertIsNone(subscription1)
        self.assertEqual(
            1,
            Notification.objects.filter(subscription=subscription,
                                        is_read=True).count())
Example #60
0
    def test_filters(self):
        """ Test filtering by category & tag """
        subcategory2 = SubCategoryFactory()
        subcategory3 = SubCategoryFactory()
        tag2 = TagFactory()
        tag3 = TagFactory()

        # Add a new tuto & publish it

        article2 = PublishableContentFactory(type="ARTICLE")
        article2.authors.add(self.user_author)
        article2.licence = self.licence
        article2.subcategory.add(subcategory2)
        article2.tags.add(self.tag)
        article2.tags.add(tag2)
        article2.save()

        article2_draft = article2.load_version()
        article2.sha_public = article2.sha_draft = article2_draft.current_version
        article2.public_version = publish_content(article2,
                                                  article2_draft,
                                                  is_major_update=True)
        article2.save()

        # Default view

        ret = [item.content for item in self.articlefeed.items()]
        self.assertEqual(ret, [article2, self.article])

        # Filter by subcategory

        self.articlefeed.query_params = {"subcategory": self.subcategory.slug}
        ret = [item.content for item in self.articlefeed.items()]
        self.assertEqual(ret, [self.article])

        self.articlefeed.query_params = {
            "subcategory": f" {self.subcategory.slug} "
        }
        ret = [item.content for item in self.articlefeed.items()]
        self.assertEqual(ret, [self.article])

        self.articlefeed.query_params = {"subcategory": subcategory2.slug}
        ret = [item.content for item in self.articlefeed.items()]
        self.assertEqual(ret, [article2])

        self.articlefeed.query_params = {"subcategory": subcategory3.slug}
        ret = [item.content for item in self.articlefeed.items()]
        self.assertEqual(ret, [])

        self.articlefeed.query_params = {"subcategory": "invalid"}
        self.assertRaises(Http404, self.articlefeed.items)

        # Filter by tag

        self.articlefeed.query_params = {"tag": self.tag.slug}
        ret = [item.content for item in self.articlefeed.items()]
        self.assertEqual(ret, [article2, self.article])

        self.articlefeed.query_params = {"tag": tag2.slug}
        ret = [item.content for item in self.articlefeed.items()]
        self.assertEqual(ret, [article2])

        self.articlefeed.query_params = {"tag": f" {tag2.slug} "}
        ret = [item.content for item in self.articlefeed.items()]
        self.assertEqual(ret, [article2])

        self.articlefeed.query_params = {"tag": tag3.slug}
        ret = [item.content for item in self.articlefeed.items()]
        self.assertEqual(ret, [])

        self.articlefeed.query_params = {"tag": "invalid"}
        self.assertRaises(Http404, self.articlefeed.items)