def post(self): name = self.get_argument("name", '') description = self.get_argument("description", '') title = self.get_argument("title", '') user_object = self.get_current_user_object() if not user_object.is_plus(): return self.redirect('/account/membership?upgrade=1') if len(user_object.shakes()) < 101: new_shake = Shake(name=name, title=title, description=description, user_id=user_object.id, type='group') try: if new_shake.save(): return self.redirect('/%s' % (new_shake.name)) except torndb.IntegrityError: # This is a rare edge case, so we handle it lazily -- IK. pass self.add_errors(new_shake.errors) return self.render("shakes/create.html", shake=new_shake) else: return self.render("shakes/no-create.html")
def test_sharedfile_saved_to_group_shake(self): test_files = os.path.join(os.path.dirname(os.path.dirname(__file__)), "files") file_key = Sourcefile.get_sha1_file_key(test_files + "/1.png") shutil.copyfile("%s/1.png" % (test_files), "/tmp/%s" % (file_key)) #create a new shake group_shake = Shake(user_id=self.user.id, type='group', title='asdf', name='asdf') group_shake.save() a_shared_file = Sharedfile.create_from_file("/tmp/%s" % (file_key),"1.png", file_key, "image/png", self.user.id, group_shake.id) self.assertTrue(group_shake.can_update(self.user.id)) a_shared_file.add_to_shake(self.user.shake()) ssfs = Shakesharedfile.all() for ssf in ssfs: self.assertEqual(ssf.sharedfile_id, a_shared_file.id)
def test_can_user_delete_from_shake(self): """ A user can only delete from a shake if they are the owner of the sharedfile or the owner of the shake. """ user_shake = self.user.shake() self.sharedfile.add_to_shake(user_shake) self.assertEqual(True, self.sharedfile.can_user_delete_from_shake(self.user, user_shake)) # A user that doesn't own the sharedfile new_user = User(name='new_user',email='*****@*****.**',verify_email_token='created', email_confirmed=0) new_user.save() self.assertEqual(False, self.sharedfile.can_user_delete_from_shake(new_user, user_shake)) # Owner of a group shake, but file doesn't belong to them. group_shake = Shake(user_id=new_user.id, type='group', title='Bears', name='bears') group_shake.save() self.sharedfile.add_to_shake(group_shake) self.assertEqual(True, self.sharedfile.can_user_delete_from_shake(new_user, group_shake)) # owner of file, but not of shake. self.assertEqual(True, self.sharedfile.can_user_delete_from_shake(self.user, group_shake))
class ShakeModelTests(BaseTestCase): def setUp(self): super(ShakeModelTests, self).setUp() self.user = User(name='admin', email='*****@*****.**', email_confirmed=1, is_paid=1) self.user.set_password('asdfasdf') self.user.save() self.shake = Shake(user_id=self.user.id, name='asdf', type='group', title='My Test Shake', description='Testing this shake test.') self.shake.save() def test_correct_owner_is_returned(self): """ Verifies the owner is correctly returned """ self.assertEqual(self.user.id, self.shake.user_id) def test_correct_page_image_is_returned(self): """ If an image exists, it should return the correct path. """ self.assertEqual(None, self.shake.page_image()) self.assertEqual('/static/images/default-icon-venti.svg', self.user.shake().page_image()) self.shake.image = 1 self.shake.save self.assertEqual( 'https://%s.s3.amazonaws.com/account/1/shake_asdf.jpg' % options.aws_bucket, self.shake.page_image()) def test_correct_thumbnail_url_is_returned(self): """ If an image exists, it should return the correct thumbnail path """ self.assertEqual( 'https://mltshp-cdn.com/static/images/default-icon-venti.svg', self.shake.thumbnail_url()) self.assertEqual( 'https://mltshp-cdn.com/static/images/default-icon-venti.svg', self.user.shake().thumbnail_url()) self.shake.image = 1 self.shake.save() self.assertEqual( 'https://%s.s3.amazonaws.com/account/1/shake_asdf_small.jpg' % options.aws_bucket, self.shake.thumbnail_url()) def test_correct_path_is_returned(self): """ Simply returns the correct path for the shake """ self.assertEqual('/asdf', self.shake.path()) self.assertEqual('/user/admin', self.user.shake().path()) def test_correct_display_name_is_returned(self): """ Display name or title is returned if set. """ self.assertEqual('My Test Shake', self.shake.display_name()) self.assertEqual('admin', self.user.shake().display_name()) def test_user_can_update_shake(self): """ Tests that a user can and cannot update a certain shake """ user1 = User(name='user1', email='*****@*****.**', email_confirmed=1, is_paid=1) user1.set_password('asdfasdf') user1.save() user2 = User(name='user2', email='*****@*****.**', email_confirmed=1, is_paid=1) user2.set_password('asdfasdf') user2.save() self.shake.add_manager(user1) self.assertTrue(self.shake.can_update(user1.id)) self.assertTrue(self.shake.can_update(self.user.id)) self.assertFalse(self.shake.can_update(user2.id)) def test_saving_validates_title(self): """ Creates shakes with valid and invalid titles """ valid_titles = ['asdf', 'This is a test.'] invalid_titles = ['', None] identifier = 1 for title in valid_titles: self.assertTrue( Shake(user_id=self.user.id, title=title, name='testing%s' % (identifier), type='group').save()) identifier += 1 for title in invalid_titles: self.assertFalse( Shake(user_id=self.user.id, title=title, name='testing%s' % (identifier), type='group').save()) identifier += 1 def test_saving_validates_name(self): """ Creates shakes with valid and invalid names """ valid_names = [ 'a-b-c', 'qwerty', '1234', '2a93sfj', 'asdfgasdfgasdfgasdfgasdfg' ] invalid_names = [ '', None, 'a x', 'AsDf', 'static', #asdf exists in the setup, static is reserved 'asdfgasdfgasdfgasdfgasdfgx' ] #too long for name in valid_names: self.assertTrue( Shake(user_id=self.user.id, title="some text", name=name, type='group').save()) for name in invalid_names: self.assertFalse( Shake(user_id=self.user.id, title="some text", name=name, type='group').save()) def test_subscribers(self): """ Tests whether subscribers returned are the subscribers to a particular shake. """ user1 = User(name='user1', email='*****@*****.**', email_confirmed=1, is_paid=1) user1.set_password('asdfasdf') user1.save() user2 = User(name='user2', email='*****@*****.**', email_confirmed=1, is_paid=1) user2.set_password('asdfasdf') user2.save() user1.subscribe(self.shake) user2.subscribe(self.shake) self.assertTrue(user1.id in [s.id for s in self.shake.subscribers()]) self.assertTrue(user2.id in [s.id for s in self.shake.subscribers()]) user1.unsubscribe(self.shake) self.assertFalse(user1.id in [s.id for s in self.shake.subscribers()]) user1.subscribe(self.shake) self.assertTrue(user1.id in [s.id for s in self.shake.subscribers()]) def test_paginated_sharedfiles_and_count(self): """ Tests both the pagination of a shake's shared files and the count """ sharedfiles = [] sourcefile = Sourcefile(width=20, height=20, file_key="asdf", thumb_key="asdf_t") sourcefile.save() for i in range(31): sf = Sharedfile(source_id=sourcefile.id, name="my shared file", user_id=self.user.id, content_type="image/png", share_key="1", description="some\ndescription\nhere", source_url="https://www.mltshp.com/?hi") sf.save() sf.add_to_shake(self.shake) sharedfiles.append(sf) self.assertEqual(len(self.shake.sharedfiles()), 10) #default self.assertEqual(len(self.shake.sharedfiles(page=1)), 10) self.assertEqual(len(self.shake.sharedfiles(page=2)), 10) self.assertEqual(len(self.shake.sharedfiles(page=3)), 10) self.assertEqual(len(self.shake.sharedfiles(page=4)), 1) self.assertEqual(len(self.shake.sharedfiles(page=1, per_page=31)), 31) def test_adding_manager(self): """ Verifies adding a new manager works """ user1 = User(name='user1', email='*****@*****.**', email_confirmed=1, is_paid=1) user1.set_password('asdfasdf') user1.save() self.shake.add_manager(user1) self.assertTrue(user1.id in [m.id for m in self.shake.managers()]) self.shake.remove_manager(user1) self.assertFalse(user1.id in [m.id for m in self.shake.managers()]) self.shake.add_manager(user1) self.assertTrue(user1.id in [m.id for m in self.shake.managers()]) def test_can_edit(self): """ Tests whether a user has the ability to edit a shake """ user1 = User(name='user1', email='*****@*****.**', email_confirmed=1, is_paid=1) user1.set_password('asdfasdf') user1.save() self.assertTrue(self.shake.can_edit(self.user)) self.assertFalse(self.shake.can_edit(user1))
class RequestInvitationTests(test.base.BaseAsyncTestCase): def setUp(self): super(RequestInvitationTests, self).setUp() self.user = User(name='joe', email='*****@*****.**', email_confirmed=1, is_paid=1) self.user.set_password('asdfasdf') self.user.save() self.sign_in("joe", "asdfasdf") self.manager = User(name='admin', email='*****@*****.**', email_confirmed=1, is_paid=1) self.manager.set_password('asdfasdf') self.manager.save() self.shake = Shake(user_id=self.manager.id, type='group', title="derp", name='derp') self.shake.save() def test_posting_request_creates_request(self): response = self.post_url('/shake/derp/request_invitation?json=1') j_response = json_decode(response.body) self.assertEqual(j_response['status'], 'ok') no = Notification.all()[0] self.assertEqual(no.sender_id, self.user.id) self.assertEqual(no.receiver_id, self.manager.id) self.assertEqual(no.action_id, self.shake.id) def test_cannot_request_after_one_already_exists(self): response = self.post_url('/shake/derp/request_invitation?json=1') j_response = json_decode(response.body) self.assertEqual(j_response['status'], 'ok') response = self.post_url('/shake/derp/request_invitation?json=1') j_response = json_decode(response.body) self.assertEqual(j_response['status'], 'error') def test_posting_request_doesnt_recreate_request(self): response = self.post_url('/shake/derp/request_invitation?json=1') j_response = json_decode(response.body) self.assertEqual(j_response['status'], 'ok') no = Notification.all()[0] self.assertEqual(no.sender_id, self.user.id) self.assertEqual(no.receiver_id, self.manager.id) self.assertEqual(no.action_id, self.shake.id) response = self.post_url('/shake/derp/request_invitation?json=1') self.assertEqual(len(Notification.all()), 1) def test_no_button_shows_when_request_has_been_made(self): response = self.post_url('/shake/derp/request_invitation?json=1') response = self.fetch_url('/derp') self.assertTrue(response.body.find('/request_invitation') == -1) def test_shake_manager_gets_notification_created(self): response = self.post_url('/shake/derp/request_invitation?json=1') n = Notification.get('receiver_id = %s', self.manager.id) self.assertEqual(n.sender_id, self.user.id) self.assertEqual(n.action_id, self.shake.id) def test_shake_accept_request_creates_editor(self): self.post_url('/shake/derp/request_invitation?json=1') self.sign_in("admin", "asdfasdf") response = self.post_url('/shake/derp/approve_invitation?json=1', arguments={'user_id': self.user.id}) manager = ShakeManager.get('user_id = %s', self.user.id) self.assertTrue(manager) def test_shake_accept_request_deletes_notification(self): self.post_url('/shake/derp/request_invitation?json=1') self.sign_in("admin", "asdfasdf") response = self.post_url('/shake/derp/approve_invitation?json=1', arguments={'user_id': self.user.id}) n = Notification.get('receiver_id = %s', self.manager.id) self.assertTrue(n.deleted) def test_shake_accept_request_creates_notification(self): self.post_url('/shake/derp/request_invitation?json=1') self.sign_in("admin", "asdfasdf") response = self.post_url('/shake/derp/approve_invitation?json=1', arguments={'user_id': self.user.id}) n = Notification.get('receiver_id = %s and type=%s', self.manager.id, "invitation_request") self.assertTrue(n.deleted) n = Notification.get('receiver_id = %s and type=%s', self.user.id, "invitation_approved") self.assertTrue(n) def test_shake_decline_request_deletes_notification(self): self.post_url('/shake/derp/request_invitation?json=1') self.sign_in("admin", "asdfasdf") response = self.post_url('/shake/derp/decline_invitation?json=1', arguments={'user_id': self.user.id}) manager = ShakeManager.get('user_id = %s', self.user.id) self.assertFalse(manager) n = Notification.get('receiver_id = %s', self.manager.id) self.assertTrue(n.deleted) def test_already_a_member_do_not_see_request_button(self): self.shake.add_manager(self.user) response = self.fetch_url('/derp') self.assertTrue(response.body.find('join this shake') == -1)
class AccountTests(test.base.BaseAsyncTestCase): def setUp(self): super(AccountTests, self).setUp() self.user = User(name='admin', email='*****@*****.**', email_confirmed=1, is_paid=1) self.user.set_password('asdfasdf') self.user.save() self.sign_in("admin", "asdfasdf") def test_user_paid_account_rss_works(self): sourcefile = Sourcefile(width=20, height=20, file_key="asdf", thumb_key="asdf_t") sourcefile.save() sharedfile = Sharedfile(source_id=sourcefile.id, name="the name",user_id=self.user.id, \ content_type="image/png", description="description", source_url="https://www.mltshp.com/?hi") sharedfile.save() sharedfile.share_key = lib.utilities.base36encode(sharedfile.id) sharedfile.save() sharedfile.add_to_shake(self.user.shake()) response = self.fetch_url('/user/admin/rss') self.assertEqual(response.headers['Content-Type'], 'application/xml') parsed_xml = lib.utilities.parse_xml(response.body) self.assertEqual(parsed_xml['rss']['channel']['item']['link'], 'https://mltshp.com/p/1') def test_user_unpaid_account_rss_404s(self): self.user.update_attribute("is_paid", 0) self.user.save() response = self.fetch_url('/user/admin/rss') self.assertEqual(response.code, 404) def test_like_save_view_count_is_returned(self): sharedfile = test.factories.sharedfile(self.user, view_count=25, save_count=50, like_count=100) response = self.fetch_url('/user/%s/counts' % self.user.name) j_response = json_decode(response.body) self.assertEqual(j_response['likes'], 100) self.assertEqual(j_response['saves'], 50) self.assertEqual(j_response['views'], 25) def test_email_not_confirmed_puts_notice_at_top(self): self.user.email_confirmed = 0 self.user.save() response = self.fetch_url('/') self.assertTrue( response.body.find('Please visit settings to confirm your email!') > -1) response = self.fetch_url('/incoming') self.assertTrue( response.body.find('Please visit settings to confirm your email!') > -1) response = self.fetch_url('/friends') self.assertTrue( response.body.find('Please visit settings to confirm your email!') > -1) def test_quick_notifications(self): """ /account/quick-notifications should return without error when populated with all possible notification types. Page should also not be accessible if you're not signed in. """ self.user2 = User(name='example2',email='*****@*****.**', \ verify_email_token = 'created', password='******', email_confirmed=1, is_paid=1) self.user2.save() self.sourcefile = Sourcefile(width=20,height=20,file_key="asdf", \ thumb_key="asdf_t") self.sourcefile.save() self.sharedfile = Sharedfile(source_id=self.sourcefile.id, name="my shared file", \ user_id=self.user.id, content_type="image/png", share_key="ok") self.sharedfile.save() self.shake = Shake(user_id=self.user2.id, name='asdf', type='group', title='My Test Shake', description='Testing this shake test.') self.shake.save() # new subscription new_sub = Subscription(user_id=self.user2.id, shake_id=1) new_sub.save() new_subscriber = Notification.new_subscriber(sender=self.user2, receiver=self.user, action_id=new_sub.id) # new favorite new_favorite = Notification.new_favorite(sender=self.user2, sharedfile=self.sharedfile) # new save new_save = Notification.new_save(sender=self.user2, sharedfile=self.sharedfile) # new comment new_comment = Comment(user_id=self.user2.id, sharedfile_id=self.sharedfile.id, body="Testing comment") new_comment.save() # new mention new_mention = Notification.new_mention(receiver=self.user, comment=new_comment) # new invitation new_mention = Notification.new_invitation(sender=self.user2, receiver=self.user, action_id=self.shake.id) response = self.fetch_url('/account/quick-notifications') self.assertEqual(200, response.code) self.sign_out() response = self.fetch_url('/account/quick-notifications', follow_redirects=False) self.assertEqual(302, response.code)
class VoucherTests(test.base.BaseAsyncTestCase): def setUp(self): super(VoucherTests, self).setUp() self.admin = test.factories.user() self.sign_in("admin", "password") self.shake = Shake(user_id=self.admin.id, name='promotion-shake', title='Promotion Shake', type='group') self.shake.save() self.expired_promotion = Promotion(name="Expired Promotion", membership_months=60, expires_at=datetime.utcnow() - timedelta(seconds=50), promotion_shake_id=0) self.expired_promotion.save() self.promotion = Promotion(name="Unit Test Sale", membership_months=60, promotion_shake_id=self.shake.id, expires_at=datetime.utcnow() + timedelta(seconds=60 * 60 * 24 * 365)) self.promotion.save() self.used_voucher = Voucher(offered_by_user_id=0, promotion_id=self.promotion.id, voucher_key="abc123") # apply_to_user saves the voucher object (because it touches the # claimed_by_user_id and dates) and also the user object (by # updating the is_paid status) self.used_voucher.apply_to_user(self.admin) self.unused_voucher = Voucher(offered_by_user_id=0, claimed_by_user_id=0, promotion_id=self.promotion.id, voucher_key="unclaimed") self.unused_voucher.save() tornado.httpclient.HTTPClient() def test_create_account_has_code_field(self): """ Create account page should display the discount code field for new user registration. """ self.sign_out() response = self.fetch_url("/create-account") self.assertEqual(200, response.code) self.assertTrue(response.body.find("Discount code:") > -1) def test_create_account_with_bad_voucher(self): """ Submitting an invalid discount code should result in an error. """ self.sign_out() arguments = self._valid_arguments() arguments["key"] = "ABCDEFGHIJKL" response = self.post_url("/create-account", arguments=arguments) self.assertEqual(200, response.code) self.assertTrue(response.body.find("Invalid discount code") > -1) def test_create_account_with_unrecognized_voucher(self): """ Submitting an invalid discount code should result in an error. """ self.sign_out() arguments = self._valid_arguments() arguments["key"] = "foobar" response = self.post_url("/create-account", arguments=arguments) self.assertEqual(200, response.code) self.assertTrue(response.body.find("Invalid discount code") > -1) def test_create_account_with_good_voucher(self): """ Submitting a valid discount code should create an account with appropriate credit applied. """ self.sign_out() arguments = self._valid_arguments() arguments["key"] = "unclaimed" # this will create the account, but the redirect doesn't # carry forward the session info, so sign in separately # then verify the confirm-account page displays with a greeting self.post_url("/create-account", arguments=arguments) self.sign_in(arguments["name"], arguments["password"]) response = self.fetch_url("/confirm-account") self.assertTrue( response.body.find("Hello, %s!" % arguments["name"]) > -1) response = self.fetch_url("/account/settings") self.assertTrue(response.body.find("5 Years") > -1) def test_settings_page_with_credit(self): """ Validate that our test user account is showing a 5 year credit on their account settings. """ response = self.fetch_url("/account/settings") self.assertTrue(response.body.find("5 Years") > -1) def test_redeem_page_with_pro_user(self): """ A pro member shouldn't have access to the redeem page. """ response = self.fetch_url("/account/redeem") self.assertTrue(response.body.find("Redeem a Coupon") == -1) def test_redeem_voucher_with_bad_voucher(self): self.sign_out() user = test.factories.user(name="free_user", email="*****@*****.**", is_paid=0) self.sign_in(user.name, "password") response = self.fetch_url("/account/settings") # verify this account is currently free self.assertTrue( response.body.find("You are currently using a free account.") > -1) arguments = {"key": "abc123"} response = self.post_url("/account/redeem", arguments) self.assertTrue(response.body.find("Invalid") > -1) def test_redeem_voucher_with_good_voucher(self): self.sign_out() user = test.factories.user(name="free_user", email="*****@*****.**") user.is_paid = 0 user.save() self.sign_in(user.name, "password") response = self.fetch_url("/account/settings") # verify this account is currently free self.assertTrue( response.body.find("You are currently using a free account.") > -1) arguments = {"key": "unclaimed"} # this will post and redirect to the settings page which should # then reflect that we are a paid user with 5 years of credit response = self.post_url("/account/redeem", arguments) self.assertTrue(response.body.find("5 Years") > -1) payments = PaymentLog.where("user_id=%s", user.id) self.assertEquals(len(payments), 1) self.assertEquals(payments[0].operation, "redeem") self.assertEquals(payments[0].status, "credit") self.assertEquals(payments[0].reference_id, str(self.promotion.id)) self.assertEquals(payments[0].transaction_id, arguments['key']) self.assertEquals(payments[0].buyer_email, user.email) self.assertEquals(payments[0].buyer_name, user.name) # self.assertEquals(payments[0].next_transaction_date, ) voucher = Voucher.get("claimed_by_user_id=%s", user.id) self.assertEquals(voucher.promotion_id, self.promotion.id) self.assertEquals(voucher.claimed_by_user_id, user.id) self.assertEquals(voucher.offered_by_user_id, self.admin.id) def test_active_promotion_list(self): promotions = Promotion.active() self.assertEqual(len(promotions), 1) self.assertEqual(promotions[0].id, self.promotion.id) def _valid_arguments(self): return { "name": "valid_user", "password": "******", "password_again": "asdfasdf", "email": "*****@*****.**", "_skip_recaptcha_test_only": True, }