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': '*****@*****.**', }
def test_build_simple_som(tmpdir): mktree( tmpdir, { 'dist/theme/assets/whatever.1234567.png': '**', 'pages': { 'foobar.md': '# hello\n\nthis is a test foo: {{ foo }}', 'posts/2032-06-01-testing.html': '# testing', 'static/image.png': '*', }, 'theme/templates/main.jinja': 'main, content:\n\n {{ content }}', }) config = Config(source_dir=str(tmpdir), tmp_dir=str(tmpdir.join('tmp')), foo='bar', defaults={'/posts/*': { 'uri': '/foobar/{slug}.html' }}) pages = build_pages(config) content_templates(pages.values(), config) source_dir = Path(tmpdir) # debug(som) assert { '/foobar.md': { 'infile': source_dir / 'pages/foobar.md', 'content_template': 'content/foobar.md', 'title': 'Foobar', 'slug': 'foobar', 'created': CloseToNow(), 'uri': '/foobar/', 'template': None, 'content': ('# hello\n' '\n' 'this is a test foo: {{ foo }}'), 'pass_through': False, }, '/posts/2032-06-01-testing.html': { 'infile': source_dir / 'pages/posts/2032-06-01-testing.html', 'content_template': 'content/posts/2032-06-01-testing.html', 'title': 'Testing', 'slug': 'testing', 'created': datetime(2032, 6, 1, 0, 0), 'uri': '/foobar/testing.html', 'template': None, 'content': '# testing', 'pass_through': False, }, '/static/image.png': { 'infile': source_dir / 'pages/static/image.png', 'title': 'image.png', 'slug': 'image.png', 'created': CloseToNow(), 'uri': '/static/image.png', 'pass_through': True, } } == pages
async def test_old_event(factory: Factory, db_conn, cli): await factory.create_company() await factory.create_user(email='*****@*****.**') await create_email(factory, db_conn) data = { 'Type': 'Notification', 'Message': json.dumps({ 'eventType': 'Send', 'mail': { 'messageId': '123456789', 'timestamp': '2000-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 ('pending', CloseToNow(delta=3) ) == await db_conn.fetchrow('select status, update_ts from emails') assert datetime(2000, 10, 16, 12, 0, tzinfo=timezone.utc) == await db_conn.fetchval( 'select ts from email_events')
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_list_donations(cli, url, 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() await factory.create_donation() await login() r = await cli.get( url('donation-opt-donations', pk=factory.donation_option_id)) assert r.status == 200, await r.text() data = await r.json() assert data == { 'donations': [ { 'id': factory.donation_id, 'amount': 20.0, 'first_name': 'Foo', 'last_name': 'Bar', 'address': None, 'city': None, 'postcode': None, 'gift_aid': False, 'user_id': factory.user_id, 'user_first_name': 'Frank', 'user_last_name': 'Spencer', 'user_email': '*****@*****.**', 'ts': CloseToNow(), 'event_id': factory.event_id, 'event_name': 'The Event Name', }, ], }
async def test_event_ticket_export_host(cli, url, login, factory: Factory, db_conn): await factory.create_company() await factory.create_cat() await factory.create_user(role='host') await factory.create_event(status='published') await factory.book_free(await factory.create_reservation()) await db_conn.execute( "UPDATE tickets SET first_name='foo', last_name='bar'") await login() r = await cli.get(url('event-tickets-export', id=factory.event_id)) assert r.status == 200 text = await r.text() data = [dict(r) for r in DictReader(StringIO(text))] assert data == [ { 'ticket_id': RegexStr(r'.{7}-\d+'), 'ticket_status': 'booked', 'booking_type': 'book-free-tickets', 'booked_at': CloseToNow(delta=3), 'price': '', 'extra_donated': '', 'extra_info': '', 'guest_name': 'foo bar', 'buyer_name': 'foo bar', 'ticket_type_name': 'Standard', }, ]
async def test_event_donations_export(cli, url, login, factory: Factory, db_conn): await factory.create_company() await factory.create_cat() await factory.create_user() await factory.create_donation_option() await factory.create_event(status='published') await factory.create_donation(gift_aid=True) await login() r = await cli.get(url('event-donations-export', id=factory.event_id)) assert r.status == 200 text = await r.text() data = [dict(r) for r in DictReader(StringIO(text))] assert len(data) == 1 assert data[0] == { 'donation_id': RegexStr(r'.{7}-\d+'), 'amount': '20.0', 'user_id': str(factory.user_id), 'user_email': '*****@*****.**', 'donation_option': str(factory.donation_option_id), 'gift_aid': 'True', 'name': 'Frank Spencer', 'timestamp': CloseToNow(delta=3), }
async def test_donations_export(cli, url, login, factory: Factory): await factory.create_company() await factory.create_cat() await factory.create_user() await factory.create_donation_option() await factory.create_event() don_id = await factory.create_donation(gift_aid=True) await login() r = await cli.get(url('export', type='donations')) assert r.status == 200 text = await r.text() data = [dict(r) for r in DictReader(StringIO(text))] assert data == [ { 'id': str(don_id), 'amount': '20.00', 'first_name': 'Foo', 'last_name': 'Bar', 'address': 'address', 'city': 'city', 'postcode': 'postcode', 'gift_aid': 'true', 'user_email': '*****@*****.**', 'user_first_name': 'Frank', 'user_last_name': 'Spencer', 'timestamp': CloseToNow(delta=3), 'event': str(factory.event_id), 'donation_option_id': str(factory.donation_option_id), 'donation_option_name': 'testing donation option', 'category_id': str(factory.category_id), 'category_name': 'Supper Clubs', }, ]
async def test_search_for_users_company(factory: Factory, db_conn, cli, url, login): assert await db_conn.fetchval('select count(*) from search') == 0 await factory.create_company() user_id = await factory.create_user(first_name='John', last_name='Doe') company2_id = await factory.create_company(name='2', domain='2') await factory.create_user(first_name='John', last_name='Doe', company_id=company2_id) await login() r = await cli.get(url('user-search', query={'q': 'John'})) assert r.status == 200, await r.text() assert await r.json() == { 'items': [ { 'id': user_id, 'name': 'John Doe', 'role_type': 'admin', 'status': 'active', 'email': '*****@*****.**', 'active_ts': CloseToNow(), }, ], }
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_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() assert info.job_try is None assert info.function == 'foobar' assert info.args == (123,) assert info.kwargs == {'a': 456} assert abs(t_before * 1000 - info.score) < 1000
async def test_book_multiple(donorfy: DonorfyActor, factory: Factory, dummy_server, cli, url, login): await factory.create_company() await factory.create_user() 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, '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() action_id = (await r.json())['action_id'] await factory.fire_stripe_webhook(action_id) trans_data = dummy_server.app['post_data'][ 'POST donorfy_api_root/standard/transactions'] assert len(trans_data) == 1 assert trans_data[0] == { 'ExistingConstituentId': '123456', 'Channel': 'nosht-supper-clubs', 'Currency': 'gbp', 'Campaign': 'supper-clubs:the-event-name', 'PaymentMethod': 'Payment Card via Stripe', 'Product': 'Event Ticket(s)', 'Fund': 'Unrestricted General', 'Department': '220 Ticket Sales', 'BankAccount': 'Unrestricted Account', 'DatePaid': CloseToNow(), 'Amount': 20.0, 'ProcessingCostsAmount': 0.5, 'Quantity': 2, 'Acknowledgement': 'supper-clubs-thanks', 'AcknowledgementText': RegexStr('Ticket ID: .*'), 'Reference': 'Events.HUF:supper-clubs the-event-name', 'AddGiftAidDeclaration': False, 'GiftAidClaimed': False, }
async def test_create_update_user(factory: Factory, db_conn): assert await db_conn.fetchval('select count(*) from search') == 0 company_id = await factory.create_company() await factory.create_company(name='Other Company', domain='example.org') user_id = await factory.create_user(first_name='John', last_name='Doe', email='*****@*****.**') assert await db_conn.fetchval('select count(*) from search') == 1 event, label, vector = await db_conn.fetchrow( 'select event, label, vector from search where user_id=$1', user_id) assert event is None assert label == 'John Doe ([email protected])' assert vector == "'activ':4C 'admin':5C 'doe':2A 'example.com':7 'john':1A 'test':6 '*****@*****.**':3B" assert await db_conn.fetchval( 'select company from search where user_id=$1', user_id) == company_id await db_conn.execute('update users set last_name=$1 where id=$2', 'DiffErent', user_id) assert await db_conn.fetchval('select count(*) from search') == 1 r = await db_conn.fetchrow( 'select label, vector, company, active_ts from search where user_id=$1', user_id) assert r['label'] == 'John DiffErent ([email protected])' assert r['vector'] == ( "'activ':4C 'admin':5C 'differ':2A 'example.com':7 'john':1A 'test':6 '*****@*****.**':3B" ) assert r['company'] == company_id assert r['active_ts'] == CloseToNow() await db_conn.execute('delete from users where id=$1', user_id) assert await db_conn.fetchval('select count(*) from search') == 0 await db_conn.execute( "INSERT INTO users (company, role) VALUES ($1, 'guest')", company_id) assert await db_conn.fetchval('select count(*) from search') == 0 await db_conn.execute( "INSERT INTO users (company, role, email) VALUES ($1, 'guest', 'x@y')", company_id) assert await db_conn.fetchval('select count(*) from search') == 1 assert await db_conn.fetchval( 'select vector from search' ) == "'guest':6C 'pend':5C 'x':1A,3B,7 'y':2A,4B,8" await db_conn.execute('delete from users') await db_conn.execute( "INSERT INTO users (company, role, first_name) VALUES ($1, 'guest', 'xx')", company_id) assert await db_conn.fetchval('select count(*) from search') == 1 assert await db_conn.fetchval('select vector from search' ) == "'guest':3C 'pend':2C 'xx':1A" assert await db_conn.fetchval('select company from search') == company_id
async def test_user_details(cli, url, login, factory: Factory): await factory.create_company(display_timezone='utc') await factory.create_user() await login() r = await cli.get(url('user-retrieve', pk=factory.user_id)) assert r.status == 200, await r.text() data = await r.json() assert data == { 'id': factory.user_id, 'name': 'Frank Spencer', 'role_type': 'admin', 'email': '*****@*****.**', 'active_ts': CloseToNow(), 'status': 'active', 'phone_number': None, 'created_ts': CloseToNow(), 'receive_emails': True, 'allow_marketing': False, 'first_name': 'Frank', 'last_name': 'Spencer', }
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_send_tickets_available(email_actor: EmailActor, factory: Factory, dummy_server, db_conn, cli): await factory.create_company() await factory.create_cat(ticket_extra_title='Foo Bar') await factory.create_user() await factory.create_event( start_ts=london.localize(datetime(2032, 6, 28, 19, 0))) anne = await factory.create_user(first_name='anne', last_name='anne', email='*****@*****.**') await db_conn.execute( 'insert into waiting_list (event, user_id) values ($1, $2)', factory.event_id, anne) assert await db_conn.fetchval('select last_notified from waiting_list' ) == datetime(2000, 1, 1, tzinfo=timezone.utc) assert await email_actor.send_tickets_available.direct( factory.event_id) == 'emailed 1 users' assert await email_actor.send_tickets_available.direct( factory.event_id) == 'no users in waiting list' assert await email_actor.send_tickets_available.direct( factory.event_id) == 'no users in waiting list' assert len(dummy_server.app['emails']) == 1 email = dummy_server.app['emails'][0] assert email['To'] == 'anne anne <*****@*****.**>' assert 'trigger=event-tickets-available' in email['X-SES-MESSAGE-TAGS'] plain = email['part:text/plain'] assert 'Great news! New tickets have become available for **The Event Name**.\n' in plain assert '<a href="https://127.0.0.1/supper-clubs/the-event-name/"><span>View Event</span></a>' in plain remove_link = re.search(r'(/api/events/.*?/waiting-list/.*?)\)', plain).group(1) assert await db_conn.fetchval('select count(*) from actions where type=$1', ActionTypes.email_waiting_list) == 1 assert await db_conn.fetchval('select count(*) from waiting_list') == 1 assert await db_conn.fetchval('select last_notified from waiting_list' ) == CloseToNow(delta=3) r = await cli.get(remove_link, allow_redirects=False) assert r.status == 307, await r.text() assert r.headers[ 'Location'] == f'http://127.0.0.1:{cli.server.port}/waiting-list-removed/' assert await db_conn.fetchval('select count(*) from waiting_list') == 0
async def test_event_tickets_admin(cli, url, db_conn, factory: Factory, login): await factory.create_company() await factory.create_cat() await factory.create_user() await factory.create_event() user2_id = await factory.create_user(first_name='guest', last_name='guest', email='*****@*****.**') r = await db_conn.fetch_b( 'INSERT INTO actions (:values__names) VALUES :values RETURNING id', values=MultipleValues( Values(company=factory.company_id, user_id=user2_id, type=ActionTypes.reserve_tickets), Values(company=factory.company_id, user_id=user2_id, type=ActionTypes.buy_tickets), )) reserve_action, paid_action = [r_['id'] for r_ in r] ticket_id = await db_conn.fetchval_b( 'INSERT INTO tickets (:values__names) VALUES :values RETURNING id', values=Values(event=factory.event_id, user_id=user2_id, reserve_action=reserve_action, paid_action=paid_action, status='paid')) await login() r = await cli.get(url('event-tickets', id=factory.event_id)) assert r.status == 200, await r.text() data = await r.json() assert data == { 'tickets': [ { 'ticket_id': ticket_id, 'extra': None, 'user_id': user2_id, 'user_name': 'guest guest', 'bought_at': CloseToNow(), 'buyer_id': user2_id, 'buyer_name': 'guest guest', }, ], }
async def test_search_for_users(factory: Factory, db_conn, cli, url, login): assert await db_conn.fetchval('select count(*) from search') == 0 await factory.create_company() user_id = await factory.create_user(first_name='John', last_name='Doe', email='*****@*****.**') r = await cli.get(url('event-search', query={'q': 'Foobar'})) assert r.status == 401, await r.text() await login(email='*****@*****.**') r = await cli.get(url('user-search', query={'q': 'john'})) assert r.status == 200, await r.text() assert await r.json() == { 'items': [ { 'id': user_id, 'name': 'John Doe', 'role_type': 'admin', 'status': 'active', 'email': '*****@*****.**', 'active_ts': CloseToNow(), }, ], } for query in ( 'john', 'doe', 'john doe', '*****@*****.**', 'testing', '@example.com', '[email protected] doe', ): r = await cli.get(url('user-search', query={'q': query})) assert r.status == 200, await r.text() items = (await r.json())['items'] assert len(items) == 1, query assert items[0]['id'] == user_id, query assert items[0]['name'] == 'John Doe', query for query in ({'q': 'missing'}, {'q': ''}, None): r = await cli.get(url('user-search', query=query)) assert r.status == 200, await r.text() assert await r.json() == {'items': []}, query
async def test_active_ts_updated(factory: Factory, db_conn): assert await db_conn.fetchval('select count(*) from search') == 0 company_id = await factory.create_company() user_id = await factory.create_user(first_name='John', last_name='Doe', email='*****@*****.**') assert await db_conn.fetchval('select count(*) from search') == 1 assert await db_conn.fetchval( 'select active_ts from search where user_id=$1', user_id) == CloseToNow() await db_conn.execute( "insert into actions (company, user_id, ts, type) values ($1, $2, '2032-01-01', 'login')", company_id, user_id, ) new_ts = await db_conn.fetchval( 'select active_ts from search where user_id=$1', user_id) assert new_ts == datetime(2032, 1, 1, tzinfo=timezone.utc)
async def test_enqueue_job(arq_redis: ArqRedis, worker, queue_name=default_queue_name): async def foobar(ctx, *args, **kwargs): return 42 j = await arq_redis.enqueue_job('foobar', 1, 2, c=3, _queue_name=queue_name) assert isinstance(j, Job) assert JobStatus.queued == await j.status() worker: Worker = worker(functions=[func(foobar, name='foobar')], queue_name=queue_name) await worker.main() r = await j.result(pole_delay=0) assert r == 42 assert JobStatus.complete == await j.status() info = await j.info() expected_queue_name = queue_name or arq_redis.default_queue_name assert info == JobResult( job_try=1, function='foobar', args=(1, 2), kwargs={'c': 3}, enqueue_time=CloseToNow(), success=True, result=42, start_time=CloseToNow(), finish_time=CloseToNow(), score=None, queue_name=expected_queue_name, ) results = await arq_redis.all_job_results() assert results == [ JobResult( function='foobar', args=(1, 2), kwargs={'c': 3}, job_try=1, enqueue_time=CloseToNow(), success=True, result=42, start_time=CloseToNow(), finish_time=CloseToNow(), score=None, queue_name=expected_queue_name, job_id=j.job_id, ) ]
async def test_enqueue_job( darq, arq_redis, worker_factory, queue_name=default_queue_name, ): darq.task(foobar) j = await arq_redis.enqueue_job( 'tests.test_jobs.foobar', [1, 2], {'c': 3}, queue_name=queue_name, ) assert isinstance(j, Job) assert JobStatus.queued == await j.status() worker = worker_factory(darq, queue_name=queue_name) await worker.main() r = await j.result(pole_delay=0) assert r == 42 assert JobStatus.complete == await j.status() info = await j.info() assert info == JobResult( job_try=1, function='tests.test_jobs.foobar', args=[1, 2], kwargs={'c': 3}, enqueue_time=CloseToNow(), success=True, result=42, start_time=CloseToNow(), finish_time=CloseToNow(), score=None, ) results = await arq_redis.all_job_results() assert results == [ JobResult( function='tests.test_jobs.foobar', args=[1, 2], kwargs={'c': 3}, job_try=1, enqueue_time=CloseToNow(), success=True, result=42, start_time=CloseToNow(), finish_time=CloseToNow(), score=None, job_id=j.job_id, ), ]
async def test_book_free_no_fee(donorfy: DonorfyActor, factory: Factory, dummy_server, cli, url, login): await factory.create_company() await factory.create_cat() await factory.create_user(role='host') await factory.create_event(price=10) await login() res = await factory.create_reservation() app = cli.app['main_app'] data = dict( booking_token=encrypt_json(app, res.dict()), book_action='buy-tickets-offline', ) r = await cli.json_post(url('event-book-tickets'), data=data) assert r.status == 200, await r.text() trans_data = dummy_server.app['post_data'][ 'POST donorfy_api_root/standard/transactions'] assert len(trans_data) == 1 assert trans_data[0] == { 'ExistingConstituentId': '123456', 'Channel': 'nosht-supper-clubs', 'Currency': 'gbp', 'Campaign': 'supper-clubs:the-event-name', 'PaymentMethod': 'Offline Payment', 'Product': 'Event Ticket(s)', 'Fund': 'Unrestricted General', 'Department': '220 Ticket Sales', 'BankAccount': 'Unrestricted Account', 'DatePaid': CloseToNow(), 'Amount': 10.0, 'ProcessingCostsAmount': 0, 'Quantity': 1, 'Acknowledgement': 'supper-clubs-thanks', 'AcknowledgementText': RegexStr('Ticket ID: .*'), 'Reference': 'Events.HUF:supper-clubs the-event-name', 'AddGiftAidDeclaration': False, 'GiftAidClaimed': False, }
async def test_user_actions(cli, url, login, factory: Factory, db_conn): await factory.create_company() await factory.create_user() await login() r = await cli.get(url('user-actions', pk=factory.user_id)) assert r.status == 200, await r.text() data = await r.json() assert data == { 'actions': [ { 'id': await db_conn.fetchval('SELECT id FROM actions'), 'ts': CloseToNow(), 'type': 'login', 'extra': { 'ip': '127.0.0.1', 'ua': RegexStr(r'Python.*'), 'url': RegexStr(r'http://127.0.0.1:\d+/api/auth-token/'), }, }, ], }
async def test_send_tickets_available_one_day(email_actor: EmailActor, factory: Factory, dummy_server, db_conn): await factory.create_company() await factory.create_cat(ticket_extra_title='Foo Bar') await factory.create_user() await factory.create_event( start_ts=london.localize(datetime(2032, 6, 28, 19, 0))) anne = await factory.create_user(first_name='anne', last_name='anne', email='*****@*****.**') await db_conn.execute( 'insert into waiting_list (event, user_id) values ($1, $2)', factory.event_id, anne) ben = await factory.create_user(first_name='ben', last_name='ben', email='*****@*****.**') recently = (datetime.now() - timedelta(hours=12)).replace(tzinfo=timezone.utc) await db_conn.execute( 'insert into waiting_list (event, user_id, last_notified) values ($1, $2, $3)', factory.event_id, ben, recently, ) assert await email_actor.send_tickets_available.direct( factory.event_id) == 'emailed 1 users' assert len(dummy_server.app['emails']) == 1 assert dummy_server.app['emails'][0][ 'To'] == 'anne anne <*****@*****.**>' s = await db_conn.fetchval( 'select last_notified from waiting_list where user_id=$1', anne) assert s == CloseToNow(delta=3) assert await db_conn.fetchval( 'select last_notified from waiting_list where user_id=$1', ben) == recently
async def test_user_list(cli, url, login, factory: Factory): await factory.create_company(display_timezone='utc') await factory.create_user() await login() r = await cli.get(url('user-browse')) assert r.status == 200, await r.text() data = await r.json() assert data == { 'items': [ { 'id': factory.user_id, 'name': 'Frank Spencer', 'role_type': 'admin', 'status': 'active', 'email': '*****@*****.**', 'active_ts': CloseToNow(delta=3), }, ], 'count': 1, 'pages': 1, }
async def test_real_upload(real_aws: AWS): async with AsyncClient(timeout=30) as client: s3 = S3Client( client, S3Config(real_aws.access_key, real_aws.secret_key, 'us-east-1', 'aioaws-testing')) path = f'{run_prefix}/testing/test.txt' await s3.upload(path, b'this is a test') try: files = [f.dict() async for f in s3.list(f'{run_prefix}/')] # debug(files) assert len(files) == 1 assert files[0] == { 'key': path, 'last_modified': CloseToNow(delta=10), 'size': 14, 'e_tag': '54b0c58c7ce9f2a8b551351102ee0938', 'storage_class': 'STANDARD', } finally: assert await s3.delete(path) == [path] assert [f.dict() async for f in s3.list(f'{run_prefix}/')] == []
async def test_enqueue_job(arq_redis: ArqRedis, worker): async def foobar(ctx, *args, **kwargs): return 42 j = await arq_redis.enqueue_job('foobar', 1, 2, c=3) assert isinstance(j, Job) assert JobStatus.queued == await j.status() worker: Worker = worker(functions=[func(foobar, name='foobar')]) await worker.main() r = await j.result(pole_delay=0) assert r == 42 assert JobStatus.complete == await j.status() info = await j.info() assert info == { 'enqueue_time': CloseToNow(), 'job_try': 1, 'function': 'foobar', 'args': (1, 2), 'kwargs': {'c': 3}, 'success': True, 'result': 42, 'start_time': CloseToNow(), 'finish_time': CloseToNow(), 'score': None, } results = await arq_redis.all_job_results() assert results == [ { 'enqueue_time': CloseToNow(), 'job_try': 1, 'function': 'foobar', 'args': (1, 2), 'kwargs': {'c': 3}, 'success': True, 'result': 42, 'start_time': CloseToNow(), 'finish_time': CloseToNow(), 'job_id': j.job_id, } ]
def test_clow_to_now_tz(): diff = timedelta(hours=2) dt = datetime.utcnow().replace(tzinfo=timezone(offset=diff)) + diff assert dt == CloseToNow()
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')
def test_close_to_now_true(): c2n = CloseToNow() dt = datetime.utcnow().strftime('%Y-%m-%dT%H:%M:%S') assert dt == c2n assert str(c2n) == repr(dt)