feat: add integration tests (#6923)

### Summary

This PR introduces several integration tests, a mix of manually written
tests and those generated using the `generate-integration-tests` Python
script located in the `scripts` folder.

### Tests Added:
- **Authentication tests**: Validating login, registration, and token
handling.
- **FindMany queries**: Fetching multiple records for all existing
entities that do not require input arguments.

### How the Integration Tests Work:
- A `setupTest` function is called during the Jest test run. This
function initializes a test instance of the application and exposes it
on a dedicated port.
- Since tests are executed in isolated workers, they do not have direct
access to the in-memory app instance. Instead, the tests query the
application through the exposed port.
- A static accessToken is used, this one as a big expiration time so it
will never expire (365 years)
- The queries are executed, and the results are validated against
expected outcomes.

### Current State and Next Steps:
- These tests currently run using the existing development seed data. We
plan to introduce more comprehensive test data using `faker` to improve
coverage.
- At the moment, the only mutation tests implemented are for
authentication. Future updates should include broader mutation testing
for other entities.

---------

Co-authored-by: Charles Bochet <charles@twenty.com>
This commit is contained in:
Jérémy M
2024-09-20 11:02:52 +02:00
committed by GitHub
parent 7781d70bb8
commit eef7f1661d
69 changed files with 2797 additions and 492 deletions

View File

@ -0,0 +1,67 @@
import request from 'supertest';
const client = request(`http://localhost:${APP_PORT}`);
describe('activitiesResolver (integration)', () => {
it('should find many activities', () => {
const queryData = {
query: `
query activities {
activities {
edges {
node {
title
body
type
reminderAt
dueAt
completedAt
id
createdAt
updatedAt
deletedAt
authorId
assigneeId
}
}
}
}
`,
};
return client
.post('/graphql')
.set('Authorization', `Bearer ${ACCESS_TOKEN}`)
.send(queryData)
.expect(200)
.expect((res) => {
expect(res.body.data).toBeDefined();
expect(res.body.errors).toBeUndefined();
})
.expect((res) => {
const data = res.body.data.activities;
expect(data).toBeDefined();
expect(Array.isArray(data.edges)).toBe(true);
const edges = data.edges;
if (edges.length > 0) {
const activities = edges[0].node;
expect(activities).toHaveProperty('title');
expect(activities).toHaveProperty('body');
expect(activities).toHaveProperty('type');
expect(activities).toHaveProperty('reminderAt');
expect(activities).toHaveProperty('dueAt');
expect(activities).toHaveProperty('completedAt');
expect(activities).toHaveProperty('id');
expect(activities).toHaveProperty('createdAt');
expect(activities).toHaveProperty('updatedAt');
expect(activities).toHaveProperty('deletedAt');
expect(activities).toHaveProperty('authorId');
expect(activities).toHaveProperty('assigneeId');
}
});
});
});

View File

@ -0,0 +1,59 @@
import request from 'supertest';
const client = request(`http://localhost:${APP_PORT}`);
describe('activityTargetsResolver (integration)', () => {
it('should find many activityTargets', () => {
const queryData = {
query: `
query activityTargets {
activityTargets {
edges {
node {
id
createdAt
updatedAt
deletedAt
activityId
personId
companyId
opportunityId
}
}
}
}
`,
};
return client
.post('/graphql')
.set('Authorization', `Bearer ${ACCESS_TOKEN}`)
.send(queryData)
.expect(200)
.expect((res) => {
expect(res.body.data).toBeDefined();
expect(res.body.errors).toBeUndefined();
})
.expect((res) => {
const data = res.body.data.activityTargets;
expect(data).toBeDefined();
expect(Array.isArray(data.edges)).toBe(true);
const edges = data.edges;
if (edges.length > 0) {
const activityTargets = edges[0].node;
expect(activityTargets).toHaveProperty('id');
expect(activityTargets).toHaveProperty('createdAt');
expect(activityTargets).toHaveProperty('updatedAt');
expect(activityTargets).toHaveProperty('deletedAt');
expect(activityTargets).toHaveProperty('activityId');
expect(activityTargets).toHaveProperty('personId');
expect(activityTargets).toHaveProperty('companyId');
expect(activityTargets).toHaveProperty('opportunityId');
}
});
});
});

View File

@ -0,0 +1,57 @@
import request from 'supertest';
const client = request(`http://localhost:${APP_PORT}`);
describe('apiKeysResolver (integration)', () => {
it('should find many apiKeys', () => {
const queryData = {
query: `
query apiKeys {
apiKeys {
edges {
node {
name
expiresAt
revokedAt
id
createdAt
updatedAt
deletedAt
}
}
}
}
`,
};
return client
.post('/graphql')
.set('Authorization', `Bearer ${ACCESS_TOKEN}`)
.send(queryData)
.expect(200)
.expect((res) => {
expect(res.body.data).toBeDefined();
expect(res.body.errors).toBeUndefined();
})
.expect((res) => {
const data = res.body.data.apiKeys;
expect(data).toBeDefined();
expect(Array.isArray(data.edges)).toBe(true);
const edges = data.edges;
if (edges.length > 0) {
const apiKeys = edges[0].node;
expect(apiKeys).toHaveProperty('name');
expect(apiKeys).toHaveProperty('expiresAt');
expect(apiKeys).toHaveProperty('revokedAt');
expect(apiKeys).toHaveProperty('id');
expect(apiKeys).toHaveProperty('createdAt');
expect(apiKeys).toHaveProperty('updatedAt');
expect(apiKeys).toHaveProperty('deletedAt');
}
});
});
});

View File

@ -1,31 +0,0 @@
import { INestApplication } from '@nestjs/common';
import request from 'supertest';
import { createApp } from './utils/create-app';
describe('AppController (e2e)', () => {
let app: INestApplication;
beforeEach(async () => {
[app] = await createApp();
});
afterEach(async () => {
await app.close();
});
it('/healthz (GET)', () => {
return request(app.getHttpServer())
.get('/healthz')
.expect(200)
.expect((response) => {
expect(response.body).toEqual({
status: 'ok',
info: { database: { status: 'up' } },
error: {},
details: { database: { status: 'up' } },
});
});
});
});

View File

@ -0,0 +1,71 @@
import request from 'supertest';
const client = request(`http://localhost:${APP_PORT}`);
describe('attachmentsResolver (integration)', () => {
it('should find many attachments', () => {
const queryData = {
query: `
query attachments {
attachments {
edges {
node {
name
fullPath
type
id
createdAt
updatedAt
deletedAt
authorId
activityId
taskId
noteId
personId
companyId
opportunityId
}
}
}
}
`,
};
return client
.post('/graphql')
.set('Authorization', `Bearer ${ACCESS_TOKEN}`)
.send(queryData)
.expect(200)
.expect((res) => {
expect(res.body.data).toBeDefined();
expect(res.body.errors).toBeUndefined();
})
.expect((res) => {
const data = res.body.data.attachments;
expect(data).toBeDefined();
expect(Array.isArray(data.edges)).toBe(true);
const edges = data.edges;
if (edges.length > 0) {
const attachments = edges[0].node;
expect(attachments).toHaveProperty('name');
expect(attachments).toHaveProperty('fullPath');
expect(attachments).toHaveProperty('type');
expect(attachments).toHaveProperty('id');
expect(attachments).toHaveProperty('createdAt');
expect(attachments).toHaveProperty('updatedAt');
expect(attachments).toHaveProperty('deletedAt');
expect(attachments).toHaveProperty('authorId');
expect(attachments).toHaveProperty('activityId');
expect(attachments).toHaveProperty('taskId');
expect(attachments).toHaveProperty('noteId');
expect(attachments).toHaveProperty('personId');
expect(attachments).toHaveProperty('companyId');
expect(attachments).toHaveProperty('opportunityId');
}
});
});
});

View File

@ -0,0 +1,65 @@
import request from 'supertest';
const client = request(`http://localhost:${APP_PORT}`);
describe('auditLogsResolver (integration)', () => {
it('should find many auditLogs', () => {
const queryData = {
query: `
query auditLogs {
auditLogs {
edges {
node {
name
properties
context
objectName
objectMetadataId
recordId
id
createdAt
updatedAt
deletedAt
workspaceMemberId
}
}
}
}
`,
};
return client
.post('/graphql')
.set('Authorization', `Bearer ${ACCESS_TOKEN}`)
.send(queryData)
.expect(200)
.expect((res) => {
expect(res.body.data).toBeDefined();
expect(res.body.errors).toBeUndefined();
})
.expect((res) => {
const data = res.body.data.auditLogs;
expect(data).toBeDefined();
expect(Array.isArray(data.edges)).toBe(true);
const edges = data.edges;
if (edges.length > 0) {
const auditLogs = edges[0].node;
expect(auditLogs).toHaveProperty('name');
expect(auditLogs).toHaveProperty('properties');
expect(auditLogs).toHaveProperty('context');
expect(auditLogs).toHaveProperty('objectName');
expect(auditLogs).toHaveProperty('objectMetadataId');
expect(auditLogs).toHaveProperty('recordId');
expect(auditLogs).toHaveProperty('id');
expect(auditLogs).toHaveProperty('createdAt');
expect(auditLogs).toHaveProperty('updatedAt');
expect(auditLogs).toHaveProperty('deletedAt');
expect(auditLogs).toHaveProperty('workspaceMemberId');
}
});
});
});

View File

@ -0,0 +1,80 @@
import request from 'supertest';
const client = request(`http://localhost:${APP_PORT}`);
const auth = {
email: 'tim@apple.dev',
password: 'Applecar2025',
};
describe('AuthResolve (integration)', () => {
let loginToken: string;
it('should challenge with email and password', () => {
const queryData = {
query: `
mutation Challenge {
challenge(email: "${auth.email}", password: "${auth.password}") {
loginToken {
token
expiresAt
}
}
}
`,
};
return client
.post('/graphql')
.send(queryData)
.expect(200)
.expect((res) => {
expect(res.body.data).toBeDefined();
expect(res.body.errors).toBeUndefined();
})
.expect((res) => {
const data = res.body.data.challenge;
expect(data).toBeDefined();
expect(data.loginToken).toBeDefined();
loginToken = data.loginToken.token;
});
});
it('should verify with login token', () => {
const queryData = {
query: `
mutation Verify {
verify(loginToken: "${loginToken}") {
tokens {
accessToken {
token
}
}
}
}
`,
};
return client
.post('/graphql')
.send(queryData)
.expect(200)
.expect((res) => {
expect(res.body.data).toBeDefined();
expect(res.body.errors).toBeUndefined();
})
.expect((res) => {
const data = res.body.data.verify;
expect(data).toBeDefined();
expect(data.tokens).toBeDefined();
const accessToken = data.tokens.accessToken;
expect(accessToken).toBeDefined();
expect(accessToken.token).toBeDefined();
});
});
});

View File

@ -0,0 +1,55 @@
import request from 'supertest';
const client = request(`http://localhost:${APP_PORT}`);
describe('blocklistsResolver (integration)', () => {
it('should find many blocklists', () => {
const queryData = {
query: `
query blocklists {
blocklists {
edges {
node {
handle
id
createdAt
updatedAt
deletedAt
workspaceMemberId
}
}
}
}
`,
};
return client
.post('/graphql')
.set('Authorization', `Bearer ${ACCESS_TOKEN}`)
.send(queryData)
.expect(200)
.expect((res) => {
expect(res.body.data).toBeDefined();
expect(res.body.errors).toBeUndefined();
})
.expect((res) => {
const data = res.body.data.blocklists;
expect(data).toBeDefined();
expect(Array.isArray(data.edges)).toBe(true);
const edges = data.edges;
if (edges.length > 0) {
const blocklists = edges[0].node;
expect(blocklists).toHaveProperty('handle');
expect(blocklists).toHaveProperty('id');
expect(blocklists).toHaveProperty('createdAt');
expect(blocklists).toHaveProperty('updatedAt');
expect(blocklists).toHaveProperty('deletedAt');
expect(blocklists).toHaveProperty('workspaceMemberId');
}
});
});
});

View File

@ -0,0 +1,63 @@
import request from 'supertest';
const client = request(`http://localhost:${APP_PORT}`);
describe('calendarChannelEventAssociationsResolver (integration)', () => {
it('should find many calendarChannelEventAssociations', () => {
const queryData = {
query: `
query calendarChannelEventAssociations {
calendarChannelEventAssociations {
edges {
node {
eventExternalId
id
createdAt
updatedAt
deletedAt
calendarChannelId
calendarEventId
}
}
}
}
`,
};
return client
.post('/graphql')
.set('Authorization', `Bearer ${ACCESS_TOKEN}`)
.send(queryData)
.expect(200)
.expect((res) => {
expect(res.body.data).toBeDefined();
expect(res.body.errors).toBeUndefined();
})
.expect((res) => {
const data = res.body.data.calendarChannelEventAssociations;
expect(data).toBeDefined();
expect(Array.isArray(data.edges)).toBe(true);
const edges = data.edges;
if (edges.length > 0) {
const calendarChannelEventAssociations = edges[0].node;
expect(calendarChannelEventAssociations).toHaveProperty(
'eventExternalId',
);
expect(calendarChannelEventAssociations).toHaveProperty('id');
expect(calendarChannelEventAssociations).toHaveProperty('createdAt');
expect(calendarChannelEventAssociations).toHaveProperty('updatedAt');
expect(calendarChannelEventAssociations).toHaveProperty('deletedAt');
expect(calendarChannelEventAssociations).toHaveProperty(
'calendarChannelId',
);
expect(calendarChannelEventAssociations).toHaveProperty(
'calendarEventId',
);
}
});
});
});

View File

@ -0,0 +1,75 @@
import request from 'supertest';
const client = request(`http://localhost:${APP_PORT}`);
describe('calendarChannelsResolver (integration)', () => {
it('should find many calendarChannels', () => {
const queryData = {
query: `
query calendarChannels {
calendarChannels {
edges {
node {
handle
syncStatus
syncStage
visibility
isContactAutoCreationEnabled
contactAutoCreationPolicy
isSyncEnabled
syncCursor
syncStageStartedAt
throttleFailureCount
id
createdAt
updatedAt
deletedAt
connectedAccountId
}
}
}
}
`,
};
return client
.post('/graphql')
.set('Authorization', `Bearer ${ACCESS_TOKEN}`)
.send(queryData)
.expect(200)
.expect((res) => {
expect(res.body.data).toBeDefined();
expect(res.body.errors).toBeUndefined();
})
.expect((res) => {
const data = res.body.data.calendarChannels;
expect(data).toBeDefined();
expect(Array.isArray(data.edges)).toBe(true);
const edges = data.edges;
if (edges.length > 0) {
const calendarChannels = edges[0].node;
expect(calendarChannels).toHaveProperty('handle');
expect(calendarChannels).toHaveProperty('syncStatus');
expect(calendarChannels).toHaveProperty('syncStage');
expect(calendarChannels).toHaveProperty('visibility');
expect(calendarChannels).toHaveProperty(
'isContactAutoCreationEnabled',
);
expect(calendarChannels).toHaveProperty('contactAutoCreationPolicy');
expect(calendarChannels).toHaveProperty('isSyncEnabled');
expect(calendarChannels).toHaveProperty('syncCursor');
expect(calendarChannels).toHaveProperty('syncStageStartedAt');
expect(calendarChannels).toHaveProperty('throttleFailureCount');
expect(calendarChannels).toHaveProperty('id');
expect(calendarChannels).toHaveProperty('createdAt');
expect(calendarChannels).toHaveProperty('updatedAt');
expect(calendarChannels).toHaveProperty('deletedAt');
expect(calendarChannels).toHaveProperty('connectedAccountId');
}
});
});
});

View File

@ -0,0 +1,65 @@
import request from 'supertest';
const client = request(`http://localhost:${APP_PORT}`);
describe('calendarEventParticipantsResolver (integration)', () => {
it('should find many calendarEventParticipants', () => {
const queryData = {
query: `
query calendarEventParticipants {
calendarEventParticipants {
edges {
node {
handle
displayName
isOrganizer
responseStatus
id
createdAt
updatedAt
deletedAt
calendarEventId
personId
workspaceMemberId
}
}
}
}
`,
};
return client
.post('/graphql')
.set('Authorization', `Bearer ${ACCESS_TOKEN}`)
.send(queryData)
.expect(200)
.expect((res) => {
expect(res.body.data).toBeDefined();
expect(res.body.errors).toBeUndefined();
})
.expect((res) => {
const data = res.body.data.calendarEventParticipants;
expect(data).toBeDefined();
expect(Array.isArray(data.edges)).toBe(true);
const edges = data.edges;
if (edges.length > 0) {
const calendarEventParticipants = edges[0].node;
expect(calendarEventParticipants).toHaveProperty('handle');
expect(calendarEventParticipants).toHaveProperty('displayName');
expect(calendarEventParticipants).toHaveProperty('isOrganizer');
expect(calendarEventParticipants).toHaveProperty('responseStatus');
expect(calendarEventParticipants).toHaveProperty('id');
expect(calendarEventParticipants).toHaveProperty('createdAt');
expect(calendarEventParticipants).toHaveProperty('updatedAt');
expect(calendarEventParticipants).toHaveProperty('deletedAt');
expect(calendarEventParticipants).toHaveProperty('calendarEventId');
expect(calendarEventParticipants).toHaveProperty('personId');
expect(calendarEventParticipants).toHaveProperty('workspaceMemberId');
}
});
});
});

View File

@ -0,0 +1,57 @@
import request from 'supertest';
const client = request(`http://localhost:${APP_PORT}`);
describe('commentsResolver (integration)', () => {
it('should find many comments', () => {
const queryData = {
query: `
query comments {
comments {
edges {
node {
body
id
createdAt
updatedAt
deletedAt
authorId
activityId
}
}
}
}
`,
};
return client
.post('/graphql')
.set('Authorization', `Bearer ${ACCESS_TOKEN}`)
.send(queryData)
.expect(200)
.expect((res) => {
expect(res.body.data).toBeDefined();
expect(res.body.errors).toBeUndefined();
})
.expect((res) => {
const data = res.body.data.comments;
expect(data).toBeDefined();
expect(Array.isArray(data.edges)).toBe(true);
const edges = data.edges;
if (edges.length > 0) {
const comments = edges[0].node;
expect(comments).toHaveProperty('body');
expect(comments).toHaveProperty('id');
expect(comments).toHaveProperty('createdAt');
expect(comments).toHaveProperty('updatedAt');
expect(comments).toHaveProperty('deletedAt');
expect(comments).toHaveProperty('authorId');
expect(comments).toHaveProperty('activityId');
}
});
});
});

View File

@ -0,0 +1,67 @@
import request from 'supertest';
const client = request(`http://localhost:${APP_PORT}`);
describe('companiesResolver (integration)', () => {
it('should find many companies', () => {
const queryData = {
query: `
query companies {
companies {
edges {
node {
name
employees
idealCustomerProfile
position
id
createdAt
updatedAt
deletedAt
accountOwnerId
tagline
workPolicy
visaSponsorship
}
}
}
}
`,
};
return client
.post('/graphql')
.set('Authorization', `Bearer ${ACCESS_TOKEN}`)
.send(queryData)
.expect(200)
.expect((res) => {
expect(res.body.data).toBeDefined();
expect(res.body.errors).toBeUndefined();
})
.expect((res) => {
const data = res.body.data.companies;
expect(data).toBeDefined();
expect(Array.isArray(data.edges)).toBe(true);
const edges = data.edges;
if (edges.length > 0) {
const companies = edges[0].node;
expect(companies).toHaveProperty('name');
expect(companies).toHaveProperty('employees');
expect(companies).toHaveProperty('idealCustomerProfile');
expect(companies).toHaveProperty('position');
expect(companies).toHaveProperty('id');
expect(companies).toHaveProperty('createdAt');
expect(companies).toHaveProperty('updatedAt');
expect(companies).toHaveProperty('deletedAt');
expect(companies).toHaveProperty('accountOwnerId');
expect(companies).toHaveProperty('tagline');
expect(companies).toHaveProperty('workPolicy');
expect(companies).toHaveProperty('visaSponsorship');
}
});
});
});

View File

@ -1,310 +0,0 @@
import { INestApplication } from '@nestjs/common';
import request from 'supertest';
import { WorkspaceAuthGuard } from 'src/engine/guards/workspace-auth.guard';
import { createApp } from './utils/create-app';
describe('CompanyResolver (e2e)', () => {
let app: INestApplication;
let companyId: string | undefined;
const authGuardMock = { canActivate: (): any => true };
beforeEach(async () => {
[app] = await createApp({
moduleBuilderHook: (moduleBuilder) =>
moduleBuilder.overrideGuard(WorkspaceAuthGuard).useValue(authGuardMock),
});
});
afterEach(async () => {
await app.close();
});
it('should create a company', () => {
const queryData = {
query: `
mutation CreateOneCompany($data: CompanyCreateInput!) {
createOneCompany(data: $data) {
id
name
domainName
address {
addressCity
}
}
}
`,
variables: {
data: {
name: 'New Company',
domainName: 'new-company.com',
address: { addressCity: 'Paris' },
},
},
};
return request(app.getHttpServer())
.post('/graphql')
.send(queryData)
.expect(200)
.expect((res) => {
const data = res.body.data.createOneCompany;
companyId = data.id;
expect(data).toBeDefined();
expect(data).toHaveProperty('id');
expect(data).toHaveProperty('name', 'New Company');
expect(data).toHaveProperty('domainName', 'new-company.com');
expect(data).toHaveProperty('address', { addressCity: 'Paris' });
});
});
it('should find many companies', () => {
const queryData = {
query: `
query FindManyCompany {
findManyCompany {
id
name
domainName
address {
addressCity
}
}
}
`,
};
return request(app.getHttpServer())
.post('/graphql')
.send(queryData)
.expect(200)
.expect((res) => {
const data = res.body.data.findManyCompany;
expect(data).toBeDefined();
expect(Array.isArray(data)).toBe(true);
expect(data.length).toBeGreaterThan(0);
const company = data.find((c) => c.id === companyId);
expect(company).toBeDefined();
expect(company).toHaveProperty('id');
expect(company).toHaveProperty('name', 'New Company');
expect(company).toHaveProperty('domainName', 'new-company.com');
expect(company).toHaveProperty('address', { addressCity: 'Paris' });
// Check if we have access to ressources outside of our workspace
const instagramCompany = data.find((c) => c.name === 'Instagram');
expect(instagramCompany).toBeUndefined();
});
});
it('should find unique company', () => {
const queryData = {
query: `
query FindUniqueCompany($where: CompanyWhereUniqueInput!) {
findUniqueCompany(where: $where) {
id
name
domainName
address {
addressCity
}
}
}
`,
variables: {
where: {
id: companyId,
},
},
};
return request(app.getHttpServer())
.post('/graphql')
.send(queryData)
.expect(200)
.expect((res) => {
const data = res.body.data.findUniqueCompany;
expect(data).toBeDefined();
expect(data).toHaveProperty('id');
expect(data).toHaveProperty('name', 'New Company');
expect(data).toHaveProperty('domainName', 'new-company.com');
expect(data).toHaveProperty('address', { addressCity: 'Paris' });
});
});
it('should not find unique company (forbidden because outside workspace)', () => {
const queryData = {
query: `
query FindUniqueCompany($where: CompanyWhereUniqueInput!) {
findUniqueCompany(where: $where) {
id
name
domainName
address {
addressCity
}
}
}
`,
variables: {
where: {
id: 'twenty-dev-a674fa6c-1455-4c57-afaf-dd5dc086361e',
},
},
};
return request(app.getHttpServer())
.post('/graphql')
.send(queryData)
.expect(200)
.expect((res) => {
const errors = res.body.errors;
const error = errors?.[0];
expect(error).toBeDefined();
expect(error.message).toBe('Forbidden resource');
});
});
it('should update a company', () => {
const queryData = {
query: `
mutation UpdateOneCompany($where: CompanyWhereUniqueInput!, $data: CompanyUpdateInput!) {
updateOneCompany(data: $data, where: $where) {
id
name
domainName
address {
addressCity
}
}
}
`,
variables: {
where: {
id: companyId,
},
data: {
name: 'Updated Company',
domainName: 'updated-company.com',
address: { addressCity: 'Updated City' },
},
},
};
return request(app.getHttpServer())
.post('/graphql')
.send(queryData)
.expect(200)
.expect((res) => {
const data = res.body.data.updateOneCompany;
expect(data).toBeDefined();
expect(data).toHaveProperty('id');
expect(data).toHaveProperty('name', 'Updated Company');
expect(data).toHaveProperty('domainName', 'updated-company.com');
expect(data).toHaveProperty('address', { addressCity: 'Updated City' });
});
});
it('should not update a company (forbidden because outside workspace)', () => {
const queryData = {
query: `
mutation UpdateOneCompany($where: CompanyWhereUniqueInput!, $data: CompanyUpdateInput!) {
updateOneCompany(data: $data, where: $where) {
id
name
domainName
address {
addressCity
}
}
}
`,
variables: {
where: {
id: 'twenty-dev-a674fa6c-1455-4c57-afaf-dd5dc086361e',
},
data: {
name: 'Updated Instagram',
},
},
};
return request(app.getHttpServer())
.post('/graphql')
.send(queryData)
.expect(200)
.expect((res) => {
const errors = res.body.errors;
const error = errors?.[0];
expect(error).toBeDefined();
expect(error.message).toBe('Forbidden resource');
});
});
it('should delete a company', () => {
const queryData = {
query: `
mutation DeleteManyCompany($ids: [String!]) {
deleteManyCompany(where: {id: {in: $ids}}) {
count
}
}
`,
variables: {
ids: [companyId],
},
};
return request(app.getHttpServer())
.post('/graphql')
.send(queryData)
.expect(200)
.expect((res) => {
const data = res.body.data.deleteManyCompany;
companyId = undefined;
expect(data).toBeDefined();
expect(data).toHaveProperty('count', 1);
});
});
it('should not delete a company (forbidden because outside workspace)', () => {
const queryData = {
query: `
mutation DeleteManyCompany($ids: [String!]) {
deleteManyCompany(where: {id: {in: $ids}}) {
count
}
}
`,
variables: {
ids: ['twenty-dev-a674fa6c-1455-4c57-afaf-dd5dc086361e'],
},
};
return request(app.getHttpServer())
.post('/graphql')
.send(queryData)
.expect(200)
.expect((res) => {
const errors = res.body.errors;
const error = errors?.[0];
expect(error).toBeDefined();
expect(error.message).toBe('Forbidden resource');
});
});
});

View File

@ -0,0 +1,48 @@
import request from 'supertest';
const graphqlClient = request(`http://localhost:${APP_PORT}`);
describe('CompanyResolver (integration)', () => {
it('should find many companies', () => {
const queryData = {
query: `
query Companies {
companies {
edges {
node {
id
name
}
}
}
}
`,
};
return graphqlClient
.post('/graphql')
.set('Authorization', `Bearer ${ACCESS_TOKEN}`)
.send(queryData)
.expect(200)
.expect((res) => {
expect(res.body.data).toBeDefined();
expect(res.body.errors).toBeUndefined();
})
.expect((res) => {
const data = res.body.data.companies;
expect(data).toBeDefined();
expect(Array.isArray(data.edges)).toBe(true);
const edges = data.edges;
if (edges.length > 0) {
const company = edges[0].node;
expect(company).toBeDefined();
expect(company).toHaveProperty('id');
expect(company).toHaveProperty('name');
}
});
});
});

View File

@ -0,0 +1,67 @@
import request from 'supertest';
const client = request(`http://localhost:${APP_PORT}`);
describe('connectedAccountsResolver (integration)', () => {
it('should find many connectedAccounts', () => {
const queryData = {
query: `
query connectedAccounts {
connectedAccounts {
edges {
node {
handle
provider
accessToken
refreshToken
lastSyncHistoryId
authFailedAt
handleAliases
id
createdAt
updatedAt
deletedAt
accountOwnerId
}
}
}
}
`,
};
return client
.post('/graphql')
.set('Authorization', `Bearer ${ACCESS_TOKEN}`)
.send(queryData)
.expect(200)
.expect((res) => {
expect(res.body.data).toBeDefined();
expect(res.body.errors).toBeUndefined();
})
.expect((res) => {
const data = res.body.data.connectedAccounts;
expect(data).toBeDefined();
expect(Array.isArray(data.edges)).toBe(true);
const edges = data.edges;
if (edges.length > 0) {
const connectedAccounts = edges[0].node;
expect(connectedAccounts).toHaveProperty('handle');
expect(connectedAccounts).toHaveProperty('provider');
expect(connectedAccounts).toHaveProperty('accessToken');
expect(connectedAccounts).toHaveProperty('refreshToken');
expect(connectedAccounts).toHaveProperty('lastSyncHistoryId');
expect(connectedAccounts).toHaveProperty('authFailedAt');
expect(connectedAccounts).toHaveProperty('handleAliases');
expect(connectedAccounts).toHaveProperty('id');
expect(connectedAccounts).toHaveProperty('createdAt');
expect(connectedAccounts).toHaveProperty('updatedAt');
expect(connectedAccounts).toHaveProperty('deletedAt');
expect(connectedAccounts).toHaveProperty('accountOwnerId');
}
});
});
});

View File

@ -0,0 +1,67 @@
import request from 'supertest';
const client = request(`http://localhost:${APP_PORT}`);
describe('favoritesResolver (integration)', () => {
it('should find many favorites', () => {
const queryData = {
query: `
query favorites {
favorites {
edges {
node {
position
id
createdAt
updatedAt
deletedAt
workspaceMemberId
personId
companyId
opportunityId
taskId
noteId
viewId
}
}
}
}
`,
};
return client
.post('/graphql')
.set('Authorization', `Bearer ${ACCESS_TOKEN}`)
.send(queryData)
.expect(200)
.expect((res) => {
expect(res.body.data).toBeDefined();
expect(res.body.errors).toBeUndefined();
})
.expect((res) => {
const data = res.body.data.favorites;
expect(data).toBeDefined();
expect(Array.isArray(data.edges)).toBe(true);
const edges = data.edges;
if (edges.length > 0) {
const favorites = edges[0].node;
expect(favorites).toHaveProperty('position');
expect(favorites).toHaveProperty('id');
expect(favorites).toHaveProperty('createdAt');
expect(favorites).toHaveProperty('updatedAt');
expect(favorites).toHaveProperty('deletedAt');
expect(favorites).toHaveProperty('workspaceMemberId');
expect(favorites).toHaveProperty('personId');
expect(favorites).toHaveProperty('companyId');
expect(favorites).toHaveProperty('opportunityId');
expect(favorites).toHaveProperty('taskId');
expect(favorites).toHaveProperty('noteId');
expect(favorites).toHaveProperty('viewId');
}
});
});
});

View File

@ -1,14 +0,0 @@
{
"moduleFileExtensions": ["js", "json", "ts"],
"rootDir": ".",
"testEnvironment": "node",
"testRegex": ".e2e-spec.ts$",
"setupFilesAfterEnv": ["<rootDir>/utils/setup-tests.ts"],
"moduleNameMapper": {
"^src/(.*)": "<rootDir>/../src/$1",
"^test/(.*)": "<rootDir>/$1"
},
"transform": {
"^.+\\.(t|j)s$": "ts-jest"
}
}

View File

@ -0,0 +1,67 @@
import request from 'supertest';
const client = request(`http://localhost:${APP_PORT}`);
describe('messageChannelMessageAssociationsResolver (integration)', () => {
it('should find many messageChannelMessageAssociations', () => {
const queryData = {
query: `
query messageChannelMessageAssociations {
messageChannelMessageAssociations {
edges {
node {
createdAt
messageExternalId
messageThreadExternalId
direction
id
updatedAt
deletedAt
messageChannelId
messageId
}
}
}
}
`,
};
return client
.post('/graphql')
.set('Authorization', `Bearer ${ACCESS_TOKEN}`)
.send(queryData)
.expect(200)
.expect((res) => {
expect(res.body.data).toBeDefined();
expect(res.body.errors).toBeUndefined();
})
.expect((res) => {
const data = res.body.data.messageChannelMessageAssociations;
expect(data).toBeDefined();
expect(Array.isArray(data.edges)).toBe(true);
const edges = data.edges;
if (edges.length > 0) {
const messageChannelMessageAssociations = edges[0].node;
expect(messageChannelMessageAssociations).toHaveProperty('createdAt');
expect(messageChannelMessageAssociations).toHaveProperty(
'messageExternalId',
);
expect(messageChannelMessageAssociations).toHaveProperty(
'messageThreadExternalId',
);
expect(messageChannelMessageAssociations).toHaveProperty('direction');
expect(messageChannelMessageAssociations).toHaveProperty('id');
expect(messageChannelMessageAssociations).toHaveProperty('updatedAt');
expect(messageChannelMessageAssociations).toHaveProperty('deletedAt');
expect(messageChannelMessageAssociations).toHaveProperty(
'messageChannelId',
);
expect(messageChannelMessageAssociations).toHaveProperty('messageId');
}
});
});
});

View File

@ -0,0 +1,85 @@
import request from 'supertest';
const client = request(`http://localhost:${APP_PORT}`);
describe('messageChannelsResolver (integration)', () => {
it('should find many messageChannels', () => {
const queryData = {
query: `
query messageChannels {
messageChannels {
edges {
node {
visibility
handle
type
isContactAutoCreationEnabled
contactAutoCreationPolicy
excludeNonProfessionalEmails
excludeGroupEmails
isSyncEnabled
syncCursor
syncedAt
syncStatus
syncStage
syncStageStartedAt
throttleFailureCount
id
createdAt
updatedAt
deletedAt
connectedAccountId
}
}
}
}
`,
};
return client
.post('/graphql')
.set('Authorization', `Bearer ${ACCESS_TOKEN}`)
.send(queryData)
.expect(200)
.expect((res) => {
expect(res.body.data).toBeDefined();
expect(res.body.errors).toBeUndefined();
})
.expect((res) => {
const data = res.body.data.messageChannels;
expect(data).toBeDefined();
expect(Array.isArray(data.edges)).toBe(true);
const edges = data.edges;
if (edges.length > 0) {
const messageChannels = edges[0].node;
expect(messageChannels).toHaveProperty('visibility');
expect(messageChannels).toHaveProperty('handle');
expect(messageChannels).toHaveProperty('type');
expect(messageChannels).toHaveProperty(
'isContactAutoCreationEnabled',
);
expect(messageChannels).toHaveProperty('contactAutoCreationPolicy');
expect(messageChannels).toHaveProperty(
'excludeNonProfessionalEmails',
);
expect(messageChannels).toHaveProperty('excludeGroupEmails');
expect(messageChannels).toHaveProperty('isSyncEnabled');
expect(messageChannels).toHaveProperty('syncCursor');
expect(messageChannels).toHaveProperty('syncedAt');
expect(messageChannels).toHaveProperty('syncStatus');
expect(messageChannels).toHaveProperty('syncStage');
expect(messageChannels).toHaveProperty('syncStageStartedAt');
expect(messageChannels).toHaveProperty('throttleFailureCount');
expect(messageChannels).toHaveProperty('id');
expect(messageChannels).toHaveProperty('createdAt');
expect(messageChannels).toHaveProperty('updatedAt');
expect(messageChannels).toHaveProperty('deletedAt');
expect(messageChannels).toHaveProperty('connectedAccountId');
}
});
});
});

View File

@ -0,0 +1,63 @@
import request from 'supertest';
const client = request(`http://localhost:${APP_PORT}`);
describe('messageParticipantsResolver (integration)', () => {
it('should find many messageParticipants', () => {
const queryData = {
query: `
query messageParticipants {
messageParticipants {
edges {
node {
role
handle
displayName
id
createdAt
updatedAt
deletedAt
messageId
personId
workspaceMemberId
}
}
}
}
`,
};
return client
.post('/graphql')
.set('Authorization', `Bearer ${ACCESS_TOKEN}`)
.send(queryData)
.expect(200)
.expect((res) => {
expect(res.body.data).toBeDefined();
expect(res.body.errors).toBeUndefined();
})
.expect((res) => {
const data = res.body.data.messageParticipants;
expect(data).toBeDefined();
expect(Array.isArray(data.edges)).toBe(true);
const edges = data.edges;
if (edges.length > 0) {
const messageParticipants = edges[0].node;
expect(messageParticipants).toHaveProperty('role');
expect(messageParticipants).toHaveProperty('handle');
expect(messageParticipants).toHaveProperty('displayName');
expect(messageParticipants).toHaveProperty('id');
expect(messageParticipants).toHaveProperty('createdAt');
expect(messageParticipants).toHaveProperty('updatedAt');
expect(messageParticipants).toHaveProperty('deletedAt');
expect(messageParticipants).toHaveProperty('messageId');
expect(messageParticipants).toHaveProperty('personId');
expect(messageParticipants).toHaveProperty('workspaceMemberId');
}
});
});
});

View File

@ -0,0 +1,51 @@
import request from 'supertest';
const client = request(`http://localhost:${APP_PORT}`);
describe('messageThreadsResolver (integration)', () => {
it('should find many messageThreads', () => {
const queryData = {
query: `
query messageThreads {
messageThreads {
edges {
node {
id
createdAt
updatedAt
deletedAt
}
}
}
}
`,
};
return client
.post('/graphql')
.set('Authorization', `Bearer ${ACCESS_TOKEN}`)
.send(queryData)
.expect(200)
.expect((res) => {
expect(res.body.data).toBeDefined();
expect(res.body.errors).toBeUndefined();
})
.expect((res) => {
const data = res.body.data.messageThreads;
expect(data).toBeDefined();
expect(Array.isArray(data.edges)).toBe(true);
const edges = data.edges;
if (edges.length > 0) {
const messageThreads = edges[0].node;
expect(messageThreads).toHaveProperty('id');
expect(messageThreads).toHaveProperty('createdAt');
expect(messageThreads).toHaveProperty('updatedAt');
expect(messageThreads).toHaveProperty('deletedAt');
}
});
});
});

View File

@ -1,9 +0,0 @@
{
"id": "20202020-a838-4fa9-b59b-96409b9a1c30",
"firstName": "Tim",
"lastName": "Apple",
"email": "tim@apple.dev",
"locale": "en",
"passwordHash": "$2b$10$66d.6DuQExxnrfI9rMqOg.U1XIYpagr6Lv05uoWLYbYmtK0HDIvS6",
"avatarUrl": null
}

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,59 @@
import request from 'supertest';
const client = request(`http://localhost:${APP_PORT}`);
describe('noteTargetsResolver (integration)', () => {
it('should find many noteTargets', () => {
const queryData = {
query: `
query noteTargets {
noteTargets {
edges {
node {
id
createdAt
updatedAt
deletedAt
noteId
personId
companyId
opportunityId
}
}
}
}
`,
};
return client
.post('/graphql')
.set('Authorization', `Bearer ${ACCESS_TOKEN}`)
.send(queryData)
.expect(200)
.expect((res) => {
expect(res.body.data).toBeDefined();
expect(res.body.errors).toBeUndefined();
})
.expect((res) => {
const data = res.body.data.noteTargets;
expect(data).toBeDefined();
expect(Array.isArray(data.edges)).toBe(true);
const edges = data.edges;
if (edges.length > 0) {
const noteTargets = edges[0].node;
expect(noteTargets).toHaveProperty('id');
expect(noteTargets).toHaveProperty('createdAt');
expect(noteTargets).toHaveProperty('updatedAt');
expect(noteTargets).toHaveProperty('deletedAt');
expect(noteTargets).toHaveProperty('noteId');
expect(noteTargets).toHaveProperty('personId');
expect(noteTargets).toHaveProperty('companyId');
expect(noteTargets).toHaveProperty('opportunityId');
}
});
});
});

View File

@ -0,0 +1,57 @@
import request from 'supertest';
const client = request(`http://localhost:${APP_PORT}`);
describe('notesResolver (integration)', () => {
it('should find many notes', () => {
const queryData = {
query: `
query notes {
notes {
edges {
node {
position
title
body
id
createdAt
updatedAt
deletedAt
}
}
}
}
`,
};
return client
.post('/graphql')
.set('Authorization', `Bearer ${ACCESS_TOKEN}`)
.send(queryData)
.expect(200)
.expect((res) => {
expect(res.body.data).toBeDefined();
expect(res.body.errors).toBeUndefined();
})
.expect((res) => {
const data = res.body.data.notes;
expect(data).toBeDefined();
expect(Array.isArray(data.edges)).toBe(true);
const edges = data.edges;
if (edges.length > 0) {
const notes = edges[0].node;
expect(notes).toHaveProperty('position');
expect(notes).toHaveProperty('title');
expect(notes).toHaveProperty('body');
expect(notes).toHaveProperty('id');
expect(notes).toHaveProperty('createdAt');
expect(notes).toHaveProperty('updatedAt');
expect(notes).toHaveProperty('deletedAt');
}
});
});
});

View File

@ -0,0 +1,75 @@
import request from 'supertest';
const client = request(`http://localhost:${APP_PORT}`);
describe('objectsResolver (integration)', () => {
it('should find many objects', () => {
const queryData = {
query: `
query objects {
objects {
edges {
node {
id
dataSourceId
nameSingular
namePlural
labelSingular
labelPlural
description
icon
isCustom
isRemote
isActive
isSystem
createdAt
updatedAt
labelIdentifierFieldMetadataId
imageIdentifierFieldMetadataId
}
}
}
}
`,
};
return client
.post('/graphql')
.set('Authorization', `Bearer ${ACCESS_TOKEN}`)
.send(queryData)
.expect(200)
.expect((res) => {
expect(res.body.data).toBeDefined();
expect(res.body.errors).toBeUndefined();
})
.expect((res) => {
const data = res.body.data.objects;
expect(data).toBeDefined();
expect(Array.isArray(data.edges)).toBe(true);
const edges = data.edges;
if (edges.length > 0) {
const objects = edges[0].node;
expect(objects).toHaveProperty('id');
expect(objects).toHaveProperty('dataSourceId');
expect(objects).toHaveProperty('nameSingular');
expect(objects).toHaveProperty('namePlural');
expect(objects).toHaveProperty('labelSingular');
expect(objects).toHaveProperty('labelPlural');
expect(objects).toHaveProperty('description');
expect(objects).toHaveProperty('icon');
expect(objects).toHaveProperty('isCustom');
expect(objects).toHaveProperty('isRemote');
expect(objects).toHaveProperty('isActive');
expect(objects).toHaveProperty('isSystem');
expect(objects).toHaveProperty('createdAt');
expect(objects).toHaveProperty('updatedAt');
expect(objects).toHaveProperty('labelIdentifierFieldMetadataId');
expect(objects).toHaveProperty('imageIdentifierFieldMetadataId');
}
});
});
});

View File

@ -0,0 +1,63 @@
import request from 'supertest';
const client = request(`http://localhost:${APP_PORT}`);
describe('opportunitiesResolver (integration)', () => {
it('should find many opportunities', () => {
const queryData = {
query: `
query opportunities {
opportunities {
edges {
node {
name
closeDate
stage
position
id
createdAt
updatedAt
deletedAt
pointOfContactId
companyId
}
}
}
}
`,
};
return client
.post('/graphql')
.set('Authorization', `Bearer ${ACCESS_TOKEN}`)
.send(queryData)
.expect(200)
.expect((res) => {
expect(res.body.data).toBeDefined();
expect(res.body.errors).toBeUndefined();
})
.expect((res) => {
const data = res.body.data.opportunities;
expect(data).toBeDefined();
expect(Array.isArray(data.edges)).toBe(true);
const edges = data.edges;
if (edges.length > 0) {
const opportunities = edges[0].node;
expect(opportunities).toHaveProperty('name');
expect(opportunities).toHaveProperty('closeDate');
expect(opportunities).toHaveProperty('stage');
expect(opportunities).toHaveProperty('position');
expect(opportunities).toHaveProperty('id');
expect(opportunities).toHaveProperty('createdAt');
expect(opportunities).toHaveProperty('updatedAt');
expect(opportunities).toHaveProperty('deletedAt');
expect(opportunities).toHaveProperty('pointOfContactId');
expect(opportunities).toHaveProperty('companyId');
}
});
});
});

View File

@ -0,0 +1,71 @@
import request from 'supertest';
const client = request(`http://localhost:${APP_PORT}`);
describe('peopleResolver (integration)', () => {
it('should find many people', () => {
const queryData = {
query: `
query people {
people {
edges {
node {
jobTitle
phone
city
avatarUrl
position
id
createdAt
updatedAt
deletedAt
companyId
intro
whatsapp
workPrefereance
performanceRating
}
}
}
}
`,
};
return client
.post('/graphql')
.set('Authorization', `Bearer ${ACCESS_TOKEN}`)
.send(queryData)
.expect(200)
.expect((res) => {
expect(res.body.data).toBeDefined();
expect(res.body.errors).toBeUndefined();
})
.expect((res) => {
const data = res.body.data.people;
expect(data).toBeDefined();
expect(Array.isArray(data.edges)).toBe(true);
const edges = data.edges;
if (edges.length > 0) {
const people = edges[0].node;
expect(people).toHaveProperty('jobTitle');
expect(people).toHaveProperty('phone');
expect(people).toHaveProperty('city');
expect(people).toHaveProperty('avatarUrl');
expect(people).toHaveProperty('position');
expect(people).toHaveProperty('id');
expect(people).toHaveProperty('createdAt');
expect(people).toHaveProperty('updatedAt');
expect(people).toHaveProperty('deletedAt');
expect(people).toHaveProperty('companyId');
expect(people).toHaveProperty('intro');
expect(people).toHaveProperty('whatsapp');
expect(people).toHaveProperty('workPrefereance');
expect(people).toHaveProperty('performanceRating');
}
});
});
});

View File

@ -0,0 +1,61 @@
import request from 'supertest';
const client = request(`http://localhost:${APP_PORT}`);
describe('serverlessFunctionsResolver (integration)', () => {
it('should find many serverlessFunctions', () => {
const queryData = {
query: `
query serverlessFunctions {
serverlessFunctions {
edges {
node {
id
name
description
sourceCodeHash
runtime
latestVersion
syncStatus
createdAt
updatedAt
}
}
}
}
`,
};
return client
.post('/graphql')
.set('Authorization', `Bearer ${ACCESS_TOKEN}`)
.send(queryData)
.expect(200)
.expect((res) => {
expect(res.body.data).toBeDefined();
expect(res.body.errors).toBeUndefined();
})
.expect((res) => {
const data = res.body.data.serverlessFunctions;
expect(data).toBeDefined();
expect(Array.isArray(data.edges)).toBe(true);
const edges = data.edges;
if (edges.length > 0) {
const serverlessFunctions = edges[0].node;
expect(serverlessFunctions).toHaveProperty('id');
expect(serverlessFunctions).toHaveProperty('name');
expect(serverlessFunctions).toHaveProperty('description');
expect(serverlessFunctions).toHaveProperty('sourceCodeHash');
expect(serverlessFunctions).toHaveProperty('runtime');
expect(serverlessFunctions).toHaveProperty('latestVersion');
expect(serverlessFunctions).toHaveProperty('syncStatus');
expect(serverlessFunctions).toHaveProperty('createdAt');
expect(serverlessFunctions).toHaveProperty('updatedAt');
}
});
});
});

View File

@ -0,0 +1,59 @@
import request from 'supertest';
const client = request(`http://localhost:${APP_PORT}`);
describe('taskTargetsResolver (integration)', () => {
it('should find many taskTargets', () => {
const queryData = {
query: `
query taskTargets {
taskTargets {
edges {
node {
id
createdAt
updatedAt
deletedAt
taskId
personId
companyId
opportunityId
}
}
}
}
`,
};
return client
.post('/graphql')
.set('Authorization', `Bearer ${ACCESS_TOKEN}`)
.send(queryData)
.expect(200)
.expect((res) => {
expect(res.body.data).toBeDefined();
expect(res.body.errors).toBeUndefined();
})
.expect((res) => {
const data = res.body.data.taskTargets;
expect(data).toBeDefined();
expect(Array.isArray(data.edges)).toBe(true);
const edges = data.edges;
if (edges.length > 0) {
const taskTargets = edges[0].node;
expect(taskTargets).toHaveProperty('id');
expect(taskTargets).toHaveProperty('createdAt');
expect(taskTargets).toHaveProperty('updatedAt');
expect(taskTargets).toHaveProperty('deletedAt');
expect(taskTargets).toHaveProperty('taskId');
expect(taskTargets).toHaveProperty('personId');
expect(taskTargets).toHaveProperty('companyId');
expect(taskTargets).toHaveProperty('opportunityId');
}
});
});
});

View File

@ -0,0 +1,63 @@
import request from 'supertest';
const client = request(`http://localhost:${APP_PORT}`);
describe('tasksResolver (integration)', () => {
it('should find many tasks', () => {
const queryData = {
query: `
query tasks {
tasks {
edges {
node {
position
title
body
dueAt
status
id
createdAt
updatedAt
deletedAt
assigneeId
}
}
}
}
`,
};
return client
.post('/graphql')
.set('Authorization', `Bearer ${ACCESS_TOKEN}`)
.send(queryData)
.expect(200)
.expect((res) => {
expect(res.body.data).toBeDefined();
expect(res.body.errors).toBeUndefined();
})
.expect((res) => {
const data = res.body.data.tasks;
expect(data).toBeDefined();
expect(Array.isArray(data.edges)).toBe(true);
const edges = data.edges;
if (edges.length > 0) {
const tasks = edges[0].node;
expect(tasks).toHaveProperty('position');
expect(tasks).toHaveProperty('title');
expect(tasks).toHaveProperty('body');
expect(tasks).toHaveProperty('dueAt');
expect(tasks).toHaveProperty('status');
expect(tasks).toHaveProperty('id');
expect(tasks).toHaveProperty('createdAt');
expect(tasks).toHaveProperty('updatedAt');
expect(tasks).toHaveProperty('deletedAt');
expect(tasks).toHaveProperty('assigneeId');
}
});
});
});

View File

@ -0,0 +1,75 @@
import request from 'supertest';
const client = request(`http://localhost:${APP_PORT}`);
describe('timelineActivitiesResolver (integration)', () => {
it('should find many timelineActivities', () => {
const queryData = {
query: `
query timelineActivities {
timelineActivities {
edges {
node {
happensAt
name
properties
linkedRecordCachedName
linkedRecordId
linkedObjectMetadataId
id
createdAt
updatedAt
deletedAt
workspaceMemberId
personId
companyId
opportunityId
noteId
taskId
}
}
}
}
`,
};
return client
.post('/graphql')
.set('Authorization', `Bearer ${ACCESS_TOKEN}`)
.send(queryData)
.expect(200)
.expect((res) => {
expect(res.body.data).toBeDefined();
expect(res.body.errors).toBeUndefined();
})
.expect((res) => {
const data = res.body.data.timelineActivities;
expect(data).toBeDefined();
expect(Array.isArray(data.edges)).toBe(true);
const edges = data.edges;
if (edges.length > 0) {
const timelineActivities = edges[0].node;
expect(timelineActivities).toHaveProperty('happensAt');
expect(timelineActivities).toHaveProperty('name');
expect(timelineActivities).toHaveProperty('properties');
expect(timelineActivities).toHaveProperty('linkedRecordCachedName');
expect(timelineActivities).toHaveProperty('linkedRecordId');
expect(timelineActivities).toHaveProperty('linkedObjectMetadataId');
expect(timelineActivities).toHaveProperty('id');
expect(timelineActivities).toHaveProperty('createdAt');
expect(timelineActivities).toHaveProperty('updatedAt');
expect(timelineActivities).toHaveProperty('deletedAt');
expect(timelineActivities).toHaveProperty('workspaceMemberId');
expect(timelineActivities).toHaveProperty('personId');
expect(timelineActivities).toHaveProperty('companyId');
expect(timelineActivities).toHaveProperty('opportunityId');
expect(timelineActivities).toHaveProperty('noteId');
expect(timelineActivities).toHaveProperty('taskId');
}
});
});
});

View File

@ -1,10 +1,6 @@
import { NestExpressApplication } from '@nestjs/platform-express';
import { Test, TestingModule, TestingModuleBuilder } from '@nestjs/testing';
import mockUser from 'test/mock-data/user.json';
import mockWorkspace from 'test/mock-data/workspace.json';
import { RequestHandler } from 'express';
import { AppModule } from 'src/app.module';
interface TestingModuleCreatePreHook {
@ -19,14 +15,14 @@ export type TestingAppCreatePreHook = (
) => Promise<void>;
/**
* Sets basic e2e testing module of app
* Sets basic integration testing module of app
*/
export const createApp = async (
config: {
moduleBuilderHook?: TestingModuleCreatePreHook;
appInitHook?: TestingAppCreatePreHook;
} = {},
): Promise<[NestExpressApplication, TestingModule]> => {
): Promise<NestExpressApplication> => {
let moduleBuilder: TestingModuleBuilder = Test.createTestingModule({
imports: [AppModule],
});
@ -36,21 +32,14 @@ export const createApp = async (
}
const moduleFixture: TestingModule = await moduleBuilder.compile();
const app = moduleFixture.createNestApplication<NestExpressApplication>();
if (config.appInitHook) {
await config.appInitHook(app);
}
const mockAuthHandler: RequestHandler = (req, _res, next) => {
req.user = {
user: mockUser,
workspace: mockWorkspace,
};
next();
};
await app.init();
app.use(mockAuthHandler);
return [await app.init(), moduleFixture];
return app;
};

View File

@ -0,0 +1,16 @@
import 'tsconfig-paths/register';
import { JestConfigWithTsJest } from 'ts-jest';
import { createApp } from './create-app';
export default async (_, projectConfig: JestConfigWithTsJest) => {
const app = await createApp({});
if (!projectConfig.globals) {
throw new Error('No globals found in project config');
}
await app.listen(projectConfig.globals.APP_PORT);
global.app = app;
};

View File

@ -1,3 +0,0 @@
global.beforeEach(() => {
// resetDb();
});

View File

@ -0,0 +1,5 @@
import 'tsconfig-paths/register';
export default async () => {
global.app.close();
};

View File

@ -0,0 +1,61 @@
import request from 'supertest';
const client = request(`http://localhost:${APP_PORT}`);
describe('viewFieldsResolver (integration)', () => {
it('should find many viewFields', () => {
const queryData = {
query: `
query viewFields {
viewFields {
edges {
node {
fieldMetadataId
isVisible
size
position
id
createdAt
updatedAt
deletedAt
viewId
}
}
}
}
`,
};
return client
.post('/graphql')
.set('Authorization', `Bearer ${ACCESS_TOKEN}`)
.send(queryData)
.expect(200)
.expect((res) => {
expect(res.body.data).toBeDefined();
expect(res.body.errors).toBeUndefined();
})
.expect((res) => {
const data = res.body.data.viewFields;
expect(data).toBeDefined();
expect(Array.isArray(data.edges)).toBe(true);
const edges = data.edges;
if (edges.length > 0) {
const viewFields = edges[0].node;
expect(viewFields).toHaveProperty('fieldMetadataId');
expect(viewFields).toHaveProperty('isVisible');
expect(viewFields).toHaveProperty('size');
expect(viewFields).toHaveProperty('position');
expect(viewFields).toHaveProperty('id');
expect(viewFields).toHaveProperty('createdAt');
expect(viewFields).toHaveProperty('updatedAt');
expect(viewFields).toHaveProperty('deletedAt');
expect(viewFields).toHaveProperty('viewId');
}
});
});
});

View File

@ -0,0 +1,61 @@
import request from 'supertest';
const client = request(`http://localhost:${APP_PORT}`);
describe('viewFiltersResolver (integration)', () => {
it('should find many viewFilters', () => {
const queryData = {
query: `
query viewFilters {
viewFilters {
edges {
node {
fieldMetadataId
operand
value
displayValue
id
createdAt
updatedAt
deletedAt
viewId
}
}
}
}
`,
};
return client
.post('/graphql')
.set('Authorization', `Bearer ${ACCESS_TOKEN}`)
.send(queryData)
.expect(200)
.expect((res) => {
expect(res.body.data).toBeDefined();
expect(res.body.errors).toBeUndefined();
})
.expect((res) => {
const data = res.body.data.viewFilters;
expect(data).toBeDefined();
expect(Array.isArray(data.edges)).toBe(true);
const edges = data.edges;
if (edges.length > 0) {
const viewFilters = edges[0].node;
expect(viewFilters).toHaveProperty('fieldMetadataId');
expect(viewFilters).toHaveProperty('operand');
expect(viewFilters).toHaveProperty('value');
expect(viewFilters).toHaveProperty('displayValue');
expect(viewFilters).toHaveProperty('id');
expect(viewFilters).toHaveProperty('createdAt');
expect(viewFilters).toHaveProperty('updatedAt');
expect(viewFilters).toHaveProperty('deletedAt');
expect(viewFilters).toHaveProperty('viewId');
}
});
});
});

View File

@ -0,0 +1,57 @@
import request from 'supertest';
const client = request(`http://localhost:${APP_PORT}`);
describe('viewSortsResolver (integration)', () => {
it('should find many viewSorts', () => {
const queryData = {
query: `
query viewSorts {
viewSorts {
edges {
node {
fieldMetadataId
direction
id
createdAt
updatedAt
deletedAt
viewId
}
}
}
}
`,
};
return client
.post('/graphql')
.set('Authorization', `Bearer ${ACCESS_TOKEN}`)
.send(queryData)
.expect(200)
.expect((res) => {
expect(res.body.data).toBeDefined();
expect(res.body.errors).toBeUndefined();
})
.expect((res) => {
const data = res.body.data.viewSorts;
expect(data).toBeDefined();
expect(Array.isArray(data.edges)).toBe(true);
const edges = data.edges;
if (edges.length > 0) {
const viewSorts = edges[0].node;
expect(viewSorts).toHaveProperty('fieldMetadataId');
expect(viewSorts).toHaveProperty('direction');
expect(viewSorts).toHaveProperty('id');
expect(viewSorts).toHaveProperty('createdAt');
expect(viewSorts).toHaveProperty('updatedAt');
expect(viewSorts).toHaveProperty('deletedAt');
expect(viewSorts).toHaveProperty('viewId');
}
});
});
});

View File

@ -0,0 +1,67 @@
import request from 'supertest';
const client = request(`http://localhost:${APP_PORT}`);
describe('viewsResolver (integration)', () => {
it('should find many views', () => {
const queryData = {
query: `
query views {
views {
edges {
node {
position
name
objectMetadataId
type
key
icon
kanbanFieldMetadataId
isCompact
id
createdAt
updatedAt
deletedAt
}
}
}
}
`,
};
return client
.post('/graphql')
.set('Authorization', `Bearer ${ACCESS_TOKEN}`)
.send(queryData)
.expect(200)
.expect((res) => {
expect(res.body.data).toBeDefined();
expect(res.body.errors).toBeUndefined();
})
.expect((res) => {
const data = res.body.data.views;
expect(data).toBeDefined();
expect(Array.isArray(data.edges)).toBe(true);
const edges = data.edges;
if (edges.length > 0) {
const views = edges[0].node;
expect(views).toHaveProperty('position');
expect(views).toHaveProperty('name');
expect(views).toHaveProperty('objectMetadataId');
expect(views).toHaveProperty('type');
expect(views).toHaveProperty('key');
expect(views).toHaveProperty('icon');
expect(views).toHaveProperty('kanbanFieldMetadataId');
expect(views).toHaveProperty('isCompact');
expect(views).toHaveProperty('id');
expect(views).toHaveProperty('createdAt');
expect(views).toHaveProperty('updatedAt');
expect(views).toHaveProperty('deletedAt');
}
});
});
});

View File

@ -0,0 +1,57 @@
import request from 'supertest';
const client = request(`http://localhost:${APP_PORT}`);
describe('webhooksResolver (integration)', () => {
it('should find many webhooks', () => {
const queryData = {
query: `
query webhooks {
webhooks {
edges {
node {
targetUrl
operation
description
id
createdAt
updatedAt
deletedAt
}
}
}
}
`,
};
return client
.post('/graphql')
.set('Authorization', `Bearer ${ACCESS_TOKEN}`)
.send(queryData)
.expect(200)
.expect((res) => {
expect(res.body.data).toBeDefined();
expect(res.body.errors).toBeUndefined();
})
.expect((res) => {
const data = res.body.data.webhooks;
expect(data).toBeDefined();
expect(Array.isArray(data.edges)).toBe(true);
const edges = data.edges;
if (edges.length > 0) {
const webhooks = edges[0].node;
expect(webhooks).toHaveProperty('targetUrl');
expect(webhooks).toHaveProperty('operation');
expect(webhooks).toHaveProperty('description');
expect(webhooks).toHaveProperty('id');
expect(webhooks).toHaveProperty('createdAt');
expect(webhooks).toHaveProperty('updatedAt');
expect(webhooks).toHaveProperty('deletedAt');
}
});
});
});

View File

@ -0,0 +1,67 @@
import request from 'supertest';
const client = request(`http://localhost:${APP_PORT}`);
describe('workspaceMembersResolver (integration)', () => {
it('should find many workspaceMembers', () => {
const queryData = {
query: `
query workspaceMembers {
workspaceMembers {
edges {
node {
id
colorScheme
avatarUrl
locale
timeZone
dateFormat
timeFormat
userEmail
userId
createdAt
updatedAt
deletedAt
}
}
}
}
`,
};
return client
.post('/graphql')
.set('Authorization', `Bearer ${ACCESS_TOKEN}`)
.send(queryData)
.expect(200)
.expect((res) => {
expect(res.body.data).toBeDefined();
expect(res.body.errors).toBeUndefined();
})
.expect((res) => {
const data = res.body.data.workspaceMembers;
expect(data).toBeDefined();
expect(Array.isArray(data.edges)).toBe(true);
const edges = data.edges;
if (edges.length > 0) {
const workspaceMembers = edges[0].node;
expect(workspaceMembers).toHaveProperty('id');
expect(workspaceMembers).toHaveProperty('colorScheme');
expect(workspaceMembers).toHaveProperty('avatarUrl');
expect(workspaceMembers).toHaveProperty('locale');
expect(workspaceMembers).toHaveProperty('timeZone');
expect(workspaceMembers).toHaveProperty('dateFormat');
expect(workspaceMembers).toHaveProperty('timeFormat');
expect(workspaceMembers).toHaveProperty('userEmail');
expect(workspaceMembers).toHaveProperty('userId');
expect(workspaceMembers).toHaveProperty('createdAt');
expect(workspaceMembers).toHaveProperty('updatedAt');
expect(workspaceMembers).toHaveProperty('deletedAt');
}
});
});
});