Repository: netbox-community/netbox-acls (language: python)

Issue:
[Bug]: Graphql tests fails
### NetBox access-list plugin version

v1.2.2

### NetBox version

v3.4.4

### Steps to Reproduce

Run test cases for graphql

### Expected Behavior

Tests should pass

### Observed Behavior

```
ERROR: test_graphql_get_object (netbox_acls.tests.test_api.ACLTestCase)
───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
╭─────────────────────────────── Traceback (most recent call last) ────────────────────────────────╮
│ /opt/netbox/netbox/utilities/api.py:41 in get_graphql_type_for_model                             │
│                                                                                                  │
│   38 │   │   app_name = 'users'                                                                  │
│   39 │   class_name = f'{app_name}.graphql.types.{model_name}Type'                               │
│   40 │   try:                                                                                    │
│ ❱ 41 │   │   return dynamic_import(class_name)                                                   │
│   42 │   except AttributeError:                                                                  │
│   43 │   │   raise GraphQLTypeNotFound(f"Could not find GraphQL type for {app_name}.{model_na    │
│   44                                                                                             │
│                                                                                                  │
│ ╭───────────────────────────── locals ──────────────────────────────╮                            │
│ │   app_name = 'netbox_acls'                                        │                            │
│ │ class_name = 'netbox_acls.graphql.types.AccessListType'           │                            │
│ │      model = <class 'netbox_acls.models.access_lists.AccessList'> │                            │
│ │ model_name = 'AccessList'                                         │                            │
│ ╰───────────────────────────────────────────────────────────────────╯                            │
│                                                                                                  │
│ /opt/netbox/netbox/utilities/utils.py:121 in dynamic_import                                      │
│                                                                                                  │
│   118 │   components = name.split('.')                                                           │
│   119 │   mod = __import__(components[0])                                                        │
│   120 │   for comp in components[1:]:                                                            │
│ ❱ 121 │   │   mod = getattr(mod, comp)                                                           │
│   122 │   return mod                                                                             │
│   123                                                                                            │
│   124                                                                                            │
│                                                                                                  │
│ ╭─────────────────────────────────────────── locals ───────────────────────────────────────────╮ │
│ │       comp = 'types'                                                                         │ │
│ │ components = ['netbox_acls', 'graphql', 'types', 'AccessListType']                           │ │
│ │        mod = <module 'netbox_acls.graphql' from                                              │ │
│ │              '/opt/netbox/venv/lib/python3.10/site-packages/netbox_acls/graphql.py'>         │ │
│ │       name = 'netbox_acls.graphql.types.AccessListType'                                      │ │
│ ╰──────────────────────────────────────────────────────────────────────────────────────────────╯ │
╰──────────────────────────────────────────────────────────────────────────────────────────────────╯
AttributeError: module 'netbox_acls.graphql' has no attribute 'types'

During handling of the above exception, another exception occurred:

╭─────────────────────────────── Traceback (most recent call last) ────────────────────────────────╮
│ /opt/netbox/venv/lib/python3.10/site-packages/django/test/utils.py:460 in inner                  │
│                                                                                                  │
│ /opt/netbox/venv/lib/python3.10/site-packages/django/test/utils.py:460 in inner                  │
│                                                                                                  │
│ /opt/netbox/netbox/utilities/testing/api.py:482 in test_graphql_get_object                       │
│                                                                                                  │
│   479 │   │   │   url = reverse('graphql')                                                       │
│   480 │   │   │   field_name = self._get_graphql_base_name()                                     │
│   481 │   │   │   object_id = self._get_queryset().first().pk                                    │
│ ❱ 482 │   │   │   query = self._build_query(field_name, id=object_id)                            │
│   483 │   │   │                                                                                  │
│   484 │   │   │   # Non-authenticated requests should fail                                       │
│   485 │   │   │   with disable_warnings('django.request'):                                       │
│                                                                                                  │
│ ╭───────────────────────────────────────── locals ─────────────────────────────────────────╮     │
│ │ field_name = 'access_list'                                                               │     │
│ │  object_id = 1                                                                           │     │
│ │       self = <netbox_acls.tests.test_api.ACLTestCase testMethod=test_graphql_get_object> │     │
│ │        url = '/graphql/'                                                                 │     │
│ ╰──────────────────────────────────────────────────────────────────────────────────────────╯     │
│                                                                                                  │
│ /opt/netbox/netbox/utilities/testing/api.py:440 in _build_query                                  │
│                                                                                                  │
│   437 │   │   │   return getattr(self, 'graphql_base_name', base_name)                           │
│   438 │   │                                                                                      │
│   439 │   │   def _build_query(self, name, **filters):                                           │
│ ❱ 440 │   │   │   type_class = get_graphql_type_for_model(self.model)                            │
│   441 │   │   │   if filters:                                                                    │
│   442 │   │   │   │   filter_string = ', '.join(f'{k}:{v}' for k, v in filters.items())          │
│   443 │   │   │   │   filter_string = f'({filter_string})'                                       │
│                                                                                                  │
│ ╭─────────────────────────────────────── locals ────────────────────────────────────────╮        │
│ │ filters = {'id': 1}                                                                   │        │
│ │    name = 'access_list'                                                               │        │
│ │    self = <netbox_acls.tests.test_api.ACLTestCase testMethod=test_graphql_get_object> │        │
│ ╰───────────────────────────────────────────────────────────────────────────────────────╯        │
│                                                                                                  │
│ /opt/netbox/netbox/utilities/api.py:43 in get_graphql_type_for_model                             │
│                                                                                                  │
│   40 │   try:                                                                                    │
│   41 │   │   return dynamic_import(class_name)                                                   │
│   42 │   except AttributeError:                                                                  │
│ ❱ 43 │   │   raise GraphQLTypeNotFound(f"Could not find GraphQL type for {app_name}.{model_na    │
│   44                                                                                             │
│   45                                                                                             │
│   46 def is_api_request(request):                                                                │
│                                                                                                  │
│ ╭───────────────────────────── locals ──────────────────────────────╮                            │
│ │   app_name = 'netbox_acls'                                        │                            │
│ │ class_name = 'netbox_acls.graphql.types.AccessListType'           │                            │
│ │      model = <class 'netbox_acls.models.access_lists.AccessList'> │                            │
│ │ model_name = 'AccessList'                                         │                            │
│ ╰───────────────────────────────────────────────────────────────────╯                            │
╰──────────────────────────────────────────────────────────────────────────────────────────────────╯
GraphQLTypeNotFound: Could not find GraphQL type for netbox_acls.AccessList

───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
ERROR: test_graphql_list_objects (netbox_acls.tests.test_api.ACLTestCase)
───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
╭─────────────────────────────── Traceback (most recent call last) ────────────────────────────────╮
│ /opt/netbox/netbox/utilities/api.py:41 in get_graphql_type_for_model                             │
│                                                                                                  │
│   38 │   │   app_name = 'users'                                                                  │
│   39 │   class_name = f'{app_name}.graphql.types.{model_name}Type'                               │
│   40 │   try:                                                                                    │
│ ❱ 41 │   │   return dynamic_import(class_name)                                                   │
│   42 │   except AttributeError:                                                                  │
│   43 │   │   raise GraphQLTypeNotFound(f"Could not find GraphQL type for {app_name}.{model_na    │
│   44                                                                                             │
│                                                                                                  │
│ ╭───────────────────────────── locals ──────────────────────────────╮                            │
│ │   app_name = 'netbox_acls'                                        │                            │
│ │ class_name = 'netbox_acls.graphql.types.AccessListType'           │                            │
│ │      model = <class 'netbox_acls.models.access_lists.AccessList'> │                            │
│ │ model_name = 'AccessList'                                         │                            │
│ ╰───────────────────────────────────────────────────────────────────╯                            │
│                                                                                                  │
│ /opt/netbox/netbox/utilities/utils.py:121 in dynamic_import                                      │
│                                                                                                  │
│   118 │   components = name.split('.')                                                           │
│   119 │   mod = __import__(components[0])                                                        │
│   120 │   for comp in components[1:]:                                                            │
│ ❱ 121 │   │   mod = getattr(mod, comp)                                                           │
│   122 │   return mod                                                                             │
│   123                                                                                            │
│   124                                                                                            │
│                                                                                                  │
│ ╭─────────────────────────────────────────── locals ───────────────────────────────────────────╮ │
│ │       comp = 'types'                                                                         │ │
│ │ components = ['netbox_acls', 'graphql', 'types', 'AccessListType']                           │ │
│ │        mod = <module 'netbox_acls.graphql' from                                              │ │
│ │              '/opt/netbox/venv/lib/python3.10/site-packages/netbox_acls/graphql.py'>         │ │
│ │       name = 'netbox_acls.graphql.types.AccessListType'                                      │ │
│ ╰──────────────────────────────────────────────────────────────────────────────────────────────╯ │
╰──────────────────────────────────────────────────────────────────────────────────────────────────╯
AttributeError: module 'netbox_acls.graphql' has no attribute 'types'

During handling of the above exception, another exception occurred:

╭─────────────────────────────── Traceback (most recent call last) ────────────────────────────────╮
│ /opt/netbox/venv/lib/python3.10/site-packages/django/test/utils.py:460 in inner                  │
│                                                                                                  │
│ /opt/netbox/venv/lib/python3.10/site-packages/django/test/utils.py:460 in inner                  │
│                                                                                                  │
│ /opt/netbox/netbox/utilities/testing/api.py:507 in test_graphql_list_objects                     │
│                                                                                                  │
│   504 │   │   def test_graphql_list_objects(self):                                               │
│   505 │   │   │   url = reverse('graphql')                                                       │
│   506 │   │   │   field_name = f'{self._get_graphql_base_name()}_list'                           │
│ ❱ 507 │   │   │   query = self._build_query(field_name)                                          │
│   508 │   │   │                                                                                  │
│   509 │   │   │   # Non-authenticated requests should fail                                       │
│   510 │   │   │   with disable_warnings('django.request'):                                       │
│                                                                                                  │
│ ╭────────────────────────────────────────── locals ──────────────────────────────────────────╮   │
│ │ field_name = 'access_list_list'                                                            │   │
│ │       self = <netbox_acls.tests.test_api.ACLTestCase testMethod=test_graphql_list_objects> │   │
│ │        url = '/graphql/'                                                                   │   │
│ ╰────────────────────────────────────────────────────────────────────────────────────────────╯   │
│                                                                                                  │
│ /opt/netbox/netbox/utilities/testing/api.py:440 in _build_query                                  │
│                                                                                                  │
│   437 │   │   │   return getattr(self, 'graphql_base_name', base_name)                           │
│   438 │   │                                                                                      │
│   439 │   │   def _build_query(self, name, **filters):                                           │
│ ❱ 440 │   │   │   type_class = get_graphql_type_for_model(self.model)                            │
│   441 │   │   │   if filters:                                                                    │
│   442 │   │   │   │   filter_string = ', '.join(f'{k}:{v}' for k, v in filters.items())          │
│   443 │   │   │   │   filter_string = f'({filter_string})'                                       │
│                                                                                                  │
│ ╭──────────────────────────────────────── locals ─────────────────────────────────────────╮      │
│ │ filters = {}                                                                            │      │
│ │    name = 'access_list_list'                                                            │      │
│ │    self = <netbox_acls.tests.test_api.ACLTestCase testMethod=test_graphql_list_objects> │      │
│ ╰─────────────────────────────────────────────────────────────────────────────────────────╯      │
│                                                                                                  │
│ /opt/netbox/netbox/utilities/api.py:43 in get_graphql_type_for_model                             │
│                                                                                                  │
│   40 │   try:                                                                                    │
│   41 │   │   return dynamic_import(class_name)                                                   │
│   42 │   except AttributeError:                                                                  │
│ ❱ 43 │   │   raise GraphQLTypeNotFound(f"Could not find GraphQL type for {app_name}.{model_na    │
│   44                                                                                             │
│   45                                                                                             │
│   46 def is_api_request(request):                                                                │
│                                                                                                  │
│ ╭───────────────────────────── locals ──────────────────────────────╮                            │
│ │   app_name = 'netbox_acls'                                        │                            │
│ │ class_name = 'netbox_acls.graphql.types.AccessListType'           │                            │
│ │      model = <class 'netbox_acls.models.access_lists.AccessList'> │                            │
│ │ model_name = 'AccessList'                                         │                            │
│ ╰───────────────────────────────────────────────────────────────────╯                            │
╰──────────────────────────────────────────────────────────────────────────────────────────────────╯
GraphQLTypeNotFound: Could not find GraphQL type for netbox_acls.AccessList
```


