diff --git a/app/js/services/projects.js b/app/js/services/projects.js new file mode 100644 index 00000000..4252c690 --- /dev/null +++ b/app/js/services/projects.js @@ -0,0 +1,60 @@ +'use strict'; + +var angular = require('angular'); +var servicesModule = require('./_index.js'); + +/** + * @ngInject + */ +var projectService = function(projectFactory, metricsService) { + var service = {}; + + var findOrCreate = function(index, storage, key, createFunction) { + var obj = index[key] || createFunction(key); + if (!index[key]) { + index[key] = obj; + storage.push(obj); + } + return obj; + }; + + var byDate = function(stats1, stats2) { + return stats1.date - stats2.date; + }; + + var createDateStats = function(date) { + return { date: date, metrics: metricsService.getNewMetrics() }; + }; + + service.createProjects = function(runsJson) { + var projects = []; + var index = {}; + + angular.forEach(runsJson, function(projectsJson, dateString) { + angular.forEach(projectsJson, function(runEntries, name) { + var project = findOrCreate(index, projects, name, projectFactory.create); + project.addRuns(dateString, runEntries); + }); + }); + + return projects; + }; + + service.getStatsByDate = function(projects) { + var index = {}; + var dateStats = []; + + angular.forEach(projects, function(project) { + angular.forEach(project.runs, function(run) { + var stats = findOrCreate(index, dateStats, run.date, createDateStats); + stats.metrics = metricsService.addMetrics(stats.metrics, run.metrics); + }); + }); + + return dateStats.sort(byDate); + }; + + return service; +}; + +servicesModule.service('projectService', projectService); diff --git a/test/unit/services/projects_spec.js b/test/unit/services/projects_spec.js new file mode 100644 index 00000000..74437319 --- /dev/null +++ b/test/unit/services/projects_spec.js @@ -0,0 +1,84 @@ +describe('ProjectService', function() { + var projectService; + + beforeEach(function() { + module('app.services'); + + var mockProjectFactory = { + create: function(name) { + return {addRuns: function() {}}; + } + }; + var mockMetricsService = { + getFailRate: function() { return 0.5; }, + getNewMetrics: function() { return {}; }, + addMetrics: function() { return 'updated'; } + }; + + module(function($provide) { + $provide.value('projectFactory', mockProjectFactory); + $provide.value('metricsService', mockMetricsService); + }); + + inject(function($injector) { + projectService = $injector.get('projectService'); + }); + }); + + it('should create projects from runs per datetime', function() { + var runs = { + '2015-10-10T20:00:00': { + 'openstack/heat': [{ fail: 1, pass: 0, skip: 0 }], + 'openstack/keystone': [{ fail: 0, pass: 1, skip: 0 }], + 'openstack/tempest': [{ fail: 0, pass: 0, skip: 1 }] + } + }; + + var projects = projectService.createProjects(runs); + + expect(projects.length).toEqual(3); + }); + + it('should update projects from different datetimes', function() { + var runs = { + '2015-10-10t20:00:00': { + 'openstack/tempest': [{ fail: 0, pass: 0, skip: 1 }] + }, + '2015-11-11t20:00:00': { + 'openstack/heat': [{ fail: 1, pass: 0, skip: 0 }], + 'openstack/tempest': [{ fail: 0, pass: 0, skip: 1 }] + } + }; + + var projects = projectService.createProjects(runs); + + expect(projects.length).toEqual(2); + }); + + it('should aggregate project stats by date', function() { + var generateProject = function(name, date, passes, failures, skips) { + return { + name: name, + runs: [{ date: date, passes: passes, failures: failures, skips: skips }] + }; + }; + var date1 = new Date('2015-10-10T20:00:00'); + var date2 = new Date('2015-11-11T20:00:00'); + var projects = [ + generateProject('p1', date1, 1, 2, 3), + generateProject('p2', date1, 4, 5, 6), + generateProject('p3', date2, 7, 8, 9), + generateProject('p4', date2, 0, 1, 2) + ]; + + var stats = projectService.getStatsByDate(projects); + + expect(stats.length).toEqual(2); + + expect(stats[0].date).toEqual(date1); + expect(stats[0].metrics).toEqual('updated'); + + expect(stats[1].date).toEqual(date2); + expect(stats[1].metrics).toEqual('updated'); + }); +});