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