Ejemplo n.º 1
0
    def test_review_tags(self):
        client = LocalizingClient()
        client.login(username='******', password='******')

        data = new_document_data()
        data.update({'review_tags':['editorial']})
        response = client.post(reverse('wiki.new_document'), data)

        doc = Document.objects.get(slug="a-test-article")

        combos = (
            ([], 0, 0, 0, 0),
            (['technical',], 1, 1, 0, 0),
            (['editorial',], 0, 0, 1, 1),
            (['technical', 'editorial',], 1, 1, 1, 1),
        )

        for tags, a, b, c, d in combos:

            # Edit the page and set the tags for this test
            data.update({ 'form': 'rev', 'review_tags': tags })
            response = client.post(reverse('wiki.edit_document', args=[doc.slug]), data)

            response = client.get(reverse('docs.views.docs'))
            page = pq(response.content)

            # Check for the section itself, and then the doc 
            eq_(a, page('div#review-technical').length)
            eq_(b, page("div#review-technical ul li h4 a:contains('%s')" %
                doc.title).length)
            eq_(c, page('div#review-editorial').length)
            eq_(d, page("div#review-editorial ul li h4 a:contains('%s')" %
                doc.title).length)
Ejemplo n.º 2
0
class DemoListViewsTest(test_utils.TestCase):
    fixtures = ['test_users.json']

    def setUp(self):
        self.user, self.admin_user, self.other_user = make_users()
        self.client = LocalizingClient()

    def test_all_demos_includes_hidden_for_staff(self):
        build_submission(self.user)
        build_hidden_submission(self.user)

        r = self.client.get(reverse('demos_all'))
        count = pq(r.content)('h2.count').text()
        eq_(count, "1 Demo")

        self.client.login(username=self.admin_user.username,
                          password='******')
        r = self.client.get(reverse('demos_all'))
        count = pq(r.content)('h2.count').text()
        eq_(count, "2 Demos")

    @attr('bug882709')
    def test_search_view(self):
        try:
            self.client.get(reverse('demos_search'))
        except:
            self.fail("Search should not ISE.")
Ejemplo n.º 3
0
    def test_invalid_slugs(self, get_current):
        """Slugs cannot contain /."""
        get_current.return_value.domain = 'testserver'
        client = LocalizingClient()
        client.login(username='******', password='******')
        data = new_document_data()
        error = 'The slug provided is not valid.'

        data['slug'] = 'inva/lid'
        response = client.post(reverse('wiki.new_document'), data)
        self.assertContains(response, error)

        data['slug'] = 'no-question-marks?'
        response = client.post(reverse('wiki.new_document'), data)
        self.assertContains(response, error)

        data['slug'] = 'no+plus'
        response = client.post(reverse('wiki.new_document'), data)
        self.assertContains(response, error)

        data['slug'] = 'valid'
        response = client.post(reverse('wiki.new_document'), data)
        self.assertRedirects(response, reverse('wiki.document_revisions',
                                               args=[data['slug']],
                                               locale='en-US'))
Ejemplo n.º 4
0
    def test_raw_section_source(self):
        """The raw source for a document section can be requested"""
        client = LocalizingClient()
        client.login(username='******', password='******')
        d, r = doc_rev("""
            <h1 id="s1">Head 1</h1>
            <p>test</p>
            <p>test</p>

            <h1 id="s2">Head 2</h1>
            <p>test</p>
            <p>test</p>

            <h1 id="s3">Head 3</h1>
            <p>test</p>
            <p>test</p>
        """)
        expected = """
            <h1 id="s2">Head 2</h1>
            <p>test</p>
            <p>test</p>
        """
        response = client.get('%s?section=s2&raw=true' %
                              reverse('wiki.document', args=[d.slug]))
        eq_(normalize_html(expected), 
            normalize_html(response.content))
Ejemplo n.º 5
0
    def test_raw_with_editing_links_source(self):
        """The raw source for a document can be requested, with section editing
        links"""
        client = LocalizingClient()
        client.login(username='******', password='******')
        d, r = doc_rev("""
            <h1 id="s1">Head 1</h1>
            <p>test</p>
            <p>test</p>

            <h1 id="s2">Head 2</h1>
            <p>test</p>
            <p>test</p>

            <h1 id="s3">Head 3</h1>
            <p>test</p>
            <p>test</p>
        """)
        expected = """
            <h1 id="s1"><a class="edit-section" data-section-id="s1" data-section-src-url="/en-US/docs/%(slug)s?raw=true&amp;section=s1" href="/en-US/docs/%(slug)s$edit?section=s1&amp;edit_links=true" title="Edit section">Edit</a>Head 1</h1>
            <p>test</p>
            <p>test</p>
            <h1 id="s2"><a class="edit-section" data-section-id="s2" data-section-src-url="/en-US/docs/%(slug)s?raw=true&amp;section=s2" href="/en-US/docs/%(slug)s$edit?section=s2&amp;edit_links=true" title="Edit section">Edit</a>Head 2</h1>
            <p>test</p>
            <p>test</p>
            <h1 id="s3"><a class="edit-section" data-section-id="s3" data-section-src-url="/en-US/docs/%(slug)s?raw=true&amp;section=s3" href="/en-US/docs/%(slug)s$edit?section=s3&amp;edit_links=true" title="Edit section">Edit</a>Head 3</h1>
            <p>test</p>
            <p>test</p>
        """ % {
            'slug': d.slug
        }
        response = client.get('%s?raw=true&edit_links=true' %
                              reverse('wiki.document', args=[d.slug]))
        eq_(normalize_html(expected), normalize_html(response.content))
Ejemplo n.º 6
0
    def test_redirect_can_be_clobbered(self):
        """When an attempt is made to retitle an article, and another article
        with that title exists but is a redirect, there should be no errors and
        the redirect should be replaced."""
        client = LocalizingClient()
        client.login(username='******', password='******')

        exist_title = "Existing doc"
        exist_slug = "existing-doc"

        # Create a new doc.
        data = new_document_data()
        data.update({"title": exist_title, "slug": exist_slug})
        resp = client.post(reverse('wiki.new_document'), data)
        eq_(302, resp.status_code)

        # Change title and slug
        data.update({
            'form': 'rev',
            'title': "Changed title",
            'slug': "changed-title"
        })
        resp = client.post(reverse('wiki.edit_document', args=[exist_slug]),
                           data)
        eq_(302, resp.status_code)

        # Change title and slug back to originals, clobbering the redirect
        data.update({'form': 'rev', 'title': exist_title, 'slug': exist_slug})
        resp = client.post(
            reverse('wiki.edit_document', args=["changed-title"]), data)
        eq_(302, resp.status_code)
Ejemplo n.º 7
0
    def test_raw_with_editing_links_source(self):
        """The raw source for a document can be requested, with section editing
        links"""
        client = LocalizingClient()
        client.login(username='******', password='******')
        d, r = doc_rev("""
            <h1 id="s1">Head 1</h1>
            <p>test</p>
            <p>test</p>

            <h1 id="s2">Head 2</h1>
            <p>test</p>
            <p>test</p>

            <h1 id="s3">Head 3</h1>
            <p>test</p>
            <p>test</p>
        """)
        expected = """
            <h1 id="s1"><a class="edit-section" data-section-id="s1" data-section-src-url="/en-US/docs/%(slug)s?raw=true&amp;section=s1" href="/en-US/docs/%(slug)s$edit?section=s1&amp;edit_links=true" title="Edit section">Edit</a>Head 1</h1>
            <p>test</p>
            <p>test</p>
            <h1 id="s2"><a class="edit-section" data-section-id="s2" data-section-src-url="/en-US/docs/%(slug)s?raw=true&amp;section=s2" href="/en-US/docs/%(slug)s$edit?section=s2&amp;edit_links=true" title="Edit section">Edit</a>Head 2</h1>
            <p>test</p>
            <p>test</p>
            <h1 id="s3"><a class="edit-section" data-section-id="s3" data-section-src-url="/en-US/docs/%(slug)s?raw=true&amp;section=s3" href="/en-US/docs/%(slug)s$edit?section=s3&amp;edit_links=true" title="Edit section">Edit</a>Head 3</h1>
            <p>test</p>
            <p>test</p>
        """ % {'slug': d.slug}
        response = client.get('%s?raw=true&edit_links=true' %
                              reverse('wiki.document', args=[d.slug]))
        eq_(normalize_html(expected), 
            normalize_html(response.content))
Ejemplo n.º 8
0
    def test_invalid_slug(self):
        """Slugs cannot contain "$", but can contain "/"."""
        client = LocalizingClient()
        client.login(username='******', password='******')
        data = new_document_data()

        data['title'] = 'valid slug'
        data['slug'] = 'valid'
        response = client.post(reverse('wiki.new_document'), data)
        self.assertRedirects(response, reverse('wiki.document',
                                               args=[data['slug']],
                                               locale='en-US'))

        # Slashes should be fine
        data['title'] = 'valid with slash'
        data['slug'] = 'va/lid'
        response = client.post(reverse('wiki.new_document'), data)
        self.assertRedirects(response, reverse('wiki.document',
                                               args=[data['slug']],
                                               locale='en-US'))

        # Dollar sign is reserved for verbs
        data['title'] = 'invalid with dollars'
        data['slug'] = 'inva$lid'
        response = client.post(reverse('wiki.new_document'), data)
        self.assertContains(response, 'The slug provided is not valid.')

        # Question mark is reserved for query params
        data['title'] = 'invalid with questions'
        data['slug'] = 'inva?lid'
        response = client.post(reverse('wiki.new_document'), data)
        self.assertContains(response, 'The slug provided is not valid.')
Ejemplo n.º 9
0
    def test_invalid_reserved_term_slug(self):
        """Slugs should not collide with reserved URL patterns"""
        client = LocalizingClient()
        client.login(username='******', password='******')
        data = new_document_data()

        # TODO: This is info derived from urls.py, but unsure how to DRY it
        reserved_slugs = (
            'ckeditor_config.js',
            'watch-ready-for-review',
            'unwatch-ready-for-review',
            'watch-approved',
            'unwatch-approved',
            '.json',
            'new',
            'all',
            'preview-wiki-content',
            'category/10',
            'needs-review/technical',
            'needs-review/',
            'feeds/atom/all/',
            'feeds/atom/needs-review/technical',
            'feeds/atom/needs-review/',
            'tag/tasty-pie'
        )

        for term in reserved_slugs:
            data['title'] = 'invalid with %s' % term
            data['slug'] = term
            response = client.post(reverse('wiki.new_document'), data)
            self.assertContains(response, 'The slug provided is not valid.')
Ejemplo n.º 10
0
    def test_title_slug_collision_errors(self):
        """When an attempt is made to retitle an article and another with that
        title already exists, there should be form errors"""
        client = LocalizingClient()
        client.login(username='******', password='******')

        exist_title = "Existing doc"
        exist_slug = "existing-doc"

        # Create a new doc.
        data = new_document_data()
        data.update({ "title": exist_title, "slug": exist_slug })
        resp = client.post(reverse('wiki.new_document'), data)
        eq_(302, resp.status_code)

        # Create another new doc.
        data = new_document_data()
        data.update({ "title": 'Some new title', "slug": 'some-new-title' })
        response = client.post(reverse('wiki.new_document'), data)
        eq_(302, resp.status_code)

        # Now, post an update with duplicate slug and title
        data.update({
            'form': 'rev',
            'title': exist_title,
            'slug': exist_slug
        })
        resp = client.post(reverse('wiki.edit_document', args=['some-new-title']), data)
        eq_(200, resp.status_code)
        p = pq(resp.content)

        ok_(p.find('.errorlist').length > 0)
        ok_(p.find('.errorlist a[href="#id_title"]').length > 0)
        ok_(p.find('.errorlist a[href="#id_slug"]').length > 0)
Ejemplo n.º 11
0
    def test_redirect_can_be_clobbered(self):
        """When an attempt is made to retitle an article, and another article
        with that title exists but is a redirect, there should be no errors and
        the redirect should be replaced."""
        client = LocalizingClient()
        client.login(username='******', password='******')

        exist_title = "Existing doc"
        exist_slug = "existing-doc"

        # Create a new doc.
        data = new_document_data()
        data.update({ "title": exist_title, "slug": exist_slug })
        resp = client.post(reverse('wiki.new_document'), data)
        eq_(302, resp.status_code)

        # Change title and slug
        data.update({'form': 'rev', 
                     'title': "Changed title", 
                     'slug': "changed-title"})
        resp = client.post(reverse('wiki.edit_document', args=[exist_slug]), 
                           data)
        eq_(302, resp.status_code)

        # Change title and slug back to originals, clobbering the redirect
        data.update({'form': 'rev', 
                     'title': exist_title, 
                     'slug': exist_slug})
        resp = client.post(reverse('wiki.edit_document', args=["changed-title"]), 
                           data)
        eq_(302, resp.status_code)
Ejemplo n.º 12
0
    def test_title_slug_collision_errors(self):
        """When an attempt is made to retitle an article and another with that
        title already exists, there should be form errors"""
        client = LocalizingClient()
        client.login(username='******', password='******')

        exist_title = "Existing doc"
        exist_slug = "existing-doc"

        # Create a new doc.
        data = new_document_data()
        data.update({"title": exist_title, "slug": exist_slug})
        resp = client.post(reverse('wiki.new_document'), data)
        eq_(302, resp.status_code)

        # Create another new doc.
        data = new_document_data()
        data.update({"title": 'Some new title', "slug": 'some-new-title'})
        response = client.post(reverse('wiki.new_document'), data)
        eq_(302, resp.status_code)

        # Now, post an update with duplicate slug and title
        data.update({'form': 'rev', 'title': exist_title, 'slug': exist_slug})
        resp = client.post(
            reverse('wiki.edit_document', args=['some-new-title']), data)
        eq_(200, resp.status_code)
        p = pq(resp.content)

        ok_(p.find('.errorlist').length > 0)
        ok_(p.find('.errorlist a[href="#id_title"]').length > 0)
        ok_(p.find('.errorlist a[href="#id_slug"]').length > 0)
Ejemplo n.º 13
0
    def test_invalid_slug(self):
        """Slugs cannot contain "$", but can contain "/"."""
        client = LocalizingClient()
        client.login(username='******', password='******')
        data = new_document_data()

        data['title'] = 'valid slug'
        data['slug'] = 'valid'
        response = client.post(reverse('wiki.new_document'), data)
        self.assertRedirects(response,
                             reverse('wiki.document', args=[data['slug']]))

        # Slashes should be fine
        data['title'] = 'valid with slash'
        data['slug'] = 'va/lid'
        response = client.post(reverse('wiki.new_document'), data)
        self.assertRedirects(response,
                             reverse('wiki.document', args=[data['slug']]))

        # Dollar sign is reserved for verbs
        data['title'] = 'invalid with dollars'
        data['slug'] = 'inva$lid'
        response = client.post(reverse('wiki.new_document'), data)
        self.assertContains(response, 'The slug provided is not valid.')

        # Question mark is reserved for query params
        data['title'] = 'invalid with questions'
        data['slug'] = 'inva?lid'
        response = client.post(reverse('wiki.new_document'), data)
        self.assertContains(response, 'The slug provided is not valid.')
Ejemplo n.º 14
0
    def test_raw_section_source(self):
        """The raw source for a document section can be requested"""
        client = LocalizingClient()
        client.login(username='******', password='******')
        d, r = doc_rev("""
            <h1 id="s1">Head 1</h1>
            <p>test</p>
            <p>test</p>

            <h1 id="s2">Head 2</h1>
            <p>test</p>
            <p>test</p>

            <h1 id="s3">Head 3</h1>
            <p>test</p>
            <p>test</p>
        """)
        expected = """
            <h1 id="s2">Head 2</h1>
            <p>test</p>
            <p>test</p>
        """
        response = client.get('%s?section=s2&raw=true' %
                              reverse('wiki.document', args=[d.slug]))
        eq_(normalize_html(expected), normalize_html(response.content))
Ejemplo n.º 15
0
    def test_kumawiki_waffle_flag(self):

        # Turn off the new wiki for everyone
        self.kumawiki_flag.everyone = False
        self.kumawiki_flag.save()
        
        client = LocalizingClient()

        resp = client.get(reverse('wiki.all_documents'))
        eq_(404, resp.status_code)
        
        resp = client.get(reverse('docs'))
        page = pq(resp.content)
        eq_(0, page.find('#kumawiki_preview').length)

        client.login(username='******', password='******')

        # Turn on the wiki for just superusers, ignore everyone else
        self.kumawiki_flag.superusers = True
        self.kumawiki_flag.everyone = None
        self.kumawiki_flag.save()

        resp = client.get(reverse('wiki.all_documents'))
        eq_(200, resp.status_code)
        
        resp = client.get(reverse('docs'))
        page = pq(resp.content)
        eq_(1, page.find('#kumawiki_preview').length)
