cronofy-elements
Advanced tools
Comparing version 1.24.1 to 1.25.0
{ | ||
"name": "cronofy-elements", | ||
"version": "1.24.1", | ||
"version": "1.25.0", | ||
"description": "Fast track scheduling with Cronofy's embeddable UI Elements", | ||
@@ -5,0 +5,0 @@ "main": "build/npm/CronofyElements.js", |
@@ -1,3 +0,2 @@ | ||
import React, { useState, useEffect } from "react"; | ||
import moment from "moment"; | ||
import React, { useState, useEffect, useRef } from "react"; | ||
import { css, jsx } from "@emotion/core"; | ||
@@ -15,2 +14,3 @@ | ||
checkSelectedState, | ||
cropDaysToWindow, | ||
cropQuery, | ||
@@ -101,10 +101,11 @@ generatePageSlots, | ||
const [slotData, setSlotData] = useState(generateDummySlots()); | ||
const [pages, setPages] = useState({ | ||
set: false, | ||
current: 1, | ||
days: [], | ||
total: 0 | ||
days: slotData.map(slotsWeek => slotsWeek.day), | ||
total: 1 | ||
}); | ||
const [slotData, setSlotData] = useState(generateDummySlots()); | ||
const [slotsForPage, setSlotsForPage] = useState(() => | ||
@@ -121,2 +122,4 @@ getSlotsForPage(slotData, pages.current) | ||
const debounceTimeout = useRef(); | ||
const triggerSlotsForPage = () => { | ||
@@ -226,5 +229,8 @@ const slots = getSlotsForPage(slotData, pages.current); | ||
const handleEmptyAvailability = (res, query) => { | ||
const handleEmptyAvailability = (empty, query) => { | ||
// Remove `max_results` from the query | ||
const { max_results, ...cleanQuery } = query; | ||
let notification; | ||
if (res.length < 1) { | ||
if (empty) { | ||
// There is no availability for any of the | ||
@@ -235,3 +241,3 @@ // pages shown in the viewer. | ||
type: "no_slots_found", | ||
query: query | ||
query: cleanQuery | ||
} | ||
@@ -252,3 +258,15 @@ }; | ||
const checkAllAvailability = query => { | ||
const checkAllAvailability = (query, days = false) => { | ||
// Ensure we're not querying more than 35 days. | ||
const croppedDays = cropDaysToWindow(days ? days : pages.days); | ||
// NOTE: if `days` is set then we're recurring and `days` | ||
// represents the remaining days to be queried. If `days` | ||
// is not set then this is the first time round, so we'll | ||
// use all the days from `pages`. | ||
// If there's an `overflow`, we'll want to keep recurring | ||
// until all the days have been queried (or until we find | ||
// an available slot). | ||
const recur = croppedDays.overflow.length > 0; | ||
// At this point we're only interested in the binary | ||
@@ -262,3 +280,3 @@ // question of has-availability/has-no-availability. | ||
currentPage: pages.current, | ||
days: pages.days, | ||
days: croppedDays.days, | ||
startTime: limits.start, | ||
@@ -270,5 +288,17 @@ endTime: limits.end, | ||
); | ||
handleGetAvailability({ | ||
query: croppedQuery, | ||
callback: res => handleEmptyAvailability(res, croppedQuery) | ||
callback: res => { | ||
if (res.length < 1) { | ||
if (recur) { | ||
return checkAllAvailability( | ||
query, | ||
croppedDays.overflow | ||
); | ||
} | ||
return handleEmptyAvailability(true, croppedQuery); | ||
} | ||
return handleEmptyAvailability(false, croppedQuery); | ||
} | ||
}); | ||
@@ -355,2 +385,4 @@ }; | ||
); | ||
clearTimeout(debounceTimeout.current); | ||
}, []); | ||
@@ -360,17 +392,20 @@ | ||
if (!pages.set) return; | ||
triggerSlotsForPage(); | ||
if (rawData && status.mode === "free_select") { | ||
// We're in free_select and we've already got our rawData, so | ||
// let's reset the loading graphics and bail... | ||
setStatus(status => ({ | ||
...status, | ||
error: false, | ||
loading: false, | ||
preloading: false | ||
})); | ||
return; | ||
} | ||
if (debounceTimeout.current) clearTimeout(debounceTimeout.current); | ||
debounceTimeout.current = setTimeout(() => { | ||
triggerSlotsForPage(); | ||
triggerDataFetching(); | ||
if (rawData && status.mode === "free_select") { | ||
// We're in free_select and we've already got our rawData, so | ||
// let's reset the loading graphics and bail... | ||
setStatus(status => ({ | ||
...status, | ||
error: false, | ||
loading: false, | ||
preloading: false | ||
})); | ||
return; | ||
} | ||
triggerDataFetching(); | ||
}, 250); | ||
}, [pages]); | ||
@@ -460,6 +495,6 @@ | ||
> | ||
<WeekWrapper /> | ||
<PagesContext.Provider | ||
value={[pages, setPages]} | ||
> | ||
<WeekWrapper /> | ||
<Footer /> | ||
@@ -466,0 +501,0 @@ </PagesContext.Provider> |
import React, { useContext } from "react"; | ||
import { css, jsx } from "@emotion/core"; | ||
import moment from "moment-timezone"; | ||
import { I18nContext, StatusContext, ThemeContext } from "./AvailabilityViewer"; | ||
import { ThemeContext } from "./AvailabilityViewer"; | ||
const ColumnHeader = ({ day }) => { | ||
const i18n = useContext(I18nContext); | ||
const ColumnHeader = ({ dayNumber, dayName }) => { | ||
const [theme, setTheme] = useContext(ThemeContext); | ||
const [status, setStatus] = useContext(StatusContext); | ||
const dayObject = moment.tz(day.day, "YYYY-MM-DD", status.tzid); | ||
const dayName = i18n.f(dayObject, "ddd"); | ||
const dayNumber = i18n.f(dayObject, "D"); | ||
return ( | ||
@@ -15,0 +9,0 @@ <div |
@@ -6,10 +6,15 @@ import React, { useContext } from "react"; | ||
import { ThemeContext, SlotsContext } from "./AvailabilityViewer"; | ||
import { ThemeContext } from "./AvailabilityViewer"; | ||
import { LabelsContext } from "./WeekWrapper"; | ||
const DayLabels = () => { | ||
const slots = useContext(SlotsContext); | ||
const labels = useContext(LabelsContext); | ||
const [theme, setTheme] = useContext(ThemeContext); | ||
const headers = slots.map(day => ( | ||
<ColumnHeader key={`header__${day.day}`} day={day} /> | ||
const headers = labels.days.map(day => ( | ||
<ColumnHeader | ||
key={`header__${day.date}`} | ||
dayNumber={day.number} | ||
dayName={day.name} | ||
/> | ||
)); | ||
@@ -16,0 +21,0 @@ |
@@ -22,3 +22,3 @@ import React, { useContext, useState } from "react"; | ||
const labelsOutput = labels.map((label, i) => ( | ||
const labelsOutput = labels.times.map((label, i) => ( | ||
<LabelItem key={label.start} label={label} i={i} /> | ||
@@ -25,0 +25,0 @@ )); |
import React, { useContext } from "react"; | ||
import { css, jsx } from "@emotion/core"; | ||
import { getMonthsDescription } from "../../helpers/slots"; | ||
import { ThemeContext } from "./AvailabilityViewer"; | ||
import { LabelsContext } from "./WeekWrapper"; | ||
import { ThemeContext, SlotsContext } from "./AvailabilityViewer"; | ||
const MonthLabels = () => { | ||
const labels = useContext(LabelsContext); | ||
const [theme, setTheme] = useContext(ThemeContext); | ||
const slots = useContext(SlotsContext); | ||
const monthLabel = getMonthsDescription(slots); | ||
return ( | ||
@@ -40,3 +37,3 @@ <div | ||
> | ||
{monthLabel} | ||
{labels.month} | ||
</div> | ||
@@ -43,0 +40,0 @@ </div> |
@@ -12,3 +12,3 @@ import React, { useContext } from "react"; | ||
const labelsOutput = labels.map(label => { | ||
const labelsOutput = labels.times.map(label => { | ||
const lineWidth = label.hour ? "1.5px" : "1px"; | ||
@@ -15,0 +15,0 @@ const dashArray = label.hour ? "3,4" : "1,2"; |
import React, { useContext, useEffect, useState } from "react"; | ||
import { css, jsx } from "@emotion/core"; | ||
import { timeLabels } from "../../helpers/slots"; | ||
import { | ||
checkIfDaysMatch, | ||
getAllLabels | ||
} from "../../helpers/utils.AvailabilityViewer"; | ||
import { useWindowSize } from "../../hooks/useWindowSize"; | ||
@@ -13,5 +16,6 @@ | ||
import { | ||
I18nContext, | ||
PagesContext, | ||
ThemeContext, | ||
LimitsContext, | ||
SlotsContext, | ||
StatusContext | ||
@@ -23,11 +27,21 @@ } from "./AvailabilityViewer"; | ||
const WeekWrapper = () => { | ||
const i18n = useContext(I18nContext); | ||
const [pages, setPages] = useContext(PagesContext); | ||
const [theme, setTheme] = useContext(ThemeContext); | ||
const [status, setStatus] = useContext(StatusContext); | ||
const slots = useContext(SlotsContext); | ||
const [limits, setLimits] = useContext(LimitsContext); | ||
const [labels, setLabels] = useState( | ||
timeLabels(limits, slots[1].day, status.tzid) | ||
// These are the time|day|month labels for *all* weeks. | ||
const [allLabels, setAllLabels] = useState(() => | ||
getAllLabels({ | ||
days: pages.days, | ||
limits, | ||
tzid: status.tzid, | ||
i18n | ||
}) | ||
); | ||
// These are the time|day|month labels for the currently visible week. | ||
const [labels, setLabels] = useState(allLabels[pages.current - 1]); | ||
const gridWrapper = React.createRef(); | ||
@@ -67,5 +81,30 @@ const size = useWindowSize(); | ||
useEffect(() => { | ||
setLabels(timeLabels(limits, slots[1].day, status.tzid)); | ||
}, [slots, limits]); | ||
if (pages.set) { | ||
// Have the days changed? | ||
const daysMatch = checkIfDaysMatch(pages.days, allLabels); | ||
if (!daysMatch) { | ||
// If they've changed we need to recalculate labels, but | ||
// this is expensive so we don't want to do it unless we | ||
// absolutely have to. | ||
setAllLabels( | ||
getAllLabels({ | ||
days: pages.days, | ||
limits, | ||
tzid: status.tzid, | ||
i18n | ||
}) | ||
); | ||
} else { | ||
setLabels(allLabels[pages.current - 1]); | ||
} | ||
} | ||
}, [pages]); | ||
useEffect(() => { | ||
// If `allLabels` is updated, make sure we | ||
// recalculate the active labels too. | ||
setLabels(allLabels[pages.current - 1]); | ||
}, [allLabels]); | ||
return ( | ||
@@ -72,0 +111,0 @@ <LabelsContext.Provider value={labels}> |
const moment = require("moment-timezone"); | ||
import { uniqueItems } from "./utils"; | ||
export const getDaysFromAvailablePeriods = ( | ||
periods, | ||
locale, | ||
tzid | ||
) => { | ||
return periods.reduce( (slots, period) => { | ||
export const getDaysFromAvailablePeriods = (periods, locale, tzid) => { | ||
return periods.reduce((slots, period) => { | ||
const startTime = moment(period.start).tz(tzid).locale(locale); | ||
@@ -14,3 +10,3 @@ const endTime = moment(period.end).tz(tzid).locale(locale); | ||
if(slots[formattedDay] === undefined) { | ||
if (slots[formattedDay] === undefined) { | ||
slots[formattedDay] = { | ||
@@ -20,19 +16,19 @@ value: formattedDay, | ||
slots: [] | ||
} | ||
}; | ||
} | ||
const periodLabel = `${formatSlotTimeLabel(startTime)} - ${formatSlotTimeLabel(endTime)}` | ||
const periodLabel = `${formatSlotTimeLabel( | ||
startTime | ||
)} - ${formatSlotTimeLabel(endTime)}`; | ||
slots[formattedDay].slots.push( | ||
{ | ||
label: periodLabel, | ||
value: period | ||
} | ||
) | ||
slots[formattedDay].slots.push({ | ||
label: periodLabel, | ||
value: period | ||
}); | ||
return slots; | ||
return slots; | ||
}, {}); | ||
}; | ||
const formatSlotTimeLabel = (time) => time.format("LT").replace(" ", ""); | ||
const formatSlotTimeLabel = time => time.format("LT").replace(" ", ""); | ||
@@ -273,7 +269,7 @@ export const slotsFromPeriod = (period, duration, acc = []) => { | ||
.utc() | ||
.format(`YYYY-MM-DDTHH:mm[:00]`), | ||
.format(`YYYY-MM-DDTHH:mm[:00Z]`), | ||
end: moment | ||
.tz(`${endDay}T${limits.end}`, "YYYY-MM-DDTHH:mm", tzid) | ||
.utc() | ||
.format(`YYYY-MM-DDTHH:mm[:00]`) | ||
.format(`YYYY-MM-DDTHH:mm[:00Z]`) | ||
}; | ||
@@ -327,5 +323,5 @@ const slots = createEmptySlotsForPeriod(timeLabelPeriod, limits.interval); | ||
export const getMonthsDescription = slots => { | ||
const coverage = slots | ||
.map(slot => moment.utc(slot.day, "YYYY-MM-DD")) | ||
export const getMonthsDescription = days => { | ||
const coverage = days | ||
.map(day => moment.utc(day, "YYYY-MM-DD")) | ||
.reduce( | ||
@@ -332,0 +328,0 @@ (acc, curr) => { |
import moment from "moment-timezone"; | ||
import { createEmptySlotsForPeriod, roundPeriod } from "./slots"; | ||
import { | ||
createEmptySlotsForPeriod, | ||
getMonthsDescription, | ||
roundPeriod | ||
} from "./slots"; | ||
import { objectToArray } from "./utils"; | ||
import { timeLabels } from "./slots"; | ||
@@ -732,1 +737,77 @@ // Use the slot's "start" time-string as the | ||
.replace(" ", ""); | ||
export const cropDaysToWindow = (rawDays, windowSize = 34) => { | ||
const days = rawDays.slice(0, windowSize); | ||
const overflow = rawDays.slice(windowSize - 1, rawDays.length); | ||
return { days, overflow }; | ||
}; | ||
export const getAllLabels = ({ days, limits, tzid, i18n }) => { | ||
// For each week that the AV could potentially show we | ||
// want to calculate: | ||
// 1. An array of days in that week | ||
// 2. An array of time label info (start-time | end-time | is-hour?) | ||
// 3. The appropriate month label for the week | ||
// Generate an array with one empty item for each week. | ||
const emptyWeeks = Array.from(new Array(Math.ceil(days.length / 7))); | ||
// Add the days to each week. | ||
const weeksWithDays = emptyWeeks.map((_, i) => { | ||
const start = i * 7; | ||
const end = start + 7; | ||
const weeklyDays = days.slice(start, end); | ||
const dayObjects = weeklyDays.map(day => { | ||
const dayObject = moment.tz(day, "YYYY-MM-DD", tzid); | ||
return { | ||
date: day, | ||
number: i18n.f(dayObject, "D"), | ||
name: i18n.f(dayObject, "ddd") | ||
}; | ||
}); | ||
return { days: dayObjects }; | ||
}); | ||
// Add the time labels to each week. | ||
const weeksWithTimes = weeksWithDays.map(week => { | ||
// `days[1]` is the second day in the week (Monday) so that even on | ||
// weeks where there is a DST transition on a Sunday, the labels are | ||
// accurate for the main bulk of the days shown. | ||
return { | ||
...week, | ||
times: timeLabels(limits, week.days[1].date, tzid) | ||
}; | ||
}); | ||
// Add a month label to each week [TODO] | ||
const weeksWithMonths = weeksWithTimes.map(week => { | ||
const simpleDaysArray = week.days.map(day => day.date); | ||
return { | ||
...week, | ||
month: getMonthsDescription(simpleDaysArray) | ||
}; | ||
}); | ||
return weeksWithMonths; | ||
}; | ||
// Do the days stored in our `allLabels` state match the days | ||
// in our `pages` context? | ||
export const checkIfDaysMatch = (days, allLabels) => { | ||
if (typeof allLabels !== "object" || allLabels.length <= 0) { | ||
// We have no saved days, so they definitely do not match | ||
return false; | ||
} | ||
// First and last days from `pages` | ||
const firstDay = days[0]; | ||
const lastDay = days[days.length - 1]; | ||
// First and last days from `allLabels` | ||
const firstSavedDay = allLabels[0].days[0].date; | ||
const lastSavedWeek = allLabels[allLabels.length - 1].days; | ||
const lastSavedDay = lastSavedWeek[lastSavedWeek.length - 1].date; | ||
return firstDay === firstSavedDay && lastDay === lastSavedDay; | ||
}; |
import * as utils from "../src/js/helpers/utils.AvailabilityViewer"; | ||
// import moment from "moment"; | ||
@@ -89,4 +88,10 @@ describe("Utilities: AvailabilityViewer", () => { | ||
const expectedOutput = { | ||
max: "2019-05-07", | ||
min: "2019-04-06" | ||
max: moment | ||
.utc("2019-05-07T08:00:00Z", "YYYY-MM-DDTHH:mm:00Z") | ||
.local() | ||
.format("YYYY-MM-DD"), | ||
min: moment | ||
.utc("2019-04-06T08:00:00Z", "YYYY-MM-DDTHH:mm:00Z") | ||
.local() | ||
.format("YYYY-MM-DD") | ||
}; | ||
@@ -105,358 +110,404 @@ | ||
// getAllWeekDays | ||
it("gets all the week days for a given period", () => { | ||
const input = { | ||
startDate: "2019-04-02", // Tue | ||
endDate: "2019-04-04" // Thu | ||
}; | ||
describe("getAllWeekDays", () => { | ||
it("gets all the week days for a given period", () => { | ||
const input = { | ||
startDate: "2019-04-02", // Tue | ||
endDate: "2019-04-04" // Thu | ||
}; | ||
const out = [ | ||
"2019-03-31", // Sun | ||
"2019-04-01", // Mon | ||
"2019-04-02", // Tue | ||
"2019-04-03", // Wed | ||
"2019-04-04", // Thu | ||
"2019-04-05", // Fri | ||
"2019-04-06" // Sat | ||
]; | ||
expect(utils.getAllWeekDays(input)).toEqual(out); | ||
}); | ||
const out = [ | ||
"2019-03-31", // Sun | ||
"2019-04-01", // Mon | ||
"2019-04-02", // Tue | ||
"2019-04-03", // Wed | ||
"2019-04-04", // Thu | ||
"2019-04-05", // Fri | ||
"2019-04-06" // Sat | ||
]; | ||
expect(utils.getAllWeekDays(input)).toEqual(out); | ||
}); | ||
it("gets all the week days for a given period with a specific start day", () => { | ||
const input = { | ||
startDate: "2019-04-02", // Tue | ||
endDate: "2019-04-04", // Thu | ||
startDay: "wednesday" | ||
}; | ||
it("gets all the week days for a given period with a specific start day", () => { | ||
const input = { | ||
startDate: "2019-04-02", // Tue | ||
endDate: "2019-04-04", // Thu | ||
startDay: "wednesday" | ||
}; | ||
const out = [ | ||
"2019-03-27", // Wed | ||
"2019-03-28", // Thu | ||
"2019-03-29", // Fri | ||
"2019-03-30", // Sat | ||
"2019-03-31", // Sun | ||
"2019-04-01", // Mon | ||
"2019-04-02", // Tue | ||
"2019-04-03", // Wed | ||
"2019-04-04", // Thu | ||
"2019-04-05", // Fri | ||
"2019-04-06", // Sat | ||
"2019-04-07", // Sun | ||
"2019-04-08", // Mon | ||
"2019-04-09" // Tue | ||
]; | ||
expect(utils.getAllWeekDays(input)).toEqual(out); | ||
}); | ||
const out = [ | ||
"2019-03-27", // Wed | ||
"2019-03-28", // Thu | ||
"2019-03-29", // Fri | ||
"2019-03-30", // Sat | ||
"2019-03-31", // Sun | ||
"2019-04-01", // Mon | ||
"2019-04-02", // Tue | ||
"2019-04-03", // Wed | ||
"2019-04-04", // Thu | ||
"2019-04-05", // Fri | ||
"2019-04-06", // Sat | ||
"2019-04-07", // Sun | ||
"2019-04-08", // Mon | ||
"2019-04-09" // Tue | ||
]; | ||
expect(utils.getAllWeekDays(input)).toEqual(out); | ||
}); | ||
it("gets all the week days for a given period that spans two weeks", () => { | ||
const input = { | ||
startDate: "2019-04-02", // Tue 1 | ||
endDate: "2019-04-10" // Wed 2 | ||
}; | ||
it("gets all the week days for a given period that spans two weeks", () => { | ||
const input = { | ||
startDate: "2019-04-02", // Tue 1 | ||
endDate: "2019-04-10" // Wed 2 | ||
}; | ||
const out = [ | ||
"2019-03-31", // Sun | ||
"2019-04-01", // Mon | ||
"2019-04-02", // Tue | ||
"2019-04-03", // Wed | ||
"2019-04-04", // Thu | ||
"2019-04-05", // Fri | ||
"2019-04-06", // Sat | ||
"2019-04-07", // Sun 2 | ||
"2019-04-08", // Mon 2 | ||
"2019-04-09", // Tue 2 | ||
"2019-04-10", // Wed 2 | ||
"2019-04-11", // Thu 2 | ||
"2019-04-12", // Fri 2 | ||
"2019-04-13" // Sat 2 | ||
]; | ||
const out = [ | ||
"2019-03-31", // Sun | ||
"2019-04-01", // Mon | ||
"2019-04-02", // Tue | ||
"2019-04-03", // Wed | ||
"2019-04-04", // Thu | ||
"2019-04-05", // Fri | ||
"2019-04-06", // Sat | ||
"2019-04-07", // Sun 2 | ||
"2019-04-08", // Mon 2 | ||
"2019-04-09", // Tue 2 | ||
"2019-04-10", // Wed 2 | ||
"2019-04-11", // Thu 2 | ||
"2019-04-12", // Fri 2 | ||
"2019-04-13" // Sat 2 | ||
]; | ||
expect(utils.getAllWeekDays(input)).toEqual(out); | ||
}); | ||
expect(utils.getAllWeekDays(input)).toEqual(out); | ||
}); | ||
it("gets all the week days for a given period that spans two weeks with a specific start day", () => { | ||
const input = { | ||
startDate: "2019-04-04", // Thu 1 | ||
endDate: "2019-04-10", // Wed 2 | ||
startDay: "wednesday" | ||
}; | ||
it("gets all the week days for a given period that spans two weeks with a specific start day", () => { | ||
const input = { | ||
startDate: "2019-04-04", // Thu 1 | ||
endDate: "2019-04-10", // Wed 2 | ||
startDay: "wednesday" | ||
}; | ||
const out = [ | ||
"2019-04-03", // Wed | ||
"2019-04-04", // Thu | ||
"2019-04-05", // Fri | ||
"2019-04-06", // Sat | ||
"2019-04-07", // Sun | ||
"2019-04-08", // Mon | ||
"2019-04-09", // Tue | ||
"2019-04-10", // Wed 2 | ||
"2019-04-11", // Thu 2 | ||
"2019-04-12", // Fri 2 | ||
"2019-04-13", // Sat 2 | ||
"2019-04-14", // Sun 2 | ||
"2019-04-15", // Mon 2 | ||
"2019-04-16" // Tue 2 | ||
]; | ||
const out = [ | ||
"2019-04-03", // Wed | ||
"2019-04-04", // Thu | ||
"2019-04-05", // Fri | ||
"2019-04-06", // Sat | ||
"2019-04-07", // Sun | ||
"2019-04-08", // Mon | ||
"2019-04-09", // Tue | ||
"2019-04-10", // Wed 2 | ||
"2019-04-11", // Thu 2 | ||
"2019-04-12", // Fri 2 | ||
"2019-04-13", // Sat 2 | ||
"2019-04-14", // Sun 2 | ||
"2019-04-15", // Mon 2 | ||
"2019-04-16" // Tue 2 | ||
]; | ||
expect(utils.getAllWeekDays(input)).toEqual(out); | ||
}); | ||
expect(utils.getAllWeekDays(input)).toEqual(out); | ||
}); | ||
it("gets all the week days for a given period that spans three weeks", () => { | ||
const input = { | ||
startDate: "2019-04-02", // Tue 1 | ||
endDate: "2019-04-16" // Tue 3 | ||
}; | ||
it("gets all the week days for a given period that spans three weeks", () => { | ||
const input = { | ||
startDate: "2019-04-02", // Tue 1 | ||
endDate: "2019-04-16" // Tue 3 | ||
}; | ||
const out = [ | ||
"2019-03-31", // Sun | ||
"2019-04-01", // Mon | ||
"2019-04-02", // Tue | ||
"2019-04-03", // Wed | ||
"2019-04-04", // Thu | ||
"2019-04-05", // Fri | ||
"2019-04-06", // Sat | ||
"2019-04-07", // Sun 2 | ||
"2019-04-08", // Mon 2 | ||
"2019-04-09", // Tue 2 | ||
"2019-04-10", // Wed 2 | ||
"2019-04-11", // Thu 2 | ||
"2019-04-12", // Fri 2 | ||
"2019-04-13", // Sat 2 | ||
"2019-04-14", // Sun 3 | ||
"2019-04-15", // Mon 3 | ||
"2019-04-16", // Tue 3 | ||
"2019-04-17", // Wed 3 | ||
"2019-04-18", // Thu 3 | ||
"2019-04-19", // Fri 3 | ||
"2019-04-20" // Sat 3 | ||
]; | ||
const out = [ | ||
"2019-03-31", // Sun | ||
"2019-04-01", // Mon | ||
"2019-04-02", // Tue | ||
"2019-04-03", // Wed | ||
"2019-04-04", // Thu | ||
"2019-04-05", // Fri | ||
"2019-04-06", // Sat | ||
"2019-04-07", // Sun 2 | ||
"2019-04-08", // Mon 2 | ||
"2019-04-09", // Tue 2 | ||
"2019-04-10", // Wed 2 | ||
"2019-04-11", // Thu 2 | ||
"2019-04-12", // Fri 2 | ||
"2019-04-13", // Sat 2 | ||
"2019-04-14", // Sun 3 | ||
"2019-04-15", // Mon 3 | ||
"2019-04-16", // Tue 3 | ||
"2019-04-17", // Wed 3 | ||
"2019-04-18", // Thu 3 | ||
"2019-04-19", // Fri 3 | ||
"2019-04-20" // Sat 3 | ||
]; | ||
expect(utils.getAllWeekDays(input)).toEqual(out); | ||
}); | ||
expect(utils.getAllWeekDays(input)).toEqual(out); | ||
}); | ||
it("gets all the week days for a given period that spans three weeks with a specific start day", () => { | ||
const input = { | ||
startDate: "2019-04-04", // Thu 1 | ||
endDate: "2019-04-18", // Thu 3 | ||
startDay: "wednesday" | ||
}; | ||
it("gets all the week days for a given period that spans three weeks with a specific start day", () => { | ||
const input = { | ||
startDate: "2019-04-04", // Thu 1 | ||
endDate: "2019-04-18", // Thu 3 | ||
startDay: "wednesday" | ||
}; | ||
const out = [ | ||
"2019-04-03", // Wed | ||
"2019-04-04", // Thu | ||
"2019-04-05", // Fri | ||
"2019-04-06", // Sat | ||
"2019-04-07", // Sun | ||
"2019-04-08", // Mon | ||
"2019-04-09", // Tue | ||
"2019-04-10", // Wed 2 | ||
"2019-04-11", // Thu 2 | ||
"2019-04-12", // Fri 2 | ||
"2019-04-13", // Sat 2 | ||
"2019-04-14", // Sun 2 | ||
"2019-04-15", // Mon 2 | ||
"2019-04-16", // Tue 2 | ||
"2019-04-17", // Wed 3 | ||
"2019-04-18", // Thu 3 | ||
"2019-04-19", // Fri 3 | ||
"2019-04-20", // Sat 3 | ||
"2019-04-21", // Sun 3 | ||
"2019-04-22", // Mon 3 | ||
"2019-04-23" // Tue 3 | ||
]; | ||
const out = [ | ||
"2019-04-03", // Wed | ||
"2019-04-04", // Thu | ||
"2019-04-05", // Fri | ||
"2019-04-06", // Sat | ||
"2019-04-07", // Sun | ||
"2019-04-08", // Mon | ||
"2019-04-09", // Tue | ||
"2019-04-10", // Wed 2 | ||
"2019-04-11", // Thu 2 | ||
"2019-04-12", // Fri 2 | ||
"2019-04-13", // Sat 2 | ||
"2019-04-14", // Sun 2 | ||
"2019-04-15", // Mon 2 | ||
"2019-04-16", // Tue 2 | ||
"2019-04-17", // Wed 3 | ||
"2019-04-18", // Thu 3 | ||
"2019-04-19", // Fri 3 | ||
"2019-04-20", // Sat 3 | ||
"2019-04-21", // Sun 3 | ||
"2019-04-22", // Mon 3 | ||
"2019-04-23" // Tue 3 | ||
]; | ||
expect(utils.getAllWeekDays(input)).toEqual(out); | ||
}); | ||
expect(utils.getAllWeekDays(input)).toEqual(out); | ||
}); | ||
it("gets all the week days for a given period that starts on a Sunday", () => { | ||
const input = { | ||
startDate: "2020-06-07", // Sun | ||
endDate: "2020-06-10" // Wed | ||
}; | ||
it("gets all the week days for a given period that starts on a Sunday", () => { | ||
const input = { | ||
startDate: "2020-06-07", // Sun | ||
endDate: "2020-06-10" // Wed | ||
}; | ||
const out = [ | ||
"2020-06-07", // Sun | ||
"2020-06-08", // Mon | ||
"2020-06-09", // Tue | ||
"2020-06-10", // Wed | ||
"2020-06-11", // Thu | ||
"2020-06-12", // Fri | ||
"2020-06-13" // Sat | ||
]; | ||
const out = [ | ||
"2020-06-07", // Sun | ||
"2020-06-08", // Mon | ||
"2020-06-09", // Tue | ||
"2020-06-10", // Wed | ||
"2020-06-11", // Thu | ||
"2020-06-12", // Fri | ||
"2020-06-13" // Sat | ||
]; | ||
expect(utils.getAllWeekDays(input)).toEqual(out); | ||
}); | ||
expect(utils.getAllWeekDays(input)).toEqual(out); | ||
}); | ||
it("gets all the week days for a given period that starts on a Saturday", () => { | ||
const input = { | ||
startDate: "2020-06-06", // Sat | ||
endDate: "2020-06-10" // Wed | ||
}; | ||
it("gets all the week days for a given period that starts on a Saturday", () => { | ||
const input = { | ||
startDate: "2020-06-06", // Sat | ||
endDate: "2020-06-10" // Wed | ||
}; | ||
const out = [ | ||
"2020-05-31", // Sun | ||
"2020-06-01", // Mon | ||
"2020-06-02", // Tue | ||
"2020-06-03", // Wed | ||
"2020-06-04", // Thu | ||
"2020-06-05", // Fri | ||
"2020-06-06", // Sat | ||
"2020-06-07", // Sun | ||
"2020-06-08", // Mon | ||
"2020-06-09", // Tue | ||
"2020-06-10", // Wed | ||
"2020-06-11", // Thu | ||
"2020-06-12", // Fri | ||
"2020-06-13" // Sat | ||
]; | ||
const out = [ | ||
"2020-05-31", // Sun | ||
"2020-06-01", // Mon | ||
"2020-06-02", // Tue | ||
"2020-06-03", // Wed | ||
"2020-06-04", // Thu | ||
"2020-06-05", // Fri | ||
"2020-06-06", // Sat | ||
"2020-06-07", // Sun | ||
"2020-06-08", // Mon | ||
"2020-06-09", // Tue | ||
"2020-06-10", // Wed | ||
"2020-06-11", // Thu | ||
"2020-06-12", // Fri | ||
"2020-06-13" // Sat | ||
]; | ||
expect(utils.getAllWeekDays(input)).toEqual(out); | ||
}); | ||
expect(utils.getAllWeekDays(input)).toEqual(out); | ||
}); | ||
it("gets all the week days for a given period that starts on the same day as provided as a week_start_day", () => { | ||
const input = { | ||
startDate: "2020-06-09", // Tue | ||
endDate: "2020-06-12", // Fri | ||
startDay: "tuesday" | ||
}; | ||
it("gets all the week days for a given period that starts on the same day as provided as a week_start_day", () => { | ||
const input = { | ||
startDate: "2020-06-09", // Tue | ||
endDate: "2020-06-12", // Fri | ||
startDay: "tuesday" | ||
}; | ||
const out = [ | ||
"2020-06-09", // Tue | ||
"2020-06-10", // Wed | ||
"2020-06-11", // Thu | ||
"2020-06-12", // Fri | ||
"2020-06-13", // Sat | ||
"2020-06-14", // Sun | ||
"2020-06-15" // Mon | ||
]; | ||
const out = [ | ||
"2020-06-09", // Tue | ||
"2020-06-10", // Wed | ||
"2020-06-11", // Thu | ||
"2020-06-12", // Fri | ||
"2020-06-13", // Sat | ||
"2020-06-14", // Sun | ||
"2020-06-15" // Mon | ||
]; | ||
expect(utils.getAllWeekDays(input)).toEqual(out); | ||
expect(utils.getAllWeekDays(input)).toEqual(out); | ||
}); | ||
}); | ||
// cropQuery | ||
const cropExtent = { | ||
startTime: "09:00", | ||
endTime: "17:00", | ||
days: [ | ||
"2020-11-06", | ||
"2020-11-07", | ||
"2020-11-08", | ||
"2020-11-09", | ||
"2020-11-10", | ||
"2020-11-11", | ||
"2020-11-12" | ||
], | ||
currentPage: 1 | ||
}; | ||
const query = { | ||
participants: [ | ||
{ | ||
required: "all", | ||
members: [{ sub: "SUB" }] | ||
} | ||
], | ||
required_duration: { minutes: 60 } | ||
}; | ||
it("correctly crops a single overlapping period", () => { | ||
const input = { | ||
...query, | ||
query_periods: [ | ||
{ start: "2020-11-09T06:00:00Z", end: "2020-11-09T19:00:00Z" } | ||
] | ||
describe("cropQuery", () => { | ||
const cropExtent = { | ||
startTime: "09:00", | ||
endTime: "17:00", | ||
days: [ | ||
"2020-11-06", | ||
"2020-11-07", | ||
"2020-11-08", | ||
"2020-11-09", | ||
"2020-11-10", | ||
"2020-11-11", | ||
"2020-11-12" | ||
], | ||
currentPage: 1 | ||
}; | ||
const out = [ | ||
{ start: "2020-11-09T09:00:00Z", end: "2020-11-09T17:00:00Z" } | ||
]; | ||
expect(utils.cropQuery(input, cropExtent).query_periods).toEqual(out); | ||
}); | ||
it("correctly crops multiple overlapping periods", () => { | ||
const input = { | ||
...query, | ||
query_periods: [ | ||
{ start: "2020-11-09T06:00:00Z", end: "2020-11-09T19:00:00Z" }, | ||
{ start: "2020-11-10T06:00:00Z", end: "2020-11-10T12:00:00Z" }, | ||
{ start: "2020-11-11T06:00:00Z", end: "2020-11-11T19:00:00Z" } | ||
] | ||
const query = { | ||
participants: [ | ||
{ | ||
required: "all", | ||
members: [{ sub: "SUB" }] | ||
} | ||
], | ||
required_duration: { minutes: 60 } | ||
}; | ||
const out = [ | ||
{ start: "2020-11-09T09:00:00Z", end: "2020-11-09T17:00:00Z" }, | ||
{ start: "2020-11-10T09:00:00Z", end: "2020-11-10T12:00:00Z" }, | ||
{ start: "2020-11-11T09:00:00Z", end: "2020-11-11T17:00:00Z" } | ||
]; | ||
expect(utils.cropQuery(input, cropExtent).query_periods).toEqual(out); | ||
}); | ||
it("correctly crops huge overlapping periods", () => { | ||
const input = { | ||
...query, | ||
query_periods: [ | ||
{ start: "2020-10-09T06:00:00Z", end: "2020-12-09T19:00:00Z" } | ||
] | ||
}; | ||
const out = [ | ||
{ start: "2020-11-06T09:00:00Z", end: "2020-11-06T17:00:00Z" }, | ||
{ start: "2020-11-07T09:00:00Z", end: "2020-11-07T17:00:00Z" }, | ||
{ start: "2020-11-08T09:00:00Z", end: "2020-11-08T17:00:00Z" }, | ||
{ start: "2020-11-09T09:00:00Z", end: "2020-11-09T17:00:00Z" }, | ||
{ start: "2020-11-10T09:00:00Z", end: "2020-11-10T17:00:00Z" }, | ||
{ start: "2020-11-11T09:00:00Z", end: "2020-11-11T17:00:00Z" }, | ||
{ start: "2020-11-12T09:00:00Z", end: "2020-11-12T17:00:00Z" } | ||
]; | ||
expect(utils.cropQuery(input, cropExtent).query_periods).toEqual(out); | ||
}); | ||
it("correctly crops a single overlapping period", () => { | ||
const input = { | ||
...query, | ||
query_periods: [ | ||
{ | ||
start: "2020-11-09T06:00:00Z", | ||
end: "2020-11-09T19:00:00Z" | ||
} | ||
] | ||
}; | ||
const out = [ | ||
{ start: "2020-11-09T09:00:00Z", end: "2020-11-09T17:00:00Z" } | ||
]; | ||
expect(utils.cropQuery(input, cropExtent).query_periods).toEqual( | ||
out | ||
); | ||
}); | ||
it("correctly crops tiny overlapping periods", () => { | ||
const input = { | ||
...query, | ||
query_periods: [ | ||
{ start: "2020-11-09T07:00:00Z", end: "2020-11-09T10:00:00Z" }, | ||
it("correctly crops multiple overlapping periods", () => { | ||
const input = { | ||
...query, | ||
query_periods: [ | ||
{ | ||
start: "2020-11-09T06:00:00Z", | ||
end: "2020-11-09T19:00:00Z" | ||
}, | ||
{ | ||
start: "2020-11-10T06:00:00Z", | ||
end: "2020-11-10T12:00:00Z" | ||
}, | ||
{ | ||
start: "2020-11-11T06:00:00Z", | ||
end: "2020-11-11T19:00:00Z" | ||
} | ||
] | ||
}; | ||
const out = [ | ||
{ start: "2020-11-09T09:00:00Z", end: "2020-11-09T17:00:00Z" }, | ||
{ start: "2020-11-10T09:00:00Z", end: "2020-11-10T12:00:00Z" }, | ||
{ start: "2020-11-11T09:00:00Z", end: "2020-11-11T17:00:00Z" } | ||
]; | ||
expect(utils.cropQuery(input, cropExtent).query_periods).toEqual( | ||
out | ||
); | ||
}); | ||
it("correctly crops huge overlapping periods", () => { | ||
const input = { | ||
...query, | ||
query_periods: [ | ||
{ | ||
start: "2020-10-09T06:00:00Z", | ||
end: "2020-12-09T19:00:00Z" | ||
} | ||
] | ||
}; | ||
const out = [ | ||
{ start: "2020-11-06T09:00:00Z", end: "2020-11-06T17:00:00Z" }, | ||
{ start: "2020-11-07T09:00:00Z", end: "2020-11-07T17:00:00Z" }, | ||
{ start: "2020-11-08T09:00:00Z", end: "2020-11-08T17:00:00Z" }, | ||
{ start: "2020-11-09T09:00:00Z", end: "2020-11-09T17:00:00Z" }, | ||
{ start: "2020-11-10T09:00:00Z", end: "2020-11-10T17:00:00Z" }, | ||
{ start: "2020-11-11T09:00:00Z", end: "2020-11-11T17:00:00Z" }, | ||
{ start: "2020-11-12T09:00:00Z", end: "2020-11-12T17:00:00Z" } | ||
]; | ||
expect(utils.cropQuery(input, cropExtent).query_periods).toEqual( | ||
out | ||
); | ||
}); | ||
it("correctly crops tiny overlapping periods", () => { | ||
const input = { | ||
...query, | ||
query_periods: [ | ||
{ | ||
start: "2020-11-09T07:00:00Z", | ||
end: "2020-11-09T10:00:00Z" | ||
}, | ||
{ | ||
start: "2020-11-09T12:00:00Z", | ||
end: "2020-11-09T14:00:00Z" | ||
}, | ||
{ | ||
start: "2020-11-09T16:00:00Z", | ||
end: "2020-11-09T22:00:00Z" | ||
} | ||
] | ||
}; | ||
const out = [ | ||
{ start: "2020-11-09T09:00:00Z", end: "2020-11-09T10:00:00Z" }, | ||
{ start: "2020-11-09T12:00:00Z", end: "2020-11-09T14:00:00Z" }, | ||
{ start: "2020-11-09T16:00:00Z", end: "2020-11-09T22:00:00Z" } | ||
] | ||
}; | ||
const out = [ | ||
{ start: "2020-11-09T09:00:00Z", end: "2020-11-09T10:00:00Z" }, | ||
{ start: "2020-11-09T12:00:00Z", end: "2020-11-09T14:00:00Z" }, | ||
{ start: "2020-11-09T16:00:00Z", end: "2020-11-09T17:00:00Z" } | ||
]; | ||
expect(utils.cropQuery(input, cropExtent).query_periods).toEqual(out); | ||
}); | ||
{ start: "2020-11-09T16:00:00Z", end: "2020-11-09T17:00:00Z" } | ||
]; | ||
expect(utils.cropQuery(input, cropExtent).query_periods).toEqual( | ||
out | ||
); | ||
}); | ||
it("correctly crops non-overlapping periods", () => { | ||
const input = { | ||
...query, | ||
query_periods: [ | ||
{ start: "2020-11-09T07:00:00Z", end: "2020-11-09T12:00:00Z" }, | ||
{ start: "2020-11-10T12:00:00Z", end: "2020-11-10T14:00:00Z" }, | ||
{ start: "2020-11-11T16:00:00Z", end: "2020-11-11T13:00:00Z" } | ||
] | ||
}; | ||
const offsetCropExtent = { | ||
...cropExtent, | ||
startTime: "15:00", | ||
endTime: "17:00" | ||
}; | ||
expect(utils.cropQuery(input, offsetCropExtent).query_periods).toEqual( | ||
[] | ||
); | ||
}); | ||
it("correctly crops non-overlapping periods", () => { | ||
const input = { | ||
...query, | ||
query_periods: [ | ||
{ | ||
start: "2020-11-09T07:00:00Z", | ||
end: "2020-11-09T12:00:00Z" | ||
}, | ||
{ | ||
start: "2020-11-10T12:00:00Z", | ||
end: "2020-11-10T14:00:00Z" | ||
}, | ||
{ | ||
start: "2020-11-11T16:00:00Z", | ||
end: "2020-11-11T13:00:00Z" | ||
} | ||
] | ||
}; | ||
const offsetCropExtent = { | ||
...cropExtent, | ||
startTime: "15:00", | ||
endTime: "17:00" | ||
}; | ||
expect( | ||
utils.cropQuery(input, offsetCropExtent).query_periods | ||
).toEqual([]); | ||
}); | ||
it("correctly crops non-overlapping but abutting periods", () => { | ||
const input = { | ||
...query, | ||
query_periods: [ | ||
{ start: "2020-11-09T07:00:00Z", end: "2020-11-09T15:00:00Z" } | ||
] | ||
}; | ||
const offsetCropExtent = { | ||
...cropExtent, | ||
startTime: "15:00", | ||
endTime: "17:00" | ||
}; | ||
expect(utils.cropQuery(input, offsetCropExtent).query_periods).toEqual( | ||
[] | ||
); | ||
it("correctly crops non-overlapping but abutting periods", () => { | ||
const input = { | ||
...query, | ||
query_periods: [ | ||
{ | ||
start: "2020-11-09T07:00:00Z", | ||
end: "2020-11-09T15:00:00Z" | ||
} | ||
] | ||
}; | ||
const offsetCropExtent = { | ||
...cropExtent, | ||
startTime: "15:00", | ||
endTime: "17:00" | ||
}; | ||
expect( | ||
utils.cropQuery(input, offsetCropExtent).query_periods | ||
).toEqual([]); | ||
}); | ||
}); | ||
@@ -743,3 +794,9 @@ | ||
}; | ||
const out = { min: "2020-11-06", max: "2020-11-12" }; | ||
const out = { | ||
min: moment | ||
.utc("2020-11-06T09:00:00Z") | ||
.local() | ||
.format("YYYY-MM-DD"), | ||
max: moment.utc("2020-11-12T17:00:00Z").local().format("YYYY-MM-DD") | ||
}; | ||
expect(utils.getMinMaxDates(input)).toEqual(out); | ||
@@ -871,193 +928,195 @@ }); | ||
// buildPeriodsFromSlots | ||
it("combines abutting slots into periods", () => { | ||
const slots = [ | ||
{ | ||
start: "2020-06-16T08:00:00Z", | ||
end: "2020-06-16T08:30:00Z" | ||
}, | ||
{ | ||
start: "2020-06-16T08:30:00Z", | ||
end: "2020-06-16T09:00:00Z" | ||
}, | ||
{ | ||
start: "2020-06-16T10:00:00Z", | ||
end: "2020-06-16T10:30:00Z" | ||
}, | ||
{ | ||
start: "2020-06-16T10:30:00Z", | ||
end: "2020-06-16T11:00:00Z" | ||
}, | ||
{ | ||
start: "2020-06-16T11:00:00Z", | ||
end: "2020-06-16T11:30:00Z" | ||
} | ||
]; | ||
const expectedPeriods = [ | ||
{ | ||
start: "2020-06-16T08:00:00Z", | ||
end: "2020-06-16T09:00:00Z" | ||
}, | ||
{ | ||
start: "2020-06-16T10:00:00Z", | ||
end: "2020-06-16T11:30:00Z" | ||
} | ||
]; | ||
const periods = utils.buildPeriodsFromSlots(slots); | ||
expect(periods.length).toEqual(2); | ||
expect(periods[0]).toEqual(expectedPeriods[0]); | ||
}); | ||
describe("buildPeriodsFromSlots", () => { | ||
it("combines abutting slots into periods", () => { | ||
const slots = [ | ||
{ | ||
start: "2020-06-16T08:00:00Z", | ||
end: "2020-06-16T08:30:00Z" | ||
}, | ||
{ | ||
start: "2020-06-16T08:30:00Z", | ||
end: "2020-06-16T09:00:00Z" | ||
}, | ||
{ | ||
start: "2020-06-16T10:00:00Z", | ||
end: "2020-06-16T10:30:00Z" | ||
}, | ||
{ | ||
start: "2020-06-16T10:30:00Z", | ||
end: "2020-06-16T11:00:00Z" | ||
}, | ||
{ | ||
start: "2020-06-16T11:00:00Z", | ||
end: "2020-06-16T11:30:00Z" | ||
} | ||
]; | ||
const expectedPeriods = [ | ||
{ | ||
start: "2020-06-16T08:00:00Z", | ||
end: "2020-06-16T09:00:00Z" | ||
}, | ||
{ | ||
start: "2020-06-16T10:00:00Z", | ||
end: "2020-06-16T11:30:00Z" | ||
} | ||
]; | ||
const periods = utils.buildPeriodsFromSlots(slots); | ||
expect(periods.length).toEqual(2); | ||
expect(periods[0]).toEqual(expectedPeriods[0]); | ||
}); | ||
it("warns when slots are negative length", () => { | ||
const slots = [ | ||
{ | ||
start: "2020-10-23T09:00:00Z", | ||
end: "2020-10-22T09:00:00Z" | ||
} | ||
]; | ||
const expectedPeriods = []; | ||
const periods = utils.buildPeriodsFromSlots(slots); | ||
it("warns when slots are negative length", () => { | ||
const slots = [ | ||
{ | ||
start: "2020-10-23T09:00:00Z", | ||
end: "2020-10-22T09:00:00Z" | ||
} | ||
]; | ||
const expectedPeriods = []; | ||
const periods = utils.buildPeriodsFromSlots(slots); | ||
}); | ||
it("combines unsorted abutting slots into periods", () => { | ||
const slots = [ | ||
{ | ||
start: "2020-06-16T08:30:00Z", | ||
end: "2020-06-16T09:00:00Z" | ||
}, | ||
{ | ||
start: "2020-06-16T08:00:00Z", | ||
end: "2020-06-16T08:30:00Z" | ||
}, | ||
{ | ||
start: "2020-06-16T10:30:00Z", | ||
end: "2020-06-16T11:00:00Z" | ||
}, | ||
{ | ||
start: "2020-06-17T10:30:00Z", | ||
end: "2020-06-17T11:00:00Z" | ||
}, | ||
{ | ||
start: "2020-06-16T11:00:00Z", | ||
end: "2020-06-16T11:30:00Z" | ||
}, | ||
{ | ||
start: "2020-06-16T10:00:00Z", | ||
end: "2020-06-16T10:30:00Z" | ||
} | ||
]; | ||
const expectedPeriods = [ | ||
{ | ||
start: "2020-06-16T08:00:00Z", | ||
end: "2020-06-16T09:00:00Z" | ||
}, | ||
{ | ||
start: "2020-06-16T10:00:00Z", | ||
end: "2020-06-16T11:30:00Z" | ||
}, | ||
{ | ||
start: "2020-06-17T10:30:00Z", | ||
end: "2020-06-17T11:00:00Z" | ||
} | ||
]; | ||
const periods = utils.buildPeriodsFromSlots(slots); | ||
expect(periods.length).toEqual(3); | ||
expect(periods[0]).toEqual(expectedPeriods[0]); | ||
expect(periods[1]).toEqual(expectedPeriods[1]); | ||
expect(periods[2]).toEqual(expectedPeriods[2]); | ||
}); | ||
}); | ||
it("combines unsorted abutting slots into periods", () => { | ||
const slots = [ | ||
{ | ||
start: "2020-06-16T08:30:00Z", | ||
end: "2020-06-16T09:00:00Z" | ||
}, | ||
{ | ||
describe("tweenSlots", () => { | ||
it("calculates tweens for slot-starts", () => { | ||
const options = { | ||
start: "2020-06-16T08:00:00Z", | ||
end: "2020-06-16T08:30:00Z" | ||
}, | ||
{ | ||
start: "2020-06-16T10:30:00Z", | ||
end: "2020-06-16T11:00:00Z" | ||
}, | ||
{ | ||
start: "2020-06-17T10:30:00Z", | ||
end: "2020-06-17T11:00:00Z" | ||
}, | ||
{ | ||
start: "2020-06-16T11:00:00Z", | ||
end: "2020-06-16T11:30:00Z" | ||
}, | ||
{ | ||
start: "2020-06-16T10:00:00Z", | ||
end: "2020-06-16T10:30:00Z" | ||
} | ||
]; | ||
const expectedPeriods = [ | ||
{ | ||
end: "2020-06-16T11:30:00Z", | ||
tzid: "Europe/London", | ||
interval: 30 | ||
}; | ||
const expected = [ | ||
"2020-06-16T08:00:00Z", | ||
"2020-06-16T08:30:00Z", | ||
"2020-06-16T09:00:00Z", | ||
"2020-06-16T09:30:00Z", | ||
"2020-06-16T10:00:00Z", | ||
"2020-06-16T10:30:00Z", | ||
"2020-06-16T11:00:00Z", | ||
"2020-06-16T11:30:00Z" | ||
]; | ||
const result = utils.tweenSlots(options); | ||
expect(result).toEqual(expected); | ||
expect(Array.isArray(result)).toBe(true); | ||
expect(result.length).toBe(expected.length); | ||
}); | ||
it("calculates tweens for cross-day slot-starts", () => { | ||
const options = { | ||
start: "2020-06-16T08:00:00Z", | ||
end: "2020-06-16T09:00:00Z" | ||
}, | ||
{ | ||
start: "2020-06-16T10:00:00Z", | ||
end: "2020-06-16T11:30:00Z" | ||
}, | ||
{ | ||
start: "2020-06-17T10:30:00Z", | ||
end: "2020-06-17T11:00:00Z" | ||
} | ||
]; | ||
const periods = utils.buildPeriodsFromSlots(slots); | ||
expect(periods.length).toEqual(3); | ||
expect(periods[0]).toEqual(expectedPeriods[0]); | ||
expect(periods[1]).toEqual(expectedPeriods[1]); | ||
expect(periods[2]).toEqual(expectedPeriods[2]); | ||
}); | ||
end: "2020-06-17T10:00:00Z", | ||
tzid: "America/Toronto", | ||
interval: 60 | ||
}; | ||
const expected = [ | ||
"2020-06-16T08:00:00Z", | ||
"2020-06-16T09:00:00Z", | ||
"2020-06-16T10:00:00Z", | ||
"2020-06-17T08:00:00Z", | ||
"2020-06-17T09:00:00Z", | ||
"2020-06-17T10:00:00Z" | ||
]; | ||
// tweenSlots | ||
it("calculates tweens for slot-starts", () => { | ||
const options = { | ||
start: "2020-06-16T08:00:00Z", | ||
end: "2020-06-16T11:30:00Z", | ||
tzid: "Europe/London", | ||
interval: 30 | ||
}; | ||
const expected = [ | ||
"2020-06-16T08:00:00Z", | ||
"2020-06-16T08:30:00Z", | ||
"2020-06-16T09:00:00Z", | ||
"2020-06-16T09:30:00Z", | ||
"2020-06-16T10:00:00Z", | ||
"2020-06-16T10:30:00Z", | ||
"2020-06-16T11:00:00Z", | ||
"2020-06-16T11:30:00Z" | ||
]; | ||
const result = utils.tweenSlots(options); | ||
expect(result).toEqual(expected); | ||
expect(Array.isArray(result)).toBe(true); | ||
expect(result.length).toBe(expected.length); | ||
}); | ||
const result = utils.tweenSlots(options); | ||
expect(result).toEqual(expected); | ||
expect(Array.isArray(result)).toBe(true); | ||
expect(result.length).toBe(expected.length); | ||
}); | ||
it("calculates tweens for cross-day slot-starts", () => { | ||
const options = { | ||
start: "2020-06-16T08:00:00Z", | ||
end: "2020-06-17T10:00:00Z", | ||
tzid: "America/Toronto", | ||
interval: 60 | ||
}; | ||
const expected = [ | ||
"2020-06-16T08:00:00Z", | ||
"2020-06-16T09:00:00Z", | ||
"2020-06-16T10:00:00Z", | ||
"2020-06-17T08:00:00Z", | ||
"2020-06-17T09:00:00Z", | ||
"2020-06-17T10:00:00Z" | ||
]; | ||
it("calculates tweens for cross-day slot-starts over timezone boundaries", () => { | ||
const options = { | ||
// In America/Toronto, these times cross midnight | ||
// so there should be blocks for FOUR days (not | ||
// just the three that 23rd - 25th would suggest) | ||
start: "2020-06-23T02:00:00Z", | ||
end: "2020-06-25T21:00:00Z", | ||
tzid: "America/Toronto", | ||
interval: 60 | ||
}; | ||
const expected = [ | ||
// Block 1 | ||
"2020-06-22T21:00:00Z", | ||
"2020-06-22T22:00:00Z", | ||
"2020-06-22T23:00:00Z", | ||
"2020-06-23T00:00:00Z", | ||
"2020-06-23T01:00:00Z", | ||
"2020-06-23T02:00:00Z", | ||
// Block 2 | ||
"2020-06-23T21:00:00Z", | ||
"2020-06-23T22:00:00Z", | ||
"2020-06-23T23:00:00Z", | ||
"2020-06-24T00:00:00Z", | ||
"2020-06-24T01:00:00Z", | ||
"2020-06-24T02:00:00Z", | ||
// Block 3 | ||
"2020-06-24T21:00:00Z", | ||
"2020-06-24T22:00:00Z", | ||
"2020-06-24T23:00:00Z", | ||
"2020-06-25T00:00:00Z", | ||
"2020-06-25T01:00:00Z", | ||
"2020-06-25T02:00:00Z", | ||
// Block 4 | ||
"2020-06-25T21:00:00Z", | ||
"2020-06-25T22:00:00Z", | ||
"2020-06-25T23:00:00Z", | ||
"2020-06-26T00:00:00Z", | ||
"2020-06-26T01:00:00Z", | ||
"2020-06-26T02:00:00Z" | ||
]; | ||
const result = utils.tweenSlots(options); | ||
expect(result).toEqual(expected); | ||
expect(Array.isArray(result)).toBe(true); | ||
expect(result.length).toBe(expected.length); | ||
const result = utils.tweenSlots(options); | ||
expect(result).toEqual(expected); | ||
expect(Array.isArray(result)).toBe(true); | ||
expect(result.length).toBe(expected.length); | ||
}); | ||
}); | ||
it("calculates tweens for cross-day slot-starts over timezone boundaries", () => { | ||
const options = { | ||
// In America/Toronto, these times cross midnight | ||
// so there should be blocks for FOUR days (not | ||
// just the three that 23rd - 25th would suggest) | ||
start: "2020-06-23T02:00:00Z", | ||
end: "2020-06-25T21:00:00Z", | ||
tzid: "America/Toronto", | ||
interval: 60 | ||
}; | ||
const expected = [ | ||
// Block 1 | ||
"2020-06-22T21:00:00Z", | ||
"2020-06-22T22:00:00Z", | ||
"2020-06-22T23:00:00Z", | ||
"2020-06-23T00:00:00Z", | ||
"2020-06-23T01:00:00Z", | ||
"2020-06-23T02:00:00Z", | ||
// Block 2 | ||
"2020-06-23T21:00:00Z", | ||
"2020-06-23T22:00:00Z", | ||
"2020-06-23T23:00:00Z", | ||
"2020-06-24T00:00:00Z", | ||
"2020-06-24T01:00:00Z", | ||
"2020-06-24T02:00:00Z", | ||
// Block 3 | ||
"2020-06-24T21:00:00Z", | ||
"2020-06-24T22:00:00Z", | ||
"2020-06-24T23:00:00Z", | ||
"2020-06-25T00:00:00Z", | ||
"2020-06-25T01:00:00Z", | ||
"2020-06-25T02:00:00Z", | ||
// Block 4 | ||
"2020-06-25T21:00:00Z", | ||
"2020-06-25T22:00:00Z", | ||
"2020-06-25T23:00:00Z", | ||
"2020-06-26T00:00:00Z", | ||
"2020-06-26T01:00:00Z", | ||
"2020-06-26T02:00:00Z" | ||
]; | ||
const result = utils.tweenSlots(options); | ||
expect(result).toEqual(expected); | ||
expect(Array.isArray(result)).toBe(true); | ||
expect(result.length).toBe(expected.length); | ||
}); | ||
// addSlotStarts | ||
@@ -1133,2 +1192,233 @@ it("adds N slot start times", () => { | ||
}); | ||
describe("cropDaysToWindow", () => { | ||
it("crops an array of days into a defined window", () => { | ||
const rawDays = [ | ||
"2021-03-25", | ||
"2021-03-26", | ||
"2021-03-27", | ||
"2021-03-28", | ||
"2021-03-29", | ||
"2021-03-30", | ||
"2021-03-31", | ||
"2021-04-01", | ||
"2021-04-02", | ||
"2021-04-03", | ||
"2021-04-04", | ||
"2021-04-05", | ||
"2021-04-06" | ||
]; | ||
const windowSize = 8; | ||
const { days, overflow } = utils.cropDaysToWindow( | ||
rawDays, | ||
windowSize | ||
); | ||
expect(days.length).toBe(8); | ||
expect(overflow.length).toBe(6); | ||
expect(days[0]).toEqual("2021-03-25"); | ||
expect(days[days.length - 1]).toEqual("2021-04-01"); | ||
}); | ||
it("works when window is longer than array", () => { | ||
const rawDays = [ | ||
"2021-03-25", | ||
"2021-03-26", | ||
"2021-03-27", | ||
"2021-03-28" | ||
]; | ||
const windowSize = 8; | ||
const { days, overflow } = utils.cropDaysToWindow( | ||
rawDays, | ||
windowSize | ||
); | ||
expect(days.length).toBe(4); | ||
expect(overflow.length).toBe(0); | ||
expect(days[0]).toEqual("2021-03-25"); | ||
expect(days[days.length - 1]).toEqual("2021-03-28"); | ||
}); | ||
it("provides an array of overflow days (with a 1 day overlap)", () => { | ||
const rawDays = [ | ||
"2021-03-25", | ||
"2021-03-26", | ||
"2021-03-27", | ||
"2021-03-28", | ||
"2021-03-29", | ||
"2021-03-30", | ||
"2021-03-31", | ||
"2021-04-01", | ||
"2021-04-02", | ||
"2021-04-03", | ||
"2021-04-04", | ||
"2021-04-05", | ||
"2021-04-06" | ||
]; | ||
const windowSize = 8; | ||
const { days, overflow } = utils.cropDaysToWindow( | ||
rawDays, | ||
windowSize | ||
); | ||
expect(days.length).toBe(8); | ||
expect(overflow.length).toBe(6); | ||
expect(days[0]).toEqual("2021-03-25"); | ||
expect(days[days.length - 1]).toEqual("2021-04-01"); | ||
expect(overflow[0]).toEqual("2021-04-01"); | ||
expect(overflow[overflow.length - 1]).toEqual("2021-04-06"); | ||
}); | ||
}); | ||
describe("generate labels", () => { | ||
it("gets all labels", () => { | ||
const options = { | ||
days: [ | ||
"2021-01-17", | ||
"2021-01-18", | ||
"2021-01-19", | ||
"2021-01-20", | ||
"2021-01-21", | ||
"2021-01-22", | ||
"2021-01-23" | ||
], | ||
limits: { | ||
duration: 60, | ||
start: "10:00", | ||
end: "14:00", | ||
interval: 30 | ||
}, | ||
tzid: "Europe/London", | ||
i18n: { | ||
f: jest.fn(() => "STRING") | ||
} | ||
}; | ||
const allLabels = utils.getAllLabels(options); | ||
expect(allLabels.length).toBe(1); | ||
expect(allLabels[0].days.length).toBe(7); | ||
expect(allLabels[0].days[0].date).toBe(options.days[0]); | ||
expect(allLabels[0].days[0].number).toBe("STRING"); | ||
expect(allLabels[0].days[0].name).toBe("STRING"); | ||
expect(allLabels[0].days[6].date).toBe(options.days[6]); | ||
expect(allLabels[0].month).toBe("Jan 2021"); | ||
expect(allLabels[0].times.length).toBe(8); | ||
expect(allLabels[0].times[0].start).toBe("2021-01-18T10:00:00Z"); | ||
expect(allLabels[0].times[0].hour).toBe(true); | ||
expect(allLabels[0].times[1].start).toBe("2021-01-18T10:30:00Z"); | ||
expect(allLabels[0].times[1].hour).toBe(false); | ||
}); | ||
it("detects when days match", () => { | ||
const days = [ | ||
"2021-01-30", | ||
"2021-01-31", | ||
"2021-02-01", | ||
"2021-02-02" | ||
]; | ||
const fullList = [ | ||
{ | ||
days: [ | ||
{ date: "2021-01-30" }, | ||
{ date: "2021-01-31" }, | ||
{ date: "2021-02-01" }, | ||
{ date: "2021-02-02" } | ||
] | ||
} | ||
]; | ||
const justKeyDates = [ | ||
{ | ||
days: [{ date: "2021-01-30" }, { date: "2021-02-02" }] | ||
} | ||
]; | ||
const matchFull = utils.checkIfDaysMatch(days, fullList); | ||
expect(matchFull).toBe(true); | ||
const matchKeyDates = utils.checkIfDaysMatch(days, justKeyDates); | ||
expect(matchKeyDates).toBe(true); | ||
}); | ||
it("detects when days differ", () => { | ||
const days = [ | ||
"2021-01-30", | ||
"2021-01-31", | ||
"2021-02-01", | ||
"2021-02-02" | ||
]; | ||
const inclusiveMore = [ | ||
{ | ||
days: [ | ||
{ date: "2021-01-29" }, | ||
{ date: "2021-01-30" }, | ||
{ date: "2021-01-31" }, | ||
{ date: "2021-02-01" }, | ||
{ date: "2021-02-02" }, | ||
{ date: "2021-02-03" } | ||
] | ||
} | ||
]; | ||
const matchInclusiveMore = utils.checkIfDaysMatch( | ||
days, | ||
inclusiveMore | ||
); | ||
expect(matchInclusiveMore).toBe(false); | ||
const inclusiveFewer = [ | ||
{ | ||
days: [{ date: "2021-01-31" }, { date: "2021-02-01" }] | ||
} | ||
]; | ||
const matchInclusiveFewer = utils.checkIfDaysMatch( | ||
days, | ||
inclusiveFewer | ||
); | ||
expect(matchInclusiveFewer).toBe(false); | ||
const overlapPre = [ | ||
{ | ||
days: [ | ||
{ date: "2021-01-29" }, | ||
{ date: "2021-01-30" }, | ||
{ date: "2021-01-31" } | ||
] | ||
} | ||
]; | ||
const matchOverlapPre = utils.checkIfDaysMatch(days, overlapPre); | ||
expect(matchOverlapPre).toBe(false); | ||
const overlapPost = [ | ||
{ | ||
days: [ | ||
{ date: "2021-02-01" }, | ||
{ date: "2021-02-02" }, | ||
{ date: "2021-02-03" } | ||
] | ||
} | ||
]; | ||
const matchOverlapPost = utils.checkIfDaysMatch(days, overlapPost); | ||
expect(matchOverlapPost).toBe(false); | ||
}); | ||
it("detects missmatch with empty option", () => { | ||
const days = [ | ||
"2021-01-30", | ||
"2021-01-31", | ||
"2021-02-01", | ||
"2021-02-02" | ||
]; | ||
const matchEmpty = utils.checkIfDaysMatch(days, []); | ||
expect(matchEmpty).toBe(false); | ||
const matchMissing = utils.checkIfDaysMatch(days); | ||
expect(matchMissing).toBe(false); | ||
}); | ||
}); | ||
}); |
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
2875224
26724