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.

Files changed (159) hide show
  1. iatoolkit/__init__.py +8 -34
  2. iatoolkit/base_company.py +14 -3
  3. iatoolkit/common/routes.py +83 -52
  4. iatoolkit/common/session_manager.py +0 -1
  5. iatoolkit/common/util.py +0 -27
  6. iatoolkit/iatoolkit.py +61 -46
  7. iatoolkit/infra/llm_client.py +7 -8
  8. iatoolkit/infra/openai_adapter.py +1 -1
  9. iatoolkit/infra/redis_session_manager.py +48 -2
  10. iatoolkit/repositories/database_manager.py +17 -2
  11. iatoolkit/repositories/models.py +31 -6
  12. iatoolkit/repositories/profile_repo.py +7 -2
  13. iatoolkit/services/auth_service.py +188 -0
  14. iatoolkit/services/branding_service.py +147 -0
  15. iatoolkit/services/dispatcher_service.py +10 -40
  16. iatoolkit/services/excel_service.py +15 -15
  17. iatoolkit/services/history_service.py +3 -12
  18. iatoolkit/services/jwt_service.py +15 -24
  19. iatoolkit/services/onboarding_service.py +43 -0
  20. iatoolkit/services/profile_service.py +97 -44
  21. iatoolkit/services/query_service.py +124 -81
  22. iatoolkit/services/tasks_service.py +1 -1
  23. iatoolkit/services/user_feedback_service.py +67 -31
  24. iatoolkit/services/user_session_context_service.py +112 -54
  25. iatoolkit/static/images/fernando.jpeg +0 -0
  26. iatoolkit/static/js/{chat_feedback.js → chat_feedback_button.js} +6 -11
  27. iatoolkit/static/js/chat_history_button.js +126 -0
  28. iatoolkit/static/js/chat_logout_button.js +36 -0
  29. iatoolkit/static/js/chat_main.js +130 -220
  30. iatoolkit/static/js/chat_onboarding_button.js +97 -0
  31. iatoolkit/static/js/chat_prompt_manager.js +94 -0
  32. iatoolkit/static/js/chat_reload_button.js +52 -0
  33. iatoolkit/static/styles/chat_iatoolkit.css +329 -507
  34. iatoolkit/static/styles/chat_modal.css +95 -56
  35. iatoolkit/static/styles/landing_page.css +182 -0
  36. iatoolkit/static/styles/onboarding.css +169 -0
  37. iatoolkit/system_prompts/query_main.prompt +3 -12
  38. iatoolkit/templates/_company_header.html +20 -0
  39. iatoolkit/templates/_login_widget.html +40 -0
  40. iatoolkit/templates/base.html +8 -3
  41. iatoolkit/templates/change_password.html +54 -37
  42. iatoolkit/templates/chat.html +149 -66
  43. iatoolkit/templates/chat_modals.html +47 -18
  44. iatoolkit/templates/error.html +41 -8
  45. iatoolkit/templates/forgot_password.html +37 -24
  46. iatoolkit/templates/index.html +140 -0
  47. iatoolkit/templates/login_simulation.html +34 -0
  48. iatoolkit/templates/onboarding_shell.html +105 -0
  49. iatoolkit/templates/signup.html +64 -66
  50. iatoolkit/views/base_login_view.py +81 -0
  51. iatoolkit/views/change_password_view.py +23 -12
  52. iatoolkit/views/external_login_view.py +61 -28
  53. iatoolkit/views/{file_store_view.py → file_store_api_view.py} +9 -2
  54. iatoolkit/views/forgot_password_view.py +23 -13
  55. iatoolkit/views/history_api_view.py +52 -0
  56. iatoolkit/views/home_view.py +58 -25
  57. iatoolkit/views/index_view.py +14 -0
  58. iatoolkit/views/init_context_api_view.py +68 -0
  59. iatoolkit/views/llmquery_api_view.py +45 -0
  60. iatoolkit/views/login_simulation_view.py +81 -0
  61. iatoolkit/views/login_view.py +118 -34
  62. iatoolkit/views/logout_api_view.py +45 -0
  63. iatoolkit/views/{prompt_view.py → prompt_api_view.py} +7 -7
  64. iatoolkit/views/signup_view.py +38 -29
  65. iatoolkit/views/{tasks_view.py → tasks_api_view.py} +10 -36
  66. iatoolkit/views/tasks_review_api_view.py +55 -0
  67. iatoolkit/views/{user_feedback_view.py → user_feedback_api_view.py} +16 -31
  68. iatoolkit/views/verify_user_view.py +13 -8
  69. {iatoolkit-0.8.1.dist-info → iatoolkit-0.63.4.dist-info}/METADATA +2 -2
  70. iatoolkit-0.63.4.dist-info/RECORD +113 -0
  71. {iatoolkit-0.8.1.dist-info → iatoolkit-0.63.4.dist-info}/top_level.txt +0 -1
  72. iatoolkit/common/auth.py +0 -200
  73. iatoolkit/static/images/arrow_up.png +0 -0
  74. iatoolkit/static/images/diagrama_iatoolkit.jpg +0 -0
  75. iatoolkit/static/images/logo_clinica.png +0 -0
  76. iatoolkit/static/images/logo_iatoolkit.png +0 -0
  77. iatoolkit/static/images/logo_maxxa.png +0 -0
  78. iatoolkit/static/images/logo_notaria.png +0 -0
  79. iatoolkit/static/images/logo_tarjeta.png +0 -0
  80. iatoolkit/static/images/logo_umayor.png +0 -0
  81. iatoolkit/static/images/upload.png +0 -0
  82. iatoolkit/static/js/chat_history.js +0 -117
  83. iatoolkit/templates/home.html +0 -201
  84. iatoolkit/templates/login.html +0 -43
  85. iatoolkit/views/chat_token_request_view.py +0 -98
  86. iatoolkit/views/chat_view.py +0 -51
  87. iatoolkit/views/download_file_view.py +0 -58
  88. iatoolkit/views/external_chat_login_view.py +0 -88
  89. iatoolkit/views/history_view.py +0 -57
  90. iatoolkit/views/llmquery_view.py +0 -65
  91. iatoolkit/views/tasks_review_view.py +0 -83
  92. iatoolkit-0.8.1.dist-info/RECORD +0 -175
  93. tests/__init__.py +0 -5
  94. tests/common/__init__.py +0 -0
  95. tests/common/test_auth.py +0 -279
  96. tests/common/test_routes.py +0 -42
  97. tests/common/test_session_manager.py +0 -59
  98. tests/common/test_util.py +0 -444
  99. tests/companies/__init__.py +0 -5
  100. tests/conftest.py +0 -36
  101. tests/infra/__init__.py +0 -5
  102. tests/infra/connectors/__init__.py +0 -5
  103. tests/infra/connectors/test_google_drive_connector.py +0 -107
  104. tests/infra/connectors/test_local_file_connector.py +0 -85
  105. tests/infra/connectors/test_s3_connector.py +0 -95
  106. tests/infra/test_call_service.py +0 -92
  107. tests/infra/test_database_manager.py +0 -59
  108. tests/infra/test_gemini_adapter.py +0 -137
  109. tests/infra/test_google_chat_app.py +0 -68
  110. tests/infra/test_llm_client.py +0 -165
  111. tests/infra/test_llm_proxy.py +0 -122
  112. tests/infra/test_mail_app.py +0 -94
  113. tests/infra/test_openai_adapter.py +0 -105
  114. tests/infra/test_redis_session_manager_service.py +0 -117
  115. tests/repositories/__init__.py +0 -5
  116. tests/repositories/test_database_manager.py +0 -87
  117. tests/repositories/test_document_repo.py +0 -76
  118. tests/repositories/test_llm_query_repo.py +0 -340
  119. tests/repositories/test_models.py +0 -38
  120. tests/repositories/test_profile_repo.py +0 -142
  121. tests/repositories/test_tasks_repo.py +0 -76
  122. tests/repositories/test_vs_repo.py +0 -107
  123. tests/services/__init__.py +0 -5
  124. tests/services/test_dispatcher_service.py +0 -274
  125. tests/services/test_document_service.py +0 -181
  126. tests/services/test_excel_service.py +0 -208
  127. tests/services/test_file_processor_service.py +0 -121
  128. tests/services/test_history_service.py +0 -164
  129. tests/services/test_jwt_service.py +0 -255
  130. tests/services/test_load_documents_service.py +0 -112
  131. tests/services/test_mail_service.py +0 -70
  132. tests/services/test_profile_service.py +0 -379
  133. tests/services/test_prompt_manager_service.py +0 -190
  134. tests/services/test_query_service.py +0 -243
  135. tests/services/test_search_service.py +0 -39
  136. tests/services/test_sql_service.py +0 -160
  137. tests/services/test_tasks_service.py +0 -252
  138. tests/services/test_user_feedback_service.py +0 -389
  139. tests/services/test_user_session_context_service.py +0 -132
  140. tests/views/__init__.py +0 -5
  141. tests/views/test_change_password_view.py +0 -191
  142. tests/views/test_chat_token_request_view.py +0 -188
  143. tests/views/test_chat_view.py +0 -98
  144. tests/views/test_download_file_view.py +0 -149
  145. tests/views/test_external_chat_login_view.py +0 -120
  146. tests/views/test_external_login_view.py +0 -102
  147. tests/views/test_file_store_view.py +0 -128
  148. tests/views/test_forgot_password_view.py +0 -142
  149. tests/views/test_history_view.py +0 -336
  150. tests/views/test_home_view.py +0 -61
  151. tests/views/test_llm_query_view.py +0 -154
  152. tests/views/test_login_view.py +0 -114
  153. tests/views/test_prompt_view.py +0 -111
  154. tests/views/test_signup_view.py +0 -140
  155. tests/views/test_tasks_review_view.py +0 -104
  156. tests/views/test_tasks_view.py +0 -130
  157. tests/views/test_user_feedback_view.py +0 -214
  158. tests/views/test_verify_user_view.py +0 -110
  159. {iatoolkit-0.8.1.dist-info → iatoolkit-0.63.4.dist-info}/WHEEL +0 -0
