Export, Import and Reset; JSON editor removed

- Export downloads one file with the saved config, all match data and
  history, the flight cache and view settings
- Import restores such a file after a confirmation; older config-only
  .json files are accepted and keep existing match data
- Reset (with a warning) deletes everything and starts over with new
  random example watches; replaces "Reset state"
- The JSON config section is gone
- Old ntfy targets no longer stop the script: they are ignored at
  runtime and on import, shown as "no longer supported" in the editor

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Måns SivertssonandClaude Opus 5.5 committed 2026-10-13 09:08:47 +02:00
1 parent 06c41615b8
commit 9caff094ac
3 files changed
+135 -64

No files matched your search

+20
View File
@@ -270,3 +270,23 @@ test('ntfy targets are rejected with a clear message; zulip is accepted', () =>
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');
});
test('import reads full exports and older config-only backups, and rejects junk', () => {
const config = { notify: [], watches: [watch()] };
const state = { matches: { tokyo: { a: {}, b: {} } }, events: [] };
const full = core.parseBackup(JSON.stringify({ app: 'sas-bonus-watch', format: 1, exported_at: '2026-10-13T08:00:00Z',
data: { config, state, collapsed: { tokyo: true }, matchSort: 'newest' } }));
assert.equal(full.full, true);
assert.equal(full.tracked, 2);
assert.deepEqual(full.state, state);
assert.deepEqual(full.prefs, { collapsed: { tokyo: true }, matchSort: 'newest' });
const old = core.parseBackup(JSON.stringify(config));
assert.deepEqual([old.full, old.config], [false, config]);
assert.throws(() => core.parseBackup('{oops'), /not valid JSON/);
assert.throws(() => core.parseBackup('{"hello": 1}'), /not a SAS bonus watch export/);
assert.throws(() => core.parseBackup(JSON.stringify({ app: 'sas-bonus-watch', data: { state } })), /no config/);
assert.throws(() => core.parseBackup(JSON.stringify({ app: 'sas-bonus-watch', data: { config: { watches: [{ origins: 'X' }] } } })),
/not a 3-letter airport code/);
});