mirror of
https://github.com/olehomelchenko/astrolabe.git
synced 2026-08-08 02:02:33 +00:00
Landing: add marketing page at /, move the app to /app/
Multi-page Vite build: index.html serves a new standalone landing (src/landing), app/index.html serves the app at /app/. The PWA service worker and manifest are scoped to /app/, so the landing stays uncontrolled and always-fresh; hash view-state routing is unchanged. The landing reuses src/core and the chart-renderer service only (never stores/orchestration/modals/components) and lazy-loads Vega. Its demos drive the real core: a hero snippet switcher over CHART_EXAMPLES, an interactive Chart Builder over a new profiled core fixture (sample-dataset), and a Theme Builder gallery with three from-scratch custom themes plus built-in presets.
This commit is contained in:
@@ -0,0 +1,49 @@
|
||||
import { describe, it, expect } from 'vitest';
|
||||
import { inferColumnType } from '@core/type-inference';
|
||||
import {
|
||||
CHART_INTENTS,
|
||||
defaultBuilderConfig,
|
||||
intentApplicable,
|
||||
isBuilderConfigValid,
|
||||
} from '@core/chart-builder';
|
||||
import {
|
||||
SAMPLE_DATASET_COLUMNS,
|
||||
SAMPLE_DATASET_NAME,
|
||||
SAMPLE_DATASET_ROWS,
|
||||
} from '@core/sample-dataset';
|
||||
|
||||
describe('sample-dataset fixture', () => {
|
||||
it('declares column types that match what inference derives from the rows', () => {
|
||||
for (const { name, type } of SAMPLE_DATASET_COLUMNS.columnTypes) {
|
||||
const values = SAMPLE_DATASET_ROWS.map((row) => row[name]);
|
||||
expect(inferColumnType(values), name).toBe(type);
|
||||
}
|
||||
});
|
||||
|
||||
it('declares column stats that match the rows', () => {
|
||||
for (const stat of SAMPLE_DATASET_COLUMNS.columnStats ?? []) {
|
||||
const values = SAMPLE_DATASET_ROWS.map((row) => row[stat.name]);
|
||||
expect(stat.distinct, stat.name).toBe(new Set(values).size);
|
||||
const numbers = values.filter((v): v is number => typeof v === 'number');
|
||||
if (numbers.length === values.length) {
|
||||
expect(stat.numericExtent, stat.name).toEqual({
|
||||
min: Math.min(...numbers),
|
||||
max: Math.max(...numbers),
|
||||
});
|
||||
} else {
|
||||
expect(stat.numericExtent, stat.name).toBeNull();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
it('opens the builder on a valid default chart', () => {
|
||||
const config = defaultBuilderConfig(SAMPLE_DATASET_NAME, SAMPLE_DATASET_COLUMNS);
|
||||
expect(isBuilderConfigValid(config)).toBe(true);
|
||||
});
|
||||
|
||||
it('makes every intent applicable, so the demo strip is fully live', () => {
|
||||
for (const intent of CHART_INTENTS) {
|
||||
expect(intentApplicable(intent, SAMPLE_DATASET_COLUMNS), intent).toBe(true);
|
||||
}
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user