Files
twenty/packages/twenty-server/test/integration/graphql/suites/event-logs/object-event-write.integration-spec.ts
T
Paul Rastoin 60b559a659 Provide custom workspace id while seeding (#21721)
# Introduction
Currently working on e2e test ci that will iterate over dedicated twenty
instance.
In order to allow multi concurrent tests to be performed we need to
isolate testing context
Allowing to provide custom workspaceId allow easy isolation and post
test cleanup on aws related account

close https://github.com/twentyhq/core-team-issues/issues/2556

<!-- This is an auto-generated description by cubic. -->
<a
href="https://cubic.dev/pr/twentyhq/twenty/pull/21721?utm_source=github"
target="_blank" rel="noopener noreferrer"
data-no-image-dialog="true"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"><source
media="(prefers-color-scheme: light)"
srcset="https://www.cubic.dev/buttons/review-in-cubic-light.svg"><img
alt="Review in cubic"
src="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"></picture></a>
<!-- End of auto-generated description by cubic. -->
2026-06-17 14:29:27 +00:00

120 lines
3.8 KiB
TypeScript

import process from 'process';
import {
type ClickHouseClient,
ClickHouseLogLevel,
createClient,
} from '@clickhouse/client';
import gql from 'graphql-tag';
import { OBJECT_RECORD_CREATED_EVENT } from 'src/engine/core-modules/event-logs/emit/events/object-event/object-record-created';
import { SEED_APPLE_WORKSPACE_ID } from 'src/engine/workspace-manager/dev-seeder/core/constants/seeder-workspaces.constant';
import { PERSON_GQL_FIELDS } from 'test/integration/constants/person-gql-fields.constants';
import { createManyOperationFactory } from 'test/integration/graphql/utils/create-many-operation-factory.util';
import { makeGraphqlAPIRequest } from 'test/integration/graphql/utils/make-graphql-api-request.util';
import { makeMetadataAPIRequest } from 'test/integration/metadata/suites/utils/make-metadata-api-request.util';
import { deleteAllRecords } from 'test/integration/utils/delete-all-records';
// End-to-end write path: creating a record fires an objectEvent through
// entityEventsToDbQueue -> the consumer -> the ClickHouse sink.
describe('Object event write (integration)', () => {
let clickHouseClient: ClickHouseClient;
let personObjectMetadataId: string;
const testWorkspaceId = SEED_APPLE_WORKSPACE_ID;
beforeAll(async () => {
jest.useRealTimers();
clickHouseClient = createClient({
url: process.env.CLICKHOUSE_URL,
log: { level: ClickHouseLogLevel.OFF },
});
await deleteAllRecords('person');
const response = await makeMetadataAPIRequest({
query: gql`
query {
objects(paging: { first: 1000 }) {
edges {
node {
id
nameSingular
}
}
}
}
`,
});
personObjectMetadataId = response.body.data.objects.edges.find(
(edge: { node: { id: string; nameSingular: string } }) =>
edge.node.nameSingular === 'person',
).node.id;
});
afterAll(async () => {
await deleteAllRecords('person');
if (clickHouseClient) {
await clickHouseClient.close();
}
});
const queryObjectEventsByRecordId = (recordId: string) =>
clickHouseClient
.query({
query: `
SELECT event, recordId, objectMetadataId, workspaceId
FROM objectEvent
WHERE recordId = '${recordId}' AND workspaceId = '${testWorkspaceId}'
`,
format: 'JSONEachRow',
})
.then((result) =>
result.json<{
event: string;
recordId: string;
objectMetadataId: string;
workspaceId: string;
}>(),
);
it('writes an objectEvent row to ClickHouse when a record is created', async () => {
const createResponse = await makeGraphqlAPIRequest(
createManyOperationFactory({
objectMetadataSingularName: 'person',
objectMetadataPluralName: 'people',
gqlFields: PERSON_GQL_FIELDS,
data: [{ name: { firstName: 'Event', lastName: 'Logged' } }],
}),
);
expect(createResponse.body.errors).toBeUndefined();
const recordId = createResponse.body.data.createPeople[0].id;
expect(recordId).toBeDefined();
let rows: Awaited<ReturnType<typeof queryObjectEventsByRecordId>> = [];
for (let attempt = 0; attempt < 20 && rows.length === 0; attempt++) {
rows = await queryObjectEventsByRecordId(recordId);
if (rows.length === 0) {
await new Promise((resolve) => setTimeout(resolve, 500));
}
}
expect(rows.length).toBeGreaterThanOrEqual(1);
expect(rows[0].event).toBe(OBJECT_RECORD_CREATED_EVENT);
expect(rows[0].recordId).toBe(recordId);
expect(rows[0].objectMetadataId).toBe(personObjectMetadataId);
await clickHouseClient.command({
query: `ALTER TABLE objectEvent DELETE WHERE recordId = '${recordId}'`,
});
});
});