snapshot of https://github.com/twentyhq/twenty.git (main, 2026-09-17; blobs > 131072B omitted)
Some checks failed
App Prod-Parity E2E Dispatch / dispatch (push) Failing after 10s
CD Storybook UI / build (push) Failing after 3m25s
CD Storybook UI / dispatch (push) Has been skipped
CD deploy main / website-changed-files (push) Successful in 18m8s
CI Agent Skills / changed-files-check (push) Successful in 18m9s
CI Create App E2E minimal / changed-files-check (push) Successful in 24s
CI Create App / changed-files-check (push) Successful in 26s
CI Docs / changed-files-check (push) Successful in 26s
CI Emails / changed-files-check (push) Successful in 28s
CI Example App Hello World / changed-files-check (push) Successful in 23s
CI Front / changed-files-check (push) Has been skipped
CI Example App Postcard / changed-files-check (push) Successful in 27s
CI UI / changed-files-check (push) Has been skipped
CI Utils Test / changed-files-check (push) Successful in 45s
CI Twenty Apps / discover (push) Successful in 1m3s
CD deploy main / deploy-main (push) Failing after 3s
CI Agent Skills / agent-skills-validate (push) Has been skipped
CI Create App / create-app-test (lint) (push) Has been skipped
CI Emails / emails-test (push) Has been skipped
CI Front / front-task (lingui:compile) (push) Has been skipped
CI Front / front-task (lint) (push) Has been skipped
CI Example App Postcard / example-app-postcard (push) Has been skipped
CI UI / ui-task (lint) (push) Has been skipped
CI UI / ui-task (pack-size) (push) Has been skipped
CI UI / ui-task (size) (push) Has been skipped
CI UI / ui-task (test) (push) Has been skipped
CI UI / ui-task (typecheck) (push) Has been skipped
CI Utils Test / utils-test (push) Has been skipped
CI Twenty Apps / ${{ matrix.app.name }} (push) Has been skipped
CI Emails / ci-emails-status-check (push) Successful in 2s
CI Example App Hello World / ci-example-app-hello-world-status-check (push) Successful in 2s
CI Example App Postcard / ci-example-app-postcard-status-check (push) Successful in 3s
CI UI / ui-sb-test (push) Has been skipped
CI Utils Test / ci-utils-test-status-check (push) Successful in 2s
CI Twenty Apps / ci-twenty-apps-status-check (push) Successful in 2s
CI UI / ci-ui-status-check (push) Successful in 2s
CI Desktop / desktop (push) Failing after 1m8s
Push docs to Crowdin / Push documentation to Crowdin (push) Failing after 55s
Push translations to Crowdin / Extract and upload translations (push) Failing after 5s
Push website translations to Crowdin / Extract and upload website translations (push) Failing after 5s
CI Create App / create-app-test (test) (push) Has been skipped
CI Create App / create-app-test (typecheck) (push) Has been skipped
CI Docs / docs-lint (push) Has been skipped
CI Example App Hello World / example-app-hello-world (push) Has been skipped
CI Front / front-task (lingui:extract) (push) Has been skipped
CI Front / front-task (test) (push) Has been skipped
CI Front / front-task (typecheck) (push) Has been skipped
CI UI / ui-sb-build (push) Failing after 1m32s
CI Twenty Apps / ${{ matrix.app.name }} (${{ matrix.server-source }}) (push) Has been skipped
CI Agent Skills / agent-skills-publish (push) Has been skipped
CI Create App / ci-create-app-status-check (push) Successful in 2s
CI Agent Skills / agent-skills-remote-source (push) Has been skipped
CI Create App E2E minimal / create-app-e2e-minimal (push) Has been cancelled
CI E2E Main / e2e-test (push) Has been cancelled
CI Front / front-sb-build (push) Has been cancelled
CI Front / front-build (push) Has been cancelled
CI Create App E2E minimal / ci-create-app-e2e-minimal-status-check (push) Has been cancelled
CI E2E Main / ci-e2e-main-status-check (push) Has been cancelled
CI E2E Main / notify-main-ci-failure (push) Has been cancelled
CI E2E Main / qa-scout-comment (push) Has been cancelled
CI Front / front-sb-test (push) Has been cancelled
CI Front / front-sb-screenshots (push) Has been cancelled
CI Front / ci-front-status-check (push) Has been cancelled
DPA Sub-Processor Sync / sync-subprocessors (push) Failing after 3s
AI Catalog Sync / sync-catalog (push) Failing after 3s

