Random themed example watches, Zulip instead of ntfy
- A fresh install generates two example watches from ARN: a themed, funny name (Christmas, New Year, getaway weekend, sun escape, ski week, Valentine's, Easter, Midsummer, bucket list), a fitting SAS award destination and dates at the theme's next occurrence; saved on first run. "New random example" regenerates the watches and keeps targets. - Notifications: ntfy and its priority column removed (ntfy entries get a clear validation error); new zulip type for Zulip's Slack-compatible webhook, with one topic per watch - Wider name field Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
05d1d28522
commit
06c41615b8
3 files changed
+202
-49
No files matched your search
@@ -218,3 +218,55 @@ test('cabins are configured by name; old codes and SAS names still work', () =>
|
||||
assert.throws(() => cabinsOf(['first']), /unknown cabin "first", use economy, premium or business/);
|
||||
assert.deepEqual(core.CABINS, { AG: 'Economy', AP: 'Premium', AB: 'Business' });
|
||||
});
|
||||
|
||||
// every award destination SAS listed from ARN on 2026-10-13 (award-finder destinations/v1)
|
||||
const SAS_FROM_ARN = new Set(('AGA ALC ALF AMS AYT ATH ATL BCN BRI BGO BER BIO BLL BHX BOO BLQ BOD BOS BRU BUD CTA CHQ ORD DUB DUS EDI FAO ' +
|
||||
'FLR FRA FUE FAE GZP GDN GVA GOT HAD HAM HAJ EVE HAU HEL INN KLR KKN KRN KRK KRS KSU CPH LCA LPA LIS LHR LYR LAX LLA LUX LYS FNC ' +
|
||||
'MAD AGP MMX MLA MAN RAK MIA MXP LIN BOM MUC NAP EWR JFK NCE OLB OSL PLQ PMO PMI CDG PSA OPO POZ PRG PUY KEF RHO FCO RNB RVN SZG ' +
|
||||
'SFO SEA ICN SVQ SFT SPU SVG STR SDL SCR TLL TLV TFS SKG HND YYZ TOS TRD UME VAA VCE VNO VBY WAW IAD VIE WRO ZRH AGH TKU AAL AES ' +
|
||||
'AAR OSD').split(' '));
|
||||
|
||||
const seeded = (seed) => () => ((seed = (seed * 16807) % 2147483647) - 1) / 2147483646;
|
||||
|
||||
test('example destinations are all SAS award destinations from ARN', () => {
|
||||
for (const t of core.THEMES) for (const code of t.places) assert.ok(SAS_FROM_ARN.has(code) && core.PLACES[code], code);
|
||||
});
|
||||
|
||||
test('date rules for yearly themes', () => {
|
||||
assert.equal(core.easterSunday(2027), '2027-03-28');
|
||||
assert.equal(core.easterSunday(2028), '2028-04-16');
|
||||
const win = (i, y) => core.THEMES[i].window(y, '2026-10-13', () => 0);
|
||||
assert.deepEqual(win(0, 2026), { from: '2026-12-20', to: '2026-12-30' }); // Christmas
|
||||
assert.deepEqual(win(4, 2027), { from: '2027-02-27', to: '2027-03-07' }); // sportlov, ISO week 9
|
||||
assert.deepEqual(win(6, 2027), { from: '2027-03-25', to: '2027-03-29' }); // Maundy Thursday -> Easter Monday
|
||||
assert.deepEqual(win(7, 2027), { from: '2027-06-24', to: '2027-06-27' }); // around Midsummer Eve, Fri 25 June
|
||||
const weekend = core.THEMES[2].window(2026, '2026-10-13', () => 0);
|
||||
assert.deepEqual(weekend, { from: '2026-11-06', to: '2026-11-09' }); // first Friday ≥ 3 weeks out, through Monday
|
||||
});
|
||||
|
||||
test('example configs are valid, near-future, themed and different each time', () => {
|
||||
const today = '2026-10-13';
|
||||
const names = new Set();
|
||||
for (let seed = 1; seed <= 200; seed++) {
|
||||
const cfg = core.exampleConfig(today, seeded(seed));
|
||||
const valid = core.validateConfig(cfg);
|
||||
assert.equal(valid.watches.length, 2);
|
||||
assert.deepEqual(cfg.notify, []);
|
||||
for (const w of cfg.watches) {
|
||||
assert.deepEqual(w.origins, ['ARN']);
|
||||
assert.ok(w.from >= '2026-10-27' && w.from <= '2027-05-11', `${w.name} ${w.from}`);
|
||||
assert.ok(w.to > w.from);
|
||||
assert.ok(w.name.includes(core.PLACES[w.destinations[0]]), w.name);
|
||||
names.add(w.name);
|
||||
}
|
||||
assert.notEqual(cfg.watches[0].name, cfg.watches[1].name);
|
||||
}
|
||||
assert.ok(names.size > 40, `only ${names.size} distinct names`);
|
||||
});
|
||||
|
||||
test('ntfy targets are rejected with a clear message; zulip is accepted', () => {
|
||||
assert.throws(() => core.validateConfig({ notify: [{ type: 'ntfy', url: 'https://ntfy.sh/x' }], watches: [watch()] }),
|
||||
/ntfy is no longer supported/);
|
||||
assert.equal(core.validateConfig({ notify: [{ type: 'zulip', url: 'https://x.zulipchat.com/api/v1/external/slack_incoming?api_key=k&stream=s' }],
|
||||
watches: [watch()] }).notify[0].type, 'zulip');
|
||||
});
|
||||
Reference in new issue
Block a user