async def test_reserve_tickets_free(cli, url, factory: Factory, login): await factory.create_company() await factory.create_cat() await factory.create_user() await factory.create_event(status='published') await login() data = { 'tickets': [{'t': True, 'first_name': 'Ticket', 'last_name': 'Buyer', 'email': '*****@*****.**'}], 'ticket_type': factory.ticket_type_id, } r = await cli.json_post(url('event-reserve-tickets', id=factory.event_id), data=data) assert r.status == 200, await r.text() data = await r.json() assert data == { 'booking_token': RegexStr(r'.+'), 'ticket_count': 1, 'extra_donated': None, 'item_price': None, 'total_price': None, 'timeout': AnyInt(), 'client_secret': None, 'action_id': AnyInt(), } assert decrypt_json(cli.app['main_app'], data['booking_token'].encode()) == { 'user_id': factory.user_id, 'action_id': AnyInt(), 'event_id': factory.event_id, 'price_cent': None, 'ticket_count': 1, 'event_name': 'The Event Name', }
async def test_get_payment_method(cli, url, login, factory: Factory): await factory.create_company(stripe_public_key=stripe_public_key, stripe_secret_key=stripe_secret_key) await factory.create_cat() await factory.create_user() await factory.create_event(status='published', price=10) await login() r = await cli.get( url('payment-method-details', payment_method='pm_card_amex')) assert r.status == 200, await r.text( ) # both db customer_id and payment_method customer_id are None data = await r.json() assert data == { 'card': { 'brand': 'amex', 'exp_month': AnyInt(), 'exp_year': AnyInt(), 'last4': '8431' }, 'address': { 'city': None, 'country': None, 'line1': None, 'line2': None, 'postal_code': None, 'state': None }, 'name': None, }
async def test_real_intent(cli, url, login, db_conn, factory: Factory): await factory.create_company(stripe_public_key=stripe_public_key, stripe_secret_key=stripe_secret_key) await factory.create_cat() await factory.create_user() await factory.create_event(status='published', price=123.45) await login() data = { 'tickets': [ { 't': True, 'first_name': 'Ticket', 'last_name': 'Buyer', 'email': '*****@*****.**' }, { 't': True, 'email': '*****@*****.**' }, ], 'ticket_type': factory.ticket_type_id, } r = await cli.json_post(url('event-reserve-tickets', id=factory.event_id), data=data) assert r.status == 200, await r.text() response_data = await r.json() assert response_data == { 'booking_token': RegexStr(r'.+'), 'ticket_count': 2, 'extra_donated': None, 'item_price': 123.45, 'total_price': 246.90, 'timeout': AnyInt(), 'client_secret': RegexStr(r'pi_.*'), 'action_id': AnyInt(), } customer_id = await db_conn.fetchval( 'SELECT stripe_customer_id FROM users WHERE id=$1', factory.user_id) assert customer_id is not None assert customer_id.startswith('cus_') app = cli.app['main_app'] r = await StripeClient(app, stripe_secret_key).get( f'payment_intents?limit=3&customer={customer_id}') assert len(r['data']) == 1 payment_intent = r['data'][0] assert payment_intent['amount'] == 246_90 assert payment_intent[ 'description'] == f'2 tickets for The Event Name ({factory.event_id})' assert payment_intent['metadata'] == { 'purpose': 'buy-tickets', 'event_id': str(factory.event_id), 'tickets_bought': '2', 'reserve_action_id': str(response_data['action_id']), 'user_id': str(factory.user_id), }
async def test_reserve_tickets(cli, url, db_conn, factory: Factory, login): await factory.create_company() await factory.create_cat() await factory.create_user(first_name=None, last_name=None, email='*****@*****.**') await factory.create_event(status='published', price=10) await login(email='*****@*****.**') data = { 'tickets': [ { 't': True, 'first_name': 'Ticket', 'last_name': 'Buyer', 'email': '*****@*****.**', 'allow_marketing': True, }, { 't': True, 'first_name': 'Other', 'last_name': 'Person', 'email': '*****@*****.**', 'extra_info': 'I love to party', 'cover_costs': None, 'allow_marketing': None, }, ], 'ticket_type': factory.ticket_type_id, } r = await cli.json_post(url('event-reserve-tickets', id=factory.event_id), data=data) assert r.status == 200, await r.text() data = await r.json() assert data == { 'booking_token': RegexStr(r'.+'), 'ticket_count': 2, 'extra_donated': None, 'item_price': 10.0, 'total_price': 20.0, 'timeout': AnyInt(), 'client_secret': RegexStr(r'payment_intent_secret_\d+'), 'action_id': AnyInt(), } booking_token = decrypt_json(cli.app['main_app'], data['booking_token'].encode()) reserve_action_id = await db_conn.fetchval("SELECT id FROM actions WHERE type='reserve-tickets'") assert booking_token == { 'user_id': factory.user_id, 'action_id': reserve_action_id, 'event_id': factory.event_id, 'price_cent': 20_00, 'ticket_count': 2, 'event_name': 'The Event Name', }
async def test_delivery(factory: Factory, db_conn, cli): await factory.create_company() await factory.create_user(email='*****@*****.**') email_id = await create_email(factory, db_conn) data = { 'Type': 'Notification', 'Message': json.dumps({ 'eventType': 'Delivery', 'mail': { 'messageId': '123456789' }, 'delivery': { 'processingTimeMillis': 789 } }), } r = await cli.post('/api/ses-webhook/', json=data, headers={'Authorization': 'Basic cHc6dGVzdHM='}) assert r.status == 204, await r.text() assert 'Delivery' == await db_conn.fetchval('select status from emails') evt = await db_conn.fetchrow('select * from email_events') assert dict(evt) == { 'id': AnyInt(), 'email': email_id, 'ts': CloseToNow(delta=3), 'status': 'Delivery', 'extra': '{"delivery_time": 789}', }
async def test_send_email(email_actor: EmailActor, factory: Factory, dummy_server, db_conn): await factory.create_company() await factory.create_user(email='*****@*****.**') u2 = await factory.create_user(email='*****@*****.**', receive_emails=False) ctx = { 'summary': 'testing', } await email_actor.send_emails( factory.company_id, Triggers.admin_notification, [UserEmail(id=factory.user_id, ctx=ctx), UserEmail(id=u2, ctx=ctx)], ) assert dummy_server.app['log'] == [ ('email_send_endpoint', 'Subject: "Update: testing", To: "Frank Spencer <*****@*****.**>"' ), ] assert 1 == await db_conn.fetchval('select count(*) from emails') email = await db_conn.fetchrow('select * from emails') assert dict(email) == { 'id': AnyInt(), 'company': factory.company_id, 'user_id': factory.user_id, 'ext_id': 'testing', 'send_ts': CloseToNow(delta=3), 'update_ts': CloseToNow(delta=3), 'status': 'pending', 'trigger': 'admin-notification', 'subject': 'Update: testing', 'address': '*****@*****.**', }
async def test_edit_update_email_defs(cli, url, login, factory: Factory, db_conn): await factory.create_company() await factory.create_user() await login() await db_conn.execute_b( 'INSERT INTO email_definitions (:values__names) VALUES :values', values=Values( company=factory.company_id, trigger=Triggers.event_reminder, subject='testing', body='xxx', title='the title', ), ) data = dict(subject='foobar', body='the body', active=False, title='different') r = await cli.json_post(url('email-defs-edit', trigger=Triggers.event_reminder.value), data=data) assert r.status == 200, await r.text() email_def = await db_conn.fetchrow('SELECT * FROM email_definitions') assert dict(email_def) == { 'id': AnyInt(), 'company': factory.company_id, 'trigger': 'event-reminder', 'active': False, 'subject': 'foobar', 'title': 'different', 'body': 'the body', }
async def test_get_jobs(arq_redis: ArqRedis): await arq_redis.enqueue_job('foobar', a=1, b=2, c=3) await asyncio.sleep(0.01) await arq_redis.enqueue_job('second', 4, b=5, c=6) await asyncio.sleep(0.01) await arq_redis.enqueue_job('third', 7, b=8) jobs = await arq_redis.queued_jobs() assert [dataclasses.asdict(j) for j in jobs] == [ { 'function': 'foobar', 'args': (), 'kwargs': { 'a': 1, 'b': 2, 'c': 3 }, 'job_try': None, 'enqueue_time': CloseToNow(), 'score': AnyInt(), }, { 'function': 'second', 'args': (4, ), 'kwargs': { 'b': 5, 'c': 6 }, 'job_try': None, 'enqueue_time': CloseToNow(), 'score': AnyInt(), }, { 'function': 'third', 'args': (7, ), 'kwargs': { 'b': 8 }, 'job_try': None, 'enqueue_time': CloseToNow(), 'score': AnyInt(), }, ] assert jobs[0].score < jobs[1].score < jobs[2].score assert isinstance(jobs[0], JobDef) assert isinstance(jobs[1], JobDef) assert isinstance(jobs[2], JobDef)
async def test_list_lots(cli, db_conn): orgs = [Values(name=f'Org {string.ascii_uppercase[i]}', slug=f'org-{i}') for i in range(7)] await db_conn.execute_b('INSERT INTO organisations (:values__names) VALUES :values', values=MultipleValues(*orgs)) r = await cli.get('/orgs/') assert r.status == 200, await r.text() obj = await r.json() assert obj == { 'items': [ {'id': AnyInt(), 'name': 'Org A', 'slug': 'org-0'}, {'id': AnyInt(), 'name': 'Org B', 'slug': 'org-1'}, {'id': AnyInt(), 'name': 'Org C', 'slug': 'org-2'}, {'id': AnyInt(), 'name': 'Org D', 'slug': 'org-3'}, {'id': AnyInt(), 'name': 'Org E', 'slug': 'org-4'}, ], 'count': 7, 'pages': 2, } r = await cli.get('/orgs/?page=2') assert r.status == 200, await r.text() obj = await r.json() assert obj == { 'items': [ {'id': AnyInt(), 'name': 'Org F', 'slug': 'org-5'}, {'id': AnyInt(), 'name': 'Org G', 'slug': 'org-6'}, ], 'count': 7, 'pages': 2, }
async def test_reserve_tickets_cover_costs(cli, url, factory: Factory, login): await factory.create_company() await factory.create_cat(cover_costs_message='Help!', cover_costs_percentage=12.5) await factory.create_user(first_name=None, last_name=None, email='*****@*****.**') await factory.create_event(status='published', price=10) await login(email='*****@*****.**') data = { 'tickets': [ { 't': True, 'first_name': 'Ticket', 'last_name': 'Buyer', 'email': '*****@*****.**', 'cover_costs': True, }, { 't': True, }, ], 'ticket_type': factory.ticket_type_id, } r = await cli.json_post(url('event-reserve-tickets', id=factory.event_id), data=data) assert r.status == 200, await r.text() data = await r.json() assert data == { 'booking_token': RegexStr(r'.+'), 'ticket_count': 2, 'extra_donated': 2.5, 'item_price': 10.0, 'total_price': 22.50, 'timeout': AnyInt(), 'client_secret': RegexStr(r'payment_intent_secret_\d+'), 'action_id': AnyInt(), } assert decrypt_json(cli.app['main_app'], data['booking_token'].encode()) == { 'user_id': factory.user_id, 'action_id': AnyInt(), 'event_id': factory.event_id, 'price_cent': 22_50, 'ticket_count': 2, 'event_name': 'The Event Name', }
async def test_link_shortening(send_email, tmpdir, cli, db_conn, worker): token = await send_with_link(send_email, tmpdir) assert 1 == await db_conn.fetchval('select count(*) from messages') m = await db_conn.fetchrow('select * from messages') assert m['status'] == 'send' assert 1 == await db_conn.fetchval('select count(*) from links') link = await db_conn.fetchrow('select * from links') assert dict(link) == { 'id': AnyInt(), 'message_id': m['id'], 'token': token, 'url': 'https://www.foobar.com' } r = await cli.get( '/l' + token, allow_redirects=False, headers={ 'X-Forwarded-For': '54.170.228.0, 141.101.88.55', 'X-Request-Start': '1969660800', 'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) ' 'Chrome/59.0.3071.115 Safari/537.36', }, ) assert r.status == 307, await r.text() assert r.headers['location'] == 'https://www.foobar.com' assert await worker.run_check() == 2 m_status = await db_conn.fetchval( 'select status from messages where id=$1', m['id']) assert m_status == 'click' assert 1 == await db_conn.fetchval('select count(*) from events') event = await db_conn.fetchrow('select * from events') assert event['status'] == 'click' assert event['ts'] == datetime(2032, 6, 1, 0, 0, tzinfo=timezone.utc) extra = json.loads(event['extra']) assert extra == { 'ip': '54.170.228.0', 'target': 'https://www.foobar.com', 'user_agent': ('Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) ' 'Chrome/59.0.3071.115 Safari/537.36'), 'user_agent_display': 'Chrome 59 on Linux', }
async def test_host_signup_email(cli, url, factory: Factory, db_conn, dummy_server, settings): await factory.create_company() assert 0 == await db_conn.fetchval('SELECT COUNT(*) FROM users') data = { 'email': '*****@*****.**', 'name': 'Jane Doe', 'grecaptcha_token': '__ok__', } r = await cli.post(url('signup-host', site='email'), data=json.dumps(data)) assert r.status == 200, await r.text() response_data = await r.json() assert 1 == await db_conn.fetchval('SELECT COUNT(*) FROM users') user = await db_conn.fetchrow( 'SELECT id, company, first_name, last_name, email, role, status FROM users' ) assert response_data == { 'user': { 'id': user['id'], 'name': 'Jane Doe', 'email': '*****@*****.**', 'role': 'host', }, } assert dict(user) == { 'id': AnyInt(), 'company': factory.company_id, 'first_name': 'Jane', 'last_name': 'Doe', 'email': '*****@*****.**', 'role': 'host', 'status': 'pending', } assert dummy_server.app['log'] == [ ('grecaptcha', '__ok__'), ( 'email_send_endpoint', 'Subject: "Testing Account Created (Action required)", To: "Jane Doe <*****@*****.**>"', ), ] email = dummy_server.app['emails'][0]['part:text/plain'] assert 'Confirm Email' in email assert 'Create & Publish Events' not in email token = re.search('/set-password/\?sig=([^"]+)', email).group(1) token_data = json.loads( fernet.Fernet(settings.auth_key).decrypt(token.encode()).decode()) assert token_data == { 'user_id': user['id'], 'nonce': RegexStr('.{20}'), }
async def test_job_info(arq_redis: ArqRedis): t_before = time() j = await arq_redis.enqueue_job('foobar', 123, a=456) info = await j.info() assert info == { 'enqueue_time': CloseToNow(), 'job_try': None, 'function': 'foobar', 'args': (123, ), 'kwargs': { 'a': 456 }, 'score': AnyInt(), } assert abs(t_before * 1000 - info['score']) < 1000
async def test_webhook_bad_signature4(cli, url, factory: Factory, settings, db_conn): await factory.create_company() body = 'whatever' t = 123456 stripe_webhook_secret = await db_conn.fetchval( 'select stripe_webhook_secret from companies') sig = hmac.new(stripe_webhook_secret.encode(), f'{t}.{body}'.encode(), hashlib.sha256).hexdigest() r = await cli.post(url('stripe-webhook'), data=body, headers={'Stripe-Signature': f't={t},v1={sig}'}) assert r.status == 400, await r.text() assert await r.json() == {'message': 'webhook too old', 'age': AnyInt()}
async def test_webhook(cli, send_email, db_conn, worker): uuid = str(uuid4()) message_id = await send_email(uid=uuid) message = await db_conn.fetchrow( 'select * from messages where external_id=$1', message_id) assert message['status'] == 'send' first_update_ts = message['update_ts'] events = await db_conn.fetchval('select count(*) from events') assert events == 0 data = { 'ts': int(2e9), 'event': 'open', '_id': message_id, 'foobar': ['hello', 'world'] } r = await cli.post('/webhook/test/', json=data) assert r.status == 200, await r.text() assert await worker.run_check() == 2 message = await db_conn.fetchrow( 'select * from messages where external_id=$1', message_id) assert message['status'] == 'open' assert message['update_ts'] > first_update_ts events = await db_conn.fetch('select * from events where message_id=$1', message['id']) events = [dict(e) for e in events] assert len(events) == 1 assert events == [{ 'id': AnyInt(), 'message_id': message['id'], 'status': 'open', 'ts': datetime(2033, 5, 18, 3, 33, 20, tzinfo=timezone.utc), 'extra': RegexStr('{.*}'), }] extra = json.loads(events[0]['extra']) assert extra['diag'] is None assert extra['opens'] is None
async def test_booking_info_limited(cli, url, factory: Factory, login, db_conn): await factory.create_company() await factory.create_cat() await factory.create_user() await factory.create_event(ticket_limit=8, status='published') await login() cat_slug, event_slug = await db_conn.fetchrow( 'SELECT cat.slug, e.slug FROM events AS e JOIN categories cat on e.category = cat.id WHERE e.id=$1', factory.event_id ) r = await cli.get(url('event-booking-info-public', category=cat_slug, event=event_slug)) assert r.status == 200, await r.text() data = await r.json() assert data == { 'tickets_remaining': 8, 'existing_tickets': 0, 'ticket_types': [{'id': AnyInt(), 'name': 'Standard', 'price': None}], }
async def test_edit_email_defs(cli, url, login, factory: Factory, db_conn): await factory.create_company() await factory.create_user() await login() data = dict(subject='foobar', active=False, body='the body') r = await cli.json_post(url('email-defs-edit', trigger=Triggers.event_reminder.value), data=data) assert r.status == 200, await r.text() email_def = await db_conn.fetchrow('SELECT * FROM email_definitions') assert dict(email_def) == { 'id': AnyInt(), 'company': factory.company_id, 'trigger': 'event-reminder', 'active': False, 'subject': 'foobar', 'title': None, 'body': 'the body', }
async def test_reserve_tickets(cli, url, db_conn, factory: Factory, login): await factory.create_company() await factory.create_cat() await factory.create_user(first_name='Ticket', last_name=None, email='*****@*****.**') await factory.create_event(status='published', price=10) await login(email='*****@*****.**') data = { 'tickets': [ { 't': True, 'name': 'Ticket Buyer', 'email': '*****@*****.**', }, { 't': True, 'name': 'Other Person', 'email': '*****@*****.**', 'extra_info': 'I love to party' }, ] } r = await cli.post(url('event-reserve-tickets', id=factory.event_id), data=json.dumps(data)) assert r.status == 200, await r.text() data = await r.json() assert data == { 'booking_token': RegexStr('.+'), 'ticket_count': 2, 'item_price_cent': 10_00, 'total_price_cent': 20_00, 'user': { 'id': factory.user_id, 'name': 'Ticket Buyer', 'email': '*****@*****.**', 'role': 'admin', }, 'timeout': AnyInt(), }
async def test_unsubscribe(factory: Factory, db_conn, cli): await factory.create_company() await factory.create_user(email='*****@*****.**') assert await db_conn.fetchval( 'select receive_emails from users where id=$1', factory.user_id) email_id = await create_email(factory, db_conn) data = { 'Type': 'Notification', 'Message': json.dumps({ 'eventType': 'Complaint', 'mail': { 'messageId': '123456789' }, 'complaint': { 'timestamp': '2032-10-16T12:00:00.000Z' }, }), } r = await cli.post('/api/ses-webhook/', json=data, headers={'Authorization': 'Basic cHc6dGVzdHM='}) assert r.status == 204, await r.text() assert 'Complaint' == await db_conn.fetchval('select status from emails') assert 1 == await db_conn.fetchval('select count(*) from email_events') evt = await db_conn.fetchrow('select * from email_events') assert dict(evt) == { 'id': AnyInt(), 'email': email_id, 'ts': datetime(2032, 10, 16, 12, 0, tzinfo=timezone.utc), 'status': 'Complaint', 'extra': '{"unsubscribe": true}', } assert not await db_conn.fetchval( 'select receive_emails from users where id=$1', factory.user_id)
async def test_booking_info_sig(cli, url, factory: Factory, login, settings, db_conn): await factory.create_company() await factory.create_cat() await factory.create_user() await factory.create_event(ticket_limit=20, status='published', public=False) await login() event_link = await db_conn.fetchval( """ SELECT event_link(cat.slug, e.slug, e.public, $2) FROM events AS e JOIN categories cat on e.category = cat.id WHERE e.id=$1 """, factory.event_id, settings.auth_key ) _, cat_slug, event_slug, sig = event_link.strip('/').split('/') r = await cli.get(url('event-booking-info-private', category=cat_slug, event=event_slug, sig=sig)) assert r.status == 200, await r.text() data = await r.json() assert data == { 'tickets_remaining': None, 'existing_tickets': 0, 'ticket_types': [{'id': AnyInt(), 'name': 'Standard', 'price': None}], }
async def test_send_webhook(factory: Factory, db_conn, cli): await factory.create_company() await factory.create_user(email='*****@*****.**') email_id = await create_email(factory, db_conn) data = { 'Type': 'Notification', 'Message': json.dumps({ 'eventType': 'Send', 'mail': { 'messageId': '123456789', 'timestamp': '2032-10-16T12:00:00.000Z' } }), } r = await cli.post('/api/ses-webhook/', json=data, headers={'Authorization': 'Basic cHc6dGVzdHM='}) assert r.status == 204, await r.text() assert 1 == await db_conn.fetchval('select count(*) from emails') dt = datetime(2032, 10, 16, 12, 0, tzinfo=timezone.utc) assert ( 'Send', dt) == await db_conn.fetchrow('select status, update_ts from emails') assert 1 == await db_conn.fetchval('select count(*) from email_events') evt = await db_conn.fetchrow('select * from email_events') assert dict(evt) == { 'id': AnyInt(), 'email': email_id, 'ts': dt, 'status': 'Send', 'extra': None, }
def test_duplicate_file(client: TestClient): r = client.delete('/testing/storage/') assert r.status_code == 200, r.text r = client.post('/create/', headers={'authorisation': 'YWJjZAy'}) assert r.status_code == 200, r.text obj = r.json() pk1 = re.sub(r'^https://example\.com/', '', obj['url']).strip('/') key1 = obj['secret_key'] site_expiration = datetime.fromisoformat( obj['site_expiration'][:-1]).replace(tzinfo=timezone.utc) expiration1 = int(round(site_expiration.timestamp())) content = 'this is a test file' r = client.post( f'/{pk1}/snap.file', data=content, headers={ 'authorisation': key1, 'content-type': 'text/html' }, ) assert r.status_code == 200, r.text # make sure expiration2 > expiration1 sleep(1) r = client.post('/create/', headers={'authorisation': 'YWJjZAy'}) assert r.status_code == 200, r.text obj = r.json() pk2 = re.sub(r'^https://example\.com/', '', obj['url']).strip('/') key2 = obj['secret_key'] site_expiration = datetime.fromisoformat( obj['site_expiration'][:-1]).replace(tzinfo=timezone.utc) expiration2 = int(round(site_expiration.timestamp())) assert expiration2 > expiration1 r = client.post( f'/{pk2}/different.file', data=content, headers={ 'authorisation': key2, 'content-type': 'foo/bar' }, ) assert r.status_code == 200, r.text r = client.get(f'/{pk1}/snap.file') assert r.status_code == 200, r.text assert r.text == content assert r.headers['content-type'] == 'text/html' r = client.get(f'/{pk2}/different.file') assert r.status_code == 200, r.text assert r.text == content assert r.headers['content-type'] == 'foo/bar' r = client.get('/testing/storage/', params={'prefix': f'site:{pk1}'}) assert r.status_code == 200, r.text assert r.json() == { f'site:{pk1}:/.smokeshow.json': { 'value': RegexStr(fr'\{{\n "url": "https://example.com/{pk1}/",\n.*'), 'metadata': { 'content_type': 'application/json', 'size': AnyInt() }, 'expiration': expiration1, }, f'site:{pk1}:/snap.file': { 'value': '1', 'metadata': { 'size': 19, 'content_type': 'text/html', 'hash': 'WIFwflSwES+QG8g6H/usrI+rdOpGpvcGo+/F99TBxiU=', }, 'expiration': expiration1, }, } r = client.get('/testing/storage/', params={'prefix': f'site:{pk2}'}) assert r.status_code == 200, r.text assert r.json() == { f'site:{pk2}:/.smokeshow.json': { 'value': RegexStr(fr'\{{\n "url": "https://example.com/{pk2}/",\n.*'), 'metadata': { 'content_type': 'application/json', 'size': AnyInt() }, 'expiration': expiration2, }, f'site:{pk2}:/different.file': { 'value': '1', 'metadata': { 'size': 19, 'content_type': 'foo/bar', 'hash': 'WIFwflSwES+QG8g6H/usrI+rdOpGpvcGo+/F99TBxiU=' }, 'expiration': expiration2, }, } r = client.get('/testing/storage/', params={'prefix': 'file:WIFwflSwES'}) assert r.status_code == 200, r.text assert r.json() == { 'file:WIFwflSwES+QG8g6H/usrI+rdOpGpvcGo+/F99TBxiU=': { 'value': 'this is a test file', 'metadata': { 'path': '/different.file', 'public_key': pk2 }, 'expiration': expiration2, } }
def test_any_int_true(): any_int = AnyInt() assert 123 == any_int assert str(any_int) == '123'
def test_any_int_false(): any_int = AnyInt() with pytest.raises(AssertionError): assert '123' == any_int assert str(any_int) == '<AnyInt>'
async def test_reserve_tickets_no_name(cli, url, db_conn, factory: Factory, login): await factory.create_company() await factory.create_cat() await factory.create_user(first_name='T', last_name='B', email='*****@*****.**') await factory.create_event(status='published', price=10) await login(email='*****@*****.**') data = { 'tickets': [ { 't': True, 'first_name': 'TT', 'last_name': 'BB', 'email': '*****@*****.**', }, { 't': True, }, ], 'ticket_type': factory.ticket_type_id, } r = await cli.json_post(url('event-reserve-tickets', id=factory.event_id), data=data) assert r.status == 200, await r.text() data = await r.json() assert data == { 'booking_token': RegexStr(r'.+'), 'ticket_count': 2, 'extra_donated': None, 'item_price': 10.0, 'total_price': 20.0, 'timeout': AnyInt(), 'client_secret': RegexStr(r'payment_intent_secret_\d+'), 'action_id': AnyInt(), } users = [dict(r) for r in await db_conn.fetch('SELECT first_name, last_name, email, role FROM users ORDER BY id')] assert users == [ { 'first_name': 'T', 'last_name': 'B', 'email': '*****@*****.**', 'role': 'admin', }, ] users = [dict(r) for r in await db_conn.fetch( """ SELECT event, user_id, first_name, last_name, reserve_action, booked_action, status, extra_info FROM tickets ORDER BY user_id """ )] reserve_action_id = await db_conn.fetchval("SELECT id FROM actions WHERE type='reserve-tickets'") assert users == [ { 'event': factory.event_id, 'user_id': factory.user_id, 'first_name': 'TT', 'last_name': 'BB', 'reserve_action': reserve_action_id, 'booked_action': None, 'status': 'reserved', 'extra_info': None, }, { 'event': factory.event_id, 'user_id': None, 'first_name': None, 'last_name': None, 'reserve_action': reserve_action_id, 'booked_action': None, 'status': 'reserved', 'extra_info': None, }, ]
def test_create_get(client: TestClient): r = client.delete('/testing/storage/') assert r.status_code == 200, r.text r = client.post('/create/', headers={'authorisation': 'YWJjZAy'}) assert r.status_code == 200, r.text obj = r.json() # debug(obj) assert obj['message'] == 'New site created successfully' assert obj['url'].startswith('https://example.com/') assert obj['site_creation'] == RegexStr( r'20\d\d-\d\d-\d\dT\d\d:\d\d:\d\d(\.\d+)?Z') site_creation = datetime.fromisoformat( obj['site_creation'][:-1]).replace(tzinfo=timezone.utc) assert site_creation == CloseToNow() site_expiration = datetime.fromisoformat( obj['site_expiration'][:-1]).replace(tzinfo=timezone.utc) assert site_expiration - site_creation == timedelta(seconds=90) pk = re.sub(r'^https://example\.com/', '', obj['url']).strip('/') r = client.post( f'/{pk}/', data='<h1>this is a test</h1>', headers={ 'authorisation': obj['secret_key'], 'content-type': 'text/html' }, ) assert r.status_code == 200, r.text assert r.json() == { 'path': '/', 'content_type': 'text/html', 'size': 23, 'total_site_size': 23 } r = client.get(f'/{pk}/') assert r.status_code == 200, r.text assert r.text == '<h1>this is a test</h1>' assert r.headers['content-type'] == 'text/html' r = client.get(f'/{pk}/.smokeshow.json') assert r.status_code == 200, r.text assert r.json() == { 'url': f'https://example.com/{pk}/', 'site_creation': CloseToNow(delta=10), 'site_expiration': RegexStr(r'20\d\d-\d\d-\d\dT.+'), 'files': ['/'], 'total_site_size': 175, } assert r.headers['content-type'] == 'application/json' r = client.post( f'/{pk}/foobar.html', data='<h1>this is my page</h1>', headers={ 'authorisation': obj['secret_key'], 'content-type': 'foo/bar' }, ) assert r.status_code == 200, r.text assert r.json() == { 'path': '/foobar.html', 'content_type': 'foo/bar', 'size': 24, 'total_site_size': 47 } r = client.get(f'/{pk}/foobar/') assert r.status_code == 200, r.text assert r.text == '<h1>this is my page</h1>' assert r.headers['content-type'] == 'foo/bar' expiration = int( round(site_expiration.replace(tzinfo=timezone.utc).timestamp())) r = client.get('/testing/storage/', params={'prefix': f'site:{pk}'}) assert r.status_code == 200, r.text # debug(r.json()) # debug(client.inspect_log_wait(wait_time=3)) assert r.json() == { f'site:{pk}:/': { 'value': '1', 'metadata': { 'size': 23, 'content_type': 'text/html', 'hash': 'H4OFKgUZxqnmcsGSJH4+soIyellWXc1Kq5t/fzbuHhQ=', }, 'expiration': expiration, }, f'site:{pk}:/.smokeshow.json': { 'value': RegexStr('{.+}'), 'metadata': { 'content_type': 'application/json', 'size': AnyInt() }, 'expiration': expiration, }, f'site:{pk}:/foobar.html': { 'value': '1', 'metadata': { 'size': 24, 'content_type': 'foo/bar', 'hash': 'jqfqkZwCywQ/gc9JZlkCIj3pbO7fBy9TTpSVYDCWfio=' }, 'expiration': expiration, }, } r = client.get('/testing/storage/', params={'prefix': 'file:'}) assert r.status_code == 200, r.text obj = r.json() assert obj['file:H4OFKgUZxqnmcsGSJH4+soIyellWXc1Kq5t/fzbuHhQ='] == { 'value': '<h1>this is a test</h1>', 'metadata': { 'path': '/', 'public_key': pk }, 'expiration': expiration, } assert obj['file:jqfqkZwCywQ/gc9JZlkCIj3pbO7fBy9TTpSVYDCWfio='] == { 'value': '<h1>this is my page</h1>', 'metadata': { 'path': '/foobar.html', 'public_key': pk }, 'expiration': expiration, }
async def test_donate_with_gift_aid(cli, url, dummy_server, factory: Factory, login, db_conn): await factory.create_company() await factory.create_cat() await factory.create_user() await factory.create_event() await factory.create_donation_option() factory.user_id = await factory.create_user( first_name='other', last_name='person', email='*****@*****.**') await login('*****@*****.**') r = await cli.json_post( url('donation-prepare', don_opt_id=factory.donation_option_id, event_id=factory.event_id)) assert r.status == 200, await r.text() action_id = await db_conn.fetchval('select id from actions where type=$1', ActionTypes.donate_prepare) data = await r.json() assert data == { 'client_secret': f'payment_intent_secret_{action_id}', 'action_id': action_id, } post_data = dict( title='Mr', first_name='Joe', last_name='Blogs', address='Testing Street', city='Testingville', postcode='TE11 0ST', ) r = await cli.json_post(url('donation-gift-aid', action_id=action_id), data=post_data) assert r.status == 200, await r.text() assert 0 == await db_conn.fetchval('SELECT COUNT(*) FROM donations') await factory.fire_stripe_webhook(action_id, amount=20_00, purpose='donate') assert dummy_server.app['log'] == [ 'POST stripe_root_url/customers', 'POST stripe_root_url/payment_intents', ('email_send_endpoint', 'Subject: "Thanks for your donation", To: "other person <*****@*****.**>"' ) ] assert 1 == await db_conn.fetchval('SELECT COUNT(*) FROM donations') r = await db_conn.fetchrow('SELECT * FROM donations') assert dict(r) == { 'id': AnyInt(), 'donation_option': factory.donation_option_id, 'amount': 20, 'gift_aid': True, 'title': 'Mr', 'first_name': 'Joe', 'last_name': 'Blogs', 'address': 'Testing Street', 'city': 'Testingville', 'postcode': 'TE11 0ST', 'action': AnyInt(), } action = await db_conn.fetchrow('SELECT * FROM actions WHERE id= $1', r['action']) assert dict(action) == { 'id': AnyInt(), 'company': factory.company_id, 'user_id': factory.user_id, 'event': factory.event_id, 'ts': CloseToNow(), 'type': 'donate', 'extra': RegexStr(r'{.*}'), } assert json.loads(action['extra']) == { 'charge_id': 'charge-id', 'stripe_balance_transaction': 'txn_charge-id', '3DS': True, 'brand': 'Visa', 'card_last4': '1234', 'card_expiry': '12/32', 'payment_metadata': { 'purpose': 'donate', 'user_id': factory.user_id, 'event_id': factory.event_id, 'reserve_action_id': action_id, }, } assert len(dummy_server.app['emails']) == 1 email = dummy_server.app['emails'][0] assert email['To'] == 'other person <*****@*****.**>' assert email['part:text/plain'] == ( 'Hi other,\n' '\n' 'Thanks for your donation to testing donation option of £20.00.\n' '\n' 'You have allowed us to collect gift aid meaning we can collect %25 on top of your original donation.\n' '\n' '_(Card Charged: Visa 12/32 - ending 1234)_\n')