mirror of
https://github.com/strapi/strapi.git
synced 2025-11-04 20:07:19 +00:00
add e2e tests
This commit is contained in:
parent
7f521c9348
commit
8dfa1c70d1
@ -1,238 +0,0 @@
|
|||||||
'use strict';
|
|
||||||
|
|
||||||
const createContext = require('../../../../../../test/helpers/create-context');
|
|
||||||
const relations = require('../relations');
|
|
||||||
|
|
||||||
describe('Relations', () => {
|
|
||||||
describe('find', () => {
|
|
||||||
test('Fails on model not found', async () => {
|
|
||||||
const notFound = jest.fn();
|
|
||||||
const ctx = createContext(
|
|
||||||
{
|
|
||||||
params: { model: 'test', targetField: 'field' },
|
|
||||||
},
|
|
||||||
{
|
|
||||||
notFound,
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
const getModel = jest.fn();
|
|
||||||
global.strapi = {
|
|
||||||
getModel,
|
|
||||||
plugins: {
|
|
||||||
'content-manager': {
|
|
||||||
services: {},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
await relations.find(ctx);
|
|
||||||
|
|
||||||
expect(notFound).toHaveBeenCalledWith('model.notFound');
|
|
||||||
});
|
|
||||||
|
|
||||||
test('Fails on invalid target field', async () => {
|
|
||||||
const badRequest = jest.fn();
|
|
||||||
const ctx = createContext(
|
|
||||||
{
|
|
||||||
params: { model: 'test', targetField: 'field' },
|
|
||||||
},
|
|
||||||
{
|
|
||||||
badRequest,
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
const getModel = jest.fn(() => ({
|
|
||||||
attributes: {},
|
|
||||||
}));
|
|
||||||
|
|
||||||
global.strapi = {
|
|
||||||
getModel,
|
|
||||||
plugins: {
|
|
||||||
'content-manager': {
|
|
||||||
services: {},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
await relations.find(ctx);
|
|
||||||
|
|
||||||
expect(badRequest).toHaveBeenCalledWith('targetField.invalid');
|
|
||||||
});
|
|
||||||
|
|
||||||
test('Fails on model not found', async () => {
|
|
||||||
const notFound = jest.fn();
|
|
||||||
const ctx = createContext(
|
|
||||||
{
|
|
||||||
params: { model: 'test', targetField: 'target' },
|
|
||||||
},
|
|
||||||
{
|
|
||||||
notFound,
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
const getModel = jest
|
|
||||||
.fn()
|
|
||||||
.mockReturnValueOnce({
|
|
||||||
attributes: { target: { type: 'relation', target: 'test' } },
|
|
||||||
})
|
|
||||||
.mockReturnValueOnce(null);
|
|
||||||
|
|
||||||
global.strapi = {
|
|
||||||
getModel,
|
|
||||||
plugins: {
|
|
||||||
'content-manager': {
|
|
||||||
services: {},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
await relations.find(ctx);
|
|
||||||
|
|
||||||
expect(notFound).toHaveBeenCalledWith('target.notFound');
|
|
||||||
});
|
|
||||||
|
|
||||||
test('Picks the mainField and id only', async () => {
|
|
||||||
const notFound = jest.fn();
|
|
||||||
const ctx = createContext(
|
|
||||||
{
|
|
||||||
params: { model: 'test', targetField: 'target' },
|
|
||||||
},
|
|
||||||
{
|
|
||||||
notFound,
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
const getModel = jest.fn(() => ({
|
|
||||||
attributes: { target: { type: 'relation', target: 'test' } },
|
|
||||||
}));
|
|
||||||
|
|
||||||
global.strapi = {
|
|
||||||
getModel,
|
|
||||||
plugins: {
|
|
||||||
'content-manager': {
|
|
||||||
services: {
|
|
||||||
'content-types': {
|
|
||||||
findConfiguration() {
|
|
||||||
return {
|
|
||||||
metadatas: {
|
|
||||||
target: {
|
|
||||||
edit: {
|
|
||||||
mainField: 'title',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
},
|
|
||||||
},
|
|
||||||
'entity-manager': {
|
|
||||||
find() {
|
|
||||||
return [
|
|
||||||
{
|
|
||||||
id: 1,
|
|
||||||
title: 'title1',
|
|
||||||
secret: 'some secret',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 2,
|
|
||||||
title: 'title2',
|
|
||||||
secret: 'some secret 2',
|
|
||||||
},
|
|
||||||
];
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
await relations.find(ctx);
|
|
||||||
|
|
||||||
expect(ctx.body).toEqual([
|
|
||||||
{
|
|
||||||
id: 1,
|
|
||||||
title: 'title1',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 2,
|
|
||||||
title: 'title2',
|
|
||||||
},
|
|
||||||
]);
|
|
||||||
});
|
|
||||||
|
|
||||||
test('Omit somes ids', async () => {
|
|
||||||
const result = [
|
|
||||||
{
|
|
||||||
id: 1,
|
|
||||||
title: 'title1',
|
|
||||||
secret: 'some secret',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 2,
|
|
||||||
title: 'title2',
|
|
||||||
secret: 'some secret 2',
|
|
||||||
},
|
|
||||||
];
|
|
||||||
const configuration = {
|
|
||||||
metadatas: {
|
|
||||||
target: {
|
|
||||||
edit: {
|
|
||||||
mainField: 'title',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
const assocModel = { uid: 'api::test.test', attributes: {} };
|
|
||||||
const notFound = jest.fn();
|
|
||||||
const find = jest.fn(() => Promise.resolve(result));
|
|
||||||
const findConfiguration = jest.fn(() => Promise.resolve(configuration));
|
|
||||||
|
|
||||||
const getModel = jest
|
|
||||||
.fn()
|
|
||||||
.mockImplementationOnce(() => ({
|
|
||||||
attributes: { target: { type: 'relation', target: 'test' } },
|
|
||||||
}))
|
|
||||||
.mockImplementationOnce(() => assocModel);
|
|
||||||
|
|
||||||
global.strapi = {
|
|
||||||
getModel,
|
|
||||||
plugins: {
|
|
||||||
'content-manager': {
|
|
||||||
services: {
|
|
||||||
'content-types': { findConfiguration },
|
|
||||||
'entity-manager': { find },
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
const ctx = createContext(
|
|
||||||
{
|
|
||||||
params: { model: 'test', targetField: 'target' },
|
|
||||||
body: { idsToOmit: [3, 4] },
|
|
||||||
},
|
|
||||||
{
|
|
||||||
notFound,
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
await relations.find(ctx);
|
|
||||||
|
|
||||||
expect(find).toHaveBeenCalledWith(
|
|
||||||
{ filters: { $and: [{ id: { $notIn: [3, 4] } }] } },
|
|
||||||
assocModel.uid,
|
|
||||||
[]
|
|
||||||
);
|
|
||||||
expect(ctx.body).toEqual([
|
|
||||||
{
|
|
||||||
id: 1,
|
|
||||||
title: 'title1',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 2,
|
|
||||||
title: 'title2',
|
|
||||||
},
|
|
||||||
]);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@ -1,6 +1,7 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const { prop, isEmpty } = require('lodash/fp');
|
const { prop, isEmpty } = require('lodash/fp');
|
||||||
|
const { hasDraftAndPublish } = require('@strapi/utils').contentTypes;
|
||||||
const { PUBLISHED_AT_ATTRIBUTE } = require('@strapi/utils').contentTypes.constants;
|
const { PUBLISHED_AT_ATTRIBUTE } = require('@strapi/utils').contentTypes.constants;
|
||||||
|
|
||||||
const { getService } = require('../utils');
|
const { getService } = require('../utils');
|
||||||
@ -14,14 +15,14 @@ module.exports = {
|
|||||||
|
|
||||||
const { component, entityId, idsToOmit, page = 1, pageSize = 10, q } = ctx.request.query;
|
const { component, entityId, idsToOmit, page = 1, pageSize = 10, q } = ctx.request.query;
|
||||||
|
|
||||||
const sourceModel = component || model;
|
const sourceModelUid = component || model;
|
||||||
|
|
||||||
const modelDef = strapi.getModel(sourceModel);
|
const sourceModel = strapi.getModel(sourceModelUid);
|
||||||
if (!modelDef) {
|
if (!sourceModel) {
|
||||||
return ctx.badRequest("The model doesn't exist");
|
return ctx.badRequest("The model doesn't exist");
|
||||||
}
|
}
|
||||||
|
|
||||||
const attribute = modelDef.attributes[targetField];
|
const attribute = sourceModel.attributes[targetField];
|
||||||
if (!attribute || attribute.type !== 'relation') {
|
if (!attribute || attribute.type !== 'relation') {
|
||||||
return ctx.badRequest("This relational field doesn't exist");
|
return ctx.badRequest("This relational field doesn't exist");
|
||||||
}
|
}
|
||||||
@ -32,8 +33,8 @@ module.exports = {
|
|||||||
const limit = Number(pageSize);
|
const limit = Number(pageSize);
|
||||||
|
|
||||||
const modelConfig = component
|
const modelConfig = component
|
||||||
? await getService('components').findConfiguration(modelDef)
|
? await getService('components').findConfiguration(sourceModel)
|
||||||
: await getService('content-types').findConfiguration(modelDef);
|
: await getService('content-types').findConfiguration(sourceModel);
|
||||||
const mainField = prop(`metadatas.${targetField}.edit.mainField`, modelConfig) || 'id';
|
const mainField = prop(`metadatas.${targetField}.edit.mainField`, modelConfig) || 'id';
|
||||||
|
|
||||||
const query = strapi.db.queryBuilder(targetedModel.uid);
|
const query = strapi.db.queryBuilder(targetedModel.uid);
|
||||||
@ -47,7 +48,7 @@ module.exports = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (entityId) {
|
if (entityId) {
|
||||||
const joinTable = strapi.db.metadata.get(sourceModel).attributes[targetField].joinTable;
|
const joinTable = strapi.db.metadata.get(sourceModelUid).attributes[targetField].joinTable;
|
||||||
const sourceColumn = component ? joinTable.joinColumn.name : joinTable.inverseJoinColumn.name;
|
const sourceColumn = component ? joinTable.joinColumn.name : joinTable.inverseJoinColumn.name;
|
||||||
const targetColumn = component ? joinTable.inverseJoinColumn.name : joinTable.joinColumn.name;
|
const targetColumn = component ? joinTable.inverseJoinColumn.name : joinTable.joinColumn.name;
|
||||||
|
|
||||||
@ -66,8 +67,13 @@ module.exports = {
|
|||||||
.count()
|
.count()
|
||||||
.first()
|
.first()
|
||||||
.execute();
|
.execute();
|
||||||
|
|
||||||
|
const fieldsToSelect = ['id', mainField];
|
||||||
|
if (hasDraftAndPublish(targetedModel)) {
|
||||||
|
fieldsToSelect.push(PUBLISHED_AT_ATTRIBUTE);
|
||||||
|
}
|
||||||
const entities = await query
|
const entities = await query
|
||||||
.select([mainField, 'id', PUBLISHED_AT_ATTRIBUTE])
|
.select(fieldsToSelect)
|
||||||
.orderBy(mainField)
|
.orderBy(mainField)
|
||||||
.offset(offset)
|
.offset(offset)
|
||||||
.limit(limit)
|
.limit(limit)
|
||||||
|
|||||||
@ -8,7 +8,7 @@ const validateFindNewSchema = yup
|
|||||||
component: yup.string(),
|
component: yup.string(),
|
||||||
entityId: yup.strapiID(),
|
entityId: yup.strapiID(),
|
||||||
q: yup.string(),
|
q: yup.string(),
|
||||||
omitIds: yup.array().of(yup.strapiID()),
|
idsToOmit: yup.array().of(yup.strapiID()),
|
||||||
page: yup
|
page: yup
|
||||||
.number()
|
.number()
|
||||||
.integer()
|
.integer()
|
||||||
|
|||||||
@ -1,196 +0,0 @@
|
|||||||
'use strict';
|
|
||||||
|
|
||||||
// Test a simple default API with no relations
|
|
||||||
|
|
||||||
const { omit, pick } = require('lodash/fp');
|
|
||||||
|
|
||||||
const { createTestBuilder } = require('../../../../../test/helpers/builder');
|
|
||||||
const { createStrapiInstance } = require('../../../../../test/helpers/strapi');
|
|
||||||
const { createAuthRequest } = require('../../../../../test/helpers/request');
|
|
||||||
|
|
||||||
let strapi;
|
|
||||||
let rq;
|
|
||||||
const data = {
|
|
||||||
products: [],
|
|
||||||
shops: [],
|
|
||||||
};
|
|
||||||
|
|
||||||
const productModel = {
|
|
||||||
attributes: {
|
|
||||||
name: {
|
|
||||||
type: 'string',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
displayName: 'Product',
|
|
||||||
singularName: 'product',
|
|
||||||
pluralName: 'products',
|
|
||||||
description: '',
|
|
||||||
collectionName: '',
|
|
||||||
};
|
|
||||||
|
|
||||||
const productWithDPModel = {
|
|
||||||
attributes: {
|
|
||||||
name: {
|
|
||||||
type: 'string',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
displayName: 'Product',
|
|
||||||
singularName: 'product',
|
|
||||||
pluralName: 'products',
|
|
||||||
draftAndPublish: true,
|
|
||||||
description: '',
|
|
||||||
collectionName: '',
|
|
||||||
};
|
|
||||||
|
|
||||||
const shopModel = {
|
|
||||||
attributes: {
|
|
||||||
name: {
|
|
||||||
type: 'string',
|
|
||||||
},
|
|
||||||
products: {
|
|
||||||
type: 'relation',
|
|
||||||
relation: 'manyToMany',
|
|
||||||
target: 'api::product.product',
|
|
||||||
targetAttribute: 'shops',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
displayName: 'Shop',
|
|
||||||
singularName: 'shop',
|
|
||||||
pluralName: 'shops',
|
|
||||||
};
|
|
||||||
|
|
||||||
const shops = [
|
|
||||||
{
|
|
||||||
name: 'market',
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
const products =
|
|
||||||
({ withPublished = false }) =>
|
|
||||||
({ shop }) => {
|
|
||||||
const shops = [shop[0].id];
|
|
||||||
|
|
||||||
const entries = [
|
|
||||||
{
|
|
||||||
name: 'tomato',
|
|
||||||
shops,
|
|
||||||
publishedAt: new Date(),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'apple',
|
|
||||||
shops,
|
|
||||||
publishedAt: null,
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
if (withPublished) {
|
|
||||||
return entries;
|
|
||||||
}
|
|
||||||
|
|
||||||
return entries.map(omit('publishedAt'));
|
|
||||||
};
|
|
||||||
|
|
||||||
describe('Relation-list route', () => {
|
|
||||||
describe('without draftAndPublish', () => {
|
|
||||||
const builder = createTestBuilder();
|
|
||||||
|
|
||||||
beforeAll(async () => {
|
|
||||||
await builder
|
|
||||||
.addContentTypes([productModel, shopModel])
|
|
||||||
.addFixtures(shopModel.singularName, shops)
|
|
||||||
.addFixtures(productModel.singularName, products({ withPublished: false }))
|
|
||||||
.build();
|
|
||||||
|
|
||||||
strapi = await createStrapiInstance();
|
|
||||||
rq = await createAuthRequest({ strapi });
|
|
||||||
|
|
||||||
data.shops = await builder.sanitizedFixturesFor(shopModel.singularName, strapi);
|
|
||||||
data.products = await builder.sanitizedFixturesFor(productModel.singularName, strapi);
|
|
||||||
});
|
|
||||||
|
|
||||||
afterAll(async () => {
|
|
||||||
await strapi.destroy();
|
|
||||||
await builder.cleanup();
|
|
||||||
});
|
|
||||||
|
|
||||||
test('Can get relation-list for products of a shop', async () => {
|
|
||||||
const res = await rq({
|
|
||||||
method: 'POST',
|
|
||||||
url: '/content-manager/relations/api::shop.shop/products',
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(res.body).toHaveLength(data.products.length);
|
|
||||||
data.products.forEach((product, index) => {
|
|
||||||
expect(res.body[index]).toStrictEqual(pick(['_id', 'id', 'name'], product));
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
test('Can get relation-list for products of a shop and omit some results', async () => {
|
|
||||||
const res = await rq({
|
|
||||||
method: 'POST',
|
|
||||||
url: '/content-manager/relations/api::shop.shop/products',
|
|
||||||
body: {
|
|
||||||
idsToOmit: [data.products[0].id],
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(res.body).toHaveLength(1);
|
|
||||||
expect(res.body[0]).toStrictEqual(pick(['_id', 'id', 'name'], data.products[1]));
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('with draftAndPublish', () => {
|
|
||||||
const builder = createTestBuilder();
|
|
||||||
|
|
||||||
beforeAll(async () => {
|
|
||||||
await builder
|
|
||||||
.addContentTypes([productWithDPModel, shopModel])
|
|
||||||
.addFixtures(shopModel.singularName, shops)
|
|
||||||
.addFixtures(productWithDPModel.singularName, products({ withPublished: true }))
|
|
||||||
.build();
|
|
||||||
|
|
||||||
strapi = await createStrapiInstance();
|
|
||||||
rq = await createAuthRequest({ strapi });
|
|
||||||
|
|
||||||
data.shops = await builder.sanitizedFixturesFor(shopModel.singularName, strapi);
|
|
||||||
data.products = await builder.sanitizedFixturesFor(productWithDPModel.singularName, strapi);
|
|
||||||
});
|
|
||||||
|
|
||||||
afterAll(async () => {
|
|
||||||
await strapi.destroy();
|
|
||||||
await builder.cleanup();
|
|
||||||
});
|
|
||||||
|
|
||||||
test('Can get relation-list for products of a shop', async () => {
|
|
||||||
const res = await rq({
|
|
||||||
method: 'POST',
|
|
||||||
url: '/content-manager/relations/api::shop.shop/products',
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(res.body).toHaveLength(data.products.length);
|
|
||||||
|
|
||||||
const tomatoProductRes = res.body.find((p) => p.name === 'tomato');
|
|
||||||
const appleProductRes = res.body.find((p) => p.name === 'apple');
|
|
||||||
|
|
||||||
expect(tomatoProductRes).toMatchObject(pick(['_id', 'id', 'name'], data.products[0]));
|
|
||||||
expect(tomatoProductRes.publishedAt).toBeISODate();
|
|
||||||
expect(appleProductRes).toStrictEqual({
|
|
||||||
...pick(['_id', 'id', 'name'], data.products[1]),
|
|
||||||
publishedAt: null,
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
test('Can get relation-list for products of a shop and omit some results', async () => {
|
|
||||||
const res = await rq({
|
|
||||||
method: 'POST',
|
|
||||||
url: '/content-manager/relations/api::shop.shop/products',
|
|
||||||
body: {
|
|
||||||
idsToOmit: [data.products[1].id],
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(res.body).toHaveLength(1);
|
|
||||||
expect(res.body[0]).toMatchObject(pick(['_id', 'id', 'name'], data.products[0]));
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@ -0,0 +1,260 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
const { createTestBuilder } = require('../../../../../test/helpers/builder');
|
||||||
|
const { createStrapiInstance } = require('../../../../../test/helpers/strapi');
|
||||||
|
const { createAuthRequest } = require('../../../../../test/helpers/request');
|
||||||
|
|
||||||
|
let strapi;
|
||||||
|
let rq;
|
||||||
|
let data = {
|
||||||
|
products: [],
|
||||||
|
shops: [],
|
||||||
|
};
|
||||||
|
|
||||||
|
const compo = {
|
||||||
|
displayName: 'compo',
|
||||||
|
attributes: {
|
||||||
|
name: {
|
||||||
|
type: 'string',
|
||||||
|
},
|
||||||
|
compoProducts: {
|
||||||
|
type: 'relation',
|
||||||
|
relation: 'manyToMany',
|
||||||
|
target: 'api::product.product',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const productModel = {
|
||||||
|
draftAndPublish: true,
|
||||||
|
attributes: {
|
||||||
|
name: {
|
||||||
|
type: 'string',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
displayName: 'Product',
|
||||||
|
singularName: 'product',
|
||||||
|
pluralName: 'products',
|
||||||
|
description: '',
|
||||||
|
collectionName: '',
|
||||||
|
};
|
||||||
|
|
||||||
|
const shopModel = {
|
||||||
|
draftAndPublish: true,
|
||||||
|
attributes: {
|
||||||
|
name: {
|
||||||
|
type: 'string',
|
||||||
|
},
|
||||||
|
products: {
|
||||||
|
type: 'relation',
|
||||||
|
relation: 'manyToMany',
|
||||||
|
target: 'api::product.product',
|
||||||
|
targetAttribute: 'shops',
|
||||||
|
inversedBy: 'shops',
|
||||||
|
},
|
||||||
|
myCompo: {
|
||||||
|
type: 'component',
|
||||||
|
repeatable: false,
|
||||||
|
component: 'default.compo',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
displayName: 'Shop',
|
||||||
|
singularName: 'shop',
|
||||||
|
pluralName: 'shops',
|
||||||
|
};
|
||||||
|
|
||||||
|
describe('Relations with Draft & Publish', () => {
|
||||||
|
const builder = createTestBuilder();
|
||||||
|
|
||||||
|
beforeAll(async () => {
|
||||||
|
await builder
|
||||||
|
.addContentTypes([productModel])
|
||||||
|
.addComponent(compo)
|
||||||
|
.addContentTypes([shopModel])
|
||||||
|
.build();
|
||||||
|
|
||||||
|
strapi = await createStrapiInstance();
|
||||||
|
rq = await createAuthRequest({ strapi });
|
||||||
|
|
||||||
|
const { body: createdProduct1 } = await rq({
|
||||||
|
method: 'POST',
|
||||||
|
url: '/content-manager/collection-types/api::product.product',
|
||||||
|
body: { name: 'Skate' },
|
||||||
|
});
|
||||||
|
await rq({
|
||||||
|
url: `/content-manager/collection-types/api::product.product/${createdProduct1.id}/actions/publish`,
|
||||||
|
method: 'POST',
|
||||||
|
});
|
||||||
|
const { body: createdProduct2 } = await rq({
|
||||||
|
method: 'POST',
|
||||||
|
url: '/content-manager/collection-types/api::product.product',
|
||||||
|
body: { name: 'Candle' },
|
||||||
|
});
|
||||||
|
|
||||||
|
data.products.push(createdProduct1);
|
||||||
|
data.products.push(createdProduct2);
|
||||||
|
|
||||||
|
const { body: createdShop } = await rq({
|
||||||
|
method: 'POST',
|
||||||
|
url: '/content-manager/collection-types/api::shop.shop',
|
||||||
|
body: {
|
||||||
|
name: 'Cazotte Shop',
|
||||||
|
products: [createdProduct1.id],
|
||||||
|
myCompo: { compoProducts: [createdProduct2.id] },
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
data.shops.push(createdShop);
|
||||||
|
});
|
||||||
|
|
||||||
|
afterAll(async () => {
|
||||||
|
await strapi.destroy();
|
||||||
|
await builder.cleanup();
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('findNew', () => {
|
||||||
|
test('relation not in a component && no entity', async () => {
|
||||||
|
let res = await rq({
|
||||||
|
method: 'GET',
|
||||||
|
url: '/content-manager/relations/api::shop.shop/products',
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(res.status).toBe(200);
|
||||||
|
expect(res.body.results).toMatchObject([
|
||||||
|
{
|
||||||
|
id: expect.any(Number),
|
||||||
|
name: 'Candle',
|
||||||
|
publishedAt: null,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: expect.any(Number),
|
||||||
|
name: 'Skate',
|
||||||
|
publishedAt: expect.any(String),
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
|
||||||
|
// can omitIds
|
||||||
|
res = await rq({
|
||||||
|
method: 'GET',
|
||||||
|
url: '/content-manager/relations/api::shop.shop/products',
|
||||||
|
qs: {
|
||||||
|
idsToOmit: [data.products[0].id],
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(res.body.results).toMatchObject([
|
||||||
|
{
|
||||||
|
id: expect.any(Number),
|
||||||
|
name: 'Candle',
|
||||||
|
publishedAt: null,
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('relation not in a component && on an entity', async () => {
|
||||||
|
let res = await rq({
|
||||||
|
method: 'GET',
|
||||||
|
url: '/content-manager/relations/api::shop.shop/products',
|
||||||
|
qs: {
|
||||||
|
entityId: data.shops[0].id,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(res.status).toBe(200);
|
||||||
|
expect(res.body.results).toMatchObject([
|
||||||
|
{
|
||||||
|
id: expect.any(Number),
|
||||||
|
name: 'Candle',
|
||||||
|
publishedAt: null,
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
|
||||||
|
// can omitIds
|
||||||
|
res = await rq({
|
||||||
|
method: 'GET',
|
||||||
|
url: '/content-manager/relations/api::shop.shop/products',
|
||||||
|
qs: {
|
||||||
|
entityId: data.shops[0].id,
|
||||||
|
idsToOmit: [data.products[1].id],
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(res.body.results).toHaveLength(0);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('relation in a component && no entity', async () => {
|
||||||
|
let res = await rq({
|
||||||
|
method: 'GET',
|
||||||
|
url: '/content-manager/relations/api::shop.shop/compoProducts',
|
||||||
|
qs: {
|
||||||
|
component: 'default.compo',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(res.status).toBe(200);
|
||||||
|
expect(res.body.results).toMatchObject([
|
||||||
|
{
|
||||||
|
id: expect.any(Number),
|
||||||
|
name: 'Candle',
|
||||||
|
publishedAt: null,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: expect.any(Number),
|
||||||
|
name: 'Skate',
|
||||||
|
publishedAt: expect.any(String),
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
|
||||||
|
// can omitIds
|
||||||
|
res = await rq({
|
||||||
|
method: 'GET',
|
||||||
|
url: '/content-manager/relations/api::shop.shop/compoProducts',
|
||||||
|
qs: {
|
||||||
|
component: 'default.compo',
|
||||||
|
idsToOmit: [data.products[0].id],
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(res.body.results).toMatchObject([
|
||||||
|
{
|
||||||
|
id: expect.any(Number),
|
||||||
|
name: 'Candle',
|
||||||
|
publishedAt: null,
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('relation in a component && on an entity', async () => {
|
||||||
|
let res = await rq({
|
||||||
|
method: 'GET',
|
||||||
|
url: '/content-manager/relations/api::shop.shop/compoProducts',
|
||||||
|
qs: {
|
||||||
|
entityId: data.shops[0].myCompo.id,
|
||||||
|
component: 'default.compo',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(res.status).toBe(200);
|
||||||
|
expect(res.body.results).toMatchObject([
|
||||||
|
{
|
||||||
|
id: expect.any(Number),
|
||||||
|
name: 'Skate',
|
||||||
|
publishedAt: expect.any(String),
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
|
||||||
|
// can omitIds
|
||||||
|
res = await rq({
|
||||||
|
method: 'GET',
|
||||||
|
url: '/content-manager/relations/api::shop.shop/compoProducts',
|
||||||
|
qs: {
|
||||||
|
entityId: data.shops[0].myCompo.id,
|
||||||
|
component: 'default.compo',
|
||||||
|
idsToOmit: [data.products[0].id],
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(res.body.results).toHaveLength(0);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
246
packages/core/content-manager/server/tests/relations.test.e2e.js
Normal file
246
packages/core/content-manager/server/tests/relations.test.e2e.js
Normal file
@ -0,0 +1,246 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
const { createTestBuilder } = require('../../../../../test/helpers/builder');
|
||||||
|
const { createStrapiInstance } = require('../../../../../test/helpers/strapi');
|
||||||
|
const { createAuthRequest } = require('../../../../../test/helpers/request');
|
||||||
|
|
||||||
|
let strapi;
|
||||||
|
let rq;
|
||||||
|
let data = {
|
||||||
|
products: [],
|
||||||
|
shops: [],
|
||||||
|
};
|
||||||
|
|
||||||
|
const compo = {
|
||||||
|
displayName: 'compo',
|
||||||
|
attributes: {
|
||||||
|
name: {
|
||||||
|
type: 'string',
|
||||||
|
},
|
||||||
|
compoProducts: {
|
||||||
|
type: 'relation',
|
||||||
|
relation: 'manyToMany',
|
||||||
|
target: 'api::product.product',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const productModel = {
|
||||||
|
attributes: {
|
||||||
|
name: {
|
||||||
|
type: 'string',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
displayName: 'Product',
|
||||||
|
singularName: 'product',
|
||||||
|
pluralName: 'products',
|
||||||
|
description: '',
|
||||||
|
collectionName: '',
|
||||||
|
};
|
||||||
|
|
||||||
|
const shopModel = {
|
||||||
|
attributes: {
|
||||||
|
name: {
|
||||||
|
type: 'string',
|
||||||
|
},
|
||||||
|
products: {
|
||||||
|
type: 'relation',
|
||||||
|
relation: 'manyToMany',
|
||||||
|
target: 'api::product.product',
|
||||||
|
targetAttribute: 'shops',
|
||||||
|
inversedBy: 'shops',
|
||||||
|
},
|
||||||
|
myCompo: {
|
||||||
|
type: 'component',
|
||||||
|
repeatable: false,
|
||||||
|
component: 'default.compo',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
displayName: 'Shop',
|
||||||
|
singularName: 'shop',
|
||||||
|
pluralName: 'shops',
|
||||||
|
};
|
||||||
|
|
||||||
|
describe('Relations', () => {
|
||||||
|
const builder = createTestBuilder();
|
||||||
|
|
||||||
|
beforeAll(async () => {
|
||||||
|
await builder
|
||||||
|
.addContentTypes([productModel])
|
||||||
|
.addComponent(compo)
|
||||||
|
.addContentTypes([shopModel])
|
||||||
|
.build();
|
||||||
|
|
||||||
|
strapi = await createStrapiInstance();
|
||||||
|
rq = await createAuthRequest({ strapi });
|
||||||
|
|
||||||
|
const { body: createdProduct1 } = await rq({
|
||||||
|
method: 'POST',
|
||||||
|
url: '/content-manager/collection-types/api::product.product',
|
||||||
|
body: { name: 'Skate' },
|
||||||
|
});
|
||||||
|
const { body: createdProduct2 } = await rq({
|
||||||
|
method: 'POST',
|
||||||
|
url: '/content-manager/collection-types/api::product.product',
|
||||||
|
body: { name: 'Candle' },
|
||||||
|
});
|
||||||
|
|
||||||
|
data.products.push(createdProduct1);
|
||||||
|
data.products.push(createdProduct2);
|
||||||
|
|
||||||
|
const { body: createdShop } = await rq({
|
||||||
|
method: 'POST',
|
||||||
|
url: '/content-manager/collection-types/api::shop.shop',
|
||||||
|
body: {
|
||||||
|
name: 'Cazotte Shop',
|
||||||
|
products: [createdProduct1.id],
|
||||||
|
myCompo: { compoProducts: [createdProduct2.id] },
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
data.shops.push(createdShop);
|
||||||
|
});
|
||||||
|
|
||||||
|
afterAll(async () => {
|
||||||
|
await strapi.destroy();
|
||||||
|
await builder.cleanup();
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('findNew', () => {
|
||||||
|
test('relation not in a component && no entity', async () => {
|
||||||
|
let res = await rq({
|
||||||
|
method: 'GET',
|
||||||
|
url: '/content-manager/relations/api::shop.shop/products',
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(res.status).toBe(200);
|
||||||
|
expect(res.body.results).toMatchObject([
|
||||||
|
{
|
||||||
|
id: expect.any(Number),
|
||||||
|
name: 'Candle',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: expect.any(Number),
|
||||||
|
name: 'Skate',
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
|
||||||
|
// can omitIds
|
||||||
|
res = await rq({
|
||||||
|
method: 'GET',
|
||||||
|
url: '/content-manager/relations/api::shop.shop/products',
|
||||||
|
qs: {
|
||||||
|
idsToOmit: [data.products[0].id],
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(res.body.results).toMatchObject([
|
||||||
|
{
|
||||||
|
id: expect.any(Number),
|
||||||
|
name: 'Candle',
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('relation not in a component && on an entity', async () => {
|
||||||
|
let res = await rq({
|
||||||
|
method: 'GET',
|
||||||
|
url: '/content-manager/relations/api::shop.shop/products',
|
||||||
|
qs: {
|
||||||
|
entityId: data.shops[0].id,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(res.status).toBe(200);
|
||||||
|
expect(res.body.results).toMatchObject([
|
||||||
|
{
|
||||||
|
id: expect.any(Number),
|
||||||
|
name: 'Candle',
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
|
||||||
|
// can omitIds
|
||||||
|
res = await rq({
|
||||||
|
method: 'GET',
|
||||||
|
url: '/content-manager/relations/api::shop.shop/products',
|
||||||
|
qs: {
|
||||||
|
entityId: data.shops[0].id,
|
||||||
|
idsToOmit: [data.products[1].id],
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(res.body.results).toHaveLength(0);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('relation in a component && no entity', async () => {
|
||||||
|
let res = await rq({
|
||||||
|
method: 'GET',
|
||||||
|
url: '/content-manager/relations/api::shop.shop/compoProducts',
|
||||||
|
qs: {
|
||||||
|
component: 'default.compo',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(res.status).toBe(200);
|
||||||
|
expect(res.body.results).toMatchObject([
|
||||||
|
{
|
||||||
|
id: expect.any(Number),
|
||||||
|
name: 'Candle',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: expect.any(Number),
|
||||||
|
name: 'Skate',
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
|
||||||
|
// can omitIds
|
||||||
|
res = await rq({
|
||||||
|
method: 'GET',
|
||||||
|
url: '/content-manager/relations/api::shop.shop/compoProducts',
|
||||||
|
qs: {
|
||||||
|
component: 'default.compo',
|
||||||
|
idsToOmit: [data.products[0].id],
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(res.body.results).toMatchObject([
|
||||||
|
{
|
||||||
|
id: expect.any(Number),
|
||||||
|
name: 'Candle',
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('relation in a component && on an entity', async () => {
|
||||||
|
let res = await rq({
|
||||||
|
method: 'GET',
|
||||||
|
url: '/content-manager/relations/api::shop.shop/compoProducts',
|
||||||
|
qs: {
|
||||||
|
entityId: data.shops[0].myCompo.id,
|
||||||
|
component: 'default.compo',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(res.status).toBe(200);
|
||||||
|
expect(res.body.results).toMatchObject([
|
||||||
|
{
|
||||||
|
id: expect.any(Number),
|
||||||
|
name: 'Skate',
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
|
||||||
|
// can omitIds
|
||||||
|
res = await rq({
|
||||||
|
method: 'GET',
|
||||||
|
url: '/content-manager/relations/api::shop.shop/compoProducts',
|
||||||
|
qs: {
|
||||||
|
entityId: data.shops[0].myCompo.id,
|
||||||
|
component: 'default.compo',
|
||||||
|
idsToOmit: [data.products[0].id],
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(res.body.results).toHaveLength(0);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
Loading…
x
Reference in New Issue
Block a user