@curless/hotel-storefront 0.27.5 → 0.27.7

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 (113) hide show
  1. package/README.md +18 -8
  2. package/dist/fence.d.ts +12 -1
  3. package/dist/fence.d.ts.map +1 -1
  4. package/dist/fence.js +0 -0
  5. package/dist/fence.js.map +1 -1
  6. package/dist/huazhu/backend.d.ts +9 -0
  7. package/dist/huazhu/backend.d.ts.map +1 -1
  8. package/dist/huazhu/backend.js +18 -2
  9. package/dist/huazhu/backend.js.map +1 -1
  10. package/dist/huazhu/cancel-policy.d.ts.map +1 -1
  11. package/dist/huazhu/cancel-policy.js +3 -1
  12. package/dist/huazhu/cancel-policy.js.map +1 -1
  13. package/dist/index.js +0 -0
  14. package/dist/legal.js +1 -1
  15. package/dist/legal.js.map +1 -1
  16. package/dist/money.d.ts +2 -0
  17. package/dist/money.d.ts.map +1 -1
  18. package/dist/money.js +43 -6
  19. package/dist/money.js.map +1 -1
  20. package/dist/server.d.ts +1 -1
  21. package/dist/server.d.ts.map +1 -1
  22. package/dist/server.js +9 -1
  23. package/dist/server.js.map +1 -1
  24. package/dist/sessions.d.ts.map +1 -1
  25. package/dist/sessions.js +3 -2
  26. package/dist/sessions.js.map +1 -1
  27. package/dist/surface.d.ts +2 -0
  28. package/dist/surface.d.ts.map +1 -1
  29. package/dist/surface.js +10 -1
  30. package/dist/surface.js.map +1 -1
  31. package/dist/tools.d.ts +4 -4
  32. package/dist/tools.d.ts.map +1 -1
  33. package/dist/tools.js +21 -8
  34. package/dist/tools.js.map +1 -1
  35. package/dist/trip-ids.js +1 -1
  36. package/dist/trip-ids.js.map +1 -1
  37. package/package.json +10 -11
  38. package/dist/__tests__/__fixtures__/huazhu-fake.d.ts +0 -2
  39. package/dist/__tests__/__fixtures__/huazhu-fake.d.ts.map +0 -1
  40. package/dist/__tests__/__fixtures__/huazhu-fake.js +0 -3
  41. package/dist/__tests__/__fixtures__/huazhu-fake.js.map +0 -1
  42. package/dist/__tests__/__helpers__/sessions.d.ts +0 -10
  43. package/dist/__tests__/__helpers__/sessions.d.ts.map +0 -1
  44. package/dist/__tests__/__helpers__/sessions.js +0 -40
  45. package/dist/__tests__/__helpers__/sessions.js.map +0 -1
  46. package/dist/__tests__/audit-p0.test.d.ts +0 -2
  47. package/dist/__tests__/audit-p0.test.d.ts.map +0 -1
  48. package/dist/__tests__/audit-p0.test.js +0 -274
  49. package/dist/__tests__/audit-p0.test.js.map +0 -1
  50. package/dist/__tests__/audit-p2.test.d.ts +0 -2
  51. package/dist/__tests__/audit-p2.test.d.ts.map +0 -1
  52. package/dist/__tests__/audit-p2.test.js +0 -98
  53. package/dist/__tests__/audit-p2.test.js.map +0 -1
  54. package/dist/__tests__/card-contract.test.d.ts +0 -2
  55. package/dist/__tests__/card-contract.test.d.ts.map +0 -1
  56. package/dist/__tests__/card-contract.test.js +0 -282
  57. package/dist/__tests__/card-contract.test.js.map +0 -1
  58. package/dist/__tests__/data.test.d.ts +0 -2
  59. package/dist/__tests__/data.test.d.ts.map +0 -1
  60. package/dist/__tests__/data.test.js +0 -210
  61. package/dist/__tests__/data.test.js.map +0 -1
  62. package/dist/__tests__/dates.test.d.ts +0 -2
  63. package/dist/__tests__/dates.test.d.ts.map +0 -1
  64. package/dist/__tests__/dates.test.js +0 -107
  65. package/dist/__tests__/dates.test.js.map +0 -1
  66. package/dist/__tests__/demo-hotels.test.d.ts +0 -2
  67. package/dist/__tests__/demo-hotels.test.d.ts.map +0 -1
  68. package/dist/__tests__/demo-hotels.test.js +0 -765
  69. package/dist/__tests__/demo-hotels.test.js.map +0 -1
  70. package/dist/__tests__/huazhu-audit.test.d.ts +0 -2
  71. package/dist/__tests__/huazhu-audit.test.d.ts.map +0 -1
  72. package/dist/__tests__/huazhu-audit.test.js +0 -234
  73. package/dist/__tests__/huazhu-audit.test.js.map +0 -1
  74. package/dist/__tests__/huazhu-backend.test.d.ts +0 -2
  75. package/dist/__tests__/huazhu-backend.test.d.ts.map +0 -1
  76. package/dist/__tests__/huazhu-backend.test.js +0 -1326
  77. package/dist/__tests__/huazhu-backend.test.js.map +0 -1
  78. package/dist/__tests__/huazhu-cancel-policy.test.d.ts +0 -2
  79. package/dist/__tests__/huazhu-cancel-policy.test.d.ts.map +0 -1
  80. package/dist/__tests__/huazhu-cancel-policy.test.js +0 -82
  81. package/dist/__tests__/huazhu-cancel-policy.test.js.map +0 -1
  82. package/dist/__tests__/huazhu-sandbox.test.d.ts +0 -2
  83. package/dist/__tests__/huazhu-sandbox.test.d.ts.map +0 -1
  84. package/dist/__tests__/huazhu-sandbox.test.js +0 -195
  85. package/dist/__tests__/huazhu-sandbox.test.js.map +0 -1
  86. package/dist/__tests__/huazhu-sellable.test.d.ts +0 -2
  87. package/dist/__tests__/huazhu-sellable.test.d.ts.map +0 -1
  88. package/dist/__tests__/huazhu-sellable.test.js +0 -192
  89. package/dist/__tests__/huazhu-sellable.test.js.map +0 -1
  90. package/dist/__tests__/present.test.d.ts +0 -2
  91. package/dist/__tests__/present.test.d.ts.map +0 -1
  92. package/dist/__tests__/present.test.js +0 -367
  93. package/dist/__tests__/present.test.js.map +0 -1
  94. package/dist/__tests__/prose.test.d.ts +0 -2
  95. package/dist/__tests__/prose.test.d.ts.map +0 -1
  96. package/dist/__tests__/prose.test.js +0 -171
  97. package/dist/__tests__/prose.test.js.map +0 -1
  98. package/dist/__tests__/server.test.d.ts +0 -2
  99. package/dist/__tests__/server.test.d.ts.map +0 -1
  100. package/dist/__tests__/server.test.js +0 -557
  101. package/dist/__tests__/server.test.js.map +0 -1
  102. package/dist/__tests__/state.test.d.ts +0 -2
  103. package/dist/__tests__/state.test.d.ts.map +0 -1
  104. package/dist/__tests__/state.test.js +0 -204
  105. package/dist/__tests__/state.test.js.map +0 -1
  106. package/dist/__tests__/tool-descriptions.test.d.ts +0 -2
  107. package/dist/__tests__/tool-descriptions.test.d.ts.map +0 -1
  108. package/dist/__tests__/tool-descriptions.test.js +0 -220
  109. package/dist/__tests__/tool-descriptions.test.js.map +0 -1
  110. package/dist/__tests__/tools.test.d.ts +0 -2
  111. package/dist/__tests__/tools.test.d.ts.map +0 -1
  112. package/dist/__tests__/tools.test.js +0 -1598
  113. package/dist/__tests__/tools.test.js.map +0 -1
