|
9 | 9 |
|
10 | 10 | from .. import settings as app_settings |
11 | 11 | from ..signals import group_templates_changed |
12 | | -from .utils import CreateDeviceGroupMixin, CreateTemplateMixin |
| 12 | +from .utils import CreateDeviceGroupMixin, CreateDeviceMixin, CreateTemplateMixin |
13 | 13 |
|
| 14 | +Device = load_model("config", "Device") |
14 | 15 | DeviceGroup = load_model("config", "DeviceGroup") |
| 16 | +Template = load_model("config", "Template") |
15 | 17 |
|
16 | 18 |
|
17 | | -class TestDeviceGroup(CreateDeviceGroupMixin, CreateTemplateMixin, TestCase): |
| 19 | +class TestDeviceGroup( |
| 20 | + CreateDeviceMixin, CreateDeviceGroupMixin, CreateTemplateMixin, TestCase |
| 21 | +): |
18 | 22 | def test_device_group(self): |
19 | 23 | self._create_device_group( |
20 | 24 | meta_data={"captive_portal_url": "https//example.com"} |
@@ -61,3 +65,53 @@ def test_device_group_signals(self): |
61 | 65 | raw=False, |
62 | 66 | using="default", |
63 | 67 | ) |
| 68 | + |
| 69 | + def test_manage_devices_group_templates_no_early_termination(self): |
| 70 | + """ |
| 71 | + Regression test: when the first device in the batch has no config |
| 72 | + (because its group has no templates), the loop must continue and |
| 73 | + still apply group templates to the second device. |
| 74 | + """ |
| 75 | + org = self._get_org() |
| 76 | + t1 = self._create_template(name="t1") |
| 77 | + # group_with_templates has a template; group_without does not |
| 78 | + group_with_templates = self._create_device_group( |
| 79 | + name="group-with-tpl", organization=org |
| 80 | + ) |
| 81 | + group_with_templates.templates.add(t1) |
| 82 | + group_without_templates = self._create_device_group( |
| 83 | + name="group-without-tpl", organization=org |
| 84 | + ) |
| 85 | + # device1: belongs to a group without templates → no config created |
| 86 | + device1 = self._create_device( |
| 87 | + name="device-no-config", |
| 88 | + organization=org, |
| 89 | + group=group_without_templates, |
| 90 | + mac_address="00:00:00:00:00:01", |
| 91 | + ) |
| 92 | + self.assertFalse(hasattr(device1, "config")) |
| 93 | + # device2: has a config object |
| 94 | + device2 = self._create_device( |
| 95 | + name="device-with-config", |
| 96 | + organization=org, |
| 97 | + mac_address="00:00:00:00:00:02", |
| 98 | + ) |
| 99 | + from openwisp_controller.config.tests.utils import Config |
| 100 | + |
| 101 | + Config.objects.create( |
| 102 | + device=device2, |
| 103 | + backend="netjsonconfig.OpenWrt", |
| 104 | + ) |
| 105 | + device2.refresh_from_db() |
| 106 | + self.assertTrue(hasattr(device2, "config")) |
| 107 | + self.assertEqual(device2.config.templates.count(), 0) |
| 108 | + # Call manage_devices_group_templates with device1 (no config) first, |
| 109 | + # then device2 (has config). device1 should be skipped, device2 must |
| 110 | + # still get group_with_templates's template applied. |
| 111 | + Device.manage_devices_group_templates( |
| 112 | + device_ids=[device1.pk, device2.pk], |
| 113 | + old_group_ids=[None, None], |
| 114 | + group_id=group_with_templates.pk, |
| 115 | + ) |
| 116 | + device2.refresh_from_db() |
| 117 | + self.assertIn(t1, device2.config.templates.all()) |
0 commit comments