Discussion / hints:

Fix patch:
diff --git a/netbox_acls/graphql/__init__.py b/netbox_acls/graphql/__init__.py
new file mode 100644
index 0000000..dd2a695
--- /dev/null
+++ b/netbox_acls/graphql/__init__.py
@@ -0,0 +1,2 @@
+from .schema import *
+from .types import *
diff --git a/netbox_acls/graphql/schema.py b/netbox_acls/graphql/schema.py
new file mode 100644
index 0000000..cdaa8a2
--- /dev/null
+++ b/netbox_acls/graphql/schema.py
@@ -0,0 +1,21 @@
+from graphene import ObjectType
+from netbox.graphql.fields import ObjectField, ObjectListField
+
+from .types import *
+
+class Query(ObjectType):
+    """
+    Defines the queries available to this plugin via the graphql api.
+    """
+
+    access_list = ObjectField(AccessListType)
+    access_list_list = ObjectListField(AccessListType)
+
+    acl_extended_rule = ObjectField(ACLExtendedRuleType)
+    acl_extended_rule_list = ObjectListField(ACLExtendedRuleType)
+
+    acl_standard_rule = ObjectField(ACLStandardRuleType)
+    acl_standard_rule_list = ObjectListField(ACLStandardRuleType)
+
+
+schema = Query
diff --git a/netbox_acls/graphql.py b/netbox_acls/graphql/types.py
similarity index 73%
rename from netbox_acls/graphql.py
rename to netbox_acls/graphql/types.py
index 8de0dd2..9e05942 100644
--- a/netbox_acls/graphql.py
+++ b/netbox_acls/graphql/types.py
@@ -2,11 +2,9 @@
 Define the object types and queries availble via the graphql api.
 """
 
-from graphene import ObjectType
-from netbox.graphql.fields import ObjectField, ObjectListField
 from netbox.graphql.types import NetBoxObjectType
 
-from . import filtersets, models
+from .. import filtersets, models
 
 __all__ = (
     "AccessListType",
@@ -15,10 +13,6 @@
     "ACLStandardRuleType",
 )
 
-#
-# Object types
-#
-
 
 class AccessListType(NetBoxObjectType):
     """
