mirror of
https://github.com/strapi/strapi.git
synced 2025-11-08 14:19:40 +00:00
fix deep query populate issue on dynamic zone
This commit is contained in:
parent
d5f620ac3b
commit
d58362aec0
@ -54,6 +54,7 @@
|
|||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@strapi/pack-up": "4.15.5",
|
"@strapi/pack-up": "4.15.5",
|
||||||
|
"@strapi/types": "4.15.5",
|
||||||
"@types/koa": "2.13.4",
|
"@types/koa": "2.13.4",
|
||||||
"@types/node": "18.18.4",
|
"@types/node": "18.18.4",
|
||||||
"eslint-config-custom": "4.15.5",
|
"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,
|
join,
|
||||||
first,
|
first,
|
||||||
omit,
|
omit,
|
||||||
|
merge,
|
||||||
} from 'lodash/fp';
|
} from 'lodash/fp';
|
||||||
|
|
||||||
import traverseFactory from './factory';
|
import traverseFactory from './factory';
|
||||||
@ -210,7 +211,9 @@ const populate = traverseFactory()
|
|||||||
|
|
||||||
for (const componentUID of components) {
|
for (const componentUID of components) {
|
||||||
const componentSchema = strapi.getModel(componentUID);
|
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);
|
Object.assign(newValue, newProperties);
|
||||||
|
|||||||
@ -9717,6 +9717,7 @@ __metadata:
|
|||||||
dependencies:
|
dependencies:
|
||||||
"@sindresorhus/slugify": "npm:1.1.0"
|
"@sindresorhus/slugify": "npm:1.1.0"
|
||||||
"@strapi/pack-up": "npm:4.15.5"
|
"@strapi/pack-up": "npm:4.15.5"
|
||||||
|
"@strapi/types": "npm:4.15.5"
|
||||||
"@types/koa": "npm:2.13.4"
|
"@types/koa": "npm:2.13.4"
|
||||||
"@types/node": "npm:18.18.4"
|
"@types/node": "npm:18.18.4"
|
||||||
date-fns: "npm:2.30.0"
|
date-fns: "npm:2.30.0"
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user