This commit is contained in:
upstream-mirror
2026-09-17 23:28:13 +05:00
commit e7da97194a
32688 changed files with 4208681 additions and 0 deletions

View File

@@ -0,0 +1,25 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`signUpInWorkspace into a non-active workspace (integration) rejects a brand-new user joining a suspended workspace with the workspace-readiness message 1`] = `
{
"extensions": {
"code": "FORBIDDEN",
"subCode": "FORBIDDEN_EXCEPTION",
"userFriendlyMessage": "Workspace is not ready to welcome new members",
},
"message": "Workspace is not ready to welcome new members",
"name": "ForbiddenError",
}
`;
exports[`signUpInWorkspace into a non-active workspace (integration) rejects an existing user joining a suspended workspace with the workspace-readiness message 1`] = `
{
"extensions": {
"code": "FORBIDDEN",
"subCode": "FORBIDDEN_EXCEPTION",
"userFriendlyMessage": "Workspace is not ready to welcome new members",
},
"message": "Workspace is not ready to welcome new members",
"name": "ForbiddenError",
}
`;

View File

@@ -0,0 +1,13 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`signUpInWorkspace with an expired personal invitation (integration) denies access when the personal invitation is expired 1`] = `
{
"extensions": {
"code": "FORBIDDEN",
"subCode": "FORBIDDEN_EXCEPTION",
"userFriendlyMessage": "User does not have access to this workspace",
},
"message": "User does not have access to this workspace",
"name": "ForbiddenError",
}
`;

View File

@@ -0,0 +1,36 @@
// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing
exports[`Successful User Sign Up (integration) should fail to sign up with duplicate email 1`] = `
{
"extensions": {
"code": "FORBIDDEN",
"subCode": "USER_ALREADY_EXISTS",
"userFriendlyMessage": "User already exists",
},
"message": "User already exists",
"name": "ForbiddenError",
}
`;
exports[`Successful User Sign Up (integration) should fail to sign up with invalid email 1`] = `
{
"extensions": {
"code": "BAD_USER_INPUT",
"userFriendlyMessage": "An error occurred.",
},
"message": "email must be an email",
"name": "UserInputError",
}
`;
exports[`Successful User Sign Up (integration) should fail to sign up with weak password 1`] = `
{
"extensions": {
"code": "BAD_USER_INPUT",
"subCode": "INVALID_INPUT",
"userFriendlyMessage": "Password too weak",
},
"message": "Password too weak",
"name": "UserInputError",
}
`;

View File

@@ -0,0 +1,53 @@
// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing
exports[`Successful User Sign Up (integration) should sign up, delete and signup same new user successfully 1`] = `
{
"canAccessFullAdminPanel": false,
"canImpersonate": false,
"createdAt": Any<String>,
"currentUserWorkspace": null,
"currentWorkspace": null,
"deletedAt": null,
"disabled": false,
"email": "test-123@example.com",
"firstName": "",
"id": Any<String>,
"isEmailVerified": false,
"lastName": "",
"locale": "en",
"updatedAt": Any<String>,
}
`;
exports[`Successful User Sign Up (integration) should sign up, delete and signup same new user successfully 2`] = `
{
"extensions": {
"code": "UNAUTHENTICATED",
"subCode": "USER_NOT_FOUND",
"userFriendlyMessage": {
"id": Any<String>,
"message": "User not found.",
},
},
"message": "User not found",
}
`;
exports[`Successful User Sign Up (integration) should sign up, delete and signup same new user successfully 3`] = `
{
"canAccessFullAdminPanel": false,
"canImpersonate": false,
"createdAt": Any<String>,
"currentUserWorkspace": null,
"currentWorkspace": null,
"deletedAt": null,
"disabled": false,
"email": "test-123@example.com",
"firstName": "",
"id": Any<String>,
"isEmailVerified": false,
"lastName": "",
"locale": "en",
"updatedAt": Any<String>,
}
`;