Ejemplo n.º 16
0
class UploadImageTestCase(TestCase):
    fixtures = ['users.json', 'questions.json']

    def setUp(self):
        super(UploadImageTestCase, self).setUp()
        self.client = LocalizingClient()
        self.client.login(username='******', password='******')

    def tearDown(self):
        ImageAttachment.objects.all().delete()
        super(UploadImageTestCase, self).tearDown()

    def test_model_invalid(self):
        """Specifying an invalid model returns 400."""
        r = post(self.client, 'upload.up_image_async', {'image': ''},
                 args=['invalid.model', 123])

        eq_(400, r.status_code)
        json_r = json.loads(r.content)
        eq_('error', json_r['status'])
        eq_('Model does not exist.', json_r['message'])

    def test_object_notexist(self):
        """Upload nothing returns 404 error and html content."""
        r = post(self.client, 'upload.up_image_async', {'image': ''},
                 args=['questions.Question', 123])

        eq_(404, r.status_code)
        json_r = json.loads(r.content)
        eq_('error', json_r['status'])
        eq_('Object does not exist.', json_r['message'])

    def test_empty_image(self):
        """Upload nothing returns 400 error and json content."""
        r = post(self.client, 'upload.up_image_async', {'image': ''},
                 args=['questions.Question', 1])

        eq_(400, r.status_code)
        json_r = json.loads(r.content)
        eq_('error', json_r['status'])
        eq_('Invalid or no image received.', json_r['message'])

    def test_basic(self):
        """Uploading an image works."""
        # TODO: posting a valid image through the test client uploads it
        raise SkipTest

    def test_invalid_image(self):
        """Make sure invalid files are not accepted as images."""
        f = open('apps/upload/__init__.py', 'rb')
        r = post(self.client, 'upload.up_image_async', {'image': f},
                 args=['questions.Question', 1])
        f.close()

        eq_(400, r.status_code)
        json_r = json.loads(r.content)
        eq_('error', json_r['status'])
        eq_('Invalid or no image received.', json_r['message'])
Ejemplo n.º 17
0
class GalleryUploadTestCase(TestCase):
    fixtures = ['users.json']

    def setUp(self):
        super(GalleryUploadTestCase, self).setUp()
        self.client = LocalizingClient()
        self.client.login(username='******', password='******')
        self.u = User.objects.get(username='******')

    def tearDown(self):
        Image.objects.all().delete()
        Video.objects.all().delete()
        super(GalleryUploadTestCase, self).tearDown()

    def test_image_draft_shows(self):
        """The image draft is loaded for this user."""
        image(title=get_draft_title(self.u), creator=self.u)
        response = get(self.client, 'gallery.gallery', args=['image'])
        eq_(200, response.status_code)
        doc = pq(response.content)
        assert doc('.image-preview img').attr('src').endswith('098f6b.jpg')
        eq_(1, doc('.image-preview img').length)

    def test_video_draft_shows(self):
        """The video draft is loaded for this user."""
        video(title=get_draft_title(self.u), creator=self.u)
        response = get(self.client, 'gallery.gallery', args=['image'])
        eq_(200, response.status_code)
        doc = pq(response.content)
        # Preview for all 3 video formats: flv, ogv, webm
        eq_(3, doc('ul li.video-preview').length)

    def test_image_draft_post(self):
        """Posting to the page saves the field values for the image draft."""
        image(title=get_draft_title(self.u), creator=self.u)
        response = post(self.client,
                        'gallery.gallery', {
                            'description': '??',
                            'title': 'test'
                        },
                        args=['image'])
        eq_(200, response.status_code)
        doc = pq(response.content)
        # Preview for all 3 video formats: flv, ogv, webm
        eq_('??', doc('#gallery-upload-modal textarea').html())
        eq_('test', doc('#gallery-upload-modal input[name="title"]').val())

    def test_video_draft_post(self):
        """Posting to the page saves the field values for the video draft."""
        video(title=get_draft_title(self.u), creator=self.u)
        response = post(self.client,
                        'gallery.gallery', {'title': 'zTestz'},
                        args=['image'])
        eq_(200, response.status_code)
        doc = pq(response.content)
        # Preview for all 3 video formats: flv, ogv, webm
        eq_('zTestz', doc('#gallery-upload-modal input[name="title"]').val())
Ejemplo n.º 18
0
 def test_retitling_ignored_for_iframe(self):
     """When the title of an article is edited in an iframe, the change is
     ignored."""
     client = LocalizingClient()
     client.login(username='******', password='******')
     new_title = 'Some New Title'
     d, r = doc_rev()
     old_title = d.title
     data = new_document_data()
     data.update({'title': new_title, 'slug': d.slug, 'form': 'rev'})
     client.post(
         '%s?iframe=1' % reverse('wiki.edit_document', args=[d.slug]), data)
     eq_(old_title, Document.uncached.get(slug=d.slug).title)
     assert "REDIRECT" not in Document.uncached.get(title=old_title).html
Ejemplo n.º 19
0
class GalleryUploadTestCase(TestCase):
    fixtures = ["users.json"]

    def setUp(self):
        super(GalleryUploadTestCase, self).setUp()
        self.client = LocalizingClient()
        self.client.login(username="******", password="******")
        self.u = User.objects.get(username="******")

    def tearDown(self):
        Image.objects.all().delete()
        Video.objects.all().delete()
        super(GalleryUploadTestCase, self).tearDown()

    def test_image_draft_shows(self):
        """The image draft is loaded for this user."""
        image(title=get_draft_title(self.u), creator=self.u)
        response = get(self.client, "gallery.gallery", args=["image"])
        eq_(200, response.status_code)
        doc = pq(response.content)
        assert doc(".image-preview img").attr("src").endswith("098f6b.jpg")
        eq_(1, doc(".image-preview img").length)

    def test_video_draft_shows(self):
        """The video draft is loaded for this user."""
        video(title=get_draft_title(self.u), creator=self.u)
        response = get(self.client, "gallery.gallery", args=["image"])
        eq_(200, response.status_code)
        doc = pq(response.content)
        # Preview for all 3 video formats: flv, ogv, webm
        eq_(3, doc("ul li.video-preview").length)

    def test_image_draft_post(self):
        """Posting to the page saves the field values for the image draft."""
        image(title=get_draft_title(self.u), creator=self.u)
        response = post(self.client, "gallery.gallery", {"description": "??", "title": "test"}, args=["image"])
        eq_(200, response.status_code)
        doc = pq(response.content)
        # Preview for all 3 video formats: flv, ogv, webm
        eq_("??", doc("#gallery-upload-modal textarea").html())
        eq_("test", doc('#gallery-upload-modal input[name="title"]').val())

    def test_video_draft_post(self):
        """Posting to the page saves the field values for the video draft."""
        video(title=get_draft_title(self.u), creator=self.u)
        response = post(self.client, "gallery.gallery", {"title": "zTestz"}, args=["image"])
        eq_(200, response.status_code)
        doc = pq(response.content)
        # Preview for all 3 video formats: flv, ogv, webm
        eq_("zTestz", doc('#gallery-upload-modal input[name="title"]').val())
Ejemplo n.º 20
0
    def test_invalid_slug(self):
        """Slugs cannot contain /."""
        client = LocalizingClient()
        client.login(username='******', password='******')
        data = new_document_data()
        data['slug'] = 'inva/lid'
        response = client.post(reverse('wiki.new_document'), data)
        self.assertContains(response, 'The slug provided is not valid.')

        data['slug'] = 'valid'
        response = client.post(reverse('wiki.new_document'), data)
        self.assertRedirects(response, reverse('wiki.document_revisions',
                                               args=[data['slug']],
                                               locale='en-US'))
Ejemplo n.º 21
0
 def test_changing_products(self):
     """Changing products works as expected."""
     client = LocalizingClient()
     client.login(username='******', password='******')
     d, r = doc_rev()
     data = new_document_data()
     data.update({'products': ['desktop', 'sync'],
                  'form': 'doc'})
     client.post(reverse('wiki.edit_document', args=[d.slug]), data)
     tags_eq(d, ['desktop', 'sync'])
     data.update({'products': ['mobile'],
                  'form': 'doc'})
     client.post(reverse('wiki.edit_document', args=[data['slug']]), data)
     tags_eq(d, ['mobile'])
Ejemplo n.º 22
0
 def test_retitling(self):
     """When the title of an article is edited, a redirect is made."""
     # Not testing slug changes separately; the model tests cover those plus
     # slug+title changes. If title changes work in the view, the rest
     # should also.
     client = LocalizingClient()
     client.login(username='******', password='******')
     new_title = 'Some New Title'
     d, r = doc_rev()
     old_title = d.title
     data = new_document_data()
     data.update({'title': new_title, 'slug': d.slug, 'form': 'rev'})
     client.post(reverse('wiki.edit_document', args=[d.slug]), data)
     eq_(new_title, Document.uncached.get(slug=d.slug).title)
     assert "REDIRECT" in Document.uncached.get(title=old_title).html
Ejemplo n.º 23
0
 def test_retitling_ignored_for_iframe(self):
     """When the title of an article is edited in an iframe, the change is
     ignored."""
     client = LocalizingClient()
     client.login(username='******', password='******')
     new_title = 'Some New Title'
     d, r = doc_rev()
     old_title = d.title
     data = new_document_data()
     data.update({'title': new_title,
                  'slug': d.slug,
                  'form': 'rev'})
     client.post('%s?iframe=1' % reverse('wiki.edit_document', args=[d.slug]), data)
     eq_(old_title, Document.uncached.get(slug=d.slug).title)
     assert "REDIRECT" not in Document.uncached.get(title=old_title).html
Ejemplo n.º 24
0
    def test_raw_section_edit(self):
        client = LocalizingClient()
        client.login(username='******', password='******')
        d, r = doc_rev("""
            <h1 id="s1">Head 1</h1>
            <p>test</p>
            <p>test</p>

            <h1 id="s2">Head 2</h1>
            <p>test</p>
            <p>test</p>

            <h1 id="s3">Head 3</h1>
            <p>test</p>
            <p>test</p>
        """)
        replace = """
            <h1 id="s2">Replace</h1>
            <p>replace</p>
        """
        expected = """
            <h1 id="s2">Replace</h1>
            <p>replace</p>
        """
        response = client.post('%s?section=s2&raw=true' %
                               reverse('wiki.edit_document', args=[d.slug]),
                               {"form": "rev",
                                "content": replace},
                               follow=True)
        eq_(normalize_html(expected), 
            normalize_html(response.content))

        expected = """
            <h1 id="s1">Head 1</h1>
            <p>test</p>
            <p>test</p>

            <h1 id="s2">Replace</h1>
            <p>replace</p>

            <h1 id="s3">Head 3</h1>
            <p>test</p>
            <p>test</p>
        """
        response = client.get('%s?raw=true' %
                               reverse('wiki.document', args=[d.slug]))
        eq_(normalize_html(expected), 
            normalize_html(response.content))
Ejemplo n.º 25
0
    def test_raw_section_edit(self):
        client = LocalizingClient()
        client.login(username='******', password='******')
        d, r = doc_rev("""
            <h1 id="s1">Head 1</h1>
            <p>test</p>
            <p>test</p>

            <h1 id="s2">Head 2</h1>
            <p>test</p>
            <p>test</p>

            <h1 id="s3">Head 3</h1>
            <p>test</p>
            <p>test</p>
        """)
        replace = """
            <h1 id="s2">Replace</h1>
            <p>replace</p>
        """
        expected = """
            <h1 id="s2">Replace</h1>
            <p>replace</p>
        """
        response = client.post('%s?section=s2&raw=true' %
                               reverse('wiki.edit_document', args=[d.slug]), {
                                   "form": "rev",
                                   "content": replace
                               },
                               follow=True)
        eq_(normalize_html(expected), normalize_html(response.content))

        expected = """
            <h1 id="s1">Head 1</h1>
            <p>test</p>
            <p>test</p>

            <h1 id="s2">Replace</h1>
            <p>replace</p>

            <h1 id="s3">Head 3</h1>
            <p>test</p>
            <p>test</p>
        """
        response = client.get('%s?raw=true' %
                              reverse('wiki.document', args=[d.slug]))
        eq_(normalize_html(expected), normalize_html(response.content))
Ejemplo n.º 26
0
    def test_ban_middleware(self):
        """Ban middleware functions correctly."""
        client = LocalizingClient()
        client.login(username='******', password='******')

        resp = client.get('/')
        self.assertTemplateNotUsed(resp, 'users/user_banned.html')

        admin = User.objects.get(username='******')
        testuser = User.objects.get(username='******')
        ban = UserBan(user=testuser, by=admin,
                      reason='Banned by unit test.',
                      is_active=True)
        ban.save()

        resp = client.get('/')
        self.assertTemplateUsed(resp, 'users/user_banned.html')
Ejemplo n.º 27
0
    def test_invalid_slug(self, get_current):
        """Slugs cannot contain /."""
        get_current.return_value.domain = 'testserver'
        client = LocalizingClient()
        client.login(username='******', password='******')
        data = new_document_data()
        data['slug'] = 'inva/lid'
        response = client.post(reverse('wiki.new_document'), data)
        self.assertContains(response, 'The slug provided is not valid.')

        data['slug'] = 'valid'
        response = client.post(reverse('wiki.new_document'), data)
        self.assertRedirects(
            response,
            reverse('wiki.document_revisions',
                    args=[data['slug']],
                    locale='en-US'))
Ejemplo n.º 28
0
 def test_retitling(self):
     """When the title of an article is edited, a redirect is made."""
     # Not testing slug changes separately; the model tests cover those plus
     # slug+title changes. If title changes work in the view, the rest
     # should also.
     client = LocalizingClient()
     client.login(username='******', password='******')
     new_title = 'Some New Title'
     d, r = doc_rev()
     old_title = d.title
     data = new_document_data()
     data.update({'title': new_title,
                  'slug': d.slug,
                  'form': 'doc'})
     client.post(reverse('wiki.edit_document', args=[d.slug]), data)
     eq_(new_title, Document.uncached.get(slug=d.slug).title)
     assert Document.uncached.get(title=old_title).redirect_url()
Ejemplo n.º 29
0
 def test_changing_metadata(self):
     """Changing metadata works as expected."""
     client = LocalizingClient()
     client.login(username='******', password='******')
     d, r = doc_rev()
     data = new_document_data()
     data.update({'firefox_versions': [1, 2, 3],
                  'operating_systems': [1, 3],
                  'form': 'doc'})
     client.post(reverse('wiki.edit_document', args=[d.slug]), data)
     eq_(3, d.firefox_versions.count())
     eq_(2, d.operating_systems.count())
     data.update({'firefox_versions': [1, 2],
                  'operating_systems': [2],
                  'form': 'doc'})
     client.post(reverse('wiki.edit_document', args=[data['slug']]), data)
     eq_(2, d.firefox_versions.count())
     eq_(1, d.operating_systems.count())
Ejemplo n.º 30
0
    def test_ban_middleware(self):
        """Ban middleware functions correctly."""
        client = LocalizingClient()
        client.login(username='******', password='******')

        resp = client.get('/')
        self.assertTemplateNotUsed(resp, 'users/user_banned.html')

        admin = User.objects.get(username='******')
        testuser = User.objects.get(username='******')
        ban = UserBan(user=testuser,
                      by=admin,
                      reason='Banned by unit test.',
                      is_active=True)
        ban.save()

        resp = client.get('/')
        self.assertTemplateUsed(resp, 'users/user_banned.html')
Ejemplo n.º 31
0
    def test_ban_permission(self):
        """The ban permission controls access to the ban view."""
        client = LocalizingClient()
        admin = User.objects.get(username="******")
        testuser = User.objects.get(username="******")

        # testuser doesn't have ban permission, can't ban.
        client.login(username="******", password="******")
        ban_url = reverse("users.ban_user", kwargs={"user_id": admin.id})
        resp = client.get(ban_url)
        eq_(302, resp.status_code)
        ok_(settings.LOGIN_URL in resp["Location"])
        client.logout()

        # admin has ban permission, can ban.
        client.login(username="******", password="******")
        ban_url = reverse("users.ban_user", kwargs={"user_id": testuser.id})
        resp = client.get(ban_url)
        eq_(200, resp.status_code)
