conftest.py 6.41 KB
Newer Older
1
import datetime
2 3
import shutil
import tempfile
4

Agate's avatar
Agate committed
5 6 7
import factory
import pytest
import requests_mock
Agate's avatar
Agate committed
8
from django.contrib.auth.models import AnonymousUser
9
from django.core.cache import cache as django_cache
10
from django.utils import timezone
11
from django.test import client
12
from dynamic_preferences.registries import global_preferences_registry
13
from rest_framework import fields as rest_fields
Agate's avatar
Agate committed
14
from rest_framework.test import APIClient, APIRequestFactory
15

16
from funkwhale_api.activity import record
17
from funkwhale_api.users.permissions import HasUserPermission
18 19 20 21 22 23


@pytest.fixture(scope="session", autouse=True)
def factories_autodiscover():
    from django.apps import apps
    from funkwhale_api import factories
Agate's avatar
Agate committed
24

25 26 27 28
    app_names = [app.name for app in apps.app_configs.values()]
    factories.registry.autodiscover(app_names)


29 30
@pytest.fixture(autouse=True)
def cache():
Agate's avatar
Agate committed
31 32 33
    """
    Returns a django Cache instance for cache-related operations
    """
34 35 36 37
    yield django_cache
    django_cache.clear()


38 39
@pytest.fixture
def factories(db):
Agate's avatar
Agate committed
40 41 42 43
    """
    Returns a dictionnary containing all registered factories with keys such as
    users.User or music.Track
    """
44
    from funkwhale_api import factories
Agate's avatar
Agate committed
45

46
    for v in factories.registry.values():
47 48 49 50 51
        try:
            v._meta.strategy = factory.CREATE_STRATEGY
        except AttributeError:
            # probably not a class based factory
            pass
52 53 54 55 56
    yield factories.registry


@pytest.fixture
def nodb_factories():
Agate's avatar
Agate committed
57 58 59 60
    """
    Returns a dictionnary containing all registered factories with a build strategy
    that does not require access to the database
    """
61
    from funkwhale_api import factories
Agate's avatar
Agate committed
62

63
    for v in factories.registry.values():
64 65 66 67 68
        try:
            v._meta.strategy = factory.BUILD_STRATEGY
        except AttributeError:
            # probably not a class based factory
            pass
69 70 71
    yield factories.registry


72
@pytest.fixture
73
def preferences(db, cache):
Agate's avatar
Agate committed
74 75 76
    """
    return a dynamic_preferences manager for global_preferences
    """
77 78 79
    manager = global_preferences_registry.manager()
    manager.all()
    yield manager
80 81


82 83
@pytest.fixture
def tmpdir():
Agate's avatar
Agate committed
84 85 86 87
    """
    Returns a temporary directory path where you can write things during your
    test
    """
88 89 90 91 92
    d = tempfile.mkdtemp()
    yield d
    shutil.rmtree(d)


Agate's avatar
Agate committed
93 94
@pytest.fixture
def tmpfile():
Agate's avatar
Agate committed
95 96 97
    """
    Returns a temporary file where you can write things during your test
    """
Agate's avatar
Agate committed
98 99 100
    yield tempfile.NamedTemporaryFile()


101 102
@pytest.fixture
def logged_in_client(db, factories, client):
Agate's avatar
Agate committed
103 104 105 106
    """
    Returns a logged-in, non-API client with an authenticated ``User``
    stored in the ``user`` attribute
    """
Agate's avatar
Agate committed
107 108 109
    user = factories["users.User"]()
    assert client.login(username=user.username, password="test")
    setattr(client, "user", user)
110
    yield client
Agate's avatar
Agate committed
111
    delattr(client, "user")
112 113


Agate's avatar
Agate committed
114 115
@pytest.fixture
def anonymous_user():
Agate's avatar
Agate committed
116
    """Returns a AnonymousUser() instance"""
Agate's avatar
Agate committed
117 118 119
    return AnonymousUser()


120 121
@pytest.fixture
def api_client(client):
Agate's avatar
Agate committed
122 123 124
    """
    Return an API client without any authentication
    """
125 126 127
    return APIClient()


Agate's avatar
Agate committed
128 129
@pytest.fixture
def logged_in_api_client(db, factories, api_client):
Agate's avatar
Agate committed
130 131 132 133
    """
    Return a logged-in API client with an authenticated ``User``
    stored in the ``user`` attribute
    """
Agate's avatar
Agate committed
134 135
    user = factories["users.User"]()
    assert api_client.login(username=user.username, password="test")
