@everyonesoftware/common 2.0.0 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (59) hide show
  1. package/.github/workflows/publish.yml +54 -36
  2. package/package.json +6 -2
  3. package/sources/asyncIterator.ts +436 -436
  4. package/sources/asyncIteratorToJavascriptAsyncIteratorAdapter.ts +47 -47
  5. package/sources/asyncResult.ts +95 -95
  6. package/sources/byteList.ts +201 -201
  7. package/sources/byteListStream.ts +120 -120
  8. package/sources/byteReadStream.ts +23 -23
  9. package/sources/byteWriteStream.ts +15 -15
  10. package/sources/characterList.ts +194 -194
  11. package/sources/characterListStream.ts +150 -150
  12. package/sources/characterReadStream.ts +80 -80
  13. package/sources/characterReadStreamIterator.ts +127 -127
  14. package/sources/concatenateIterable.ts +118 -118
  15. package/sources/concatenateIterator.ts +164 -164
  16. package/sources/currentProcess.ts +157 -157
  17. package/sources/dateTime.ts +129 -129
  18. package/sources/depthFirstSearch.ts +229 -229
  19. package/sources/flatMapIterable.ts +103 -103
  20. package/sources/flatMapIterator.ts +151 -151
  21. package/sources/generator.ts +250 -250
  22. package/sources/index.ts +1 -1
  23. package/sources/iterator.ts +480 -480
  24. package/sources/javascriptAsyncIteratorToAsyncIteratorAdapter.ts +123 -123
  25. package/sources/javascriptSetSet.ts +133 -133
  26. package/sources/listQueue.ts +61 -61
  27. package/sources/listStack.ts +61 -61
  28. package/sources/luxonDateTime.ts +108 -108
  29. package/sources/mapAsyncIterator.ts +140 -140
  30. package/sources/mutableMap.ts +291 -291
  31. package/sources/node.ts +36 -36
  32. package/sources/promiseAsyncResult.ts +173 -173
  33. package/sources/queue.ts +48 -48
  34. package/sources/recreationDotGovClient.ts +258 -258
  35. package/sources/searchControl.ts +41 -41
  36. package/sources/set.ts +243 -243
  37. package/sources/skipAsyncIterator.ts +144 -144
  38. package/sources/stack.ts +47 -47
  39. package/sources/syncResult.ts +299 -299
  40. package/sources/takeAsyncIterator.ts +140 -140
  41. package/sources/whereAsyncIterator.ts +142 -142
  42. package/sources/wonderlandTrailClient.ts +1502 -1502
  43. package/tests/assertTestTests.ts +74 -74
  44. package/tests/byteListStreamTests.ts +389 -389
  45. package/tests/byteListTests.ts +26 -26
  46. package/tests/characterListStreamTests.ts +390 -390
  47. package/tests/characterListTests.ts +249 -249
  48. package/tests/dateTimeTests.ts +29 -29
  49. package/tests/depthFirstSearchTests.ts +105 -105
  50. package/tests/generatorTests.ts +85 -85
  51. package/tests/mutableMapTests.ts +153 -153
  52. package/tests/promiseAsyncResultTests.ts +687 -687
  53. package/tests/queueTests.ts +28 -28
  54. package/tests/recreationDotGovClientTests.ts +190 -190
  55. package/tests/setTests.ts +139 -139
  56. package/tests/stackTests.ts +65 -65
  57. package/tests/syncResultTests.ts +1250 -1250
  58. package/tests/wonderlandTrailClientTests.ts +451 -451
  59. package/tsup.config.ts +12 -12