@@ -1,87 +0,0 @@
1
- # Copyright (c) 2024 Fernando Libedinsky
2
- # Product: IAToolkit
3
- #
4
- # IAToolkit is open source software.
5
-
6
- from unittest.mock import patch, MagicMock
7
- from iatoolkit.repositories.database_manager import DatabaseManager
8
- import pytest
9
-
10
- class TestDatabaseManager:
11
- def setup_method(self):
12
- self.mock_engine = MagicMock()
13
- self.mock_sessionmaker = MagicMock()
14
- self.mock_scoped_session = MagicMock()
15
- self.mock_base_metadata = MagicMock()
16
- self.mock_inspect = MagicMock()
17
-
18
- self.database_url = "sqlite:///:memory:"
19
-
20
- # Lista para almacenar todos los patches
21
- self.patchers = []
22
-
23
- # Crear y agregar patches a la lista
24
- patcher_engine = patch('iatoolkit.repositories.database_manager.create_engine', return_value=self.mock_engine)
25
- patcher_sessionmaker = patch('iatoolkit.repositories.database_manager.sessionmaker', return_value=self.mock_sessionmaker)
26
- patcher_scoped_session = patch('iatoolkit.repositories.database_manager.scoped_session',
27
- return_value=self.mock_scoped_session)
28
- patcher_metadata = patch('iatoolkit.repositories.database_manager.Base.metadata', self.mock_base_metadata)
29
- patcher_inspect = patch('iatoolkit.repositories.database_manager.inspect', self.mock_inspect)
30
-
31
- self.patchers.extend(
32
- [patcher_engine, patcher_sessionmaker, patcher_scoped_session, patcher_metadata, patcher_inspect])
33
-
34
- # Inicia todos los patches y almacena los mocks retornados si es necesario
35
- self.mock_create_engine = patcher_engine.start()
36
- self.mock_sessionmaker_function = patcher_sessionmaker.start()
37
- self.mock_scoped_session_function = patcher_scoped_session.start()
38
- self.mock_inspect = patcher_inspect.start()
39
- patcher_metadata.start()
40
-
41
- self.db_manager = DatabaseManager(self.database_url)
42
-
43
- def teardown_method(self):
44
- for patcher in self.patchers:
45
- patcher.stop()
46
-
47
- def test_init_initializes_engine_and_session_factory(self):
48
- self.mock_create_engine.assert_called_once_with(self.database_url, echo=False)
49
- self.mock_sessionmaker_function.assert_called_once_with(bind=self.mock_engine)
50
-
51
- def test_get_session_returns_scoped_session(self):
52
- session = self.db_manager.get_session()
53
- assert session == self.mock_scoped_session()
54
-
55
- def test_create_all_calls_metadata_create_all(self):
56
- self.db_manager.create_all()
57
- assert self.mock_base_metadata.create_all.call_count == 1
58
-
59
- def test_drop_all_calls_metadata_drop_all(self):
60
- self.db_manager.drop_all()
61
- self.mock_base_metadata.drop_all.assert_called_once_with(self.mock_engine)
62
-
63
- def test_remove_session_calls_scoped_session_remove(self):
64
- self.db_manager.remove_session()
65
- self.mock_scoped_session.remove.assert_called_once()
66
-
67
- def test_get_table_schema_table_exists(self):
68
- """Prueba get_table_schema cuando la tabla existe"""
69
- self.mock_inspect.return_value.get_table_names.return_value = ['test_table']
70
- self.mock_inspect.return_value.get_columns.return_value = [
71
- {"name": "id", "type": "INTEGER"},
72
- {"name": "name", "type": "VARCHAR"}
73
- ]
74
-
75
- result = self.db_manager.get_table_schema('test_table')
76
-
77
- # Verificar que el resultado contiene la información esperada
78
- assert "{'table': 'test_table', 'description': 'Definición de la tabla test_table.', 'fields': [{'name': 'id', 'type': 'INTEGER'}, {'name': 'name', 'type': 'VARCHAR'}]}" == result.strip()
79
-
80
- def test_get_table_schema_table_not_exists(self):
81
- """Prueba get_table_schema cuando la tabla no existe"""
82
- self.mock_inspect.return_value.get_table_names.return_value = []
83
-
84
- with pytest.raises(RuntimeError) as exc_info:
85
- self.db_manager.get_table_schema('non_existent_table')
86
-
87
- assert "La tabla 'non_existent_table' no existe en la BD" in str(exc_info.value)
@@ -1,76 +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 iatoolkit.repositories.models import Document, Company
9
- from iatoolkit.repositories.document_repo import DocumentRepo
10
- from iatoolkit.common.exceptions import IAToolkitException
11
- import base64
12
-
13
-
14
- class TestDocumentRepo:
15
- def setup_method(self):
16
- # Mock the DatabaseManager
17
- self.mock_db_manager = MagicMock()
18
- self.session = self.mock_db_manager.get_session()
19
-
20
- # Initialize DocumentRepo with the mocked DatabaseManager
21
- self.repo = DocumentRepo(self.mock_db_manager)
22
- self.mock_document = Document(company_id=1,
23
- filename='test.txt',
24
- content='123',
25
- content_b64=base64.b64encode('123'.encode('utf-8')).decode('utf-8'),
26
- meta={'repertorio_id': 10})
27
- self.mock_company = Company(name='company')
28
-
29
-
30
- def test_insert_when_ok(self):
31
- self.repo.insert(self.mock_document)
32
-
33
- # Assert
34
- self.session.add.assert_called()
35
- self.session.commit.assert_called()
36
-
37
- def test_get_missing_company(self):
38
- # Act & Assert
39
- with pytest.raises(IAToolkitException) as exc_info:
40
- self.repo.get(None, filename="test_file.txt")
41
-
42
- assert exc_info.value.error_type == IAToolkitException.ErrorType.PARAM_NOT_FILLED
43
-
44
- def test_get_document_by_filename(self):
45
- self.session.query.return_value.filter_by.return_value.first.return_value = self.mock_document
46
-
47
- # Act
48
- result = self.repo.get(self.mock_company, filename="test_file.txt")
49
-
50
- # Assert
51
- assert result == self.mock_document
52
- self.session.query.assert_called()
53
-
54
- def test_get_by_id_when_id_is_none(self):
55
- result = self.repo.get_by_id(0)
56
-
57
- assert result is None
58
- self.session.query.assert_not_called()
59
-
60
- def test_get_by_id_when_document_not_found(self):
61
- self.session.query.return_value.filter_by.return_value.first.return_value = None
62
-
63
- result = self.repo.get_by_id(999)
64
-
65
- assert result is None
66
- self.session.query.assert_called()
67
-
68
- def test_get_by_id_when_document_exists(self):
69
- self.session.query.return_value.filter_by.return_value.first.return_value = self.mock_document
70
-
71
- result = self.repo.get_by_id(1)
72
-
73
- assert result == self.mock_document
74
- self.session.query.assert_called()
75
-
76
-
@@ -1,340 +0,0 @@
1
- # Copyright (c) 2024 Fernando Libedinsky
2
- # Product: IAToolkit
3
- #
4
- # IAToolkit is open source software.
5
-
6
- from iatoolkit.repositories.database_manager import DatabaseManager
7
- from iatoolkit.repositories.models import LLMQuery, Function, Company, Prompt, PromptCategory
8
- from iatoolkit.repositories.llm_query_repo import LLMQueryRepo
9
- from datetime import datetime, timedelta
10
-
11
-
12
- class TestLLMQueryRepo:
13
- def setup_method(self):
14
- self.db_manager = DatabaseManager('sqlite:///:memory:')
15
- self.db_manager.create_all()
16
- self.session = self.db_manager.get_session()
17
- self.repo = LLMQueryRepo(self.db_manager)
18
- self.query = LLMQuery(id=1, company_id=2,
19
- user_identifier='user_1',
20
- query="test query",
21
- output='an output',
22
- response={'answer': 'an answer'},
23
- answer_time=3)
24
- self.function = Function(name="function1",
25
- company_id=1,
26
- description="A description",
27
- parameters={'name': 'value'})
28
- self.company = Company(name='test_company',
29
- short_name='test')
30
- self.session.add(self.company)
31
- self.session.commit()
32
-
33
-
34
- def test_add_query_when_success(self):
35
- new_query = self.repo.add_query(self.query)
36
- assert new_query.id == 1
37
-
38
- def test_get_company_functions_when_ok(self):
39
- self.function.company_id = self.company.id
40
-
41
- self.session.add(self.function)
42
- self.session.commit()
43
- assert len(self.repo.get_company_functions(self.company)) == 1
44
-
45
- def test_create_or_update_function_when_new_function(self):
46
- new_function = Function(name="function1",
47
- company_id=1,
48
- description="A description",
49
- parameters={'name': 'value'})
50
- result = self.repo.create_or_update_function(new_function=new_function)
51
- assert result.id is not None
52
- assert result.name == "function1"
53
- assert result.description == "A description"
54
-
55
- def test_create_or_update_function_when_updating_function(self):
56
- # Add an initial function
57
- function = Function(name="function1",
58
- company_id=self.company.id,
59
- description="A description",
60
- parameters={'name': 'value'})
61
- self.session.add(function)
62
- self.session.commit()
63
-
64
- # Update the description
65
- upd_function = Function(name="function1",
66
- company_id=self.company.id,
67
- description="New description",
68
- parameters={'name': 'value 2'})
69
- result = self.repo.create_or_update_function(new_function=upd_function)
70
- assert result.id == function.id
71
- assert result.description == "New description"
72
- assert result.parameters['name'] == 'value 2'
73
-
74
- def test_create_or_update_prompt_when_new_prompt(self):
75
- new_prompt = Prompt(name="prompt1",
76
- company_id=self.company.id,
77
- description="an intelligent prompt",
78
- filename='')
79
- result = self.repo.create_or_update_prompt(new_prompt=new_prompt)
80
- assert result.id is not None
81
- assert result.name == "prompt1"
82
- assert result.description == "an intelligent prompt"
83
- assert result.active is True
84
-
85
- def test_create_or_update_prompt_when_updating_prompt(self):
86
-
87
- category = self.repo.create_or_update_prompt_category(PromptCategory(name='Cobranzas', order=6,
88
- company_id=self.company.id))
89
- prompt = Prompt(name="prompt1",
90
- company_id=self.company.id,
91
- category_id=category.id,
92
- active=True,
93
- order=1,
94
- description="an intelligent prompt",
95
- filename='')
96
- self.session.add(prompt)
97
- self.session.commit()
98
-
99
- # Update the description
100
- upd_prompt = Prompt(name="prompt1",
101
- company_id=self.company.id,
102
- category_id=category.id,
103
- active=True,
104
- order=3,
105
- description="a super intelligent prompt",
106
- filename='')
107
- result = self.repo.create_or_update_prompt(new_prompt=upd_prompt)
108
- assert result.description == "a super intelligent prompt"
109
- assert result.id == prompt.id
110
-
111
- def test_get_history_empty_result(self):
112
- """Test get_history when no queries exist for the user"""
113
- # Get history for non-existent user
114
- history = self.repo.get_history(self.company, 'nonexistent_user')
115
-
116
- # Should return empty list
117
- assert len(history) == 0
118
- assert history == []
119
-
120
- def test_get_history_different_company(self):
121
- """Test get_history filters by company_id correctly"""
122
- # Add two companies
123
- company1 = Company(name='company1', short_name='comp1')
124
- company2 = Company(name='company2', short_name='comp2')
125
- self.session.add(company1)
126
- self.session.add(company2)
127
- self.session.commit()
128
-
129
- # Create queries for different companies
130
- query1 = LLMQuery(
131
- company_id=company1.id,
132
- user_identifier='user123',
133
- query="Company 1 query",
134
- output='Company 1 output',
135
- response={'answer': 'Company 1 answer'},
136
- answer_time=3
137
- )
138
- query2 = LLMQuery(
139
- company_id=company2.id,
140
- user_identifier='user123',
141
- query="Company 2 query",
142
- output='Company 2 output',
143
- response={'answer': 'Company 2 answer'},
144
- answer_time=3
145
- )
146
-
147
- # Add queries to database
148
- self.session.add(query1)
149
- self.session.add(query2)
150
- self.session.commit()
151
-
152
- # Get history for company1
153
- history1 = self.repo.get_history(company1, 'user123')
154
- assert len(history1) == 1
155
- assert history1[0].query == "Company 1 query"
156
-
157
- # Get history for company2
158
- history2 = self.repo.get_history(company2, 'user123')
159
- assert len(history2) == 1
160
- assert history2[0].query == "Company 2 query"
161
-
162
- def test_get_history_limit_100(self):
163
- """Test get_history respects the limit of 100 queries"""
164
- # Create 110 queries
165
- queries = []
166
- base_time = datetime(2024, 1, 15, 10, 30, 0)
167
- for i in range(110):
168
- # Use timedelta to create unique timestamps
169
- query = LLMQuery(
170
- company_id=self.company.id,
171
- user_identifier='user123',
172
- query=f"Query {i}",
173
- output=f'Output {i}',
174
- response={'answer': f'Answer {i}'},
175
- answer_time=3,
176
- created_at=base_time + timedelta(seconds=i) # Different timestamps
177
- )
178
- queries.append(query)
179
-
180
- # Add all queries to database
181
- for query in queries:
182
- self.session.add(query)
183
- self.session.commit()
184
-
185
- # Get history
186
- history = self.repo.get_history(self.company, 'user123')
187
-
188
- # Should return only 100 queries (limit)
189
- assert len(history) == 100
190
- # Should be ordered by created_at desc (newest first)
191
- assert history[0].query == "Query 109" # Newest
192
- assert history[99].query == "Query 10" # 100th newest
193
-
194
- def test_get_history_mixed_user_types(self):
195
- """Test get_history correctly filters by user type"""
196
- # Create queries for different user types
197
- external_query = LLMQuery(
198
- company_id=self.company.id,
199
- user_identifier='external_user',
200
- query="External user query",
201
- output='External output',
202
- response={'answer': 'External answer'},
203
- answer_time=3
204
- )
205
- local_query = LLMQuery(
206
- company_id=self.company.id,
207
- user_identifier='user_456',
208
- query="Local user query",
209
- output='Local output',
210
- response={'answer': 'Local answer'},
211
- answer_time=3
212
- )
213
-
214
- # Add queries to database
215
- self.session.add(external_query)
216
- self.session.add(local_query)
217
- self.session.commit()
218
-
219
- # Get history for external user
220
- external_history = self.repo.get_history(self.company, 'external_user')
221
- assert len(external_history) == 1
222
- assert external_history[0].query == "External user query"
223
-
224
- # Get history for local user
225
- local_history = self.repo.get_history(self.company, 'user_456')
226
- assert len(local_history) == 1
227
- assert local_history[0].query == "Local user query"
228
-
229
- def test_get_history_ordering(self):
230
- """Test get_history orders by created_at desc correctly"""
231
-
232
- # Create queries with different timestamps
233
- old_query = LLMQuery(
234
- company_id=self.company.id,
235
- user_identifier='user123',
236
- query="Old query",
237
- output='Old output',
238
- response={'answer': 'Old answer'},
239
- answer_time=3,
240
- created_at=datetime(2024, 1, 15, 10, 30, 0)
241
- )
242
- new_query = LLMQuery(
243
- company_id=self.company.id,
244
- user_identifier='user123',
245
- query="New query",
246
- output='New output',
247
- response={'answer': 'New answer'},
248
- answer_time=3,
249
- created_at=datetime(2024, 1, 15, 11, 30, 0)
250
- )
251
-
252
- # Add queries to database
253
- self.session.add(old_query)
254
- self.session.add(new_query)
255
- self.session.commit()
256
-
257
- # Get history
258
- history = self.repo.get_history(self.company, 'user123')
259
-
260
- # Should be ordered by created_at desc (newest first)
261
- assert len(history) == 2
262
- assert history[0].query == "New query" # Newest first
263
- assert history[1].query == "Old query" # Oldest last
264
-
265
- def test_get_history_no_company_queries(self):
266
- """Test get_history when company exists but has no queries"""
267
-
268
- # Get history for company with no queries
269
- history = self.repo.get_history(self.company, 'user123')
270
-
271
- # Should return empty list
272
- assert len(history) == 0
273
- assert history == []
274
-
275
- def test_get_prompts_when_prompts_exist(self):
276
- """Test get_prompts returns all prompts for a company."""
277
- # Create active and inactive prompts for the same company
278
- prompt1 = Prompt(name="active_prompt",
279
- company_id=self.company.id,
280
- description="An active prompt",
281
- active=True,
282
- filename='')
283
- prompt2 = Prompt(name="inactive_prompt",
284
- company_id=self.company.id,
285
- description="An inactive prompt",
286
- active=False,
287
- filename='')
288
-
289
- self.session.add_all([prompt1, prompt2])
290
- self.session.commit()
291
-
292
- # Get prompts for the company
293
- prompts = self.repo.get_prompts(self.company)
294
-
295
- # Should return both prompts
296
- assert len(prompts) == 2
297
- prompt_names = {p.name for p in prompts}
298
- assert "active_prompt" in prompt_names
299
- assert "inactive_prompt" in prompt_names
300
-
301
- def test_get_prompts_when_no_prompts_exist(self):
302
- """Test get_prompts returns an empty list when a company has no prompts."""
303
- # Get prompts for a company with no prompts
304
- prompts = self.repo.get_prompts(self.company)
305
-
306
- # Should return an empty list
307
- assert len(prompts) == 0
308
- assert prompts == []
309
-
310
- def test_get_prompts_filters_by_company(self):
311
- """Test get_prompts only returns prompts for the specified company."""
312
- # Create another company
313
- other_company = Company(name='other_company', short_name='other')
314
- self.session.add(other_company)
315
- self.session.commit()
316
-
317
- # Create a prompt for the main company
318
- prompt1 = Prompt(name="main_company_prompt",
319
- company_id=self.company.id,
320
- description="Prompt for the main company",
321
- filename='')
322
-
323
- # Create a prompt for the other company
324
- prompt2 = Prompt(name="other_company_prompt",
325
- company_id=other_company.id,
326
- description="Prompt for the other company",
327
- filename='')
328
-
329
- self.session.add_all([prompt1, prompt2])
330
- self.session.commit()
331
-
332
- # Get prompts for the main company
333
- prompts = self.repo.get_prompts(self.company)
334
-
335
- # Should only return the prompt for the main company
336
- assert len(prompts) == 1
337
- assert prompts[0].name == "main_company_prompt"
338
- assert prompts[0].company_id == self.company.id
339
-
340
-
@@ -1,38 +0,0 @@
1
- # Copyright (c) 2024 Fernando Libedinsky
2
- # Product: IAToolkit
3
- #
4
- # IAToolkit is open source software.
5
-
6
- from unittest.mock import patch, MagicMock
7
- from iatoolkit.repositories.models import Company, Function, Document, User, LLMQuery, VSDoc
8
- from sqlalchemy.orm import relationship
9
-
10
-
11
- class TestModels:
12
- def setup_method(self):
13
- self.mock_base = MagicMock()
14
-
15
- # Aquí almacenamos las referencias de los objetos mock retornados
16
- self.mock_relationship = patch('sqlalchemy.orm.relationship', MagicMock(return_value=relationship)).start()
17
- self.mock_column = patch('sqlalchemy.Column', MagicMock()).start()
18
- self.mock_integer = patch('sqlalchemy.Integer', MagicMock()).start()
19
- self.mock_string = patch('sqlalchemy.String', MagicMock()).start()
20
- self.mock_float = patch('sqlalchemy.Float', MagicMock()).start()
21
- self.mock_date_time = patch('sqlalchemy.DateTime', MagicMock()).start()
22
- self.mock_json = patch('sqlalchemy.JSON', MagicMock()).start()
23
- self.mock_foreign_key = patch('sqlalchemy.ForeignKey', MagicMock()).start()
24
-
25
- self.model_classes = [Company, Function, Document, User, LLMQuery, VSDoc]
26
-
27
- def teardown_method(self):
28
- patch.stopall()
29
-
30
- def test_model_definitions(self):
31
- for model_class in self.model_classes:
32
- instance = model_class() # Asegurarse de que se puedan instanciar correctamente
33
- instance.to_dict()
34
- assert instance is not None
35
-
36
- def test_relationship_calls(self):
37
- # Ahora usamos call_count en el mock generado
38
- assert self.mock_relationship.call_count == 0
@@ -1,142 +0,0 @@
1
- # Copyright (c) 2024 Fernando Libedinsky
2
- # Product: IAToolkit
3
- #
4
- # IAToolkit is open source software.
5
-
6
- from iatoolkit.repositories.database_manager import DatabaseManager
7
- from iatoolkit.repositories.models import User, Company, UserFeedback
8
- from iatoolkit.repositories.profile_repo import ProfileRepo
9
-
10
-
11
- class TestProfileRepo:
12
- def setup_method(self):
13
- self.db_manager = DatabaseManager('sqlite:///:memory:')
14
- self.db_manager.create_all()
15
- self.session = self.db_manager.get_session()
16
- self.repo = ProfileRepo(self.db_manager)
17
-
18
- self.user = User(email='fernando@opensoft.cl',
19
- first_name='Fernando',
20
- last_name='Libedinsky',
21
- password='123')
22
-
23
- self.company = Company(name='opensoft', short_name='open')
24
-
25
- def test_get_user_by_id_when_not_found(self):
26
- result = self.repo.get_user_by_id(2)
27
- assert result is None
28
-
29
- def test_get_user_by_id_when_success(self):
30
- self.session.add(self.user)
31
- result = self.repo.get_user_by_id(1)
32
- assert result == self.user
33
-
34
- def test_get_user_by_email_when_not_found(self):
35
- result = self.repo.get_user_by_email('fl@opensoft')
36
- assert result is None
37
-
38
- def test_get_user_by_email_when_success(self):
39
- self.session.add(self.user)
40
- result = self.repo.get_user_by_email('fernando@opensoft.cl')
41
- assert result == self.user
42
-
43
- def test_create_user_when_ok(self):
44
- new_user = self.repo.create_user(self.user)
45
- assert new_user.id == 1
46
-
47
- def test_save_and_update_user_when_ok(self):
48
- new_user = self.repo.create_user(self.user)
49
- new_user.first_name = 'fernando'
50
-
51
- updated_user = self.repo.save_user(new_user)
52
- assert updated_user.id == 1
53
-
54
- def test_update_user_when_not_exist(self):
55
- user = self.repo.update_user(self.user.email, first_name='Fernando')
56
- assert user == None
57
-
58
- def test_verify_user_when_ok(self):
59
- self.session.add(self.user)
60
- user = self.repo.verify_user(self.user.email)
61
- assert user.verified == True
62
-
63
- def test_set_temp_code_when_ok(self):
64
- self.session.add(self.user)
65
- temp_code = 'CCGT'
66
- user = self.repo.set_temp_code(self.user.email,temp_code)
67
-
68
- assert user.temp_code == temp_code
69
-
70
- def test_reset_temp_code_when_ok(self):
71
- self.session.add(self.user)
72
- user = self.repo.reset_temp_code(self.user.email)
73
-
74
- assert user.temp_code == None
75
-
76
- def test_update_password_when_ok(self):
77
- self.session.add(self.user)
78
- hashed_password = 'ggdvXz'
79
- user = self.repo.update_password(self.user.email, hashed_password)
80
-
81
- assert user.password == hashed_password
82
-
83
- def test_get_company_when_no_exist(self):
84
- assert self.repo.get_company('opensoft') == None
85
-
86
- def test_get_company_when_ok(self):
87
- self.session.add(self.company)
88
- assert self.repo.get_company('opensoft') == self.company
89
- assert self.repo.get_company_by_short_name('open') == self.company
90
-
91
- def test_get_company_by_id_when_not_found(self):
92
- result = self.repo.get_company_by_id(999)
93
-
94
- assert result is None
95
-
96
- def test_get_company_by_id_when_success(self):
97
- self.session.add(self.company)
98
-
99
- result = self.repo.get_company_by_id(1)
100
- assert result == self.company
101
-
102
- def test_get_companies_when_no_companies_exist(self):
103
- result = self.repo.get_companies()
104
- assert result == []
105
-
106
- def test_get_companies_when_companies_exist(self):
107
- company_opensoft = Company(name='Opensoft', short_name='open')
108
- company_testlabs = Company(name='TestLabs', short_name='test')
109
- self.session.add(company_opensoft)
110
- self.session.add(company_testlabs)
111
- self.session.commit()
112
-
113
- result = self.repo.get_companies()
114
-
115
- assert len(result) == 2
116
- assert result[0].name == 'Opensoft'
117
- assert result[1].name == 'TestLabs'
118
-
119
- def test_create_company_when_company_exists(self):
120
- self.session.add(self.company)
121
-
122
- result = self.repo.create_company(Company(name='opensoft'))
123
-
124
- assert result.id == self.company.id
125
- assert result.name == self.company.name
126
-
127
- def test_create_company_when_new_company(self):
128
- result = self.repo.create_company(Company(name='NewCompany', short_name='new'))
129
-
130
- assert result.id is not None
131
- assert result.name == 'NewCompany'
132
-
133
- def test_save_feedback_when_ok(self):
134
- company = self.repo.create_company(Company(name='my_company', short_name='my_company'))
135
- feedback = UserFeedback(company_id=company.id,
136
- external_user_id='flibe',
137
- message='feedback message',
138
- rating=4)
139
- new_feed = self.repo.save_feedback(feedback)
140
- assert new_feed.message == 'feedback message'
141
- assert new_feed.rating == 4
142
-