From fef4c5ca9e351754cc4aba8bc4d0b44949e3f588 Mon Sep 17 00:00:00 2001 From: "zhenhui.lin" <315713565@163.com> Date: Wed, 19 Apr 2017 16:09:36 +0800 Subject: [PATCH] =?UTF-8?q?calendar=E7=BB=84=E4=BB=B6=E8=87=AA=E5=8A=A8?= =?UTF-8?q?=E5=8C=96=E6=B5=8B=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/calendar/_index.js | 8 - src/calendar/calendar.spec.js | 447 ++++++++++++++++++++++++++++++++++ src/calendar/component.js | 55 +++-- src/calendar/index.js | 13 +- 4 files changed, 489 insertions(+), 34 deletions(-) delete mode 100644 src/calendar/_index.js create mode 100644 src/calendar/calendar.spec.js 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;