iatoolkit 0.8.1__py3-none-any.whl → 0.63.4__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of iatoolkit might be problematic. Click here for more details.
- iatoolkit/__init__.py +8 -34
- iatoolkit/base_company.py +14 -3
- iatoolkit/common/routes.py +83 -52
- iatoolkit/common/session_manager.py +0 -1
- iatoolkit/common/util.py +0 -27
- iatoolkit/iatoolkit.py +61 -46
- iatoolkit/infra/llm_client.py +7 -8
- iatoolkit/infra/openai_adapter.py +1 -1
- iatoolkit/infra/redis_session_manager.py +48 -2
- iatoolkit/repositories/database_manager.py +17 -2
- iatoolkit/repositories/models.py +31 -6
- iatoolkit/repositories/profile_repo.py +7 -2
- iatoolkit/services/auth_service.py +188 -0
- iatoolkit/services/branding_service.py +147 -0
- iatoolkit/services/dispatcher_service.py +10 -40
- iatoolkit/services/excel_service.py +15 -15
- iatoolkit/services/history_service.py +3 -12
- iatoolkit/services/jwt_service.py +15 -24
- iatoolkit/services/onboarding_service.py +43 -0
- iatoolkit/services/profile_service.py +97 -44
- iatoolkit/services/query_service.py +124 -81
- iatoolkit/services/tasks_service.py +1 -1
- iatoolkit/services/user_feedback_service.py +67 -31
- iatoolkit/services/user_session_context_service.py +112 -54
- iatoolkit/static/images/fernando.jpeg +0 -0
- iatoolkit/static/js/{chat_feedback.js → chat_feedback_button.js} +6 -11
- iatoolkit/static/js/chat_history_button.js +126 -0
- iatoolkit/static/js/chat_logout_button.js +36 -0
- iatoolkit/static/js/chat_main.js +130 -220
- iatoolkit/static/js/chat_onboarding_button.js +97 -0
- iatoolkit/static/js/chat_prompt_manager.js +94 -0
- iatoolkit/static/js/chat_reload_button.js +52 -0
- iatoolkit/static/styles/chat_iatoolkit.css +329 -507
- iatoolkit/static/styles/chat_modal.css +95 -56
- iatoolkit/static/styles/landing_page.css +182 -0
- iatoolkit/static/styles/onboarding.css +169 -0
- iatoolkit/system_prompts/query_main.prompt +3 -12
- iatoolkit/templates/_company_header.html +20 -0
- iatoolkit/templates/_login_widget.html +40 -0
- iatoolkit/templates/base.html +8 -3
- iatoolkit/templates/change_password.html +54 -37
- iatoolkit/templates/chat.html +149 -66
- iatoolkit/templates/chat_modals.html +47 -18
- iatoolkit/templates/error.html +41 -8
- iatoolkit/templates/forgot_password.html +37 -24
- iatoolkit/templates/index.html +140 -0
- iatoolkit/templates/login_simulation.html +34 -0
- iatoolkit/templates/onboarding_shell.html +105 -0
- iatoolkit/templates/signup.html +64 -66
- iatoolkit/views/base_login_view.py +81 -0
- iatoolkit/views/change_password_view.py +23 -12
- iatoolkit/views/external_login_view.py +61 -28
- iatoolkit/views/{file_store_view.py → file_store_api_view.py} +9 -2
- iatoolkit/views/forgot_password_view.py +23 -13
- iatoolkit/views/history_api_view.py +52 -0
- iatoolkit/views/home_view.py +58 -25
- iatoolkit/views/index_view.py +14 -0
- iatoolkit/views/init_context_api_view.py +68 -0
- iatoolkit/views/llmquery_api_view.py +45 -0
- iatoolkit/views/login_simulation_view.py +81 -0
- iatoolkit/views/login_view.py +118 -34
- iatoolkit/views/logout_api_view.py +45 -0
- iatoolkit/views/{prompt_view.py → prompt_api_view.py} +7 -7
- iatoolkit/views/signup_view.py +38 -29
- iatoolkit/views/{tasks_view.py → tasks_api_view.py} +10 -36
- iatoolkit/views/tasks_review_api_view.py +55 -0
- iatoolkit/views/{user_feedback_view.py → user_feedback_api_view.py} +16 -31
- iatoolkit/views/verify_user_view.py +13 -8
- {iatoolkit-0.8.1.dist-info → iatoolkit-0.63.4.dist-info}/METADATA +2 -2
- iatoolkit-0.63.4.dist-info/RECORD +113 -0
- {iatoolkit-0.8.1.dist-info → iatoolkit-0.63.4.dist-info}/top_level.txt +0 -1
- iatoolkit/common/auth.py +0 -200
- iatoolkit/static/images/arrow_up.png +0 -0
- iatoolkit/static/images/diagrama_iatoolkit.jpg +0 -0
- iatoolkit/static/images/logo_clinica.png +0 -0
- iatoolkit/static/images/logo_iatoolkit.png +0 -0
- iatoolkit/static/images/logo_maxxa.png +0 -0
- iatoolkit/static/images/logo_notaria.png +0 -0
- iatoolkit/static/images/logo_tarjeta.png +0 -0
- iatoolkit/static/images/logo_umayor.png +0 -0
- iatoolkit/static/images/upload.png +0 -0
- iatoolkit/static/js/chat_history.js +0 -117
- iatoolkit/templates/home.html +0 -201
- iatoolkit/templates/login.html +0 -43
- iatoolkit/views/chat_token_request_view.py +0 -98
- iatoolkit/views/chat_view.py +0 -51
- iatoolkit/views/download_file_view.py +0 -58
- iatoolkit/views/external_chat_login_view.py +0 -88
- iatoolkit/views/history_view.py +0 -57
- iatoolkit/views/llmquery_view.py +0 -65
- iatoolkit/views/tasks_review_view.py +0 -83
- iatoolkit-0.8.1.dist-info/RECORD +0 -175
- tests/__init__.py +0 -5
- tests/common/__init__.py +0 -0
- tests/common/test_auth.py +0 -279
- tests/common/test_routes.py +0 -42
- tests/common/test_session_manager.py +0 -59
- tests/common/test_util.py +0 -444
- tests/companies/__init__.py +0 -5
- tests/conftest.py +0 -36
- tests/infra/__init__.py +0 -5
- tests/infra/connectors/__init__.py +0 -5
- tests/infra/connectors/test_google_drive_connector.py +0 -107
- tests/infra/connectors/test_local_file_connector.py +0 -85
- tests/infra/connectors/test_s3_connector.py +0 -95
- tests/infra/test_call_service.py +0 -92
- tests/infra/test_database_manager.py +0 -59
- tests/infra/test_gemini_adapter.py +0 -137
- tests/infra/test_google_chat_app.py +0 -68
- tests/infra/test_llm_client.py +0 -165
- tests/infra/test_llm_proxy.py +0 -122
- tests/infra/test_mail_app.py +0 -94
- tests/infra/test_openai_adapter.py +0 -105
- tests/infra/test_redis_session_manager_service.py +0 -117
- tests/repositories/__init__.py +0 -5
- tests/repositories/test_database_manager.py +0 -87
- tests/repositories/test_document_repo.py +0 -76
- tests/repositories/test_llm_query_repo.py +0 -340
- tests/repositories/test_models.py +0 -38
- tests/repositories/test_profile_repo.py +0 -142
- tests/repositories/test_tasks_repo.py +0 -76
- tests/repositories/test_vs_repo.py +0 -107
- tests/services/__init__.py +0 -5
- tests/services/test_dispatcher_service.py +0 -274
- tests/services/test_document_service.py +0 -181
- tests/services/test_excel_service.py +0 -208
- tests/services/test_file_processor_service.py +0 -121
- tests/services/test_history_service.py +0 -164
- tests/services/test_jwt_service.py +0 -255
- tests/services/test_load_documents_service.py +0 -112
- tests/services/test_mail_service.py +0 -70
- tests/services/test_profile_service.py +0 -379
- tests/services/test_prompt_manager_service.py +0 -190
- tests/services/test_query_service.py +0 -243
- tests/services/test_search_service.py +0 -39
- tests/services/test_sql_service.py +0 -160
- tests/services/test_tasks_service.py +0 -252
- tests/services/test_user_feedback_service.py +0 -389
- tests/services/test_user_session_context_service.py +0 -132
- tests/views/__init__.py +0 -5
- tests/views/test_change_password_view.py +0 -191
- tests/views/test_chat_token_request_view.py +0 -188
- tests/views/test_chat_view.py +0 -98
- tests/views/test_download_file_view.py +0 -149
- tests/views/test_external_chat_login_view.py +0 -120
- tests/views/test_external_login_view.py +0 -102
- tests/views/test_file_store_view.py +0 -128
- tests/views/test_forgot_password_view.py +0 -142
- tests/views/test_history_view.py +0 -336
- tests/views/test_home_view.py +0 -61
- tests/views/test_llm_query_view.py +0 -154
- tests/views/test_login_view.py +0 -114
- tests/views/test_prompt_view.py +0 -111
- tests/views/test_signup_view.py +0 -140
- tests/views/test_tasks_review_view.py +0 -104
- tests/views/test_tasks_view.py +0 -130
- tests/views/test_user_feedback_view.py +0 -214
- tests/views/test_verify_user_view.py +0 -110
- {iatoolkit-0.8.1.dist-info → iatoolkit-0.63.4.dist-info}/WHEEL +0 -0
tests/views/test_prompt_view.py
DELETED
|
@@ -1,111 +0,0 @@
|
|
|
1
|
-
# Copyright (c) 2024 Fernando Libedinsky
|
|
2
|
-
# Product: IAToolkit
|
|
3
|
-
#
|
|
4
|
-
# IAToolkit is open source software.
|
|
5
|
-
|
|
6
|
-
import pytest
|
|
7
|
-
from unittest.mock import MagicMock
|
|
8
|
-
from flask import Flask
|
|
9
|
-
from iatoolkit.views.prompt_view import PromptView
|
|
10
|
-
from iatoolkit.services.prompt_manager_service import PromptService
|
|
11
|
-
from iatoolkit.common.auth import IAuthentication
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
class TestPromptView:
|
|
15
|
-
@staticmethod
|
|
16
|
-
def create_app():
|
|
17
|
-
"""Creates a Flask app instance for testing."""
|
|
18
|
-
app = Flask(__name__)
|
|
19
|
-
app.testing = True
|
|
20
|
-
return app
|
|
21
|
-
|
|
22
|
-
@pytest.fixture(autouse=True)
|
|
23
|
-
def setup(self):
|
|
24
|
-
"""Set up the test client and mock dependencies for each test."""
|
|
25
|
-
self.app = self.create_app()
|
|
26
|
-
self.client = self.app.test_client()
|
|
27
|
-
self.prompt_service = MagicMock(spec=PromptService)
|
|
28
|
-
self.iauthentication = MagicMock(spec=IAuthentication)
|
|
29
|
-
|
|
30
|
-
# Default to successful authentication
|
|
31
|
-
self.iauthentication.verify.return_value = {'success': True}
|
|
32
|
-
|
|
33
|
-
# Register the view with mocked dependencies
|
|
34
|
-
prompt_view = PromptView.as_view("prompt",
|
|
35
|
-
iauthentication=self.iauthentication,
|
|
36
|
-
prompt_service=self.prompt_service)
|
|
37
|
-
self.app.add_url_rule('/<company_short_name>/prompts',
|
|
38
|
-
view_func=prompt_view,
|
|
39
|
-
methods=["GET"])
|
|
40
|
-
|
|
41
|
-
def test_get_when_auth_error(self):
|
|
42
|
-
"""Test response when authentication fails."""
|
|
43
|
-
self.iauthentication.verify.return_value = {
|
|
44
|
-
'success': False,
|
|
45
|
-
'error_message': 'Authentication token is invalid'
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
response = self.client.get('/test_company/prompts')
|
|
49
|
-
|
|
50
|
-
assert response.status_code == 401
|
|
51
|
-
assert response.json['error_message'] == 'Authentication token is invalid'
|
|
52
|
-
self.prompt_service.get_user_prompts.assert_not_called()
|
|
53
|
-
|
|
54
|
-
def test_get_when_service_returns_error(self):
|
|
55
|
-
"""Test response when the prompt service returns a logical error."""
|
|
56
|
-
self.prompt_service.get_user_prompts.return_value = {
|
|
57
|
-
'error': 'Company not configured for prompts'
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
response = self.client.get('/test_company/prompts')
|
|
61
|
-
|
|
62
|
-
assert response.status_code == 402
|
|
63
|
-
assert response.json['error_message'] == 'Company not configured for prompts'
|
|
64
|
-
self.iauthentication.verify.assert_called_once_with('test_company')
|
|
65
|
-
self.prompt_service.get_user_prompts.assert_called_once_with('test_company')
|
|
66
|
-
|
|
67
|
-
def test_get_when_service_raises_exception(self):
|
|
68
|
-
"""Test response when the prompt service raises an unhandled exception."""
|
|
69
|
-
self.prompt_service.get_user_prompts.side_effect = Exception('Unexpected database error')
|
|
70
|
-
|
|
71
|
-
response = self.client.get('/test_company/prompts')
|
|
72
|
-
|
|
73
|
-
assert response.status_code == 500
|
|
74
|
-
assert response.json['error_message'] == 'Unexpected database error'
|
|
75
|
-
|
|
76
|
-
def test_get_success(self):
|
|
77
|
-
"""Test a successful request to retrieve prompts."""
|
|
78
|
-
mock_response = {
|
|
79
|
-
'message': [
|
|
80
|
-
{'prompt': 'sales_prompt', 'description': 'A prompt for sales questions'},
|
|
81
|
-
{'prompt': 'support_prompt', 'description': 'A prompt for support inquiries'}
|
|
82
|
-
]
|
|
83
|
-
}
|
|
84
|
-
self.prompt_service.get_user_prompts.return_value = mock_response
|
|
85
|
-
|
|
86
|
-
response = self.client.get('/test_company/prompts')
|
|
87
|
-
|
|
88
|
-
assert response.status_code == 200
|
|
89
|
-
assert response.json == mock_response
|
|
90
|
-
self.iauthentication.verify.assert_called_once_with('test_company')
|
|
91
|
-
self.prompt_service.get_user_prompts.assert_called_once_with('test_company')
|
|
92
|
-
|
|
93
|
-
def test_get_success_with_empty_list(self):
|
|
94
|
-
"""Test a successful request that results in an empty list of prompts."""
|
|
95
|
-
mock_response = {'message': []}
|
|
96
|
-
self.prompt_service.get_user_prompts.return_value = mock_response
|
|
97
|
-
|
|
98
|
-
response = self.client.get('/test_company/prompts')
|
|
99
|
-
|
|
100
|
-
assert response.status_code == 200
|
|
101
|
-
assert response.json == mock_response
|
|
102
|
-
|
|
103
|
-
def test_get_calls_services_with_correct_company(self):
|
|
104
|
-
"""Test that services are called with the correct company name from the URL."""
|
|
105
|
-
self.prompt_service.get_user_prompts.return_value = {'message': []}
|
|
106
|
-
|
|
107
|
-
company_name = 'another-company'
|
|
108
|
-
self.client.get(f'/{company_name}/prompts')
|
|
109
|
-
|
|
110
|
-
self.iauthentication.verify.assert_called_once_with(company_name)
|
|
111
|
-
self.prompt_service.get_user_prompts.assert_called_once_with(company_name)
|
tests/views/test_signup_view.py
DELETED
|
@@ -1,140 +0,0 @@
|
|
|
1
|
-
# Copyright (c) 2024 Fernando Libedinsky
|
|
2
|
-
# Product: IAToolkit
|
|
3
|
-
#
|
|
4
|
-
# IAToolkit is open source software.
|
|
5
|
-
|
|
6
|
-
import pytest
|
|
7
|
-
from flask import Flask
|
|
8
|
-
from unittest.mock import MagicMock, patch
|
|
9
|
-
from iatoolkit.services.profile_service import ProfileService
|
|
10
|
-
from iatoolkit.views.signup_view import SignupView
|
|
11
|
-
from iatoolkit.repositories.models import Company
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
class TestSignupView:
|
|
15
|
-
@staticmethod
|
|
16
|
-
def create_app():
|
|
17
|
-
"""Configura la aplicación Flask para pruebas."""
|
|
18
|
-
app = Flask(__name__)
|
|
19
|
-
app.testing = True
|
|
20
|
-
|
|
21
|
-
return app
|
|
22
|
-
|
|
23
|
-
@pytest.fixture(autouse=True)
|
|
24
|
-
def setup(self):
|
|
25
|
-
"""Configura el cliente y los mocks antes de cada test."""
|
|
26
|
-
self.app = self.create_app()
|
|
27
|
-
self.client = self.app.test_client()
|
|
28
|
-
self.profile_service = MagicMock(spec=ProfileService)
|
|
29
|
-
self.test_company = Company(
|
|
30
|
-
id=1,
|
|
31
|
-
name="Empresa de Prueba",
|
|
32
|
-
short_name="test_company",
|
|
33
|
-
logo_file="test_logo.png"
|
|
34
|
-
)
|
|
35
|
-
self.profile_service.get_company_by_short_name.return_value = self.test_company
|
|
36
|
-
|
|
37
|
-
# Registrar la vista
|
|
38
|
-
view = SignupView.as_view("signup", profile_service=self.profile_service)
|
|
39
|
-
self.app.add_url_rule("/<company_short_name>/signup", view_func=view, methods=["GET", "POST"])
|
|
40
|
-
|
|
41
|
-
@patch("iatoolkit.views.signup_view.render_template")
|
|
42
|
-
@patch("iatoolkit.views.signup_view.URLSafeTimedSerializer")
|
|
43
|
-
def test_get_when_invalid_company(self, mock_serializer, mock_render):
|
|
44
|
-
mock_serializer.return_value.loads.return_value = "nonexistent@email.com"
|
|
45
|
-
self.profile_service.get_company_by_short_name.return_value = None
|
|
46
|
-
response = self.client.get("/test_company/signup")
|
|
47
|
-
assert response.status_code == 404
|
|
48
|
-
|
|
49
|
-
@patch("iatoolkit.views.signup_view.render_template")
|
|
50
|
-
@patch("iatoolkit.views.signup_view.URLSafeTimedSerializer")
|
|
51
|
-
def test_post_when_invalid_company(self, mock_serializer, mock_render):
|
|
52
|
-
mock_serializer.return_value.loads.return_value = "nonexistent@email.com"
|
|
53
|
-
self.profile_service.get_company_by_short_name.return_value = None
|
|
54
|
-
response = self.client.post("/test_company/signup",
|
|
55
|
-
data={},
|
|
56
|
-
content_type="application/x-www-form-urlencoded")
|
|
57
|
-
|
|
58
|
-
assert response.status_code == 404
|
|
59
|
-
|
|
60
|
-
@patch("iatoolkit.views.signup_view.render_template")
|
|
61
|
-
@patch("iatoolkit.views.signup_view.URLSafeTimedSerializer")
|
|
62
|
-
def test_get_signup_page(self, mock_serializer, mock_render_template):
|
|
63
|
-
mock_serializer.return_value.loads.return_value = "nonexistent@email.com"
|
|
64
|
-
mock_render_template.return_value = "<html><body><h1>Signup Page</h1></body></html>"
|
|
65
|
-
response = self.client.get("/test_company/signup")
|
|
66
|
-
|
|
67
|
-
assert response.status_code == 200
|
|
68
|
-
|
|
69
|
-
@patch("iatoolkit.views.signup_view.render_template")
|
|
70
|
-
@patch("iatoolkit.views.signup_view.url_for")
|
|
71
|
-
@patch("iatoolkit.views.signup_view.URLSafeTimedSerializer")
|
|
72
|
-
def test_post_with_error(self, mock_serializer, mock_url_for, mock_render_template):
|
|
73
|
-
mock_serializer.return_value.loads.return_value = "nonexistent@email.com"
|
|
74
|
-
mock_url_for.return_value = 'http://verification'
|
|
75
|
-
mock_render_template.return_value = "<html><body></body></html>"
|
|
76
|
-
self.profile_service.signup.return_value = \
|
|
77
|
-
{'error': 'user exists'}
|
|
78
|
-
|
|
79
|
-
response = self.client.post("/test_company/signup",
|
|
80
|
-
data={
|
|
81
|
-
"first_name": "Juan",
|
|
82
|
-
"last_name": "Perez",
|
|
83
|
-
"email": "test@email.com",
|
|
84
|
-
"password": "password123",
|
|
85
|
-
"confirm_password": "password123"
|
|
86
|
-
},
|
|
87
|
-
content_type="application/x-www-form-urlencoded")
|
|
88
|
-
|
|
89
|
-
assert response.status_code == 400
|
|
90
|
-
|
|
91
|
-
@patch("iatoolkit.views.signup_view.render_template")
|
|
92
|
-
@patch("iatoolkit.views.signup_view.url_for")
|
|
93
|
-
@patch("iatoolkit.views.signup_view.URLSafeTimedSerializer")
|
|
94
|
-
def test_post_when_ok(self, mock_serializer, mock_url_for, mock_render_template):
|
|
95
|
-
mock_render_template.return_value = "<html><body></body></html>"
|
|
96
|
-
mock_serializer.return_value.loads.return_value = "nonexistent@email.com"
|
|
97
|
-
mock_url_for.return_value = 'http://verification'
|
|
98
|
-
self.profile_service.signup.return_value = \
|
|
99
|
-
{"message": "User created"}
|
|
100
|
-
|
|
101
|
-
response = self.client.post("/test_company/signup",
|
|
102
|
-
data={
|
|
103
|
-
"first_name": "Juan",
|
|
104
|
-
"last_name": "Perez",
|
|
105
|
-
"email": "juan@email.com",
|
|
106
|
-
"password": "password123",
|
|
107
|
-
"confirm_password": "password123"
|
|
108
|
-
},
|
|
109
|
-
content_type="application/x-www-form-urlencoded")
|
|
110
|
-
|
|
111
|
-
assert response.status_code == 200
|
|
112
|
-
mock_render_template.assert_called_once_with(
|
|
113
|
-
"login.html",
|
|
114
|
-
company=self.test_company,
|
|
115
|
-
company_short_name='test_company',
|
|
116
|
-
alert_message="User created",
|
|
117
|
-
alert_icon='success'
|
|
118
|
-
)
|
|
119
|
-
|
|
120
|
-
@patch("iatoolkit.views.signup_view.render_template")
|
|
121
|
-
@patch("iatoolkit.views.signup_view.URLSafeTimedSerializer")
|
|
122
|
-
def test_post_unexpected_error(self, mock_serializer, mock_render_template):
|
|
123
|
-
mock_serializer.return_value.loads.side_effect = Exception('an error')
|
|
124
|
-
response = self.client.post("/test_company/signup",
|
|
125
|
-
data={
|
|
126
|
-
"first_name": "Juan",
|
|
127
|
-
"last_name": "Perez",
|
|
128
|
-
"email": "juan@email.com",
|
|
129
|
-
"password": "password123",
|
|
130
|
-
"confirm_password": "password123"
|
|
131
|
-
},
|
|
132
|
-
content_type="application/x-www-form-urlencoded")
|
|
133
|
-
|
|
134
|
-
mock_render_template.assert_called_once_with(
|
|
135
|
-
"error.html",
|
|
136
|
-
company=self.test_company,
|
|
137
|
-
company_short_name='test_company',
|
|
138
|
-
message="Ha ocurrido un error inesperado."
|
|
139
|
-
)
|
|
140
|
-
assert response.status_code == 500
|
|
@@ -1,104 +0,0 @@
|
|
|
1
|
-
# Copyright (c) 2024 Fernando Libedinsky
|
|
2
|
-
# Product: IAToolkit
|
|
3
|
-
#
|
|
4
|
-
# IAToolkit is open source software.
|
|
5
|
-
|
|
6
|
-
import pytest
|
|
7
|
-
from unittest.mock import MagicMock
|
|
8
|
-
from flask import Flask
|
|
9
|
-
from iatoolkit.repositories.profile_repo import ProfileRepo
|
|
10
|
-
from iatoolkit.views.tasks_review_view import TaskReviewView
|
|
11
|
-
from iatoolkit.services.tasks_service import TaskService, TaskStatus
|
|
12
|
-
from iatoolkit.repositories.models import Company, ApiKey
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
class TestTaskReviewView:
|
|
17
|
-
|
|
18
|
-
def setup_method(self):
|
|
19
|
-
self.app = Flask(__name__)
|
|
20
|
-
self.client = self.app.test_client()
|
|
21
|
-
|
|
22
|
-
self.mock_task_service = MagicMock(spec=TaskService)
|
|
23
|
-
self.mock_profile_repo = MagicMock(spec=ProfileRepo)
|
|
24
|
-
|
|
25
|
-
# Instanciamos la vista con el mock del servicio
|
|
26
|
-
self.task_review_view = TaskReviewView.as_view("tasks-review",
|
|
27
|
-
task_service=self.mock_task_service,
|
|
28
|
-
profile_repo=self.mock_profile_repo)
|
|
29
|
-
self.app.add_url_rule('/tasks/review/<int:task_id>', view_func=self.task_review_view, methods=["POST"])
|
|
30
|
-
|
|
31
|
-
# API Key exitosa
|
|
32
|
-
self.api_key = ApiKey(key="test_key", company_id=100)
|
|
33
|
-
self.api_key.company = Company(id=100, name="Test Company", short_name="test_company")
|
|
34
|
-
self.mock_profile_repo.get_active_api_key_entry.return_value = self.api_key
|
|
35
|
-
self.valid_header = {"Authorization": f"Bearer {self.api_key.key}"}
|
|
36
|
-
|
|
37
|
-
@pytest.mark.parametrize("missing_field", ["review_user", "approved"])
|
|
38
|
-
def test_post_when_missing_required_fields(self, missing_field):
|
|
39
|
-
payload = {
|
|
40
|
-
"review_user": "test_username",
|
|
41
|
-
"approved": True,
|
|
42
|
-
"comment": "this is a comment",
|
|
43
|
-
}
|
|
44
|
-
payload.pop(missing_field)
|
|
45
|
-
|
|
46
|
-
response = self.client.post('/tasks/review/1',
|
|
47
|
-
headers=self.valid_header,
|
|
48
|
-
json=payload)
|
|
49
|
-
|
|
50
|
-
assert response.status_code == 400
|
|
51
|
-
assert response.get_json() == {
|
|
52
|
-
"error": f"El campo {missing_field} es requerido"
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
self.mock_task_service.create_task.assert_not_called()
|
|
56
|
-
|
|
57
|
-
def test_post_when_internal_exception_error(self):
|
|
58
|
-
self.mock_task_service.review_task.side_effect = Exception("Internal Error")
|
|
59
|
-
|
|
60
|
-
payload = {
|
|
61
|
-
"review_user": "test_username",
|
|
62
|
-
"approved": True,
|
|
63
|
-
"comment": "this is a comment",
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
response = self.client.post('/tasks/review/1',
|
|
67
|
-
headers=self.valid_header,
|
|
68
|
-
json=payload)
|
|
69
|
-
|
|
70
|
-
assert response.status_code == 500
|
|
71
|
-
assert response.get_json() == {
|
|
72
|
-
"error": "Internal Error"
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
self.mock_task_service.review_task.assert_called_once()
|
|
76
|
-
|
|
77
|
-
def test_post_when_successful_creation(self):
|
|
78
|
-
mocked_task = MagicMock()
|
|
79
|
-
mocked_task.id = 123
|
|
80
|
-
mocked_task.status = TaskStatus.aprobada
|
|
81
|
-
self.mock_task_service.review_task.return_value = mocked_task
|
|
82
|
-
|
|
83
|
-
payload = {
|
|
84
|
-
"review_user": "test_username",
|
|
85
|
-
"approved": True,
|
|
86
|
-
"comment": "this is a comment",
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
response = self.client.post('/tasks/review/1',
|
|
90
|
-
headers=self.valid_header,
|
|
91
|
-
json=payload)
|
|
92
|
-
|
|
93
|
-
assert response.status_code == 200
|
|
94
|
-
assert response.get_json() == {
|
|
95
|
-
"task_id": 123,
|
|
96
|
-
"status": "aprobada"
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
self.mock_task_service.review_task.assert_called_once_with(
|
|
100
|
-
task_id=1,
|
|
101
|
-
review_user="test_username",
|
|
102
|
-
approved=True,
|
|
103
|
-
comment="this is a comment"
|
|
104
|
-
)
|
tests/views/test_tasks_view.py
DELETED
|
@@ -1,130 +0,0 @@
|
|
|
1
|
-
# Copyright (c) 2024 Fernando Libedinsky
|
|
2
|
-
# Product: IAToolkit
|
|
3
|
-
#
|
|
4
|
-
# IAToolkit is open source software.
|
|
5
|
-
|
|
6
|
-
import pytest
|
|
7
|
-
from unittest.mock import MagicMock
|
|
8
|
-
from flask import Flask
|
|
9
|
-
from iatoolkit.views.tasks_view import TaskView
|
|
10
|
-
from iatoolkit.services.tasks_service import TaskService
|
|
11
|
-
from iatoolkit.repositories.profile_repo import ProfileRepo
|
|
12
|
-
from iatoolkit.repositories.models import Company, ApiKey
|
|
13
|
-
from datetime import datetime
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
class TestTaskView:
|
|
17
|
-
|
|
18
|
-
def setup_method(self):
|
|
19
|
-
self.app = Flask(__name__)
|
|
20
|
-
self.client = self.app.test_client()
|
|
21
|
-
|
|
22
|
-
# Mock del TaskService
|
|
23
|
-
self.mock_task_service = MagicMock(spec=TaskService)
|
|
24
|
-
self.mock_profile_repo = MagicMock(spec=ProfileRepo)
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
# Instanciamos la vista con el mock del servicio
|
|
28
|
-
self.task_view = TaskView.as_view("tasks",
|
|
29
|
-
task_service=self.mock_task_service,
|
|
30
|
-
profile_repo=self.mock_profile_repo)
|
|
31
|
-
self.app.add_url_rule('/tasks', view_func=self.task_view, methods=["POST"])
|
|
32
|
-
|
|
33
|
-
# API Key exitosa
|
|
34
|
-
self.api_key = ApiKey(key="test_key", company_id=100)
|
|
35
|
-
self.api_key.company = Company(id=100, name="Test Company", short_name="test_company")
|
|
36
|
-
self.mock_profile_repo.get_active_api_key_entry.return_value = self.api_key
|
|
37
|
-
self.valid_header = {"Authorization": f"Bearer {self.api_key.key}"}
|
|
38
|
-
|
|
39
|
-
@pytest.mark.parametrize("missing_field", ["company", "task_type", "client_data"])
|
|
40
|
-
def test_post_when_missing_required_fields(self, missing_field):
|
|
41
|
-
payload = {
|
|
42
|
-
"company": "test_company",
|
|
43
|
-
"task_type": "test_type",
|
|
44
|
-
"client_data": {"key": "value"},
|
|
45
|
-
}
|
|
46
|
-
payload.pop(missing_field)
|
|
47
|
-
|
|
48
|
-
response = self.client.post('/tasks',
|
|
49
|
-
headers=self.valid_header,
|
|
50
|
-
json=payload)
|
|
51
|
-
|
|
52
|
-
assert response.status_code == 400
|
|
53
|
-
assert response.get_json() == {
|
|
54
|
-
"error": f"El campo {missing_field} es requerido"
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
self.mock_task_service.create_task.assert_not_called()
|
|
58
|
-
|
|
59
|
-
def test_post_when_invalid_execute_at_format(self):
|
|
60
|
-
payload = {
|
|
61
|
-
"company": "test_company",
|
|
62
|
-
"task_type": "test_type",
|
|
63
|
-
"client_data": {"key": "value"},
|
|
64
|
-
"execute_at": "fecha-invalida"
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
response = self.client.post('/tasks',
|
|
68
|
-
headers=self.valid_header,
|
|
69
|
-
json=payload)
|
|
70
|
-
|
|
71
|
-
assert response.status_code == 400
|
|
72
|
-
assert response.get_json() == {
|
|
73
|
-
"error": "El formato de execute_at debe ser YYYY-MM-DD HH:MM:SS"
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
self.mock_task_service.create_task.assert_not_called()
|
|
77
|
-
|
|
78
|
-
def test_post_when_internal_exception_error(self):
|
|
79
|
-
self.mock_task_service.create_task.side_effect = Exception("Internal Error")
|
|
80
|
-
|
|
81
|
-
payload = {
|
|
82
|
-
"company": "test_company",
|
|
83
|
-
"task_type": "test_type",
|
|
84
|
-
"client_data": {"key": "value"}
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
response = self.client.post('/tasks',
|
|
88
|
-
headers=self.valid_header,
|
|
89
|
-
json=payload)
|
|
90
|
-
|
|
91
|
-
assert response.status_code == 500
|
|
92
|
-
assert response.get_json() == {
|
|
93
|
-
"error": "Internal Error"
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
self.mock_task_service.create_task.assert_called_once()
|
|
97
|
-
|
|
98
|
-
def test_post_when_successful_creation(self):
|
|
99
|
-
mocked_task = MagicMock()
|
|
100
|
-
mocked_task.id = 123
|
|
101
|
-
mocked_task.status.name = "CREATED"
|
|
102
|
-
self.mock_task_service.create_task.return_value = mocked_task
|
|
103
|
-
|
|
104
|
-
payload = {
|
|
105
|
-
"company": "test_company",
|
|
106
|
-
"company_task_id": 100,
|
|
107
|
-
"task_type": "test_type",
|
|
108
|
-
"client_data": {"key": "value"},
|
|
109
|
-
"execute_at": "2024-04-17 10:00:00"
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
response = self.client.post('/tasks', headers=self.valid_header,
|
|
113
|
-
json=payload)
|
|
114
|
-
|
|
115
|
-
assert response.status_code == 201
|
|
116
|
-
assert response.get_json() == {
|
|
117
|
-
"task_id": 123,
|
|
118
|
-
"status": "CREATED"
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
execute_datetime = datetime.fromisoformat(payload["execute_at"])
|
|
122
|
-
|
|
123
|
-
self.mock_task_service.create_task.assert_called_once_with(
|
|
124
|
-
company_short_name="test_company",
|
|
125
|
-
task_type_name="test_type",
|
|
126
|
-
client_data={"key": "value"},
|
|
127
|
-
company_task_id=100,
|
|
128
|
-
execute_at=execute_datetime,
|
|
129
|
-
files=[]
|
|
130
|
-
)
|