parent
3f4e854ad6
commit
7ca70709e9
@ -1,46 +0,0 @@ |
||||
//-- copyright
|
||||
// OpenProject is a project management system.
|
||||
// Copyright (C) 2012-2018 the OpenProject Foundation (OPF)
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License version 3.
|
||||
//
|
||||
// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
|
||||
// Copyright (C) 2006-2017 Jean-Philippe Lang
|
||||
// Copyright (C) 2010-2013 the ChiliProject Team
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
//
|
||||
// See docs/COPYRIGHT.rdoc for more details.
|
||||
//++
|
||||
|
||||
import {opUiComponentsModule} from '../../../angular-modules'; |
||||
|
||||
function opDateTimeDirective($compile:ng.ICompileService, TimezoneService:any) { |
||||
return { |
||||
restrict: 'EA', |
||||
scope: { dateTimeValue: '=' }, |
||||
// Note: we cannot reuse op-date here as this does not apply the user's configured timezone
|
||||
template: '<span title="{{ date }} {{ time }}"><span>{{date}}</span> <span>{{time}}</span></span>', |
||||
link: function(scope:any, element:ng.IAugmentedJQuery) { |
||||
var c = TimezoneService.formattedDatetimeComponents(scope.dateTimeValue); |
||||
scope.date = c[0]; |
||||
scope.time = c[1]; |
||||
$compile(element.contents())(scope); |
||||
} |
||||
}; |
||||
} |
||||
|
||||
opUiComponentsModule.directive('opDateTime', opDateTimeDirective); |
@ -1,43 +0,0 @@ |
||||
//-- copyright
|
||||
// OpenProject is a project management system.
|
||||
// Copyright (C) 2012-2015 the OpenProject Foundation (OPF)
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License version 3.
|
||||
//
|
||||
// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
|
||||
// Copyright (C) 2006-2013 Jean-Philippe Lang
|
||||
// Copyright (C) 2010-2013 the ChiliProject Team
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
//
|
||||
// See doc/COPYRIGHT.rdoc for more details.
|
||||
//++
|
||||
|
||||
import {openprojectModule} from '../../../angular-modules'; |
||||
|
||||
describe('URI service', () => { |
||||
var URI:any; |
||||
|
||||
beforeEach(angular.mock.module(openprojectModule.name)); |
||||
beforeEach(angular.mock.inject(function (_URI_:any) { |
||||
URI = _URI_; |
||||
})); |
||||
|
||||
it('should exist', () => { |
||||
expect(URI).to.exist; |
||||
}); |
||||
}); |
||||
|
@ -0,0 +1,164 @@ |
||||
//-- copyright
|
||||
// OpenProject is a project management system.
|
||||
// Copyright (C) 2012-2018 the OpenProject Foundation (OPF)
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License version 3.
|
||||
//
|
||||
// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
|
||||
// Copyright (C) 2006-2017 Jean-Philippe Lang
|
||||
// Copyright (C) 2010-2013 the ChiliProject Team
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
//
|
||||
// See docs/COPYRIGHT.rdoc for more details.
|
||||
//++
|
||||
|
||||
import {Inject, Injectable} from '@angular/core'; |
||||
import {I18nToken} from 'core-app/angular4-transition-utils'; |
||||
import {ConfigurationService} from 'core-components/common/config/configuration.service'; |
||||
import {opServicesModule} from 'core-app/angular-modules'; |
||||
import {downgradeInjectable} from '@angular/upgrade/static'; |
||||
|
||||
@Injectable() |
||||
export class TimezoneService { |
||||
constructor(readonly ConfigurationService:ConfigurationService, |
||||
@Inject(I18nToken) readonly I18n:op.I18n) { |
||||
} |
||||
|
||||
public setupLocale() { |
||||
moment.locale(I18n.locale); |
||||
} |
||||
|
||||
/** |
||||
* Takes a utc date time string and turns it into |
||||
* a local date time moment object. |
||||
*/ |
||||
public parseDatetime(datetime:string, format?:string) { |
||||
var d = moment.utc(datetime, format); |
||||
|
||||
if (this.ConfigurationService.isTimezoneSet()) { |
||||
d.local(); |
||||
d.tz(this.ConfigurationService.timezone()); |
||||
} |
||||
|
||||
return d; |
||||
} |
||||
|
||||
public parseDate(date:string, format?:string) { |
||||
return moment(date, format); |
||||
} |
||||
|
||||
/** |
||||
* Parses a string that is considered to be a local date and |
||||
* turns it into a utc date time moment object. |
||||
* 'Local' might mean the browsers default time zone or the one configured |
||||
* in the Configuration Service. |
||||
* |
||||
* @param {String} date |
||||
* @param {String} format |
||||
* @returns {Moment} |
||||
*/ |
||||
public parseLocalDateTime(date:string, format?:string) { |
||||
var result; |
||||
format = format || this.getTimeFormat(); |
||||
|
||||
if (this.ConfigurationService.isTimezoneSet()) { |
||||
result = moment.tz(date, format!, this.ConfigurationService.timezone()); |
||||
} else { |
||||
result = moment(date, format); |
||||
} |
||||
result.utc(); |
||||
|
||||
return result; |
||||
} |
||||
|
||||
/** |
||||
* Parses the specified datetime and applies the user's configured timezone, if any. |
||||
* |
||||
* This will effectfully transform the [server] provided datetime object to the user's configured local timezone. |
||||
* |
||||
* @param {String} datetime in 'YYYY-MM-DDTHH:mm:ssZ' format |
||||
* @returns {Moment} |
||||
*/ |
||||
public parseISODatetime(datetime:string) { |
||||
return this.parseDatetime(datetime, 'YYYY-MM-DDTHH:mm:ssZ'); |
||||
} |
||||
|
||||
public parseISODate(date:string) { |
||||
return this.parseDate(date, 'YYYY-MM-DD'); |
||||
} |
||||
|
||||
public formattedDate(date:string) { |
||||
var d = this.parseDate(date); |
||||
return d.format(this.getDateFormat()); |
||||
} |
||||
|
||||
public formattedTime(datetimeString:string) { |
||||
return this.parseDatetime(datetimeString).format(this.getTimeFormat()); |
||||
} |
||||
|
||||
public formattedDatetime(datetimeString:string) { |
||||
var c = this.formattedDatetimeComponents(datetimeString); |
||||
return c[0] + ' ' + c[1]; |
||||
} |
||||
|
||||
public formattedDatetimeComponents(datetimeString:string) { |
||||
var d = this.parseDatetime(datetimeString); |
||||
return [ |
||||
d.format(this.getDateFormat()), |
||||
d.format(this.getTimeFormat()) |
||||
]; |
||||
} |
||||
|
||||
public toHours(durationString:string) { |
||||
return Number(moment.duration(durationString).asHours().toFixed(2)); |
||||
} |
||||
|
||||
public formattedDuration(durationString:string) { |
||||
return this.I18n.t('js.units.hour', { count: this.toHours(durationString) }); |
||||
} |
||||
|
||||
public formattedISODate(date:any) { |
||||
return this.parseDate(date).format('YYYY-MM-DD'); |
||||
} |
||||
|
||||
public formattedISODateTime(datetime:any) { |
||||
return datetime.format(); |
||||
} |
||||
|
||||
public isValidISODate(date:any) { |
||||
return this.isValid(date, 'YYYY-MM-DD'); |
||||
} |
||||
|
||||
public isValidISODateTime(dateTime:string) { |
||||
return this.isValid(dateTime, 'YYYY-MM-DDTHH:mm:ssZ'); |
||||
} |
||||
|
||||
public isValid(date:string, dateFormat:string) { |
||||
var format = dateFormat || this.getDateFormat(); |
||||
return moment(date, [format], true).isValid(); |
||||
} |
||||
|
||||
public getDateFormat() { |
||||
return this.ConfigurationService.dateFormatPresent() ? this.ConfigurationService.dateFormat() : 'L'; |
||||
} |
||||
|
||||
public getTimeFormat() { |
||||
return this.ConfigurationService.timeFormatPresent() ? this.ConfigurationService.timeFormat() : 'LT'; |
||||
} |
||||
} |
||||
|
||||
opServicesModule.service('timezoneService', downgradeInjectable(TimezoneService)); |
@ -1,56 +0,0 @@ |
||||
//-- copyright
|
||||
// OpenProject is a project management system.
|
||||
// Copyright (C) 2012-2015 the OpenProject Foundation (OPF)
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License version 3.
|
||||
//
|
||||
// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
|
||||
// Copyright (C) 2006-2013 Jean-Philippe Lang
|
||||
// Copyright (C) 2010-2013 the ChiliProject Team
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
//
|
||||
// See doc/COPYRIGHT.rdoc for more details.
|
||||
//++
|
||||
|
||||
function transformDateUtc(TimezoneService:any):any { |
||||
return { |
||||
restrict: 'A', |
||||
scope: { |
||||
}, |
||||
require: '^ngModel', |
||||
link: function (scope:ng.IScope, element:HTMLElement, attrs:any, ngModelController:any) { |
||||
ngModelController.$parsers.push(function (data:string) { |
||||
if (!TimezoneService.isValidISODate(data)) { |
||||
return ''; |
||||
} |
||||
var d = TimezoneService.parseLocalDateTime(data); |
||||
return TimezoneService.formattedISODateTime(d); |
||||
}); |
||||
ngModelController.$formatters.push(function (data:string) { |
||||
if (!TimezoneService.isValidISODateTime(data)) { |
||||
return ''; |
||||
} |
||||
var d = TimezoneService.parseISODatetime(data); |
||||
return TimezoneService.formattedISODate(d); |
||||
}); |
||||
} |
||||
}; |
||||
} |
||||
|
||||
angular |
||||
.module('openproject') |
||||
.directive('transformDateUtc', transformDateUtc); |
@ -1,64 +0,0 @@ |
||||
//-- copyright
|
||||
// OpenProject is a project management system.
|
||||
// Copyright (C) 2012-2015 the OpenProject Foundation (OPF)
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License version 3.
|
||||
//
|
||||
// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
|
||||
// Copyright (C) 2006-2013 Jean-Philippe Lang
|
||||
// Copyright (C) 2010-2013 the ChiliProject Team
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
//
|
||||
// See doc/COPYRIGHT.rdoc for more details.
|
||||
//++
|
||||
|
||||
function transformDate(TimezoneService:any) { |
||||
return { |
||||
restrict:'A', |
||||
require: '^ngModel', |
||||
link: function( |
||||
scope:ng.IScope, |
||||
element:ng.IAugmentedJQuery, |
||||
attrs:ng.IAttributes, |
||||
ngModelController:any) { |
||||
ngModelController.$parsers.push(function(data:any) { |
||||
if (moment(data, 'YYYY-MM-DD', true).isValid()) { |
||||
return data; |
||||
} else { |
||||
return null; |
||||
} |
||||
}); |
||||
ngModelController.$formatters.push(function(data:any) { |
||||
if (moment(data, 'YYYY-MM-DD', true).isValid()) { |
||||
var d = TimezoneService.parseDate(data); |
||||
return TimezoneService.formattedISODate(d); |
||||
} else { |
||||
return null; |
||||
} |
||||
}); |
||||
} |
||||
}; |
||||
} |
||||
|
||||
// TODO:deprecate and replace by transformDate
|
||||
angular |
||||
.module('openproject') |
||||
.directive('transformDateValue', transformDate); |
||||
|
||||
// angular
|
||||
// .module('openproject')
|
||||
// .directive('transformDate', transformDate);
|
@ -1,56 +0,0 @@ |
||||
//-- copyright
|
||||
// OpenProject is a project management system.
|
||||
// Copyright (C) 2012-2015 the OpenProject Foundation (OPF)
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License version 3.
|
||||
//
|
||||
// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
|
||||
// Copyright (C) 2006-2013 Jean-Philippe Lang
|
||||
// Copyright (C) 2010-2013 the ChiliProject Team
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
//
|
||||
// See doc/COPYRIGHT.rdoc for more details.
|
||||
//++
|
||||
|
||||
import {Duration} from 'moment'; |
||||
|
||||
function transformDuration(TimezoneService:any) { |
||||
return { |
||||
restrict:'A', |
||||
require: 'ngModel', |
||||
link: function( |
||||
scope:ng.IScope, |
||||
element:ng.IAugmentedJQuery, |
||||
attrs:ng.IAttributes, |
||||
ngModelController:any) { |
||||
ngModelController.$parsers.push(function(value:any):Duration|void { |
||||
if (!isNaN(value)) { |
||||
let floatValue = parseFloat(value); |
||||
return moment.duration(floatValue, 'hours'); |
||||
} |
||||
}); |
||||
|
||||
ngModelController.$formatters.push(function(value:any) { |
||||
return TimezoneService.toHours(value); |
||||
}); |
||||
} |
||||
}; |
||||
}; |
||||
|
||||
angular |
||||
.module('openproject') |
||||
.directive('transformDurationValue', transformDuration); |
@ -1,64 +0,0 @@ |
||||
// -- copyright
|
||||
// OpenProject is a project management system.
|
||||
// Copyright (C) 2012-2015 the OpenProject Foundation (OPF)
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License version 3.
|
||||
//
|
||||
// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
|
||||
// Copyright (C) 2006-2013 Jean-Philippe Lang
|
||||
// Copyright (C) 2010-2013 the ChiliProject Team
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
//
|
||||
// See doc/COPYRIGHT.rdoc for more details.
|
||||
// ++
|
||||
|
||||
var expect = chai.expect; |
||||
|
||||
describe('requestForConfirmation directive', () => { |
||||
var scope:any, element:any, controller:any, body:any; |
||||
beforeEach(angular.mock.module('openproject', 'openproject.uiComponents')); |
||||
|
||||
beforeEach(angular.mock.inject(($compile:any, $rootScope:any) => { |
||||
var html = ` |
||||
<form class="request-for-confirmation"> |
||||
<input type="text" id="somevalue" /> |
||||
</form> |
||||
`;
|
||||
|
||||
element = angular.element(html); |
||||
|
||||
scope = $rootScope.$new(); |
||||
body = angular.element(document.body); |
||||
|
||||
$compile(element)(scope); |
||||
body.append(element); |
||||
scope.$digest(); |
||||
|
||||
controller = element.controller('requestForConfirmation'); |
||||
})); |
||||
|
||||
it('should call the dialog when submitting', () => { |
||||
sinon.spy(controller, 'openConfirmationDialog'); |
||||
element.trigger('submit'); |
||||
expect(controller.openConfirmationDialog).to.have.been.called; |
||||
}); |
||||
|
||||
afterEach(() => { |
||||
element.remove(); |
||||
body.remove('.ngdialog-theme-openproject'); |
||||
}); |
||||
}); |
@ -1,137 +0,0 @@ |
||||
// -- copyright
|
||||
// OpenProject is a project management system.
|
||||
// Copyright (C) 2012-2015 the OpenProject Foundation (OPF)
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License version 3.
|
||||
//
|
||||
// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
|
||||
// Copyright (C) 2006-2013 Jean-Philippe Lang
|
||||
// Copyright (C) 2010-2013 the ChiliProject Team
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
//
|
||||
// See doc/COPYRIGHT.rdoc for more details.
|
||||
// ++
|
||||
|
||||
/*jshint expr: true*/ |
||||
|
||||
describe('workPackageCommentDirectiveTest', function() { |
||||
var I18n, wpActivityService, compile, scope, element, stateParams, q, commentCreation; |
||||
var workPackageFieldService = {}; |
||||
var html = "<work-package-comment work-package='workPackage' activities='activities'></work-package-comment>"; |
||||
stateParams = {}; |
||||
|
||||
beforeEach(angular.mock.module('ui.router', |
||||
'openproject', |
||||
'openproject.api', |
||||
'openproject.models', |
||||
'openproject.layout', |
||||
'openproject.services', |
||||
'openproject.uiComponents', |
||||
'openproject.inplace-edit', |
||||
'openproject.workPackages.tabs', |
||||
'openproject.workPackages.directives', |
||||
'openproject.workPackages.models')); |
||||
|
||||
beforeEach(angular.mock.module('openproject.templates', function($provide) { |
||||
var configurationService = { |
||||
commentsSortedInDescendingOrder: function() { return []; } |
||||
}; |
||||
|
||||
$provide.constant('$stateParams', stateParams); |
||||
$provide.constant('ConfigurationService', configurationService); |
||||
})); |
||||
|
||||
beforeEach(angular.mock.module('openproject.services', function($provide) { |
||||
$provide.constant('WorkPackageFieldService', workPackageFieldService); |
||||
$provide.constant('WorkPackageService', {}); |
||||
})); |
||||
|
||||
beforeEach(inject(function($rootScope, $compile, $q, _I18n_, _wpActivityService_) { |
||||
I18n = _I18n_; |
||||
q = $q; |
||||
scope = $rootScope.$new(); |
||||
|
||||
compile = function() { |
||||
workPackageFieldService.isEmpty = sinon.stub().returns(true); |
||||
element = $compile(html)(scope); |
||||
scope.$digest(); |
||||
}; |
||||
|
||||
workPackageFieldService.isEmpty = sinon.stub().returns(true); |
||||
|
||||
wpActivityService = _wpActivityService_; |
||||
var createComments = sinon.stub(wpActivityService, 'createComment'); |
||||
commentCreation = q.defer(); |
||||
createComments.returns(commentCreation.promise); |
||||
|
||||
var stub = sinon.stub(I18n, 't'); |
||||
stub.withArgs('js.label_add_comment_title').returns('trans_title'); |
||||
stub.withArgs('js.label_add_comment').returns('trans_add_comment'); |
||||
stub.withArgs('js.button_cancel').returns('trans_cancel'); |
||||
})); |
||||
|
||||
afterEach(function() { |
||||
I18n.t.restore(); |
||||
wpActivityService.createComment.restore(); |
||||
}); |
||||
|
||||
beforeEach(function() { |
||||
var workPackage = { |
||||
addComment: { |
||||
$link: { |
||||
href: 'addComment' |
||||
} |
||||
}, |
||||
$plain: function() { return {}; } |
||||
}; |
||||
|
||||
scope.workPackage = workPackage; |
||||
}); |
||||
|
||||
|
||||
describe('activity comments', function() { |
||||
describe('without comment link in work package', function() { |
||||
beforeEach(function() { |
||||
scope.workPackage.addComment = undefined; |
||||
compile(); |
||||
}); |
||||
|
||||
it('should not display the comments form', function() { |
||||
expect(element.find('.work-packages--activity--add-comment').length).to.equal(0); |
||||
}); |
||||
}); |
||||
|
||||
describe('with comment link in work package', function() { |
||||
var commentSection, commentField; |
||||
|
||||
beforeEach(function() { |
||||
compile(); |
||||
|
||||
commentSection = element.find('.work-packages--activity--add-comment'); |
||||
}); |
||||
|
||||
it('should display the comments form', function() { |
||||
expect(commentSection.length).to.equal(1); |
||||
}); |
||||
|
||||
it('should display a placeholder in the comments field', function() { |
||||
var readvalue = commentSection.find('.inplace-edit--read-value > span'); |
||||
expect(readvalue.text().trim()).to.equal('trans_title'); |
||||
}); |
||||
}); |
||||
}); |
||||
}); |
@ -1,71 +0,0 @@ |
||||
//-- copyright
|
||||
// OpenProject is a project management system.
|
||||
// Copyright (C) 2012-2018 the OpenProject Foundation (OPF)
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License version 3.
|
||||
//
|
||||
// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
|
||||
// Copyright (C) 2006-2017 Jean-Philippe Lang
|
||||
// Copyright (C) 2010-2013 the ChiliProject Team
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
//
|
||||
// See docs/COPYRIGHT.rdoc for more details.
|
||||
//++
|
||||
|
||||
/*jshint expr: true*/ |
||||
|
||||
describe('WorkPackageService', function() { |
||||
|
||||
var WorkPackageService, |
||||
stateParams = {}; |
||||
beforeEach(angular.mock.module('openproject.api', 'openproject.layout','openproject.services', |
||||
'openproject.models')); |
||||
|
||||
beforeEach(angular.mock.module('openproject.templates', function($provide) { |
||||
var configurationService = {}; |
||||
|
||||
configurationService.isTimezoneSet = sinon.stub().returns(false); |
||||
|
||||
$provide.constant('$stateParams', stateParams); |
||||
$provide.constant('ConfigurationService', configurationService); |
||||
})); |
||||
|
||||
beforeEach(inject(function(_WorkPackageService_){ |
||||
WorkPackageService = _WorkPackageService_; |
||||
})); |
||||
|
||||
describe('performBulkDelete', function() { |
||||
var deleteFunction; |
||||
|
||||
beforeEach(inject(function($http) { |
||||
deleteFunction = sinon.stub($http, 'delete'); |
||||
})); |
||||
|
||||
beforeEach(inject(function($http) { |
||||
var ids = [1,2] |
||||
WorkPackageService.performBulkDelete(ids); |
||||
})); |
||||
|
||||
it('sends a delete request', function() { |
||||
expect(deleteFunction).to.have.been.called; |
||||
}); |
||||
|
||||
it('sends the work package ids to the bulk delete action', function() { |
||||
expect(deleteFunction).to.have.been.calledWith('/work_packages/bulk', { params: { 'ids[]': [1, 2] } }); |
||||
}); |
||||
}); |
||||
}); |
@ -1,130 +0,0 @@ |
||||
//-- copyright
|
||||
// OpenProject is a project management system.
|
||||
// Copyright (C) 2012-2015 the OpenProject Foundation (OPF)
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License version 3.
|
||||
//
|
||||
// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
|
||||
// Copyright (C) 2006-2013 Jean-Philippe Lang
|
||||
// Copyright (C) 2010-2013 the ChiliProject Team
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
//
|
||||
// See doc/COPYRIGHT.rdoc for more details.
|
||||
//++
|
||||
|
||||
import {wpDirectivesModule, opTemplatesModule, opConfigModule} from '../../../angular-modules'; |
||||
import {WorkPackageUploadDirectiveController} from './wp-attachments-upload.directive'; |
||||
import ICompileService = angular.ICompileService; |
||||
import IRootScopeService = angular.IRootScopeService; |
||||
import IAugmentedJQuery = angular.IAugmentedJQuery; |
||||
import IQService = angular.IQService; |
||||
import ICompileProvider = angular.ICompileProvider; |
||||
|
||||
describe('wpAttachmentsUpload directive', () => { |
||||
var $rootScope: IRootScopeService; |
||||
var $q: IQService; |
||||
var html: string; |
||||
var compile: any; |
||||
var element: IAugmentedJQuery; |
||||
var controller: WorkPackageUploadDirectiveController; |
||||
|
||||
var rootElement: IAugmentedJQuery; |
||||
|
||||
var workPackage: any; |
||||
var mockMaxSize: number = 123; |
||||
|
||||
beforeEach(angular.mock.module( |
||||
wpDirectivesModule.name, |
||||
opConfigModule.name, |
||||
opTemplatesModule.name, |
||||
|
||||
($compileProvider: ICompileProvider) => { |
||||
$compileProvider.directive('ngfDrop', () => ({ |
||||
restrict: 'A', |
||||
scope: {ngfChange: '&', ngModel: '='}, |
||||
|
||||
controller: () => angular.noop(), |
||||
controllerAs: '$ctrl', |
||||
bindToController: true |
||||
})); |
||||
})); |
||||
beforeEach(angular.mock.inject(function (_$rootScope_: IRootScopeService, |
||||
_$q_:any, |
||||
$compile: ICompileService, |
||||
ConfigurationService:any) { |
||||
[$rootScope, $q] = _.toArray(arguments); |
||||
|
||||
html = `<wp-attachments-upload attachments="attachments" work-package="workPackage">
|
||||
</wp-attachments-upload>`; |
||||
|
||||
workPackage = { |
||||
canAddAttachments: false, |
||||
attachments: {pending: []} |
||||
}; |
||||
|
||||
const scope: any = $rootScope.$new(); |
||||
scope.workPackage = workPackage; |
||||
|
||||
ConfigurationService.api = () => $q.when({maximumAttachmentFileSize: mockMaxSize}); |
||||
|
||||
compile = () => { |
||||
element = $compile(html)(scope); |
||||
scope.$digest(); |
||||
controller = element.controller('wpAttachmentsUpload'); |
||||
rootElement = element.find('.wp-attachment-upload'); |
||||
}; |
||||
|
||||
compile(); |
||||
})); |
||||
|
||||
it('should not be empty', () => { |
||||
expect(element.html()).to.not.be.empty; |
||||
}); |
||||
|
||||
it('should not be rendered', () => { |
||||
expect(rootElement).to.have.length(0); |
||||
}); |
||||
|
||||
it('should have the provided maxFileSize', () => { |
||||
expect(controller.maxFileSize).to.eq(mockMaxSize); |
||||
}); |
||||
|
||||
describe('when it is possible to add attachments to the work package', () => { |
||||
beforeEach(() => { |
||||
workPackage.canAddAttachments = true; |
||||
compile(); |
||||
}); |
||||
|
||||
it('should display the directive', () => { |
||||
expect(rootElement).to.have.length(1); |
||||
}); |
||||
|
||||
describe('when clicking the parent element', () => { |
||||
var clicked:any; |
||||
|
||||
beforeEach(() => { |
||||
clicked = false; |
||||
rootElement.click(() => clicked = true); |
||||
element.click(); |
||||
}); |
||||
|
||||
it('should click the first child', () => { |
||||
expect(clicked).to.be.true; |
||||
}); |
||||
}); |
||||
}); |
||||
}); |
@ -0,0 +1,171 @@ |
||||
//-- copyright
|
||||
// OpenProject is a project management system.
|
||||
// Copyright (C) 2012-2017 the OpenProject Foundation (OPF)
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License version 3.
|
||||
//
|
||||
// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
|
||||
// Copyright (C) 2006-2017 Jean-Philippe Lang
|
||||
// Copyright (C) 2010-2013 the ChiliProject Team
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
//
|
||||
// See doc/COPYRIGHT.rdoc for more details.
|
||||
//++
|
||||
|
||||
/*jshint expr: true*/ |
||||
|
||||
import {async, ComponentFixture, TestBed} from '@angular/core/testing'; |
||||
import {QueryMenuService} from 'core-components/wp-query-menu/wp-query-menu.service'; |
||||
import {WpQueryMenuDirective} from 'core-components/wp-query-menu/wp-query-menu.directive'; |
||||
import {Component} from '@angular/core'; |
||||
import {WorkPackagesListChecksumService} from 'core-components/wp-list/wp-list-checksum.service'; |
||||
import {TransitionService} from '@uirouter/core'; |
||||
import {$stateToken} from 'core-app/angular4-transition-utils'; |
||||
|
||||
@Component({ |
||||
template: ` |
||||
<div id="main-menu-work-packages-wrapper"> |
||||
<a id="main-menu-work-packages" wp-query-menu>Work packages</a> |
||||
<ul class="menu-children"></ul>' |
||||
</div> |
||||
` |
||||
}) |
||||
class WpQueryMenuTestComponent { } |
||||
|
||||
describe('wp-query-menu directive', () => { |
||||
let app:WpQueryMenuTestComponent; |
||||
let fixture:ComponentFixture<WpQueryMenuTestComponent> |
||||
let element:JQuery; |
||||
let menuContainer:JQuery; |
||||
|
||||
let queryMenuService = new QueryMenuService(); |
||||
let transitionCallback:(id:any) => any; |
||||
|
||||
const $transitionStub = { |
||||
onStart: (criteria:any, callback:(transition:any) => any) => { |
||||
transitionCallback = (id:any) => callback({ |
||||
params: (val:string) => { return { queryId: id }; } |
||||
} as any); |
||||
} |
||||
}; |
||||
|
||||
|
||||
beforeEach(async(() => { |
||||
// noinspection JSIgnoredPromiseFromCall
|
||||
return TestBed.configureTestingModule({ |
||||
declarations: [ |
||||
WpQueryMenuTestComponent, |
||||
WpQueryMenuDirective |
||||
], |
||||
providers: [ |
||||
{ provide: $stateToken, useValue: { go: (...args:any[]) => undefined } }, |
||||
{ provide: WorkPackagesListChecksumService, useValue: { clear: () => undefined } }, |
||||
{ provide: TransitionService, useValue: $transitionStub }, |
||||
{ provide: QueryMenuService, useValue: queryMenuService }, |
||||
] |
||||
}).compileComponents() |
||||
.then(() => { |
||||
fixture = TestBed.createComponent(WpQueryMenuTestComponent); |
||||
app = fixture.debugElement.componentInstance; |
||||
element = jQuery(fixture.elementRef.nativeElement); |
||||
menuContainer = element.find('ul.menu-children'); |
||||
}); |
||||
})); |
||||
|
||||
describe('#add for a query', function() { |
||||
var menuItem:any, itemLink:any; |
||||
var path = '/work_packages?query_id=1', |
||||
title = 'Query', |
||||
objectId = '1'; |
||||
|
||||
var generateMenuItem = function() { |
||||
queryMenuService.add(title, path, objectId); |
||||
fixture.detectChanges(); |
||||
|
||||
menuItem = menuContainer.children('li'); |
||||
itemLink = menuItem.children('a'); |
||||
}; |
||||
|
||||
beforeEach(() => { |
||||
generateMenuItem(); |
||||
}); |
||||
|
||||
it ('adds a query menu item', function() { |
||||
expect(menuItem).to.have.length(1); |
||||
}); |
||||
|
||||
it('assigns the item type as class', function() { |
||||
expect(itemLink.hasClass('query-menu-item')).to.be.true; |
||||
}); |
||||
|
||||
describe('when the query id matches the query id of the state params', function() { |
||||
beforeEach(inject(function() { |
||||
transitionCallback(objectId); |
||||
fixture.detectChanges(); |
||||
})); |
||||
|
||||
it('marks the new item as selected', function() { |
||||
expect(itemLink.hasClass('selected'), 'is selected').to.be.true; |
||||
}); |
||||
|
||||
it('toggles the selected state on state change', function() { |
||||
transitionCallback(null); |
||||
fixture.detectChanges(); |
||||
expect(itemLink.hasClass('selected'), 'is selected').to.be.false; |
||||
}); |
||||
}); |
||||
}); |
||||
|
||||
describe('#generateMenuItem for the work package index item', function() { |
||||
var menuItem:any, itemLink:any; |
||||
var path = '/work_packages', |
||||
title = 'Work Packages', |
||||
objectId:any = undefined; |
||||
|
||||
beforeEach(function() { |
||||
queryMenuService.add(title, path, objectId); |
||||
fixture.detectChanges(); |
||||
|
||||
menuItem = menuContainer.children('li'); |
||||
itemLink = menuItem.children('a'); |
||||
}); |
||||
|
||||
describe('on a work_package page', function() { |
||||
|
||||
describe('for a null query_id', function() { |
||||
beforeEach(inject(function() { |
||||
transitionCallback(null); |
||||
fixture.detectChanges(); |
||||
})); |
||||
|
||||
it('marks the item as selected', function() { |
||||
expect(itemLink.hasClass('selected'), 'is not selected').to.be.false; |
||||
}); |
||||
}); |
||||
describe('for a string query_id', function() { |
||||
beforeEach(inject(function() { |
||||
transitionCallback('1'); |
||||
fixture.detectChanges(); |
||||
})); |
||||
|
||||
it('does not mark the item as selected', function() { |
||||
expect(itemLink.hasClass('selected'), 'is not selected').to.be.false; |
||||
}); |
||||
}); |
||||
}); |
||||
}); |
||||
}); |
@ -1,244 +0,0 @@ |
||||
//-- copyright
|
||||
// OpenProject is a project management system.
|
||||
// Copyright (C) 2012-2017 the OpenProject Foundation (OPF)
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License version 3.
|
||||
//
|
||||
// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
|
||||
// Copyright (C) 2006-2017 Jean-Philippe Lang
|
||||
// Copyright (C) 2010-2013 the ChiliProject Team
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
//
|
||||
// See doc/COPYRIGHT.rdoc for more details.
|
||||
//++
|
||||
|
||||
/*jshint expr: true*/ |
||||
|
||||
|
||||
import {QueryMenuService} from 'core-components/wp-query-menu/wp-query-menu.service'; |
||||
|
||||
describe('queryMenuItemFactory', function() { |
||||
var menuContainer:any, element:any, document:any, |
||||
$rootScope:ng.IRootScopeService, scope:ng.IScope, |
||||
queryMenu:QueryMenuService, state:any = {}, stateParams:any = {}; |
||||
|
||||
beforeEach(angular.mock.module('openproject.layout')); |
||||
beforeEach(angular.mock.module('openproject.templates', |
||||
'openproject.services', |
||||
'openproject.uiComponents', |
||||
'openproject.models', |
||||
'openproject.api', |
||||
function($provide:ng.auto.IProvideService) { |
||||
var configurationService:any = {}; |
||||
|
||||
configurationService.isTimezoneSet = sinon.stub().returns(false); |
||||
|
||||
$provide.constant('ConfigurationService', configurationService); |
||||
})); |
||||
|
||||
beforeEach(angular.mock.module('openproject.templates', function($provide:ng.auto.IProvideService) { |
||||
// Mock check whether we are on a work_packages page
|
||||
state = { includes: function() { return true; } }; |
||||
$provide.value('$state', state); |
||||
|
||||
$provide.value('$stateParams', stateParams); |
||||
})); |
||||
|
||||
beforeEach(inject(function(_$rootScope_:ng.IRootScopeService, |
||||
$compile:ng.ICompileService, |
||||
$document:ng.IDocumentService) { |
||||
$rootScope = _$rootScope_; |
||||
|
||||
// set up html body
|
||||
const template = ` |
||||
<div id="main-menu-work-packages-wrapper"> |
||||
<a id="main-menu-work-packages" wp-query-menu>Work packages</a> |
||||
<ul class="menu-children"></ul>' |
||||
</div> |
||||
`;
|
||||
element = angular.element(template); |
||||
$compile(element)($rootScope); |
||||
|
||||
document = $document[0]; |
||||
var body = angular.element(document.body); |
||||
body.append(element); |
||||
menuContainer = element.find('ul.menu-children'); |
||||
})); |
||||
|
||||
beforeEach(inject(function(_queryMenu_:QueryMenuService) { |
||||
queryMenu = _queryMenu_; |
||||
})); |
||||
|
||||
afterEach(inject(function() { |
||||
// The document does not seem to be cleaned up after each test instead each
|
||||
// test leaves additional DOM. Thus the tests are not independent.
|
||||
// Therefore we clean it by hand.
|
||||
element.remove(); |
||||
})); |
||||
|
||||
describe('#add for a query', function() { |
||||
var menuItem:any, itemLink:any; |
||||
var path = '/work_packages?query_id=1', |
||||
title = 'Query', |
||||
objectId = '1'; |
||||
|
||||
var generateMenuItem = function() { |
||||
queryMenu.add(title, path, objectId); |
||||
|
||||
menuItem = menuContainer.children('li'); |
||||
itemLink = menuItem.children('a'); |
||||
scope = itemLink.scope(); |
||||
}; |
||||
|
||||
beforeEach(generateMenuItem); |
||||
|
||||
it ('adds a query menu item', function() { |
||||
expect(menuItem).to.have.length(1); |
||||
}); |
||||
|
||||
it('assigns the item type as class', function() { |
||||
expect(itemLink.hasClass('query-menu-item')).to.be.true; |
||||
}); |
||||
|
||||
describe('when the query id matches the query id of the state params', function() { |
||||
beforeEach(inject(function() { |
||||
stateParams['query_id'] = objectId; |
||||
$rootScope.$apply(); |
||||
})); |
||||
|
||||
it('marks the new item as selected', function() { |
||||
expect(itemLink.hasClass('selected')).to.be.true; |
||||
}); |
||||
|
||||
it('toggles the selected state on state change', function() { |
||||
stateParams['query_id'] = null; |
||||
$rootScope.$apply(); |
||||
expect(itemLink.hasClass('selected')).to.be.false; |
||||
}); |
||||
}); |
||||
|
||||
describe('when the query id is undefined', function(){ |
||||
beforeEach(inject(function() { |
||||
stateParams['query_id'] = undefined; |
||||
$rootScope.$apply(); |
||||
})); |
||||
|
||||
it('marks the new item as unselected', function() { |
||||
expect(itemLink.hasClass('selected')).to.be.false; |
||||
}); |
||||
|
||||
it('toggles the selected state on state change', function() { |
||||
stateParams['query_id'] = objectId; |
||||
$rootScope.$apply(); |
||||
|
||||
expect(itemLink.hasClass('selected')).to.be.true; |
||||
}); |
||||
}); |
||||
}); |
||||
|
||||
describe('#generateMenuItem for the work package index item', function() { |
||||
var menuItem:any, itemLink:any; |
||||
var path = '/work_packages', |
||||
title = 'Work Packages', |
||||
objectId:any = undefined; |
||||
|
||||
beforeEach(function() { |
||||
queryMenu.add(title, path, objectId); |
||||
$rootScope.$apply(); |
||||
|
||||
menuItem = menuContainer.children('li'); |
||||
itemLink = menuItem.children('a'); |
||||
scope = itemLink.scope(); |
||||
}); |
||||
|
||||
describe('on a work_package page', function() { |
||||
|
||||
describe('for an undefined query_id', function() { |
||||
beforeEach(inject(function() { |
||||
stateParams['query_id'] = undefined; |
||||
$rootScope.$apply(); |
||||
})); |
||||
|
||||
it('marks the item as selected', function() { |
||||
expect(itemLink.hasClass('selected')).to.be.false; |
||||
}); |
||||
}); |
||||
|
||||
describe('for a null query_id', function() { |
||||
beforeEach(inject(function() { |
||||
stateParams['query_id'] = null; |
||||
$rootScope.$apply(); |
||||
})); |
||||
|
||||
it('marks the item as selected', function() { |
||||
expect(itemLink.hasClass('selected')).to.be.false; |
||||
}); |
||||
}); |
||||
|
||||
describe('for an integer query_id', function() { |
||||
beforeEach(inject(function() { |
||||
stateParams['query_id'] = 1; |
||||
$rootScope.$apply(); |
||||
})); |
||||
|
||||
it('does not mark the item as selected', function() { |
||||
expect(itemLink.hasClass('selected')).to.be.false; |
||||
}); |
||||
}); |
||||
|
||||
describe('for a string query_id', function() { |
||||
beforeEach(inject(function() { |
||||
stateParams['query_id'] = "1"; |
||||
$rootScope.$apply(); |
||||
})); |
||||
|
||||
it('does not mark the item as selected', function() { |
||||
expect(itemLink.hasClass('selected')).to.be.false; |
||||
}); |
||||
}); |
||||
}); |
||||
|
||||
describe('on a non-work package page', function() { |
||||
beforeEach(function() { |
||||
// Change mock for checking whether we are on a work_packages page
|
||||
state.includes = function() { return false; }; |
||||
}); |
||||
|
||||
describe('for an undefined query_id', function() { |
||||
beforeEach(inject(function() { |
||||
stateParams['query_id'] = undefined; |
||||
$rootScope.$apply(); |
||||
})); |
||||
|
||||
it('marks the item as selected', function() { |
||||
expect(itemLink.hasClass('selected')).to.be.false; |
||||
}); |
||||
}); |
||||
|
||||
describe('for a null query_id', function() { |
||||
beforeEach(inject(function() { |
||||
stateParams['query_id'] = null; |
||||
$rootScope.$apply(); |
||||
})); |
||||
|
||||
it('marks the item as selected', function() { |
||||
expect(itemLink.hasClass('selected')).to.be.false; |
||||
}); |
||||
}); |
||||
}); |
||||
}); |
||||
}); |
@ -1,157 +0,0 @@ |
||||
//-- copyright
|
||||
// OpenProject is a project management system.
|
||||
// Copyright (C) 2012-2018 the OpenProject Foundation (OPF)
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License version 3.
|
||||
//
|
||||
// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
|
||||
// Copyright (C) 2006-2017 Jean-Philippe Lang
|
||||
// Copyright (C) 2010-2013 the ChiliProject Team
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
//
|
||||
// See docs/COPYRIGHT.rdoc for more details.
|
||||
//++
|
||||
|
||||
module.exports = function(ConfigurationService, I18n) { |
||||
var TimezoneService = { |
||||
|
||||
setupLocale: function() { |
||||
moment.locale(I18n.locale); |
||||
}, |
||||
|
||||
/** |
||||
* Takes a utc date time string and turns it into |
||||
* a local date time moment object. |
||||
*/ |
||||
parseDatetime: function(datetime, format) { |
||||
var d = moment.utc(datetime, format); |
||||
|
||||
if (ConfigurationService.isTimezoneSet()) { |
||||
d.local(); |
||||
d.tz(ConfigurationService.timezone()); |
||||
} |
||||
|
||||
return d; |
||||
}, |
||||
|
||||
parseDate: function(date, format) { |
||||
return moment(date, format); |
||||
}, |
||||
|
||||
/** |
||||
* Parses a string that is considered to be a local date and |
||||
* turns it into a utc date time moment object. |
||||
* 'Local' might mean the browsers default time zone or the one configured |
||||
* in the Configuration Service. |
||||
* |
||||
* @param {String} date |
||||
* @param {String} format |
||||
* @returns {Moment} |
||||
*/ |
||||
parseLocalDateTime: function(date, format) { |
||||
var result; |
||||
|
||||
if (ConfigurationService.isTimezoneSet()) { |
||||
result = moment.tz(date, format, ConfigurationService.timezone()); |
||||
} else { |
||||
result = moment(date, format); |
||||
} |
||||
result.utc(); |
||||
|
||||
return result; |
||||
}, |
||||
|
||||
/** |
||||
* Parses the specified datetime and applies the user's configured timezone, if any. |
||||
* |
||||
* This will effectfully transform the [server] provided datetime object to the user's configured local timezone. |
||||
* |
||||
* @param {String} datetime in 'YYYY-MM-DDTHH:mm:ssZ' format |
||||
* @returns {Moment} |
||||
*/ |
||||
parseISODatetime: function(datetime) { |
||||
return this.parseDatetime(datetime, 'YYYY-MM-DDTHH:mm:ssZ'); |
||||
}, |
||||
|
||||
parseISODate: function(date) { |
||||
return TimezoneService.parseDate(date, 'YYYY-MM-DD'); |
||||
}, |
||||
|
||||
formattedDate: function(date) { |
||||
var d = TimezoneService.parseDate(date); |
||||
return d.format(TimezoneService.getDateFormat()); |
||||
}, |
||||
|
||||
formattedTime: function(datetimeString) { |
||||
return TimezoneService.parseDatetime(datetimeString).format(TimezoneService.getTimeFormat()); |
||||
}, |
||||
|
||||
formattedDatetime: function(datetimeString) { |
||||
var c = TimezoneService.formattedDatetimeComponents(datetimeString); |
||||
return c[0] + ' ' + c[1]; |
||||
}, |
||||
|
||||
formattedDatetimeComponents: function(datetimeString) { |
||||
var d = TimezoneService.parseDatetime(datetimeString); |
||||
return [ |
||||
d.format(TimezoneService.getDateFormat()), |
||||
d.format(TimezoneService.getTimeFormat()) |
||||
]; |
||||
}, |
||||
|
||||
toHours: function(durationString) { |
||||
return Number(moment.duration(durationString).asHours().toFixed(2)); |
||||
}, |
||||
|
||||
formattedDuration: function(durationString) { |
||||
return I18n.t('js.units.hour', { count: TimezoneService.toHours(durationString) }); |
||||
}, |
||||
|
||||
formattedISODate: function(date) { |
||||
return TimezoneService.parseDate(date).format('YYYY-MM-DD'); |
||||
}, |
||||
|
||||
formattedISODateTime: function(datetime) { |
||||
return datetime.format(); |
||||
}, |
||||
|
||||
isValidISODate: function(date) { |
||||
return TimezoneService.isValid(date, 'YYYY-MM-DD'); |
||||
}, |
||||
|
||||
isValidISODateTime: function(dateTime) { |
||||
return TimezoneService.isValid(dateTime, 'YYYY-MM-DDTHH:mm:ssZ'); |
||||
}, |
||||
|
||||
isValid: function(date, dateFormat) { |
||||
var format = dateFormat || (ConfigurationService.dateFormatPresent() ? |
||||
ConfigurationService.dateFormat() : 'L'); |
||||
return moment(date, [format], true).isValid(); |
||||
}, |
||||
|
||||
|
||||
getDateFormat: function() { |
||||
return ConfigurationService.dateFormatPresent() ? ConfigurationService.dateFormat() : 'L'; |
||||
}, |
||||
|
||||
getTimeFormat: function() { |
||||
return ConfigurationService.timeFormatPresent() ? ConfigurationService.timeFormat() : 'LT'; |
||||
} |
||||
}; |
||||
|
||||
return TimezoneService; |
||||
}; |
@ -1,80 +0,0 @@ |
||||
//-- copyright
|
||||
// OpenProject is a project management system.
|
||||
// Copyright (C) 2012-2018 the OpenProject Foundation (OPF)
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License version 3.
|
||||
//
|
||||
// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
|
||||
// Copyright (C) 2006-2017 Jean-Philippe Lang
|
||||
// Copyright (C) 2010-2013 the ChiliProject Team
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
//
|
||||
// See docs/COPYRIGHT.rdoc for more details.
|
||||
//++
|
||||
|
||||
describe('transformDateValue Directive', function() { |
||||
var compile, element, rootScope, scope; |
||||
|
||||
var shouldBehaveLikeAParser = function (value, expected) { |
||||
it('these should parse as expected', function () { |
||||
compile(); |
||||
element.val(value); |
||||
element.trigger('input'); |
||||
expect(scope.dateValue).to.eql(expected); |
||||
}); |
||||
}; |
||||
|
||||
var shouldBehaveLikeAFormatter = function (value, expected) { |
||||
it('should format the value as expected', function () { |
||||
scope.dateValue = value; |
||||
compile(); |
||||
expect(element.val()).to.eql(expected); |
||||
}); |
||||
} |
||||
|
||||
beforeEach(angular.mock.module('openproject')); |
||||
|
||||
beforeEach(inject(function($rootScope, $compile) { |
||||
var html = |
||||
'<input type="text" ng-model="dateValue" transform-date-value/>'; |
||||
|
||||
element = angular.element(html); |
||||
rootScope = $rootScope; |
||||
scope = $rootScope.$new(); |
||||
scope.dateValue = null; |
||||
|
||||
compile = function() { |
||||
$compile(element)(scope); |
||||
scope.$digest(); |
||||
}; |
||||
})); |
||||
|
||||
describe('when given valid date values', function() { |
||||
var dateValue = '2016-12-01'; |
||||
shouldBehaveLikeAParser(dateValue, dateValue); |
||||
shouldBehaveLikeAFormatter(dateValue, dateValue); |
||||
}); |
||||
|
||||
describe('when given invalid date values', function () { |
||||
shouldBehaveLikeAParser('', null); |
||||
shouldBehaveLikeAParser('invalid', null); |
||||
shouldBehaveLikeAParser('2016-12', null); |
||||
shouldBehaveLikeAFormatter(undefined, ''); |
||||
shouldBehaveLikeAFormatter(null, ''); |
||||
shouldBehaveLikeAFormatter('2016-12', ''); |
||||
}); |
||||
}); |
@ -1,128 +0,0 @@ |
||||
//-- copyright
|
||||
// OpenProject is a project management system.
|
||||
// Copyright (C) 2012-2018 the OpenProject Foundation (OPF)
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License version 3.
|
||||
//
|
||||
// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
|
||||
// Copyright (C) 2006-2017 Jean-Philippe Lang
|
||||
// Copyright (C) 2010-2013 the ChiliProject Team
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
//
|
||||
// See docs/COPYRIGHT.rdoc for more details.
|
||||
//++
|
||||
|
||||
describe('transformDateUtc Directive', function() { |
||||
var compile, element, rootScope, scope, ConfigurationService, isTimezoneSetStub, timezoneStub; |
||||
|
||||
var prepare = function () { |
||||
|
||||
angular.mock.module('openproject'); |
||||
|
||||
inject(function($rootScope, $compile, _ConfigurationService_) { |
||||
var html = |
||||
'<input type="text" ng-model="dateValue" transform-date-utc />'; |
||||
|
||||
ConfigurationService = _ConfigurationService_; |
||||
isTimezoneSetStub = sinon.stub(ConfigurationService, 'isTimezoneSet'); |
||||
isTimezoneSetStub.returns(true); |
||||
timezoneStub = sinon.stub(ConfigurationService, 'timezone'); |
||||
|
||||
element = angular.element(html); |
||||
rootScope = $rootScope; |
||||
scope = $rootScope.$new(); |
||||
scope.dateValue = null; |
||||
|
||||
compile = function () { |
||||
$compile(element)(scope); |
||||
scope.$digest(); |
||||
}; |
||||
}); |
||||
}; |
||||
|
||||
var shouldBehaveLikeAParser = function (value, expected) { |
||||
it('these should parse as expected', function () { |
||||
compile(); |
||||
element.val(value); |
||||
element.trigger('input'); |
||||
expect(scope.dateValue).to.eql(expected); |
||||
}); |
||||
}; |
||||
|
||||
var shouldBehaveLikeAFormatter = function (value, expected) { |
||||
it('should format the value as expected', function () { |
||||
scope.dateValue = value; |
||||
compile(); |
||||
expect(element.val()).to.eql(expected); |
||||
}); |
||||
} |
||||
|
||||
var shouldBehaveCorrectlyWhenGivenInvalidDateValues = function () { |
||||
describe('when given invalid date values', function () { |
||||
shouldBehaveLikeAParser(null, null); |
||||
shouldBehaveLikeAParser('invalid', ''); |
||||
shouldBehaveLikeAParser('2016-12', ''); |
||||
shouldBehaveLikeAFormatter('', ''); |
||||
shouldBehaveLikeAFormatter('invalid', ''); |
||||
shouldBehaveLikeAFormatter('2016-12', ''); |
||||
}); |
||||
}; |
||||
|
||||
context('when having UTC configured', function () { |
||||
beforeEach(function () { |
||||
prepare(); |
||||
timezoneStub.returns('UTC'); |
||||
}); |
||||
|
||||
describe('when given valid date values', function() { |
||||
var value = '2016-12-01'; |
||||
var expectedValue = value + 'T00:00:00Z'; |
||||
shouldBehaveLikeAParser(value, expectedValue); |
||||
shouldBehaveLikeAFormatter(expectedValue, value); |
||||
}); |
||||
|
||||
shouldBehaveCorrectlyWhenGivenInvalidDateValues(); |
||||
}); |
||||
|
||||
context('when having GMT+1 zone configured', function () { |
||||
beforeEach(function () { |
||||
prepare(); |
||||
// moment-timezone: GMT+1 is actually GMT-1
|
||||
timezoneStub.returns('Etc/GMT+1'); |
||||
}); |
||||
|
||||
describe('it has the time adjusted', function () { |
||||
var value = '2016-12-03T00:00:00Z'; |
||||
var expectedValue = '2016-12-02'; |
||||
shouldBehaveLikeAFormatter(value, expectedValue); |
||||
}); |
||||
}); |
||||
|
||||
context('when having GMT-1 zone configured', function () { |
||||
beforeEach(function () { |
||||
prepare(); |
||||
// moment-timezone: GMT-1 is actually GMT+1
|
||||
timezoneStub.returns('Etc/GMT-1'); |
||||
}); |
||||
|
||||
describe('it has the time adjusted', function () { |
||||
var value = '2016-12-01'; |
||||
var expectedValue = '2016-11-30T23:00:00Z'; |
||||
shouldBehaveLikeAParser(value, expectedValue); |
||||
}); |
||||
}); |
||||
}); |
Loading…
Reference in new issue