import { ThirdPartyDraggable } from '@fullcalendar/interaction'
import { testEventDrag } from '../lib/dnd-resize-utils.js'
import { CalendarWrapper } from '../lib/wrappers/CalendarWrapper.js'
// TODO: Use the built-in Draggable for some of these tests
describe('advanced external dnd', () => {
let dragEl
let thirdPartyDraggable
beforeEach(() => {
dragEl = $('
yo
')
.css({
width: 200,
background: 'blue',
color: 'white',
})
.appendTo('body')
.draggable()
thirdPartyDraggable = new ThirdPartyDraggable({
itemSelector: '.drag',
})
})
afterEach(() => {
thirdPartyDraggable.destroy()
dragEl.remove()
dragEl = null
})
pushOptions({
initialDate: '2014-11-13',
scrollTime: '00:00:00',
droppable: true,
})
describe('in timeGrid slots', () => {
pushOptions({
initialView: 'timeGridWeek',
})
describe('when no element event data', () => {
describe('when given duration through defaultTimedEventDuration', () => {
pushOptions({
defaultTimedEventDuration: '2:30',
})
defineTests()
})
describe('when given duration through data attribute', () => {
beforeEach(() => {
dragEl.attr('data-event', JSON.stringify({
duration: '2:30',
create: false, // only an external element, won't create or render as an event
}))
})
defineTests()
})
function defineTests() {
it('fires correctly', (done) => {
testExternalElDrag({}, '2014-11-13T03:00:00Z', '2014-11-13T03:00:00Z', true, done)
})
it('is not affected by eventOverlap:false', (done) => {
let options = {
eventOverlap: false,
events: [{
start: '2014-11-13T01:00:00',
end: '2014-11-13T05:00:00',
}],
}
testExternalElDrag(options, '2014-11-13T03:00:00Z', '2014-11-13T03:00:00Z', true, done)
})
it('is not affected by an event object\'s overlap:false', (done) => {
let options = {
events: [{
start: '2014-11-13T01:00:00',
end: '2014-11-13T05:00:00',
overlap: false,
}],
}
testExternalElDrag(options, '2014-11-13T03:00:00Z', '2014-11-13T03:00:00Z', true, done)
})
it('is not affected by eventConstraint', (done) => {
let options = {
eventConstraint: {
start: '03:00',
end: '10:00',
},
}
testExternalElDrag(options, '2014-11-13T02:00:00Z', '2014-11-13T02:00:00Z', true, done)
})
describe('with selectOverlap:false', () => {
pushOptions({
selectOverlap: false,
events: [{
start: '2014-11-13T04:00:00',
end: '2014-11-13T08:00:00',
}],
})
it('is not allowed to overlap an event', (done) => {
testExternalElDrag({}, '2014-11-13T02:00:00Z', '2014-11-13T02:00:00Z', false, done)
})
})
describe('with a selectConstraint', () => {
pushOptions({
selectConstraint: {
startTime: '04:00',
endTime: '08:00',
},
})
it('can be dropped within', (done) => {
testExternalElDrag({}, '2014-11-13T05:30:00Z', '2014-11-13T05:30:00Z', true, done)
})
it('cannot be dropped when not fully contained', (done) => {
testExternalElDrag({}, '2014-11-13T06:00:00Z', '2014-11-13T06:00:00Z', false, done)
})
})
}
})
describe('when event data is given', () => {
it('fires correctly', (done) => {
dragEl.attr('data-event', JSON.stringify({
title: 'hey',
}))
testExternalEventDrag({}, '2014-11-13T02:00:00Z', '2014-11-13T02:00:00Z', true, done)
})
describe('when given a start time', () => {
describe('through the event object\'s time property', () => {
beforeEach(() => {
dragEl.attr('data-event', JSON.stringify({
startTime: '05:00',
}))
})
it('voids the given time when dropped on a timed slot', (done) => {
testExternalEventDrag({}, '2014-11-13T02:00:00Z', '2014-11-13T02:00:00Z', true, done)
// will test the resulting event object's start
})
})
})
describe('when given a duration', () => {
describe('through the event object\'s duration property', () => {
beforeEach(() => {
dragEl.attr('data-event', JSON.stringify({
duration: '05:00',
}))
})
it('accepts the given duration when dropped on a timed slot', (done) => {
testExternalEventDrag({}, '2014-11-13T02:00:00Z', '2014-11-13T02:00:00Z', true, () => {
let event = currentCalendar.getEvents()[0]
expect(event.start).toEqualDate('2014-11-13T02:00:00Z')
expect(event.end).toEqualDate('2014-11-13T07:00:00Z')
done()
})
})
})
})
describe('when given stick:true', () => {
describe('through the event object', () => {
beforeEach(() => {
dragEl.attr('data-event', JSON.stringify({
stick: true,
}))
})
it('keeps the event when navigating away and back', (done) => {
testExternalEventDrag({}, '2014-11-13T02:00:00Z', '2014-11-13T02:00:00Z', true, () => {
setTimeout(() => { // make sure to escape handlers
let calendarWrapper = new CalendarWrapper(currentCalendar)
expect(calendarWrapper.getEventEls().length).toBe(1)
currentCalendar.next()
expect(calendarWrapper.getEventEls().length).toBe(0)
currentCalendar.prev()
expect(calendarWrapper.getEventEls().length).toBe(1)
done()
}, 0)
})
})
})
})
describe('when an overlap is specified', () => {
describe('via eventOverlap', () => {
pushOptions({
eventOverlap: false,
events: [{
start: '2014-11-13T05:00:00',
end: '2014-11-13T08:00:00',
}],
})
beforeEach(() => {
dragEl.attr('data-event', '{}')
})
defineTests()
})
describe('via an overlap on this event', () => {
pushOptions({
events: [{
start: '2014-11-13T05:00:00',
end: '2014-11-13T08:00:00',
}],
})
beforeEach(() => {
dragEl.attr('data-event', JSON.stringify({
overlap: false,
}))
})
defineTests()
})
describe('via an overlap on the other event', () => {
pushOptions({
events: [{
start: '2014-11-13T05:00:00',
end: '2014-11-13T08:00:00',
overlap: false,
}],
})
beforeEach(() => {
dragEl.attr('data-event', '{}')
})
defineTests()
})
function defineTests() {
it('allows a drop when not colliding with the other event', (done) => {
testExternalEventDrag({}, '2014-11-13T08:00:00Z', '2014-11-13T08:00:00Z', true, done)
})
it('prevents a drop when colliding with the other event', (done) => {
testExternalEventDrag({}, '2014-11-13T06:00:00Z', '2014-11-13T06:00:00Z', false, done)
})
}
})
describe('when a constraint is specified', () => {
describe('via eventConstraint', () => {
pushOptions({
eventConstraint: {
startTime: '04:00',
endTime: '08:00',
},
})
beforeEach(() => {
dragEl.attr('data-event', JSON.stringify({
duration: '02:00',
}))
})
defineTests()
})
describe('via the event object\'s constraint property', () => {
beforeEach(() => {
dragEl.attr('data-event', JSON.stringify({
duration: '02:00',
constraint: {
startTime: '04:00',
endTime: '08:00',
},
}))
})
defineTests()
})
function defineTests() {
it('allows a drop when inside the constraint', (done) => {
testExternalEventDrag({}, '2014-11-13T05:00:00Z', '2014-11-13T05:00:00Z', true, done)
})
it('disallows a drop when partially outside of the constraint', (done) => {
testExternalEventDrag({}, '2014-11-13T07:00:00Z', '2014-11-13T07:00:00Z', false, done)
})
}
})
})
})
// TODO: write more tests for DayGrid!
describe('in month whole-days', () => {
pushOptions({
initialView: 'dayGridMonth',
})
describe('when event data is given', () => {
it('fires correctly', (done) => {
dragEl.attr('data-event', JSON.stringify({
title: 'hey',
}))
testExternalEventDrag({}, '2014-11-13', '2014-11-13', true, done)
})
describe('when given a start time', () => {
describe('through the event object\'s time property', () => {
beforeEach(() => {
dragEl.attr('data-event', JSON.stringify({
startTime: '05:00',
}))
})
it('accepts the given start time for the dropped day', (done) => {
testExternalEventDrag({}, '2014-11-13', '2014-11-13T05:00:00Z', true, () => {
// the whole-day start was already checked. we still need to check the exact time
let event = currentCalendar.getEvents()[0]
expect(event.start).toEqualDate('2014-11-13T05:00:00Z')
done()
})
})
})
})
})
})
function testExternalElDrag(options, dragToDate, expectedDate, expectSuccess, callback) { // with NO event creation
options.droppable = true
options.drop = (arg) => {
expect(arg.date instanceof Date).toBe(true)
expect(arg.date).toEqualDate(expectedDate)
expect(typeof arg.jsEvent).toBe('object')
}
options.eventReceive = () => {}
spyOn(options, 'drop').and.callThrough()
spyOn(options, 'eventReceive').and.callThrough()
testEventDrag(options, dragToDate, expectSuccess, () => {
if (expectSuccess) {
expect(options.drop).toHaveBeenCalled()
} else {
expect(options.drop).not.toHaveBeenCalled()
}
expect(options.eventReceive).not.toHaveBeenCalled()
callback()
}, 'drag') // .drag className
}
function testExternalEventDrag(options, dragToDate, expectedDate, expectSuccess, callback) {
let expectedAllDay = dragToDate.indexOf('T') === -1 // for the drop callback only!
options.droppable = true
options.drop = (arg) => {
expect(arg.date instanceof Date).toBe(true)
expect(arg.date).toEqualDate(dragToDate)
expect(arg.allDay).toBe(expectedAllDay)
expect(typeof arg.jsEvent).toBe('object')
}
options.eventReceive = (arg) => {
expect(arg.event.start).toEqualDate(expectedDate)
}
spyOn(options, 'drop').and.callThrough()
spyOn(options, 'eventReceive').and.callThrough()
testEventDrag(options, dragToDate, expectSuccess, () => {
if (expectSuccess) {
expect(options.drop).toHaveBeenCalled()
expect(options.eventReceive).toHaveBeenCalled()
} else {
expect(options.drop).not.toHaveBeenCalled()
expect(options.eventReceive).not.toHaveBeenCalled()
}
callback()
}, 'drag') // .drag className
}
})