Passed
Push — develop ( 8c70ee...cae2d7 )
by Bastien
01:41
created

DefaultTest._create_thread_and_test()   A

Complexity

Conditions 1

Size

Total Lines 22
Code Lines 17

Duplication

Lines 0
Ratio 0 %

Importance

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