summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatt Borland <matt.borland@hpe.com>2016-07-18 13:50:00 -0600
committerCindy Lu <clu@us.ibm.com>2016-10-11 15:49:55 -0700
commite8e84c2db43043dd9414b823472e4139a0c24e16 (patch)
tree27345df0f7d7cf049afca8773973e82a2f8eb2dd
parentdd6c6447554a6e837cf3e21688e61bbb9a40d965 (diff)
Flavors panel can switch to Angular
This patch enables all of the features for the Flavors panel to use Angular but disables it, so that it is easy to switch on/off. Note that we add integration test switches since it can't read the Django conf. Note that I changed the common tests to allow for testing of api calls that don't produce error toasts, because we needed better branch coverage, and the deleteFlavor api wasn't fully branch-tested. Change-Id: I92b1b57bd486e5eb87179cb8d44b7551e9de2e0f Partially-Implements: blueprint ng-flavors
Notes
Notes (review): Code-Review+2: Thai Tran <tqtran@us.ibm.com> Code-Review+1: Allen <chen.qiaomin@99cloud.net> Code-Review+2: Travis Tripp <travis.tripp@hpe.com> Workflow+1: Travis Tripp <travis.tripp@hpe.com> Verified+2: Jenkins Submitted-by: Jenkins Submitted-at: Fri, 14 Oct 2016 20:13:13 +0000 Reviewed-on: https://review.openstack.org/343917 Project: openstack/horizon Branch: refs/heads/master
-rw-r--r--doc/source/topics/settings.rst3
-rw-r--r--openstack_dashboard/dashboards/admin/flavors/urls.py21
-rw-r--r--openstack_dashboard/dashboards/admin/flavors/views.py5
-rw-r--r--openstack_dashboard/dashboards/admin/static/dashboard/admin/admin.module.js46
-rw-r--r--openstack_dashboard/dashboards/admin/static/dashboard/admin/admin.module.spec.js38
-rw-r--r--openstack_dashboard/dashboards/admin/static/dashboard/admin/flavors/filters/has-extras.filter.js44
-rw-r--r--openstack_dashboard/dashboards/admin/static/dashboard/admin/flavors/filters/has-extras.filter.spec.js43
-rw-r--r--openstack_dashboard/dashboards/admin/static/dashboard/admin/flavors/flavors.module.js30
-rw-r--r--openstack_dashboard/dashboards/admin/static/dashboard/admin/flavors/flavors.module.spec.js24
-rw-r--r--openstack_dashboard/dashboards/admin/static/dashboard/admin/flavors/table/flavors-table.controller.js87
-rw-r--r--openstack_dashboard/dashboards/admin/static/dashboard/admin/flavors/table/flavors-table.controller.spec.js77
-rw-r--r--openstack_dashboard/dashboards/admin/static/dashboard/admin/flavors/table/flavors-table.html63
-rw-r--r--openstack_dashboard/enabled/_2000_admin.py1
-rw-r--r--openstack_dashboard/enabled/_2080_admin_flavors_panel.py15
-rw-r--r--openstack_dashboard/enabled/_2081_admin_flavors_panel.py31
-rw-r--r--openstack_dashboard/local/local_settings.d/_2010_integration_tests_deprecated.py.example2
-rw-r--r--openstack_dashboard/settings.py1
-rw-r--r--openstack_dashboard/static/app/core/core.module.js1
-rw-r--r--openstack_dashboard/static/app/core/flavors/flavors.module.js121
-rw-r--r--openstack_dashboard/static/app/core/flavors/flavors.service.js37
-rw-r--r--openstack_dashboard/static/app/core/flavors/flavors.service.spec.js41
-rw-r--r--openstack_dashboard/static/app/core/flavors/panel.html3
-rw-r--r--openstack_dashboard/static/app/core/flavors/summary.html19
-rw-r--r--openstack_dashboard/static/app/core/openstack-service-api/nova.service.js10
-rw-r--r--openstack_dashboard/static/app/core/openstack-service-api/nova.service.spec.js11
-rw-r--r--openstack_dashboard/test/integration_tests/config.py7
-rw-r--r--openstack_dashboard/test/integration_tests/horizon.conf3
-rw-r--r--openstack_dashboard/test/integration_tests/pages/admin/system/flavorspage.py11
-rw-r--r--openstack_dashboard/test/integration_tests/tests/test_flavors.py30
-rw-r--r--openstack_dashboard/test/settings.py3
-rw-r--r--releasenotes/notes/flavor-panel-switch-6b5cd5f0964f4ba3.yaml13
31 files changed, 333 insertions, 508 deletions
diff --git a/doc/source/topics/settings.rst b/doc/source/topics/settings.rst
index 64cd3ea..e598a30 100644
--- a/doc/source/topics/settings.rst
+++ b/doc/source/topics/settings.rst
@@ -432,7 +432,8 @@ This example sorts flavors by vcpus in descending order::
432Default:: 432Default::
433 433
434 { 434 {
435 'images_panel': True 435 'images_panel': True,
436 'flavors_panel': False,
436 } 437 }
437 438
438A dictionary of currently available AngularJS features. This allows simple 439A dictionary of currently available AngularJS features. This allows simple
diff --git a/openstack_dashboard/dashboards/admin/flavors/urls.py b/openstack_dashboard/dashboards/admin/flavors/urls.py
index 4f044b4..6739aa5 100644
--- a/openstack_dashboard/dashboards/admin/flavors/urls.py
+++ b/openstack_dashboard/dashboards/admin/flavors/urls.py
@@ -16,13 +16,24 @@
16# License for the specific language governing permissions and limitations 16# License for the specific language governing permissions and limitations
17# under the License. 17# under the License.
18 18
19from django.conf import settings
19from django.conf.urls import url 20from django.conf.urls import url
20 21
21from openstack_dashboard.dashboards.admin.flavors import views 22from openstack_dashboard.dashboards.admin.flavors import views
22 23
23 24
24urlpatterns = [ 25if settings.ANGULAR_FEATURES['flavors_panel']:
25 url(r'^$', views.IndexView.as_view(), name='index'), 26 # New angular panel
26 url(r'^create/$', views.CreateView.as_view(), name='create'), 27 urlpatterns = [
27 url(r'^(?P<id>[^/]+)/update/$', views.UpdateView.as_view(), name='update'), 28 url(r'^$', views.AngularIndexView.as_view(), name='index'),
28] 29 url(r'^create/$', views.AngularIndexView.as_view(), name='create'),
30 url(r'^(?P<id>[^/]+)/update/$', views.AngularIndexView.as_view(),
31 name='index'),
32 ]
33else:
34 urlpatterns = [
35 url(r'^$', views.IndexView.as_view(), name='index'),
36 url(r'^create/$', views.CreateView.as_view(), name='create'),
37 url(r'^(?P<id>[^/]+)/update/$',
38 views.UpdateView.as_view(), name='update'),
39 ]
diff --git a/openstack_dashboard/dashboards/admin/flavors/views.py b/openstack_dashboard/dashboards/admin/flavors/views.py
index 0bfc44e..a4322ce 100644
--- a/openstack_dashboard/dashboards/admin/flavors/views.py
+++ b/openstack_dashboard/dashboards/admin/flavors/views.py
@@ -18,6 +18,7 @@
18 18
19from django.core.urlresolvers import reverse_lazy 19from django.core.urlresolvers import reverse_lazy
20from django.utils.translation import ugettext_lazy as _ 20from django.utils.translation import ugettext_lazy as _
21from django.views import generic
21 22
22from horizon import exceptions 23from horizon import exceptions
23from horizon import tables 24from horizon import tables
@@ -34,6 +35,10 @@ from openstack_dashboard.dashboards.admin.flavors \
34INDEX_URL = "horizon:admin:flavors:index" 35INDEX_URL = "horizon:admin:flavors:index"
35 36
36 37
38class AngularIndexView(generic.TemplateView):
39 template_name = 'angular.html'
40
41
37class IndexView(tables.DataTableView): 42class IndexView(tables.DataTableView):
38 table_class = project_tables.FlavorsTable 43 table_class = project_tables.FlavorsTable
39 template_name = 'admin/flavors/index.html' 44 template_name = 'admin/flavors/index.html'
diff --git a/openstack_dashboard/dashboards/admin/static/dashboard/admin/admin.module.js b/openstack_dashboard/dashboards/admin/static/dashboard/admin/admin.module.js
deleted file mode 100644
index b068dca..0000000
--- a/openstack_dashboard/dashboards/admin/static/dashboard/admin/admin.module.js
+++ /dev/null
@@ -1,46 +0,0 @@
1/**
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 */
15
16(function() {
17 'use strict';
18
19 /**
20 * @ngdoc horizon.dashboard.admin
21 * @ngModule
22 *
23 * @description
24 * Dashboard module to host various admin panels.
25 */
26 angular
27 .module('horizon.dashboard.admin', [
28 'horizon.dashboard.admin.flavors'
29 ])
30 .config(config);
31
32 config.$inject = [
33 '$provide',
34 '$windowProvider'
35 ];
36
37 /**
38 * @name horizon.dashboard.admin.basePath
39 * @description Base path for the admin dashboard
40 */
41 function config($provide, $windowProvider) {
42 var path = $windowProvider.$get().STATIC_URL + 'dashboard/admin/';
43 $provide.constant('horizon.dashboard.admin.basePath', path);
44 }
45
46})();
diff --git a/openstack_dashboard/dashboards/admin/static/dashboard/admin/admin.module.spec.js b/openstack_dashboard/dashboards/admin/static/dashboard/admin/admin.module.spec.js
deleted file mode 100644
index d9ca3f6..0000000
--- a/openstack_dashboard/dashboards/admin/static/dashboard/admin/admin.module.spec.js
+++ /dev/null
@@ -1,38 +0,0 @@
1/**
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 */
15(function() {
16 'use strict';
17
18 describe('horizon.dashboard.admin', function() {
19 var staticUrl, basePath;
20
21 beforeEach(module('horizon.dashboard.admin'));
22
23 beforeEach(inject(function($injector) {
24 staticUrl = $injector.get('$window').STATIC_URL;
25 basePath = $injector.get('horizon.dashboard.admin.basePath');
26 }));
27
28 it('should exist', function() {
29 expect(angular.module('horizon.dashboard.admin')).toBeDefined();
30 });
31
32 it('should set path properly', function () {
33 expect(basePath).toEqual(staticUrl + 'dashboard/admin/');
34 });
35
36 });
37
38})();
diff --git a/openstack_dashboard/dashboards/admin/static/dashboard/admin/flavors/filters/has-extras.filter.js b/openstack_dashboard/dashboards/admin/static/dashboard/admin/flavors/filters/has-extras.filter.js
deleted file mode 100644
index 80017bb..0000000
--- a/openstack_dashboard/dashboards/admin/static/dashboard/admin/flavors/filters/has-extras.filter.js
+++ /dev/null
@@ -1,44 +0,0 @@
1/**
2 *
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain 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,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15(function () {
16 'use strict';
17
18 angular
19 .module('horizon.dashboard.admin.flavors')
20 .filter('hasExtras', hasExtrasFilter);
21
22 hasExtrasFilter.$inject = [];
23
24 /**
25 * @ngdoc filter
26 * @name hasExtrasFilter
27 * @description
28 * If input is defined and has more than one property return 'Yes' else return 'No'
29 *
30 */
31 function hasExtrasFilter() {
32 return function check(input) {
33 if (input &&
34 angular.isObject(input) &&
35 !angular.isArray(input) &&
36 Object.keys(input).length > 0) {
37 return true;
38 }
39
40 return false;
41 };
42 }
43
44})();
diff --git a/openstack_dashboard/dashboards/admin/static/dashboard/admin/flavors/filters/has-extras.filter.spec.js b/openstack_dashboard/dashboards/admin/static/dashboard/admin/flavors/filters/has-extras.filter.spec.js
deleted file mode 100644
index 6c53f41..0000000
--- a/openstack_dashboard/dashboards/admin/static/dashboard/admin/flavors/filters/has-extras.filter.spec.js
+++ /dev/null
@@ -1,43 +0,0 @@
1/**
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 */
15(function() {
16 'use strict';
17
18 describe('horizon.dashboard.admin.flavors.hasExtras', function() {
19
20 var hasExtras;
21
22 beforeEach(module('horizon.framework.util.i18n'));
23 beforeEach(module('horizon.dashboard.admin.flavors'));
24
25 beforeEach(inject(function(_hasExtrasFilter_) {
26 hasExtras = _hasExtrasFilter_;
27 }));
28
29 it('returns Yes when key is present', function() {
30 var input = { 1: 'test' };
31 expect(hasExtras(input)).toBeTruthy();
32 });
33
34 it('returns No when object is undefined or has no properties', function() {
35 expect(hasExtras()).not.toBeTruthy();
36 expect(hasExtras({})).not.toBeTruthy();
37 expect(hasExtras('string')).not.toBeTruthy();
38 expect(hasExtras(1)).not.toBeTruthy();
39 expect(hasExtras([1])).not.toBeTruthy();
40 });
41 });
42
43})();
diff --git a/openstack_dashboard/dashboards/admin/static/dashboard/admin/flavors/flavors.module.js b/openstack_dashboard/dashboards/admin/static/dashboard/admin/flavors/flavors.module.js
deleted file mode 100644
index 2f1f106..0000000
--- a/openstack_dashboard/dashboards/admin/static/dashboard/admin/flavors/flavors.module.js
+++ /dev/null
@@ -1,30 +0,0 @@
1/**
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 */
15
16(function() {
17 'use strict';
18
19 /**
20 * @ngdoc horizon.dashboard.admin.flavors
21 * @ngModule
22 *
23 * @description
24 * Provides all of the services and widgets required
25 * to support and display the flavors panel.
26 */
27 angular
28 .module('horizon.dashboard.admin.flavors', []);
29
30})();
diff --git a/openstack_dashboard/dashboards/admin/static/dashboard/admin/flavors/flavors.module.spec.js b/openstack_dashboard/dashboards/admin/static/dashboard/admin/flavors/flavors.module.spec.js
deleted file mode 100644
index 5a35e76..0000000
--- a/openstack_dashboard/dashboards/admin/static/dashboard/admin/flavors/flavors.module.spec.js
+++ /dev/null
@@ -1,24 +0,0 @@
1/**
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 */
15(function () {
16 'use strict';
17
18 describe('horizon.dashboard.admin.flavors', function () {
19 it('should exist', function () {
20 expect(angular.module('horizon.dashboard.admin.flavors')).toBeDefined();
21 });
22 });
23
24})();
diff --git a/openstack_dashboard/dashboards/admin/static/dashboard/admin/flavors/table/flavors-table.controller.js b/openstack_dashboard/dashboards/admin/static/dashboard/admin/flavors/table/flavors-table.controller.js
deleted file mode 100644
index b5b7d3f..0000000
--- a/openstack_dashboard/dashboards/admin/static/dashboard/admin/flavors/table/flavors-table.controller.js
+++ /dev/null
@@ -1,87 +0,0 @@
1/**
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 */
15
16(function() {
17 'use strict';
18
19 angular
20 .module('horizon.dashboard.admin.flavors')
21 .controller('FlavorsTableController', FlavorsTableController);
22
23 FlavorsTableController.$inject = [
24 'horizon.app.core.openstack-service-api.nova'
25 ];
26
27 /**
28 * @ngdoc FlavorsTableController
29 * @ngController
30 *
31 * @description
32 * Controller for the flavors panel.
33 * Serves as the focal point for table actions.
34 */
35 function FlavorsTableController(
36 nova
37 ) {
38 var ctrl = this;
39
40 ctrl.flavors = [];
41 ctrl.iflavors = [];
42
43 ctrl.searchFacets = getSearchFacets();
44
45 init();
46
47 ////////////////////////////////
48
49 function init() {
50 nova.getFlavors(true, true).then(onGetFlavors);
51 }
52
53 function onGetFlavors(response) {
54 ctrl.flavors = response.data.items;
55 }
56
57 function getSearchFacets() {
58 return [
59 {
60 label: gettext('Name'),
61 name: 'name',
62 singleton: true
63 },
64 {
65 label: gettext('VCPUs'),
66 name: 'vcpus',
67 singleton: true
68 },
69 {
70 label: gettext('RAM'),
71 name: 'ram',
72 singleton: true
73 },
74 {
75 label: gettext('Public'),
76 name: 'os-flavor-access:is_public',
77 singleton: true,
78 options: [
79 {label: gettext('Yes'), key: 'true'},
80 {label: gettext('No'), key: 'false'}
81 ]
82 }
83 ];
84 }
85
86 }
87})();
diff --git a/openstack_dashboard/dashboards/admin/static/dashboard/admin/flavors/table/flavors-table.controller.spec.js b/openstack_dashboard/dashboards/admin/static/dashboard/admin/flavors/table/flavors-table.controller.spec.js
deleted file mode 100644
index ab7ceab..0000000
--- a/openstack_dashboard/dashboards/admin/static/dashboard/admin/flavors/table/flavors-table.controller.spec.js
+++ /dev/null
@@ -1,77 +0,0 @@
1/**
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 */
15(function () {
16 'use strict';
17
18 describe('horizon.dashboard.admin.flavors.controller.FlavorsTableController', function () {
19
20 var flavors = [{id: '1'}, {id: '2'}];
21
22 var novaAPI = {
23 getFlavors: function() {
24 var deferred = $q.defer();
25 deferred.resolve({data: {items: flavors}});
26 return deferred.promise;
27 }
28 };
29
30 var controller, $q, $scope;
31
32 beforeEach(module('horizon.framework'));
33
34 beforeEach(module('horizon.app.core.openstack-service-api', function($provide) {
35 $provide.value('horizon.app.core.openstack-service-api.nova', novaAPI);
36 }));
37
38 beforeEach(module('horizon.dashboard.admin', function($provide) {
39 $provide.constant('horizon.dashboard.admin.basePath', '/a/sample/path/');
40 }));
41
42 beforeEach(module('horizon.dashboard.admin.flavors'));
43
44 beforeEach(inject(function ($injector, _$rootScope_) {
45 $scope = _$rootScope_.$new();
46 $q = $injector.get('$q');
47 controller = $injector.get('$controller');
48 }));
49
50 function createController() {
51 return controller('FlavorsTableController', {});
52 }
53
54 it('should set facets for search', function () {
55 var ctrl = createController();
56 expect(ctrl.searchFacets).toBeDefined();
57 expect(ctrl.searchFacets.length).toEqual(4);
58 expect(ctrl.searchFacets[0].name).toEqual('name');
59 expect(ctrl.searchFacets[1].name).toEqual('vcpus');
60 expect(ctrl.searchFacets[2].name).toEqual('ram');
61 expect(ctrl.searchFacets[3].name).toEqual('os-flavor-access:is_public');
62 });
63
64 it('should invoke nova apis', function() {
65 spyOn(novaAPI, 'getFlavors').and.callThrough();
66
67 var ctrl = createController();
68 $scope.$apply();
69
70 expect(novaAPI.getFlavors).toHaveBeenCalled();
71 expect(ctrl.flavors).toEqual(flavors);
72 expect(ctrl.iflavors).toBeDefined();
73 });
74
75 });
76
77})();
diff --git a/openstack_dashboard/dashboards/admin/static/dashboard/admin/flavors/table/flavors-table.html b/openstack_dashboard/dashboards/admin/static/dashboard/admin/flavors/table/flavors-table.html
deleted file mode 100644
index b6a578e..0000000
--- a/openstack_dashboard/dashboards/admin/static/dashboard/admin/flavors/table/flavors-table.html
+++ /dev/null
@@ -1,63 +0,0 @@
1<div ng-controller="FlavorsTableController as table">
2
3 <hz-magic-search-context filter-facets="table.searchFacets">
4 <hz-magic-search-bar>
5 </hz-magic-search-bar>
6
7 <table st-magic-search
8 hz-table ng-cloak
9 st-table="table.iflavors"
10 st-safe-src="table.flavors"
11 class="table table-striped table-rsp table-detail">
12
13 <thead>
14
15 <tr>
16 <th class="select-col">
17 <input type="checkbox" hz-select-all="table.iflavors">
18 </th>
19 <th class="rsp-p1" st-sort="name" translate>Flavor Name</th>
20 <th class="rsp-p1" st-sort="vcpus" translate>VCPUs</th>
21 <th class="rsp-p1" st-sort="ram" st-sort-default="ram" translate>RAM</th>
22 <th class="rsp-p2" st-sort="disk" translate>Root Disk</th>
23 <th class="rsp-p2" st-sort="ephermal" translate>Ephemeral Disk</th>
24 <th class="rsp-p2" st-sort="swap" translate>Swap Disk</th>
25 <th class="rsp-p2" st-sort="rxtx_factor" translate>RX/TX factor</th>
26 <th class="rsp-p2" st-sort="id" translate>ID</th>
27 <th class="rsp-p2" st-sort="is_public" translate>Public</th>
28 <th class="rsp-p2" st-sort="metadata" translate>Metadata</th>
29 <th class="rsp-p2"></th>
30 </tr>
31
32 </thead>
33
34 <tbody>
35 <tr ng-repeat="flavor in table.iflavors track by flavor.id">
36 <td class="select-col">
37 <input type="checkbox"
38 ng-model="tCtrl.selections[flavor.id].checked"
39 hz-select="flavor">
40 </td>
41 <td class="rsp-p1">{$ flavor.name $}</td>
42 <td class="rsp-p1">{$ flavor.vcpus $}</td>
43 <td class="rsp-p1">{$ flavor.ram | mb $}</td>
44 <td class="rsp-p2">{$ flavor.disk | gb $}</td>
45 <td class="rsp-p2">{$ flavor.ephemeral | gb $}</td>
46 <td class="rsp-p2">{$ flavor.swap | mb $}</td>
47 <td class="rsp-p2">{$ flavor.rxtx_factor $}</td>
48 <td class="rsp-p2">{$ flavor.id $}</td>
49 <td class="rsp-p2">{$ flavor.is_public | yesno $}</td>
50 <td class="rsp-p2">{$ flavor.extras | hasExtras | yesno $}</td>
51 <td class="rsp-p2">
52 </td>
53 </tr>
54
55 <tr hz-no-items items="table.iflavors"></tr>
56
57 </tbody>
58
59 <tfoot hz-table-footer items="table.iflavors"></tfoot>
60
61 </table>
62 </hz-magic-search-context>
63</div>
diff --git a/openstack_dashboard/enabled/_2000_admin.py b/openstack_dashboard/enabled/_2000_admin.py
index 34363d7..50972cd 100644
--- a/openstack_dashboard/enabled/_2000_admin.py
+++ b/openstack_dashboard/enabled/_2000_admin.py
@@ -21,7 +21,6 @@ ADD_INSTALLED_APPS = [
21] 21]
22 22
23ADD_ANGULAR_MODULES = [ 23ADD_ANGULAR_MODULES = [
24 'horizon.dashboard.admin',
25] 24]
26 25
27AUTO_DISCOVER_STATIC_FILES = True 26AUTO_DISCOVER_STATIC_FILES = True
diff --git a/openstack_dashboard/enabled/_2080_admin_flavors_panel.py b/openstack_dashboard/enabled/_2080_admin_flavors_panel.py
index ee40018..9e41097 100644
--- a/openstack_dashboard/enabled/_2080_admin_flavors_panel.py
+++ b/openstack_dashboard/enabled/_2080_admin_flavors_panel.py
@@ -1,3 +1,18 @@
1# (c) Copyright 2016 Hewlett Packard Enterprise Development LP
2#
3# Licensed under the Apache License, Version 2.0 (the "License");
4# you may not use this file except in compliance with the License.
5# You may obtain 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,
11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
12# implied.
13# See the License for the specific language governing permissions and
14# limitations under the License.
15
1# The slug of the panel to be added to HORIZON_CONFIG. Required. 16# The slug of the panel to be added to HORIZON_CONFIG. Required.
2PANEL = 'flavors' 17PANEL = 'flavors'
3# The slug of the dashboard the PANEL associated with. Required. 18# The slug of the dashboard the PANEL associated with. Required.
diff --git a/openstack_dashboard/enabled/_2081_admin_flavors_panel.py b/openstack_dashboard/enabled/_2081_admin_flavors_panel.py
deleted file mode 100644
index 7efcbd2..0000000
--- a/openstack_dashboard/enabled/_2081_admin_flavors_panel.py
+++ /dev/null
@@ -1,31 +0,0 @@
1# (c) Copyright 2015 Hewlett-Packard Development Company, L.P.
2# (c) Copyright 2015 ThoughtWorks, Inc.
3#
4# Licensed under the Apache License, Version 2.0 (the "License"); you may
5# not use this file except in compliance with the License. You may obtain
6# a copy of the License at
7#
8# http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13# License for the specific language governing permissions and limitations
14# under the License.
15
16# The slug of the dashboard the PANEL associated with. Required.
17PANEL_DASHBOARD = 'admin'
18
19# The slug of the panel group the PANEL is associated with.
20# If you want the panel to show up without a panel group,
21# use the panel group "default".
22PANEL_GROUP = 'admin'
23
24# The slug of the panel to be added to HORIZON_CONFIG. Required.
25PANEL = 'ngflavors'
26
27# If set to True, this settings file will not be added to the settings.
28DISABLED = True
29
30# Python panel class of the PANEL to be added.
31ADD_PANEL = 'openstack_dashboard.dashboards.admin.ngflavors.panel.NGFlavors'
diff --git a/openstack_dashboard/local/local_settings.d/_2010_integration_tests_deprecated.py.example b/openstack_dashboard/local/local_settings.d/_2010_integration_tests_deprecated.py.example
index 87c9e67..2028a2c 100644
--- a/openstack_dashboard/local/local_settings.d/_2010_integration_tests_deprecated.py.example
+++ b/openstack_dashboard/local/local_settings.d/_2010_integration_tests_deprecated.py.example
@@ -2,4 +2,4 @@
2# wanting to only test legacy panels. Since 'local' modules are evaluated 2# wanting to only test legacy panels. Since 'local' modules are evaluated
3# after settings.py, these configurations will override the default settings. 3# after settings.py, these configurations will override the default settings.
4 4
5ANGULAR_FEATURES.update({"images_panel": False}) \ No newline at end of file 5ANGULAR_FEATURES.update({"images_panel": False, "flavors_panel": False})
diff --git a/openstack_dashboard/settings.py b/openstack_dashboard/settings.py
index 7a9c5a8..3ec6992 100644
--- a/openstack_dashboard/settings.py
+++ b/openstack_dashboard/settings.py
@@ -305,6 +305,7 @@ COMPRESS_OFFLINE_CONTEXT = 'horizon.themes.offline_context'
305# Dictionary of currently available angular features 305# Dictionary of currently available angular features
306ANGULAR_FEATURES = { 306ANGULAR_FEATURES = {
307 'images_panel': True, 307 'images_panel': True,
308 'flavors_panel': False,
308} 309}
309 310
310# Notice all customizable configurations should be above this line 311# Notice all customizable configurations should be above this line
diff --git a/openstack_dashboard/static/app/core/core.module.js b/openstack_dashboard/static/app/core/core.module.js
index 8ecfc58..eebfb5c 100644
--- a/openstack_dashboard/static/app/core/core.module.js
+++ b/openstack_dashboard/static/app/core/core.module.js
@@ -33,6 +33,7 @@
33 .module('horizon.app.core', [ 33 .module('horizon.app.core', [
34 'horizon.app.core.conf', 34 'horizon.app.core.conf',
35 'horizon.app.core.cloud-services', 35 'horizon.app.core.cloud-services',
36 'horizon.app.core.flavors',
36 'horizon.app.core.images', 37 'horizon.app.core.images',
37 'horizon.app.core.metadata', 38 'horizon.app.core.metadata',
38 'horizon.app.core.openstack-service-api', 39 'horizon.app.core.openstack-service-api',
diff --git a/openstack_dashboard/static/app/core/flavors/flavors.module.js b/openstack_dashboard/static/app/core/flavors/flavors.module.js
new file mode 100644
index 0000000..5f9b23d
--- /dev/null
+++ b/openstack_dashboard/static/app/core/flavors/flavors.module.js
@@ -0,0 +1,121 @@
1/**
2 * (c) Copyright 2015 Hewlett-Packard Development Company, L.P.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License"); you may
5 * not use this file except in compliance with the License. You may obtain
6 * a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13 * License for the specific language governing permissions and limitations
14 * under the License.
15 */
16
17(function() {
18 'use strict';
19
20 /**
21 * @ngdoc overview
22 * @ngname horizon.app.core.flavors
23 *
24 * @description
25 * Provides all of the services and widgets required
26 * to support and display flavors related content.
27 */
28 angular
29 .module('horizon.app.core.flavors', [
30 'ngRoute',
31 'horizon.framework.conf',
32 'horizon.app.core'
33 ])
34 .constant('horizon.app.core.flavors.resourceType', 'OS::Nova::Flavor')
35 .run(run)
36 .config(config);
37
38 run.$inject = [
39 'horizon.framework.conf.resource-type-registry.service',
40 'horizon.app.core.flavors.basePath',
41 'horizon.app.core.flavors.service',
42 'horizon.app.core.flavors.resourceType'
43 ];
44
45 function run(registry, basePath, flavorsService, flavorResourceType) {
46 registry.getResourceType(flavorResourceType)
47 .setNames(gettext('Flavor'), gettext('Flavors'))
48 .setSummaryTemplateUrl(basePath + 'summary.html')
49 .setProperties(flavorProperties())
50 .setListFunction(flavorsService.getFlavorsPromise)
51 .tableColumns
52 .append({
53 id: 'name',
54 priority: 1
55 })
56 .append({
57 id: 'vcpus',
58 priority: 2
59 })
60 .append({
61 id: 'ram',
62 priority: 1,
63 sortDefault: true
64 })
65 .append({
66 id: 'disk',
67 priority: 2
68 })
69 .append({
70 id: 'id',
71 priority: 1
72 })
73 .append({
74 id: 'os-flavor-access:is_public',
75 priority: 2
76 });
77
78 /**
79 * @name roleProperties
80 * @description resource properties for flavor module
81 */
82 function flavorProperties() {
83 return {
84 name: gettext('Flavor Name'),
85 vcpus: gettext('VCPUs'),
86 ram: {label: gettext('RAM'), filters: ['mb']},
87 disk: {label: gettext('Root Disk'), filters: ['gb']},
88 'OS-FLV-EXT-DATA:ephemeral': {label: gettext('Ephmeral Disk'), filters: ['gb']},
89 swap: {label: gettext('Swap Disk'), filters: ['gb']},
90 rxtx_factor: gettext('RX/TX Factor'),
91 id: gettext('ID'),
92 'os-flavor-access:is_public': {label: gettext('Public'), filters: ['yesno']},
93 metadata: gettext('Metadata')
94 };
95 }
96 }
97
98 config.$inject = [
99 '$provide',
100 '$windowProvider',
101 '$routeProvider'
102 ];
103
104 /**
105 * @name config
106 * @param {Object} $provide
107 * @param {Object} $windowProvider
108 * @param {Object} $routeProvider
109 * @description Routes used by this module.
110 * @returns {undefined} Returns nothing
111 */
112 function config($provide, $windowProvider, $routeProvider) {
113 var path = $windowProvider.$get().STATIC_URL + 'app/core/flavors/';
114 $provide.constant('horizon.app.core.flavors.basePath', path);
115
116 $routeProvider.when('/admin/flavors', {
117 templateUrl: path + 'panel.html'
118 });
119 }
120
121})();
diff --git a/openstack_dashboard/static/app/core/flavors/flavors.service.js b/openstack_dashboard/static/app/core/flavors/flavors.service.js
new file mode 100644
index 0000000..fdb960a
--- /dev/null
+++ b/openstack_dashboard/static/app/core/flavors/flavors.service.js
@@ -0,0 +1,37 @@
1/*
2 * (c) Copyright 2016 Hewlett Packard Enterprise Development LP
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16(function() {
17 "use strict";
18
19 angular.module('horizon.app.core.flavors')
20 .factory('horizon.app.core.flavors.service', flavorsService);
21
22 flavorsService.$inject = [
23 'horizon.app.core.openstack-service-api.nova'
24 ];
25
26 function flavorsService(nova) {
27 return {
28 getFlavorsPromise: getFlavorsPromise
29 };
30
31 function getFlavorsPromise(params) {
32 var fullParams = angular.extend({}, params, {get_extras: true});
33 return nova.getFlavors(fullParams);
34 }
35 }
36
37})();
diff --git a/openstack_dashboard/static/app/core/flavors/flavors.service.spec.js b/openstack_dashboard/static/app/core/flavors/flavors.service.spec.js
new file mode 100644
index 0000000..76bb25a
--- /dev/null
+++ b/openstack_dashboard/static/app/core/flavors/flavors.service.spec.js
@@ -0,0 +1,41 @@
1/*
2 * (c) Copyright 2016 Hewlett Packard Enterprise Development LP
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17(function() {
18 "use strict";
19
20 describe('flavors service', function() {
21 var service;
22 beforeEach(module('horizon.framework.util'));
23 beforeEach(module('horizon.framework.conf'));
24 beforeEach(module('horizon.app.core.flavors'));
25 beforeEach(inject(function($injector) {
26 service = $injector.get('horizon.app.core.flavors.service');
27 }));
28
29 describe('getFlavorsPromise', function() {
30 it("provides a promise that gets translated", inject(function($q, $injector) {
31 var glance = $injector.get('horizon.app.core.openstack-service-api.nova');
32 var deferred = $q.defer();
33 spyOn(glance, 'getFlavors').and.returnValue(deferred.promise);
34 service.getFlavorsPromise({});
35 deferred.resolve({data: {items: [{id: 1, updated_at: 'jul1'}]}});
36 expect(glance.getFlavors).toHaveBeenCalled();
37 }));
38 });
39
40 });
41})();
diff --git a/openstack_dashboard/static/app/core/flavors/panel.html b/openstack_dashboard/static/app/core/flavors/panel.html
new file mode 100644
index 0000000..4e30c10
--- /dev/null
+++ b/openstack_dashboard/static/app/core/flavors/panel.html
@@ -0,0 +1,3 @@
1<hz-resource-panel resource-type-name="OS::Nova::Flavor">
2 <hz-resource-table resource-type-name="OS::Nova::Flavor"></hz-resource-table>
3</hz-resource-panel>
diff --git a/openstack_dashboard/static/app/core/flavors/summary.html b/openstack_dashboard/static/app/core/flavors/summary.html
new file mode 100644
index 0000000..01b2a51
--- /dev/null
+++ b/openstack_dashboard/static/app/core/flavors/summary.html
@@ -0,0 +1,19 @@
1<hz-resource-property-list
2 resource-type-name="OS::Nova::Flavor"
3 item="item"
4 property-groups="[
5 ['name', 'id'],
6 ['vcpus', 'ram'],
7 ['disk', 'OS-FLV-EXT-DATA:ephemeral', 'swap'],
8 ['rxtx_factor']]">
9 </hz-resource-property-list>
10<div class="row">
11 <div class="col-md-4">
12 <dl>
13 <div ng-repeat="(key, value) in item.extras">
14 <dt>{$ key $}</dt>
15 <dd>{$ value $}</dd>
16 </div>
17 </dl>
18 </div>
19</div>
diff --git a/openstack_dashboard/static/app/core/openstack-service-api/nova.service.js b/openstack_dashboard/static/app/core/openstack-service-api/nova.service.js
index 30a66e4..cd06208 100644
--- a/openstack_dashboard/static/app/core/openstack-service-api/nova.service.js
+++ b/openstack_dashboard/static/app/core/openstack-service-api/nova.service.js
@@ -468,14 +468,8 @@
468 * call per flavor). 468 * call per flavor).
469 * @returns {Object} The result of the API call 469 * @returns {Object} The result of the API call
470 */ 470 */
471 function getFlavors(isPublic, getExtras) { 471 function getFlavors(params) {
472 var config = {'params': {}}; 472 var config = params ? { 'params' : params} : { 'params' : {} };
473 if (isPublic) {
474 config.params.is_public = 'true';
475 }
476 if (getExtras) {
477 config.params.get_extras = 'true';
478 }
479 return apiService.get('/api/nova/flavors/', config) 473 return apiService.get('/api/nova/flavors/', config)
480 .success(function (data) { 474 .success(function (data) {
481 // The colon character ':' in the flavor data causes problems when used 475 // The colon character ':' in the flavor data causes problems when used
diff --git a/openstack_dashboard/static/app/core/openstack-service-api/nova.service.spec.js b/openstack_dashboard/static/app/core/openstack-service-api/nova.service.spec.js
index 967d2f7..bd92338 100644
--- a/openstack_dashboard/static/app/core/openstack-service-api/nova.service.spec.js
+++ b/openstack_dashboard/static/app/core/openstack-service-api/nova.service.spec.js
@@ -286,8 +286,6 @@
286 }, 286 },
287 "error": "Unable to retrieve the flavors.", 287 "error": "Unable to retrieve the flavors.",
288 "testInput": [ 288 "testInput": [
289 false,
290 false
291 ] 289 ]
292 }, 290 },
293 { 291 {
@@ -301,8 +299,7 @@
301 }, 299 },
302 "error": "Unable to retrieve the flavors.", 300 "error": "Unable to retrieve the flavors.",
303 "testInput": [ 301 "testInput": [
304 true, 302 {is_public: "true"}
305 false
306 ] 303 ]
307 }, 304 },
308 { 305 {
@@ -316,8 +313,7 @@
316 }, 313 },
317 "error": "Unable to retrieve the flavors.", 314 "error": "Unable to retrieve the flavors.",
318 "testInput": [ 315 "testInput": [
319 false, 316 {get_extras: "true"}
320 true
321 ] 317 ]
322 }, 318 },
323 { 319 {
@@ -332,8 +328,7 @@
332 }, 328 },
333 "error": "Unable to retrieve the flavors.", 329 "error": "Unable to retrieve the flavors.",
334 "testInput": [ 330 "testInput": [
335 true, 331 {is_public: "true", get_extras: "true"}
336 true
337 ] 332 ]
338 }, 333 },
339 { 334 {
diff --git a/openstack_dashboard/test/integration_tests/config.py b/openstack_dashboard/test/integration_tests/config.py
index 2bcb6ab..668bc1d 100644
--- a/openstack_dashboard/test/integration_tests/config.py
+++ b/openstack_dashboard/test/integration_tests/config.py
@@ -102,6 +102,12 @@ SeleniumGroup = [
102 help="Is the browser size maximized for each test?"), 102 help="Is the browser size maximized for each test?"),
103] 103]
104 104
105FlavorsGroup = [
106 cfg.StrOpt('panel_type',
107 default='legacy',
108 help='type/version of flavors panel'),
109]
110
105ScenarioGroup = [ 111ScenarioGroup = [
106 cfg.StrOpt('ssh_user', 112 cfg.StrOpt('ssh_user',
107 default='cirros', 113 default='cirros',
@@ -163,6 +169,7 @@ def get_config():
163 cfg.CONF.register_opts(NetworkGroup, group="network") 169 cfg.CONF.register_opts(NetworkGroup, group="network")
164 cfg.CONF.register_opts(AvailableServiceGroup, group="service_available") 170 cfg.CONF.register_opts(AvailableServiceGroup, group="service_available")
165 cfg.CONF.register_opts(SeleniumGroup, group="selenium") 171 cfg.CONF.register_opts(SeleniumGroup, group="selenium")
172 cfg.CONF.register_opts(FlavorsGroup, group="flavors")
166 cfg.CONF.register_opts(ImageGroup, group="image") 173 cfg.CONF.register_opts(ImageGroup, group="image")
167 cfg.CONF.register_opts(ScenarioGroup, group="scenario") 174 cfg.CONF.register_opts(ScenarioGroup, group="scenario")
168 cfg.CONF.register_opts(InstancesGroup, group="launch_instances") 175 cfg.CONF.register_opts(InstancesGroup, group="launch_instances")
diff --git a/openstack_dashboard/test/integration_tests/horizon.conf b/openstack_dashboard/test/integration_tests/horizon.conf
index a4eeba0..a832499 100644
--- a/openstack_dashboard/test/integration_tests/horizon.conf
+++ b/openstack_dashboard/test/integration_tests/horizon.conf
@@ -33,6 +33,9 @@ explicit_wait=90
33# (boolean) 33# (boolean)
34maximize_browser=yes 34maximize_browser=yes
35 35
36[flavors]
37panel_type=legacy
38
36[image] 39[image]
37# http accessible image (string value) 40# http accessible image (string value)
38panel_type=angular 41panel_type=angular
diff --git a/openstack_dashboard/test/integration_tests/pages/admin/system/flavorspage.py b/openstack_dashboard/test/integration_tests/pages/admin/system/flavorspage.py
index b28780e..70da247 100644
--- a/openstack_dashboard/test/integration_tests/pages/admin/system/flavorspage.py
+++ b/openstack_dashboard/test/integration_tests/pages/admin/system/flavorspage.py
@@ -15,6 +15,8 @@ from openstack_dashboard.test.integration_tests.regions import forms
15from openstack_dashboard.test.integration_tests.regions import menus 15from openstack_dashboard.test.integration_tests.regions import menus
16from openstack_dashboard.test.integration_tests.regions import tables 16from openstack_dashboard.test.integration_tests.regions import tables
17 17
18from selenium.webdriver.common import by
19
18 20
19class FlavorsTable(tables.TableRegion): 21class FlavorsTable(tables.TableRegion):
20 name = "flavors" 22 name = "flavors"
@@ -144,3 +146,12 @@ class FlavorsPage(basepage.BaseNavigationPage):
144 def is_flavor_public(self, name): 146 def is_flavor_public(self, name):
145 row = self._get_flavor_row(name) 147 row = self._get_flavor_row(name)
146 return row.cells[self.FLAVORS_TABLE_PUBLIC_COLUMN].text == "Yes" 148 return row.cells[self.FLAVORS_TABLE_PUBLIC_COLUMN].text == "Yes"
149
150
151class FlavorsPageNG(FlavorsPage):
152 _resource_page_header_locator = (by.By.CSS_SELECTOR,
153 'hz-resource-panel hz-page-header h1')
154
155 @property
156 def header(self):
157 return self._get_element(*self._resource_page_header_locator)
diff --git a/openstack_dashboard/test/integration_tests/tests/test_flavors.py b/openstack_dashboard/test/integration_tests/tests/test_flavors.py
index 5e0400b..f427b0c 100644
--- a/openstack_dashboard/test/integration_tests/tests/test_flavors.py
+++ b/openstack_dashboard/test/integration_tests/tests/test_flavors.py
@@ -12,10 +12,28 @@
12 12
13import random 13import random
14 14
15from openstack_dashboard.test.integration_tests import decorators
15from openstack_dashboard.test.integration_tests import helpers 16from openstack_dashboard.test.integration_tests import helpers
16from openstack_dashboard.test.integration_tests.regions import messages 17from openstack_dashboard.test.integration_tests.regions import messages
17 18
18 19
20@decorators.config_option_required('flavors.panel_type', 'angular',
21 message="Legacy Panels not tested")
22class TestFlavorAngular(helpers.AdminTestCase):
23 @property
24 def flavors_page(self):
25 from openstack_dashboard.test.integration_tests.pages.admin.\
26 system.flavorspage import FlavorsPageNG
27 self.home_pg.go_to_system_flavorspage()
28 return FlavorsPageNG(self.driver, self.CONFIG)
29
30 def test_basic_flavors_browse(self):
31 flavors_page = self.flavors_page
32 self.assertEqual(flavors_page.header.text, 'Flavors')
33
34
35@decorators.config_option_required('flavors.panel_type', 'legacy',
36 message="Angular Panels not tested")
19class TestFlavors(helpers.AdminTestCase): 37class TestFlavors(helpers.AdminTestCase):
20 FLAVOR_NAME = helpers.gen_random_resource_name("flavor") 38 FLAVOR_NAME = helpers.gen_random_resource_name("flavor")
21 39
@@ -48,6 +66,18 @@ class TestFlavors(helpers.AdminTestCase):
48 self.assertFalse( 66 self.assertFalse(
49 self.flavors_page.is_flavor_present(self.FLAVOR_NAME)) 67 self.flavors_page.is_flavor_present(self.FLAVOR_NAME))
50 68
69 def test_flavor_header(self):
70 header_text = self.driver.find_element_by_tag_name('h1').text
71 self.assertEqual(header_text, 'Flavors')
72
73 def test_flavor_module_exists(self):
74 js_cmd = "$('html').append('<div id=\"testonly\">'"\
75 " + angular.module('horizon.app.core.flavors').name"\
76 " + '</div>');"
77 self.driver.execute_script(js_cmd)
78 value = self.driver.find_element_by_id('testonly').text
79 self.assertEqual(value, 'horizon.app.core.flavors')
80
51 def test_flavor_create(self): 81 def test_flavor_create(self):
52 """tests the flavor creation and deletion functionalities: 82 """tests the flavor creation and deletion functionalities:
53 * creates a new flavor 83 * creates a new flavor
diff --git a/openstack_dashboard/test/settings.py b/openstack_dashboard/test/settings.py
index 4aab9cf..9b59306 100644
--- a/openstack_dashboard/test/settings.py
+++ b/openstack_dashboard/test/settings.py
@@ -99,7 +99,8 @@ HORIZON_CONFIG = {
99} 99}
100 100
101ANGULAR_FEATURES = { 101ANGULAR_FEATURES = {
102 'images_panel': False # Use the legacy panel so unit tests are still run 102 'images_panel': False, # Use the legacy panel so unit tests are still run
103 'flavors_panel': False,
103} 104}
104 105
105STATICFILES_DIRS = settings_utils.get_xstatic_dirs( 106STATICFILES_DIRS = settings_utils.get_xstatic_dirs(
diff --git a/releasenotes/notes/flavor-panel-switch-6b5cd5f0964f4ba3.yaml b/releasenotes/notes/flavor-panel-switch-6b5cd5f0964f4ba3.yaml
new file mode 100644
index 0000000..2c3812b
--- /dev/null
+++ b/releasenotes/notes/flavor-panel-switch-6b5cd5f0964f4ba3.yaml
@@ -0,0 +1,13 @@
1---
2prelude: >
3 The Flavor panel now may be configured to use
4 either the legacy or Angular code.
5features:
6 - ANGULAR_FEATURES now allows for a key 'flavors_panel' to be
7 specified as True or False indicating whether the Angular
8 version of the panel is enabled.
9 - Integration tests for Flavor features may also be toggled
10 in openstack_dashboard/test/integration_tests/horizon.conf
11 using the 'panel_type' feature in the 'flavors' setting,
12 either set to 'legacy' or 'angular' to match the enabled
13 panel type.