@@ -1,282 +0,0 @@
1
- import { createHash } from 'node:crypto';
2
- import { readFileSync, readdirSync } from 'node:fs';
3
- import { fileURLToPath } from 'node:url';
4
- import { describe, expect, it } from 'vitest';
5
- import { REQUEST_KINDS } from '../backend.js';
6
- import { HOTEL_CARD_HTML, HOTEL_CARD_SOURCE_SHA } from '../card.generated.js';
7
- import { toolNames } from '../config.js';
8
- import { buildOutputSchemas } from '../tools.js';
9
- // The card is served from `card.generated.ts`, not from `widget/`. Two things
10
- // can quietly come apart, and both look fine until a guest is looking at the
11
- // card:
12
- //
13
- // 1. the widget is edited and not rebuilt - the committed HTML is then last
14
- // week's card, and nothing else in the repo notices;
15
- // 2. a tool learns a new `view` and the card has no renderer for it - the
16
- // guest gets "this card could not be drawn" for an answer the server was
17
- // happy with.
18
- //
19
- // One test each.
20
- const widget = fileURLToPath(new URL('../../widget/', import.meta.url));
21
- describe('the built card', () => {
22
- it('is the card the widget sources currently produce', () => {
23
- const dir = `${widget}src`;
24
- const h = createHash('sha256');
25
- for (const name of readdirSync(dir).sort()) {
26
- h.update(name);
27
- h.update(readFileSync(`${dir}/${name}`));
28
- }
29
- h.update('index.html');
30
- h.update(readFileSync(`${widget}index.html`));
31
- expect(h.digest('hex'), 'widget/ has changed since the card was built - run `npm run build` in widget/').toBe(HOTEL_CARD_SOURCE_SHA);
32
- });
33
- it('is one self-contained page, with nothing fetched from anywhere', () => {
34
- expect(HOTEL_CARD_HTML.startsWith('<!doctype html>')).toBe(true);
35
- expect(HOTEL_CARD_HTML).not.toMatch(/<script[^>]+src=["']http/i);
36
- expect(HOTEL_CARD_HTML).not.toMatch(/<link[^>]+href=["']http/i);
37
- });
38
- it('draws every view the tools can answer with', () => {
39
- const names = toolNames({});
40
- const schemas = buildOutputSchemas(names);
41
- const views = new Set();
42
- for (const [tool, schema] of Object.entries(schemas)) {
43
- // The look-up draws nothing by design - its answer is text for the model.
44
- if (tool === names.lookUp)
45
- continue;
46
- const v = schema
47
- .properties?.view;
48
- for (const name of v?.enum ?? (v?.const ? [v.const] : []))
49
- views.add(name);
50
- }
51
- expect(views.size).toBeGreaterThan(10);
52
- for (const view of views) {
53
- // `error` is the card's fallback branch rather than a named renderer.
54
- if (view === 'error')
55
- continue;
56
- // A view whose name is a valid identifier comes out of the minifier as a
57
- // BARE key - `extras:someFn` - so looking only for the quoted string
58
- // reports a renderer missing that is right there.
59
- const drawn = HOTEL_CARD_HTML.includes(`"${view}"`) ||
60
- new RegExp(`\\b${view}\\s*:`).test(HOTEL_CARD_HTML);
61
- expect(drawn, `the card has no renderer for ${view}`).toBe(true);
62
- }
63
- });
64
- // ⚠️ TWICE a component's own `display` beat the UA's `[hidden]` at equal
65
- // specificity, because ours is the later sheet: the guest form was on screen
66
- // from the start, and the trip button stayed up on an empty trip - which is
67
- // how a guest reached a page with no way back. One blunt rule fixes the
68
- // class; this keeps it there.
69
- it('lets nothing outrank the hidden attribute', () => {
70
- expect(HOTEL_CARD_HTML.replace(/\s+/g, '')).toContain('[hidden]{display:none!important');
71
- });
72
- // A native dropdown paints itself in the OS's own chrome - a blue macOS
73
- // highlight in the middle of a card that follows the host's theme.
74
- it('has no native dropdown in it', () => {
75
- expect(HOTEL_CARD_HTML).not.toMatch(/<select\b/i);
76
- });
77
- // ⚠️ A CARD THAT NAVIGATES HAS TO COME BACK. Tapping a column of a comparison
78
- // replaced the comparison with that hotel and the comparison was gone - the
79
- // brand in the header goes HOME, which is a different answer, not the one the
80
- // guest was reading. robin tapped the second of three and could not get back
81
- // to the three (2026-09-21).
82
- it('has a way back to the answer a tap navigated away from', () => {
83
- expect(HOTEL_CARD_HTML).toContain('id="backbtn"');
84
- expect(HOTEL_CARD_HTML).toContain('data-act="back"');
85
- });
86
- // ⚠️ THE STRIP'S CHIPS ARE THE DATE BAR'S OWN ACTION. Each carries the hotel
87
- // and its own nights, so tapping one goes through the path that already
88
- // exists - no second way to change the dates, which is how the two would
89
- // come apart.
90
- it('draws the nearby dates as chips that carry their own nights', () => {
91
- expect(HOTEL_CARD_HTML).toContain('flex-dates');
92
- expect(HOTEL_CARD_HTML).toMatch(/data-ci=/);
93
- });
94
- // ⚠️ A CHIP THE SERVER DROPS IS A PROMISE THE CARD MADE AND NOBODY KEPT. The
95
- // guest ticks "quiet room", the booking goes through, the confirmation lists
96
- // everything except that - and nothing anywhere says why. One list, both
97
- // sides.
98
- it('offers exactly the preferences the server understands', () => {
99
- const src = readFileSync(`${widget}src/card.ts`, 'utf8');
100
- const list = src.slice(src.indexOf('const REQUESTS'), src.indexOf('const OPPOSITES'));
101
- const ids = [...list.matchAll(/id: '([a-z-]+)'/g)].map((m) => m[1]);
102
- expect(ids).toEqual(REQUEST_KINDS);
103
- });
104
- // ⚠️ THE CARD DOES NO ARITHMETIC ON MONEY. Every price it holds is a string
105
- // the server formatted; "HK$8,588" and "HK$10,305.60" cannot be compared
106
- // without parsing money out of text, and a card that parsed it would be one
107
- // locale away from marking the wrong date as the cheapest. The server sends
108
- // the mark.
109
- it('takes the cheapest date as a flag rather than working it out', () => {
110
- const src = readFileSync(`${widget}src/card.ts`, 'utf8');
111
- const strip = src.slice(src.indexOf('const dateStrip'), src.indexOf('const hotelView'));
112
- expect(strip).toContain('d.best');
113
- expect(strip, 'the strip is parsing money out of a formatted price').not.toMatch(/parseFloat|parseInt|Number\(|replace\(/);
114
- });
115
- it('says the two things this connector must never stop saying', () => {
116
- expect(HOTEL_CARD_HTML).toContain('Nothing has been charged');
117
- expect(HOTEL_CARD_HTML).toContain('No card is taken');
118
- });
119
- });
120
- // The history, read from the source: these are rules about what the card does,
121
- // and a minified build keeps the strings but not the shape. Each one is a bug
122
- // the 2026-09-28 audit walked into on the live connector.
123
- describe("the card's history", () => {
124
- const SRC = readFileSync(`${widget}src/card.ts`, 'utf8');
125
- const CSS = readFileSync(`${widget}src/card.css`, 'utf8');
126
- // ⚠️ A CHIP THAT IS SEVERAL CALLS makes them in turn, and Back returns to
127
- // where it was pressed once, not once per stay.
128
- it('runs a chip’s calls one after another, pushing Back only for the first', () => {
129
- expect(SRC).toContain('await call(String(a.tool), a.args ?? {}, { push: i === 0 });');
130
- expect(SRC).toContain('x?.ask || x?.asks?.length');
131
- // Check-out day is a line, not another stay.
132
- expect(SRC).toContain('Check out · ${esc(it.name)}');
133
- });
134
- // ⚠️ SHORT BY DEFAULT (robin, 2026-09-29: 「这个首页选择的还是太长了」): the top
135
- // cities and one row of regions, each region opening its own countries.
136
- it('opens the places page on the top cities and a row of regions, folded', () => {
137
- expect(SRC).toContain('data-region-body="${i}" hidden');
138
- expect(SRC).toContain('Top cities');
139
- expect(SRC).toContain('const COUNTRIES_SHOWN = 6;');
140
- });
141
- it('pushes a step only when the guest moves, never for a refresh of the same view', () => {
142
- expect(SRC).toContain('placeOf(next) === placeOf(lastPayload)');
143
- });
144
- // ⚠️ THE CHAT SCROLLS, NOT THE CARD: a page change pressed from low on the
145
- // card opened the new page with its top above the screen (robin,
146
- // 2026-09-29). Only when the header is off screen - `nearest` - so a guest
147
- // who never scrolled sees nothing move.
148
- it('brings the top of a new page into view when the guest moves', () => {
149
- expect(SRC).toContain("head.scrollIntoView({ block: 'nearest'");
150
- expect(SRC).toContain('if (moved) showTop();');
151
- });
152
- // ⚠️ A LIST IS PAGED IN WHOLE ROWS, IN PLACE (robin, 2026-09-29): three
153
- // rows of however many fit across - six in a chat - Previous and Next, and
154
- // the lot only in full screen - never "Show more" growing the card inline
155
- // without end.
156
- it('pages a list three whole rows at a time, and shows the lot only full screen', () => {
157
- expect(SRC).toContain('const PAGE_ROWS = 3;');
158
- expect(SRC).toContain('data-act="page-next"');
159
- expect(SRC).toContain('data-act="page-prev"');
160
- expect(SRC).toMatch(/fullscreen\(\)\s*\?\s*\(d\.hotels \?\? \[\]\)\s*:\s*\(d\.hotels \?\? \[\]\)\.slice\(0, pageDrawn\)/);
161
- expect(SRC).toContain("availableDisplayModes: ['inline', 'fullscreen']");
162
- });
163
- // ⚠️ THE PLAN IS ONE CARD WORTH READING (robin, 2026-09-29): the day in order,
164
- // the hotel once per stay as a hotel, the nights after it as one line.
165
- it('draws the day in order, and each stay once with its picture and its nights', () => {
166
- expect(SRC).toContain('<ol class="moments">');
167
- expect(SRC).toContain('class="plan-stay"');
168
- expect(SRC).toContain('class="plan-night"');
169
- });
170
- // ⚠️ THE HEADS OF A COMPARISON LINE UP ROW BY ROW: the "Recommended" mark
171
- // pushed its own column's picture down and nothing lined up (2026-09-29).
172
- it('gives every comparison head the same rows, a mark or its empty place', () => {
173
- expect(SRC).toContain("pickmark${c.recommended ? '' : ' none'}");
174
- expect(CSS).toContain('grid-template-rows: subgrid;');
175
- });
176
- it('asks a step again when something has changed since it was drawn', () => {
177
- expect(SRC).toContain('step.version === stateVersion');
178
- expect(SRC).toMatch(/CHANGES_STATE = new Set\(\[[^\]]*'requestBooking'/s);
179
- });
180
- it('does not offer back to a booked trip or a finished change', () => {
181
- expect(SRC).toContain("forget(['trip', 'needs-dates', 'needs-guest'])");
182
- expect(SRC).toMatch(/const noBack = new Set\(\[[^\]]*'changed'/s);
183
- });
184
- it('confirms a change of room count in both directions', () => {
185
- // `rooms` used to go only when it was above one: "2 rooms → 1" could not be made.
186
- expect(SRC).not.toContain('Number(to.rooms) > 1');
187
- });
188
- it('draws every booking of a trip of more than one stay, and a refusal in words', () => {
189
- expect(SRC).toContain('d.bookings');
190
- expect(SRC).toContain('error: errorView');
191
- });
192
- });
193
- describe('a trip that cannot be requested', () => {
194
- const SRC = readFileSync(`${widget}src/card.ts`, 'utf8');
195
- it('draws no booking form under an add-on with no room', () => {
196
- expect(SRC).toContain('d.needsRoom.length');
197
- expect(SRC).toContain('Goes with a stay');
198
- });
199
- });
200
- describe('a list longer than a page', () => {
201
- const SRC = readFileSync(`${widget}src/card.ts`, 'utf8');
202
- it('offers the places it counted and the next page, folded into this one', () => {
203
- expect(SRC).toContain('data-place=');
204
- expect(SRC).toContain("act === 'more-hotels'");
205
- // The next page joins the list on screen; it does not replace it.
206
- expect(SRC).toContain('hotels: [...(shown.hotels ?? []), ...(next.hotels ?? [])]');
207
- });
208
- });
209
- describe("a list's order", () => {
210
- const SRC = readFileSync(`${widget}src/card.ts`, 'utf8');
211
- it('is a row at the top of the list, with no price order across currencies', () => {
212
- expect(SRC).toContain('data-sort=');
213
- expect(SRC).toContain("priced || !k.startsWith('price')");
214
- });
215
- });
216
- describe('where, then when', () => {
217
- const SRC = readFileSync(`${widget}src/card.ts`, 'utf8');
218
- it('opens on a place and the dates, and prices a tile for the stay', () => {
219
- expect(SRC).toContain('id="dci"');
220
- expect(SRC).toContain('data-act="find"');
221
- expect(SRC).toContain('const tilePrice = ');
222
- expect(SRC).toContain('data-act="find-booking"');
223
- });
224
- });
225
- describe("a list's filters", () => {
226
- const SRC = readFileSync(`${widget}src/card.ts`, 'utf8');
227
- it('fold behind one button that counts them, with a way to clear them', () => {
228
- expect(SRC).toContain('data-panel="${key}"');
229
- expect(SRC).toContain('data-act="clear-filters"');
230
- expect(SRC).toContain('data-filter=');
231
- });
232
- });
233
- // Three things a guest read wrong off a room's price, and one view that showed
234
- // demonstration money unmarked (2026-10-05 audit).
235
- describe("a room's price and its terms", () => {
236
- const SRC = readFileSync(`${widget}src/card.ts`, 'utf8');
237
- it('strikes through the public rate for the same number of rooms as the price under it', () => {
238
- expect(SRC).toContain('r.publicRoomsTotal ?? r.publicStayTotal');
239
- });
240
- it('shows the free-cancellation deadline as the server wrote it, hour and all', () => {
241
- expect(SRC).toContain('r.freeCancellationLocal');
242
- expect(SRC).not.toMatch(/freeCancellationUntil\)\.slice\(0, 10\)/);
243
- });
244
- it('does not call a before-tax nightly rate "incl. tax"', () => {
245
- expect(SRC).not.toContain('· incl. tax');
246
- expect(SRC).toContain('/ night + tax');
247
- });
248
- it('marks the cancellation fee as demonstration money', () => {
249
- const cancel = SRC.slice(SRC.indexOf('const cancelView'), SRC.indexOf('const cancelView') + 1200);
250
- expect(cancel).toContain('demoStrip()');
251
- });
252
- });
253
- // A trip id opens the trip, not the bookings (2026-10-05 audit, P0-3): the
254
- // card asks for a booking by its code and the email it was shown with it.
255
- describe("the card's booking buttons", () => {
256
- const SRC = readFileSync(`${widget}src/card.ts`, 'utf8');
257
- it('send the code and its email, never the code alone', () => {
258
- for (const call of [
259
- "call('previewCancellation', byCode(",
260
- "call('cancelBooking', { ...byCode(",
261
- "call('listExtras', byCode(",
262
- ]) {
263
- expect(SRC).toContain(call);
264
- }
265
- expect(SRC).not.toMatch(/call\('(previewCancellation|cancelBooking)', \{ booking:/);
266
- });
267
- });
268
- // One pager for every Curless card (card-kit/pager.ts, robin 2026-10-05): the
269
- // hotel list pages with the shelf's markup, so it takes the shelf's look.
270
- describe("the hotel list's pages", () => {
271
- const SRC = readFileSync(`${widget}src/card.ts`, 'utf8');
272
- const CSS = readFileSync(`${widget}src/card.css`, 'utf8');
273
- it('use the shared pager and its "show more", with our own data-act', () => {
274
- expect(SRC).toContain('pagerHtml({');
275
- expect(SRC).toContain('prev: \'data-act="page-prev"\'');
276
- expect(SRC).toContain('next: \'data-act="page-next"\'');
277
- expect(SRC).toContain('moreHtml(');
278
- expect(SRC).not.toContain('class="pager"');
279
- expect(CSS).not.toMatch(/^\.pager\b/m);
280
- });
281
- });
282
- //# sourceMappingURL=card-contract.test.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"card-contract.test.js","sourceRoot":"","sources":["../../src/__tests__/card-contract.test.ts"],"names":[],"mappings":"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"}
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=data.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"data.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/data.test.ts"],"names":[],"mappings":""}
@@ -1,210 +0,0 @@
1
- import { readFileSync } from 'node:fs';
2
- import { fileURLToPath } from 'node:url';
3
- import { describe, expect, it } from 'vitest';
4
- import { loadHotelData, parseHotelData } from '../data.js';
5
- import { formatMoney, money, taxOn, toMinor } from '../money.js';
6
- const FIXTURE = fileURLToPath(new URL('./__fixtures__/brand.json', import.meta.url));
7
- const hotel = (over = {}) => ({
8
- id: 'h1',
9
- name: 'A Hotel',
10
- brand: 'Brand',
11
- city: 'Hong Kong',
12
- cityId: 'hong-kong',
13
- summary: 'Somewhere to sleep.',
14
- amenities: ['Pool'],
15
- currency: 'HKD',
16
- taxRate: 0.13,
17
- weekendUplift: 0.2,
18
- rooms: [
19
- {
20
- id: 'r1',
21
- name: 'Deluxe',
22
- sleeps: 2,
23
- breakfast: false,
24
- nightly: 1000,
25
- roomsLeft: 3,
26
- refundable: true,
27
- freeCancelHours: 48,
28
- },
29
- ],
30
- ...over,
31
- });
32
- const file = (over = {}) => ({ brand: 'Brand', hotels: [hotel(over)] });
33
- describe('the brand file we actually ship', () => {
34
- // ⚠️ THESE ARE THE PACKAGE'S TESTS, ON THE PACKAGE'S OWN FIXTURE. Claims about
35
- // a BRAND's data - how many hotels it has, whether its search hint's numbers
36
- // are true, whether every property carries an address - left with the data
37
- // when Shangri-La became a customer (2026-09-21). They are claims about their
38
- // file and they belong in their repository; what stays here is the LOADER,
39
- // which is ours.
40
- it('parses a brand file and hands back what the tools need', () => {
41
- const data = loadHotelData(FIXTURE);
42
- expect(data.brand).toBe('Shangri-La');
43
- expect(data.hotels.length).toBeGreaterThan(5);
44
- for (const h of data.hotels) {
45
- expect(h.currency).toMatch(/^[A-Z]{3}$/);
46
- expect(h.rooms.length).toBeGreaterThan(0);
47
- }
48
- // More than one currency in one file, which is what makes the trip's
49
- // one-currency refusal and the comparison's currency note reachable at all.
50
- expect(new Set(data.hotels.map((h) => h.currency)).size).toBeGreaterThan(1);
51
- });
52
- it('keeps the hand-written hotels exactly as they were written', () => {
53
- const island = loadHotelData(FIXTURE).hotels.find((h) => h.id === 'hong-kong-island');
54
- expect(island?.name).toBe('Island Shangri-La, Hong Kong');
55
- expect(island?.area).toBe('Admiralty');
56
- expect(island?.rooms.find((r) => r.id === 'deluxe-city')?.nightly).toBe(3800);
57
- expect(island?.rating?.count).toBe(3184);
58
- });
59
- // ⚠️ A ROOM'S PICTURE HAS TO BE THAT ROOM'S. These came from each room type's
60
- // own page on the group's site, one per room - the easy wrong version is the
61
- // hotel's hero shot repeated down the list, which puts a lobby under the word
62
- // "Deluxe Peak View Room" and reads as a photograph of a room.
63
- it('gives the hand-written hotels a picture per ROOM, none of them shared', () => {
64
- const curated = new Set([
65
- 'hong-kong-island',
66
- 'hong-kong-kowloon',
67
- 'hong-kong-kerry',
68
- 'shanghai-pudong',
69
- 'shanghai-jingan',
70
- 'beijing-china-world',
71
- 'beijing-kerry',
72
- 'shenzhen-futian',
73
- ]);
74
- // ⚠️ COMPARED WITHOUT THE QUERY STRING. The generator appends `?w=960` to a
75
- // HOTEL's photograph and not to a room's, so the same picture in both places
76
- // compared unequal and this guard slept through it: Kerry Beijing's hero was
77
- // its own Questers family room, hotel hero and room thumbnail the same
78
- // image (found when the brand data left the repo, 2026-09-21).
79
- const same = (u) => String(u ?? '').split('?')[0] ?? '';
80
- const seen = new Map();
81
- for (const h of loadHotelData(FIXTURE).hotels) {
82
- if (!curated.has(h.id))
83
- continue;
84
- for (const r of h.rooms) {
85
- expect(r.imageUrl, `${h.id}/${r.id} has no photograph`).toBeTruthy();
86
- expect(same(r.imageUrl), `${h.id}/${r.id} reuses the hotel's own picture`).not.toBe(same(h.imageUrl));
87
- const where = seen.get(same(r.imageUrl));
88
- expect(where, `${h.id}/${r.id} shares a photograph with ${where}`).toBeUndefined();
89
- seen.set(same(r.imageUrl), `${h.id}/${r.id}`);
90
- }
91
- }
92
- });
93
- // ⚠️ AN ADDRESS IS A FACT OR IT IS NOTHING. Generated hotels had none at all
94
- // for two days - the card showed a real property with no street - and the one
95
- // tempting fix is to write "in the centre of <city>", which is a sentence
96
- // nobody can post a letter to. These come off each property's own page.
97
- it('gives every hotel the address its own page publishes', () => {
98
- for (const h of loadHotelData(FIXTURE).hotels) {
99
- expect(h.address, `${h.id} has no address`).toBeTruthy();
100
- expect(h.address?.length, `${h.id}'s address is too short to be one`).toBeGreaterThan(12);
101
- }
102
- });
103
- it('gives every hotel a photograph, because a wall of grey plates is not a storefront', () => {
104
- const missing = loadHotelData(FIXTURE)
105
- .hotels.filter((h) => !h.imageUrl)
106
- .map((h) => h.id);
107
- // JEN Hong Kong is not on the group's property list under a slug we could
108
- // harvest; it is the only one allowed to fall back to its drawn plate.
109
- expect(missing).toEqual(['hong-kong-jen']);
110
- });
111
- // ⚠️ THE POLICY AND THE ROOMS HAVE TO AGREE. The generated cancellation text
112
- // asserted a flat "free until 48 hours before" while the hotels carry 24, 48
113
- // and 72 hour rates - so a guest holding a 24-hour club rate was told, in the
114
- // hotel's own voice, that they had twice the time the card was showing them
115
- // on the same screen.
116
- it('never promises a cancellation window no room actually has', () => {
117
- for (const h of loadHotelData(FIXTURE).hotels) {
118
- const text = h.policies?.cancellation ?? '';
119
- const real = new Set(h.rooms.filter((r) => r.refundable).map((r) => String(r.freeCancelHours)));
120
- const claimed = [...text.matchAll(/(\d+)\s*(?:,|or|and|hours)/g)].map((m) => m[1]);
121
- for (const hours of claimed)
122
- expect(real, `${h.id} names ${hours} hours; its rooms have ${[...real].join(', ')}`).toContain(hours);
123
- // …and the SHORTEST window is the one that has to be named. Naming only
124
- // the long one is how a guest on a 24-hour rate reads "free until 48
125
- // hours before" in the hotel's own voice while the card, on the same
126
- // screen, shows them a deadline a day earlier.
127
- if (claimed.length && real.size) {
128
- const shortest = Math.min(...[...real].map(Number));
129
- expect(claimed.map(Number), `${h.id} names ${claimed.join('/')} hours but has a ${shortest}-hour rate`).toContain(shortest);
130
- }
131
- }
132
- });
133
- // ⚠️ POINTS ARE EARNED PER UNIT OF ONE CURRENCY. A hotel quoting in a
134
- // currency the programme cannot convert either earns at 1:1 - ¥150,000
135
- // becoming 150,000 points - or earns nothing at all. Both are a number on a
136
- // card nobody can defend, so the file is refused.
137
- it('refuses a hotel charging in a currency the programme cannot convert', () => {
138
- const data = JSON.parse(readFileSync(FIXTURE, 'utf8'));
139
- const broken = { ...data, hotels: [{ ...data.hotels[0], id: 'x', currency: 'NZD' }] };
140
- expect(() => parseHotelData(broken)).toThrow(/no earn rate/);
141
- });
142
- // ⚠️ A BRAND'S OWN PRODUCT NAMES BELONG TO THAT BRAND. Four generated hotels
143
- // sold a "Horizon Club Room" under a Traders or Kerry sign - a Shangri-La
144
- // lounge those brands do not run, printed on a card next to a real hotel's
145
- // real photograph.
146
- it('does not sell one brand’s named product under another brand’s sign', () => {
147
- for (const h of loadHotelData(FIXTURE).hotels) {
148
- if (h.brand === 'Shangri-La')
149
- continue;
150
- for (const r of h.rooms)
151
- expect(r.name, `${h.id} is a ${h.brand} and sells "${r.name}"`).not.toMatch(/Horizon/i);
152
- }
153
- });
154
- it('gives every room a cancellation story, one way or the other', () => {
155
- for (const h of loadHotelData(FIXTURE).hotels) {
156
- for (const r of h.rooms) {
157
- expect(r.refundable ? typeof r.freeCancelHours : 'undefined').toBe(r.refundable ? 'number' : 'undefined');
158
- }
159
- expect(h.policies?.cancellation, `${h.id} must publish a cancellation policy`).toBeTruthy();
160
- }
161
- });
162
- });
163
- describe('what the validator refuses', () => {
164
- it('a tax rate written as a percentage - 16 would be a 1600% tax that still renders', () => {
165
- expect(() => parseHotelData(file({ taxRate: 16 }))).toThrow(/taxRate is 16/);
166
- });
167
- it('a rate typed in minor units, which would look like a real if eye-watering price', () => {
168
- expect(() => parseHotelData(file({ rooms: [{ ...hotel().rooms[0], nightly: 380_000 }] }))).toThrow(/nightly is 380000/);
169
- });
170
- it('"free to cancel" with no deadline, and a deadline on a rate that has none', () => {
171
- expect(() => parseHotelData(file({ rooms: [{ ...hotel().rooms[0], freeCancelHours: undefined }] }))).toThrow(/must say freeCancelHours/);
172
- expect(() => parseHotelData(file({ rooms: [{ ...hotel().rooms[0], refundable: false }] }))).toThrow(/free window that does not exist/);
173
- });
174
- it('two hotels or two room types sharing an id, which would hold the wrong room', () => {
175
- expect(() => parseHotelData({ brand: 'B', hotels: [hotel(), hotel()] })).toThrow(/share the id h1/);
176
- expect(() => parseHotelData(file({ rooms: [hotel().rooms[0], { ...hotel().rooms[0], name: 'Other' }] }))).toThrow(/share the id r1/);
177
- });
178
- it('a hotel nobody can book, and a policy topic nothing would display', () => {
179
- expect(() => parseHotelData(file({ rooms: [] }))).toThrow(/no room types/);
180
- expect(() => parseHotelData(file({ policies: { parking: 'Free.' } }))).toThrow(/topic parking/);
181
- });
182
- it('a rating with no count behind it', () => {
183
- expect(() => parseHotelData(file({ rating: { value: 4.8, scaleMax: 5 } }))).toThrow(/rating.count/);
184
- });
185
- it('a file that is empty, or missing the brand it belongs to', () => {
186
- expect(() => parseHotelData({ hotels: [] })).toThrow(/no hotels/);
187
- expect(() => parseHotelData({ hotels: [hotel()] })).toThrow(/brand/);
188
- });
189
- });
190
- describe('money', () => {
191
- it('holds prices as integer minor units, so a tax rate cannot produce 4293.999999', () => {
192
- expect(toMinor(3800, 'HKD')).toBe(380_000);
193
- expect(toMinor(3800, 'JPY')).toBe(3800);
194
- expect(taxOn(money(380_000, 'HKD'), 0.13)).toEqual({ minor: 49_400, currency: 'HKD' });
195
- });
196
- it('writes money the way the guest reads it', () => {
197
- expect(formatMoney(money(380_000, 'HKD'))).toBe('HK$3,800');
198
- expect(formatMoney(money(1_030_560, 'HKD'))).toBe('HK$10,305.60');
199
- expect(formatMoney(money(145_000, 'CNY'))).toBe('¥1,450');
200
- expect(formatMoney(money(12_000, 'JPY'))).toBe('JP¥12,000');
201
- expect(formatMoney(money(5000, 'AED'))).toBe('50 AED');
202
- });
203
- // A trip in two currencies is totalled per currency and never summed; the
204
- // symbols are all that tells the two totals apart.
205
- it('never writes two currencies with the same symbol', () => {
206
- const written = ['HKD', 'CNY', 'SGD', 'USD', 'JPY', 'EUR', 'GBP'].map((c) => formatMoney(money(100, c)).replace(/[\d.,]/g, ''));
207
- expect(new Set(written).size).toBe(written.length);
208
- });
209
- });
210
- //# sourceMappingURL=data.test.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"data.test.js","sourceRoot":"","sources":["../../src/__tests__/data.test.ts"],"names":[],"mappings":"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"}
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=dates.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"dates.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/dates.test.ts"],"names":[],"mappings":""}