class AccountEmailTests(test_utils.TestCase): fixtures = ['test_users.json'] def setUp(self): self.client = LocalizingClient() def test_account_email_page_requires_signin(self): url = reverse('account_email') r = self.client.get(url, follow=True) eq_(200, r.status_code) ok_(len(r.redirect_chain) > 0) ok_('Sign In' in r.content) def test_account_email_page(self): u = User.objects.get(username='******') self.client.login(username=u.username, password=TESTUSER_PASSWORD) url = reverse('account_email') r = self.client.get(url) test_strings = ['Make Primary', 'Re-send Verification', 'Remove', 'Add Email', 'Edit profile'] eq_(200, r.status_code) for test_string in test_strings: ok_(test_string in r.content)
class DemoListViewsTest(test_utils.TestCase): fixtures = ['test_users.json'] def setUp(self): self.user, self.admin_user, self.other_user = make_users() self.client = LocalizingClient() def test_all_demos_includes_hidden_for_staff(self): build_submission(self.user) build_hidden_submission(self.user) r = self.client.get(reverse('demos_all')) count = pq(r.content)('h2.count').text() eq_(count, "1 Demo") self.client.login(username=self.admin_user.username, password='******') r = self.client.get(reverse('demos_all')) count = pq(r.content)('h2.count').text() eq_(count, "2 Demos") @attr('bug882709') def test_search_view(self): try: self.client.get(reverse('demos_search')) except: self.fail("Search should not ISE.")
class SocialAccountConnectionsTests(test_utils.TestCase): fixtures = ['test_users.json'] def setUp(self): self.client = LocalizingClient() def test_account_connections_page_requires_signin(self): url = reverse('socialaccount_connections') r = self.client.get(url, follow=True) eq_(200, r.status_code) ok_(len(r.redirect_chain) > 0) ok_('Sign In' in r.content) def test_account_connections_page(self): u = User.objects.get(username='******') self.client.login(username=u.username, password=TESTUSER_PASSWORD) url = reverse('socialaccount_connections') r = self.client.get(url) test_strings = ['Disconnect', 'Connect a new account', 'Edit profile'] eq_(200, r.status_code) for test_string in test_strings: ok_(test_string in r.content, msg="Expected %s in content" % test_string)
class DemoListViewsTest(test_utils.TestCase): fixtures = ["test_users.json"] def setUp(self): self.user, self.admin_user, self.other_user = make_users() self.client = LocalizingClient() def test_all_demos_includes_hidden_for_staff(self): build_submission(self.user) build_hidden_submission(self.user) r = self.client.get(reverse("demos_all")) count = pq(r.content)("h2.count").text() eq_(count, "1 Demo") self.client.login(username=self.admin_user.username, password="******") r = self.client.get(reverse("demos_all")) count = pq(r.content)("h2.count").text() eq_(count, "2 Demos") @attr("bug882709") def test_search_view(self): try: self.client.get(reverse("demos_search")) except: self.fail("Search should not ISE.")
class EventsViewsTest(test_utils.TestCase): fixtures = ['calendar.json'] def setUp(self): self.client = LocalizingClient() calendar_reload() def test_events(self): url = reverse('events') r = self.client.get(url, follow=True) eq_(200, r.status_code) def test_events_map_flag(self): url = reverse('events') r = self.client.get(url, follow=True) eq_(200, r.status_code) doc = pq(r.content) eq_([], doc.find('#map_canvas')) ok_("maps.google.com" not in r.content) events_map_flag = Flag.objects.create(name='events_map', everyone=True) events_map_flag.save() r = self.client.get(url, follow=True) eq_(200, r.status_code) doc = pq(r.content) eq_(1, len(doc.find('#map_canvas'))) ok_("maps.google.com" in r.content)
class LandingViewsTest(test_utils.TestCase): fixtures = ['test_data.json', ] def setUp(self): self.client = LocalizingClient() def test_home(self): url = reverse('landing.views.home') r = self.client.get(url, follow=True) eq_(200, r.status_code) def test_promote_buttons(self): url = reverse('landing.views.promote_buttons') r = self.client.get(url, follow=True) eq_(200, r.status_code)
class ViewTests(TestCase): fixtures = ['test_users.json', 'wiki/documents.json'] def setUp(self): self.client = LocalizingClient() def mk_request(self, user=None, ip='192.168.123.123', user_agent='FakeBrowser 1.0'): request = HttpRequest() request.user = user and user or AnonymousUser() request.method = 'GET' request.META['REMOTE_ADDR'] = ip request.META['HTTP_USER_AGENT'] = user_agent return request def test_flagged_view(self): request = self.mk_request() objects_to_flag = [ {'obj': save_valid_submission(), 'flag_type': 'notworking', 'explanation': 'I am not good at computer.'}, {'obj': Document.objects.get(pk=4), 'flag_type': 'bad', 'explanation': 'This is in fact not a pipe.'}, {'obj': Document.objects.get(pk=8), 'flag_type': 'unneeded', 'explanation': 'Camels are for Perl, not Python.'}, ] for o in objects_to_flag: flag, created = ContentFlag.objects.flag(request=request, object=o['obj'], flag_type=o['flag_type'], explanation=o['explanation']) resp = self.client.get(reverse('contentflagging.flagged')) eq_(200, resp.status_code)
class ViewTests(TestCase): fixtures = ["test_users.json", "wiki/documents.json"] def setUp(self): self.client = LocalizingClient() def mk_request(self, user=None, ip="192.168.123.123", user_agent="FakeBrowser 1.0"): request = HttpRequest() request.user = user and user or AnonymousUser() request.method = "GET" request.META["REMOTE_ADDR"] = ip request.META["HTTP_USER_AGENT"] = user_agent return request def test_flagged_view(self): request = self.mk_request() objects_to_flag = [ {"obj": save_valid_submission(), "flag_type": "notworking", "explanation": "I am not good at computer."}, {"obj": Document.objects.get(pk=4), "flag_type": "bad", "explanation": "This is in fact not a pipe."}, { "obj": Document.objects.get(pk=8), "flag_type": "unneeded", "explanation": "Camels are for Perl, not Python.", }, ] for o in objects_to_flag: flag, created = ContentFlag.objects.flag( request=request, object=o["obj"], flag_type=o["flag_type"], explanation=o["explanation"] ) resp = self.client.get(reverse("contentflagging.flagged")) eq_(200, resp.status_code)
class HomeTests(test_utils.TestCase): def setUp(self): self.client = LocalizingClient() def test_google_analytics(self): url = reverse('landing.views.home') with override_constance_settings(GOOGLE_ANALYTICS_ACCOUNT='0'): r = self.client.get(url, follow=True) eq_(200, r.status_code) ok_('ga(\'create' not in r.content) with override_constance_settings(GOOGLE_ANALYTICS_ACCOUNT='UA-99999999-9'): r = self.client.get(url, follow=True) eq_(200, r.status_code) ok_('ga(\'create' in r.content)
def test_breadcrumb(): """Make sure breadcrumb links start with /.""" c = LocalizingClient() response = c.get(reverse('search')) doc = pq(response.content) href = doc('.breadcrumbs a')[0] eq_('/', href.attrib['href'][0])
class HomeTests(test_utils.TestCase): def setUp(self): self.client = LocalizingClient() def test_google_analytics(self): url = reverse('landing.views.home') with override_constance_settings(GOOGLE_ANALYTICS_ACCOUNT='0'): r = self.client.get(url, follow=True) eq_(200, r.status_code) ok_('var _gaq' not in r.content) with override_constance_settings( GOOGLE_ANALYTICS_ACCOUNT='UA-99999999-9'): r = self.client.get(url, follow=True) eq_(200, r.status_code) ok_('var _gaq' in r.content)
class LandingViewsTest(test_utils.TestCase): fixtures = [ 'test_data.json', ] def setUp(self): self.client = LocalizingClient() def test_home(self): url = reverse('landing.views.home') r = self.client.get(url, follow=True) eq_(200, r.status_code) def test_promote_buttons(self): url = reverse('landing.views.promote_buttons') r = self.client.get(url, follow=True) eq_(200, r.status_code)
def test_ban_middleware(self): """Ban middleware functions correctly.""" client = LocalizingClient() client.login(username='******', password='******') resp = client.get('/') self.assertTemplateNotUsed(resp, 'users/user_banned.html') admin = User.objects.get(username='******') testuser = User.objects.get(username='******') ban = UserBan(user=testuser, by=admin, reason='Banned by unit test.', is_active=True) ban.save() resp = client.get('/') self.assertTemplateUsed(resp, 'users/user_banned.html')
def test_ban_permission(self): """The ban permission controls access to the ban view.""" client = LocalizingClient() admin = User.objects.get(username='******') testuser = User.objects.get(username='******') # testuser doesn't have ban permission, can't ban. client.login(username='******', password='******') ban_url = reverse('users.ban_user', kwargs={'user_id': admin.id}) resp = client.get(ban_url) eq_(302, resp.status_code) ok_(str(settings.LOGIN_URL) in resp['Location']) client.logout() # admin has ban permission, can ban. client.login(username='******', password='******') ban_url = reverse('users.ban_user', kwargs={'user_id': testuser.id}) resp = client.get(ban_url) eq_(200, resp.status_code)
class LandingViewsTest(test_utils.TestCase): fixtures = ['test_data.json', ] def setUp(self): self.client = LocalizingClient() def test_home(self): url = reverse('landing.views.home') r = self.client.get(url, follow=True) eq_(200, r.status_code) def test_search(self): raise SkipTest('Search test disabled until we switch to kuma wiki') url = reverse('landing.views.search') r = self.client.get(url, follow=True) eq_(200, r.status_code) def test_promote_buttons(self): url = reverse('landing.views.promote_buttons') r = self.client.get(url, follow=True) eq_(200, r.status_code)
def test_404_already_logged_in(self): """The login buttons should not display on the 404 page when the user is logged in""" client = LocalizingClient() # View page as a logged in user client.login(username='******', password='******') response = client.get('/something-doesnt-exist', follow=True) doc = pq(response.content) login_block = doc.find('.socialaccount_providers') eq_(len(login_block), 0) eq_(404, response.status_code) client.logout()
def test_ban_permission(self): """The ban permission controls access to the ban view.""" client = LocalizingClient() admin = User.objects.get(username='******') testuser = User.objects.get(username='******') # testuser doesn't have ban permission, can't ban. client.login(username='******', password='******') ban_url = reverse('users.ban_user', kwargs={'user_id': admin.id}) resp = client.get(ban_url) eq_(302, resp.status_code) ok_(settings.LOGIN_URL in resp['Location']) client.logout() # admin has ban permission, can ban. client.login(username='******', password='******') ban_url = reverse('users.ban_user', kwargs={'user_id': testuser.id}) resp = client.get(ban_url) eq_(200, resp.status_code)
class LandingViewsTest(test_utils.TestCase): fixtures = ['test_data.json'] def setUp(self): self.client = LocalizingClient() def test_home(self): url = reverse('landing.views.home') r = self.client.get(url, follow=True) eq_(200, r.status_code) def test_promote_buttons(self): url = reverse('landing.views.promote_buttons') r = self.client.get(url, follow=True) eq_(200, r.status_code) def test_contribute_json(self): # using the non-localizing client here as contribute.json # is not-localizable client = Client() r = client.get(reverse('contribute_json')) eq_(200, r.status_code) ok_('application/json' in r['Content-Type'])
class LandingViewsTest(test_utils.TestCase): fixtures = [ 'test_data.json', ] def setUp(self): self.client = LocalizingClient() def test_home(self): url = reverse('landing.views.home') r = self.client.get(url, follow=True) eq_(200, r.status_code) def test_search(self): raise SkipTest('Search test disabled until we switch to kuma wiki') url = reverse('landing.views.search') r = self.client.get(url, follow=True) eq_(200, r.status_code) def test_promote_buttons(self): url = reverse('landing.views.promote_buttons') r = self.client.get(url, follow=True) eq_(200, r.status_code)
class LearnViewsTest(test_utils.TestCase): def setUp(self): self.client = LocalizingClient() def test_learn(self): url = reverse('landing.views.learn') r = self.client.get(url, follow=True) eq_(200, r.status_code) def test_learn_html(self): url = reverse('landing.views.learn_html') r = self.client.get(url, follow=True) eq_(200, r.status_code) def test_learn_css(self): url = reverse('landing.views.learn_css') r = self.client.get(url, follow=True) eq_(200, r.status_code) def test_learn_javascript(self): url = reverse('landing.views.learn_javascript') r = self.client.get(url, follow=True) eq_(200, r.status_code)
class ViewTests(TestCase): fixtures = ['test_users.json', 'wiki/documents.json'] def setUp(self): self.client = LocalizingClient() def mk_request(self, user=None, ip='192.168.123.123', user_agent='FakeBrowser 1.0'): request = HttpRequest() request.user = user and user or AnonymousUser() request.method = 'GET' request.META['REMOTE_ADDR'] = ip request.META['HTTP_USER_AGENT'] = user_agent return request def test_flagged_view(self): request = self.mk_request() objects_to_flag = [ { 'obj': save_valid_submission(), 'flag_type': 'notworking', 'explanation': 'I am not good at computer.' }, { 'obj': Document.objects.get(pk=4), 'flag_type': 'bad', 'explanation': 'This is in fact not a pipe.' }, { 'obj': Document.objects.get(pk=8), 'flag_type': 'unneeded', 'explanation': 'Camels are for Perl, not Python.' }, ] for o in objects_to_flag: flag, created = ContentFlag.objects.flag( request=request, object=o['obj'], flag_type=o['flag_type'], explanation=o['explanation']) resp = self.client.get(reverse('contentflagging.flagged')) eq_(200, resp.status_code)
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 a[href*="login"]') eq_(choices.length, 1) @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], locale="en-US") 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") @logged_in def test_edit_no_tags(self): s = save_valid_submission("hello world") edit_url = reverse("demos_edit", args=[s.slug]) r = self.client.post( edit_url, data=dict( title=s.title, summary="This is a test edit", description="Some description goes here", license_name="gpl", accept_terms="1", ), ) eq_(r.status_code, 302) r = self.client.get(edit_url) eq_(r.status_code, 200) @logged_in def test_edit_with_challenge_tag(self): s = save_valid_submission("hello world") edit_url = reverse("demos_edit", args=[s.slug]) r = self.client.post( edit_url, data=dict( title=s.title, summary="This is a test edit", description="Some description goes here", tech_tags=("tech:audio",), challenge_tags=parse_tags(constance.config.DEMOS_DEVDERBY_CHALLENGE_CHOICE_TAGS)[0], license_name="gpl", accept_terms="1", ), ) eq_(r.status_code, 302) r = self.client.get(edit_url) eq_(r.status_code, 200) def test_challenge_tag_to_date_parts(self): tag = "challenge:2011:october" eq_(challenge_utils.challenge_tag_to_date_parts(tag), (2011, 10)) def test_challenge_tag_to_end_date(self): tag = "challenge:2011:october" eq_(challenge_utils.challenge_tag_to_end_date(tag), datetime.date(2011, 10, 31)) tag = "challenge:2011:february" eq_(challenge_utils.challenge_tag_to_end_date(tag), datetime.date(2011, 2, 28)) tag = "challenge:2012:february" eq_(challenge_utils.challenge_tag_to_end_date(tag), datetime.date(2012, 2, 29)) def test_challenge_closed(self): open_tag = "challenge:%s" % make_challenge_tag() closed_dt = datetime.date.today() - datetime.timedelta(days=32) closed_tag = "challenge:%s" % closed_dt.strftime("%Y:%B").lower() assert not challenge_utils.challenge_closed([open_tag]) assert challenge_utils.challenge_closed([closed_tag]) def test_challenge_closed_model(self): s = save_valid_submission("hellow world") assert not s.challenge_closed() s.taggit_tags.set_ns("challenge:", make_challenge_tag()) assert not s.challenge_closed() closed_dt = datetime.date.today() - datetime.timedelta(days=32) s.taggit_tags.set_ns("challenge:", closed_dt.strftime("%Y:%B").lower()) assert s.challenge_closed() def test_derby_before_deadline(self): s = save_valid_submission("hello world") s.taggit_tags.set_ns("challenge:", make_challenge_tag()) form = SubmissionEditForm(instance=s) assert "demo_package" in form.fields assert "challenge_tags" in form.fields def test_derby_after_deadline(self): s = save_valid_submission("hello world") closed_dt = datetime.date.today() - datetime.timedelta(days=32) s.taggit_tags.set_ns("challenge:", closed_dt.strftime("%Y:%B").lower()) form = SubmissionEditForm(instance=s) assert "demo_package" not in form.fields assert "challenge_tags" not in form.fields @logged_in def test_derby_tag_saving(self): """ There's some tricky bits in the handling of editing and saving challenge tags; this test just exercises a cycle of edit/save a couple times in a row to make sure we don't go foul in there. """ s = save_valid_submission("hello world") closed_dt = datetime.date.today() - datetime.timedelta(days=32) s.taggit_tags.set_ns("challenge:", closed_dt.strftime("%Y:%B").lower()) edit_url = reverse("demos_edit", args=[s.slug]) r = self.client.get(edit_url) eq_(r.status_code, 200) 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 s.slug in r["Location"] r = self.client.get(edit_url) eq_(r.status_code, 200) 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 s.slug in r["Location"] r = self.client.get(edit_url) eq_(r.status_code, 200) @attr("bug702156") def test_missing_screenshots_no_exceptions(self): """Demo with missing screenshots should not cause exceptions in views""" # Create the submission... s = save_valid_submission("hello world") s.taggit_tags.set_ns("tech:", "javascript") s.featured = True s.save() # Ensure the new screenshot and thumbnail URL code works when there's a # screenshot present. try: r = self.client.get(reverse("demos_all")) r = self.client.get(reverse("demos_tag", args=["tech:javascript"])) r = self.client.get(reverse("demos_detail", args=[s.slug])) r = self.client.get(reverse("demos_feed_recent", args=["atom"])) r = self.client.get(reverse("demos_feed_featured", args=["json"])) except: ok_(False, "No exceptions should have been thrown") # Forcibly delete the screenshot - should not be possible from # user-facing UI per form validation, but we should at least not throw # exceptions. s.screenshot_1.storage.delete(s.screenshot_1.name) s.screenshot_1 = None s.save() # Big bucks, no whammies... try: r = self.client.get(reverse("demos_all")) r = self.client.get(reverse("demos_tag", args=["tech:javascript"])) r = self.client.get(reverse("demos_detail", args=[s.slug])) r = self.client.get(reverse("demos_feed_recent", args=["atom"])) r = self.client.get(reverse("demos_feed_featured", args=["json"])) except: ok_(False, "No exceptions should have been thrown") @attr("bug745902") def test_long_slug(self): """ A title longer than 50 characters should truncate to a 50-character slug during (python-level) save, not on DB insertion, so that anything that wants the slug to build a URL has the value that actually ends up in the DB. """ s = save_valid_submission("AudioVisualizer for Alternative Music Notation Systems") s.taggit_tags.set_ns("tech:", "javascript") s.save() ok_(len(s.slug) == 50) r = self.client.get(reverse("demos.views.detail", args=(s.slug,))) ok_(r.status_code == 200) @attr("bug781823") def test_unicode(self): """ Unicode characters in the summary or description doesn't brick the feed """ s = save_valid_submission("ΦOTOS ftw", "ΦOTOS ΦOTOS ΦOTOS") s.featured = 1 s.save() r = self.client.get(reverse("demos_feed_featured", args=["json"])) ok_(r.status_code == 200) def test_make_unique_slug(self): """ Ensure that unique slugs are generated even from titles whose first 50 characters are identical. """ s = save_valid_submission( "This is a really long title whose only purpose in life is to be " "longer than fifty characters" ) s2 = save_valid_submission( "This is a really long title whose only purpose in life is to be " "longer than fifty characters and not the same as the first title" ) s3 = save_valid_submission( "This is a really long title whose only purpose in life is to be " "longer than fifty characters and not the same as the first or " "second title" ) ok_(s.slug != s2.slug and s.slug != s3.slug and s2.slug != s3.slug)
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('article').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_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 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) 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('article h1').text()) u = User.objects.get(username='******') eq_(old_email, u.email)
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() # TODO: upgrade mock to 0.8.0 so we can do this. """ self.lookup = mock.patch('basket.lookup_user') self.subscribe = mock.patch('basket.subscribe') self.unsubscribe = mock.patch('basket.unsubscribe') self.lookup.return_value = mock_lookup_user() self.subscribe.return_value = True self.unsubscribe.return_value = True self.lookup.start() self.subscribe.start() self.unsubscribe.start() def tearDown(self): self.lookup.stop() self.subscribe.stop() self.unsubscribe.stop() """ 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('basket.lookup_user') @mock.patch('basket.subscribe') @mock.patch('basket.unsubscribe') @mock.patch('users.views._verify_browserid') def test_valid_assertion_with_new_account_creation(self, _verify_browserid, unsubscribe, subscribe, lookup_user): new_username = '******' new_email = '*****@*****.**' lookup_user.return_value = mock_lookup_user() subscribe.return_value = True unsubscribe.return_value = True _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', 'country': 'us', 'format': 'html' }) # 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('basket.lookup_user') @mock.patch('basket.subscribe') @mock.patch('basket.unsubscribe') @mock.patch('users.views._verify_browserid') def test_valid_assertion_changing_email(self, _verify_browserid, unsubscribe, subscribe, lookup_user): # just need to be authenticated, not necessarily BrowserID self.client.login(username='******', password='******') lookup_user.return_value = mock_lookup_user() subscribe.return_value = True unsubscribe.return_value = True _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('basket.lookup_user') @mock.patch('basket.subscribe') @mock.patch('basket.unsubscribe') @mock.patch('users.views._verify_browserid') def test_valid_assertion_doesnt_steal_email(self, _verify_browserid, unsubscribe, subscribe, lookup_user): # just need to be authenticated, not necessarily BrowserID self.client.login(username='******', password='******') lookup_user.return_value = mock_lookup_user() subscribe.return_value = True unsubscribe.return_value = True _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() # TODO: upgrade mock to 0.8.0 so we can do this. """ self.lookup = mock.patch('basket.lookup_user') self.subscribe = mock.patch('basket.subscribe') self.unsubscribe = mock.patch('basket.unsubscribe') self.lookup.return_value = mock_lookup_user() self.subscribe.return_value = True self.unsubscribe.return_value = True self.lookup.start() self.subscribe.start() self.unsubscribe.start() def tearDown(self): self.lookup.stop() self.subscribe.stop() self.unsubscribe.stop() """ 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('basket.lookup_user') @mock.patch('basket.subscribe') @mock.patch('basket.unsubscribe') @mock.patch('users.views._verify_browserid') @override_settings(CELERY_ALWAYS_EAGER=True) def test_valid_assertion_with_new_account_creation(self, _verify_browserid, unsubscribe, subscribe, lookup_user): Switch.objects.create(name='welcome_email', active=True) new_username = '******' new_email = '*****@*****.**' lookup_user.return_value = mock_lookup_user() subscribe.return_value = True unsubscribe.return_value = True _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', 'country': 'us', 'format': 'html'}) # 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") # Ensure the user was sent a welcome email welcome_email = mail.outbox[0] expected_subject = u'Take the next step to get involved on MDN!' expected_to = [new_email] eq_(expected_subject, welcome_email.subject) eq_(expected_to, welcome_email.to) ok_(u'Hi %s' % new_username in welcome_email.body) @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('basket.lookup_user') @mock.patch('basket.subscribe') @mock.patch('basket.unsubscribe') @mock.patch('users.views._verify_browserid') def test_valid_assertion_changing_email(self, _verify_browserid, unsubscribe, subscribe, lookup_user): # just need to be authenticated, not necessarily BrowserID self.client.login(username='******', password='******') lookup_user.return_value = mock_lookup_user() subscribe.return_value = True unsubscribe.return_value = True _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('basket.lookup_user') @mock.patch('basket.subscribe') @mock.patch('basket.unsubscribe') @mock.patch('users.views._verify_browserid') def test_valid_assertion_doesnt_steal_email(self, _verify_browserid, unsubscribe, subscribe, lookup_user): # just need to be authenticated, not necessarily BrowserID self.client.login(username='******', password='******') lookup_user.return_value = mock_lookup_user() subscribe.return_value = True unsubscribe.return_value = True _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 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) 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('article 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('article').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_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 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', 'country', 'format'): form[fn] = doc.find('#profile-edit *[name="%s"]' % fn).val() form['country'] = 'us' form['format'] = 'html' 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('users.profile', 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('users.profile', 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('users.profile', args=(user.username,)) try: self.client.get(url, follow=True) except PageNotAnInteger: ok_(False, "Non-numeric page number should not cause an error") @mock.patch('basket.lookup_user') @mock.patch('basket.subscribe') @mock.patch('basket.unsubscribe') def test_profile_edit(self, unsubscribe, subscribe, lookup_user): lookup_user.return_value = mock_lookup_user() subscribe.return_value = True unsubscribe.return_value = True profile = UserProfile.objects.get(user__username='******') user = profile.user url = reverse('users.profile', 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('users.profile', 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", country="us", format="html" ) 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('users.profile_edit', args=(u.username,)) in resp['Location']) @mock.patch('basket.lookup_user') @mock.patch('basket.subscribe') @mock.patch('basket.unsubscribe') def test_profile_edit_beta(self, unsubscribe, subscribe, lookup_user): lookup_user.return_value = mock_lookup_user() subscribe.return_value = True unsubscribe.return_value = True user = User.objects.get(username='******') self.client.login(username=user.username, password=TESTUSER_PASSWORD) url = reverse('users.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('users.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')) @mock.patch('basket.lookup_user') @mock.patch('basket.subscribe') @mock.patch('basket.unsubscribe') def test_profile_edit_websites(self, unsubscribe, subscribe, lookup_user): lookup_user.return_value = mock_lookup_user() subscribe.return_value = True unsubscribe.return_value = True user = User.objects.get(username='******') self.client.login(username=user.username, password=TESTUSER_PASSWORD) url = reverse('users.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', u'linkedin': u'https://www.linkedin.com/in/testuser', u'mozillians': u'https://mozillians.org/u/testuser', u'facebook': u'https://www.facebook.com/test.user' } 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('users.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) @mock.patch('basket.lookup_user') @mock.patch('basket.subscribe') @mock.patch('basket.unsubscribe') def test_profile_edit_interests(self, unsubscribe, subscribe, lookup_user): lookup_user.return_value = mock_lookup_user() subscribe.return_value = True unsubscribe.return_value = True user = User.objects.get(username='******') self.client.login(username=user.username, password=TESTUSER_PASSWORD) url = reverse('users.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) @mock.patch('basket.lookup_user') @mock.patch('basket.subscribe') @mock.patch('basket.unsubscribe') def test_bug_709938_interests(self, unsubscribe, subscribe, lookup_user): lookup_user.return_value = mock_lookup_user() subscribe.return_value = True unsubscribe.return_value = True user = User.objects.get(username='******') self.client.login(username=user.username, password=TESTUSER_PASSWORD) url = reverse('users.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()) @mock.patch('basket.lookup_user') @mock.patch('basket.subscribe') @mock.patch('basket.unsubscribe') def test_bug_698126_l10n(self, unsubscribe, subscribe, lookup_user): """Test that the form field names are localized""" lookup_user.return_value = mock_lookup_user() subscribe.return_value = True unsubscribe.return_value = True user = User.objects.get(username='******') self.client.login(username=user.username, password=TESTUSER_PASSWORD) url = reverse('users.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) def test_bug_811751_banned_profile(self): """A banned user's profile should not be viewable""" profile = UserProfile.objects.get(user__username='******') user = profile.user url = reverse('users.profile', args=(user.username,)) # Profile viewable if not banned response = self.client.get(url, follow=True) self.assertNotEqual(response.status_code, 403) # Ban User admin = User.objects.get(username='******') testuser = User.objects.get(username='******') ban = UserBan(user=testuser, by=admin, reason='Banned by unit test.', is_active=True) ban.save() # Profile not viewable if banned response = self.client.get(url, follow=True) self.assertEqual(response.status_code, 403) # Admin can view banned user's profile self.client.login(username='******', password='******') response = self.client.get(url, follow=True) self.assertNotEqual(response.status_code, 403)
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="profile-%s"]' % fn).val() form['country'] = 'us' form['format'] = 'html' 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('users.profile', 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(reverse('users.my_profile')) eq_(302, resp.status_code) ok_(reverse('users.profile', args=(u.username,)) in resp['Location']) def test_bug_698971(self): """A non-numeric page number should not cause an error""" user = User.objects.get(username='******') url = '%s?page=asdf' % reverse('users.profile', args=(user.username,)) try: self.client.get(url, follow=True) except PageNotAnInteger: ok_(False, "Non-numeric page number should not cause an error") @mock.patch('basket.lookup_user') @mock.patch('basket.subscribe') @mock.patch('basket.unsubscribe') def test_profile_edit(self, unsubscribe, subscribe, lookup_user): lookup_user.return_value = mock_lookup_user() subscribe.return_value = True unsubscribe.return_value = True profile = UserProfile.objects.get(user__username='******') user = profile.user url = reverse('users.profile', 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('users.profile', 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="profile-fullname"]').val()) eq_(profile.title, doc.find('#profile-edit input[name="profile-title"]').val()) eq_(profile.organization, doc.find('#profile-edit input[name="profile-organization"]').val()) eq_(profile.location, doc.find('#profile-edit input[name="profile-location"]').val()) eq_(profile.irc_nickname, doc.find('#profile-edit input[name="profile-irc_nickname"]').val()) new_attrs = { 'profile-email': '*****@*****.**', 'profile-fullname': "Another Name", 'profile-title': "Another title", 'profile-organization': "Another org", 'profile-country': "us", 'profile-format': "html" } r = self.client.post(url, new_attrs, follow=True) doc = pq(r.content) eq_(1, doc.find('#profile-head').length) eq_(new_attrs['profile-fullname'], doc.find('#profile-head .main .fn').text()) eq_(new_attrs['profile-title'], doc.find('#profile-head .info .title').text()) eq_(new_attrs['profile-organization'], doc.find('#profile-head .info .org').text()) profile = UserProfile.objects.get(user__username=user.username) eq_(new_attrs['profile-fullname'], profile.fullname) eq_(new_attrs['profile-title'], profile.title) eq_(new_attrs['profile-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(reverse('users.my_profile_edit')) eq_(302, resp.status_code) ok_(reverse('users.profile_edit', args=(u.username,)) in resp['Location']) @mock.patch('basket.lookup_user') @mock.patch('basket.subscribe') @mock.patch('basket.unsubscribe') def test_profile_edit_beta(self, unsubscribe, subscribe, lookup_user): lookup_user.return_value = mock_lookup_user() subscribe.return_value = True unsubscribe.return_value = True user = User.objects.get(username='******') self.client.login(username=user.username, password=TESTUSER_PASSWORD) url = reverse('users.profile_edit', args=(user.username,)) r = self.client.get(url, follow=True) doc = pq(r.content) eq_(None, doc.find('input#id_profile-beta').attr('checked')) form = self._get_current_form_field_values(doc) form['profile-beta'] = True r = self.client.post(url, form, follow=True) url = reverse('users.profile_edit', args=(user.username,)) r = self.client.get(url, follow=True) doc = pq(r.content) eq_('checked', doc.find('input#id_profile-beta').attr('checked')) @mock.patch('basket.lookup_user') @mock.patch('basket.subscribe') @mock.patch('basket.unsubscribe') def test_profile_edit_websites(self, unsubscribe, subscribe, lookup_user): lookup_user.return_value = mock_lookup_user() subscribe.return_value = True unsubscribe.return_value = True user = User.objects.get(username='******') self.client.login(username=user.username, password=TESTUSER_PASSWORD) url = reverse('users.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', u'linkedin': u'https://www.linkedin.com/in/testuser', u'mozillians': u'https://mozillians.org/u/testuser', u'facebook': u'https://www.facebook.com/test.user' } form = self._get_current_form_field_values(doc) # Fill out the form with websites. form.update(dict(('profile-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('users.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="profile-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(('profile-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 #profiles .%s .errorlist' for n in ('website', 'twitter', 'stackoverflow'): eq_(1, doc.find(tmpl % n).length) @mock.patch('basket.lookup_user') @mock.patch('basket.subscribe') @mock.patch('basket.unsubscribe') def test_profile_edit_interests(self, unsubscribe, subscribe, lookup_user): lookup_user.return_value = mock_lookup_user() subscribe.return_value = True unsubscribe.return_value = True user = User.objects.get(username='******') self.client.login(username=user.username, password=TESTUSER_PASSWORD) url = reverse('users.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['profile-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['profile-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['profile-expertise'] = ', '.join(test_expertise) r = self.client.post(url, form, follow=True) doc = pq(r.content) eq_(1, doc.find('.error #id_profile-expertise').length) @mock.patch('basket.lookup_user') @mock.patch('basket.subscribe') @mock.patch('basket.unsubscribe') def test_bug_709938_interests(self, unsubscribe, subscribe, lookup_user): lookup_user.return_value = mock_lookup_user() subscribe.return_value = True unsubscribe.return_value = True user = User.objects.get(username='******') self.client.login(username=user.username, password=TESTUSER_PASSWORD) url = reverse('users.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['profile-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()) @mock.patch('basket.lookup_user') @mock.patch('basket.subscribe') @mock.patch('basket.unsubscribe') def test_bug_698126_l10n(self, unsubscribe, subscribe, lookup_user): """Test that the form field names are localized""" lookup_user.return_value = mock_lookup_user() subscribe.return_value = True unsubscribe.return_value = True user = User.objects.get(username='******') self.client.login(username=user.username, password=TESTUSER_PASSWORD) url = reverse('users.profile_edit', args=(user.username,)) r = self.client.get(url, follow=True) for field in r.context['profile_form'].fields: # if label is localized it's a lazy proxy object ok_(not isinstance( r.context['profile_form'].fields[field].label, basestring), 'Field %s is a string!' % field)
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", "country", "format", ): form[fn] = doc.find('#profile-edit *[name="%s"]' % fn).val() form["country"] = "us" form["format"] = "html" 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") @mock.patch("basket.lookup_user") @mock.patch("basket.subscribe") @mock.patch("basket.unsubscribe") def test_profile_edit(self, unsubscribe, subscribe, lookup_user): lookup_user.return_value = mock_lookup_user() subscribe.return_value = True unsubscribe.return_value = True 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", country="us", format="html", ) 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"]) @mock.patch("basket.lookup_user") @mock.patch("basket.subscribe") @mock.patch("basket.unsubscribe") def test_profile_edit_beta(self, unsubscribe, subscribe, lookup_user): lookup_user.return_value = mock_lookup_user() subscribe.return_value = True unsubscribe.return_value = True 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")) @mock.patch("basket.lookup_user") @mock.patch("basket.subscribe") @mock.patch("basket.unsubscribe") def test_profile_edit_websites(self, unsubscribe, subscribe, lookup_user): lookup_user.return_value = mock_lookup_user() subscribe.return_value = True unsubscribe.return_value = True 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", u"linkedin": u"https://www.linkedin.com/in/testuser", u"mozillians": u"https://mozillians.org/u/testuser", u"facebook": u"https://www.facebook.com/test.user", } 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) @mock.patch("basket.lookup_user") @mock.patch("basket.subscribe") @mock.patch("basket.unsubscribe") def test_profile_edit_interests(self, unsubscribe, subscribe, lookup_user): lookup_user.return_value = mock_lookup_user() subscribe.return_value = True unsubscribe.return_value = True 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) @mock.patch("basket.lookup_user") @mock.patch("basket.subscribe") @mock.patch("basket.unsubscribe") def test_bug_709938_interests(self, unsubscribe, subscribe, lookup_user): lookup_user.return_value = mock_lookup_user() subscribe.return_value = True unsubscribe.return_value = True 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() @mock.patch("basket.lookup_user") @mock.patch("basket.subscribe") @mock.patch("basket.unsubscribe") def test_bug_698126_l10n(self, unsubscribe, subscribe, lookup_user): """Test that the form field names are localized""" lookup_user.return_value = mock_lookup_user() subscribe.return_value = True unsubscribe.return_value = True 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 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 a[href*="signin"]') eq_(choices.length, 1) @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], locale='en-US') 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') @logged_in def test_edit_no_tags(self): s = save_valid_submission('hello world') edit_url = reverse('demos_edit', args=[s.slug]) r = self.client.post(edit_url, data=dict( title=s.title, summary='This is a test edit', description='Some description goes here', license_name='gpl', accept_terms='1', )) eq_(r.status_code, 302) r = self.client.get(edit_url) eq_(r.status_code, 200) @logged_in def test_edit_with_challenge_tag(self): s = save_valid_submission('hello world') edit_url = reverse('demos_edit', args=[s.slug]) r = self.client.post( edit_url, data=dict( title=s.title, summary='This is a test edit', description='Some description goes here', tech_tags=('tech:audio', ), challenge_tags=parse_tags( constance.config.DEMOS_DEVDERBY_CHALLENGE_CHOICE_TAGS)[0], license_name='gpl', accept_terms='1', )) eq_(r.status_code, 302) r = self.client.get(edit_url) eq_(r.status_code, 200) def test_challenge_tag_to_date_parts(self): tag = 'challenge:2011:october' eq_(challenge_utils.challenge_tag_to_date_parts(tag), (2011, 10)) def test_challenge_tag_to_end_date(self): tag = 'challenge:2011:october' eq_(challenge_utils.challenge_tag_to_end_date(tag), datetime.date(2011, 10, 31)) tag = 'challenge:2011:february' eq_(challenge_utils.challenge_tag_to_end_date(tag), datetime.date(2011, 2, 28)) tag = 'challenge:2012:february' eq_(challenge_utils.challenge_tag_to_end_date(tag), datetime.date(2012, 2, 29)) def test_challenge_closed(self): open_tag = 'challenge:%s' % make_challenge_tag() closed_dt = datetime.date.today() - datetime.timedelta(days=32) closed_tag = 'challenge:%s' % closed_dt.strftime('%Y:%B').lower() assert not challenge_utils.challenge_closed([open_tag]) assert challenge_utils.challenge_closed([closed_tag]) def test_challenge_closed_model(self): s = save_valid_submission('hellow world') assert not s.challenge_closed() s.taggit_tags.set_ns('challenge:', make_challenge_tag()) assert not s.challenge_closed() closed_dt = datetime.date.today() - datetime.timedelta(days=32) s.taggit_tags.set_ns('challenge:', closed_dt.strftime('%Y:%B').lower()) assert s.challenge_closed() def test_derby_before_deadline(self): s = save_valid_submission('hello world') s.taggit_tags.set_ns('challenge:', make_challenge_tag()) form = SubmissionEditForm(instance=s) assert 'demo_package' in form.fields assert 'challenge_tags' in form.fields def test_derby_after_deadline(self): s = save_valid_submission('hello world') closed_dt = datetime.date.today() - datetime.timedelta(days=32) s.taggit_tags.set_ns('challenge:', closed_dt.strftime('%Y:%B').lower()) form = SubmissionEditForm(instance=s) assert 'demo_package' not in form.fields assert 'challenge_tags' not in form.fields @logged_in def test_derby_tag_saving(self): """ There's some tricky bits in the handling of editing and saving challenge tags; this test just exercises a cycle of edit/save a couple times in a row to make sure we don't go foul in there. """ s = save_valid_submission('hello world') closed_dt = datetime.date.today() - datetime.timedelta(days=32) s.taggit_tags.set_ns('challenge:', closed_dt.strftime('%Y:%B').lower()) edit_url = reverse('demos_edit', args=[s.slug]) r = self.client.get(edit_url) eq_(r.status_code, 200) 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 s.slug in r['Location'] r = self.client.get(edit_url) eq_(r.status_code, 200) 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 s.slug in r['Location'] r = self.client.get(edit_url) eq_(r.status_code, 200) @attr('bug702156') def test_missing_screenshots_no_exceptions(self): """Demo with missing screenshots should not cause exceptions in views""" # Create the submission... s = save_valid_submission('hello world') s.taggit_tags.set_ns('tech:', 'javascript') s.featured = True s.save() # Ensure the new screenshot and thumbnail URL code works when there's a # screenshot present. try: r = self.client.get(reverse('demos_all')) r = self.client.get(reverse('demos_tag', args=['tech:javascript'])) r = self.client.get(reverse('demos_detail', args=[s.slug])) r = self.client.get(reverse('demos_feed_recent', args=['atom'])) r = self.client.get(reverse('demos_feed_featured', args=['json'])) except: ok_(False, "No exceptions should have been thrown") # Forcibly delete the screenshot - should not be possible from # user-facing UI per form validation, but we should at least not throw # exceptions. s.screenshot_1.storage.delete(s.screenshot_1.name) s.screenshot_1 = None s.save() # Big bucks, no whammies... try: r = self.client.get(reverse('demos_all')) r = self.client.get(reverse('demos_tag', args=['tech:javascript'])) r = self.client.get(reverse('demos_detail', args=[s.slug])) r = self.client.get(reverse('demos_feed_recent', args=['atom'])) r = self.client.get(reverse('demos_feed_featured', args=['json'])) except: ok_(False, "No exceptions should have been thrown") @attr('bug745902') def test_long_slug(self): """ A title longer than 50 characters should truncate to a 50-character slug during (python-level) save, not on DB insertion, so that anything that wants the slug to build a URL has the value that actually ends up in the DB. """ s = save_valid_submission( "AudioVisualizer for Alternative Music Notation Systems") s.taggit_tags.set_ns('tech:', 'javascript') s.save() ok_(len(s.slug) == 50) r = self.client.get(reverse('kuma.demos.views.detail', args=(s.slug, ))) ok_(r.status_code == 200) @attr('bug781823') def test_unicode(self): """ Unicode characters in the summary or description doesn't brick the feed """ s = save_valid_submission('ΦOTOS ftw', 'ΦOTOS ΦOTOS ΦOTOS') s.featured = 1 s.save() r = self.client.get(reverse('demos_feed_featured', args=['json'])) ok_(r.status_code == 200) def test_make_unique_slug(self): """ Ensure that unique slugs are generated even from titles whose first 50 characters are identical. """ s = save_valid_submission( "This is a really long title whose only purpose in life is to be " "longer than fifty characters") s2 = save_valid_submission( "This is a really long title whose only purpose in life is to be " "longer than fifty characters and not the same as the first title") s3 = save_valid_submission( "This is a really long title whose only purpose in life is to be " "longer than fifty characters and not the same as the first or " "second title") ok_(s.slug != s2.slug and s.slug != s3.slug and s2.slug != s3.slug)