strapi/packages/plugins/graphql/tests/graphql-relations.test.e2e.js

839 lines
19 KiB
JavaScript
Raw Normal View History

'use strict';
// Helpers.
2021-09-21 19:38:15 +02:00
const { pick } = require('lodash/fp');
2021-04-29 11:11:46 +02:00
const { createTestBuilder } = require('../../../../test/helpers/builder');
const { createStrapiInstance } = require('../../../../test/helpers/strapi');
const { createAuthRequest } = require('../../../../test/helpers/request');
const builder = createTestBuilder();
let strapi;
let rq;
let graphqlQuery;
2021-09-21 19:38:15 +02:00
// Utils
const selectFields = pick(['name', 'color']);
const rgbColorComponent = {
attributes: {
name: {
type: 'text',
},
red: {
type: 'integer',
},
green: {
type: 'integer',
},
blue: {
type: 'integer',
},
},
name: 'rgbColor',
};
const documentModel = {
2019-11-14 16:37:57 +01:00
attributes: {
name: {
type: 'richtext',
},
2019-11-14 16:37:57 +01:00
content: {
type: 'richtext',
},
2019-11-14 16:37:57 +01:00
},
singularName: 'document',
pluralName: 'documents',
displayName: 'Document',
description: '',
collectionName: '',
};
const labelModel = {
2019-11-14 16:37:57 +01:00
attributes: {
name: {
type: 'richtext',
},
2019-11-14 16:37:57 +01:00
documents: {
2021-07-08 18:15:32 +02:00
type: 'relation',
relation: 'manyToMany',
2021-08-06 18:09:49 +02:00
target: 'api::document.document',
2019-11-14 16:37:57 +01:00
targetAttribute: 'labels',
},
color: {
type: 'component',
component: 'default.rgb-color',
repeatable: false,
},
2019-11-14 16:37:57 +01:00
},
singularName: 'label',
pluralName: 'labels',
displayName: 'Label',
description: '',
collectionName: '',
};
const carModel = {
attributes: {
name: {
type: 'text',
},
},
singularName: 'car',
pluralName: 'cars',
displayName: 'Car',
description: '',
collectionName: '',
};
const personModel = {
attributes: {
name: {
type: 'text',
},
privateName: {
type: 'text',
private: true,
},
privateCars: {
2021-07-08 18:15:32 +02:00
type: 'relation',
relation: 'oneToMany',
2021-08-06 18:09:49 +02:00
target: 'api::car.car',
targetAttribute: 'person',
private: true,
},
},
displayName: 'Person',
singularName: 'person',
pluralName: 'people',
description: '',
collectionName: '',
};
describe('Test Graphql Relations API End to End', () => {
beforeAll(async () => {
await builder
.addComponent(rgbColorComponent)
.addContentTypes([documentModel, labelModel, carModel, personModel])
.build();
strapi = await createStrapiInstance();
rq = await createAuthRequest({ strapi });
graphqlQuery = body => {
return rq({
url: '/graphql',
method: 'POST',
body,
});
};
});
afterAll(async () => {
await strapi.destroy();
await builder.cleanup();
});
describe('Test relations features', () => {
let data = {
labels: [],
documents: [],
people: [],
cars: [],
};
const labelsPayload = [
{ name: 'label 1', color: null },
{ name: 'label 2', color: null },
{ name: 'labelWithColor', color: { name: 'tomato', red: 255, green: 99, blue: 71 } },
];
2019-03-28 15:08:00 +01:00
const documentsPayload = [{ name: 'document 1' }, { name: 'document 2' }];
test.each(labelsPayload)('Create label %o', async label => {
const res = await graphqlQuery({
query: /* GraphQL */ `
2021-09-21 19:38:15 +02:00
mutation createLabel($data: LabelInput!) {
createLabel(data: $data) {
data {
attributes {
name
2021-09-21 19:38:15 +02:00
color {
name
red
green
blue
}
}
}
}
}
`,
variables: {
2021-09-21 19:38:15 +02:00
data: label,
},
});
expect(res.statusCode).toBe(200);
expect(res.body).toEqual({
data: {
createLabel: {
2021-09-21 19:38:15 +02:00
data: {
attributes: label,
},
},
},
});
});
test('List labels', async () => {
const res = await graphqlQuery({
query: /* GraphQL */ `
{
labels {
2021-09-21 19:38:15 +02:00
data {
id
attributes {
name
color {
name
red
green
blue
}
}
}
}
}
`,
});
const { body } = res;
expect(res.statusCode).toBe(200);
expect(body).toMatchObject({
data: {
2021-09-21 19:38:15 +02:00
labels: {
data: labelsPayload.map(label => ({ id: expect.any(String), attributes: label })),
},
},
});
// assign for later use
2021-09-21 19:38:15 +02:00
data.labels = data.labels.concat(res.body.data.labels.data);
});
test.each(documentsPayload)('Create document linked to every labels %o', async document => {
const res = await graphqlQuery({
query: /* GraphQL */ `
2021-09-21 19:38:15 +02:00
mutation createDocument($data: DocumentInput!) {
createDocument(data: $data) {
data {
id
attributes {
name
2021-09-21 19:38:15 +02:00
labels {
data {
id
attributes {
name
color {
name
red
green
blue
}
}
}
2019-04-09 18:35:49 +02:00
}
}
}
}
}
`,
variables: {
2021-09-21 19:38:15 +02:00
data: {
...document,
labels: data.labels.map(t => t.id),
},
},
});
const { body } = res;
expect(res.statusCode).toBe(200);
expect(body).toMatchObject({
data: {
createDocument: {
2021-09-21 19:38:15 +02:00
data: {
id: expect.any(String),
attributes: {
...selectFields(document),
labels: {
data: expect.arrayContaining(data.labels),
},
},
},
},
},
});
2021-09-21 19:38:15 +02:00
data.documents.push(body.data.createDocument.data);
});
test('List documents with labels', async () => {
const res = await graphqlQuery({
query: /* GraphQL */ `
{
documents {
2021-09-21 19:38:15 +02:00
data {
id
2021-09-21 19:38:15 +02:00
attributes {
name
2021-09-21 19:38:15 +02:00
labels {
data {
id
attributes {
name
color {
name
red
green
blue
}
}
}
}
}
}
}
}
`,
});
const { body } = res;
expect(res.statusCode).toBe(200);
expect(body).toMatchObject({
2019-04-09 18:35:49 +02:00
data: {
2021-09-21 19:38:15 +02:00
documents: {
data: expect.arrayContaining(data.documents),
},
2019-04-09 18:35:49 +02:00
},
});
// assign for later use
2021-09-21 19:38:15 +02:00
data.documents = res.body.data.documents.data;
});
test('List Labels with documents', async () => {
const res = await graphqlQuery({
query: /* GraphQL */ `
{
labels {
2021-09-21 19:38:15 +02:00
data {
id
2021-09-21 19:38:15 +02:00
attributes {
name
color {
name
red
green
blue
}
documents {
data {
id
attributes {
name
}
}
}
}
}
}
}
`,
});
const { body } = res;
expect(res.statusCode).toBe(200);
expect(body).toMatchObject({
data: {
2021-09-21 19:38:15 +02:00
labels: {
data: expect.arrayContaining(
data.labels.map(label => ({
id: label.id,
attributes: {
...label.attributes,
documents: {
data: expect.arrayContaining(
data.documents.map(document => ({
id: document.id,
attributes: selectFields(document.attributes),
}))
),
},
},
}))
),
},
},
});
// assign for later use
2021-09-21 19:38:15 +02:00
data.labels = res.body.data.labels.data;
});
test('Deep query', async () => {
const res = await graphqlQuery({
query: /* GraphQL */ `
{
2021-09-21 19:38:15 +02:00
documents(filters: { labels: { name: { contains: "label 1" } } }) {
data {
id
2021-09-21 19:38:15 +02:00
attributes {
name
2021-09-21 19:38:15 +02:00
labels {
data {
id
attributes {
name
color {
name
red
green
blue
}
}
}
}
}
}
}
}
`,
});
expect(res.statusCode).toBe(200);
expect(res.body).toMatchObject({
data: {
2021-09-21 19:38:15 +02:00
documents: {
data: expect.arrayContaining(data.documents),
},
},
});
});
test('Update Document relations removes correctly a relation', async () => {
2021-09-21 19:38:15 +02:00
const document = data.documents[0];
const labels = [data.labels[0]];
// if I remove a label from an document is it working
const res = await graphqlQuery({
query: /* GraphQL */ `
2021-09-21 19:38:15 +02:00
mutation updateDocument($id: ID!, $data: DocumentInput!) {
updateDocument(id: $id, data: $data) {
data {
id
2021-09-21 19:38:15 +02:00
attributes {
name
2021-09-21 19:38:15 +02:00
labels {
data {
id
attributes {
name
color {
name
red
green
blue
}
}
}
}
}
}
}
}
`,
variables: {
2021-09-21 19:38:15 +02:00
id: document.id,
data: {
labels: labels.map(label => label.id),
},
},
});
expect(res.body).toMatchObject({
data: {
updateDocument: {
2021-09-21 19:38:15 +02:00
data: {
id: document.id,
attributes: {
...selectFields(document.attributes),
labels: {
data: labels.map(label => ({
id: label.id,
attributes: {
...selectFields(label.attributes),
color: null,
},
})),
},
},
},
},
},
});
});
test('Delete Labels and test Documents relations', async () => {
for (let label of data.labels) {
const res = await graphqlQuery({
query: /* GraphQL */ `
2021-09-21 19:38:15 +02:00
mutation deleteLabel($id: ID!) {
deleteLabel(id: $id) {
data {
2019-08-23 14:15:24 +02:00
id
2021-09-21 19:38:15 +02:00
attributes {
name
2021-09-21 19:38:15 +02:00
color {
name
red
green
blue
}
}
}
}
}
`,
variables: {
2021-09-21 19:38:15 +02:00
id: label.id,
},
});
expect(res.statusCode).toBe(200);
2019-08-23 14:15:24 +02:00
expect(res.body).toMatchObject({
data: {
deleteLabel: {
2021-09-21 19:38:15 +02:00
data: {
2019-08-23 14:15:24 +02:00
id: label.id,
2021-09-21 19:38:15 +02:00
attributes: {
...selectFields(label.attributes),
color: null,
},
2019-08-23 14:15:24 +02:00
},
},
},
});
}
const res = await graphqlQuery({
query: /* GraphQL */ `
{
documents {
2021-09-21 19:38:15 +02:00
data {
id
2021-09-21 19:38:15 +02:00
attributes {
name
2021-09-21 19:38:15 +02:00
labels {
data {
id
attributes {
name
color {
name
red
green
blue
}
}
}
}
}
}
}
}
`,
});
const { body } = res;
expect(res.statusCode).toBe(200);
expect(body).toMatchObject({
data: {
2021-09-21 19:38:15 +02:00
documents: {
data: expect.arrayContaining(
data.documents.map(document => ({
id: document.id,
attributes: {
...selectFields(document.attributes),
labels: { data: [] },
},
}))
),
},
},
});
});
test('Delete Documents', async () => {
for (let document of data.documents) {
const res = await graphqlQuery({
query: /* GraphQL */ `
2021-09-21 19:38:15 +02:00
mutation deleteDocument($id: ID!) {
deleteDocument(id: $id) {
data {
2019-08-23 14:15:24 +02:00
id
2021-09-21 19:38:15 +02:00
attributes {
name
labels {
data {
id
attributes {
name
color {
name
red
green
}
}
}
}
}
}
}
}
`,
variables: {
2021-09-21 19:38:15 +02:00
id: document.id,
},
});
expect(res.statusCode).toBe(200);
2019-08-23 14:15:24 +02:00
expect(res.body).toMatchObject({
data: {
deleteDocument: {
2021-09-21 19:38:15 +02:00
data: {
2019-08-23 14:15:24 +02:00
id: document.id,
2021-09-21 19:38:15 +02:00
attributes: {
...selectFields(document.attributes),
labels: { data: [] },
},
2019-08-23 14:15:24 +02:00
},
},
},
});
}
});
test('Create person', async () => {
const person = {
name: 'Chuck Norris',
privateName: 'Jean-Eude',
};
2021-09-21 19:38:15 +02:00
const res = await graphqlQuery({
query: /* GraphQL */ `
2021-09-21 19:38:15 +02:00
mutation createPerson($data: PersonInput!) {
createPerson(data: $data) {
data {
id
2021-09-21 19:38:15 +02:00
attributes {
name
}
}
}
}
`,
variables: {
2021-09-21 19:38:15 +02:00
data: person,
},
});
expect(res.statusCode).toBe(200);
expect(res.body).toEqual({
data: {
createPerson: {
2021-09-21 19:38:15 +02:00
data: {
id: expect.anything(),
2021-09-21 19:38:15 +02:00
attributes: {
name: person.name,
},
},
},
},
});
2021-09-21 19:38:15 +02:00
data.people.push(res.body.data.createPerson.data);
});
test("Can't list a private field", async () => {
const res = await graphqlQuery({
query: /* GraphQL */ `
{
people {
2021-09-21 19:38:15 +02:00
data {
attributes {
name
privateName
}
}
}
}
`,
});
expect(res.statusCode).toBe(400);
expect(res.body).toMatchObject({
errors: [
{
message: 'Cannot query field "privateName" on type "Person".',
// message: 'Cannot query field "people" on type "Query".',
},
],
});
});
test('Create a car linked to a person (oneToMany)', async () => {
const car = {
name: 'Peugeot 508',
person: data.people[0].id,
};
2021-09-21 19:38:15 +02:00
const res = await graphqlQuery({
query: /* GraphQL */ `
2021-09-21 19:38:15 +02:00
mutation createCar($data: CarInput!) {
createCar(data: $data) {
data {
id
2021-09-21 19:38:15 +02:00
attributes {
name
2021-09-21 19:38:15 +02:00
person {
data {
id
attributes {
name
}
}
}
}
}
}
}
`,
variables: {
2021-09-21 19:38:15 +02:00
data: car,
},
});
expect(res.statusCode).toBe(200);
expect(res.body).toMatchObject({
data: {
createCar: {
2021-09-21 19:38:15 +02:00
data: {
id: expect.anything(),
2021-09-21 19:38:15 +02:00
attributes: {
name: car.name,
person: {
data: data.people[0],
},
},
},
},
},
});
2021-09-21 19:38:15 +02:00
data.cars.push({ id: res.body.data.createCar.data.id });
});
test("Can't list a private oneToMany relation", async () => {
const res = await graphqlQuery({
query: /* GraphQL */ `
{
people {
2021-09-21 19:38:15 +02:00
data {
attributes {
name
privateCars
}
}
}
}
`,
});
expect(res.statusCode).toBe(400);
expect(res.body).toMatchObject({
errors: [
{
message: 'Cannot query field "privateCars" on type "Person".',
},
],
});
});
test('Edit person/cars relations removes correctly a car', async () => {
const newPerson = {
name: 'Check Norris Junior',
privateCars: [],
};
const mutationRes = await graphqlQuery({
query: /* GraphQL */ `
2021-09-21 19:38:15 +02:00
mutation updatePerson($id: ID!, $data: PersonInput!) {
updatePerson(id: $id, data: $data) {
data {
id
}
}
}
`,
variables: {
2021-09-21 19:38:15 +02:00
id: data.people[0].id,
data: newPerson,
},
});
2021-09-21 19:38:15 +02:00
expect(mutationRes.statusCode).toBe(200);
const queryRes = await graphqlQuery({
query: /* GraphQL */ `
query($id: ID!) {
car(id: $id) {
2021-09-21 19:38:15 +02:00
data {
attributes {
person {
data {
id
}
}
}
}
}
}
`,
variables: {
id: data.cars[0].id,
},
});
2021-09-21 19:38:15 +02:00
expect(queryRes.statusCode).toBe(200);
expect(queryRes.body).toEqual({
data: {
car: {
2021-09-21 19:38:15 +02:00
data: {
attributes: {
person: {
data: null,
},
},
},
},
},
});
});
});
});