Ejemplo n.º 32
0
    def test_ban_view(self):
        testuser = User.objects.get(username="******")
        admin = User.objects.get(username="******")

        client = LocalizingClient()
        client.login(username="******", password="******")

        data = {"reason": "Banned by unit test."}
        ban_url = reverse("users.ban_user", kwargs={"user_id": testuser.id})

        resp = client.post(ban_url, data)
        eq_(302, resp.status_code)
        ok_(testuser.get_absolute_url() in resp["Location"])

        testuser_banned = User.objects.get(username="******")
        ok_(not testuser_banned.is_active)

        bans = UserBan.objects.filter(user=testuser, by=admin, reason="Banned by unit test.")
        ok_(bans.count())
Ejemplo n.º 33
0
    def test_ban_permission(self):
        """The ban permission controls access to the ban view."""
        client = LocalizingClient()
        admin = User.objects.get(username='******')
        testuser = User.objects.get(username='******')

        # testuser doesn't have ban permission, can't ban.
        client.login(username='******', password='******')
        ban_url = reverse('users.ban_user', kwargs={'user_id': admin.id})
        resp = client.get(ban_url)
        eq_(302, resp.status_code)
        ok_(settings.LOGIN_URL in resp['Location'])
        client.logout()

        # admin has ban permission, can ban.
        client.login(username='******', password='******')
        ban_url = reverse('users.ban_user', kwargs={'user_id': testuser.id})
        resp = client.get(ban_url)
        eq_(200, resp.status_code)
Ejemplo n.º 34
0
    def test_edit_midair_collision(self):
        client = LocalizingClient()
        client.login(username='******', password='******')

        # Post a new document.
        data = new_document_data()
        resp = client.post(reverse('wiki.new_document'), data)
        doc = Document.objects.get(slug=data['slug'])

        # Edit #1 starts...
        resp = client.get(reverse('wiki.edit_document', args=[doc.slug]))
        page = pq(resp.content)
        rev_id1 = page.find('input[name="current_rev"]').attr('value')

        # Edit #2 starts...
        resp = client.get(reverse('wiki.edit_document', args=[doc.slug]))
        page = pq(resp.content)
        rev_id2 = page.find('input[name="current_rev"]').attr('value')

        # Edit #2 submits successfully
        data.update({
            'form': 'rev',
            'content': 'This edit got there first',
            'current_rev': rev_id2
        })
        resp = client.post(reverse('wiki.edit_document', args=[doc.slug]),
                           data)
        eq_(302, resp.status_code)

        # Edit #1 submits, but receives a mid-aired notification
        data.update({
            'form': 'rev',
            'content': 'This edit gets mid-aired',
            'current_rev': rev_id1
        })
        resp = client.post(reverse('wiki.edit_document', args=[doc.slug]),
                           data)
        eq_(200, resp.status_code)

        ok_(
            unicode(MIDAIR_COLLISION).encode('utf-8') in resp.content,
            "Midair collision message should appear")
Ejemplo n.º 35
0
    def test_invalid_reserved_term_slug(self):
        """Slugs should not collide with reserved URL patterns"""
        client = LocalizingClient()
        client.login(username='******', password='******')
        data = new_document_data()

        # TODO: This is info derived from urls.py, but unsure how to DRY it
        reserved_slugs = ('ckeditor_config.js', 'watch-ready-for-review',
                          'unwatch-ready-for-review', 'watch-approved',
                          'unwatch-approved', '.json', 'new', 'all',
                          'preview-wiki-content', 'category/10',
                          'needs-review/technical', 'needs-review/',
                          'feeds/atom/all/',
                          'feeds/atom/needs-review/technical',
                          'feeds/atom/needs-review/', 'tag/tasty-pie')

        for term in reserved_slugs:
            data['title'] = 'invalid with %s' % term
            data['slug'] = term
            response = client.post(reverse('wiki.new_document'), data)
            self.assertContains(response, 'The slug provided is not valid.')
Ejemplo n.º 36
0
    def test_ban_view(self):
        testuser = User.objects.get(username='******')
        admin = User.objects.get(username='******')

        client = LocalizingClient()
        client.login(username='******', password='******')

        data = {'reason': 'Banned by unit test.'}
        ban_url = reverse('users.ban_user', kwargs={'user_id': testuser.id})

        resp = client.post(ban_url, data)
        eq_(302, resp.status_code)
        ok_(testuser.get_absolute_url() in resp['Location'])

        testuser_banned = User.objects.get(username='******')
        ok_(not testuser_banned.is_active)

        bans = UserBan.objects.filter(user=testuser,
                                      by=admin,
                                      reason='Banned by unit test.')
        ok_(bans.count())
Ejemplo n.º 37
0
 def test_changing_metadata(self):
     """Changing metadata works as expected."""
     client = LocalizingClient()
     client.login(username='******', password='******')
     d, r = doc_rev()
     data = new_document_data()
     data.update({
         'firefox_versions': [1, 2, 3],
         'operating_systems': [1, 3],
         'form': 'doc'
     })
     client.post(reverse('wiki.edit_document', args=[d.slug]), data)
     eq_(3, d.firefox_versions.count())
     eq_(2, d.operating_systems.count())
     data.update({
         'firefox_versions': [1, 2],
         'operating_systems': [2],
         'form': 'doc'
     })
     client.post(reverse('wiki.edit_document', args=[data['slug']]), data)
     eq_(2, d.firefox_versions.count())
     eq_(1, d.operating_systems.count())
Ejemplo n.º 38
0
    def test_edit_midair_collision(self):
        client = LocalizingClient()
        client.login(username='******', password='******')

        # Post a new document.
        data = new_document_data()
        resp = client.post(reverse('wiki.new_document'), data)
        doc = Document.objects.get(slug=data['slug'])

        # Edit #1 starts...
        resp = client.get(reverse('wiki.edit_document', args=[doc.slug]))
        page = pq(resp.content)
        rev_id1 = page.find('input[name="current_rev"]').attr('value')

        # Edit #2 starts...
        resp = client.get(reverse('wiki.edit_document', args=[doc.slug]))
        page = pq(resp.content)
        rev_id2 = page.find('input[name="current_rev"]').attr('value')

        # Edit #2 submits successfully
        data.update({
            'form': 'rev',
            'content': 'This edit got there first',
            'current_rev': rev_id2
        })
        resp = client.post(reverse('wiki.edit_document', args=[doc.slug]), data)
        eq_(302, resp.status_code)

        # Edit #1 submits, but receives a mid-aired notification
        data.update({
            'form': 'rev',
            'content': 'This edit gets mid-aired',
            'current_rev': rev_id1
        })
        resp = client.post(reverse('wiki.edit_document', args=[doc.slug]), data)
        eq_(200, resp.status_code)

        ok_(unicode(MIDAIR_COLLISION).encode('utf-8') in resp.content,
            "Midair collision message should appear")
Ejemplo n.º 39
0
    def test_ban_view(self):
        testuser = User.objects.get(username='******')
        admin = User.objects.get(username='******')

        client = LocalizingClient()
        client.login(username='******', password='******')

        data = {'reason': 'Banned by unit test.'}
        ban_url = reverse('users.ban_user',
                          kwargs={'user_id': testuser.id})

        resp = client.post(ban_url, data)
        eq_(302, resp.status_code)
        ok_(testuser.get_absolute_url() in resp['Location'])

        testuser_banned = User.objects.get(username='******')
        ok_(not testuser_banned.is_active)

        bans = UserBan.objects.filter(user=testuser,
                                      by=admin,
                                      reason='Banned by unit test.')
        ok_(bans.count())
Ejemplo n.º 40
0
class ChangeEmailTestCase(TestCase):
    fixtures = ['users.json']

    def setUp(self):
        self.client = LocalizingClient()
        # Create some notifications
        EventWatch.objects.create(content_type_id=1, watch_id=2,
                                  email='user47963@nowhere')

    @mock.patch_object(Site.objects, 'get_current')
    def test_user_change_email(self, get_current):
        """Send email to change user's email and then change it."""
        get_current.return_value.domain = 'su.mo.com'

        self.client.login(username='******', password='******')
        # Attempt to change email.
        response = self.client.post(reverse('users.change_email'),
                                    {'email': '*****@*****.**'},
                                    follow=True)
        eq_(200, response.status_code)

        # Be notified to click a confirmation link.
        eq_(1, len(mail.outbox))
        assert mail.outbox[0].subject.find('Please confirm your') == 0
        ec = EmailChange.objects.all()[0]
        assert ec.activation_key in mail.outbox[0].body
        eq_('*****@*****.**', ec.email)

        # Visit confirmation link to change email.
        response = self.client.get(reverse('users.confirm_email',
                                           args=[ec.activation_key]))
        eq_(200, response.status_code)
        u = User.objects.get(username='******')
        eq_('*****@*****.**', u.email)

        # Notifications have been updated.
        # TODO: remove this after notifications model is updated.
        ew = EventWatch.objects.get()
        eq_('*****@*****.**', ew.email)
Ejemplo n.º 41
0
class UploadImageTestCase(TestCase):
    fixtures = ['users.json']

    def setUp(self):
        super(UploadImageTestCase, self).setUp()
        self.client = LocalizingClient()
        self.client.login(username='******', password='******')

    def tearDown(self):
        Image.objects.all().delete()
        super(UploadImageTestCase, self).tearDown()

    def test_empty_image(self):
        """Specifying an invalid model returns 400."""
        r = post(self.client, 'gallery.upload_async', {'file': ''},
                 args=['image'])

        eq_(400, r.status_code)
        json_r = json.loads(r.content)
        eq_('error', json_r['status'])
        eq_('Could not upload your image.', json_r['message'])
        eq_('You have not selected an image to upload.',
            json_r['errors']['file'][0])

    def test_upload_image(self):
        """Uploading an image works."""
        with open(TEST_IMG) as f:
            r = post(self.client, 'gallery.upload_async', {'file': f},
                     args=['image'])
        img = Image.objects.all()[0]

        eq_(1, Image.objects.count())
        eq_(200, r.status_code)
        json_r = json.loads(r.content)
        eq_('success', json_r['status'])
        file = json_r['file']
        eq_('test.jpg', file['name'])
        eq_(90, file['width'])
        eq_(120, file['height'])
        assert file['url'].endswith(img.get_absolute_url())
        eq_('pcraciunoiu', img.creator.username)
        eq_(150, img.file.width)
        eq_(200, img.file.height)
        eq_(get_draft_title(img.creator), img.title)
        eq_('Autosaved draft.', img.description)
        eq_('en-US', img.locale)

    def test_upload_unicode_image(self):
        """Uploading an unicode image works."""
        with open(u'apps/upload/tests/media/123ascii\u6709\u52b9.jpg') as f:
            r = post(self.client, 'gallery.upload_async', {'file': f},
                     args=['image'])

        eq_(1, Image.objects.count())
        eq_(200, r.status_code)
        json_r = json.loads(r.content)
        eq_('success', json_r['status'])

    def test_invalid_image(self):
        """Make sure invalid files are not accepted as images."""
        with open('apps/gallery/__init__.py', 'rb') as f:
            r = post(self.client, 'gallery.upload_async', {'file': f},
                     args=['image'])

        eq_(400, r.status_code)
        json_r = json.loads(r.content)
        eq_('error', json_r['status'])
        eq_('Could not upload your image.', json_r['message'])
        eq_('Upload a valid image. The file you uploaded was either not an '
            'image or a corrupted image.', json_r['errors']['file'][0])

    def test_invalid_image_extension(self):
        """Make sure invalid extensions are not accepted as images."""
        with open('apps/upload/tests/media/test_invalid.ext', 'rb') as f:
            r = post(self.client, 'gallery.upload_async', {'file': f},
                     args=['image'])

        eq_(400, r.status_code)
        json_r = json.loads(r.content)
        eq_('error', json_r['status'])
        eq_('Could not upload your image.', json_r['message'])
        eq_('Please upload an image with one of the following extensions: '
            'jpg, jpeg, png, gif.', json_r['errors']['__all__'][0])

    def test_invalid_thumbnail_extension(self):
        """Make sure invalid extensions are not accepted as thumbnails."""
        with open('apps/upload/tests/media/test_invalid.ext', 'rb') as f:
            r = post(self.client, 'gallery.upload_async', {'thumbnail': f},
                     args=['video'])

        eq_(400, r.status_code)
        json_r = json.loads(r.content)
        eq_('error', json_r['status'])
        eq_('Could not upload your video.', json_r['message'])
        eq_('Please upload an image with one of the following extensions: '
            'jpg, jpeg, png, gif.', json_r['errors']['__all__'][0])

    def test_upload_image_long_filename(self):
        """Uploading an image with a filename that's too long fails."""
        with open('apps/upload/tests/media/a_really_long_filename_worth_'
                  'more_than_250_characters__a_really_long_filename_worth_'
                  'more_than_250_characters__a_really_long_filename_worth_'
                  'more_than_250_characters__a_really_long_filename_worth_'
                  'more_than_250_characters__a_really_long_filename_yes_.jpg')\
            as f:
            r = post(self.client, 'gallery.upload_async', {'file': f},
                     args=['image'])

        eq_(400, r.status_code)
        json_r = json.loads(r.content)
        eq_('error', json_r['status'])
        eq_('Could not upload your image.', json_r['message'])
        eq_(forms.MSG_IMAGE_LONG % {'length': 251,
                                    'max': settings.MAX_FILENAME_LENGTH},
            json_r['errors']['file'][0])

    def test_upload_draft_image(self):
        """Uploading draft image works, sets locale too."""
        u = User.objects.get(username='******')
        img = image(creator=u, title=get_draft_title(u))
        # No thumbnail yet.
        eq_(None, img.thumbnail)

        r = post(self.client, 'gallery.upload',
                 {'locale': 'de', 'title': 'Hasta la vista',
                  'description': 'Auf wiedersehen!'},
                 args=['image'])

        eq_(200, r.status_code)
        img = Image.objects.all()[0]
        eq_('de', img.locale)
        eq_('Hasta la vista', img.title)
        eq_('Auf wiedersehen!', img.description)
        # Thumbnail generated after form is saved.
        eq_(90, img.thumbnail.width)

    def test_image_title_locale_unique_validation(self):
        """Posting an existing locale/title combination shows a validation
        error."""
        u = User.objects.get(username='******')
        image(creator=u, title=get_draft_title(u))
        post(self.client, 'gallery.upload',
             {'locale': 'de', 'title': 'Hasta la vista',
              'description': 'Auf wiedersehen!'}, args=['image'])
        image(creator=u, title=get_draft_title(u))
        r = post(self.client, 'gallery.upload',
                 {'locale': 'de', 'title': 'Hasta la vista',
                  'description': 'Auf wiedersehen!'},
                 args=['image'])
        eq_(200, r.status_code)
        doc = pq(r.content)
        msg = 'Image with this Locale and Title already exists.'
        assert doc('ul.errorlist li').text().startswith(msg)
