mirror of
https://github.com/olehomelchenko/astrolabe.git
synced 2026-08-08 02:02:33 +00:00
Snapshot URL datasets locally on add; preview tabular data as a table
This commit is contained in:
@@ -42,15 +42,82 @@ describe('save — create', () => {
|
||||
expect(ds?.rowCount).toBe(2);
|
||||
});
|
||||
|
||||
test('a valid URL infers format from the extension', () => {
|
||||
test('save() does not commit a URL create — it must go through commitUrlSnapshot', () => {
|
||||
store().startCreate();
|
||||
store().updateForm({ name: 'Remote', source: 'url', input: 'https://example.com/data.csv' });
|
||||
// The component fetches first; save() never touches the network, so a URL create
|
||||
// through save() is a no-op rather than an unfetched record.
|
||||
expect(store().save(T)).toBe(false);
|
||||
expect(store().datasets).toHaveLength(0);
|
||||
});
|
||||
});
|
||||
|
||||
describe('commitUrlSnapshot — create from a fetched body', () => {
|
||||
test('snapshots the body, infers format from content, and profiles it', () => {
|
||||
store().startCreate();
|
||||
store().updateForm({ name: 'Remote', source: 'url', input: 'https://example.com/data.csv' });
|
||||
|
||||
expect(store().save(T)).toBe(true);
|
||||
expect(store().commitUrlSnapshot({ text: 'a,b\n1,2\n3,4' }, T)).toBe(true);
|
||||
const ds = selectSelectedDataset(store());
|
||||
expect(ds?.source).toBe('url');
|
||||
expect(ds?.url).toBe('https://example.com/data.csv');
|
||||
expect(ds?.format).toBe('csv');
|
||||
expect(ds?.rowCount).toBeNull(); // URL datasets aren't profiled
|
||||
expect(ds?.data).toBe('a,b\n1,2\n3,4');
|
||||
expect(ds?.rowCount).toBe(2);
|
||||
expect(ds?.columns).toEqual(['a', 'b']);
|
||||
expect(ds?.fetchedAt).toBe(T.toISOString());
|
||||
expect(store().view).toBe('detail');
|
||||
});
|
||||
|
||||
test('a duplicate name is rejected even with a successful fetch', () => {
|
||||
store().add(
|
||||
createDataset({ name: 'Dupe', data: [{ a: 1 }], format: 'json', source: 'inline', now: T }),
|
||||
);
|
||||
store().startCreate();
|
||||
store().updateForm({ name: 'dupe', source: 'url', input: 'https://x/y.csv' });
|
||||
expect(store().commitUrlSnapshot({ text: 'a\n1' }, T)).toBe(false);
|
||||
expect(store().formError).toMatch(/already exists/i);
|
||||
});
|
||||
});
|
||||
|
||||
describe('URL dataset edits & refresh', () => {
|
||||
const seedUrl = () => {
|
||||
store().startCreate();
|
||||
store().updateForm({ name: 'Remote', source: 'url', input: 'https://x/y.csv' });
|
||||
store().commitUrlSnapshot({ text: 'a,b\n1,2' }, T);
|
||||
return store().selectedId!;
|
||||
};
|
||||
|
||||
test('a metadata-only edit (same URL) updates name without re-fetching', () => {
|
||||
const id = seedUrl();
|
||||
store().startEdit();
|
||||
store().updateForm({ name: 'Renamed' }); // URL field stays https://x/y.csv
|
||||
const later = new Date('2026-07-01T00:00:00Z');
|
||||
expect(store().save(later)).toBe(true);
|
||||
const ds = store().datasets.find((d) => d.id === id)!;
|
||||
expect(ds.name).toBe('Renamed');
|
||||
expect(ds.data).toBe('a,b\n1,2'); // snapshot untouched
|
||||
expect(ds.fetchedAt).toBe(T.toISOString()); // not re-fetched
|
||||
expect(ds.modified).toBe(later.toISOString());
|
||||
});
|
||||
|
||||
test('refreshDataset re-snapshots, re-profiles, and advances fetchedAt', () => {
|
||||
const id = seedUrl();
|
||||
const later = new Date('2026-07-01T00:00:00Z');
|
||||
expect(store().refreshDataset(id, { text: 'a,b\n1,2\n3,4\n5,6' }, later)).toBe(true);
|
||||
const ds = store().datasets.find((d) => d.id === id)!;
|
||||
expect(ds.rowCount).toBe(3);
|
||||
expect(ds.fetchedAt).toBe(later.toISOString());
|
||||
expect(ds.modified).toBe(later.toISOString());
|
||||
expect(ds.name).toBe('Remote'); // preserved
|
||||
});
|
||||
|
||||
test('refreshDataset is a no-op for an inline dataset', () => {
|
||||
store().add(
|
||||
createDataset({ name: 'Inline', data: [{ a: 1 }], format: 'json', source: 'inline', now: T }),
|
||||
);
|
||||
const id = store().selectedId!;
|
||||
expect(store().refreshDataset(id, { text: 'a\n1' }, T)).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user