diff --git a/setup.cfg b/apps/common/tests/__init__.py similarity index 100% rename from setup.cfg rename to apps/common/tests/__init__.py diff --git a/apps/common/tests/test_api.py b/apps/common/tests/test_api.py new file mode 100644 index 0000000..1117018 --- /dev/null +++ b/apps/common/tests/test_api.py @@ -0,0 +1,52 @@ +from django.urls import reverse +from faker import Faker +from model_bakery import baker +from rest_framework.test import APITestCase + +from apps.common.models import GenericSource +from apps.common.tests.test_common import LoggedInMixin + +fake = Faker() + + +class TestGenericSourceViewSet(LoggedInMixin, APITestCase): + def setUp(self): + self.generic_source = baker.make( + GenericSource, description=fake.text() + ) + super().setUp() + + def test_create(self): + data = {"name": fake.name(), "description": fake.text()} + url = reverse("genericsource-list") + response = self.client.post(url, data) + assert response.status_code == 201 + + def test_get(self): + fake_data = baker.make( + GenericSource, name=fake.name(), description=fake.text() + ) + url = reverse("genericsource-detail", kwargs={"pk": fake_data.id}) + response = self.client.get(url) + assert response.status_code == 200 + + def test_get_all(self): + url = reverse("genericsource-list") + response = self.client.get(url) + assert response.status_code == 200 + + def test_update(self): + fake_data = baker.make( + GenericSource, name=fake.name(), description=fake.text() + ) + url = reverse("genericsource-detail", kwargs={"pk": fake_data.id}) + response = self.client.patch(url, {"name": "changed name"}) + assert response.status_code == 200 + + def test_delete(self): + fake_data = baker.make( + GenericSource, name=fake.name(), description=fake.text() + ) + url = reverse("genericsource-detail", kwargs={"pk": fake_data.id}) + response = self.client.delete(url) + assert response.status_code == 204 diff --git a/apps/common/tests/test_common.py b/apps/common/tests/test_common.py new file mode 100644 index 0000000..5eca67e --- /dev/null +++ b/apps/common/tests/test_common.py @@ -0,0 +1,31 @@ +import uuid + +from django.contrib.auth import get_user_model +from django.contrib.auth.models import Permission +from faker import Faker +from rest_framework.test import APIRequestFactory, APITestCase + +fake = Faker() +factory = APIRequestFactory() + + +class LoggedInMixin(APITestCase): + """A mixin for user to be used across these tests.""" + + def setUp(self): + """Create a test user for the logged-in session.""" + super(LoggedInMixin, self).setUp() + username = str(uuid.uuid4()) + self.user = get_user_model().objects.create_superuser( + email=fake.email(), + password="pass@123", + username=username, + ) + all_perms = Permission.objects.all() + for perm in all_perms: + self.user.user_permissions.add(perm) + self.user.save() + + assert ( + self.client.login(username=username, password="pass@123") is True + ) diff --git a/apps/dashboards/tests/__init__.py b/apps/dashboards/tests/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/apps/dashboards/tests/test_api.py b/apps/dashboards/tests/test_api.py new file mode 100644 index 0000000..e67bb08 --- /dev/null +++ b/apps/dashboards/tests/test_api.py @@ -0,0 +1,94 @@ +from django.urls import reverse +from faker import Faker +from model_bakery import baker +from rest_framework.test import APIRequestFactory, APITestCase + +from apps.common.tests.test_common import LoggedInMixin +from apps.dashboards.models import Dashboard, Visualization + +fake = Faker() +factory = APIRequestFactory() + + +class TestVisualizationViewSet(LoggedInMixin, APITestCase): + def setUp(self): + self.visualization = baker.make(Visualization) + super().setUp() + + def test_create(self): + data = { + "title": self.visualization.title, + "description": self.visualization.description, + "source": self.visualization.source, + "width": self.visualization.width, + "height": self.visualization.height, + "weight": self.visualization.weight, + "is_published": self.visualization.is_published, + } + url = reverse("visualization-list") + response = self.client.post(url, data) + assert response.status_code == 201 + + def test_get(self): + fake_data = baker.make(Visualization) + url = reverse("visualization-detail", kwargs={"pk": fake_data.id}) + response = self.client.get(url) + assert response.status_code == 200 + + def test_get_all(self): + url = reverse("visualization-list") + response = self.client.get(url) + assert response.status_code == 200 + + def test_update(self): + fake_data = baker.make(Visualization) + url = reverse("visualization-detail", kwargs={"pk": fake_data.id}) + response = self.client.patch(url, {"title": "updated title"}) + assert response.status_code == 200 + + def test_delete(self): + fake_data = baker.make(Visualization) + url = reverse("visualization-detail", kwargs={"pk": fake_data.id}) + response = self.client.delete(url) + assert response.status_code == 204 + + +class TestDashboardViewSet(LoggedInMixin, APITestCase): + def setUp(self): + self.dashboard = baker.make(Dashboard) + super().setUp() + + def test_create(self): + data = { + "title": self.dashboard.title, + "description": self.dashboard.description, + "layout": self.dashboard.layout, + "weight": self.dashboard.weight, + "visualizations": self.dashboard.visualizations, + } + url = reverse("dashboard-list") + response = self.client.post(url, data) + assert response.status_code == 201 + + def test_get(self): + fake_data = baker.make(Dashboard) + url = reverse("dashboard-detail", kwargs={"pk": fake_data.id}) + response = self.client.get(url) + assert response.status_code == 200 + + def test_get_all(self): + url = reverse("dashboard-list") + response = self.client.get(url) + assert response.status_code == 200 + + def test_update(self): + fake_data = baker.make(Dashboard) + url = reverse("dashboard-detail", kwargs={"pk": fake_data.id}) + response = self.client.patch(url, {"title": "updated title"}) + assert response.status_code == 200 + + def test_delete(self): + fake_data = baker.make(Dashboard) + url = reverse("dashboard-detail", kwargs={"pk": fake_data.id}) + response = self.client.delete(url) + assert response.status_code == 204 diff --git a/apps/sql_data/models.py b/apps/sql_data/models.py index 2a332a5..0c264c5 100644 --- a/apps/sql_data/models.py +++ b/apps/sql_data/models.py @@ -173,7 +173,7 @@ def data_source_name(self) -> str: @property def is_complete(self) -> bool: # TODO: Add implementation. - return False + return False # pragma: no cover class Meta(AbstractExtractMetadata.Meta): verbose_name_plural = "Sql upload metadata" diff --git a/apps/sql_data/tests/__init__.py b/apps/sql_data/tests/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/apps/sql_data/tests/test_api.py b/apps/sql_data/tests/test_api.py new file mode 100644 index 0000000..847fe3f --- /dev/null +++ b/apps/sql_data/tests/test_api.py @@ -0,0 +1,48 @@ +from django.urls import reverse +from faker import Faker +from model_bakery import baker +from rest_framework.test import APIRequestFactory, APITestCase + +from apps.common.tests.test_common import LoggedInMixin +from apps.sql_data.models import SQLUploadChunk, SQLUploadMetadata + +fake = Faker() +factory = APIRequestFactory() + + +class TestSQLUploadChunkViewSet(LoggedInMixin, APITestCase): + def setUp(self): + self.sql_upload_chunk = baker.make(SQLUploadChunk) + super().setUp() + + def test_get(self): + fake_data = baker.make(SQLUploadChunk) + url = reverse("sqluploadchunk-detail", kwargs={"pk": fake_data.id}) + response = self.client.get(url) + assert response.status_code == 200 + + def test_get_all(self): + url = reverse("sqluploadchunk-list") + response = self.client.get(url) + assert response.status_code == 200 + + def test_update(self): + fake_data = baker.make(SQLUploadChunk) + url = reverse("sqluploadchunk-detail", kwargs={"pk": fake_data.id}) + response = self.client.patch(url, {"chunk-index": 4}) + assert response.status_code == 200 + + +class TestSQLUploadMetadataViewSet(LoggedInMixin, APITestCase): + def setUp(self): + self.upload_metadata = baker.make(SQLUploadMetadata) + super().setUp() + + def test_create(self): + data = {"chunk_index": 1} + url = reverse( + "sqluploadmetadata-start-chunk-upload", + kwargs={"pk": self.upload_metadata.pk}, + ) + response = self.client.post(url, data, format="json") + assert response.status_code == 201 diff --git a/apps/sql_data/tests/test_models.py b/apps/sql_data/tests/test_models.py new file mode 100644 index 0000000..9f5405a --- /dev/null +++ b/apps/sql_data/tests/test_models.py @@ -0,0 +1,69 @@ +import pytest +from django.conf import settings +from faker import Faker +from model_bakery import baker +from rest_framework.test import APITestCase + +from apps.common.tests.test_common import LoggedInMixin +from apps.sql_data.models import ( + DataSourceVersion, + SQLExtractMetadata, + SQLUploadChunk, + SQLUploadMetadata, + sql_extracts_upload_to, +) + +pytestmark = pytest.mark.django_db + +fake = Faker() + + +class InitializeTestData(LoggedInMixin, APITestCase): + def setUp(self): + self.upload_chunk = baker.make( + SQLUploadChunk, chunk_content=fake.file_name() + ) + self.data_source_version = baker.make(DataSourceVersion) + self.extract_metadata = baker.make(SQLExtractMetadata) + self.sql_upload_metadata = baker.make( + SQLUploadMetadata, extract_metadata=self.extract_metadata + ) + + super().setUp() + + def test_upload_metadata(self): + assert ( + self.extract_metadata.data_source.name + == self.sql_upload_metadata.data_source_name + ) + + def test_uploaded_chunk_str(self): + assert str(self.upload_chunk) == str( + self.upload_chunk.chunk_index + ) + "__" + str(self.upload_chunk.id) + + sql_upload_chunk = self.upload_chunk + meta = sql_upload_chunk.upload_metadata.extract_metadata + extracts_group_name: str = meta.preferred_uploads_name or meta.name + name = sql_upload_chunk.upload_metadata.name + chunk_index = sql_upload_chunk.chunk_index + pk = str(sql_upload_chunk.pk) + assert sql_extracts_upload_to( + sql_upload_chunk, fake.text() + ) == "%s/%s/%s/%s/%d__%s" % ( + settings.BASE_EXTRACTS_UPLOAD_DIR_NAME, + settings.SQL_EXTRACTS_UPLOAD_DIR_NAME, + extracts_group_name, + name, + chunk_index, + pk, + ) + + def test_data_source_version_str(self): + assert ( + str(self.data_source_version) + == str(self.data_source_version.data_source) + + " v(" + + str(self.data_source_version.data_source_version) + + ")" + ) diff --git a/pyproject.toml b/pyproject.toml index bbf99bc..951761d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.black] line-length = 79 -target-version = ["py37"] +target-version = ["py39"] [tool.coverage.html] @@ -78,7 +78,7 @@ typeCheckingMode = "basic" [tool.pytest.ini_options] -addopts = "--ds=config.settings.test --cov-fail-under=53 --cov --cov-config=pyproject.toml --cov-report=html --cov-report=term-missing -n auto --junitxml='junitxml_report/report.xml' -v --durations=10 --cache-clear --create-db" +addopts = "--ds=config.settings.test --cov-fail-under=90 --cov --cov-config=pyproject.toml --cov-report=html --cov-report=term-missing -n auto --junitxml='junitxml_report/report.xml' -v --durations=10 --cache-clear --create-db" console_output_style = "progress" log_cli = 1 log_cli_date_format = "%Y-%m-%d %H:%M:%S" diff --git a/requirements/test.txt b/requirements/test.txt index 3b7036c..a9b6520 100644 --- a/requirements/test.txt +++ b/requirements/test.txt @@ -27,7 +27,7 @@ pytest-sugar~=0.9.5 pytest-xdist~=2.5.0 pytest~=7.1.2 tox~=3.25.1 - +model-bakery~=1.7.0 # Coverage # -----------------------------------------------------------------------------