Ejemplo n.º 42
0
class BrowserIDTestCase(TestCase):
    fixtures = ['test_users.json']

    def setUp(self):
        # Ensure @ssl_required goes unenforced.
        settings.DEBUG = True
        # Set up some easily-testable redirects.
        settings.LOGIN_REDIRECT_URL = 'SUCCESS'
        settings.LOGIN_REDIRECT_URL_FAILURE = 'FAILURE'
        # BrowserID will squawk if this isn't set
        settings.SITE_URL = 'http://testserver'
        self.client = LocalizingClient()

    def test_invalid_post(self):
        resp = self.client.post(
            reverse('users.browserid_verify', locale='en-US'))
        eq_(302, resp.status_code)
        ok_('FAILURE' in resp['Location'])

    @mock.patch('users.views._verify_browserid')
    def test_invalid_assertion(self, _verify_browserid):
        _verify_browserid.return_value = None

        resp = self.client.post(
            reverse('users.browserid_verify', locale='en-US'),
            {'assertion': 'bad data'})
        eq_(302, resp.status_code)
        ok_('FAILURE' in resp['Location'])

    @mock_get_deki_user_by_email
    @mock_put_mindtouch_user
    @mock_mindtouch_login
    @mock.patch('users.views._verify_browserid')
    def test_valid_assertion_with_django_user(self, _verify_browserid):
        _verify_browserid.return_value = {'email': '*****@*****.**'}

        # Posting the fake assertion to browserid_verify should work, with the
        # actual verification method mocked out.
        resp = self.client.post(
            reverse('users.browserid_verify', locale='en-US'),
            {'assertion': 'PRETENDTHISISVALID'})
        eq_(302, resp.status_code)
        ok_('SUCCESS' in resp['Location'])

        # The session should look logged in, now.
        ok_('_auth_user_id' in self.client.session.keys())
        eq_('django_browserid.auth.BrowserIDBackend',
            self.client.session.get('_auth_user_backend', ''))

    @mock_get_deki_user_by_email
    @mock_put_mindtouch_user
    @mock_mindtouch_login
    @mock.patch('users.views._verify_browserid')
    def test_explain_popup(self, _verify_browserid):
        _verify_browserid.return_value = {'email': '*****@*****.**'}
        resp = self.client.get(reverse('home', locale='en-US'))

        # Posting the fake assertion to browserid_verify should work, with the
        # actual verification method mocked out.
        resp = self.client.post(
            reverse('users.browserid_verify', locale='en-US'),
            {'assertion': 'PRETENDTHISISVALID'})
        eq_('1', resp.cookies.get('browserid_explained').value)

        resp = self.client.get(reverse('users.logout'), locale='en-US')

        # even after logout, cookie should prevent the toggle
        resp = self.client.get(reverse('home', locale='en-US'))
        eq_('1', self.client.cookies.get('browserid_explained').value)

    @mock_get_deki_user_by_email
    @mock_put_mindtouch_user
    @mock_mindtouch_login
    @mock.patch('users.views._verify_browserid')
    def test_valid_assertion_with_mindtouch_user(self, _verify_browserid):
        if not settings.DEKIWIKI_ENDPOINT:
            # Don't even bother with this test, if there's no MindTouch API
            raise SkipTest()

        mt_email = '*****@*****.**'
        _verify_browserid.return_value = {'email': mt_email}

        # Probably overkill but let's be sure we're testing the right thing.
        try:
            User.objects.get(email=mt_email)
            ok_(False, "The MindTouch user shouldn't exist in Django yet.")
        except User.DoesNotExist:
            pass

        if not getattr(settings, 'DEKIWIKI_MOCK', False):
            # HACK: Ensure that expected user details are in MindTouch when not
            # mocking the API
            user_xml = MINDTOUCH_USER_XML % dict(username="******",
                                                 email=mt_email,
                                                 fullname="None",
                                                 status="active",
                                                 language="",
                                                 timezone="-08:00",
                                                 role="Contributor")
            DekiUserBackend.put_mindtouch_user(deki_user_id='=testaccount',
                                               user_xml=user_xml)

        deki_user = DekiUserBackend.get_deki_user_by_email(mt_email)
        ok_(deki_user is not None, "The MindTouch user should exist")

        # Posting the fake assertion to browserid_verify should work, with the
        # actual verification method mocked out.
        resp = self.client.post(
            reverse('users.browserid_verify', locale='en-US'),
            {'assertion': 'PRETENDTHISISVALID'})
        eq_(302, resp.status_code)
        ok_('SUCCESS' in resp['Location'])

        # The session should look logged in, now.
        ok_('_auth_user_id' in self.client.session.keys())
        eq_('django_browserid.auth.BrowserIDBackend',
            self.client.session.get('_auth_user_backend', ''))

        # And, after all the above, there should be a Django user now.
        try:
            User.objects.get(email=mt_email)
        except User.DoesNotExist:
            ok_(False, "The MindTouch user should exist in Django now.")

    @attr('current')
    @mock.patch('dekicompat.backends.DekiUserBackend.get_deki_user_by_email')
    @mock.patch('users.views._verify_browserid')
    def test_valid_assertion_with_mt_disabled(self, _verify_browserid,
                                              mock_get_deki_user_by_email):
        """On valid browserid assertion, when Django user is not found, yet
        MindTouch API disabled, there should be no attempt to look the user up
        in MindTouch"""
        mt_email = '*****@*****.**'
        _verify_browserid.return_value = {'email': mt_email}

        # HACK: mock has an assert_called_with, but I want something like
        # never_called or call_count. Instead, I have this:
        trap = {'was_called': False}

        def my_get_deki_user_by_email(email):
            trap['was_called'] = True
            return False

        mock_get_deki_user_by_email.side_effect = my_get_deki_user_by_email

        _old = settings.DEKIWIKI_ENDPOINT
        settings.DEKIWIKI_ENDPOINT = False
        resp = self.client.post(
            reverse('users.browserid_verify', locale='en-US'),
            {'assertion': 'PRETENDTHISISVALID'})
        settings.DEKIWIKI_ENDPOINT = _old

        # This should end up being a redirect to register
        eq_(302, resp.status_code)
        ok_('browserid_register' in resp['Location'])

        ok_(not trap['was_called'])

    @mock_missing_get_deki_user_by_email
    @mock_missing_get_deki_user
    @mock_post_mindtouch_user
    @mock_put_mindtouch_user
    @mock_mindtouch_login
    @mock.patch('users.views._verify_browserid')
    def test_valid_assertion_with_new_account_creation(self,
                                                       _verify_browserid):
        new_username = '******'
        new_email = '*****@*****.**'
        _verify_browserid.return_value = {'email': new_email}

        try:
            user = User.objects.get(email=new_email)
            ok_(False, "User for email should not yet exist")
        except User.DoesNotExist:
            pass

        if not getattr(settings, 'DEKIWIKI_MOCK', False):
            # HACK: When not mocking the MindTouch API, ensure that there's no
            # leftover user with the same name & email as what we want to
            # register
            import random
            rand_num = random.randint(0, 1000000)
            user_xml = MINDTOUCH_USER_XML % dict(username="******" %
                                                 (new_username, rand_num),
                                                 email="%s_%s" %
                                                 (rand_num, new_email),
                                                 fullname="",
                                                 status="inactive",
                                                 language="",
                                                 timezone="-08:00",
                                                 role="Contributor")
            DekiUserBackend.put_mindtouch_user(deki_user_id='=%s' %
                                               new_username,
                                               user_xml=user_xml)

        # Sign in with a verified email, but with no existing account
        resp = self.client.post(
            reverse('users.browserid_verify', locale='en-US'),
            {'assertion': 'PRETENDTHISISVALID'})
        eq_(302, resp.status_code)

        # This should be a redirect to the BrowserID registration page.
        redir_url = resp['Location']
        reg_url = reverse('users.browserid_register', locale='en-US')
        ok_(reg_url in redir_url)

        # And, as part of the redirect, the verified email address should be in
        # our session now.
        ok_(SESSION_VERIFIED_EMAIL in self.client.session.keys())
        verified_email = self.client.session[SESSION_VERIFIED_EMAIL]
        eq_(new_email, verified_email)

        # Grab the redirect, assert that there's a create_user form present
        resp = self.client.get(redir_url)
        page = pq(resp.content)
        form = page.find('form#create_user')
        eq_(1, form.length)

        # There should be no error lists on first load
        eq_(0, page.find('.errorlist').length)

        # Submit the create_user form, with a chosen username
        resp = self.client.post(redir_url, {
            'username': '******',
            'action': 'register'
        })

        # The submission should result in a redirect to the session's redirect
        # value
        eq_(302, resp.status_code)
        redir_url = resp['Location']
        ok_('SUCCESS' in redir_url)

        # The session should look logged in, now.
        ok_('_auth_user_id' in self.client.session.keys())
        eq_('django_browserid.auth.BrowserIDBackend',
            self.client.session.get('_auth_user_backend', ''))

        if settings.DEKIWIKI_ENDPOINT:
            ok_(self.client.cookies.get('authtoken'), 'Should have set '
                'authtoken cookie for '
                'MindTouch')

        # Ensure that the user was created, and with the submitted username and
        # verified email address
        try:
            user = User.objects.get(email=new_email)
            eq_(new_username, user.username)
            eq_(new_email, user.email)
        except User.DoesNotExist:
            ok_(False, "New user should have been created")

    @mock_missing_get_deki_user_by_email
    @mock_post_mindtouch_user
    @mock_put_mindtouch_user
    @mock_mindtouch_login
    @mock_get_deki_user
    @mock.patch('users.views._verify_browserid')
    def test_valid_assertion_with_existing_account_login(
            self, _verify_browserid):
        """ Removed the existing user form: we don't auth the password with
        MindTouch anymore """
        new_email = '*****@*****.**'
        _verify_browserid.return_value = {'email': new_email}

        try:
            User.objects.get(email=new_email)
            ok_(False, "User for email should not yet exist")
        except User.DoesNotExist:
            pass

        # Sign in with a verified email, but with no existing account
        resp = self.client.post(
            reverse('users.browserid_verify', locale='en-US'),
            {'assertion': 'PRETENDTHISISVALID'})
        eq_(302, resp.status_code)

        # This should be a redirect to the BrowserID registration page.
        redir_url = resp['Location']
        reg_url = reverse('users.browserid_register', locale='en-US')
        ok_(reg_url in redir_url)

        # And, as part of the redirect, the verified email address should be in
        # our session now.
        ok_(SESSION_VERIFIED_EMAIL in self.client.session.keys())
        verified_email = self.client.session[SESSION_VERIFIED_EMAIL]
        eq_(new_email, verified_email)

        # Grab the redirect, assert that there's a create_user form present
        resp = self.client.get(redir_url)
        page = pq(resp.content)
        form = page.find('form#existing_user')
        eq_(0, form.length)

    @mock.patch('dekicompat.backends.DekiUserBackend.mindtouch_login')
    @mock.patch('users.views._verify_browserid')
    def test_mindtouch_disabled_redirect_login(self, _verify_browserid,
                                               mock_mindtouch_login):
        """When DEKIWIKI_ENDPOINT unavailable, skip MindTouch auth."""
        _verify_browserid.return_value = {'email': '*****@*****.**'}

        # HACK: mock has an assert_called_with, but I want something like
        # never_called or call_count. Instead, I have this:
        trap = {'was_called': False}

        def my_mindtouch_login(username, password, force=False):
            trap['was_called'] = True
            return False

        mock_mindtouch_login.side_effect = my_mindtouch_login

        _old = settings.DEKIWIKI_ENDPOINT
        settings.DEKIWIKI_ENDPOINT = False
        resp = self.client.post(
            reverse('users.browserid_verify', locale='en-US'),
            {'assertion': 'PRETENDTHISISVALID'})
        settings.DEKIWIKI_ENDPOINT = _old

        eq_(302, resp.status_code)
        ok_('SUCCESS' in resp['Location'])

        # The session should look logged in, now.
        ok_('_auth_user_id' in self.client.session.keys())
        eq_('django_browserid.auth.BrowserIDBackend',
            self.client.session.get('_auth_user_backend', ''))

        ok_(not trap['was_called'])

    @mock_get_deki_user_by_email
    @mock_put_mindtouch_user
    @mock_mindtouch_login
    @mock.patch('users.views._verify_browserid')
    def test_valid_assertion_changing_email(self, _verify_browserid):
        # just need to be authenticated, not necessarily BrowserID
        self.client.login(username='******', password='******')

        _verify_browserid.return_value = {'email': '*****@*****.**'}

        resp = self.client.post(
            reverse('users.browserid_change_email', locale='en-US'),
            {'assertion': 'PRETENDTHISISVALID'})
        eq_(302, resp.status_code)
        ok_('profiles/testuser/edit' in resp['Location'])

        resp = self.client.get(
            reverse('devmo_profile_edit', locale='en-US', args=[
                'testuser',
            ]))
        eq_(200, resp.status_code)
        doc = pq(resp.content)
        ok_('*****@*****.**' in doc.find('li#field_email').text())

    @mock_get_deki_user_by_email
    @mock_put_mindtouch_user
    @mock_mindtouch_login
    @mock.patch('users.views._verify_browserid')
    def test_valid_assertion_doesnt_steal_email(self, _verify_browserid):
        # just need to be authenticated, not necessarily BrowserID
        self.client.login(username='******', password='******')

        _verify_browserid.return_value = {'email': '*****@*****.**'}

        # doesn't change email if the new email already belongs to another user
        resp = self.client.post(
            reverse('users.browserid_change_email', locale='en-US'),
            {'assertion': 'PRETENDTHISISVALID'})
        eq_(302, resp.status_code)
        ok_('change_email' in resp['Location'])

        resp = self.client.get(
            reverse('devmo_profile_edit', locale='en-US', args=[
                'testuser',
            ]))
        eq_(200, resp.status_code)
        doc = pq(resp.content)
        ok_('*****@*****.**' in doc.find('li#field_email').text())
Ejemplo n.º 43
0
class DeleteEditImageTestCase(TestCase):
    fixtures = ['users.json']

    def setUp(self):
        super(DeleteEditImageTestCase, self).setUp()
        self.client = LocalizingClient()
        self.client.login(username='******', password='******')

    def tearDown(self):
        Image.objects.all().delete()
        super(DeleteEditImageTestCase, self).tearDown()

    def test_delete_image(self):
        """Deleting an uploaded image works."""
        # Upload the image first
        im = image()
        r = post(self.client, 'gallery.delete_media', args=['image', im.id])

        eq_(200, r.status_code)
        eq_(0, Image.objects.count())

    def test_delete_image_without_permissions(self):
        """Can't delete an image I didn't create."""
        self.client.login(username='******', password='******')
        img = image()
        r = post(self.client, 'gallery.delete_media', args=['image', img.id])

        eq_(403, r.status_code)
        eq_(1, Image.objects.count())

    def test_delete_own_image(self):
        """Can delete an image I created."""
        self.client.login(username='******', password='******')
        u = User.objects.get(username='******')
        img = image(creator=u)
        r = post(self.client, 'gallery.delete_media', args=['image', img.id])

        eq_(200, r.status_code)
        eq_(0, Image.objects.count())

    def test_edit_own_image(self):
        """Can edit an image I created."""
        u = User.objects.get(username='******')
        img = image(creator=u)
        r = post(self.client, 'gallery.edit_media', {'description': 'arrr'},
                 args=['image', img.id])

        eq_(200, r.status_code)
        eq_('arrr', Image.uncached.get().description)

    def test_edit_image_without_permissions(self):
        """Can't edit an image I didn't create."""
        u = User.objects.get(username='******')
        img = image(creator=u)
        r = post(self.client, 'gallery.edit_media', {'description': 'arrr'},
                 args=['image', img.id])

        eq_(403, r.status_code)

    def test_edit_image_with_permissions(self):
        """Editing image sets the updated_by field."""
        self.client.login(username='******', password='******')
        img = image()
        r = post(self.client, 'gallery.edit_media', {'description': 'arrr'},
                 args=['image', img.id])

        eq_(200, r.status_code)
        eq_('admin', Image.objects.get().updated_by.username)
