|
11 | 11 | from ddt import data, ddt, unpack |
12 | 12 | from django.contrib.auth import get_user_model |
13 | 13 | from django.urls import reverse |
| 14 | +from organizations.models import Organization |
14 | 15 | from rest_framework import status |
15 | 16 | from rest_framework.test import APIClient |
16 | 17 |
|
@@ -853,6 +854,117 @@ def test_put_accepts_valid_full_course_key_scope(self, _mock_exists, _mock_assig |
853 | 854 | self.assertEqual(len(response.data["completed"]), 1) |
854 | 855 |
|
855 | 856 |
|
| 857 | +@ddt |
| 858 | +class TestOrgsAPIView(ViewTestMixin): |
| 859 | + """Test suite for OrgsAPIView.""" |
| 860 | + |
| 861 | + @classmethod |
| 862 | + def setUpTestData(cls): |
| 863 | + """Create Organization fixtures.""" |
| 864 | + super().setUpTestData() |
| 865 | + |
| 866 | + Organization.objects.bulk_create( |
| 867 | + [ |
| 868 | + Organization(name="Alpha University", short_name="AlphaU"), |
| 869 | + Organization(name="Beta Institute", short_name="BetaI"), |
| 870 | + Organization(name="Gamma College", short_name="GammaC"), |
| 871 | + ] |
| 872 | + ) |
| 873 | + |
| 874 | + def setUp(self): |
| 875 | + """Set up test fixtures.""" |
| 876 | + super().setUp() |
| 877 | + self.url = reverse("openedx_authz:orgs-view") |
| 878 | + |
| 879 | + def test_get_orgs_returns_all(self): |
| 880 | + """Test that all orgs are returned when no search param is provided. |
| 881 | +
|
| 882 | + Expected result: |
| 883 | + - Returns 200 OK status |
| 884 | + - Returns all 3 orgs |
| 885 | + """ |
| 886 | + response = self.client.get(self.url) |
| 887 | + |
| 888 | + self.assertEqual(response.status_code, status.HTTP_200_OK) |
| 889 | + self.assertEqual(response.data["count"], 3) |
| 890 | + self.assertEqual(len(response.data["results"]), 3) |
| 891 | + |
| 892 | + @data( |
| 893 | + # Match by name |
| 894 | + ("Alpha", 1), |
| 895 | + ("university", 1), |
| 896 | + # Match by short_name |
| 897 | + ("BetaI", 1), |
| 898 | + ("gamma", 1), |
| 899 | + # Partial match across multiple orgs |
| 900 | + ("a", 3), |
| 901 | + # No match |
| 902 | + ("nonexistent", 0), |
| 903 | + ) |
| 904 | + @unpack |
| 905 | + def test_get_orgs_search(self, search_term: str, expected_count: int): |
| 906 | + """Test filtering orgs by name or short_name via the search param. |
| 907 | +
|
| 908 | + Expected result: |
| 909 | + - Returns 200 OK status |
| 910 | + - Returns only orgs matching the search term |
| 911 | + """ |
| 912 | + response = self.client.get(self.url, {"search": search_term}) |
| 913 | + |
| 914 | + self.assertEqual(response.status_code, status.HTTP_200_OK) |
| 915 | + self.assertEqual(response.data["count"], expected_count) |
| 916 | + self.assertEqual(len(response.data["results"]), expected_count) |
| 917 | + |
| 918 | + @data( |
| 919 | + ({}, 3, False), |
| 920 | + ({"page": 1, "page_size": 2}, 2, True), |
| 921 | + ({"page": 2, "page_size": 2}, 1, False), |
| 922 | + ({"page": 1, "page_size": 3}, 3, False), |
| 923 | + ) |
| 924 | + @unpack |
| 925 | + def test_get_orgs_pagination(self, query_params: dict, expected_count: int, has_next: bool): |
| 926 | + """Test pagination of org results. |
| 927 | +
|
| 928 | + Expected result: |
| 929 | + - Returns 200 OK status |
| 930 | + - Returns correct page size and next link |
| 931 | + """ |
| 932 | + response = self.client.get(self.url, query_params) |
| 933 | + |
| 934 | + self.assertEqual(response.status_code, status.HTTP_200_OK) |
| 935 | + self.assertEqual(len(response.data["results"]), expected_count) |
| 936 | + if has_next: |
| 937 | + self.assertIsNotNone(response.data["next"]) |
| 938 | + else: |
| 939 | + self.assertIsNone(response.data["next"]) |
| 940 | + |
| 941 | + def test_get_orgs_response_shape(self): |
| 942 | + """Test that each org result contains the expected fields. |
| 943 | +
|
| 944 | + Expected result: |
| 945 | + - Each result has id, name, and short_name fields |
| 946 | + """ |
| 947 | + response = self.client.get(self.url) |
| 948 | + |
| 949 | + self.assertEqual(response.status_code, status.HTTP_200_OK) |
| 950 | + result = response.data["results"][0] |
| 951 | + self.assertIn("id", result) |
| 952 | + self.assertIn("name", result) |
| 953 | + self.assertIn("short_name", result) |
| 954 | + |
| 955 | + def test_get_orgs_unauthenticated(self): |
| 956 | + """Test that unauthenticated requests are rejected. |
| 957 | +
|
| 958 | + Expected result: |
| 959 | + - Returns 401 UNAUTHORIZED status |
| 960 | + """ |
| 961 | + self.client.force_authenticate(user=None) |
| 962 | + |
| 963 | + response = self.client.get(self.url) |
| 964 | + |
| 965 | + self.assertEqual(response.status_code, status.HTTP_401_UNAUTHORIZED) |
| 966 | + |
| 967 | + |
856 | 968 | @ddt |
857 | 969 | class TestRoleListView(ViewTestMixin): |
858 | 970 | """Test suite for RoleListView.""" |
|
0 commit comments