diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 9196a6fa..23a8d81a 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -9,8 +9,8 @@ jobs: strategy: max-parallel: 4 matrix: - python-version: [3.5, 3.6, 3.7, 3.8] - django-version: [2.2, 2.2.8, 3.0, 3.1] + python-version: [3.5, 3.6, 3.7, 3.8, 3.9, '3.10'] + django-version: [2.2, 2.2.8, 3.0, 3.1, 3.2] exclude: - python-version: 3.5 django-version: 2.2.8 @@ -18,13 +18,23 @@ jobs: django-version: 3.0 - python-version: 3.5 django-version: 3.1 + - python-version: 3.5 + django-version: 3.2 - python-version: 3.8 django-version: 2.2 + - python-version: 3.10 + django-version: 2.2 + - python-version: 3.10 + django-version: 2.2.8 + - python-version: 3.10 + django-version: 3.0 + - python-version: 3.10 + django-version: 3.1 steps: - uses: actions/checkout@v2 - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v1 + uses: actions/setup-python@v2 with: python-version: ${{ matrix.python-version }} - name: Install Dependencies diff --git a/.travis.yml b/.travis.yml index 80e29c19..a8e1cd59 100644 --- a/.travis.yml +++ b/.travis.yml @@ -14,6 +14,7 @@ env: - DJANGO="django>=2.2.8,<3.0" - DJANGO="django>=3.0,<3.1" - DJANGO="django>=3.1,<3.2" + - DJANGO="django>=3.2,<3.3" install: - pip install ${DJANGO} @@ -31,6 +32,8 @@ matrix: env: DJANGO="django>=3.0,<3.1" - python: "3.5" env: DJANGO="django>=3.1,<3.2" + - python: "3.5" + env: DJANGO="django>=3.2,<3.3" - python: "3.8" env: DJANGO="django>=2.0,<2.1" - python: "3.8" diff --git a/easyaudit/tests/test_app/tests.py b/easyaudit/tests/test_app/tests.py index c10267ab..96568a32 100644 --- a/easyaudit/tests/test_app/tests.py +++ b/easyaudit/tests/test_app/tests.py @@ -8,7 +8,7 @@ asgi_views_supported = django.VERSION >= (3, 1) if asgi_views_supported: from asgiref.sync import sync_to_async -from django.test import TestCase, override_settings, tag +from django.test import TestCase, override_settings, tag, TransactionTestCase, SimpleTestCase from django.urls import reverse, reverse_lazy @@ -24,14 +24,14 @@ from easyaudit.middleware.easyaudit import set_current_user, clear_request -TEST_USER_EMAIL = 'joe@example.com' -TEST_USER_PASSWORD = 'password' -TEST_ADMIN_EMAIL = 'admin@example.com' -TEST_ADMIN_PASSWORD = 'password' +class WithUserInfoMixin: + def setUp(self): + self.username = 'joe@example.com' + self.email = 'joe@example.com' + self.password = 'password' -@override_settings(TEST=True) -class TestDjangoCompat(TestCase): +class TestDjangoCompat(SimpleTestCase): def test_model_state(self): """Ensures models have the internal `_state` object.""" @@ -128,20 +128,11 @@ class TestAuditBigIntModels(TestAuditModels): @override_settings(TEST=True) -class TestMiddleware(TestCase): - def _setup_user(self, email, password): - user = User(username=email) - user.set_password(password) - user.save() - return user - - def _log_in_user(self, email, password): - login = self.client.login(username=email, password=password) - self.assertTrue(login) +class TestMiddleware(WithUserInfoMixin, TestCase): def test_middleware_logged_in(self): - user = self._setup_user(TEST_USER_EMAIL, TEST_USER_PASSWORD) - self._log_in_user(TEST_USER_EMAIL, TEST_USER_PASSWORD) + user = User.objects.create_user(self.username, self.email, self.password) + self.client.login(username=self.username, password=self.password) create_obj_url = reverse("test_app:create-obj") self.client.post(create_obj_url) self.assertEqual(TestModel.objects.count(), 1) @@ -158,7 +149,7 @@ def test_middleware_not_logged_in(self): self.assertEqual(crud_event.user, None) def test_manual_set_user(self): - user = self._setup_user(TEST_USER_EMAIL, TEST_USER_PASSWORD) + user = User.objects.create_user(self.username, self.email, self.password) # set user/request set_current_user(user) @@ -180,7 +171,7 @@ def test_manual_set_user(self): @skip("Test may need a rewrite but the library logic has been rolled back.") def test_middleware_logged_in_user_in_request(self): - user = self._setup_user(TEST_USER_EMAIL, TEST_USER_PASSWORD) + user = User.objects.create_user(self.username, self.email, self.password) self.client.force_login(user) create_obj_url = reverse("test_app:create-obj") self.client.post(create_obj_url) @@ -193,47 +184,23 @@ def test_middleware_logged_in_user_in_request(self): @tag("asgi") @override_settings(TEST=True) @skipIf(not asgi_views_supported, "Testing ASGI is easier with Django 3.1") -class TestASGIRequestEvent(TestCase): - - def _setup_user(self, email, password): - user = User.objects.create(username=email) - user.set_password(password) - user.save() - return user - - def _log_in_user(self, email, password): - login = self.async_client.login(username=email, password=password) - self.assertTrue(login) +class TestASGIRequestEvent(WithUserInfoMixin, TransactionTestCase): async def test_login(self): - user = await sync_to_async(self._setup_user)(TEST_USER_EMAIL, TEST_USER_PASSWORD) - await sync_to_async(self._log_in_user)(TEST_USER_EMAIL, TEST_USER_PASSWORD) + user = await sync_to_async(User.objects.create_user)(self.username, self.email, self.password) + await sync_to_async(self.async_client.login)(username=self.username, password=self.password) self.assertEqual((await sync_to_async(RequestEvent.objects.count)()), 0) resp = await self.async_client.get(reverse_lazy("test_app:index")) self.assertEqual(resp.status_code, 200) assert (await sync_to_async(RequestEvent.objects.get)(user=user)) - # asyncio and transactions do not mix all that well, so here we are performing manual cleanup of the objects - # created within this test - await sync_to_async(user.delete)() - await sync_to_async(RequestEvent.objects.all().delete)() @override_settings(TEST=True) -class TestWSGIRequestEvent(TestCase): - - def _setup_user(self, email, password): - user = User.objects.create(username=email) - user.set_password(password) - user.save() - return user - - def _log_in_user(self, email, password): - login = self.client.login(username=email, password=password) - self.assertTrue(login) +class TestWSGIRequestEvent(WithUserInfoMixin, TestCase): def test_login(self): - user = self._setup_user(TEST_USER_EMAIL, TEST_USER_PASSWORD) - self._log_in_user(TEST_USER_EMAIL, TEST_USER_PASSWORD) + user = User.objects.create_user(self.username, self.email, self.password) + self.client.login(username=self.username, password=self.password) self.assertEqual(RequestEvent.objects.count(), 0) resp = self.client.get(reverse_lazy("test_app:index")) self.assertEqual(resp.status_code, 200) @@ -241,16 +208,7 @@ def test_login(self): @override_settings(TEST=True) -class TestAuditAdmin(TestCase): - - def _setup_superuser(self, email, password): - admin = User.objects.create_superuser(email, email, password) - admin.save() - return admin - - def _log_in_user(self, email, password): - login = self.client.login(username=email, password=password) - self.assertTrue(login) +class TestAuditAdmin(WithUserInfoMixin, TestCase): def _list_filters(self, content): """ @@ -273,8 +231,8 @@ def _list_filters(self, content): return filters def test_request_event_admin_no_users(self): - self._setup_superuser(TEST_ADMIN_EMAIL, TEST_ADMIN_PASSWORD) - self._log_in_user(TEST_ADMIN_EMAIL, TEST_ADMIN_PASSWORD) + User.objects.create_superuser(self.username, self.email, self.password) + self.client.login(username=self.username, password=self.password) response = self.client.get(reverse('admin:easyaudit_requestevent_changelist')) self.assertEqual(200, response.status_code) filters = self._list_filters(response.content) diff --git a/setup.py b/setup.py index 5a44e816..97257313 100644 --- a/setup.py +++ b/setup.py @@ -15,7 +15,7 @@ include_package_data=True, install_requires=[ "beautifulsoup4", - "django>=2.2,<3.2" + "django>=2.2,<3.3" ], python_requires=">=3.5", license='GPL3', @@ -30,6 +30,7 @@ "Framework :: Django :: 2.2", "Framework :: Django :: 3.0", "Framework :: Django :: 3.1", + "Framework :: Django :: 3.2", 'Intended Audience :: Developers', 'License :: OSI Approved :: GNU General Public License v3 (GPLv3)', 'Operating System :: OS Independent', @@ -39,6 +40,8 @@ 'Programming Language :: Python :: 3.6', 'Programming Language :: Python :: 3.7', 'Programming Language :: Python :: 3.8', + 'Programming Language :: Python :: 3.9', + 'Programming Language :: Python :: 3.10', 'Topic :: Software Development :: Libraries :: Python Modules', ], )