mirror of
https://github.com/olehomelchenko/astrolabe.git
synced 2026-08-08 02:02:33 +00:00
Fix dataset-ref walk false positive and wire spec-mandated success toasts
- Prune the data payload and top-level datasets keys in all three ref walks (extractDatasetRefs, renameDatasetInSpec, resolveDatasetRefs) so a data row carrying a field named "data" is no longer misread as a library reference, spuriously rewritten, or made to throw DatasetNotFoundError. Adds tests, including a guard that lookup-transform refs (from.data) still resolve. - Wire the deferred success toasts now the Toaster has landed: publish, revert, extract-to-dataset, and snippet/dataset delete. Copy follows the council title-vs-message rule (title states the action, message adds the consequence). - Reconcile the spec's blanket toast mandate to "toast only what the user can't already see": no toast on visible-result creates (snippet, dataset form); Copy Reference stays inline and gains an aria-live announcement (new shared .visually-hidden utility) instead of a toast-per-copy. - Move the toast region to bottom-right so it stops covering the header action cluster (Publish/Revert, theme/datasets). - Update docs/spec 01F/02/05 and docs/architecture/07 + 10 to match.
This commit is contained in:
@@ -47,6 +47,28 @@ describe('extractDatasetRefs', () => {
|
||||
// "foo" is self-defined and not a library dependency; "Library" is.
|
||||
expect(extractDatasetRefs(spec)).toEqual(['Library']);
|
||||
});
|
||||
|
||||
test('a data row carrying a field literally named "data" is not a reference', () => {
|
||||
// The inline rows happen to have a column called `data` whose value looks
|
||||
// like a reference object — it is payload, not a library dependency.
|
||||
const spec = {
|
||||
data: { values: [{ data: { name: 'NotARef' } }, { data: { name: 'AlsoNot' } }] },
|
||||
mark: 'bar',
|
||||
};
|
||||
expect(extractDatasetRefs(spec)).toEqual([]);
|
||||
});
|
||||
|
||||
test('does not descend into a self-defined datasets payload', () => {
|
||||
const spec = { datasets: { local: [{ data: { name: 'Buried' } }] }, mark: 'bar' };
|
||||
expect(extractDatasetRefs(spec)).toEqual([]);
|
||||
});
|
||||
|
||||
test('collects a reference from a lookup transform (from.data)', () => {
|
||||
const spec = {
|
||||
transform: [{ lookup: 'id', from: { data: { name: 'Lookup' }, key: 'id', fields: ['x'] } }],
|
||||
};
|
||||
expect(extractDatasetRefs(spec)).toEqual(['Lookup']);
|
||||
});
|
||||
});
|
||||
|
||||
describe('recomputeDatasetRefs', () => {
|
||||
@@ -105,4 +127,22 @@ describe('renameDatasetInSpec', () => {
|
||||
expect(out.data.name).toBe('Old'); // self-defined — left untouched
|
||||
expect(Object.keys(out.datasets)).toEqual(['Old']);
|
||||
});
|
||||
|
||||
test('does not rewrite a "data" field buried in inline data rows', () => {
|
||||
const spec = {
|
||||
data: { name: 'Old', values: [{ data: { name: 'Old' } }] },
|
||||
mark: 'bar',
|
||||
};
|
||||
const out = renameDatasetInSpec(spec, 'Old', 'New');
|
||||
expect(out.data.name).toBe('New'); // the real reference is renamed
|
||||
expect(out.data.values[0].data.name).toBe('Old'); // the row payload is left alone
|
||||
});
|
||||
|
||||
test('renames a reference inside a lookup transform (from.data)', () => {
|
||||
const spec = {
|
||||
transform: [{ lookup: 'id', from: { data: { name: 'Old' }, key: 'id' } }],
|
||||
};
|
||||
const out = renameDatasetInSpec(spec, 'Old', 'New');
|
||||
expect(out.transform[0].from.data.name).toBe('New');
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user