diff --git a/app/js/controllers/tests-detail.js b/app/js/controllers/tests-detail.js new file mode 100644 index 00000000..f7876a5f --- /dev/null +++ b/app/js/controllers/tests-detail.js @@ -0,0 +1,82 @@ +'use strict'; + +var controllersModule = require('./_index'); +var _ = require('underscore'); + +/** + * @ngInject + */ +function TestsDetailController($scope, healthService, testService, key, $location) { + + // ViewModel + var vm = this; + vm.searchTest = ''; + vm.key = decodeURIComponent(key); + + vm.processData = function(data) { + vm.chartData = {}; + + var testsByHierarchy = _.groupBy(data.tests, function(test) { + var testId = testService.removeIdNoise(test.test_id); + var keyMatcher = /^(\w*)\./g; + var matches = keyMatcher.exec(testId); + + if (matches) { + return matches[1]; + } + + return 'Others'; + }); + + var getTestFailureAvg = function(test) { + return test.failure / test.run_count; + }; + + _.each(testsByHierarchy, function(tests, hierarchy, list) { + if (!vm.chartData[hierarchy]) { + vm.chartData[hierarchy] = [{ + key: hierarchy, + values: [], + tests: [] + }]; + } + + var orderedTests = _.sortBy(tests, function(test) { + return getTestFailureAvg(test) * -1; + }); + + var topFailures = _.first(orderedTests, 10); + + topFailures.forEach(function(test) { + var failureAverage = getTestFailureAvg(test); + if (!isNaN(failureAverage) && parseFloat(failureAverage) > 0.01) { + var chartData = { + label: test.test_id, + value: failureAverage + }; + vm.chartData[hierarchy][0].values.push(chartData); + } + }); + + orderedTests.forEach(function(test) { + test.failureAverage = getTestFailureAvg(test); + vm.chartData[hierarchy][0].tests.push(test); + }); + }); + }; + + vm.loadData = function() { + healthService.getTests().then(function(response) { + vm.processData(response.data); + }); + }; + + vm.searchTest = $location.search().searchTest || ''; + + vm.loadData(); + + vm.onSearchChange = function() { + $location.search('searchTest', $scope.testsDetail.searchTest); + }; +} +controllersModule.controller('TestsDetailController', TestsDetailController); diff --git a/app/js/controllers/tests.js b/app/js/controllers/tests.js index 227fac0d..87777557 100644 --- a/app/js/controllers/tests.js +++ b/app/js/controllers/tests.js @@ -27,40 +27,15 @@ function TestsController($scope, healthService, testService, $location) { return 'Others'; }); - var getTestFailureAvg = function(test) { - return test.failure / test.run_count; - }; - - _.each(testsByHierarchy, function(tests, hierarchy, list) { - if (!vm.chartData[hierarchy]) { - vm.chartData[hierarchy] = [{ - key: hierarchy, + var sortedKeys = _.sortBy(_.keys(testsByHierarchy)); + _.each(sortedKeys, function(key) { + if (!vm.chartData[key]) { + vm.chartData[key] = [{ + key: key, values: [], tests: [] }]; } - - var orderedTests = _.sortBy(tests, function(test) { - return getTestFailureAvg(test) * -1; - }); - - var topFailures = _.first(orderedTests, 10); - - topFailures.forEach(function(test) { - var failureAverage = getTestFailureAvg(test); - if (!isNaN(failureAverage) && parseFloat(failureAverage) > 0.01) { - var chartData = { - label: test.test_id, - value: failureAverage - }; - vm.chartData[hierarchy][0].values.push(chartData); - } - }); - - orderedTests.forEach(function(test) { - test.failureAverage = getTestFailureAvg(test); - vm.chartData[hierarchy][0].tests.push(test); - }); }); }; diff --git a/app/js/on_config.js b/app/js/on_config.js index 6a3bd252..2f7b8ef9 100644 --- a/app/js/on_config.js +++ b/app/js/on_config.js @@ -31,6 +31,17 @@ function OnConfig($stateProvider, $locationProvider, $urlRouterProvider) { templateUrl: 'tests.html', title: 'Tests' }) + .state('testsDetail', { + url: '/tests/:key', + controller: 'TestsDetailController as testsDetail', + templateUrl: 'tests-detail.html', + title: 'Tests Detail', + resolve: /*@ngInject*/ { + 'key': function($stateParams) { + return $stateParams.key; + } + } + }) .state('job', { url: '/job/:jobName', controller: 'JobController as job', diff --git a/app/js/services/health-api.js b/app/js/services/health-api.js index 485af6f0..a8c6df0e 100644 --- a/app/js/services/health-api.js +++ b/app/js/services/health-api.js @@ -100,6 +100,7 @@ function HealthService($http, config) { service.getTests = function() { return config.get().then(function(config) { return $http.jsonp(config.apiRoot + '/tests', { + cache: true, params: { callback: 'JSON_CALLBACK' } }); }); diff --git a/app/views/tests-detail.html b/app/views/tests-detail.html new file mode 100644 index 00000000..733106c2 --- /dev/null +++ b/app/views/tests-detail.html @@ -0,0 +1,70 @@ +
+
+

Tests Detail

+ +
+
+ +
+
+
+ +
+
+
+
+ +
+ +
+
+
+
+
+ +
+
+
+ + + + + + + + + + + + + + + + + + + +
+ Test ID + + Passed + + Failed + + Failure % + + Avg. Runtime (secs.) +
+ {{test.test_id | limitTo: 110}} + {{ test.success | number }}{{ test.failure | number }}{{ test.failureAverage * 100 | number: 2 }}%{{ test.run_time | number: 2 }}
+
+
+
+
+
+
+
diff --git a/app/views/tests.html b/app/views/tests.html index a016e000..4fe4a2af 100644 --- a/app/views/tests.html +++ b/app/views/tests.html @@ -13,58 +13,18 @@
- -
- -
-
-
-
-
- -
-
-
- - - - - - - - - - - - - - - - - - - -
- Test ID - - Passed - - Failed - - Failure % - - Avg. Runtime (secs.) -
- {{test.test_id | limitTo: 110}} - {{ test.success | number }}{{ test.failure | number }}{{ test.failureAverage * 100 | number: 2 }}%{{ test.run_time | number: 2 }}
+
+
+

Details list

+
+
+ - +
-
diff --git a/test/unit/controllers/tests_detail_spec.js b/test/unit/controllers/tests_detail_spec.js new file mode 100644 index 00000000..186fb1c5 --- /dev/null +++ b/test/unit/controllers/tests_detail_spec.js @@ -0,0 +1,107 @@ +describe('TestsDetailController', function() { + beforeEach(function() { + module('app'); + module('app.controllers'); + }); + + var $scope, $httpBackend, $controller, healthService; + var API_ROOT = 'http://8.8.4.4:8080'; + var DEFAULT_START_DATE = new Date(); + + beforeEach(inject(function($rootScope, _$httpBackend_, _$controller_, _healthService_) { + $httpBackend = _$httpBackend_; + + mockConfigService(); + mockHealthService(); + + $scope = $rootScope.$new(); + $controller = _$controller_; + healthService = _healthService_; + })); + + function mockHealthService() { + var expectedResponse = { + tests: [ + { + failure: 5592, + id: '00187173-ab23-4181-9a15-e291a0d8e2d1', + run_count: 55920, + run_time: 0.608151, + success: 55920, + test_id: 'tempest.api.identity.admin.v2.test_users.one' + }, + { + failure: 0, + id: '001c6860-c966-4c0b-9928-ecccd162bed0', + run_count: 4939, + run_time: 5.97596, + success: 4939, + test_id: 'tempest.api.volume.admin.test_snapshots_actions.two' + }, + { + failure: 1, + id: '002a15e0-f6d1-472a-bd66-bb13ac4d77aa', + run_count: 32292, + run_time: 1.18864, + success: 32291, + test_id: 'tempest.api.network.test_routers.three' + } + ] + }; + + var endpoint = API_ROOT + '/tests?callback=JSON_CALLBACK'; + $httpBackend.expectJSONP(endpoint) + .respond(200, expectedResponse); + } + + function mockConfigService() { + var expectedResponse = { apiRoot: API_ROOT }; + var endpoint = 'config.json'; + $httpBackend.expectGET(endpoint).respond(200, expectedResponse); + } + + it('should process chart data correctly', function() { + var testsDetailController = $controller('TestsDetailController', { + healthService: healthService, + $scope: $scope, + key: 'tempest' + }); + $httpBackend.flush(); + + var expectedChartData = { + 'tempest': [{ + key: 'tempest', + values: [{ + label: 'tempest.api.identity.admin.v2.test_users.one', + value: 0.1 + }], + tests: [{ + failure: 5592, + id: '00187173-ab23-4181-9a15-e291a0d8e2d1', + run_count: 55920, + run_time: 0.608151, + success: 55920, + test_id: 'tempest.api.identity.admin.v2.test_users.one', + failureAverage: 0.1 + }, { + failure: 1, + id: '002a15e0-f6d1-472a-bd66-bb13ac4d77aa', + run_count: 32292, + run_time: 1.18864, + success: 32291, + test_id: 'tempest.api.network.test_routers.three', + failureAverage: 0.0000309674222717701 + }, { + failure: 0, + id: '001c6860-c966-4c0b-9928-ecccd162bed0', + run_count: 4939, + run_time: 5.97596, + success: 4939, + test_id: 'tempest.api.volume.admin.test_snapshots_actions.two', + failureAverage: 0 + }] + }] + }; + expect(testsDetailController.chartData).toEqual(expectedChartData); + }); +}); diff --git a/test/unit/controllers/tests_spec.js b/test/unit/controllers/tests_spec.js index 3988c4c2..ebfdbd23 100644 --- a/test/unit/controllers/tests_spec.js +++ b/test/unit/controllers/tests_spec.js @@ -70,35 +70,8 @@ describe('TestsController', function() { var expectedChartData = { 'tempest': [{ key: 'tempest', - values: [{ - label: 'tempest.api.identity.admin.v2.test_users.one', - value: 0.1 - }], - tests: [{ - failure: 5592, - id: '00187173-ab23-4181-9a15-e291a0d8e2d1', - run_count: 55920, - run_time: 0.608151, - success: 55920, - test_id: 'tempest.api.identity.admin.v2.test_users.one', - failureAverage: 0.1 - }, { - failure: 1, - id: '002a15e0-f6d1-472a-bd66-bb13ac4d77aa', - run_count: 32292, - run_time: 1.18864, - success: 32291, - test_id: 'tempest.api.network.test_routers.three', - failureAverage: 0.0000309674222717701 - }, { - failure: 0, - id: '001c6860-c966-4c0b-9928-ecccd162bed0', - run_count: 4939, - run_time: 5.97596, - success: 4939, - test_id: 'tempest.api.volume.admin.test_snapshots_actions.two', - failureAverage: 0 - }] + values: [], + tests: [] }] }; expect(testsController.chartData).toEqual(expectedChartData);