moksha/public/javascript/moksha.js | 3 moksha/tests/__init__.py | 88 +++++++++++++++++------- moksha/tests/functional/__init__.py | 2 moksha/tests/functional/test_authentication.py | 86 +++++++++++++++++++++++ moksha/tests/functional/test_root.py | 36 +++++++-- moksha/tests/models/__init__.py | 49 +++++++++++++ moksha/tests/models/test_auth.py | 51 ++++++++++++++ moksha/tests/models/test_entity.py | 91 +++++++++++++++++++++++++ moksha/tests/test_entity.py | 89 ------------------------ moksha/tests/test_hub.py | 2 moksha/tests/test_models.py | 39 ---------- test.ini | 4 + 12 files changed, 375 insertions(+), 165 deletions(-)
New commits: commit 7f021f6aaddc2d7c06b8ad65cc327bc1a528ee61 Author: Luke Macken lmacken@redhat.com Date: Mon Mar 16 12:00:12 2009 -0400
Add a main_without_authn test app to our test.ini
diff --git a/test.ini b/test.ini index f3d55cc..50d5df7 100644 --- a/test.ini +++ b/test.ini @@ -19,4 +19,8 @@ port = 5000 sqlalchemy.url = sqlite:///:memory: use = config:development.ini
+[app:main_without_authn] +use = main +skip_authentication = True + # Add additional test specific configuration options as necessary.
commit fa5061dede467dcece0f904ce4619c8c5560fb0d Author: Luke Macken lmacken@redhat.com Date: Mon Mar 16 11:58:37 2009 -0400
Bring our test suite up to speed with the latest TurboGears2 quickstart
diff --git a/moksha/tests/__init__.py b/moksha/tests/__init__.py index c5f1b84..fe3ed4e 100644 --- a/moksha/tests/__init__.py +++ b/moksha/tests/__init__.py @@ -1,38 +1,74 @@ -"""Pylons application test package +# -*- coding: utf-8 -*- +"""Unit and functional test suite for Moksha """
-When the test runner finds and executes tests within this directory, -this file will be loaded to setup the test environment. - -It registers the root directory of the project in sys.path and -pkg_resources, in case the project hasn't been installed with -setuptools. It also initializes the application via websetup (paster -setup-app) with the project's test.ini configuration file. -""" -import os +from os import path import sys
-import pkg_resources -import webtest -import paste.script.appinstall +from tg import config from paste.deploy import loadapp +from paste.script.appinstall import SetupCommand from routes import url_for +from webtest import TestApp +from nose.tools import eq_
-__all__ = ['url_for', 'TestController'] +from moksha import model + +__all__ = ['setup_db', 'teardown_db', 'TestController', 'url_for']
-here_dir = os.path.dirname(os.path.abspath(__file__)) -conf_dir = os.path.dirname(os.path.dirname(here_dir)) +def setup_db(): + engine = config['pylons.app_globals'].sa_engine + model.init_model(engine) + model.metadata.create_all(engine)
-sys.path.insert(0, conf_dir) -pkg_resources.working_set.add_entry(conf_dir) -pkg_resources.require('Paste') -pkg_resources.require('PasteScript') +def teardown_db(): + engine = config['pylons.app_globals'].sa_engine + model.metadata.drop_all(engine) + +def setup_app(application): + # Loading the application: + conf_dir = config.here + wsgiapp = loadapp('config:test.ini#%s' % application, + relative_to=conf_dir) + app = TestApp(wsgiapp) + # Setting it up: + test_file = path.join(conf_dir, 'test.ini') + cmd = SetupCommand('setup-app') + cmd.run([test_file]) + return app + +__all__ = ['url_for', 'TestController']
-test_file = os.path.join(conf_dir, 'test.ini') -cmd = paste.script.appinstall.SetupCommand('setup-app') -cmd.run([test_file])
class TestController(object): + """ + Base functional test case for the controllers. + + The Moksha application instance (``self.app``) set up in this test + case (and descendants) has authentication disabled, so that developers can + test the protected areas independently of the :mod:`repoze.who` plugins + used initially. This way, authentication can be tested once and separately. + + Check Moksha for the repoze.who integration tests. + + This is the officially supported way to test protected areas with + repoze.who-testutil (http://code.gustavonarea.net/repoze.who-testutil/). + + """ + + application_under_test = 'main_without_authn' + + def setUp(self): + # Loading the application: + conf_dir = config.here + wsgiapp = loadapp('config:test.ini#%s' % self.application_under_test, + relative_to=conf_dir) + self.app = TestApp(wsgiapp) + # Setting it up: + test_file = path.join(conf_dir, 'test.ini') + cmd = SetupCommand('setup-app') + cmd.run([test_file])
- def __init__(self, *args, **kwargs): - wsgiapp = loadapp('config:test.ini', relative_to=conf_dir) - self.app = webtest.TestApp(wsgiapp) + def tearDown(self): + # Cleaning up the database: + engine = config['pylons.app_globals'].sa_engine + model.metadata.drop_all(engine) diff --git a/moksha/tests/functional/__init__.py b/moksha/tests/functional/__init__.py index e69de29..74b869b 100644 --- a/moksha/tests/functional/__init__.py +++ b/moksha/tests/functional/__init__.py @@ -0,0 +1,2 @@ +# -*- coding: utf-8 -*- +"""Functional test suite for the controllers of the application.""" \ No newline at end of file diff --git a/moksha/tests/functional/test_authentication.py b/moksha/tests/functional/test_authentication.py new file mode 100644 index 0000000..3992eaf --- /dev/null +++ b/moksha/tests/functional/test_authentication.py @@ -0,0 +1,86 @@ +# -*- coding: utf-8 -*- +""" +Integration tests for the :mod:`repoze.who`-powered authentication sub-system. + +As Moksah grows and the authentication method changes, only these tests +should be updated. + +""" + +from moksha.tests import TestController + + +class TestAuthentication(TestController): + """ + Tests for the default authentication setup. + + By default in TurboGears 2, :mod:`repoze.who` is configured with the same + plugins specified by repoze.what-quickstart (which are listed in + http://code.gustavonarea.net/repoze.what-quickstart/#repoze.what.plugins.qui...). + + As the settings for those plugins change, or the plugins are replaced, + these tests should be updated. + + """ + + application_under_test = 'main' + + def test_forced_login(self): + """ + Anonymous users must be redirected to the login form when authorization + is denied. + + Next, upon successful login they should be redirected to the initially + requested page. + + """ + # Requesting a protected area + resp = self.app.get('/secc/', status=302) + assert resp.location.startswith('http://localhost/login') + # Getting the login form: + resp = resp.follow(status=200) + form = resp.form + # Submitting the login form: + form['login'] = u'manager' + form['password'] = 'managepass' + post_login = form.submit(status=302) + # Being redirected to the initially requested page: + assert post_login.location.startswith('http://localhost/post_login') + initial_page = post_login.follow(status=302) + assert 'authtkt' in initial_page.request.cookies, \ + "Session cookie wasn't defined: %s" % initial_page.request.cookies + assert initial_page.location.startswith('http://localhost/secc/'), \ + initial_page.location + + def test_voluntary_login(self): + """Voluntary logins must work correctly""" + # Going to the login form voluntarily: + resp = self.app.get('/login', status=200) + form = resp.form + # Submitting the login form: + form['login'] = u'manager' + form['password'] = 'managepass' + post_login = form.submit(status=302) + # Being redirected to the home page: + assert post_login.location.startswith('http://localhost/post_login') + home_page = post_login.follow(status=302) + assert 'authtkt' in home_page.request.cookies, \ + 'Session cookie was not defined: %s' % home_page.request.cookies + assert home_page.location == 'http://localhost/' + + def test_logout(self): + """Logouts must work correctly""" + # Logging in voluntarily the quick way: + resp = self.app.get('/login_handler?login=manager&password=managepass', + status=302) + resp = resp.follow(status=302) + assert 'authtkt' in resp.request.cookies, \ + 'Session cookie was not defined: %s' % resp.request.cookies + # Logging out: + resp = self.app.get('/logout_handler', status=302) + assert resp.location.startswith('http://localhost/post_logout') + # Finally, redirected to the home page: + home_page = resp.follow(status=302) + assert home_page.request.cookies.get('authtkt') == '', \ + 'Session cookie was not deleted: %s' % home_page.request.cookies + assert home_page.location == 'http://localhost/', home_page.location diff --git a/moksha/tests/functional/test_root.py b/moksha/tests/functional/test_root.py index 2d5dab9..168c90a 100644 --- a/moksha/tests/functional/test_root.py +++ b/moksha/tests/functional/test_root.py @@ -1,19 +1,39 @@ # -*- coding: utf-8 -*- +""" +Functional test suite for the root controller.
-from moksha.tests import TestController +This is an example of how functional tests can be written for controllers. + +As opposed to a unit-test, which test a small unit of functionality, +functional tests exercise the whole application and its WSGI stack. + +Please read http://pythonpaste.org/webtest/ for more information. + +""" from nose.tools import assert_true
-# This is an example of how you can write functional tests for your controller. -# As opposed to a pure unit-test which test a small unit of functionallity, -# these functional tests exercise the whole app and it's WSGI stack. -# Please read http://pythonpaste.org/webtest/ for more information +from moksha.tests import TestController +
class TestRootController(TestController): def test_index(self): response = self.app.get('/') - msg = 'content' + msg = 'TurboGears 2 is rapid web application development toolkit '\ + 'designed to make your life easier.' + # You can look for specific strings: assert_true(msg in response) - # You can also access a BeautifulSoup'ed version - # first run $ easy_install BeautifulSoup and then run this test + + # You can also access a BeautifulSoup'ed response in your tests + # (First run $ easy_install BeautifulSoup + # and then uncomment the next two lines) + #links = response.html.findAll('a') + #print links #assert_true(links, "Mummy, there are no links here!") + + def test_secc_with_anonymous(self): + """Anonymous users must not access the secure controller""" + # We should get a redirect to login + resp = self.app.get('/secc', status=302) + print resp + assert "/login?came_from=http%3A%2F%2Flocalhost%2Fsecc" in resp diff --git a/moksha/tests/models/__init__.py b/moksha/tests/models/__init__.py new file mode 100644 index 0000000..02a3d71 --- /dev/null +++ b/moksha/tests/models/__init__.py @@ -0,0 +1,49 @@ +# -*- coding: utf-8 -*- +"""Unit test suite for the models of the application.""" +from nose.tools import assert_equals + +from moksha.model import DBSession +from moksha.tests import setup_db, teardown_db + +__all__ = ['ModelTest'] + +#Create an empty database before we start our tests for this module +def setup(): + setup_db() + +#Teardown that database +def teardown(): + teardown_db() + +class ModelTest(object): + """Base unit test case for the models.""" + + klass = None + attrs = {} + + def setup(self): + try: + new_attrs = {} + new_attrs.update(self.attrs) + new_attrs.update(self.do_get_dependencies()) + self.obj = self.klass(**new_attrs) + DBSession.add(self.obj) + DBSession.flush() + return self.obj + except: + DBSession.rollback() + raise + + def tearDown(self): + DBSession.rollback() + + def do_get_dependencies(self): + return {} + + def test_create_obj(self): + pass + + def test_query_obj(self): + obj = DBSession.query(self.klass).one() + for key, value in self.attrs.iteritems(): + assert_equals(getattr(obj, key), value) diff --git a/moksha/tests/models/test_auth.py b/moksha/tests/models/test_auth.py new file mode 100644 index 0000000..f753cc9 --- /dev/null +++ b/moksha/tests/models/test_auth.py @@ -0,0 +1,51 @@ +# -*- coding: utf-8 -*- +"""Test suite for the TG app's models""" +from nose.tools import eq_ + +from moksha import model +from moksha.tests.models import ModelTest + +class TestGroup(ModelTest): + """Unit test case for the ``Group`` model.""" + klass = model.Group + attrs = dict( + group_name = u"test_group", + display_name = u"Test Group" + ) + + +class TestUser(ModelTest): + """Unit test case for the ``User`` model.""" + + klass = model.User + attrs = dict( + user_name = u"ignucius", + email_address = u"ignucius@example.org" + ) + + def test_obj_creation_username(self): + """The obj constructor must set the user name right""" + eq_(self.obj.user_name, u"ignucius") + + def test_obj_creation_email(self): + """The obj constructor must set the email right""" + eq_(self.obj.email_address, u"ignucius@example.org") + + def test_no_permissions_by_default(self): + """User objects should have no permission by default.""" + eq_(len(self.obj.permissions), 0) + + def test_getting_by_email(self): + """Users should be fetcheable by their email addresses""" + him = model.User.by_email_address(u"ignucius@example.org") + eq_(him, self.obj) + + +class TestPermission(ModelTest): + """Unit test case for the ``Permission`` model.""" + + klass = model.Permission + attrs = dict( + permission_name = u"test_permission", + description = u"This is a test Description" + ) diff --git a/moksha/tests/test_entity.py b/moksha/tests/test_entity.py deleted file mode 100644 index bcba377..0000000 --- a/moksha/tests/test_entity.py +++ /dev/null @@ -1,89 +0,0 @@ -# -*- coding: utf-8 -*- -"""Test Moksha's Entity/Fact model""" - -from datetime import datetime -from nose.tools import eq_, assert_true -from sqlalchemy import * -from moksha.model import DBSession, Entity, Fact, with_characteristic -from moksha.tests.test_models import TestModel - -class TestEntity(TestModel): - """Test case for the Entity model.""" - - def setUp(self): - super(TestEntity, self).setUp() - self.entity = Entity(u'lmacken') - self.entity[u'firstname'] = u'Luke' - self.entity[u'lastname'] = u'Macken' - self.entity[u'age'] = 24 - self.entity[u'dob'] = datetime(1984, 11, 02) - self.entity[u'l33t'] = True - - def test_entity_creation_name(self): - eq_(self.entity.name, u'lmacken') - - def test_fact_types(self): - DBSession.add(self.entity) - DBSession.flush() - me = DBSession.query(Entity).filter_by(name=u'lmacken').one() - eq_(me[u'lastname'], u'Macken') - eq_(me[u'age'], 24) - eq_(me[u'dob'], datetime(1984, 11, 2)) - eq_(me[u'l33t'], True) - - def test_getting_by_name(self): - """ Entities should be fetchable by their name """ - DBSession.add(self.entity) - lmacken = Entity.by_name(u'lmacken') - eq_(lmacken, self.entity) - - def test_filter_by_name(self): - DBSession.add(self.entity) - me = DBSession.query(Entity).filter_by(name=u'lmacken').one() - eq_(me.name, u'lmacken') - eq_(me[u'firstname'], u'Luke') - - def test_query_by_fact(self): - """ Query entities by facts """ - DBSession.add(self.entity) - assert DBSession.query(Entity).filter( - Entity.facts.any( - and_(Fact.key == u'l33t', - Fact.value == True))).first() - - def test_query_with_characteristic(self): - """ Query entities based on facts using with_characteristic """ - DBSession.add(self.entity) - assert (DBSession.query(Entity). - filter(or_(Entity.facts.any( - with_characteristic(u'dob', datetime(1984, 11, 02))), - not_(Entity.facts.any(Fact.key == u'l33t'))))).first() - - def test_query_facts_by_characteristic(self): - """ Query facts by certain characteristics """ - DBSession.add(self.entity) - assert (DBSession.query(Fact). - filter(with_characteristic(u'l33t', True))).one() - - """ - def test_hooks(self): - from moksha.hook import Hook, MokshaHookMapperExtension - from moksha.model import model - insert = update = delete = False - - class MyHook(Hook): - def after_insert(self, instance): - insert = True - def after_update(self, instance): - update = True - def after_delete(self, instance): - delete = True - - model.moksha_mapper_extension.hooks['after_insert'].append(MyHook()) - - # create a new entity - something = Entity(u'something') - DBSession.add(something) - DBSession.flush() - assert insert - """ diff --git a/moksha/tests/test_hub.py b/moksha/tests/test_hub.py index eed35f5..8f9b8d4 100644 --- a/moksha/tests/test_hub.py +++ b/moksha/tests/test_hub.py @@ -1,7 +1,7 @@ """Test Moksha's Hub """
+import moksha from nose.tools import eq_, assert_true -from moksha import hub
class TestHub:
diff --git a/moksha/tests/test_models.py b/moksha/tests/test_models.py deleted file mode 100644 index 20247a0..0000000 --- a/moksha/tests/test_models.py +++ /dev/null @@ -1,39 +0,0 @@ -# -*- coding: utf-8 -*- -"""Test suite for the TG app's models""" - -from tg.testutil import DBTest -from nose.tools import eq_ - -from moksha import model - - -class TestModel(DBTest): - """The base class for testing models in you TG project.""" - model = model - -class TestUser(TestModel): - """Test case for the User model.""" - - def setUp(self): - super(TestUser, self).setUp() - self.member = model.User() - self.member.user_name = u"ignucius" - self.member.email_address = u"ignucius@example.org" - - def test_member_creation_username(self): - """The member constructor must set the user name right""" - eq_(self.member.user_name, u"ignucius") - - def test_member_creation_email(self): - """The member constructor must set the email right""" - eq_(self.member.email_address, u"ignucius@example.org") - - def test_no_permissions_by_default(self): - """User objects should have no permission by default.""" - eq_(len(self.member.permissions), 0) - - def test_getting_by_email(self): - """Users should be fetcheable by their email addresses""" - model.DBSession.add(self.member) - him = model.User.by_email_address(u"ignucius@example.org") - eq_(him, self.member)
commit 7ca549ed8250309fc3505b10844771aaf2646bba Author: Luke Macken lmacken@redhat.com Date: Mon Mar 16 11:58:08 2009 -0400
Bring our fact/entity tests up to speed
diff --git a/moksha/tests/models/test_entity.py b/moksha/tests/models/test_entity.py new file mode 100644 index 0000000..522efaf --- /dev/null +++ b/moksha/tests/models/test_entity.py @@ -0,0 +1,91 @@ +# -*- coding: utf-8 -*- +"""Test Moksha's Entity/Fact model""" + +from datetime import datetime +from nose.tools import eq_, assert_true +from sqlalchemy import * +from moksha.model import DBSession, Entity, Fact, with_characteristic +from moksha.tests.models import ModelTest + +class TestEntity(ModelTest): + """Test case for the Entity model.""" + + klass = Entity + attrs = dict(name='lmacken') + + def setup(self): + super(TestEntity, self).setup() + self.obj[u'firstname'] = u'Luke' + self.obj[u'lastname'] = u'Macken' + self.obj[u'age'] = 24 + self.obj[u'dob'] = datetime(1984, 11, 02) + self.obj[u'l33t'] = True + + def test_entity_creation_name(self): + eq_(self.obj.name, u'lmacken') + + def test_fact_types(self): + DBSession.add(self.obj) + DBSession.flush() + me = DBSession.query(Entity).filter_by(name=u'lmacken').one() + eq_(me[u'lastname'], u'Macken') + eq_(me[u'age'], 24) + eq_(me[u'dob'], datetime(1984, 11, 2)) + eq_(me[u'l33t'], True) + + def test_getting_by_name(self): + """ Entities should be fetchable by their name """ + DBSession.add(self.obj) + lmacken = Entity.by_name(u'lmacken') + eq_(lmacken, self.obj) + + def test_filter_by_name(self): + DBSession.add(self.obj) + me = DBSession.query(Entity).filter_by(name=u'lmacken').one() + eq_(me.name, u'lmacken') + eq_(me[u'firstname'], u'Luke') + + def test_query_by_fact(self): + """ Query entities by facts """ + DBSession.add(self.obj) + assert DBSession.query(Entity).filter( + Entity.facts.any( + and_(Fact.key == u'l33t', + Fact.value == True))).first() + + def test_query_with_characteristic(self): + """ Query entities based on facts using with_characteristic """ + DBSession.add(self.obj) + assert (DBSession.query(Entity). + filter(or_(Entity.facts.any( + with_characteristic(u'dob', datetime(1984, 11, 02))), + not_(Entity.facts.any(Fact.key == u'l33t'))))).first() + + def test_query_facts_by_characteristic(self): + """ Query facts by certain characteristics """ + DBSession.add(self.obj) + assert (DBSession.query(Fact). + filter(with_characteristic(u'l33t', True))).one() + + """ + def test_hooks(self): + from moksha.hook import Hook, MokshaHookMapperExtension + from moksha.model import model + insert = update = delete = False + + class MyHook(Hook): + def after_insert(self, instance): + insert = True + def after_update(self, instance): + update = True + def after_delete(self, instance): + delete = True + + model.moksha_mapper_extension.hooks['after_insert'].append(MyHook()) + + # create a new entity + something = Entity(u'something') + DBSession.add(something) + DBSession.flush() + assert insert + """
commit ab7d22e5f3726a658489f9cc7e41be681d85f1a6 Author: Luke Macken lmacken@redhat.com Date: Mon Mar 16 10:54:48 2009 -0400
Remove unneeded div creation
diff --git a/moksha/public/javascript/moksha.js b/moksha/public/javascript/moksha.js index d5ae03f..10cd51c 100644 --- a/moksha/public/javascript/moksha.js +++ b/moksha/public/javascript/moksha.js @@ -83,7 +83,6 @@ moksha = { if (!fragment.jquery) fragment = $(fragment);
- var $div = $('<div />'); var $f = moksha.filter_scripts(fragment);
return $f; @@ -152,4 +151,4 @@ moksha = {
}
-})(); \ No newline at end of file +})();
moksha-commits@lists.fedorahosted.org