136
    api_client.force_authenticate(user=user)
Agate's avatar
Agate committed
137
    setattr(api_client, "user", user)
Agate's avatar
Agate committed
138
    yield api_client
Agate's avatar
Agate committed
139
    delattr(api_client, "user")
Agate's avatar
Agate committed
140 141


142 143
@pytest.fixture
def superuser_api_client(db, factories, api_client):
Agate's avatar
Agate committed
144 145 146 147
    """
    Return a logged-in API client with an authenticated superuser
    stored in the ``user`` attribute
    """
Agate's avatar
Agate committed
148 149 150
    user = factories["users.SuperUser"]()
    assert api_client.login(username=user.username, password="test")
    setattr(api_client, "user", user)
151
    yield api_client
Agate's avatar
Agate committed
152
    delattr(api_client, "user")
153 154


155 156
@pytest.fixture
def superuser_client(db, factories, client):
Agate's avatar
Agate committed
157 158 159 160
    """
    Return a logged-in, non-API client with an authenticated ``User``
    stored in the ``user`` attribute
    """
Agate's avatar
Agate committed
161 162 163
    user = factories["users.SuperUser"]()
    assert client.login(username=user.username, password="test")
    setattr(client, "user", user)
164
    yield client
Agate's avatar
Agate committed
165
    delattr(client, "user")
166 167


168 169
@pytest.fixture
def api_request():
Agate's avatar
Agate committed
170 171 172
    """
    Returns a dummy API request object you can pass to API views
    """
173 174 175
    return APIRequestFactory()


176 177
@pytest.fixture
def fake_request():
Agate's avatar
Agate committed
178 179 180
    """
    Returns a dummy, non-API request object you can pass to regular views
    """
181 182 183
    return client.RequestFactory()


184 185 186 187 188 189 190 191 192 193 194
@pytest.fixture
def activity_registry():
    state = list(record.registry.items())
    yield record.registry
    record.registry.clear()
    for key, value in state:
        record.registry[key] = value


@pytest.fixture
def activity_muted(activity_registry, mocker):
Agate's avatar
Agate committed
195
    yield mocker.patch.object(record, "send")
Agate's avatar
Agate committed
196 197 198 199


@pytest.fixture(autouse=True)
def media_root(settings):
Agate's avatar
Agate committed
200 201 202
    """
    Sets settings.MEDIA_ROOT to a temporary path and returns this path
    """
Agate's avatar
Agate committed
203 204 205 206
    tmp_dir = tempfile.mkdtemp()
    settings.MEDIA_ROOT = tmp_dir
    yield settings.MEDIA_ROOT
    shutil.rmtree(tmp_dir)
207 208 209 210


@pytest.fixture
def r_mock():
Agate's avatar
Agate committed
211 212 213 214
    """
    Returns a requests_mock.mock() object you can use to mock HTTP calls made
    using python-requests
    """
215 216
    with requests_mock.mock() as m:
        yield m
217 218 219 220


@pytest.fixture
def authenticated_actor(factories, mocker):
Agate's avatar
Agate committed
221 222 223
    """
    Returns an authenticated ActivityPub actor
    """
Agate's avatar
Agate committed
224
    actor = factories["federation.Actor"]()
225
    mocker.patch(
Agate's avatar
Agate committed
226 227 228
        "funkwhale_api.federation.authentication.SignatureAuthentication.authenticate_actor",
        return_value=actor,
    )
229
    yield actor
230 231 232 233


@pytest.fixture
def assert_user_permission():
Agate's avatar
Agate committed
234
    def inner(view, permissions, operator="and"):
235
        assert HasUserPermission in view.permission_classes
Agate's avatar
Agate committed
236
        assert getattr(view, "permission_operator", "and") == operator
237
        assert set(view.required_permissions) == set(permissions)
Agate's avatar
Agate committed
238

239
    return inner
240 241 242 243 244 245 246 247 248 249 250


@pytest.fixture
def to_api_date():
    def inner(value):
        if isinstance(value, datetime.datetime):
            f = rest_fields.DateTimeField()
            return f.to_representation(value)
        if isinstance(value, datetime.date):
            f = rest_fields.DateField()
            return f.to_representation(value)
Agate's avatar
Agate committed
251 252
        raise ValueError("Invalid value: {}".format(value))

253
    return inner
254 255 256 257 258 259 260


@pytest.fixture()
def now(mocker):
    now = timezone.now()
    mocker.patch("django.utils.timezone.now", return_value=now)
    return now