Ejemplo n.º 44
0
class UploadVideoTestCase(TestCase):
    fixtures = ['users.json']

    def setUp(self):
        super(UploadVideoTestCase, self).setUp()
        self.client = LocalizingClient()
        self.client.login(username='******', password='******')

    def tearDown(self):
        Video.objects.all().delete()
        super(UploadVideoTestCase, self).tearDown()

    def _upload_extension(self, ext):
        with open(TEST_VID[ext]) as f:
            r = post(self.client, 'gallery.upload_async', {ext: f},
                     args=['video'])
        return r

    def test_upload_video(self):
        """Uploading a video works."""
        r = self._upload_extension('ogv')
        vid = Video.objects.all()[0]

        eq_(1, Video.objects.count())
        eq_(200, r.status_code)
        json_r = json.loads(r.content)
        eq_('success', json_r['status'])
        file = json_r['file']
        eq_('test.ogv', file['name'])
        eq_(32, file['width'])
        eq_(32, file['height'])
        assert file['url'].endswith(vid.get_absolute_url())
        eq_('pcraciunoiu', vid.creator.username)
        eq_(get_draft_title(vid.creator), vid.title)
        eq_('Autosaved draft.', vid.description)
        eq_('en-US', vid.locale)
        with open(TEST_VID['ogv']) as f:
            eq_(f.read(), vid.ogv.read())

    def test_delete_video_ogv(self):
        """Deleting an uploaded video works."""
        # Upload the video first
        self._upload_extension('ogv')
        vid = Video.objects.all()[0]
        r = post(self.client, 'gallery.delete_media',
                 args=['video', vid.id])

        eq_(200, r.status_code)
        eq_(0, Video.objects.count())

    def test_upload_video_ogv_flv(self):
        """Upload the same video, in ogv and flv formats"""
        ogv = open(TEST_VID['ogv'])
        flv = open(TEST_VID['flv'])
        post(self.client, 'gallery.upload_async', {'ogv': ogv, 'flv': flv},
             args=['video'])
        ogv.close()
        flv.close()
        vid = Video.objects.all()[0]
        assert vid.ogv.url.endswith('098f6b.ogv')
        assert vid.flv.url.endswith('098f6b.flv')

    def test_upload_video_all(self):
        """Upload the same video, in all formats"""
        webm = open(TEST_VID['webm'])
        ogv = open(TEST_VID['ogv'])
        flv = open(TEST_VID['flv'])
        post(self.client, 'gallery.upload_async',
             {'webm': webm, 'ogv': ogv, 'flv': flv}, args=['video'])
        webm.close()
        ogv.close()
        flv.close()
        vid = Video.objects.all()[0]
        assert vid.webm.url.endswith('098f6b.webm')
        assert vid.ogv.url.endswith('098f6b.ogv')
        assert vid.flv.url.endswith('098f6b.flv')

    def test_video_required(self):
        """At least one video format is required to upload."""
        r = post(self.client, 'gallery.upload_async', args=['video'])
        eq_(400, r.status_code)
        json_r = json.loads(r.content)
        eq_('error', json_r['status'])
        eq_('Could not upload your video.', json_r['message'])
        eq_('The video has no files associated with it. You must upload one '
            'of the following extensions: webm, ogv, flv.',
            json_r['errors']['__all__'][0])

    def test_upload_video_long_filename(self):
        """Uploading a video with a filename that's too long fails."""
        for k in ('flv', 'ogv', 'webm'):
            with open('apps/upload/tests/media/a_really_long_filename_worth_'
                      'more_than_250_characters__a_really_long_filename_worth_'
                      'more_than_250_characters__a_really_long_filename_worth_'
                      'more_than_250_characters__a_really_long_filename_worth_'
                      'more_than_250_characters__a_really_long_filename_yes_'
                      '.jpg')\
                as f:
                r = post(self.client, 'gallery.upload_async', {k: f},
                         args=['video'])

            eq_(400, r.status_code)
            json_r = json.loads(r.content)
            eq_('error', json_r['status'])
            eq_('Could not upload your video.', json_r['message'])
            message = getattr(forms, 'MSG_' + k.upper() + '_LONG')
            eq_(message % {'length': 251, 'max': settings.MAX_FILENAME_LENGTH},
                json_r['errors'][k][0])

    def test_invalid_video_extension(self):
        """Make sure invalid video extensions are not accepted."""
        with open(INVALID_VID) as f:
            r = post(self.client, 'gallery.upload_async', {'webm': f},
                     args=['video'])
        eq_(400, r.status_code)
        json_r = json.loads(r.content)
        eq_('error', json_r['status'])
        eq_('Could not upload your video.', json_r['message'])
        eq_(forms.MSG_VID_REQUIRED, json_r['errors']['__all__'][0])

    def test_upload_thumbnail(self):
        """Uploading a thumbnail sets the field and adds a poster."""
        r = self._upload_extension('thumbnail')
        vid = Video.objects.all()[0]

        eq_(1, Video.objects.count())
        eq_(200, r.status_code)
        eq_(150, vid.thumbnail.width)
        eq_(150, vid.poster.width)

    def test_upload_draft_video(self):
        """Uploading draft video works, sets locale too."""
        # Upload a thumbnail/poster
        self._upload_extension('webm')
        self._upload_extension('thumbnail')
        vid = Video.uncached.all()[0]
        assert vid.thumbnail
        assert vid.poster

        r = post(self.client, 'gallery.upload',
                 {'locale': 'de', 'title': 'Hasta la vista',
                  'description': 'Auf wiedersehen!'},
                 args=['video'])

        vid = Video.uncached.all()[0]
        eq_(200, r.status_code)
        eq_('de', vid.locale)
        eq_('Hasta la vista', vid.title)
        eq_('Auf wiedersehen!', vid.description)
        # Thumbnail and poster generated after form is saved.
        eq_(150, vid.poster.width)
        eq_(90, vid.thumbnail.width)
Ejemplo n.º 45
0
class BrowserIDTestCase(TestCase):
    fixtures = ['test_users.json']

    def setUp(self):
        # Ensure @ssl_required goes unenforced.
        settings.DEBUG = True
        # Set up some easily-testable redirects.
        settings.LOGIN_REDIRECT_URL = 'SUCCESS'
        settings.LOGIN_REDIRECT_URL_FAILURE = 'FAILURE'
        # BrowserID will squawk if this isn't set
        settings.SITE_URL = 'http://testserver'
        self.client = LocalizingClient()

    def test_invalid_post(self):
        resp = self.client.post(reverse('users.browserid_verify',
                                        locale='en-US'))
        eq_(302, resp.status_code)
        ok_('FAILURE' in resp['Location'])

    @mock.patch('users.views._verify_browserid')
    def test_invalid_assertion(self, _verify_browserid):
        _verify_browserid.return_value = None

        resp = self.client.post(reverse('users.browserid_verify',
                                        locale='en-US'),
                                {'assertion': 'bad data'})
        eq_(302, resp.status_code)
        ok_('FAILURE' in resp['Location'])

    @mock_get_deki_user_by_email
    @mock_put_mindtouch_user
    @mock_mindtouch_login
    @mock.patch('users.views._verify_browserid')
    def test_valid_assertion_with_django_user(self, _verify_browserid):
        _verify_browserid.return_value = {'email': '*****@*****.**'}

        # Posting the fake assertion to browserid_verify should work, with the
        # actual verification method mocked out.
        resp = self.client.post(reverse('users.browserid_verify',
                                        locale='en-US'),
                                {'assertion': 'PRETENDTHISISVALID'})
        eq_(302, resp.status_code)
        ok_('SUCCESS' in resp['Location'])

        # The session should look logged in, now.
        ok_('_auth_user_id' in self.client.session.keys())
        eq_('django_browserid.auth.BrowserIDBackend',
            self.client.session.get('_auth_user_backend', ''))

    @mock_get_deki_user_by_email
    @mock_put_mindtouch_user
    @mock_mindtouch_login
    @mock.patch('users.views._verify_browserid')
    def test_explain_popup(self, _verify_browserid):
        _verify_browserid.return_value = {'email': '*****@*****.**'}
        resp = self.client.get(reverse('home', locale='en-US'))

        # Posting the fake assertion to browserid_verify should work, with the
        # actual verification method mocked out.
        resp = self.client.post(reverse('users.browserid_verify',
                                        locale='en-US'),
                                {'assertion': 'PRETENDTHISISVALID'})
        eq_('1', resp.cookies.get('browserid_explained').value)

        resp = self.client.get(reverse('users.logout'), locale='en-US')

        # even after logout, cookie should prevent the toggle
        resp = self.client.get(reverse('home', locale='en-US'))
        eq_('1', self.client.cookies.get('browserid_explained').value)

    @mock_get_deki_user_by_email
    @mock_put_mindtouch_user
    @mock_mindtouch_login
    @mock.patch('users.views._verify_browserid')
    def test_valid_assertion_with_mindtouch_user(self, _verify_browserid):
        if not settings.DEKIWIKI_ENDPOINT:
            # Don't even bother with this test, if there's no MindTouch API
            raise SkipTest()

        mt_email = '*****@*****.**'
        _verify_browserid.return_value = {'email': mt_email}

        # Probably overkill but let's be sure we're testing the right thing.
        try:
            User.objects.get(email=mt_email)
            ok_(False, "The MindTouch user shouldn't exist in Django yet.")
        except User.DoesNotExist:
            pass

        if not getattr(settings, 'DEKIWIKI_MOCK', False):
            # HACK: Ensure that expected user details are in MindTouch when not
            # mocking the API
            user_xml = MINDTOUCH_USER_XML % dict(username="******",
                    email=mt_email, fullname="None", status="active",
                    language="", timezone="-08:00", role="Contributor")
            DekiUserBackend.put_mindtouch_user(deki_user_id='=testaccount',
                                               user_xml=user_xml)

        deki_user = DekiUserBackend.get_deki_user_by_email(mt_email)
        ok_(deki_user is not None, "The MindTouch user should exist")

        # Posting the fake assertion to browserid_verify should work, with the
        # actual verification method mocked out.
        resp = self.client.post(reverse('users.browserid_verify',
                                        locale='en-US'),
                                {'assertion': 'PRETENDTHISISVALID'})
        eq_(302, resp.status_code)
        ok_('SUCCESS' in resp['Location'])

        # The session should look logged in, now.
        ok_('_auth_user_id' in self.client.session.keys())
        eq_('django_browserid.auth.BrowserIDBackend',
            self.client.session.get('_auth_user_backend', ''))

        # And, after all the above, there should be a Django user now.
        try:
            User.objects.get(email=mt_email)
        except User.DoesNotExist:
            ok_(False, "The MindTouch user should exist in Django now.")

    @attr('current')
    @mock.patch('dekicompat.backends.DekiUserBackend.get_deki_user_by_email')
    @mock.patch('users.views._verify_browserid')
    def test_valid_assertion_with_mt_disabled(self, _verify_browserid,
                                              mock_get_deki_user_by_email):
        """On valid browserid assertion, when Django user is not found, yet
        MindTouch API disabled, there should be no attempt to look the user up
        in MindTouch"""
        mt_email = '*****@*****.**'
        _verify_browserid.return_value = {'email': mt_email}

        # HACK: mock has an assert_called_with, but I want something like
        # never_called or call_count. Instead, I have this:
        trap = {'was_called': False}

        def my_get_deki_user_by_email(email):
            trap['was_called'] = True
            return False
        mock_get_deki_user_by_email.side_effect = my_get_deki_user_by_email

        _old = settings.DEKIWIKI_ENDPOINT
        settings.DEKIWIKI_ENDPOINT = False
        resp = self.client.post(reverse('users.browserid_verify',
                                        locale='en-US'),
                                {'assertion': 'PRETENDTHISISVALID'})
        settings.DEKIWIKI_ENDPOINT = _old

        # This should end up being a redirect to register
        eq_(302, resp.status_code)
        ok_('browserid_register' in resp['Location'])

        ok_(not trap['was_called'])

    @mock_missing_get_deki_user_by_email
    @mock_missing_get_deki_user
    @mock_post_mindtouch_user
    @mock_put_mindtouch_user
    @mock_mindtouch_login
    @mock.patch('users.views._verify_browserid')
    def test_valid_assertion_with_new_account_creation(self,
                                                       _verify_browserid):
        new_username = '******'
        new_email = '*****@*****.**'
        _verify_browserid.return_value = {'email': new_email}

        try:
            user = User.objects.get(email=new_email)
            ok_(False, "User for email should not yet exist")
        except User.DoesNotExist:
            pass

        if not getattr(settings, 'DEKIWIKI_MOCK', False):
            # HACK: When not mocking the MindTouch API, ensure that there's no
            # leftover user with the same name & email as what we want to
            # register
            import random
            rand_num = random.randint(0, 1000000)
            user_xml = MINDTOUCH_USER_XML % dict(
                    username="******" % (new_username, rand_num),
                    email="%s_%s" % (rand_num, new_email),
                    fullname="", status="inactive",
                    language="", timezone="-08:00",
                    role="Contributor")
            DekiUserBackend.put_mindtouch_user(
                    deki_user_id='=%s' % new_username, user_xml=user_xml)

        # Sign in with a verified email, but with no existing account
        resp = self.client.post(reverse('users.browserid_verify',
                                        locale='en-US'),
                                {'assertion': 'PRETENDTHISISVALID'})
        eq_(302, resp.status_code)

        # This should be a redirect to the BrowserID registration page.
        redir_url = resp['Location']
        reg_url = reverse('users.browserid_register', locale='en-US')
        ok_(reg_url in redir_url)

        # And, as part of the redirect, the verified email address should be in
        # our session now.
        ok_(SESSION_VERIFIED_EMAIL in self.client.session.keys())
        verified_email = self.client.session[SESSION_VERIFIED_EMAIL]
        eq_(new_email, verified_email)

        # Grab the redirect, assert that there's a create_user form present
        resp = self.client.get(redir_url)
        page = pq(resp.content)
        form = page.find('form#create_user')
        eq_(1, form.length)

        # There should be no error lists on first load
        eq_(0, page.find('.errorlist').length)

        # Submit the create_user form, with a chosen username
        resp = self.client.post(redir_url, {'username': '******',
                                            'action': 'register'})

        # The submission should result in a redirect to the session's redirect
        # value
        eq_(302, resp.status_code)
        redir_url = resp['Location']
        ok_('SUCCESS' in redir_url)

        # The session should look logged in, now.
        ok_('_auth_user_id' in self.client.session.keys())
        eq_('django_browserid.auth.BrowserIDBackend',
            self.client.session.get('_auth_user_backend', ''))

        if settings.DEKIWIKI_ENDPOINT:
            ok_(self.client.cookies.get('authtoken'), 'Should have set '
                                                      'authtoken cookie for '
                                                      'MindTouch')

        # Ensure that the user was created, and with the submitted username and
        # verified email address
        try:
            user = User.objects.get(email=new_email)
            eq_(new_username, user.username)
            eq_(new_email, user.email)
        except User.DoesNotExist:
            ok_(False, "New user should have been created")

    @mock_missing_get_deki_user_by_email
    @mock_post_mindtouch_user
    @mock_put_mindtouch_user
    @mock_mindtouch_login
    @mock_get_deki_user
    @mock.patch('users.views._verify_browserid')
    def test_valid_assertion_with_existing_account_login(self,
                                                         _verify_browserid):
        """ Removed the existing user form: we don't auth the password with
        MindTouch anymore """
        new_email = '*****@*****.**'
        _verify_browserid.return_value = {'email': new_email}

        try:
            User.objects.get(email=new_email)
            ok_(False, "User for email should not yet exist")
        except User.DoesNotExist:
            pass

        # Sign in with a verified email, but with no existing account
        resp = self.client.post(reverse('users.browserid_verify',
                                        locale='en-US'),
                                {'assertion': 'PRETENDTHISISVALID'})
        eq_(302, resp.status_code)

        # This should be a redirect to the BrowserID registration page.
        redir_url = resp['Location']
        reg_url = reverse('users.browserid_register', locale='en-US')
        ok_(reg_url in redir_url)

        # And, as part of the redirect, the verified email address should be in
        # our session now.
        ok_(SESSION_VERIFIED_EMAIL in self.client.session.keys())
        verified_email = self.client.session[SESSION_VERIFIED_EMAIL]
        eq_(new_email, verified_email)

        # Grab the redirect, assert that there's a create_user form present
        resp = self.client.get(redir_url)
        page = pq(resp.content)
        form = page.find('form#existing_user')
        eq_(0, form.length)

    @mock.patch('dekicompat.backends.DekiUserBackend.mindtouch_login')
    @mock.patch('users.views._verify_browserid')
    def test_mindtouch_disabled_redirect_login(self, _verify_browserid,
                                               mock_mindtouch_login):
        """When DEKIWIKI_ENDPOINT unavailable, skip MindTouch auth."""
        _verify_browserid.return_value = {'email': '*****@*****.**'}

        # HACK: mock has an assert_called_with, but I want something like
        # never_called or call_count. Instead, I have this:
        trap = {'was_called': False}

        def my_mindtouch_login(username, password, force=False):
            trap['was_called'] = True
            return False
        mock_mindtouch_login.side_effect = my_mindtouch_login

        _old = settings.DEKIWIKI_ENDPOINT
        settings.DEKIWIKI_ENDPOINT = False
        resp = self.client.post(reverse('users.browserid_verify',
                                        locale='en-US'),
                                {'assertion': 'PRETENDTHISISVALID'})
        settings.DEKIWIKI_ENDPOINT = _old

        eq_(302, resp.status_code)
        ok_('SUCCESS' in resp['Location'])

        # The session should look logged in, now.
        ok_('_auth_user_id' in self.client.session.keys())
        eq_('django_browserid.auth.BrowserIDBackend',
            self.client.session.get('_auth_user_backend', ''))

        ok_(not trap['was_called'])

    @mock_get_deki_user_by_email
    @mock_put_mindtouch_user
    @mock_mindtouch_login
    @mock.patch('users.views._verify_browserid')
    def test_valid_assertion_changing_email(self, _verify_browserid):
        # just need to be authenticated, not necessarily BrowserID
        self.client.login(username='******', password='******')

        _verify_browserid.return_value = {'email': '*****@*****.**'}

        resp = self.client.post(reverse('users.browserid_change_email',
                                        locale='en-US'),
                                {'assertion': 'PRETENDTHISISVALID'})
        eq_(302, resp.status_code)
        ok_('profiles/testuser/edit' in resp['Location'])

        resp = self.client.get(reverse('devmo_profile_edit', locale='en-US',
                                       args=['testuser', ]))
        eq_(200, resp.status_code)
        doc = pq(resp.content)
        ok_('*****@*****.**' in doc.find('li#field_email').text())

    @mock_get_deki_user_by_email
    @mock_put_mindtouch_user
    @mock_mindtouch_login
    @mock.patch('users.views._verify_browserid')
    def test_valid_assertion_doesnt_steal_email(self, _verify_browserid):
        # just need to be authenticated, not necessarily BrowserID
        self.client.login(username='******', password='******')

        _verify_browserid.return_value = {'email': '*****@*****.**'}

        # doesn't change email if the new email already belongs to another user
        resp = self.client.post(reverse('users.browserid_change_email',
                                        locale='en-US'),
                                {'assertion': 'PRETENDTHISISVALID'})
        eq_(302, resp.status_code)
        ok_('change_email' in resp['Location'])

        resp = self.client.get(reverse('devmo_profile_edit', locale='en-US',
                                       args=['testuser', ]))
        eq_(200, resp.status_code)
        doc = pq(resp.content)
        ok_('*****@*****.**' in doc.find('li#field_email').text())
