__init__.py 8.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294
  1. # -*- coding: utf-8 -*-
  2. import unittest
  3. import plaster
  4. import requests
  5. import transaction
  6. from depot.manager import DepotManager
  7. from pyramid import testing
  8. from sqlalchemy.exc import IntegrityError
  9. from tracim.lib.core.content import ContentApi
  10. from tracim.lib.core.workspace import WorkspaceApi
  11. from tracim.models import get_engine
  12. from tracim.models import DeclarativeBase
  13. from tracim.models import get_session_factory
  14. from tracim.models import get_tm_session
  15. from tracim.models.data import Workspace
  16. from tracim.models.data import ContentType
  17. from tracim.models.data import ContentRevisionRO
  18. from tracim.models.data import Content
  19. from tracim.lib.utils.logger import logger
  20. from tracim.fixtures import FixturesLoader
  21. from tracim.fixtures.users_and_groups import Base as BaseFixture
  22. from tracim.config import CFG
  23. from tracim.extensions import hapic
  24. from tracim import web
  25. from webtest import TestApp
  26. from io import BytesIO
  27. from PIL import Image
  28. def eq_(a, b, msg=None):
  29. # TODO - G.M - 05-04-2018 - Remove this when all old nose code is removed
  30. assert a == b, msg or "%r != %r" % (a, b)
  31. # TODO - G.M - 2018-06-179 - Refactor slug change function
  32. # as a kind of pytest fixture ?
  33. def set_html_document_slug_to_legacy(session_factory) -> None:
  34. """
  35. Simple function to help some functional test. This modify "html-documents"
  36. type content in database to legacy "page" slug.
  37. :param session_factory: session factory of the test
  38. :return: Nothing.
  39. """
  40. dbsession = get_tm_session(
  41. session_factory,
  42. transaction.manager
  43. )
  44. content_query = dbsession.query(ContentRevisionRO).filter(ContentRevisionRO.type == 'page').filter(ContentRevisionRO.content_id == 6) # nopep8
  45. assert content_query.count() == 0
  46. html_documents_query = dbsession.query(ContentRevisionRO).filter(ContentRevisionRO.type == 'html-documents') # nopep8
  47. html_documents_query.update({ContentRevisionRO.type: 'page'})
  48. transaction.commit()
  49. assert content_query.count() > 0
  50. def create_1000px_png_test_image():
  51. file = BytesIO()
  52. image = Image.new('RGBA', size=(1000, 1000), color=(0, 0, 0))
  53. image.save(file, 'png')
  54. file.name = 'test_image.png'
  55. file.seek(0)
  56. return file
  57. class FunctionalTest(unittest.TestCase):
  58. fixtures = [BaseFixture]
  59. sqlalchemy_url = 'sqlite:///tracim_test.sqlite'
  60. def setUp(self):
  61. logger._logger.setLevel('WARNING')
  62. DepotManager._clear()
  63. self.settings = {
  64. 'sqlalchemy.url': self.sqlalchemy_url,
  65. 'user.auth_token.validity': '604800',
  66. 'depot_storage_dir': '/tmp/test/depot',
  67. 'depot_storage_name': 'test',
  68. 'preview_cache_dir': '/tmp/test/preview_cache',
  69. 'preview.jpg.restricted_dims': True,
  70. 'email.notification.activated': 'false',
  71. }
  72. hapic.reset_context()
  73. self.engine = get_engine(self.settings)
  74. DeclarativeBase.metadata.create_all(self.engine)
  75. self.session_factory = get_session_factory(self.engine)
  76. self.app_config = CFG(self.settings)
  77. self.app_config.configure_filedepot()
  78. self.init_database(self.settings)
  79. DepotManager._clear()
  80. self.run_app()
  81. def run_app(self):
  82. app = web({}, **self.settings)
  83. self.testapp = TestApp(app)
  84. def init_database(self, settings):
  85. with transaction.manager:
  86. dbsession = get_tm_session(self.session_factory, transaction.manager)
  87. try:
  88. fixtures_loader = FixturesLoader(dbsession, self.app_config)
  89. fixtures_loader.loads(self.fixtures)
  90. transaction.commit()
  91. print("Database initialized.")
  92. except IntegrityError:
  93. print('Warning, there was a problem when adding default data'
  94. ', it may have already been added:')
  95. import traceback
  96. print(traceback.format_exc())
  97. transaction.abort()
  98. print('Database initialization failed')
  99. def tearDown(self):
  100. logger.debug(self, 'TearDown Test...')
  101. from tracim.models.meta import DeclarativeBase
  102. testing.tearDown()
  103. transaction.abort()
  104. DeclarativeBase.metadata.drop_all(self.engine)
  105. DepotManager._clear()
  106. class FunctionalTestEmptyDB(FunctionalTest):
  107. fixtures = []
  108. class FunctionalTestNoDB(FunctionalTest):
  109. sqlalchemy_url = 'sqlite://'
  110. def init_database(self, settings):
  111. self.engine = get_engine(settings)
  112. class CommandFunctionalTest(FunctionalTest):
  113. def run_app(self):
  114. self.session = get_tm_session(self.session_factory, transaction.manager)
  115. class BaseTest(unittest.TestCase):
  116. """
  117. Pyramid default test.
  118. """
  119. config_uri = 'tests_configs.ini'
  120. config_section = 'base_test'
  121. def setUp(self):
  122. logger._logger.setLevel('WARNING')
  123. logger.debug(self, 'Setup Test...')
  124. self.settings = plaster.get_settings(
  125. self.config_uri,
  126. self.config_section
  127. )
  128. self.config = testing.setUp(settings = self.settings)
  129. self.config.include('tracim.models')
  130. DepotManager._clear()
  131. DepotManager.configure(
  132. 'test', {'depot.backend': 'depot.io.memory.MemoryFileStorage'}
  133. )
  134. settings = self.config.get_settings()
  135. self.app_config = CFG(settings)
  136. from tracim.models import (
  137. get_engine,
  138. get_session_factory,
  139. get_tm_session,
  140. )
  141. self.engine = get_engine(settings)
  142. session_factory = get_session_factory(self.engine)
  143. self.session = get_tm_session(session_factory, transaction.manager)
  144. self.init_database()
  145. def init_database(self):
  146. logger.debug(self, 'Init Database Schema...')
  147. from tracim.models.meta import DeclarativeBase
  148. DeclarativeBase.metadata.create_all(self.engine)
  149. def tearDown(self):
  150. logger.debug(self, 'TearDown Test...')
  151. from tracim.models.meta import DeclarativeBase
  152. testing.tearDown()
  153. transaction.abort()
  154. DeclarativeBase.metadata.drop_all(self.engine)
  155. class StandardTest(BaseTest):
  156. """
  157. BaseTest with default fixtures
  158. """
  159. fixtures = [BaseFixture]
  160. def init_database(self):
  161. BaseTest.init_database(self)
  162. fixtures_loader = FixturesLoader(
  163. session=self.session,
  164. config=CFG(self.config.get_settings()))
  165. fixtures_loader.loads(self.fixtures)
  166. class DefaultTest(StandardTest):
  167. def _create_workspace_and_test(self, name, user) -> Workspace:
  168. """
  169. All extra parameters (*args, **kwargs) are for Workspace init
  170. :return: Created workspace instance
  171. """
  172. WorkspaceApi(
  173. current_user=user,
  174. session=self.session,
  175. config=self.app_config,
  176. ).create_workspace(name, save_now=True)
  177. eq_(
  178. 1,
  179. self.session.query(Workspace).filter(
  180. Workspace.label == name
  181. ).count()
  182. )
  183. return self.session.query(Workspace).filter(
  184. Workspace.label == name
  185. ).one()
  186. def _create_content_and_test(
  187. self,
  188. name,
  189. workspace,
  190. *args,
  191. **kwargs
  192. ) -> Content:
  193. """
  194. All extra parameters (*args, **kwargs) are for Content init
  195. :return: Created Content instance
  196. """
  197. content = Content(*args, **kwargs)
  198. content.label = name
  199. content.workspace = workspace
  200. self.session.add(content)
  201. self.session.flush()
  202. content_api = ContentApi(
  203. current_user=None,
  204. session=self.session,
  205. config=self.app_config,
  206. )
  207. eq_(
  208. 1,
  209. content_api.get_canonical_query().filter(
  210. Content.label == name
  211. ).count()
  212. )
  213. return content_api.get_canonical_query().filter(
  214. Content.label == name
  215. ).one()
  216. def _create_thread_and_test(self,
  217. user,
  218. workspace_name='workspace_1',
  219. folder_name='folder_1',
  220. thread_name='thread_1') -> Content:
  221. """
  222. :return: Thread
  223. """
  224. workspace = self._create_workspace_and_test(workspace_name, user)
  225. folder = self._create_content_and_test(
  226. folder_name, workspace,
  227. type=ContentType.Folder,
  228. owner=user
  229. )
  230. thread = self._create_content_and_test(
  231. thread_name,
  232. workspace,
  233. type=ContentType.Thread,
  234. parent=folder,
  235. owner=user
  236. )
  237. return thread
  238. class MailHogTest(DefaultTest):
  239. """
  240. Theses test need a working mailhog
  241. """
  242. config_section = 'mail_test'
  243. def tearDown(self):
  244. logger.debug(self, 'Cleanup MailHog list...')
  245. requests.delete('http://127.0.0.1:8025/api/v1/messages')