def test_url_microblog_context(self): self.portal.invokeFactory('Folder', 'f1', title=u"Folder 1") f1 = self.portal['f1'] alsoProvides(f1, IMicroblogContext) su = StatusUpdate('foo bar', microblog_context=f1) self.assertEqual(su.absolute_url(), '{}/@@post'.format(f1.absolute_url()))
def __init__(self, text, userid, creator=None): StatusUpdate.__init__(self, text) self.userid = userid if creator: self.creator = creator else: self.creator = userid
def test_edit_sets_edited(self): su = StatusUpdate('foo') self.assertEqual(su.edited, None) su.edit('bar') self.assertEqual(str(su.edited.__class__), "<class 'DateTime.DateTime.DateTime'>") self.assertNotEqual(su.edited, su.date)
def test_workspace_tile(self): ''' This will test the existence of the workspaces.tile and its functionality ''' tile = api.content.get_view('workspaces.tile', self.portal, self.request) su = StatusUpdate('Proposal draft V1.0 # This is a mock!!!', **{ 'microblog_context': self.workspace, }) su.id = 123456789L su.creator = 'charlotte_holzer' su.date = DateTime('2008/02/14 18:43') mb = queryUtility(IMicroblogTool) mb.add(su) workspaces = tile.workspaces(include_activities=True) self.assertEqual(len(workspaces), 1) demo_ws = workspaces[0] activities = demo_ws['activities'] self.assertEqual(len(activities), 1) self.assertDictEqual( activities[0], { 'object': 'Proposal draft V1.0 # This is a mock!!!', 'subject': 'charlotte_holzer', 'time': { 'datetime': '2008-02-14', 'title': '14 February 2008, 18:43' }, 'verb': 'posted' })
def test_delete_microblog_context_and_content(self): su1 = StatusUpdate('test', content_context=self.document) self.container.add(su1) su2 = StatusUpdate('foobar', microblog_context=self.microblog_context) self.container.add(su2) self.portal.manage_delObjects([self.ws_id]) self.assertEqual([], (list(self.container.values())))
def test_delete_content_replies(self): su1 = StatusUpdate('test', content_context=self.document) self.container.add(su1) su2 = StatusUpdate('foobar', thread_id=su1.id) self.container.add(su2) self.microblog_context.manage_delObjects([self.doc_id]) self.assertEqual([], (list(self.container.values())))
def test_nonmember_unauthorized_write(self): login(self.portal, 'alice_lindstrom') su1 = StatusUpdate('test #foo') su2 = StatusUpdate('test #foo', self.workspace) self.tool.add(su1) # should raise, since Alice is not a member of the workspace self.assertRaises(Unauthorized, self.tool.add, su2)
def setUp(self): self.portal = self.layer['portal'] setRoles(self.portal, TEST_USER_ID, ['Manager']) workflowTool = getToolByName(self.portal, 'portal_workflow') workflowTool.setDefaultChain('simple_publication_workflow') workflowTool.updateRoleMappings() f1 = api.content.create(self.portal, 'Folder', 'f1', title=u'Folder 1') alsoProvides(f1, IMicroblogContext) f1.reindexObject() f2 = api.content.create(self.portal, 'Folder', 'f2', title=u'Folder 2') alsoProvides(f2, IMicroblogContext) f2.reindexObject() api.content.transition(f2, 'publish') self.assertEqual(api.content.get_state(f1), 'private') self.assertEqual(api.content.get_state(f2), 'published') tool = queryUtility(IMicroblogTool) self.su1 = su1 = StatusUpdate('test #foo', f1) tool.add(su1) self.su2 = su2 = StatusUpdate('test #foo', f2) tool.add(su2) # the tool is queued tool.flush_queue() # set up new user api.user.create('*****@*****.**', username='******', password='******')
def test_member_allowed_write(self): login(self.portal, 'allan_neece') su1 = StatusUpdate('test #foo') su2 = StatusUpdate('test #foo', self.workspace) self.tool.add(su1) # should NOT raise Unauthorized self.tool.add(su2)
def test_thread_microblog_context(self): self.portal.invokeFactory('Folder', 'f1', title=u"Folder 1") f1 = self.portal['f1'] alsoProvides(f1, IMicroblogContext) su1 = StatusUpdate('foo', microblog_context=f1) self.container.add(su1) su2 = StatusUpdate('foo', thread_id=su1.id) self.assertEqual(f1, su2.microblog_context)
def create( text, context=None, thread_id=None, mention_ids=None, tags=None, user=None, userid=None, time=None, ): """Create a status update (post). :param text: [required] text of the post :type text: Unicode object :param context: Container of the post :type context: Content object :param user: User who should post. By default the current user posts. :type user: user object :param userid: userid of the user who should post. :type userid: string :param time: time when the post should happen. By default the current time. :type time: datetime object :returns: Newly created statusupdate :rtype: StatusUpdate object """ status_obj = StatusUpdate( text=text, context=context, thread_id=thread_id, mention_ids=mention_ids, tags=tags ) # By default the post is done by the current user # Passing a userid or user allows to post as a different user if user is None and userid is not None: user = api.user.get(userid=userid) if user is not None: status_obj.userid = user.getId() status_obj.creator = user.getUserName() # By default the post happens now # Passing a time (as a datetime-object) the id and the date can be set if time is not None: assert(isinstance(time, datetime)) delta = time - datetime.utcfromtimestamp(0) status_obj.id = long(delta.total_seconds() * 1e6) status_obj.date = DateTime(time) status_id = status_obj.id microblog = queryUtility(IMicroblogTool) microblog.add(status_obj) return microblog.get(status_id)
def test_url_content_context(self): self.portal.invokeFactory('Folder', 'f1', title=u"Folder 1") f1 = self.portal['f1'] alsoProvides(f1, IMicroblogContext) doc = api.content.create( container=f1, type='Document', title='My document', ) su = StatusUpdate('foo bar', content_context=doc) self.assertEqual(su.absolute_url(), '{}/view'.format(doc.absolute_url()))
def test_reply_to_contentupdate_is_human_update(self): self.portal.invokeFactory('Folder', 'f1', title=u"Folder 1") f1 = self.portal['f1'] alsoProvides(f1, IMicroblogContext) doc = api.content.create( container=f1, type='Document', title='My document', ) su1 = StatusUpdate('', content_context=doc) self.container.add(su1) su2 = StatusUpdate('', thread_id=su1.id) self.assertTrue(su2.is_human_update)
def test_like_status_update(self): # test statusupdate su = StatusUpdate('Some cool news!') container = piapi.microblog.get_microblog() container.add(su) update_id = str(su.id) self.request.form['like_button'] = 'like' self.request["REQUEST_METHOD"] = "POST" view = api.content.get_view('toggle_like_statusupdate', self.portal, self.request) self.assertRaises(KeyError, view) view = view.publishTraverse(self.request, update_id) # Toggle like for statusupdate on output = view() self.assertIn('(1)', output) self.assertIn('Unlike', output) user_likes = self.util.get_likes("update", self.user_id) self.assertTrue( self.util.is_liked("update", update_id, self.user_id)) self.assertEqual(len(user_likes), 1) # Toggle like for statusupdate off output = view() user_likes = self.util.get_likes("update", self.user_id) self.assertEqual(len(user_likes), 0) self.assertIn('(0)', output) self.assertIn('Like', output)
def test_add_multi_portal(self): portal = api.portal.get() self.assertIsNotNone(portal) portal_request = portal.REQUEST tool = queryUtility(IMicroblogTool) for i in xrange(0, 10): su = StatusUpdate('Test {}'.format(str(i + 1))) tool.add(su) # running in sync mode, no need to sleep self.assertEqual(len(request_subscriber.messages), 10) self.assertIn(('Test 1', portal_request.getURL()), request_subscriber.messages) self.assertIn(('Test 2', portal_request.getURL()), request_subscriber.messages) self.assertIn(('Test 3', portal_request.getURL()), request_subscriber.messages) self.assertIn(('Test 4', portal_request.getURL()), request_subscriber.messages) self.assertIn(('Test 5', portal_request.getURL()), request_subscriber.messages) self.assertIn(('Test 6', portal_request.getURL()), request_subscriber.messages) self.assertIn(('Test 7', portal_request.getURL()), request_subscriber.messages) self.assertIn(('Test 8', portal_request.getURL()), request_subscriber.messages) self.assertIn(('Test 9', portal_request.getURL()), request_subscriber.messages) self.assertIn(('Test 10', portal_request.getURL()), request_subscriber.messages)
def test_add_multi_portal(self): portal = api.portal.get() self.assertIsNotNone(portal) portal_path = '/'.join(portal.getPhysicalPath()) tool = queryUtility(IMicroblogTool) for i in xrange(0, 10): su = StatusUpdate('Test {}'.format(str(i + 1))) if i == 5: time.sleep(1) # Next message triggers queue flush tool.add(su) # Here we need to sleep for some time to give the thread timer # queue committer in ploneintranet.microblog # time to commit the statuses. time.sleep(2) self.assertEqual( portal_subscriber.messages, [ ('Test 1', portal_path), ('Test 2', portal_path), ('Test 3', portal_path), ('Test 4', portal_path), ('Test 5', portal_path), ('Test 6', portal_path), ('Test 7', portal_path), ('Test 8', portal_path), ('Test 9', portal_path), ('Test 10', portal_path) ] )
def test_anon_cannot_delete(self): logout() su = StatusUpdate('foo') self.container.add(su) login(self.portal, 'user_jane') with self.assertRaises(Unauthorized): self.container.delete(su.id)
def test_creator_delete(self): login(self.portal, 'user_steve') su = StatusUpdate('foo') self.container.add(su) self.container.delete(su.id) with self.assertRaises(KeyError): self.container.get(su.id)
def test_status_update(self): ''' Let's try to create a status_update and inspect the created adapter ''' with api.env.adopt_user('test_user_adapters_'): su = StatusUpdate(u'Test à') pm = api.portal.get_tool('ploneintranet_microblog') pm.add(su) pin = api.portal.get_tool('ploneintranet_notifications') message = pin.get_user_queue(api.user.get('test_user_adapters_'))[-1] self.assertEqual(message.predicate, 'STATUS_UPDATE') self.assertDictEqual( message.actors[0], { 'fullname': 'Kelly Sj\xc3\xb6gren', 'userid': 'test_user_adapters_', 'email': '*****@*****.**' }) self.assertIsInstance(message.obj['id'], long) self.assertEqual(message.obj['title'], u'Test \xe0') self.assertEqual(message.obj['url'], 'plone/@@stream/network') self.assertEqual(message.obj['read'], False) self.assertIsInstance(message.obj['message_last_modification_date'], datetime)
def test_nonmember_secured_read(self): login(self.portal, 'allan_neece') su = StatusUpdate('test #foo', self.workspace) self.tool.add(su) logout() login(self.portal, 'alice_lindstrom') # silently filters all you're not allowed to see self.assertFalse(su.id in self.tool.keys())
def test_nonmember_unauthorized_get(self): login(self.portal, 'allan_neece') su = StatusUpdate('test #foo', self.workspace) self.tool.add(su) logout() login(self.portal, 'alice_lindstrom') # should raise, since Alice is not a member of the workspace self.assertRaises(Unauthorized, self.tool.get, su.id)
def test_mentions_mapping(self): su = StatusUpdate('foo', mention_ids=['user_steve', ]) self.container.add(su) found = [x for x in self.container._mentions_mapping.get('user_steve')] self.assertIn(su.id, found) self.container.delete(su.id) found = [x for x in self.container._mentions_mapping.get('user_steve')] self.assertNotIn(su.id, found)
def test_mentions(self): test_user = api.user.create(email='*****@*****.**', username='******', properties={'fullname': 'Test User'}) userid = test_user.getId() fullname = test_user.getProperty('fullname') su = StatusUpdate('foo', mention_ids=[userid]) self.assertEqual(su.mentions, {userid: fullname})
def test_tag_mapping(self): su = StatusUpdate('foo', tags=['foo', 'bar']) self.container.add(su) found = [x for x in self.container._tag_mapping.get('bar')] self.assertIn(su.id, found) self.container.delete(su.id) found = [x for x in self.container._tag_mapping.get('bar')] self.assertNotIn(su.id, found)
def create_stream(context, stream, files_dir): contexts_cache = {} microblog = queryUtility(IMicroblogTool) like_tool = getUtility(ILikesTool) microblog.clear() for status in stream: kwargs = {} if status['context']: if status['context'] not in contexts_cache: contexts_cache[status['context']] = api.content.get( path='/' + decode(status['context']).lstrip('/') ) kwargs['context'] = contexts_cache[status['context']] status_obj = StatusUpdate(status['text'], **kwargs) status_obj.userid = status['user'] status_obj.creator = api.user.get( username=status['user'] ).getUserName() offset_time = status['timestamp'] * 60 status_obj.id -= int(offset_time * 1e6) status_obj.date = DateTime(time.time() - offset_time) microblog.add(status_obj) # THIS BREAKS BECAUSE DOCCONV. FIX DOCCONV, UNCOMMENT # if 'attachment' in status: # attachment_definition = status['attachment'] # attachment_filename = os.path.join( # files_dir, # attachment_definition['filename'] # ) # attachment = context.openDataFile(attachment_filename) # fake_field = FakeFileField( # attachment_definition['filename'], # attachment # ) # attachment_obj = create_attachment(fake_field) # attachments = IAttachmentStorage(status_obj) # attachments.add(attachment_obj) # like some status-updates if 'likes' in status: for user_id in status['likes']: like_tool.like( item_id=str(status_obj.id), user_id=user_id, )
def create_stream(context, stream, files_dir): contexts_cache = {} microblog = queryUtility(IMicroblogTool) if len([x for x in microblog.keys()]) > 0: log.info("microblog already setup. skipping for speed.") return like_tool = getUtility(INetworkTool) microblog.clear() for status in stream: kwargs = {} microblog_context = status['microblog_context'] if microblog_context: if microblog_context not in contexts_cache: contexts_cache[microblog_context] = api.content.get( path='/' + decode(microblog_context).lstrip('/') ) kwargs['microblog_context'] = contexts_cache[microblog_context] status_obj = StatusUpdate(status['text'], **kwargs) status_obj.userid = status['user'] status_obj.creator = api.user.get( username=status['user'] ).getUserName() offset_time = status['timestamp'] * 60 status_obj.id -= int(offset_time * 1e6) status_obj.date = DateTime(time.time() - offset_time) # THIS BREAKS BECAUSE docconv.client.async.queueConversionJob FIXME # if 'attachment' in status: # _definition = status['attachment'] # _filename = os.path.join(files_dir, _definition['filename']) # _data = context.readDataFile(_filename) # attachment_obj = create_attachment(_filename, _data) # attachments = IAttachmentStorage(status_obj) # attachments.add(attachment_obj) microblog.add(status_obj) # like some status-updates if 'likes' in status: for user_id in status['likes']: like_tool.like( "update", user_id=user_id, item_id=str(status_obj.id), )
def test_user_mapping(self): login(self.portal, 'user_steve') su = StatusUpdate('foo') self.container.add(su) found = [x for x in self.container._user_mapping.get('user_steve')] self.assertIn(su.id, found) self.container.delete(su.id) found = [x for x in self.container._user_mapping.get('user_steve')] self.assertNotIn(su.id, found)
def test_attachments(self): su = StatusUpdate('foo bar') attachments = IAttachmentStorage(su) f = ATFile('data.dat') attachments.add(f) self.assertEqual([k for k in attachments.keys()], [f.getId()]) attachments.remove(f.getId()) self.assertEqual(len(attachments.keys()), 0)
def create_stream(context, stream, files_dir): contexts_cache = {} microblog = queryUtility(IMicroblogTool) if len([x for x in microblog.keys()]) > 0: log.info("microblog already setup. skipping for speed.") return like_tool = getUtility(INetworkTool) microblog.clear() for status in stream: kwargs = {} microblog_context = status['microblog_context'] if microblog_context: if microblog_context not in contexts_cache: contexts_cache[microblog_context] = api.content.get( path='/' + decode(microblog_context).lstrip('/')) kwargs['microblog_context'] = contexts_cache[microblog_context] status_obj = StatusUpdate(status['text'], **kwargs) status_obj.userid = status['user'] status_obj.creator = api.user.get( username=status['user']).getUserName() offset_time = status['timestamp'] * 60 status_obj.id -= int(offset_time * 1e6) status_obj.date = DateTime(time.time() - offset_time) # THIS BREAKS BECAUSE docconv.client.async.queueConversionJob FIXME # if 'attachment' in status: # _definition = status['attachment'] # _filename = os.path.join(files_dir, _definition['filename']) # _data = context.readDataFile(_filename) # attachment_obj = create_attachment(_filename, _data) # attachments = IAttachmentStorage(status_obj) # attachments.add(attachment_obj) microblog.add(status_obj) # like some status-updates if 'likes' in status: for user_id in status['likes']: like_tool.like( "update", user_id=user_id, item_id=str(status_obj.id), )
def test_content_context_init_sets_microblog_context(self): self.portal.invokeFactory('Folder', 'f1', title=u"Folder 1") f1 = self.portal['f1'] alsoProvides(f1, IMicroblogContext) doc = api.content.create( container=f1, type='Document', title='My document', ) su1 = StatusUpdate('foo', content_context=doc) self.assertEqual(f1, su1.microblog_context)
def test_normal_contentupdate_not_is_human_update(self): self.portal.invokeFactory('Folder', 'f1', title=u"Folder 1") f1 = self.portal['f1'] alsoProvides(f1, IMicroblogContext) doc = api.content.create( container=f1, type='Document', title='My document', ) su1 = StatusUpdate('', content_context=doc) self.assertFalse(su1.is_human_update)
def test_thread_content_context(self): doc = api.content.create( container=self.portal, type='Document', title='My document', ) api.content.transition(doc, to_state='published') found = [x for x in self.container.values()] su1 = found[0] su2 = StatusUpdate('foo', thread_id=su1.id) self.assertEqual(None, su2.microblog_context) self.assertEqual(doc, su2.content_context)
def test_extracted_contentupdate_is_human_update(self): self.portal.invokeFactory('Folder', 'f1', title=u"Folder 1") f1 = self.portal['f1'] alsoProvides(f1, IMicroblogContext) doc = api.content.create( container=f1, type='Document', title='My document', ) su1 = StatusUpdate('I have some text. That makes me human', content_context=doc) self.assertTrue(su1.is_human_update)
def test_workspace_tile(self): ''' This will test the existence of the workspaces.tile and its functionality ''' tile = api.content.get_view( 'workspaces.tile', self.portal, self.request ) su = StatusUpdate( 'Proposal draft V1.0 # This is a mock!!!', **{ 'microblog_context': self.workspace, } ) su.id = 123456789L su.creator = 'charlotte_holzer' su.date = DateTime('2008/02/14 18:43') mb = queryUtility(IMicroblogTool) mb.add(su) workspaces = tile.workspaces() self.assertEqual(len(workspaces), 1) demo_ws = workspaces[0] activities = demo_ws['activities'] self.assertEqual(len(activities), 1) self.assertDictEqual( activities[0], { 'object': 'Proposal draft V1.0 # This is a mock!!!', 'subject': 'charlotte_holzer', 'time': { 'datetime': '2008-02-14', 'title': '14 February 2008, 18:43' }, 'verb': 'posted' } )
def demo(context): if context.readDataFile('ploneintranet.socialsuite_demo.txt') is None: return portal = site = context.getSite() avatar_path = os.path.join(context._profile_path, 'avatars') # create users users = [] for file_name in os.listdir(avatar_path): userid = str(file_name.split('.')[0]) users.append(userid) properties = dict( fullname=" ".join([x.capitalize() for x in userid.split("_")]), location=random.choice( ("New York", "Chicago", "San Francisco", "Paris", "Amsterdam", "Zurich")), description=" ".join(loremipsum.get_sentences(2))) try: api.user.create(email='*****@*****.**' % userid, username=userid, password='******', properties=properties) except ValueError: user = api.user.get(username=userid) user.setMemberProperties(properties) portrait = context.openDataFile(file_name, 'avatars') scaled, mimetype = scale_image(portrait) portrait = Image(id=userid, file=scaled, title='') memberdata = getToolByName(site, 'portal_memberdata') memberdata._setPortrait(portrait, userid) # setup social network graph = queryUtility(INetworkGraph) graph.clear() testusers = ['clare_presler', 'kurt_silvio'] graph.follow("user", testusers[0], testusers[1]) # give clare som extra followers for fan in ['christian_stoner', 'guy_hachey', 'jamie_jacko']: graph.follow("user", testusers[0], fan) # fully random followers for i in xrange(100): followee = random.choice(users) follower = random.choice(users) if followee in testusers or follower in testusers \ or followee == follower: continue else: graph.follow("user", followee, follower) # setup publicly accessible folder and document portal.invokeFactory('Folder', 'public', title=u"Public Folder") public = portal['public'] public.invokeFactory('Document', 'd1', title=u"Public Document") # create and fill a local IMicroblogContext workspace workspace_users = ['clare_presler', 'dollie_nocera', 'esmeralda_claassen', 'pearlie_whitby'] if 'workspace' not in portal: portal.invokeFactory('Folder', 'workspace', title=u"Secure Workspace") # enable local microblog directlyProvides(portal.workspace, IMicroblogContext) # in testing we don't have the 'normal' default workflow workflowTool = getToolByName(portal, 'portal_workflow') if workflowTool.getInfoFor(portal.workspace, 'review_state') != 'private': workflowTool.doActionFor(portal.workspace, 'hide') # share workspace with some users for userid in workspace_users: api.user.grant_roles(username=userid, obj=portal.workspace, roles=['Contributor', 'Reader', 'Editor']) # update object_provides + workflow state + sharing indexes portal.workspace.reindexObject() # microblog random loremipsum # prepare microblog microblog = queryUtility(IMicroblogTool) microblog.clear() # wipe all tags = ("hr", "marketing", "fail", "innovation", "learning", "easy", "newbiz", "conference", "help", "checkthisout") for i in xrange(100): # select random user userid = random.choice(users) # generate text text = " ".join(loremipsum.get_sentences(3)) if random.choice((True, False)): text += " #%s" % random.choice(tags) if userid in workspace_users: # workspace status = StatusUpdate(text, context=portal.workspace, tags=['girlspace']) else: # global status = StatusUpdate(text) status.userid = userid status.creator = " ".join([x.capitalize() for x in userid.split("_")]) # distribute most over last week if i < 90: offset_time = random.random() * 3600 * 24 * 7 status.id -= int(offset_time * 1e6) status.date = DateTime(time.time() - offset_time) microblog.add(status) # microblog deterministic test content most recent # workspace t0 = ('Workspaces can have local microblogs and activitystreams. ' 'Local activitystreams show only local status updates. ' 'Microblog updates will show globally only for users who ' 'have the right permissions. This demo has a #girlspace workspace.') s0 = StatusUpdate(t0, context=portal.workspace, tags=['girlspace']) s0.userid = workspace_users[0] # clare s0.creator = " ".join([x.capitalize() for x in s0.userid.split("_")]) microblog.add(s0) # global t1 = ('The "My Network" section only shows updates ' 'of people you are following.') s1 = StatusUpdate(t1) s1.userid = testusers[0] # clare s1.creator = " ".join([x.capitalize() for x in s1.userid.split("_")]) microblog.add(s1) t2 = 'The "Explore" section shows all updates of all people.' s2 = StatusUpdate(t2) s2.userid = testusers[1] # kurt s2.creator = " ".join([x.capitalize() for x in s2.userid.split("_")]) microblog.add(s2) t3 = 'The #demo hashtag demonstrates that you can filter on topic' s3 = StatusUpdate(t3, tags=['demo']) s3.userid = s2.userid # kurt s3.creator = s2.creator microblog.add(s3) # commit microblog.flush_queue() transaction.commit()