class ReminderEmailTestCase(TestCase): fixtures = ['test_users.json'] def setUp(self): self.client = LocalizingClient() @mock.patch_object(Site.objects, 'get_current') def test_reminder_email(self, get_current): """Should send simple email reminder to user.""" get_current.return_value.domain = 'dev.mo.org' response = self.client.post(reverse('users.send_email_reminder'), {'username': '******'}, follow=True) eq_(200, response.status_code) eq_(1, len(mail.outbox)) email = mail.outbox[0] assert email.subject.find('Email Address Reminder') == 0 assert 'testuser' in email.body @mock.patch_object(Site.objects, 'get_current') def test_unknown_user_no_email_sent(self, get_current): """Should send simple email reminder to user.""" get_current.return_value.domain = 'dev.mo.org' response = self.client.post(reverse('users.send_email_reminder'), {'username': '******'}, follow=True) eq_(200, response.status_code) eq_(0, len(mail.outbox))
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'))
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)
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.')
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)
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)
class AppsViewsTest(test_utils.TestCase): def setUp(self): self.client = LocalizingClient() @patch('landing.views.basket.subscribe') def test_apps_subscription(self, subscribe): subscribe.return_value = True url = reverse('landing.views.apps_newsletter') r = self.client.post(url, {'format': 'html', 'email': '*****@*****.**', 'agree': 'checked'}, follow=True) eq_(200, r.status_code) # assert thank you message self.assertContains(r, 'Thank you') eq_(1, subscribe.call_count) @patch('landing.views.basket.subscribe') def test_apps_subscription_bad_values(self, subscribe): subscribe.return_value = True url = reverse('landing.views.apps_newsletter') r = self.client.post(url, {'format': 1, 'email': 'nope'}) eq_(200, r.status_code) # assert error self.assertContains(r, 'Enter a valid e-mail address.') self.assertContains(r, 'Select a valid choice.') self.assertContains(r, 'You must agree to the privacy policy.')
class AppsViewsTest(test_utils.TestCase): def setUp(self): self.client = LocalizingClient() def test_apps_menu_item(self): url = reverse("landing.views.home") r = self.client.get(url) eq_(200, r.status_code) doc = pq(r.content) nav_sub_topics = doc.find("ul#nav-sub-topics") ok_(nav_sub_topics) apps_item = nav_sub_topics.find("li#nav-sub-apps") eq_("Apps", apps_item.text()) def test_apps(self): url = reverse("landing.views.apps") r = self.client.get(url, follow=True) eq_(200, r.status_code) doc = pq(r.content) signup_form = doc.find("form.fm-subscribe") eq_(reverse("apps_subscription", locale="en-US"), signup_form.attr("action")) @patch("landing.views.basket.subscribe") def test_apps_subscription(self, subscribe): subscribe.return_value = True url = reverse("landing.views.apps_subscription") r = self.client.post(url, {"format": "html", "email": "*****@*****.**", "agree": "checked"}, follow=True) eq_(200, r.status_code) # assert thank you message self.assertContains(r, "Thank you") eq_(1, subscribe.call_count) @patch("landing.views.basket.subscribe") def test_apps_subscription_ajax(self, subscribe): subscribe.return_value = True url = reverse("landing.views.apps_subscription") r = self.client.post( url, {"format": "html", "email": "*****@*****.**", "agree": "checked"}, HTTP_X_REQUESTED_WITH="XMLHttpRequest", ) eq_(200, r.status_code) # assert thank you message self.assertContains(r, "Thank you") self.assertNotContains(r, "<html") self.assertNotContains(r, "<head>") self.assertNotContains(r, "<title>") eq_(1, subscribe.call_count) @patch("landing.views.basket.subscribe") def test_apps_subscription_bad_values(self, subscribe): subscribe.return_value = True url = reverse("landing.views.apps_subscription") r = self.client.post(url, {"format": 1, "email": "nope"}) eq_(200, r.status_code) # assert error self.assertContains(r, "Enter a valid e-mail address.") self.assertContains(r, "Select a valid choice.") self.assertContains(r, "You must agree to the privacy policy.")
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'))
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'])
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
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.')
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'))
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()
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())
class AppsViewsTest(SkippedTestCase): def setUp(self): self.client = LocalizingClient() super(AppsViewsTest, self).setUp() def _good_newsletter_post(self): url = reverse('landing.views.apps_newsletter') r = self.client.post(url, {'format': 'html', 'country': 'pt', 'email': '*****@*****.**', 'agree': 'checked'}, follow=True) eq_(200, r.status_code) return r @patch('landing.views.basket.subscribe') def test_apps_subscription(self, subscribe): subscribe.return_value = {'status': 'success'} r = self._good_newsletter_post() # assert thank you message self.assertContains(r, 'Thank you') eq_(1, subscribe.call_count) @patch('landing.views.basket.subscribe') def test_apps_subscription_bad_values(self, subscribe): subscribe.return_value = True url = reverse('landing.views.apps_newsletter') r = self.client.post(url, {'format': 1, 'email': 'nope'}) eq_(200, r.status_code) # assert error self.assertContains(r, 'Enter a valid e-mail address.') self.assertContains(r, 'Select a valid choice.') self.assertContains(r, 'You must agree to the privacy policy.') @patch('landing.views.basket.subscribe') def test_apps_subscription_exception_retry(self, subscribe): subscribe.side_effect = basket.base.BasketException("500!") subscribe.return_value = True self._good_newsletter_post() eq_(constance.config.BASKET_RETRIES, subscribe.call_count)
class AppsViewsTest(test_utils.TestCase): def setUp(self): self.client = LocalizingClient() def _good_newsletter_post(self): url = reverse('landing.views.apps_newsletter') r = self.client.post(url, { 'format': 'html', 'country': 'pt', 'email': '*****@*****.**', 'agree': 'checked' }, follow=True) eq_(200, r.status_code) return r @patch('landing.views.basket.subscribe') def test_apps_subscription(self, subscribe): subscribe.return_value = {'status': 'success'} r = self._good_newsletter_post() # assert thank you message self.assertContains(r, 'Thank you') eq_(1, subscribe.call_count) @patch('landing.views.basket.subscribe') def test_apps_subscription_bad_values(self, subscribe): subscribe.return_value = True url = reverse('landing.views.apps_newsletter') r = self.client.post(url, {'format': 1, 'email': 'nope'}) eq_(200, r.status_code) # assert error self.assertContains(r, 'Enter a valid e-mail address.') self.assertContains(r, 'Select a valid choice.') self.assertContains(r, 'You must agree to the privacy policy.') @patch('landing.views.basket.subscribe') def test_apps_subscription_exception_retry(self, subscribe): subscribe.side_effect = basket.base.BasketException("500!") subscribe.return_value = True self._good_newsletter_post() eq_(constance.config.BASKET_RETRIES, subscribe.call_count)
class ReminderEmailTestCase(TestCase): fixtures = ["test_users.json"] def setUp(self): self.client = LocalizingClient() @mock.patch_object(Site.objects, "get_current") def test_reminder_email(self, get_current): """Should send simple email reminder to user.""" get_current.return_value.domain = "dev.mo.org" response = self.client.post(reverse("users.send_email_reminder"), {"username": "******"}, follow=True) eq_(200, response.status_code) eq_(1, len(mail.outbox)) email = mail.outbox[0] assert email.subject.find("Email Address Reminder") == 0 assert "testuser" in email.body @mock.patch_object(Site.objects, "get_current") def test_unknown_user_no_email_sent(self, get_current): """Should send simple email reminder to user.""" get_current.return_value.domain = "dev.mo.org" response = self.client.post(reverse("users.send_email_reminder"), {"username": "******"}, follow=True) eq_(200, response.status_code) eq_(0, len(mail.outbox)) @mock.patch_object(Site.objects, "get_current") def test_user_without_email_message(self, get_current): """Should send simple email reminder to user.""" get_current.return_value.domain = "dev.mo.org" u = User.objects.get(username="******") u.email = "" u.save() response = self.client.post(reverse("users.send_email_reminder"), {"username": "******"}, follow=True) eq_(200, response.status_code) eq_(0, len(mail.outbox)) ok_("Could not find email" in response.content) ok_("file a bug" in response.content)
class AppsViewsTest(SkippedTestCase): def setUp(self): self.client = LocalizingClient() super(AppsViewsTest, self).setUp() def _good_newsletter_post(self): url = reverse("landing.views.apps_newsletter") r = self.client.post( url, {"format": "html", "country": "pt", "email": "*****@*****.**", "agree": "checked"}, follow=True ) eq_(200, r.status_code) return r @patch("landing.views.basket.subscribe") def test_apps_subscription(self, subscribe): subscribe.return_value = {"status": "success"} r = self._good_newsletter_post() # assert thank you message self.assertContains(r, "Thank you") eq_(1, subscribe.call_count) @patch("landing.views.basket.subscribe") def test_apps_subscription_bad_values(self, subscribe): subscribe.return_value = True url = reverse("landing.views.apps_newsletter") r = self.client.post(url, {"format": 1, "email": "nope"}) eq_(200, r.status_code) # assert error self.assertContains(r, "Enter a valid e-mail address.") self.assertContains(r, "Select a valid choice.") self.assertContains(r, "You must agree to the privacy policy.") @patch("landing.views.basket.subscribe") def test_apps_subscription_exception_retry(self, subscribe): subscribe.side_effect = basket.base.BasketException("500!") subscribe.return_value = True self._good_newsletter_post() eq_(constance.config.BASKET_RETRIES, subscribe.call_count)
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")
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))
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())
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)
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())
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)
class LoginTestCase(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 @mock.patch_object(Site.objects, 'get_current') def test_bad_login_fails_both_backends(self, get_current): get_current.return_value.domain = 'dev.mo.org' self.assertRaises(User.DoesNotExist, User.objects.get, username='******') response = self.client.post(reverse('users.login'), {'username': '******', 'password': '******'}, follow=True) eq_(200, response.status_code) self.assertContains(response, 'Please enter a correct username and ' 'password.') @mock.patch_object(Site.objects, 'get_current') def test_django_login(self, get_current): get_current.return_value.domain = 'dev.mo.org' response = self.client.post(reverse('users.login'), {'username': '******', 'password': '******'}, follow=True) eq_(200, response.status_code) doc = pq(response.content) eq_('testuser', doc.find('ul.user-state a:first').text()) @mock.patch_object(Site.objects, 'get_current') def test_django_login_wont_redirect_to_login(self, get_current): get_current.return_value.domain = 'dev.mo.org' login_uri = reverse('users.login') response = self.client.post(login_uri, {'username': '******', 'password': '******', 'next': login_uri}, follow=True) eq_(200, response.status_code) for redirect_url, code in response.redirect_chain: ok_(login_uri not in redirect_url, "Found %s in redirect_chain" % login_uri) doc = pq(response.content) eq_('testuser', doc.find('ul.user-state a:first').text()) @mock.patch_object(Site.objects, 'get_current') def test_logged_in_message(self, get_current): get_current.return_value.domain = 'dev.mo.org' login_uri = reverse('users.login') response = self.client.post(login_uri, {'username': '******', 'password': '******'}, follow=True) eq_(200, response.status_code) response = self.client.get(login_uri, follow=True) eq_(200, response.status_code) doc = pq(response.content) eq_("You are already logged in.", doc.find('div#content-main').text()) @mock.patch_object(Site.objects, 'get_current') def test_django_login_redirects_to_next(self, get_current): get_current.return_value.domain = 'dev.mo.org' login_uri = reverse('users.login') response = self.client.post(login_uri, {'username': '******', 'password': '******'}, follow=True) eq_(200, response.status_code) response = self.client.get(login_uri, {'next': '/en-US/demos/submit'}, follow=True) eq_('http://testserver/en-US/demos/submit', response.redirect_chain[0][0]) @mock.patch('dekicompat.backends.DekiUserBackend.mindtouch_login') def test_mindtouch_disabled_login(self, mock_mindtouch_login): """When DEKIWIKI_ENDPOINT unavailable, skip MindTouch auth.""" # 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 # Try to log in as a MindTouch user, assert that MindTouch auth was # never attempted. _old = settings.DEKIWIKI_ENDPOINT settings.DEKIWIKI_ENDPOINT = False self.client.post(reverse('users.login'), {'username': '******', 'password': '******'}, follow=True) settings.DEKIWIKI_ENDPOINT = _old ok_(not trap['was_called']) @mock_mindtouch_login @mock_get_deki_user @mock_put_mindtouch_user @mock.patch_object(Site.objects, 'get_current') def test_mindtouch_creds_create_user_and_profile(self, get_current): if not settings.DEKIWIKI_ENDPOINT: # Don't even bother with this test, if there's no MindTouch API raise SkipTest() get_current.return_value.domain = 'dev.mo.org' if not getattr(settings, 'DEKIWIKI_MOCK', False): # HACK: Ensure that expected user details are in MindTouch when not # mocking the API mt_email = '*****@*****.**' 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) passwd_url = '%s/@api/deki/users/%s/password?apikey=%s' % ( settings.DEKIWIKI_ENDPOINT, '=testaccount', settings.DEKIWIKI_APIKEY) requests.put(passwd_url, data='theplanet') self.assertRaises(User.DoesNotExist, User.objects.get, username='******') # Try to log in as a MindTouch user response = self.client.post(reverse('users.login'), {'username': '******', 'password': '******'}, follow=True) eq_(200, response.status_code) # Ensure there are no validation errors page = pq(response.content) eq_(0, page.find('.errorlist').length, "There should be no validation errors in login") # Login should have auto-created django user u = User.objects.get(username='******') eq_(True, u.is_active) ok_(u.get_profile()) # Login page should show welcome back doc = pq(response.content) eq_('testaccount', doc.find('ul.user-state a:first').text()) @mock.patch_object(Site.objects, 'get_current') def test_clean_next_url_request_properties(self, get_current): '''_clean_next_url checks POST, GET, and REFERER''' get_current.return_value.domain = 'dev.mo.org' r = RequestFactory().get('/users/login', {'next': '/demos/submit'}, HTTP_REFERER='referer-trumped-by-get') eq_('/demos/submit', _clean_next_url(r)) r = RequestFactory().post('/users/login', {'next': '/demos/submit'}) eq_('/demos/submit', _clean_next_url(r)) r = RequestFactory().get('/users/login', HTTP_REFERER='/demos/submit') eq_('/demos/submit', _clean_next_url(r)) @mock.patch_object(Site.objects, 'get_current') def test_clean_next_url_no_self_redirects(self, get_current): '''_clean_next_url checks POST, GET, and REFERER''' get_current.return_value.domain = 'dev.mo.org' for next in [settings.LOGIN_URL, settings.LOGOUT_URL]: r = RequestFactory().get('/users/login', {'next': next}) eq_(None, _clean_next_url(r)) @mock.patch_object(Site.objects, 'get_current') def test_clean_next_url_invalid_next_parameter(self, get_current): '''_clean_next_url cleans invalid urls''' get_current.return_value.domain = 'dev.mo.org' for next in self._invalid_nexts(): r = RequestFactory().get('/users/login', {'next': next}) eq_(None, _clean_next_url(r)) @mock.patch_object(Site.objects, 'get_current') def test_login_invalid_next_parameter(self, get_current): '''Test with an invalid ?next=http://example.com parameter.''' get_current.return_value.domain = 'testserver.com' valid_next = reverse('home', locale=settings.LANGUAGE_CODE) for invalid_next in self._invalid_nexts(): # Verify that _valid_ next parameter is set in form hidden field. response = self.client.get(urlparams(reverse('users.login'), next=invalid_next)) eq_(200, response.status_code) doc = pq(response.content) eq_(valid_next, doc('input[name="next"]')[0].attrib['value']) # Verify that it gets used on form POST. response = self.client.post(reverse('users.login'), {'username': '******', 'password': '******', 'next': invalid_next}) eq_(302, response.status_code) eq_('http://testserver' + valid_next, response['location']) self.client.logout() def _invalid_nexts(self): return ['http://foobar.com/evil/', '//goo.gl/y-bad']
class RegisterTestCase(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 @mock_missing_get_deki_user @mock_put_mindtouch_user @mock_post_mindtouch_user @mock.patch_object(Site.objects, 'get_current') def test_new_user(self, get_current): get_current.return_value.domain = 'su.mo.com' now = time() username = '******' % now response = self.client.post(reverse('users.register'), {'username': username, 'email': '*****@*****.**', 'password': '******', 'password2': 'foo'}, follow=True) eq_(200, response.status_code) u = User.objects.get(username=username) assert u.password.startswith('sha256') assert not u.is_active eq_(1, len(mail.outbox)) assert mail.outbox[0].subject.find('Please confirm your') == 0 key = RegistrationProfile.objects.all()[0].activation_key assert mail.outbox[0].body.find('activate/%s' % key) > 0 # Now try to log in u.is_active = True u.save() response = self.client.post(reverse('users.login'), {'username': username, 'password': '******'}, follow=True) eq_(200, response.status_code) eq_('http://testserver/en-US/', response.redirect_chain[0][0]) @mock_missing_get_deki_user @mock_post_mindtouch_user @mock_put_mindtouch_user @mock.patch_object(Site.objects, 'get_current') def test_unicode_password(self, get_current): get_current.return_value.domain = 'su.mo.com' now = time() username = '******' % now u_str = u'\xe5\xe5\xee\xe9\xf8\xe7\u6709\u52b9' response = self.client.post(reverse('users.register', locale='ja'), {'username': username, 'email': '*****@*****.**', 'password': u_str, 'password2': u_str}, follow=True) eq_(200, response.status_code) u = User.objects.get(username=username) u.is_active = True u.save() assert u.password.startswith('sha256') # make sure you can login now response = self.client.post(reverse('users.login', locale='ja'), {'username': username, 'password': u_str}, follow=True) eq_(200, response.status_code) eq_('http://testserver/ja/', response.redirect_chain[0][0]) @mock_put_mindtouch_user @mock_post_mindtouch_user @mock.patch_object(Site.objects, 'get_current') def test_new_user_activation(self, get_current): get_current.return_value.domain = 'su.mo.com' now = time() username = '******' % now user = RegistrationProfile.objects.create_inactive_user( username, 'testpass', '*****@*****.**') assert not user.is_active key = RegistrationProfile.objects.all()[0].activation_key url = reverse('users.activate', args=[key]) response = self.client.get(url, follow=True) eq_(200, response.status_code) user = User.objects.get(pk=user.pk) assert user.is_active @mock_put_mindtouch_user @mock_post_mindtouch_user @mock.patch_object(Site.objects, 'get_current') def test_new_user_claim_watches(self, get_current): """Claim user watches upon activation.""" old, settings.CELERY_ALWAYS_EAGER = settings.CELERY_ALWAYS_EAGER, True get_current.return_value.domain = 'su.mo.com' watch(email='*****@*****.**', save=True) now = time() username = '******' % now user = RegistrationProfile.objects.create_inactive_user( username, 'testpass', '*****@*****.**') key = RegistrationProfile.objects.all()[0].activation_key self.client.get(reverse('users.activate', args=[key]), follow=True) # Watches are claimed. assert user.watch_set.exists() settings.CELERY_ALWAYS_EAGER = old @mock_get_deki_user def test_duplicate_username(self): response = self.client.post(reverse('users.register'), {'username': '******', 'email': '*****@*****.**', 'password': '******', 'password2': 'foo'}, follow=True) self.assertContains(response, 'already exists') @mock_get_deki_user def test_duplicate_mindtouch_username(self): if not settings.DEKIWIKI_ENDPOINT: # Don't even bother with this test, if there's no MindTouch API raise SkipTest() response = self.client.post(reverse('users.register'), {'username': '******', 'email': '*****@*****.**', 'password': '******', 'password2': 'foo'}, follow=True) self.assertContains(response, 'already exists') @mock_get_deki_user def test_duplicate_email(self): User.objects.create(username='******', email='*****@*****.**').save() response = self.client.post(reverse('users.register'), {'username': '******', 'email': '*****@*****.**', 'password': '******', 'password2': 'foo'}, follow=True) self.assertContains(response, 'already exists') @mock_get_deki_user def test_no_match_passwords(self): response = self.client.post(reverse('users.register'), {'username': '******', 'email': '*****@*****.**', 'password': '******', 'password2': 'bar'}, follow=True) self.assertContains(response, 'must match')
class ChangeEmailTestCase(TestCase): fixtures = ['users.json'] def setUp(self): self.client = LocalizingClient() def test_redirect(self): """Test our redirect from old url to new one.""" response = self.client.get(reverse('users.old_change_email', locale='en-US'), follow=False) eq_(301, response.status_code) eq_('http://testserver/en-US/users/change_email', response['location']) @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) 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 = '*****@*****.**' User.objects.filter(username='******').update(email=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 User.objects.filter(username='******').update(email=new_email) # 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 rrosario', doc('#main h1').text()) u = User.objects.get(username='******') eq_(old_email, u.email)
class LoginTestCase(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 @mock.patch_object(Site.objects, 'get_current') def test_bad_login_fails_both_backends(self, get_current): get_current.return_value.domain = 'dev.mo.org' self.assertRaises(User.DoesNotExist, User.objects.get, username='******') response = self.client.post(reverse('users.login'), {'username': '******', 'password': '******'}, follow=True) eq_(200, response.status_code) self.assertContains(response, 'Please enter a correct username and ' 'password.') @mock.patch_object(Site.objects, 'get_current') def test_django_login(self, get_current): get_current.return_value.domain = 'dev.mo.org' response = self.client.post(reverse('users.login'), {'username': '******', 'password': '******'}, follow=True) eq_(200, response.status_code) doc = pq(response.content) eq_('testuser', doc.find('ul.user-state a:first').text()) @mock.patch_object(Site.objects, 'get_current') def test_django_login_wont_redirect_to_login(self, get_current): get_current.return_value.domain = 'dev.mo.org' login_uri = reverse('users.login') response = self.client.post(login_uri, {'username': '******', 'password': '******', 'next': login_uri}, follow=True) eq_(200, response.status_code) for redirect_url, code in response.redirect_chain: ok_(login_uri not in redirect_url, "Found %s in redirect_chain" % login_uri) doc = pq(response.content) eq_('testuser', doc.find('ul.user-state a:first').text()) @mock.patch_object(Site.objects, 'get_current') def test_logged_in_message(self, get_current): get_current.return_value.domain = 'dev.mo.org' login_uri = reverse('users.login') response = self.client.post(login_uri, {'username': '******', 'password': '******'}, follow=True) eq_(200, response.status_code) response = self.client.get(login_uri, follow=True) eq_(200, response.status_code) doc = pq(response.content) eq_("You are already logged in.", doc.find('div#content-main').text()) @mock.patch_object(Site.objects, 'get_current') def test_django_login_redirects_to_next(self, get_current): get_current.return_value.domain = 'dev.mo.org' login_uri = reverse('users.login') response = self.client.post(login_uri, {'username': '******', 'password': '******'}, follow=True) eq_(200, response.status_code) response = self.client.get(login_uri, {'next': '/en-US/demos/submit'}, follow=True) eq_('http://testserver/en-US/demos/submit', response.redirect_chain[0][0]) @mock.patch('dekicompat.backends.DekiUserBackend.mindtouch_login') def test_mindtouch_disabled_login(self, mock_mindtouch_login): """When DEKIWIKI_ENDPOINT unavailable, skip MindTouch auth.""" # 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 # Try to log in as a MindTouch user, assert that MindTouch auth was # never attempted. _old = settings.DEKIWIKI_ENDPOINT settings.DEKIWIKI_ENDPOINT = False self.client.post(reverse('users.login'), {'username': '******', 'password': '******'}, follow=True) settings.DEKIWIKI_ENDPOINT = _old ok_(not trap['was_called']) @mock_mindtouch_login @mock_get_deki_user @mock_put_mindtouch_user @mock.patch_object(Site.objects, 'get_current') def test_mindtouch_creds_create_user_and_profile(self, get_current): if not settings.DEKIWIKI_ENDPOINT: # Don't even bother with this test, if there's no MindTouch API raise SkipTest() get_current.return_value.domain = 'dev.mo.org' if not getattr(settings, 'DEKIWIKI_MOCK', False): # HACK: Ensure that expected user details are in MindTouch when not # mocking the API mt_email = '*****@*****.**' 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) passwd_url = '%s/@api/deki/users/%s/password?apikey=%s' % ( settings.DEKIWIKI_ENDPOINT, '=testaccount', settings.DEKIWIKI_APIKEY) requests.put(passwd_url, data='theplanet') self.assertRaises(User.DoesNotExist, User.objects.get, username='******') # Try to log in as a MindTouch user response = self.client.post(reverse('users.login'), {'username': '******', 'password': '******'}, follow=True) eq_(200, response.status_code) # Ensure there are no validation errors page = pq(response.content) eq_(0, page.find('.errorlist').length, "There should be no validation errors in login") # Login should have auto-created django user u = User.objects.get(username='******') eq_(True, u.is_active) ok_(u.get_profile()) # Login page should show welcome back doc = pq(response.content) eq_('testaccount', doc.find('ul.user-state a:first').text())
class DemoViewsTest(test_utils.TestCase): fixtures = ['test_users.json'] def setUp(self): self.testuser = User.objects.get(username='******') self.testuser.set_password(TESTUSER_PASSWORD) self.testuser.save() self.client = LocalizingClient() def test_submit_loggedout(self): r = self.client.get(reverse('demos_submit')) choices = pq(r.content)('p.choices') eq_(choices.find('a.button').length, 2) @logged_in def test_submit_loggedin(self): r = self.client.get(reverse('demos_submit')) assert pq(r.content)('form#demo-submit') @logged_in def test_submit_post_invalid(self): r = self.client.post(reverse('demos_submit'), data={}) d = pq(r.content) assert d('form#demo-submit') assert d('li#field_title ul.errorlist') assert d('li#field_summary ul.errorlist') assert d('li#field_screenshot_1 ul.errorlist') assert d('li#field_demo_package ul.errorlist') assert d('li#field_license_name ul.errorlist') assert d('li#field_captcha ul.errorlist') assert d('li#field_accept_terms ul.errorlist') @logged_in @disable_captcha def test_submit_post_valid(self): # Create a valid demo zip file zf_fout = StringIO() zf = zipfile.ZipFile(zf_fout, 'w') zf.writestr('index.html', """<html></html>""") zf.close() # Create a new file for input zf_fin = StringIO(zf_fout.getvalue()) zf_fin.name = 'demo.zip' r = self.client.post(reverse('demos_submit'), data=dict( title='Test submission', summary='This is a test demo submission', description='Some description goes here', tech_tags=('tech:audio', 'tech:video', 'tech:websockets',), screenshot_1=open(SCREENSHOT_PATH), demo_package=zf_fin, license_name='gpl', accept_terms='1', )) eq_(302, r.status_code) assert 'Location' in r assert 'test-submission' in r['Location'] try: obj = Submission.objects.get(slug='test-submission') eq_('Test submission', obj.title) except Submission.DoesNotExist: assert False result_tags = [t.name for t in obj.taggit_tags.all_ns('tech:')] result_tags.sort() eq_(['tech:audio', 'tech:video', 'tech:websockets'], result_tags) @logged_in def test_edit_invalid(self): s = save_valid_submission() edit_url = reverse('demos_edit', args=[s.slug]) r = self.client.post(edit_url, data=dict()) d = pq(r.content) assert d('form#demo-submit') assert d('li#field_title ul.errorlist') assert d('li#field_summary ul.errorlist') assert d('li#field_license_name ul.errorlist') @logged_in def test_edit_valid(self): s = save_valid_submission() edit_url = reverse('demos_edit', args=[s.slug]) r = self.client.post(edit_url, data=dict( title=s.title, summary='This is a test demo submission', description='Some description goes here', tech_tags=('tech:audio', 'tech:video', 'tech:websockets',), license_name='gpl', accept_terms='1', )) eq_(302, r.status_code) assert 'Location' in r assert 'hello-world' in r['Location'] try: obj = Submission.objects.get(slug='hello-world') eq_('This is a test demo submission', obj.summary) except Submission.DoesNotExist: assert False def test_detail(self): s = save_valid_submission('hello world') url = reverse('demos_detail', args=[s.slug]) r = self.client.get(url) d = pq(r.content) eq_(s.title, d('h1.page-title').text()) edit_link = d('ul.manage a.edit') assert not edit_link def test_detail_censored(self): s = save_valid_submission('hello world') s.censored = True s.save() url = reverse('demos_detail', args=[s.slug]) r = self.client.get(url) d = pq(r.content) eq_('Permission Denied', d('h1.page-title').text()) def test_detail_censored_url(self): s = save_valid_submission('hello world') s.censored = True s.censored_url = "http://developer.mozilla.org" s.save() url = reverse('demos_detail', args=[s.slug]) r = self.client.get(url) eq_(302, r.status_code) eq_("http://developer.mozilla.org", r['Location']) @logged_in def test_creator_can_edit(self): s = save_valid_submission('hello world') url = reverse('demos_detail', args=[s.slug]) r = self.client.get(url) d = pq(r.content) edit_link = d('ul#demo-manage a.edit') assert edit_link edit_url = reverse('demos_edit', args=[s.slug]) eq_(edit_url, edit_link.attr("href")) r = self.client.get(edit_url) assert pq(r.content)('form#demo-submit') eq_('Save changes', pq(r.content)('p.fm-submit button[type="submit"]').text()) @logged_in def test_hidden_field(self): s = save_valid_submission('hello world') edit_url = reverse('demos_edit', args=[s.slug]) r = self.client.get(edit_url) assert pq(r.content)('input[name="hidden"][type="checkbox"]') @logged_in def test_derby_field(self): s = save_valid_submission('hello world') edit_url = reverse('demos_edit', args=[s.slug]) r = self.client.get(edit_url) assert pq(r.content)('fieldset#devderby-submit')
class LoginTestCase(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 @mock.patch_object(Site.objects, 'get_current') def test_bad_login_fails_both_backends(self, get_current): get_current.return_value.domain = 'dev.mo.org' self.assertRaises(User.DoesNotExist, User.objects.get, username='******') response = self.client.post(reverse('users.login'), { 'username': '******', 'password': '******' }, follow=True) eq_(200, response.status_code) self.assertContains(response, 'Please enter a correct username and ' 'password.') @mock.patch_object(Site.objects, 'get_current') def test_django_login(self, get_current): get_current.return_value.domain = 'dev.mo.org' response = self.client.post(reverse('users.login'), { 'username': '******', 'password': '******' }, follow=True) eq_(200, response.status_code) doc = pq(response.content) eq_('testuser', doc.find('ul.user-state a:first').text()) @mock.patch_object(Site.objects, 'get_current') def test_django_login_wont_redirect_to_login(self, get_current): get_current.return_value.domain = 'dev.mo.org' login_uri = reverse('users.login') response = self.client.post(login_uri, { 'username': '******', 'password': '******', 'next': login_uri }, follow=True) eq_(200, response.status_code) for redirect_url, code in response.redirect_chain: ok_(login_uri not in redirect_url, "Found %s in redirect_chain" % login_uri) doc = pq(response.content) eq_('testuser', doc.find('ul.user-state a:first').text()) @mock.patch_object(Site.objects, 'get_current') def test_logged_in_message(self, get_current): get_current.return_value.domain = 'dev.mo.org' login_uri = reverse('users.login') response = self.client.post(login_uri, { 'username': '******', 'password': '******' }, follow=True) eq_(200, response.status_code) response = self.client.get(login_uri, follow=True) eq_(200, response.status_code) doc = pq(response.content) eq_("You are already logged in.", doc.find('div#content-main').text()) @mock.patch_object(Site.objects, 'get_current') def test_django_login_redirects_to_next(self, get_current): get_current.return_value.domain = 'dev.mo.org' login_uri = reverse('users.login') response = self.client.post(login_uri, { 'username': '******', 'password': '******' }, follow=True) eq_(200, response.status_code) response = self.client.get(login_uri, {'next': '/en-US/demos/submit'}, follow=True) eq_('http://testserver/en-US/demos/submit', response.redirect_chain[0][0]) @mock.patch('dekicompat.backends.DekiUserBackend.mindtouch_login') def test_mindtouch_disabled_login(self, mock_mindtouch_login): """When DEKIWIKI_ENDPOINT unavailable, skip MindTouch auth.""" # 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 # Try to log in as a MindTouch user, assert that MindTouch auth was # never attempted. _old = settings.DEKIWIKI_ENDPOINT settings.DEKIWIKI_ENDPOINT = False response = self.client.post(reverse('users.login'), { 'username': '******', 'password': '******' }, follow=True) settings.DEKIWIKI_ENDPOINT = _old ok_(not trap['was_called']) @mock_mindtouch_login @mock_get_deki_user @mock_put_mindtouch_user @mock.patch_object(Site.objects, 'get_current') def test_mindtouch_creds_create_user_and_profile(self, get_current): if not settings.DEKIWIKI_ENDPOINT: # Don't even bother with this test, if there's no MindTouch API raise SkipTest() get_current.return_value.domain = 'dev.mo.org' if not getattr(settings, 'DEKIWIKI_MOCK', False): # HACK: Ensure that expected user details are in MindTouch when not # mocking the API mt_email = '*****@*****.**' 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) passwd_url = '%s/@api/deki/users/%s/password?apikey=%s' % ( settings.DEKIWIKI_ENDPOINT, '=testaccount', settings.DEKIWIKI_APIKEY) requests.put(passwd_url, data='theplanet') self.assertRaises(User.DoesNotExist, User.objects.get, username='******') # Try to log in as a MindTouch user response = self.client.post(reverse('users.login'), { 'username': '******', 'password': '******' }, follow=True) eq_(200, response.status_code) # Ensure there are no validation errors page = pq(response.content) eq_(0, page.find('.errorlist').length, "There should be no validation errors in login") # Login should have auto-created django user u = User.objects.get(username='******') eq_(True, u.is_active) ok_(u.get_profile()) # Login page should show welcome back doc = pq(response.content) eq_('testaccount', doc.find('ul.user-state a:first').text())
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')
class AppsViewsTest(test_utils.TestCase): def setUp(self): self.client = LocalizingClient() def test_apps_menu_item(self): url = reverse('landing.views.home') r = self.client.get(url) eq_(200, r.status_code) doc = pq(r.content) nav_sub_topics = doc.find('ul#nav-sub-topics') ok_(nav_sub_topics) apps_item = nav_sub_topics.find('li#nav-sub-apps') eq_('Apps', apps_item.text()) def test_apps(self): url = reverse('landing.views.apps') r = self.client.get(url, follow=True) eq_(200, r.status_code) doc = pq(r.content) signup_form = doc.find('form.fm-subscribe') eq_(reverse('apps_subscription', locale='en-US'), signup_form.attr('action')) @patch('landing.views.basket.subscribe') def test_apps_subscription(self, subscribe): subscribe.return_value = True url = reverse('landing.views.apps_subscription') r = self.client.post(url, { 'format': 'html', 'email': '*****@*****.**', 'agree': 'checked' }, follow=True) eq_(200, r.status_code) # assert thank you message self.assertContains(r, 'Thank you') eq_(1, subscribe.call_count) @patch('landing.views.basket.subscribe') def test_apps_subscription_ajax(self, subscribe): subscribe.return_value = True url = reverse('landing.views.apps_subscription') r = self.client.post(url, { 'format': 'html', 'email': '*****@*****.**', 'agree': 'checked' }, HTTP_X_REQUESTED_WITH='XMLHttpRequest') eq_(200, r.status_code) # assert thank you message self.assertContains(r, 'Thank you') self.assertNotContains(r, '<html') self.assertNotContains(r, '<head>') self.assertNotContains(r, '<title>') eq_(1, subscribe.call_count) @patch('landing.views.basket.subscribe') def test_apps_subscription_bad_values(self, subscribe): subscribe.return_value = True url = reverse('landing.views.apps_subscription') r = self.client.post(url, {'format': 1, 'email': 'nope'}) eq_(200, r.status_code) # assert error self.assertContains(r, 'Enter a valid e-mail address.') self.assertContains(r, 'Select a valid choice.') self.assertContains(r, 'You must agree to the privacy policy.')
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)
class RegisterTestCase(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 @mock_missing_get_deki_user @mock_put_mindtouch_user @mock_post_mindtouch_user @mock.patch_object(Site.objects, 'get_current') def test_new_user(self, get_current): get_current.return_value.domain = 'su.mo.com' now = time() username = '******' % now response = self.client.post(reverse('users.register'), { 'username': username, 'email': '*****@*****.**', 'password': '******', 'password2': 'foo' }, follow=True) eq_(200, response.status_code) u = User.objects.get(username=username) assert u.password.startswith('sha256') assert not u.is_active eq_(1, len(mail.outbox)) assert mail.outbox[0].subject.find('Please confirm your') == 0 key = RegistrationProfile.objects.all()[0].activation_key assert mail.outbox[0].body.find('activate/%s' % key) > 0 # Now try to log in u.is_active = True u.save() response = self.client.post(reverse('users.login'), { 'username': username, 'password': '******' }, follow=True) eq_(200, response.status_code) eq_('http://testserver/en-US/', response.redirect_chain[0][0]) @mock_missing_get_deki_user @mock_put_mindtouch_user @mock_post_mindtouch_user @mock.patch_object(Site.objects, 'get_current') def test_new_user_posts_mindtouch_user(self, get_current): get_current.return_value.domain = 'su.mo.com' now = time() username = '******' % now response = self.client.post(reverse('users.register'), { 'username': username, 'email': '*****@*****.**', 'password': '******', 'password2': 'foo' }, follow=True) eq_(200, response.status_code) u = User.objects.get(username=username) assert u.password.startswith('sha256') assert not u.is_active eq_(1, len(mail.outbox)) assert mail.outbox[0].subject.find('Please confirm your') == 0 key = RegistrationProfile.objects.all()[0].activation_key assert mail.outbox[0].body.find('activate/%s' % key) > 0 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_(username, doc('username').text()) # Now try to log in u.is_active = True u.save() response = self.client.post(reverse('users.login'), { 'username': username, 'password': '******' }, follow=True) eq_(200, response.status_code) eq_('http://testserver/en-US/', response.redirect_chain[0][0]) @mock_missing_get_deki_user @mock_put_mindtouch_user @mock_perform_post_mindtouch_user @mock.patch_object(Site.objects, 'get_current') def test_new_user_retries_mindtouch_post(self, get_current): if not settings.DEKIWIKI_ENDPOINT: # Don't even bother with this test, if there's no MindTouch API raise SkipTest() get_current.return_value.domain = 'dev.mo.org' now = time() username = '******' % now response = self.client.post(reverse('users.register'), { 'username': username, 'email': '*****@*****.**', 'password': '******', 'password2': 'foo' }, follow=True) eq_(200, response.status_code) ok_("Please try again later." in response.content) self.assertRaises(User.DoesNotExist, User.objects.get, username=username) @mock_missing_get_deki_user @mock_post_mindtouch_user @mock_put_mindtouch_user @mock.patch_object(Site.objects, 'get_current') def test_unicode_password(self, get_current): get_current.return_value.domain = 'su.mo.com' now = time() username = '******' % now u_str = u'\xe5\xe5\xee\xe9\xf8\xe7\u6709\u52b9' response = self.client.post(reverse('users.register', locale='ja'), { 'username': username, 'email': '*****@*****.**', 'password': u_str, 'password2': u_str }, follow=True) eq_(200, response.status_code) u = User.objects.get(username=username) u.is_active = True u.save() assert u.password.startswith('sha256') # make sure you can login now response = self.client.post(reverse('users.login', locale='ja'), { 'username': username, 'password': u_str }, follow=True) eq_(200, response.status_code) eq_('http://testserver/ja/', response.redirect_chain[0][0]) @mock_put_mindtouch_user @mock_post_mindtouch_user @mock.patch_object(Site.objects, 'get_current') def test_new_user_activation(self, get_current): get_current.return_value.domain = 'su.mo.com' now = time() username = '******' % now user = RegistrationProfile.objects.create_inactive_user( username, 'testpass', '*****@*****.**') assert not user.is_active key = RegistrationProfile.objects.all()[0].activation_key url = reverse('users.activate', args=[key]) response = self.client.get(url, follow=True) eq_(200, response.status_code) user = User.objects.get(pk=user.pk) assert user.is_active @mock_put_mindtouch_user @mock_post_mindtouch_user @mock.patch_object(Site.objects, 'get_current') def test_new_user_claim_watches(self, get_current): """Claim user watches upon activation.""" old, settings.CELERY_ALWAYS_EAGER = settings.CELERY_ALWAYS_EAGER, True get_current.return_value.domain = 'su.mo.com' watch(email='*****@*****.**', save=True) now = time() username = '******' % now user = RegistrationProfile.objects.create_inactive_user( username, 'testpass', '*****@*****.**') key = RegistrationProfile.objects.all()[0].activation_key self.client.get(reverse('users.activate', args=[key]), follow=True) # Watches are claimed. assert user.watch_set.exists() settings.CELERY_ALWAYS_EAGER = old @mock_get_deki_user def test_duplicate_username(self): response = self.client.post(reverse('users.register'), { 'username': '******', 'email': '*****@*****.**', 'password': '******', 'password2': 'foo' }, follow=True) self.assertContains(response, 'already exists') @mock_get_deki_user def test_duplicate_mindtouch_username(self): if not settings.DEKIWIKI_ENDPOINT: # Don't even bother with this test, if there's no MindTouch API raise SkipTest() response = self.client.post(reverse('users.register'), { 'username': '******', 'email': '*****@*****.**', 'password': '******', 'password2': 'foo' }, follow=True) self.assertContains(response, 'already exists') @mock_get_deki_user def test_duplicate_email(self): User.objects.create(username='******', email='*****@*****.**').save() response = self.client.post(reverse('users.register'), { 'username': '******', 'email': '*****@*****.**', 'password': '******', 'password2': 'foo' }, follow=True) self.assertContains(response, 'already exists') @mock_get_deki_user def test_no_match_passwords(self): response = self.client.post(reverse('users.register'), { 'username': '******', 'email': '*****@*****.**', 'password': '******', 'password2': 'bar' }, follow=True) self.assertContains(response, 'must match')
class DemoViewsTest(test_utils.TestCase): fixtures = ['test_users.json'] def setUp(self): self.testuser = User.objects.get(username='******') self.testuser.set_password(TESTUSER_PASSWORD) self.testuser.save() self.client = LocalizingClient() def test_submit_loggedout(self): r = self.client.get(reverse('demos_submit')) choices = pq(r.content)('p.choices') eq_(choices.find('a.button').length, 2) @logged_in def test_submit_loggedin(self): r = self.client.get(reverse('demos_submit')) assert pq(r.content)('form#demo-submit') @logged_in def test_submit_post_invalid(self): r = self.client.post(reverse('demos_submit'), data={}) d = pq(r.content) assert d('form#demo-submit') assert d('li#field_title ul.errorlist') assert d('li#field_summary ul.errorlist') assert d('li#field_screenshot_1 ul.errorlist') assert d('li#field_demo_package ul.errorlist') assert d('li#field_license_name ul.errorlist') assert d('li#field_captcha ul.errorlist') assert d('li#field_accept_terms ul.errorlist') @logged_in @disable_captcha def test_submit_post_valid(self): # Create a valid demo zip file zf_fout = StringIO() zf = zipfile.ZipFile(zf_fout, 'w') zf.writestr('index.html', """<html></html>""") zf.close() # Create a new file for input zf_fin = StringIO(zf_fout.getvalue()) zf_fin.name = 'demo.zip' r = self.client.post(reverse('demos_submit'), data=dict( title='Test submission', summary='This is a test demo submission', description='Some description goes here', tech_tags=( 'tech:audio', 'tech:video', 'tech:websockets', ), screenshot_1=open(SCREENSHOT_PATH), demo_package=zf_fin, license_name='gpl', accept_terms='1', )) eq_(302, r.status_code) assert 'Location' in r assert 'test-submission' in r['Location'] try: obj = Submission.objects.get(slug='test-submission') eq_('Test submission', obj.title) except Submission.DoesNotExist: assert False result_tags = [t.name for t in obj.taggit_tags.all_ns('tech:')] result_tags.sort() eq_(['tech:audio', 'tech:video', 'tech:websockets'], result_tags) @logged_in def test_edit_invalid(self): s = save_valid_submission() edit_url = reverse('demos_edit', args=[s.slug]) r = self.client.post(edit_url, data=dict()) d = pq(r.content) assert d('form#demo-submit') assert d('li#field_title ul.errorlist') assert d('li#field_summary ul.errorlist') assert d('li#field_license_name ul.errorlist') @logged_in def test_edit_valid(self): s = save_valid_submission() edit_url = reverse('demos_edit', args=[s.slug]) r = self.client.post(edit_url, data=dict( title=s.title, summary='This is a test demo submission', description='Some description goes here', tech_tags=( 'tech:audio', 'tech:video', 'tech:websockets', ), license_name='gpl', accept_terms='1', )) eq_(302, r.status_code) assert 'Location' in r assert 'hello-world' in r['Location'] try: obj = Submission.objects.get(slug='hello-world') eq_('This is a test demo submission', obj.summary) except Submission.DoesNotExist: assert False def test_detail(self): s = save_valid_submission('hello world') url = reverse('demos_detail', args=[s.slug]) r = self.client.get(url) d = pq(r.content) eq_(s.title, d('h1.page-title').text()) edit_link = d('ul.manage a.edit') assert not edit_link def test_detail_censored(self): s = save_valid_submission('hello world') s.censored = True s.save() url = reverse('demos_detail', args=[s.slug]) r = self.client.get(url) d = pq(r.content) eq_('Permission Denied', d('h1.page-title').text()) def test_detail_censored_url(self): s = save_valid_submission('hello world') s.censored = True s.censored_url = "http://developer.mozilla.org" s.save() url = reverse('demos_detail', args=[s.slug]) r = self.client.get(url) eq_(302, r.status_code) eq_("http://developer.mozilla.org", r['Location']) @logged_in def test_creator_can_edit(self): s = save_valid_submission('hello world') url = reverse('demos_detail', args=[s.slug]) r = self.client.get(url) d = pq(r.content) edit_link = d('ul#demo-manage a.edit') assert edit_link edit_url = reverse('demos_edit', args=[s.slug]) eq_(edit_url, edit_link.attr("href")) r = self.client.get(edit_url) assert pq(r.content)('form#demo-submit') eq_('Save changes', pq(r.content)('p.fm-submit button[type="submit"]').text()) @logged_in def test_hidden_field(self): s = save_valid_submission('hello world') edit_url = reverse('demos_edit', args=[s.slug]) r = self.client.get(edit_url) assert pq(r.content)('input[name="hidden"][type="checkbox"]') @logged_in def test_derby_field(self): s = save_valid_submission('hello world') edit_url = reverse('demos_edit', args=[s.slug]) r = self.client.get(edit_url) assert pq(r.content)('fieldset#devderby-submit')
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())
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.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.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.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 # 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', '')) # 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.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('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.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())
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)
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)