mirror of
https://github.com/strapi/strapi.git
synced 2025-09-02 21:32:43 +00:00
fix xToOne relations + finish e2e tests
This commit is contained in:
parent
8f73a1d761
commit
bd82249ab6
@ -7,8 +7,15 @@ const { createAuthRequest } = require('../../../../../../test/helpers/request');
|
||||
const builder = createTestBuilder();
|
||||
let strapi;
|
||||
let rq;
|
||||
const data = {
|
||||
categories: [],
|
||||
categoriesdp: {
|
||||
published: [],
|
||||
draft: [],
|
||||
},
|
||||
};
|
||||
|
||||
const product = {
|
||||
const productModel = {
|
||||
displayName: 'Product',
|
||||
singularName: 'product',
|
||||
pluralName: 'products',
|
||||
@ -25,6 +32,12 @@ const product = {
|
||||
target: 'api::categorydp.categorydp',
|
||||
targetAttribute: 'product',
|
||||
},
|
||||
onecategorydp: {
|
||||
type: 'relation',
|
||||
relation: 'oneToOne',
|
||||
target: 'api::categorydp.categorydp',
|
||||
targetAttribute: 'oneproduct',
|
||||
},
|
||||
categories: {
|
||||
type: 'relation',
|
||||
relation: 'oneToMany',
|
||||
@ -38,6 +51,7 @@ const product = {
|
||||
comporep: {
|
||||
component: 'default.compo',
|
||||
type: 'component',
|
||||
repeatable: true,
|
||||
},
|
||||
dz: {
|
||||
components: ['default.compo'],
|
||||
@ -46,7 +60,7 @@ const product = {
|
||||
},
|
||||
};
|
||||
|
||||
const categoryDP = {
|
||||
const categoryDPModel = {
|
||||
displayName: 'Category Draft & Publish',
|
||||
singularName: 'categorydp',
|
||||
pluralName: 'categoriesdp',
|
||||
@ -54,41 +68,41 @@ const categoryDP = {
|
||||
attributes: {
|
||||
name: {
|
||||
type: 'string',
|
||||
unique: true,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const category = {
|
||||
const categoryModel = {
|
||||
displayName: 'Category',
|
||||
singularName: 'category',
|
||||
pluralName: 'categories',
|
||||
attributes: {
|
||||
name: {
|
||||
type: 'string',
|
||||
unique: true,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const compo = {
|
||||
const compoModel = {
|
||||
displayName: 'compo',
|
||||
attributes: {
|
||||
name: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
},
|
||||
categoriesdp: {
|
||||
type: 'relation',
|
||||
relation: 'oneToMany',
|
||||
target: 'api::categorydp.categorydp',
|
||||
targetAttribute: 'product',
|
||||
},
|
||||
categories: {
|
||||
type: 'relation',
|
||||
relation: 'oneToMany',
|
||||
target: 'api::category.category',
|
||||
targetAttribute: 'product',
|
||||
},
|
||||
onecategorydp: {
|
||||
type: 'relation',
|
||||
relation: 'oneToOne',
|
||||
target: 'api::categorydp.categorydp',
|
||||
},
|
||||
},
|
||||
};
|
||||
@ -96,13 +110,45 @@ const compo = {
|
||||
describe('CM API - Basic', () => {
|
||||
beforeAll(async () => {
|
||||
await builder
|
||||
.addContentTypes([categoryDP, category])
|
||||
.addComponent(compo)
|
||||
.addContentTypes([product])
|
||||
.addContentTypes([categoryDPModel, categoryModel])
|
||||
.addComponent(compoModel)
|
||||
.addContentTypes([productModel])
|
||||
.build();
|
||||
|
||||
strapi = await createStrapiInstance();
|
||||
rq = await createAuthRequest({ strapi });
|
||||
|
||||
const { body: category } = await rq({
|
||||
method: 'POST',
|
||||
url: '/content-manager/collection-types/api::category.category',
|
||||
body: { name: 'Food' },
|
||||
});
|
||||
data.categories.push(category);
|
||||
|
||||
const { body: categoryPublished } = await rq({
|
||||
method: 'POST',
|
||||
url: '/content-manager/collection-types/api::categorydp.categorydp',
|
||||
body: { name: 'Food' },
|
||||
});
|
||||
await rq({
|
||||
method: 'POST',
|
||||
url: `/content-manager/collection-types/api::categorydp.categorydp/${categoryPublished.id}/actions/publish`,
|
||||
});
|
||||
data.categoriesdp.published.push(categoryPublished);
|
||||
|
||||
const { body: categoryDraft1 } = await rq({
|
||||
method: 'POST',
|
||||
url: '/content-manager/collection-types/api::categorydp.categorydp',
|
||||
body: { name: 'Food' },
|
||||
});
|
||||
data.categoriesdp.draft.push(categoryDraft1);
|
||||
|
||||
const { body: categoryDraft2 } = await rq({
|
||||
method: 'POST',
|
||||
url: '/content-manager/collection-types/api::categorydp.categorydp',
|
||||
body: { name: 'Food' },
|
||||
});
|
||||
data.categoriesdp.draft.push(categoryDraft2);
|
||||
});
|
||||
|
||||
afterAll(async () => {
|
||||
@ -111,11 +157,40 @@ describe('CM API - Basic', () => {
|
||||
});
|
||||
|
||||
test('Return 0 when no relations are set', async () => {
|
||||
const { body: product } = await rq({
|
||||
method: 'POST',
|
||||
url: '/content-manager/collection-types/api::product.product',
|
||||
body: { name: 'Pizza' },
|
||||
});
|
||||
|
||||
const { body } = await rq({
|
||||
method: 'GET',
|
||||
url: `/content-manager/collection-types/api::product.product/${product.id}/actions/numberOfDraftRelations`,
|
||||
});
|
||||
|
||||
expect(body.data).toBe(0);
|
||||
});
|
||||
|
||||
test('Return 0 when only relations without d&p are set', async () => {
|
||||
const { body: product } = await rq({
|
||||
method: 'POST',
|
||||
url: '/content-manager/collection-types/api::product.product',
|
||||
body: {
|
||||
name: 'Pizza',
|
||||
onecategorydp: data.categories[0].id,
|
||||
categories: [data.categories[0].id],
|
||||
compo: {
|
||||
onecategorydp: data.categories[0].id,
|
||||
categories: [data.categories[0].id],
|
||||
},
|
||||
comporep: [{ categories: [data.categories[0].id], onecategorydp: data.categories[0].id }],
|
||||
dz: [
|
||||
{
|
||||
__component: 'default.compo',
|
||||
categories: [data.categories[0].id],
|
||||
onecategorydp: data.categories[0].id,
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
|
||||
@ -126,4 +201,159 @@ describe('CM API - Basic', () => {
|
||||
|
||||
expect(body.data).toBe(0);
|
||||
});
|
||||
|
||||
test('Return 0 when relations without d&p are set & published relations only', async () => {
|
||||
const categoryId = data.categories[0].id;
|
||||
const publishedId = data.categoriesdp.published[0].id;
|
||||
|
||||
const { body: product } = await rq({
|
||||
method: 'POST',
|
||||
url: '/content-manager/collection-types/api::product.product',
|
||||
body: {
|
||||
name: 'Pizza',
|
||||
onecategorydp: publishedId,
|
||||
categories: [categoryId],
|
||||
categoriesdp: [publishedId],
|
||||
compo: {
|
||||
onecategorydp: publishedId,
|
||||
categories: [categoryId],
|
||||
categoriesdp: [publishedId],
|
||||
},
|
||||
comporep: [
|
||||
{ onecategorydp: publishedId, categories: [categoryId], categoriesdp: [publishedId] },
|
||||
],
|
||||
dz: [
|
||||
{
|
||||
__component: 'default.compo',
|
||||
onecategorydp: publishedId,
|
||||
categories: [categoryId],
|
||||
categoriesdp: [publishedId],
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
|
||||
const { body } = await rq({
|
||||
method: 'GET',
|
||||
url: `/content-manager/collection-types/api::product.product/${product.id}/actions/numberOfDraftRelations`,
|
||||
});
|
||||
|
||||
expect(body.data).toBe(0);
|
||||
});
|
||||
|
||||
test('Return 8 when there are 8 drafts (1 xToOne & 1 xToMany on ct, compo, comporep, dz)', async () => {
|
||||
const categoryId = data.categories[0].id;
|
||||
const draftId = data.categoriesdp.draft[0].id;
|
||||
|
||||
const { body: product } = await rq({
|
||||
method: 'POST',
|
||||
url: '/content-manager/collection-types/api::product.product',
|
||||
body: {
|
||||
name: 'Pizza',
|
||||
onecategorydp: draftId,
|
||||
categories: [categoryId],
|
||||
categoriesdp: [draftId],
|
||||
compo: {
|
||||
onecategorydp: draftId,
|
||||
categories: [categoryId],
|
||||
categoriesdp: [draftId],
|
||||
},
|
||||
comporep: [{ onecategorydp: draftId, categories: [categoryId], categoriesdp: [draftId] }],
|
||||
dz: [
|
||||
{
|
||||
__component: 'default.compo',
|
||||
onecategorydp: draftId,
|
||||
categories: [categoryId],
|
||||
categoriesdp: [draftId],
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
|
||||
const { body } = await rq({
|
||||
method: 'GET',
|
||||
url: `/content-manager/collection-types/api::product.product/${product.id}/actions/numberOfDraftRelations`,
|
||||
});
|
||||
|
||||
expect(body.data).toBe(8);
|
||||
});
|
||||
|
||||
test('Return 8 when there are 8 drafts (1 xToOne & 1/2 xToMany on ct, compo, comporep, dz)', async () => {
|
||||
const categoryId = data.categories[0].id;
|
||||
const draftId = data.categoriesdp.draft[0].id;
|
||||
|
||||
const { body: product } = await rq({
|
||||
method: 'POST',
|
||||
url: '/content-manager/collection-types/api::product.product',
|
||||
body: {
|
||||
name: 'Pizza',
|
||||
onecategorydp: draftId,
|
||||
categories: [categoryId],
|
||||
categoriesdp: [draftId, categoryId],
|
||||
compo: {
|
||||
onecategorydp: draftId,
|
||||
categories: [categoryId],
|
||||
categoriesdp: [draftId, categoryId],
|
||||
},
|
||||
comporep: [
|
||||
{ onecategorydp: draftId, categories: [categoryId], categoriesdp: [draftId, categoryId] },
|
||||
],
|
||||
dz: [
|
||||
{
|
||||
onecategorydp: draftId,
|
||||
__component: 'default.compo',
|
||||
categories: [categoryId],
|
||||
categoriesdp: [draftId, categoryId],
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
|
||||
const { body } = await rq({
|
||||
method: 'GET',
|
||||
url: `/content-manager/collection-types/api::product.product/${product.id}/actions/numberOfDraftRelations`,
|
||||
});
|
||||
|
||||
expect(body.data).toBe(8);
|
||||
});
|
||||
|
||||
test('Return 12 when there are 12 drafts (1 xToOne & 2 xToMany on ct, compo, comporep, dz)', async () => {
|
||||
const categoryId = data.categories[0].id;
|
||||
const draft1Id = data.categoriesdp.draft[0].id;
|
||||
const draft2Id = data.categoriesdp.draft[1].id;
|
||||
|
||||
const { body: product } = await rq({
|
||||
method: 'POST',
|
||||
url: '/content-manager/collection-types/api::product.product',
|
||||
body: {
|
||||
name: 'Pizza',
|
||||
onecategorydp: draft1Id,
|
||||
categories: [categoryId],
|
||||
categoriesdp: [draft1Id, draft2Id],
|
||||
compo: {
|
||||
onecategorydp: draft1Id,
|
||||
categories: [categoryId],
|
||||
categoriesdp: [draft1Id, draft2Id],
|
||||
},
|
||||
comporep: [
|
||||
{ onecategorydp: draft1Id, categories: [categoryId], categoriesdp: [draft1Id, draft2Id] },
|
||||
],
|
||||
dz: [
|
||||
{
|
||||
onecategorydp: draft1Id,
|
||||
__component: 'default.compo',
|
||||
categories: [categoryId],
|
||||
categoriesdp: [draft1Id, draft2Id],
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
|
||||
const { body } = await rq({
|
||||
method: 'GET',
|
||||
url: `/content-manager/collection-types/api::product.product/${product.id}/actions/numberOfDraftRelations`,
|
||||
});
|
||||
|
||||
expect(body.data).toBe(12);
|
||||
});
|
||||
});
|
||||
|
@ -11,7 +11,7 @@ const { fromRow } = require('../transform');
|
||||
* @returns
|
||||
*/
|
||||
const XtoOne = async (input, ctx) => {
|
||||
const { attribute, attributeName, results, populateValue, targetMeta } = input;
|
||||
const { attribute, attributeName, results, populateValue, targetMeta, isCount } = input;
|
||||
const { db, qb } = ctx;
|
||||
|
||||
const fromTargetRow = (rowOrRows) => fromRow(targetMeta, rowOrRows);
|
||||
@ -61,6 +61,41 @@ const XtoOne = async (input, ctx) => {
|
||||
results.map((r) => r[referencedColumnName]).filter((value) => !_.isNil(value))
|
||||
);
|
||||
|
||||
if (isCount) {
|
||||
if (_.isEmpty(referencedValues)) {
|
||||
results.forEach((result) => {
|
||||
result[attributeName] = { count: 0 };
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
const rows = await qb
|
||||
.init(populateValue)
|
||||
.join({
|
||||
alias,
|
||||
referencedTable: joinTable.name,
|
||||
referencedColumn: joinTable.inverseJoinColumn.name,
|
||||
rootColumn: joinTable.inverseJoinColumn.referencedColumn,
|
||||
rootTable: qb.alias,
|
||||
on: joinTable.on,
|
||||
})
|
||||
.select([joinColAlias, qb.raw('count(*) AS count')])
|
||||
.where({ [joinColAlias]: referencedValues })
|
||||
.groupBy(joinColAlias)
|
||||
.execute({ mapResults: false });
|
||||
|
||||
const map = rows.reduce((map, row) => {
|
||||
map[row[joinColumnName]] = { count: Number(row.count) };
|
||||
return map;
|
||||
}, {});
|
||||
|
||||
results.forEach((result) => {
|
||||
result[attributeName] = map[result[referencedColumnName]] || { count: 0 };
|
||||
});
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (_.isEmpty(referencedValues)) {
|
||||
results.forEach((result) => {
|
||||
result[attributeName] = null;
|
||||
|
Loading…
x
Reference in New Issue
Block a user