@@ -1,452 +1,452 @@
1
- import { PreConditionError } from "../sources/preConditionError";
2
- import { isWonderlandTrailLocation, WonderlandTrailAvailability, WonderlandTrailAvailabilityType, WonderlandTrailClient, WonderlandTrailConnection, WonderlandTrailDirection, WonderlandTrailLocation, WonderlandTrailLocations, WonderlandTrailReservationType } from "../sources/wonderlandTrailClient";
3
- import { Test } from "./test";
4
- import { TestRunner } from "./testRunner";
5
- import { Iterable } from "../sources/iterable";
6
- import { DateTime } from "../sources/dateTime";
7
- import { Map } from "../sources/map";
8
- import { MutableMap } from "../sources/mutableMap";
9
- import { NotFoundError } from "../sources/notFoundError";
10
- import { HttpClient } from "../sources/httpClient";
11
-
12
- export function test(runner: TestRunner): void
13
- {
14
- runner.testFile("wonderlandTrailClient.ts", () =>
15
- {
16
- runner.testFunction("isWonderlandTrailLocation()", () =>
17
- {
18
- function isWonderlandTrailLocationTest(value: unknown, expected: boolean): void
19
- {
20
- runner.test(`with ${runner.toString(value)}`, (test: Test) =>
21
- {
22
- test.assertEqual(isWonderlandTrailLocation(value), expected);
23
- });
24
- }
25
-
26
- isWonderlandTrailLocationTest(undefined, false);
27
- isWonderlandTrailLocationTest(null, false);
28
- isWonderlandTrailLocationTest(20, false);
29
- isWonderlandTrailLocationTest({}, false);
30
- isWonderlandTrailLocationTest(WonderlandTrailLocations.boxCanyon, true);
31
- });
32
-
33
- runner.testType("WonderlandTrailLocations", () =>
34
- {
35
- runner.testFunction("getLocations()", (test: Test) =>
36
- {
37
- const locations: Iterable<WonderlandTrailLocation> = WonderlandTrailLocations.getLocations();
38
- test.assertNotUndefinedAndNotNull(locations);
39
- test.assertEqual(locations.getCount().await(), 27);
40
- });
41
-
42
- runner.testFunction("getTrailheads()", (test: Test) =>
43
- {
44
- const trailheads: Iterable<WonderlandTrailLocation> = WonderlandTrailLocations.getTrailheads();
45
- test.assertEqual(6, trailheads.getCount().await());
46
- test.assertEqual(
47
- [
48
- WonderlandTrailLocations.sunriseVisitorCenter.name,
49
- WonderlandTrailLocations.whiteRiver.name,
50
- WonderlandTrailLocations.fryingPanCreek.name,
51
- WonderlandTrailLocations.boxCanyon.name,
52
- WonderlandTrailLocations.reflectionLakes.name,
53
- WonderlandTrailLocations.longmire.name,
54
- ],
55
- trailheads.map(t => t.name).toArray().await(),
56
- );
57
- });
58
- });
59
-
60
- runner.testType("WonderlandTrailAvailability", () =>
61
- {
62
- runner.testFunction("addAvailability()", () =>
63
- {
64
- runner.test("with undefined location", (test: Test) =>
65
- {
66
- const availability: WonderlandTrailAvailability = WonderlandTrailAvailability.create();
67
- test.assertThrows(() => availability.addAvailability(undefined!, DateTime.now()), new PreConditionError(
68
- "Expression: location",
69
- "Expected: not undefined and not null",
70
- "Actual: undefined",
71
- ));
72
- });
73
-
74
- runner.test("with null location", (test: Test) =>
75
- {
76
- const availability: WonderlandTrailAvailability = WonderlandTrailAvailability.create();
77
- test.assertThrows(() => availability.addAvailability(null!, DateTime.now()), new PreConditionError(
78
- "Expression: location",
79
- "Expected: not undefined and not null",
80
- "Actual: null",
81
- ));
82
- });
83
-
84
- runner.test("with undefined date", (test: Test) =>
85
- {
86
- const availability: WonderlandTrailAvailability = WonderlandTrailAvailability.create();
87
- test.assertThrows(() => availability.addAvailability(WonderlandTrailLocations.boxCanyon, undefined!), new PreConditionError(
88
- "Expression: date",
89
- "Expected: not undefined and not null",
90
- "Actual: undefined",
91
- ));
92
- });
93
-
94
- runner.test("with null date", (test: Test) =>
95
- {
96
- const availability: WonderlandTrailAvailability = WonderlandTrailAvailability.create();
97
- test.assertThrows(() => availability.addAvailability(WonderlandTrailLocations.boxCanyon, null!), new PreConditionError(
98
- "Expression: date",
99
- "Expected: not undefined and not null",
100
- "Actual: null",
101
- ));
102
- });
103
-
104
- runner.test("with neither individual nor group site data", (test: Test) =>
105
- {
106
- const availability: WonderlandTrailAvailability = WonderlandTrailAvailability.create();
107
-
108
- const location: WonderlandTrailLocation = WonderlandTrailLocations.boxCanyon;
109
- const date: DateTime = DateTime.parse("2025-07-04");
110
- test.assertEqual(Map.create(), availability.getAvailability(location))
111
-
112
- availability.addAvailability(location, date);
113
-
114
- const expected: MutableMap<string, WonderlandTrailAvailabilityType> = Map.create();
115
- expected.set(date.toDateString(), { groupSite: undefined, individualSite: undefined });
116
- test.assertEqual(expected, availability.getAvailability(location));
117
- });
118
-
119
- runner.test("with individual site data", (test: Test) =>
120
- {
121
- const availability: WonderlandTrailAvailability = WonderlandTrailAvailability.create();
122
-
123
- const location: WonderlandTrailLocation = WonderlandTrailLocations.boxCanyon;
124
- const date: DateTime = DateTime.parse("2025-07-04");
125
- test.assertEqual(Map.create(), availability.getAvailability(location))
126
-
127
- availability.addAvailability(location, date, WonderlandTrailReservationType.Walkup);
128
-
129
- const expected: MutableMap<string, WonderlandTrailAvailabilityType> = Map.create();
130
- expected.set(date.toDateString(), { groupSite: undefined, individualSite: WonderlandTrailReservationType.Walkup });
131
- test.assertEqual(expected, availability.getAvailability(location));
132
- });
133
-
134
- runner.test("with group site data", (test: Test) =>
135
- {
136
- const availability: WonderlandTrailAvailability = WonderlandTrailAvailability.create();
137
-
138
- const location: WonderlandTrailLocation = WonderlandTrailLocations.boxCanyon;
139
- const date: DateTime = DateTime.parse("2025-07-04");
140
- test.assertEqual(Map.create(), availability.getAvailability(location))
141
-
142
- availability.addAvailability(location, date, undefined, WonderlandTrailReservationType.Reserved);
143
-
144
- const expected: MutableMap<string, WonderlandTrailAvailabilityType> = Map.create();
145
- expected.set(date.toDateString(), { groupSite: WonderlandTrailReservationType.Reserved, individualSite: undefined });
146
- test.assertEqual(expected, availability.getAvailability(location));
147
- });
148
- });
149
-
150
- runner.testFunction("getAvailability()", () =>
151
- {
152
- function getAvailabilityErrorTest(location: WonderlandTrailLocation, expected: Error): void
153
- {
154
- runner.test(`with ${runner.toString(location)}`, (test: Test) =>
155
- {
156
- const availability: WonderlandTrailAvailability = WonderlandTrailAvailability.create();
157
- test.assertThrows(() => availability.getAvailability(location), expected);
158
- });
159
- }
160
-
161
- getAvailabilityErrorTest(undefined!, new PreConditionError(
162
- "Expression: location",
163
- "Expected: not undefined and not null",
164
- "Actual: undefined",
165
- ));
166
- getAvailabilityErrorTest(null!, new PreConditionError(
167
- "Expression: location",
168
- "Expected: not undefined and not null",
169
- "Actual: null",
170
- ));
171
-
172
- runner.test("when location isn't found", (test: Test) =>
173
- {
174
- const availability: WonderlandTrailAvailability = WonderlandTrailAvailability.create();
175
- const location: WonderlandTrailLocation = WonderlandTrailLocations.boxCanyon;
176
- const locationAvailability: MutableMap<string, WonderlandTrailAvailabilityType> = availability.getAvailability(location);
177
- test.assertNotUndefinedAndNotNull(locationAvailability);
178
- test.assertFalse(locationAvailability.any().await());
179
- test.assertSame(locationAvailability, availability.getAvailability(location));
180
- });
181
-
182
- runner.test("when location is found", (test: Test) =>
183
- {
184
- const availability: WonderlandTrailAvailability = WonderlandTrailAvailability.create();
185
-
186
- const location: WonderlandTrailLocation = WonderlandTrailLocations.boxCanyon;
187
- const date: DateTime = DateTime.parse("2025-07-04");
188
- availability.addAvailability(location, date, WonderlandTrailReservationType.Reserved, WonderlandTrailReservationType.Walkup);
189
-
190
- const locationAvailability: MutableMap<string, WonderlandTrailAvailabilityType> = availability.getAvailability(location);
191
- const expected: MutableMap<string, WonderlandTrailAvailabilityType> = Map.create();
192
- expected.set(date.toDateString(), {
193
- groupSite: WonderlandTrailReservationType.Walkup,
194
- individualSite: WonderlandTrailReservationType.Reserved,
195
- });
196
- test.assertEqual(locationAvailability, expected);
197
- test.assertSame(locationAvailability, availability.getAvailability(location));
198
- });
199
- });
200
-
201
- runner.testFunction("getDayAvailability()", () =>
202
- {
203
- function getDayAvailabilityErrorTest(location: WonderlandTrailLocation, date: DateTime, expected: Error): void
204
- {
205
- runner.test(`with ${runner.andList([location, date])}`, (test: Test) =>
206
- {
207
- const availability: WonderlandTrailAvailability = WonderlandTrailAvailability.create();
208
- test.assertThrows(() => availability.getDayAvailability(location, date).await(), expected);
209
- });
210
- }
211
-
212
- getDayAvailabilityErrorTest(undefined!, DateTime.parse("2025-07-04"), new PreConditionError(
213
- "Expression: location",
214
- "Expected: not undefined and not null",
215
- "Actual: undefined",
216
- ));
217
- getDayAvailabilityErrorTest(null!, DateTime.parse("2025-07-04"), new PreConditionError(
218
- "Expression: location",
219
- "Expected: not undefined and not null",
220
- "Actual: null",
221
- ));
222
- getDayAvailabilityErrorTest(WonderlandTrailLocations.boxCanyon, undefined!, new PreConditionError(
223
- "Expression: date",
224
- "Expected: not undefined and not null",
225
- "Actual: undefined",
226
- ));
227
- getDayAvailabilityErrorTest(WonderlandTrailLocations.boxCanyon, null!, new PreConditionError(
228
- "Expression: date",
229
- "Expected: not undefined and not null",
230
- "Actual: null",
231
- ));
232
-
233
- runner.test("with not found location or date", (test: Test) =>
234
- {
235
- const availability: WonderlandTrailAvailability = WonderlandTrailAvailability.create();
236
- const location: WonderlandTrailLocation = WonderlandTrailLocations.boxCanyon;
237
- const date: DateTime = DateTime.parse("2025-07-04");
238
-
239
- test.assertThrows(() => availability.getDayAvailability(location, date).await(), new NotFoundError(
240
- "No availability was found for Box Canyon on 2025-07-04.",
241
- ));
242
- });
243
-
244
- runner.test("when location and date are found", (test: Test) =>
245
- {
246
- const availability: WonderlandTrailAvailability = WonderlandTrailAvailability.create();
247
-
248
- const location: WonderlandTrailLocation = WonderlandTrailLocations.boxCanyon;
249
- const date: DateTime = DateTime.parse("2025-07-04");
250
- availability.addAvailability(location, date, WonderlandTrailReservationType.Reserved, WonderlandTrailReservationType.Walkup);
251
-
252
- const dayAvailability: WonderlandTrailAvailabilityType = availability.getDayAvailability(location, date).await();
253
- const expected: WonderlandTrailAvailabilityType = {
254
- groupSite: WonderlandTrailReservationType.Walkup,
255
- individualSite: WonderlandTrailReservationType.Reserved,
256
- };
257
- test.assertEqual(dayAvailability, expected);
258
- test.assertSame(dayAvailability, availability.getDayAvailability(location, date).await());
259
- });
260
- });
261
- });
262
-
263
- runner.testType("WonderlandTrailDirection", () =>
264
- {
265
- runner.testFunction("toString()", (test: Test) =>
266
- {
267
- test.assertEqual("Clockwise", WonderlandTrailDirection.clockwise.toString());
268
- test.assertEqual("CounterClockwise", WonderlandTrailDirection.counterClockwise.toString());
269
- });
270
-
271
- runner.testFunction("reverse()", (test: Test) =>
272
- {
273
- test.assertSame(WonderlandTrailDirection.counterClockwise, WonderlandTrailDirection.clockwise.reverse());
274
- test.assertSame(WonderlandTrailDirection.clockwise, WonderlandTrailDirection.counterClockwise.reverse());
275
- });
276
- });
277
-
278
- runner.testType("WonderlandTrailConnection", () =>
279
- {
280
- runner.testFunction("create()", (test: Test) =>
281
- {
282
- const connection: WonderlandTrailConnection = WonderlandTrailConnection.create(
283
- WonderlandTrailLocations.boxCanyon,
284
- WonderlandTrailLocations.carbonRiver,
285
- 5000,
286
- 2000,
287
- 10,
288
- WonderlandTrailDirection.clockwise,
289
- Iterable.create([
290
- WonderlandTrailLocations.cataractValley,
291
- WonderlandTrailLocations.devilsDream,
292
- ]),
293
- );
294
- test.assertNotUndefinedAndNotNull(connection);
295
- test.assertEqual(connection.startLocation, WonderlandTrailLocations.boxCanyon);
296
- test.assertEqual(connection.endLocation, WonderlandTrailLocations.carbonRiver);
297
- test.assertEqual(connection.distanceMiles, 5000);
298
- test.assertEqual(connection.ascentFeet, 2000);
299
- test.assertEqual(connection.descentFeet, 10);
300
- test.assertEqual(connection.direction, WonderlandTrailDirection.clockwise);
301
- test.assertEqual(connection.intermediateLocations, Iterable.create([
302
- WonderlandTrailLocations.cataractValley,
303
- WonderlandTrailLocations.devilsDream,
304
- ]));
305
- });
306
-
307
- runner.testFunction("getLocations()", () =>
308
- {
309
- runner.test("when connection is not a loop", (test: Test) =>
310
- {
311
- const connection: WonderlandTrailConnection = WonderlandTrailConnection.create(
312
- WonderlandTrailLocations.boxCanyon,
313
- WonderlandTrailLocations.carbonRiver,
314
- 5000,
315
- 2000,
316
- 10,
317
- WonderlandTrailDirection.clockwise,
318
- Iterable.create([
319
- WonderlandTrailLocations.cataractValley,
320
- WonderlandTrailLocations.devilsDream,
321
- ]),
322
- );
323
- test.assertEqual(connection.getLocations(), Iterable.create([
324
- WonderlandTrailLocations.boxCanyon,
325
- WonderlandTrailLocations.cataractValley,
326
- WonderlandTrailLocations.devilsDream,
327
- WonderlandTrailLocations.carbonRiver,
328
- ]));
329
- });
330
-
331
- runner.test("when connection is a loop", (test: Test) =>
332
- {
333
- const connection: WonderlandTrailConnection = WonderlandTrailConnection.create(
334
- WonderlandTrailLocations.boxCanyon,
335
- WonderlandTrailLocations.boxCanyon,
336
- 5000,
337
- 2000,
338
- 10,
339
- WonderlandTrailDirection.clockwise,
340
- Iterable.create([
341
- WonderlandTrailLocations.cataractValley,
342
- WonderlandTrailLocations.devilsDream,
343
- ]),
344
- );
345
- test.assertEqual(connection.getLocations(), Iterable.create([
346
- WonderlandTrailLocations.boxCanyon,
347
- WonderlandTrailLocations.cataractValley,
348
- WonderlandTrailLocations.devilsDream,
349
- ]));
350
- });
351
- });
352
-
353
- runner.testFunction("reverseDirection()", (test: Test) =>
354
- {
355
- const connection: WonderlandTrailConnection = WonderlandTrailConnection.create(
356
- WonderlandTrailLocations.boxCanyon,
357
- WonderlandTrailLocations.carbonRiver,
358
- 5000,
359
- 2000,
360
- 10,
361
- WonderlandTrailDirection.clockwise,
362
- Iterable.create([
363
- WonderlandTrailLocations.cataractValley,
364
- WonderlandTrailLocations.devilsDream,
365
- ]),
366
- );
367
- const reversedConnection: WonderlandTrailConnection = connection.reverseDirection();
368
- test.assertNotSame(connection, reversedConnection);
369
- test.assertEqual(reversedConnection.startLocation, WonderlandTrailLocations.carbonRiver);
370
- test.assertEqual(reversedConnection.endLocation, WonderlandTrailLocations.boxCanyon);
371
- test.assertEqual(reversedConnection.distanceMiles, 5000);
372
- test.assertEqual(reversedConnection.ascentFeet, 10);
373
- test.assertEqual(reversedConnection.descentFeet, 2000);
374
- test.assertEqual(reversedConnection.direction, WonderlandTrailDirection.counterClockwise);
375
- test.assertEqual(reversedConnection.intermediateLocations, Iterable.create([
376
- WonderlandTrailLocations.cataractValley,
377
- WonderlandTrailLocations.devilsDream,
378
- ]));
379
- });
380
- });
381
-
382
- runner.testType("WonderlandTrailClient", () =>
383
- {
384
- runner.testFunction("create()", () =>
385
- {
386
- runner.test("with undefined HttpClient", (test: Test) =>
387
- {
388
- test.assertThrows(() => WonderlandTrailClient.create(undefined!), new PreConditionError(
389
- "Expression: httpClient",
390
- "Expected: not undefined and not null",
391
- "Actual: undefined",
392
- ));
393
- });
394
-
395
- runner.test("with null HttpClient", (test: Test) =>
396
- {
397
- test.assertThrows(() => WonderlandTrailClient.create(null!), new PreConditionError(
398
- "Expression: httpClient",
399
- "Expected: not undefined and not null",
400
- "Actual: null",
401
- ));
402
- });
403
-
404
- runner.test("with defined HttpClient", (test: Test) =>
405
- {
406
- const httpClient: HttpClient = HttpClient.create();
407
- const client: WonderlandTrailClient = WonderlandTrailClient.create(httpClient);
408
- test.assertNotUndefinedAndNotNull(client);
409
- });
410
- });
411
-
412
- runner.testFunction("getAvailability()", runner.skip(true, "Ignore slow running tests for now"), () =>
413
- {
414
- runner.test("with year in the past", async (test: Test) =>
415
- {
416
- const httpClient: HttpClient = HttpClient.create();
417
- const client: WonderlandTrailClient = WonderlandTrailClient.create(httpClient);
418
-
419
- const availability: WonderlandTrailAvailability = await client.getAvailability(4, 2023, true, true, true);
420
- test.assertNotUndefinedAndNotNull(availability);
421
- test.assertFalse(availability.any());
422
- });
423
-
424
- runner.test("with month in the past", async (test: Test) =>
425
- {
426
- const httpClient: HttpClient = HttpClient.create();
427
- const client: WonderlandTrailClient = WonderlandTrailClient.create(httpClient);
428
-
429
- const availability: WonderlandTrailAvailability = await client.getAvailability(3, 2026, true, true, true);
430
- test.assertNotUndefinedAndNotNull(availability);
431
- test.assertFalse(availability.any());
432
- });
433
-
434
- runner.test("with a future month in the current year", async (test: Test) =>
435
- {
436
- const httpClient: HttpClient = HttpClient.create();
437
- const client: WonderlandTrailClient = WonderlandTrailClient.create(httpClient);
438
-
439
- const availability: WonderlandTrailAvailability = await client.getAvailability({
440
- month: 7,
441
- year: 2026,
442
- allowGroupSites: true,
443
- allowIndividualSites: true,
444
- allowWalkupPermits: true,
445
- });
446
- test.assertNotUndefinedAndNotNull(availability);
447
- test.assertTrue(availability.any());
448
- });
449
- });
450
- });
451
- });
1
+ import { PreConditionError } from "../sources/preConditionError";
2
+ import { isWonderlandTrailLocation, WonderlandTrailAvailability, WonderlandTrailAvailabilityType, WonderlandTrailClient, WonderlandTrailConnection, WonderlandTrailDirection, WonderlandTrailLocation, WonderlandTrailLocations, WonderlandTrailReservationType } from "../sources/wonderlandTrailClient";
3
+ import { Test } from "./test";
4
+ import { TestRunner } from "./testRunner";
5
+ import { Iterable } from "../sources/iterable";
6
+ import { DateTime } from "../sources/dateTime";
7
+ import { Map } from "../sources/map";
8
+ import { MutableMap } from "../sources/mutableMap";
9
+ import { NotFoundError } from "../sources/notFoundError";
10
+ import { HttpClient } from "../sources/httpClient";
11
+
12
+ export function test(runner: TestRunner): void
13
+ {
14
+ runner.testFile("wonderlandTrailClient.ts", () =>
15
+ {
16
+ runner.testFunction("isWonderlandTrailLocation()", () =>
17
+ {
18
+ function isWonderlandTrailLocationTest(value: unknown, expected: boolean): void
19
+ {
20
+ runner.test(`with ${runner.toString(value)}`, (test: Test) =>
21
+ {
22
+ test.assertEqual(isWonderlandTrailLocation(value), expected);
23
+ });
24
+ }
25
+
26
+ isWonderlandTrailLocationTest(undefined, false);
27
+ isWonderlandTrailLocationTest(null, false);
28
+ isWonderlandTrailLocationTest(20, false);
29
+ isWonderlandTrailLocationTest({}, false);
30
+ isWonderlandTrailLocationTest(WonderlandTrailLocations.boxCanyon, true);
31
+ });
32
+
33
+ runner.testType("WonderlandTrailLocations", () =>
34
+ {
35
+ runner.testFunction("getLocations()", (test: Test) =>
36
+ {
37
+ const locations: Iterable<WonderlandTrailLocation> = WonderlandTrailLocations.getLocations();
38
+ test.assertNotUndefinedAndNotNull(locations);
39
+ test.assertEqual(locations.getCount().await(), 27);
40
+ });
41
+
42
+ runner.testFunction("getTrailheads()", (test: Test) =>
43
+ {
44
+ const trailheads: Iterable<WonderlandTrailLocation> = WonderlandTrailLocations.getTrailheads();
45
+ test.assertEqual(6, trailheads.getCount().await());
46
+ test.assertEqual(
47
+ [
48
+ WonderlandTrailLocations.sunriseVisitorCenter.name,
49
+ WonderlandTrailLocations.whiteRiver.name,
50
+ WonderlandTrailLocations.fryingPanCreek.name,
51
+ WonderlandTrailLocations.boxCanyon.name,
52
+ WonderlandTrailLocations.reflectionLakes.name,
53
+ WonderlandTrailLocations.longmire.name,
54
+ ],
55
+ trailheads.map(t => t.name).toArray().await(),
56
+ );
57
+ });
58
+ });
59
+
60
+ runner.testType("WonderlandTrailAvailability", () =>
61
+ {
62
+ runner.testFunction("addAvailability()", () =>
63
+ {
64
+ runner.test("with undefined location", (test: Test) =>
65
+ {
66
+ const availability: WonderlandTrailAvailability = WonderlandTrailAvailability.create();
67
+ test.assertThrows(() => availability.addAvailability(undefined!, DateTime.now()), new PreConditionError(
68
+ "Expression: location",
69
+ "Expected: not undefined and not null",
70
+ "Actual: undefined",
71
+ ));
72
+ });
73
+
74
+ runner.test("with null location", (test: Test) =>
75
+ {
76
+ const availability: WonderlandTrailAvailability = WonderlandTrailAvailability.create();
77
+ test.assertThrows(() => availability.addAvailability(null!, DateTime.now()), new PreConditionError(
78
+ "Expression: location",
79
+ "Expected: not undefined and not null",
80
+ "Actual: null",
81
+ ));
82
+ });
83
+
84
+ runner.test("with undefined date", (test: Test) =>
85
+ {
86
+ const availability: WonderlandTrailAvailability = WonderlandTrailAvailability.create();
87
+ test.assertThrows(() => availability.addAvailability(WonderlandTrailLocations.boxCanyon, undefined!), new PreConditionError(
88
+ "Expression: date",
89
+ "Expected: not undefined and not null",
90
+ "Actual: undefined",
91
+ ));
92
+ });
93
+
94
+ runner.test("with null date", (test: Test) =>
95
+ {
96
+ const availability: WonderlandTrailAvailability = WonderlandTrailAvailability.create();
97
+ test.assertThrows(() => availability.addAvailability(WonderlandTrailLocations.boxCanyon, null!), new PreConditionError(
98
+ "Expression: date",
99
+ "Expected: not undefined and not null",
100
+ "Actual: null",
101
+ ));
102
+ });
103
+
104
+ runner.test("with neither individual nor group site data", (test: Test) =>
105
+ {
106
+ const availability: WonderlandTrailAvailability = WonderlandTrailAvailability.create();
107
+
108
+ const location: WonderlandTrailLocation = WonderlandTrailLocations.boxCanyon;
109
+ const date: DateTime = DateTime.parse("2025-07-04");
110
+ test.assertEqual(Map.create(), availability.getAvailability(location))
111
+
112
+ availability.addAvailability(location, date);
113
+
114
+ const expected: MutableMap<string, WonderlandTrailAvailabilityType> = Map.create();
115
+ expected.set(date.toDateString(), { groupSite: undefined, individualSite: undefined });
116
+ test.assertEqual(expected, availability.getAvailability(location));
117
+ });
118
+
119
+ runner.test("with individual site data", (test: Test) =>
120
+ {
121
+ const availability: WonderlandTrailAvailability = WonderlandTrailAvailability.create();
122
+
123
+ const location: WonderlandTrailLocation = WonderlandTrailLocations.boxCanyon;
124
+ const date: DateTime = DateTime.parse("2025-07-04");
125
+ test.assertEqual(Map.create(), availability.getAvailability(location))
126
+
127
+ availability.addAvailability(location, date, WonderlandTrailReservationType.Walkup);
128
+
129
+ const expected: MutableMap<string, WonderlandTrailAvailabilityType> = Map.create();
130
+ expected.set(date.toDateString(), { groupSite: undefined, individualSite: WonderlandTrailReservationType.Walkup });
131
+ test.assertEqual(expected, availability.getAvailability(location));
132
+ });
133
+
134
+ runner.test("with group site data", (test: Test) =>
135
+ {
136
+ const availability: WonderlandTrailAvailability = WonderlandTrailAvailability.create();
137
+
138
+ const location: WonderlandTrailLocation = WonderlandTrailLocations.boxCanyon;
139
+ const date: DateTime = DateTime.parse("2025-07-04");
140
+ test.assertEqual(Map.create(), availability.getAvailability(location))
141
+
142
+ availability.addAvailability(location, date, undefined, WonderlandTrailReservationType.Reserved);
143
+
144
+ const expected: MutableMap<string, WonderlandTrailAvailabilityType> = Map.create();
145
+ expected.set(date.toDateString(), { groupSite: WonderlandTrailReservationType.Reserved, individualSite: undefined });
146
+ test.assertEqual(expected, availability.getAvailability(location));
147
+ });
148
+ });
149
+
150
+ runner.testFunction("getAvailability()", () =>
151
+ {
152
+ function getAvailabilityErrorTest(location: WonderlandTrailLocation, expected: Error): void
153
+ {
154
+ runner.test(`with ${runner.toString(location)}`, (test: Test) =>
155
+ {
156
+ const availability: WonderlandTrailAvailability = WonderlandTrailAvailability.create();
157
+ test.assertThrows(() => availability.getAvailability(location), expected);
158
+ });
159
+ }
160
+
161
+ getAvailabilityErrorTest(undefined!, new PreConditionError(
162
+ "Expression: location",
163
+ "Expected: not undefined and not null",
164
+ "Actual: undefined",
165
+ ));
166
+ getAvailabilityErrorTest(null!, new PreConditionError(
167
+ "Expression: location",
168
+ "Expected: not undefined and not null",
169
+ "Actual: null",
170
+ ));
171
+
172
+ runner.test("when location isn't found", (test: Test) =>
173
+ {
174
+ const availability: WonderlandTrailAvailability = WonderlandTrailAvailability.create();
175
+ const location: WonderlandTrailLocation = WonderlandTrailLocations.boxCanyon;
176
+ const locationAvailability: MutableMap<string, WonderlandTrailAvailabilityType> = availability.getAvailability(location);
177
+ test.assertNotUndefinedAndNotNull(locationAvailability);
178
+ test.assertFalse(locationAvailability.any().await());
179
+ test.assertSame(locationAvailability, availability.getAvailability(location));
180
+ });
181
+
182
+ runner.test("when location is found", (test: Test) =>
183
+ {
184
+ const availability: WonderlandTrailAvailability = WonderlandTrailAvailability.create();
185
+
186
+ const location: WonderlandTrailLocation = WonderlandTrailLocations.boxCanyon;
187
+ const date: DateTime = DateTime.parse("2025-07-04");
188
+ availability.addAvailability(location, date, WonderlandTrailReservationType.Reserved, WonderlandTrailReservationType.Walkup);
189
+
190
+ const locationAvailability: MutableMap<string, WonderlandTrailAvailabilityType> = availability.getAvailability(location);
191
+ const expected: MutableMap<string, WonderlandTrailAvailabilityType> = Map.create();
192
+ expected.set(date.toDateString(), {
193
+ groupSite: WonderlandTrailReservationType.Walkup,
194
+ individualSite: WonderlandTrailReservationType.Reserved,
195
+ });
196
+ test.assertEqual(locationAvailability, expected);
197
+ test.assertSame(locationAvailability, availability.getAvailability(location));
198
+ });
199
+ });
200
+
201
+ runner.testFunction("getDayAvailability()", () =>
202
+ {
203
+ function getDayAvailabilityErrorTest(location: WonderlandTrailLocation, date: DateTime, expected: Error): void
204
+ {
205
+ runner.test(`with ${runner.andList([location, date])}`, (test: Test) =>
206
+ {
207
+ const availability: WonderlandTrailAvailability = WonderlandTrailAvailability.create();
208
+ test.assertThrows(() => availability.getDayAvailability(location, date).await(), expected);
209
+ });
210
+ }
211
+
212
+ getDayAvailabilityErrorTest(undefined!, DateTime.parse("2025-07-04"), new PreConditionError(
213
+ "Expression: location",
214
+ "Expected: not undefined and not null",
215
+ "Actual: undefined",
216
+ ));
217
+ getDayAvailabilityErrorTest(null!, DateTime.parse("2025-07-04"), new PreConditionError(
218
+ "Expression: location",
219
+ "Expected: not undefined and not null",
220
+ "Actual: null",
221
+ ));
222
+ getDayAvailabilityErrorTest(WonderlandTrailLocations.boxCanyon, undefined!, new PreConditionError(
223
+ "Expression: date",
224
+ "Expected: not undefined and not null",
225
+ "Actual: undefined",
226
+ ));
227
+ getDayAvailabilityErrorTest(WonderlandTrailLocations.boxCanyon, null!, new PreConditionError(
228
+ "Expression: date",
229
+ "Expected: not undefined and not null",
230
+ "Actual: null",
231
+ ));
232
+
233
+ runner.test("with not found location or date", (test: Test) =>
234
+ {
235
+ const availability: WonderlandTrailAvailability = WonderlandTrailAvailability.create();
236
+ const location: WonderlandTrailLocation = WonderlandTrailLocations.boxCanyon;
237
+ const date: DateTime = DateTime.parse("2025-07-04");
238
+
239
+ test.assertThrows(() => availability.getDayAvailability(location, date).await(), new NotFoundError(
240
+ "No availability was found for Box Canyon on 2025-07-04.",
241
+ ));
242
+ });
243
+
244
+ runner.test("when location and date are found", (test: Test) =>
245
+ {
246
+ const availability: WonderlandTrailAvailability = WonderlandTrailAvailability.create();
247
+
248
+ const location: WonderlandTrailLocation = WonderlandTrailLocations.boxCanyon;
249
+ const date: DateTime = DateTime.parse("2025-07-04");
250
+ availability.addAvailability(location, date, WonderlandTrailReservationType.Reserved, WonderlandTrailReservationType.Walkup);
251
+
252
+ const dayAvailability: WonderlandTrailAvailabilityType = availability.getDayAvailability(location, date).await();
253
+ const expected: WonderlandTrailAvailabilityType = {
254
+ groupSite: WonderlandTrailReservationType.Walkup,
255
+ individualSite: WonderlandTrailReservationType.Reserved,
256
+ };
257
+ test.assertEqual(dayAvailability, expected);
258
+ test.assertSame(dayAvailability, availability.getDayAvailability(location, date).await());
259
+ });
260
+ });
261
+ });
262
+
263
+ runner.testType("WonderlandTrailDirection", () =>
264
+ {
265
+ runner.testFunction("toString()", (test: Test) =>
266
+ {
267
+ test.assertEqual("Clockwise", WonderlandTrailDirection.clockwise.toString());
268
+ test.assertEqual("CounterClockwise", WonderlandTrailDirection.counterClockwise.toString());
269
+ });
270
+
271
+ runner.testFunction("reverse()", (test: Test) =>
272
+ {
273
+ test.assertSame(WonderlandTrailDirection.counterClockwise, WonderlandTrailDirection.clockwise.reverse());
274
+ test.assertSame(WonderlandTrailDirection.clockwise, WonderlandTrailDirection.counterClockwise.reverse());
275
+ });
276
+ });
277
+
278
+ runner.testType("WonderlandTrailConnection", () =>
279
+ {
280
+ runner.testFunction("create()", (test: Test) =>
281
+ {
282
+ const connection: WonderlandTrailConnection = WonderlandTrailConnection.create(
283
+ WonderlandTrailLocations.boxCanyon,
284
+ WonderlandTrailLocations.carbonRiver,
285
+ 5000,
286
+ 2000,
287
+ 10,
288
+ WonderlandTrailDirection.clockwise,
289
+ Iterable.create([
290
+ WonderlandTrailLocations.cataractValley,
291
+ WonderlandTrailLocations.devilsDream,
292
+ ]),
293
+ );
294
+ test.assertNotUndefinedAndNotNull(connection);
295
+ test.assertEqual(connection.startLocation, WonderlandTrailLocations.boxCanyon);
296
+ test.assertEqual(connection.endLocation, WonderlandTrailLocations.carbonRiver);
297
+ test.assertEqual(connection.distanceMiles, 5000);
298
+ test.assertEqual(connection.ascentFeet, 2000);
299
+ test.assertEqual(connection.descentFeet, 10);
300
+ test.assertEqual(connection.direction, WonderlandTrailDirection.clockwise);
301
+ test.assertEqual(connection.intermediateLocations, Iterable.create([
302
+ WonderlandTrailLocations.cataractValley,
303
+ WonderlandTrailLocations.devilsDream,
304
+ ]));
305
+ });
306
+
307
+ runner.testFunction("getLocations()", () =>
308
+ {
309
+ runner.test("when connection is not a loop", (test: Test) =>
310
+ {
311
+ const connection: WonderlandTrailConnection = WonderlandTrailConnection.create(
312
+ WonderlandTrailLocations.boxCanyon,
313
+ WonderlandTrailLocations.carbonRiver,
314
+ 5000,
315
+ 2000,
316
+ 10,
317
+ WonderlandTrailDirection.clockwise,
318
+ Iterable.create([
319
+ WonderlandTrailLocations.cataractValley,
320
+ WonderlandTrailLocations.devilsDream,
321
+ ]),
322
+ );
323
+ test.assertEqual(connection.getLocations(), Iterable.create([
324
+ WonderlandTrailLocations.boxCanyon,
325
+ WonderlandTrailLocations.cataractValley,
326
+ WonderlandTrailLocations.devilsDream,
327
+ WonderlandTrailLocations.carbonRiver,
328
+ ]));
329
+ });
330
+
331
+ runner.test("when connection is a loop", (test: Test) =>
332
+ {
333
+ const connection: WonderlandTrailConnection = WonderlandTrailConnection.create(
334
+ WonderlandTrailLocations.boxCanyon,
335
+ WonderlandTrailLocations.boxCanyon,
336
+ 5000,
337
+ 2000,
338
+ 10,
339
+ WonderlandTrailDirection.clockwise,
340
+ Iterable.create([
341
+ WonderlandTrailLocations.cataractValley,
342
+ WonderlandTrailLocations.devilsDream,
343
+ ]),
344
+ );
345
+ test.assertEqual(connection.getLocations(), Iterable.create([
346
+ WonderlandTrailLocations.boxCanyon,
347
+ WonderlandTrailLocations.cataractValley,
348
+ WonderlandTrailLocations.devilsDream,
349
+ ]));
350
+ });
351
+ });
352
+
353
+ runner.testFunction("reverseDirection()", (test: Test) =>
354
+ {
355
+ const connection: WonderlandTrailConnection = WonderlandTrailConnection.create(
356
+ WonderlandTrailLocations.boxCanyon,
357
+ WonderlandTrailLocations.carbonRiver,
358
+ 5000,
359
+ 2000,
360
+ 10,
361
+ WonderlandTrailDirection.clockwise,
362
+ Iterable.create([
363
+ WonderlandTrailLocations.cataractValley,
364
+ WonderlandTrailLocations.devilsDream,
365
+ ]),
366
+ );
367
+ const reversedConnection: WonderlandTrailConnection = connection.reverseDirection();
368
+ test.assertNotSame(connection, reversedConnection);
369
+ test.assertEqual(reversedConnection.startLocation, WonderlandTrailLocations.carbonRiver);
370
+ test.assertEqual(reversedConnection.endLocation, WonderlandTrailLocations.boxCanyon);
371
+ test.assertEqual(reversedConnection.distanceMiles, 5000);
372
+ test.assertEqual(reversedConnection.ascentFeet, 10);
373
+ test.assertEqual(reversedConnection.descentFeet, 2000);
374
+ test.assertEqual(reversedConnection.direction, WonderlandTrailDirection.counterClockwise);
375
+ test.assertEqual(reversedConnection.intermediateLocations, Iterable.create([
376
+ WonderlandTrailLocations.cataractValley,
377
+ WonderlandTrailLocations.devilsDream,
378
+ ]));
379
+ });
380
+ });
381
+
382
+ runner.testType("WonderlandTrailClient", () =>
383
+ {
384
+ runner.testFunction("create()", () =>
385
+ {
386
+ runner.test("with undefined HttpClient", (test: Test) =>
387
+ {
388
+ test.assertThrows(() => WonderlandTrailClient.create(undefined!), new PreConditionError(
389
+ "Expression: httpClient",
390
+ "Expected: not undefined and not null",
391
+ "Actual: undefined",
392
+ ));
393
+ });
394
+
395
+ runner.test("with null HttpClient", (test: Test) =>
396
+ {
397
+ test.assertThrows(() => WonderlandTrailClient.create(null!), new PreConditionError(
398
+ "Expression: httpClient",
399
+ "Expected: not undefined and not null",
400
+ "Actual: null",
401
+ ));
402
+ });
403
+
404
+ runner.test("with defined HttpClient", (test: Test) =>
405
+ {
406
+ const httpClient: HttpClient = HttpClient.create();
407
+ const client: WonderlandTrailClient = WonderlandTrailClient.create(httpClient);
408
+ test.assertNotUndefinedAndNotNull(client);
409
+ });
410
+ });
411
+
412
+ runner.testFunction("getAvailability()", runner.skip(true, "Ignore slow running tests for now"), () =>
413
+ {
414
+ runner.test("with year in the past", async (test: Test) =>
415
+ {
416
+ const httpClient: HttpClient = HttpClient.create();
417
+ const client: WonderlandTrailClient = WonderlandTrailClient.create(httpClient);
418
+
419
+ const availability: WonderlandTrailAvailability = await client.getAvailability(4, 2023, true, true, true);
420
+ test.assertNotUndefinedAndNotNull(availability);
421
+ test.assertFalse(availability.any());
422
+ });
423
+
424
+ runner.test("with month in the past", async (test: Test) =>
425
+ {
426
+ const httpClient: HttpClient = HttpClient.create();
427
+ const client: WonderlandTrailClient = WonderlandTrailClient.create(httpClient);
428
+
429
+ const availability: WonderlandTrailAvailability = await client.getAvailability(3, 2026, true, true, true);
430
+ test.assertNotUndefinedAndNotNull(availability);
431
+ test.assertFalse(availability.any());
432
+ });
433
+
434
+ runner.test("with a future month in the current year", async (test: Test) =>
435
+ {
436
+ const httpClient: HttpClient = HttpClient.create();
437
+ const client: WonderlandTrailClient = WonderlandTrailClient.create(httpClient);
438
+
439
+ const availability: WonderlandTrailAvailability = await client.getAvailability({
440
+ month: 7,
441
+ year: 2026,
442
+ allowGroupSites: true,
443
+ allowIndividualSites: true,
444
+ allowWalkupPermits: true,
445
+ });
446
+ test.assertNotUndefinedAndNotNull(availability);
447
+ test.assertTrue(availability.any());
448
+ });
449
+ });
450
+ });
451
+ });
452
452
  }