Ejemplo n.º 46
0
class ProfileViewsTest(test_utils.TestCase):

    def setUp(self):
        self.client = LocalizingClient()

    def test_profile_view(self):
        """A user profile can be viewed"""
        (user, deki_user, profile) = self._create_profile()

        url = reverse('devmo.views.profile_view',
                      args=(user.username,))
        r = self.client.get(url, follow=True)
        doc = pq(r.content)

        eq_(profile.user.username,
            doc.find('#profile-head.vcard .nickname').text())
        eq_(profile.fullname,
            doc.find('#profile-head.vcard .fn').text())
        eq_(profile.title,
            doc.find('#profile-head.vcard .title').text())
        eq_(profile.organization,
            doc.find('#profile-head.vcard .org').text())
        eq_(profile.location,
            doc.find('#profile-head.vcard .loc').text())
        eq_(profile.irc_nickname,
            doc.find('#profile-head.vcard .irc').text())
        eq_(profile.bio,
            doc.find('#profile-head.vcard .bio').text())

    @attr('current')
    def test_profile_edit(self):
        (user, deki_user, profile) = self._create_profile()

        url = reverse('devmo.views.profile_view',
                      args=(user.username,))
        r = self.client.get(url, follow=True)
        doc = pq(r.content)

        eq_(0, doc.find('#profile-head .edit .button').length)

        self.client.login(username=user.username, 
                password=TESTUSER_PASSWORD)

        url = reverse('devmo.views.profile_view',
                      args=(user.username,))
        r = self.client.get(url, follow=True)
        doc = pq(r.content)

        edit_button = doc.find('#profile-head .edit .button')
        eq_(1, edit_button.length)

        url = edit_button.attr('href')
        r = self.client.get(url, follow=True)
        doc = pq(r.content)

        eq_(profile.fullname,
            doc.find('#profile-edit input[name="fullname"]').val())
        eq_(profile.title,
            doc.find('#profile-edit input[name="title"]').val())
        eq_(profile.organization,
            doc.find('#profile-edit input[name="organization"]').val())
        eq_(profile.location,
            doc.find('#profile-edit input[name="location"]').val())
        eq_(profile.irc_nickname,
            doc.find('#profile-edit input[name="irc_nickname"]').val())

        new_attrs = dict(
            email="*****@*****.**",
            fullname="Another Name",
            title="Another title",
            organization="Another org",
        )

        r = self.client.post(url, new_attrs, follow=True)
        doc = pq(r.content)

        eq_(1, doc.find('#profile-head').length)
        eq_(new_attrs['fullname'],
            doc.find('#profile-head .main .fn').text())
        eq_(new_attrs['title'],
            doc.find('#profile-head .info .title').text())
        eq_(new_attrs['organization'],
            doc.find('#profile-head .info .org').text())

        profile = UserProfile.objects.get(user__username=user.username)
        eq_(new_attrs['fullname'], profile.fullname)
        eq_(new_attrs['title'], profile.title)
        eq_(new_attrs['organization'], profile.organization)

    def test_profile_edit_websites(self):
        (user, deki_user, profile) = self._create_profile()

        self.client.login(username=user.username, 
                password=TESTUSER_PASSWORD)

        url = reverse('devmo.views.profile_edit',
                      args=(user.username,))
        r = self.client.get(url, follow=True)
        doc = pq(r.content)

        test_sites = {
            u'website': u'http://example.com/',
            u'twitter': u'http://twitter.com/lmorchard',
            u'github': u'http://github.com/lmorchard',
            u'stackoverflow': u'http://stackoverflow.com/users/lmorchard',
        }

        # Scrape out the existing significant form field values.
        form = dict()
        for fn in ('email', 'fullname', 'title', 'organization', 'location',
                'irc_nickname', 'bio', 'interests'):
            form[fn] = doc.find('#profile-edit *[name="%s"]' % fn).val()

        # Fill out the form with websites.
        form.update(dict(('websites_%s' % k, v)
                    for k, v in test_sites.items()))

        # Submit the form, verify redirect to profile detail
        r = self.client.post(url, form, follow=True)
        doc = pq(r.content)
        eq_(1, doc.find('#profile-head').length)

        p = UserProfile.objects.get(user=user)

        # Verify the websites are saved in the profile.
        eq_(test_sites, p.websites)

        # Verify the saved websites appear in the editing form
        url = reverse('devmo.views.profile_edit',
                      args=(user.username,))
        r = self.client.get(url, follow=True)
        doc = pq(r.content)
        for k, v in test_sites.items():
            eq_(v, doc.find('#profile-edit *[name="websites_%s"]' % k).val())

        # Come up with some bad sites, either invalid URL or bad URL prefix
        bad_sites = {
            u'website': u'HAHAHA WHAT IS A WEBSITE',
            u'twitter': u'http://facebook.com/lmorchard',
            u'stackoverflow': u'http://overqueueblah.com/users/lmorchard',
        }
        form.update(dict(('websites_%s' % k, v)
                    for k, v in bad_sites.items()))

        # Submit the form, verify errors for all of the bad sites
        r = self.client.post(url, form, follow=True)
        doc = pq(r.content)
        eq_(1, doc.find('#profile-edit').length)
        tmpl = '#profile-edit #elsewhere .%s .errorlist'
        for n in ('website', 'twitter', 'stackoverflow'):
            eq_(1, doc.find(tmpl % n).length)

    def test_profile_edit_interests(self):
        (user, deki_user, profile) = self._create_profile()

        self.client.login(username=user.username, 
                password=TESTUSER_PASSWORD)

        url = reverse('devmo.views.profile_edit',
                      args=(user.username,))
        r = self.client.get(url, follow=True)
        doc = pq(r.content)

        form = dict()
        for fn in ('email', 'fullname', 'title', 'organization', 'location',
                'irc_nickname', 'bio', 'interests'):
            form[fn] = doc.find('#profile-edit *[name="%s"]' % fn).val()

        test_tags = ['javascript', 'css', 'canvas', 'html', 'homebrewing']

        form['interests'] = ', '.join(test_tags)

        r = self.client.post(url, form, follow=True)
        doc = pq(r.content)

        eq_(1, doc.find('#profile-head').length)

        p = UserProfile.objects.get(user=user)

        result_tags = [t.name.replace('profile:interest:', '')
                for t in p.tags.all_ns('profile:interest:')]
        result_tags.sort()
        test_tags.sort()
        eq_(test_tags, result_tags)

        test_expertise = ['css', 'canvas']
        form['expertise'] = ', '.join(test_expertise)
        r = self.client.post(url, form, follow=True)
        doc = pq(r.content)

        eq_(1, doc.find('#profile-head').length)

        p = UserProfile.objects.get(user=user)

        result_tags = [t.name.replace('profile:expertise:', '')
                for t in p.tags.all_ns('profile:expertise')]
        result_tags.sort()
        test_expertise.sort()
        eq_(test_expertise, result_tags)

        # Now, try some expertise tags not covered in interests
        test_expertise = ['css', 'canvas', 'mobile', 'movies']
        form['expertise'] = ', '.join(test_expertise)
        r = self.client.post(url, form, follow=True)
        doc = pq(r.content)

        eq_(1, doc.find('.error #id_expertise').length)

    def _create_profile(self):
        """Create a user, deki_user, and a profile for a test account"""
        user = User.objects.create_user('tester23', '*****@*****.**',
                                        'trustno1')

        deki_user = DekiUser(id=0, username='******',
                             fullname='Tester Twentythree',
                             email='*****@*****.**',
                             gravatar='', profile_url=None)

        profile = UserProfile()
        profile.user = user
        profile.fullname = "Tester Twentythree"
        profile.title = "Spaceship Pilot"
        profile.organization = "UFO"
        profile.location = "Outer Space"
        profile.irc_nickname = "ircuser"
        profile.bio = "I am a freaky space alien."
        profile.save()

        return (user, deki_user, profile)

    def _break(self, url, r):
        logging.debug("URL  %s" % url)
        logging.debug("STAT %s" % r.status_code)
        logging.debug("HEAD %s" % r.items())
        logging.debug("CONT %s" % r.content)
        ok_(False)
Ejemplo n.º 47
0
class MobileAAQTests(MobileTestCase):
    fixtures = ['users.json', 'questions.json']
    data = {
        'title':
        'A test question',
        'content':
        'I have this question that I hope...',
        'sites_affected':
        'http://example.com',
        'ff_version':
        '3.6.6',
        'os':
        'Intel Mac OS X 10.6',
        'plugins':
        '* Shockwave Flash 10.1 r53',
        'useragent':
        'Mozilla/5.0 (Macintosh; U; Intel Mac OS X '
        '10.6; en-US; rv:1.9.2.6) Gecko/20100625 '
        'Firefox/3.6.6'
    }

    def setUp(self):
        self.client = LocalizingClient()
        super(MobileAAQTests, self).setUp()

    def _new_question(self, post_it=False):
        """Post a new question and return the response."""
        url = urlparams(reverse('questions.new_question'),
                        product='desktop',
                        category='d1',
                        search='A test question',
                        showform=1)
        if post_it:
            return self.client.post(url, self.data, follow=True)
        return self.client.get(url, follow=True)

    def test_logged_out(self):
        """New question is posted through mobile."""
        response = self._new_question()
        eq_(200, response.status_code)
        self.assertTemplateUsed(response,
                                'questions/mobile/new_question_login.html')

    @mock.patch.object(Site.objects, 'get_current')
    def test_logged_in_get(self, get_current):
        """New question is posted through mobile."""
        get_current.return_value.domain = 'testserver'
        self.client.login(username='******', password='******')
        response = self._new_question()
        eq_(200, response.status_code)
        self.assertTemplateUsed(response, 'questions/mobile/new_question.html')

    @mock.patch.object(Site.objects, 'get_current')
    def test_logged_in_post(self, get_current):
        """New question is posted through mobile."""
        get_current.return_value.domain = 'testserver'
        self.client.login(username='******', password='******')
        response = self._new_question(post_it=True)
        eq_(200, response.status_code)
        assert Question.objects.filter(title='A test question')

    @mock.patch.object(Site.objects, 'get_current')
    def test_aaq_new_question_inactive(self, get_current):
        """New question is posted through mobile."""
        get_current.return_value.domain = 'testserver'
        # Log in first.
        self.client.login(username='******', password='******')
        # Then become inactive.
        u = User.objects.get(username='******')
        u.is_active = False
        u.save()

        response = self._new_question(post_it=True)
        eq_(200, response.status_code)
        self.assertTemplateUsed(response,
                                'questions/mobile/confirm_email.html')
Ejemplo n.º 48
0
class ChangeEmailTestCase(TestCase):
    fixtures = ['test_users.json']

    def setUp(self):
        self.client = LocalizingClient()

    @mock.patch_object(Site.objects, 'get_current')
    def test_user_change_email(self, get_current):
        """Send email to change user's email and then change it."""
        get_current.return_value.domain = 'su.mo.com'

        self.client.login(username='******', password='******')
        # Attempt to change email.
        response = self.client.post(reverse('users.change_email'),
                                    {'email': '*****@*****.**'},
                                    follow=True)
        eq_(200, response.status_code)

        # Be notified to click a confirmation link.
        eq_(1, len(mail.outbox))
        assert mail.outbox[0].subject.find('Please confirm your') == 0
        ec = EmailChange.objects.all()[0]
        assert ec.activation_key in mail.outbox[0].body
        eq_('*****@*****.**', ec.email)

        # Visit confirmation link to change email.
        response = self.client.get(reverse('users.confirm_email',
                                           args=[ec.activation_key]))
        eq_(200, response.status_code)
        u = User.objects.get(username='******')
        eq_('*****@*****.**', u.email)

    @mock_get_deki_user
    @mock_put_mindtouch_user
    @mock.patch_object(Site.objects, 'get_current')
    def test_user_change_email_updates_mindtouch(self, get_current):
        """Send email to change user's email and then change it."""
        get_current.return_value.domain = 'su.mo.com'

        self.client.login(username='******', password='******')
        # Attempt to change email.
        response = self.client.post(reverse('users.change_email'),
                                    {'email': '*****@*****.**'},
                                    follow=True)
        eq_(200, response.status_code)

        # Be notified to click a confirmation link.
        eq_(1, len(mail.outbox))
        assert mail.outbox[0].subject.find('Please confirm your') == 0
        ec = EmailChange.objects.all()[0]
        assert ec.activation_key in mail.outbox[0].body
        eq_('*****@*****.**', ec.email)

        # Visit confirmation link to change email.
        response = self.client.get(reverse('users.confirm_email',
                                           args=[ec.activation_key]))
        eq_(200, response.status_code)
        u = User.objects.get(username='******')
        eq_('*****@*****.**', u.email)

        if not settings.DEKIWIKI_MOCK:
            deki_id = u.get_profile().deki_user_id
            doc = get_deki_user_doc(u)
            eq_(str(deki_id), doc('user').attr('id'))
            eq_('*****@*****.**',
                doc('user').find('email').text())

    def test_user_change_email_same(self):
        """Changing to same email shows validation error."""
        self.client.login(username='******', password='******')
        user = User.objects.get(username='******')
        user.email = '*****@*****.**'
        user.save()
        response = self.client.post(reverse('users.change_email'),
                                    {'email': user.email})
        eq_(200, response.status_code)
        doc = pq(response.content)
        eq_('This is your current email.', doc('ul.errorlist').text())

    def test_user_change_email_duplicate(self):
        """Changing to same email shows validation error."""
        self.client.login(username='******', password='******')
        email = '*****@*****.**'
        response = self.client.post(reverse('users.change_email'),
                                    {'email': email})
        eq_(200, response.status_code)
        doc = pq(response.content)
        eq_('A user with that email address already exists.',
            doc('ul.errorlist').text())

    @mock.patch_object(Site.objects, 'get_current')
    def test_user_confirm_email_duplicate(self, get_current):
        """If we detect a duplicate email when confirming an email change,
        don't change it and notify the user."""
        get_current.return_value.domain = 'su.mo.com'
        self.client.login(username='******', password='******')
        old_email = User.objects.get(username='******').email
        new_email = '*****@*****.**'
        response = self.client.post(reverse('users.change_email'),
                                    {'email': new_email})
        eq_(200, response.status_code)
        assert mail.outbox[0].subject.find('Please confirm your') == 0
        ec = EmailChange.objects.all()[0]

        # Before new email is confirmed, give the same email to a user
        other_user = User.objects.filter(username='******')[0]
        other_user.email = new_email
        other_user.save()

        # Visit confirmation link and verify email wasn't changed.
        response = self.client.get(reverse('users.confirm_email',
                                           args=[ec.activation_key]))
        eq_(200, response.status_code)
        doc = pq(response.content)
        eq_('Unable to change email for user testuser',
            doc('.main h1').text())
        u = User.objects.get(username='******')
        eq_(old_email, u.email)
