Add periodic exchange task management API
Some checks failed
CI/CD Pipeline / Code Quality Checks (push) Successful in 3m16s
CI/CD Pipeline / Run Tests (push) Successful in 3m26s
CI/CD Pipeline / Telegram Notify Success (push) Failing after 1m29s
CI/CD Pipeline / Run Tests (pull_request) Successful in 1m44s
CI/CD Pipeline / Code Quality Checks (pull_request) Successful in 20m19s
CI/CD Pipeline / Telegram Notify Success (pull_request) Failing after 1m34s
Some checks failed
CI/CD Pipeline / Code Quality Checks (push) Successful in 3m16s
CI/CD Pipeline / Run Tests (push) Successful in 3m26s
CI/CD Pipeline / Telegram Notify Success (push) Failing after 1m29s
CI/CD Pipeline / Run Tests (pull_request) Successful in 1m44s
CI/CD Pipeline / Code Quality Checks (pull_request) Successful in 20m19s
CI/CD Pipeline / Telegram Notify Success (pull_request) Failing after 1m34s
This commit is contained in:
@@ -1,11 +1,14 @@
|
||||
"""Tests for exchange API views."""
|
||||
|
||||
import json
|
||||
from types import SimpleNamespace
|
||||
from unittest.mock import patch
|
||||
|
||||
from apps.exchange.models import ExchangeConnection
|
||||
from apps.exchange.services import ExchangeServiceError
|
||||
from apps.exchange.services import ExchangePeriodicTaskService, ExchangeServiceError
|
||||
from django.conf import settings
|
||||
from django.urls import reverse
|
||||
from django_celery_beat.models import IntervalSchedule, PeriodicTask
|
||||
from rest_framework import status
|
||||
from rest_framework.test import APITestCase
|
||||
|
||||
@@ -20,6 +23,7 @@ class ExchangeViewsTest(APITestCase):
|
||||
self.connections_url = reverse("api_v1:exchange:connections")
|
||||
self.test_connection_url = reverse("api_v1:exchange:connections-test")
|
||||
self.copy_url = reverse("api_v1:exchange:copy")
|
||||
self.periodic_tasks_url = reverse("api_v1:exchange:periodic-tasks")
|
||||
|
||||
def test_connections_endpoint_admin_only(self):
|
||||
response = self.client.get(self.connections_url)
|
||||
@@ -164,3 +168,141 @@ class ExchangeViewsTest(APITestCase):
|
||||
|
||||
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
|
||||
self.assertIn("table", str(response.data))
|
||||
|
||||
def test_periodic_tasks_endpoint_admin_only(self):
|
||||
response = self.client.get(self.periodic_tasks_url)
|
||||
self.assertEqual(response.status_code, status.HTTP_401_UNAUTHORIZED)
|
||||
|
||||
self.client.force_authenticate(self.user)
|
||||
response = self.client.get(self.periodic_tasks_url)
|
||||
self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)
|
||||
|
||||
self.client.force_authenticate(self.admin)
|
||||
response = self.client.get(self.periodic_tasks_url)
|
||||
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
||||
self.assertTrue(response.data["success"])
|
||||
self.assertEqual(response.data["data"], [])
|
||||
|
||||
def test_create_periodic_interval_task_success(self):
|
||||
payload = {
|
||||
"name": "exchange-copy-hourly",
|
||||
"description": "Hourly sync",
|
||||
"enabled": True,
|
||||
"schedule_type": "interval",
|
||||
"interval_every": 1,
|
||||
"interval_period": "hours",
|
||||
"mode": "all",
|
||||
}
|
||||
|
||||
self.client.force_authenticate(self.admin)
|
||||
response = self.client.post(self.periodic_tasks_url, payload, format="json")
|
||||
|
||||
self.assertEqual(response.status_code, status.HTTP_201_CREATED)
|
||||
task = PeriodicTask.objects.get(id=response.data["data"]["id"])
|
||||
self.assertEqual(task.task, ExchangePeriodicTaskService.TASK_NAME)
|
||||
self.assertEqual(response.data["data"]["schedule_type"], "interval")
|
||||
self.assertEqual(response.data["data"]["interval_every"], 1)
|
||||
self.assertEqual(response.data["data"]["interval_period"], "hours")
|
||||
self.assertEqual(
|
||||
json.loads(task.kwargs),
|
||||
{
|
||||
"payload": {
|
||||
"mode": "all",
|
||||
"table": None,
|
||||
"tables": None,
|
||||
"truncate_before_copy": True,
|
||||
}
|
||||
},
|
||||
)
|
||||
|
||||
def test_list_periodic_tasks_returns_only_exchange_tasks(self):
|
||||
interval = IntervalSchedule.objects.create(every=1, period="hours")
|
||||
PeriodicTask.objects.create(
|
||||
name="exchange-copy-hourly",
|
||||
task=ExchangePeriodicTaskService.TASK_NAME,
|
||||
interval=interval,
|
||||
kwargs=json.dumps(
|
||||
{"payload": {"mode": "all", "truncate_before_copy": True}}
|
||||
),
|
||||
)
|
||||
PeriodicTask.objects.create(
|
||||
name="another-task",
|
||||
task="apps.parsers.tasks.fake_task",
|
||||
interval=interval,
|
||||
kwargs="{}",
|
||||
)
|
||||
|
||||
self.client.force_authenticate(self.admin)
|
||||
response = self.client.get(self.periodic_tasks_url)
|
||||
|
||||
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
||||
self.assertEqual(len(response.data["data"]), 1)
|
||||
self.assertEqual(response.data["data"][0]["name"], "exchange-copy-hourly")
|
||||
|
||||
def test_update_periodic_task_switches_to_crontab(self):
|
||||
interval = IntervalSchedule.objects.create(every=1, period="hours")
|
||||
task = PeriodicTask.objects.create(
|
||||
name="exchange-copy-hourly",
|
||||
task=ExchangePeriodicTaskService.TASK_NAME,
|
||||
description="Hourly sync",
|
||||
enabled=True,
|
||||
interval=interval,
|
||||
kwargs=json.dumps(
|
||||
{
|
||||
"payload": {
|
||||
"mode": "all",
|
||||
"table": None,
|
||||
"tables": None,
|
||||
"truncate_before_copy": True,
|
||||
}
|
||||
}
|
||||
),
|
||||
)
|
||||
detail_url = reverse(
|
||||
"api_v1:exchange:periodic-task-detail",
|
||||
kwargs={"task_id": task.id},
|
||||
)
|
||||
payload = {
|
||||
"schedule_type": "crontab",
|
||||
"crontab_minute": "0",
|
||||
"crontab_hour": "4",
|
||||
"crontab_day_of_week": "*",
|
||||
"crontab_day_of_month": "*",
|
||||
"crontab_month_of_year": "*",
|
||||
"mode": "single",
|
||||
"table": "parsers_proxy",
|
||||
"enabled": False,
|
||||
}
|
||||
|
||||
self.client.force_authenticate(self.admin)
|
||||
response = self.client.patch(detail_url, payload, format="json")
|
||||
|
||||
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
||||
task.refresh_from_db()
|
||||
self.assertIsNone(task.interval)
|
||||
self.assertIsNotNone(task.crontab)
|
||||
self.assertEqual(str(task.crontab.timezone), settings.TIME_ZONE)
|
||||
self.assertFalse(task.enabled)
|
||||
self.assertEqual(response.data["data"]["schedule_type"], "crontab")
|
||||
self.assertEqual(response.data["data"]["crontab_hour"], "4")
|
||||
self.assertEqual(response.data["data"]["mode"], "single")
|
||||
self.assertEqual(response.data["data"]["table"], "parsers_proxy")
|
||||
self.assertFalse(IntervalSchedule.objects.filter(id=interval.id).exists())
|
||||
|
||||
def test_periodic_task_detail_returns_404_for_non_exchange_task(self):
|
||||
interval = IntervalSchedule.objects.create(every=1, period="hours")
|
||||
task = PeriodicTask.objects.create(
|
||||
name="another-task",
|
||||
task="apps.parsers.tasks.fake_task",
|
||||
interval=interval,
|
||||
kwargs="{}",
|
||||
)
|
||||
detail_url = reverse(
|
||||
"api_v1:exchange:periodic-task-detail",
|
||||
kwargs={"task_id": task.id},
|
||||
)
|
||||
|
||||
self.client.force_authenticate(self.admin)
|
||||
response = self.client.get(detail_url)
|
||||
|
||||
self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)
|
||||
|
||||
Reference in New Issue
Block a user