Skip to content

Commit

Permalink
Merge pull request #18966 from strapi/fix/deep-populate-dynamiczone
Browse files Browse the repository at this point in the history
fix deep query populate issue on dynamic zone
  • Loading branch information
Bassel17 committed Dec 5, 2023
2 parents 5fc7637 + d58362a commit 8e2421b
Show file tree
Hide file tree
Showing 5 changed files with 295 additions and 1 deletion.
1 change: 1 addition & 0 deletions packages/core/utils/package.json
Expand Up @@ -54,6 +54,7 @@
},
"devDependencies": {
"@strapi/pack-up": "4.15.5",
"@strapi/types": "4.15.5",
"@types/koa": "2.13.4",
"@types/node": "18.18.4",
"eslint-config-custom": "4.15.5",
Expand Down
265 changes: 265 additions & 0 deletions packages/core/utils/src/__tests__/query-populate.test.ts
@@ -0,0 +1,265 @@
import { traverseQueryPopulate } from '../traverse';
import { setGlobalStrapi, getStrapiFactory } from './test-utils';

describe('traverseQueryPopulate', () => {
test('should return an empty object incase no populatable field exists', async () => {
const query = await traverseQueryPopulate(jest.fn(), {
schema: {
kind: 'collectionType',
attributes: {
title: {
type: 'string',
},
},
},
})('*');

expect(query).toEqual({});
});

test('should return all populatable fields', async () => {
const strapi = getStrapiFactory({
getModel: jest.fn((uid) => {
return {
uid,
attributes: {
street: {
type: 'string',
},
},
};
}),
db: {
metadata: {
get: jest.fn(() => ({
columnToAttribute: {
address: 'address',
some: 'some',
},
})),
},
},
})();

setGlobalStrapi(strapi);

const query = await traverseQueryPopulate(jest.fn(), {
schema: {
kind: 'collectionType',
attributes: {
title: {
type: 'string',
},
address: {
type: 'relation',
relation: 'oneToOne',
target: 'api::address.address',
},
some: {
type: 'relation',
relation: 'ManyToMany',
target: 'api::some.some',
},
},
},
})('*');

expect(query).toEqual({ address: true, some: true });
});

test('should return only selected populatable field', async () => {
const strapi = getStrapiFactory({
getModel: jest.fn((uid) => {
return {
uid,
attributes: {
street: {
type: 'string',
},
},
};
}),
db: {
metadata: {
get: jest.fn(() => ({
columnToAttribute: {
address: 'address',
},
})),
},
},
})();

setGlobalStrapi(strapi);

const query = await traverseQueryPopulate(jest.fn(), {
schema: {
kind: 'collectionType',
attributes: {
title: {
type: 'string',
},
address: {
type: 'relation',
relation: 'oneToOne',
target: 'api::address.address',
},
some: {
type: 'relation',
relation: 'ManyToMany',
target: 'api::some.some',
},
},
},
})('address');

expect(query).toEqual('address');
});

test('should populate dynamiczone', async () => {
const strapi = getStrapiFactory({
getModel: jest.fn((uid) => {
return {
uid,
attributes: {
street: {
type: 'string',
},
},
};
}),
db: {
metadata: {
get: jest.fn(() => ({
columnToAttribute: {
address: 'address',
},
})),
},
},
})();

setGlobalStrapi(strapi);

const query = await traverseQueryPopulate(jest.fn(), {
schema: {
kind: 'collectionType',
attributes: {
title: {
type: 'string',
},
address: {
type: 'relation',
relation: 'oneToOne',
target: 'api::address.address',
},
some: {
type: 'relation',
relation: 'ManyToMany',
target: 'api::some.some',
},
zone: {
type: 'dynamiczone',
components: ['blog.test-como', 'some.another-como'],
},
},
},
})('*');

expect(query).toEqual({
address: true,
some: true,
zone: true,
});
});

test('should deep populate dynamiczone components', async () => {
const strapi = getStrapiFactory({
getModel: jest.fn((uid) => {
if (uid === 'blog.test-como') {
return {
uid,
attributes: {
street: {
type: 'string',
},
address: {
type: 'relation',
relation: 'oneToOne',
target: 'api::address.address',
},
},
};
}
if (uid === 'some.another-como') {
return {
uid,
attributes: {
street: {
type: 'string',
},
some: {
type: 'relation',
relation: 'ManyToMany',
target: 'api::some.some',
},
},
};
}
return {
uid,
attributes: {
street: {
type: 'string',
},
},
};
}),
db: {
metadata: {
get: jest.fn(() => ({
columnToAttribute: {
address: 'address',
},
})),
},
},
})();

setGlobalStrapi(strapi);

const query = await traverseQueryPopulate(jest.fn(), {
schema: {
kind: 'collectionType',
attributes: {
title: {
type: 'string',
},
address: {
type: 'relation',
relation: 'oneToOne',
target: 'api::address.address',
},
some: {
type: 'relation',
relation: 'ManyToMany',
target: 'api::some.some',
},
zone: {
type: 'dynamiczone',
components: ['blog.test-como', 'some.another-como'],
},
},
},
})({ zone: { populate: '*' } });

expect(query).toEqual({
zone: {
populate: {
address: true,
some: true,
},
},
});
});
});
24 changes: 24 additions & 0 deletions packages/core/utils/src/__tests__/test-utils.ts
@@ -0,0 +1,24 @@
import type { LoadedStrapi } from '@strapi/types';

/**
* Update the global store with the given strapi value
*/
export const setGlobalStrapi = (strapi: LoadedStrapi): void => {
(global as unknown as Global).strapi = strapi;
};

/**
* Create a "Strapi" like object factory based on the
* given params and cast it to the correct type
*/
export const getStrapiFactory =
<
T extends {
[key in keyof Partial<LoadedStrapi>]: unknown;
}
>(
properties?: T
) =>
(additionalProperties?: Partial<T>) => {
return { ...properties, ...additionalProperties } as LoadedStrapi;
};
5 changes: 4 additions & 1 deletion packages/core/utils/src/traverse/query-populate.ts
Expand Up @@ -11,6 +11,7 @@ import {
join,
first,
omit,
merge,
} from 'lodash/fp';

import traverseFactory from './factory';
Expand Down Expand Up @@ -210,7 +211,9 @@ const populate = traverseFactory()

for (const componentUID of components) {
const componentSchema = strapi.getModel(componentUID);
newProperties = await recurse(visitor, { schema: componentSchema, path }, newProperties);

const properties = await recurse(visitor, { schema: componentSchema, path }, value);
newProperties = merge(newProperties, properties);
}

Object.assign(newValue, newProperties);
Expand Down
1 change: 1 addition & 0 deletions yarn.lock
Expand Up @@ -9717,6 +9717,7 @@ __metadata:
dependencies:
"@sindresorhus/slugify": "npm:1.1.0"
"@strapi/pack-up": "npm:4.15.5"
"@strapi/types": "npm:4.15.5"
"@types/koa": "npm:2.13.4"
"@types/node": "npm:18.18.4"
date-fns: "npm:2.30.0"
Expand Down

0 comments on commit 8e2421b

Please sign in to comment.