Ejemplo n.º 49
0
class ProfileViewsTest(test_utils.TestCase):
    def setUp(self):
        self.client = LocalizingClient()

    def test_profile_view(self):
        """A user profile can be viewed"""
        (user, deki_user, profile) = self._create_profile()

        url = reverse('devmo.views.profile_view', args=(user.username, ))
        r = self.client.get(url, follow=True)
        doc = pq(r.content)

        eq_(profile.user.username,
            doc.find('#profile-head.vcard .nickname').text())
        eq_(profile.fullname, doc.find('#profile-head.vcard .fn').text())
        eq_(profile.title, doc.find('#profile-head.vcard .title').text())
        eq_(profile.organization, doc.find('#profile-head.vcard .org').text())
        eq_(profile.location, doc.find('#profile-head.vcard .loc').text())
        eq_(profile.irc_nickname, doc.find('#profile-head.vcard .irc').text())
        eq_(profile.bio, doc.find('#profile-head.vcard .bio').text())

    @attr('current')
    def test_profile_edit(self):
        (user, deki_user, profile) = self._create_profile()

        url = reverse('devmo.views.profile_view', args=(user.username, ))
        r = self.client.get(url, follow=True)
        doc = pq(r.content)

        eq_(0, doc.find('#profile-head .edit .button').length)

        self.client.login(username=user.username, password=TESTUSER_PASSWORD)

        url = reverse('devmo.views.profile_view', args=(user.username, ))
        r = self.client.get(url, follow=True)
        doc = pq(r.content)

        edit_button = doc.find('#profile-head .edit .button')
        eq_(1, edit_button.length)

        url = edit_button.attr('href')
        r = self.client.get(url, follow=True)
        doc = pq(r.content)

        eq_(profile.fullname,
            doc.find('#profile-edit input[name="fullname"]').val())
        eq_(profile.title, doc.find('#profile-edit input[name="title"]').val())
        eq_(profile.organization,
            doc.find('#profile-edit input[name="organization"]').val())
        eq_(profile.location,
            doc.find('#profile-edit input[name="location"]').val())
        eq_(profile.irc_nickname,
            doc.find('#profile-edit input[name="irc_nickname"]').val())

        new_attrs = dict(
            email="*****@*****.**",
            fullname="Another Name",
            title="Another title",
            organization="Another org",
        )

        r = self.client.post(url, new_attrs, follow=True)
        doc = pq(r.content)

        eq_(1, doc.find('#profile-head').length)
        eq_(new_attrs['fullname'], doc.find('#profile-head .main .fn').text())
        eq_(new_attrs['title'], doc.find('#profile-head .info .title').text())
        eq_(new_attrs['organization'],
            doc.find('#profile-head .info .org').text())

        profile = UserProfile.objects.get(user__username=user.username)
        eq_(new_attrs['fullname'], profile.fullname)
        eq_(new_attrs['title'], profile.title)
        eq_(new_attrs['organization'], profile.organization)

    def test_profile_edit_websites(self):
        (user, deki_user, profile) = self._create_profile()

        self.client.login(username=user.username, password=TESTUSER_PASSWORD)

        url = reverse('devmo.views.profile_edit', args=(user.username, ))
        r = self.client.get(url, follow=True)
        doc = pq(r.content)

        test_sites = {
            u'website': u'http://example.com/',
            u'twitter': u'http://twitter.com/lmorchard',
            u'github': u'http://github.com/lmorchard',
            u'stackoverflow': u'http://stackoverflow.com/users/lmorchard',
        }

        # Scrape out the existing significant form field values.
        form = dict()
        for fn in ('email', 'fullname', 'title', 'organization', 'location',
                   'irc_nickname', 'bio', 'interests'):
            form[fn] = doc.find('#profile-edit *[name="%s"]' % fn).val()

        # Fill out the form with websites.
        form.update(dict(
            ('websites_%s' % k, v) for k, v in test_sites.items()))

        # Submit the form, verify redirect to profile detail
        r = self.client.post(url, form, follow=True)
        doc = pq(r.content)
        eq_(1, doc.find('#profile-head').length)

        p = UserProfile.objects.get(user=user)

        # Verify the websites are saved in the profile.
        eq_(test_sites, p.websites)

        # Verify the saved websites appear in the editing form
        url = reverse('devmo.views.profile_edit', args=(user.username, ))
        r = self.client.get(url, follow=True)
        doc = pq(r.content)
        for k, v in test_sites.items():
            eq_(v, doc.find('#profile-edit *[name="websites_%s"]' % k).val())

        # Come up with some bad sites, either invalid URL or bad URL prefix
        bad_sites = {
            u'website': u'HAHAHA WHAT IS A WEBSITE',
            u'twitter': u'http://facebook.com/lmorchard',
            u'stackoverflow': u'http://overqueueblah.com/users/lmorchard',
        }
        form.update(dict(('websites_%s' % k, v) for k, v in bad_sites.items()))

        # Submit the form, verify errors for all of the bad sites
        r = self.client.post(url, form, follow=True)
        doc = pq(r.content)
        eq_(1, doc.find('#profile-edit').length)
        tmpl = '#profile-edit #elsewhere .%s .errorlist'
        for n in ('website', 'twitter', 'stackoverflow'):
            eq_(1, doc.find(tmpl % n).length)

    def test_profile_edit_interests(self):
        (user, deki_user, profile) = self._create_profile()

        self.client.login(username=user.username, password=TESTUSER_PASSWORD)

        url = reverse('devmo.views.profile_edit', args=(user.username, ))
        r = self.client.get(url, follow=True)
        doc = pq(r.content)

        form = dict()
        for fn in ('email', 'fullname', 'title', 'organization', 'location',
                   'irc_nickname', 'bio', 'interests'):
            form[fn] = doc.find('#profile-edit *[name="%s"]' % fn).val()

        test_tags = ['javascript', 'css', 'canvas', 'html', 'homebrewing']

        form['interests'] = ', '.join(test_tags)

        r = self.client.post(url, form, follow=True)
        doc = pq(r.content)

        eq_(1, doc.find('#profile-head').length)

        p = UserProfile.objects.get(user=user)

        result_tags = [
            t.name.replace('profile:interest:', '')
            for t in p.tags.all_ns('profile:interest:')
        ]
        result_tags.sort()
        test_tags.sort()
        eq_(test_tags, result_tags)

        test_expertise = ['css', 'canvas']
        form['expertise'] = ', '.join(test_expertise)
        r = self.client.post(url, form, follow=True)
        doc = pq(r.content)

        eq_(1, doc.find('#profile-head').length)

        p = UserProfile.objects.get(user=user)

        result_tags = [
            t.name.replace('profile:expertise:', '')
            for t in p.tags.all_ns('profile:expertise')
        ]
        result_tags.sort()
        test_expertise.sort()
        eq_(test_expertise, result_tags)

        # Now, try some expertise tags not covered in interests
        test_expertise = ['css', 'canvas', 'mobile', 'movies']
        form['expertise'] = ', '.join(test_expertise)
        r = self.client.post(url, form, follow=True)
        doc = pq(r.content)

        eq_(1, doc.find('.error #id_expertise').length)

    def _create_profile(self):
        """Create a user, deki_user, and a profile for a test account"""
        user = User.objects.create_user('tester23', '*****@*****.**',
                                        'trustno1')

        deki_user = DekiUser(id=0,
                             username='******',
                             fullname='Tester Twentythree',
                             email='*****@*****.**',
                             gravatar='',
                             profile_url=None)

        profile = UserProfile()
        profile.user = user
        profile.fullname = "Tester Twentythree"
        profile.title = "Spaceship Pilot"
        profile.organization = "UFO"
        profile.location = "Outer Space"
        profile.irc_nickname = "ircuser"
        profile.bio = "I am a freaky space alien."
        profile.save()

        return (user, deki_user, profile)

    def _break(self, url, r):
        logging.debug("URL  %s" % url)
        logging.debug("STAT %s" % r.status_code)
        logging.debug("HEAD %s" % r.items())
        logging.debug("CONT %s" % r.content)
        ok_(False)
Ejemplo n.º 50
0
class GalleryUploadTestCase(TestCase):
    fixtures = ['users.json']

    def setUp(self):
        super(GalleryUploadTestCase, self).setUp()
        self.client = LocalizingClient()
        self.client.login(username='******', password='******')
        self.u = User.objects.get(username='******')

    def tearDown(self):
        Image.objects.all().delete()
        Video.objects.all().delete()
        super(GalleryUploadTestCase, self).tearDown()

    def test_image_draft_shows(self):
        """The image draft is loaded for this user."""
        image(is_draft=True, creator=self.u)
        response = get(self.client, 'gallery.gallery', args=['image'])
        eq_(200, response.status_code)
        doc = pq(response.content)
        assert doc('.file.preview img').attr('src').endswith('098f6b.jpg')
        eq_(1, doc('.file.preview img').length)

    def test_video_draft_shows(self):
        """The video draft is loaded for this user."""
        video(is_draft=True, creator=self.u)
        response = get(self.client, 'gallery.gallery', args=['image'])
        eq_(200, response.status_code)
        doc = pq(response.content)
        # Preview for all 3 video formats: flv, ogv, webm
        eq_(3, doc('#gallery-upload-video .preview input').length)

    def test_image_draft_post(self):
        """Posting to the page saves the field values for the image draft."""
        image(is_draft=True, creator=self.u)
        response = post(self.client,
                        'gallery.gallery', {
                            'description': '??',
                            'title': 'test'
                        },
                        args=['image'])
        eq_(200, response.status_code)
        doc = pq(response.content)
        # Preview for all 3 video formats: flv, ogv, webm
        eq_('??', doc('#gallery-upload-modal textarea').html())
        eq_('test', doc('#gallery-upload-modal input[name="title"]').val())

    def test_video_draft_post(self):
        """Posting to the page saves the field values for the video draft."""
        video(is_draft=True, creator=self.u)
        response = post(self.client,
                        'gallery.gallery', {'title': 'zTestz'},
                        args=['image'])
        eq_(200, response.status_code)
        doc = pq(response.content)
        # Preview for all 3 video formats: flv, ogv, webm
        eq_('zTestz', doc('#gallery-upload-modal input[name="title"]').val())

    def test_modal_locale_selected(self):
        """Locale value is selected for upload modal."""
        response = get(self.client,
                       'gallery.gallery',
                       args=['image'],
                       locale='fr')
        doc = pq(response.content)
        eq_('fr',
            doc('#gallery-upload-image option[selected="selected"]').val())
        eq_('fr',
            doc('#gallery-upload-video option[selected="selected"]').val())

    def test_invalid_messages(self):
        # TODO(paul) POSTing invalid data shows error messages and pre-fills
        raise SkipTest
Ejemplo n.º 51
0
class ProfileViewsTest(TestCase):
    fixtures = ['test_users.json']

    def setUp(self):
        self.old_debug = settings.DEBUG
        settings.DEBUG = True
        self.client = LocalizingClient()
        self.client.logout()

    def tearDown(self):
        settings.DEBUG = self.old_debug

    def _get_current_form_field_values(self, doc):
        # Scrape out the existing significant form field values.
        form = dict()
        for fn in ('email', 'fullname', 'title', 'organization', 'location',
                   'irc_nickname', 'bio', 'interests'):
            form[fn] = doc.find('#profile-edit *[name="%s"]' % fn).val()
        return form

    @attr('docs_activity')
    def test_profile_view(self):
        """A user profile can be viewed"""
        profile = UserProfile.objects.get(user__username='******')
        user = profile.user
        url = reverse('devmo.views.profile_view', args=(user.username, ))
        r = self.client.get(url, follow=True)
        doc = pq(r.content)

        eq_(profile.user.username,
            doc.find('#profile-head.vcard .nickname').text())
        eq_(profile.fullname, doc.find('#profile-head.vcard .fn').text())
        eq_(profile.title, doc.find('#profile-head.vcard .title').text())
        eq_(profile.organization, doc.find('#profile-head.vcard .org').text())
        eq_(profile.location, doc.find('#profile-head.vcard .loc').text())
        eq_('IRC: ' + profile.irc_nickname,
            doc.find('#profile-head.vcard .irc').text())
        eq_(profile.bio, doc.find('#profile-head.vcard .bio').text())

    def test_my_profile_view(self):
        u = User.objects.get(username='******')
        self.client.login(username=u.username, password=TESTUSER_PASSWORD)
        resp = self.client.get('/profile/')
        eq_(302, resp.status_code)
        ok_(
            reverse('devmo.views.profile_view', args=(
                u.username, )) in resp['Location'])

    def test_bug_698971(self):
        """A non-numeric page number should not cause an error"""
        (user, profile) = create_profile()

        url = '%s?page=asdf' % reverse('devmo.views.profile_view',
                                       args=(user.username, ))

        try:
            self.client.get(url, follow=True)
        except PageNotAnInteger:
            ok_(False, "Non-numeric page number should not cause an error")

    def test_profile_edit(self):
        profile = UserProfile.objects.get(user__username='******')
        user = profile.user
        url = reverse('devmo.views.profile_view', args=(user.username, ))
        r = self.client.get(url, follow=True)
        doc = pq(r.content)
        eq_(0, doc.find('#profile-head .edit .button').length)

        self.client.login(username=user.username, password=TESTUSER_PASSWORD)

        url = reverse('devmo.views.profile_view', args=(user.username, ))
        r = self.client.get(url, follow=True)
        doc = pq(r.content)

        edit_button = doc.find('#profile-head .edit #edit-profile')
        eq_(1, edit_button.length)

        url = edit_button.attr('href')
        r = self.client.get(url, follow=True)
        doc = pq(r.content)

        eq_(profile.fullname,
            doc.find('#profile-edit input[name="fullname"]').val())
        eq_(profile.title, doc.find('#profile-edit input[name="title"]').val())
        eq_(profile.organization,
            doc.find('#profile-edit input[name="organization"]').val())
        eq_(profile.location,
            doc.find('#profile-edit input[name="location"]').val())
        eq_(profile.irc_nickname,
            doc.find('#profile-edit input[name="irc_nickname"]').val())

        new_attrs = dict(
            email='*****@*****.**',
            fullname="Another Name",
            title="Another title",
            organization="Another org",
        )

        r = self.client.post(url, new_attrs, follow=True)
        doc = pq(r.content)

        eq_(1, doc.find('#profile-head').length)
        eq_(new_attrs['fullname'], doc.find('#profile-head .main .fn').text())
        eq_(new_attrs['title'], doc.find('#profile-head .info .title').text())
        eq_(new_attrs['organization'],
            doc.find('#profile-head .info .org').text())

        profile = UserProfile.objects.get(user__username=user.username)
        eq_(new_attrs['fullname'], profile.fullname)
        eq_(new_attrs['title'], profile.title)
        eq_(new_attrs['organization'], profile.organization)

    def test_my_profile_edit(self):
        u = User.objects.get(username='******')
        self.client.login(username=u.username, password=TESTUSER_PASSWORD)
        resp = self.client.get('/profile/edit')
        eq_(302, resp.status_code)
        ok_(
            reverse('devmo.views.profile_edit', args=(
                u.username, )) in resp['Location'])

    def test_profile_edit_beta(self):
        user = User.objects.get(username='******')
        self.client.login(username=user.username, password=TESTUSER_PASSWORD)

        url = reverse('devmo.views.profile_edit', args=(user.username, ))
        r = self.client.get(url, follow=True)
        doc = pq(r.content)
        eq_(None, doc.find('input#id_beta').attr('checked'))

        form = self._get_current_form_field_values(doc)
        form['beta'] = True

        r = self.client.post(url, form, follow=True)

        url = reverse('devmo.views.profile_edit', args=(user.username, ))
        r = self.client.get(url, follow=True)
        doc = pq(r.content)
        eq_('checked', doc.find('input#id_beta').attr('checked'))

    def test_profile_edit_websites(self):
        user = User.objects.get(username='******')
        self.client.login(username=user.username, password=TESTUSER_PASSWORD)

        url = reverse('devmo.views.profile_edit', args=(user.username, ))
        r = self.client.get(url, follow=True)
        doc = pq(r.content)

        test_sites = {
            u'website': u'http://example.com/',
            u'twitter': u'http://twitter.com/lmorchard',
            u'github': u'http://github.com/lmorchard',
            u'stackoverflow': u'http://stackoverflow.com/users/lmorchard',
        }

        form = self._get_current_form_field_values(doc)

        # Fill out the form with websites.
        form.update(dict(
            ('websites_%s' % k, v) for k, v in test_sites.items()))

        # Submit the form, verify redirect to profile detail
        r = self.client.post(url, form, follow=True)
        doc = pq(r.content)
        eq_(1, doc.find('#profile-head').length)

        p = UserProfile.objects.get(user=user)

        # Verify the websites are saved in the profile.
        eq_(test_sites, p.websites)

        # Verify the saved websites appear in the editing form
        url = reverse('devmo.views.profile_edit', args=(user.username, ))
        r = self.client.get(url, follow=True)
        doc = pq(r.content)
        for k, v in test_sites.items():
            eq_(v, doc.find('#profile-edit *[name="websites_%s"]' % k).val())

        # Come up with some bad sites, either invalid URL or bad URL prefix
        bad_sites = {
            u'website': u'HAHAHA WHAT IS A WEBSITE',
            u'twitter': u'http://facebook.com/lmorchard',
            u'stackoverflow': u'http://overqueueblah.com/users/lmorchard',
        }
        form.update(dict(('websites_%s' % k, v) for k, v in bad_sites.items()))

        # Submit the form, verify errors for all of the bad sites
        r = self.client.post(url, form, follow=True)
        doc = pq(r.content)
        eq_(1, doc.find('#profile-edit').length)
        tmpl = '#profile-edit #elsewhere .%s .errorlist'
        for n in ('website', 'twitter', 'stackoverflow'):
            eq_(1, doc.find(tmpl % n).length)

    def test_profile_edit_interests(self):
        user = User.objects.get(username='******')
        self.client.login(username=user.username, password=TESTUSER_PASSWORD)

        url = reverse('devmo.views.profile_edit', args=(user.username, ))
        r = self.client.get(url, follow=True)
        doc = pq(r.content)

        test_tags = ['javascript', 'css', 'canvas', 'html', 'homebrewing']

        form = self._get_current_form_field_values(doc)

        form['interests'] = ', '.join(test_tags)

        r = self.client.post(url, form, follow=True)
        doc = pq(r.content)
        eq_(1, doc.find('#profile-head').length)

        p = UserProfile.objects.get(user=user)

        result_tags = [
            t.name.replace('profile:interest:', '')
            for t in p.tags.all_ns('profile:interest:')
        ]
        result_tags.sort()
        test_tags.sort()
        eq_(test_tags, result_tags)

        test_expertise = ['css', 'canvas']
        form['expertise'] = ', '.join(test_expertise)
        r = self.client.post(url, form, follow=True)
        doc = pq(r.content)

        eq_(1, doc.find('#profile-head').length)

        p = UserProfile.objects.get(user=user)

        result_tags = [
            t.name.replace('profile:expertise:', '')
            for t in p.tags.all_ns('profile:expertise')
        ]
        result_tags.sort()
        test_expertise.sort()
        eq_(test_expertise, result_tags)

        # Now, try some expertise tags not covered in interests
        test_expertise = ['css', 'canvas', 'mobile', 'movies']
        form['expertise'] = ', '.join(test_expertise)
        r = self.client.post(url, form, follow=True)
        doc = pq(r.content)

        eq_(1, doc.find('.error #id_expertise').length)

    def test_bug_709938_interests(self):
        user = User.objects.get(username='******')
        self.client.login(username=user.username, password=TESTUSER_PASSWORD)

        url = reverse('devmo.views.profile_edit', args=(user.username, ))
        r = self.client.get(url, follow=True)
        doc = pq(r.content)

        test_tags = [
            u'science,Technology,paradox,knowledge,modeling,big data,'
            u'vector,meme,heuristics,harmony,mathesis universalis,'
            u'symmetry,mathematics,computer graphics,field,chemistry,'
            u'religion,astronomy,physics,biology,literature,'
            u'spirituality,Art,Philosophy,Psychology,Business,Music,'
            u'Computer Science'
        ]

        form = self._get_current_form_field_values(doc)

        form['interests'] = test_tags

        r = self.client.post(url, form, follow=True)
        eq_(200, r.status_code)
        doc = pq(r.content)
        eq_(1, doc.find('ul.errorlist li').length)
        assert ('Ensure this value has at most 255 characters'
                in doc.find('ul.errorlist li').text())

    def test_bug_698126_l10n(self):
        """Test that the form field names are localized"""
        user = User.objects.get(username='******')
        self.client.login(username=user.username, password=TESTUSER_PASSWORD)

        url = reverse('devmo.views.profile_edit', args=(user.username, ))
        r = self.client.get(url, follow=True)
        for field in r.context['form'].fields:
            # if label is localized it's a lazy proxy object
            ok_(
                not isinstance(r.context['form'].fields[field].label,
                               basestring), 'Field %s is a string!' % field)

    def _break(self, url, r):
        logging.debug("URL  %s" % url)
        logging.debug("STAT %s" % r.status_code)
        logging.debug("HEAD %s" % r.items())
        logging.debug("CONT %s" % r.content)
        ok_(False)
