@publidata/utils-opening-hours
Version:
Collection of methods to handle opening hours
276 lines (237 loc) • 11.5 kB
JavaScript
const chai = require("chai");
const { expect } = chai;
const moment = require("moment");
const {
openOnceAYear,
willOpenAgain,
displayOpenings,
willOpenAgainToday,
getTodaysNextOpening,
getLastKnownOpeningDate,
getOpeningCountsFromRange
} = require("../src/opening-hours.js");
chai.use(require("chai-datetime"));
const MONTH_SHORT = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
const NOW = new Date();
const TODAY_OPENING = `${NOW.getFullYear()} ${MONTH_SHORT[NOW.getMonth()]} ${NOW.getDate()}`;
const ONE_HOUR_BEF = new Date(NOW);
ONE_HOUR_BEF.setHours(NOW.getHours() - 1);
const TWO_HOURS_BEF = new Date(NOW);
TWO_HOURS_BEF.setHours(NOW.getHours() - 2);
const ONE_HOUR_AF = new Date(NOW);
ONE_HOUR_AF.setHours(NOW.getHours() + 1);
const TWO_HOURS_AF = new Date(NOW);
TWO_HOURS_AF.setHours(NOW.getHours() + 2);
describe("Unit tests", () => {
describe("willOpenAgain", () => {
it("should displayOpenings", () => {
const oh = `${TODAY_OPENING} ${ONE_HOUR_BEF.getHours()}:00-${TWO_HOURS_AF.getHours()}:00`;
// const oh= "24/7 off"
console.log('displayOpenings(oh)',displayOpenings(oh));
expect(displayOpenings(oh)).to.be.a('object');
});
it("should return true when there is a next opening but is currently close", () => {
const oh = `${TODAY_OPENING} ${ONE_HOUR_AF.getHours()}:00-${TWO_HOURS_AF.getHours()}:00`;
expect(willOpenAgain(oh)).to.be.true;
});
// it("should return false when there is no next opening but is currently open", () => {
// const oh = `${TODAY_OPENING} ${ONE_HOUR_BEF.getHours()}:${ONE_HOUR_BEF.getMinutes()}-${ONE_HOUR_AF.getHours()}:${ONE_HOUR_AF.getMinutes()}`;
// expect(willOpenAgain(oh)).to.be.false;
// });
it("should return true when it opens every week", () => {
const oh = "Mo 06:00-17:00";
expect(willOpenAgain(oh)).to.be.true;
});
it("should return false if it's definitively closed", () => {
const oh = "off";
expect(willOpenAgain(oh)).to.be.false;
});
it("should return false if the last opening is in the past", () => {
const oh = "2022 Jan 01-2022 Nov 13 Mo 06:00-17:00";
expect(willOpenAgain(oh)).to.be.false;
});
});
describe("willOpenAgainToday", () => {
const oh = "08:00-10:00,11:00-13:00,14:00-16:00";
const today = new Date();
it("should return true at 00:00", () => {
const now = new Date(today.getFullYear(), today.getMonth(), today.getDate(), 0, 0, 0);
expect(willOpenAgainToday(oh, now)).to.equal(true);
});
it("should return true at 06:00", () => {
const now = new Date(today.getFullYear(), today.getMonth(), today.getDate(), 6, 0, 0);
expect(willOpenAgainToday(oh, now)).to.equal(true);
});
it("should return true at 10:00", () => {
const now = new Date(today.getFullYear(), today.getMonth(), today.getDate(), 10, 0, 0);
expect(willOpenAgainToday(oh, now)).to.equal(true);
});
it("should return true at 12:00", () => {
const now = new Date(today.getFullYear(), today.getMonth(), today.getDate(), 12, 0, 0);
expect(willOpenAgainToday(oh, now)).to.equal(true);
});
it("should return false at 15:00", () => {
const now = new Date(today.getFullYear(), today.getMonth(), today.getDate(), 15, 0, 0);
expect(willOpenAgainToday(oh, now)).to.equal(false);
});
it("should return false at 18:00", () => {
const now = new Date(today.getFullYear(), today.getMonth(), today.getDate(), 18, 0, 0);
expect(willOpenAgainToday(oh, now)).to.equal(false);
});
it("should return false at 23:59", () => {
const now = new Date(today.getFullYear(), today.getMonth(), today.getDate(), 23, 59, 0);
expect(willOpenAgainToday(oh, now)).to.equal(false);
});
describe("with one opening in the day", () => {
const ohOneOpening = "09:00-18:00";
it("should return false the all day, 10h case", () => {
const now = new Date(today.getFullYear(), today.getMonth(), today.getDate(), 10, 0, 0);
expect(willOpenAgainToday(ohOneOpening, now)).to.equal(false);
})
it("should return false the all day, 8h case", () => {
const now = new Date(today.getFullYear(), today.getMonth(), today.getDate(), 8, 0, 0);
expect(willOpenAgainToday(ohOneOpening, now)).to.equal(false);
})
it("should return false the all day, 19h case", () => {
const now = new Date(today.getFullYear(), today.getMonth(), today.getDate(), 19, 0, 0);
expect(willOpenAgainToday(ohOneOpening, now)).to.equal(false);
})
it("should return false the all day, 23h59 case", () => {
const now = new Date(today.getFullYear(), today.getMonth(), today.getDate(), 23, 59, 0);
expect(willOpenAgainToday(ohOneOpening, now)).to.equal(false);
})
})
});
describe("getTodaysNextOpening", () => {
const oh = "08:00-10:00, 11:00-13:00, 14:00-16:00";
const today = new Date();
it("should return 08:00 at 00:00", () => {
const now = new Date(today.getFullYear(), today.getMonth(), today.getDate(), 0, 0, 0);
const next_opening = new Date(today.getFullYear(), today.getMonth(), today.getDate(), 8, 0, 0);
expect(getTodaysNextOpening(oh, now)).to.equalDate(next_opening);
});
it("should return 08:00 at 06:00", () => {
const now = new Date(today.getFullYear(), today.getMonth(), today.getDate(), 6, 0, 0);
const next_opening = new Date(today.getFullYear(), today.getMonth(), today.getDate(), 8, 0, 0);
expect(getTodaysNextOpening(oh, now)).to.equalDate(next_opening);
});
it("should return 11:00 at 10:00", () => {
const now = new Date(today.getFullYear(), today.getMonth(), today.getDate(), 10, 0, 0);
const next_opening = new Date(today.getFullYear(), today.getMonth(), today.getDate(), 11, 0, 0);
expect(getTodaysNextOpening(oh, now)).to.equalDate(next_opening);
});
it("should return 14:00 at 12:00", () => {
const now = new Date(today.getFullYear(), today.getMonth(), today.getDate(), 12, 0, 0);
const next_opening = new Date(today.getFullYear(), today.getMonth(), today.getDate(), 14, 0, 0);
expect(getTodaysNextOpening(oh, now)).to.equalDate(next_opening);
});
it("should return null at 15:00", () => {
const now = new Date(today.getFullYear(), today.getMonth(), today.getDate(), 15, 0, 0);
expect(getTodaysNextOpening(oh, now)).to.equal(null);
});
it("should return null at 18:00", () => {
const now = new Date(today.getFullYear(), today.getMonth(), today.getDate(), 18, 0, 0);
expect(getTodaysNextOpening(oh, now)).to.equal(null);
});
it("should return null at 23:59", () => {
const now = new Date(today.getFullYear(), today.getMonth(), today.getDate(), 23, 59, 0);
expect(getTodaysNextOpening(oh, now)).to.equal(null);
});
});
describe("getOpeningCountsFromRange", () => {
it("should return 0 for 0 days", () => {
expect(getOpeningCountsFromRange("08:00-10:00, 11:00-13:00, 14:00-16:00", moment(), moment())).to.equal(0);
});
it("should return 1 for 1 opening in the time range", () => {
const oh = "May 9 13:10-14:00";
const start = moment("2022-01-01");
const end = moment("2022-12-31");
expect(getOpeningCountsFromRange(oh, start, end)).to.equal(1);
});
it("should return 1 for 1 opening in the time range of two years with OH specifying year", () => {
const oh = "2022 May 9 13:10-14:00";
const start = moment("2022-01-01");
const end = moment("2023-12-31");
expect(getOpeningCountsFromRange(oh, start, end)).to.equal(1);
});
it("should return 2 for opening each year in a range of two years without OH specifying year", () => {
const oh = "May 9 13:10-14:00";
const start = moment("2022-01-01");
const end = moment("2023-12-31");
expect(getOpeningCountsFromRange(oh, start, end)).to.equal(2);
});
it("should return the correct number of days", () => {
// The 10 and 20 of next month
const month = MONTH_SHORT[moment().month() + 1] || MONTH_SHORT[0];
const oh = `${month} 10; ${month} 20; PH off`;
const start = moment().add(1, "month").startOf("month");
const end = moment().add(1, "month").endOf("month");
expect(getOpeningCountsFromRange(oh, start, end)).to.equal(2);
});
it("should return the correct number for a periodicity", () => {
const oh = "Mo-Fr 10:00-12:00;"; // 20 days
const start = moment("2022-01-01");
const end = moment("2022-01-31");
expect(getOpeningCountsFromRange(oh, start, end)).to.equal(20);
});
it("should return the correct number for an opening every two weeks in a year", () => {
const oh = "08:00-11:00"; // 20 days
const start = moment("2022-01-01").hour(0).minute(0).second(0).millisecond(0);
const end = moment("2022-12-31").hour(23).minute(59).second(59).millisecond(999);
expect(getOpeningCountsFromRange(oh, start, end)).to.equal(365);
});
});
describe("openOnceAYear", () => {
it("should return true if year periodicity and no year in OH", () => {
const oh = "May 9 13:10-14:00";
expect(openOnceAYear(oh)).to.be.true;
});
it("should return true if year periodicity and year in OH", () => {
const oh = "2022 May 9 13:10-14:00";
expect(openOnceAYear(oh)).to.be.true;
});
it("should return true if opens in two different years", () => {
const oh = "2022 May 9 13:10-14:00; 2023 May 10 13:10-14:00";
expect(openOnceAYear(oh)).to.be.true;
});
it("should return false if opens in two times in the same year", () => {
const oh = "2023 May 9 13:10-14:00; 2023 May 10 13:10-14:00";
expect(openOnceAYear(oh)).to.be.false;
});
it("should return false if opens in two times without specifying year", () => {
const oh = "May 9 13:10-14:00; May 10 13:10-14:00";
expect(openOnceAYear(oh)).to.be.false;
});
it("should return false if it's a period", () => {
const oh = "Mo-Fr 10:00-12:00";
expect(openOnceAYear(oh)).to.be.false;
});
it("should handle an empty string", () => {
expect(openOnceAYear("")).to.be.false;
});
});
describe("getLastKnownOpeningDate", () => {
it("should return the last known opening date", () => {
const oh = "2022 May 9 13:10-14:00; 2023 May 10 13:10-14:00";
const lastKnownOpeningDate = getLastKnownOpeningDate(oh);
lastKnownOpeningDate.setHours(0, 0, 0, 0);
expect(lastKnownOpeningDate).to.equalDate(new Date("2023-05-10T00:00:00.000Z"));
});
it("should return the last known opening date", () => {
const oh = "2022 Jan 01-2023 Jan 15 Mo,Tu,Th,Fr,Su 18:00-24:00";
const lastKnownOpeningDate = getLastKnownOpeningDate(oh);
lastKnownOpeningDate.setHours(0, 0, 0, 0);
expect(lastKnownOpeningDate).to.equalDate(new Date("2023-01-15T00:00:00.000Z"));
});
it("should handle an infinite OH", () => {
const oh = "Mo-Fr 10:00-12:00";
const lastKnownOpeningDate = getLastKnownOpeningDate(oh);
expect(lastKnownOpeningDate).to.be.undefined;
});
it("should handle an infinite OH (24/7)", () => {
const oh = "24/7";
const lastKnownOpeningDate = getLastKnownOpeningDate(oh);
expect(lastKnownOpeningDate).to.be.undefined;
});
});
});