mirror of
https://github.com/strapi/strapi.git
synced 2025-11-01 18:33:55 +00:00
fix deep query populate issue on dynamic zone
This commit is contained in:
parent
d5f620ac3b
commit
d58362aec0
@ -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",
|
||||
|
||||
265
packages/core/utils/src/__tests__/query-populate.test.ts
Normal file
265
packages/core/utils/src/__tests__/query-populate.test.ts
Normal file
@ -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
packages/core/utils/src/__tests__/test-utils.ts
Normal file
24
packages/core/utils/src/__tests__/test-utils.ts
Normal file
@ -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;
|
||||
};
|
||||
@ -11,6 +11,7 @@ import {
|
||||
join,
|
||||
first,
|
||||
omit,
|
||||
merge,
|
||||
} from 'lodash/fp';
|
||||
|
||||
import traverseFactory from './factory';
|
||||
@ -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);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user