View File

@@ -0,0 +1,59 @@
import request from 'supertest';
import { expectOneNotInternalServerErrorSnapshot } from 'test/integration/graphql/utils/expect-one-not-internal-server-error-snapshot.util';
import { signUpOperationFactory } from 'test/integration/graphql/utils/sign-up-operation-factory.util';
import { signUp } from 'test/integration/graphql/utils/sign-up.util';
import { WorkspaceActivationStatus } from 'twenty-shared/workspace';
import { SEED_APPLE_WORKSPACE_ID } from 'src/engine/workspace-manager/dev-seeder/core/constants/seeder-workspaces.constant';
const client = request(`http://localhost:${APP_PORT}`);
describe('signUpInWorkspace into a non-active workspace (integration)', () => {
const existingUserEmail = `existing-non-active-${Date.now()}@example.com`;
const password = 'Test123!@#';
beforeAll(async () => {
await signUp({
input: { email: existingUserEmail, password },
expectToFail: false,
});
await testDataSource.query(
'UPDATE core.workspace SET "activationStatus" = $1 WHERE id = $2',
[WorkspaceActivationStatus.SUSPENDED, SEED_APPLE_WORKSPACE_ID],
);
});
afterAll(async () => {
await testDataSource.query(
'UPDATE core.workspace SET "activationStatus" = $1 WHERE id = $2',
[WorkspaceActivationStatus.ACTIVE, SEED_APPLE_WORKSPACE_ID],
);
await testDataSource.query('DELETE FROM core."user" WHERE email = $1', [
existingUserEmail,
]);
});
it('rejects an existing user joining a suspended workspace with the workspace-readiness message', async () => {
const response = await client.post('/metadata').send(
signUpOperationFactory({
email: existingUserEmail,
password,
}),
);
expectOneNotInternalServerErrorSnapshot({ errors: response.body.errors });
});
it('rejects a brand-new user joining a suspended workspace with the workspace-readiness message', async () => {
const response = await client.post('/metadata').send(
signUpOperationFactory({
email: `new-non-active-${Date.now()}@example.com`,
password,
}),
);
expectOneNotInternalServerErrorSnapshot({ errors: response.body.errors });
});
});

View File

@@ -0,0 +1,40 @@
import { expectOneNotInternalServerErrorSnapshot } from 'test/integration/graphql/utils/expect-one-not-internal-server-error-snapshot.util';
import {
deleteWorkspaceInvitationsByEmail,
seedWorkspaceInvitation,
} from 'test/integration/graphql/utils/seed-workspace-invitation.util';
import { signUpInWorkspaceOperationFactory } from 'test/integration/graphql/utils/sign-up-in-workspace-operation-factory.util';
import { makeMetadataAPIRequest } from 'test/integration/metadata/suites/utils/make-metadata-api-request.util';
import { SEED_APPLE_WORKSPACE_ID } from 'src/engine/workspace-manager/dev-seeder/core/constants/seeder-workspaces.constant';
const ONE_HOUR_IN_MS = 60 * 60 * 1000;
describe('signUpInWorkspace with an expired personal invitation (integration)', () => {
const email = `expired-invite-signup-${Date.now()}@example.com`;
const token = `expired-invite-signup-token-${Date.now()}`;
beforeAll(() =>
seedWorkspaceInvitation({
email,
value: token,
expiresAt: new Date(Date.now() - ONE_HOUR_IN_MS),
}),
);
afterAll(() => deleteWorkspaceInvitationsByEmail({ email }));
it('denies access when the personal invitation is expired', async () => {
const response = await makeMetadataAPIRequest(
signUpInWorkspaceOperationFactory({
email,
workspaceId: SEED_APPLE_WORKSPACE_ID,
workspacePersonalInviteToken: token,
}),
undefined,
);
expect(response.body.data?.signUpInWorkspace).toBeFalsy();
expectOneNotInternalServerErrorSnapshot({ errors: response.body.errors });
});
});

View File

