Add some first unit tests
This commit is contained in:
Generated
+1
@@ -3,6 +3,7 @@
|
|||||||
<component name="NewModuleRootManager" inherit-compiler-output="true">
|
<component name="NewModuleRootManager" inherit-compiler-output="true">
|
||||||
<exclude-output />
|
<exclude-output />
|
||||||
<content url="file://$MODULE_DIR$">
|
<content url="file://$MODULE_DIR$">
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/tests" isTestSource="true" />
|
||||||
<excludeFolder url="file://$MODULE_DIR$/.venv" />
|
<excludeFolder url="file://$MODULE_DIR$/.venv" />
|
||||||
</content>
|
</content>
|
||||||
<orderEntry type="jdk" jdkName="Python 3.10 (ActiveCollabAPI)" jdkType="Python SDK" />
|
<orderEntry type="jdk" jdkName="Python 3.10 (ActiveCollabAPI)" jdkType="Python SDK" />
|
||||||
|
|||||||
Generated
+20
@@ -0,0 +1,20 @@
|
|||||||
|
<component name="ProjectRunConfigurationManager">
|
||||||
|
<configuration default="false" name="Unittests" type="tests" factoryName="Unittests">
|
||||||
|
<module name="ActiveCollabAPI" />
|
||||||
|
<option name="ENV_FILES" value="" />
|
||||||
|
<option name="INTERPRETER_OPTIONS" value="" />
|
||||||
|
<option name="PARENT_ENVS" value="true" />
|
||||||
|
<option name="SDK_HOME" value="$PROJECT_DIR$/.venv/bin/python" />
|
||||||
|
<option name="SDK_NAME" value="Python 3.10 (ActiveCollabAPI)" />
|
||||||
|
<option name="WORKING_DIRECTORY" value="" />
|
||||||
|
<option name="IS_MODULE_SDK" value="false" />
|
||||||
|
<option name="ADD_CONTENT_ROOTS" value="true" />
|
||||||
|
<option name="ADD_SOURCE_ROOTS" value="true" />
|
||||||
|
<EXTENSION ID="PythonCoverageRunConfigurationExtension" runner="coverage.py" />
|
||||||
|
<option name="_new_pattern" value="""" />
|
||||||
|
<option name="_new_additionalArguments" value="""" />
|
||||||
|
<option name="_new_target" value="""" />
|
||||||
|
<option name="_new_targetType" value=""PATH"" />
|
||||||
|
<method v="2" />
|
||||||
|
</configuration>
|
||||||
|
</component>
|
||||||
@@ -3,17 +3,20 @@ import json
|
|||||||
|
|
||||||
# 3rd party libs
|
# 3rd party libs
|
||||||
import requests
|
import requests
|
||||||
|
from requests import Response
|
||||||
|
|
||||||
from ActiveCollabAPI import AC_LOGIN_BASE_URL, AC_USER_AGENT
|
from ActiveCollabAPI import AC_LOGIN_BASE_URL, AC_USER_AGENT
|
||||||
|
|
||||||
|
|
||||||
class ACAuthenticator:
|
class ACAuthenticator:
|
||||||
|
base_url = ""
|
||||||
base_url = AC_LOGIN_BASE_URL
|
|
||||||
|
|
||||||
user = None
|
user = None
|
||||||
accounts = None
|
accounts = None
|
||||||
|
|
||||||
|
def __init__(self, base_url: str):
|
||||||
|
self.base_url = base_url
|
||||||
|
|
||||||
def headers(self):
|
def headers(self):
|
||||||
return {
|
return {
|
||||||
'Content-Type': 'application/json; charset=utf8',
|
'Content-Type': 'application/json; charset=utf8',
|
||||||
@@ -21,14 +24,18 @@ class ACAuthenticator:
|
|||||||
'User-Agent': AC_USER_AGENT
|
'User-Agent': AC_USER_AGENT
|
||||||
}
|
}
|
||||||
|
|
||||||
def login(self, email, password):
|
def login(self, email: str, password: str) -> Response:
|
||||||
login_data = {
|
login_data = {
|
||||||
'email': email,
|
'email': email,
|
||||||
'password': password
|
'password': password
|
||||||
}
|
}
|
||||||
res = requests.post(self.base_url,
|
return requests.post(self.base_url,
|
||||||
data=json.dumps(login_data),
|
data=json.dumps(login_data),
|
||||||
headers=self.headers())
|
headers=self.headers())
|
||||||
|
|
||||||
|
def login_with_check(self, email: str, password: str):
|
||||||
|
res = self.login(email, password)
|
||||||
|
|
||||||
if res.status_code != 200:
|
if res.status_code != 200:
|
||||||
raise Exception('Login failed!')
|
raise Exception('Login failed!')
|
||||||
|
|
||||||
@@ -38,7 +45,7 @@ class ACAuthenticator:
|
|||||||
|
|
||||||
self.user = login_res['user']
|
self.user = login_res['user']
|
||||||
self.accounts = login_res['accounts']
|
self.accounts = login_res['accounts']
|
||||||
return login_res
|
return res
|
||||||
|
|
||||||
def find_account(self, value, key='user_display_name'):
|
def find_account(self, value, key='user_display_name'):
|
||||||
found = list(filter(lambda a: a[key] == value,
|
found = list(filter(lambda a: a[key] == value,
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import configparser
|
|||||||
import logging
|
import logging
|
||||||
from pprint import pprint
|
from pprint import pprint
|
||||||
|
|
||||||
|
from ActiveCollabAPI import AC_LOGIN_BASE_URL
|
||||||
from ActiveCollabAPI.ACAuthenticator import ACAuthenticator
|
from ActiveCollabAPI.ACAuthenticator import ACAuthenticator
|
||||||
from ActiveCollabAPI.ACClient import ACClient
|
from ActiveCollabAPI.ACClient import ACClient
|
||||||
from ActiveCollabAPI.ACTokenAuthenticator import ACTokenAuthenticator
|
from ActiveCollabAPI.ACTokenAuthenticator import ACTokenAuthenticator
|
||||||
@@ -19,7 +20,8 @@ requests_log = logging.getLogger("urllib3")
|
|||||||
requests_log.setLevel(logging.DEBUG)
|
requests_log.setLevel(logging.DEBUG)
|
||||||
requests_log.propagate = True
|
requests_log.propagate = True
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
|
def main():
|
||||||
config = configparser.ConfigParser()
|
config = configparser.ConfigParser()
|
||||||
config.read('config.ini')
|
config.read('config.ini')
|
||||||
|
|
||||||
@@ -28,32 +30,37 @@ if __name__ == "__main__":
|
|||||||
account_name = config['LOGIN']['account_name']
|
account_name = config['LOGIN']['account_name']
|
||||||
|
|
||||||
# 1. you need to log in to get a session and a list of accounts
|
# 1. you need to log in to get a session and a list of accounts
|
||||||
auth = ACAuthenticator()
|
auth = ACAuthenticator(AC_LOGIN_BASE_URL)
|
||||||
session = auth.login(username, password)
|
auth.login_with_check(username, password)
|
||||||
pprint(session)
|
|
||||||
user = session['user']
|
|
||||||
# use first account
|
# use first account
|
||||||
account = auth.find_account(account_name)
|
account = auth.find_account(account_name)
|
||||||
|
|
||||||
# 2. you need to get a token for this account
|
# 2. you need to get a token for this account
|
||||||
# token = ACTokenAuthenticator(account, user).issue_token_intent()
|
token = ACTokenAuthenticator(account, auth.user).issue_token_intent()
|
||||||
# pprint(token)
|
# pprint(token)
|
||||||
|
|
||||||
# 3. now you can query the API
|
# 3. now you can query the API
|
||||||
# ac = ACClient(account, token)
|
ac = ACClient(account, token)
|
||||||
|
|
||||||
|
# check version
|
||||||
|
res = ac.get_info()
|
||||||
|
ac_version = res.json()
|
||||||
|
pprint(ac_version)
|
||||||
|
if ac_version['version'] != '7.4.337':
|
||||||
|
raise Exception("Supporting only Version 7.4.337!")
|
||||||
|
|
||||||
# get a list of all projects
|
# get a list of all projects
|
||||||
# res = ac.get_projects()
|
# res = ac.get_projects()
|
||||||
# pprint(res.json())
|
# pprint(res.json())
|
||||||
|
|
||||||
# get task with sub tasks
|
# get task with sub-tasks
|
||||||
# https://app.activecollab.com/416910/projects/310/tasks/6274
|
# "https://app.activecollab.com/416910/projects/310/tasks/6260"
|
||||||
# project_id = 310
|
# project_id = 310
|
||||||
# task_id = 6281
|
# task_id = 6260
|
||||||
# task_res = ac.get_project_task(project_id, task_id)
|
# task_res = ac.get_project_task(project_id, task_id)
|
||||||
# pprint(task_res.json())
|
# pprint(task_res.json())
|
||||||
# task = task_res.json()
|
# task = task_res.json()
|
||||||
# res = ac.unassign_all_sub_task(task)
|
# ac.delete_all_open_subtasks(task)
|
||||||
|
|
||||||
# create a new subtask for the task without assignment
|
# create a new subtask for the task without assignment
|
||||||
# subtask = {
|
# subtask = {
|
||||||
@@ -66,10 +73,10 @@ if __name__ == "__main__":
|
|||||||
# pprint(res.json())
|
# pprint(res.json())
|
||||||
|
|
||||||
# # bulk create subtasks
|
# # bulk create subtasks
|
||||||
subtask_texts = []
|
# subtask_texts = []
|
||||||
with open("sub-tasks.txt", "r", encoding="utf-8") as fh:
|
# with open("sub-tasks.txt", "r", encoding="utf-8") as fh:
|
||||||
for line in fh:
|
# for line in fh:
|
||||||
subtask_texts.append(line.rstrip('\n'))
|
# subtask_texts.append(line.rstrip('\n'))
|
||||||
# create
|
# create
|
||||||
# for text in subtask_texts:
|
# for text in subtask_texts:
|
||||||
# subtask['body'] = text
|
# subtask['body'] = text
|
||||||
@@ -98,5 +105,10 @@ if __name__ == "__main__":
|
|||||||
# res = ac.delete_subtask(subtask)
|
# res = ac.delete_subtask(subtask)
|
||||||
# pprint(res.json())
|
# pprint(res.json())
|
||||||
|
|
||||||
# res = ac.get_info()
|
res = ac.get_projects()
|
||||||
# pprint(res.json())
|
if res.status_code == 200:
|
||||||
|
pprint(res.json())
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
|
|||||||
@@ -0,0 +1,85 @@
|
|||||||
|
import json
|
||||||
|
from unittest import TestCase
|
||||||
|
from unittest.mock import patch
|
||||||
|
|
||||||
|
from ActiveCollabAPI import AC_LOGIN_BASE_URL
|
||||||
|
from ActiveCollabAPI.ACAuthenticator import ACAuthenticator
|
||||||
|
|
||||||
|
|
||||||
|
class TestACAuthenticator(TestCase):
|
||||||
|
def test_headers(self):
|
||||||
|
authenticator = ACAuthenticator(AC_LOGIN_BASE_URL)
|
||||||
|
headers = authenticator.headers()
|
||||||
|
self.assertIn('Content-Type', headers)
|
||||||
|
self.assertEqual('application/json; charset=utf8', headers['Content-Type'])
|
||||||
|
self.assertIn('Accept', headers)
|
||||||
|
self.assertEqual('application/json', headers['Accept'])
|
||||||
|
self.assertIn('User-Agent', headers)
|
||||||
|
|
||||||
|
def mock_login_success(self):
|
||||||
|
return {
|
||||||
|
"accounts": [
|
||||||
|
{
|
||||||
|
"name": 12345678,
|
||||||
|
"url": "https:\/\/app.activecollab.com\/12345678",
|
||||||
|
"display_name": "433339",
|
||||||
|
"user_display_name": "#12345678",
|
||||||
|
"position": 1,
|
||||||
|
"class": "ActiveCollab\\Shepherd\\Model\\Account\\ActiveCollab\\FeatherAccount",
|
||||||
|
"status": "trial"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"is_ok": 1,
|
||||||
|
"user": {
|
||||||
|
"avatar_url": "https:\/\/activecollab.com\/avatar.php?user_id=12345678&size=80",
|
||||||
|
"first_name": "users first",
|
||||||
|
"last_name": "users last",
|
||||||
|
"intent": "random-string"}
|
||||||
|
}
|
||||||
|
|
||||||
|
def mock_login_failed(self):
|
||||||
|
return {
|
||||||
|
"is_ok": 3
|
||||||
|
}
|
||||||
|
|
||||||
|
def test_login_success_gets_user_and_accounts_list(self):
|
||||||
|
with patch("ActiveCollabAPI.ACAuthenticator.requests.post") as mock_post:
|
||||||
|
mock_post.return_value.status_code = 200
|
||||||
|
mock_post.return_value.json.return_value = self.mock_login_success()
|
||||||
|
|
||||||
|
email = "collab@example.com"
|
||||||
|
password = "VeryS3cret!"
|
||||||
|
authenticator = ACAuthenticator(AC_LOGIN_BASE_URL)
|
||||||
|
response = authenticator.login_with_check(email, password)
|
||||||
|
|
||||||
|
self.assertEquals(200, response.status_code)
|
||||||
|
res_data = response.json()
|
||||||
|
self.assertEqual(1, res_data['is_ok'])
|
||||||
|
user = res_data["user"]
|
||||||
|
self.assertEqual("users first", user["first_name"])
|
||||||
|
self.assertEqual("users last", user["last_name"])
|
||||||
|
accounts = res_data["accounts"]
|
||||||
|
self.assertGreater(len(accounts), 0)
|
||||||
|
self.assertEqual(12345678, accounts[0]["name"])
|
||||||
|
|
||||||
|
def test_login_failed_http401(self):
|
||||||
|
with self.assertRaises(Exception) as exc:
|
||||||
|
with patch("ActiveCollabAPI.ACAuthenticator.requests.post") as mock_post:
|
||||||
|
mock_post.return_value.status_code = 401
|
||||||
|
mock_post.return_value.json.return_value = self.mock_login_failed()
|
||||||
|
|
||||||
|
email = "collab@example.com"
|
||||||
|
password = "VeryS3cret!"
|
||||||
|
authenticator = ACAuthenticator(AC_LOGIN_BASE_URL)
|
||||||
|
response = authenticator.login_with_check(email, password)
|
||||||
|
|
||||||
|
def test_login_failed_not_ok(self):
|
||||||
|
with self.assertRaises(Exception) as exc:
|
||||||
|
with patch("ActiveCollabAPI.ACAuthenticator.requests.post") as mock_post:
|
||||||
|
mock_post.return_value.status_code = 200
|
||||||
|
mock_post.return_value.json.return_value = self.mock_login_failed()
|
||||||
|
|
||||||
|
email = "collab@example.com"
|
||||||
|
password = "VeryS3cret!"
|
||||||
|
authenticator = ACAuthenticator(AC_LOGIN_BASE_URL)
|
||||||
|
response = authenticator.login_with_check(email, password)
|
||||||
Reference in New Issue
Block a user