diff --git a/src/calendar/_index.js b/src/calendar/_index.js
deleted file mode 100644
index 8b95b6f..0000000
--- a/src/calendar/_index.js
+++ /dev/null
@@ -1,8 +0,0 @@
-import angular from 'angular';
-import Component from './component';
-import Modal from './modal';
-
-export default angular.module('qtAngularUi.calendar', [])
-.directive('calendar', Component)
-.directive('calendarModal', Modal)
-.name;
diff --git a/src/calendar/calendar.spec.js b/src/calendar/calendar.spec.js
new file mode 100644
index 0000000..3f780c0
--- /dev/null
+++ b/src/calendar/calendar.spec.js
@@ -0,0 +1,447 @@
+/* eslint max-nested-callbacks: off */
+/* eslint-env mocha */
+/* global expect */
+
+import _ from 'lodash';
+import moment from 'moment';
+import angular from 'angular';
+import 'angular-mocks';
+
+import $ from 'jquery';
+import Calendar from './index';
+
+/**
+ * $('a').click()无效的解决方法
+ * @param {element} el
+ * clickElement($('a')[0]);
+ */
+let clickElement = function (el) {
+ let ev = document.createEvent('MouseEvent');
+ ev.initMouseEvent('click', true, true, window, null, 0, 0, 0, 0, false, false, false, false, 0, null);
+ el.dispatchEvent(ev);
+};
+
+describe('calendar 组件', function () {
+ const { module, inject } = angular.mock;
+ const template = '';
+ const templateDisabled = '';
+
+ beforeEach(function () {
+ // 初始化 Calendar 组件
+ module(Calendar);
+
+ // 清场
+ document.body.innerHTML = '';
+ });
+
+ describe('结构规范', function () {
+ it('会返回组件名称', function () {
+ expect(Calendar).to.be.a('string');
+ });
+
+ it('能进行初始化', function () {
+ inject(function ($rootScope, $compile) {
+ let $element = $compile(template)($rootScope.$new());
+ let $modalScope = $element.children().scope();
+ let $scope = {};
+ let elems = $element.find('div');
+
+ angular.forEach(elems, function (e) {
+ let elem = angular.element(e);
+ if (elem.hasClass('calendar')) {
+ $scope = elem.children().scope();
+ }
+ });
+
+ expect($modalScope.isOpen).to.be.false;
+ expect($scope.selected).to.be.an('array');
+ });
+ });
+
+ it('应该拥有额定的结构', function () {
+ inject(function ($rootScope, $compile) {
+ let $element = $compile(template)($rootScope.$new());
+ let $modalScope = $element.children().scope();
+
+ let watchIsOpen = _.find($modalScope.$$watchers, { exp: 'isOpen' });
+
+ expect($modalScope.isOpen).to.be.a('boolean');
+ expect(watchIsOpen.exp).to.be.a('string');
+
+ let $scope = {};
+ let elems = $element.find('div');
+
+ angular.forEach(elems, function (e) {
+ let elem = angular.element(e);
+
+ if (elem.hasClass('calendar')) {
+ $scope = elem.children().scope();
+ }
+ });
+
+ expect($scope.selected).to.be.an('array');
+ expect($scope.month).to.be.an('object');
+ expect($scope.select).to.be.a('function');
+ expect($scope.isSelected).to.be.a('function');
+ expect($scope.focus).to.be.a('function');
+ expect($scope.next).to.be.a('function');
+ expect($scope.previous).to.be.a('function');
+ });
+ });
+ });
+
+ describe('触发流程', function () {
+ it('能够打开和关闭', function () {
+ inject(function ($rootScope, $compile, $timeout) {
+ let $newScope = $rootScope.$new();
+ $newScope.isOpenCalendar = false;
+ let $element = $compile(template)($newScope);
+ let $elementScope = $element.scope();
+ let $scope = $element.children().scope();
+
+ angular.element(document.body).append($element);
+
+ expect($scope.isOpen).to.be.false;
+ expect(angular.element(document.body).hasClass('calendar-modal-open')).to.be.false;
+
+ // 打开
+ $elementScope.isOpenCalendar = true;
+
+ $elementScope.$digest();
+ expect($scope.isOpen).to.be.true;
+ expect(angular.element(document.body).hasClass('calendar-modal-open')).to.be.true;
+ expect($element.hasClass('in')).to.be.false;
+ expect($element.hasClass('hide')).to.be.false;
+
+ $timeout.flush();
+ expect($element.hasClass('in')).to.be.true;
+
+ // 关闭
+ // $('.calendar-backdrop').click();
+ clickElement($('.calendar-modal>a.button')[0]);
+ $('.calendar-modal>a.button').click();
+
+ expect($elementScope.isOpenCalendar).to.be.false;
+ expect($scope.isOpen).to.be.false;
+ expect(angular.element(document.body).hasClass('calendar-modal-open')).to.be.false;
+ expect($element.hasClass('in')).to.be.false;
+ expect($element.hasClass('hide')).to.be.false;
+
+ $timeout.flush();
+ expect($element.hasClass('hide')).to.be.true;
+ });
+ });
+
+ it('能够初始化激活的日期', function () {
+ inject(function ($rootScope, $compile) {
+ let $newScope = $rootScope.$new();
+ $newScope.schooltimes = [new Date('2017-02-02')];
+ let $element = $compile(template)($newScope);
+
+ angular.element(document.body).append($element);
+
+ let $scope = angular.element($('.calendar')[0].childNodes[0]).scope();
+
+ expect($scope.selected).to.equal($newScope.schooltimes);
+ });
+ });
+
+ it('能够初始化第一个月', function () {
+ inject(function ($rootScope, $compile) {
+ let $element = $compile(template)($rootScope.$new());
+
+ angular.element(document.body).append($element);
+
+ let $scope = angular.element($('.calendar')[0].childNodes[0]).scope();
+ let month = moment();
+ let date = month.clone();
+
+ date
+ .date(1)
+ .day(0)
+ .hour(0)
+ .minute(0)
+ .second(0)
+ .millisecond(0);
+
+ for (let i = 0; 5 > i; i ++) {
+ for (let j = 0; 7 > j; j ++) {
+ expect($scope.weeks[i].days[j].name).to.equal(date.format('dd').substring(0, 1));
+ expect($scope.weeks[i].days[j].number).to.equal(date.date());
+ expect($scope.weeks[i].days[j].isCurrentMonth).to.equal(date.month() === month.month());
+ expect($scope.weeks[i].days[j].isToday).to.equal(date.isSame(new Date(), 'day'));
+ expect($scope.weeks[i].days[j].date.format()).to.equal(date.format());
+
+ date = date.clone();
+ date.add(1, 'd');
+ }
+ }
+ });
+ });
+
+ it('能够选择日期', function () {
+ inject(function ($rootScope, $compile) {
+ let $newScope = $rootScope.$new();
+ $newScope.schooltimes = [moment(new Date()).format('YYYY-MM-DD')];
+ let $element = $compile(template)($newScope);
+
+ angular.element(document.body).append($element);
+
+ let $scope = angular.element($('.calendar')[0].childNodes[0]).scope();
+ $scope.$digest();
+
+ let $days = $('div.day');
+
+ for (let i = 0; $days.length > i; i ++) {
+ let $dayScope = angular.element($days[i].childNodes[0]).scope();
+ let date = $dayScope.day.date.format('YYYY-MM-DD');
+ let index = $scope.selected.indexOf(date);
+
+ if ($scope.isSelected($dayScope.day)) {
+ expect(index).to.not.equal(-1);
+
+ $days.eq(i).click();
+ index = $scope.selected.indexOf(date);
+ expect(index).to.equal(-1);
+ }
+ else {
+ expect(index).to.equal(-1);
+
+ $days.eq(i).click();
+ index = $scope.selected.indexOf(date);
+ expect(index).to.not.equal(-1);
+ }
+ }
+ });
+ });
+
+ it('禁止选择日期', function () {
+ inject(function ($rootScope, $compile) {
+ let $newScope = $rootScope.$new();
+ $newScope.schooltimes = [moment(new Date()).format('YYYY-MM-DD')];
+ let $element = $compile(templateDisabled)($newScope);
+
+ angular.element(document.body).append($element);
+
+ let $scope = angular.element($('.calendar')[0].childNodes[0]).scope();
+ $scope.$digest();
+
+ let $days = $('div.day');
+
+ for (let i = 0; $days.length > i; i ++) {
+ let $dayScope = angular.element($days[i].childNodes[0]).scope();
+ let date = $dayScope.day.date.format('YYYY-MM-DD');
+ let index = $scope.selected.indexOf(date);
+
+ if ($scope.isSelected($dayScope.day)) {
+ expect(index).to.not.equal(-1);
+
+ $days.eq(i).click();
+ index = $scope.selected.indexOf(date);
+ expect(index).to.not.equal(-1);
+ }
+ else {
+ expect(index).to.equal(-1);
+
+ $days.eq(i).click();
+ index = $scope.selected.indexOf(date);
+ expect(index).to.equal(-1);
+ }
+ }
+ });
+ });
+
+ it('能够跳转到某年', function () {
+ inject(function ($rootScope, $compile) {
+ let $element = $compile(template)($rootScope.$new());
+
+ angular.element(document.body).append($element);
+
+ let $scope = angular.element($('.calendar')[0].childNodes[0]).scope();
+ let year = 2008;
+ let month = $scope.month.clone();
+
+ $scope.redirectYear(year);
+ month.date(1).year(year);
+ let date = month.clone();
+
+ date
+ .date(1)
+ .day(0)
+ .hour(0)
+ .minute(0)
+ .second(0)
+ .millisecond(0);
+
+ for (let i = 0; 5 > i; i ++) {
+ for (let j = 0; 7 > j; j ++) {
+ expect($scope.weeks[i].days[j].name).to.equal(date.format('dd').substring(0, 1));
+ expect($scope.weeks[i].days[j].number).to.equal(date.date());
+ expect($scope.weeks[i].days[j].isCurrentMonth).to.equal(date.month() === month.month());
+ expect($scope.weeks[i].days[j].isToday).to.equal(date.isSame(new Date(), 'day'));
+ expect($scope.weeks[i].days[j].date.format()).to.equal(date.format());
+
+ date = date.clone();
+ date.add(1, 'd');
+ }
+ }
+ });
+ });
+
+ it('能够跳转到某月份', function () {
+ inject(function ($rootScope, $compile) {
+ let $newScope = $rootScope.$new();
+ $newScope.schooltimes = [new Date('2017-02-02')];
+ let $element = $compile(template)($newScope);
+
+ angular.element(document.body).append($element);
+
+ let $scope = angular.element($('.calendar')[0].childNodes[0]).scope();
+ let month = $scope.month.clone();
+
+ $scope.redirectMonth(5);
+ month.date(1).month(5);
+
+ let date = month.clone();
+
+ date
+ .date(1)
+ .day(0)
+ .hour(0)
+ .minute(0)
+ .second(0)
+ .millisecond(0);
+
+ for (let i = 0; 5 > i; i ++) {
+ for (let j = 0; 7 > j; j ++) {
+ expect($scope.weeks[i].days[j].name).to.equal(date.format('dd').substring(0, 1));
+ expect($scope.weeks[i].days[j].number).to.equal(date.date());
+ expect($scope.weeks[i].days[j].isCurrentMonth).to.equal(date.month() === month.month());
+ expect($scope.weeks[i].days[j].isToday).to.equal(date.isSame(new Date(), 'day'));
+ expect($scope.weeks[i].days[j].date.format()).to.equal(date.format());
+
+ date = date.clone();
+ date.add(1, 'd');
+ }
+ }
+ });
+ });
+
+ it('能够跳转到指定日期', function () {
+ inject(function ($rootScope, $compile) {
+ let $newScope = $rootScope.$new();
+ $newScope.schooltimes = [new Date('2017-02-02')];
+ let $element = $compile(template)($newScope);
+
+ angular.element(document.body).append($element);
+
+ let $scope = angular.element($('.calendar')[0].childNodes[0]).scope();
+ let month = moment('2008-01-02');
+ let date = month.clone();
+
+ expect($scope.focus('sdfa.,.9**-/,.-')).to.be.false;
+
+ $scope.focus('2008-01-02');
+
+ date
+ .date(1)
+ .day(0)
+ .hour(0)
+ .minute(0)
+ .second(0)
+ .millisecond(0);
+
+ for (let i = 0; 5 > i; i ++) {
+ for (let j = 0; 7 > j; j ++) {
+ expect($scope.weeks[i].days[j].name).to.equal(date.format('dd').substring(0, 1));
+ expect($scope.weeks[i].days[j].number).to.equal(date.date());
+ expect($scope.weeks[i].days[j].isCurrentMonth).to.equal(date.month() === month.month());
+ expect($scope.weeks[i].days[j].isToday).to.equal(date.isSame(new Date(), 'day'));
+ expect($scope.weeks[i].days[j].date.format()).to.equal(date.format());
+
+ date = date.clone();
+ date.add(1, 'd');
+ }
+ }
+ });
+ });
+
+ it('能够跳转下个月', function () {
+ inject(function ($rootScope, $compile) {
+ let $newScope = $rootScope.$new();
+ $newScope.schooltimes = [new Date('2017-02-02')];
+ let $element = $compile(template)($newScope);
+
+ angular.element(document.body).append($element);
+
+ let $scope = angular.element($('.calendar')[0].childNodes[0]).scope();
+ let month = $scope.month.clone();
+
+ $scope.next();
+ month.add(1, 'M');
+
+ let date = month.clone();
+
+ date
+ .date(1)
+ .day(0)
+ .hour(0)
+ .minute(0)
+ .second(0)
+ .millisecond(0);
+
+ for (let i = 0; 5 > i; i ++) {
+ for (let j = 0; 7 > j; j ++) {
+ expect($scope.weeks[i].days[j].name).to.equal(date.format('dd').substring(0, 1));
+ expect($scope.weeks[i].days[j].number).to.equal(date.date());
+ expect($scope.weeks[i].days[j].isCurrentMonth).to.equal(date.month() === month.month());
+ expect($scope.weeks[i].days[j].isToday).to.equal(date.isSame(new Date(), 'day'));
+ expect($scope.weeks[i].days[j].date.format()).to.equal(date.format());
+
+ date = date.clone();
+ date.add(1, 'd');
+ }
+ }
+ });
+ });
+
+ it('能够跳转上个月', function () {
+ inject(function ($rootScope, $compile) {
+ let $newScope = $rootScope.$new();
+ $newScope.schooltimes = [new Date('2017-02-02')];
+ let $element = $compile(template)($newScope);
+
+ angular.element(document.body).append($element);
+
+ let $scope = angular.element($('.calendar')[0].childNodes[0]).scope();
+ let month = $scope.month.clone();
+
+ $scope.previous();
+ month.subtract(1, 'M');
+
+ let date = month.clone();
+
+ date
+ .date(1)
+ .day(0)
+ .hour(0)
+ .minute(0)
+ .second(0)
+ .millisecond(0);
+
+ for (let i = 0; 5 > i; i ++) {
+ for (let j = 0; 7 > j; j ++) {
+ expect($scope.weeks[i].days[j].name).to.equal(date.format('dd').substring(0, 1));
+ expect($scope.weeks[i].days[j].number).to.equal(date.date());
+ expect($scope.weeks[i].days[j].isCurrentMonth).to.equal(date.month() === month.month());
+ expect($scope.weeks[i].days[j].isToday).to.equal(date.isSame(new Date(), 'day'));
+ expect($scope.weeks[i].days[j].date.format()).to.equal(date.format());
+
+ date = date.clone();
+ date.add(1, 'd');
+ }
+ }
+ });
+ });
+ });
+});
diff --git a/src/calendar/component.js b/src/calendar/component.js
index 8ea664e..b7128c0 100644
--- a/src/calendar/component.js
+++ b/src/calendar/component.js
@@ -17,11 +17,7 @@ export default function () {
$scope.selected = _.isArray($scope.selected) ? $scope.selected : [];
$scope.month = $scope.selected[0] ? moment($scope.selected[0]) : moment();
- let start = $scope.month.clone();
- start.date(1);
-
- _removeTime(start.day(0));
- _buildMonth($scope, start, $scope.month);
+ _buildMonth($scope, $scope.month);
$scope.select = function (day) {
if (isDisabled) {
@@ -41,30 +37,49 @@ export default function () {
return -1 !== $scope.selected.indexOf(date);
};
- $scope.focus = function (next) {
- _buildMonth($scope, next, $scope.month);
+ $scope.redirectYear = function (number) {
+ $scope.month
+ .date(1)
+ .year(number);
+
+ _buildMonth($scope, $scope.month);
};
- $scope.next = function () {
- let next = $scope.month.clone();
- _removeTime(next.month(next.month() + 1).date(1));
+ $scope.redirectMonth = function (number) {
+ $scope.month
+ .date(1)
+ .month(number);
- $scope.month.month($scope.month.month() + 1);
- _buildMonth($scope, next, $scope.month);
+ _buildMonth($scope, $scope.month);
};
- $scope.previous = function () {
- let previous = $scope.month.clone();
- _removeTime(previous.month(previous.month() - 1).date(1));
+ $scope.focus = function (date) {
+ let month = moment(date);
+
+ if (!month.isValid()) {
+ return false;
+ }
+
+ $scope.month = month.clone();
- $scope.month.month($scope.month.month() - 1);
- _buildMonth($scope, previous, $scope.month);
+ _buildMonth($scope, $scope.month);
+ };
+
+ $scope.next = function () {
+ $scope.month.add(1, 'M');
+ _buildMonth($scope, $scope.month);
+ };
+
+ $scope.previous = function () {
+ $scope.month.subtract(1, 'M');
+ _buildMonth($scope, $scope.month);
};
}
};
- function _removeTime (date) {
+ function _startTime (date) {
return date
+ .date(1)
.day(0)
.hour(0)
.minute(0)
@@ -72,11 +87,11 @@ export default function () {
.millisecond(0);
}
- function _buildMonth ($scope, start, month) {
+ function _buildMonth ($scope, month) {
$scope.weeks = [];
let done = false;
- let date = start.clone();
+ let date = _startTime(month.clone());
let monthIndex = date.month();
let count = 0;
diff --git a/src/calendar/index.js b/src/calendar/index.js
index 8e1104a..e9c1613 100644
--- a/src/calendar/index.js
+++ b/src/calendar/index.js
@@ -1,9 +1,10 @@
-if (window.angular && window.angular.env && window.angular.env.QT_UI_LOG) {
- window.console.log('qt-angular-ui/src/calendar load');
-}
-
import './index.scss';
-import component from './_index';
+import angular from 'angular';
+import Component from './component';
+import Modal from './modal';
-export default component;
\ No newline at end of file
+export default angular.module('qtAngularUi.calendar', [])
+.directive('calendar', Component)
+.directive('calendarModal', Modal)
+.name;