Commit 472cb08c0072c33f3313613e9203de824a2ed26c
1 parent
fce7ff0f
Exists in
dev
Add new tests of F14 and fixing the 'level_required' decorator to check if an us…
…er can access to a view depending his role
Showing
10 changed files
with
480 additions
and
22 deletions
Show diff stats
src/core/pyros_django/dashboard/decorator.py
... | ... | @@ -10,13 +10,13 @@ def level_required(*list_of_roles): |
10 | 10 | """ |
11 | 11 | def wrapper(view_func): |
12 | 12 | def _decorator(request, *args, **kwargs): |
13 | - if len(args) > 0 : | |
13 | + if len(list_of_roles) > 0 : | |
14 | 14 | if request.session.get("role"): |
15 | 15 | if request.session.get("role") not in list_of_roles: |
16 | - | |
16 | + | |
17 | 17 | return HttpResponseForbidden() |
18 | 18 | else: |
19 | - role = UserLevel.objects.get(name=request.user.get_priority()) | |
19 | + role = UserLevel.objects.get(priority=request.user.get_priority()).name | |
20 | 20 | if role not in list_of_roles: |
21 | 21 | return HttpResponseForbidden() |
22 | 22 | response = view_func(request, *args, **kwargs) | ... | ... |
src/core/pyros_django/obsconfig/configpyros.py
... | ... | @@ -7,8 +7,8 @@ class ConfigPyros: |
7 | 7 | # (AKo) : Config file path is checked on the settings file, if the file isn't valid (i.e not found) the error will be launched by the settings file when starting the application |
8 | 8 | devices_links = {} |
9 | 9 | current_file = None |
10 | - COMPONENT_PATH = os.path.join(os.environ["DJANGO_PATH"],"../../../../config/components/") | |
11 | - GENERIC_DEVICES_PATH = os.path.join(os.environ["DJANGO_PATH"],"../../../../config/devices/") | |
10 | + COMPONENT_PATH = os.path.join(os.environ["DJANGO_PATH"],"../../../config/components/") | |
11 | + GENERIC_DEVICES_PATH = os.path.join(os.environ["DJANGO_PATH"],"../../../config/devices/") | |
12 | 12 | pickle_file = "obsconfig.p" |
13 | 13 | obs_config = None |
14 | 14 | devices = None |
... | ... | @@ -253,9 +253,9 @@ class ConfigPyros: |
253 | 253 | config_file = yaml.safe_load(stream) |
254 | 254 | # if we're reading a generic device configuration, the path to get the schema is different than usual |
255 | 255 | if is_generic: |
256 | - self.SCHEMA_PATH = os.path.join(os.path.abspath(os.path.dirname(config_file_name)),"../schemas/") | |
256 | + self.SCHEMA_PATH =os.path.join(os.environ["DJANGO_PATH"],"../../../config/schemas/") | |
257 | 257 | else: |
258 | - self.SCHEMA_PATH = os.path.join(os.path.abspath(os.path.dirname(config_file_name)),"../../../config/schemas/") | |
258 | + self.SCHEMA_PATH = os.path.join(os.environ["DJANGO_PATH"],"../../../config/schemas/") | |
259 | 259 | |
260 | 260 | # read and verify that the device configuration match the schema |
261 | 261 | result = self.check_and_return_config(config_file_name,self.SCHEMA_PATH+config_file["schema"]) | ... | ... |
src/core/pyros_django/obsconfig/fixtures/computer_test.yml
... | ... | @@ -4,21 +4,21 @@ schema: schema_computer-2.0.yml |
4 | 4 | # Here is the description of the configuration of an isolated computer |
5 | 5 | COMPUTER: |
6 | 6 | |
7 | - _inventory_label: CPT-XCY-001 | |
8 | - _manufacturer: XCY | |
9 | - _model: X26A | |
10 | - _description: "Intel(R) Core(TM) i5-4250U CPU @ 1.30GHz 1.90 GHz RAM = 4 GB" | |
11 | - _sn: 00331-10000-00001-AA478 | |
12 | - _power: | |
13 | - _voltage: 12 | |
14 | - _intensity: 5 | |
15 | - _socket: "IEC 60130-10 Type A: 5.5 mm OD, 2.5 mm ID" | |
7 | + inventory_label: CPT-XCY-001 | |
8 | + manufacturer: XCY | |
9 | + model: X26A | |
10 | + description: "Intel(R) Core(TM) i5-4250U CPU @ 1.30GHz 1.90 GHz RAM = 4 GB" | |
11 | + sn: 00331-10000-00001-AA478 | |
12 | + power: | |
13 | + voltage: 12 | |
14 | + intensity: 5 | |
15 | + socket: "IEC 60130-10 Type A: 5.5 mm OD, 2.5 mm ID" | |
16 | 16 | |
17 | - _hostname: XCY1 | |
18 | - _virtual_machine: False | |
19 | - _os: Windows | |
20 | - _os_version: "10" | |
21 | - _network_interfaces: | |
17 | + hostname: XCY1 | |
18 | + virtual_machine: False | |
19 | + os: Windows | |
20 | + os_version: "10" | |
21 | + network_interfaces: | |
22 | 22 | - 00-A8-3D-68-22-87 # Gigabit 2 |
23 | 23 | - 00-A8-3D-68-22-86 # Gigabit 3 |
24 | 24 | - 16-82-FE-44-64-E8 # Wifi | ... | ... |
src/core/pyros_django/obsconfig/fixtures/device_FLI_KITS_sn0x1.yml
0 → 100644
... | ... | @@ -0,0 +1,9 @@ |
1 | +# Schema file to check the syntax of this config file | |
2 | +schema: schema_device-2.0.yml | |
3 | + | |
4 | +# Here is the description of the configuration of an isolated device | |
5 | +DEVICE: | |
6 | + | |
7 | + generic: device_FLI_KITS_generic.yml | |
8 | + inventory_label: GPS-FLI-0x1 | |
9 | + sn: SN0x1 | ... | ... |
src/core/pyros_django/obsconfig/fixtures/device_ZWO_ASI1600MMPro_test_complex.yml
0 → 100644
... | ... | @@ -0,0 +1,12 @@ |
1 | +# Schema file to check the syntax of this config file | |
2 | +schema: schema_device-2.0.yml | |
3 | + | |
4 | +# Here is the description of the configuration of an isolated device | |
5 | +DEVICE: | |
6 | + | |
7 | + inventory_label: Undefined | |
8 | + manufacturer: ZWO | |
9 | + generic: device_ZWO_ASI1600MMPro_generic.yml | |
10 | + | |
11 | + ATTACHED_DEVICES: | |
12 | + - file: device_FLI_KITS_sn0x1.yml | |
0 | 13 | \ No newline at end of file | ... | ... |
No preview for this file type
src/core/pyros_django/obsconfig/fixtures/observatory_config_ok_complex.yml
0 → 100644
... | ... | @@ -0,0 +1,131 @@ |
1 | +# Schema file to check the syntax of this config file | |
2 | +schema: schema_observatory-2.0.yml | |
3 | + | |
4 | +# Here is the description of the configuration of an observatory | |
5 | +OBSERVATORY: | |
6 | + | |
7 | + name: observatory_test | |
8 | + | |
9 | + # === Inventory of available devices | |
10 | + # A device is a hardware with a maximum of one connection to drive it with a computer. | |
11 | + # As a device can be shared with various units, it is defined at the observatory level. | |
12 | + DEVICES: | |
13 | + | |
14 | + # Each device is defined by a specific configuration file that enumarate the components. | |
15 | + | |
16 | + - DEVICE: | |
17 | + name: AstroMecCA | |
18 | + file: device_Astromecca_TM350_test.yml | |
19 | + | |
20 | + - DEVICE: | |
21 | + name: PLC-meteo | |
22 | + file: device_Raspberry_MiFe_test.yml | |
23 | + # Describe here the configuration of the device in operation | |
24 | + network_interface_index: 0 | |
25 | + network_ip: 192.168.0.2 | |
26 | + | |
27 | + - DEVICE: | |
28 | + name: SkyWatcher | |
29 | + file: device_SkyWatcher_ED80_test.yml | |
30 | + | |
31 | + | |
32 | + - DEVICE: | |
33 | + name: ZWO | |
34 | + file: device_ZWO_ASI1600MMPro_test_complex.yml | |
35 | + | |
36 | + | |
37 | + # === Inventory of available computers | |
38 | + # A computer is a hardware of a virtual machine. | |
39 | + # As a computer can be shared with various units, it is defined at the observatory level. | |
40 | + COMPUTERS: | |
41 | + | |
42 | + - COMPUTER: | |
43 | + | |
44 | + name: MainComputer | |
45 | + file: computer_test.yml | |
46 | + # Describe here the configuration of the computer in operation | |
47 | + role: Main | |
48 | + # Choice of the interface to connect the computer to the network (cf.network_interfaces infile) | |
49 | + network_interface_index: 0 | |
50 | + # IP attributed by the Router | |
51 | + network_ip: 192.168.0.11 | |
52 | + | |
53 | + # === Assembly of devices into units | |
54 | + # A unit is a robotic telescope | |
55 | + UNITS: | |
56 | + | |
57 | + - UNIT: | |
58 | + name: test-unit | |
59 | + home: "GPS 2.0375 E 43.6443484725 136.9" | |
60 | + horizon: | |
61 | + type: ALTAZ | |
62 | + line: [ [0,0], [360,0] ] | |
63 | + | |
64 | + DATABASE: | |
65 | + computer: MainComputer | |
66 | + file: pyros/docker/variables.env | |
67 | + | |
68 | + AGENTS: | |
69 | + | |
70 | + - AGENT_DEVICE: | |
71 | + computer: MainComputer | |
72 | + name: plc | |
73 | + device: PLC-meteo | |
74 | + is_real: False | |
75 | + | |
76 | + - AGENT_DEVICE: | |
77 | + computer: MainComputer | |
78 | + name: mount | |
79 | + # device name should be AstroMecCA | |
80 | + device: AstroMecCA | |
81 | + is_real: False | |
82 | + | |
83 | + - AGENT_DEVICE: | |
84 | + computer: None | |
85 | + name: optic | |
86 | + device: SkyWatcher | |
87 | + is_real: False | |
88 | + | |
89 | + - AGENT_DEVICE: | |
90 | + computer: MainComputer | |
91 | + name: camera | |
92 | + path: private/plugin/agent_devices | |
93 | + device: ZWO | |
94 | + protocol: private/plugin/agent_devices/camera_protocol.py | |
95 | + is_real: False | |
96 | + | |
97 | + - AGENT: | |
98 | + computer: MainComputer | |
99 | + name: majordome | |
100 | + path: ~ | |
101 | + | |
102 | + TOPOLOGY: | |
103 | + | |
104 | + SECURITY: | |
105 | + name: PLC | |
106 | + COMPONENT_AGENTS: | |
107 | + - WeatherStation: plc | |
108 | + - BuildingCover: plc | |
109 | + | |
110 | + MOUNT: | |
111 | + name: TM350-prototype | |
112 | + COMPONENT_AGENTS: | |
113 | + - MountPointing: mount | |
114 | + | |
115 | + CHANNELS: | |
116 | + | |
117 | + - CHANNEL: | |
118 | + name: OpticalChannel | |
119 | + COMPONENT_AGENTS: | |
120 | + - OpticImager: optic | |
121 | + - DetectorSensor: camera | |
122 | + - DetectorShutter: camera | |
123 | + | |
124 | + CHANNEL_GROUPS: | |
125 | + | |
126 | + logic: 'or' # opt | |
127 | + GROUPS: | |
128 | + - GROUP: | |
129 | + logic: 'and' # opt | |
130 | + channels: | |
131 | + - OpticalChannel | ... | ... |
src/core/pyros_django/obsconfig/fixtures/observatory_configuration_ok_complex.yml
0 → 100644
... | ... | @@ -0,0 +1,131 @@ |
1 | +# Schema file to check the syntax of this config file | |
2 | +schema: schema_observatory-2.0.yml | |
3 | + | |
4 | +# Here is the description of the configuration of an observatory | |
5 | +OBSERVATORY: | |
6 | + | |
7 | + name: observatory_test | |
8 | + | |
9 | + # === Inventory of available devices | |
10 | + # A device is a hardware with a maximum of one connection to drive it with a computer. | |
11 | + # As a device can be shared with various units, it is defined at the observatory level. | |
12 | + DEVICES: | |
13 | + | |
14 | + # Each device is defined by a specific configuration file that enumarate the components. | |
15 | + | |
16 | + - DEVICE: | |
17 | + name: AstroMecCA | |
18 | + file: device_Astromecca_TM350_test.yml | |
19 | + | |
20 | + - DEVICE: | |
21 | + name: PLC-meteo | |
22 | + file: device_Raspberry_MiFe_test.yml | |
23 | + # Describe here the configuration of the device in operation | |
24 | + network_interface_index: 0 | |
25 | + network_ip: 192.168.0.2 | |
26 | + | |
27 | + - DEVICE: | |
28 | + name: SkyWatcher | |
29 | + file: device_SkyWatcher_ED80_test.yml | |
30 | + | |
31 | + | |
32 | + - DEVICE: | |
33 | + name: ZWO | |
34 | + file: device_ZWO_ASI1600MMPro_test.yml | |
35 | + | |
36 | + | |
37 | + # === Inventory of available computers | |
38 | + # A computer is a hardware of a virtual machine. | |
39 | + # As a computer can be shared with various units, it is defined at the observatory level. | |
40 | + COMPUTERS: | |
41 | + | |
42 | + - COMPUTER: | |
43 | + | |
44 | + name: MainComputer | |
45 | + file: computer_test.yml | |
46 | + # Describe here the configuration of the computer in operation | |
47 | + role: Main | |
48 | + # Choice of the interface to connect the computer to the network (cf.network_interfaces infile) | |
49 | + network_interface_index: 0 | |
50 | + # IP attributed by the Router | |
51 | + network_ip: 192.168.0.11 | |
52 | + | |
53 | + # === Assembly of devices into units | |
54 | + # A unit is a robotic telescope | |
55 | + UNITS: | |
56 | + | |
57 | + - UNIT: | |
58 | + name: test-unit | |
59 | + home: "GPS 2.0375 E 43.6443484725 136.9" | |
60 | + horizon: | |
61 | + type: ALTAZ | |
62 | + line: [ [0,0], [360,0] ] | |
63 | + | |
64 | + DATABASE: | |
65 | + computer: MainComputer | |
66 | + file: pyros/docker/variables.env | |
67 | + | |
68 | + AGENTS: | |
69 | + | |
70 | + - AGENT_DEVICE: | |
71 | + computer: MainComputer | |
72 | + name: plc | |
73 | + device: PLC-meteo | |
74 | + is_real: False | |
75 | + | |
76 | + - AGENT_DEVICE: | |
77 | + computer: MainComputer | |
78 | + name: mount | |
79 | + # device name should be AstroMecCA | |
80 | + device: AstroMecCA | |
81 | + is_real: False | |
82 | + | |
83 | + - AGENT_DEVICE: | |
84 | + computer: None | |
85 | + name: optic | |
86 | + device: SkyWatcher | |
87 | + is_real: False | |
88 | + | |
89 | + - AGENT_DEVICE: | |
90 | + computer: MainComputer | |
91 | + name: camera | |
92 | + path: private/plugin/agent_devices | |
93 | + device: ZWO | |
94 | + protocol: private/plugin/agent_devices/camera_protocol.py | |
95 | + is_real: False | |
96 | + | |
97 | + - AGENT: | |
98 | + computer: MainComputer | |
99 | + name: majordome | |
100 | + path: ~ | |
101 | + | |
102 | + TOPOLOGY: | |
103 | + | |
104 | + SECURITY: | |
105 | + name: PLC | |
106 | + COMPONENT_AGENTS: | |
107 | + - WeatherStation: plc | |
108 | + - BuildingCover: plc | |
109 | + | |
110 | + MOUNT: | |
111 | + name: TM350-prototype | |
112 | + COMPONENT_AGENTS: | |
113 | + - MountPointing: mount | |
114 | + | |
115 | + CHANNELS: | |
116 | + | |
117 | + - CHANNEL: | |
118 | + name: OpticalChannel | |
119 | + COMPONENT_AGENTS: | |
120 | + - OpticImager: optic | |
121 | + - DetectorSensor: camera | |
122 | + - DetectorShutter: camera | |
123 | + | |
124 | + CHANNEL_GROUPS: | |
125 | + | |
126 | + logic: 'or' # opt | |
127 | + GROUPS: | |
128 | + - GROUP: | |
129 | + logic: 'and' # opt | |
130 | + channels: | |
131 | + - OpticalChannel | ... | ... |
src/core/pyros_django/obsconfig/fixtures/observatory_configuration_ok_simple.yml
0 → 100644
... | ... | @@ -0,0 +1,131 @@ |
1 | +# Schema file to check the syntax of this config file | |
2 | +schema: schema_observatory-2.0.yml | |
3 | + | |
4 | +# Here is the description of the configuration of an observatory | |
5 | +OBSERVATORY: | |
6 | + | |
7 | + name: observatory_test | |
8 | + | |
9 | + # === Inventory of available devices | |
10 | + # A device is a hardware with a maximum of one connection to drive it with a computer. | |
11 | + # As a device can be shared with various units, it is defined at the observatory level. | |
12 | + DEVICES: | |
13 | + | |
14 | + # Each device is defined by a specific configuration file that enumarate the components. | |
15 | + | |
16 | + - DEVICE: | |
17 | + name: AstroMecCA | |
18 | + file: device_Astromecca_TM350_test.yml | |
19 | + | |
20 | + - DEVICE: | |
21 | + name: PLC-meteo | |
22 | + file: device_Raspberry_MiFe_test.yml | |
23 | + # Describe here the configuration of the device in operation | |
24 | + network_interface_index: 0 | |
25 | + network_ip: 192.168.0.2 | |
26 | + | |
27 | + - DEVICE: | |
28 | + name: SkyWatcher | |
29 | + file: device_SkyWatcher_ED80_test.yml | |
30 | + | |
31 | + | |
32 | + - DEVICE: | |
33 | + name: ZWO | |
34 | + file: device_ZWO_ASI1600MMPro_test.yml | |
35 | + | |
36 | + | |
37 | + # === Inventory of available computers | |
38 | + # A computer is a hardware of a virtual machine. | |
39 | + # As a computer can be shared with various units, it is defined at the observatory level. | |
40 | + COMPUTERS: | |
41 | + | |
42 | + - COMPUTER: | |
43 | + | |
44 | + name: MainComputer | |
45 | + file: computer_test.yml | |
46 | + # Describe here the configuration of the computer in operation | |
47 | + role: Main | |
48 | + # Choice of the interface to connect the computer to the network (cf.network_interfaces infile) | |
49 | + network_interface_index: 0 | |
50 | + # IP attributed by the Router | |
51 | + network_ip: 192.168.0.11 | |
52 | + | |
53 | + # === Assembly of devices into units | |
54 | + # A unit is a robotic telescope | |
55 | + UNITS: | |
56 | + | |
57 | + - UNIT: | |
58 | + name: test-unit | |
59 | + home: "GPS 2.0375 E 43.6443484725 136.9" | |
60 | + horizon: | |
61 | + type: ALTAZ | |
62 | + line: [ [0,0], [360,0] ] | |
63 | + | |
64 | + DATABASE: | |
65 | + computer: MainComputer | |
66 | + file: pyros/docker/variables.env | |
67 | + | |
68 | + AGENTS: | |
69 | + | |
70 | + - AGENT_DEVICE: | |
71 | + computer: MainComputer | |
72 | + name: plc | |
73 | + device: PLC-meteo | |
74 | + is_real: False | |
75 | + | |
76 | + - AGENT_DEVICE: | |
77 | + computer: MainComputer | |
78 | + name: mount | |
79 | + # device name should be AstroMecCA | |
80 | + device: AstroMecCA | |
81 | + is_real: False | |
82 | + | |
83 | + - AGENT_DEVICE: | |
84 | + computer: None | |
85 | + name: optic | |
86 | + device: SkyWatcher | |
87 | + is_real: False | |
88 | + | |
89 | + - AGENT_DEVICE: | |
90 | + computer: MainComputer | |
91 | + name: camera | |
92 | + path: private/plugin/agent_devices | |
93 | + device: ZWO | |
94 | + protocol: private/plugin/agent_devices/camera_protocol.py | |
95 | + is_real: False | |
96 | + | |
97 | + - AGENT: | |
98 | + computer: MainComputer | |
99 | + name: majordome | |
100 | + path: ~ | |
101 | + | |
102 | + TOPOLOGY: | |
103 | + | |
104 | + SECURITY: | |
105 | + name: PLC | |
106 | + COMPONENT_AGENTS: | |
107 | + - WeatherStation: plc | |
108 | + - BuildingCover: plc | |
109 | + | |
110 | + MOUNT: | |
111 | + name: TM350-prototype | |
112 | + COMPONENT_AGENTS: | |
113 | + - MountPointing: mount | |
114 | + | |
115 | + CHANNELS: | |
116 | + | |
117 | + - CHANNEL: | |
118 | + name: OpticalChannel | |
119 | + COMPONENT_AGENTS: | |
120 | + - OpticImager: optic | |
121 | + - DetectorSensor: camera | |
122 | + - DetectorShutter: camera | |
123 | + | |
124 | + CHANNEL_GROUPS: | |
125 | + | |
126 | + logic: 'or' # opt | |
127 | + GROUPS: | |
128 | + - GROUP: | |
129 | + logic: 'and' # opt | |
130 | + channels: | |
131 | + - OpticalChannel | ... | ... |
src/core/pyros_django/obsconfig/tests.py
1 | 1 | from django.test import TestCase |
2 | 2 | from common.models import PyrosUser |
3 | 3 | from .configpyros import ConfigPyros |
4 | +from django.urls import reverse | |
4 | 5 | import unittest |
5 | 6 | class ObservatoryConfigurationTests(TestCase): |
6 | 7 | fixtures = ['tests/common_test_TZ.json'] |
... | ... | @@ -8,4 +9,47 @@ class ObservatoryConfigurationTests(TestCase): |
8 | 9 | def test_OCF_view_config_ko(self): |
9 | 10 | u1 = PyrosUser.objects.get(username="haribo") |
10 | 11 | config_ko = ConfigPyros("obsconfig/fixtures/observatory_configuration_ko.yml") |
11 | - | |
12 | 12 | \ No newline at end of file |
13 | + | |
14 | + def test_OCF_read_config_get_content(self): | |
15 | + config = ConfigPyros("obsconfig/fixtures/observatory_configuration_ok_simple.yml") | |
16 | + # get_devices, and get_computers are already tested in load | |
17 | + self.assertEqual(config.get_obs_name(),"observatory_test") | |
18 | + self.assertEqual(len(config.get_units()),1) | |
19 | + first_unit = config.get_units()["test-unit"] | |
20 | + self.assertEqual(first_unit["name"],"test-unit") | |
21 | + self.assertEqual(len(config.get_channels(first_unit)),1) | |
22 | + self.assertEqual(len(config.get_agents_per_device(first_unit)),4) | |
23 | + self.assertIn("AstroMecCA",config.get_devices().keys()) | |
24 | + self.assertIn("MainComputer",config.get_computers().keys()) | |
25 | + self.assertEqual(config.get_device_capabilities("AstroMecCA")[0]["component"],"MountPointing") | |
26 | + self.assertEquals(len(config.devices_links),0) | |
27 | + | |
28 | + def test_OCF_view_config_simple(self): | |
29 | + config = ConfigPyros("obsconfig/fixtures/observatory_configuration_ok_simple.yml") | |
30 | + u1 = PyrosUser.objects.get(username="haribo") | |
31 | + u1.set_password("password123") | |
32 | + u1.save() | |
33 | + self.client.login(username="haribo",password="password123") | |
34 | + response = self.client.get(reverse('obs_astronomer_config')) | |
35 | + self.assertEqual(response.status_code, 200) | |
36 | + self.assertTemplateUsed(response, 'base.html') | |
37 | + self.assertTemplateUsed(response, 'obsconfig/obs_astronomer_config.html') | |
38 | + self.assertContains(response, 'AstroMecCA') | |
39 | + self.assertContains(response,"PLC") | |
40 | + self.assertContains(response,"OpticalChannel") | |
41 | + | |
42 | + def test_OCF_view_config_complex(self): | |
43 | + config = ConfigPyros("obsconfig/fixtures/observatory_configuration_ok_complex.yml") | |
44 | + u1 = PyrosUser.objects.get(username="haribo") | |
45 | + u1.set_password("password123") | |
46 | + u1.save() | |
47 | + self.client.login(username="haribo",password="password123") | |
48 | + response = self.client.get(reverse('obs_astronomer_config')) | |
49 | + self.assertEqual(response.status_code, 200) | |
50 | + self.assertTemplateUsed(response, 'base.html') | |
51 | + self.assertTemplateUsed(response, 'obsconfig/obs_astronomer_config.html') | |
52 | + self.assertContains(response, 'AstroMecCA') | |
53 | + self.assertContains(response,"PLC") | |
54 | + self.assertContains(response,"OpticalChannel") | |
55 | + # testing if GPS capability is attached to Camera ZWO | |
56 | + self.assertContains(response,"DetectorTimer") | |
13 | 57 | \ No newline at end of file | ... | ... |