fix deep query populate issue on dynamic zone

This commit is contained in:
Bassel Kanso 2023-12-01 12:43:12 +02:00
parent d5f620ac3b
commit d58362aec0
5 changed files with 295 additions and 1 deletions

View File

@ -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",

View 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,
},
},
});
});
});

View 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;
};

View File

@ -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);

View File

@ -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"