@@ -0,0 +1,60 @@
import { expectOneNotInternalServerErrorSnapshot } from 'test/integration/graphql/utils/expect-one-not-internal-server-error-snapshot.util';
import { signUp } from 'test/integration/graphql/utils/sign-up.util';
describe('Successful User Sign Up (integration)', () => {
it('should fail to sign up with invalid email', async () => {
const { errors } = await signUp({
input: {
email: 'invalid-email',
password: 'Test123!@#',
},
expectToFail: true,
});
expectOneNotInternalServerErrorSnapshot({
errors,
});
});
it('should fail to sign up with duplicate email', async () => {
const testEmail = `test-duplicate@example.com`;
const { data: firstSignUp } = await signUp({
input: {
email: testEmail,
password: 'Test123!@#',
},
expectToFail: false,
});
expect(
firstSignUp.signUp.tokens.accessOrWorkspaceAgnosticToken.token,
).toBeDefined();
const { errors } = await signUp({
input: {
email: testEmail,
password: 'AnotherPassword123!',
},
expectToFail: true,
});
expectOneNotInternalServerErrorSnapshot({
errors,
});
});
it('should fail to sign up with weak password', async () => {
const { errors } = await signUp({
input: {
email: `test-123@example.com`,
password: '123',
},
expectToFail: true,
});
expectOneNotInternalServerErrorSnapshot({
errors,
});
});
});

View File

@@ -0,0 +1,38 @@
import { randomUUID } from 'crypto';
import { deleteUser } from 'test/integration/graphql/utils/delete-user.util';
import { getOnboardingStatus } from 'test/integration/graphql/utils/get-onboarding-status.util';
import { signUpInWorkspaceAndGetAccessToken } from 'test/integration/graphql/utils/sign-up-in-workspace-and-get-access-token.util';
import { isDefined } from 'twenty-shared/utils';
import { OnboardingStatus } from 'src/engine/core-modules/onboarding/enums/onboarding-status.enum';
describe('Onboarding status when signing up in an existing workspace (integration)', () => {
let createdUserAccessToken: string | undefined;
afterEach(async () => {
if (isDefined(createdUserAccessToken)) {
await deleteUser({
accessToken: createdUserAccessToken,
expectToFail: false,
});
createdUserAccessToken = undefined;
}
});
it('should start with the connect-account step for a new user joining through an invite', async () => {
createdUserAccessToken = await signUpInWorkspaceAndGetAccessToken(
`invited-onboarding-status-${randomUUID()}@example.com`,
);
const {
data: { currentUser },
} = await getOnboardingStatus({
accessToken: createdUserAccessToken,
expectToFail: false,
});
expect(currentUser.onboardingStatus).toBe(OnboardingStatus.SYNC_EMAIL);
});
});

View File

@@ -0,0 +1,72 @@
import { deleteUser } from 'test/integration/graphql/utils/delete-user.util';
import { getAuthTokensFromLoginToken } from 'test/integration/graphql/utils/get-auth-tokens-from-login-token.util';
import {
deleteWorkspaceInvitationsByEmail,
seedWorkspaceInvitation,
} from 'test/integration/graphql/utils/seed-workspace-invitation.util';
import { signUpInWorkspaceOperationFactory } from 'test/integration/graphql/utils/sign-up-in-workspace-operation-factory.util';
import { makeMetadataAPIRequest } from 'test/integration/metadata/suites/utils/make-metadata-api-request.util';
import { SEED_APPLE_WORKSPACE_ID } from 'src/engine/workspace-manager/dev-seeder/core/constants/seeder-workspaces.constant';
const ONE_HOUR_IN_MS = 60 * 60 * 1000;
describe('signUpInWorkspace with a valid personal invitation (integration)', () => {
const email = `valid-invite-signup-${Date.now()}@example.com`;
const token = `valid-invite-signup-token-${Date.now()}`;
let accessToken: string | undefined;
beforeAll(() =>
seedWorkspaceInvitation({
email,
value: token,
expiresAt: new Date(Date.now() + ONE_HOUR_IN_MS),
}),
);
afterAll(async () => {
if (accessToken) {
await deleteUser({ accessToken, expectToFail: false });
}
await deleteWorkspaceInvitationsByEmail({ email });
});
it('grants access when the personal invitation is still valid', async () => {
const response = await makeMetadataAPIRequest(
signUpInWorkspaceOperationFactory({
email,
workspaceId: SEED_APPLE_WORKSPACE_ID,
workspacePersonalInviteToken: token,
}),
undefined,
);
expect(response.body.errors).toBeUndefined();
const signUpPayload = response.body.data.signUpInWorkspace;
expect(signUpPayload.workspace.id).toBe(SEED_APPLE_WORKSPACE_ID);
expect(signUpPayload.loginToken.token).toBeDefined();
await testDataSource.query(
'UPDATE core."user" SET "isEmailVerified" = true WHERE email = $1',
[email],
);
const {
data: { getAuthTokensFromLoginToken: authTokensData },
} = await getAuthTokensFromLoginToken({
loginToken: signUpPayload.loginToken.token,
origin:
signUpPayload.workspace.workspaceUrls?.subdomainUrl ??
'http://localhost:3001',
expectToFail: false,
});
accessToken = authTokensData.tokens.accessOrWorkspaceAgnosticToken.token;
expect(accessToken).toBeDefined();
});
});

