async def test_create_app_wrong_name(tmpworkdir, event_loop): mktree(tmpworkdir, SIMPLE_APP) config = Config(app_path='app.py', app_factory_name='missing') with pytest.raises(AiohttpDevConfigError) as excinfo: config.import_app_factory() assert excinfo.value.args[ 0] == "Module 'app.py' does not define a 'missing' attribute/class"
async def test_all_options(tmpdir, test_client, loop, template_engine, session, database, example): StartProject( path=str(tmpdir), name='foobar', template_engine=template_engine, session=session, database=database, example=example, ) assert 'app' in {p.basename for p in tmpdir.listdir()} style_guide = flake8.get_style_guide() report = style_guide.check_files([str(tmpdir)]) assert report.total_errors == 0 if database != 'none': return config = Config(app_path='app/main.py', root_path=str(tmpdir), static_path='.') app_factory = config.import_app_factory() app = app_factory() modify_main_app(app, config) cli = await test_client(app) r = await cli.get('/') assert r.status == 200 text = await r.text() assert '<title>foobar</title>' in text
async def test_db_creation(tmpdir, test_client, loop): StartProject( path=str(tmpdir), name='foobar postgres test', template_engine=TemplateChoice.JINJA, session=SessionChoices.NONE, database=DatabaseChoice.PG_SA, example=ExampleChoice.MESSAGE_BOARD, ) assert 'app' in {p.basename for p in tmpdir.listdir()} style_guide = flake8.get_style_guide() report = style_guide.check_files([str(tmpdir)]) assert report.total_errors == 0 db_password = os.getenv('APP_DB_PASSWORD', '') env = { 'APP_DB_PASSWORD': db_password, 'PATH': os.getenv('PATH', ''), } p = subprocess.run(['make', 'reset-database'], stdout=subprocess.PIPE, stderr=subprocess.STDOUT, cwd=str(tmpdir), env=env, universal_newlines=True) assert p.returncode == 0, p.stdout assert 'creating database "foobar"...' assert 'creating tables from model definition...' os.environ['APP_DB_PASSWORD'] = db_password config = Config(app_path='app/main.py', root_path=str(tmpdir)) app = config.app_factory(loop=loop) modify_main_app(app, config) cli = await test_client(app) r = await cli.get('/') assert r.status == 200 text = await r.text() assert '<title>foobar postgres test</title>' in text
async def test_start_run(tmpdir, loop, aiohttp_client, smart_caplog): StartProject(path=str(tmpdir.join('the-path')), name='foobar') assert {p.basename for p in tmpdir.listdir()} == {'the-path'} assert {p.basename for p in tmpdir.join('the-path').listdir()} == { 'app', 'requirements.txt', 'README.md', 'static', } assert """\ adev.main INFO: Starting new aiohttp project "foobar" at "/<tmpdir>/the-path" adev.main INFO: project created, 13 files generated\n""" == smart_caplog.log.replace( str(tmpdir), '/<tmpdir>') config = Config(app_path='the-path/app/', root_path=str(tmpdir), static_path='.') app_factory = config.import_app_factory() app = await app_factory() modify_main_app(app, config) assert isinstance(app, aiohttp.web.Application) cli = await aiohttp_client(app) r = await cli.get('/') assert r.status == 200 text = await r.text() assert "Success! you've setup a basic aiohttp app." in text
async def test_start_other_dir(tmpdir, loop, test_client, caplog): StartProject(path=str(tmpdir.join('the-path')), name='foobar', database=DatabaseChoice.NONE) assert {p.basename for p in tmpdir.listdir()} == {'the-path'} assert {p.basename for p in tmpdir.join('the-path').listdir()} == { 'app', 'Makefile', 'requirements.txt', 'README.md', 'activate.settings.sh', 'setup.cfg', 'static', 'tests', } assert """\ adev.main INFO: Starting new aiohttp project "foobar" at "/<tmpdir>/the-path" adev.main INFO: config: template_engine: jinja session: secure database: none example: message-board adev.main INFO: project created, 16 files generated\n""" == caplog.log.replace(str(tmpdir), '/<tmpdir>') config = Config(app_path='the-path/app/', root_path=str(tmpdir)) app = config.app_factory(loop=loop) modify_main_app(app, config) assert isinstance(app, aiohttp.web.Application) cli = await test_client(app) r = await cli.get('/') assert r.status == 200 text = await r.text() assert "Success! you've setup a basic aiohttp app." in text
async def test_serve_main_app(tmpworkdir, loop, mocker): asyncio.set_event_loop(loop) mktree(tmpworkdir, SIMPLE_APP) mock_modify_main_app = mocker.patch('aiohttp_devtools.runserver.serve.modify_main_app') loop.call_later(0.5, loop.stop) config = Config(app_path='app.py') await start_main_app(config, config.import_app_factory(), loop) mock_modify_main_app.assert_called_with(mock.ANY, config)
async def test_not_app(tmpworkdir): mktree(tmpworkdir, { 'app.py': """\ def app_factory(): return 123 """ }) config = Config(app_path='app.py') with pytest.raises(AiohttpDevConfigError): await config.load_app(config.import_app_factory())
async def test_run_app_test_client(loop, tmpworkdir, test_client): mktree(tmpworkdir, SIMPLE_APP) config = Config(app_path='app.py') app = config.app_factory(loop=loop) modify_main_app(app, config) assert isinstance(app, aiohttp.web.Application) cli = await test_client(app) r = await cli.get('/') assert r.status == 200 text = await r.text() assert text == 'hello world'
async def test_not_app(tmpworkdir): mktree(tmpworkdir, {'app.py': """\ def app_factory(): return 123 """}) config = Config(app_path='app.py') with pytest.raises( AiohttpDevConfigError, match= r"'app_factory' returned 'int' not an aiohttp\.web\.Application"): await config.load_app(config.import_app_factory())
async def test_serve_main_app(tmpworkdir, event_loop, mocker): asyncio.set_event_loop(event_loop) mktree(tmpworkdir, SIMPLE_APP) mock_modify_main_app = mocker.patch( 'aiohttp_devtools.runserver.serve.modify_main_app') event_loop.call_later(0.5, event_loop.stop) config = Config(app_path="app.py", main_port=0) runner = await create_main_app(config, config.import_app_factory()) await start_main_app(runner, config.main_port) mock_modify_main_app.assert_called_with(mock.ANY, config) await runner.cleanup()
async def test_wrong_function_signature(tmpworkdir): mktree( tmpworkdir, { 'app.py': """\ def app_factory(foo): return web.Application() """ }) config = Config(app_path='app.py') with pytest.raises( AiohttpDevConfigError, match=r"'app\.py\.app_factory' should not have required arguments" ): await config.load_app(config.import_app_factory())
def test_serve_main_app_app_instance(tmpworkdir, loop, mocker): mktree( tmpworkdir, { 'app.py': """\ from aiohttp import web async def hello(request): return web.Response(text='<h1>hello world</h1>', content_type='text/html') app = web.Application() app.router.add_get('/', hello) """ }) asyncio.set_event_loop(loop) mocker.spy(loop, 'create_server') mock_modify_main_app = mocker.patch( 'aiohttp_devtools.runserver.serve.modify_main_app') loop.call_later(0.5, loop.stop) config = Config(app_path='app.py') serve_main_app(config) assert loop.is_closed() loop.create_server.assert_called_with(mock.ANY, '0.0.0.0', 8000, backlog=128) mock_modify_main_app.assert_called_with(mock.ANY, config)
async def test_no_loop_coroutine(tmpworkdir): mktree(tmpworkdir, { 'app.py': """\ from aiohttp import web async def hello(request): return web.Response(text='<h1>hello world</h1>', content_type='text/html') async def app_factory(): a = web.Application() a.router.add_get('/', hello) return a """ }) config = Config(app_path='app.py') app = await config.load_app(config.import_app_factory()) assert isinstance(app, web.Application)
async def test_start_main_app_app_instance(tmpworkdir, loop, mocker): mktree(tmpworkdir, { 'app.py': """\ from aiohttp import web async def hello(request): return web.Response(text='<h1>hello world</h1>', content_type='text/html') app = web.Application() app.router.add_get('/', hello) """ }) mock_modify_main_app = mocker.patch('aiohttp_devtools.runserver.serve.modify_main_app') config = Config(app_path='app.py') await start_main_app(config, config.import_app_factory(), loop) mock_modify_main_app.assert_called_with(mock.ANY, config)
def test_modify_main_app_all_on(tmpworkdir): mktree(tmpworkdir, SIMPLE_APP) config = Config(app_path='app.py', debug_toolbar=True, static_path='.') app = DummyApplication() modify_main_app(app, config) assert len(app.on_response_prepare) == 1 assert len(app.middlewares) == 2 assert app['static_root_url'] == 'http://localhost:8001/static' assert app._debug is True
def test_modify_main_app_all_off(tmpworkdir): mktree(tmpworkdir, SIMPLE_APP) config = Config(app_path='app.py', livereload=False, host='foobar.com', static_path='.') app = DummyApplication() modify_main_app(app, config) assert len(app.on_response_prepare) == 0 assert len(app.middlewares) == 0 assert app['static_root_url'] == 'http://foobar.com:8001/static' assert app._debug is True
def test_serve_main_app(tmpworkdir, loop, mocker): mktree(tmpworkdir, SIMPLE_APP) mocker.spy(loop, 'create_server') mock_modify_main_app = mocker.patch('aiohttp_devtools.runserver.serve.modify_main_app') loop.call_later(0.5, loop.stop) config = Config(app_path='app.py') serve_main_app(config, loop=loop) assert loop.is_closed() loop.create_server.assert_called_with(mock.ANY, '0.0.0.0', 8000, backlog=128) mock_modify_main_app.assert_called_with(mock.ANY, config)
def test_modify_main_app_all_on(tmpworkdir): mktree(tmpworkdir, SIMPLE_APP) config = Config(app_path='app.py', static_path='.') app = DummyApplication() subapp = DummyApplication() app.add_subapp("/sub/", subapp) modify_main_app(app, config) # type: ignore[arg-type] assert len(app.on_response_prepare) == 1 assert len(app.middlewares) == 1 assert app['static_root_url'] == 'http://localhost:8001/static' assert subapp['static_root_url'] == "http://localhost:8001/static" assert app._debug is True
async def test_modify_main_app_on_prepare(tmpworkdir): mktree(tmpworkdir, SIMPLE_APP) config = Config(app_path='app.py', host='foobar.com') app = DummyApplication() modify_main_app(app, config) # type: ignore[arg-type] on_prepare = app.on_response_prepare[0] request = MagicMock(spec=Request) request.path = '/' response = MagicMock(spec=Response) response.body = b'<h1>body</h1>' response.content_type = 'text/html' await on_prepare(request, response) assert response.body == b'<h1>body</h1>\n<script src="http://foobar.com:8001/livereload.js"></script>\n'
async def test_load_simple_app(tmpworkdir): mktree(tmpworkdir, SIMPLE_APP) Config(app_path='app.py')
async def test_create_app_wrong_name(tmpworkdir, loop): mktree(tmpworkdir, SIMPLE_APP) with pytest.raises(AiohttpDevConfigError) as excinfo: Config(app_path='app.py', app_factory_name='missing') assert excinfo.value.args[ 0] == 'Module "app.py" does not define a "missing" attribute/class'
def test_invalid_options(tmpworkdir, files, exc, loop): asyncio.set_event_loop(loop) mktree(tmpworkdir, files) with pytest.raises(AiohttpDevConfigError) as excinfo: Config(app_path='.').check() assert exc.format(tmpworkdir=tmpworkdir) == excinfo.value.args[0]