def test_update_db_fresh(self) -> None: files_path = str(Path(gettempdir(), randstr())) app = CatApp(redis_url='15', files_path=files_path) app.r.flushdb() app.update() # type: ignore[no-untyped-call] self.assertEqual(app.settings.title, 'CatApp') self.assertTrue(Path(files_path).is_dir())
def setUp(self) -> None: super().setUp() self.app = CatApp(redis_url='15', files_path=mkdtemp()) self.app.r.flushdb() self.app.update() # type: ignore self.staff_member = self.app.login() # type: ignore self.user = self.app.login() # type: ignore
def setUp(self): super().setUp() self.app = CatApp(redis_url='15', files_path=mkdtemp()) self.app.r.flushdb() handlers = [ (r'/api/cats$', CollectionEndpoint, {'get_collection': lambda: self.app.cats}), *make_orderable_endpoints(r'/api/cats', lambda: self.app.cats), *make_trashable_endpoints(r'/api/cats/([^/]+)', lambda i: self.app.cats[i]) ] self.server = Server(self.app, handlers, client_path='hello', client_modules_path='node_modules', port=16160) self.server.start() self.staff_member = self.app.login() self.user = self.app.login() self.client_user = self.user
async def test_update_db_version_first(self): Trashable.RETENTION = timedelta(seconds=0.2) # NOTE: Tag tmp can be removed on next database update self.setup_db('tmp') await sleep(1) app = CatApp(redis_url='15', files_path=mkdtemp()) app.update() # Update to version 3 self.assertFalse(app.settings.provider_description) # Update to version 4 self.assertNotIn('trashed', app.settings.json()) self.assertFalse(app.cats[0].trashed) # Update to version 5 self.assertFalse(hasattr(app.settings, 'favicon')) self.assertIsNone(app.settings.icon_small) self.assertIsNone(app.settings.icon_large) # Update to version 6 user = app.settings.staff[0] self.assertTrue(app.settings.push_vapid_private_key) self.assertTrue(app.settings.push_vapid_public_key) self.assertIsNotNone(app.activity.subscribers) self.assertEqual(user.device_notification_status, 'off') self.assertIsNone(user.push_subscription) # Update to version 7 app.user = app.settings.staff[0] self.assertEqual([event.type for event in app.activity], ['editable-edit', 'editable-edit', 'meow']) # Update to version 8 cats = list(app.cats.values()) app.start_empty_trash() await sleep(0.1) self.assertEqual(list(app.cats.values()), cats) await sleep(0.3) self.assertEqual(list(app.cats.values()), cats[:1]) # Update to version 9 first = app.activity[-1].time.replace(tzinfo=timezone.utc) last = app.activity[0].time.replace(tzinfo=timezone.utc) self.assertEqual(app.user.create_time, first) self.assertEqual(app.user.authenticate_time, last) user = app.users[1] self.assertEqual(user.create_time, user.authenticate_time) self.assertAlmostEqual(user.create_time, app.now(), delta=timedelta(minutes=1)) self.assertGreater(user.create_time, last)
async def test_update_db_version_previous(self): self.setup_db('0.38.1') await sleep(1) app = CatApp(redis_url='15', files_path=mkdtemp()) app.update() # type: ignore app.user = app.settings.staff[0] first = app.activity[-1].time.replace(tzinfo=timezone.utc) last = app.cats[1].activity[0].time.replace(tzinfo=timezone.utc) self.assertEqual(app.user.create_time, first) self.assertEqual(app.user.authenticate_time, last) user = app.users[1] self.assertEqual(user.create_time, user.authenticate_time) self.assertAlmostEqual(user.create_time, app.now(), delta=timedelta(minutes=1)) self.assertGreater(user.create_time, last)
def test_init_redis_url_invalid(self): with self.assertRaisesRegex(micro.ValueError, 'redis_url_invalid'): CatApp(redis_url='//localhost:foo')
def test_login_no_redis(self): app = CatApp(redis_url='//localhost:16160') with self.assertRaises(RedisError): app.login()
class ServerTest(ServerTestCase): def setUp(self): super().setUp() self.app = CatApp(redis_url='15', files_path=mkdtemp()) self.app.r.flushdb() handlers = [ (r'/api/cats$', CollectionEndpoint, {'get_collection': lambda: self.app.cats}), *make_orderable_endpoints(r'/api/cats', lambda: self.app.cats), *make_trashable_endpoints(r'/api/cats/([^/]+)', lambda i: self.app.cats[i]) ] self.server = Server(self.app, handlers, client_path='hello', client_modules_path='node_modules', port=16160) self.server.start() self.staff_member = self.app.login() self.user = self.app.login() self.client_user = self.user @gen_test async def test_availability(self): file_url = await self.app.files.write(b'Meow!', 'text/plain') # UI await self.request('/') await self.request('/manifest.webmanifest') await self.request( '/log-client-error', method='POST', body='{"type": "Error", "stack": "micro.UI.prototype.createdCallback", "url": "/"}') # API await self.request('/api/login', method='POST', body='') await self.request('/api/users/' + self.user.id) await self.request('/api/users/' + self.user.id, method='POST', body='{"name": "Happy"}') await self.request('/api/users/{}'.format(self.app.user.id), method='PATCH', body='{"op": "disable_notifications"}') await self.request('/api/settings') await self.request('/api/analytics/referrals', method='POST', body='{"url": "https://example.org/"}') await self.request(self.server.rewrite(file_url)) await self.request('/files', method='POST', body=b'<svg />', headers={'Content-Type': 'image/svg+xml'}) # API (generic) cat = self.app.cats.create() await self.request('/api/cats/move', method='POST', body='{{"item_id": "{}", "to_id": null}}'.format(cat.id)) await self.request('/api/cats/{}/trash'.format(cat.id), method='POST', body='') await self.request('/api/cats/{}/restore'.format(cat.id), method='POST', body='') # API (as staff member) self.client_user = self.staff_member await self.request( '/api/settings', method='POST', body='{"title": "CatzApp", "icon": "http://example.org/static/icon.svg"}') await self.request('/api/activity/v2') await self.request('/api/activity/v2', method='PATCH', body='{"op": "subscribe"}') await self.request('/api/activity/v2', method='PATCH', body='{"op": "unsubscribe"}') await self.request('/api/analytics/stats/users') await self.request('/api/analytics/referrals') @gen_test def test_endpoint_request(self): response = yield self.request('/api/users/' + self.user.id) user = json.loads(response.body.decode()) self.assertEqual(user.get('__type__'), 'User') self.assertEqual(user.get('id'), self.user.id) @gen_test def test_endpoint_request_invalid_body(self): with self.assertRaises(HTTPClientError) as cm: yield self.request('/api/users/' + self.user.id, method='POST', body='foo') e = cm.exception self.assertEqual(e.code, http.client.BAD_REQUEST) @gen_test def test_endpoint_request_key_error(self): with self.assertRaises(HTTPClientError) as cm: yield self.request('/api/users/foo') self.assertEqual(cm.exception.code, http.client.NOT_FOUND) @gen_test def test_endpoint_request_input_error(self): with self.assertRaises(HTTPClientError) as cm: yield self.request('/api/users/' + self.user.id, method='POST', body='{"name": 42}') self.assertEqual(cm.exception.code, http.client.BAD_REQUEST) error = json.loads(cm.exception.response.body.decode()) self.assertEqual(error.get('__type__'), 'InputError') @gen_test def test_endpoint_request_value_error(self): with self.assertRaises(HTTPClientError) as cm: yield self.request('/api/settings', method='POST', body='{"provider_description": {"en": " "}}') self.assertEqual(cm.exception.code, http.client.BAD_REQUEST) self.assertIn('provider_description_bad_type', cm.exception.response.body.decode()) @gen_test async def test_collection_endpoint_get(self): self.app.cats.create(name='Happy') self.app.cats.create(name='Grumpy') self.app.cats.create(name='Long') response = await self.request('/api/cats?slice=1:') cats = json.loads(response.body.decode()) self.assertEqual(cats.get('count'), 3) self.assertEqual([cat.get('name') for cat in cats.get('items', [])], ['Grumpy', 'Long']) self.assertEqual(cats.get('slice'), [1, 3])