diff --git a/.github/workflows/actions/nx-affected/action.yaml b/.github/workflows/actions/nx-affected/action.yaml index 7c2cdcfe7..c87a8a1e3 100644 --- a/.github/workflows/actions/nx-affected/action.yaml +++ b/.github/workflows/actions/nx-affected/action.yaml @@ -7,6 +7,9 @@ inputs: required: false tasks: required: true + configuration: + required: false + default: 'ci' runs: using: "composite" @@ -15,4 +18,4 @@ runs: uses: nrwl/nx-set-shas@v4 - name: Run affected command shell: bash - run: npx nx affected --nxBail --configuration=ci -t=${{ inputs.tasks }} --parallel=${{ inputs.parallel }} --exclude='*,!tag:${{ inputs.tag }}' \ No newline at end of file + run: npx nx affected --nxBail --configuration=${{ inputs.configuration }} -t=${{ inputs.tasks }} --parallel=${{ inputs.parallel }} --exclude='*,!tag:${{ inputs.tag }}' \ No newline at end of file diff --git a/.github/workflows/ci-server.yaml b/.github/workflows/ci-server.yaml index bc282fb55..2cc724eb1 100644 --- a/.github/workflows/ci-server.yaml +++ b/.github/workflows/ci-server.yaml @@ -170,6 +170,7 @@ jobs: - 6379:6379 env: NX_REJECT_UNKNOWN_LOCAL_CACHE: 0 + NODE_ENV: test steps: - name: Fetch custom Github Actions and base branch history uses: actions/checkout@v4 @@ -183,6 +184,7 @@ jobs: echo "BILLING_STRIPE_API_KEY=test-api-key" >> .env.test echo "BILLING_STRIPE_BASE_PLAN_PRODUCT_ID=test-base-plan-product-id" >> .env.test echo "BILLING_STRIPE_WEBHOOK_SECRET=test-webhook-secret" >> .env.test + echo "BILLING_PLAN_REQUIRED_LINK=http://localhost:3001/stripe-redirection" >> .env.test - name: Restore server setup uses: ./.github/workflows/actions/restore-cache with: @@ -194,15 +196,14 @@ jobs: npx nx build twenty-shared npx nx build twenty-emails - name: Server / Create Test DB - env: - NODE_ENV: test run: | PGPASSWORD=postgres psql -h localhost -p 5432 -U postgres -d postgres -c 'CREATE DATABASE "test";' - name: Server / Run Integration Tests uses: ./.github/workflows/actions/nx-affected with: tag: scope:backend - tasks: 'test:integration:with-db-reset' + tasks: 'test:integration' + configuration: 'with-db-reset' - name: Server / Upload reset-logs file if: always() uses: actions/upload-artifact@v4 diff --git a/packages/twenty-server/.env.test b/packages/twenty-server/.env.test index d78464a75..c5f81ad3e 100644 --- a/packages/twenty-server/.env.test +++ b/packages/twenty-server/.env.test @@ -7,6 +7,8 @@ EXCEPTION_HANDLER_DRIVER=console SENTRY_DSN=https://ba869cb8fd72d5faeb6643560939cee0@o4505516959793152.ingest.sentry.io/4506660900306944 MUTATION_MAXIMUM_RECORD_AFFECTED=100 +FRONTEND_URL=http://localhost:3001 + AUTH_GOOGLE_ENABLED=false MESSAGING_PROVIDER_GMAIL_ENABLED=false CALENDAR_PROVIDER_GOOGLE_ENABLED=false diff --git a/packages/twenty-server/jest-integration.config.ts b/packages/twenty-server/jest-integration.config.ts index deab56040..6528137b0 100644 --- a/packages/twenty-server/jest-integration.config.ts +++ b/packages/twenty-server/jest-integration.config.ts @@ -1,6 +1,9 @@ import { JestConfigWithTsJest, pathsToModuleNameMapper } from 'ts-jest'; +import { NodeEnvironment } from 'src/engine/core-modules/environment/interfaces/node-environment.interface'; + const isBillingEnabled = process.env.IS_BILLING_ENABLED === 'true'; + // eslint-disable-next-line @typescript-eslint/no-var-requires const tsConfig = require('./tsconfig.json'); @@ -14,12 +17,12 @@ const jestConfig: JestConfigWithTsJest = { rootDir: '.', testEnvironment: 'node', testRegex: isBillingEnabled - ? 'integration-spec.ts' + ? '\\.integration-spec\\.ts$' : '^(?!.*billing).*\\.integration-spec\\.ts$', modulePathIgnorePatterns: ['/dist'], globalSetup: '/test/integration/utils/setup-test.ts', globalTeardown: '/test/integration/utils/teardown-test.ts', - testTimeout: 15000, + testTimeout: 20000, maxWorkers: 1, transform: { '^.+\\.(t|j)s$': [ @@ -61,6 +64,7 @@ const jestConfig: JestConfigWithTsJest = { }, globals: { APP_PORT: 4000, + NODE_ENV: NodeEnvironment.test, ADMIN_ACCESS_TOKEN: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIyMDIwMjAyMC05ZTNiLTQ2ZDQtYTU1Ni04OGI5ZGRjMmIwMzQiLCJ3b3Jrc3BhY2VJZCI6IjIwMjAyMDIwLTFjMjUtNGQwMi1iZjI1LTZhZWNjZjdlYTQxOSIsIndvcmtzcGFjZU1lbWJlcklkIjoiMjAyMDIwMjAtMDY4Ny00YzQxLWI3MDctZWQxYmZjYTk3MmE3IiwidXNlcldvcmtzcGFjZUlkIjoiMjAyMDIwMjAtOWUzYi00NmQ0LWE1NTYtODhiOWRkYzJiMDM1IiwiaWF0IjoxNzM5NTQ3NjYxLCJleHAiOjMzMjk3MTQ3NjYxfQ.fbOM9yhr3jWDicPZ1n771usUURiPGmNdeFApsgrbxOw', EXPIRED_ACCESS_TOKEN: diff --git a/packages/twenty-server/src/database/commands/data-seed-dev-workspace.command.ts b/packages/twenty-server/src/database/commands/data-seed-dev-workspace.command.ts index b67264efe..5ea2ae50d 100644 --- a/packages/twenty-server/src/database/commands/data-seed-dev-workspace.command.ts +++ b/packages/twenty-server/src/database/commands/data-seed-dev-workspace.command.ts @@ -32,6 +32,7 @@ import { TypeORMService } from 'src/database/typeorm/typeorm.service'; import { InjectCacheStorage } from 'src/engine/core-modules/cache-storage/decorators/cache-storage.decorator'; import { CacheStorageService } from 'src/engine/core-modules/cache-storage/services/cache-storage.service'; import { CacheStorageNamespace } from 'src/engine/core-modules/cache-storage/types/cache-storage-namespace.enum'; +import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; import { DataSourceEntity } from 'src/engine/metadata-modules/data-source/data-source.entity'; import { DataSourceService } from 'src/engine/metadata-modules/data-source/data-source.service'; import { FieldMetadataService } from 'src/engine/metadata-modules/field-metadata/field-metadata.service'; @@ -67,6 +68,7 @@ export class DataSeedWorkspaceCommand extends CommandRunner { private readonly workspaceSchemaCache: CacheStorageService, private readonly seederService: SeederService, private readonly workspaceManagerService: WorkspaceManagerService, + private readonly environmentService: EnvironmentService, ) { super(); } @@ -92,7 +94,9 @@ export class DataSeedWorkspaceCommand extends CommandRunner { await rawDataSource.initialize(); - await seedCoreSchema(rawDataSource, workspaceId); + const isBillingEnabled = this.environmentService.get('IS_BILLING_ENABLED'); + + await seedCoreSchema(rawDataSource, workspaceId, isBillingEnabled); await rawDataSource.destroy(); diff --git a/packages/twenty-server/src/database/typeorm-seeds/core/billing/billing-subscription.ts b/packages/twenty-server/src/database/typeorm-seeds/core/billing/billing-subscription.ts new file mode 100644 index 000000000..886d553c8 --- /dev/null +++ b/packages/twenty-server/src/database/typeorm-seeds/core/billing/billing-subscription.ts @@ -0,0 +1,33 @@ +import { DataSource } from 'typeorm'; + +const tableName = 'billingSubscription'; + +export const seedBillingSubscriptions = async ( + workspaceDataSource: DataSource, + schemaName: string, + workspaceId: string, +) => { + await workspaceDataSource + .createQueryBuilder() + .insert() + .into(`${schemaName}.${tableName}`, [ + 'workspaceId', + 'stripeCustomerId', + 'stripeSubscriptionId', + 'status', + 'metadata', + ]) + .orIgnore() + .values([ + { + workspaceId, + stripeCustomerId: 'cus_default0', + stripeSubscriptionId: 'sub_default0', + status: 'active', + metadata: { + workspaceId, + }, + }, + ]) + .execute(); +}; diff --git a/packages/twenty-server/src/database/typeorm-seeds/core/index.ts b/packages/twenty-server/src/database/typeorm-seeds/core/index.ts index 0762b050a..1aae1bb17 100644 --- a/packages/twenty-server/src/database/typeorm-seeds/core/index.ts +++ b/packages/twenty-server/src/database/typeorm-seeds/core/index.ts @@ -1,5 +1,6 @@ import { DataSource } from 'typeorm'; +import { seedBillingSubscriptions } from 'src/database/typeorm-seeds/core/billing/billing-subscription'; import { seedFeatureFlags } from 'src/database/typeorm-seeds/core/feature-flags'; import { seedUserWorkspaces } from 'src/database/typeorm-seeds/core/user-workspaces'; import { seedUsers } from 'src/database/typeorm-seeds/core/users'; @@ -8,6 +9,7 @@ import { seedWorkspaces } from 'src/database/typeorm-seeds/core/workspaces'; export const seedCoreSchema = async ( workspaceDataSource: DataSource, workspaceId: string, + isBillingEnabled: boolean, ) => { const schemaName = 'core'; @@ -15,4 +17,12 @@ export const seedCoreSchema = async ( await seedUsers(workspaceDataSource, schemaName); await seedUserWorkspaces(workspaceDataSource, schemaName, workspaceId); await seedFeatureFlags(workspaceDataSource, schemaName, workspaceId); + + if (isBillingEnabled) { + await seedBillingSubscriptions( + workspaceDataSource, + schemaName, + workspaceId, + ); + } }; diff --git a/packages/twenty-server/src/engine/api/graphql/graphql-query-runner/errors/graphql-query-runner.exception.ts b/packages/twenty-server/src/engine/api/graphql/graphql-query-runner/errors/graphql-query-runner.exception.ts index 9a956a282..5e7f0d2ac 100644 --- a/packages/twenty-server/src/engine/api/graphql/graphql-query-runner/errors/graphql-query-runner.exception.ts +++ b/packages/twenty-server/src/engine/api/graphql/graphql-query-runner/errors/graphql-query-runner.exception.ts @@ -22,4 +22,5 @@ export enum GraphqlQueryRunnerExceptionCode { METADATA_CACHE_FEATURE_FLAG_RECOMPUTATION_REQUIRED = 'METADATA_CACHE_FEATURE_FLAG_RECOMPUTATION_REQUIRED', RELATION_SETTINGS_NOT_FOUND = 'RELATION_SETTINGS_NOT_FOUND', RELATION_TARGET_OBJECT_METADATA_NOT_FOUND = 'RELATION_TARGET_OBJECT_METADATA_NOT_FOUND', + NOT_IMPLEMENTED = 'NOT_IMPLEMENTED', } diff --git a/packages/twenty-server/src/engine/api/graphql/workspace-query-runner/utils/graphql-query-runner-exception-handler.util.ts b/packages/twenty-server/src/engine/api/graphql/workspace-query-runner/utils/graphql-query-runner-exception-handler.util.ts index 773f61ff7..8a2799084 100644 --- a/packages/twenty-server/src/engine/api/graphql/workspace-query-runner/utils/graphql-query-runner-exception-handler.util.ts +++ b/packages/twenty-server/src/engine/api/graphql/workspace-query-runner/utils/graphql-query-runner-exception-handler.util.ts @@ -22,6 +22,7 @@ export const graphqlQueryRunnerExceptionHandler = ( case GraphqlQueryRunnerExceptionCode.ARGS_CONFLICT: case GraphqlQueryRunnerExceptionCode.FIELD_NOT_FOUND: case GraphqlQueryRunnerExceptionCode.INVALID_QUERY_INPUT: + case GraphqlQueryRunnerExceptionCode.NOT_IMPLEMENTED: throw new UserInputError(error.message); case GraphqlQueryRunnerExceptionCode.RECORD_NOT_FOUND: throw new NotFoundError(error.message); diff --git a/packages/twenty-server/src/engine/core-modules/admin-panel/__tests__/admin-panel.service.spec.ts b/packages/twenty-server/src/engine/core-modules/admin-panel/__tests__/admin-panel.service.spec.ts index 15bb17f22..00a723cec 100644 --- a/packages/twenty-server/src/engine/core-modules/admin-panel/__tests__/admin-panel.service.spec.ts +++ b/packages/twenty-server/src/engine/core-modules/admin-panel/__tests__/admin-panel.service.spec.ts @@ -9,29 +9,12 @@ import { import { LoginTokenService } from 'src/engine/core-modules/auth/token/services/login-token.service'; import { DomainManagerService } from 'src/engine/core-modules/domain-manager/services/domain-manager.service'; import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; -import { FeatureFlagKey } from 'src/engine/core-modules/feature-flag/enums/feature-flag-key.enum'; -import { FeatureFlag } from 'src/engine/core-modules/feature-flag/feature-flag.entity'; import { User } from 'src/engine/core-modules/user/user.entity'; -import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity'; const UserFindOneMock = jest.fn(); -const WorkspaceFindOneMock = jest.fn(); -const FeatureFlagUpdateMock = jest.fn(); -const FeatureFlagSaveMock = jest.fn(); const LoginTokenServiceGenerateLoginTokenMock = jest.fn(); const EnvironmentServiceGetAllMock = jest.fn(); -jest.mock( - 'src/engine/core-modules/feature-flag/enums/feature-flag-key.enum', - () => { - return { - FeatureFlagKey: { - IsFlagEnabled: 'IS_FLAG_ENABLED', - }, - }; - }, -); - jest.mock( '../../environment/constants/environment-variables-group-metadata', () => ({ @@ -62,25 +45,12 @@ describe('AdminPanelService', () => { const module: TestingModule = await Test.createTestingModule({ providers: [ AdminPanelService, - { - provide: getRepositoryToken(Workspace, 'core'), - useValue: { - findOne: WorkspaceFindOneMock, - }, - }, { provide: getRepositoryToken(User, 'core'), useValue: { findOne: UserFindOneMock, }, }, - { - provide: getRepositoryToken(FeatureFlag, 'core'), - useValue: { - update: FeatureFlagUpdateMock, - save: FeatureFlagSaveMock, - }, - }, { provide: LoginTokenService, useValue: { @@ -112,80 +82,6 @@ describe('AdminPanelService', () => { expect(service).toBeDefined(); }); - it('should update an existing feature flag if it exists', async () => { - const workspaceId = 'workspace-id'; - const featureFlag = 'IsFlagEnabled' as FeatureFlagKey; - const value = true; - const existingFlag = { - id: 'flag-id', - key: 'IS_FLAG_ENABLED', - value: false, - }; - - WorkspaceFindOneMock.mockReturnValueOnce({ - id: workspaceId, - featureFlags: [existingFlag], - }); - - await service.updateWorkspaceFeatureFlags(workspaceId, featureFlag, value); - - expect(FeatureFlagUpdateMock).toHaveBeenCalledWith(existingFlag.id, { - value, - }); - expect(FeatureFlagSaveMock).not.toHaveBeenCalled(); - }); - - it('should create a new feature flag if it does not exist', async () => { - const workspaceId = 'workspace-id'; - const featureFlag = 'IsFlagEnabled' as FeatureFlagKey; - const value = true; - - WorkspaceFindOneMock.mockReturnValueOnce({ - id: workspaceId, - featureFlags: [], - }); - - await service.updateWorkspaceFeatureFlags(workspaceId, featureFlag, value); - - expect(FeatureFlagSaveMock).toHaveBeenCalledWith({ - key: 'IS_FLAG_ENABLED', - value, - workspaceId, - }); - expect(FeatureFlagUpdateMock).not.toHaveBeenCalled(); - }); - - it('should throw an exception if the workspace is not found', async () => { - const workspaceId = 'non-existent-workspace'; - const featureFlag = 'IsFlagEnabled' as FeatureFlagKey; - const value = true; - - WorkspaceFindOneMock.mockReturnValueOnce(null); - - await expect( - service.updateWorkspaceFeatureFlags(workspaceId, featureFlag, value), - ).rejects.toThrowError( - new AuthException('Workspace not found', AuthExceptionCode.INVALID_INPUT), - ); - }); - - it('should throw an exception if the flag is not found', async () => { - const workspaceId = 'non-existent-workspace'; - const featureFlag = 'IsUnknownFlagEnabled' as FeatureFlagKey; - const value = true; - - WorkspaceFindOneMock.mockReturnValueOnce(null); - - await expect( - service.updateWorkspaceFeatureFlags(workspaceId, featureFlag, value), - ).rejects.toThrowError( - new AuthException( - 'Invalid feature flag key', - AuthExceptionCode.INVALID_INPUT, - ), - ); - }); - it('should impersonate a user and return workspace and loginToken on success', async () => { const mockUser = { id: 'user-id', diff --git a/packages/twenty-server/src/engine/core-modules/admin-panel/admin-panel.module.ts b/packages/twenty-server/src/engine/core-modules/admin-panel/admin-panel.module.ts index 6defbcb60..afdc157ff 100644 --- a/packages/twenty-server/src/engine/core-modules/admin-panel/admin-panel.module.ts +++ b/packages/twenty-server/src/engine/core-modules/admin-panel/admin-panel.module.ts @@ -7,20 +7,20 @@ import { AdminPanelResolver } from 'src/engine/core-modules/admin-panel/admin-pa import { AdminPanelService } from 'src/engine/core-modules/admin-panel/admin-panel.service'; import { AuthModule } from 'src/engine/core-modules/auth/auth.module'; import { DomainManagerModule } from 'src/engine/core-modules/domain-manager/domain-manager.module'; -import { FeatureFlag } from 'src/engine/core-modules/feature-flag/feature-flag.entity'; +import { FeatureFlagModule } from 'src/engine/core-modules/feature-flag/feature-flag.module'; import { HealthModule } from 'src/engine/core-modules/health/health.module'; import { RedisClientModule } from 'src/engine/core-modules/redis-client/redis-client.module'; import { User } from 'src/engine/core-modules/user/user.entity'; -import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity'; @Module({ imports: [ - TypeOrmModule.forFeature([User, Workspace, FeatureFlag], 'core'), + TypeOrmModule.forFeature([User], 'core'), AuthModule, DomainManagerModule, HealthModule, RedisClientModule, TerminusModule, + FeatureFlagModule, ], providers: [AdminPanelResolver, AdminPanelService, AdminPanelHealthService], exports: [AdminPanelService], diff --git a/packages/twenty-server/src/engine/core-modules/admin-panel/admin-panel.resolver.ts b/packages/twenty-server/src/engine/core-modules/admin-panel/admin-panel.resolver.ts index a94a0d90e..fb527300c 100644 --- a/packages/twenty-server/src/engine/core-modules/admin-panel/admin-panel.resolver.ts +++ b/packages/twenty-server/src/engine/core-modules/admin-panel/admin-panel.resolver.ts @@ -12,6 +12,9 @@ import { UserLookup } from 'src/engine/core-modules/admin-panel/dtos/user-lookup import { UserLookupInput } from 'src/engine/core-modules/admin-panel/dtos/user-lookup.input'; import { QueueMetricsTimeRange } from 'src/engine/core-modules/admin-panel/enums/queue-metrics-time-range.enum'; import { AuthGraphqlApiExceptionFilter } from 'src/engine/core-modules/auth/filters/auth-graphql-api-exception.filter'; +import { FeatureFlagException } from 'src/engine/core-modules/feature-flag/feature-flag.exception'; +import { FeatureFlagService } from 'src/engine/core-modules/feature-flag/services/feature-flag.service'; +import { UserInputError } from 'src/engine/core-modules/graphql/utils/graphql-errors.util'; import { HealthIndicatorId } from 'src/engine/core-modules/health/enums/health-indicator-id.enum'; import { WorkerHealthIndicator } from 'src/engine/core-modules/health/indicators/worker.health'; import { MessageQueue } from 'src/engine/core-modules/message-queue/message-queue.constants'; @@ -30,6 +33,7 @@ export class AdminPanelResolver { private adminService: AdminPanelService, private adminPanelHealthService: AdminPanelHealthService, private workerHealthIndicator: WorkerHealthIndicator, + private featureFlagService: FeatureFlagService, ) {} @UseGuards(WorkspaceAuthGuard, UserAuthGuard, ImpersonateGuard) @@ -53,13 +57,21 @@ export class AdminPanelResolver { async updateWorkspaceFeatureFlag( @Args() updateFlagInput: UpdateWorkspaceFeatureFlagInput, ): Promise { - await this.adminService.updateWorkspaceFeatureFlags( - updateFlagInput.workspaceId, - updateFlagInput.featureFlag, - updateFlagInput.value, - ); + try { + await this.featureFlagService.upsertWorkspaceFeatureFlag({ + workspaceId: updateFlagInput.workspaceId, + featureFlag: updateFlagInput.featureFlag, + value: updateFlagInput.value, + }); - return true; + return true; + } catch (error) { + if (error instanceof FeatureFlagException) { + throw new UserInputError(error.message); + } + + throw error; + } } @UseGuards(WorkspaceAuthGuard, UserAuthGuard, AdminPanelGuard) diff --git a/packages/twenty-server/src/engine/core-modules/admin-panel/admin-panel.service.ts b/packages/twenty-server/src/engine/core-modules/admin-panel/admin-panel.service.ts index 01cb52e4f..fd375859a 100644 --- a/packages/twenty-server/src/engine/core-modules/admin-panel/admin-panel.service.ts +++ b/packages/twenty-server/src/engine/core-modules/admin-panel/admin-panel.service.ts @@ -18,15 +18,8 @@ import { EnvironmentVariablesGroup } from 'src/engine/core-modules/environment/e import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; import { FeatureFlagKey } from 'src/engine/core-modules/feature-flag/enums/feature-flag-key.enum'; import { FeatureFlag } from 'src/engine/core-modules/feature-flag/feature-flag.entity'; -import { - FeatureFlagException, - FeatureFlagExceptionCode, -} from 'src/engine/core-modules/feature-flag/feature-flag.exception'; -import { featureFlagValidator } from 'src/engine/core-modules/feature-flag/validates/feature-flag.validate'; import { User } from 'src/engine/core-modules/user/user.entity'; import { userValidator } from 'src/engine/core-modules/user/user.validate'; -import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity'; -import { workspaceValidator } from 'src/engine/core-modules/workspace/workspace.validate'; @Injectable() export class AdminPanelService { @@ -36,10 +29,6 @@ export class AdminPanelService { private readonly domainManagerService: DomainManagerService, @InjectRepository(User, 'core') private readonly userRepository: Repository, - @InjectRepository(Workspace, 'core') - private readonly workspaceRepository: Repository, - @InjectRepository(FeatureFlag, 'core') - private readonly featureFlagRepository: Repository, ) {} async impersonate(userId: string, workspaceId: string) { @@ -131,44 +120,6 @@ export class AdminPanelService { }; } - async updateWorkspaceFeatureFlags( - workspaceId: string, - featureFlag: FeatureFlagKey, - value: boolean, - ) { - featureFlagValidator.assertIsFeatureFlagKey( - featureFlag, - new FeatureFlagException( - 'Invalid feature flag key', - FeatureFlagExceptionCode.INVALID_FEATURE_FLAG_KEY, - ), - ); - - const workspace = await this.workspaceRepository.findOne({ - where: { id: workspaceId }, - relations: ['featureFlags'], - }); - - workspaceValidator.assertIsDefinedOrThrow( - workspace, - new AuthException('Workspace not found', AuthExceptionCode.INVALID_INPUT), - ); - - const existingFlag = workspace.featureFlags?.find( - (flag) => flag.key === FeatureFlagKey[featureFlag], - ); - - if (existingFlag) { - await this.featureFlagRepository.update(existingFlag.id, { value }); - } else { - await this.featureFlagRepository.save({ - key: FeatureFlagKey[featureFlag], - value, - workspaceId: workspace.id, - }); - } - } - getEnvironmentVariablesGrouped(): EnvironmentVariablesOutput { const rawEnvVars = this.environmentService.getAll(); const groupedData = new Map< diff --git a/packages/twenty-server/src/engine/core-modules/domain-manager/services/domain-manager.service.ts b/packages/twenty-server/src/engine/core-modules/domain-manager/services/domain-manager.service.ts index d9c87550b..b28ef7057 100644 --- a/packages/twenty-server/src/engine/core-modules/domain-manager/services/domain-manager.service.ts +++ b/packages/twenty-server/src/engine/core-modules/domain-manager/services/domain-manager.service.ts @@ -1,17 +1,17 @@ import { Injectable, Logger } from '@nestjs/common'; import { InjectRepository } from '@nestjs/typeorm'; -import { Repository } from 'typeorm'; import { isDefined } from 'twenty-shared'; +import { Repository } from 'typeorm'; +import { SEED_APPLE_WORKSPACE_ID } from 'src/database/typeorm-seeds/core/workspaces'; +import { WorkspaceSubdomainCustomDomainAndIsCustomDomainEnabledType } from 'src/engine/core-modules/domain-manager/domain-manager.type'; import { CustomDomainValidRecords } from 'src/engine/core-modules/domain-manager/dtos/custom-domain-valid-records'; import { generateRandomSubdomain } from 'src/engine/core-modules/domain-manager/utils/generate-random-subdomain'; import { getSubdomainFromEmail } from 'src/engine/core-modules/domain-manager/utils/get-subdomain-from-email'; import { getSubdomainNameFromDisplayName } from 'src/engine/core-modules/domain-manager/utils/get-subdomain-name-from-display-name'; import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity'; -import { WorkspaceSubdomainCustomDomainAndIsCustomDomainEnabledType } from 'src/engine/core-modules/domain-manager/domain-manager.type'; -import { SEED_APPLE_WORKSPACE_ID } from 'src/database/typeorm-seeds/core/workspaces'; import { workspaceValidator } from 'src/engine/core-modules/workspace/workspace.validate'; @Injectable() diff --git a/packages/twenty-server/src/engine/core-modules/feature-flag/services/__tests__/feature-flag.service.spec.ts b/packages/twenty-server/src/engine/core-modules/feature-flag/services/__tests__/feature-flag.service.spec.ts new file mode 100644 index 000000000..fdefa21d9 --- /dev/null +++ b/packages/twenty-server/src/engine/core-modules/feature-flag/services/__tests__/feature-flag.service.spec.ts @@ -0,0 +1,268 @@ +import { Test, TestingModule } from '@nestjs/testing'; +import { getRepositoryToken } from '@nestjs/typeorm'; + +import { FeatureFlagKey } from 'src/engine/core-modules/feature-flag/enums/feature-flag-key.enum'; +import { FeatureFlag } from 'src/engine/core-modules/feature-flag/feature-flag.entity'; +import { + FeatureFlagException, + FeatureFlagExceptionCode, +} from 'src/engine/core-modules/feature-flag/feature-flag.exception'; +import { FeatureFlagService } from 'src/engine/core-modules/feature-flag/services/feature-flag.service'; +import { featureFlagValidator } from 'src/engine/core-modules/feature-flag/validates/feature-flag.validate'; +import { publicFeatureFlagValidator } from 'src/engine/core-modules/feature-flag/validates/is-public-feature-flag.validate'; + +jest.mock( + 'src/engine/core-modules/feature-flag/validates/is-public-feature-flag.validate', +); +jest.mock( + 'src/engine/core-modules/feature-flag/validates/feature-flag.validate', +); + +describe('FeatureFlagService', () => { + let service: FeatureFlagService; + + const mockFeatureFlagRepository = { + findOneBy: jest.fn(), + find: jest.fn(), + upsert: jest.fn(), + }; + + const workspaceId = 'workspace-id'; + const featureFlag = FeatureFlagKey.IsWorkflowEnabled; + + beforeEach(async () => { + jest.clearAllMocks(); + + ( + publicFeatureFlagValidator.assertIsPublicFeatureFlag as jest.Mock + ).mockReset(); + (featureFlagValidator.assertIsFeatureFlagKey as jest.Mock).mockReset(); + + const module: TestingModule = await Test.createTestingModule({ + providers: [ + FeatureFlagService, + { + provide: getRepositoryToken(FeatureFlag, 'core'), + useValue: mockFeatureFlagRepository, + }, + ], + }).compile(); + + service = module.get(FeatureFlagService); + }); + + it('should be defined', () => { + expect(service).toBeDefined(); + }); + + describe('isFeatureEnabled', () => { + it('should return true when feature flag is enabled', async () => { + // Prepare + mockFeatureFlagRepository.findOneBy.mockResolvedValue({ + key: featureFlag, + value: true, + workspaceId, + }); + + // Act + const result = await service.isFeatureEnabled(featureFlag, workspaceId); + + // Assert + expect(result).toBe(true); + expect(mockFeatureFlagRepository.findOneBy).toHaveBeenCalledWith({ + workspaceId, + key: featureFlag, + value: true, + }); + }); + + it('should return false when feature flag is not found', async () => { + // Prepare + mockFeatureFlagRepository.findOneBy.mockResolvedValue(null); + + // Act + const result = await service.isFeatureEnabled(featureFlag, workspaceId); + + // Assert + expect(result).toBe(false); + }); + + it('should return false when feature flag value is false', async () => { + // Prepare + mockFeatureFlagRepository.findOneBy.mockResolvedValue({ + key: featureFlag, + value: false, + workspaceId, + }); + + // Act + const result = await service.isFeatureEnabled(featureFlag, workspaceId); + + // Assert + expect(result).toBe(false); + }); + }); + + describe('getWorkspaceFeatureFlags', () => { + it('should return all feature flags for a workspace', async () => { + // Prepare + const mockFeatureFlags = [ + { key: FeatureFlagKey.IsWorkflowEnabled, value: true, workspaceId }, + { key: FeatureFlagKey.IsCopilotEnabled, value: false, workspaceId }, + ]; + + mockFeatureFlagRepository.find.mockResolvedValue(mockFeatureFlags); + + // Act + const result = await service.getWorkspaceFeatureFlags(workspaceId); + + // Assert + expect(result).toEqual(mockFeatureFlags); + expect(mockFeatureFlagRepository.find).toHaveBeenCalledWith({ + where: { workspaceId }, + }); + }); + }); + + describe('getWorkspaceFeatureFlagsMap', () => { + it('should return a map of feature flags for a workspace', async () => { + // Prepare + const mockFeatureFlags = [ + { key: FeatureFlagKey.IsWorkflowEnabled, value: true, workspaceId }, + { key: FeatureFlagKey.IsCopilotEnabled, value: false, workspaceId }, + ]; + + mockFeatureFlagRepository.find.mockResolvedValue(mockFeatureFlags); + + // Act + const result = await service.getWorkspaceFeatureFlagsMap(workspaceId); + + // Assert + expect(result).toEqual({ + [FeatureFlagKey.IsWorkflowEnabled]: true, + [FeatureFlagKey.IsCopilotEnabled]: false, + }); + }); + }); + + describe('enableFeatureFlags', () => { + it('should enable multiple feature flags for a workspace', async () => { + // Prepare + const keys = [ + FeatureFlagKey.IsWorkflowEnabled, + FeatureFlagKey.IsCopilotEnabled, + ]; + + mockFeatureFlagRepository.upsert.mockResolvedValue({}); + + // Act + await service.enableFeatureFlags(keys, workspaceId); + + // Assert + expect(mockFeatureFlagRepository.upsert).toHaveBeenCalledWith( + keys.map((key) => ({ workspaceId, key, value: true })), + { + conflictPaths: ['workspaceId', 'key'], + skipUpdateIfNoValuesChanged: true, + }, + ); + }); + }); + + describe('upsertWorkspaceFeatureFlag', () => { + it('should upsert a feature flag for a workspace', async () => { + // Prepare + const value = true; + const mockFeatureFlag = { + key: featureFlag, + value, + workspaceId, + }; + + mockFeatureFlagRepository.upsert.mockResolvedValue({ + generatedMaps: [mockFeatureFlag], + }); + + ( + featureFlagValidator.assertIsFeatureFlagKey as jest.Mock + ).mockImplementation(() => true); + + // Act + const result = await service.upsertWorkspaceFeatureFlag({ + workspaceId, + featureFlag, + value, + }); + + // Assert + expect(result).toEqual(mockFeatureFlag); + expect(mockFeatureFlagRepository.upsert).toHaveBeenCalledWith( + { + key: FeatureFlagKey[featureFlag], + value, + workspaceId, + }, + { + conflictPaths: ['workspaceId', 'key'], + skipUpdateIfNoValuesChanged: true, + }, + ); + }); + + it('should throw an exception when feature flag key is invalid', async () => { + // Prepare + const invalidFeatureFlag = 'INVALID_KEY' as FeatureFlagKey; + const value = true; + + ( + featureFlagValidator.assertIsFeatureFlagKey as jest.Mock + ).mockImplementation(() => { + throw new FeatureFlagException( + 'Invalid feature flag key', + FeatureFlagExceptionCode.INVALID_FEATURE_FLAG_KEY, + ); + }); + + // Act & Assert + await expect( + service.upsertWorkspaceFeatureFlag({ + workspaceId, + featureFlag: invalidFeatureFlag, + value, + }), + ).rejects.toThrow( + new FeatureFlagException( + 'Invalid feature flag key', + FeatureFlagExceptionCode.INVALID_FEATURE_FLAG_KEY, + ), + ); + }); + + it('should throw an exception when non-public feature flag is used with shouldBePublic=true', async () => { + // Prepare + ( + publicFeatureFlagValidator.assertIsPublicFeatureFlag as jest.Mock + ).mockImplementation(() => { + throw new FeatureFlagException( + 'Invalid feature flag key, flag is not public', + FeatureFlagExceptionCode.INVALID_FEATURE_FLAG_KEY, + ); + }); + + // Act & Assert + await expect( + service.upsertWorkspaceFeatureFlag({ + workspaceId, + featureFlag, + value: true, + shouldBePublic: true, + }), + ).rejects.toThrow( + new FeatureFlagException( + 'Invalid feature flag key, flag is not public', + FeatureFlagExceptionCode.INVALID_FEATURE_FLAG_KEY, + ), + ); + }); + }); +}); diff --git a/packages/twenty-server/src/engine/core-modules/feature-flag/services/feature-flag.service.ts b/packages/twenty-server/src/engine/core-modules/feature-flag/services/feature-flag.service.ts index 319daa6fe..8225b9e3d 100644 --- a/packages/twenty-server/src/engine/core-modules/feature-flag/services/feature-flag.service.ts +++ b/packages/twenty-server/src/engine/core-modules/feature-flag/services/feature-flag.service.ts @@ -7,6 +7,12 @@ import { FeatureFlagMap } from 'src/engine/core-modules/feature-flag/interfaces/ import { FeatureFlagKey } from 'src/engine/core-modules/feature-flag/enums/feature-flag-key.enum'; import { FeatureFlag } from 'src/engine/core-modules/feature-flag/feature-flag.entity'; +import { + FeatureFlagException, + FeatureFlagExceptionCode, +} from 'src/engine/core-modules/feature-flag/feature-flag.exception'; +import { featureFlagValidator } from 'src/engine/core-modules/feature-flag/validates/feature-flag.validate'; +import { publicFeatureFlagValidator } from 'src/engine/core-modules/feature-flag/validates/is-public-feature-flag.validate'; @Injectable() export class FeatureFlagService { @@ -64,4 +70,48 @@ export class FeatureFlagService { }, ); } + + public async upsertWorkspaceFeatureFlag({ + workspaceId, + featureFlag, + value, + shouldBePublic = false, + }: { + workspaceId: string; + featureFlag: FeatureFlagKey; + value: boolean; + shouldBePublic?: boolean; + }): Promise { + if (shouldBePublic) { + publicFeatureFlagValidator.assertIsPublicFeatureFlag( + featureFlag, + new FeatureFlagException( + 'Invalid feature flag key, flag is not public', + FeatureFlagExceptionCode.INVALID_FEATURE_FLAG_KEY, + ), + ); + } + + featureFlagValidator.assertIsFeatureFlagKey( + featureFlag, + new FeatureFlagException( + 'Invalid feature flag key', + FeatureFlagExceptionCode.INVALID_FEATURE_FLAG_KEY, + ), + ); + + const upsertResult = await this.featureFlagRepository.upsert( + { + key: FeatureFlagKey[featureFlag], + value, + workspaceId: workspaceId, + }, + { + conflictPaths: ['workspaceId', 'key'], + skipUpdateIfNoValuesChanged: true, + }, + ); + + return upsertResult.generatedMaps[0] as FeatureFlag; + } } diff --git a/packages/twenty-server/src/engine/core-modules/lab/lab.module.ts b/packages/twenty-server/src/engine/core-modules/lab/lab.module.ts index ae4fb2fd5..67dea4a5e 100644 --- a/packages/twenty-server/src/engine/core-modules/lab/lab.module.ts +++ b/packages/twenty-server/src/engine/core-modules/lab/lab.module.ts @@ -1,22 +1,13 @@ import { Module } from '@nestjs/common'; -import { TypeOrmModule } from '@nestjs/typeorm'; -import { FeatureFlag } from 'src/engine/core-modules/feature-flag/feature-flag.entity'; import { FeatureFlagModule } from 'src/engine/core-modules/feature-flag/feature-flag.module'; -import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity'; import { PermissionsModule } from 'src/engine/metadata-modules/permissions/permissions.module'; import { LabResolver } from './lab.resolver'; -import { LabService } from './services/lab.service'; - @Module({ - imports: [ - TypeOrmModule.forFeature([FeatureFlag, Workspace], 'core'), - FeatureFlagModule, - PermissionsModule, - ], - providers: [LabService, LabResolver], - exports: [LabService], + imports: [FeatureFlagModule, PermissionsModule], + providers: [LabResolver], + exports: [], }) export class LabModule {} diff --git a/packages/twenty-server/src/engine/core-modules/lab/lab.resolver.ts b/packages/twenty-server/src/engine/core-modules/lab/lab.resolver.ts index d4fd60c0e..a50977253 100644 --- a/packages/twenty-server/src/engine/core-modules/lab/lab.resolver.ts +++ b/packages/twenty-server/src/engine/core-modules/lab/lab.resolver.ts @@ -3,8 +3,10 @@ import { Args, Mutation, Resolver } from '@nestjs/graphql'; import { AuthGraphqlApiExceptionFilter } from 'src/engine/core-modules/auth/filters/auth-graphql-api-exception.filter'; import { FeatureFlag } from 'src/engine/core-modules/feature-flag/feature-flag.entity'; +import { FeatureFlagException } from 'src/engine/core-modules/feature-flag/feature-flag.exception'; +import { FeatureFlagService } from 'src/engine/core-modules/feature-flag/services/feature-flag.service'; +import { UserInputError } from 'src/engine/core-modules/graphql/utils/graphql-errors.util'; import { UpdateLabPublicFeatureFlagInput } from 'src/engine/core-modules/lab/dtos/update-lab-public-feature-flag.input'; -import { LabService } from 'src/engine/core-modules/lab/services/lab.service'; import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity'; import { AuthWorkspace } from 'src/engine/decorators/auth/auth-workspace.decorator'; import { SettingsPermissionsGuard } from 'src/engine/guards/settings-permissions.guard'; @@ -16,7 +18,7 @@ import { PermissionsGraphqlApiExceptionFilter } from 'src/engine/metadata-module @UseFilters(AuthGraphqlApiExceptionFilter, PermissionsGraphqlApiExceptionFilter) @UseGuards(SettingsPermissionsGuard(SettingsPermissions.WORKSPACE)) export class LabResolver { - constructor(private labService: LabService) {} + constructor(private featureFlagService: FeatureFlagService) {} @UseGuards(WorkspaceAuthGuard) @Mutation(() => FeatureFlag) @@ -24,6 +26,18 @@ export class LabResolver { @Args('input') input: UpdateLabPublicFeatureFlagInput, @AuthWorkspace() workspace: Workspace, ): Promise { - return this.labService.updateLabPublicFeatureFlag(workspace.id, input); + try { + return await this.featureFlagService.upsertWorkspaceFeatureFlag({ + workspaceId: workspace.id, + featureFlag: input.publicFeatureFlag, + value: input.value, + shouldBePublic: true, + }); + } catch (error) { + if (error instanceof FeatureFlagException) { + throw new UserInputError(error.message); + } + throw error; + } } } diff --git a/packages/twenty-server/src/engine/core-modules/lab/services/lab.service.ts b/packages/twenty-server/src/engine/core-modules/lab/services/lab.service.ts deleted file mode 100644 index 66e57957c..000000000 --- a/packages/twenty-server/src/engine/core-modules/lab/services/lab.service.ts +++ /dev/null @@ -1,81 +0,0 @@ -import { Injectable } from '@nestjs/common'; -import { InjectRepository } from '@nestjs/typeorm'; - -import { Repository } from 'typeorm'; - -import { - AuthException, - AuthExceptionCode, -} from 'src/engine/core-modules/auth/auth.exception'; -import { FeatureFlagKey } from 'src/engine/core-modules/feature-flag/enums/feature-flag-key.enum'; -import { FeatureFlag } from 'src/engine/core-modules/feature-flag/feature-flag.entity'; -import { - FeatureFlagException, - FeatureFlagExceptionCode, -} from 'src/engine/core-modules/feature-flag/feature-flag.exception'; -import { featureFlagValidator } from 'src/engine/core-modules/feature-flag/validates/feature-flag.validate'; -import { publicFeatureFlagValidator } from 'src/engine/core-modules/feature-flag/validates/is-public-feature-flag.validate'; -import { UpdateLabPublicFeatureFlagInput } from 'src/engine/core-modules/lab/dtos/update-lab-public-feature-flag.input'; -import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity'; -import { workspaceValidator } from 'src/engine/core-modules/workspace/workspace.validate'; - -@Injectable() -export class LabService { - constructor( - @InjectRepository(FeatureFlag, 'core') - private readonly featureFlagRepository: Repository, - @InjectRepository(Workspace, 'core') - private readonly workspaceRepository: Repository, - ) {} - - async updateLabPublicFeatureFlag( - workspaceId: string, - payload: UpdateLabPublicFeatureFlagInput, - ): Promise { - featureFlagValidator.assertIsFeatureFlagKey( - payload.publicFeatureFlag, - new FeatureFlagException( - 'Invalid feature flag key', - FeatureFlagExceptionCode.INVALID_FEATURE_FLAG_KEY, - ), - ); - - publicFeatureFlagValidator.assertIsPublicFeatureFlag( - FeatureFlagKey[payload.publicFeatureFlag], - new FeatureFlagException( - 'Feature flag is not public', - FeatureFlagExceptionCode.FEATURE_FLAG_IS_NOT_PUBLIC, - ), - ); - - const workspace = await this.workspaceRepository.findOne({ - where: { id: workspaceId }, - }); - - workspaceValidator.assertIsDefinedOrThrow( - workspace, - new AuthException('Workspace not found', AuthExceptionCode.INVALID_INPUT), - ); - - const existingFlag = await this.featureFlagRepository.findOne({ - where: { - workspaceId, - key: FeatureFlagKey[payload.publicFeatureFlag], - }, - }); - - if (existingFlag) { - await this.featureFlagRepository.update(existingFlag.id, { - value: payload.value, - }); - - return { ...existingFlag, value: payload.value }; - } - - return this.featureFlagRepository.save({ - key: FeatureFlagKey[payload.publicFeatureFlag], - value: payload.value, - workspaceId, - }); - } -} diff --git a/packages/twenty-server/src/engine/metadata-modules/field-metadata/field-metadata.resolver.ts b/packages/twenty-server/src/engine/metadata-modules/field-metadata/field-metadata.resolver.ts index e242c063b..1d76f5cea 100644 --- a/packages/twenty-server/src/engine/metadata-modules/field-metadata/field-metadata.resolver.ts +++ b/packages/twenty-server/src/engine/metadata-modules/field-metadata/field-metadata.resolver.ts @@ -1,9 +1,4 @@ -import { - BadRequestException, - UnauthorizedException, - UseFilters, - UseGuards, -} from '@nestjs/common'; +import { UnauthorizedException, UseFilters, UseGuards } from '@nestjs/common'; import { Args, Context, @@ -17,6 +12,7 @@ import { FieldMetadataType } from 'twenty-shared'; import { FeatureFlagKey } from 'src/engine/core-modules/feature-flag/enums/feature-flag-key.enum'; import { FeatureFlagService } from 'src/engine/core-modules/feature-flag/services/feature-flag.service'; +import { ValidationError } from 'src/engine/core-modules/graphql/utils/graphql-errors.util'; import { I18nContext } from 'src/engine/core-modules/i18n/types/i18n-context.type'; import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity'; import { IDataloaders } from 'src/engine/dataloaders/dataloader.interface'; @@ -123,19 +119,19 @@ export class FieldMetadataResolver { }); if (!fieldMetadata) { - throw new BadRequestException('Field does not exist'); + throw new ValidationError('Field does not exist'); } if (!fieldMetadata.isCustom) { - throw new BadRequestException("Standard Fields can't be deleted"); + throw new ValidationError("Standard Fields can't be deleted"); } if (fieldMetadata.isActive) { - throw new BadRequestException("Active fields can't be deleted"); + throw new ValidationError("Active fields can't be deleted"); } if (fieldMetadata.type === FieldMetadataType.RELATION) { - throw new BadRequestException( + throw new ValidationError( "Relation fields can't be deleted, you need to delete the RelationMetadata instead", ); } diff --git a/packages/twenty-server/src/engine/metadata-modules/object-metadata/services/object-metadata-migration.service.ts b/packages/twenty-server/src/engine/metadata-modules/object-metadata/services/object-metadata-migration.service.ts index 5fa9c9323..53de846fa 100644 --- a/packages/twenty-server/src/engine/metadata-modules/object-metadata/services/object-metadata-migration.service.ts +++ b/packages/twenty-server/src/engine/metadata-modules/object-metadata/services/object-metadata-migration.service.ts @@ -22,6 +22,7 @@ import { WorkspaceMigrationFactory } from 'src/engine/metadata-modules/workspace import { WorkspaceMigrationService } from 'src/engine/metadata-modules/workspace-migration/workspace-migration.service'; import { computeObjectTargetTable } from 'src/engine/utils/compute-object-target-table.util'; import { computeTableName } from 'src/engine/utils/compute-table-name.util'; +import { RELATION_MIGRATION_PRIORITY_PREFIX } from 'src/engine/workspace-manager/workspace-migration-runner/workspace-migration-runner.service'; @Injectable() export class ObjectMetadataMigrationService { @@ -228,7 +229,7 @@ export class ObjectMetadataMigrationService { if (relationToDelete.direction === 'from') { await this.workspaceMigrationService.createCustomMigration( generateMigrationName( - `delete-${relationToDelete.fromObjectName}-${relationToDelete.toObjectName}`, + `delete-${RELATION_MIGRATION_PRIORITY_PREFIX}-${relationToDelete.fromObjectName}-${relationToDelete.toObjectName}`, ), workspaceId, [ diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-runner/workspace-migration-runner.service.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-runner/workspace-migration-runner.service.ts index eb21019d7..814c2f374 100644 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-runner/workspace-migration-runner.service.ts +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-runner/workspace-migration-runner.service.ts @@ -33,6 +33,8 @@ import { tableDefaultColumns } from 'src/engine/workspace-manager/workspace-migr import { WorkspaceMigrationTypeService } from './services/workspace-migration-type.service'; +export const RELATION_MIGRATION_PRIORITY_PREFIX = '1000'; + @Injectable() export class WorkspaceMigrationRunnerService { private readonly logger = new Logger(WorkspaceMigrationRunnerService.name); diff --git a/packages/twenty-server/src/modules/view/pre-hooks.ts/view-delete-many.pre-query.hook.ts b/packages/twenty-server/src/modules/view/pre-hooks.ts/view-delete-many.pre-query.hook.ts index a70fe63b4..d928e3c79 100644 --- a/packages/twenty-server/src/modules/view/pre-hooks.ts/view-delete-many.pre-query.hook.ts +++ b/packages/twenty-server/src/modules/view/pre-hooks.ts/view-delete-many.pre-query.hook.ts @@ -1,13 +1,12 @@ import { WorkspaceQueryHookInstance } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-hook/interfaces/workspace-query-hook.interface'; import { DeleteManyResolverArgs } from 'src/engine/api/graphql/workspace-resolver-builder/interfaces/workspace-resolvers-builder.interface'; +import { + GraphqlQueryRunnerException, + GraphqlQueryRunnerExceptionCode, +} from 'src/engine/api/graphql/graphql-query-runner/errors/graphql-query-runner.exception'; import { WorkspaceQueryHook } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-hook/decorators/workspace-query-hook.decorator'; import { AuthContext } from 'src/engine/core-modules/auth/types/auth-context.type'; -import { - ViewException, - ViewExceptionCode, - ViewExceptionMessage, -} from 'src/modules/view/views.exception'; @WorkspaceQueryHook(`view.deleteMany`) export class ViewDeleteManyPreQueryHook implements WorkspaceQueryHookInstance { @@ -18,9 +17,9 @@ export class ViewDeleteManyPreQueryHook implements WorkspaceQueryHookInstance { _objectName: string, _payload: DeleteManyResolverArgs, ): Promise { - throw new ViewException( - ViewExceptionMessage.METHOD_NOT_IMPLEMENTED, - ViewExceptionCode.METHOD_NOT_IMPLEMENTED, + throw new GraphqlQueryRunnerException( + 'Method not implemented', + GraphqlQueryRunnerExceptionCode.NOT_IMPLEMENTED, ); } } diff --git a/packages/twenty-server/src/modules/view/pre-hooks.ts/view-delete-one.pre-query.hook.ts b/packages/twenty-server/src/modules/view/pre-hooks.ts/view-delete-one.pre-query.hook.ts index 05d2742fa..e508d7a0d 100644 --- a/packages/twenty-server/src/modules/view/pre-hooks.ts/view-delete-one.pre-query.hook.ts +++ b/packages/twenty-server/src/modules/view/pre-hooks.ts/view-delete-one.pre-query.hook.ts @@ -1,14 +1,13 @@ import { WorkspaceQueryHookInstance } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-hook/interfaces/workspace-query-hook.interface'; import { DeleteOneResolverArgs } from 'src/engine/api/graphql/workspace-resolver-builder/interfaces/workspace-resolvers-builder.interface'; +import { + GraphqlQueryRunnerException, + GraphqlQueryRunnerExceptionCode, +} from 'src/engine/api/graphql/graphql-query-runner/errors/graphql-query-runner.exception'; import { WorkspaceQueryHook } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-hook/decorators/workspace-query-hook.decorator'; import { AuthContext } from 'src/engine/core-modules/auth/types/auth-context.type'; import { TwentyORMGlobalManager } from 'src/engine/twenty-orm/twenty-orm-global.manager'; -import { - ViewException, - ViewExceptionCode, - ViewExceptionMessage, -} from 'src/modules/view/views.exception'; @WorkspaceQueryHook(`view.deleteOne`) export class ViewDeleteOnePreQueryHook implements WorkspaceQueryHookInstance { @@ -34,16 +33,16 @@ export class ViewDeleteOnePreQueryHook implements WorkspaceQueryHookInstance { }); if (!view) { - throw new ViewException( - ViewExceptionMessage.VIEW_NOT_FOUND, - ViewExceptionCode.VIEW_NOT_FOUND, + throw new GraphqlQueryRunnerException( + 'View not found', + GraphqlQueryRunnerExceptionCode.INVALID_QUERY_INPUT, ); } if (view.key === 'INDEX') { - throw new ViewException( - ViewExceptionMessage.CANNOT_DELETE_INDEX_VIEW, - ViewExceptionCode.CANNOT_DELETE_INDEX_VIEW, + throw new GraphqlQueryRunnerException( + 'Cannot delete INDEX view', + GraphqlQueryRunnerExceptionCode.INVALID_QUERY_INPUT, ); } diff --git a/packages/twenty-server/test/integration/billing/utils/create-mock-stripe-product-updated-data.util.ts b/packages/twenty-server/test/integration/billing/utils/create-mock-stripe-product-updated-data.util.ts index b65f70da1..8f771dd7d 100644 --- a/packages/twenty-server/test/integration/billing/utils/create-mock-stripe-product-updated-data.util.ts +++ b/packages/twenty-server/test/integration/billing/utils/create-mock-stripe-product-updated-data.util.ts @@ -1,5 +1,7 @@ import Stripe from 'stripe'; +import { BillingUsageType } from 'src/engine/core-modules/billing/enums/billing-usage-type.enum'; + export const createMockStripeProductUpdatedData = ( overrides = {}, ): Stripe.ProductUpdatedEvent.Data => ({ @@ -13,7 +15,11 @@ export const createMockStripeProductUpdatedData = ( images: [], livemode: false, marketing_features: [], - metadata: {}, + metadata: { + planKey: 'base', + isBaseProduct: 'true', + priceUsageBased: BillingUsageType.LICENSED, + }, name: 'kjnnjkjknkjnjkn', package_dimensions: null, shippable: null, diff --git a/packages/twenty-server/test/integration/graphql/suites/auth.integration-spec.ts b/packages/twenty-server/test/integration/graphql/suites/auth.integration-spec.ts index 0d406cee5..ccbba0cbc 100644 --- a/packages/twenty-server/test/integration/graphql/suites/auth.integration-spec.ts +++ b/packages/twenty-server/test/integration/graphql/suites/auth.integration-spec.ts @@ -1,6 +1,8 @@ import request from 'supertest'; -const client = request(`http://localhost:${APP_PORT}`); +const SERVER_URL = `http://localhost:${APP_PORT}`; + +const client = request(SERVER_URL); const auth = { email: 'tim@apple.dev', @@ -26,6 +28,7 @@ describe('AuthResolve (integration)', () => { return client .post('/graphql') + .set('Origin', SERVER_URL) .send(queryData) .expect(200) .expect((res) => { @@ -59,6 +62,7 @@ describe('AuthResolve (integration)', () => { return client .post('/graphql') + .set('Origin', SERVER_URL) .send(queryData) .expect(200) .expect((res) => { diff --git a/packages/twenty-server/test/integration/graphql/suites/object-generated/search-api-keys.integration-spec.ts b/packages/twenty-server/test/integration/graphql/suites/object-generated/search-api-keys.integration-spec.ts deleted file mode 100644 index 51dffa306..000000000 --- a/packages/twenty-server/test/integration/graphql/suites/object-generated/search-api-keys.integration-spec.ts +++ /dev/null @@ -1,57 +0,0 @@ -import request from 'supertest'; - -const client = request(`http://localhost:${APP_PORT}`); - -describe('searchApiKeysResolver (e2e)', () => { - it('should find many searchApiKeys', () => { - const queryData = { - query: ` - query searchApiKeys { - searchApiKeys { - edges { - node { - name - expiresAt - revokedAt - id - createdAt - updatedAt - deletedAt - } - } - } - } - `, - }; - - return client - .post('/graphql') - .set('Authorization', `Bearer ${ADMIN_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.searchApiKeys; - - expect(data).toBeDefined(); - expect(Array.isArray(data.edges)).toBe(true); - - const edges = data.edges; - - if (edges.length > 0) { - const searchApiKeys = edges[0].node; - - expect(searchApiKeys).toHaveProperty('name'); - expect(searchApiKeys).toHaveProperty('expiresAt'); - expect(searchApiKeys).toHaveProperty('revokedAt'); - expect(searchApiKeys).toHaveProperty('id'); - expect(searchApiKeys).toHaveProperty('createdAt'); - expect(searchApiKeys).toHaveProperty('updatedAt'); - expect(searchApiKeys).toHaveProperty('deletedAt'); - } - }); - }); -}); diff --git a/packages/twenty-server/test/integration/graphql/suites/object-generated/search-attachments.integration-spec.ts b/packages/twenty-server/test/integration/graphql/suites/object-generated/search-attachments.integration-spec.ts deleted file mode 100644 index 4d678b803..000000000 --- a/packages/twenty-server/test/integration/graphql/suites/object-generated/search-attachments.integration-spec.ts +++ /dev/null @@ -1,73 +0,0 @@ -import request from 'supertest'; - -const client = request(`http://localhost:${APP_PORT}`); - -describe('searchAttachmentsResolver (e2e)', () => { - it('should find many searchAttachments', () => { - const queryData = { - query: ` - query searchAttachments { - searchAttachments { - edges { - node { - name - fullPath - type - id - createdAt - updatedAt - deletedAt - authorId - taskId - noteId - personId - companyId - opportunityId - petId - surveyResultId - } - } - } - } - `, - }; - - return client - .post('/graphql') - .set('Authorization', `Bearer ${ADMIN_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.searchAttachments; - - expect(data).toBeDefined(); - expect(Array.isArray(data.edges)).toBe(true); - - const edges = data.edges; - - if (edges.length > 0) { - const searchAttachments = edges[0].node; - - expect(searchAttachments).toHaveProperty('name'); - expect(searchAttachments).toHaveProperty('fullPath'); - expect(searchAttachments).toHaveProperty('type'); - expect(searchAttachments).toHaveProperty('id'); - expect(searchAttachments).toHaveProperty('createdAt'); - expect(searchAttachments).toHaveProperty('updatedAt'); - expect(searchAttachments).toHaveProperty('deletedAt'); - expect(searchAttachments).toHaveProperty('authorId'); - expect(searchAttachments).toHaveProperty('taskId'); - expect(searchAttachments).toHaveProperty('noteId'); - expect(searchAttachments).toHaveProperty('personId'); - expect(searchAttachments).toHaveProperty('companyId'); - expect(searchAttachments).toHaveProperty('opportunityId'); - expect(searchAttachments).toHaveProperty('petId'); - expect(searchAttachments).toHaveProperty('surveyResultId'); - } - }); - }); -}); diff --git a/packages/twenty-server/test/integration/graphql/suites/object-generated/search-audit-logs.integration-spec.ts b/packages/twenty-server/test/integration/graphql/suites/object-generated/search-audit-logs.integration-spec.ts deleted file mode 100644 index 967a3775d..000000000 --- a/packages/twenty-server/test/integration/graphql/suites/object-generated/search-audit-logs.integration-spec.ts +++ /dev/null @@ -1,65 +0,0 @@ -import request from 'supertest'; - -const client = request(`http://localhost:${APP_PORT}`); - -describe('searchAuditLogsResolver (e2e)', () => { - it('should find many searchAuditLogs', () => { - const queryData = { - query: ` - query searchAuditLogs { - searchAuditLogs { - edges { - node { - name - properties - context - objectName - objectMetadataId - recordId - id - createdAt - updatedAt - deletedAt - workspaceMemberId - } - } - } - } - `, - }; - - return client - .post('/graphql') - .set('Authorization', `Bearer ${ADMIN_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.searchAuditLogs; - - expect(data).toBeDefined(); - expect(Array.isArray(data.edges)).toBe(true); - - const edges = data.edges; - - if (edges.length > 0) { - const searchAuditLogs = edges[0].node; - - expect(searchAuditLogs).toHaveProperty('name'); - expect(searchAuditLogs).toHaveProperty('properties'); - expect(searchAuditLogs).toHaveProperty('context'); - expect(searchAuditLogs).toHaveProperty('objectName'); - expect(searchAuditLogs).toHaveProperty('objectMetadataId'); - expect(searchAuditLogs).toHaveProperty('recordId'); - expect(searchAuditLogs).toHaveProperty('id'); - expect(searchAuditLogs).toHaveProperty('createdAt'); - expect(searchAuditLogs).toHaveProperty('updatedAt'); - expect(searchAuditLogs).toHaveProperty('deletedAt'); - expect(searchAuditLogs).toHaveProperty('workspaceMemberId'); - } - }); - }); -}); diff --git a/packages/twenty-server/test/integration/graphql/suites/object-generated/search-blocklists.integration-spec.ts b/packages/twenty-server/test/integration/graphql/suites/object-generated/search-blocklists.integration-spec.ts deleted file mode 100644 index 2ab6a1b1d..000000000 --- a/packages/twenty-server/test/integration/graphql/suites/object-generated/search-blocklists.integration-spec.ts +++ /dev/null @@ -1,55 +0,0 @@ -import request from 'supertest'; - -const client = request(`http://localhost:${APP_PORT}`); - -describe('searchBlocklistsResolver (e2e)', () => { - it('should find many searchBlocklists', () => { - const queryData = { - query: ` - query searchBlocklists { - searchBlocklists { - edges { - node { - handle - id - createdAt - updatedAt - deletedAt - workspaceMemberId - } - } - } - } - `, - }; - - return client - .post('/graphql') - .set('Authorization', `Bearer ${ADMIN_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.searchBlocklists; - - expect(data).toBeDefined(); - expect(Array.isArray(data.edges)).toBe(true); - - const edges = data.edges; - - if (edges.length > 0) { - const searchBlocklists = edges[0].node; - - expect(searchBlocklists).toHaveProperty('handle'); - expect(searchBlocklists).toHaveProperty('id'); - expect(searchBlocklists).toHaveProperty('createdAt'); - expect(searchBlocklists).toHaveProperty('updatedAt'); - expect(searchBlocklists).toHaveProperty('deletedAt'); - expect(searchBlocklists).toHaveProperty('workspaceMemberId'); - } - }); - }); -}); diff --git a/packages/twenty-server/test/integration/graphql/suites/object-generated/search-calendar-channel-event-associations.integration-spec.ts b/packages/twenty-server/test/integration/graphql/suites/object-generated/search-calendar-channel-event-associations.integration-spec.ts deleted file mode 100644 index 5cf6e9222..000000000 --- a/packages/twenty-server/test/integration/graphql/suites/object-generated/search-calendar-channel-event-associations.integration-spec.ts +++ /dev/null @@ -1,73 +0,0 @@ -import request from 'supertest'; - -const client = request(`http://localhost:${APP_PORT}`); - -describe('searchCalendarChannelEventAssociationsResolver (e2e)', () => { - it('should find many searchCalendarChannelEventAssociations', () => { - const queryData = { - query: ` - query searchCalendarChannelEventAssociations { - searchCalendarChannelEventAssociations { - edges { - node { - eventExternalId - recurringEventExternalId - id - createdAt - updatedAt - deletedAt - calendarChannelId - calendarEventId - } - } - } - } - `, - }; - - return client - .post('/graphql') - .set('Authorization', `Bearer ${ADMIN_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.searchCalendarChannelEventAssociations; - - expect(data).toBeDefined(); - expect(Array.isArray(data.edges)).toBe(true); - - const edges = data.edges; - - if (edges.length > 0) { - const searchCalendarChannelEventAssociations = edges[0].node; - - expect(searchCalendarChannelEventAssociations).toHaveProperty( - 'eventExternalId', - ); - expect(searchCalendarChannelEventAssociations).toHaveProperty( - 'recurringEventExternalId', - ); - expect(searchCalendarChannelEventAssociations).toHaveProperty('id'); - expect(searchCalendarChannelEventAssociations).toHaveProperty( - 'createdAt', - ); - expect(searchCalendarChannelEventAssociations).toHaveProperty( - 'updatedAt', - ); - expect(searchCalendarChannelEventAssociations).toHaveProperty( - 'deletedAt', - ); - expect(searchCalendarChannelEventAssociations).toHaveProperty( - 'calendarChannelId', - ); - expect(searchCalendarChannelEventAssociations).toHaveProperty( - 'calendarEventId', - ); - } - }); - }); -}); diff --git a/packages/twenty-server/test/integration/graphql/suites/object-generated/search-calendar-channels.integration-spec.ts b/packages/twenty-server/test/integration/graphql/suites/object-generated/search-calendar-channels.integration-spec.ts deleted file mode 100644 index 0f51fc3e5..000000000 --- a/packages/twenty-server/test/integration/graphql/suites/object-generated/search-calendar-channels.integration-spec.ts +++ /dev/null @@ -1,79 +0,0 @@ -import request from 'supertest'; - -const client = request(`http://localhost:${APP_PORT}`); - -describe('searchCalendarChannelsResolver (e2e)', () => { - it('should find many searchCalendarChannels', () => { - const queryData = { - query: ` - query searchCalendarChannels { - searchCalendarChannels { - edges { - node { - handle - syncStatus - syncStage - visibility - isContactAutoCreationEnabled - contactAutoCreationPolicy - isSyncEnabled - syncCursor - syncedAt - syncStageStartedAt - throttleFailureCount - id - createdAt - updatedAt - deletedAt - connectedAccountId - } - } - } - } - `, - }; - - return client - .post('/graphql') - .set('Authorization', `Bearer ${ADMIN_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.searchCalendarChannels; - - expect(data).toBeDefined(); - expect(Array.isArray(data.edges)).toBe(true); - - const edges = data.edges; - - if (edges.length > 0) { - const searchCalendarChannels = edges[0].node; - - expect(searchCalendarChannels).toHaveProperty('handle'); - expect(searchCalendarChannels).toHaveProperty('syncStatus'); - expect(searchCalendarChannels).toHaveProperty('syncStage'); - expect(searchCalendarChannels).toHaveProperty('visibility'); - expect(searchCalendarChannels).toHaveProperty( - 'isContactAutoCreationEnabled', - ); - expect(searchCalendarChannels).toHaveProperty( - 'contactAutoCreationPolicy', - ); - expect(searchCalendarChannels).toHaveProperty('isSyncEnabled'); - expect(searchCalendarChannels).toHaveProperty('syncCursor'); - expect(searchCalendarChannels).toHaveProperty('syncedAt'); - expect(searchCalendarChannels).toHaveProperty('syncStageStartedAt'); - expect(searchCalendarChannels).toHaveProperty('throttleFailureCount'); - expect(searchCalendarChannels).toHaveProperty('id'); - expect(searchCalendarChannels).toHaveProperty('createdAt'); - expect(searchCalendarChannels).toHaveProperty('updatedAt'); - expect(searchCalendarChannels).toHaveProperty('deletedAt'); - expect(searchCalendarChannels).toHaveProperty('connectedAccountId'); - } - }); - }); -}); diff --git a/packages/twenty-server/test/integration/graphql/suites/object-generated/search-calendar-event-participants.integration-spec.ts b/packages/twenty-server/test/integration/graphql/suites/object-generated/search-calendar-event-participants.integration-spec.ts deleted file mode 100644 index 6c6c4c9ed..000000000 --- a/packages/twenty-server/test/integration/graphql/suites/object-generated/search-calendar-event-participants.integration-spec.ts +++ /dev/null @@ -1,71 +0,0 @@ -import request from 'supertest'; - -const client = request(`http://localhost:${APP_PORT}`); - -describe('searchCalendarEventParticipantsResolver (e2e)', () => { - it('should find many searchCalendarEventParticipants', () => { - const queryData = { - query: ` - query searchCalendarEventParticipants { - searchCalendarEventParticipants { - edges { - node { - handle - displayName - isOrganizer - responseStatus - id - createdAt - updatedAt - deletedAt - calendarEventId - personId - workspaceMemberId - } - } - } - } - `, - }; - - return client - .post('/graphql') - .set('Authorization', `Bearer ${ADMIN_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.searchCalendarEventParticipants; - - expect(data).toBeDefined(); - expect(Array.isArray(data.edges)).toBe(true); - - const edges = data.edges; - - if (edges.length > 0) { - const searchCalendarEventParticipants = edges[0].node; - - expect(searchCalendarEventParticipants).toHaveProperty('handle'); - expect(searchCalendarEventParticipants).toHaveProperty('displayName'); - expect(searchCalendarEventParticipants).toHaveProperty('isOrganizer'); - expect(searchCalendarEventParticipants).toHaveProperty( - 'responseStatus', - ); - expect(searchCalendarEventParticipants).toHaveProperty('id'); - expect(searchCalendarEventParticipants).toHaveProperty('createdAt'); - expect(searchCalendarEventParticipants).toHaveProperty('updatedAt'); - expect(searchCalendarEventParticipants).toHaveProperty('deletedAt'); - expect(searchCalendarEventParticipants).toHaveProperty( - 'calendarEventId', - ); - expect(searchCalendarEventParticipants).toHaveProperty('personId'); - expect(searchCalendarEventParticipants).toHaveProperty( - 'workspaceMemberId', - ); - } - }); - }); -}); diff --git a/packages/twenty-server/test/integration/graphql/suites/object-generated/search-calendar-events.integration-spec.ts b/packages/twenty-server/test/integration/graphql/suites/object-generated/search-calendar-events.integration-spec.ts deleted file mode 100644 index 3e7c4083a..000000000 --- a/packages/twenty-server/test/integration/graphql/suites/object-generated/search-calendar-events.integration-spec.ts +++ /dev/null @@ -1,73 +0,0 @@ -import request from 'supertest'; - -const client = request(`http://localhost:${APP_PORT}`); - -describe('searchCalendarEventsResolver (e2e)', () => { - it('should find many searchCalendarEvents', () => { - const queryData = { - query: ` - query searchCalendarEvents { - searchCalendarEvents { - edges { - node { - title - isCanceled - isFullDay - startsAt - endsAt - externalCreatedAt - externalUpdatedAt - description - location - iCalUID - conferenceSolution - id - createdAt - updatedAt - deletedAt - } - } - } - } - `, - }; - - return client - .post('/graphql') - .set('Authorization', `Bearer ${ADMIN_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.searchCalendarEvents; - - expect(data).toBeDefined(); - expect(Array.isArray(data.edges)).toBe(true); - - const edges = data.edges; - - if (edges.length > 0) { - const searchCalendarEvents = edges[0].node; - - expect(searchCalendarEvents).toHaveProperty('title'); - expect(searchCalendarEvents).toHaveProperty('isCanceled'); - expect(searchCalendarEvents).toHaveProperty('isFullDay'); - expect(searchCalendarEvents).toHaveProperty('startsAt'); - expect(searchCalendarEvents).toHaveProperty('endsAt'); - expect(searchCalendarEvents).toHaveProperty('externalCreatedAt'); - expect(searchCalendarEvents).toHaveProperty('externalUpdatedAt'); - expect(searchCalendarEvents).toHaveProperty('description'); - expect(searchCalendarEvents).toHaveProperty('location'); - expect(searchCalendarEvents).toHaveProperty('iCalUID'); - expect(searchCalendarEvents).toHaveProperty('conferenceSolution'); - expect(searchCalendarEvents).toHaveProperty('id'); - expect(searchCalendarEvents).toHaveProperty('createdAt'); - expect(searchCalendarEvents).toHaveProperty('updatedAt'); - expect(searchCalendarEvents).toHaveProperty('deletedAt'); - } - }); - }); -}); diff --git a/packages/twenty-server/test/integration/graphql/suites/object-generated/search-companies.integration-spec.ts b/packages/twenty-server/test/integration/graphql/suites/object-generated/search-companies.integration-spec.ts deleted file mode 100644 index 76107f55b..000000000 --- a/packages/twenty-server/test/integration/graphql/suites/object-generated/search-companies.integration-spec.ts +++ /dev/null @@ -1,69 +0,0 @@ -import request from 'supertest'; - -const client = request(`http://localhost:${APP_PORT}`); - -describe('searchCompaniesResolver (e2e)', () => { - it('should find many searchCompanies', () => { - const queryData = { - query: ` - query searchCompanies { - searchCompanies { - edges { - node { - name - employees - idealCustomerProfile - position - searchVector - id - createdAt - updatedAt - deletedAt - accountOwnerId - tagline - workPolicy - visaSponsorship - } - } - } - } - `, - }; - - return client - .post('/graphql') - .set('Authorization', `Bearer ${ADMIN_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.searchCompanies; - - expect(data).toBeDefined(); - expect(Array.isArray(data.edges)).toBe(true); - - const edges = data.edges; - - if (edges.length > 0) { - const searchCompanies = edges[0].node; - - expect(searchCompanies).toHaveProperty('name'); - expect(searchCompanies).toHaveProperty('employees'); - expect(searchCompanies).toHaveProperty('idealCustomerProfile'); - expect(searchCompanies).toHaveProperty('position'); - expect(searchCompanies).toHaveProperty('searchVector'); - expect(searchCompanies).toHaveProperty('id'); - expect(searchCompanies).toHaveProperty('createdAt'); - expect(searchCompanies).toHaveProperty('updatedAt'); - expect(searchCompanies).toHaveProperty('deletedAt'); - expect(searchCompanies).toHaveProperty('accountOwnerId'); - expect(searchCompanies).toHaveProperty('tagline'); - expect(searchCompanies).toHaveProperty('workPolicy'); - expect(searchCompanies).toHaveProperty('visaSponsorship'); - } - }); - }); -}); diff --git a/packages/twenty-server/test/integration/graphql/suites/object-generated/search-connected-accounts.integration-spec.ts b/packages/twenty-server/test/integration/graphql/suites/object-generated/search-connected-accounts.integration-spec.ts deleted file mode 100644 index 48a351587..000000000 --- a/packages/twenty-server/test/integration/graphql/suites/object-generated/search-connected-accounts.integration-spec.ts +++ /dev/null @@ -1,69 +0,0 @@ -import request from 'supertest'; - -const client = request(`http://localhost:${APP_PORT}`); - -describe('searchConnectedAccountsResolver (e2e)', () => { - it('should find many searchConnectedAccounts', () => { - const queryData = { - query: ` - query searchConnectedAccounts { - searchConnectedAccounts { - edges { - node { - handle - provider - accessToken - refreshToken - lastSyncHistoryId - authFailedAt - handleAliases - scopes - id - createdAt - updatedAt - deletedAt - accountOwnerId - } - } - } - } - `, - }; - - return client - .post('/graphql') - .set('Authorization', `Bearer ${ADMIN_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.searchConnectedAccounts; - - expect(data).toBeDefined(); - expect(Array.isArray(data.edges)).toBe(true); - - const edges = data.edges; - - if (edges.length > 0) { - const searchConnectedAccounts = edges[0].node; - - expect(searchConnectedAccounts).toHaveProperty('handle'); - expect(searchConnectedAccounts).toHaveProperty('provider'); - expect(searchConnectedAccounts).toHaveProperty('accessToken'); - expect(searchConnectedAccounts).toHaveProperty('refreshToken'); - expect(searchConnectedAccounts).toHaveProperty('lastSyncHistoryId'); - expect(searchConnectedAccounts).toHaveProperty('authFailedAt'); - expect(searchConnectedAccounts).toHaveProperty('handleAliases'); - expect(searchConnectedAccounts).toHaveProperty('scopes'); - expect(searchConnectedAccounts).toHaveProperty('id'); - expect(searchConnectedAccounts).toHaveProperty('createdAt'); - expect(searchConnectedAccounts).toHaveProperty('updatedAt'); - expect(searchConnectedAccounts).toHaveProperty('deletedAt'); - expect(searchConnectedAccounts).toHaveProperty('accountOwnerId'); - } - }); - }); -}); diff --git a/packages/twenty-server/test/integration/graphql/suites/object-generated/search-favorites.integration-spec.ts b/packages/twenty-server/test/integration/graphql/suites/object-generated/search-favorites.integration-spec.ts deleted file mode 100644 index 82265314b..000000000 --- a/packages/twenty-server/test/integration/graphql/suites/object-generated/search-favorites.integration-spec.ts +++ /dev/null @@ -1,77 +0,0 @@ -import request from 'supertest'; - -const client = request(`http://localhost:${APP_PORT}`); - -describe('searchFavoritesResolver (e2e)', () => { - it('should find many searchFavorites', () => { - const queryData = { - query: ` - query searchFavorites { - searchFavorites { - edges { - node { - position - id - createdAt - updatedAt - deletedAt - forWorkspaceMemberId - personId - companyId - opportunityId - workflowId - workflowVersionId - workflowRunId - taskId - noteId - viewId - petId - surveyResultId - } - } - } - } - `, - }; - - return client - .post('/graphql') - .set('Authorization', `Bearer ${ADMIN_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.searchFavorites; - - expect(data).toBeDefined(); - expect(Array.isArray(data.edges)).toBe(true); - - const edges = data.edges; - - if (edges.length > 0) { - const searchFavorites = edges[0].node; - - expect(searchFavorites).toHaveProperty('position'); - expect(searchFavorites).toHaveProperty('id'); - expect(searchFavorites).toHaveProperty('createdAt'); - expect(searchFavorites).toHaveProperty('updatedAt'); - expect(searchFavorites).toHaveProperty('deletedAt'); - expect(searchFavorites).toHaveProperty('forWorkspaceMemberId'); - expect(searchFavorites).toHaveProperty('personId'); - expect(searchFavorites).toHaveProperty('companyId'); - expect(searchFavorites).toHaveProperty('opportunityId'); - expect(searchFavorites).toHaveProperty('workflowId'); - expect(searchFavorites).toHaveProperty('workflowVersionId'); - expect(searchFavorites).toHaveProperty('workflowRunId'); - expect(searchFavorites).toHaveProperty('taskId'); - expect(searchFavorites).toHaveProperty('noteId'); - expect(searchFavorites).toHaveProperty('viewId'); - expect(searchFavorites).toHaveProperty('petId'); - expect(searchFavorites).toHaveProperty('surveyResultId'); - } - }); - }); -}); diff --git a/packages/twenty-server/test/integration/graphql/suites/object-generated/search-message-channel-message-associations.integration-spec.ts b/packages/twenty-server/test/integration/graphql/suites/object-generated/search-message-channel-message-associations.integration-spec.ts deleted file mode 100644 index 329a32720..000000000 --- a/packages/twenty-server/test/integration/graphql/suites/object-generated/search-message-channel-message-associations.integration-spec.ts +++ /dev/null @@ -1,77 +0,0 @@ -import request from 'supertest'; - -const client = request(`http://localhost:${APP_PORT}`); - -describe('searchMessageChannelMessageAssociationsResolver (e2e)', () => { - it('should find many searchMessageChannelMessageAssociations', () => { - const queryData = { - query: ` - query searchMessageChannelMessageAssociations { - searchMessageChannelMessageAssociations { - edges { - node { - messageExternalId - messageThreadExternalId - direction - id - createdAt - updatedAt - deletedAt - messageChannelId - messageId - } - } - } - } - `, - }; - - return client - .post('/graphql') - .set('Authorization', `Bearer ${ADMIN_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.searchMessageChannelMessageAssociations; - - expect(data).toBeDefined(); - expect(Array.isArray(data.edges)).toBe(true); - - const edges = data.edges; - - if (edges.length > 0) { - const searchMessageChannelMessageAssociations = edges[0].node; - - expect(searchMessageChannelMessageAssociations).toHaveProperty( - 'messageExternalId', - ); - expect(searchMessageChannelMessageAssociations).toHaveProperty( - 'messageThreadExternalId', - ); - expect(searchMessageChannelMessageAssociations).toHaveProperty( - 'direction', - ); - expect(searchMessageChannelMessageAssociations).toHaveProperty('id'); - expect(searchMessageChannelMessageAssociations).toHaveProperty( - 'createdAt', - ); - expect(searchMessageChannelMessageAssociations).toHaveProperty( - 'updatedAt', - ); - expect(searchMessageChannelMessageAssociations).toHaveProperty( - 'deletedAt', - ); - expect(searchMessageChannelMessageAssociations).toHaveProperty( - 'messageChannelId', - ); - expect(searchMessageChannelMessageAssociations).toHaveProperty( - 'messageId', - ); - } - }); - }); -}); diff --git a/packages/twenty-server/test/integration/graphql/suites/object-generated/search-message-channels.integration-spec.ts b/packages/twenty-server/test/integration/graphql/suites/object-generated/search-message-channels.integration-spec.ts deleted file mode 100644 index 718e3ad44..000000000 --- a/packages/twenty-server/test/integration/graphql/suites/object-generated/search-message-channels.integration-spec.ts +++ /dev/null @@ -1,87 +0,0 @@ -import request from 'supertest'; - -const client = request(`http://localhost:${APP_PORT}`); - -describe('searchMessageChannelsResolver (e2e)', () => { - it('should find many searchMessageChannels', () => { - const queryData = { - query: ` - query searchMessageChannels { - searchMessageChannels { - 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 ${ADMIN_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.searchMessageChannels; - - expect(data).toBeDefined(); - expect(Array.isArray(data.edges)).toBe(true); - - const edges = data.edges; - - if (edges.length > 0) { - const searchMessageChannels = edges[0].node; - - expect(searchMessageChannels).toHaveProperty('visibility'); - expect(searchMessageChannels).toHaveProperty('handle'); - expect(searchMessageChannels).toHaveProperty('type'); - expect(searchMessageChannels).toHaveProperty( - 'isContactAutoCreationEnabled', - ); - expect(searchMessageChannels).toHaveProperty( - 'contactAutoCreationPolicy', - ); - expect(searchMessageChannels).toHaveProperty( - 'excludeNonProfessionalEmails', - ); - expect(searchMessageChannels).toHaveProperty('excludeGroupEmails'); - expect(searchMessageChannels).toHaveProperty('isSyncEnabled'); - expect(searchMessageChannels).toHaveProperty('syncCursor'); - expect(searchMessageChannels).toHaveProperty('syncedAt'); - expect(searchMessageChannels).toHaveProperty('syncStatus'); - expect(searchMessageChannels).toHaveProperty('syncStage'); - expect(searchMessageChannels).toHaveProperty('syncStageStartedAt'); - expect(searchMessageChannels).toHaveProperty('throttleFailureCount'); - expect(searchMessageChannels).toHaveProperty('id'); - expect(searchMessageChannels).toHaveProperty('createdAt'); - expect(searchMessageChannels).toHaveProperty('updatedAt'); - expect(searchMessageChannels).toHaveProperty('deletedAt'); - expect(searchMessageChannels).toHaveProperty('connectedAccountId'); - } - }); - }); -}); diff --git a/packages/twenty-server/test/integration/graphql/suites/object-generated/search-message-participants.integration-spec.ts b/packages/twenty-server/test/integration/graphql/suites/object-generated/search-message-participants.integration-spec.ts deleted file mode 100644 index fc4603e24..000000000 --- a/packages/twenty-server/test/integration/graphql/suites/object-generated/search-message-participants.integration-spec.ts +++ /dev/null @@ -1,63 +0,0 @@ -import request from 'supertest'; - -const client = request(`http://localhost:${APP_PORT}`); - -describe('searchMessageParticipantsResolver (e2e)', () => { - it('should find many searchMessageParticipants', () => { - const queryData = { - query: ` - query searchMessageParticipants { - searchMessageParticipants { - edges { - node { - role - handle - displayName - id - createdAt - updatedAt - deletedAt - messageId - personId - workspaceMemberId - } - } - } - } - `, - }; - - return client - .post('/graphql') - .set('Authorization', `Bearer ${ADMIN_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.searchMessageParticipants; - - expect(data).toBeDefined(); - expect(Array.isArray(data.edges)).toBe(true); - - const edges = data.edges; - - if (edges.length > 0) { - const searchMessageParticipants = edges[0].node; - - expect(searchMessageParticipants).toHaveProperty('role'); - expect(searchMessageParticipants).toHaveProperty('handle'); - expect(searchMessageParticipants).toHaveProperty('displayName'); - expect(searchMessageParticipants).toHaveProperty('id'); - expect(searchMessageParticipants).toHaveProperty('createdAt'); - expect(searchMessageParticipants).toHaveProperty('updatedAt'); - expect(searchMessageParticipants).toHaveProperty('deletedAt'); - expect(searchMessageParticipants).toHaveProperty('messageId'); - expect(searchMessageParticipants).toHaveProperty('personId'); - expect(searchMessageParticipants).toHaveProperty('workspaceMemberId'); - } - }); - }); -}); diff --git a/packages/twenty-server/test/integration/graphql/suites/object-generated/search-message-threads.integration-spec.ts b/packages/twenty-server/test/integration/graphql/suites/object-generated/search-message-threads.integration-spec.ts deleted file mode 100644 index e0f997d9a..000000000 --- a/packages/twenty-server/test/integration/graphql/suites/object-generated/search-message-threads.integration-spec.ts +++ /dev/null @@ -1,51 +0,0 @@ -import request from 'supertest'; - -const client = request(`http://localhost:${APP_PORT}`); - -describe('searchMessageThreadsResolver (e2e)', () => { - it('should find many searchMessageThreads', () => { - const queryData = { - query: ` - query searchMessageThreads { - searchMessageThreads { - edges { - node { - id - createdAt - updatedAt - deletedAt - } - } - } - } - `, - }; - - return client - .post('/graphql') - .set('Authorization', `Bearer ${ADMIN_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.searchMessageThreads; - - expect(data).toBeDefined(); - expect(Array.isArray(data.edges)).toBe(true); - - const edges = data.edges; - - if (edges.length > 0) { - const searchMessageThreads = edges[0].node; - - expect(searchMessageThreads).toHaveProperty('id'); - expect(searchMessageThreads).toHaveProperty('createdAt'); - expect(searchMessageThreads).toHaveProperty('updatedAt'); - expect(searchMessageThreads).toHaveProperty('deletedAt'); - } - }); - }); -}); diff --git a/packages/twenty-server/test/integration/graphql/suites/object-generated/search-messages.integration-spec.ts b/packages/twenty-server/test/integration/graphql/suites/object-generated/search-messages.integration-spec.ts deleted file mode 100644 index d479bf834..000000000 --- a/packages/twenty-server/test/integration/graphql/suites/object-generated/search-messages.integration-spec.ts +++ /dev/null @@ -1,61 +0,0 @@ -import request from 'supertest'; - -const client = request(`http://localhost:${APP_PORT}`); - -describe('searchMessagesResolver (e2e)', () => { - it('should find many searchMessages', () => { - const queryData = { - query: ` - query searchMessages { - searchMessages { - edges { - node { - headerMessageId - subject - text - receivedAt - id - createdAt - updatedAt - deletedAt - messageThreadId - } - } - } - } - `, - }; - - return client - .post('/graphql') - .set('Authorization', `Bearer ${ADMIN_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.searchMessages; - - expect(data).toBeDefined(); - expect(Array.isArray(data.edges)).toBe(true); - - const edges = data.edges; - - if (edges.length > 0) { - const searchMessages = edges[0].node; - - expect(searchMessages).toHaveProperty('headerMessageId'); - expect(searchMessages).toHaveProperty('subject'); - expect(searchMessages).toHaveProperty('text'); - expect(searchMessages).toHaveProperty('receivedAt'); - expect(searchMessages).toHaveProperty('id'); - expect(searchMessages).toHaveProperty('createdAt'); - expect(searchMessages).toHaveProperty('updatedAt'); - expect(searchMessages).toHaveProperty('deletedAt'); - expect(searchMessages).toHaveProperty('messageThreadId'); - } - }); - }); -}); diff --git a/packages/twenty-server/test/integration/graphql/suites/object-generated/search-note-targets.integration-spec.ts b/packages/twenty-server/test/integration/graphql/suites/object-generated/search-note-targets.integration-spec.ts deleted file mode 100644 index 58b3a9766..000000000 --- a/packages/twenty-server/test/integration/graphql/suites/object-generated/search-note-targets.integration-spec.ts +++ /dev/null @@ -1,63 +0,0 @@ -import request from 'supertest'; - -const client = request(`http://localhost:${APP_PORT}`); - -describe('searchNoteTargetsResolver (e2e)', () => { - it('should find many searchNoteTargets', () => { - const queryData = { - query: ` - query searchNoteTargets { - searchNoteTargets { - edges { - node { - id - createdAt - updatedAt - deletedAt - noteId - personId - companyId - opportunityId - petId - surveyResultId - } - } - } - } - `, - }; - - return client - .post('/graphql') - .set('Authorization', `Bearer ${ADMIN_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.searchNoteTargets; - - expect(data).toBeDefined(); - expect(Array.isArray(data.edges)).toBe(true); - - const edges = data.edges; - - if (edges.length > 0) { - const searchNoteTargets = edges[0].node; - - expect(searchNoteTargets).toHaveProperty('id'); - expect(searchNoteTargets).toHaveProperty('createdAt'); - expect(searchNoteTargets).toHaveProperty('updatedAt'); - expect(searchNoteTargets).toHaveProperty('deletedAt'); - expect(searchNoteTargets).toHaveProperty('noteId'); - expect(searchNoteTargets).toHaveProperty('personId'); - expect(searchNoteTargets).toHaveProperty('companyId'); - expect(searchNoteTargets).toHaveProperty('opportunityId'); - expect(searchNoteTargets).toHaveProperty('petId'); - expect(searchNoteTargets).toHaveProperty('surveyResultId'); - } - }); - }); -}); diff --git a/packages/twenty-server/test/integration/graphql/suites/object-generated/search-notes.integration-spec.ts b/packages/twenty-server/test/integration/graphql/suites/object-generated/search-notes.integration-spec.ts deleted file mode 100644 index df1399ac7..000000000 --- a/packages/twenty-server/test/integration/graphql/suites/object-generated/search-notes.integration-spec.ts +++ /dev/null @@ -1,57 +0,0 @@ -import request from 'supertest'; - -const client = request(`http://localhost:${APP_PORT}`); - -describe('searchNotesResolver (e2e)', () => { - it('should find many searchNotes', () => { - const queryData = { - query: ` - query searchNotes { - searchNotes { - edges { - node { - position - title - body - id - createdAt - updatedAt - deletedAt - } - } - } - } - `, - }; - - return client - .post('/graphql') - .set('Authorization', `Bearer ${ADMIN_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.searchNotes; - - expect(data).toBeDefined(); - expect(Array.isArray(data.edges)).toBe(true); - - const edges = data.edges; - - if (edges.length > 0) { - const searchNotes = edges[0].node; - - expect(searchNotes).toHaveProperty('position'); - expect(searchNotes).toHaveProperty('title'); - expect(searchNotes).toHaveProperty('body'); - expect(searchNotes).toHaveProperty('id'); - expect(searchNotes).toHaveProperty('createdAt'); - expect(searchNotes).toHaveProperty('updatedAt'); - expect(searchNotes).toHaveProperty('deletedAt'); - } - }); - }); -}); diff --git a/packages/twenty-server/test/integration/graphql/suites/object-generated/search-opportunities.integration-spec.ts b/packages/twenty-server/test/integration/graphql/suites/object-generated/search-opportunities.integration-spec.ts deleted file mode 100644 index 0009eb027..000000000 --- a/packages/twenty-server/test/integration/graphql/suites/object-generated/search-opportunities.integration-spec.ts +++ /dev/null @@ -1,65 +0,0 @@ -import request from 'supertest'; - -const client = request(`http://localhost:${APP_PORT}`); - -describe('searchOpportunitiesResolver (e2e)', () => { - it('should find many searchOpportunities', () => { - const queryData = { - query: ` - query searchOpportunities { - searchOpportunities { - edges { - node { - name - closeDate - stage - position - searchVector - id - createdAt - updatedAt - deletedAt - pointOfContactId - companyId - } - } - } - } - `, - }; - - return client - .post('/graphql') - .set('Authorization', `Bearer ${ADMIN_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.searchOpportunities; - - expect(data).toBeDefined(); - expect(Array.isArray(data.edges)).toBe(true); - - const edges = data.edges; - - if (edges.length > 0) { - const searchOpportunities = edges[0].node; - - expect(searchOpportunities).toHaveProperty('name'); - expect(searchOpportunities).toHaveProperty('closeDate'); - expect(searchOpportunities).toHaveProperty('stage'); - expect(searchOpportunities).toHaveProperty('position'); - expect(searchOpportunities).toHaveProperty('searchVector'); - expect(searchOpportunities).toHaveProperty('id'); - expect(searchOpportunities).toHaveProperty('createdAt'); - expect(searchOpportunities).toHaveProperty('updatedAt'); - expect(searchOpportunities).toHaveProperty('deletedAt'); - expect(searchOpportunities).toHaveProperty('pointOfContactId'); - expect(searchOpportunities).toHaveProperty('companyId'); - } - }); - }); -}); diff --git a/packages/twenty-server/test/integration/graphql/suites/object-generated/search-people.integration-spec.ts b/packages/twenty-server/test/integration/graphql/suites/object-generated/search-people.integration-spec.ts deleted file mode 100644 index c76afa0a3..000000000 --- a/packages/twenty-server/test/integration/graphql/suites/object-generated/search-people.integration-spec.ts +++ /dev/null @@ -1,69 +0,0 @@ -import request from 'supertest'; - -const client = request(`http://localhost:${APP_PORT}`); - -describe('searchPeopleResolver (e2e)', () => { - it('should find many searchPeople', () => { - const queryData = { - query: ` - query searchPeople { - searchPeople { - edges { - node { - jobTitle - city - avatarUrl - position - searchVector - id - createdAt - updatedAt - deletedAt - companyId - intro - workPreference - performanceRating - } - } - } - } - `, - }; - - return client - .post('/graphql') - .set('Authorization', `Bearer ${ADMIN_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.searchPeople; - - expect(data).toBeDefined(); - expect(Array.isArray(data.edges)).toBe(true); - - const edges = data.edges; - - if (edges.length > 0) { - const searchPeople = edges[0].node; - - expect(searchPeople).toHaveProperty('jobTitle'); - expect(searchPeople).toHaveProperty('city'); - expect(searchPeople).toHaveProperty('avatarUrl'); - expect(searchPeople).toHaveProperty('position'); - expect(searchPeople).toHaveProperty('searchVector'); - expect(searchPeople).toHaveProperty('id'); - expect(searchPeople).toHaveProperty('createdAt'); - expect(searchPeople).toHaveProperty('updatedAt'); - expect(searchPeople).toHaveProperty('deletedAt'); - expect(searchPeople).toHaveProperty('companyId'); - expect(searchPeople).toHaveProperty('intro'); - expect(searchPeople).toHaveProperty('workPreference'); - expect(searchPeople).toHaveProperty('performanceRating'); - } - }); - }); -}); diff --git a/packages/twenty-server/test/integration/graphql/suites/object-generated/search-rockets.integration-spec.ts b/packages/twenty-server/test/integration/graphql/suites/object-generated/search-rockets.integration-spec.ts deleted file mode 100644 index bdca97b23..000000000 --- a/packages/twenty-server/test/integration/graphql/suites/object-generated/search-rockets.integration-spec.ts +++ /dev/null @@ -1,57 +0,0 @@ -import request from 'supertest'; - -const client = request(`http://localhost:${APP_PORT}`); - -describe('searchPetsResolver (e2e)', () => { - it('should find many searchPets', () => { - const queryData = { - query: ` - query searchPets { - searchPets { - edges { - node { - id - name - createdAt - updatedAt - deletedAt - position - searchVector - } - } - } - } - `, - }; - - return client - .post('/graphql') - .set('Authorization', `Bearer ${ADMIN_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.searchPets; - - expect(data).toBeDefined(); - expect(Array.isArray(data.edges)).toBe(true); - - const edges = data.edges; - - if (edges.length > 0) { - const searchPets = edges[0].node; - - expect(searchPets).toHaveProperty('id'); - expect(searchPets).toHaveProperty('name'); - expect(searchPets).toHaveProperty('createdAt'); - expect(searchPets).toHaveProperty('updatedAt'); - expect(searchPets).toHaveProperty('deletedAt'); - expect(searchPets).toHaveProperty('position'); - expect(searchPets).toHaveProperty('searchVector'); - } - }); - }); -}); diff --git a/packages/twenty-server/test/integration/graphql/suites/object-generated/search-task-targets.integration-spec.ts b/packages/twenty-server/test/integration/graphql/suites/object-generated/search-task-targets.integration-spec.ts deleted file mode 100644 index 9934a8e08..000000000 --- a/packages/twenty-server/test/integration/graphql/suites/object-generated/search-task-targets.integration-spec.ts +++ /dev/null @@ -1,63 +0,0 @@ -import request from 'supertest'; - -const client = request(`http://localhost:${APP_PORT}`); - -describe('searchTaskTargetsResolver (e2e)', () => { - it('should find many searchTaskTargets', () => { - const queryData = { - query: ` - query searchTaskTargets { - searchTaskTargets { - edges { - node { - id - createdAt - updatedAt - deletedAt - taskId - personId - companyId - opportunityId - petId - surveyResultId - } - } - } - } - `, - }; - - return client - .post('/graphql') - .set('Authorization', `Bearer ${ADMIN_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.searchTaskTargets; - - expect(data).toBeDefined(); - expect(Array.isArray(data.edges)).toBe(true); - - const edges = data.edges; - - if (edges.length > 0) { - const searchTaskTargets = edges[0].node; - - expect(searchTaskTargets).toHaveProperty('id'); - expect(searchTaskTargets).toHaveProperty('createdAt'); - expect(searchTaskTargets).toHaveProperty('updatedAt'); - expect(searchTaskTargets).toHaveProperty('deletedAt'); - expect(searchTaskTargets).toHaveProperty('taskId'); - expect(searchTaskTargets).toHaveProperty('personId'); - expect(searchTaskTargets).toHaveProperty('companyId'); - expect(searchTaskTargets).toHaveProperty('opportunityId'); - expect(searchTaskTargets).toHaveProperty('petId'); - expect(searchTaskTargets).toHaveProperty('surveyResultId'); - } - }); - }); -}); diff --git a/packages/twenty-server/test/integration/graphql/suites/object-generated/search-tasks.integration-spec.ts b/packages/twenty-server/test/integration/graphql/suites/object-generated/search-tasks.integration-spec.ts deleted file mode 100644 index 1552c094f..000000000 --- a/packages/twenty-server/test/integration/graphql/suites/object-generated/search-tasks.integration-spec.ts +++ /dev/null @@ -1,63 +0,0 @@ -import request from 'supertest'; - -const client = request(`http://localhost:${APP_PORT}`); - -describe('searchTasksResolver (e2e)', () => { - it('should find many searchTasks', () => { - const queryData = { - query: ` - query searchTasks { - searchTasks { - edges { - node { - position - title - body - dueAt - status - id - createdAt - updatedAt - deletedAt - assigneeId - } - } - } - } - `, - }; - - return client - .post('/graphql') - .set('Authorization', `Bearer ${ADMIN_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.searchTasks; - - expect(data).toBeDefined(); - expect(Array.isArray(data.edges)).toBe(true); - - const edges = data.edges; - - if (edges.length > 0) { - const searchTasks = edges[0].node; - - expect(searchTasks).toHaveProperty('position'); - expect(searchTasks).toHaveProperty('title'); - expect(searchTasks).toHaveProperty('body'); - expect(searchTasks).toHaveProperty('dueAt'); - expect(searchTasks).toHaveProperty('status'); - expect(searchTasks).toHaveProperty('id'); - expect(searchTasks).toHaveProperty('createdAt'); - expect(searchTasks).toHaveProperty('updatedAt'); - expect(searchTasks).toHaveProperty('deletedAt'); - expect(searchTasks).toHaveProperty('assigneeId'); - } - }); - }); -}); diff --git a/packages/twenty-server/test/integration/graphql/suites/object-generated/search-timeline-activities.integration-spec.ts b/packages/twenty-server/test/integration/graphql/suites/object-generated/search-timeline-activities.integration-spec.ts deleted file mode 100644 index 92fd793a8..000000000 --- a/packages/twenty-server/test/integration/graphql/suites/object-generated/search-timeline-activities.integration-spec.ts +++ /dev/null @@ -1,89 +0,0 @@ -import request from 'supertest'; - -const client = request(`http://localhost:${APP_PORT}`); - -describe('searchTimelineActivitiesResolver (e2e)', () => { - it('should find many searchTimelineActivities', () => { - const queryData = { - query: ` - query searchTimelineActivities { - searchTimelineActivities { - edges { - node { - happensAt - name - properties - linkedRecordCachedName - linkedRecordId - linkedObjectMetadataId - id - createdAt - updatedAt - deletedAt - workspaceMemberId - personId - companyId - opportunityId - noteId - taskId - workflowId - workflowVersionId - workflowRunId - petId - surveyResultId - } - } - } - } - `, - }; - - return client - .post('/graphql') - .set('Authorization', `Bearer ${ADMIN_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.searchTimelineActivities; - - expect(data).toBeDefined(); - expect(Array.isArray(data.edges)).toBe(true); - - const edges = data.edges; - - if (edges.length > 0) { - const searchTimelineActivities = edges[0].node; - - expect(searchTimelineActivities).toHaveProperty('happensAt'); - expect(searchTimelineActivities).toHaveProperty('name'); - expect(searchTimelineActivities).toHaveProperty('properties'); - expect(searchTimelineActivities).toHaveProperty( - 'linkedRecordCachedName', - ); - expect(searchTimelineActivities).toHaveProperty('linkedRecordId'); - expect(searchTimelineActivities).toHaveProperty( - 'linkedObjectMetadataId', - ); - expect(searchTimelineActivities).toHaveProperty('id'); - expect(searchTimelineActivities).toHaveProperty('createdAt'); - expect(searchTimelineActivities).toHaveProperty('updatedAt'); - expect(searchTimelineActivities).toHaveProperty('deletedAt'); - expect(searchTimelineActivities).toHaveProperty('workspaceMemberId'); - expect(searchTimelineActivities).toHaveProperty('personId'); - expect(searchTimelineActivities).toHaveProperty('companyId'); - expect(searchTimelineActivities).toHaveProperty('opportunityId'); - expect(searchTimelineActivities).toHaveProperty('noteId'); - expect(searchTimelineActivities).toHaveProperty('taskId'); - expect(searchTimelineActivities).toHaveProperty('workflowId'); - expect(searchTimelineActivities).toHaveProperty('workflowVersionId'); - expect(searchTimelineActivities).toHaveProperty('workflowRunId'); - expect(searchTimelineActivities).toHaveProperty('petId'); - expect(searchTimelineActivities).toHaveProperty('surveyResultId'); - } - }); - }); -}); diff --git a/packages/twenty-server/test/integration/graphql/suites/object-generated/search-view-fields.integration-spec.ts b/packages/twenty-server/test/integration/graphql/suites/object-generated/search-view-fields.integration-spec.ts deleted file mode 100644 index a9b3022dc..000000000 --- a/packages/twenty-server/test/integration/graphql/suites/object-generated/search-view-fields.integration-spec.ts +++ /dev/null @@ -1,61 +0,0 @@ -import request from 'supertest'; - -const client = request(`http://localhost:${APP_PORT}`); - -describe('searchViewFieldsResolver (e2e)', () => { - it('should find many searchViewFields', () => { - const queryData = { - query: ` - query searchViewFields { - searchViewFields { - edges { - node { - fieldMetadataId - isVisible - size - position - id - createdAt - updatedAt - deletedAt - viewId - } - } - } - } - `, - }; - - return client - .post('/graphql') - .set('Authorization', `Bearer ${ADMIN_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.searchViewFields; - - expect(data).toBeDefined(); - expect(Array.isArray(data.edges)).toBe(true); - - const edges = data.edges; - - if (edges.length > 0) { - const searchViewFields = edges[0].node; - - expect(searchViewFields).toHaveProperty('fieldMetadataId'); - expect(searchViewFields).toHaveProperty('isVisible'); - expect(searchViewFields).toHaveProperty('size'); - expect(searchViewFields).toHaveProperty('position'); - expect(searchViewFields).toHaveProperty('id'); - expect(searchViewFields).toHaveProperty('createdAt'); - expect(searchViewFields).toHaveProperty('updatedAt'); - expect(searchViewFields).toHaveProperty('deletedAt'); - expect(searchViewFields).toHaveProperty('viewId'); - } - }); - }); -}); diff --git a/packages/twenty-server/test/integration/graphql/suites/object-generated/search-view-filters.integration-spec.ts b/packages/twenty-server/test/integration/graphql/suites/object-generated/search-view-filters.integration-spec.ts deleted file mode 100644 index 68d2e3622..000000000 --- a/packages/twenty-server/test/integration/graphql/suites/object-generated/search-view-filters.integration-spec.ts +++ /dev/null @@ -1,61 +0,0 @@ -import request from 'supertest'; - -const client = request(`http://localhost:${APP_PORT}`); - -describe('searchViewFiltersResolver (e2e)', () => { - it('should find many searchViewFilters', () => { - const queryData = { - query: ` - query searchViewFilters { - searchViewFilters { - edges { - node { - fieldMetadataId - operand - value - displayValue - id - createdAt - updatedAt - deletedAt - viewId - } - } - } - } - `, - }; - - return client - .post('/graphql') - .set('Authorization', `Bearer ${ADMIN_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.searchViewFilters; - - expect(data).toBeDefined(); - expect(Array.isArray(data.edges)).toBe(true); - - const edges = data.edges; - - if (edges.length > 0) { - const searchViewFilters = edges[0].node; - - expect(searchViewFilters).toHaveProperty('fieldMetadataId'); - expect(searchViewFilters).toHaveProperty('operand'); - expect(searchViewFilters).toHaveProperty('value'); - expect(searchViewFilters).toHaveProperty('displayValue'); - expect(searchViewFilters).toHaveProperty('id'); - expect(searchViewFilters).toHaveProperty('createdAt'); - expect(searchViewFilters).toHaveProperty('updatedAt'); - expect(searchViewFilters).toHaveProperty('deletedAt'); - expect(searchViewFilters).toHaveProperty('viewId'); - } - }); - }); -}); diff --git a/packages/twenty-server/test/integration/graphql/suites/object-generated/search-view-sorts.integration-spec.ts b/packages/twenty-server/test/integration/graphql/suites/object-generated/search-view-sorts.integration-spec.ts deleted file mode 100644 index b1e24b7a9..000000000 --- a/packages/twenty-server/test/integration/graphql/suites/object-generated/search-view-sorts.integration-spec.ts +++ /dev/null @@ -1,57 +0,0 @@ -import request from 'supertest'; - -const client = request(`http://localhost:${APP_PORT}`); - -describe('searchViewSortsResolver (e2e)', () => { - it('should find many searchViewSorts', () => { - const queryData = { - query: ` - query searchViewSorts { - searchViewSorts { - edges { - node { - fieldMetadataId - direction - id - createdAt - updatedAt - deletedAt - viewId - } - } - } - } - `, - }; - - return client - .post('/graphql') - .set('Authorization', `Bearer ${ADMIN_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.searchViewSorts; - - expect(data).toBeDefined(); - expect(Array.isArray(data.edges)).toBe(true); - - const edges = data.edges; - - if (edges.length > 0) { - const searchViewSorts = edges[0].node; - - expect(searchViewSorts).toHaveProperty('fieldMetadataId'); - expect(searchViewSorts).toHaveProperty('direction'); - expect(searchViewSorts).toHaveProperty('id'); - expect(searchViewSorts).toHaveProperty('createdAt'); - expect(searchViewSorts).toHaveProperty('updatedAt'); - expect(searchViewSorts).toHaveProperty('deletedAt'); - expect(searchViewSorts).toHaveProperty('viewId'); - } - }); - }); -}); diff --git a/packages/twenty-server/test/integration/graphql/suites/object-generated/search-views.integration-spec.ts b/packages/twenty-server/test/integration/graphql/suites/object-generated/search-views.integration-spec.ts deleted file mode 100644 index 4c45a6990..000000000 --- a/packages/twenty-server/test/integration/graphql/suites/object-generated/search-views.integration-spec.ts +++ /dev/null @@ -1,67 +0,0 @@ -import request from 'supertest'; - -const client = request(`http://localhost:${APP_PORT}`); - -describe('searchViewsResolver (e2e)', () => { - it('should find many searchViews', () => { - const queryData = { - query: ` - query searchViews { - searchViews { - edges { - node { - name - objectMetadataId - type - key - icon - kanbanFieldMetadataId - position - isCompact - id - createdAt - updatedAt - deletedAt - } - } - } - } - `, - }; - - return client - .post('/graphql') - .set('Authorization', `Bearer ${ADMIN_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.searchViews; - - expect(data).toBeDefined(); - expect(Array.isArray(data.edges)).toBe(true); - - const edges = data.edges; - - if (edges.length > 0) { - const searchViews = edges[0].node; - - expect(searchViews).toHaveProperty('name'); - expect(searchViews).toHaveProperty('objectMetadataId'); - expect(searchViews).toHaveProperty('type'); - expect(searchViews).toHaveProperty('key'); - expect(searchViews).toHaveProperty('icon'); - expect(searchViews).toHaveProperty('kanbanFieldMetadataId'); - expect(searchViews).toHaveProperty('position'); - expect(searchViews).toHaveProperty('isCompact'); - expect(searchViews).toHaveProperty('id'); - expect(searchViews).toHaveProperty('createdAt'); - expect(searchViews).toHaveProperty('updatedAt'); - expect(searchViews).toHaveProperty('deletedAt'); - } - }); - }); -}); diff --git a/packages/twenty-server/test/integration/graphql/suites/object-generated/search-webhooks.integration-spec.ts b/packages/twenty-server/test/integration/graphql/suites/object-generated/search-webhooks.integration-spec.ts deleted file mode 100644 index ae9ece343..000000000 --- a/packages/twenty-server/test/integration/graphql/suites/object-generated/search-webhooks.integration-spec.ts +++ /dev/null @@ -1,57 +0,0 @@ -import request from 'supertest'; - -const client = request(`http://localhost:${APP_PORT}`); - -describe('searchWebhooksResolver (e2e)', () => { - it('should find many searchWebhooks', () => { - const queryData = { - query: ` - query searchWebhooks { - searchWebhooks { - edges { - node { - id - targetUrl - operations - description - createdAt - updatedAt - deletedAt - } - } - } - } - `, - }; - - return client - .post('/graphql') - .set('Authorization', `Bearer ${ADMIN_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.searchWebhooks; - - expect(data).toBeDefined(); - expect(Array.isArray(data.edges)).toBe(true); - - const edges = data.edges; - - if (edges.length > 0) { - const searchWebhooks = edges[0].node; - - expect(searchWebhooks).toHaveProperty('id'); - expect(searchWebhooks).toHaveProperty('targetUrl'); - expect(searchWebhooks).toHaveProperty('operations'); - expect(searchWebhooks).toHaveProperty('description'); - expect(searchWebhooks).toHaveProperty('createdAt'); - expect(searchWebhooks).toHaveProperty('updatedAt'); - expect(searchWebhooks).toHaveProperty('deletedAt'); - } - }); - }); -}); diff --git a/packages/twenty-server/test/integration/graphql/suites/object-generated/search-workflow-event-listeners.integration-spec.ts b/packages/twenty-server/test/integration/graphql/suites/object-generated/search-workflow-event-listeners.integration-spec.ts deleted file mode 100644 index 8476c4eb7..000000000 --- a/packages/twenty-server/test/integration/graphql/suites/object-generated/search-workflow-event-listeners.integration-spec.ts +++ /dev/null @@ -1,55 +0,0 @@ -import request from 'supertest'; - -const client = request(`http://localhost:${APP_PORT}`); - -describe('searchWorkflowEventListenersResolver (e2e)', () => { - it('should find many searchWorkflowEventListeners', () => { - const queryData = { - query: ` - query searchWorkflowEventListeners { - searchWorkflowEventListeners { - edges { - node { - eventName - id - createdAt - updatedAt - deletedAt - workflowId - } - } - } - } - `, - }; - - return client - .post('/graphql') - .set('Authorization', `Bearer ${ADMIN_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.searchWorkflowEventListeners; - - expect(data).toBeDefined(); - expect(Array.isArray(data.edges)).toBe(true); - - const edges = data.edges; - - if (edges.length > 0) { - const searchWorkflowEventListeners = edges[0].node; - - expect(searchWorkflowEventListeners).toHaveProperty('eventName'); - expect(searchWorkflowEventListeners).toHaveProperty('id'); - expect(searchWorkflowEventListeners).toHaveProperty('createdAt'); - expect(searchWorkflowEventListeners).toHaveProperty('updatedAt'); - expect(searchWorkflowEventListeners).toHaveProperty('deletedAt'); - expect(searchWorkflowEventListeners).toHaveProperty('workflowId'); - } - }); - }); -}); diff --git a/packages/twenty-server/test/integration/graphql/suites/object-generated/search-workflow-runs.integration-spec.ts b/packages/twenty-server/test/integration/graphql/suites/object-generated/search-workflow-runs.integration-spec.ts deleted file mode 100644 index cbd18eb22..000000000 --- a/packages/twenty-server/test/integration/graphql/suites/object-generated/search-workflow-runs.integration-spec.ts +++ /dev/null @@ -1,69 +0,0 @@ -import request from 'supertest'; - -const client = request(`http://localhost:${APP_PORT}`); - -describe('searchWorkflowRunsResolver (e2e)', () => { - it('should find many searchWorkflowRuns', () => { - const queryData = { - query: ` - query searchWorkflowRuns { - searchWorkflowRuns { - edges { - node { - workflowRunId - name - startedAt - endedAt - status - output - position - id - createdAt - updatedAt - deletedAt - workflowVersionId - workflowId - } - } - } - } - `, - }; - - return client - .post('/graphql') - .set('Authorization', `Bearer ${ADMIN_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.searchWorkflowRuns; - - expect(data).toBeDefined(); - expect(Array.isArray(data.edges)).toBe(true); - - const edges = data.edges; - - if (edges.length > 0) { - const searchWorkflowRuns = edges[0].node; - - expect(searchWorkflowRuns).toHaveProperty('workflowRunId'); - expect(searchWorkflowRuns).toHaveProperty('name'); - expect(searchWorkflowRuns).toHaveProperty('startedAt'); - expect(searchWorkflowRuns).toHaveProperty('endedAt'); - expect(searchWorkflowRuns).toHaveProperty('status'); - expect(searchWorkflowRuns).toHaveProperty('output'); - expect(searchWorkflowRuns).toHaveProperty('position'); - expect(searchWorkflowRuns).toHaveProperty('id'); - expect(searchWorkflowRuns).toHaveProperty('createdAt'); - expect(searchWorkflowRuns).toHaveProperty('updatedAt'); - expect(searchWorkflowRuns).toHaveProperty('deletedAt'); - expect(searchWorkflowRuns).toHaveProperty('workflowVersionId'); - expect(searchWorkflowRuns).toHaveProperty('workflowId'); - } - }); - }); -}); diff --git a/packages/twenty-server/test/integration/graphql/suites/object-generated/search-workflow-versions.integration-spec.ts b/packages/twenty-server/test/integration/graphql/suites/object-generated/search-workflow-versions.integration-spec.ts deleted file mode 100644 index b5550f232..000000000 --- a/packages/twenty-server/test/integration/graphql/suites/object-generated/search-workflow-versions.integration-spec.ts +++ /dev/null @@ -1,63 +0,0 @@ -import request from 'supertest'; - -const client = request(`http://localhost:${APP_PORT}`); - -describe('searchWorkflowVersionsResolver (e2e)', () => { - it('should find many searchWorkflowVersions', () => { - const queryData = { - query: ` - query searchWorkflowVersions { - searchWorkflowVersions { - edges { - node { - name - trigger - steps - status - position - id - createdAt - updatedAt - deletedAt - workflowId - } - } - } - } - `, - }; - - return client - .post('/graphql') - .set('Authorization', `Bearer ${ADMIN_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.searchWorkflowVersions; - - expect(data).toBeDefined(); - expect(Array.isArray(data.edges)).toBe(true); - - const edges = data.edges; - - if (edges.length > 0) { - const searchWorkflowVersions = edges[0].node; - - expect(searchWorkflowVersions).toHaveProperty('name'); - expect(searchWorkflowVersions).toHaveProperty('trigger'); - expect(searchWorkflowVersions).toHaveProperty('steps'); - expect(searchWorkflowVersions).toHaveProperty('status'); - expect(searchWorkflowVersions).toHaveProperty('position'); - expect(searchWorkflowVersions).toHaveProperty('id'); - expect(searchWorkflowVersions).toHaveProperty('createdAt'); - expect(searchWorkflowVersions).toHaveProperty('updatedAt'); - expect(searchWorkflowVersions).toHaveProperty('deletedAt'); - expect(searchWorkflowVersions).toHaveProperty('workflowId'); - } - }); - }); -}); diff --git a/packages/twenty-server/test/integration/graphql/suites/object-generated/search-workflows.integration-spec.ts b/packages/twenty-server/test/integration/graphql/suites/object-generated/search-workflows.integration-spec.ts deleted file mode 100644 index c0ed4a128..000000000 --- a/packages/twenty-server/test/integration/graphql/suites/object-generated/search-workflows.integration-spec.ts +++ /dev/null @@ -1,59 +0,0 @@ -import request from 'supertest'; - -const client = request(`http://localhost:${APP_PORT}`); - -describe('searchWorkflowsResolver (e2e)', () => { - it('should find many searchWorkflows', () => { - const queryData = { - query: ` - query searchWorkflows { - searchWorkflows { - edges { - node { - name - lastPublishedVersionId - statuses - position - id - createdAt - updatedAt - deletedAt - } - } - } - } - `, - }; - - return client - .post('/graphql') - .set('Authorization', `Bearer ${ADMIN_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.searchWorkflows; - - expect(data).toBeDefined(); - expect(Array.isArray(data.edges)).toBe(true); - - const edges = data.edges; - - if (edges.length > 0) { - const searchWorkflows = edges[0].node; - - expect(searchWorkflows).toHaveProperty('name'); - expect(searchWorkflows).toHaveProperty('lastPublishedVersionId'); - expect(searchWorkflows).toHaveProperty('statuses'); - expect(searchWorkflows).toHaveProperty('position'); - expect(searchWorkflows).toHaveProperty('id'); - expect(searchWorkflows).toHaveProperty('createdAt'); - expect(searchWorkflows).toHaveProperty('updatedAt'); - expect(searchWorkflows).toHaveProperty('deletedAt'); - } - }); - }); -}); diff --git a/packages/twenty-server/test/integration/graphql/suites/object-generated/search-workspace-members.integration-spec.ts b/packages/twenty-server/test/integration/graphql/suites/object-generated/search-workspace-members.integration-spec.ts deleted file mode 100644 index 4408b0dbf..000000000 --- a/packages/twenty-server/test/integration/graphql/suites/object-generated/search-workspace-members.integration-spec.ts +++ /dev/null @@ -1,67 +0,0 @@ -import request from 'supertest'; - -const client = request(`http://localhost:${APP_PORT}`); - -describe('searchWorkspaceMembersResolver (e2e)', () => { - it('should find many searchWorkspaceMembers', () => { - const queryData = { - query: ` - query searchWorkspaceMembers { - searchWorkspaceMembers { - edges { - node { - id - colorScheme - avatarUrl - locale - timeZone - dateFormat - timeFormat - userEmail - userId - createdAt - updatedAt - deletedAt - } - } - } - } - `, - }; - - return client - .post('/graphql') - .set('Authorization', `Bearer ${ADMIN_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.searchWorkspaceMembers; - - expect(data).toBeDefined(); - expect(Array.isArray(data.edges)).toBe(true); - - const edges = data.edges; - - if (edges.length > 0) { - const searchWorkspaceMembers = edges[0].node; - - expect(searchWorkspaceMembers).toHaveProperty('id'); - expect(searchWorkspaceMembers).toHaveProperty('colorScheme'); - expect(searchWorkspaceMembers).toHaveProperty('avatarUrl'); - expect(searchWorkspaceMembers).toHaveProperty('locale'); - expect(searchWorkspaceMembers).toHaveProperty('timeZone'); - expect(searchWorkspaceMembers).toHaveProperty('dateFormat'); - expect(searchWorkspaceMembers).toHaveProperty('timeFormat'); - expect(searchWorkspaceMembers).toHaveProperty('userEmail'); - expect(searchWorkspaceMembers).toHaveProperty('userId'); - expect(searchWorkspaceMembers).toHaveProperty('createdAt'); - expect(searchWorkspaceMembers).toHaveProperty('updatedAt'); - expect(searchWorkspaceMembers).toHaveProperty('deletedAt'); - } - }); - }); -}); diff --git a/packages/twenty-server/test/integration/graphql/suites/settings-permissions/data-model.integration-spec.ts b/packages/twenty-server/test/integration/graphql/suites/settings-permissions/data-model.integration-spec.ts index 5311cd63a..03d7b0afa 100644 --- a/packages/twenty-server/test/integration/graphql/suites/settings-permissions/data-model.integration-spec.ts +++ b/packages/twenty-server/test/integration/graphql/suites/settings-permissions/data-model.integration-spec.ts @@ -3,7 +3,6 @@ import { updateFeatureFlagFactory } from 'test/integration/graphql/utils/update- import { createCustomTextFieldMetadata } from 'test/integration/metadata/suites/field-metadata/utils/create-custom-text-field-metadata.util'; import { createOneFieldMetadataFactory } from 'test/integration/metadata/suites/field-metadata/utils/create-one-field-metadata-factory.util'; import { deleteOneFieldMetadataItemFactory } from 'test/integration/metadata/suites/field-metadata/utils/delete-one-field-metadata-factory.util'; -import { deleteFieldMetadata } from 'test/integration/metadata/suites/field-metadata/utils/delete-one-field-metadata.util'; import { updateOneFieldMetadataFactory } from 'test/integration/metadata/suites/field-metadata/utils/update-one-field-metadata-factory.util'; import { createOneObjectMetadataFactory } from 'test/integration/metadata/suites/object-metadata/utils/create-one-object-metadata-factory.util'; import { createListingCustomObject } from 'test/integration/metadata/suites/object-metadata/utils/create-test-object-metadata.util'; @@ -52,7 +51,6 @@ describe('datamodel permissions', () => { testFieldId = createdFieldMetadaId; }); afterAll(async () => { - await deleteFieldMetadata(testFieldId); await deleteOneObjectMetadataItem(listingObjectId); }); describe('createOne', () => { diff --git a/packages/twenty-server/test/integration/graphql/suites/settings-permissions/workspace.integration-spec.ts b/packages/twenty-server/test/integration/graphql/suites/settings-permissions/workspace.integration-spec.ts index 34e7db383..a54df968d 100644 --- a/packages/twenty-server/test/integration/graphql/suites/settings-permissions/workspace.integration-spec.ts +++ b/packages/twenty-server/test/integration/graphql/suites/settings-permissions/workspace.integration-spec.ts @@ -485,7 +485,9 @@ describe('workspace permissions', () => { .expect((res) => { expect(res.body.data).toBeDefined(); expect(res.body.errors).toBeDefined(); - expect(res.body.errors[0].message).toBe('Invalid feature flag key'); // this error shows that update has been attempted after the permission check + expect(res.body.errors[0].message).toBe( + 'Invalid feature flag key, flag is not public', + ); }); }); diff --git a/packages/twenty-server/test/integration/metadata/suites/field-metadata/create-one-field-metadata.integration-spec.ts b/packages/twenty-server/test/integration/metadata/suites/field-metadata/create-one-field-metadata.integration-spec.ts index e4a29aef1..8f7e8a5a0 100644 --- a/packages/twenty-server/test/integration/metadata/suites/field-metadata/create-one-field-metadata.integration-spec.ts +++ b/packages/twenty-server/test/integration/metadata/suites/field-metadata/create-one-field-metadata.integration-spec.ts @@ -32,10 +32,10 @@ describe('createOne', () => { const graphqlOperation = createOneFieldMetadataFactory({ input: { field: createFieldInput }, gqlFields: ` - id - name - label - isLabelSyncedWithName + id + name + label + isLabelSyncedWithName `, }); @@ -58,10 +58,10 @@ describe('createOne', () => { const graphqlOperation = createOneFieldMetadataFactory({ input: { field: createFieldInput }, gqlFields: ` - id - name - label - isLabelSyncedWithName + id + name + label + isLabelSyncedWithName `, }); diff --git a/packages/twenty-server/test/integration/metadata/suites/field-metadata/delete-one-field-metadata.integration-spec.ts b/packages/twenty-server/test/integration/metadata/suites/field-metadata/delete-one-field-metadata.integration-spec.ts index ec5db3292..a6ef9219d 100644 --- a/packages/twenty-server/test/integration/metadata/suites/field-metadata/delete-one-field-metadata.integration-spec.ts +++ b/packages/twenty-server/test/integration/metadata/suites/field-metadata/delete-one-field-metadata.integration-spec.ts @@ -1,5 +1,4 @@ import { createOneOperationFactory } from 'test/integration/graphql/utils/create-one-operation-factory.util'; -import { deleteOneOperationFactory } from 'test/integration/graphql/utils/delete-one-operation-factory.util'; import { findOneOperationFactory } from 'test/integration/graphql/utils/find-one-operation-factory.util'; import { makeGraphqlAPIRequest } from 'test/integration/graphql/utils/make-graphql-api-request.util'; import { createCustomTextFieldMetadata } from 'test/integration/metadata/suites/field-metadata/utils/create-custom-text-field-metadata.util'; @@ -50,14 +49,6 @@ describe('deleteOne', () => { viewId = createdView.id; }); afterEach(async () => { - // delete view - const deleteViewOperation = deleteOneOperationFactory({ - objectMetadataSingularName: 'View', - gqlFields: 'id', - recordId: viewId, - }); - - await makeGraphqlAPIRequest(deleteViewOperation); await deleteOneObjectMetadataItem(listingObjectId); }); it('should reset kanban aggregate operation when deleting a field used as kanbanAggregateOperationFieldMetadataId', async () => { diff --git a/packages/twenty-server/test/integration/metadata/suites/field-metadata/update-one-field-metadata.integration-spec.ts b/packages/twenty-server/test/integration/metadata/suites/field-metadata/update-one-field-metadata.integration-spec.ts index fc20c7907..ba3df6c96 100644 --- a/packages/twenty-server/test/integration/metadata/suites/field-metadata/update-one-field-metadata.integration-spec.ts +++ b/packages/twenty-server/test/integration/metadata/suites/field-metadata/update-one-field-metadata.integration-spec.ts @@ -1,5 +1,4 @@ import { createCustomTextFieldMetadata } from 'test/integration/metadata/suites/field-metadata/utils/create-custom-text-field-metadata.util'; -import { deleteFieldMetadata } from 'test/integration/metadata/suites/field-metadata/utils/delete-one-field-metadata.util'; import { updateOneFieldMetadataFactory } from 'test/integration/metadata/suites/field-metadata/utils/update-one-field-metadata-factory.util'; import { createListingCustomObject } from 'test/integration/metadata/suites/object-metadata/utils/create-test-object-metadata.util'; import { deleteOneObjectMetadataItem } from 'test/integration/metadata/suites/object-metadata/utils/delete-one-object-metadata.util'; @@ -22,7 +21,6 @@ describe('updateOne', () => { testFieldId = createdFieldMetadaId; }); afterEach(async () => { - await deleteFieldMetadata(testFieldId); await deleteOneObjectMetadataItem(listingObjectId); }); diff --git a/packages/twenty-server/test/integration/metadata/suites/object-metadata/failing-create-one-object-metadata.integration-spec.ts b/packages/twenty-server/test/integration/metadata/suites/object-metadata/failing-create-one-object-metadata.integration-spec.ts index 31e4b7ba8..f71d4ab54 100644 --- a/packages/twenty-server/test/integration/metadata/suites/object-metadata/failing-create-one-object-metadata.integration-spec.ts +++ b/packages/twenty-server/test/integration/metadata/suites/object-metadata/failing-create-one-object-metadata.integration-spec.ts @@ -2,8 +2,8 @@ import { getMockCreateObjectInput } from 'test/integration/utils/object-metadata import { performFailingObjectMetadataCreation } from 'test/integration/utils/object-metadata/perform-failing-object-metadata-creation'; import { EachTestingContext } from 'twenty-shared'; -import { CreateObjectInput } from 'src/engine/metadata-modules/object-metadata/dtos/create-object.input'; import { ErrorCode } from 'src/engine/core-modules/graphql/utils/graphql-errors.util'; +import { CreateObjectInput } from 'src/engine/metadata-modules/object-metadata/dtos/create-object.input'; type CreateObjectInputPayload = Omit< CreateObjectInput, diff --git a/packages/twenty-server/test/integration/metadata/suites/object-metadata/rename-custom-object.integration-spec.ts b/packages/twenty-server/test/integration/metadata/suites/object-metadata/rename-custom-object.integration-spec.ts index 8b96d3baa..6effe14b1 100644 --- a/packages/twenty-server/test/integration/metadata/suites/object-metadata/rename-custom-object.integration-spec.ts +++ b/packages/twenty-server/test/integration/metadata/suites/object-metadata/rename-custom-object.integration-spec.ts @@ -168,7 +168,7 @@ describe('Custom object renaming', () => { // Act const createRelationGraphqlOperation = createOneRelationMetadataFactory({ input: { - relation: { + relationMetadata: { fromDescription: '', fromIcon: 'IconRelationOneToMany', fromLabel: 'Guest', @@ -193,10 +193,10 @@ describe('Custom object renaming', () => { ); // Assert - customRelationId = relationResponse.body.data.createOneRelation.id; + customRelationId = relationResponse.body.data.createOneRelationMetadata.id; relationFieldMetadataOnPersonId = - relationResponse.body.data.createOneRelation.fromFieldMetadataId; + relationResponse.body.data.createOneRelationMetadata.fromFieldMetadataId; }); it('3. should rename custom object', async () => { diff --git a/packages/twenty-server/test/integration/metadata/suites/object-metadata/utils/create-test-object-metadata.util.ts b/packages/twenty-server/test/integration/metadata/suites/object-metadata/utils/create-test-object-metadata.util.ts index bc64f863f..b269dfca3 100644 --- a/packages/twenty-server/test/integration/metadata/suites/object-metadata/utils/create-test-object-metadata.util.ts +++ b/packages/twenty-server/test/integration/metadata/suites/object-metadata/utils/create-test-object-metadata.util.ts @@ -17,9 +17,9 @@ export const createListingCustomObject = async () => { const createObjectOperation = createOneObjectMetadataFactory({ input: { object: LISTING_OBJECT }, gqlFields: ` - id - nameSingular - `, + id + nameSingular + `, }); const response = await makeMetadataAPIRequest(createObjectOperation); diff --git a/packages/twenty-server/test/integration/metadata/suites/object-metadata/utils/objects-metadata-factory.util.ts b/packages/twenty-server/test/integration/metadata/suites/object-metadata/utils/objects-metadata-factory.util.ts index 02531af1d..d76d76100 100644 --- a/packages/twenty-server/test/integration/metadata/suites/object-metadata/utils/objects-metadata-factory.util.ts +++ b/packages/twenty-server/test/integration/metadata/suites/object-metadata/utils/objects-metadata-factory.util.ts @@ -17,7 +17,7 @@ export const objectsMetadataFactory = ({ objects(filter: $filter, paging: $paging) { edges { node { - ${gqlFields} + ${gqlFields} } } } diff --git a/packages/twenty-server/test/integration/metadata/suites/utils/create-one-relation-metadata-factory.util.ts b/packages/twenty-server/test/integration/metadata/suites/utils/create-one-relation-metadata-factory.util.ts index 0f6479b33..e67f156a8 100644 --- a/packages/twenty-server/test/integration/metadata/suites/utils/create-one-relation-metadata-factory.util.ts +++ b/packages/twenty-server/test/integration/metadata/suites/utils/create-one-relation-metadata-factory.util.ts @@ -5,7 +5,7 @@ import { CreateRelationInput } from 'src/engine/metadata-modules/relation-metada type CreateOneRelationFactoryParams = { gqlFields: string; input?: { - relation: Omit; + relationMetadata: Omit; }; }; diff --git a/packages/twenty-server/test/integration/metadata/suites/utils/fields-metadata-factory.util.ts b/packages/twenty-server/test/integration/metadata/suites/utils/fields-metadata-factory.util.ts index 97eb83291..b8157d248 100644 --- a/packages/twenty-server/test/integration/metadata/suites/utils/fields-metadata-factory.util.ts +++ b/packages/twenty-server/test/integration/metadata/suites/utils/fields-metadata-factory.util.ts @@ -13,11 +13,11 @@ export const fieldsMetadataFactory = ({ input, }: FieldsFactoryParams) => ({ query: gql` - query FieldsMetadata($filter: fieldFilter!, $paging: CursorPaging!) { + query FieldsMetadata($filter: FieldFilter!, $paging: CursorPaging!) { fields(filter: $filter, paging: $paging) { edges { node { - ${gqlFields} + ${gqlFields} } } } diff --git a/packages/twenty-server/test/integration/rest/suites/rest-api-core-create-one.integration-spec.ts b/packages/twenty-server/test/integration/rest/suites/rest-api-core-create-one.integration-spec.ts index fc60cb4f8..d1b3bc5fd 100644 --- a/packages/twenty-server/test/integration/rest/suites/rest-api-core-create-one.integration-spec.ts +++ b/packages/twenty-server/test/integration/rest/suites/rest-api-core-create-one.integration-spec.ts @@ -5,7 +5,7 @@ import { import { makeRestAPIRequest } from 'test/integration/rest/utils/make-rest-api-request.util'; import { generateRecordName } from 'test/integration/utils/generate-record-name'; -describe('Core REST API Create One endpoint', () => { +describe.skip('Core REST API Create One endpoint', () => { afterAll(async () => { await makeRestAPIRequest({ method: 'delete', diff --git a/packages/twenty-server/test/integration/rest/suites/rest-api-core-delete.integration-spec.ts b/packages/twenty-server/test/integration/rest/suites/rest-api-core-delete.integration-spec.ts index 70a27d894..ff6cf123e 100644 --- a/packages/twenty-server/test/integration/rest/suites/rest-api-core-delete.integration-spec.ts +++ b/packages/twenty-server/test/integration/rest/suites/rest-api-core-delete.integration-spec.ts @@ -8,7 +8,7 @@ import { makeGraphqlAPIRequest } from 'test/integration/graphql/utils/make-graph import { makeRestAPIRequest } from 'test/integration/rest/utils/make-rest-api-request.util'; import { generateRecordName } from 'test/integration/utils/generate-record-name'; -describe('Core REST API Delete One endpoint', () => { +describe.skip('Core REST API Delete One endpoint', () => { let people: any; beforeAll(async () => { diff --git a/packages/twenty-server/test/integration/rest/suites/rest-api-core-update.integration-spec.ts b/packages/twenty-server/test/integration/rest/suites/rest-api-core-update.integration-spec.ts index ea773f024..92d248e1f 100644 --- a/packages/twenty-server/test/integration/rest/suites/rest-api-core-update.integration-spec.ts +++ b/packages/twenty-server/test/integration/rest/suites/rest-api-core-update.integration-spec.ts @@ -6,7 +6,7 @@ import { import { makeRestAPIRequest } from 'test/integration/rest/utils/make-rest-api-request.util'; import { generateRecordName } from 'test/integration/utils/generate-record-name'; -describe('Core REST API Update One endpoint', () => { +describe.skip('Core REST API Update One endpoint', () => { let initialPersonData; beforeAll(async () => {