def test_ListItem(self): l = Message.ListItem('title', 'subtitle', 'http://test.com/image_url') jsonschema.validate(l.as_dict(), Message.ListItem.schema()) self.assertEquals(l, l.FromDict(l.as_dict())) l.set_default_action(Message.Button(Message.ButtonType.WEB_URL, 'test', url='http://test.com')) l.set_button(Message.Button(Message.ButtonType.WEB_URL, 'test', url='http://test.com')) jsonschema.validate(l.as_dict(), Message.ListItem.schema()) self.assertEquals(l, l.FromDict(l.as_dict()))
def test_broadcast_update(self): # Test get all broadcasts rv = self.app.get('/api/bots/%d/broadcasts' % self.bot_ids[0]) self.assertEquals(rv.status_code, HTTPStatus.STATUS_OK) data = json.loads(rv.data) broadcast_id = data['broadcasts'][0]['id'] # Test invalid status update, status can only be 'Canceled' input_data = { 'bot_id': self.bot_ids[0], 'name': 'New broadcast', 'messages': [Message('1234').as_dict()], 'scheduled_time': int(time.time()), 'status': 'Queued' } rv = self.app.put('/api/broadcasts/%d' % broadcast_id, data=json.dumps(input_data), content_type='application/json') self.assertEquals(rv.status_code, HTTPStatus.STATUS_CLIENT_ERROR) # Test broadcast cancelation input_data = { 'bot_id': self.bot_ids[0], 'name': 'New broadcast', 'messages': [Message('1234').as_dict()], 'scheduled_time': int(time.time()), 'status': 'Canceled' } rv = self.app.put('/api/broadcasts/%d' % broadcast_id, data=json.dumps(input_data), content_type='application/json') self.assertEquals(rv.status_code, HTTPStatus.STATUS_OK) rv = self.app.get('/api/broadcasts/%d' % broadcast_id) self.assertEquals(rv.status_code, HTTPStatus.STATUS_OK) data = json.loads(rv.data) self.assertEquals(data['messages'][0]['text'], '1234') # Broadcast is canceled, should be unmodifiable input_data = { 'bot_id': self.bot_ids[0], 'name': 'New broadcast 2', 'messages': [Message('1234').as_dict()], 'scheduled_time': int(time.time()), } rv = self.app.put('/api/broadcasts/%d' % broadcast_id, data=json.dumps(input_data), content_type='application/json') self.assertEquals(rv.status_code, HTTPStatus.STATUS_CLIENT_ERROR)
def test_Bubble(self): b = Message.Bubble('title') jsonschema.validate(b.as_dict(), Message.Bubble.schema()) self.assertEquals(b, b.FromDict(b.as_dict())) b = Message.Bubble('title', 'http://test.com/item_url', 'http://test.com/image_url', 'subtitle') jsonschema.validate(b.as_dict(), Message.Bubble.schema()) self.assertEquals(b, b.FromDict(b.as_dict())) b.add_button(Message.Button(Message.ButtonType.WEB_URL, 'test', url='http://test.com')) b.add_button(Message.Button(Message.ButtonType.POSTBACK, 'test', payload='payload')) jsonschema.validate(b.as_dict(), Message.Bubble.schema()) self.assertEquals(b, b.FromDict(b.as_dict()))
def test_input_transformation_reconstruction(self): """Test that input transformation is applied when constructing message with Message.FromDict.""" msg_dict = { "text": "test", "quick_replies": [ { "content_type": "text", "title": "A", }, { "content_type": "text", "title": "B" }, { "content_type": "location", } ] } g.input_transformation = [] Message.FromDict(msg_dict) transform_keys = reduce(lambda x, y: x + y, [x[0] for x in g.input_transformation], []) self.assertTrue('^A$' in transform_keys) self.assertTrue('^B$' in transform_keys) self.assertFalse(None in transform_keys)
def broadcast_task(broadcast_id): with DatabaseSession(): broadcast = Broadcast.get_by(id=broadcast_id, single=True) # The broadcast entry could be delted by user if not broadcast: return # Either broadcast in progress or already sent if broadcast.status != BroadcastStatusEnum.QUEUED: return # The user may have changed the broadcasting time, ignore it as it # should be automatically rescheduled. if broadcast.scheduled_time >= datetime.now(): return broadcast.status = BroadcastStatusEnum.SENDING try: DatabaseManager.commit() except (InvalidRequestError, IntegrityError): # The broadcast task have changed during our modification, retry. DatabaseManager.rollback() return broadcast_task(broadcast_id) # Do the actually broadcast bot = Bot.get_by(id=broadcast.bot_id, account_id=broadcast.account_id, single=True) # Bot may have been deleted if not bot: return messages = [Message.FromDict(m) for m in broadcast.messages] broadcast_message_async(bot, messages)
def test_send_message(self): """Test message sending.""" m = Message('Message test') target = 'bb8.backend.messaging_provider.facebook.send_message' with mock.patch(target) as mock_send_message: messaging.send_message(self.user_1, [m, m]) mock_send_message.assert_called_once_with(self.user_1, [m, m])
def test_Push(self): ms = [Message('AppAPI: Push: Test message')] self._service.Push([self.user_1.id], ms) with self.assertRaises(RuntimeError): self._service.Push([self.user_1.id], ['bad message']) # Wait for celery to process task time.sleep(5)
def validate_broadcast_schema(broadcast_json): """Validate broadcast request schema.""" try: jsonschema.validate(broadcast_json, Broadcast.schema()) for message in broadcast_json['messages']: jsonschema.validate(message, Message.schema()) except jsonschema.exceptions.ValidationError: logger.error('Validation failed for `broadcast_json\'!') raise
def send_ack_message(self, user, message, variables): """Send text message. If *messages* is a list of message, choice a random one from the list then send it. """ if isinstance(message, list): message = random.choice(message) messaging.send_message(user, Message(message, variables=variables))
def test_broadcast_create_get(self): """Test broadcast create and access. Also very that broadcast access permision is bound by account. """ # Create an invalid broadcast input_data = { 'bot_id': self.bot_ids[0], 'name': 'New broadcast', 'messages': [{ 'some_invalid': 'format' }], 'scheduled_time': int(time.time()), } rv = self.app.post('/api/broadcasts', data=json.dumps(input_data), content_type='application/json') self.assertEquals(rv.status_code, HTTPStatus.STATUS_CLIENT_ERROR) # Create an invalid broadcast targeting bot own by account2 input_data = { 'bot_id': self.bot_ids[1], 'name': 'New broadcast', 'messages': [Message('test').as_dict()], 'scheduled_time': int(time.time()), } rv = self.app.post('/api/broadcasts', data=json.dumps(input_data), content_type='application/json') self.assertEquals(rv.status_code, HTTPStatus.STATUS_CLIENT_ERROR) # Test get one broadcasts rv = self.app.get('/api/broadcasts/%d' % self.broadcast_ids[0]) self.assertEquals(rv.status_code, HTTPStatus.STATUS_OK) data = json.loads(rv.data) self.assertEquals(data['name'], 'New broadcast') # Test invalid broadcast_id rv = self.app.get('/api/broadcasts/9999999') self.assertEquals(rv.status_code, HTTPStatus.STATUS_CLIENT_ERROR) # Test invalid broadcast_id (broadcast own by account2) rv = self.app.get('/api/broadcasts/%s' % self.broadcast_ids[1]) self.assertEquals(rv.status_code, HTTPStatus.STATUS_CLIENT_ERROR) # Login as account2, and should have access to the second broadcast self.login(self.account2) rv = self.app.get('/api/broadcasts/%s' % self.broadcast_ids[1]) self.assertEquals(rv.status_code, HTTPStatus.STATUS_OK) # Test sending immediately (scheduled_time = 0) self.create_broadcast(self.bot_ids[1], eta=0)
def test_Button(self): with self.assertRaises(RuntimeError): Message.Button('wrong_type', 'test', 'http://test.com') with self.assertRaises(jsonschema.exceptions.ValidationError): b = Message.Button(Message.ButtonType.WEB_URL, 'test', payload='payload') jsonschema.validate(b.as_dict(), Message.Button.schema()) b = Message.Button(Message.ButtonType.WEB_URL, 'test', url='http://test.com') jsonschema.validate(b.as_dict(), Message.Button.schema()) self.assertEquals(b, b.FromDict(b.as_dict())) b = Message.Button(Message.ButtonType.POSTBACK, 'postback', payload='postback') jsonschema.validate(b.as_dict(), Message.Button.schema()) self.assertEquals(b, b.FromDict(b.as_dict())) b = Message.Button(Message.ButtonType.ELEMENT_SHARE) jsonschema.validate(b.as_dict(), Message.Button.schema()) self.assertEquals(b, b.FromDict(b.as_dict()))
def Broadcast(self, request, unused_context): with DatabaseSession(): bot = Bot.get_by(id=request.bot_id, single=True) if not bot: raise RuntimeError('Bot<%d> does not exist' % request.bot_id) eta = None if request.eta == 0 else request.eta messages_dict = cPickle.loads(request.messages_object) if request.static: msgs = [Message.FromDict(m, {}) for m in messages_dict] messaging_tasks.broadcast_message_async(bot, msgs, eta) else: users = User.get_by(bot_id=request.bot_id) messaging_tasks.push_message_from_dict_async( users, messages_dict, eta) return app_service_pb2.Empty()
def create_broadcast(self, bot_id, eta=int(time.time())): # Test create broadcasts input_data = { 'bot_id': bot_id, 'name': 'New broadcast', 'messages': [Message('Test message').as_dict()], 'scheduled_time': eta, } rv = self.app.post('/api/broadcasts', data=json.dumps(input_data), content_type='application/json') self.assertEquals(rv.status_code, HTTPStatus.STATUS_OK) data = json.loads(rv.data) self.assertEquals(data['name'], input_data['name']) self.assertEquals(data['status'], 'Queued') self.broadcast_ids.append(data['id'])
def test_settings_memory_rendering(self): """Test memory and setting variable access.""" g.user = self.user_1 g.user.settings['key1'] = 'value1' m = Message("{{settings.key1|upper}}") self.assertEquals(m.as_dict()['text'], 'VALUE1') g.user = self.user_1 g.user.memory['key2'] = 'value2' m = Message("{{memory.key2|upper}}") self.assertEquals(m.as_dict()['text'], 'VALUE2')
def test_QuickReply(self): q1 = Message.QuickReply(Message.QuickReplyType.TEXT, 'quick_reply_1', acceptable_inputs=['1', '2']) jsonschema.validate(q1.as_dict(), Message.QuickReply.schema()) self.assertEquals(q1, q1.FromDict(q1.as_dict())) q2 = Message.QuickReply(Message.QuickReplyType.LOCATION) jsonschema.validate(q2.as_dict(), Message.QuickReply.schema()) self.assertEquals(q2, q2.FromDict(q2.as_dict())) q3 = Message.QuickReply(Message.QuickReplyType.TEXT, 'quick_reply_2', acceptable_inputs=['3', '4']) m = Message('test') m.add_quick_reply(q1) m.add_quick_reply(q2) m.add_quick_reply(q3) jsonschema.validate(m.as_dict(), Message.schema()) self.assertEquals(m, m.FromDict(m.as_dict())) transform_keys = reduce(lambda x, y: x + y, [x[0] for x in g.input_transformation], []) self.assertTrue('^quick_reply_1$' in transform_keys) self.assertTrue('1' in transform_keys) self.assertTrue('3' in transform_keys)
def test_send_message(self): """Test facebook message sending.""" # Test simple text message m = Message('test') facebook.send_message(self.user, [m]) # Test image message m = Message(image_url='http://i.imgur.com/4loi6PJ.jpg') facebook.send_message(self.user, [m]) # Test button template message m = Message(buttons_text='Button template test') m.add_button(Message.Button(Message.ButtonType.WEB_URL, 'Google', url='http://www.google.com/')) m.add_button(Message.Button(Message.ButtonType.WEB_URL, '17', url='http://www.17.media/')) facebook.send_message(self.user, [m]) # Test list template message m = Message(top_element_style=Message.ListTopElementStyle.LARGE) l = Message.ListItem('Google', 'google.com', 'http://i.imgur.com/1QfaG1u.png') l.set_default_action(Message.Button(Message.ButtonType.WEB_URL, url='http://www.google.com')) l.set_button(Message.Button(Message.ButtonType.WEB_URL, title='Goto Google', url='http://www.google.com/')) m.add_list_item(l) l = Message.ListItem('17', 'http://www.17.media/', 'http://i.imgur.com/4loi6PJ.jpg') l.set_button(Message.Button(Message.ButtonType.WEB_URL, title='Goto 17', url='http://www.17.media/')) m.add_list_item(l) m.add_button(Message.Button(Message.ButtonType.WEB_URL, '17', url='http://www.17.media/')) facebook.send_message(self.user, [m]) # Test generic template message m = Message() bubble = Message.Bubble('Generic template test', 'http://www.starwars.com/', 'http://i.imgur.com/4loi6PJ.jpg', 'Bubble subtitle') bubble.add_button(Message.Button(Message.ButtonType.WEB_URL, 'Starwars', url='http://www.starwars.com/')) bubble.add_button(Message.Button(Message.ButtonType.WEB_URL, 'Google', url='http://www.google.com/')) bubble.add_button(Message.Button(Message.ButtonType.WEB_URL, '17', url='http://www.17.media/')) m.add_bubble(bubble) m.add_bubble(bubble) m.add_bubble(bubble) facebook.send_message(self.user, [m])
def test_Message(self): but1 = Message.Button(Message.ButtonType.WEB_URL, 'test', url='http://test.com') but2 = Message.Button(Message.ButtonType.POSTBACK, 'test', payload='payload') b = Message.Bubble('title', 'http://test.com/item_url', 'http://test.com/image_url', 'subtitle') b.add_button(but1) b.add_button(but2) m = Message('test') jsonschema.validate(m.as_dict(), Message.schema()) self.assertEquals(m, m.FromDict(m.as_dict())) m = Message(image_url='http://test.com/image_url') jsonschema.validate(m.as_dict(), Message.schema()) self.assertEquals(m, m.FromDict(m.as_dict())) # Buttons message m = Message(buttons_text='question') m.add_button(but1) m.add_button(but2) jsonschema.validate(m.as_dict(), Message.schema()) self.assertEquals(m, m.FromDict(m.as_dict())) transform_keys = reduce(lambda x, y: x + y, [x[0] for x in g.input_transformation], []) self.assertTrue('^1$' not in transform_keys) self.assertTrue('^2$' in transform_keys) # List message l = Message.ListItem('title', 'subtitle', 'http://test.com/image_url') l.set_button(Message.Button(Message.ButtonType.WEB_URL, 'test', url='http://test.com')) m = Message(top_element_style=Message.ListTopElementStyle.COMPACT) m.add_list_item(l) with self.assertRaises(jsonschema.ValidationError): # Need at least two list items jsonschema.validate(m.as_dict(), Message.schema()) m.add_list_item(l) jsonschema.validate(m.as_dict(), Message.schema()) # Generic message g.input_transformation = [] m = Message() m.add_bubble(b) m.add_bubble(b) jsonschema.validate(m.as_dict(), Message.schema()) self.assertEquals(m, m.FromDict(m.as_dict())) transform_keys = reduce(lambda x, y: x + y, [x[0] for x in g.input_transformation], []) self.assertTrue('^1-2$' in transform_keys) self.assertTrue('^2-2$' in transform_keys) with self.assertRaises(RuntimeError): m = Message('test', 'url')
def test_Broadcast(self): ms = [Message('AppAPI: Broadcast: Test message')] self._service.Broadcast(self.bot.id, ms) # Wait for celery to process task time.sleep(5)
def test_message_variable_rendering(self): """Test that variable in message can be rendered correctly.""" variables = { 'user': { 'first_name': 'Isaac', 'last_name': 'Huang', }, 'date': 'today' } m = Message('Hi {{user.first_name}}', variables=variables) self.assertEquals(m.as_dict()['text'], 'Hi Isaac') m = Message() bubble = Message.Bubble('Bubble Test', 'http://www.starwars.com/', 'http://i.imgur.com/4loi6PJ.jpg', '{{user.first_name}}', variables=variables) bubble.add_button(Message.Button(Message.ButtonType.WEB_URL, '{{user.last_name}}', url='http://www.starwars.com/', variables=variables)) m.add_bubble(bubble) bubble = m.as_dict()['attachment']['payload']['elements'][0] self.assertEquals(bubble['subtitle'], 'Isaac') self.assertEquals(bubble['buttons'][0]['title'], 'Huang') # Test error wrong_tmpl = 'Hi {{some.key}}' m = Message(wrong_tmpl) self.assertEquals(m.as_dict()['text'], wrong_tmpl)
def test_query_expression_rendering(self): """Test that query expresssion can be query and rendered correctly.""" CollectedDatum(user_id=self.user_1.id, key='data', value='value1').add() DatabaseManager.commit() time.sleep(1) CollectedDatum(user_id=self.user_1.id, key='data', value='value2').add() DatabaseManager.commit() time.sleep(1) CollectedDatum(user_id=self.user_1.id, key='data', value='value3').add() CollectedDatum(user_id=self.user_1.id, key='aaa', value='aaa').add() CollectedDatum(user_id=self.user_2.id, key='data', value='value4').add() DatabaseManager.commit() g.user = self.user_1 m = Message("{{data('data').first|upper}}") self.assertEquals(m.as_dict()['text'], 'VALUE1') m = Message("{{data('data').get(1)}}") self.assertEquals(m.as_dict()['text'], 'value2') m = Message("{{data('data').last}}") self.assertEquals(m.as_dict()['text'], 'value3') m = Message("{{data('data').lru(0)}}") self.assertEquals(m.as_dict()['text'], 'value3') m = Message("{{data('data').lru(1)}}") self.assertEquals(m.as_dict()['text'], 'value2') m = Message("{{data('data').fallback('valuef').get(5)}}") self.assertEquals(m.as_dict()['text'], 'valuef') m = Message("{{data('data').order_by('-created_at').first}}") self.assertEquals(m.as_dict()['text'], 'value3') m = Message("{{data('data').count}}") self.assertEquals(m.as_dict()['text'], '3') # Test error with self.assertRaises(Exception): Message("{{data('data')|some_filter}}") wrong_tmpl = "{{data('some_key').first}}" m = Message(wrong_tmpl) self.assertEquals(m.as_dict()['text'], wrong_tmpl)