Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 30 additions & 30 deletions packages/narrative/src/getNarratives.specs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { InMemoryFileStore } from '@auto-engineer/file-store';
import { NodeFileStore } from '@auto-engineer/file-store/node';
import { beforeEach, describe, expect, it } from 'vitest';
import { getNarratives } from './getNarratives';
import { type DataSource, type Example, type Model, modelToNarrative, type Narrative, type QuerySlice } from './index';
import { type Example, type Model, modelToNarrative, type Narrative, type QuerySlice } from './index';
import { modelSchema } from './schema';

const __filename = fileURLToPath(import.meta.url);
Expand Down Expand Up @@ -112,12 +112,12 @@ describe('getNarratives', (_mode) => {
/query items\(\$itemId: String!\) {\s+items\(itemId: \$itemId\) {\s+id\s+description\s+}/,
);

const data = viewItemSlice?.server?.data as DataSource[] | undefined;
if (!data || !Array.isArray(data)) throw new Error('No data found in view items slice');
const data = viewItemSlice?.server?.data;
if (!data || !Array.isArray(data.items)) throw new Error('No data found in view items slice');

expect(data).toHaveLength(1);
expect(data[0].target).toMatchObject({ type: 'State', name: 'items' });
expect(data[0].origin).toMatchObject({ name: 'ItemsProjection', type: 'projection' });
expect(data.items).toHaveLength(1);
expect(data.items[0].target).toMatchObject({ type: 'State', name: 'items' });
expect(data.items[0].origin).toMatchObject({ name: 'ItemsProjection', type: 'projection' });

const specs = viewItemSlice?.server?.specs;
if (specs == null || specs.length === 0 || specs[0].feature === '')
Expand Down Expand Up @@ -224,7 +224,7 @@ describe('getNarratives', (_mode) => {
f.slices.some((s) => {
if (s.type === 'command' || s.type === 'query') {
return (
s.server.data?.some(
s.server.data?.items?.some(
(d) =>
('destination' in d && d.destination?.type === 'integration') ||
('origin' in d && d.origin?.type === 'integration'),
Expand Down Expand Up @@ -1494,17 +1494,17 @@ flow('Projection Test', () => {

if (summarySlice?.type !== 'query') return;

const data = summarySlice.server.data as DataSource[] | undefined;
const data = summarySlice.server.data;
expect(data).toBeDefined();
expect(data).toHaveLength(1);
expect(data?.items).toHaveLength(1);

expect(data?.[0].origin).toMatchObject({
expect(data?.items?.[0].origin).toMatchObject({
type: 'projection',
name: 'TodoSummary',
singleton: true,
});

expect(data?.[0].origin).not.toHaveProperty('idField');
expect(data?.items?.[0].origin).not.toHaveProperty('idField');
});

it('should generate correct origin for regular projection with single idField', async () => {
Expand Down Expand Up @@ -1546,17 +1546,17 @@ flow('Projection Test', () => {

if (todoSlice?.type !== 'query') return;

const data = todoSlice.server.data as DataSource[] | undefined;
const data = todoSlice.server.data;
expect(data).toBeDefined();
expect(data).toHaveLength(1);
expect(data?.items).toHaveLength(1);

expect(data?.[0].origin).toMatchObject({
expect(data?.items?.[0].origin).toMatchObject({
type: 'projection',
name: 'Todos',
idField: 'todoId',
});

expect(data?.[0].origin).not.toHaveProperty('singleton');
expect(data?.items?.[0].origin).not.toHaveProperty('singleton');
});

it('should generate correct origin for composite projection with multiple idFields', async () => {
Expand Down Expand Up @@ -1598,17 +1598,17 @@ flow('Projection Test', () => {

if (userProjectSlice?.type !== 'query') return;

const data = userProjectSlice.server.data as DataSource[] | undefined;
const data = userProjectSlice.server.data;
expect(data).toBeDefined();
expect(data).toHaveLength(1);
expect(data?.items).toHaveLength(1);

expect(data?.[0].origin).toMatchObject({
expect(data?.items?.[0].origin).toMatchObject({
type: 'projection',
name: 'UserProjects',
idField: ['userId', 'projectId'],
});

expect(data?.[0].origin).not.toHaveProperty('singleton');
expect(data?.items?.[0].origin).not.toHaveProperty('singleton');
});

it('should validate all three projection patterns together', async () => {
Expand Down Expand Up @@ -1684,8 +1684,8 @@ flow('All Projection Patterns', () => {

const summarySlice = projectionFlow.slices.find((s) => s.name === 'views summary');
if (summarySlice?.type === 'query') {
const data = summarySlice.server.data as DataSource[] | undefined;
expect(data?.[0].origin).toMatchObject({
const data = summarySlice.server.data;
expect(data?.items?.[0].origin).toMatchObject({
type: 'projection',
name: 'TodoSummary',
singleton: true,
Expand All @@ -1694,8 +1694,8 @@ flow('All Projection Patterns', () => {

const todoSlice = projectionFlow.slices.find((s) => s.name === 'views todo');
if (todoSlice?.type === 'query') {
const data = todoSlice.server.data as DataSource[] | undefined;
expect(data?.[0].origin).toMatchObject({
const data = todoSlice.server.data;
expect(data?.items?.[0].origin).toMatchObject({
type: 'projection',
name: 'Todos',
idField: 'todoId',
Expand All @@ -1704,8 +1704,8 @@ flow('All Projection Patterns', () => {

const userProjectSlice = projectionFlow.slices.find((s) => s.name === 'views user project todos');
if (userProjectSlice?.type === 'query') {
const data = userProjectSlice.server.data as DataSource[] | undefined;
expect(data?.[0].origin).toMatchObject({
const data = userProjectSlice.server.data;
expect(data?.items?.[0].origin).toMatchObject({
type: 'projection',
name: 'UserProjectTodos',
idField: ['userId', 'projectId'],
Expand Down Expand Up @@ -1770,15 +1770,15 @@ flow('Data Item IDs', () => {
const commandSlice = dataIdsFlow.slices.find((s) => s.name === 'places order');
if (commandSlice?.type === 'command') {
const sinkData = commandSlice.server.data;
expect(sinkData).toHaveLength(1);
expect(sinkData?.[0].id).toBe('SINK-001');
expect(sinkData?.items).toHaveLength(1);
expect(sinkData?.items?.[0].id).toBe('SINK-001');
}

const querySlice = dataIdsFlow.slices.find((s) => s.name === 'views order status');
if (querySlice?.type === 'query') {
const sourceData = querySlice.server.data as DataSource[] | undefined;
expect(sourceData).toHaveLength(1);
expect(sourceData?.[0].id).toBe('SOURCE-001');
const sourceData = querySlice.server.data;
expect(sourceData?.items).toHaveLength(1);
expect(sourceData?.items?.[0].id).toBe('SOURCE-001');
}
});
});
140 changes: 79 additions & 61 deletions packages/narrative/src/id/addAutoIds.specs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -688,12 +688,14 @@ describe('addAutoIds', () => {
server: {
description: 'Test server',
specs: [],
data: [
{
target: { type: 'Event', name: 'TestEvent' },
destination: { type: 'stream', pattern: 'test-stream' },
},
],
data: {
items: [
{
target: { type: 'Event', name: 'TestEvent' },
destination: { type: 'stream', pattern: 'test-stream' },
},
],
},
},
},
],
Expand All @@ -708,7 +710,8 @@ describe('addAutoIds', () => {
const slice = result.narratives[0].slices[0];

if ('server' in slice && slice.server?.data) {
expect(slice.server.data[0].id).toMatch(AUTO_ID_REGEX);
expect(slice.server.data.id).toMatch(AUTO_ID_REGEX);
expect(slice.server.data.items[0].id).toMatch(AUTO_ID_REGEX);
}
});

Expand All @@ -728,12 +731,14 @@ describe('addAutoIds', () => {
server: {
description: 'Test server',
specs: [],
data: [
{
target: { type: 'State', name: 'TestState' },
origin: { type: 'projection', name: 'TestProjection' },
},
],
data: {
items: [
{
target: { type: 'State', name: 'TestState' },
origin: { type: 'projection', name: 'TestProjection' },
},
],
},
},
},
],
Expand All @@ -748,7 +753,8 @@ describe('addAutoIds', () => {
const slice = result.narratives[0].slices[0];

if ('server' in slice && slice.server?.data) {
expect(slice.server.data[0].id).toMatch(AUTO_ID_REGEX);
expect(slice.server.data.id).toMatch(AUTO_ID_REGEX);
expect(slice.server.data.items[0].id).toMatch(AUTO_ID_REGEX);
}
});

Expand All @@ -768,17 +774,19 @@ describe('addAutoIds', () => {
server: {
description: 'Test server',
specs: [],
data: [
{
id: 'SINK-001',
target: { type: 'Command', name: 'TestCommand' },
destination: { type: 'stream', pattern: 'test-stream' },
_withState: {
target: { type: 'State', name: 'TestState' },
origin: { type: 'projection', name: 'TestProjection' },
data: {
items: [
{
id: 'SINK-001',
target: { type: 'Command', name: 'TestCommand' },
destination: { type: 'stream', pattern: 'test-stream' },
_withState: {
target: { type: 'State', name: 'TestState' },
origin: { type: 'projection', name: 'TestProjection' },
},
},
},
],
],
},
},
},
],
Expand All @@ -793,7 +801,7 @@ describe('addAutoIds', () => {
const slice = result.narratives[0].slices[0];

if ('server' in slice && slice.server?.data) {
const sink = slice.server.data[0];
const sink = slice.server.data.items[0];
expect(sink.id).toBe('SINK-001');
if ('destination' in sink && sink._withState) {
expect(sink._withState.id).toMatch(AUTO_ID_REGEX);
Expand All @@ -815,18 +823,21 @@ describe('addAutoIds', () => {
id: 'SLICE-001',
server: {
specs: [],
data: [
{
id: 'EXISTING-SINK-001',
target: { type: 'Event', name: 'TestEvent' },
destination: { type: 'stream', pattern: 'test-stream' },
},
{
id: 'EXISTING-SOURCE-001',
target: { type: 'State', name: 'TestState' },
origin: { type: 'projection', name: 'TestProjection' },
},
],
data: {
id: 'EXISTING-DATA-001',
items: [
{
id: 'EXISTING-SINK-001',
target: { type: 'Event', name: 'TestEvent' },
destination: { type: 'stream', pattern: 'test-stream' },
},
{
id: 'EXISTING-SOURCE-001',
target: { type: 'State', name: 'TestState' },
origin: { type: 'projection', name: 'TestProjection' },
},
],
},
},
},
],
Expand All @@ -841,8 +852,9 @@ describe('addAutoIds', () => {
const slice = result.narratives[0].slices[0];

if ('server' in slice && slice.server?.data) {
expect(slice.server.data[0].id).toBe('EXISTING-SINK-001');
expect(slice.server.data[1].id).toBe('EXISTING-SOURCE-001');
expect(slice.server.data.id).toBe('EXISTING-DATA-001');
expect(slice.server.data.items[0].id).toBe('EXISTING-SINK-001');
expect(slice.server.data.items[1].id).toBe('EXISTING-SOURCE-001');
}
});

Expand All @@ -862,12 +874,14 @@ describe('addAutoIds', () => {
server: {
description: 'Test server',
specs: [],
data: [
{
target: { type: 'Event', name: 'TestEvent' },
destination: { type: 'stream', pattern: 'test-stream' },
},
],
data: {
items: [
{
target: { type: 'Event', name: 'TestEvent' },
destination: { type: 'stream', pattern: 'test-stream' },
},
],
},
},
},
],
Expand All @@ -882,7 +896,8 @@ describe('addAutoIds', () => {
addAutoIds(model);

if ('server' in originalSlice && originalSlice.server?.data) {
expect(originalSlice.server.data[0].id).toBeUndefined();
expect(originalSlice.server.data.id).toBeUndefined();
expect(originalSlice.server.data.items[0].id).toBeUndefined();
}
});

Expand All @@ -900,20 +915,22 @@ describe('addAutoIds', () => {
id: 'SLICE-001',
server: {
specs: [],
data: [
{
target: { type: 'Event', name: 'Event1' },
destination: { type: 'stream', pattern: 'stream1' },
},
{
target: { type: 'Event', name: 'Event2' },
destination: { type: 'stream', pattern: 'stream2' },
},
{
target: { type: 'State', name: 'State1' },
origin: { type: 'projection', name: 'Proj1' },
},
],
data: {
items: [
{
target: { type: 'Event', name: 'Event1' },
destination: { type: 'stream', pattern: 'stream1' },
},
{
target: { type: 'Event', name: 'Event2' },
destination: { type: 'stream', pattern: 'stream2' },
},
{
target: { type: 'State', name: 'State1' },
origin: { type: 'projection', name: 'Proj1' },
},
],
},
},
},
],
Expand All @@ -928,7 +945,8 @@ describe('addAutoIds', () => {
const slice = result.narratives[0].slices[0];

if ('server' in slice && slice.server?.data) {
const ids = slice.server.data.map((d) => d.id);
expect(slice.server.data.id).toMatch(AUTO_ID_REGEX);
const ids = slice.server.data.items.map((d) => d.id);
expect(ids[0]).toMatch(AUTO_ID_REGEX);
expect(ids[1]).toMatch(AUTO_ID_REGEX);
expect(ids[2]).toMatch(AUTO_ID_REGEX);
Expand Down
Loading