Coverage for src/paperap/tests/pytest.py: 85%

1"""

2

3

4

5

6 ----------------------------------------------------------------------------

7

8 METADATA:

9

10 File: pytest.py

11 Project: paperap

12 Created: 2025-03-12

13 Version: 0.0.5

14 Author: Jess Mann

15 Email: jess@jmann.me

16 Copyright (c) 2025 Jess Mann

17

18 ----------------------------------------------------------------------------

19

20 LAST MODIFIED:

21

22 2025-03-12 By Jess Mann

23

24"""

25 from __future__ import annotations

26

27 import json

28 import logging

29 import os

30 from pathlib import Path

31 from typing import TYPE_CHECKING, Any, Callable, Generic, Iterator, override

32 import pytest

33

34 from pydantic import ValidationError

35 from typing_extensions import TypeAlias, TypeVar

36

37 from paperap.client import PaperlessClient

38 from paperap.models import (BaseQuerySet, Correspondent, CorrespondentQuerySet,

39 CustomField, CustomFieldQuerySet,

40 Document, DocumentQuerySet, DocumentType,

41 DocumentTypeQuerySet, Group, GroupQuerySet,

42 Profile, ProfileQuerySet, SavedView,

43 SavedViewQuerySet, ShareLinks, ShareLinksQuerySet,

44 StandardModel, StandardQuerySet, StoragePath,

45 StoragePathQuerySet, Tag, TagQuerySet, Task,

46 TaskQuerySet, UISettings, UISettingsQuerySet, User,

47 UserQuerySet, Workflow, WorkflowAction,

48 WorkflowActionQuerySet, WorkflowQuerySet,

49 WorkflowTrigger, WorkflowTriggerQuerySet)

50 from paperap.resources import (BaseResource, CorrespondentResource,

51 CustomFieldResource,

52 DocumentResource, DocumentTypeResource,

53 GroupResource, ProfileResource,

54 SavedViewResource, ShareLinksResource,

55 StandardResource, StoragePathResource,

56 TagResource, TaskResource, UISettingsResource,

57 UserResource, WorkflowActionResource,

58 WorkflowResource, WorkflowTriggerResource)

59 from paperap.tests.factories import (CorrespondentFactory, DocumentFactory,

60 DocumentTypeFactory, GroupFactory,

61 ProfileFactory, PydanticFactory,

62 SavedViewFactory, ShareLinksFactory,

63 StoragePathFactory, TagFactory,

64 TaskFactory, UISettingsFactory,

65 UserFactory, WorkflowActionFactory,

66 WorkflowFactory, WorkflowTriggerFactory)

67

68 from paperap.tests.testcase import TestMixin

69

70 logger = logging.getLogger(__name__)

71

72 _StandardModel = TypeVar("_StandardModel", bound="StandardModel", default="StandardModel")

73 _StandardResource = TypeVar("_StandardResource", bound="StandardResource", default="StandardResource")

74 _StandardQuerySet = TypeVar("_StandardQuerySet", bound="StandardQuerySet", default="StandardQuerySet")

75

76 class PyTestCase(

77 TestMixin[_StandardModel, _StandardResource, _StandardQuerySet],

78 Generic[_StandardModel, _StandardResource, _StandardQuerySet]

79):

80 @pytest.fixture(autouse=True)

81 def setUp(self, mocker) -> None:

82 """

83 Set up the test case by initializing the client, resource, and model data.

84 """

85 self.setup_references()

86 self.setup_client(mocker)

87 self.setup_resource()

88 self.setup_model_data()

89 self.setup_model()

90

91 @override

92 def setup_client(self, mocker : Any = None, **kwargs):

93 """Set up the PaperlessClient instance, optionally mocking environment variables."""

94 if not hasattr(self, "client") or not self.client:

95 if self.mock_env:

96 # Patch os.environ with pytest

97 mocker.patch.dict(os.environ, self.env_data, clear=True)

98 self.client = PaperlessClient()

99 else:

100 self.client = PaperlessClient()

101

102 @override

103 def validate_field(self, field_name: str, test_cases: list[tuple[Any, Any]]):

104 """Validate that a model field processes data correctly."""

105 for input_value, expected in test_cases:

106 if isinstance(expected, type) and issubclass(expected, Exception):

107 with pytest.raises(expected, match=f"Setting {self.model.__class__.__name__}.{field_name} failed"):

108 setattr(self.model, field_name, input_value)

109 else:

110 setattr(self.model, field_name, input_value)

111 real_value = getattr(self.model, field_name)

112 assert isinstance(real_value, type(expected)), f"Expected type {type(expected)}, got {type(real_value)}"

113 assert real_value == expected, f"Expected {expected}, got {real_value}"

114

115 class CustomFieldPyTest(PyTestCase["CustomField", "CustomFieldResource", "CustomFieldQuerySet"]):

116 """

117 A test case for the CustomField model and resource.

118 """

119 resource_class = CustomFieldResource

120 model_type = CustomField

121 queryset_type = CustomFieldQuerySet

122 #factory = PydanticFactory

