moment-recur
Version:
A momentjs plugin for matching and generating recurring dates.
476 lines (404 loc) • 19.4 kB
JavaScript
// Getting rid of jshint warnings (the yellow lines and exclaimation points are annoying)
var jasmine = jasmine, describe = describe, it = it, moment = moment, expect = expect, beforeEach = beforeEach;
// TOTEST:
// Export Rules
// Repeats function
var startDate = "01/01/2013";
var endDate = "01/01/2014";
describe("Creating a recurring moment", function() {
var nowMoment = moment();
var nowDate = nowMoment.format("L");
it("from moment constructor, with options parameter - moment.recur(options)", function() {
var recur = moment.recur({ start:startDate, end:endDate });
expect(recur.start.format("L")).toBe(startDate);
expect(recur.end.format("L")).toBe(endDate);
});
it("from moment constructor, with start parameter only - moment.recur(start)", function() {
var recur = moment.recur(startDate);
expect(recur.start.format("L")).toBe(startDate);
});
it("from moment constructor, with start and end parameters - moment.recur(start, end)", function() {
var recur = moment.recur(startDate, endDate);
expect(recur.start.format("L")).toBe(startDate);
expect(recur.end.format("L")).toBe(endDate);
});
it("from moment function, with options parameter - moment().recur(options)", function() {
var recur = moment().recur({ start:startDate, end:endDate });
expect(recur.start.format("L")).toBe(startDate);
expect(recur.end.format("L")).toBe(endDate);
});
it("from moment function, with start and end parameters - moment().recur(start, end)", function() {
var recur = moment().recur(startDate, endDate);
expect(recur.start.format("L")).toBe(startDate);
expect(recur.end.format("L")).toBe(endDate);
});
it("from moment function, with starting moment and end parameter - moment(start).recur(end)", function() {
var recur = moment(startDate).recur(endDate);
expect(recur.start.format("L")).toBe(startDate);
expect(recur.end.format("L")).toBe(endDate);
});
it("from moment function, starting now, with end parameter - moment().recur(end)", function() {
var recur = nowMoment.recur(endDate);
expect(recur.start.format("L")).toBe(nowDate);
expect(recur.end.format("L")).toBe(endDate);
});
it("from moment function, starting now - moment().recur()", function() {
var recur = nowMoment.recur();
expect(recur.start.format("L")).toBe(nowDate);
});
it("from moment function, with starting moment and end parameter, which is a moment object - moment(start).recur(end)", function() {
var startMoment = moment(startDate);
var endMoment = moment(endDate);
var recur = moment(startMoment).recur(endMoment);
expect(recur.start.format("L")).toBe(startDate);
expect(recur.end.format("L")).toBe(endDate);
});
});
describe("Setting", function() {
var recur;
beforeEach(function() {
recur = moment().recur();
});
it("'start' should be getable/setable with startDate()", function() {
recur.startDate(startDate);
expect(recur.startDate().format("L")).toBe(startDate);
});
it("'end' should be getable/setable with endDate()", function() {
recur.endDate(endDate);
expect(recur.endDate().format("L")).toBe(endDate);
});
it("'from' should be getable/setable with fromDate()", function() {
recur.fromDate(startDate);
expect(recur.fromDate().format("L")).toBe(startDate);
});
});
describe("The every() function", function() {
it("should create a rule when a unit and measurement is passed", function() {
var recurrence = moment().recur().every(1, "day");
expect(recurrence.save().rules.length).toBe(1);
});
it("should not create a rule when only a unit is passed", function() {
var recurrence = moment().recur().every(1);
expect(recurrence.save().rules.length).toBe(0);
});
it("should set the temporary units property", function() {
var recurrence = moment().recur().every(1);
expect(recurrence.units).not.toBeNull();
});
it("should accept an array", function() {
var recurrence = moment().recur().every([1, 2]);
expect(recurrence.units).not.toBeNull();
});
});
describe("An interval", function() {
it("should not match a date before the start date", function() {
var start = moment(startDate);
var before = start.clone().subtract(1, "day");
var recurrence = start.recur();
recurrence.every(1, "day");
expect(recurrence.matches(before)).toBe(false);
});
it("should not match a date after the end date", function() {
var start = moment(startDate);
var after = moment(endDate).add(1, "day");
var recurrence = start.recur();
recurrence.endDate(endDate).every(1, "day");
expect(recurrence.matches(after)).toBe(false);
});
it("can be daily", function() {
var recurrence = moment(startDate).recur().every(2).days();
expect(recurrence.matches( moment(startDate).add(2, "days") )).toBe(true);
expect(recurrence.matches( moment(startDate).add(3, "days") )).toBe(false);
});
it("can be weekly", function() {
var recurrence = moment(startDate).recur().every(2).weeks();
expect(recurrence.matches( moment(startDate).add(2, "weeks") )).toBe(true);
expect(recurrence.matches( moment(startDate).add(2, "days") )).toBe(false);
expect(recurrence.matches( moment(startDate).add(3, "weeks") )).toBe(false);
});
it("can be monthly", function() {
var recurrence = moment(startDate).recur().every(3).months();
expect(recurrence.matches( moment(startDate).add(3, "months") )).toBe(true);
expect(recurrence.matches( moment(startDate).add(2, "months") )).toBe(false);
expect(recurrence.matches( moment(startDate).add(2, "days"))).toBe(false);
});
it("can be yearly", function() {
var recurrence = moment(startDate).recur().every(2).years();
expect(recurrence.matches( moment(startDate).add(2, "year") )).toBe(true);
expect(recurrence.matches( moment(startDate).add(3, "year") )).toBe(false);
expect(recurrence.matches( moment(startDate).add(2, "days") )).toBe(false);
});
it("can be an array of intervals", function() {
var recurrence = moment(startDate).recur().every([3,5]).days();
expect(recurrence.matches( moment(startDate).add(3, "days"))).toBe(true);
expect(recurrence.matches( moment(startDate).add(5, "days"))).toBe(true);
expect(recurrence.matches( moment(startDate).add(10, "days"))).toBe(true);
expect(recurrence.matches( moment(startDate).add(4, "days"))).toBe(false);
expect(recurrence.matches( moment(startDate).add(8, "days"))).toBe(false);
});
});
describe("The Calendar Interval", function() {
describe("daysOfWeek", function() {
it("should work", function () {
var recurrence = moment.recur().every(["Sunday", 1]).daysOfWeek();
expect(recurrence.matches(moment().day("Sunday"))).toBe(true);
expect(recurrence.matches(moment().day(1))).toBe(true);
expect(recurrence.matches(moment().day(3))).toBe(false);
});
it("should work with timezones", function () {
var recurrence = moment.tz('2015-01-25',"America/Vancouver").recur().every(["Sunday", 1]).daysOfWeek();
var check = moment.tz('2015-02-01',"Asia/Hong_Kong");
expect(recurrence.matches(check)).toBe(true);
});
});
it("daysOfMonth should work", function() {
var recurrence = moment('2015-01-01').recur().every([1, 10]).daysOfMonth();
expect(recurrence.matches( moment('2015-01-01'))).toBe(true);
expect(recurrence.matches( moment('2015-01-02'))).toBe(false);
expect(recurrence.matches( moment('2015-01-10'))).toBe(true);
expect(recurrence.matches( moment('2015-01-15'))).toBe(false);
expect(recurrence.matches( moment('2015-02-01'))).toBe(true);
expect(recurrence.matches( moment('2015-02-02'))).toBe(false);
expect(recurrence.matches( moment('2015-02-10'))).toBe(true);
expect(recurrence.matches( moment('2015-02-15'))).toBe(false);
});
it("weeksOfMonth should work", function() {
var recurrence = moment.recur().every([1, 3]).weeksOfMonth();
expect(recurrence.matches( moment(startDate).date(6) )).toBe(true);
expect(recurrence.matches( moment(startDate).date(26) )).toBe(true);
expect(recurrence.matches( moment(startDate).date(27) )).toBe(false);
});
it("weeksOfYear should work", function() {
var recurrence = moment.recur().every(20).weekOfYear();
expect(recurrence.matches( moment("05/14/2014") )).toBe(true);
expect(recurrence.matches( moment(startDate) )).toBe(false);
});
it("monthsOfYear should work", function() {
var recurrence = moment.recur().every("January").monthsOfYear();
expect(recurrence.matches( moment().month("January") )).toBe(true);
expect(recurrence.matches( moment().month("February") )).toBe(false);
});
it("rules can be combined", function() {
var valentines = moment.recur().every(14).daysOfMonth()
.every("Februray").monthsOfYear();
expect(valentines.matches( moment("02/14/2014") )).toBe(true);
expect(valentines.matches( moment(startDate) )).toBe(false);
});
it("can be passed units, without every()", function() {
var recurrence = moment.recur().daysOfMonth([1,3]);
expect(recurrence.matches("01/01/2014")).toBe(true);
expect(recurrence.matches("01/03/2014")).toBe(true);
expect(recurrence.matches("01/06/2014")).toBe(false);
});
});
describe("Rules", function() {
it("should be overridden when duplicated", function() {
var recurrence = moment("01/01/2014").recur().every(1).day();
recurrence.every(2).days();
expect(recurrence.rules.length).toBe(1);
});
it("should be forgettable", function() {
var recurrence = moment("01/01/2014").recur().every(1).day();
recurrence.forget("days");
expect(recurrence.rules.length).toBe(0);
});
it("should be possible to see if one exists", function() {
var recurrence = moment("01/01/2014").recur().every(1).day();
expect(recurrence.hasRule("days")).toBe(true);
expect(recurrence.hasRule("months")).toBe(false);
});
});
describe("weeksOfMonthByDay()", function() {
it("can recur on the 1st and 3rd Sundays of the month", function() {
var recurrence;
recurrence = moment.recur()
.every(["Sunday"]).daysOfWeek()
.every([0, 2]).weeksOfMonthByDay();
expect(recurrence.matches(moment(startDate))).toBe(false);
expect(recurrence.matches(moment(startDate).date(6))).toBe(true);
expect(recurrence.matches(moment(startDate).date(8))).toBe(false);
expect(recurrence.matches(moment(startDate).date(13))).toBe(false);
expect(recurrence.matches(moment(startDate).date(20))).toBe(true);
expect(recurrence.matches(moment(startDate).date(27))).toBe(false);
});
it("can recur on the 2nd, 4th and 5th Sundays and Thursdays of the month", function() {
var recurrence;
recurrence = moment.recur()
.every(["Sunday", "Thursday"]).daysOfWeek()
.every([1, 3, 4]).weeksOfMonthByDay();
expect(recurrence.matches(moment(startDate).date(6))).toBe(false);
expect(recurrence.matches(moment(startDate).date(13))).toBe(true);
expect(recurrence.matches(moment(startDate).date(20))).toBe(false);
expect(recurrence.matches(moment(startDate).date(27))).toBe(true);
expect(recurrence.matches(moment(startDate).date(3))).toBe(false);
expect(recurrence.matches(moment(startDate).date(10))).toBe(true);
expect(recurrence.matches(moment(startDate).date(17))).toBe(false);
expect(recurrence.matches(moment(startDate).date(24))).toBe(true);
expect(recurrence.matches(moment(startDate).date(31))).toBe(true);
});
it("can recur on the 4th Wednesday of the month", function() {
var recurrence;
recurrence = moment.recur()
.every(moment('2017-09-27').day()).daysOfWeek()
.every(moment('2017-09-27').monthWeekByDay()).weeksOfMonthByDay();
expect(recurrence.matches(moment('2017-09-27'))).toBe(true);
expect(recurrence.matches(moment('2017-10-25'))).toBe(true);
expect(recurrence.matches(moment('2017-11-22'))).toBe(true);
expect(recurrence.matches(moment('2017-12-27'))).toBe(true);
});
it("will throw an error if used without daysOfWeek()", function() {
var recurrence, caught = { message: false };
try {
recurrence = moment.recur().every(0).weeksOfMonthByDay();
} catch (e) {
caught = e;
}
expect(caught.message).toBe('weeksOfMonthByDay must be combined with daysOfWeek');
});
});
describe("Future Dates", function() {
it("can be generated", function() {
var recurrence, nextDates;
recurrence = moment("01/01/2014").recur().every(2).days();
nextDates = recurrence.next(3, "L");
expect(nextDates.length).toBe(3);
expect(nextDates[0]).toBe("01/03/2014");
expect(nextDates[1]).toBe("01/05/2014");
expect(nextDates[2]).toBe("01/07/2014");
});
it("can start from a temporary 'from' date", function() {
var recurrence, nextDates;
recurrence = moment("01/01/2014").recur().every(2).days();
recurrence.fromDate("02/05/2014");
nextDates = recurrence.next(3, "L");
expect(nextDates.length).toBe(3);
expect(nextDates[0]).toBe("02/06/2014");
expect(nextDates[1]).toBe("02/08/2014");
expect(nextDates[2]).toBe("02/10/2014");
});
});
describe("Previous Dates", function() {
it("can be generated", function() {
var recurrence, nextDates;
recurrence = moment("01/01/2014").recur().every(2).days();
nextDates = recurrence.previous(3, "L");
expect(nextDates.length).toBe(3);
expect(nextDates[0]).toBe("12/30/2013");
expect(nextDates[1]).toBe("12/28/2013");
expect(nextDates[2]).toBe("12/26/2013");
});
});
describe("All Dates", function() {
it("can be generated", function() {
var recurrence, allDates;
recurrence = moment("01/01/2014").recur("01/07/2014").every(2).days();
allDates = recurrence.all("L");
expect(allDates.length).toBe(4);
expect(allDates[0]).toBe("01/01/2014");
expect(allDates[1]).toBe("01/03/2014");
expect(allDates[2]).toBe("01/05/2014");
expect(allDates[3]).toBe("01/07/2014");
});
it("can start from a temporary 'from' date", function() {
var recurrence, allDates;
recurrence = moment().recur("01/01/2014", "01/08/2014").every(2).days();
recurrence.fromDate("01/05/2014");
allDates = recurrence.all("L");
expect(allDates.length).toBe(2);
expect(allDates[0]).toBe("01/05/2014");
expect(allDates[1]).toBe("01/07/2014");
});
it('should throw error if start date is after end date', function() {
var recurrence, allDates;
recurrence = moment().recur("07/26/2017", "08/01/2013").every(2).days();
expect(function() {
recurrence.all("L");
}).toThrow(new Error("Start date cannot be later than end date."));
});
it('should only generate a single date when start date and end date are the same', function() {
var recurrence, allDates;
recurrence = moment().recur("01/01/2014", "01/01/2014").every(1).days();
allDates = recurrence.all("L");
expect(allDates.length).toBe(1);
expect(allDates[0]).toBe("01/01/2014");
});
});
describe("Exceptions", function() {
var mo, exception, recur, exceptionWithTz;
beforeEach(function() {
mo = moment(startDate);
exception = mo.clone().add(3, "day");
recur = mo.clone().recur().every(1, "days");
exceptionWithTz = moment.tz(exception.format('YYYY-MM-DD'), 'Asia/Hong_Kong');
});
it("should prevent exception days from matching", function() {
recur.except(exception);
expect(recur.matches(exception)).toBe(false);
});
it('should work when the passed in exception is in a different time zone', function() {
recur.except(exception);
expect(recur.matches(exceptionWithTz)).toBe(false);
});
it("should be removeable", function() {
recur.except(exception);
recur.forget(exception);
expect(recur.matches(exception)).toBe(true);
});
});
describe('Exceptions with weeks', function() {
var mo, exception, recur, exceptionWithTz;
beforeEach(function() {
mo = moment(startDate);
exception = mo.clone().add(7, "day");
recur = mo.clone().recur().every(1, "weeks");
exceptionWithTz = moment.tz(exception.format('YYYY-MM-DD'), 'Asia/Hong_Kong');
});
it('should not match on the exception day', function() {
expect(recur.matches(exception)).toBe(true);
recur.except(exception);
expect(recur.matches(exception)).toBe(false);
});
it('should not match on the exception day', function() {
expect(recur.matches(exceptionWithTz)).toBe(true);
recur.except(exception);
expect(recur.matches(exceptionWithTz)).toBe(false);
});
});
describe("Options", function() {
it("should be importable", function() {
var recurrence = moment().recur({
start: "01/01/2014",
end: "12/31/2014",
rules: [
{ units: { 2 : true }, measure: "days" }
],
exceptions: ["01/05/2014"]
});
expect(recurrence.startDate().format("L")).toBe("01/01/2014");
expect(recurrence.endDate().format("L")).toBe("12/31/2014");
expect(recurrence.rules.length).toBe(1);
expect(recurrence.exceptions.length).toBe(1);
expect(recurrence.matches("01/03/2014")).toBe(true);
expect(recurrence.matches("01/05/2014")).toBe(false);
});
it("shold be exportable", function() {
var recurrence = moment("01/01/2014").recur("12/31/2014").every(2, "days").except("01/05/2014");
var data = recurrence.save();
expect(data.start).toBe("01/01/2014");
expect(data.end).toBe("12/31/2014");
expect(data.exceptions[0]).toBe("01/05/2014");
expect(data.rules[0].units[2]).toBe(true);
expect(data.rules[0].measure).toBe("days");
});
});
describe("The repeats() function", function() {
it("should return true when there are rules set", function() {
var recurrence = moment().recur().every(1).days();
expect(recurrence.repeats()).toBe(true);
});
it("should return false when there are no rules set", function() {
var recurrence = moment().recur();
expect(recurrence.repeats()).toBe(false);
});
});
;