Skip to content

Commit

Permalink
Merge pull request #13855 from strapi/fix/dz-populate-same-field-name
Browse files Browse the repository at this point in the history
Better handle populating of dynamic-zones
  • Loading branch information
Convly committed Aug 1, 2022
2 parents 9866d64 + 952bca2 commit ce6c3f9
Show file tree
Hide file tree
Showing 4 changed files with 180 additions and 11 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ const productWithDz = {
collectionName: '',
};

describe('Core API - Basic + dz', () => {
describe('CM API - Basic + dz', () => {
beforeAll(async () => {
await builder
.addComponent(compo)
Expand Down
173 changes: 173 additions & 0 deletions packages/core/content-manager/server/tests/api/populate-dz.test.e2e.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,173 @@
'use strict';

const { createTestBuilder } = require('../../../../../../test/helpers/builder');
const { createStrapiInstance } = require('../../../../../../test/helpers/strapi');
const { createAuthRequest } = require('../../../../../../test/helpers/request');

const builder = createTestBuilder();
let strapi;
let rq;
let data = {
productsWithDz: [],
categories: [],
};

const compo1 = {
displayName: 'compo1',
attributes: {
title: {
type: 'string',
},
category: {
type: 'relation',
relation: 'oneToOne',
target: 'api::category.category',
},
},
};

const compo2 = {
displayName: 'compo2',
attributes: {
name: {
type: 'string',
},
category_diff: {
type: 'relation',
relation: 'oneToOne',
target: 'api::category.category',
},
},
};

const compoA = {
displayName: 'compoA',
attributes: {
items: {
type: 'component',
repeatable: false,
component: 'default.compo1',
},
},
};

const compoB = {
displayName: 'compoB',
attributes: {
items: {
type: 'component',
repeatable: false,
component: 'default.compo2',
},
},
};

const category = {
attributes: {
name: {
type: 'string',
},
},
displayName: 'Category',
singularName: 'category',
pluralName: 'categories',
description: '',
collectionName: '',
};

const productWithDz = {
attributes: {
name: {
type: 'string',
},
dz: {
components: ['default.compo-a', 'default.compo-b'],
type: 'dynamiczone',
required: true,
},
},
displayName: 'Product with dz',
singularName: 'product-with-dz',
pluralName: 'product-with-dzs',
description: '',
collectionName: '',
};

describe('CM API - Populate dz', () => {
beforeAll(async () => {
await builder
.addContentType(category)
.addComponent(compo1)
.addComponent(compo2)
.addComponent(compoA)
.addComponent(compoB)
.addContentType(productWithDz)
.build();

strapi = await createStrapiInstance();
rq = await createAuthRequest({ strapi });
});

afterAll(async () => {
await strapi.destroy();
await builder.cleanup();
});

test('Populate works in dz even with same names in different components', async () => {
const categoryRes = await rq({
method: 'POST',
url: '/content-manager/collection-types/api::category.category',
body: { name: 'name' },
});

expect(categoryRes.status).toBe(200);

data.categories.push(categoryRes.body);

const productRes = await rq({
method: 'POST',
url: '/content-manager/collection-types/api::product-with-dz.product-with-dz',
body: {
name: 'name',
dz: [
{
__component: 'default.compo-a',
items: { id: 2, title: 'AAAA', category: data.categories[0].id },
},
{
__component: 'default.compo-b',
items: { id: 2, name: 'BBBB', category_diff: data.categories[0].id },
},
],
},
});

expect(productRes.status).toBe(200);

data.productsWithDz.push(productRes.body);

expect(productRes.body).toMatchObject({
name: 'name',
dz: [
{
__component: 'default.compo-a',
items: {
title: 'AAAA',
category: {
name: 'name',
},
},
},
{
__component: 'default.compo-b',
items: {
name: 'BBBB',
category_diff: {
name: 'name',
},
},
},
],
});
});
});
14 changes: 5 additions & 9 deletions packages/core/utils/lib/convert-query-params.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
* Converts the standard Strapi REST query params to a more usable format for querying
* You can read more here: https://docs.strapi.io/developer-docs/latest/developer-resources/database-apis-reference/rest-api.html#filters
*/
const { has, isEmpty, isObject, isPlainObject, cloneDeep, get } = require('lodash/fp');
const { has, isEmpty, isObject, isPlainObject, cloneDeep, get, mergeAll } = require('lodash/fp');
const _ = require('lodash');
const parseType = require('./parse-type');
const contentTypesUtils = require('./content-types');
Expand Down Expand Up @@ -170,17 +170,13 @@ const convertPopulateObject = (populate, schema) => {
// FIXME: This is a temporary solution for dynamic zones that should be
// fixed when we'll implement a more accurate way to query them
if (attribute.type === 'dynamiczone') {
const generatedFakeDynamicZoneSchema = {
uid: `${schema.uid}.${key}`,
attributes: attribute.components
.sort()
.map(uid => strapi.getModel(uid).attributes)
.reduce((acc, componentAttributes) => ({ ...acc, ...componentAttributes }), {}),
};
const populates = attribute.components
.map(uid => strapi.getModel(uid))
.map(schema => convertNestedPopulate(subPopulate, schema));

return {
...acc,
[key]: convertNestedPopulate(subPopulate, generatedFakeDynamicZoneSchema),
[key]: mergeAll(populates),
};
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
const { Kind, valueFromASTUntyped } = require('graphql');
const { omit } = require('lodash/fp');
const { unionType, scalarType } = require('nexus');
const { ApplicationError } = require('@strapi/utils');
const { ApplicationError } = require('@strapi/utils').errors;

module.exports = ({ strapi }) => {
const buildTypeDefinition = (name, components) => {
Expand Down

0 comments on commit ce6c3f9

Please sign in to comment.