View File

@@ -0,0 +1,95 @@
import { deleteUser } from 'test/integration/graphql/utils/delete-user.util';
import { expectOneNotInternalServerErrorSnapshot } from 'test/integration/graphql/utils/expect-one-not-internal-server-error-snapshot.util';
import { getCurrentUser } from 'test/integration/graphql/utils/get-current-user.util';
import { signUp } from 'test/integration/graphql/utils/sign-up.util';
import { extractRecordIdsAndDatesAsExpectAny } from 'test/utils/extract-record-ids-and-dates-as-expect-any';
import { isDefined } from 'twenty-shared/utils';
import { type SignUpInput } from 'src/engine/core-modules/auth/dto/sign-up.input';
describe('Successful User Sign Up (integration)', () => {
let createdUserAccessToken: string | undefined;
afterEach(async () => {
if (isDefined(createdUserAccessToken)) {
await deleteUser({
accessToken: createdUserAccessToken,
expectToFail: false,
});
createdUserAccessToken = undefined;
}
});
it('should sign up, delete and signup same new user successfully', async () => {
const input: SignUpInput = {
email: `test-123@example.com`,
password: 'Test123!@#',
};
const { data: firstSignUpData } = await signUp({
input,
expectToFail: false,
});
createdUserAccessToken =
firstSignUpData.signUp.tokens.accessOrWorkspaceAgnosticToken.token;
expect(
firstSignUpData.signUp.tokens.accessOrWorkspaceAgnosticToken.token,
).toBeDefined();
expect(firstSignUpData.signUp.tokens.refreshToken.token).toBeDefined();
expect(
firstSignUpData.signUp.availableWorkspaces.availableWorkspacesForSignIn,
).toEqual([]);
expect(
firstSignUpData.signUp.availableWorkspaces.availableWorkspacesForSignUp,
).toEqual([]);
const {
data: { currentUser: currentUserAfterSignUp },
} = await getCurrentUser({
accessToken: createdUserAccessToken,
expectToFail: false,
});
expect(currentUserAfterSignUp.deletedAt).toBeNull();
expect(currentUserAfterSignUp).toMatchSnapshot(
extractRecordIdsAndDatesAsExpectAny({ ...currentUserAfterSignUp }),
);
await deleteUser({
accessToken: createdUserAccessToken,
expectToFail: false,
});
const { errors: getCurrentUserAfterDeleteErrors } = await getCurrentUser({
accessToken: createdUserAccessToken,
expectToFail: true,
});
expectOneNotInternalServerErrorSnapshot({
errors: getCurrentUserAfterDeleteErrors,
});
const { data: secondSignUpData } = await signUp({
input,
expectToFail: false,
});
createdUserAccessToken =
secondSignUpData.signUp.tokens.accessOrWorkspaceAgnosticToken.token;
const {
data: { currentUser: currentUserAfterSecondSignUp },
} = await getCurrentUser({
accessToken: createdUserAccessToken,
expectToFail: false,
});
expect(currentUserAfterSecondSignUp.deletedAt).toBeNull();
expect(currentUserAfterSecondSignUp).toMatchSnapshot(
extractRecordIdsAndDatesAsExpectAny({ ...currentUserAfterSecondSignUp }),
);
});
});