Skip to content

Commit

Permalink
Merge pull request #4 from proteanhq/enhancements/protean-0.0.11
Browse files Browse the repository at this point in the history
Enhancements to become compatible with Protean 0.0.11

- Upgrade to be compatible with Python 3.7+ only
- Upgrade other packages where possible
- Remove Schemas
- Change Test cases to use Fixtures
  • Loading branch information
subhashb authored Apr 30, 2019
2 parents 0616e9a + 0135308 commit 5f3a051
Show file tree
Hide file tree
Showing 15 changed files with 195 additions and 562 deletions.
426 changes: 0 additions & 426 deletions .pylintrc

This file was deleted.

3 changes: 2 additions & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
language: python
dist: xenial
python:
- '3.6'
- '3.7'
install:
- pip install -r requirements/test.txt
- python setup.py install
Expand Down
1 change: 0 additions & 1 deletion MANIFEST.in
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ include .bumpversion.cfg
include .coveragerc
include .cookiecutterrc
include .editorconfig
include .pylintrc

include AUTHORS.rst
include CHANGELOG.rst
Expand Down
2 changes: 1 addition & 1 deletion README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ Development

::

pyenv virtualenv -p python3.6 3.6.5 protean-flask-dev
pyenv virtualenv -p python3.7 3.7.2 protean-flask-dev

To run the all tests run::

Expand Down
6 changes: 1 addition & 5 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1 @@
click==7.0
protean==0.0.9
authentic==0.0.9
protean-flask==0.0.9
-r requirements/dev.txt
-r requirements/prod.txt
10 changes: 4 additions & 6 deletions requirements/dev.txt
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
check-manifest==0.37
coverage==4.5.1
-r prod.txt

check-manifest==0.38
coverage==4.5.3
docutils==0.14
flake8==3.5.0
pylint==2.0.0
tox==3.1.2
twine==1.11.0
4 changes: 4 additions & 0 deletions requirements/prod.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
click==7.0
protean==0.0.11
authentic==0.0.11
protean-flask==0.0.11
8 changes: 4 additions & 4 deletions requirements/test.txt
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
-r dev.txt

