I finally figured it out after a week of killing myself...
There were several problems:
There is some conflict between Flask-Security and Flask-SSLify. Although the automatic https redirection works fine on the actual web server, in the tests it prevent logging in completely. I figured this out by making fake test routes and trying to
POST
random data. NoPOST
in the test client worked. To fix this, I had to change my test configDEBUG
toTrue
. Note that this is not a great workaround, since stuff like CSS and JS won't be compiled and other app behavior might be different...Flask-Security does not work with factory_boy(or I was not using factory_boy correctly?). I was trying to create users and roles through factory_boy because I saw some sample app tutorial that used it. After I fixed the above problem, it kept telling me that the user did not exist. I ended up stealing the code from Flask-Security's own tests for creating fake users with different roles.
The problematic code:
session = db.create_scoped_session()
class RoleFactory(SQLAlchemyModelFactory):
FACTORY_FOR = Role
FACTORY_SESSION = session
id = Sequence(int)
name = 'admin'
description = 'Administrator'
class EmployeeFactory(SQLAlchemyModelFactory):
FACTORY_FOR = Employee
FACTORY_SESSION = session
id = Sequence(int)
email = Sequence(lambda n: 'user{0}@app.com'.format(n))
password = LazyAttribute(lambda a: encrypt_password('password'))
username = Sequence(lambda n: 'user{0}'.format(n))
#last_login_at = datetime.utcnow()
#current_login_at = datetime.utcnow()
last_login_ip = '127.0.0.1'
current_login_ip = '127.0.0.1'
login_count = 1
roles = LazyAttribute(lambda _: [RoleFactory()])
active = True
This was my test case:
class MyAppTestCase(FlaskTestCaseMixin, MyTestCase):
def _create_app(self):
raise NotImplementedError
def _create_fixtures(self):
#self.user = EmployeeFactory()
populate_data(1)
def setUp(self):
super(MyAppTestCase, self).setUp()
self.app = self._create_app()
self.client = self.app.test_client()
self.app_context = self.app.app_context()
self.app_context.push()
db.create_all()
self._create_fixtures()
self._create_csrf_token()
def tearDown(self):
super(MyAppTestCase, self).tearDown()
db.drop_all()
self.app_context.pop()
def _post(self, route, data=None, content_type=None, follow_redirects=True, headers=None):
content_type = content_type or 'application/x-www-form-urlencoded'
return self.client.post(route, data=data, follow_redirects=follow_redirects, content_type=content_type, headers=headers)
def _login(self, email=None, password=None):
email = email or 'matt@lp.com' #self.user.email
password = password or 'password'
data = {
'email': email,
'password': password,
'remember': 'y'
}
return self._post('/login', data=data)