class TestService(TestCase): def setUp(self): self.config = testing.setUp() self.config.include("cornice") self.config.scan("cornice.tests.test_service") self.config.scan("cornice.tests.test_pyramidhook") self.app = TestApp(CatchErrors(self.config.make_wsgi_app())) def tearDown(self): testing.tearDown() def test_404(self): # a get on a resource that explicitely return a 404 should return # 404 self.app.get("/service", status=404) def test_405(self): # calling a unknown verb on an existing resource should return a 405 self.app.post("/service", status=405) def test_acl_support(self): self.app.delete('/service') def test_class_support(self): self.app.get('/fresh-air', status=400) resp = self.app.get('/fresh-air', headers={'X-Temperature': '50'}) self.assertEquals(resp.body, 'fresh air')
class IntegrationTests(unittest.TestCase): def setUp(self): from webtest import TestApp from pyramid.paster import get_app app = get_app('development.ini') self.app = TestApp(app) def tearDown(self): testing.tearDown() def test_login_view(self): self.app.authorization = ('Basic', ('user', 'password')) response = self.app.get('/login') self.assertEqual(response.status_int, 200) def test_logout_view(self): # run login to start session self.app.authorization = ('Basic', ('user', 'password')) self.app.get('/login') response = self.app.get('/logout') self.assertEqual(response.status_int, 200) def test_logout_not_loggedin(self): # expect 403 when trying to log out again from pyramid.httpexceptions import HTTPForbidden response = self.app.get('/logout', expect_errors=True) self.assertEqual(response.status_int, 401)
def test_extra_predicates(): config = setup() app = App(testing_config=config) @app.path(path='{id}') class Model(object): def __init__(self, id): self.id = id @app.view(model=Model, name='foo', id='a') def get_a(self, request): return 'a' @app.view(model=Model, name='foo', id='b') def get_b(self, request): return 'b' @app.predicate(name='id', order=2, default='') def get_id(self, request): return self.id config.commit() c = Client(app) response = c.get('/a/foo') assert response.body == 'a' response = c.get('/b/foo') assert response.body == 'b'
class ViewsFunctionalTest(unittest.TestCase): def setUp(self): from adhocracy_frontend import main from webtest import TestApp app = main({}) self.testapp = TestApp(app) @mark.xfail(reason='asset build:/stylesheets/a3.css must exists') def test_static_view(self): resp = self.testapp.get('/static/root.html', status=200) assert '200' in resp.status def test_config_json_view(self): resp = self.testapp.get('/config.json', status=200) assert '200' in resp.status @mark.xfail(reason='asset build:/stylesheets/a3.css must exists') def test_embed_view(self): resp = self.testapp.get('/embed/XX', status=200) assert '200' in resp.status @mark.xfail(reason='asset build:/stylesheets/a3.css must exists') def test_register_view(self): resp = self.testapp.get('/register', status=200) assert '200' in resp.status
def test_enforce_https_wrong(self): config = copy.deepcopy(SHARED_DEFAULTS) config["enforce_https"] = True application = RoutingApplication(config) app = TestApp(application, extra_environ={"REMOTE_ADDR": "127.0.0.1"}) app.get("/", status=406) app.post("/connect", status=406)
class ImperativeIncludeConfigurationTest(unittest.TestCase): def setUp(self): from pyramid.config import Configurator config = Configurator() from pyramid.tests.pkgs.includeapp1.root import configure configure(config) app = config.make_wsgi_app() from webtest import TestApp self.testapp = TestApp(app) self.config = config def tearDown(self): self.config.end() def test_root(self): res = self.testapp.get('/', status=200) self.assertTrue(b'root' in res.body) def test_two(self): res = self.testapp.get('/two', status=200) self.assertTrue(b'two' in res.body) def test_three(self): res = self.testapp.get('/three', status=200) self.assertTrue(b'three' in res.body)
class TestResource(unittest.TestCase): def setUp(self): from pyramid.renderers import JSONP self.config = testing.setUp() self.config.add_renderer("jsonp", JSONP(param_name="callback")) self.config.include("cornice") self.config.scan("cornice.tests.test_resource") self.app = TestApp(CatchErrors(self.config.make_wsgi_app())) def tearDown(self): testing.tearDown() def test_basic_resource(self): self.assertEquals(self.app.get("/users").json, {"status": "ok", "result": {"users": [1, 2]}}) self.assertEquals(self.app.get("/users/1").json, {"status": "ok", "result": {"name": "gawel"}}) resp = self.app.get("/users/1?callback=test") self.assertEquals(resp.body, 'test({"status": "ok", "result": {"name": "gawel"}})', resp.body) def test_accept_headers(self): # the accept headers should work even in case they're specified in a # resource method self.assertEquals( self.app.post("/users", headers={"Accept": "text/json"}, params=json.dumps({"test": "yeah"})).json, {"status": "ok", "result": {"test": "yeah"}}, )
def test_custom_with_trailing_slash(self): class CustomController(RestController): _custom_actions = { 'detail': ['GET'], 'create': ['POST'], 'update': ['PUT'], 'remove': ['DELETE'], } @expose() def detail(self): return 'DETAIL' @expose() def create(self): return 'CREATE' @expose() def update(self, id): return id @expose() def remove(self, id): return id app = TestApp(make_app(CustomController())) r = app.get('/detail') assert r.status_int == 200 assert r.body == b_('DETAIL') r = app.get('/detail/') assert r.status_int == 200 assert r.body == b_('DETAIL') r = app.post('/create') assert r.status_int == 200 assert r.body == b_('CREATE') r = app.post('/create/') assert r.status_int == 200 assert r.body == b_('CREATE') r = app.put('/update/123') assert r.status_int == 200 assert r.body == b_('123') r = app.put('/update/123/') assert r.status_int == 200 assert r.body == b_('123') r = app.delete('/remove/456') assert r.status_int == 200 assert r.body == b_('456') r = app.delete('/remove/456/') assert r.status_int == 200 assert r.body == b_('456')
def test_pull_task(): test_app = TestApp(app) session = create_session() task1 = Task() task1.uuid = 'de305d54-75b4-431b-adb2-eb6b9e546018' task1.test_id = 'de305d54-75b4-431b-adb2-eb6b9e546018' task1.claimed = datetime.utcnow() task1.data = json.dumps({'wait_time': 123}) session.add(task1) task2 = Task() task2.uuid = 'de305d54-75b4-431b-adb2-eb6b9e546019' task2.test_id = 'de305d54-75b4-431b-adb2-eb6b9e546019' task2.claimed = datetime.utcnow() task2.completed = datetime.utcnow() task2.result_data = json.dumps({'result': 'epic success'}) session.add(task2) task3 = Task() task3.uuid = 'de305d54-75b4-431b-adb2-eb6b9e546020' task3.test_id = 'de305d54-75b4-431b-adb2-eb6b9e546020' task3.claimed = datetime.utcnow() task3.failed = datetime.utcnow() task3.error = 'unknown error' session.add(task3) session.commit() test_app.get('/task/de305d54-75b4-431b-adb2-eb6b9e546018') test_app.get('/task/de305d54-75b4-431b-adb2-eb6b9e546019') test_app.get('/task/de305d54-75b4-431b-adb2-eb6b9e546020')
def test_get_with_var_args(self): class OthersController(object): @expose() def index(self, one, two, three): return 'NESTED: %s, %s, %s' % (one, two, three) class ThingsController(RestController): others = OthersController() @expose() def get_one(self, *args): return ', '.join(args) class RootController(object): things = ThingsController() # create the app app = TestApp(make_app(RootController())) # test get request r = app.get('/things/one/two/three') assert r.status_int == 200 assert r.body == b_('one, two, three') # test nested get request r = app.get('/things/one/two/three/others/') assert r.status_int == 200 assert r.body == b_('NESTED: one, two, three')
def test_404_with_lookup(self): class LookupController(RestController): def __init__(self, _id): self._id = _id @expose() def get_all(self): return 'ID: %s' % self._id class ThingsController(RestController): @expose() def _lookup(self, _id, *remainder): return LookupController(_id), remainder class RootController(object): things = ThingsController() # create the app app = TestApp(make_app(RootController())) # these should 404 for path in ('/things', '/things/'): r = app.get(path, expect_errors=True) assert r.status_int == 404 r = app.get('/things/foo') assert r.status_int == 200 assert r.body == b_('ID: foo')
def test_simple_generic(self): class RootController(object): @expose(generic=True) def index(self): pass @index.when(method="POST", template="json") def do_post(self): return dict(result="POST") @index.when(method="GET") def do_get(self): return "GET" app = TestApp(Pecan(RootController())) r = app.get("/") assert r.status_int == 200 assert r.body == "GET" r = app.post("/") assert r.status_int == 200 assert r.body == dumps(dict(result="POST")) r = app.get("/do_get", status=404) assert r.status_int == 404
def test_disconnect_hooks_multiple_listener(self): hook1_has_been_called = [] def hook1_listener(): hook1_has_been_called.append(True) hook2_has_been_called = [] def hook2_listener(): hook2_has_been_called.append(True) class RootController(TGController): @expose() def test(self): tg.hooks.notify('custom_hook', controller=RootController.test) return 'HI!' conf = AppConfig(minimal=True, root_controller=RootController()) tg.hooks.register('custom_hook', hook1_listener) tg.hooks.register('custom_hook', hook2_listener) conf.package = PackageWithModel() app = conf.make_wsgi_app() app = TestApp(app) app.get('/test') app.get('/test') tg.hooks.disconnect('custom_hook', hook2_listener) app.get('/test') # Disconnecting an unregistered hook should do nothing. tg.hooks.disconnect('unregistered', hook1_listener) assert len(hook1_has_been_called) == 3, hook1_has_been_called assert len(hook2_has_been_called) == 2, hook2_has_been_called
def test_type_hints_and_converters(): config = setup() class app(morepath.App): testing_config = config class Model(object): def __init__(self, d): self.d = d from datetime import date @app.path(model=Model, path='', converters=dict(d=date)) def get_model(d): return Model(d) @app.view(model=Model) def default(self, request): return "View: %s" % self.d @app.view(model=Model, name='link') def link(self, request): return request.link(self) config.commit() c = Client(app()) response = c.get('/?d=20140120') assert response.body == b"View: 2014-01-20" response = c.get('/link?d=20140120') assert response.body == b'http://localhost/?d=20140120'
def test_link_for_none_means_no_parameter(): config = setup() class app(morepath.App): testing_config = config class Model(object): def __init__(self, id): self.id = id @app.path(model=Model, path='') def get_model(id): return Model(id) @app.view(model=Model) def default(self, request): return "View: %s" % self.id @app.view(model=Model, name='link') def link(self, request): return request.link(self) config.commit() c = Client(app()) response = c.get('/') assert response.body == b"View: None" response = c.get('/link') assert response.body == b'http://localhost/'
def test_variable_path_parameter_required_with_default(): config = setup() class app(morepath.App): testing_config = config class Model(object): def __init__(self, id): self.id = id @app.path(model=Model, path='', required=['id']) def get_model(id='b'): return Model(id) @app.view(model=Model) def default(self, request): return "View: %s" % self.id @app.view(model=Model, name='link') def link(self, request): return request.link(self) config.commit() c = Client(app()) response = c.get('/?id=a') assert response.body == b"View: a" response = c.get('/', status=400)
def test_variable_path_one_step(): config = setup() class app(morepath.App): testing_config = config class Model(object): def __init__(self, name): self.name = name @app.path(model=Model, path='{name}') def get_model(name): return Model(name) @app.view(model=Model) def default(self, request): return "View: %s" % self.name @app.view(model=Model, name='link') def link(self, request): return request.link(self) config.commit() c = Client(app()) response = c.get('/foo') assert response.body == b'View: foo' response = c.get('/foo/link') assert response.body == b'http://localhost/foo'
def test_variable_path_explicit_trumps_implicit(): config = setup() class app(morepath.App): testing_config = config class Model(object): def __init__(self, id): self.id = id @app.path(model=Model, path='{id}', converters=dict(id=Converter(int))) def get_model(id='foo'): return Model(id) @app.view(model=Model) def default(self, request): return "View: %s (%s)" % (self.id, type(self.id)) @app.view(model=Model, name='link') def link(self, request): return request.link(self) config.commit() c = Client(app()) response = c.get('/1') assert response.body in \ (b"View: 1 (<type 'int'>)", b"View: 1 (<class 'int'>)") response = c.get('/1/link') assert response.body == b'http://localhost/1' response = c.get('/broken', status=404)
def test_simple_path_two_steps(): config = setup() class app(morepath.App): testing_config = config class Model(object): def __init__(self): pass @app.path(model=Model, path='one/two') def get_model(): return Model() @app.view(model=Model) def default(self, request): return "View" @app.view(model=Model, name='link') def link(self, request): return request.link(self) config.commit() c = Client(app()) response = c.get('/one/two') assert response.body == b'View' response = c.get('/one/two/link') assert response.body == b'http://localhost/one/two'
def test_absorb_path_root(): config = setup() class app(morepath.App): testing_config = config class Model(object): def __init__(self, absorb): self.absorb = absorb @app.path(model=Model, path='', absorb=True) def get_model(absorb): return Model(absorb) @app.view(model=Model) def default(self, request): return "A:%s L:%s" % (self.absorb, request.link(self)) config.commit() c = Client(app()) response = c.get('/a') assert response.body == b'A:a L:http://localhost/a' response = c.get('/') assert response.body == b'A: L:http://localhost/' response = c.get('/a/b') assert response.body == b'A:a/b L:http://localhost/a/b'
def test_error_when_path_variables_isnt_dict(): config = setup() class App(morepath.App): testing_config = config class Model(object): def __init__(self, id): self.store_id = id @App.path(model=Model, path='models/{id}', variables=lambda m: 'nondict') def get_model(id): return Model(id) @App.view(model=Model) def default(self, request): return request.link(self) config.commit() c = Client(App()) with pytest.raises(LinkError): c.get('/models/1')
def test_script_name(): config = setup() class app(morepath.App): testing_config = config class Model(object): def __init__(self): pass @app.path(model=Model, path='simple') def get_model(): return Model() @app.view(model=Model) def default(self, request): return "View" @app.view(model=Model, name='link') def link(self, request): return request.link(self) config.commit() c = Client(app()) response = c.get('/prefix/simple', extra_environ=dict(SCRIPT_NAME='/prefix')) assert response.body == b'View' response = c.get('/prefix/simple/link', extra_environ=dict(SCRIPT_NAME='/prefix')) assert response.body == b'http://localhost/prefix/simple'
def test_url_parameter_list_but_only_one_allowed(): config = setup() class app(morepath.App): testing_config = config class Model(object): def __init__(self, item): self.item = item @app.path(model=Model, path='/', converters={'item': int}) def get_model(item): return Model(item) @app.view(model=Model) def default(self, request): return repr(self.item) @app.view(model=Model, name='link') def link(self, request): return request.link(self) config.commit() c = Client(app()) c.get('/?item=1&item=2', status=400) c.get('/link?item=1&item=2', status=400)
class TestServiceDefinition(unittest2.TestCase): def setUp(self): if not metlog: raise(unittest2.SkipTest('no metlog')) mozconfig = Config(StringIO(dedent(""" [test1] backend = mozsvc.metrics.MetlogPlugin sender_class=metlog.senders.DebugCaptureSender """))) settings = {"config": mozconfig} self.plugin = load_from_config("test1", mozconfig) self.config = Configurator(settings=settings) self.config.include("cornice") self.config.scan("mozsvc.tests.test_service_definition") self.app = TestApp(CatchErrors(self.config.make_wsgi_app())) def tearDown(self): testing.tearDown() def test_decorated_view_fn(self): # passing a decorator in to the service api call should result in a # decorated view callable resp = self.app.get("/service3") self.assertEquals(resp.json, {'test': 'succeeded', 'wrapped0': 'yes'}) def test_stacked_decorated_view(self): # passing a decorator in to the service api call should result in a # decorated view callable, ordering of the particular decorators # shouldn't break things resp = self.app.get("/service4") self.assertEquals(resp.json, {'test': 'succeeded', 'wrapped0': 'yes'}) resp = self.app.get("/service5") self.assertEquals(resp.json, {'test': 'succeeded', 'wrapped0': 'yes'})
def test_custom_serializer(): was_used = [False, False] class CustomSerializer(object): def loads(self, data_string): was_used[0] = True return json.loads(data_string.decode('utf-8')) def dumps(self, data): was_used[1] = True return json.dumps(data).encode('utf-8') serializer = CustomSerializer() options = {'session.validate_key':'hoobermas', 'session.type':'cookie', 'data_serializer': serializer} app = TestApp(SessionMiddleware(simple_app, **options)) res = app.get('/') assert 'current value is: 1' in res res = app.get('/') cookie = SignedCookie('hoobermas') session_data = cookie.value_decode(app.cookies['beaker.session.id'])[0] session_data = b64decode(session_data) data = serializer.loads(session_data) assert data['value'] == 2 res = app.get('/') assert 'current value is: 3' in res assert all(was_used)
def test_it(self): from pyramid.config import Configurator from pyramid_jinja2 import includeme from webtest import TestApp import os here = os.path.abspath(os.path.dirname(__file__)) templates_dir = os.path.join(here, 'templates') def myview(request): return {} config1 = Configurator(settings={ 'jinja2.directories': os.path.join(templates_dir, 'foo')}) includeme(config1) config1.add_view(view=myview, renderer='mytemplate.jinja2') config2 = Configurator(settings={ 'jinja2.directories': os.path.join(templates_dir, 'bar')}) includeme(config2) config2.add_view(view=myview, renderer='mytemplate.jinja2') self.assertNotEqual(config1.registry.settings, config2.registry.settings) app1 = config1.make_wsgi_app() testapp = TestApp(app1) self.assertEqual(testapp.get('/').body, bytes_('foo')) app2 = config2.make_wsgi_app() testapp = TestApp(app2) self.assertEqual(testapp.get('/').body, bytes_('bar'))
def test_200(): from pyramid.config import Configurator from webtest import TestApp mock_metric = mock.Mock() def main(global_config, **settings): config = Configurator(settings=settings) config.include('pyramid_datadog') config.configure_metrics(mock_metric) def test_view(request): return {} config.add_route('home', '/') config.add_view(test_view, route_name='home', renderer='json') return config.make_wsgi_app() app = main({}) app = TestApp(app) app.get('/') mock_metric.timing.assert_has_calls([ mock.call('pyramid.request.duration.route_match', mock.ANY), mock.call('pyramid.request.duration.traversal', mock.ANY), mock.call('pyramid.request.duration.view', mock.ANY, tags=['route:home']), mock.call('pyramid.request.duration.template_render', mock.ANY, tags=['route:home']), mock.call('pyramid.request.duration.total', mock.ANY, tags=['route:home', 'status_code:200', 'status_type:2xx']) ])
def test_extra_parameters(): config = setup() class app(morepath.App): testing_config = config class Model(object): def __init__(self, extra_parameters): self.extra_parameters = extra_parameters @app.path(model=Model, path='/') def get_model(extra_parameters): return Model(extra_parameters) @app.view(model=Model) def default(self, request): return repr(sorted(self.extra_parameters.items())) @app.view(model=Model, name='link') def link(self, request): return request.link(self) config.commit() c = Client(app()) response = c.get('/?a=A&b=B') assert response.body in \ (b"[(u'a', u'A'), (u'b', u'B')]", b"[('a', 'A'), ('b', 'B')]") response = c.get('/link?a=A&b=B') assert sorted(response.body[len('http://localhost/?'):].split(b"&")) == [ b'a=A', b'b=B']
class NonAutocommittingConfigurationTestResource(TestCase): """ Test that we don't fail Pyramid's conflict detection when using a manually- committing :class:`pyramid.config.Configurator` instance. """ def setUp(self): from pyramid.renderers import JSONP self.config = testing.setUp(autocommit=False) self.config.add_renderer('jsonp', JSONP(param_name='callback')) self.config.include("cornice") add_view(UserImp.get, renderer='json') add_view(UserImp.get, renderer='jsonp') add_view(UserImp.collection_post, renderer='json', accept='text/json') user_resource = add_resource( UserImp, collection_path='/users', path='/users/{id}', name='user_service', factory=dummy_factory) self.config.add_cornice_resource(user_resource) self.app = TestApp(CatchErrors(self.config.make_wsgi_app())) def tearDown(self): testing.tearDown() def test_get(self): self.app.get('/users/1')
def test_variable_path_two_variables(): config = setup() class app(morepath.App): testing_config = config class Model(object): def __init__(self, name, version): self.name = name self.version = version @app.path(model=Model, path='{name}-{version}') def get_model(name, version): return Model(name, version) @app.view(model=Model) def default(self, request): return "View: %s %s" % (self.name, self.version) @app.view(model=Model, name='link') def link(self, request): return request.link(self) config.commit() c = Client(app()) response = c.get('/foo-one') assert response.body == b'View: foo one' response = c.get('/foo-one/link') assert response.body == b'http://localhost/foo-one'
def test_access_redis(app: App): """Simple check we can corrcetly access Redis with text encodings.""" resp = app.get("/redis_test") assert resp.status_code == 200
class TestConflictApp(unittest.TestCase): package = 'tests.pkgs.conflictapp' def _makeConfig(self): from pyramid.config import Configurator config = Configurator() return config def test_autoresolved_view(self): config = self._makeConfig() config.include(self.package) app = config.make_wsgi_app() self.testapp = TestApp(app) res = self.testapp.get('/') self.assertTrue(b'a view' in res.body) res = self.testapp.get('/route') self.assertTrue(b'route view' in res.body) def test_overridden_autoresolved_view(self): from pyramid.response import Response config = self._makeConfig() config.include(self.package) def thisview(request): return Response('this view') config.add_view(thisview) app = config.make_wsgi_app() self.testapp = TestApp(app) res = self.testapp.get('/') self.assertTrue(b'this view' in res.body) def test_overridden_route_view(self): from pyramid.response import Response config = self._makeConfig() config.include(self.package) def thisview(request): return Response('this view') config.add_view(thisview, route_name='aroute') app = config.make_wsgi_app() self.testapp = TestApp(app) res = self.testapp.get('/route') self.assertTrue(b'this view' in res.body) def test_nonoverridden_authorization_policy(self): config = self._makeConfig() config.include(self.package) app = config.make_wsgi_app() self.testapp = TestApp(app) res = self.testapp.get('/protected', status=403) self.assertTrue(b'403 Forbidden' in res.body) def test_overridden_authorization_policy(self): config = self._makeConfig() config.include(self.package) class DummySecurityPolicy: def permits(self, context, principals, permission): return True config.set_authorization_policy(DummySecurityPolicy()) app = config.make_wsgi_app() self.testapp = TestApp(app) res = self.testapp.get('/protected', status=200) self.assertTrue('protected view' in res)
def test_defaults(self): config = copy.deepcopy(SHARED_DEFAULTS) application = RoutingApplication(config) app = TestApp(application, extra_environ={"REMOTE_ADDR": "127.0.0.1"}) app.get("/", status=404) app.post("/connect", status=403)
def test_view_notices_statistics(gazette_app): editor = Client(gazette_app) login_editor_3(editor) # this has no group publisher = Client(gazette_app) login_publisher(publisher) def statistic(state, sheet_name, qs=None): result = publisher.get('/notices/{}/statistics-xlsx?{}'.format( state, qs or '')) book = open_workbook(file_contents=result.body) for sheet in book.sheets(): if sheet.name == sheet_name: return [[ sheet.cell(row, col).value for col in range(sheet.ncols) ] for row in range(sheet.nrows)] # No notices yet states = ('drafted', 'submitted', 'accepted', 'rejected') for s in states: editor.get('/notices/{}/statistics'.format(s), status=403) editor.get('/notices/{}/statistics-xlsx'.format(s), status=403) publisher.get('/notices/{}/statistics'.format(s)) assert statistic(s, 'Organisationen') == [['Organisation', 'Anzahl']] assert statistic(s, 'Rubriken') == [['Rubrik', 'Anzahl']] assert statistic(s, 'Gruppen') == [['Gruppe', 'Anzahl']] # Add users and groups admin = Client(gazette_app) login_admin(admin) manage = admin.get('/groups').click("Neu") for group in ('A', 'B', 'C'): manage.form['name'] = group manage.form.submit() manage = admin.get('/users').click("Neu") for user, group in ( ('*****@*****.**', 'B'), ('*****@*****.**', 'B'), ('*****@*****.**', 'C'), ): manage.form['role'] = 'member' manage.form['name'] = user manage.form['username'] = user manage.form['group'] = dict( (x[2], x[0]) for x in manage.form['group'].options)[group] with patch('onegov.gazette.views.users.random_password') as password: password.return_value = 'hunter2' manage.form.submit().maybe_follow() user_1 = Client(gazette_app) user_2 = Client(gazette_app) user_3 = Client(gazette_app) for user, client in ( ('*****@*****.**', user_1), ('*****@*****.**', user_2), ('*****@*****.**', user_3), ): login = client.get('/auth/login') login.form['username'] = user login.form['password'] = '******' login.form.submit() # Add notices with freeze_time("2017-11-01 11:00"): for (organization, category, submit, user, issues) in ( ('100', '13', False, editor, ['2017-44']), ('100', '13', False, user_1, ['2017-45']), ('100', '11', False, user_1, ['2017-46']), ('200', '11', False, user_1, ['2017-47']), ('100', '12', True, user_1, ['2017-47', '2017-45']), ('100', '14', True, user_1, ['2017-45', '2017-46']), ('300', '14', True, user_1, ['2017-46']), ('100', '11', False, user_2, ['2017-47']), ('100', '12', True, user_2, ['2017-47']), ('200', '14', False, user_2, ['2017-45', '2017-47']), ('100', '14', True, user_3, ['2017-46']), ('100', '12', True, user_3, ['2017-47']), ('100', '14', False, user_3, ['2017-47']), ('100', '14', True, user_3, ['2017-45', '2017-46', '2017-47']), ): manage = user.get('/notices/drafted/new-notice') manage.form['title'] = "Titel" manage.form['organization'] = organization manage.form['category'] = category manage.form['text'] = "Text" manage.form['author_place'] = 'Govikon' manage.form['author_name'] = 'State Chancellerist' manage.form['author_date'] = '2019-01-01' manage.form['issues'] = issues manage = manage.form.submit().maybe_follow() if submit: manage.click("Einreichen").form.submit() for s in ('rejected', 'accepted'): assert statistic(s, 'Organisationen') == [['Organisation', 'Anzahl']] assert statistic(s, 'Rubriken') == [['Rubrik', 'Anzahl']] assert statistic(s, 'Gruppen') == [['Gruppe', 'Anzahl']] assert publisher.get('/notices/drafted/statistics') assert publisher.get('/notices/submitted/statistics') assert publisher.get('/notices/published/statistics') # organizations/drafted: 5 x 100, 3 x 200 assert statistic('drafted', 'Organisationen') == [['Organisation', 'Anzahl'], ['Civic Community', 3], ['State Chancellery', 5]] # organizations/submitted: 10 x 100, 1 x 300 assert statistic('submitted', 'Organisationen') == [ ['Organisation', 'Anzahl'], ['Municipality', 1], ['State Chancellery', 10], ] # organizations/submitted/2017-45/46: 6 x 100, 1 x 300 assert statistic('submitted', 'Organisationen', 'from_date=2017-11-10&to_date=2017-11-17') == [ ['Organisation', 'Anzahl'], ['Municipality', 1], ['State Chancellery', 6], ] # categories/drafted: 3 x 11, 2 x 13, 3 x 14 assert statistic('drafted', 'Rubriken') == [ ['Rubrik', 'Anzahl'], ['Commercial Register', 2], ['Education', 3], ['Elections', 3], ] # categories/submitted: 4 x 12, 7 x 14 assert statistic('submitted', 'Rubriken') == [ ['Rubrik', 'Anzahl'], ['Elections', 7], ['Submissions', 4], ] # categories/submitted/2017-45/46: 1 x 12, 6 x 14 assert statistic('submitted', 'Rubriken', 'from_date=2017-11-10&to_date=2017-11-17') == [ ['Rubrik', 'Anzahl'], ['Elections', 6], ['Submissions', 1], ] # groups/drafted: 1 x w/o, 6 x B, 1 x C assert '>5</td>' in publisher.get('/notices/drafted/statistics') assert statistic('drafted', 'Gruppen') == [ ['Gruppe', 'Anzahl'], ['B', 6], ['C', 1], ] # groups/submitted: 6 x B, 5 x C assert '>4</td>' in publisher.get('/notices/submitted/statistics') assert statistic('submitted', 'Gruppen') == [ ['Gruppe', 'Anzahl'], ['B', 6], ['C', 5], ] # groups/submitted/2017-45/46: 4 x B, 3 x C assert statistic('submitted', 'Gruppen', 'from_date=2017-11-10&to_date=2017-11-17') == [ ['Gruppe', 'Anzahl'], ['B', 4], ['C', 3], ]
def test_view_notices_order(gazette_app): def get_items(page): return [a.text for a in page.pyquery('td strong a')] def get_ordering(page): return { r['order'][0]: r['direction'][0] for r in [ parse_qs(urlparse(a.attrib['href']).query) for a in page.pyquery('th a') ] } with freeze_time("2017-11-01 11:00"): client = Client(gazette_app) login_publisher(client) # new notice manage = client.get('/notices/drafted/new-notice') manage.form['title'] = "Erneuerungswahlen" manage.form['organization'] = '100' manage.form['category'] = '11' manage.form['issues'] = ['2017-44', '2017-46'] manage.form['text'] = "1. Oktober 2017" manage.form['author_place'] = 'Govikon' manage.form['author_name'] = 'State Chancellerist' manage.form['author_date'] = '2019-01-01' manage.form.submit() client.get('/notice/erneuerungswahlen/submit').form.submit() client.get('/notice/erneuerungswahlen/accept').form.submit() manage = client.get('/notices/drafted/new-notice') manage.form['title'] = "Kantonsratswahlen" manage.form['organization'] = '200' manage.form['category'] = '13' manage.form['issues'] = ['2017-45', '2017-47'] manage.form['text'] = "10. Oktober 2017" manage.form['author_place'] = 'Govikon' manage.form['author_name'] = 'State Chancellerist' manage.form['author_date'] = '2019-01-01' manage.form.submit() client.get('/notice/kantonsratswahlen/submit').form.submit() client.get('/notice/kantonsratswahlen/accept').form.submit() # Default sorting ordered = client.get('/notices/accepted') assert get_items(ordered) == ["Erneuerungswahlen", "Kantonsratswahlen"] assert get_ordering(client.get('/notices/accepted')) == { 'title': 'asc', 'organization': 'asc', 'category': 'asc', 'group.name': 'asc', 'user.name': 'asc', 'first_issue': 'desc' } # Invalid sorting ordered = client.get('/notices/accepted?order=xxx') assert get_items(ordered) == ["Erneuerungswahlen", "Kantonsratswahlen"] assert get_ordering(client.get('/notices/accepted')) == { 'title': 'asc', 'organization': 'asc', 'category': 'asc', 'group.name': 'asc', 'user.name': 'asc', 'first_issue': 'desc' } # Omit direction ordered = client.get('/notices/accepted?order=category') assert get_items(ordered) == ["Kantonsratswahlen", "Erneuerungswahlen"] assert get_ordering(ordered) == { 'title': 'asc', 'organization': 'asc', 'category': 'desc', 'group.name': 'asc', 'user.name': 'asc', 'first_issue': 'asc' } # Sort by # ... title url = '/notices/accepted?order={}&direction={}' ordered = client.get(url.format('title', 'asc')) assert get_items(ordered) == ["Erneuerungswahlen", "Kantonsratswahlen"] assert get_ordering(ordered) == { 'title': 'desc', 'organization': 'asc', 'category': 'asc', 'group.name': 'asc', 'user.name': 'asc', 'first_issue': 'asc' } ordered = client.get(url.format('title', 'desc')) assert get_items(ordered) == ["Kantonsratswahlen", "Erneuerungswahlen"] assert get_ordering(ordered) == { 'title': 'asc', 'organization': 'asc', 'category': 'asc', 'group.name': 'asc', 'user.name': 'asc', 'first_issue': 'asc' } # ... organization ordered = client.get(url.format('organization', 'asc')) assert get_items(ordered) == ["Kantonsratswahlen", "Erneuerungswahlen"] assert get_ordering(ordered) == { 'title': 'asc', 'organization': 'desc', 'category': 'asc', 'group.name': 'asc', 'user.name': 'asc', 'first_issue': 'asc' } ordered = client.get(url.format('organization', 'desc')) assert get_items(ordered) == ["Erneuerungswahlen", "Kantonsratswahlen"] assert get_ordering(ordered) == { 'title': 'asc', 'organization': 'asc', 'category': 'asc', 'group.name': 'asc', 'user.name': 'asc', 'first_issue': 'asc' } # ... category ordered = client.get(url.format('category', 'asc')) assert get_items(ordered) == ["Kantonsratswahlen", "Erneuerungswahlen"] assert get_ordering(ordered) == { 'title': 'asc', 'organization': 'asc', 'category': 'desc', 'group.name': 'asc', 'user.name': 'asc', 'first_issue': 'asc' } ordered = client.get(url.format('category', 'desc')) assert get_items(ordered) == ["Erneuerungswahlen", "Kantonsratswahlen"] assert get_ordering(ordered) == { 'title': 'asc', 'organization': 'asc', 'category': 'asc', 'group.name': 'asc', 'user.name': 'asc', 'first_issue': 'asc' } # ... group ordered = client.get(url.format('group.name', 'asc')) assert get_ordering(ordered) == { 'title': 'asc', 'organization': 'asc', 'category': 'asc', 'group.name': 'desc', 'user.name': 'asc', 'first_issue': 'asc' } ordered = client.get(url.format('category', 'desc')) assert get_ordering(ordered) == { 'title': 'asc', 'organization': 'asc', 'category': 'asc', 'group.name': 'asc', 'user.name': 'asc', 'first_issue': 'asc' } # ... user ordered = client.get(url.format('user.name', 'asc')) assert get_ordering(ordered) == { 'title': 'asc', 'organization': 'asc', 'category': 'asc', 'group.name': 'asc', 'user.name': 'desc', 'first_issue': 'asc' } ordered = client.get(url.format('category', 'desc')) assert get_items(ordered) == ["Erneuerungswahlen", "Kantonsratswahlen"] assert get_ordering(ordered) == { 'title': 'asc', 'organization': 'asc', 'category': 'asc', 'group.name': 'asc', 'user.name': 'asc', 'first_issue': 'asc' } # ... issues ordered = client.get(url.format('first_issue', 'asc')) assert get_items(ordered) == ["Erneuerungswahlen", "Kantonsratswahlen"] assert get_ordering(ordered) == { 'title': 'asc', 'organization': 'asc', 'category': 'asc', 'group.name': 'asc', 'user.name': 'asc', 'first_issue': 'desc' } ordered = client.get(url.format('first_issue', 'desc')) assert get_items(ordered) == ["Kantonsratswahlen", "Erneuerungswahlen"] assert get_ordering(ordered) == { 'title': 'asc', 'organization': 'asc', 'category': 'asc', 'group.name': 'asc', 'user.name': 'asc', 'first_issue': 'asc' }
def test_view_notices(gazette_app): with freeze_time("2017-11-01 11:00"): publisher = Client(gazette_app) login_publisher(publisher) editor_1 = Client(gazette_app) login_editor_1(editor_1) editor_2 = Client(gazette_app) login_editor_2(editor_2) editor_3 = Client(gazette_app) login_editor_3(editor_3) for user in (publisher, editor_1, editor_2, editor_3): for state in ('drafted', 'submitted', 'rejected', 'accepted', 'published'): assert "Keine Meldungen" in user.get('/notices/' + state) # new notices manage = editor_1.get('/notices/drafted/new-notice') manage.form['title'] = "Erneuerungswahlen" manage.form['organization'] = '200' manage.form['category'] = '11' manage.form['issues'] = ['2017-44', '2017-45'] manage.form['text'] = "1. Oktober 2017" manage.form['author_place'] = 'Govikon' manage.form['author_name'] = 'State Chancellerist' manage.form['author_date'] = '2019-01-01' manage.form.submit() manage = editor_3.get('/notices/drafted/new-notice') manage.form['title'] = "Kantonsratswahlen" manage.form['organization'] = '200' manage.form['category'] = '11' manage.form['issues'] = ['2017-44', '2017-45'] manage.form['text'] = "1. Oktober 2017" manage.form['author_place'] = 'Govikon' manage.form['author_name'] = 'State Chancellerist' manage.form['author_date'] = '2019-01-01' manage.form.submit() for user in (publisher, editor_1, editor_2, editor_3): for state in ('submitted', 'rejected', 'accepted', 'published'): assert "Keine Meldungen" in user.get('/notices/' + state) assert "Erneuerungswahlen" in publisher.get('/notices/drafted') assert "Erneuerungswahlen" in editor_1.get('/notices/drafted') assert "Erneuerungswahlen" in editor_2.get('/notices/drafted') assert "Erneuerungswahlen" not in editor_3.get('/notices/drafted') assert "Kantonsratswahlen" in publisher.get('/notices/drafted') assert "Kantonsratswahlen" not in editor_1.get('/notices/drafted') assert "Kantonsratswahlen" not in editor_1.get('/notices/drafted') assert "Kantonsratswahlen" in editor_3.get('/notices/drafted') # submit notices editor_1.get('/notice/erneuerungswahlen/submit').form.submit() editor_3.get('/notice/kantonsratswahlen/submit').form.submit() for user in (publisher, editor_1, editor_2, editor_3): for state in ('drafted', 'rejected', 'accepted', 'published'): assert "Keine Meldungen" in user.get('/notices/' + state) assert "Erneuerungswahlen" in publisher.get('/notices/submitted') assert "Erneuerungswahlen" in editor_1.get('/notices/submitted') assert "Erneuerungswahlen" in editor_2.get('/notices/submitted') assert "Erneuerungswahlen" not in editor_3.get('/notices/submitted') assert "Kantonsratswahlen" in publisher.get('/notices/submitted') assert "Kantonsratswahlen" not in editor_1.get('/notices/submitted') assert "Kantonsratswahlen" not in editor_2.get('/notices/submitted') assert "Kantonsratswahlen" in editor_3.get('/notices/submitted') # reject notices manage = publisher.get('/notice/erneuerungswahlen/reject') manage.form['comment'] = 'comment' manage.form.submit() manage = publisher.get('/notice/kantonsratswahlen/reject') manage.form['comment'] = 'comment' manage.form.submit() for user in (publisher, editor_1, editor_2, editor_3): for state in ('drafted', 'submitted', 'accepted', 'published'): assert "Keine Meldungen" in user.get('/notices/' + state) assert "Erneuerungswahlen" in publisher.get('/notices/rejected') assert "Erneuerungswahlen" in editor_1.get('/notices/rejected') assert "Erneuerungswahlen" in editor_2.get('/notices/rejected') assert "Erneuerungswahlen" not in editor_3.get('/notices/rejected') assert "Kantonsratswahlen" in publisher.get('/notices/rejected') assert "Kantonsratswahlen" not in editor_1.get('/notices/rejected') assert "Kantonsratswahlen" not in editor_2.get('/notices/rejected') assert "Kantonsratswahlen" in editor_3.get('/notices/rejected') # submit & accept notices editor_1.get('/notice/erneuerungswahlen/submit').form.submit() publisher.get('/notice/erneuerungswahlen/accept').form.submit() editor_3.get('/notice/kantonsratswahlen/submit').form.submit() publisher.get('/notice/kantonsratswahlen/accept').form.submit() for user in (publisher, editor_1, editor_2, editor_3): for state in ('drafted', 'submitted', 'rejected', 'published'): assert "Keine Meldungen" in user.get('/notices/' + state) assert "Erneuerungswahlen" in publisher.get('/notices/accepted') assert "Erneuerungswahlen" in editor_1.get('/notices/accepted') assert "Erneuerungswahlen" in editor_2.get('/notices/accepted') assert "Erneuerungswahlen" not in editor_3.get('/notices/accepted') assert "Kantonsratswahlen" in publisher.get('/notices/accepted') assert "Kantonsratswahlen" not in editor_1.get('/notices/accepted') assert "Kantonsratswahlen" not in editor_2.get('/notices/accepted') assert "Kantonsratswahlen" in editor_3.get('/notices/accepted') # publish notices assert "Erneuerungswahlen" in publisher.get('/notices/accepted') assert "Erneuerungswahlen" in editor_1.get('/notices/accepted') assert "Erneuerungswahlen" in editor_2.get('/notices/accepted') assert "Erneuerungswahlen" not in editor_3.get('/notices/accepted') assert "Kantonsratswahlen" in publisher.get('/notices/accepted') assert "Kantonsratswahlen" not in editor_1.get('/notices/accepted') assert "Kantonsratswahlen" not in editor_2.get('/notices/accepted') assert "Kantonsratswahlen" in editor_3.get('/notices/accepted')
def test_view_notices_filter(gazette_app): with freeze_time("2017-11-01 11:00"): client = Client(gazette_app) login_editor_1(client) manage = client.get('/notices/drafted/new-notice') manage.form['title'] = "Erneuerungswahlen" manage.form['organization'] = '100' manage.form['category'] = '11' manage.form['issues'] = ['2017-44', '2017-45'] manage.form['text'] = "1. Oktober 2017" manage.form['author_place'] = 'Govikon' manage.form['author_name'] = 'State Chancellerist' manage.form['author_date'] = '2019-01-01' manage.form.submit() client.get('/notice/erneuerungswahlen/submit').form.submit() login_editor_2(client) manage = client.get('/notices/drafted/new-notice') manage.form['title'] = "Kantonsratswahlen" manage.form['organization'] = '200' manage.form['category'] = '12' manage.form['issues'] = ['2017-45', '2017-46'] manage.form['text'] = "9. Oktober 2017" manage.form['author_place'] = 'Govikon' manage.form['author_name'] = 'State Chancellerist' manage.form['author_date'] = '2019-01-01' manage.form.submit() client.get('/notice/kantonsratswahlen/submit').form.submit() login_publisher(client) manage = client.get('/notices/drafted/new-notice') manage.form['title'] = "Regierungsratswahlen" manage.form['organization'] = '300' manage.form['category'] = '13' manage.form['issues'] = ['2017-47'] manage.form['text'] = "10. Oktober 2017" manage.form['author_place'] = 'Govikon' manage.form['author_name'] = 'State Chancellerist' manage.form['author_date'] = '2019-01-01' manage.form.submit() client.get('/notice/regierungsratswahlen/submit').form.submit() manage = client.get('/notice/kantonsratswahlen/edit') manage.form['text'] = "10. Oktober 2017" manage.form.submit() manage = client.get('/notices/submitted') assert "Erneuerungswahlen" in manage assert "Kantonsratswahlen" in manage assert "Regierungsratswahlen" in manage assert '<option value="2017-11-03">2017-44</option>' in manage assert '<option value="2017-11-10">2017-45</option>' in manage assert '<option value="2017-11-17">2017-46</option>' in manage assert '<option value="2017-11-24">2017-47</option>' in manage assert '<option value="2017-12-01">2017-48</option>' not in manage assert '<option value="100">State Chancellery</option>' in manage assert '<option value="200">Civic Community</option>' in manage assert '<option value="300">Municipality</option>' in manage assert '<option value="500">Corporation</option>' not in manage assert '<option value="11">Education</option>' in manage assert '<option value="12">Submissions</option>' in manage assert '<option value="13">Commercial Register</option>' in manage assert '<option value="14">Elections</option>' not in manage manage.form['term'] = 'neuerun' manage = manage.form.submit().maybe_follow() assert "Erneuerungswahlen" in manage assert "Kantonsratswahlen" not in manage assert "Regierungsratswahlen" not in manage manage = client.get('/notices/submitted') manage.form['term'] = '10. Oktober' manage = manage.form.submit().maybe_follow() assert "Erneuerungswahlen" not in manage assert "Kantonsratswahlen" in manage assert "Regierungsratswahlen" in manage manage = client.get('/notices/submitted') manage.form['term'] = '10. Oktober' manage.form['categories'] = '12' manage = manage.form.submit().maybe_follow() assert "Erneuerungswahlen" not in manage assert "Kantonsratswahlen" in manage assert "Regierungsratswahlen" not in manage manage = client.get('/notices/submitted') manage.form['term'] = '10. Oktober' manage.form['organizations'] = '200' manage = manage.form.submit().maybe_follow() assert "Erneuerungswahlen" not in manage assert "Kantonsratswahlen" in manage assert "Regierungsratswahlen" not in manage manage = client.get('/notices/submitted') manage.form['term'] = '10. Oktober' manage.form['from_date'] = '2017-11-17' manage.form['to_date'] = '2017-11-17' manage = manage.form.submit().maybe_follow() assert "Erneuerungswahlen" not in manage assert "Kantonsratswahlen" in manage assert "Regierungsratswahlen" not in manage manage = client.get('/notices/submitted') manage.form['own'] = True manage = manage.form.submit().maybe_follow() assert "Erneuerungswahlen" not in manage assert "Kantonsratswahlen" in manage assert "Regierungsratswahlen" in manage
class Level3FunctionalTests(unittest.TestCase): def setUp(self): session_opts = { 'session.type': 'memory', } beaker_app = beaker.middleware.SessionMiddleware(main.app, session_opts) db = sqlite3.connect(DATABASE_NAME) database.create_tables(db) self.users, self.images = database.sample_data(db) self.app = TestApp(beaker_app) bottle.debug() # force debug messages in error pages returned by webtest def tearDown(self): pass def doLogin(self, email, password): """Perform a login, returns the response to the login request""" response = self.app.get('/') loginform = response.forms['loginform'] loginform['nick'] = email loginform['password'] = password return loginform.submit() def testMyImagesForm(self): """As a registered user, when I load the "My Images" page I see a form that has a file selection input and a button labelled "Upload Image". """ imagefilename = "iceland.jpg" (password, nick, avatar) = self.users[0] # login and then get the my images page self.doLogin(nick, password) response = self.app.get('/my') # the page should contain an upload form self.assertIn('uploadform', response.forms) form = response.forms['uploadform'] # action should be /upload self.assertEqual('/upload', form.action) # try uploading a file form['imagefile'] = webtest.Upload(imagefilename, content_type='image/jpeg') response = form.submit() # expect a redirect to the /my page self.assertIn(response.status, ['303 See Other', '302 Found']) (_, _, path, _, _, _) = urlparse(response.headers['Location']) self.assertEqual('/my', path) # and when I retrieve that page I see my image at the top response = self.app.get('/my') flowtows = response.html.find_all(class_='flowtow') # should find my image in the first one div = flowtows[0] img = div.find("img") # should be the image src attribute self.assertIn(imagefilename, img['src']) # and we should be able to retrieve it #response = self.app.get(img['src']) #self.assertEqual("200 OK", response.status) # remove the uploaded image os.unlink('../static/images/iceland.jpg') def testMyImagesFormNoLogin(self): """ As an unregistered user (not logged in) if I try to upload an image by accessing the /upload URL directly, I get a redirect response back to the home page. """ imagefilename = "iceland.jpg" (password, nick, avatar) = self.users[0] # login and then get the my images page self.doLogin(nick, password) response = self.app.get('/my') # the page should contain an upload form self.assertIn('uploadform', response.forms) form = response.forms['uploadform'] # action should be /upload self.assertEqual('/upload', form.action) # try uploading a file form['imagefile'] = webtest.Upload(imagefilename, content_type='image/jpeg') # before we submit, we'll logout logoutform = response.forms['logoutform'] response3 = logoutform.submit() # now submit the form as a regular user response = form.submit() # expect a redirect to the / page self.assertIn(response.status, ['303 See Other', '302 Found']) (_, _, path, _, _, _) = urlparse(response.headers['Location']) self.assertEqual('/', path, "expected redirect to '/' after non-login file upload") # and when I retrieve that page I should not see the image response = self.app.get('/') imgs = response.html.find_all('img') for img in imgs: self.assertNotIn(imagefilename, img['src'], "found image that should not have uploaded")
class TestResource(TestCase): def setUp(self): from pyramid.renderers import JSONP self.config = testing.setUp() self.config.add_renderer('jsonp', JSONP(param_name='callback')) self.config.include("cornice") self.authz_policy = ACLAuthorizationPolicy() self.config.set_authorization_policy(self.authz_policy) self.authn_policy = AuthTktAuthenticationPolicy('$3kr1t') self.config.set_authentication_policy(self.authn_policy) self.config.scan("tests.test_resource") self.app = TestApp(CatchErrors(self.config.make_wsgi_app())) def tearDown(self): testing.tearDown() def test_basic_resource(self): self.assertEqual(self.app.get("/users").json, {'users': [1, 2]}) self.assertEqual(self.app.get("/users/1").json, {'name': 'gawel'}) resp = self.app.get("/users/1?callback=test", headers={'Accept': 'application/javascript'}) self.assertIn(b'test({"name": "gawel"})', resp.body, msg=resp.body) @mock.patch('cornice.resource.Service') def test_without_collection_path_has_one_service(self, mocked_service): @resource(path='/nocollection/{id}', name='nocollection') class NoCollection(object): def __init__(self, request, context=None): pass self.assertEqual(mocked_service.call_count, 1) def test_accept_headers(self): # the accept headers should work even in case they're specified in a # resource method self.assertEqual( self.app.post("/users", headers={'Accept': 'application/json'}, params=json.dumps({'test': 'yeah'})).json, {'test': 'yeah'}) def patch(self, *args, **kwargs): return self.app._gen_request('PATCH', *args, **kwargs) def test_head_and_patch(self): self.app.head("/users") self.app.head("/users/1") self.assertEqual( self.patch("/users").json, {'test': 'yeah'}) self.assertEqual( self.patch("/users/1").json, {'test': 'yeah'}) def test_context_factory(self): self.assertEqual(self.app.put('/users/1').json, {'type': 'context!'}) def test_explicit_collection_service_name(self): route_url = testing.DummyRequest().route_url # service must exist self.assert_(route_url('collection_user_service')) def test_explicit_service_name(self): route_url = testing.DummyRequest().route_url self.assert_(route_url('user_service', id=42)) # service must exist @mock.patch('cornice.resource.Service') def test_factory_is_autowired(self, mocked_service): @resource(collection_path='/list', path='/list/{id}', name='list') class List(object): pass factory_args = [kw.get('factory') for _, kw in mocked_service.call_args_list] self.assertEqual([List, List], factory_args) def test_acl_is_deprecated(self): def custom_acl(request): return [] with self.assertRaises(ConfigurationError): @resource(collection_path='/list', path='/list/{id}', name='list', collection_acl=custom_acl, acl=custom_acl) class List(object): pass def test_acl_support_unauthenticated_thing_get(self): # calling a view with permissions without an auth'd user => 403 self.app.get('/thing', status=HTTPForbidden.code) def test_acl_support_unauthenticated_forbidden_thing_get(self): # calling a view with permissions without an auth'd user => 403 with mock.patch.object(self.authn_policy, 'authenticated_userid', return_value=None): result = self.app.get('/thing', status=HTTPForbidden.code) def test_acl_support_authenticated_allowed_thing_get(self): with mock.patch.object(self.authn_policy, 'unauthenticated_userid', return_value='alice'): with mock.patch.object(self.authn_policy, 'authenticated_userid', return_value='alice'): result = self.app.get('/thing', status=HTTPOk.code) self.assertEqual("yay", result.json)
class TestSimpleApp(PyramidMongoEngineTestCase): def setUp(self): super(TestSimpleApp, self).setUp() from .apptest import main app = main({ "mongodb_name": "dbapp_test", "mongo_url": "mongodb://localhost" }) from webtest import TestApp self.app = TestApp(app) from .apptest import User params = {"email": "*****@*****.**", "username": "******"} User(**params).save() def tearDown(self): super(TestSimpleApp, self).tearDown() from .apptest import User User.drop_collection() def test_get_msg_app(self): res = self.app.get('/') self.assertEquals(200, res.status_code) self.assertEquals({"msg": "hello test app"}, res.json) def test_post_save_user(self): params = {"email": "*****@*****.**", "username": "******"} res = self.app.post('/users/', params=params) json_res = res.json["user"] self.assertEquals(200, res.status_code) self.assertEquals(params["username"], json_res["username"]) def test_get_all_users(self): res = self.app.get("/users/") self.assertEquals(1, len(res.json["users"])) def test_get_by_username(self): res = self.app.get("/user/testerd/get") user = res.json["user"] self.assertEquals(200, res.status_code) self.assertEquals(user["username"], "testerd") def test_get_not_found_username(self): res = self.app.get("/user/notfound/get", expect_errors=True) self.assertEquals(404, res.status_code) def test_get_first_user(self): res = self.app.get("/users/?first=true") user = res.json["users"] self.assertEquals(200, res.status_code) self.assertEquals(user["username"], "testerd") def test_get_first_user_not_found(self): from .apptest import User User.drop_collection() res = self.app.get("/users/?first=true", expect_errors=True) self.assertEquals(404, res.status_code) def test_delete_user(self): res = self.app.delete("/user/testerd/delete") self.assertEquals(200, res.status_code) res2 = self.app.get("/user/testerd/get", expect_errors=True) self.assertEquals(404, res2.status_code)
class FunctionalTests(unittest.TestCase): """ these tests are functional tests to check functionality of the whole app (i.e. integration tests) they also serve to get coverage for 'main' """ def setUp(self): self.config = testing.setUp() self.config.include('pyramid_mailer.testing') try: DBSession.close() DBSession.remove() # print("removed old DBSession ==============================") except: # print("no DBSession to remove =============================") pass # try: # os.remove('test_webtest_functional.db') # #print "deleted old test database" # except: # pass # #print "never mind" my_settings = { # 'sqlalchemy.url': 'sqlite:///test_webtest_functional.db', 'sqlalchemy.url': 'sqlite:///:memory:', 'available_languages': 'da de en es fr', 'c3smembership.mailaddr': '*****@*****.**', 'testing.mail_to_console': 'false' } engine = engine_from_config(my_settings) DBSession.configure(bind=engine) self.session = DBSession # () Base.metadata.create_all(engine) # dummy database entries for testing with transaction.manager: member1 = C3sMember( # german firstname=u'SomeFirstnäme', lastname=u'SomeLastnäme', email=u'*****@*****.**', address1=u"addr one", address2=u"addr two", postcode=u"12345", city=u"Footown Mäh", country=u"Foocountry", locale=u"DE", date_of_birth=date.today(), email_is_confirmed=False, email_confirm_code=u'ABCDEFGFOO', password=u'arandompassword', date_of_submission=date.today(), membership_type=u'normal', member_of_colsoc=True, name_of_colsoc=u"GEMA", num_shares=u'23', ) DBSession.add(member1) DBSession.flush() from c3smembership import main app = main({}, **my_settings) app.registry.get_mailer = get_mailer from webtest import TestApp self.testapp = TestApp(app) def tearDown(self): self.session.close() self.session.remove() # os.remove('test_webtest_functional.db') def test_base_template(self): """load the front page, check string exists""" res = self.testapp.get('/', status=200) self.failUnless('Cultural Commons Collecting Society' in res.body) self.failUnless('Copyright 2014, C3S SCE' in res.body) # def test_faq_template(self): # """load the FAQ page, check string exists""" # res = self.testapp.get('/faq', status=200) # self.failUnless('FAQ' in res.body) # self.failUnless( # 'Copyright 2013, OpenMusicContest.org e.V.' in res.body) def test_lang_en_LOCALE(self): """load the front page, forced to english (default pyramid way), check english string exists""" res = self.testapp.reset() # delete cookie res = self.testapp.get('/?_LOCALE_=en', status=200) self.failUnless('Application for Membership of ' in res.body) def test_lang_en(self): """load the front page, set to english (w/ pretty query string), check english string exists""" res = self.testapp.reset() # delete cookie res = self.testapp.get('/?en', status=302) self.failUnless('The resource was found at' in res.body) # we are being redirected... res1 = res.follow() self.failUnless('Application for Membership of ' in res1.body) # so let's test the app's obedience to the language requested by the browser # i.e. will it respond to http header Accept-Language? # def test_accept_language_header_da(self): # """check the http 'Accept-Language' header obedience: danish # load the front page, check danish string exists""" # res = self.testapp.reset() # delete cookie # res = self.testapp.get('/', status=200, # headers={ # 'Accept-Language': 'da'}) # #print(res.body) # if you want to see the pages source # self.failUnless( # '<input type="hidden" name="_LOCALE_" value="da"' in res.body) def test_accept_language_header_de_DE(self): """check the http 'Accept-Language' header obedience: german load the front page, check german string exists""" res = self.testapp.reset() # delete cookie res = self.testapp.get('/', status=200, headers={'Accept-Language': 'de-DE'}) # print(res.body) # if you want to see the pages source self.failUnless('Mitgliedschaftsantrag für die' in res.body) self.failUnless( '<input type="hidden" name="locale" value="de"' in res.body) def test_accept_language_header_en(self): """check the http 'Accept-Language' header obedience: english load the front page, check english string exists""" res = self.testapp.reset() # delete cookie res = self.testapp.get('/', status=200, headers={'Accept-Language': 'en'}) # print(res.body) # if you want to see the pages source self.failUnless("I want to become" in res.body) # def test_accept_language_header_es(self): # """check the http 'Accept-Language' header obedience: spanish # load the front page, check spanish string exists""" # res = self.testapp.reset() # delete cookie # res = self.testapp.get('/', status=200, # headers={ # 'Accept-Language': 'es'}) # #print(res.body) # if you want to see the pages source # self.failUnless( # 'Luego de enviar el siguiente formulario,' in res.body) # def test_accept_language_header_fr(self): # """check the http 'Accept-Language' header obedience: french # load the front page, check french string exists""" # res = self.testapp.reset() # delete cookie # res = self.testapp.get('/', status=200, # headers={ # 'Accept-Language': 'fr'}) # #print(res.body) # if you want to see the pages source # self.failUnless( # 'En envoyant un courriel à [email protected] vous pouvez' in res.body) def test_no_cookies(self): """load the front page, check default english string exists""" res = self.testapp.reset() # delete cookie res = self.testapp.get('/', status=200, headers={'Accept-Language': 'af, cn'}) # ask for missing languages # print res.body self.failUnless('Application for Membership' in res.body) ############################################################################# # check for validation stuff def test_form_lang_en_non_validating(self): """load the join form, check english string exists""" res = self.testapp.reset() res = self.testapp.get('/?_LOCALE_=en', status=200) form = res.form # print(form.fields) # print(form.fields.values()) form['firstname'] = 'John' # form['address2'] = 'some address part' res2 = form.submit('submit') self.failUnless( 'There was a problem with your submission' in res2.body) def test_form_lang_de(self): """load the join form, check german string exists""" res = self.testapp.get('/?de', status=302) # print(res) self.failUnless('The resource was found at' in res.body) # we are being redirected... res2 = res.follow() # print(res2) # test for german translation of template text (lingua_xml) self.failUnless('Mitgliedschaftsantrag für die' in res2.body) # test for german translation of form field label (lingua_python) self.failUnless('Vorname' in res2.body) def test_form_lang_LOCALE_de(self): """load the join form in german, check german string exists this time forcing german locale the pyramid way """ res = self.testapp.get('/?_LOCALE_=de', status=200) # test for german translation of template text (lingua_xml) self.failUnless('Mitgliedschaftsantrag für die' in res.body) # test for german translation of form field label (lingua_python) self.failUnless('Vorname' in res.body) ########################################################################### # checking the success page that sends out email with verification link def test_check_email_en_wo_context(self): """try to access the 'check_email' page and be redirected check english string exists""" res = self.testapp.reset() res = self.testapp.get('/check_email?en', status=302) self.failUnless('The resource was found at' in res.body) # we are being redirected... res1 = res.follow() # print(res1) self.failUnless('Application for Membership of ' in str(res1.body), 'expected string was not found in web UI') ########################################################################### # checking the view that gets code and mail, asks for a password def test_verify_email_en_w_bad_code(self): """load the page in english, be redirected to the form (data is missing) check english string exists""" res = self.testapp.reset() res = self.testapp.get('/verify/[email protected]/ABCD-----', status=200) self.failUnless('Password' in res.body) form = res.form form['password'] = '******' res2 = form.submit('submit') self.failUnless('Password' in res2.body) def test_verify_email_en_w_good_code(self): """ """ res = self.testapp.reset() res = self.testapp.get('/verify/[email protected]/ABCDEFGFOO', status=200) self.failUnless('Password' in res.body) form = res.form form['password'] = '******' res2 = form.submit('submit') # print res2.body self.failUnless( 'C3S_SCE_AFM_SomeFirstn_meSomeLastn_me.pdf' in res2.body) # 'Your Email has been confirmed, Firstnäme Lastname!' in res.body) # res2 = self.testapp.get( # '/C3S_SCE_AFM_Firstn_meLastname.pdf', status=200) # self.failUnless(len(res2.body) > 70000) def test_success_wo_data_en(self): """load the success page in english (via query_string), check for redirection and english string exists""" res = self.testapp.reset() res = self.testapp.get('/success?en', status=302) self.failUnless('The resource was found at' in res.body) # we are being redirected... res1 = res.follow() # print(res1) self.failUnless( # check text on page redirected to 'Please fill out the form' in str(res1.body), 'expected string was not found in web UI') def test_success_pdf_wo_data_en(self): """ try to load a pdf (which must fail because the form was not used) check for redirection to the form and test string exists """ res = self.testapp.reset() res = self.testapp.get('/C3S_SCE_AFM_ThefirstnameThelastname.pdf', status=302) self.failUnless('The resource was found at' in res.body) # we are being redirected... res1 = res.follow() # print(res1) self.failUnless( # check text on page redirected to 'Please fill out the form' in str(res1.body), 'expected string was not found in web UI') def test_email_confirmation(self): """ test email confirmation form and PDF download with a known login/dataset """ res = self.testapp.reset() res = self.testapp.get('/verify/[email protected]/ABCDEFGFOO', status=200) # print(res.body) form = res.form form['password'] = '******' res2 = form.submit('submit') # print res2.body self.failUnless("Load your PDF..." in res2.body) self.failUnless( "/C3S_SCE_AFM_SomeFirstn_meSomeLastn_me.pdf" in res2.body) # load the PDF, check size res3 = self.testapp.get('/C3S_SCE_AFM_SomeFirstn_meSomeLastn_me.pdf', status=200) # print("length of result: %s") % len(res3.body) # print("body result: %s") % (res3.body) # ouch, PDF content! self.failUnless(80000 < len(res3.body) < 220000) # check pdf size def test_email_confirmation_wrong_mail(self): """ test email confirmation with a wrong email """ res = self.testapp.reset() res = self.testapp.get('/verify/[email protected]/ABCDEFGHIJ', status=200) # print(res.body) self.failUnless("Please enter your password." in res.body) # XXX this test shows nothing interesting def test_email_confirmation_wrong_code(self): """ test email confirmation with a wrong code """ res = self.testapp.reset() res = self.testapp.get('/verify/[email protected]/WRONGCODE', status=200) # print(res.body) self.failUnless("Please enter your password." in res.body) def test_success_check_email(self): """ test "check email" success page with wrong data: this should redirect to the form. """ res = self.testapp.reset() res = self.testapp.get('/check_email', status=302) res2 = res.follow() self.failUnless("Please fill out the form" in res2.body)
def setUp(self): """Create a simple WSGI app.""" app = App(BaseHandler(SimpleSequence)) self.res = app.get('/.dds')
class TestViews(unittest.TestCase): """ very basic tests for the main views """ def setUp(self): self.config = testing.setUp() self.config.include('pyramid_mailer.testing') self.config.registry.settings[ 'c3smembership.url'] = 'https://yes.c3s.cc' self.config.registry.settings['c3smembership.mailaddr'] = '*****@*****.**' self.config.registry.settings['testing.mail_to_console'] = 'false' DBSession.remove() self.session = _initTestingDB() def tearDown(self): DBSession.remove() testing.tearDown() def test_show_success(self): """ test the success page """ from c3smembership.views.afm import show_success self.config.add_route('join', '/') request = testing.DummyRequest( params={'appstruct': { 'firstname': 'foo', 'lastname': 'bar', }}) request.session['appstruct'] = { 'person': { 'firstname': 'foo', 'lastname': 'bar', } } result = show_success(request) # print result self.assertTrue(result['lastname'] is 'bar') self.assertTrue(result['firstname'] is 'foo') def test_success_check_email(self): """ test the success_check_email view """ from c3smembership.views.afm import success_check_email self.config.add_route('join', '/') from pyramid_mailer import get_mailer request = testing.DummyRequest( params={'appstruct': { 'firstname': 'foo', 'lastname': 'bar', }}) request.session['appstruct'] = { 'person': { 'firstname': 'foo', 'lastname': 'bar', 'email': '*****@*****.**', 'locale': 'de', }, 'email_confirm_code': '12345678', } mailer = get_mailer(request) result = success_check_email(request) # print result self.assertTrue(result['lastname'] is 'bar') self.assertTrue(result['firstname'] is 'foo') self.assertEqual(len(mailer.outbox), 1) self.assertEqual(mailer.outbox[0].subject, 'C3S: confirm your email address and load your PDF') # self.assertEqual(mailer.outbox[0]., "hello world") verif_link = "https://yes.c3s.cc/verify/[email protected]/12345678" self.assertTrue("Hallo foo bar!" in mailer.outbox[0].body) self.assertTrue(verif_link in mailer.outbox[0].body) def test_success_check_email_redirect(self): """ test the success_check_email view redirection when appstruct is missing """ from c3smembership.views.afm import success_check_email self.config.add_route('join', '/') request = testing.DummyRequest() result = success_check_email(request) self.assertEqual('302 Found', result._status) self.assertEqual('http://example.com/', result.location) def _fill_form_valid_natural(self, form): # print form.fields form['firstname'] = u'SomeFirstname' form['lastname'] = u'SomeLastname' form['email'] = u'*****@*****.**' form['password'] = u'jG2NVfOn0BroGrAXR7wy' form['password-confirm'] = u'jG2NVfOn0BroGrAXR7wy' form['address1'] = u"addr one" form['address2'] = u"addr two" form['postcode'] = u"12345" form['city'] = u"Footown Meeh" form['country'].value__set(u"DE") form['year'] = unicode(date.today().year - 40) form['month'] = '1' form['day'] = '1' form['locale'] = u"DE" form['membership_type'].value__set(u'normal') form['other_colsoc'].value__set(u'no') form['name_of_colsoc'] = u"GEMA" form['num_shares'] = u'23' form['got_statute'].value__set(True) form['got_dues_regulations'].value__set(True) return form def test_join_c3s(self): # setup self.config = testing.setUp() self.config.include('pyramid_mailer.testing') DBSession.close() DBSession.remove() my_settings = { 'sqlalchemy.url': 'sqlite:///:memory:', 'available_languages': 'da de en es fr', 'c3smembership.dashboard_number': '30' } engine = engine_from_config(my_settings) DBSession.configure(bind=engine) Base.metadata.create_all(engine) with transaction.manager: # a group for accountants/staff accountants_group = Group(name=u"staff") DBSession.add(accountants_group) DBSession.flush() # staff personnel staffer1 = C3sStaff( login=u"rut", password=u"berries", email=u"*****@*****.**", ) staffer1.groups = [accountants_group] DBSession.add(accountants_group) DBSession.add(staffer1) DBSession.flush() app = main({}, **my_settings) self.testapp = TestApp(app) # sucess for valid entry res = self.testapp.get('/', status=200) form = self._fill_form_valid_natural(res.form) res = form.submit(u'submit', status=302) res = res.follow() self.assertTrue('information below to be correct' in res.body) # success for 18th birthday res = self.testapp.get('/', status=200) form = self._fill_form_valid_natural(res.form) form['year'] = unicode(date.today().year - 18) form['month'] = unicode(date.today().month) form['day'] = unicode(date.today().day) res = form.submit(u'submit', status=302) res = res.follow() self.assertTrue('information below to be correct' in res.body) # failure on test one day before 18th birthday res = self.testapp.get('/', status=200) form = self._fill_form_valid_natural(res.form) form['year'] = unicode(date.today().year - 18) form['month'] = unicode(date.today().month) form['day'] = unicode(date.today().day + 1) res = form.submit(u'submit', status=200) self.assertTrue('underaged person is currently not' in res.body) # failure for statute not checked res = self.testapp.get('/', status=200) form = self._fill_form_valid_natural(res.form) form['got_dues_regulations'].value__set(False) res = form.submit(u'submit', status=200) # failure for dues regulations not checked res = self.testapp.get('/', status=200) form = self._fill_form_valid_natural(res.form) form['got_dues_regulations'].value__set(False) res = form.submit(u'submit', status=200) # teardown DBSession.close() DBSession.remove() testing.tearDown() def test_success_verify_email(self): """ test the success_verify_email view """ from c3smembership.views.afm import success_verify_email self.config.add_route('join', '/') # without submitting request = testing.DummyRequest() request.matchdict['email'] = '*****@*****.**' request.matchdict['code'] = '12345678' result = success_verify_email(request) self.assertEqual(request.session.peek_flash('message_above_login'), [u'Please enter your password.']) self.assertEqual(result['result_msg'], 'something went wrong.') self.assertEqual(result['firstname'], '') self.assertEqual(result['lastname'], '') self.assertEqual(result['post_url'], '/verify/[email protected]/12345678') self.assertEqual(result['namepart'], '') self.assertEqual(result['correct'], False)
class Test_1_UI(unittest.TestCase): config = os.path.join(dirname, 'test.ini') extra_environ = {} def setUp(self): app = loadapp('config:%s' % self.config, global_conf={'db':'sqlite://'}) self.app = TestApp(app, extra_environ=self.extra_environ) self.config = Configurator(autocommit=True) self.config.begin() def test_index(self): resp = self.app.get('/') def test_1_crud(self): # index resp = self.app.get('/admin') self.assertEqual(resp.status_int, 302) assert '/admin/' in resp.location, resp resp = self.app.get('/admin/') resp.mustcontain('/admin/Foo') resp = resp.click('Foo') ## Simple model # add page resp.mustcontain('/admin/Foo/new') resp = resp.click(linkid='new') resp.mustcontain('/admin/Foo"') form = resp.forms[0] form['Foo--bar'] = 'value' resp = form.submit() assert resp.headers['location'] == 'http://localhost/admin/Foo', resp # model index resp = resp.follow() resp.mustcontain('<td>value</td>') form = resp.forms[0] resp = form.submit() # edit page form = resp.forms[0] form['Foo-1-bar'] = 'new value' #form['_method'] = 'PUT' resp = form.submit() resp = resp.follow() # model index resp.mustcontain('<td>new value</td>') # delete resp = self.app.get('/admin/Foo') resp.mustcontain('<td>new value</td>') resp = resp.forms[1].submit() resp = resp.follow() assert 'new value' not in resp, resp def test_2_model(self): # index resp = self.app.get('/foo') self.assertEqual(resp.status_int, 302) assert '/' in resp.location, resp ## Simple model resp = self.app.get('/foo/') # add page resp.mustcontain('/foo/new') resp = resp.click(linkid='new') resp.mustcontain('/foo') form = resp.forms[0] form['Foo--bar'] = 'value' resp = form.submit() assert resp.headers['location'] == 'http://localhost/foo/', resp # model index resp = resp.follow() resp.mustcontain('<td>value</td>') form = resp.forms[0] resp = form.submit() # edit page form = resp.forms[0] form['Foo-1-bar'] = 'new value' #form['_method'] = 'PUT' resp = form.submit() resp = resp.follow() # model index resp.mustcontain('<td>new value</td>') # delete resp = self.app.get('/foo/') resp.mustcontain('<td>new value</td>') resp = resp.forms[1].submit() resp = resp.follow() assert 'new value' not in resp, resp def test_3_json(self): # index response = self.app.get('/admin/json') response.mustcontain('{"models": {', '"Foo": "http://localhost/admin/Foo/json"') ## Simple model # add page response = self.app.post('/admin/Foo/json', {'bar': 'value'}) data = response.json id = data['absolute_url'].split('/')[-1] response.mustcontain('"bar": "value"') # get data response = self.app.get(str(data['absolute_url'])) response.mustcontain('"bar": "value"') # edit page response = self.app.post(str(data['absolute_url']), {'bar': 'new value'}) response.mustcontain('"bar": "new value"') # delete response = self.app.delete(str(data['absolute_url'])) self.assert_(response.json['id'] > 0) def test_4_json_prefix(self): # index response = self.app.get('/admin/json') response.mustcontain('{"models": {', '"Foo": "http://localhost/admin/Foo/json"') ## Simple model # add page response = self.app.post('/admin/Foo/json?with_prefix=True', {'Foo--bar': 'value', 'with_prefix': 'true'}) data = response.json id = data['absolute_url'].split('/')[-1] response.mustcontain('"Foo-%s-bar": "value"' % id) # get data response = self.app.get(str(data['absolute_url'])+'?with_prefix=True') response.mustcontain('"Foo-%s-bar": "value"' % id) # edit page response = self.app.post(str(data['absolute_url']+'?with_prefix=True'), {'Foo-%s-bar' % id: 'new value', 'with_prefix': 'true'}) response.mustcontain('"Foo-%s-bar": "new value"' % id) # delete response = self.app.delete(str(data['absolute_url']+'?with_prefix=True')) self.assert_(response.json['id'] > 0) def test_5_xhr(self): # add page resp = self.app.post('/admin/Foo/', {'Foo--bar':'value'}, extra_environ={'HTTP_X_REQUESTED_WITH':'XMLHttpRequest'}) self.assertEqual(resp.content_type, 'text/plain') resp = self.app.post('/admin/Foo/1', {'Foo-1-bar':'value'}, extra_environ={'HTTP_X_REQUESTED_WITH':'XMLHttpRequest'}) self.assertEqual(resp.content_type, 'text/plain') # assume all are deleted response = self.app.delete('/admin/Foo/1', extra_environ={'HTTP_X_REQUESTED_WITH':'XMLHttpRequest'}) self.assertEqual(resp.content_type, 'text/plain')
def test_cache_manager(): app = TestApp(CacheMiddleware(cache_manager_app)) res = app.get('/') assert 'test_key is: test value' in res assert 'test_key cleared' in res
class AccountantsFunctionalTests(unittest.TestCase): """ these tests are functional tests to check functionality of the whole app (i.e. integration tests) they also serve to get coverage for 'main' """ def setUp(self): self.config = testing.setUp() self.config.include('pyramid_mailer.testing') try: DBSession.close() DBSession.remove() # print "closed and removed DBSession" except: pass # print "no session to close" # try: # os.remove('test_webtest_accountants.db') # #print "deleted old test database" # except: # pass # #print "never mind" # self.session = DBSession() my_settings = { # 'sqlalchemy.url': 'sqlite:///test_webtest_accountants.db', 'sqlalchemy.url': 'sqlite:///:memory:', 'available_languages': 'da de en es fr', 'c3smembership.dashboard_number': '30' } engine = engine_from_config(my_settings) DBSession.configure(bind=engine) Base.metadata.create_all(engine) self._insert_members() with transaction.manager: # a group for accountants/staff accountants_group = Group(name=u"staff") try: DBSession.add(accountants_group) DBSession.flush() # print("adding group staff") except: print("could not add group staff.") # pass # staff personnel staffer1 = C3sStaff( login=u"rut", password=u"berries", email=u"*****@*****.**", ) staffer1.groups = [accountants_group] try: DBSession.add(accountants_group) DBSession.add(staffer1) DBSession.flush() except: print("it borked! (rut)") # pass from c3smembership import main app = main({}, **my_settings) from webtest import TestApp self.testapp = TestApp(app) def tearDown(self): DBSession.close() DBSession.remove() # os.remove('test_webtest_accountants.db') testing.tearDown() def _insert_members(self): with transaction.manager: member1 = C3sMember( # german firstname=u'SomeFirstnäme', lastname=u'SomeLastnäme', email=u'*****@*****.**', address1=u"addr one", address2=u"addr two", postcode=u"12345", city=u"Footown Mäh", country=u"Foocountry", locale=u"DE", date_of_birth=date.today(), email_is_confirmed=False, email_confirm_code=u'ABCDEFGFOO', password=u'arandompassword', date_of_submission=date.today(), membership_type=u'normal', member_of_colsoc=True, name_of_colsoc=u"GEMA", num_shares=u'23', ) member2 = C3sMember( # german firstname=u'AAASomeFirstnäme', lastname=u'XXXSomeLastnäme', email=u'*****@*****.**', address1=u"addr one", address2=u"addr two", postcode=u"12345", city=u"Footown Mäh", country=u"Foocountry", locale=u"DE", date_of_birth=date.today(), email_is_confirmed=False, email_confirm_code=u'ABCDEFGBAR', password=u'arandompassword', date_of_submission=date.today(), membership_type=u'normal', member_of_colsoc=True, name_of_colsoc=u"GEMA", num_shares=u'23', ) member3 = C3sMember( # german firstname=u'BBBSomeFirstnäme', lastname=u'AAASomeLastnäme', email=u'*****@*****.**', address1=u"addr one", address2=u"addr two", postcode=u"12345", city=u"Footown Mäh", country=u"Foocountry", locale=u"DE", date_of_birth=date.today(), email_is_confirmed=False, email_confirm_code=u'ABCDEFGBAZ', password=u'arandompassword', date_of_submission=date.today(), membership_type=u'normal', member_of_colsoc=True, name_of_colsoc=u"GEMA", num_shares=u'23', ) DBSession.add(member1) DBSession.add(member2) DBSession.add(member3) DBSession.flush() def get_dashboard_page(self, page_number, sort_property, sort_direction, status): return self.testapp.get( '/dashboard?page-number={0}&sort-property={1}&sort-direction={2}'. format(page_number, sort_property, sort_direction), status=status, ) def test_login_and_dashboard(self): """ load the login form, dashboard, member detail """ # # login # res = self.testapp.get('/login', status=200) self.failUnless('login' in res.body) # try invalid user form = res.form form['login'] = '******' form['password'] = '******' res2 = form.submit('submit') self.failUnless('Please note: There were errors' in res2.body) # try valid user & invalid password form = res2.form form['login'] = '******' form['password'] = '******' res3 = form.submit('submit', status=200) # try valid user, valid password form = res2.form form['login'] = '******' form['password'] = '******' res3 = form.submit('submit', status=302) # # being logged in ... res4 = res3.follow() # print(res4.body) self.failUnless('Dashboard' in res4.body) # now that we are logged in, # the login view should redirect us to the dashboard res5 = self.testapp.get('/login', status=302) # so yes: that was a redirect res6 = res5.follow() # print(res4.body) self.failUnless('Dashboard' in res6.body) # choose number of applications shown res6a = self.testapp.get('/dashboard', status=200, extra_environ={ 'num_display': '30', }) self.failUnless('<h1>Dashboard' in res6a.body) res6a = self.get_dashboard_page(1, 'id', 'asc', 200) self.failUnless('<h1>Dashboard' in res6a.body) # invalid sorting property # expect redirect to valid sorting property res6b = self.get_dashboard_page(1, 'invalid', 'asc', 400) # invalid sorting direction # expect displaying of the default sort direction res6b = self.get_dashboard_page(1, 'id', 'invalid', 200) # invalid page number: string # expect displaying of the first page res6b = self.get_dashboard_page('invalid', 'id', 'asc', 200) self.failUnless('<p>Number of data sets:' in res6b.body) # change the number of items to show form = res6b.forms[0] form['page_size'] = "42" # post a number: OK resX = form.submit('submit', status=200) form = resX.forms[0] form['page_size'] = "mooo" # post a string: no good res7 = form.submit('submit', status=200) # member details # # now look at some members details with nonexistant id res7 = self.testapp.get('/detail/5000', status=302) res7a = res7.follow() self.failUnless('Dashboard' in res7a.body) # now look at some members details res7 = self.testapp.get('/detail/1', status=200) self.failUnless('Firstnäme' in res7.body) self.failUnless('Eingang bestätigen' in res7.body) self.failUnless('Zahlungseingang bestätigen' in res7.body) # if we are logged in and try to access the login page # we will be redirected to the dashboard straight away resL = self.testapp.get('/login', status=302) self.failUnless('302 Found' in resL.body) self.failUnless('http://localhost/dashboard' in resL.location) # finally log out ################################################## res9 = self.testapp.get('/logout', status=302) # redirects to login res10 = res9.follow() self.failUnless('login' in res10.body) def test_switch_signature_and_payment(self): # login res = self.testapp.get('/login', status=200) form = res.form form['login'] = '******' form['password'] = '******' res2 = form.submit('submit', status=302) # being logged in ... res3 = res2.follow() # have a set of headers with and without 'dashboard' in http referrer headers_dash = [('Referer', 'http://this.app/dashboard')] headers_nodash = [('Referer', 'http://this.app/dashboard')] # switch signature resD2a = self.testapp.get('/switch_sig/1', status=302, headers=headers_dash) # # # # # OFF resD2b = resD2a.follow() # we are taken to the dashboard resD2b = self.testapp.get('/detail/1', status=200) # print resD2b.body self.assertTrue("Eingang bestätigen" not in resD2b.body) resD2a = self.testapp.get('/switch_sig/1', status=302, headers=headers_nodash) # # # # # ON resD2b = resD2a.follow() # we are taken to the dashboard resD2b = self.testapp.get('/detail/1', status=200) self.assertTrue("Eingang bestätigen" in resD2b.body) # # switch payment resD3a = self.testapp.get('/switch_pay/1', status=302, headers=headers_dash) # # # # OFF resD3b = resD3a.follow() # we are taken to the dashboard resD3b = self.testapp.get('/detail/1', status=200) self.assertTrue("Zahlungseingang bestätigen" not in resD3b.body) resD3a = self.testapp.get('/switch_pay/1', status=302, headers=headers_dash) # # # # ON resD3b = resD3a.follow() # we are taken to the dashboard resD3b = self.testapp.get('/detail/1', status=200) self.assertTrue("Zahlungseingang bestätigen" in resD3b.body) # #################################################################### # delete an entry _num = C3sMember.get_number() resDel2 = self.testapp.get('/delete/1?deletion_confirmed=1', status=302) _num2 = C3sMember.get_number() self.assertTrue(int(_num2) + 1 == int(_num)) resDel3 = resDel2.follow() self.failUnless('was deleted' in resDel3.body) # finally log out ################################################## res9 = self.testapp.get('/logout', status=302) # redirects to login res10 = res9.follow() self.failUnless('login' in res10.body) def test_dashboard_orderByIdAsc_dashboardOrdered(self): res2 = self._login() res2 = self.get_dashboard_page(1, 'id', 'asc', 200) pq = self._get_pyquery(res2.body) # column-order: id code firstname lastname first_member_row = pq('tr:nth-child(2)') id_ = first_member_row('td:nth-child(1)') self.assertEqual('1', id_.text()) def test_dashboard_orderByIdDesc_dashboardOrdered(self): res2 = self._login() res2 = self.get_dashboard_page(1, 'id', 'desc', 200) pq = self._get_pyquery(res2.body) first_member_row = pq('tr:nth-child(2)') id_ = first_member_row('td:nth-child(1)') self.assertEqual('3', id_.text()) def test_dashboard_orderByFirstnameAsc_dashboardOrdered(self): res2 = self._login() res2 = self.get_dashboard_page(1, 'firstname', 'asc', 200) # print res2.body pq = self._get_pyquery(res2.body) first_member_row = pq('tr:nth-child(2)') # print "the first row: {}".format(first_member_row) first_name = first_member_row('td:nth-child(3)') # print "the first name: {}".format(first_name) self.assertEqual(u'AAASomeFirstnäme', first_name.text()) def test_dashboard_orderByFirstnameDesc_dashboardOrdered(self): res2 = self._login() res2 = self.get_dashboard_page(1, 'firstname', 'desc', 200) pq = self._get_pyquery(res2.body) first_member_row = pq('tr:nth-child(2)') first_name = first_member_row('td:nth-child(3)') self.assertEqual(u'SomeFirstnäme', first_name.text()) def test_dashboard_orderByLastnameAsc_dashboardOrdered(self): res2 = self._login() res2 = self.get_dashboard_page(1, 'lastname', 'asc', 200) pq = self._get_pyquery(res2.body) first_member_row = pq('tr:nth-child(2)') last_name = first_member_row('td:nth-child(4)') self.assertEqual(u'AAASomeLastnäme', last_name.text()) def test_dashboard_orderByLastnameDesc_dashboardOrdered(self): self._login() res2 = self.get_dashboard_page(1, 'lastname', 'desc', 200) pq = self._get_pyquery(res2.body) first_member_row = pq('tr:nth-child(2)') last_name = first_member_row('td:nth-child(4)') self.assertEqual(u'XXXSomeLastnäme', last_name.text()) def test_dashboard_afterDelete_sameOrderAsBefore(self): self._login() self.get_dashboard_page(1, 'lastname', 'asc', 200) # To set cookie with order & orderby # Delete member with lastname AAASomeLastnäme resdel = self.testapp.get('/delete/3?deletion_confirmed=1') resdel = resdel.follow() pq = self._get_pyquery(resdel.body) first_member_row = pq('tr:nth-child(2)') last_name = first_member_row('td:nth-child(4)') self.assertEqual(u'SomeLastnäme', last_name.text()) def test_dashboard_afterDelete_messageShown(self): self._login() resdel = self.testapp.get('/delete/1?deletion_confirmed=1') resdel = resdel.follow() pq = self._get_pyquery(resdel.body) message = pq('#message').text() self.assertTrue('was deleted' in message) def test_dashboard_onFirstPage_noPreviousLinkShown(self): self._login() self._change_num_to_show("1") res = self.get_dashboard_page(1, 'id', 'desc', 200) pq = self._get_pyquery(res.body) self.assertEqual(len(pq("#navigate_previous")), 0) def test_dashboard_onFirstPage_nextLinkShown(self): self._login() self._change_num_to_show("1") res = self.get_dashboard_page(1, 'id', 'desc', 200) pq = self._get_pyquery(res.body) self.assertEqual(len(pq("#navigate_next")), 1) def test_dashboard_onSomePage_nextPreviousLinkShown(self): self._login() self._change_num_to_show("1") res = self.get_dashboard_page(2, 'id', 'desc', 200) pq = self._get_pyquery(res.body) self.assertEqual(len(pq("#navigate_next")), 1) self.assertEqual(len(pq("#navigate_previous")), 1) def test_dashboard_onLastPage_previousLinkShown(self): self._login() self._change_num_to_show("1") res = self.get_dashboard_page(3, 'id', 'desc', 200) pq = self._get_pyquery(res.body) self.assertEqual(len(pq("#navigate_previous")), 1) def test_dashboard_onLastPage_noNextLinkShown(self): self._login() self._change_num_to_show("1") res = self.get_dashboard_page(3, 'id', 'desc', 200) pq = self._get_pyquery(res.body) self.assertEqual(len(pq("#navigate_next")), 0) def _get_pyquery(self, html): from pyquery import PyQuery as pq pure_html = ''.join(html.split('\n')[2:]) pure_html = "<html>" + pure_html d = pq(pure_html) return d def _login(self): res = self.testapp.get('/login', status=200) self.failUnless('login' in res.body) # try valid user, valid password form = res.form form['login'] = '******' form['password'] = '******' res2 = form.submit('submit', status=302) # # being logged in ... res3 = res2.follow() self.failUnless('Dashboard' in res3.body) return res3 def _change_num_to_show(self, num_to_show="1"): res = self.get_dashboard_page(1, 'id', 'desc', 200) form = res.forms[0] form['page_size'] = num_to_show resX = form.submit('submit', status=200) return resX def test_search_code(self): """ load the search page and search for confirmation code """ # # login # res3 = self._login() res3 = self.testapp.get('/search_codes', status=200) """ we fill the confirmation code search form with a valid code, submit the form and check results """ # try invalid code form = res3.forms[0] form['code_to_show'] = 'foo' res = form.submit() self.failUnless('Search for members' in res.body) self.failUnless('Code finden' in res.body) # now use existing code form = res.forms[0] # print form.fields form['code_to_show'] = 'ABCDEFGBAZ' # print form['code_to_show'].value res2 = form.submit() # print res2.body res = res2.follow() self.failUnless('Details for Member Application' in res.body) self.failUnless('ABCDEFGBAZ' in res.body) def test_search_people(self): """ load the search page and search for people """ # # login # res3 = self._login() res3 = self.testapp.get('/search_people', status=200) """ we fill the confirmation code search form with a valid code, submit the form and check results """ # try invalid code form = res3.forms[0] form['code_to_show'] = 'foo' res = form.submit() self.failUnless('Search for members' in res.body) self.failUnless('Personen finden' in res.body) # now use existing code form = res.forms[0] # print form.fields form['code_to_show'] = u'XXXSomeLastnäme' # print form['code_to_show'].value res = form.submit() # print res.body # res = res2.follow() # self.failUnless('Details for Member Application' in res.body) # self.failUnless('ABCDEFGBAZ' in res.body) # XXX FIXME def test_dashboard_regenerate_pdf(self): """ load the dashboard and regenerate a PDF """ # # login # res = self.testapp.get('/login', status=200) self.failUnless('login' in res.body) # try valid user, valid password form = res.form form['login'] = '******' form['password'] = '******' res2 = form.submit('submit', status=302) # # being logged in ... res3 = res2.follow() self.failUnless('Dashboard' in res3.body) """ try to load a users PDF check size """ # try invalid code pdf = self.testapp.get('/re_C3S_SCE_AFM_WRONGCODE.pdf') self.failUnless('The resource was found at' in pdf.body) pdf = self.testapp.get('/re_C3S_SCE_AFM_ABCDEFGFOO.pdf') # now use existing code self.failUnless(80000 < len(pdf.body) < 220000) # check pdf size
class TestDapServer(unittest.TestCase): """Tests for the pydap server.""" def setUp(self): """Create an installation.""" self.install = tempfile.mkdtemp(suffix="pydap") # create directory for data with two files data = os.path.join(self.install, "data") os.mkdir(data) os.mkdir(os.path.join(data, "subdir")) with open(os.path.join(data, "README.txt"), "w") as fp: fp.write("Hello, world!") with open(os.path.join(data, "data.foo"), "w") as fp: pass # create templates directory templates = os.path.join(self.install, "templates") init(templates) app = DapServer(data, templates) app.handlers = [DummyHandler] app = StaticMiddleware(app, os.path.join(templates, "static")) self.app = App(app) def tearDown(self): """Remove the installation.""" shutil.rmtree(self.install) def test_app_root(self): """Test a regular request.""" res = self.app.get("/") self.assertEqual(res.status, "200 OK") def test_app_hack(self): """Test a request to a resource that is outside the root dir.""" with self.assertRaises(AppError): self.app.get("/../../../../../../../etc/passwd") def test_app_file(self): """Test that we can download a file.""" res = self.app.get("/README.txt") self.assertEqual(res.text, "Hello, world!") def test_dap_request(self): """Test that DAP requests work.""" res = self.app.get("/data.foo.dds") self.assertEqual(res.text, "Success!") def test_invalid_dap_request(self): """Test invalid DAP requests.""" with self.assertRaises(ExtensionNotSupportedError): self.app.get("/README.txt.dds") def test_thredds_catalog_request(self): """Test that THREDDS Catalog requests work.""" res = self.app.get("/catalog.xml") self.assertEqual(res.status, "200 OK") self.assertTrue(res.text.startswith('<?xml')) xml = etree.fromstring(res.text) self.assertEqual( xml.tag, '{http://www.unidata.ucar.edu/namespaces/thredds/InvCatalog/v1.0}catalog' ) # noqa def test_not_found(self): """Test 404 responses.""" with self.assertRaises(AppError): self.app.get("/README.html") def test_asset(self): """Test that we can load a static asset.""" res = self.app.get("/static/style.css") self.assertEqual(res.status, "200 OK")
class TestService(TestCase): def setUp(self): self.config = testing.setUp( settings={'pyramid.debug_authorization': True}) # Set up debug_authorization logging to console logging.basicConfig(level=logging.DEBUG) debug_logger = logging.getLogger() self.config.registry.registerUtility(debug_logger, IDebugLogger) self.config.include("cornice") self.authz_policy = ACLAuthorizationPolicy() self.config.set_authorization_policy(self.authz_policy) self.authn_policy = AuthTktAuthenticationPolicy('$3kr1t') self.config.set_authentication_policy(self.authn_policy) self.config.scan("tests.test_service") self.config.scan("tests.test_pyramidhook") self.app = TestApp(CatchErrors(self.config.make_wsgi_app())) register_service_views(self.config, service) def tearDown(self): testing.tearDown() def test_404(self): # a get on a resource that explicitly return a 404 should return 404 self.app.get("/service", status=HTTPNotFound.code) def test_405(self): # calling a unknown verb on an existing resource should return a 405 self.app.post("/service", status=HTTPMethodNotAllowed.code) def test_204(self): resp = self.app.delete("/service", status=204) self.assertNotIn("Content-Type", resp.headers) def test_acl_support_unauthenticated_service_patch(self): # calling a view with permissions without an auth'd user => 403 self.app.patch('/service', status=HTTPForbidden.code) def test_acl_support_authenticated_allowed_service_patch(self): with mock.patch.object(self.authn_policy, 'unauthenticated_userid', return_value='bob'): result = self.app.patch('/service', status=HTTPOk.code) self.assertEqual("yay", result.json) # The other user with 'write' permission with mock.patch.object(self.authn_policy, 'unauthenticated_userid', return_value='dan'): result = self.app.patch('/service', status=HTTPOk.code) self.assertEqual("yay", result.json) def test_acl_support_authenticated_valid_user_wrong_permission_service_patch( self): with mock.patch.object(self.authn_policy, 'unauthenticated_userid', return_value='alice'): self.app.patch('/service', status=HTTPForbidden.code) def test_acl_support_authenticated_valid_user_permission_denied_service_patch( self): with mock.patch.object(self.authn_policy, 'unauthenticated_userid', return_value='carol'): self.app.patch('/service', status=HTTPForbidden.code) def test_acl_support_authenticated_invalid_user_service_patch(self): with mock.patch.object(self.authn_policy, 'unauthenticated_userid', return_value='mallory'): self.app.patch('/service', status=HTTPForbidden.code) def test_acl_support_authenticated_allowed_service_put(self): with mock.patch.object(self.authn_policy, 'unauthenticated_userid', return_value='dan'): result = self.app.put('/service', status=HTTPOk.code) self.assertEqual("updated_view", result.json) def test_acl_support_authenticated_valid_user_wrong_permission_service_put( self): with mock.patch.object(self.authn_policy, 'unauthenticated_userid', return_value='bob'): self.app.put('/service', status=HTTPForbidden.code) def test_acl_support_authenticated_valid_user_permission_denied_service_put( self): with mock.patch.object(self.authn_policy, 'unauthenticated_userid', return_value='carol'): self.app.put('/service', status=HTTPForbidden.code) def test_acl_support_authenticated_invalid_user_service_put(self): with mock.patch.object(self.authn_policy, 'unauthenticated_userid', return_value='mallory'): self.app.put('/service', status=HTTPForbidden.code) def test_class_support(self): self.app.get('/fresh-air', status=400) resp = self.app.get('/fresh-air', headers={'X-Temperature': '50'}) self.assertEqual(resp.body, b'fresh air with context!')
class Browser(BasicBrowser): """A Browser that can be used to test a WSGI application in the current thread, without the need for a separate web server. This class implements methods matching the actions a user would perform using a browser. :param wsgi_app: The application instance under test. """ def __init__(self, wsgi_app): self.testapp = TestApp(wsgi_app) self.last_response = None self.history = [] def open(self, url_string, follow_redirects=True, **kwargs): """GETs the URL in `url_string`. :param url_string: A string containing the URL to be opened. :keyword follow_redirects: If False, this method acts as a simple GET request. If True (the default), the method hebaves like a browser would, by opening redirect responses. :keyword relative: Set to True to indicate that `url_string` contains a path relative to the current location. Other keyword arguments are passed directly on to `WebTest.get <http://webtest.readthedocs.org/en/latest/api.html#webtest.app.TestApp.get>`_. """ if self.last_response: self.history.append(self.last_response.request.url) relative = not url_string.startswith('/') if relative: url_string = self.get_full_path(url_string) self.last_response = self.testapp.get(url_string, **kwargs) if follow_redirects: self.follow_response() def go_back(self): """GETs the previous location (like the back button on a browser). """ previous = self.history.pop() self.open(previous) def refresh(self): """GETs the current location again (like the refresh button on a browser). """ self.open(self.last_request.url) def follow_response(self): """Assuming the last response received was a redirect, follows that response (and other redirect responses that may be received in the process until a response is received which is not a redirect. """ counter = 0 while self.status >= 300 and self.status < 400: self.last_response = self.last_response.follow() counter += 1 assert counter <= 10, 'HTTP Redirect loop detected.' def post(self, url_string, form_values, **kwargs): """POSTs the given form values to the url given. :param url_string: A string containing the URL to be posted to. :param form_values: A dictionary containing form data in its key/value pairs. Other keyword arguments are passed directly on to `WebTest.post <http://webtest.readthedocs.org/en/latest/api.html#webtest.app.TestApp.post>`_. """ self.last_response = self.testapp.post( (ascii_as_bytes_or_str(url_string)), form_values, **kwargs) def relative(self, url_string): url_bits = urllib_parse.urlparse(url_string) return urllib_parse.urlunparse(('', '', url_bits.path, url_bits.params, url_bits.query, url_bits.fragment)) @property def raw_html(self): """Returns the HTML for the current location unchanged.""" return self.last_response.body.decode('utf-8') @property def status(self): """Returns the HTTP status code for the last response.""" return int(self.last_response.status.split(' ')[0]) @property def title(self): """Returns the title of the current location.""" titles = self.xpath('/html/head/title') assert len(titles) > 0, 'Error: no title element found' return titles[0].text @property def last_request(self): """Returns the last request.""" return self.last_response.request @property def location_path(self): """Returns the current location url path.""" return self.last_response.request.path @property def location_scheme(self): """Returns the the last request scheme(HTTP/HTTPS).""" return self.last_response.request.scheme @property def location_query_string(self): """Returns the current query string.""" return self.last_response.request.query_string def get_form_for(self, locator): """Return the form for the given `locator`. :param locator: An instance of :class:`XPath` or a string containing an XPath expression. """ xpath = six.text_type(locator) form_id = self.xpath('%s[@form]' % xpath)[0].attrib['form'] form_element = self.xpath('//form[@id=\'%s\']' % form_id)[0] patch_Field() return self.last_response.forms[form_element.attrib['id']] def type(self, locator, text): """Types the text in `text` into the input found by the `locator`. :param locator: An instance of :class:`XPath` or a string containing an XPath expression. :param text: The text to be typed. """ xpath = six.text_type(locator) inputs = self.xpath(xpath) assert len(inputs) == 1 form = self.get_form_for(xpath) form.fields[inputs[0].name][0].value = text def click(self, locator, **kwargs): """Clicks on the element found by `locator`. :param locator: An instance of :class:`XPath` or a string containing an XPath expression. Other keyword arguments are passed directly on to `Form.submit <http://webtest.readthedocs.org/en/latest/api.html#webtest.forms.Form.submit>`_. """ xpath = six.text_type(locator) buttons = self.xpath(xpath) assert len( buttons ) == 1, 'Could not find one (and only one) button for %s' % locator button = buttons[0] if button.tag == 'input' and button.attrib['type'] == 'submit': button_name = self.xpath(xpath)[0].name form = self.get_form_for(xpath) form.action = ascii_as_bytes_or_str(self.relative(form.action)) self.last_response = form.submit(button_name, **kwargs) self.follow_response() elif button.tag == 'a': self.open(button.attrib['href'], **kwargs) elif button.tag == 'input' and button.type == 'checkbox': form = self.get_form_for(xpath) [checkbox] = form.fields[button.name] checkbox.value = 'on' if not checkbox.value else None else: raise AssertionError( 'This browser can only click on buttons, a elements, or checkboxes' ) def select(self, locator, label_to_choose): """Finds the select element indicated by `locator` and selects one of its options. :param locator: An instance of :class:`XPath` or a string containing an XPath expression. :param label_to_choose: The label of the option that should be selected. """ xpath = six.text_type(locator) select = self.xpath(xpath) assert len( select ) == 1, 'Could not find one (and only one) element for %s' % locator select = select[0] assert select.tag == 'select', 'Expected %s to find a select tag' % locator form = self.get_form_for(xpath) for option in select.findall('option'): if option.text == label_to_choose: form[select.attrib['name']] = list(option.values())[0] return raise AssertionError('Option %s not found' % label_to_choose) def get_value(self, locator): """Returns the value of the input indicated by `locator`. :param locator: An instance of :class:`XPath` or a string containing an XPath expression. """ xpath = six.text_type(locator) inputs = self.xpath(xpath) assert len(inputs) == 1 form = self.get_form_for(xpath) return form.fields[inputs[0].name][0].value def get_full_path(self, relative_path): return urllib_parse.urljoin(self.location_path, relative_path) def is_image_shown(self, locator): """Answers whether the located image is available from the server (ie, whether the src attribute of an img element is accessible). :param locator: An instance of :class:`XPath` or a string containing an XPath expression. """ xpath = six.text_type(locator) try: img_src = self.lxml_html.xpath(xpath)[0].attrib['src'] self.open(img_src) self.go_back() except: return False return True def create_cookie(self, cookie_dict): """Creates a cookie from the given `cookie_dict`. :param cookie_dict: A dictionary with two keys: 'name' and 'value'. The values of these\ keys are the name of the cookie and its value, respectively. The keys 'path', 'domain', 'secure', 'expiry' can also be set to values.\ These have the respective meanings as defined in `RFC6265 <http://tools.ietf.org/html/rfc6265#section-5.2>` """ name = ascii_as_bytes_or_str(cookie_dict['name']) value = ascii_as_bytes_or_str(cookie_dict['value']) path = ascii_as_bytes_or_str(cookie_dict.get('path', '')) path_set = path != '' domain = ascii_as_bytes_or_str(cookie_dict.get('domain', '')) domain_set = domain != '' secure = cookie_dict.get('secure', False) expires = cookie_dict.get('expiry', None) cookie = Cookie(0, name, value, None, False, domain, domain_set, None, path, path_set, secure, expires, None, None, None, None) self.testapp.cookiejar.set_cookie(cookie) def is_element_enabled(self, locator): """Answers whether the located element is reactive to user commands or not. For <a> elements, this means that they have an href attribute, for inputs it means that they are not disabled. :param locator: An instance of :class:`XPath` or a string containing an XPath expression. """ xpath = six.text_type(locator) [element] = self.xpath(xpath) if element.tag == 'a': return 'href' in element.attrib if element.tag == 'input': return 'disabled' not in element.attrib assert None, 'Not yet implemented'
def test_view_home(swissvotes_app): client = Client(swissvotes_app) home = client.get('/').maybe_follow() assert "<h2>home</h2>" in home assert home.request.url.endswith('page/home')
class DwarfTestCase(utils.TestCase): def setUp(self): super(DwarfTestCase, self).setUp() self.app = TestApp(ApiServer().app) # Commented out to silence pylint # def tearDown(self): # super(DwarfTestCase, self).tearDown() def test_list_versions(self): resp = self.app.get('/image', status=300) self.assertEqual(json.loads(resp.body), list_versions_resp()) def test_list_images(self): # Preload test images self.create_image(image1) self.create_image(image2) resp = self.app.get('/image/v2/images', status=200) self.assertEqual(json.loads(resp.body), list_images_resp([image1, image2])) def test_show_image(self): # Preload a test image self.create_image(image1) resp = self.app.get('/image/v2/images/%s' % image1['id'], status=200) self.assertEqual(json.loads(resp.body), show_image_resp(image1)) def test_delete_image(self): # Preload a test image self.create_image(image1) resp = self.app.delete('/image/v2/images/%s' % image1['id'], status=204) self.assertEqual(resp.body, '') self.assertEqual(os.path.exists('/tmp/dwarf/images/%s' % image1['id']), False) resp = self.app.get('/image/v2/images', status=200) self.assertEqual(json.loads(resp.body), list_images_resp([])) def test_update_image(self): # Preload a test image self.create_image(image1) key = 'name' val = 'Patched test image 1' resp = self.app.patch('/image/v2/images/%s' % image1['id'], params=json.dumps([{'op': 'replace', 'path': '/' + key, 'value': val}]), status=200) patched = deepcopy(image1) patched[key] = val self.assertEqual(json.loads(resp.body), update_image_resp(patched)) def test_create_image(self): # Create the image in the database resp = self.app.post('/image/v2/images', params=json.dumps(create_image_req(image1)), status=201) self.assertEqual(json.loads(resp.body), create_image_resp(image1)) # Upload the image data resp = self.app.put('/image/v2/images/%s/file' % image1['id'], params=image1['data'], status=204) with open('/tmp/dwarf/images/%s' % image1['id'], 'r') as fh: self.assertEqual(fh.read(), image1['data']) # ------------------------------------------------------------------------- # Additional tests for code coverage def test_delete_image_cc(self): # Preload a test image self.create_image(image1) os.unlink(image1['file']) resp = self.app.delete('/image/v2/images/%s' % image1['id'], status=204) self.assertEqual(resp.body, '')
class APIV2ZoneImportExportTest(ApiV2TestCase): def setUp(self): super(APIV2ZoneImportExportTest, self).setUp() self.config(enable_api_admin=True, group='service:api') self.config(enabled_extensions_admin=['zones'], group='service:api') # Create the application adminapp = admin_api.factory({}) # Inject the NormalizeURIMiddleware middleware adminapp = middleware.NormalizeURIMiddleware(adminapp) # Inject the FaultWrapper middleware adminapp = middleware.FaultWrapperMiddleware(adminapp) # Inject the TestContext middleware adminapp = middleware.TestContextMiddleware(adminapp, self.admin_context.tenant, self.admin_context.tenant) # Obtain a test client self.adminclient = TestApp(adminapp) # # Zone import/export def test_missing_origin(self): fixture = self.get_zonefile_fixture(variant='noorigin') response = self.client.post_json('/zones/tasks/imports', fixture, headers={'Content-type': 'text/dns'}) import_id = response.json_body['id'] self.wait_for_import(import_id, errorok=True) url = '/zones/tasks/imports/%s' % import_id response = self.client.get(url) self.assertEqual(response.json['status'], 'ERROR') origin_msg = ("The $ORIGIN statement is required and must be the" " first statement in the zonefile.") self.assertEqual(response.json['message'], origin_msg) def test_missing_soa(self): fixture = self.get_zonefile_fixture(variant='nosoa') response = self.client.post_json('/zones/tasks/imports', fixture, headers={'Content-type': 'text/dns'}) import_id = response.json_body['id'] self.wait_for_import(import_id, errorok=True) url = '/zones/tasks/imports/%s' % import_id response = self.client.get(url) self.assertEqual(response.json['status'], 'ERROR') origin_msg = ("Malformed zonefile.") self.assertEqual(response.json['message'], origin_msg) def test_malformed_zonefile(self): fixture = self.get_zonefile_fixture(variant='malformed') response = self.client.post_json('/zones/tasks/imports', fixture, headers={'Content-type': 'text/dns'}) import_id = response.json_body['id'] self.wait_for_import(import_id, errorok=True) url = '/zones/tasks/imports/%s' % import_id response = self.client.get(url) self.assertEqual(response.json['status'], 'ERROR') origin_msg = ("Malformed zonefile.") self.assertEqual(response.json['message'], origin_msg) def test_import_export(self): # Since v2 doesn't support getting records, import and export the # fixture, making sure they're the same according to dnspython post_response = self.client.post('/zones/tasks/imports', self.get_zonefile_fixture(), headers={'Content-type': 'text/dns'}) import_id = post_response.json_body['id'] self.wait_for_import(import_id) url = '/zones/tasks/imports/%s' % import_id response = self.client.get(url) self.policy({'zone_export': '@'}) get_response = self.adminclient.get('/zones/export/%s' % response.json['zone_id'], headers={'Accept': 'text/dns'}) if six.PY2: exported_zonefile = get_response.body else: exported_zonefile = get_response.body.decode('utf-8') imported = dnszone.from_text(self.get_zonefile_fixture()) exported = dnszone.from_text(exported_zonefile) # Compare SOA emails, since zone comparison takes care of origin imported_soa = imported.get_rdataset(imported.origin, 'SOA') imported_email = imported_soa[0].rname.to_text() exported_soa = exported.get_rdataset(exported.origin, 'SOA') exported_email = exported_soa[0].rname.to_text() self.assertEqual(imported_email, exported_email) # Delete SOAs since they have, at the very least, different serials, # and dnspython considers that to be not equal. imported.delete_rdataset(imported.origin, 'SOA') exported.delete_rdataset(exported.origin, 'SOA') # Delete NS records, since they won't be the same imported.delete_rdataset(imported.origin, 'NS') exported.delete_rdataset(exported.origin, 'NS') imported.delete_rdataset('delegation', 'NS') self.assertEqual(imported, exported)
class TestHosts(unittest2.TestCase): def setUp(self): # Test application self.app = TestApp(alignak_webui.app.session_app) print('login accepted - go to home page') self.login_response = self.app.post('/login', { 'username': '******', 'password': '******' }) # A session cookie exist assert self.app.cookies['Alignak-WebUI'] for cookie in self.app.cookiejar: if cookie.name == 'Alignak-WebUI': assert cookie.expires is None # A session exists and it contains: current user, his realm and his live synthesis self.session = self.login_response.request.environ['beaker.session'] assert 'current_user' in self.session and self.session['current_user'] assert self.session['current_user'].name == 'admin' assert 'current_realm' in self.session and self.session['current_realm'] assert self.session['current_realm'].name == 'All' # assert 'current_ls' in self.session and self.session['current_ls'] # edition_mode is defined but not activated in the session... assert 'edition_mode' in self.session assert False == self.session['edition_mode'] def tearDown(self): print('logout') self.app.get('/logout') def test_hosts_templates_table(self): """View hosts templates page in edition mode""" print('get page /hosts/templates (edition mode)') response = self.app.get('/hosts/templates') response.mustcontain( '<div id="hosts-templates">', '<form role="form" data-element="None" class="element_form" method="post" action="/host_form/None">', '<legend>Creating a new host:</legend>', '<input class="form-control" type="text" id="name" name="name" placeholder="Host name" value="">', '<input class="form-control" type="text" id="alias" alias="alias" placeholder="Host alias" value="">', '<input class="form-control" type="text" id="address" name="address" placeholder="0.0.0.0" value="">', '<input class="form-control" type="text" id="realm" realm="realm" placeholder="Host realm" value="">', '<input type="checkbox" id="_is_template" name="_is_template">', '<input id="_dummy" name="_dummy" type="checkbox" data-id="58f7250c06fd4b31e230280a" data-linked="">', '<input id="generic-passive-host" name="generic-passive-host" type="checkbox" data-id="58f7250f06fd4b31e2302814" data-linked="">', '<input id="windows-passive-host" name="windows-passive-host" type="checkbox" data-id="58f7250f06fd4b31e2302815" data-linked="generic-passive-host">' ) def test_hosts_templates_table(self): """View hosts templates table in edition mode""" print('get page /hosts/templates/table (normal mode)') response = self.app.get('/hosts/templates/table') response.mustcontain( '<div id="hosts_templates_table" class="alignak_webui_table ">', "$('#tbl_hosts_templates_table').DataTable( {", # Because of a templates table 'titleAttr: "Navigate to the hosts table"', # Because of edition mode... no=[ '''titleAttr: "Create a new item"''', '''var url = "/host_form/None";''', ]) print('Enable edition mode') response = self.app.post('/edition_mode', params={'state': 'on'}) session = response.request.environ['beaker.session'] # edition_mode is defined and activated in the session... assert 'edition_mode' in session assert True == session['edition_mode'] assert response.json == { 'edition_mode': True, 'message': 'Edition mode enabled' } print('get page /hosts/templates/table (edition mode)') response = self.app.get('/hosts/templates/table') response.mustcontain( '<div id="hosts_templates_table" class="alignak_webui_table ">', "$('#tbl_hosts_templates_table').DataTable( {", # Because of a templates table 'titleAttr: "Navigate to the hosts table"', # Because of edition mode... '''titleAttr: "Create a new item"''', ) def test_hosts_table(self): """View hosts table in edition mode""" print('get page /hosts/table (normal mode)') response = self.app.get('/hosts/table') response.mustcontain( '<div id="hosts_table" class="alignak_webui_table ">', "$('#tbl_hosts_table').DataTable( {", '<table id="tbl_hosts_table" ', no=[ '''text: "<span class='fa fa-edit'></span>"''', '''titleAttr: "Edit the selected item"''', ]) print('Enable edition mode') response = self.app.post('/edition_mode', params={'state': 'on'}) session = response.request.environ['beaker.session'] # edition_mode is defined and activated in the session... assert 'edition_mode' in session assert True == session['edition_mode'] assert response.json == { 'edition_mode': True, 'message': 'Edition mode enabled' } print('get page /hosts/table (edition mode)') response = self.app.get('/hosts/table') response.mustcontain( '<div id="hosts_table" class="alignak_webui_table ">', "$('#tbl_hosts_table').DataTable( {", '<table id="tbl_hosts_table" ', '''text: "<span class='text-warning fa fa-edit'></span>"''', '''titleAttr: "Edit the selected item"''', ) def test_host_form(self): """View host edition form""" # Get host in the backend datamgr = DataManager(alignak_webui.app.app, session=self.session) host = datamgr.get_host({'where': {'name': 'alignak_glpi'}}) print('get page /host_form (reading mode)') response = self.app.get('/host_form/%s' % host.id) response.mustcontain( '''<div id="form_host">''', '''<form role="form" data-element="%s" class="element_form " >''' % host.id, no=[ '''$('form[data-element="%s"]').on("submit", function (evt) {''' % host.id ]) print('Enable edition mode') response = self.app.post('/edition_mode', params={'state': 'on'}) session = response.request.environ['beaker.session'] # edition_mode is defined and activated in the session... assert 'edition_mode' in session assert True == session['edition_mode'] assert response.json == { 'edition_mode': True, 'message': 'Edition mode enabled' } print('get page /host_form (edition mode) - with an host id') response = self.app.get('/host_form/%s' % host.id) response.mustcontain( '''<div id="form_host">''', '''<form role="form" data-element="%s" class="element_form " method="post" action="/host_form/%s">''' % (host.id, host.id), '''$('form[data-element="%s"]').on("submit", function (evt) {''' % host.id) print('get page /host_form (edition mode) - with an host name') response = self.app.get('/host_form/%s' % host.name) response.mustcontain( '''<div id="form_host">''', '''<form role="form" data-element="%s" class="element_form " method="post" action="/host_form/%s">''' % (host.id, host.id), '''$('form[data-element="%s"]').on("submit", function (evt) {''' % host.id) print('get page /host_form (edition mode) - for a new host') response = self.app.get('/host_form/unknown_host') response.mustcontain( '''<div id="form_host">''', '''<form role="form" data-element="None" class="element_form " method="post" action="/host_form/None">''', '''<h4>You are creating a new host.</h4>''', '''$('form[data-element="None"]').on("submit", function (evt) {''') def test_host_new_host(self): """Create a new host edition form""" datamgr = DataManager(alignak_webui.app.app, session=self.session) # Get realm in the backend realm = datamgr.get_realm({'where': {'name': 'All'}}) # Get host template in the backend template = datamgr.get_host( {'where': { 'name': 'generic-host', '_is_template': True }}) print('Enable edition mode') response = self.app.post('/edition_mode', params={'state': 'on'}) session = response.request.environ['beaker.session'] # edition_mode is defined and activated in the session... assert 'edition_mode' in session assert True == session['edition_mode'] assert response.json == { 'edition_mode': True, 'message': 'Edition mode enabled' } # Count hosts count = datamgr.count_objects('host') print("Host count: %s" % count) print('get page /host_form (edition mode) - for a new host') response = self.app.get('/host_form/unknown_host') response.mustcontain( '''<div id="form_host">''', '''<form role="form" data-element="None" class="element_form " method="post" action="/host_form/None">''', '''<h4>You are creating a new host.</h4>''', '''$('form[data-element="None"]').on("submit", function (evt) {''') # A name is enough to create a new host print('Host creation - missing name') data = { "_is_template": False, } response = self.app.post('/host_form/None', params=data) print(response.json) assert response.json == { '_is_template': False, '_message': 'host creation failed!', '_errors': [''] } # A name is enough to create a new host print('Host creation without template') data = { "_is_template": False, 'name': "New host", 'alias': "Friendly name" } response = self.app.post('/host_form/None', params=data) # Returns the new item _id new_host_id = response.json['_id'] resp = response.json resp.pop('_id') assert resp == { "_message": "New host created", "_realm": realm.id, "_is_template": False, "name": "New host", 'alias': "Friendly name" } # Count hosts (one more!) new_count = datamgr.count_objects('host') print("Host count: %s" % new_count) assert new_count == count + 1 # Get the new host in the backend host = datamgr.get_host({'where': {'name': 'New host'}}) assert host assert host.id == new_host_id assert host.name == "New host" assert host.alias == "Friendly name" print('Host creation with a template') data = { "_is_template": False, "_templates": [template.id], 'name': "New host 2", 'alias': "Friendly name 2" } response = self.app.post('/host_form/None', params=data) # Returns the new item _id new_host_id = response.json['_id'] resp = response.json resp.pop('_id') assert resp == { "_message": "New host created", "_realm": realm.id, "_is_template": False, "_templates": [template.id], "name": "New host 2", 'alias': "Friendly name 2" } # Count hosts (one more!) new_count = datamgr.count_objects('host') print("Host count: %s" % new_count) assert new_count == count + 2 # Get the new host in the backend host = datamgr.get_host({'where': {'name': 'New host 2'}}) assert host assert host.id == new_host_id assert host.name == "New host 2" assert host.alias == "Friendly name 2" def test_host_submit_form(self): """Edit and submit host edition form""" datamgr = DataManager(alignak_webui.app.app, session=self.session) # Get host and service in the backend host = datamgr.get_host({'where': {'name': 'alignak_glpi'}}) services = datamgr.get_host_services(host) service = services[0] print('Enable edition mode') response = self.app.post('/edition_mode', params={'state': 'on'}) session = response.request.environ['beaker.session'] # edition_mode is defined and activated in the session... assert 'edition_mode' in session assert True == session['edition_mode'] assert response.json == { 'edition_mode': True, 'message': 'Edition mode enabled' } print('get page /host_form (edition mode) - with an host id') response = self.app.get('/host_form/%s' % host.id) response.mustcontain( '''<div id="form_host">''', '''<form role="form" data-element="%s" class="element_form " method="post" action="/host_form/%s">''' % (host.id, host.id), '''$('form[data-element="%s"]').on("submit", function (evt) {''' % host.id) print('Post form updates') data = {'name': host.name, 'alias': "Alias edited"} response = self.app.post('/host_form/%s' % host.id, params=data) assert response.json == { "_message": "host 'alignak_glpi' updated", "alias": "Alias edited" } def test_host_delete(self): """Delete the newly created hosts""" datamgr = DataManager(alignak_webui.app.app, session=self.session) # Count hosts count = datamgr.count_objects('host') print("Host count: %s" % count) # Get host and service in the backend host = datamgr.get_host({'where': {'name': 'pi1'}}) assert datamgr.delete_object('service', host) is False assert datamgr.delete_object('host', host) is True # Count hosts (one less!) new_count = datamgr.count_objects('host') print("Host count: %s" % new_count) assert new_count == count - 1 # Get host and service in the backend host = datamgr.get_host({'where': {'name': 'pi2'}}) assert datamgr.delete_object('service', host) is False assert datamgr.delete_object('host', host) is True # Count hosts (one less!) new_count = datamgr.count_objects('host') print("Host count: %s" % new_count) assert new_count == count - 2
class AdminTest(unittest.TestCase): def setUp(self): app.config['TESTING'] = True app.config['SQLALCHEMY_DATABASE_URI'] = "sqlite:///{0}/test.db".format( base) self.app = TestApp(app) db.create_all() def tearDown(self): db.session.remove() db.drop_all() def create_people(self): people = [ Person(name="David"), Person(name="Claudia"), Person(name="Cesar"), Person(name="Tricia"), ] for person in people: db.session.add(person) db.session.commit() return people def create_events(self): people = self.create_people() events = [ Event(movie="The Matrix", date=date(2013, 4, 1), picker=people[0]), Event(movie="Fight Club", date=date(2013, 4, 8), picker=people[1]), Event(movie="Psycho", date=date(2013, 4, 15), picker=people[2]), Event(movie="Alien", date=date(2013, 4, 22), picker=people[0]), Event(movie="Yojimbo", date=date(2013, 4, 29), picker=people[1]), Event(movie="Goodfellas", date=date(2013, 5, 6), picker=people[2]), Event(movie="Toy Story", date=date(2013, 5, 13), picker=people[0]), ] for event in events: event.attendees = people[:3] db.session.commit() return events def test_create_event(self): self.create_people() home = self.app.get('/admin/') event_list = home.click("Event") create_event = event_list.click("Create") people_ids = [p.id for p in Person.query.all()] create_event.form['attendees'] = people_ids create_event.form['date'].value = "2013-04-01" create_event.form['movie'].value = "Leon" create_event.form['picker'] = people_ids[0] create_event.form.submit() events = Event.query.all() self.assertEqual(len(events), 1) self.assertItemsEqual([p.id for p in events[0].attendees], people_ids) self.assertEqual(unicode(events[0].date), '2013-04-01') self.assertEqual(events[0].movie, "Leon") self.assertEqual(events[0].picker.id, people_ids[0]) def test_create_person(self): home = self.app.get('/admin/') people_list = home.click("Person") create_person = people_list.click("Create") create_person.form['name'].value = "Janelle" create_person.form.submit() people = Person.query.all() self.assertEqual(len(people), 1) self.assertEqual(people[0].name, "Janelle") def test_event_list(self): self.create_events() home = self.app.get('/admin/') event_list = home.click("Event") self.assertIn("The Matrix", event_list) self.assertIn("2013-04-01", event_list) self.assertIn("Fight Club", event_list) self.assertIn("2013-04-08", event_list) def test_person_list(self): self.create_events() home = self.app.get('/admin/') people_list = home.click("Person") self.assertIn("David", people_list) self.assertIn("Claudia", people_list) self.assertIn("Cesar", people_list) self.assertIn("Tricia", people_list) self.assertIn("Toy Story, Alien, The Matrix", people_list) self.assertIn("Yojimbo, Fight Club", people_list) self.assertIn("Goodfellas, Psycho", people_list) self.assertIn("33", people_list) self.assertIn("-67", people_list) self.assertIn("N/A", people_list)
class TestEditionModeDenied(unittest2.TestCase): def setUp(self): # Test application self.app = TestApp(alignak_webui.app.session_app) print('login accepted - go to home page') self.login_response = self.app.post('/login', { 'username': '******', 'password': '******' }) # A session cookie exist assert self.app.cookies['Alignak-WebUI'] for cookie in self.app.cookiejar: if cookie.name == 'Alignak-WebUI': assert cookie.expires is None # A session exists and it contains: current user, his realm and his live synthesis self.session = self.login_response.request.environ['beaker.session'] assert 'current_user' in self.session and self.session['current_user'] assert self.session['current_user'].name == 'guest' assert 'current_realm' in self.session and self.session['current_realm'] assert self.session['current_realm'].name == 'All' # assert 'current_ls' in self.session and self.session['current_ls'] # edition_mode is defined but not activated in the session... assert 'edition_mode' in self.session assert False == self.session['edition_mode'] def tearDown(self): print('logout') self.app.get('/logout') def test_enable_disable(self): """Enable / disable edition mode is denied for non admin user""" print('Enable edition mode - denied') self.app.post('/edition_mode', params={'state': 'on'}, status=401) print('Disable edition mode - denied') self.app.post('/edition_mode', params={'state': 'off'}, status=401) print( 'get page /host_form (read-only mode) - for a new host - granted') # Authorized... self.app.get('/host_form/alignak_glpi', status=200) print('get page /host_form (edition mode) - for a new host - denied') # Redirected... self.app.get('/host_form/None', status=302) print('Host creation without template - denied') data = { "_is_template": False, 'name': "New host", 'alias': "Friendly name" } self.app.post('/host_form/None', params=data, status=401) print('Host templates page - denied') self.app.get('/hosts/templates', status=302) print('Post form updates - denied') data = {'name': 'alignak_glpi', 'alias': "Alias edited"} response = self.app.post('/host_form/alignak_glpi', params=data, status=401)
def test_api(path, get_params, expected_status): app = TestApp(logic) assert app.get(path + '?%s' % (get_params or ''), status=expected_status).status_code == expected_status
class DecoratorTests(unittest.TestCase): def setUp(self): self.testbed = testbed.Testbed() self.testbed.activate() self.testbed.init_datastore_v3_stub() self.testbed.init_memcache_stub() self.testbed.init_user_stub() decorator = OAuth2Decorator(client_id='foo_client_id', client_secret='foo_client_secret', scope=['foo_scope', 'bar_scope']) self.decorator = decorator class TestRequiredHandler(webapp.RequestHandler): @decorator.oauth_required def get(self): pass class TestAwareHandler(webapp.RequestHandler): @decorator.oauth_aware def get(self): self.response.out.write('Hello World!') application = webapp.WSGIApplication( [('/oauth2callback', OAuth2Handler), ('/foo_path', TestRequiredHandler), ('/bar_path', TestAwareHandler)], debug=True) self.app = TestApp(application) users.get_current_user = UserMock self.httplib2_orig = httplib2.Http httplib2.Http = Http2Mock def tearDown(self): self.testbed.deactivate() httplib2.Http = self.httplib2_orig def test_required(self): # An initial request to an oauth_required decorated path should be a # redirect to start the OAuth dance. response = self.app.get('/foo_path') self.assertTrue(response.status.startswith('302')) q = parse_qs(response.headers['Location'].split('?', 1)[1]) self.assertEqual('http://localhost/oauth2callback', q['redirect_uri'][0]) self.assertEqual('foo_client_id', q['client_id'][0]) self.assertEqual('foo_scope bar_scope', q['scope'][0]) self.assertEqual('http://localhost/foo_path', q['state'][0]) self.assertEqual('code', q['response_type'][0]) self.assertEqual(False, self.decorator.has_credentials()) # Now simulate the callback to /oauth2callback. response = self.app.get('/oauth2callback', { 'code': 'foo_access_code', 'state': 'foo_path', }) self.assertEqual('http://localhost/foo_path', response.headers['Location']) self.assertEqual(None, self.decorator.credentials) # Now requesting the decorated path should work. response = self.app.get('/foo_path') self.assertEqual('200 OK', response.status) self.assertEqual(True, self.decorator.has_credentials()) self.assertEqual('foo_refresh_token', self.decorator.credentials.refresh_token) self.assertEqual('foo_access_token', self.decorator.credentials.access_token) # Invalidate the stored Credentials. self.decorator.credentials.invalid = True self.decorator.credentials.store.put(self.decorator.credentials) # Invalid Credentials should start the OAuth dance again. response = self.app.get('/foo_path') self.assertTrue(response.status.startswith('302')) q = parse_qs(response.headers['Location'].split('?', 1)[1]) self.assertEqual('http://localhost/oauth2callback', q['redirect_uri'][0]) def test_aware(self): # An initial request to an oauth_aware decorated path should not redirect. response = self.app.get('/bar_path') self.assertEqual('Hello World!', response.body) self.assertEqual('200 OK', response.status) self.assertEqual(False, self.decorator.has_credentials()) url = self.decorator.authorize_url() q = parse_qs(url.split('?', 1)[1]) self.assertEqual('http://localhost/oauth2callback', q['redirect_uri'][0]) self.assertEqual('foo_client_id', q['client_id'][0]) self.assertEqual('foo_scope bar_scope', q['scope'][0]) self.assertEqual('http://localhost/bar_path', q['state'][0]) self.assertEqual('code', q['response_type'][0]) # Now simulate the callback to /oauth2callback. url = self.decorator.authorize_url() response = self.app.get('/oauth2callback', { 'code': 'foo_access_code', 'state': 'bar_path', }) self.assertEqual('http://localhost/bar_path', response.headers['Location']) self.assertEqual(False, self.decorator.has_credentials()) # Now requesting the decorated path will have credentials. response = self.app.get('/bar_path') self.assertEqual('200 OK', response.status) self.assertEqual('Hello World!', response.body) self.assertEqual(True, self.decorator.has_credentials()) self.assertEqual('foo_refresh_token', self.decorator.credentials.refresh_token) self.assertEqual('foo_access_token', self.decorator.credentials.access_token)
class TestEditionMode(unittest2.TestCase): def setUp(self): # Test application self.app = TestApp(alignak_webui.app.session_app) print('login accepted - go to home page') self.login_response = self.app.post('/login', { 'username': '******', 'password': '******' }) # A session cookie exist assert self.app.cookies['Alignak-WebUI'] for cookie in self.app.cookiejar: if cookie.name == 'Alignak-WebUI': assert cookie.expires is None # A session exists and it contains: current user, his realm and his live synthesis self.session = self.login_response.request.environ['beaker.session'] assert 'current_user' in self.session and self.session['current_user'] assert self.session['current_user'].name == 'admin' assert 'current_realm' in self.session and self.session['current_realm'] assert self.session['current_realm'].name == 'All' # assert 'current_ls' in self.session and self.session['current_ls'] # edition_mode is defined but not activated in the session... assert 'edition_mode' in self.session assert False == self.session['edition_mode'] def tearDown(self): print('logout') self.app.get('/logout') def test_enable_disable(self): """Enable / disable edition mode""" print('Enable edition mode') response = self.app.post('/edition_mode', params={'state': 'on'}) session = response.request.environ['beaker.session'] # edition_mode is defined and activated in the session... assert 'edition_mode' in session assert True == session['edition_mode'] assert response.json == { 'edition_mode': True, 'message': 'Edition mode enabled' } print('Disable edition mode') response = self.app.post('/edition_mode', params={'state': 'off'}) session = response.request.environ['beaker.session'] # edition_mode is defined and activated in the session... assert 'edition_mode' in session assert False == session['edition_mode'] assert response.json == { 'edition_mode': False, 'message': 'Edition mode disabled' } print('Disable edition mode') # Any value other than 'on', edition is False response = self.app.post('/edition_mode', params={'state': ''}) session = response.request.environ['beaker.session'] # edition_mode is defined and activated in the session... assert 'edition_mode' in session assert False == session['edition_mode'] assert response.json == { 'edition_mode': False, 'message': 'Edition mode disabled' } # No state parameter, edition is False response = self.app.post('/edition_mode') session = response.request.environ['beaker.session'] # edition_mode is defined and activated in the session... assert 'edition_mode' in session assert False == session['edition_mode'] assert response.json == { 'edition_mode': False, 'message': 'Edition mode disabled' } def test_edition_mode_menu(self): """In edition mode, a new menu exist in the menu bar""" print('test edition mode menu') print('get dashboard') response = self.app.get('/dashboard') response.mustcontain( '<div id="dashboard">', no=[ '<!-- Templates actions bar -->', '<li class="dropdown" data-toggle="tooltip" data-placement="bottom" title="Templates menu">', '<ul class="dropdown-menu" role="menu" aria-labelledby="Edition mode menu">', '<span>Hosts templates</span>', '<span>Services templates</span>', '<span>Users templates</span>' ]) print('Enable edition mode') response = self.app.post('/edition_mode', params={'state': 'on'}) session = response.request.environ['beaker.session'] # edition_mode is defined and activated in the session... assert 'edition_mode' in session assert True == session['edition_mode'] assert response.json == { 'edition_mode': True, 'message': 'Edition mode enabled' } print('get dashboard (edition mode)') response = self.app.get('/dashboard') response.mustcontain( '<div id="dashboard">', '<!-- Templates actions bar -->', '<li class="dropdown" data-toggle="tooltip" data-placement="bottom" title="Edition menu">', '<ul class="dropdown-menu" role="menu" aria-labelledby="Edition mode menu">', '<span>Hosts templates</span>', '<span>Services templates</span>', '<span>Users templates</span>') print('Disable edition mode') response = self.app.post('/edition_mode', params={'state': 'off'}) session = response.request.environ['beaker.session'] # edition_mode is defined and activated in the session... assert 'edition_mode' in session assert False == session['edition_mode'] assert response.json == { 'edition_mode': False, 'message': 'Edition mode disabled' } print('get dashboard') response = self.app.get('/dashboard') response.mustcontain( '<div id="dashboard">', no=[ '<!-- Templates actions bar -->', '<li class="dropdown" data-toggle="tooltip" data-placement="bottom" title="Edition menu">', '<ul class="dropdown-menu" role="menu" aria-labelledby="Edition mode menu">', '<span>Hosts templates</span>', '<span>Services templates</span>', '<span>Users templates</span>' ])
class TestVMActionsHTTP(unittest.TestCase): """Tests API functions associated with VM actions. Note that all tests are in-process, we don't actually start a HTTP server, but we do communicate HTTP requests and responses. Outside of setUp, all calls to the database should be via the HTTP API. """ def setUp(self): """Launch pserve using webtest with test settings""" self.appconf = get_app(test_ini) self.app = TestApp(self.appconf) #For speed, allow cookie setting. # self.app.cookiejar.set_policy(DefaultCookiePolicy(allowed_domains=[])) # This sets global var "engine" - in the case of SQLite this is a fresh RAM # DB each time. If we only did this on class instantiation the database would # be dirty and one test could influence another. # TODO - add a test that tests this. server.choose_engine("SQLite") # Punch in new administrator account with direct server call # This will implicitly generate the tables. user_id = server.create_user("administrators", "administrator", "administrator", "administrator") #server.touch_to_add_user_group("administrator", "administrators") server.touch_to_add_password(user_id, "adminpass") self.app.authorization = ('Basic', ('administrator', 'adminpass')) # This sorts out the auth token cookie. self.app.get('/users') self.app.authorization = None """VM-related API functions.""" def test_create_own_retrieve_servers(self): # FIX """ Create a server. Ensure that a 200 OK response results. Add an owner to a server. Ensure that a 200 OK response results. A user can request a list of servers that they own. An administrator can list all the servers. """ # Create user and server self.create_user("testuser") self.create_server("testserver") # Add ownership response = self.app.put('/servers/testserver/owner', { 'artifact_id': 'testserver', 'actor_id': 'bcollier' }) # Get server response = self.app.get('/servers/testserver', {'hostname': 'testserver'}) # Get server ownership - !! Not implemented # FIXME # # response = self.app.get('/servers/testserver/owner', # {'artifact_id': 'testserver'}) """ Server State-Change Functions. """ def test_server_states(self): """ Check that a server appears in various states after using the relevant API call. This also tests the function 'retrieve_servers_in_state'. """ # Create server sid = self.create_server("testserver") def get_state(): response = self.app.get('/servers/testserver/state') return response.json #All the states listed should simply add a touch and succeed without drama. for state in STATES_TO_TEST: res = self.app.post('/servers/testserver/' + state) #print("Push result = " + str(res)) self.assertEqual(get_state(), state) #Also confirm this works by ID resp2 = self.app.get('/servers/by_id/%s/state' % sid) self.assertEqual(resp2.json, STATES_TO_TEST[-1]) def test_retrieve_server(self): """ Pull back details of our server by name. """ self.create_server("testserver") # Create server # Retrieve server details response = self.app.get('/servers/testserver', {'hostname': 'testserver'}) def test_retrieve_server_by_id(self): """ Our server will have ID 1. Check that we can retrieve details of it. """ sid = self.create_server("testserver") # Create server # Retrieve server details by name self.assertEqual(sid, 1) response = self.app.get('/servers/by_id/1') # def test_update_server(self): # """ Not currently implemented. """ # # self.create_server("testserver") # Create server # Update server details # Check server details # def test_delete_server(self): # """ Not currently implemented. """ def test_set_get_server_specification(self): """ Follows hard-coded rules for machine behaviour. Set machine CPUs to 2, RAM to 123. Check, should pass. Set machine CPUs to 0. Check, should fail. Check that machine RAM and Cores are 2 and 123 as above. """ self.create_server("testserver") # Create server # Set server spec response = self.app.post('/servers/testserver/specification', { 'name': 'testserver', 'cores': 2, 'ram': 123 }, status=200, expect_errors=False) response = self.app.post('/servers/testserver/specification', { 'name': 'testserver', 'cores': 0, 'ram': 40 }, status=400, expect_errors=False) # Get server spec response = self.app.get('/servers/testserver/specification', {'hostname': 'testserver'}, status=200, expect_errors=False) self.assertEqual(response.json['cores'], 2) self.assertEqual(response.json['ram'], 123) def test_retrieve_servers_by_state(self): """ The agents need to find out about servers to be acted on. Test for states/XXX """ app = self.app self.create_server("testserver1") self.create_server("testserver2") app.post('/servers/testserver1/Stopping') app.post('/servers/testserver2/Stopping') res1 = app.get('/states/Stopping') self.assertEqual(res1.json, [{ "artifact_id": 1, "artifact_uuid": "testserver1", "artifact_name": "testserver1" }, { "artifact_id": 2, "artifact_uuid": "testserver2", "artifact_name": "testserver2" }]) #And after changing states around self.create_server("testserver3") app.post('/servers/testserver3/Stopping') app.post('/servers/testserver2/Starting') app.post('/servers/testserver3/Starting') app.post('/servers/testserver2/Stopping') res2 = app.get('/states/Stopping') self.assertEqual(res2.json, [{ "artifact_id": 1, "artifact_uuid": "testserver1", "artifact_name": "testserver1" }, { "artifact_id": 2, "artifact_uuid": "testserver2", "artifact_name": "testserver2" }]) def test_retrieve_job_progress(self): """ Not currently implemented. """ def test_retrieve_server_touches(self): """ Not currently implemented. """ def test_retrieve_state_summary(self): """ Test for /states """ app = self.app # Generate base status table status_table = {s: 0 for s in server.get_state_list()} r = app.get("/states") self.assertEqual(r.json, status_table) for n in range(1, 6): self.create_server("testserver%i" % n) app.post('/servers/testserver1/Stopping') app.post('/servers/testserver2/Stopping') app.post('/servers/testserver3/Stopping') app.post('/servers/testserver4/Started') app.post('/servers/testserver5/Starting') # Test1 - servers set to only one state. st1 = status_table.copy() st1['Stopping'] = 3 st1['Started'] = 1 st1['Starting'] = 1 r = app.get("/states") self.assertEqual(r.json, st1) # Test2 - server states have been changed app.post('/servers/testserver3/Started') app.post('/servers/testserver3/Stopping') app.post('/servers/testserver4/Stopping') app.post('/servers/testserver3/Starting') st2 = status_table.copy() st2['Stopping'] = 3 st2['Started'] = 0 st2['Starting'] = 2 r = app.get("/states") self.assertEqual(r.json, st2) ############################################################################### # Support Functions, calling server admin views # ############################################################################### def create_user(self, name): response = self.app.put('/users/' + name, { 'type': 'users', 'handle': name + '@example.com', 'name': name + " " + name, 'username': name }, status=200, expect_errors=False) def create_server(self, name): return self.app.put('/servers/' + name, { 'hostname': name, 'uuid': name }, status=200, expect_errors=False).json
class FunctionalTests(unittest.TestCase): def setUp(self): from arhea.arhea import main settings = { 'sqlalchemy.default.url': 'sqlite://', 'sqlalchemy.ea.url': 'sqlite://', 'jinja2.directories' : ['arhea:arhea/app_sec/templates', 'arhea:arhea/templates', 'arhea:arhea/app_hr/templates', 'arhea:arhea/app_apps/templates'], 'session.secret' : 'sess', 'auth.secret' : 'auth', 'admin_gtwy': 'https://admin-dev.telekom.ee', 'ldap.user': '******', 'ldap.pwd': 'Pawer5ty9', 'ldap.user_base': 'OU=Inimesed,OU=ET,DC=et,DC=ee', 'ldap.group_base': 'OU=Arhea,OU=Roll,OU=RBAC,OU=ET,DC=et,DC=ee', } app = main({}, **settings) from webtest import TestApp self.testapp = TestApp(app) self.session = _initTestingDB() #Login for tests to work res = self.testapp.get('/login') form = res.form form['login'] = '******' form['password'] = '******' form['came_from'] = '/' res = form.submit('submit') def tearDown(self): del self.testapp self.session.remove() def test_homepage(self): res = self.testapp.get('/', status=200) self.assertIn(b'Telekom', res.body) def test_unexisting_page(self): self.testapp.get('/SomePage', status=404) def test_departments_query_sort_unknown(self): res = self.testapp.get('/departments?sort=SqlInjection', status=302) self.assertEqual(res.location, 'http://localhost/') def test_departments_report(self): res = self.testapp.get('/departments', status=200) self.assertIn(b'<h3>Departments</h3>', res.body) def test_employees_report(self): res = self.testapp.get('/employees', status=200) self.assertIn(b'<h3>Employees</h3>', res.body) def test_department_form_add_GET(self): # Get the form res = self.testapp.get('/departments/add', status=200) self.assertIn(b'department_name', res.body) def test_department_form_add_POST(self): # Get the form res = self.testapp.get('/departments/add') form = res.form form['department_name'] = 'test' res = form.submit('submit') self.assertEqual(res.location, 'http://localhost/departments') def test_department_form_edit_GET(self): # Get the form res = self.testapp.get('/departments/1/edit', status=200) self.assertIn(b'A Minu Test', res.body) def test_department_form_edit_GET_unknown_id(self): # Get the form res = self.testapp.get('/departments/1000/edit', status=404) self.assertIn(b'Resource not found!', res.body) def test_department_form_edit_POST(self): # Get the form res = self.testapp.get('/departments/1/edit') form = res.form form['department_name'] = 'test' res = form.submit('submit') self.assertEqual(res.location, 'http://localhost/departments') def test_employee_form_GET(self): # Get the form res = self.testapp.get('/employees/add', status=200) self.assertIn(b'first_name', res.body) def test_employee_form_edit_GET(self): # Get the form res = self.testapp.get('/employees/1/edit', status=200) self.assertIn(b'John', res.body) def test_employee_form_edit_GET_unknown_id(self): # Get the form res = self.testapp.get('/employees/100/edit', status=404) self.assertIn(b'Resource not found!', res.body)