Ejemplo n.º 52
0
    def test_midair_section_collision(self):
        """If both a revision and the edited section has changed, then a
        section edit is a collision."""
        client = LocalizingClient()
        client.login(username='******', password='******')

        doc, rev = doc_rev("""
            <h1 id="s1">Head 1</h1>
            <p>test</p>
            <p>test</p>

            <h1 id="s2">Head 2</h1>
            <p>test</p>
            <p>test</p>

            <h1 id="s3">Head 3</h1>
            <p>test</p>
            <p>test</p>
        """)
        replace_1 = """
            <h1 id="s2">replace</h1>
            <p>replace</p>
        """
        replace_2 = """
            <h1 id="s2">first replace</h1>
            <p>first replace</p>
        """
        data = {'form': 'rev', 'content': rev.content}

        # Edit #1 starts...
        resp = client.get('%s?section=s2' %
                          reverse('wiki.edit_document', args=[doc.slug]))
        page = pq(resp.content)
        rev_id1 = page.find('input[name="current_rev"]').attr('value')

        # Edit #2 starts...
        resp = client.get('%s?section=s2' %
                          reverse('wiki.edit_document', args=[doc.slug]))
        page = pq(resp.content)
        rev_id2 = page.find('input[name="current_rev"]').attr('value')

        # Edit #2 submits successfully
        data.update({
            'form': 'rev',
            'content': replace_2,
            'current_rev': rev_id2
        })
        resp = client.post(
            '%s?section=s2&raw=true' %
            reverse('wiki.edit_document', args=[doc.slug]), data)
        eq_(302, resp.status_code)

        # Edit #1 submits, but since it's the same section, there's a collision
        data.update({
            'form': 'rev',
            'content': replace_1,
            'current_rev': rev_id1
        })
        resp = client.post(
            '%s?section=s2&raw=true' %
            reverse('wiki.edit_document', args=[doc.slug]), data)
        # With the raw API, we should get a 409 Conflict on collision.
        eq_(409, resp.status_code)
Ejemplo n.º 53
0
    def test_midair_section_merge(self):
        """If a page was changed while someone was editing, but the changes
        didn't affect the specific section being edited, then ignore the midair
        warning"""
        client = LocalizingClient()
        client.login(username='******', password='******')

        doc, rev = doc_rev("""
            <h1 id="s1">Head 1</h1>
            <p>test</p>
            <p>test</p>

            <h1 id="s2">Head 2</h1>
            <p>test</p>
            <p>test</p>

            <h1 id="s3">Head 3</h1>
            <p>test</p>
            <p>test</p>
        """)
        replace_1 = """
            <h1 id="s1">replace</h1>
            <p>replace</p>
        """
        replace_2 = """
            <h1 id="s2">replace</h1>
            <p>replace</p>
        """
        expected = """
            <h1 id="s1">replace</h1>
            <p>replace</p>

            <h1 id="s2">replace</h1>
            <p>replace</p>

            <h1 id="s3">Head 3</h1>
            <p>test</p>
            <p>test</p>
        """
        data = {'form': 'rev', 'content': rev.content}

        # Edit #1 starts...
        resp = client.get('%s?section=s1' %
                          reverse('wiki.edit_document', args=[doc.slug]))
        page = pq(resp.content)
        rev_id1 = page.find('input[name="current_rev"]').attr('value')

        # Edit #2 starts...
        resp = client.get('%s?section=s2' %
                          reverse('wiki.edit_document', args=[doc.slug]))
        page = pq(resp.content)
        rev_id2 = page.find('input[name="current_rev"]').attr('value')

        # Edit #2 submits successfully
        data.update({
            'form': 'rev',
            'content': replace_2,
            'current_rev': rev_id2
        })
        resp = client.post(
            '%s?section=s2&raw=true' %
            reverse('wiki.edit_document', args=[doc.slug]), data)
        eq_(302, resp.status_code)

        # Edit #1 submits, but since it's a different section, there's no
        # mid-air collision
        data.update({
            'form': 'rev',
            'content': replace_1,
            'current_rev': rev_id1
        })
        resp = client.post(
            '%s?section=s1&raw=true' %
            reverse('wiki.edit_document', args=[doc.slug]), data)
        # No conflict, but we should get a 205 Reset as an indication that the
        # page needs a refresh.
        eq_(205, resp.status_code)

        # Finally, make sure that all the edits landed
        response = client.get('%s?raw=true' %
                              reverse('wiki.document', args=[doc.slug]))
        eq_(normalize_html(expected), normalize_html(response.content))

        # Also, ensure that the revision is slipped into the headers
        eq_(unicode(Document.uncached.get(slug=doc.slug).current_revision.id),
            unicode(response['x-kuma-revision']))
Ejemplo n.º 54
0
class ChangeEmailTestCase(TestCase):
    fixtures = ['test_users.json']

    def setUp(self):
        self.client = LocalizingClient()

    @mock.patch_object(Site.objects, 'get_current')
    def test_user_change_email(self, get_current):
        """Send email to change user's email and then change it."""
        get_current.return_value.domain = 'su.mo.com'

        self.client.login(username='******', password='******')
        # Attempt to change email.
        response = self.client.post(reverse('users.change_email'),
                                    {'email': '*****@*****.**'},
                                    follow=True)
        eq_(200, response.status_code)

        # Be notified to click a confirmation link.
        eq_(1, len(mail.outbox))
        assert mail.outbox[0].subject.find('Please confirm your') == 0
        ec = EmailChange.objects.all()[0]
        assert ec.activation_key in mail.outbox[0].body
        eq_('*****@*****.**', ec.email)

        # Visit confirmation link to change email.
        response = self.client.get(
            reverse('users.confirm_email', args=[ec.activation_key]))
        eq_(200, response.status_code)
        u = User.objects.get(username='******')
        eq_('*****@*****.**', u.email)

    @mock_get_deki_user
    @mock_put_mindtouch_user
    @mock.patch_object(Site.objects, 'get_current')
    def test_user_change_email_updates_mindtouch(self, get_current):
        """Send email to change user's email and then change it."""
        get_current.return_value.domain = 'su.mo.com'

        self.client.login(username='******', password='******')
        # Attempt to change email.
        response = self.client.post(reverse('users.change_email'),
                                    {'email': '*****@*****.**'},
                                    follow=True)
        eq_(200, response.status_code)

        # Be notified to click a confirmation link.
        eq_(1, len(mail.outbox))
        assert mail.outbox[0].subject.find('Please confirm your') == 0
        ec = EmailChange.objects.all()[0]
        assert ec.activation_key in mail.outbox[0].body
        eq_('*****@*****.**', ec.email)

        # Visit confirmation link to change email.
        response = self.client.get(
            reverse('users.confirm_email', args=[ec.activation_key]))
        eq_(200, response.status_code)
        u = User.objects.get(username='******')
        eq_('*****@*****.**', u.email)

        if not settings.DEKIWIKI_MOCK:
            deki_id = u.get_profile().deki_user_id
            doc = get_deki_user_doc(u)
            eq_(str(deki_id), doc('user').attr('id'))
            eq_('*****@*****.**',
                doc('user').find('email').text())

    def test_user_change_email_same(self):
        """Changing to same email shows validation error."""
        self.client.login(username='******', password='******')
        user = User.objects.get(username='******')
        user.email = '*****@*****.**'
        user.save()
        response = self.client.post(reverse('users.change_email'),
                                    {'email': user.email})
        eq_(200, response.status_code)
        doc = pq(response.content)
        eq_('This is your current email.', doc('ul.errorlist').text())

    def test_user_change_email_duplicate(self):
        """Changing to same email shows validation error."""
        self.client.login(username='******', password='******')
        email = '*****@*****.**'
        response = self.client.post(reverse('users.change_email'),
                                    {'email': email})
        eq_(200, response.status_code)
        doc = pq(response.content)
        eq_('A user with that email address already exists.',
            doc('ul.errorlist').text())

    @mock.patch_object(Site.objects, 'get_current')
    def test_user_confirm_email_duplicate(self, get_current):
        """If we detect a duplicate email when confirming an email change,
        don't change it and notify the user."""
        get_current.return_value.domain = 'su.mo.com'
        self.client.login(username='******', password='******')
        old_email = User.objects.get(username='******').email
        new_email = '*****@*****.**'
        response = self.client.post(reverse('users.change_email'),
                                    {'email': new_email})
        eq_(200, response.status_code)
        assert mail.outbox[0].subject.find('Please confirm your') == 0
        ec = EmailChange.objects.all()[0]

        # Before new email is confirmed, give the same email to a user
        other_user = User.objects.filter(username='******')[0]
        other_user.email = new_email
        other_user.save()

        # Visit confirmation link and verify email wasn't changed.
        response = self.client.get(
            reverse('users.confirm_email', args=[ec.activation_key]))
        eq_(200, response.status_code)
        doc = pq(response.content)
        eq_('Unable to change email for user testuser', doc('.main h1').text())
        u = User.objects.get(username='******')
        eq_(old_email, u.email)
Ejemplo n.º 55
0
    def test_review_tags(self, get_current):
        get_current.return_value.domain = 'su.mo.com'
        """Review tags can be managed on document revisions"""
        client = LocalizingClient()
        client.login(username='******', password='******')

        # Create a new doc with one review tag
        data = new_document_data()
        data.update({'review_tags': ['technical']})
        response = client.post(reverse('wiki.new_document'), data)

        # Ensure there's now a doc with that expected tag in its newest
        # revision
        doc = Document.objects.get(slug="a-test-article")
        rev = doc.revisions.order_by('-id').all()[0]
        review_tags = [x.name for x in rev.review_tags.all()]
        eq_(['technical'], review_tags)

        # Now, post an update with two tags
        data.update({
            'form': 'rev',
            'review_tags': ['editorial', 'technical'],
        })
        response = client.post(reverse('wiki.edit_document', args=[doc.slug]),
                               data)

        # Ensure the doc's newest revision has both tags.
        doc = Document.objects.get(slug="a-test-article")
        rev = doc.revisions.order_by('-id').all()[0]
        review_tags = [x.name for x in rev.review_tags.all()]
        review_tags.sort()
        eq_(['editorial', 'technical'], review_tags)

        # Now, ensure that warning boxes appear for the review tags.
        response = client.get(reverse('wiki.document', args=[doc.slug]), data)
        page = pq(response.content)
        eq_(1, page.find('.warning.review-technical').length)
        eq_(1, page.find('.warning.review-editorial').length)

        # Ensure the page appears on the listing pages
        response = client.get(reverse('wiki.list_review'))
        eq_(
            1,
            pq(response.content).find("ul.documents li a:contains('%s')" %
                                      doc.title).length)
        response = client.get(
            reverse('wiki.list_review_tag', args=('technical', )))
        eq_(
            1,
            pq(response.content).find("ul.documents li a:contains('%s')" %
                                      doc.title).length)
        response = client.get(
            reverse('wiki.list_review_tag', args=('editorial', )))
        eq_(
            1,
            pq(response.content).find("ul.documents li a:contains('%s')" %
                                      doc.title).length)

        # Also, ensure that the page appears in the proper feeds
        # HACK: Too lazy to parse the XML. Lazy lazy.
        response = client.get(
            reverse('wiki.feeds.list_review', args=('atom', )))
        ok_('<entry><title>%s</title>' % doc.title in response.content)
        response = client.get(
            reverse('wiki.feeds.list_review_tag', args=(
                'atom',
                'technical',
            )))
        ok_('<entry><title>%s</title>' % doc.title in response.content)
        response = client.get(
            reverse('wiki.feeds.list_review_tag', args=(
                'atom',
                'editorial',
            )))
        ok_('<entry><title>%s</title>' % doc.title in response.content)

        # Post an edit that removes one of the tags.
        data.update({
            'form': 'rev',
            'review_tags': [
                'editorial',
            ],
        })
        response = client.post(reverse('wiki.edit_document', args=[doc.slug]),
                               data)

        # Ensure only one of the tags' warning boxes appears, now.
        response = client.get(reverse('wiki.document', args=[doc.slug]), data)
        page = pq(response.content)
        eq_(0, page.find('.warning.review-technical').length)
        eq_(1, page.find('.warning.review-editorial').length)

        # Ensure the page appears on the listing pages
        response = client.get(reverse('wiki.list_review'))
        eq_(
            1,
            pq(response.content).find("ul.documents li a:contains('%s')" %
                                      doc.title).length)
        response = client.get(
            reverse('wiki.list_review_tag', args=('technical', )))
        eq_(
            0,
            pq(response.content).find("ul.documents li a:contains('%s')" %
                                      doc.title).length)
        response = client.get(
            reverse('wiki.list_review_tag', args=('editorial', )))
        eq_(
            1,
            pq(response.content).find("ul.documents li a:contains('%s')" %
                                      doc.title).length)

        # Also, ensure that the page appears in the proper feeds
        # HACK: Too lazy to parse the XML. Lazy lazy.
        response = client.get(
            reverse('wiki.feeds.list_review', args=('atom', )))
        ok_('<entry><title>%s</title>' % doc.title in response.content)
        response = client.get(
            reverse('wiki.feeds.list_review_tag', args=(
                'atom',
                'technical',
            )))
        ok_('<entry><title>%s</title>' % doc.title not in response.content)
        response = client.get(
            reverse('wiki.feeds.list_review_tag', args=(
                'atom',
                'editorial',
            )))
        ok_('<entry><title>%s</title>' % doc.title in response.content)