fix updates from socket.io for jobs and resultsets

This commit is contained in:
Cameron Dawson 2014-04-08 09:00:26 -07:00
Родитель 2f7bc79c70
Коммит 2965a31428
13 изменённых файлов: 413 добавлений и 92 удалений

Просмотреть файл

@ -17,6 +17,20 @@
"logViewer": true,
"angular": true,
"_": true,
"Config": true
"Config": true,
//jasmine
"jasmine" : false,
"it" : false,
"xit" : false,
"describe" : false,
"xdescribe" : false,
"beforeEach" : false,
"afterEach" : false,
"expect" : false,
"module" : false,
"inject" : false,
"getJSONFixture" : false,
"spyOn" : false
}
}

Просмотреть файл

@ -12,9 +12,11 @@ module.exports = function (config) {
'app/vendor/jquery.ui.effect.js',
'app/vendor/jquery.ui.effect-highlight.js',
'app/vendor/bootstrap*.js',
'app/js/app.js',
'app/js/**/*.js',
'app/js/controllers/**/*.js',
'app/js/services/**/*.js',
'app/js/models/**/*.js',
'app/plugins/**/*.js',
'test/vendor/angular/angular-mocks.js',
'test/vendor/jasmine-jquery.js',

Просмотреть файл

@ -0,0 +1,86 @@
// Karma configuration
// Generated on Mon Apr 07 2014 17:41:06 GMT-0700 (PDT)
module.exports = function(config) {
config.set({
// base path that will be used to resolve all patterns (eg. files, exclude)
basePath: '..',
// frameworks to use
// available frameworks: https://npmjs.org/browse/keyword/karma-adapter
frameworks: ['jasmine'],
// list of files / patterns to load in the browser
files: [
'app/vendor/angular/angular.js',
'app/vendor/angular/angular-*.js',
'app/vendor/ui-bootstrap-*.js',
'app/vendor/jquery-*.js',
'app/vendor/jquery.ui.effect.js',
'app/vendor/jquery.ui.effect-highlight.js',
'app/vendor/bootstrap*.js',
'app/js/app.js',
'app/js/**/*.js',
'app/js/controllers/**/*.js',
'app/js/services/**/*.js',
'app/js/models/**/*.js',
'app/plugins/**/*.js',
'test/vendor/angular/angular-mocks.js',
'test/vendor/jasmine-jquery.js',
'test/unit/**/*.js',
'app/vendor/*.js',
// fixtures
{pattern: 'test/mock/*.json', watched: true, served: true, included: false}
],
// list of files to exclude
exclude: [
],
// preprocess matching files before serving them to the browser
// available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
preprocessors: {
'app/js/**/*.js': ['coverage']
},
// test results reporter to use
// possible values: 'dots', 'progress'
// available reporters: https://npmjs.org/browse/keyword/karma-reporter
reporters: ['progress', 'coverage'],
// web server port
port: 9876,
// enable / disable colors in the output (reporters and logs)
colors: true,
// level of logging
// possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
logLevel: config.LOG_INFO,
// enable / disable watching file and executing tests whenever any file changes
autoWatch: false,
// start these browsers
// available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
browsers: ['Firefox'],
// Continuous Integration mode
// if true, Karma captures browsers, runs the tests and exits
singleRun: true
});
};

Просмотреть файл

@ -3,64 +3,75 @@
/* jasmine specs for controllers go here */
describe('JobsCtrl', function(){
var $httpBackend, createJobsCtrl, createResultSetCtrl, jobScope, resultsetScope;
var $httpBackend, createResultSetCtrl, jobScope, resultsetScope;
var a = "foo";
beforeEach(module('treeherder'));
beforeEach(inject(function ($injector, $rootScope, $controller, thUrl) {
$httpBackend = $injector.get('$httpBackend');
jasmine.getJSONFixtures().fixturesPath='base/test/mock';
$httpBackend.whenGET('http://local.treeherder.mozilla.org/api/repository/').respond(
getJSONFixture('repositories.json')
);
$httpBackend.whenGET('http://local.treeherder.mozilla.org/api/project/mozilla-inbound/resultset/?count=10&format=json&full=false').respond(
getJSONFixture('resultset_list.json')
);
$httpBackend.whenGET('http://local.treeherder.mozilla.org/api/project/mozilla-inbound/jobs/1235/').respond(
getJSONFixture('job_1235.json')
);
$httpBackend.whenGET('http://local.treeherder.mozilla.org/api/project/mozilla-inbound/artifact/403/').respond(
getJSONFixture('artifact_403.json')
);
$httpBackend.whenGET('http://local.treeherder.mozilla.org/api/project/mozilla-inbound/artifact/403').respond(
getJSONFixture('artifact_403.json')
);
$httpBackend.whenGET('http://local.treeherder.mozilla.org/api/project/mozilla-inbound/note?job_id=1235').respond(
getJSONFixture('notes_job_1235.json')
);
$httpBackend.whenGET('http://local.treeherder.mozilla.org/api/project/mozilla-inbound/note/?job_id=1235').respond(
getJSONFixture('notes_job_1235.json')
);
$httpBackend.whenGET('resources/job_groups.json').respond(
getJSONFixture('job_groups.json')
);
jobScope = $rootScope.$new();
//setting attributes derived from the parent controller
jobScope.mru_repos = [];
$rootScope.new_failures = [];
$controller('JobsCtrl', {'$scope': jobScope});
resultsetScope = jobScope.$new();
createResultSetCtrl = function(resultset) {
resultsetScope.resultset = resultset;
var ctrl = $controller('ResultSetCtrl', {'$scope': resultsetScope});
return ctrl;
};
$httpBackend.flush();
beforeEach(inject(function (
// $injector,
// $rootScope,
// $controller
) {
var projectPrefix = 'http://local.treeherder.mozilla.org/api/project/mozilla-inbound/';
//
// $httpBackend = $injector.get('$httpBackend');
// jasmine.getJSONFixtures().fixturesPath='base/test/mock';
//
// $httpBackend.whenGET('http://local.treeherder.mozilla.org/api/repository/').respond(
// getJSONFixture('repositories.json')
// );
//
// $httpBackend.whenGET(projectPrefix + 'resultset/?count=10&format=json&full=false').respond(
// getJSONFixture('resultset_list.json')
// );
//
// $httpBackend.whenGET(projectPrefix + 'jobs/1235/').respond(
// getJSONFixture('job_1235.json')
// );
//
// $httpBackend.whenGET(projectPrefix + 'artifact/403/').respond(
// getJSONFixture('artifact_403.json')
// );
//
// $httpBackend.whenGET(projectPrefix + 'artifact/403').respond(
// getJSONFixture('artifact_403.json')
// );
//
// $httpBackend.whenGET(projectPrefix + 'note?job_id=1235').respond(
// getJSONFixture('notes_job_1235.json')
// );
//
// $httpBackend.whenGET(projectPrefix + 'note/?job_id=1235').respond(
// getJSONFixture('notes_job_1235.json')
// );
//
// $httpBackend.whenGET('resources/job_groups.json').respond(
// getJSONFixture('job_groups.json')
// );
//
// a = "foo";
//
// jobScope = $rootScope.$new();
//
// //setting attributes derived from the parent controller
// jobScope.mru_repos = [];
// $rootScope.new_failures = [];
//
// $controller('JobsCtrl', {'$scope': jobScope});
//
// resultsetScope = jobScope.$new();
// createResultSetCtrl = function(resultset) {
// resultsetScope.resultset = resultset;
// return $controller('ResultSetCtrl', {'$scope': resultsetScope});
// };
// $httpBackend.flush();
}));
it('should be foo', function() {
expect(a).toEqual("foo");
});
/*
Tests JobsCtrl
*/

Просмотреть файл

@ -0,0 +1,164 @@
'use strict';
describe('ThResultSetModel', function(){
var $httpBackend,
rootScope,
model;
beforeEach(module('treeherder'));
beforeEach(inject(function ($injector, $rootScope, $controller, ThResultSetModel) {
$httpBackend = $injector.get('$httpBackend');
jasmine.getJSONFixtures().fixturesPath='base/test/mock';
$httpBackend.whenGET('http://local.treeherder.mozilla.org/api/project/mozilla-inbound/resultset/?count=10&format=json&full=false').respond(
getResultSets()
);
$httpBackend.whenGET('http://local.treeherder.mozilla.org/api/project/mozilla-inbound/jobs/1235/').respond(
getJSONFixture('job_1235.json')
);
rootScope = $rootScope.$new();
model = new ThResultSetModel();
model.fetchResultSets("foo", 1);
// $httpBackend.flush();
}));
/*
Tests ThResultSetModel
*/
it('should have 1 resultset', function() {
expect(model.getResultSetsArray().length).toBe(1);
});
/**
* Test that events for new jobs gets those job updates on the current repo
*/
it('should add new the current repo', function() {
// expect(jobScope.result_sets.length).toBe(10);
});
/**
* Test that events for new jobs gets those job updates on a cached repo (not current)
*/
it('should add new to a cached repo', function() {
// expect(jobScope.result_sets.length).toBe(10);
});
var getResultSets = function() {
return [
{
"repository_id": 4,
"job_counts": {
"exception": 0,
"retry": 0,
"success": 2,
"unknown": 0,
"usercancel": 0,
"running": 0,
"busted": 0,
"testfailed": 0,
"total": 4,
"pending": 0
},
"revision_hash": "05c298c5ae3bcc37fd00397511646135bf2416f6",
"revision_count": 2,
"author": "Brian Grinstead <test@mozilla.com>",
"platforms": [
{
"name": "linux64",
"groups": [
{
"symbol": "?",
"jobs": [
{
"machine_name": "bld-centos6-hp-031",
"job_group_symbol": "?",
"job_type_name": "Build",
"job_group_name": "unknown",
"platform_option": "debug",
"reason": "scheduler",
"failure_classification_id": 1,
"job_type_symbol": "B",
"platform": "linux64",
"state": "pending",
"result_set_id": 4939,
"result": "unknown",
"job_coalesced_to_guid": null,
"id": 590604,
"resource_uri": "/api/project/try/jobs/590604/"
},
{
"machine_name": "try-linux64-spot-129",
"job_group_symbol": "?",
"job_type_name": "Static Checking Build",
"job_group_name": "unknown",
"platform_option": "debug",
"reason": "scheduler",
"failure_classification_id": 1,
"job_type_symbol": "S",
"platform": "linux64",
"state": "completed",
"result_set_id": 4939,
"result": "success",
"job_coalesced_to_guid": null,
"id": 590599,
"resource_uri": "/api/project/try/jobs/590599/"
}
],
"name": "unknown"
}
],
"option": "debug"
}
],
"revisions_uri": "/api/project/try/resultset/4939/revisions/",
"push_timestamp": 1396899074,
"id": 4939,
"revision": "793611be6b26"
}
];
};
var getNewJobs = function() {
return [
{
"submit_timestamp": 1396899126,
"machine_name": "bld-centos6-hp-031",
"job_group_symbol": "?",
"job_group_name": "unknown",
"platform_option": "debug",
"job_type_description": "fill me",
"result_set_id": 4939,
"result": "success",
"id": 590604,
"machine_platform_architecture": "x86_64",
"end_timestamp": 1396901922,
"build_platform": "linux64",
"job_guid": "1cb281fce9b62d27423dfbe31d50a9744f4fc0d6",
"job_type_name": "Build",
"platform": "linux64",
"state": "completed",
"build_os": "linux",
"option_collection_hash": "32faaecac742100f7753f0c1d0aa0add01b4046b",
"who": "bgrinstead@mozilla.com",
"failure_classification_id": 1,
"job_type_symbol": "B",
"reason": "scheduler",
"job_group_description": "fill me",
"job_coalesced_to_guid": null,
"machine_platform_os": "linux",
"start_timestamp": 1396899181,
"build_architecture": "x86_64",
"build_platform_id": 10,
"machine_id": 346,
"resource_uri": "/api/project/try/jobs/590604/"
}
];
};
});

Просмотреть файл

@ -15,8 +15,7 @@ treeherder.config(function($routeProvider, $httpProvider, $logProvider) {
// comment out the next line to enable them
$logProvider.debugEnabled(false);
// needed to avoid CORS issue when getting the logs from the ftp site
// @@@ hack for now to get it to work in the short-term
// avoid CORS issue when getting the logs from the ftp site
$httpProvider.defaults.useXDomain = true;
delete $httpProvider.defaults.headers.common['X-Requested-With'];

Просмотреть файл

@ -82,7 +82,7 @@ treeherder.controller('MainCtrl',
* The watched repos in the nav bar can be either on the left or the
* right side of the screen and the drop-down menu may get cut off
* if it pulls right while on the left side of the screen.
* And it can change any time the user re-sized the window, so we must
* And it can change any time the user re-sizes the window, so we must
* check this each time a drop-down is invoked.
*/
$scope.setDropDownPull = function(event) {
@ -103,6 +103,7 @@ treeherder.controller('MainCtrl',
$rootScope.urlBasePath = $location.absUrl().split('?')[0];
$scope.isRepoPanelShowing = false;
$scope.changeRepo = function(repo_name) {
// hide the repo panel if they chose to load one.
$scope.isRepoPanelShowing = false;

Просмотреть файл

@ -4,14 +4,14 @@ treeherder.factory('ThJobModel', function($http, ThLog, thUrl) {
// ThJobModel is the js counterpart of job
var ThJobModel = function(data) {
// creates a new instance of ThJobArtifactModel
// creates a new instance of ThJobModel
// using the provided properties
angular.extend(this, data);
};
ThJobModel.get_uri = function(){return thUrl.getProjectUrl("/jobs/");};
ThJobModel.get_uri = function(repoName){return thUrl.getProjectUrl("/jobs/", repoName);};
ThJobModel.get_list = function(options) {
ThJobModel.get_list = function(repoName, options) {
// a static method to retrieve a list of ThJobModel
var query_string = $.param(options);
return $http.get(ThJobModel.get_uri()+"?"+query_string)
@ -24,9 +24,9 @@ treeherder.factory('ThJobModel', function($http, ThLog, thUrl) {
});
};
ThJobModel.get = function(pk) {
ThJobModel.get = function(repoName, pk) {
// a static method to retrieve a single instance of ThJobModel
return $http.get(ThJobModel.get_uri()+pk+"/").then(function(response) {
return $http.get(ThJobModel.get_uri(repoName)+pk+"/").then(function(response) {
return new ThJobModel(response.data);
});
};

Просмотреть файл

@ -1,10 +1,9 @@
'use strict';
treeherder.factory('ThResultSetModel',
['$rootScope', 'thResultSets', 'thSocket',
'ThJobModel', 'thEvents', 'thAggregateIds', 'ThLog',
function($rootScope, thResultSets, thSocket,
ThJobModel, thEvents, thAggregateIds, ThLog) {
function($rootScope, $location, thResultSets, thSocket,
ThJobModel, thEvents, thAggregateIds, ThLog,
thNotify) {
var $log = new ThLog("ThResultSetModel");
@ -28,8 +27,16 @@ treeherder.factory('ThResultSetModel',
var addRepository = function(repoName){
//Initialize a new repository in the repositories structure
var locationSearch = _.clone($location.search());
$log.debug("locationSearch", locationSearch);
if(_.isEmpty(repositories[repoName]) ||
!_.isEqual(locationSearch, repositories[repoName].search)){
$log.debug(
"fetching new resultset list with parameters:",
locationSearch
);
if(_.isEmpty(repositories[repoName])){
repositories[repoName] = {
name:repoName,
@ -54,7 +61,8 @@ treeherder.factory('ThResultSetModel',
loadingStatus: {
appending: false,
prepending: false
}
},
search: locationSearch
};
// Add a connect listener
@ -327,7 +335,7 @@ treeherder.factory('ThResultSetModel',
* in the data model.
*/
var fetchJobs = function(repoName, jobFetchList) {
ThJobModel.get_list({
ThJobModel.get_list(repoName, {
id__in: jobFetchList.join()
}).then(
_.bind(updateJobs, $rootScope, repoName),
@ -568,8 +576,13 @@ treeherder.factory('ThResultSetModel',
*/
if(resultsetList.length > 0){
repositories[repoName].loadingStatus.prepending = true;
thResultSets.getResultSets(0, resultsetList.length, resultsetList).
success( _.bind(prependResultSets, $rootScope, repoName) );
thResultSets.getResultSets(repoName, 0, resultsetList.length, resultsetList).
success( _.bind(prependResultSets, $rootScope, repoName) ).
error(function(data) {
thNotify.send("Error retrieving job data!", "danger", true);
$log.error(data);
prependResultSets(repoName, []);
});
}
};
@ -580,9 +593,15 @@ treeherder.factory('ThResultSetModel',
*/
repositories[repoName].loadingStatus.appending = true;
thResultSets.getResultSets(
repositories[repoName].rsOffsetId, count
).success( _.bind(appendResultSets, $rootScope, repoName) );
repoName,
repositories[repoName].rsOffsetId,
count).
success( _.bind(appendResultSets, $rootScope, repoName)).
error(function(data) {
thNotify.send("Error retrieving job data!", "danger", true);
$log.error(data);
appendResultSets(repoName, []);
});
};
//Public interface
@ -616,4 +635,4 @@ treeherder.factory('ThResultSetModel',
return api;
}]);
});

Просмотреть файл

@ -1,14 +1,17 @@
'use strict';
/* Services */
treeherder.factory('thUrl',['$rootScope', 'thServiceDomain', 'ThLog', function($rootScope, thServiceDomain, ThLog) {
treeherder.factory('thUrl', function($rootScope, thServiceDomain, ThLog) {
var thUrl = {
getRootUrl: function(uri) {
return thServiceDomain + "/api" + uri;
},
getProjectUrl: function(uri) {
return thServiceDomain + "/api/project/" + $rootScope.repoName + uri;
getProjectUrl: function(uri, repoName) {
if (_.isUndefined(repoName)) {
repoName = $rootScope.repoName;
}
return thServiceDomain + "/api/project/" + repoName + uri;
},
getLogViewerUrl: function(job_id) {
return "logviewer.html#?job_id=" + job_id + "&repo=" + $rootScope.repoName;
@ -20,7 +23,7 @@ treeherder.factory('thUrl',['$rootScope', 'thServiceDomain', 'ThLog', function($
};
return thUrl;
}]);
});
treeherder.factory('thSocket', function ($rootScope, ThLog, thUrl) {
var $log = new ThLog("thSocket");

Просмотреть файл

@ -1,11 +1,13 @@
'use strict';
treeherder.factory('thResultSets',
function($http, $location, thUrl, thServiceDomain) {
function($http, $location, thUrl, thServiceDomain, ThLog) {
var $log = new ThLog("thResultSets");
// get the resultsets for this repo
return {
getResultSets: function(rsOffsetId, count, resultsetlist) {
getResultSets: function(repoName, rsOffsetId, count, resultsetlist) {
rsOffsetId = typeof rsOffsetId === 'undefined'? 0: rsOffsetId;
count = typeof count === 'undefined'? 10: count;
var params = {
@ -15,15 +17,33 @@ treeherder.factory('thResultSets',
};
if(rsOffsetId > 0){
params['id__lt'] = rsOffsetId;
params.id__lt = rsOffsetId;
}
// if there are any search params on the url line, they should
// pass directly to the set of resultsets.
// with the exception of ``repo``. That has no effect on the
// service at this time, but it could be confusing.
var locationParams = $location.search();
var locationParams = _.clone($location.search());
delete locationParams.repo;
// support date ranges. we must convert the strings to a timezone
// appropriate timestamp
$log.debug("locationParams", locationParams);
if (_.has(locationParams, "startdate")) {
params.push_timestamp__gte = Date.parse(
locationParams.startdate)/1000;
delete locationParams.startdate;
}
if (_.has(locationParams, "enddate")) {
params.push_timestamp__lt = Date.parse(
locationParams.enddate)/1000 + 84600;
delete locationParams.enddate;
}
$log.debug("updated params", params);
_.extend(params, locationParams);
if (resultsetlist) {
@ -33,7 +53,7 @@ treeherder.factory('thResultSets',
id__in: resultsetlist.join()
});
}
return $http.get(thUrl.getProjectUrl("/resultset/"),
return $http.get(thUrl.getProjectUrl("/resultset/", repoName),
{params: params}
);
},

Просмотреть файл

@ -31,6 +31,8 @@
<a href="https://secure.pub.build.mozilla.org/clobberer/?branch={{name}}" target="_blank">clobberer</a>
</li>
<li class="divider"></li>
<li class="watched-repo-dropdown-item">
<a href="" ng-click="unwatchRepo(name)">unwatch</a>
</li>

Просмотреть файл

@ -2,12 +2,12 @@
"name": "treeherder-ui",
"description": "The UI portion of Mozilla Treeherder",
"devDependencies": {
"phantomjs" : ">=1.9.7",
"karma" : ">=0.12.0",
"karma-cli" : ">=0.0.4",
"karma-junit-reporter" : ">=0.2.1",
"karma-coverage" : ">=0.2.0",
"karma-jasmine" : ">=0.1.5",
"karma-ng-scenario" : ">=0.1.0"
}
"phantomjs": ">=1.9.7",
"karma": ">=0.12.0",
"karma-cli": "0.0.4",
"karma-junit-reporter": ">=0.2.1",
"karma-coverage": ">=0.2.0",
"karma-jasmine": ">=0.1.5",
"karma-ng-scenario": ">=0.1.0"
}
}