@@ -79,25 +73,3 @@ class Meta:
         fields = "__all__"
         filterset_class = filtersets.ACLStandardRuleFilterSet
 
-
-#
-# Queries
-#
-
-
-class Query(ObjectType):
-    """
-    Defines the queries availible to this plugin via the graphql api.
-    """
-
-    access_list = ObjectField(AccessListType)
-    access_list_list = ObjectListField(AccessListType)
-
-    acl_extended_rule = ObjectField(ACLExtendedRuleType)
-    acl_extended_rule_list = ObjectListField(ACLExtendedRuleType)
-
-    acl_standard_rule = ObjectField(ACLStandardRuleType)
-    acl_standard_rule_list = ObjectListField(ACLStandardRuleType)
-
-
-schema = Query


Test patch:
diff --git a/netbox_acls/tests/test_api.py b/netbox_acls/tests/test_api.py
index afbd4fa..77559e6 100644
--- a/netbox_acls/tests/test_api.py
+++ b/netbox_acls/tests/test_api.py
@@ -17,11 +17,7 @@ def test_root(self):
 
 
 class ACLTestCase(
-    APIViewTestCases.GetObjectViewTestCase,
-    APIViewTestCases.ListObjectsViewTestCase,
-    APIViewTestCases.CreateObjectViewTestCase,
-    APIViewTestCases.UpdateObjectViewTestCase,
-    APIViewTestCases.DeleteObjectViewTestCase,
+    APIViewTestCases.APIViewTestCase,
 ):
     """Test the AccessList Test"""