1# Copyright 2012 Nebula, Inc.
2#
3#    Licensed under the Apache License, Version 2.0 (the "License"); you may
4#    not use this file except in compliance with the License. You may obtain
5#    a copy of the License at
6#
7#         http://www.apache.org/licenses/LICENSE-2.0
8#
9#    Unless required by applicable law or agreed to in writing, software
10#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12#    License for the specific language governing permissions and limitations
13#    under the License.
14
15from unittest import mock
16
17from django.conf import settings
18from django.test.utils import override_settings
19from django.urls import reverse
20
21from openstack_dashboard import api
22from openstack_dashboard.test import helpers as test
23
24from openstack_dashboard.dashboards.admin.images import tables
25
26INDEX_TEMPLATE = 'horizon/common/_data_table_view.html'
27
28
29class ImageCreateViewTest(test.BaseAdminViewTests):
30    @mock.patch.object(api.glance, 'get_image_schemas')
31    @mock.patch.object(api.glance, 'image_list_detailed')
32    def test_admin_image_create_view_uses_admin_template(self,
33                                                         mock_image_list,
34                                                         mock_schemas_list):
35        filters1 = {'disk_format': 'aki'}
36        filters2 = {'disk_format': 'ari'}
37
38        mock_schemas_list.return_value = self.image_schemas.first()
39        mock_image_list.return_value = [self.images.list(), False, False]
40
41        res = self.client.get(
42            reverse('horizon:admin:images:create'))
43
44        calls = [mock.call(test.IsHttpRequest(), filters=filters1),
45                 mock.call(test.IsHttpRequest(), filters=filters2)]
46        mock_image_list.assert_has_calls(calls)
47
48        self.assertTemplateUsed(res, 'admin/images/create.html')
49
50
51class ImagesViewTest(test.BaseAdminViewTests):
52    @mock.patch.object(api.glance, 'image_list_detailed')
53    @mock.patch.object(api.keystone, 'tenant_list')
54    def test_images_list(self, mock_tenant_list, mock_image_list):
55        filters = {'is_public': None}
56        mock_image_list.return_value = [self.images.list(), False, False]
57        mock_tenant_list.return_value = [self.tenants.list(), False]
58
59        # Test tenant list
60        res = self.client.get(
61            reverse('horizon:admin:images:index'))
62
63        mock_tenant_list.assert_called_once_with(test.IsHttpRequest())
64        mock_image_list.assert_called_once_with(test.IsHttpRequest(),
65                                                marker=None,
66                                                paginate=True,
67                                                filters=filters,
68                                                sort_dir='asc',
69                                                sort_key='name',
70                                                reversed_order=False)
71        self.assertContains(res, 'test_tenant', 9, 200)
72        self.assertTemplateUsed(res, INDEX_TEMPLATE)
73        self.assertEqual(len(res.context['images_table'].data),
74                         len(self.images.list()))
75
76    @test.update_settings(FILTER_DATA_FIRST={'admin.images': True})
77    def test_images_list_with_admin_filter_first(self):
78        res = self.client.get(reverse('horizon:admin:images:index'))
79        self.assertTemplateUsed(res, INDEX_TEMPLATE)
80        images = res.context['table'].data
81        self.assertCountEqual(images, [])
82
83    @override_settings(API_RESULT_PAGE_SIZE=2)
84    @mock.patch.object(api.glance, 'image_list_detailed')
85    @mock.patch.object(api.keystone, 'tenant_list')
86    def test_images_list_get_pagination(self, mock_tenant_list,
87                                        mock_image_list):
88        images = self.images.list()[:5]
89        filters = {'is_public': None}
90        kwargs = {'paginate': True, 'filters': filters,
91                  'sort_dir': 'asc', 'sort_key': 'name',
92                  'reversed_order': False}
93        mock_image_list.side_effect = [[images, True, True],
94                                       [images[:2], True, True],
95                                       [images[2:4], True, True],
96                                       [images[4:], True, True]]
97
98        mock_tenant_list.return_value = [self.tenants.list(), False]
99        # Test tenant list
100        url = reverse('horizon:admin:images:index')
101        res = self.client.get(url)
102
103        image_calls = [mock.call(test.IsHttpRequest(), marker=None, **kwargs),
104                       mock.call(test.IsHttpRequest(), marker=None, **kwargs),
105                       mock.call(test.IsHttpRequest(),
106                                 marker=images[2].id, **kwargs),
107                       mock.call(test.IsHttpRequest(),
108                                 marker=images[4].id, **kwargs)]
109        # get all
110        self.assertEqual(len(res.context['images_table'].data),
111                         len(images))
112        self.assertTemplateUsed(res, INDEX_TEMPLATE)
113        self.assertContains(res, 'test_tenant', 7, 200)
114
115        res = self.client.get(url)
116        # get first page with 2 items
117        self.assertEqual(len(res.context['images_table'].data),
118                         settings.API_RESULT_PAGE_SIZE)
119
120        params = "=".join([tables.AdminImagesTable._meta.pagination_param,
121                           images[2].id])
122        url = "?".join([reverse('horizon:admin:images:index'), params])
123        res = self.client.get(url)
124        # get second page (items 2-4)
125        self.assertEqual(len(res.context['images_table'].data),
126                         settings.API_RESULT_PAGE_SIZE)
127        self.assertContains(res, 'test_tenant', 4, 200)
128
129        params = "=".join([tables.AdminImagesTable._meta.pagination_param,
130                           images[4].id])
131        url = "?".join([reverse('horizon:admin:images:index'), params])
132        res = self.client.get(url)
133
134        # get third page (item 5)
135        self.assertEqual(len(res.context['images_table'].data),
136                         1)
137        self.assertContains(res, 'test_tenant', 3, 200)
138
139        mock_image_list.assert_has_calls(image_calls)
140        mock_tenant_list.assert_called_with(test.IsHttpRequest())
141
142    @override_settings(API_RESULT_PAGE_SIZE=2)
143    @mock.patch.object(api.glance, 'image_list_detailed')
144    @mock.patch.object(api.keystone, 'tenant_list')
145    def test_images_list_get_prev_pagination(self, mock_tenant_list,
146                                             mock_image_list):
147        images = self.images.list()[:3]
148        filters = {'is_public': None}
149        kwargs = {'paginate': True, 'filters': filters,
150                  'sort_dir': 'asc', 'sort_key': 'name'}
151
152        mock_image_list.side_effect = [[images, True, False],
153                                       [images[:2], True, True],
154                                       [images[2:], True, True],
155                                       [images[:2], True, True]]
156
157        mock_tenant_list.return_value = [self.tenants.list(), False]
158
159        image_calls = [mock.call(test.IsHttpRequest(), marker=None,
160                                 reversed_order=False, **kwargs),
161                       mock.call(test.IsHttpRequest(), marker=None,
162                                 reversed_order=False, **kwargs),
163                       mock.call(test.IsHttpRequest(), marker=images[2].id,
164                                 reversed_order=False, **kwargs),
165                       mock.call(test.IsHttpRequest(), marker=images[2].id,
166                                 reversed_order=True, **kwargs)]
167
168        url = reverse('horizon:admin:images:index')
169        res = self.client.get(url)
170        # get all
171        self.assertEqual(len(res.context['images_table'].data),
172                         len(images))
173        self.assertTemplateUsed(res, INDEX_TEMPLATE)
174        self.assertContains(res, 'test_tenant', 5, 200)
175
176        res = self.client.get(url)
177        # get first page with 2 items
178        self.assertEqual(len(res.context['images_table'].data),
179                         settings.API_RESULT_PAGE_SIZE)
180        self.assertContains(res, 'test_tenant', 4, 200)
181
182        params = "=".join([tables.AdminImagesTable._meta.pagination_param,
183                           images[2].id])
184        url = "?".join([reverse('horizon:admin:images:index'), params])
185        res = self.client.get(url)
186        # get second page (item 3)
187        self.assertEqual(len(res.context['images_table'].data), 1)
188        self.assertContains(res, 'test_tenant', 3, 200)
189
190        params = "=".join([tables.AdminImagesTable._meta.prev_pagination_param,
191                           images[2].id])
192        url = "?".join([reverse('horizon:admin:images:index'), params])
193        res = self.client.get(url)
194        # prev back to get first page with 2 items
195        self.assertEqual(len(res.context['images_table'].data),
196                         settings.API_RESULT_PAGE_SIZE)
197        self.assertContains(res, 'test_tenant', 4, 200)
198
199        mock_image_list.assert_has_calls(image_calls)
200        mock_tenant_list.assert_called_with(test.IsHttpRequest())
201