From 1c1d77d5f0da1359444a7ad808fb2ad0f3328596 Mon Sep 17 00:00:00 2001 From: Christian Capeans Date: Mon, 31 Jul 2023 13:02:53 +0200 Subject: [PATCH] Add test to check relations inside components are transferred --- .../src/engine/__tests__/engine.test.ts | 132 +++++++++++++++--- 1 file changed, 110 insertions(+), 22 deletions(-) diff --git a/packages/core/data-transfer/src/engine/__tests__/engine.test.ts b/packages/core/data-transfer/src/engine/__tests__/engine.test.ts index 0af68b86c7..3324ba991e 100644 --- a/packages/core/data-transfer/src/engine/__tests__/engine.test.ts +++ b/packages/core/data-transfer/src/engine/__tests__/engine.test.ts @@ -3,6 +3,7 @@ import { cloneDeep } from 'lodash/fp'; import { Readable, Writable } from 'stream-chain'; import type { Schema } from '@strapi/strapi'; import { createTransferEngine, TRANSFER_STAGES } from '..'; + import type { IAsset, IConfiguration, @@ -20,6 +21,27 @@ import { const getMockSourceStream = (data: Iterable) => Readable.from(data); +const defaultLinksData: Array = [ + { + kind: 'relation.basic', + relation: 'oneToOne', + left: { type: 'api::foo.foo', ref: 1, field: 'foo' }, + right: { type: 'api::bar.bar', ref: 2, field: 'bar' }, + }, + { + kind: 'relation.basic', + relation: 'oneToMany', + left: { type: 'api::foo.foo', ref: 1, field: 'foos' }, + right: { type: 'api::bar.bar', ref: 2, field: 'bar' }, + }, + { + kind: 'relation.basic', + relation: 'oneToMany', + left: { type: 'basic.foo', field: 'foo', ref: 1 }, + right: { type: 'api::foo.foo', ref: 1 }, + }, +]; + const schemas = { 'admin::permission': { collectionName: 'admin_permissions', @@ -143,6 +165,63 @@ const schemas = { uid: 'api::homepage.homepage', globalId: 'Homepage', }, + 'api::bar.bar': { + kind: 'collectionType', + collectionName: 'bars', + modelType: 'contentType', + info: { + singularName: 'bar', + pluralName: 'bars', + displayName: 'bar', + description: '', + }, + options: { + draftAndPublish: true, + }, + pluginOptions: {}, + attributes: { + bar: { + type: 'integer', + }, + foo: { + displayName: 'foo', + type: 'component', + repeatable: false, + component: 'basic.foo', + }, + }, + }, + 'api::foo.foo': { + kind: 'collectionType', + collectionName: 'foos', + modelType: 'contentType', + info: { + singularName: 'foo', + pluralName: 'foos', + displayName: 'foo', + }, + options: { + draftAndPublish: true, + }, + pluginOptions: {}, + attributes: { + foo: { + type: 'string', + }, + }, + }, + 'basic.foo': { + collectionName: 'components_basic_foos', + info: { displayName: 'Good Basic' }, + options: {}, + attributes: { + foo: { type: 'relation', relation: 'oneToOne', target: 'api::foo.foo' }, + }, + modelType: 'component', + modelName: 'foo-basic', + uid: 'basic.foo', + globalId: 'ComponentBasicFoo', + }, }; type Entity = IEntity< @@ -158,22 +237,8 @@ const getEntitiesMockSourceStream = ( ] ) => getMockSourceStream(data); -const getLinksMockSourceStream = ( - data: Array = [ - { - kind: 'relation.basic', - relation: 'oneToOne', - left: { type: 'api::foo.foo', ref: 1, field: 'foo' }, - right: { type: 'api::bar.bar', ref: 2, field: 'bar' }, - }, - { - kind: 'relation.basic', - relation: 'oneToMany', - left: { type: 'api::foo.foo', ref: 1, field: 'foos' }, - right: { type: 'api::bar.bar', ref: 2, field: 'bar' }, - }, - ] -) => getMockSourceStream(data); +const getLinksMockSourceStream = (data: Array = defaultLinksData) => + getMockSourceStream(data); const getAssetsMockSourceStream = ( data: Iterable = [ @@ -228,10 +293,13 @@ const getSchemasMockSourceStream = ( ] ) => getMockSourceStream(data); -const getMockDestinationStream = () => { +const getMockDestinationStream = (listener?) => { const stream = new Writable({ objectMode: true, write(chunk, encoding, callback) { + if (listener) { + listener(chunk); + } callback(); }, }); @@ -279,7 +347,9 @@ const createSource = (streamData?: { }; }; -const createDestination = (): IDestinationProvider => { +const createDestination = ( + overrideOptions?: Partial +): IDestinationProvider => { return { type: 'destination', name: 'completeDestination', @@ -288,12 +358,12 @@ const createDestination = (): IDestinationProvider => { bootstrap: jest.fn(), close: jest.fn(), - createEntitiesWriteStream: jest.fn().mockResolvedValue(getMockDestinationStream()), createLinksWriteStream: jest.fn().mockResolvedValue(getMockDestinationStream()), createAssetsWriteStream: jest.fn().mockResolvedValue(getMockDestinationStream()), createConfigurationWriteStream: jest.fn().mockResolvedValue(getMockDestinationStream()), createSchemasWriteStream: jest.fn().mockResolvedValue(getMockDestinationStream()), + ...overrideOptions, }; }; @@ -320,8 +390,8 @@ describe('Transfer engine', () => { exclude: [], } as unknown as ITransferEngineOptions; - let completeSource; - let completeDestination; + let completeSource: ISourceProvider; + let completeDestination: IDestinationProvider; beforeEach(() => { jest.restoreAllMocks(); @@ -444,7 +514,7 @@ describe('Transfer engine', () => { // Two values are emitted by default for each stage // TODO: this is no longer true, we should be checking the sum of the various mocked streams - const itemPerStage = 2; + const itemPerStage = 3; expect(calls).toEqual((sourceStages.length - providerStages.length) * itemPerStage); }); @@ -501,6 +571,24 @@ describe('Transfer engine', () => { expect(calls).toEqual(3); // 3 deleted stages above }); + + test('relations inside components are transferred', async () => { + const processedLinks: ILink[] = []; + + completeDestination = createDestination({ + createLinksWriteStream: jest.fn().mockResolvedValue( + getMockDestinationStream((chunk: ILink) => { + processedLinks.push(chunk); + }) + ), + }); + const engine = createTransferEngine(completeSource, completeDestination, defaultOptions); + + await engine.transferLinks(); + + expect(completeDestination.createLinksWriteStream).toHaveBeenCalled(); + expect(processedLinks).toStrictEqual(defaultLinksData); + }); }); describe('integrity checks', () => {