From 4f0737fe7dba14f81fc17affd82edc2f96a5d112 Mon Sep 17 00:00:00 2001 From: Adam Shaw Date: Fri, 22 Aug 2014 18:31:21 -0700 Subject: [PATCH] tests for all things eventLimit related --- tests/automated/dayPopoverFormat.js | 43 +++++ tests/automated/eventLimit-popover.js | 212 ++++++++++++++++++++++++ tests/automated/eventLimit.js | 223 ++++++++++++++++++++++++++ tests/automated/eventLimitClick.js | 135 ++++++++++++++++ tests/automated/eventLimitText.js | 48 ++++++ tests/lib/jasmine-ext.js | 38 +++++ 6 files changed, 699 insertions(+) create mode 100644 tests/automated/dayPopoverFormat.js create mode 100644 tests/automated/eventLimit-popover.js create mode 100644 tests/automated/eventLimit.js create mode 100644 tests/automated/eventLimitClick.js create mode 100644 tests/automated/eventLimitText.js diff --git a/tests/automated/dayPopoverFormat.js b/tests/automated/dayPopoverFormat.js new file mode 100644 index 0000000..dfefac5 --- /dev/null +++ b/tests/automated/dayPopoverFormat.js @@ -0,0 +1,43 @@ + +describe('dayPopoverFormat', function() { + + var options; + + beforeEach(function() { + affix('#cal'); + options = { + defaultDate: '2014-08-01', + eventLimit: 3, + events: [ + { title: 'event1', start: '2014-07-28', end: '2014-07-30', className: 'event1' }, + { title: 'event2', start: '2014-07-29', end: '2014-07-31', className: 'event2' }, + { title: 'event3', start: '2014-07-29', className: 'event3' }, + { title: 'event4', start: '2014-07-29', className: 'event4' } + ] + }; + }); + + function init() { + $('#cal').fullCalendar(options); + $('.fc-more').simulate('click'); + } + + it('can be set to a custom value', function() { + options.dayPopoverFormat = 'ddd, MMMM'; + init(); + expect($('.fc-more-popover > .fc-header .fc-title')).toHaveText('Tue, July'); + }); + + it('is affected by the current locale when the value is default', function() { + options.lang = 'fr'; + init(); + expect($('.fc-more-popover > .fc-header .fc-title')).toHaveText('29 juillet 2014'); + }); + + it('still maintains the same format when explicitly set, and there is a lang', function() { + options.lang = 'fr'; + options.dayPopoverFormat = 'YYYY'; + init(); + expect($('.fc-more-popover > .fc-header .fc-title')).toHaveText('2014'); + }); +}); diff --git a/tests/automated/eventLimit-popover.js b/tests/automated/eventLimit-popover.js new file mode 100644 index 0000000..dd99670 --- /dev/null +++ b/tests/automated/eventLimit-popover.js @@ -0,0 +1,212 @@ + +describe('eventLimit popover', function() { + + var options; + + beforeEach(function() { + affix('#cal'); + options = { + defaultView: 'month', + defaultDate: '2014-08-01', + eventLimit: 3, + events: [ + { title: 'event1', start: '2014-07-28', end: '2014-07-30', className: 'event1' }, + { title: 'event2', start: '2014-07-29', end: '2014-07-31', className: 'event2' }, + { title: 'event3', start: '2014-07-29', className: 'event3' }, + { title: 'event4', start: '2014-07-29', className: 'event4' } + ] + } + }); + + function init() { + $('#cal').fullCalendar(options); + $('.fc-more').simulate('click'); + } + + [ 'month', 'basicWeek', 'agendaWeek' ].forEach(function(viewName) { + + describe('when in ' + viewName + ' view', function() { + + beforeEach(function() { + options.defaultView = viewName; + }); + + it('aligns horizontally with left edge of cell if LTR', function() { + options.isRTL = false; + init(); + var cellLeft = $('.fc-day-grid .fc-row:eq(0) .fc-bg td:not(.fc-axis):eq(2)').offset().left; + var popoverLeft = $('.fc-more-popover').offset().left; + var diff = Math.abs(cellLeft - popoverLeft); + expect(diff).toBeLessThan(2); + }); + + it('aligns horizontally with left edge of cell if RTL', function() { + options.isRTL = true; + init(); + var cell = $('.fc-day-grid .fc-row:eq(0) .fc-bg td:not(.fc-axis):eq(4)'); + var cellRight = cell.offset().left + cell.outerWidth(); + var popover = $('.fc-more-popover'); + var popoverRight = popover.offset().left + popover.outerWidth(); + var diff = Math.abs(cellRight - popoverRight); + expect(diff).toBeLessThan(2); + }); + }); + }); + + describe('when in month view', function() { + + beforeEach(function() { + options.defaultView = 'month'; + }); + + it('aligns with top of cell', function() { + init(); + var popoverTop = $('.fc-more-popover').offset().top; + var rowTop = $('.fc-day-grid .fc-row:eq(0)').offset().top; + var diff = Math.abs(popoverTop - rowTop); + expect(diff).toBeLessThan(2); + }); + }); + + [ 'basicWeek', 'agendaWeek' ].forEach(function(viewName) { + + describe('when in ' + viewName + ' view', function() { + + beforeEach(function() { + options.defaultView = viewName; + }); + + it('aligns with top of header', function() { + init(); + var popoverTop = $('.fc-more-popover').offset().top; + var headTop = $('.fc-view > table > thead .fc-row').offset().top; + var diff = Math.abs(popoverTop - headTop); + expect(diff).toBeLessThan(2); + }); + }); + }); + + // TODO: somehow test how the popover does to the edge of any scroll container + + it('closes when user clicks the X', function() { + init(); + expect($('.fc-more-popover')).toBeVisible(); + $('.fc-more-popover .fc-close').simulate('click'); + expect($('.fc-more-popover')).not.toBeVisible(); + }); + + it('doesn\'t close when user clicks somewhere inside of the popover', function() { + init(); + expect($('.fc-more-popover')).toBeVisible(); + expect($('.fc-more-popover .fc-header')).toBeInDOM(); + $('.fc-more-popover .fc-header').simulate('mousedown').simulate('click'); + expect($('.fc-more-popover')).toBeVisible(); + }); + + it('closes when user clicks outside of the popover', function() { + init(); + expect($('.fc-more-popover')).toBeVisible(); + $('body').simulate('mousedown').simulate('click'); + expect($('.fc-more-popover')).not.toBeVisible(); + }); + + it('has the correct event contents', function() { + init(); + expect($('.fc-more-popover .event1')).toBeMatchedBy('.fc-not-start.fc-end'); + expect($('.fc-more-popover .event2')).toBeMatchedBy('.fc-start.fc-not-end'); + expect($('.fc-more-popover .event3')).toBeMatchedBy('.fc-start.fc-end'); + expect($('.fc-more-popover .event4')).toBeMatchedBy('.fc-start.fc-end'); + }); + + + describe('when dragging events out', function() { + + beforeEach(function() { + options.editable = true; + }); + + describe('when dragging an all-day event to a different day', function() { + + it('should have the new day and remain all-day', function(done) { + + options.eventDrop = function(event) { + expect(event.start).toEqualMoment('2014-07-28'); + expect(event.allDay).toBe(true); + done(); + }; + init(); + + setTimeout(function() { // simulate was getting confused about which thing was being clicked :( + $('.fc-more-popover .event4').simulate('drag-n-drop', { + dragTarget: $('.fc-day-grid .fc-row:eq(0) .fc-bg td:not(.fc-axis):eq(1)') // one day before + }); + }, 0); + }); + }); + + describe('when dragging a timed event to a whole day', function() { + + it('should move to new day but maintain its time', function(done) { + + options.events.push({ // add timed event + title: 'event5', + start: '2014-07-29T13:00:00', + className: 'event5' + }); + options.eventDrop = function(event) { + expect(event.start).toEqualMoment('2014-07-28T13:00:00'); + expect(event.allDay).toBe(false); + done(); + }; + init(); + + setTimeout(function() { // simulate was getting confused about which thing was being clicked :( + $('.fc-more-popover .event5').simulate('drag-n-drop', { + dragTarget: $('.fc-day-grid .fc-row:eq(0) .fc-bg td:not(.fc-axis):eq(1)') // one day before + }); + }, 0); + }); + }); + + describe('when dragging a whole day event to a timed slot', function() { + + it('should assume the new time, with a cleared end', function(done) { + + options.defaultView = 'agendaWeek'; + options.scrollTime = '00:00:00'; + options.eventDrop = function(event) { + expect(event.start).toEqualMoment('2014-07-30T03:00:00'); + expect(event.allDay).toBe(false); + done(); + }; + init(); + + setTimeout(function() { // simulate was getting confused about which thing was being clicked :( + $('.fc-more-popover .event4').simulate('drag-n-drop', { + dragTarget: $('.fc-slats tr:eq(6)') // the middle will be 7/30, 3:00am + }); + }, 0); + }); + }); + + describe('when a single-day event isn\'t dragged out all the way', function() { + + it('shouldn\'t do anything', function(done) { + + options.eventDragStop = function() { + setTimeout(function() { // try to wait until drag is over. eventDrop won't fire BTW + expect($('.fc-more-popover')).toBeInDOM(); + done(); + },0); + }; + init(); + + $('.fc-more-popover .event4').simulate('drag-n-drop', { + dx: 20 + }); + }); + }); + + }); + +}); diff --git a/tests/automated/eventLimit.js b/tests/automated/eventLimit.js new file mode 100644 index 0000000..470b0c1 --- /dev/null +++ b/tests/automated/eventLimit.js @@ -0,0 +1,223 @@ + +describe('eventLimit', function() { + + var options; + + beforeEach(function() { + affix('#cal'); + options = { + defaultDate: '2014-08-01' // important that it is the first week, so works w/ month + week views + }; + }); + + describe('as a number', function() { + + beforeEach(function() { + options.eventLimit = 3; + }); + + [ 'month', 'basicWeek', 'agendaWeek' ].forEach(function(viewName) { + + describe('when in ' + viewName + ' view', function() { + + beforeEach(function() { + options.defaultView = viewName; + }); + + it('doesn\'t display a more link when limit is more than the # of events', function() { + options.events = [ + { title: 'event1', start: '2014-07-29' }, + { title: 'event2', start: '2014-07-29' } + ]; + $('#cal').fullCalendar(options); + expect($('.fc-more').length).toBe(0); + }); + + it('doesn\'t display a more link when limit equal to the # of events', function() { + options.events = [ + { title: 'event1', start: '2014-07-29' }, + { title: 'event2', start: '2014-07-29' }, + { title: 'event2', start: '2014-07-29' } + ]; + $('#cal').fullCalendar(options); + expect($('.fc-more').length).toBe(0); + }); + + it('displays a more link when limit is less than the # of events', function() { + options.events = [ + { title: 'event1', start: '2014-07-29' }, + { title: 'event2', start: '2014-07-29' }, + { title: 'event2', start: '2014-07-29' }, + { title: 'event2', start: '2014-07-29' } + ]; + $('#cal').fullCalendar(options); + expect($('.fc-more').length).toBe(1); + expect($('.fc-more')).toHaveText('+2 more'); + }); + + it('displays one more per day, when a multi-day event is above', function() { + options.events = [ + { title: 'event1', start: '2014-07-29', end: '2014-07-31' }, + { title: 'event2', start: '2014-07-29', end: '2014-07-31' }, + { title: 'event2', start: '2014-07-29', end: '2014-07-31' }, + { title: 'event2', start: '2014-07-29', end: '2014-07-31' } + ]; + $('#cal').fullCalendar(options); + var cells = $('.fc-day-grid .fc-row:eq(0) .fc-bg td:not(.fc-axis)'); + expect($('.fc-more').length).toBe(2); + expect($('.fc-more').eq(0)).toHaveText('+2 more'); + expect($('.fc-more').eq(0)).toBeBoundedBy(cells.eq(2)); + expect($('.fc-more').eq(1)).toHaveText('+2 more'); + expect($('.fc-more').eq(1)).toBeBoundedBy(cells.eq(3)); + }); + + it('will render a link in a multi-day event\'s second column ' + + 'if it has already been hidden in the first', + function() { + options.events = [ + { title: 'event1', start: '2014-07-29', end: '2014-07-31' }, + { title: 'event2', start: '2014-07-29', end: '2014-07-31' }, + { title: 'event2', start: '2014-07-29', end: '2014-07-31' }, + { title: 'event2', start: '2014-07-29' } + ]; + $('#cal').fullCalendar(options); + var cells = $('.fc-day-grid .fc-row:eq(0) .fc-bg td:not(.fc-axis)'); + expect($('.fc-more').length).toBe(2); + expect($('.fc-more').eq(0)).toHaveText('+2 more'); + expect($('.fc-more').eq(0)).toBeBoundedBy(cells.eq(2)); + expect($('.fc-more').eq(1)).toHaveText('+1 more'); + expect($('.fc-more').eq(1)).toBeBoundedBy(cells.eq(3)); + }); + + it('will render a link in a multi-day event\'s second column ' + + 'if it has already been hidden in the first even if he second column hardly has any events', + function() { + options.events = [ + { title: 'event1', start: '2014-07-28', end: '2014-07-30' }, + { title: 'event2', start: '2014-07-28', end: '2014-07-30' }, + { title: 'event2', start: '2014-07-28', end: '2014-07-30' }, + { title: 'event2', start: '2014-07-29', end: '2014-07-31' } + ]; + $('#cal').fullCalendar(options); + var cells = $('.fc-day-grid .fc-row:eq(0) .fc-bg td:not(.fc-axis)'); + var link = $('.fc-more').eq(0); // will appear to be the third link, but will be in first row, so 0dom + expect(link.length).toBe(1); + expect(link).toHaveText('+1 more'); + expect(link).toBeBoundedBy(cells.eq(3)); + }); + + it('will render a link in place of a hidden single day event, if covered by a multi-day', function() { + options.events = [ + { title: 'event1', start: '2014-07-28', end: '2014-07-30' }, + { title: 'event2', start: '2014-07-28', end: '2014-07-30' }, + { title: 'event2', start: '2014-07-28' }, + { title: 'event2', start: '2014-07-28' } + ]; + $('#cal').fullCalendar(options); + var cells = $('.fc-day-grid .fc-row:eq(0) .fc-bg td:not(.fc-axis)'); + var link = $('.fc-more').eq(0); + expect(link.length).toBe(1); + expect(link).toHaveText('+2 more'); + expect(link).toBeBoundedBy(cells.eq(1)); + }); + + it('will render a link in place of a hidden single day event, if covered by a multi-day ' + + 'and in its second column', + function() { + options.events = [ + { title: 'event1', start: '2014-07-28', end: '2014-07-30' }, + { title: 'event2', start: '2014-07-28', end: '2014-07-30' }, + { title: 'event2', start: '2014-07-29' }, + { title: 'event2', start: '2014-07-29' } + ]; + $('#cal').fullCalendar(options); + var cells = $('.fc-day-grid .fc-row:eq(0) .fc-bg td:not(.fc-axis)'); + var link = $('.fc-more').eq(0); + expect(link.length).toBe(1); + expect(link).toHaveText('+2 more'); + expect(link).toBeBoundedBy(cells.eq(2)); + }); + }); + }); + }); + + describe('when auto', function() { + + beforeEach(function() { + options.eventLimit = true; + }); + + describe('in month view', function() { + + beforeEach(function() { + options.defaultView = 'month'; + }); + + it('renders the heights of all the rows the same, regardless of # of events', function() { + options.events = [ + { title: 'event1', start: '2014-07-28', end: '2014-07-30' }, + { title: 'event2', start: '2014-07-28', end: '2014-07-30' }, + { title: 'event2', start: '2014-07-29' }, + { title: 'event2', start: '2014-07-29' }, + { title: 'event2', start: '2014-07-29' }, + { title: 'event2', start: '2014-07-29' }, + { title: 'event2', start: '2014-07-29' }, + { title: 'event2', start: '2014-07-29' }, + { title: 'event2', start: '2014-07-29' }, + { title: 'event2', start: '2014-07-29' }, + { title: 'event2', start: '2014-07-29' }, + { title: 'event2', start: '2014-07-29' }, + { title: 'event2', start: '2014-07-29' } + ]; + $('#cal').fullCalendar(options); + var rowEls = $('.fc-day-grid .fc-row').slice(0, -1); // remove last b/c it will be a different height + expect(rowEls.length).toBeGreaterThan(0); + var height = rowEls.height(); + rowEls.each(function(i, node) { + expect($(node).height()).toBe(height); + }); + }); + }); + + [ 'month', 'basicWeek' ].forEach(function(viewName) { + + describe('in ' + viewName + ' view', function() { + + beforeEach(function() { + options.defaultView = viewName; + }); + + it('doesn\'t render a more link where there should obviously not be a limit', function() { + options.events = [ + { title: 'event1', start: '2014-07-28', end: '2014-07-30' } + ]; + $('#cal').fullCalendar(options); + expect($('.fc-more').length).toBe(0); + }); + }); + }); + + describe('in agendaWeek view', function() { + + beforeEach(function() { + options.defaultView = 'agendaWeek'; + }); + + it('behaves as if limit is 5', function() { + options.events = [ + { title: 'event1', start: '2014-07-29' }, + { title: 'event2', start: '2014-07-29' }, + { title: 'event2', start: '2014-07-29' }, + { title: 'event2', start: '2014-07-29' }, + { title: 'event2', start: '2014-07-29' }, + { title: 'event2', start: '2014-07-29' }, + { title: 'event2', start: '2014-07-29' } + ]; + $('#cal').fullCalendar(options); + expect($('.fc-event:visible').length).toBe(4); + expect($('.fc-more').length).toBe(1); + expect($('.fc-more')).toHaveText('+3 more'); + }); + }); + }); +}); diff --git a/tests/automated/eventLimitClick.js b/tests/automated/eventLimitClick.js new file mode 100644 index 0000000..98e800e --- /dev/null +++ b/tests/automated/eventLimitClick.js @@ -0,0 +1,135 @@ + +describe('eventLimitClick', function() { // simulate a click + + var options; + + beforeEach(function() { + affix('#cal'); + options = { + defaultDate: '2014-08-01', // important that it is the first week, so works w/ month + week views + defaultView: 'month', + eventLimit: 3, + events: [ + { title: 'event1', start: '2014-07-29' }, + { title: 'event2', start: '2014-07-29' }, + { title: 'event2', start: '2014-07-29' }, + { title: 'event2', start: '2014-07-29' } + ] + }; + }); + + describe('when set to "popover"', function() { + + beforeEach(function() { + options.eventLimitClick = 'popover'; + }); + + it('renders a popover upon click', function() { + $('#cal').fullCalendar(options); + $('.fc-more').simulate('click'); + expect($('.fc-more-popover')).toBeVisible(); + }); + + // more popover tests are done in eventLimit-popover + }); + + describe('when set to "week"', function() { + + beforeEach(function() { + options.eventLimitClick = 'week'; + }); + + it('should go to basicWeek if it is one of the available views', function() { + options.header = { + left: 'prev,next today', + center: 'title', + right: 'month,basicWeek,basicDay' + }; + $('#cal').fullCalendar(options); + $('.fc-more').simulate('click'); + var view = $('#cal').fullCalendar('getView'); + expect(view.name).toBe('basicWeek'); + }); + + it('should go to agendaWeek if it is one of the available views', function() { + options.header = { + left: 'prev,next today', + center: 'title', + right: 'month,agendaWeek,agendaDay' + }; + $('#cal').fullCalendar(options); + $('.fc-more').simulate('click'); + var view = $('#cal').fullCalendar('getView'); + expect(view.name).toBe('agendaWeek'); + }); + }); + + describe('when set to "day"', function() { + + beforeEach(function() { + options.eventLimitClick = 'day'; + }); + + it('should go to basicDay if it is one of the available views', function() { + options.header = { + left: 'prev,next today', + center: 'title', + right: 'month,basicWeek,basicDay' + }; + $('#cal').fullCalendar(options); + $('.fc-more').simulate('click'); + var view = $('#cal').fullCalendar('getView'); + expect(view.name).toBe('basicDay'); + }); + + it('should go to agendaDay if it is one of the available views', function() { + options.header = { + left: 'prev,next today', + center: 'title', + right: 'month,agendaWeek,agendaDay' + }; + $('#cal').fullCalendar(options); + $('.fc-more').simulate('click'); + var view = $('#cal').fullCalendar('getView'); + expect(view.name).toBe('agendaDay'); + }); + }); + + it('works with an explicit view name', function() { + options.eventLimitClick = 'agendaWeek'; + options.header = { + left: 'prev,next today', + center: 'title', + right: 'month,basicWeek,basicDay' + }; + $('#cal').fullCalendar(options); + $('.fc-more').simulate('click'); + var view = $('#cal').fullCalendar('getView'); + expect(view.name).toBe('agendaWeek'); + }); + + it('works with custom function and all the arguments are correct', function() { + options.eventLimitClick = function(cellInfo, jsEvent) { + expect(typeof cellInfo).toBe('object'); + expect(typeof jsEvent).toBe('object'); + expect(cellInfo.date).toEqualMoment('2014-07-29'); + expect(cellInfo.dayEl.data('date')).toBe('2014-07-29'); + expect(cellInfo.hiddenSegs.length).toBe(2); + expect(cellInfo.segs.length).toBe(4); + expect(cellInfo.moreEl).toHaveClass('fc-more'); + }; + $('#cal').fullCalendar(options); + $('.fc-more').simulate('click'); + }); + + it('works with custom function, and can return a view name', function() { + options.eventLimitClick = function(cellInfo, jsEvent) { + return 'agendaDay'; + }; + $('#cal').fullCalendar(options); + $('.fc-more').simulate('click'); + var view = $('#cal').fullCalendar('getView'); + expect(view.name).toBe('agendaDay'); + }); + +}); diff --git a/tests/automated/eventLimitText.js b/tests/automated/eventLimitText.js new file mode 100644 index 0000000..5c3ab2d --- /dev/null +++ b/tests/automated/eventLimitText.js @@ -0,0 +1,48 @@ + +describe('eventLimitText', function() { + + var options; + + beforeEach(function() { + affix('#cal'); + options = { + defaultDate: '2014-08-01', // important that it is the first week, so works w/ month + week views + defaultView: 'month', + eventLimit: 3, + events: [ + { title: 'event1', start: '2014-07-29' }, + { title: 'event2', start: '2014-07-29' }, + { title: 'event2', start: '2014-07-29' }, + { title: 'event2', start: '2014-07-29' } + ] + }; + }); + + it('allows a string', function() { + options.eventLimitText = 'extra'; + $('#cal').fullCalendar(options); + expect($('.fc-more')).toHaveText('+2 extra'); + }); + + it('allows a function', function() { + options.eventLimitText = function(n) { + expect(typeof n).toBe('number'); + return 'there are ' + n + ' more events!'; + }; + $('#cal').fullCalendar(options); + expect($('.fc-more')).toHaveText('there are 2 more events!'); + }); + + it('has a default value that is affected by the custom locale', function() { + options.lang = 'fr'; + $('#cal').fullCalendar(options); + expect($('.fc-more')).toHaveText('+2 en plus'); + }); + + it('is not affected by a custom locale when the value is explicitly specified', function() { + options.lang = 'fr'; + options.eventLimitText = 'extra'; + $('#cal').fullCalendar(options); + expect($('.fc-more')).toHaveText('+2 extra'); + }); +}); diff --git a/tests/lib/jasmine-ext.js b/tests/lib/jasmine-ext.js index 4a2d991..ab861cf 100644 --- a/tests/lib/jasmine-ext.js +++ b/tests/lib/jasmine-ext.js @@ -8,6 +8,9 @@ beforeEach(function() { moment.suppressDeprecationWarnings = true; jasmine.addMatchers({ + + // Moment and Duration + toEqualMoment: function() { return { compare: function(actual, expected) { @@ -51,7 +54,30 @@ beforeEach(function() { return result; } }; + }, + + + // Geometry + + toBeBoundedBy: function() { + return { + compare: function(actual, expected) { + var outer = getBounds(expected); + var inner = getBounds(actual); + var result = { + pass: inner.left >= outer.left && + inner.right <= outer.right && + inner.top >= outer.top && + inner.bottom <= outer.bottom + }; + if (!result.pass) { + result.message = 'Element does not bound other element'; + } + return result; + } + }; } + }); function serializeDuration(duration) { @@ -67,4 +93,16 @@ beforeEach(function() { return n.length >= width ? n : new Array(width - n.length + 1).join('0') + n; } + function getBounds(node) { + var el = $(node); + var offset = el.offset(); + + return { + top: offset.top, + left: offset.left, + right: offset.left + el.outerWidth(), + bottom: offset.top + el.outerHeight() + }; + } + });