From 3d3e9e1a825f76319d8498585933f948c7b4ed49 Mon Sep 17 00:00:00 2001 From: mohamedsalem401 Date: Mon, 20 Jan 2025 02:32:26 +0200 Subject: [PATCH] Tests for nested collection components --- .../nestedComponentDataCollections.ts.snap | 36 ++ .../nestedComponentDataCollections.ts | 314 ++++++++++++++++++ 2 files changed, 350 insertions(+) create mode 100644 packages/core/test/specs/data_sources/model/data_collection/__snapshots__/nestedComponentDataCollections.ts.snap create mode 100644 packages/core/test/specs/data_sources/model/data_collection/nestedComponentDataCollections.ts diff --git a/packages/core/test/specs/data_sources/model/data_collection/__snapshots__/nestedComponentDataCollections.ts.snap b/packages/core/test/specs/data_sources/model/data_collection/__snapshots__/nestedComponentDataCollections.ts.snap new file mode 100644 index 000000000..36dae289f --- /dev/null +++ b/packages/core/test/specs/data_sources/model/data_collection/__snapshots__/nestedComponentDataCollections.ts.snap @@ -0,0 +1,36 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Collection component Nested collections are correctly serialized 1`] = ` +{ + "collectionDef": { + "collectionConfig": { + "collectionId": "parent_collection", + "dataSource": { + "path": "my_data_source_id", + "type": "data-variable", + }, + }, + "componentDef": { + "collectionDef": { + "collectionConfig": { + "collectionId": "nested_collection", + "dataSource": { + "path": "nested_data_source_id", + "type": "data-variable", + }, + }, + "componentDef": { + "name": { + "path": "user", + "type": "parent-collection-variable", + "variableType": "currentItem", + }, + "type": "default", + }, + }, + "type": "collection-component", + }, + }, + "type": "collection-component", +} +`; diff --git a/packages/core/test/specs/data_sources/model/data_collection/nestedComponentDataCollections.ts b/packages/core/test/specs/data_sources/model/data_collection/nestedComponentDataCollections.ts new file mode 100644 index 000000000..d77ff13ce --- /dev/null +++ b/packages/core/test/specs/data_sources/model/data_collection/nestedComponentDataCollections.ts @@ -0,0 +1,314 @@ +import { Component, DataRecord, DataSource, DataSourceManager, Editor } from '../../../../../src'; +import { DataVariableType } from '../../../../../src/data_sources/model/DataVariable'; +import { + CollectionComponentType, + CollectionVariableType, +} from '../../../../../src/data_sources/model/data_collection/constants'; +import { DataCollectionStateVariableType } from '../../../../../src/data_sources/model/data_collection/types'; +import EditorModel from '../../../../../src/editor/model/Editor'; +import { setupTestEditor } from '../../../../common'; + +describe('Collection component', () => { + let em: EditorModel; + let editor: Editor; + let dsm: DataSourceManager; + let dataSource: DataSource; + let nestedDataSource: DataSource; + let wrapper: Component; + let firstRecord: DataRecord; + let secondRecord: DataRecord; + let firstNestedRecord: DataRecord; + let secondNestedRecord: DataRecord; + + beforeEach(() => { + ({ em, editor, dsm } = setupTestEditor()); + wrapper = em.getWrapper()!; + dataSource = dsm.add({ + id: 'my_data_source_id', + records: [ + { id: 'user1', user: 'user1', age: '12' }, + { id: 'user2', user: 'user2', age: '14' }, + ], + }); + + nestedDataSource = dsm.add({ + id: 'nested_data_source_id', + records: [ + { id: 'user1', user: 'nested_user1', age: '12' }, + { id: 'user2', user: 'nested_user2', age: '14' }, + { id: 'user3', user: 'nested_user3', age: '16' }, + ], + }); + + firstRecord = dataSource.getRecord('user1')!; + secondRecord = dataSource.getRecord('user2')!; + firstNestedRecord = nestedDataSource.getRecord('user1')!; + secondNestedRecord = nestedDataSource.getRecord('user2')!; + }); + + afterEach(() => { + em.destroy(); + }); + + test('Nested collections bind to correct data sources', () => { + const parentCollection = wrapper.components({ + type: CollectionComponentType, + collectionDef: { + componentDef: { + type: CollectionComponentType, + collectionDef: { + componentDef: { + type: 'default', + name: { + type: CollectionVariableType, + variableType: DataCollectionStateVariableType.currentItem, + collectionId: 'nested_collection', + path: 'user', + }, + }, + collectionConfig: { + collectionId: 'nested_collection', + dataSource: { + type: DataVariableType, + path: 'nested_data_source_id', + }, + }, + }, + }, + collectionConfig: { + collectionId: 'parent_collection', + dataSource: { + type: DataVariableType, + path: 'my_data_source_id', + }, + }, + }, + })[0]; + + const nestedCollection = parentCollection.components().at(0); + const nestedFirstChild = nestedCollection.components().at(0); + const nestedSecondChild = nestedCollection.components().at(1); + + expect(nestedFirstChild.get('name')).toBe('nested_user1'); + expect(nestedSecondChild.get('name')).toBe('nested_user2'); + }); + + test('Updates in parent collection propagate to nested collections', () => { + const parentCollection = wrapper.components({ + type: CollectionComponentType, + collectionDef: { + componentDef: { + type: CollectionComponentType, + collectionDef: { + componentDef: { + type: 'default', + name: { + type: CollectionVariableType, + variableType: DataCollectionStateVariableType.currentItem, + collectionId: 'nested_collection', + path: 'user', + }, + }, + collectionConfig: { + collectionId: 'nested_collection', + dataSource: { + type: DataVariableType, + path: 'nested_data_source_id', + }, + }, + }, + }, + collectionConfig: { + collectionId: 'parent_collection', + dataSource: { + type: DataVariableType, + path: 'my_data_source_id', + }, + }, + }, + })[0]; + + const nestedCollection = parentCollection.components().at(0); + const nestedFirstChild = nestedCollection.components().at(0); + const nestedSecondChild = nestedCollection.components().at(1); + + firstNestedRecord.set('user', 'updated_user1'); + expect(nestedFirstChild.get('name')).toBe('updated_user1'); + expect(nestedSecondChild.get('name')).toBe('nested_user2'); + }); + + test('Nested collections are correctly serialized', () => { + const parentCollection = wrapper.components({ + type: CollectionComponentType, + collectionDef: { + componentDef: { + type: CollectionComponentType, + collectionDef: { + componentDef: { + type: 'default', + name: { + type: CollectionVariableType, + variableType: DataCollectionStateVariableType.currentItem, + path: 'user', + }, + }, + collectionConfig: { + collectionId: 'nested_collection', + dataSource: { + type: DataVariableType, + path: 'nested_data_source_id', + }, + }, + }, + }, + collectionConfig: { + collectionId: 'parent_collection', + dataSource: { + type: DataVariableType, + path: 'my_data_source_id', + }, + }, + }, + })[0]; + + const serialized = parentCollection.toJSON(); + expect(serialized).toMatchSnapshot(); + }); + + test('Nested collections respect startIndex and endIndex', () => { + const parentCollection = wrapper.components({ + type: CollectionComponentType, + collectionDef: { + componentDef: { + type: CollectionComponentType, + collectionDef: { + componentDef: { + type: 'default', + name: { + type: CollectionVariableType, + variableType: DataCollectionStateVariableType.currentItem, + collectionId: 'nested_collection', + path: 'user', + }, + }, + collectionConfig: { + collectionId: 'nested_collection', + startIndex: 0, + endIndex: 1, + dataSource: { + type: DataVariableType, + path: 'nested_data_source_id', + }, + }, + }, + }, + collectionConfig: { + collectionId: 'parent_collection', + dataSource: { + type: DataVariableType, + path: 'my_data_source_id', + }, + }, + }, + })[0]; + + const nestedCollection = parentCollection.components().at(0); + expect(nestedCollection.components().length).toBe(2); + }); + + test('Nested collection gets and watches value from the parent collection', () => { + const parentCollection = wrapper.components({ + type: CollectionComponentType, + collectionDef: { + componentDef: { + type: CollectionComponentType, + collectionDef: { + componentDef: { + type: 'default', + name: { + type: CollectionVariableType, + variableType: DataCollectionStateVariableType.currentItem, + collectionId: 'parent_collection', + path: 'user', + }, + }, + collectionConfig: { + collectionId: 'nested_collection', + dataSource: { + type: DataVariableType, + path: 'nested_data_source_id', + }, + }, + }, + }, + collectionConfig: { + collectionId: 'parent_collection', + dataSource: { + type: DataVariableType, + path: 'my_data_source_id', + }, + }, + }, + })[0]; + + const nestedCollection = parentCollection.components().at(0); + const firstNestedChild = nestedCollection.components().at(0); + + // Verify initial value + expect(firstNestedChild.get('name')).toBe('user1'); + + // Update value in parent collection and verify nested collection updates + firstRecord.set('user', 'updated_user1'); + expect(firstNestedChild.get('name')).toBe('updated_user1'); + }); + + test('Nested collection switches to using its own collection variable', () => { + const parentCollection = wrapper.components({ + type: CollectionComponentType, + collectionDef: { + componentDef: { + type: CollectionComponentType, + collectionDef: { + componentDef: { + type: 'default', + name: { + type: CollectionVariableType, + variableType: DataCollectionStateVariableType.currentItem, + path: 'user', + collectionId: 'parent_collection', + }, + }, + collectionConfig: { + collectionId: 'nested_collection', + dataSource: { + type: DataVariableType, + path: 'nested_data_source_id', + }, + }, + }, + }, + collectionConfig: { + collectionId: 'parent_collection', + dataSource: { + type: DataVariableType, + path: 'my_data_source_id', + }, + }, + }, + })[0]; + + const nestedCollection = parentCollection.components().at(0); + + const firstChild = nestedCollection.components().at(0); + // Replace the collection variable with one from the inner collection + firstChild.set('name', { + // @ts-ignore + type: CollectionVariableType, + variableType: DataCollectionStateVariableType.currentItem, + path: 'user', + collectionId: 'nested_collection', + }); + + expect(firstChild.get('name')).toBe('nested_user1'); + }); +});