123

124 class DocumentPyTest(PyTestCase["Document", "DocumentResource", "DocumentQuerySet"]):

125 """

126 A test case for the Document model and resource.

127 """

128 resource_class = DocumentResource

129 model_type = Document

130 queryset_type = DocumentQuerySet

131 factory = DocumentFactory

132

133 class DocumentTypePyTest(PyTestCase["DocumentType", "DocumentTypeResource", "DocumentTypeQuerySet"]):

134 """

135 A test case for the DocumentType model and resource.

136 """

137 resource_class = DocumentTypeResource

138 model_type = DocumentType

139 queryset_type = DocumentTypeQuerySet

140 factory = DocumentTypeFactory

141

142 class CorrespondentPyTest(PyTestCase["Correspondent", "CorrespondentResource", "CorrespondentQuerySet"]):

143 """

144 A test case for the Correspondent model and resource.

145 """

146 resource_class = CorrespondentResource

147 model_type = Correspondent

148 queryset_type = CorrespondentQuerySet

149 factory = CorrespondentFactory

150

151 class TagPyTest(PyTestCase["Tag", "TagResource", "TagQuerySet"]):

152 """

153 A test case for the Tag model and resource.

154 """

155 resource_class = TagResource

156 model_type = Tag

157 queryset_type = TagQuerySet

158 factory = TagFactory

159

160 class UserPyTest(PyTestCase["User", "UserResource", "UserQuerySet"]):

161 """

162 A test case for the User model and resource.

163 """

164 resource_class = UserResource

165 model_type = User

166 queryset_type = UserQuerySet

167 factory = UserFactory

168

169 class GroupPyTest(PyTestCase["Group", "GroupResource", "GroupQuerySet"]):

170 """

171 A test case for the Group model and resource.

172 """

173 resource_class = GroupResource

174 model_type = Group

175 queryset_type = GroupQuerySet

176 factory = GroupFactory

177

178 class ProfilePyTest(PyTestCase["Profile", "ProfileResource", "ProfileQuerySet"]):

179 """

180 A test case for the Profile model and resource.

181 """

182 resource_class = ProfileResource

183 model_type = Profile

184 queryset_type = ProfileQuerySet

185 factory = ProfileFactory

186

187 class TaskPyTest(PyTestCase["Task", "TaskResource", "TaskQuerySet"]):

188 """

189 A test case for the Task model and resource.

190 """

191 resource_class = TaskResource

192 model_type = Task

193 queryset_type = TaskQuerySet

194 factory = TaskFactory

195

196 class WorkflowPyTest(PyTestCase["Workflow", "WorkflowResource", "WorkflowQuerySet"]):

197 """

198 A test case for the Workflow model and resource.

199 """

200 resource_class = WorkflowResource

201 model_type = Workflow

202 queryset_type = WorkflowQuerySet

203 factory = WorkflowFactory

204

205 class SavedViewPyTest(PyTestCase["SavedView", "SavedViewResource", "SavedViewQuerySet"]):

206 """

207 A test case for the SavedView model and resource.

208 """

209 resource_class = SavedViewResource

210 model_type = SavedView

211 queryset_type = SavedViewQuerySet

212 factory = SavedViewFactory

213

214 class ShareLinksPyTest(PyTestCase["ShareLinks", "ShareLinksResource", "ShareLinksQuerySet"]):

215 """

216 A test case for ShareLinks

217 """

218 resource_class = ShareLinksResource

219 model_type = ShareLinks

220 queryset_type = ShareLinksQuerySet

221 factory = ShareLinksFactory

222

223 class UISettingsPyTest(PyTestCase["UISettings", "UISettingsResource", "UISettingsQuerySet"]):

224 """

225 A test case for the UISettings model and resource.

226 """

227 resource_class = UISettingsResource

228 model_type = UISettings

229 queryset_type = UISettingsQuerySet

230 factory = UISettingsFactory

231

232 class StoragePathPyTest(PyTestCase["StoragePath", "StoragePathResource", "StoragePathQuerySet"]):

233 """

234 A test case for the StoragePath model and resource.

235 """

236 resource_class = StoragePathResource

237 model_type = StoragePath

238 queryset_type = StoragePathQuerySet

239 factory = StoragePathFactory

240

241 class WorkflowActionPyTest(PyTestCase["WorkflowAction", "WorkflowActionResource", "WorkflowActionQuerySet"]):

242 """

243 A test case for the WorkflowAction model and resource.

244 """

245 resource_class = WorkflowActionResource

246 model_type = WorkflowAction

247 queryset_type = WorkflowActionQuerySet

248 factory = WorkflowActionFactory

249

250 class WorkflowTriggerPyTest(PyTestCase["WorkflowTrigger", "WorkflowTriggerResource", "WorkflowTriggerQuerySet"]):

251 """

252 A test case for the WorkflowTrigger model and resource.

253 """

254 resource_class = WorkflowTriggerResource

255 model_type = WorkflowTrigger

256 queryset_type = WorkflowTriggerQuerySet

257 factory = WorkflowTriggerFactory