mock==2.0.0
pytest==3.6.3
pytest-cov==2.5.1
pytest-travis-fold==1.3.0
pluggy==0.9.0
pytest-cov==2.6.1
pytest-flake8==1.0.4
pluggy==0.6.0
pytest-travis-fold==1.3.0
pytest==4.4.1
8 changes: 4 additions & 4 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ def read(*names, **kwargs):
'Operating System :: POSIX :: Linux',
'Operating System :: OS/2',
'Programming Language :: Python',
'Programming Language :: Python :: 3.6',
'Programming Language :: Python :: 3.7',
'Programming Language :: Python :: 3 :: Only',
'Topic :: Database',
'Topic :: Software Development :: Libraries',
Expand All @@ -66,9 +66,9 @@ def read(*names, **kwargs):
],
install_requires=[
'click==7.0',
'protean==0.0.9',
'authentic==0.0.9',
'protean-flask==0.0.9'
'protean==0.0.11',
'authentic==0.0.11',
'protean-flask==0.0.11'
],
extras_require={
# eg:
Expand Down
53 changes: 53 additions & 0 deletions tests/conftest.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,57 @@
"""Module to setup Factories and other required artifacts for tests"""
import os

import pytest

os.environ['PROTEAN_CONFIG'] = 'tests.support.sample_config'


def pytest_addoption(parser):
"""Additional options for running tests with pytest"""
parser.addoption(
"--slow", action="store_true", default=False, help="run slow tests"
)


def pytest_collection_modifyitems(config, items):
"""Configure special markers on tests, so as to control execution"""
if config.getoption("--slow"):
# --slow given in cli: do not skip slow tests
return
skip_slow = pytest.mark.skip(reason="need --slow option to run")
for item in items:
if "slow" in item.keywords:
item.add_marker(skip_slow)


@pytest.fixture(scope="session", autouse=True)
def register_models():
"""Register Test Models with Dict Repo
Run only once for the entire test suite
"""
from protean.core.repository import repo_factory
from authentic.utils import get_account_entity

from .support.sample_app.entities import Human

Account = get_account_entity()

repo_factory.register(Account)
repo_factory.register(Human)


@pytest.fixture(autouse=True)
def run_around_tests():
"""Cleanup Database after each test run"""
from protean.core.repository import repo_factory
from authentic.utils import get_account_entity
from .support.sample_app.entities import Human

Account = get_account_entity()

# A test function will be run at this point
yield

repo_factory.get_repository(Account).delete_all()
repo_factory.get_repository(Human).delete_all()
4 changes: 2 additions & 2 deletions tests/support/sample_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,9 @@
TESTING = True

# Define the repositories
REPOSITORIES = {
DATABASES = {
'default': {
'PROVIDER': 'protean.impl.repository.dict_repo'
'PROVIDER': 'protean.impl.repository.dict_repo.DictProvider'
}
}

Expand Down
103 changes: 59 additions & 44 deletions tests/test_account_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@
import base64
import json

import pytest
from authentic.utils import get_account_entity
from passlib.hash import pbkdf2_sha256
from protean.core.repository import repo_factory

from .support.sample_app import app

Expand All @@ -14,32 +14,34 @@
class TestViews:
"""Class to test all the account blueprint views"""

@classmethod
def setup_class(cls):
""" Setup for this test case"""
@pytest.fixture(scope="function", autouse=True)
def client(self):
""" Setup client for test cases """
yield app.test_client()

# Create the test client
cls.client = app.test_client()
cls.auth_header = {
@pytest.fixture(scope="function", autouse=True)
def auth_header(self):
""" Setup auth header for test cases """
header = {
'Authorization': b'Basic ' +
base64.b64encode(b'janedoe:duMmy@123')
}
yield header

# Create a test account
cls.account = Account.create({
@pytest.fixture(scope="function", autouse=True)
def account(self):
""" Setup dummy account for test cases """

new_account = Account.create({
'email': '[email protected]',
'username': 'janedoe',
'name': 'Jane Doe',
'password': pbkdf2_sha256.hash('duMmy@123'),
'phone': '90080000800',
})
yield new_account

@classmethod
def teardown_class(cls):
""" Teardown for this test case """
repo_factory.Account.delete_all()

def test_create(self):
def test_create(self, client, auth_header):
""" Test creating an account """

# Create an account object
Expand All @@ -50,9 +52,9 @@ def test_create(self):
'password': 'heLLo@123',
'confirm_password': 'heLLo@123',
}
rv = self.client.post(
rv = client.post(
'/auth/accounts', data=json.dumps(account_info),
headers=self.auth_header, content_type='application/json')
headers=auth_header, content_type='application/json')
assert rv.status_code == 201

expected_resp = {
Expand All @@ -69,20 +71,20 @@ def test_create(self):
}
assert rv.json == expected_resp

def test_update(self):
def test_update(self, client, auth_header, account):
""" Test updating an existing account """

# update an account object
update_info = {
'phone': '9007007007',
}
rv = self.client.put(
f'/auth/accounts/{self.account.id}', data=json.dumps(update_info),
headers=self.auth_header, content_type='application/json')
rv = client.put(
f'/auth/accounts/{account.id}', data=json.dumps(update_info),
headers=auth_header, content_type='application/json')
assert rv.status_code == 200
expected_resp = {
'account': {'email': '[email protected]',
'id': self.account.id,
'id': account.id,
'is_active': True,
'is_locked': False,
'is_verified': False,
Expand All @@ -94,35 +96,48 @@ def test_update(self):
}
assert rv.json == expected_resp

def test_show(self):
def test_show(self, client, auth_header, account):
""" Test showing an existing account """

rv = self.client.get(
f'/auth/accounts/{self.account.id}', headers=self.auth_header)
rv = client.get(
f'/auth/accounts/{account.id}', headers=auth_header)
assert rv.status_code == 200
expected_resp = {
'account': {'email': '[email protected]',
'id': self.account.id,
'id': account.id,
'is_active': True,
'is_locked': False,
'is_verified': False,
'name': 'Jane Doe',
'phone': '9007007007',
'phone': '90080000800',
'timezone': None,
'title': None,
'username': 'janedoe'}
}
assert rv.json == expected_resp

def test_login(self):
def test_login(self, client, auth_header):
""" Test logging in using account credentials """

# Create an account object
account_info = {
'username': 'johnny',
'email': '[email protected]',
'name': 'John Doe',
'password': 'heLLo@123',
'confirm_password': 'heLLo@123',
}
rv = client.post(
'/auth/accounts', data=json.dumps(account_info),
headers=auth_header, content_type='application/json')
assert rv.status_code == 201

# Send the login request
credentials = {
'username_or_email': 'johnny',
'password': 'heLLo@79',
}
rv = self.client.post(
rv = client.post(
f'/auth/login', data=json.dumps(credentials),
content_type='application/json')
assert rv.status_code == 422
Expand All @@ -131,24 +146,24 @@ def test_login(self):

# Try using the right credentials
credentials['password'] = 'heLLo@123'
rv = self.client.post(
rv = client.post(
f'/auth/login', data=json.dumps(credentials),
content_type='application/json')
assert rv.status_code == 200
assert rv.json['username'] == 'johnny'

def test_logout(self):
def test_logout(self, client, auth_header):
""" Test logging out of the application """

# Send the logout request
rv = self.client.post(
'/auth/logout', data=json.dumps({}), headers=self.auth_header,
rv = client.post(
'/auth/logout', data=json.dumps({}), headers=auth_header,
content_type='application/json')

assert rv.status_code == 200
assert rv.json == {'message': 'success'}

def test_update_password(self):
def test_update_password(self, client, auth_header):
""" Test updating password of an account """

# update an account object
Expand All @@ -157,19 +172,19 @@ def test_update_password(self):
'new_password': 'duMmy@456',
'confirm_password': 'duMmy@456',
}
rv = self.client.post(
rv = client.post(
'/auth/accounts/change-password', data=json.dumps(password_update),
headers=self.auth_header, content_type='application/json')
headers=auth_header, content_type='application/json')
assert rv.status_code == 200

expected_resp = {'message': 'Success'}
assert rv.json == expected_resp

def test_reset_password(self):
def test_reset_password(self, client, account):
""" Test resetting the password for an account """

# Send a reset password request
rv = self.client.post(
rv = client.post(
'/auth/accounts/reset-password',
data=json.dumps({'email': '[email protected]'}),
content_type='application/json')
Expand All @@ -179,15 +194,15 @@ def test_reset_password(self):
assert rv.json == expected_resp

# Get the verification token for the account
account = Account.get(self.account.id)
account = Account.get(account.id)
assert account.verification_token is not None

# Send the reset password request
password_update = {
'new_password': 'duMmy@789',
'confirm_password': 'duMmy@789',
}
rv = self.client.post(
rv = client.post(
f'/auth/accounts/reset-password/{account.verification_token}',
data=json.dumps(password_update),
content_type='application/json')
Expand All @@ -196,12 +211,12 @@ def test_reset_password(self):
expected_resp = {'message': 'Success'}
assert rv.json == expected_resp

def test_delete(self):
def test_delete(self, client, account):
""" Test deleting an existing account """
auth_header = {
'Authorization': b'Basic ' +
base64.b64encode(b'janedoe:duMmy@789')
base64.b64encode(b'janedoe:duMmy@123')
}
rv = self.client.delete(
f'/auth/accounts/{self.account.id}', headers=auth_header)
rv = client.delete(
f'/auth/accounts/{account.id}', headers=auth_header)
assert rv.status_code == 204
Loading

0 comments on commit 5f3a051

Please sign in to comment.