This repository was archived by the owner on Jun 6, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 35
/
Copy pathindex.test.js
316 lines (282 loc) · 10 KB
/
index.test.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
const customParseFormat = require("dayjs/plugin/customParseFormat");
const dayjs = require("dayjs");
const tap = require("tap");
// The customParseFormat plugin changes the way the dayjs() utility method
// handles format strings. Specifically, MM and DD format tokens will REQUIRE
// two-digit months and days, whereas the default constructor will happily take
// single-digit months and days. Add the plugin to our tests to make sure we
// still work in environments where the plugin is being used.
dayjs.extend(customParseFormat);
const federalHolidays = require("./index");
const getDate = dateString => new Date(`${dateString} 00:00:00`);
const getDateUTC = dateString => new Date(`${dateString}T00:00:00Z`);
tap.test("handles standard federal holidays", async tests => {
tests.test(
"gets observed holidays, accounting for actual holidays on weekends",
async test => {
[
"2010-12-31", // New Year's Day falls on a Saturday, observed before
"2012-01-02", // New Year's Day falls on a Sunday, observed after
"2014-01-01",
"2014-01-20",
"2014-02-17",
"2014-05-26",
"2014-07-04",
"2014-09-01",
"2014-10-13",
"2014-11-11",
"2014-11-27",
"2014-12-25",
"2015-07-03", // Independence Day falls on a Saturday, observed before
"2016-12-26", // Christmas Day falls on a Sunday, observed after
"2017-12-25",
"2021-05-31" // https://github.com/18F/us-federal-holidays/issues/28
].forEach(dateString => {
const date = getDate(dateString);
const utcDate = getDateUTC(dateString);
test.ok(
federalHolidays.isAHoliday(date),
`${dateString} is a holiday (observed)`
);
test.ok(
federalHolidays.isAHoliday(utcDate, { utc: true }),
`${dateString} UTC is a holiday (observed)`
);
});
}
);
tests.test(
"actual holidays on weekends are not listed as observed holidays",
async test => {
[
"2011-01-01", // New Year's Day falls on a Saturday, so is not a holiday
"2012-01-01", // New Year's Day falls on a Sunday, so is not a holiday
"2015-07-04", // Independence Day falls on a Saturday, so is not a holiday
"2016-12-25", // Christmas Day falls on a Sunday, so is not a holiday
"2021-05-24" // https://github.com/18F/us-federal-holidays/issues/28
].forEach(dateString => {
const date = getDate(dateString);
const utcDate = getDateUTC(dateString);
test.notOk(
federalHolidays.isAHoliday(date),
`${dateString} is not a holiday (observed)`
);
test.notOk(
federalHolidays.isAHoliday(utcDate, { utc: true }),
`${dateString} UTC is not a holiday (observed)`
);
});
}
);
tests.test("Juneteenth is only included from 2021 onwards", async test => {
test.notOk(
federalHolidays.isAHoliday(getDate("2020-06-19")),
"Juneteenth is not a holiday in 2020"
);
// In 2021, Juneteenth fell on a Saturday, so the observed holiday was the
// 18th instead of the 19th.
test.ok(
federalHolidays.isAHoliday(getDate("2021-06-18")),
"Juneteenth is a holiday in 2021"
);
// 2023 is the first year that the observation of Juneteenth falls on the
// actual holiday.
test.ok(
federalHolidays.isAHoliday(getDate("2023-06-19")),
"Juneteenth is a holiday in 2023"
);
test.notOk(
federalHolidays
.allForYear(2020)
.some(({ name }) => name === "Juneteenth National Independence Day"),
"Juneteenth is not included in the list of holidays for 2020"
);
test.ok(
federalHolidays
.allForYear(2021)
.some(({ name }) => name === "Juneteenth National Independence Day"),
"Juneteenth is included in the list of holidays for 2021"
);
});
tests.test(
"honors requests not to shift holidays on weekends",
async test => {
test.ok(
federalHolidays.isAHoliday(getDate("2011-01-01"), {
shiftSaturdayHolidays: false
}),
`2011-01-01 is a holiday if Sundays are not shifted`
);
test.ok(
federalHolidays.isAHoliday(getDate("2012-01-01"), {
shiftSundayHolidays: false
}),
`2012-01-01 is a holiday if Sundays are not shifted`
);
test.ok(
federalHolidays.isAHoliday(getDate("2015-07-04"), {
shiftSaturdayHolidays: false
}),
`2015-07-04 is a holiday if Saturdays are not shifted`
);
test.ok(
federalHolidays.isAHoliday(getDate("2016-12-25"), {
shiftSundayHolidays: false
}),
`2016-12-25 is a holiday if Saturdays are not shifted`
);
}
);
tests.test(
"handles federal holidays within a range (Saturday and Sunday holidays shifted)",
async test => {
const holidays = federalHolidays.inRange(
new Date("2015-07-03"),
new Date("2016-12-26")
);
holidays.forEach(holiday => {
test.ok(
federalHolidays.isAHoliday(getDate(holiday.dateString)),
`${holiday.dateString} is a holiday (observed)`
);
// Make sure the alsoObservedAs property gets pulled through
if (
holiday.name === "Washington's Birthday" ||
holiday.name === "Columbus Day"
) {
test.ok(holiday.alsoObservedAs);
}
});
}
);
tests.test(
"handles federal holidays within a range (Saturday shifted only)",
async test => {
const shiftSaturdayHolidays = true;
const shiftSundayHolidays = false;
const holidays = federalHolidays.inRange(
new Date("2015-07-03"),
new Date("2016-12-26"),
{ shiftSaturdayHolidays, shiftSundayHolidays }
);
holidays.forEach(holiday => {
test.ok(
federalHolidays.isAHoliday(getDate(holiday.dateString), {
shiftSaturdayHolidays,
shiftSundayHolidays
}),
`${holiday.dateString} is a holiday (observed)`
);
});
}
);
tests.test(
"handles federal holidays within a range (Sunday shifted only)",
async test => {
const shiftSaturdayHolidays = false;
const shiftSundayHolidays = true;
const holidays = federalHolidays.inRange(
new Date("2015-07-03"),
new Date("2016-12-26"),
{ shiftSaturdayHolidays, shiftSundayHolidays }
);
holidays.forEach(holiday => {
test.ok(
federalHolidays.isAHoliday(getDate(holiday.dateString), {
shiftSaturdayHolidays,
shiftSundayHolidays
}),
`${holiday.dateString} is a holiday (observed)`
);
});
}
);
tests.test(
"handles federal holidays within a range (none shifted)",
async test => {
const shiftSaturdayHolidays = false;
const shiftSundayHolidays = false;
const holidays = federalHolidays.inRange(
new Date("2015-07-03"),
new Date("2016-12-26"),
{ shiftSaturdayHolidays, shiftSundayHolidays }
);
holidays.forEach(holiday => {
test.ok(
federalHolidays.isAHoliday(getDate(holiday.dateString), {
shiftSaturdayHolidays,
shiftSundayHolidays
}),
`${holiday.dateString} is a holiday (observed)`
);
});
}
);
tests.test("handles default dates and ranges", async defaultTests => {
const testYear = 2000;
let GlobalDate;
// Create a proxy for the global Date object. This way we can control the
// date that is created for default arguments.
defaultTests.beforeEach(() => {
GlobalDate = global.Date;
const ProxiedDate = new Proxy(Date, {
construct: (_, args) => {
// We only want to override the constructor if there aren't any
// arguments. In that case, use our magic date of July 1. Otherwise,
// pass the arguments on to the real Date constructor.
if (args.length === 0) {
return new GlobalDate(`${testYear}-07-01T00:00:00.000Z`);
}
return new GlobalDate(...args);
}
});
global.Date = ProxiedDate;
});
defaultTests.afterEach(() => {
// Put the real Date object back.
global.Date = GlobalDate;
});
// We've already tested isAHoliday and allForYear with args, so let's assume
// they're correct. If not, our earlier tests should have caught that. If
// they didn't... uhoh.
defaultTests.test("indicates whether today is a holiday", async test => {
// July 1 should not be a holiday in any year.
test.same(federalHolidays.isAHoliday(), false, "is not a holiday");
});
defaultTests.test(
"fetches all holidays for the current year",
async test => {
const expected = federalHolidays.allForYear(testYear);
const holidays = federalHolidays.allForYear();
test.match(holidays, expected, "gets the expected holidays");
test.same(
holidays.length,
expected.length,
"gets exactly the expected holidays"
);
}
);
defaultTests.test(
"defaults to a range from now to one year from now",
async test => {
const holidays = federalHolidays.inRange();
// Safe-ify these tests against changing test years. In 2021, Juneteenth
// was added to the holiday calendar. If the test year is before 2020,
// there are 4 holidays preceding July 1, so we start our slice at
// holiday #5 (index 4). From 2021 onwards, there are 5 holidays before
// July 1, so we start our slice at holiday #6 (index 5).
const slice = testYear > 2020 ? 5 : 4;
const expected = [
...federalHolidays.allForYear(testYear).slice(slice),
...federalHolidays.allForYear(testYear + 1).slice(0, slice)
];
test.match(holidays, expected, "get the expected holidays");
test.same(
holidays.length,
expected.length,
"gets exactly the expected holidays"
);
}
);
});
});