def test_trello_url(self): w = Webhook() self.assertEqual(w.trello_url, '/webhooks/') w.id = 1 self.assertEqual(w.trello_url, '/webhooks/') w.id = None self.assertEqual(w.trello_url, '/webhooks/')
def test__update_remote(self): w = Webhook() # no trello_id, no update self.assertRaises(AssertionError, w._update_remote) w.trello_id = "123" w._update_remote() self.assertEqual(w.verb, 'PUT')
def test_callback_url(self): hook = Webhook( trello_model_id="M", auth_token="A", ).save(sync=False) self.assertEqual(hook.callback_url, CALLBACK_DOMAIN + hook.get_absolute_url())
def test_str_repr(self): hook = Webhook(trello_id='A', trello_model_id='B', auth_token='C') self.assertEqual( str(hook), u"Webhook: %s" % (hook.callback_url) ) self.assertEqual( unicode(hook), u"Webhook: %s" % (hook.callback_url) ) self.assertEqual( repr(hook), u"<Webhook id=%s, trello_id='%s', model='%s'>" % (hook.id, hook.trello_id, hook.trello_model_id) ) # now with an id hook.id = 1 self.assertEqual( str(hook), u"Webhook %i: %s" % (hook.id, hook.callback_url) ) self.assertEqual( unicode(hook), u"Webhook %i: %s" % (hook.id, hook.callback_url) ) self.assertEqual( repr(hook), u"<Webhook id=%s, trello_id='%s', model='%s'>" % (hook.id, hook.trello_id, hook.trello_model_id) )
def test__create_remote(self): w = Webhook() w._create_remote() self.assertTrue(w.is_active) self.assertEqual(w.verb, 'POST') self.assertEqual(w.trello_id, 'NEW_TRELLO_ID') w.trello_id = "123" self.assertRaises(AssertionError, w._create_remote)
def test_callback_url(self): hook = Webhook( trello_model_id="M", auth_token="A", ).save(sync=False) self.assertEqual( hook.callback_url, CALLBACK_DOMAIN + hook.get_absolute_url() )
def test_post_args(self): w = Webhook(auth_token="X", description="Foo-Bar", trello_model_id="123") self.assertEqual( w.post_args(), { 'callbackURL': w.callback_url, 'description': w.description, 'idModel': w.trello_model_id })
def test_get_client(self): # should fail without a token w = Webhook() self.assertRaises(AssertionError, w.get_client) # give it a token and should now get back a TrelloClient w.auth_token = 'X' client = w.get_client() self.assertEqual(client.api_key, TRELLO_API_KEY) self.assertEqual(client.api_secret, TRELLO_API_SECRET) self.assertEqual(client.resource_owner_key, w.auth_token) self.assertEqual(client.resource_owner_secret, None)
def test_get_absolute_url(self): hook = Webhook( trello_model_id="M", auth_token="A", ).save(sync=False) self.assertEqual( hook.get_absolute_url(), reverse('trello_callback_url', kwargs={ 'auth_token': hook.auth_token, 'trello_model_id': hook.trello_model_id }))
def test_post_args(self): w = Webhook( auth_token="X", description="Foo-Bar", trello_model_id="123" ) self.assertEqual( w.post_args(), { 'callbackURL': w.callback_url, 'description': w.description, 'idModel': w.trello_model_id } )
def test_get_absolute_url(self): hook = Webhook( trello_model_id="M", auth_token="A", ).save(sync=False) self.assertEqual( hook.get_absolute_url(), reverse( 'trello_callback_url', kwargs={ 'auth_token': hook.auth_token, 'trello_model_id': hook.trello_model_id } ) )
def handle(self, *args, **options): """Sync webhooks between local database and Trello. The syncing process is bidirectional - you may have webhooks registered with Trello that are not in the local database, and you may also webhooks in the local database that are not registered with Trello. Webhooks are registered in Trello against a combination of the Trello model id and a user token. The `list_hooks` API call requires a user token, and this _may_ be supplied as a command option (--token, -t). Alternatively, any tokens that are in the local database are also used, when calling `list_hooks`. The logic works like this: 1. Sync all local webhooks to Trello 2. Fetch all remote webhooks, using all available tokens 3. Save any remote webhooks not already stored locally At this point you should have the same webhooks locally and remotely. Any further edits (e.g. deletion) can be made from the admin site. """ local_webhooks = Webhook.objects.all() for webhook in local_webhooks: logger.info(u"Syncing local webhook (%r) to Trello", webhook) webhook.sync() # set of unique tokens that we know about from local webhooks, # combined with those that were passed in from the command args tokens = set([w.auth_token for w in local_webhooks] + [a for a in args]) # used to match webhooks when comparing with remote hooks local_match = lambda h: h.id in [w.trello_id for w in local_webhooks] if len(tokens) == 0: logger.info(u"There are no user tokens with which to check Trello.") # noqa logger.info(u"Usage: sync_webhooks <token token ...>") # noqa return logger.info(u"Checking %i Trello user tokens for missing local webhooks", len(tokens)) # noqa for token in tokens: for hook in Webhook.remote_objects.list_hooks(token): if local_match(hook): logger.info(u"Remote webhook (%s) already exists locally", hook) # noqa else: logger.info(u"Remote webhook (%s) does not exist locally", hook) # noqa Webhook( trello_id=hook.id, trello_model_id=hook.id_model, description=hook.desc, auth_token=hook.token, is_active=hook.active ).save(sync=False) local_webhooks = Webhook.objects.all() logger.info(u"Sync complete. There are %i webhooks.", local_webhooks.count()) for webhook in Webhook.objects.all(): logger.info(u"%s", webhook)
def test_str_repr(self): hook = Webhook(trello_id='A', trello_model_id='B', auth_token='C') self.assertEqual(str(hook), u"Webhook: %s" % (hook.callback_url)) self.assertEqual(unicode(hook), u"Webhook: %s" % (hook.callback_url)) self.assertEqual( repr(hook), u"<Webhook id=%s, trello_id='%s', model='%s'>" % (hook.id, hook.trello_id, hook.trello_model_id)) # now with an id hook.id = 1 self.assertEqual(str(hook), u"Webhook %i: %s" % (hook.id, hook.callback_url)) self.assertEqual(unicode(hook), u"Webhook %i: %s" % (hook.id, hook.callback_url)) self.assertEqual( repr(hook), u"<Webhook id=%s, trello_id='%s', model='%s'>" % (hook.id, hook.trello_id, hook.trello_model_id))
def test_save_no_sync(self): # Check that save updates the timestamps self.assertEqual(Webhook.objects.count(), 0) hook = Webhook().save(sync=False) self.assertEqual(Webhook.objects.count(), 1) self.assertIsNotNone(hook.id) self.assertEqual(hook.trello_model_id, '') self.assertEqual(hook.trello_id, '') self.assertEqual(hook.description, '') self.assertIsInstance(hook.created_at, datetime.datetime) self.assertEqual(hook.last_updated_at, hook.last_updated_at) self.assertEqual(hook.auth_token, '') timestamp = hook.created_at # and that saving again updates the last_updated_at hook.save(sync=False) self.assertEqual(hook.created_at, timestamp) self.assertNotEqual(hook.last_updated_at, timestamp)
def test_default_properties(self): hook = Webhook() self.assertEqual(hook.id, None) self.assertEqual(hook.trello_model_id, '') self.assertEqual(hook.trello_id, '') self.assertEqual(hook.description, '') self.assertEqual(hook.created_at, None) self.assertEqual(hook.last_updated_at, None) self.assertEqual(hook.auth_token, '') self.assertIsNone(hook.is_active)
def test_post_200(self): Webhook( auth_token=self.payload['auth_token'], trello_model_id=self.payload['trello_model_id']).save(sync=False) self.assertEqual(CallbackEvent.objects.count(), 0) test_payload = get_sample_data('commentCard', 'json') resp = self.client.post(self.url, data=json.dumps(test_payload), content_type='application/json') self.assertEqual(resp.status_code, 200) self.assertEqual(CallbackEvent.objects.count(), 1) self.assertEqual(CallbackEvent.objects.get().event_payload, test_payload)
def test_save_sync(self): # now try without syncing - should have no verb hook = Webhook() self.assertFalse(hasattr(hook, 'verb')) hook.save() self.assertEqual(hook.verb, 'POST') self.assertEqual(hook.trello_id, 'NEW_TRELLO_ID') # validate that an existing id is unchanged, hook.trello_id = 'OLD_TRELLO_ID' hook.save() self.assertEqual(hook.verb, 'PUT') self.assertEqual(hook.trello_id, 'OLD_TRELLO_ID')
def test_add_callback(self): hook = Webhook().save(sync=False) payload = get_sample_data('commentCard', 'json') event = hook.add_callback(json.dumps(payload)) self.assertEqual(event.webhook, hook) self.assertEqual(event.event_payload, payload)
def test_sync(self): w = Webhook() self.assertEqual(w.sync().verb, 'POST') w.trello_id = "123" self.assertEqual(w.sync().verb, 'PUT')
def test_touch(self): hook = Webhook().save(sync=False) self.assertTrue(hook.created_at == hook.last_updated_at) hook.touch() self.assertTrue(hook.last_updated_at > hook.created_at)
def test_has_trello_id(self): hook = Webhook() self.assertEqual(hook.trello_id, '') self.assertFalse(hook.has_trello_id) hook.trello_id = '1' self.assertTrue(hook.has_trello_id)
def test_delete(self): self.assertEqual(Webhook.objects.count(), 0) hook = Webhook().save(sync=False) self.assertEqual(Webhook.objects.count(), 1) hook.delete() self.assertEqual(Webhook.objects.count(), 0)
def setUp(self): self.webhook = Webhook(auth_token="ABC").save(sync=False) self.event = CallbackEvent(webhook=self.webhook, event_type='commentCard').save() self.admin = CallbackEventAdmin(CallbackEvent, None)