Skip to content
Open
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
19 changes: 19 additions & 0 deletions src/server/services/import/import-v2.ts
Original file line number Diff line number Diff line change
Expand Up @@ -290,6 +290,25 @@ function setComponents(
}
} else if (isDynamicZoneAttribute(attribute)) {
store[attributeName] = (attributeValue as FileEntryDynamicZone[]).map(({ __component, id }) => getComponentData(__component, `${id}`, { fileIdToDbId, componentsDataStore }));
} else if (isRelationAttribute(attribute)) {
switch (attribute.relation) {
case 'oneToMany':
case 'manyToMany':
store[attributeName] = (attributeValue as (number | string)[]).map((id) => fileIdToDbId.getMapping(attribute.target, id));
break;
case 'oneToOne':
case 'manyToOne':
store[attributeName] = fileIdToDbId.getMapping(attribute.target, `${attributeValue as number | string}`);
break;
}
}
else if (isMediaAttribute(attribute)) {
if (attribute.multiple) {
store[attributeName] = (attributeValue as number[] | string[]).map((id) => fileIdToDbId.getMapping('plugin::upload.file', id));
}
else {
store[attributeName] = fileIdToDbId.getMapping('plugin::upload.file', `${attributeValue as number | string}`);
}
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
{
"kind": "collectionType",
"collectionName": "relation_c",
"info": {
"singularName": "relation-c",
"pluralName": "relations-c",
"displayName": "RelationC"
},
"options": {
"draftAndPublish": false
},
"pluginOptions": {
"import-export-entries": {
"idField": "name"
}
},
"attributes": {
"name": {
"type": "string",
"unique": true,
"required": true
},
"relationOneToOne": {
"type": "relation",
"relation": "oneToOne",
"target": "api::with-relation.relation-d"
},
"relationOneToMany": {
"type": "relation",
"relation": "oneToMany",
"target": "api::with-relation.relation-d"
},
"relationManyToOne": {
"type": "relation",
"relation": "manyToOne",
"target": "api::with-relation.relation-d"
},
"relationManyToMany": {
"type": "relation",
"relation": "manyToMany",
"target": "api::with-relation.relation-d"
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
{
"kind": "collectionType",
"collectionName": "relation_d",
"info": {
"singularName": "relation-d",
"pluralName": "relations-d",
"displayName": "RelationD"
},
"options": {
"draftAndPublish": false
},
"pluginOptions": {
"import-export-entries": {
"idField": "name"
}
},
"attributes": {
"name": {
"type": "string",
"unique": true,
"required": true
},
"relationOneToOne": {
"type": "relation",
"relation": "oneToOne",
"target": "api::with-relation.relation-c"
},
"relationOneToMany": {
"type": "relation",
"relation": "oneToMany",
"target": "api::with-relation.relation-c"
},
"relationManyToOne": {
"type": "relation",
"relation": "manyToOne",
"target": "api::with-relation.relation-c"
},
"relationManyToMany": {
"type": "relation",
"relation": "manyToMany",
"target": "api::with-relation.relation-c"
}
}
}
74 changes: 67 additions & 7 deletions tests/specs/import.spec.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
const map = require('lodash/map');
const pick = require('lodash/pick');
const { getModel } = require('../../server/utils/models');
const omit = require('lodash/omit');

const { getModel } = require('../../server/utils/models');
const { getService, SLUGS, generateData } = require('../utils');

describe('import service', () => {
Expand Down Expand Up @@ -513,15 +514,13 @@ describe('import service', () => {
expect(entriesA.length).toBe(CONFIG[SLUGS.RELATION_A].length);
CONFIG[SLUGS.RELATION_A].forEach((configData, idx) => {
expect(entriesA[idx].id).toBe(configData.id);
expect(entriesA[idx].title).toBe(configData.title);
expect(entriesA[idx].description).toBe(configData.description);
expect(entriesA[idx].name).toBe(configData.name);
});

expect(entriesB.length).toBe(CONFIG[SLUGS.RELATION_B].length);
CONFIG[SLUGS.RELATION_B].forEach((configData, idx) => {
expect(entriesB[idx].id).toBe(configData.id);
expect(entriesB[idx].title).toBe(configData.title);
expect(entriesB[idx].description).toBe(configData.description);
expect(entriesB[idx].name).toBe(configData.name);
});
});

Expand All @@ -539,12 +538,73 @@ describe('import service', () => {
expect(failures.length).toBeGreaterThanOrEqual(1);
expect(entries.length).toBe(0);
});


it('should map document id to db id for one to one relation', async () => {
const CONFIG = {
[SLUGS.RELATION_A]: [generateData(SLUGS.RELATION_A, { id: 1, relationOneToOne: 12, })],
[SLUGS.RELATION_B]: [generateData(SLUGS.RELATION_B, { id: 12, })],
};
const fileContent = buildJsonV2FileContent(CONFIG, { omitId:true });

const { failures } = await getService('import').importDataV2(fileContent, { slug: SLUGS.RELATION_A, user: {}, idField: 'name' });
const [entriesA, entriesB] = await Promise.all([
strapi.db.query(SLUGS.RELATION_A).findMany({ populate: {"relationOneToOne":true}}),
strapi.db.query(SLUGS.RELATION_B).findMany()
]);

expect(failures.length).toBe(0);

expect(entriesA.length).toBe(CONFIG[SLUGS.RELATION_A].length);
CONFIG[SLUGS.RELATION_A].forEach((configData, idx) => {
expect(entriesA[idx].id).toBe(configData.id);
expect(entriesA[idx].name).toBe(configData.name);
expect(entriesA[idx].relationOneToOne.id).toBe(entriesB[0].id);
});

expect(entriesB.length).toBe(CONFIG[SLUGS.RELATION_B].length);
CONFIG[SLUGS.RELATION_B].forEach((configData, idx) => {
expect(entriesB[idx].id).not.toBe(configData.id);
expect(entriesB[idx].name).toBe(configData.name);
});
});

it('should map document id to db id for one to many relation using idField in Strapi', async () => {
const CONFIG = {
[SLUGS.RELATION_C]: [generateData(SLUGS.RELATION_C, { id: 1, relationOneToMany: [11, 12], })],
[SLUGS.RELATION_D]: [generateData(SLUGS.RELATION_D, { id: 11, }), generateData(SLUGS.RELATION_D, { id: 12, })],
};
const fileContent = buildJsonV2FileContent(CONFIG, { omitId:true });

const { failures } = await getService('import').importDataV2(fileContent, { slug: SLUGS.RELATION_C, user: {} });

const [entriesC, entriesD] = await Promise.all([
strapi.db.query(SLUGS.RELATION_C).findMany({ populate: {"relationOneToMany":true}}),
strapi.db.query(SLUGS.RELATION_D).findMany()
]);


expect(failures.length).toBe(0);
expect(entriesC.length).toBe(CONFIG[SLUGS.RELATION_C].length);
CONFIG[SLUGS.RELATION_C].forEach((configData, idx) => {
expect(entriesC[idx].id).toBe(configData.id);
expect(entriesC[idx].name).toBe(configData.name);
expect(entriesC[idx].relationOneToMany.map(item=>item.id)).toStrictEqual(entriesD.map(item => item.id));
});


expect(entriesD.length).toBe(CONFIG[SLUGS.RELATION_D].length);
CONFIG[SLUGS.RELATION_D].forEach((configData, idx) => {
expect(entriesD[idx]).not.toBe(configData.id);
expect(entriesD[idx].name).toBe(configData.name);
});
});
});
});

const buildJsonV2FileContent = (config) => {
const buildJsonV2FileContent = (config, { omitId } = {}) => {
return {
version: 2,
data: Object.fromEntries(map(config, (data, slug) => [slug, Object.fromEntries(data.map((datum) => [datum.id, datum]))])),
data: Object.fromEntries(map(config, (data, slug) => [slug, Object.fromEntries(data.map((datum) => [datum.id, omitId ? omit(datum, ["id"]) : datum]))])),
};
};
14 changes: 14 additions & 0 deletions tests/utils/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ const SLUGS = {
COMPONENT_COMPONENT: 'component.component',
RELATION_A: 'api::with-relation.relation-a',
RELATION_B: 'api::with-relation.relation-b',
RELATION_C: 'api::with-relation.relation-c',
RELATION_D: 'api::with-relation.relation-d',
SINGLE_TYPE: 'api::single-type.single-type',
SINGLE_TYPE_SIMPLE: 'api::single-type.single-type-simple',
};
Expand Down Expand Up @@ -52,6 +54,18 @@ const generateData = (slug, customData = {}) => {
...customData,
};
}
if (slug === SLUGS.RELATION_C) {
return {
name: faker.helpers.unique(faker.word.noun),
...customData,
};
}
if (slug === SLUGS.RELATION_D) {
return {
name: faker.helpers.unique(faker.word.noun),
...customData,
};
}
if (slug === SLUGS.SINGLE_TYPE) {
return {
title: faker.helpers.unique(faker.word.noun),
Expand Down