From eff19c4205ecdff3a29c0a74bf72eed86012fd83 Mon Sep 17 00:00:00 2001 From: William Phetsinorath Date: Tue, 4 Aug 2026 17:02:05 +0200 Subject: [PATCH 1/6] refactor(server-nestjs): rename Controller vars to Service in e2e specs Signed-off-by: William Phetsinorath Change-Id: I52821443aadd7c74cfcd7a88c90996ab6a6a6964 --- apps/server-nestjs/test/argocd.e2e-spec.ts | 10 +++--- apps/server-nestjs/test/gitlab.e2e-spec.ts | 26 ++++++++-------- apps/server-nestjs/test/keycloak.e2e-spec.ts | 32 ++++++++++---------- apps/server-nestjs/test/nexus.e2e-spec.ts | 10 +++--- apps/server-nestjs/test/vault.e2e-spec.ts | 10 +++--- 5 files changed, 44 insertions(+), 44 deletions(-) diff --git a/apps/server-nestjs/test/argocd.e2e-spec.ts b/apps/server-nestjs/test/argocd.e2e-spec.ts index 67f42a78f6..01e414fa8c 100644 --- a/apps/server-nestjs/test/argocd.e2e-spec.ts +++ b/apps/server-nestjs/test/argocd.e2e-spec.ts @@ -25,9 +25,9 @@ const canRunArgoCDE2E const describeWithArgoCD = describe.runIf(canRunArgoCDE2E) -describeWithArgoCD('ArgoCDController (e2e)', {}, () => { +describeWithArgoCD('ArgoCDService (e2e)', {}, () => { let moduleRef: TestingModule - let argocdController: ArgoCDService + let argocdService: ArgoCDService let gitlab: GitlabClientService let gitlabClient: Gitlab let vault: VaultClientService @@ -60,7 +60,7 @@ describeWithArgoCD('ArgoCDController (e2e)', {}, () => { await moduleRef.init() - argocdController = moduleRef.get(ArgoCDService) + argocdService = moduleRef.get(ArgoCDService) gitlab = moduleRef.get(GitlabClientService) gitlabClient = moduleRef.get(GITLAB_REST_CLIENT) vault = moduleRef.get(VaultClientService) @@ -252,7 +252,7 @@ describeWithArgoCD('ArgoCDController (e2e)', {}, () => { const staleAction = await gitlab.generateCreateOrUpdateAction(infraProject, 'main', staleFilePath, 'stale: true\n') await gitlab.maybeCreateCommit(infraProject, 'ci: :robot_face: Seed stale values', staleAction ? [staleAction] : []) - await argocdController.handleUpsert(project) + await argocdService.handleUpsert(project) const expectedFilePath = `${project.name}/${clusterLabel}/${envDevName}/values.yaml` const file = await gitlabClient.RepositoryFiles.show(infraRepoId, expectedFilePath, 'main') @@ -294,7 +294,7 @@ describeWithArgoCD('ArgoCDController (e2e)', {}, () => { select: projectSelect, }) - await argocdController.handleUpsert(after) + await argocdService.handleUpsert(after) const updatedDev = await gitlabClient.RepositoryFiles.show(infraRepoId, devFilePath, 'main') const devRaw = Buffer.from(updatedDev.content, 'base64').toString('utf8') diff --git a/apps/server-nestjs/test/gitlab.e2e-spec.ts b/apps/server-nestjs/test/gitlab.e2e-spec.ts index 32f51abf3d..0bbdb39f9b 100644 --- a/apps/server-nestjs/test/gitlab.e2e-spec.ts +++ b/apps/server-nestjs/test/gitlab.e2e-spec.ts @@ -25,10 +25,10 @@ const canRunGitlabE2E const describeWithGitLab = describe.runIf(canRunGitlabE2E) -describeWithGitLab('GitlabController (e2e)', {}, () => { +describeWithGitLab('GitlabService (e2e)', {}, () => { let moduleRef: TestingModule - let gitlabController: GitlabService - let gitlabService: GitlabClientService + let gitlabService: GitlabService + let gitlabClientService: GitlabClientService let gitlabClient: Gitlab let vaultService: VaultClientService let prisma: PrismaService @@ -46,8 +46,8 @@ describeWithGitLab('GitlabController (e2e)', {}, () => { await moduleRef.init() - gitlabController = moduleRef.get(GitlabService) - gitlabService = moduleRef.get(GitlabClientService) + gitlabService = moduleRef.get(GitlabService) + gitlabClientService = moduleRef.get(GitlabClientService) gitlabClient = moduleRef.get(GITLAB_REST_CLIENT) vaultService = moduleRef.get(VaultClientService) prisma = moduleRef.get(PrismaService) @@ -109,9 +109,9 @@ describeWithGitLab('GitlabController (e2e)', {}, () => { // Clean GitLab group if (testProjectSlug && config.projectsRootDir) { const fullPath = `${config.projectsRootDir}/${testProjectSlug}` - const group = await gitlabService.getGroupByPath(fullPath) + const group = await gitlabClientService.getGroupByPath(fullPath) if (group) { - await gitlabService.deleteGroup(group).catch(() => {}) + await gitlabClientService.deleteGroup(group).catch(() => {}) } } @@ -146,7 +146,7 @@ describeWithGitLab('GitlabController (e2e)', {}, () => { }) // Act - await gitlabController.handleUpsert(project) + await gitlabService.handleUpsert(project) // Assert const groupPath = `${config.projectsRootDir}/${testProjectSlug}` @@ -155,11 +155,11 @@ describeWithGitLab('GitlabController (e2e)', {}, () => { name: z.string(), full_path: z.string(), web_url: z.string(), - }).parse(await gitlabService.getGroupByPath(groupPath)) + }).parse(await gitlabClientService.getGroupByPath(groupPath)) expect(group.full_path).toBe(groupPath) // Check membership - const members = await gitlabService.getGroupMembers(group) + const members = await gitlabClientService.getGroupMembers(group) const isMember = members.some(m => m.id === ownerUser.id) expect(isMember).toBe(true) @@ -219,16 +219,16 @@ describeWithGitLab('GitlabController (e2e)', {}, () => { select: projectSelect, }) - await gitlabController.handleUpsert(project) + await gitlabService.handleUpsert(project) const groupPath = `${config.projectsRootDir}/${testProjectSlug}` const group = z.object({ id: z.number(), name: z.string(), web_url: z.string(), - }).parse(await gitlabService.getGroupByPath(groupPath)) + }).parse(await gitlabClientService.getGroupByPath(groupPath)) - const members = await gitlabService.getGroupMembers(group) + const members = await gitlabClientService.getGroupMembers(group) const isNewMemberPresent = members.some(m => m.id === newUserGitlabId) expect(isNewMemberPresent).toBe(true) }, 72000) diff --git a/apps/server-nestjs/test/keycloak.e2e-spec.ts b/apps/server-nestjs/test/keycloak.e2e-spec.ts index b6efcd4e42..12417a1b55 100644 --- a/apps/server-nestjs/test/keycloak.e2e-spec.ts +++ b/apps/server-nestjs/test/keycloak.e2e-spec.ts @@ -24,9 +24,9 @@ const canRunKeycloakE2E const describeWithKeycloak = describe.runIf(canRunKeycloakE2E) -describeWithKeycloak('KeycloakController (e2e)', () => { +describeWithKeycloak('KeycloakService (e2e)', () => { let moduleRef: TestingModule - let keycloakController: KeycloakService + let keycloakService: KeycloakService let keycloak: KeycloakClientService let keycloakAdminClient: KcAdminClient let prisma: PrismaService @@ -44,7 +44,7 @@ describeWithKeycloak('KeycloakController (e2e)', () => { await moduleRef.init() - keycloakController = moduleRef.get(KeycloakService) + keycloakService = moduleRef.get(KeycloakService) keycloak = moduleRef.get(KeycloakClientService) keycloakAdminClient = moduleRef.get(KEYCLOAK_ADMIN_CLIENT) prisma = moduleRef.get(PrismaService) @@ -147,7 +147,7 @@ describeWithKeycloak('KeycloakController (e2e)', () => { }) // Act - await keycloakController.handleUpsert(project) + await keycloakService.handleUpsert(project) // Assert // Check main project group @@ -215,7 +215,7 @@ describeWithKeycloak('KeycloakController (e2e)', () => { }) // Act - await keycloakController.handleUpsert(project) + await keycloakService.handleUpsert(project) // Assert const projectGroup = z.object({ @@ -278,7 +278,7 @@ describeWithKeycloak('KeycloakController (e2e)', () => { }) // Sync add - await keycloakController.handleUpsert(project) + await keycloakService.handleUpsert(project) // Verify added const projectGroup = z.object({ @@ -303,7 +303,7 @@ describeWithKeycloak('KeycloakController (e2e)', () => { }) // Sync remove - await keycloakController.handleUpsert(project) + await keycloakService.handleUpsert(project) // Verify removed members = await keycloak.getGroupMembers(projectGroup.id) @@ -343,7 +343,7 @@ describeWithKeycloak('KeycloakController (e2e)', () => { }) // Act - should not throw - await expect(keycloakController.handleUpsert(project)).resolves.not.toThrow() + await expect(keycloakService.handleUpsert(project)).resolves.not.toThrow() // Cleanup await prisma.projectMembers.deleteMany({ where: { userId: fakeUserId } }) @@ -387,7 +387,7 @@ describeWithKeycloak('KeycloakController (e2e)', () => { }) // Sync to ensure they are added initially - await keycloakController.handleUpsert(project) + await keycloakService.handleUpsert(project) const projectGroup = z.object({ id: z.string(), @@ -401,7 +401,7 @@ describeWithKeycloak('KeycloakController (e2e)', () => { expect(members.some(m => m.id === kcUser.id)).toBe(false) // Sync again - await keycloakController.handleUpsert(project) + await keycloakService.handleUpsert(project) // Verify added back members = await keycloak.getGroupMembers(projectGroup.id) @@ -447,7 +447,7 @@ describeWithKeycloak('KeycloakController (e2e)', () => { }) // Sync to create group - await keycloakController.handleUpsert(project) + await keycloakService.handleUpsert(project) // Manually add user to Keycloak group const projectGroup = z.object({ @@ -460,7 +460,7 @@ describeWithKeycloak('KeycloakController (e2e)', () => { expect(members.some(m => m.id === kcUser.id)).toBe(true) // Sync again to remove user - await keycloakController.handleUpsert(project) + await keycloakService.handleUpsert(project) // Verify removed members = await keycloak.getGroupMembers(projectGroup.id) @@ -478,7 +478,7 @@ describeWithKeycloak('KeycloakController (e2e)', () => { where: { id: testProjectId }, select: projectSelect, }) - await keycloakController.handleUpsert(project) + await keycloakService.handleUpsert(project) const projectGroup = z.object({ id: z.string(), @@ -492,7 +492,7 @@ describeWithKeycloak('KeycloakController (e2e)', () => { expect(deletedProjectGroup).toBeUndefined() // Sync - await keycloakController.handleUpsert(project) + await keycloakService.handleUpsert(project) // Verify recreated const recreatedProjectGroup = z.object({ @@ -507,7 +507,7 @@ describeWithKeycloak('KeycloakController (e2e)', () => { where: { id: testProjectId }, select: projectSelect, }) - await keycloakController.handleUpsert(project) + await keycloakService.handleUpsert(project) const roleGroup = z.object({ id: z.string(), @@ -521,7 +521,7 @@ describeWithKeycloak('KeycloakController (e2e)', () => { expect(deletedRoleGroup).toBeUndefined() // Sync - await keycloakController.handleUpsert(project) + await keycloakService.handleUpsert(project) // Verify recreated const recreatedRoleGroup = z.object({ diff --git a/apps/server-nestjs/test/nexus.e2e-spec.ts b/apps/server-nestjs/test/nexus.e2e-spec.ts index d74d66ee82..93841f88c2 100644 --- a/apps/server-nestjs/test/nexus.e2e-spec.ts +++ b/apps/server-nestjs/test/nexus.e2e-spec.ts @@ -28,9 +28,9 @@ const canRunNexusE2E const describeWithNexus = describe.runIf(canRunNexusE2E) -describeWithNexus('NexusController (e2e)', () => { +describeWithNexus('NexusService (e2e)', () => { let moduleRef: TestingModule - let nexusController: NexusService + let nexusService: NexusService let nexusClient: NexusClientService let vaultService: VaultClientService let config: ConfigType @@ -47,7 +47,7 @@ describeWithNexus('NexusController (e2e)', () => { await moduleRef.init() - nexusController = moduleRef.get(NexusService) + nexusService = moduleRef.get(NexusService) nexusClient = moduleRef.get(NexusClientService) vaultService = moduleRef.get(VaultClientService) config = moduleRef.get(baseConfigFactory.KEY) @@ -70,7 +70,7 @@ describeWithNexus('NexusController (e2e)', () => { afterAll(async () => { if (testProjectSlug) { - await nexusController.handleDelete(makeProjectWithDetails({ slug: testProjectSlug })).catch(() => {}) + await nexusService.handleDelete(makeProjectWithDetails({ slug: testProjectSlug })).catch(() => {}) } if (prisma) { @@ -112,7 +112,7 @@ describeWithNexus('NexusController (e2e)', () => { select: projectSelect, }) - await nexusController.handleUpsert(project) + await nexusService.handleUpsert(project) const mavenReleaseRepo = `${testProjectSlug}-repository-release` const mavenSnapshotRepo = `${testProjectSlug}-repository-snapshot` diff --git a/apps/server-nestjs/test/vault.e2e-spec.ts b/apps/server-nestjs/test/vault.e2e-spec.ts index 819c62dc92..a2696732cc 100644 --- a/apps/server-nestjs/test/vault.e2e-spec.ts +++ b/apps/server-nestjs/test/vault.e2e-spec.ts @@ -22,9 +22,9 @@ const canRunVaultE2E const describeWithVault = describe.runIf(canRunVaultE2E) -describeWithVault('VaultController (e2e)', () => { +describeWithVault('VaultService (e2e)', () => { let moduleRef: TestingModule - let vaultController: VaultService + let vaultService: VaultService let vaultClient: VaultClientService let prisma: PrismaService @@ -39,7 +39,7 @@ describeWithVault('VaultController (e2e)', () => { await moduleRef.init() - vaultController = moduleRef.get(VaultService) + vaultService = moduleRef.get(VaultService) vaultClient = moduleRef.get(VaultClientService) prisma = moduleRef.get(PrismaService) @@ -60,7 +60,7 @@ describeWithVault('VaultController (e2e)', () => { afterAll(async () => { if (testProjectSlug) { - await vaultController.handleDelete(makeProjectWithDetails({ slug: testProjectSlug })).catch(() => {}) + await vaultService.handleDelete(makeProjectWithDetails({ slug: testProjectSlug })).catch(() => {}) } if (prisma) { @@ -95,7 +95,7 @@ describeWithVault('VaultController (e2e)', () => { select: projectSelect, }) - await vaultController.handleUpsert(project) + await vaultService.handleUpsert(project) const group = await vaultClient.getIdentityGroupName(testProjectSlug) expect(group.data?.id).toBeTruthy() From 87f5a907e625cfd9fe70b79ec64aff396ef73586 Mon Sep 17 00:00:00 2001 From: William Phetsinorath Date: Tue, 4 Aug 2026 17:02:27 +0200 Subject: [PATCH 2/6] test(server-nestjs): align E2E specs with DSO orchestration Signed-off-by: William Phetsinorath Change-Id: I217045bef20e4cdabe25f49d312165d16a6a6964 --- apps/server-nestjs/test/argocd.e2e-spec.ts | 4 +- apps/server-nestjs/test/gitlab.e2e-spec.ts | 15 +++- apps/server-nestjs/test/keycloak.e2e-spec.ts | 15 ++++ apps/server-nestjs/test/log.e2e-spec.ts | 30 ++++--- apps/server-nestjs/test/nexus.e2e-spec.ts | 20 +++++ .../test/project-bulk.e2e-spec.ts | 4 +- .../test/project-hooks.e2e-spec.ts | 4 +- .../test/project-members.e2e-spec.ts | 4 +- .../test/project-roles.e2e-spec.ts | 4 +- .../test/project-secrets.e2e-spec.ts | 2 +- .../test/project-services.e2e-spec.ts | 15 ++-- apps/server-nestjs/test/project.e2e-spec.ts | 8 +- apps/server-nestjs/test/registry.e2e-spec.ts | 9 +++ apps/server-nestjs/test/vault.e2e-spec.ts | 18 ++++- apps/server-nestjs/test/zone.e2e-spec.ts | 79 +++++++++++++++++++ 15 files changed, 191 insertions(+), 40 deletions(-) create mode 100644 apps/server-nestjs/test/zone.e2e-spec.ts diff --git a/apps/server-nestjs/test/argocd.e2e-spec.ts b/apps/server-nestjs/test/argocd.e2e-spec.ts index 01e414fa8c..f3a98dac9a 100644 --- a/apps/server-nestjs/test/argocd.e2e-spec.ts +++ b/apps/server-nestjs/test/argocd.e2e-spec.ts @@ -25,7 +25,7 @@ const canRunArgoCDE2E const describeWithArgoCD = describe.runIf(canRunArgoCDE2E) -describeWithArgoCD('ArgoCDService (e2e)', {}, () => { +describeWithArgoCD('ArgoCDService (e2e)', () => { let moduleRef: TestingModule let argocdService: ArgoCDService let gitlab: GitlabClientService @@ -212,7 +212,7 @@ describeWithArgoCD('ArgoCDService (e2e)', {}, () => { vaultProjectValuesPath = `${config.projectsRootDir}/${testProjectId}` await vault.write({ e2e: true }, vaultProjectValuesPath) - }) + }, 144000) afterAll(async () => { if (vaultProjectValuesPath) { diff --git a/apps/server-nestjs/test/gitlab.e2e-spec.ts b/apps/server-nestjs/test/gitlab.e2e-spec.ts index 0bbdb39f9b..01ca74d515 100644 --- a/apps/server-nestjs/test/gitlab.e2e-spec.ts +++ b/apps/server-nestjs/test/gitlab.e2e-spec.ts @@ -25,7 +25,7 @@ const canRunGitlabE2E const describeWithGitLab = describe.runIf(canRunGitlabE2E) -describeWithGitLab('GitlabService (e2e)', {}, () => { +describeWithGitLab('GitlabService (e2e)', () => { let moduleRef: TestingModule let gitlabService: GitlabService let gitlabClientService: GitlabClientService @@ -233,4 +233,17 @@ describeWithGitLab('GitlabService (e2e)', {}, () => { expect(isNewMemberPresent).toBe(true) }, 72000) }) + + it('should remove project group from GitLab on delete', async () => { + const project = await prisma.project.findUniqueOrThrow({ + where: { id: testProjectId }, + select: projectSelect, + }) + + await gitlabService.handleDelete(project) + + const groupPath = `${config.projectsRootDir}/${testProjectSlug}` + const group = await gitlabClientService.getGroupByPath(groupPath) + expect(group).toBeUndefined() + }, 72000) }) diff --git a/apps/server-nestjs/test/keycloak.e2e-spec.ts b/apps/server-nestjs/test/keycloak.e2e-spec.ts index 12417a1b55..c45458fc18 100644 --- a/apps/server-nestjs/test/keycloak.e2e-spec.ts +++ b/apps/server-nestjs/test/keycloak.e2e-spec.ts @@ -529,4 +529,19 @@ describeWithKeycloak('KeycloakService (e2e)', () => { }).parse(await keycloak.getGroupByPath(`/${testProjectSlug}/console/${testRoleName}`)) expect(recreatedRoleGroup?.name).toBe(testRoleName) }, 60000) + + it('should remove project groups from Keycloak on delete', async () => { + const project = await prisma.project.findUniqueOrThrow({ + where: { id: testProjectId }, + select: projectSelect, + }) + + await keycloakService.handleDelete(project) + + const deletedProjectGroup = await keycloak.getGroupByPath(`/${testProjectSlug}`) + expect(deletedProjectGroup).toBeUndefined() + + const deletedConsoleGroup = await keycloak.getGroupByPath(`/${testProjectSlug}/console`) + expect(deletedConsoleGroup).toBeUndefined() + }, 60000) }) diff --git a/apps/server-nestjs/test/log.e2e-spec.ts b/apps/server-nestjs/test/log.e2e-spec.ts index 72214c56aa..4d81a4e725 100644 --- a/apps/server-nestjs/test/log.e2e-spec.ts +++ b/apps/server-nestjs/test/log.e2e-spec.ts @@ -1,7 +1,9 @@ import type { TestingModule } from '@nestjs/testing' import { faker } from '@faker-js/faker' +import { ConfigModule } from '@nestjs/config' import { Test } from '@nestjs/testing' import { afterAll, beforeAll, describe, expect, it, vi } from 'vitest' +import { baseConfigFactory } from '../src/config/base.config' import { AuthModule } from '../src/modules/infrastructure/auth/auth.module' import { DatabaseModule } from '../src/modules/infrastructure/database/database.module' import { PrismaService } from '../src/modules/infrastructure/database/prisma.service' @@ -10,6 +12,7 @@ import { LoggerModule } from '../src/modules/infrastructure/logger/logger.module import { PermissionModule } from '../src/modules/infrastructure/permission/permission.module' import { LogModule } from '../src/modules/log/log.module' import { LogService } from '../src/modules/log/log.service' +import { getDotenvPaths } from '../src/utils/dotenv.utils' const canRunLogE2E = Boolean(process.env.E2E) @@ -29,7 +32,7 @@ describeWithLog('LogService (e2e)', () => { beforeAll(async () => { moduleRef = await Test.createTestingModule({ - imports: [LogModule, AuthModule, DatabaseModule, EventsModule, LoggerModule, PermissionModule], + imports: [ConfigModule.forRoot({ envFilePath: getDotenvPaths(), isGlobal: true, load: [baseConfigFactory] }), LogModule, AuthModule, DatabaseModule, EventsModule, LoggerModule, PermissionModule], }).compile() await moduleRef.init() @@ -156,32 +159,35 @@ describeWithLog('LogService (e2e)', () => { const { total: allTotal, logs: allLogs } = await logService.getLogs({ offset: 0, - limit: 10, + limit: 50, projectId: undefined, clean: true, }) expect(allTotal).toBeGreaterThan(2) - expect(allLogs).toHaveLength(10) - expect(allLogs[0]).toMatchObject({ + + const globalEntry = allLogs.find(log => log.id === globalLog.id) + expect(globalEntry).toMatchObject({ id: globalLog.id, action: 'global-upsert', userId: null, }) - expect(allLogs[0].data).not.toHaveProperty('args') - expect(allLogs[0].data).not.toHaveProperty('results') - expect(allLogs[0].data).not.toHaveProperty('config') - expect(allLogs[1]).toMatchObject({ + expect(globalEntry?.data).not.toHaveProperty('args') + expect(globalEntry?.data).not.toHaveProperty('results') + expect(globalEntry?.data).not.toHaveProperty('config') + + const projectEntry = allLogs.find(log => log.id === projectLog.id) + expect(projectEntry).toMatchObject({ id: projectLog.id, action: 'project-upsert', userId: ownerId, }) - expect(allLogs[1].data).toMatchObject({ + expect(projectEntry?.data).toMatchObject({ warning: ['careful'], totalExecutionTime: 42, messageResume: 'done', }) - expect(allLogs[1].data).not.toHaveProperty('args') - expect(allLogs[1].data).not.toHaveProperty('results') - expect(allLogs[1].data).not.toHaveProperty('config') + expect(projectEntry?.data).not.toHaveProperty('args') + expect(projectEntry?.data).not.toHaveProperty('results') + expect(projectEntry?.data).not.toHaveProperty('config') }) }) diff --git a/apps/server-nestjs/test/nexus.e2e-spec.ts b/apps/server-nestjs/test/nexus.e2e-spec.ts index 93841f88c2..bf63f947f2 100644 --- a/apps/server-nestjs/test/nexus.e2e-spec.ts +++ b/apps/server-nestjs/test/nexus.e2e-spec.ts @@ -147,4 +147,24 @@ describeWithNexus('NexusService (e2e)', () => { expect(secret.data?.NEXUS_USERNAME).toBe(testProjectSlug) expect(secret.data?.NEXUS_PASSWORD).toBeTruthy() }) + + it('should remove project from Nexus on delete', async () => { + const project = await prisma.project.findUniqueOrThrow({ + where: { id: testProjectId }, + select: projectSelect, + }) + + await nexusService.handleDelete(project) + + const mavenReleaseRepo = `${testProjectSlug}-repository-release` + const repo = await nexusClient.getRepositoriesMavenHosted(mavenReleaseRepo) + expect(repo).toBeNull() + + const roleId = `${testProjectSlug}-ID` + const role = await nexusClient.getSecurityRoles(roleId) + expect(role).toBeNull() + + const users = await nexusClient.getSecurityUsers(testProjectSlug) + expect(users.some(u => u.userId === testProjectSlug)).toBe(false) + }) }) diff --git a/apps/server-nestjs/test/project-bulk.e2e-spec.ts b/apps/server-nestjs/test/project-bulk.e2e-spec.ts index 3a1e80f39d..8548971e55 100644 --- a/apps/server-nestjs/test/project-bulk.e2e-spec.ts +++ b/apps/server-nestjs/test/project-bulk.e2e-spec.ts @@ -15,11 +15,11 @@ import { ProjectBulkModule } from '../src/modules/project-bulk/project-bulk.modu import { ProjectBulkService } from '../src/modules/project-bulk/project-bulk.service' import { getDotenvPaths } from '../src/utils/dotenv.utils' -const canRunProjectBulkE2E = Boolean(process.env.E2E) && Boolean(process.env.DB_URL) +const canRunProjectBulkE2E = Boolean(process.env.E2E) const describeWithProjectBulk = describe.runIf(canRunProjectBulkE2E) -describeWithProjectBulk('ProjectBulkService (e2e)', {}, () => { +describeWithProjectBulk('ProjectBulkService (e2e)', () => { let moduleRef: TestingModule let prisma: PrismaService let service: ProjectBulkService diff --git a/apps/server-nestjs/test/project-hooks.e2e-spec.ts b/apps/server-nestjs/test/project-hooks.e2e-spec.ts index ab6e75184e..91d56e504f 100644 --- a/apps/server-nestjs/test/project-hooks.e2e-spec.ts +++ b/apps/server-nestjs/test/project-hooks.e2e-spec.ts @@ -19,11 +19,11 @@ import { VaultClientService } from '../src/modules/vault/vault-client.service' import { VaultService } from '../src/modules/vault/vault.service' import { getDotenvPaths } from '../src/utils/dotenv.utils' -const canRunProjectHooksE2E = Boolean(process.env.E2E) && Boolean(process.env.DB_URL) +const canRunProjectHooksE2E = Boolean(process.env.E2E) const describeWithProjectHooks = describe.runIf(canRunProjectHooksE2E) -describeWithProjectHooks('ProjectHooksService (e2e)', {}, () => { +describeWithProjectHooks('ProjectHooksService (e2e)', () => { let moduleRef: TestingModule let prisma: PrismaService let service: ProjectHooksService diff --git a/apps/server-nestjs/test/project-members.e2e-spec.ts b/apps/server-nestjs/test/project-members.e2e-spec.ts index 10dec97860..315bdba2dd 100644 --- a/apps/server-nestjs/test/project-members.e2e-spec.ts +++ b/apps/server-nestjs/test/project-members.e2e-spec.ts @@ -19,11 +19,11 @@ import { ProjectMembersModule } from '../src/modules/project-members/project-mem import { ProjectMembersService } from '../src/modules/project-members/project-members.service' import { getDotenvPaths } from '../src/utils/dotenv.utils' -const canRunProjectMembersE2E = Boolean(process.env.E2E) && Boolean(process.env.DB_URL) +const canRunProjectMembersE2E = Boolean(process.env.E2E) const describeWithProjectMembers = describe.runIf(canRunProjectMembersE2E) -describeWithProjectMembers('ProjectMembersService (e2e)', {}, () => { +describeWithProjectMembers('ProjectMembersService (e2e)', () => { let moduleRef: TestingModule let prisma: PrismaService let service: ProjectMembersService diff --git a/apps/server-nestjs/test/project-roles.e2e-spec.ts b/apps/server-nestjs/test/project-roles.e2e-spec.ts index 0f530ebf53..3f180330d0 100644 --- a/apps/server-nestjs/test/project-roles.e2e-spec.ts +++ b/apps/server-nestjs/test/project-roles.e2e-spec.ts @@ -16,11 +16,11 @@ import { ProjectRolesModule } from '../src/modules/project-roles/project-roles.m import { ProjectRolesService } from '../src/modules/project-roles/project-roles.service' import { getDotenvPaths } from '../src/utils/dotenv.utils' -const canRunProjectRolesE2E = Boolean(process.env.E2E) && Boolean(process.env.DB_URL) +const canRunProjectRolesE2E = Boolean(process.env.E2E) const describeWithProjectRoles = describe.runIf(canRunProjectRolesE2E) -describeWithProjectRoles('ProjectRolesService (e2e)', {}, () => { +describeWithProjectRoles('ProjectRolesService (e2e)', () => { let moduleRef: TestingModule let prisma: PrismaService let service: ProjectRolesService diff --git a/apps/server-nestjs/test/project-secrets.e2e-spec.ts b/apps/server-nestjs/test/project-secrets.e2e-spec.ts index 9eec3ec83f..52414baf75 100644 --- a/apps/server-nestjs/test/project-secrets.e2e-spec.ts +++ b/apps/server-nestjs/test/project-secrets.e2e-spec.ts @@ -21,7 +21,7 @@ const canRunProjectSecretsE2E const describeWithProjectSecrets = describe.runIf(canRunProjectSecretsE2E) -describeWithProjectSecrets('ProjectSecretsService (e2e)', {}, () => { +describeWithProjectSecrets('ProjectSecretsService (e2e)', () => { let moduleRef: TestingModule let prisma: PrismaService let service: ProjectSecretsService diff --git a/apps/server-nestjs/test/project-services.e2e-spec.ts b/apps/server-nestjs/test/project-services.e2e-spec.ts index 21a284ea91..4a8b41f222 100644 --- a/apps/server-nestjs/test/project-services.e2e-spec.ts +++ b/apps/server-nestjs/test/project-services.e2e-spec.ts @@ -11,18 +11,15 @@ import { PrismaService } from '../src/modules/infrastructure/database/prisma.ser import { EventsModule } from '../src/modules/infrastructure/events/events.module' import { LoggerModule } from '../src/modules/infrastructure/logger/logger.module' import { PermissionModule } from '../src/modules/infrastructure/permission/permission.module' +import { NEXUS_CONFIG_KEY_ACTIVATE_NPM_REPO, PLUGIN_NAME } from '../src/modules/nexus/nexus.constants' import { ProjectServicesModule } from '../src/modules/project-services/project-services.module' import { ProjectServicesService } from '../src/modules/project-services/project-services.service' import { getDotenvPaths } from '../src/utils/dotenv.utils' -const canRunServicesE2E - = Boolean(process.env.E2E) - +const canRunServicesE2E = Boolean(process.env.E2E) const describeWithServices = describe.runIf(canRunServicesE2E) -const PLUGIN_NAME = 'gitlab' - -describeWithServices('ProjectServicesService (e2e)', {}, () => { +describeWithServices('ProjectServicesService (e2e)', () => { let moduleRef: TestingModule let prisma: PrismaService let service: ProjectServicesService @@ -103,8 +100,8 @@ describeWithServices('ProjectServicesService (e2e)', {}, () => { it('update stores project configuration', async () => { await service.update(projectId, { - gitlab: { - enabled: 'enabled', + nexus: { + activateNpmRepo: 'enabled', }, }, ['user']) @@ -113,7 +110,7 @@ describeWithServices('ProjectServicesService (e2e)', {}, () => { projectId_pluginName_key: { projectId, pluginName: PLUGIN_NAME, - key: 'user.enabled', + key: NEXUS_CONFIG_KEY_ACTIVATE_NPM_REPO, }, }, select: { diff --git a/apps/server-nestjs/test/project.e2e-spec.ts b/apps/server-nestjs/test/project.e2e-spec.ts index 0aa6b9011d..0a670aa45a 100644 --- a/apps/server-nestjs/test/project.e2e-spec.ts +++ b/apps/server-nestjs/test/project.e2e-spec.ts @@ -13,16 +13,16 @@ import { PrismaService } from '../src/modules/infrastructure/database/prisma.ser import { EventsModule } from '../src/modules/infrastructure/events/events.module' import { LoggerModule } from '../src/modules/infrastructure/logger/logger.module' import { PermissionModule } from '../src/modules/infrastructure/permission/permission.module' -import { ProjectPermissionModule } from '../src/modules/infrastructure/permission/project/project.module' import { makeCreateProjectBody } from '../src/modules/project/project-testing.utils' +import { ProjectModule } from '../src/modules/project/project.module' import { ProjectService } from '../src/modules/project/project.service' import { getDotenvPaths } from '../src/utils/dotenv.utils' -const canRunProjectE2E = Boolean(process.env.E2E) && Boolean(process.env.DB_URL) +const canRunProjectE2E = Boolean(process.env.E2E) const describeWithProject = describe.runIf(canRunProjectE2E) -describeWithProject('ProjectService (e2e)', {}, () => { +describeWithProject('ProjectService (e2e)', () => { let moduleRef: TestingModule let prisma: PrismaService let service: ProjectService @@ -32,7 +32,7 @@ describeWithProject('ProjectService (e2e)', {}, () => { beforeAll(async () => { moduleRef = await Test.createTestingModule({ - imports: [ConfigModule.forRoot({ envFilePath: getDotenvPaths(), isGlobal: true, load: [baseConfigFactory] }), AuthModule, DatabaseModule, EventsModule, LoggerModule, PermissionModule, ProjectPermissionModule], + imports: [ConfigModule.forRoot({ envFilePath: getDotenvPaths(), isGlobal: true, load: [baseConfigFactory] }), AuthModule, DatabaseModule, EventsModule, LoggerModule, PermissionModule, ProjectModule], }).compile() await moduleRef.init() diff --git a/apps/server-nestjs/test/registry.e2e-spec.ts b/apps/server-nestjs/test/registry.e2e-spec.ts index d86e89d6c7..cf2d0e982a 100644 --- a/apps/server-nestjs/test/registry.e2e-spec.ts +++ b/apps/server-nestjs/test/registry.e2e-spec.ts @@ -82,4 +82,13 @@ describeWithRegistry('RegistryService (e2e)', () => { expect(rwSecret.data?.USERNAME).toBe(`robot$${projectSlug}+${ROBOT_NAME_RW}`) expect(projectSecret.data?.USERNAME).toBe(`robot$${projectSlug}+${ROBOT_NAME_PROJECT}`) }) + + it('should remove project from Harbor on delete', async () => { + const result = await registry.handleDelete(makeProjectWithDetails({ slug: projectSlug })) + + expect(result.harbor?.status).toBe('OK') + + const project = await client.getProjectByName(projectSlug) + expect(project.status).toBe(404) + }) }) diff --git a/apps/server-nestjs/test/vault.e2e-spec.ts b/apps/server-nestjs/test/vault.e2e-spec.ts index a2696732cc..b20cae90a8 100644 --- a/apps/server-nestjs/test/vault.e2e-spec.ts +++ b/apps/server-nestjs/test/vault.e2e-spec.ts @@ -97,9 +97,21 @@ describeWithVault('VaultService (e2e)', () => { await vaultService.handleUpsert(project) - const group = await vaultClient.getIdentityGroupName(testProjectSlug) + const adminGroupName = `project-${testProjectSlug}-admin` + const group = await vaultClient.getIdentityGroupName(adminGroupName) expect(group.data?.id).toBeTruthy() - expect(group.data?.name).toBe(testProjectSlug) - expect(group.data?.alias?.name).toBe(`/${testProjectSlug}`) + expect(group.data?.name).toBe(adminGroupName) + }, 180000) + + it('should remove project from Vault on delete', async () => { + const project = await prisma.project.findUniqueOrThrow({ + where: { id: testProjectId }, + select: projectSelect, + }) + + await vaultService.handleDelete(project) + + const adminGroupName = `project-${testProjectSlug}-admin` + await expect(vaultClient.getIdentityGroupName(adminGroupName)).rejects.toThrow('Not Found') }, 180000) }) diff --git a/apps/server-nestjs/test/zone.e2e-spec.ts b/apps/server-nestjs/test/zone.e2e-spec.ts new file mode 100644 index 0000000000..98e29e4932 --- /dev/null +++ b/apps/server-nestjs/test/zone.e2e-spec.ts @@ -0,0 +1,79 @@ +import type { TestingModule } from '@nestjs/testing' +import { faker } from '@faker-js/faker' +import { ConfigModule } from '@nestjs/config' +import { Test } from '@nestjs/testing' +import { afterAll, beforeAll, describe, expect, it, vi } from 'vitest' +import { baseConfigFactory } from '../src/config/base.config' +import { AuthModule } from '../src/modules/infrastructure/auth/auth.module' +import { DatabaseModule } from '../src/modules/infrastructure/database/database.module' +import { PrismaService } from '../src/modules/infrastructure/database/prisma.service' +import { EventsModule } from '../src/modules/infrastructure/events/events.module' +import { LoggerModule } from '../src/modules/infrastructure/logger/logger.module' +import { PermissionModule } from '../src/modules/infrastructure/permission/permission.module' +import { VaultClientService } from '../src/modules/vault/vault-client.service' +import { makeZoneWithDetails } from '../src/modules/vault/vault-testing.utils' +import { VaultModule } from '../src/modules/vault/vault.module' +import { VaultService } from '../src/modules/vault/vault.service' +import { getDotenvPaths } from '../src/utils/dotenv.utils' + +const canRunZoneE2E = Boolean(process.env.E2E) + +const describeWithZone = describe.runIf(canRunZoneE2E) + +describeWithZone('Zone lifecycle (e2e)', () => { + let moduleRef: TestingModule + let vaultService: VaultService + let vaultClient: VaultClientService + let prisma: PrismaService + + let zoneId: string + let zoneSlug: string + + beforeAll(async () => { + moduleRef = await Test.createTestingModule({ + imports: [VaultModule, ConfigModule.forRoot({ envFilePath: getDotenvPaths(), isGlobal: true, load: [baseConfigFactory] }), AuthModule, DatabaseModule, EventsModule, LoggerModule, PermissionModule], + }).compile() + + await moduleRef.init() + + vaultService = moduleRef.get(VaultService) + vaultClient = moduleRef.get(VaultClientService) + prisma = moduleRef.get(PrismaService) + + zoneId = faker.string.uuid() + zoneSlug = faker.helpers.slugify(`test-zone-${faker.string.alphanumeric({ length: 10 }).toLowerCase()}`) + }) + + afterAll(async () => { + if (zoneSlug) { + await vaultService.deleteZone(zoneSlug).catch(() => {}) + } + + if (prisma) { + await prisma.zone.deleteMany({ where: { id: zoneId } }).catch(() => {}) + } + + await moduleRef?.close() + + vi.unstubAllEnvs() + }) + + it('should provision zone secrets space in Vault (mount, policy, approle)', async () => { + const zone = makeZoneWithDetails({ id: zoneId, slug: zoneSlug }) + + await vaultService.handleUpsertZone(zone) + + const kvName = `zone-${zoneSlug}` + const roleId = await vaultClient.getAuthApproleRoleRoleId(kvName) + expect(roleId).toBeTruthy() + }, 180000) + + it('should remove zone from Vault on delete', async () => { + const zone = makeZoneWithDetails({ id: zoneId, slug: zoneSlug }) + + await vaultService.handleDeleteZone(zone) + + const kvName = `zone-${zoneSlug}` + await expect(vaultClient.getAuthApproleRoleRoleId(kvName)).rejects.toThrow() + }, 180000) +}) From 468b4b7cced2cf5b8ea7249694273d7ab2fc125c Mon Sep 17 00:00:00 2001 From: William Phetsinorath Date: Tue, 4 Aug 2026 17:15:55 +0200 Subject: [PATCH 3/6] refactor(server-nestjs): drive e2e specs via event emission --- apps/server-nestjs/test/argocd.e2e-spec.ts | 10 +++--- apps/server-nestjs/test/gitlab.e2e-spec.ts | 12 +++---- apps/server-nestjs/test/keycloak.e2e-spec.ts | 34 +++++++++---------- apps/server-nestjs/test/nexus.e2e-spec.ts | 12 +++---- apps/server-nestjs/test/registry.e2e-spec.ts | 10 +++--- apps/server-nestjs/test/sonarqube.e2e-spec.ts | 11 +++--- apps/server-nestjs/test/vault.e2e-spec.ts | 12 +++---- apps/server-nestjs/test/zone.e2e-spec.ts | 7 ++-- 8 files changed, 57 insertions(+), 51 deletions(-) diff --git a/apps/server-nestjs/test/argocd.e2e-spec.ts b/apps/server-nestjs/test/argocd.e2e-spec.ts index f3a98dac9a..9f8a256ab8 100644 --- a/apps/server-nestjs/test/argocd.e2e-spec.ts +++ b/apps/server-nestjs/test/argocd.e2e-spec.ts @@ -3,13 +3,13 @@ import type { ConfigType } from '@nestjs/config' import type { TestingModule } from '@nestjs/testing' import { faker } from '@faker-js/faker' import { ConfigModule } from '@nestjs/config' +import { EventEmitter2 } from '@nestjs/event-emitter' import { Test } from '@nestjs/testing' import { afterAll, beforeAll, describe, expect, it, vi } from 'vitest' import { parse } from 'yaml' import { baseConfigFactory } from '../src/config/base.config' import { projectSelect } from '../src/modules/argocd/argocd-datastore.service' import { ArgoCDModule } from '../src/modules/argocd/argocd.module' -import { ArgoCDService } from '../src/modules/argocd/argocd.service' import { GITLAB_REST_CLIENT, GitlabClientService } from '../src/modules/gitlab/gitlab-client.service' import { AuthModule } from '../src/modules/infrastructure/auth/auth.module' import { DatabaseModule } from '../src/modules/infrastructure/database/database.module' @@ -27,7 +27,7 @@ const describeWithArgoCD = describe.runIf(canRunArgoCDE2E) describeWithArgoCD('ArgoCDService (e2e)', () => { let moduleRef: TestingModule - let argocdService: ArgoCDService + let eventEmitter: EventEmitter2 let gitlab: GitlabClientService let gitlabClient: Gitlab let vault: VaultClientService @@ -60,11 +60,11 @@ describeWithArgoCD('ArgoCDService (e2e)', () => { await moduleRef.init() - argocdService = moduleRef.get(ArgoCDService) gitlab = moduleRef.get(GitlabClientService) gitlabClient = moduleRef.get(GITLAB_REST_CLIENT) vault = moduleRef.get(VaultClientService) prisma = moduleRef.get(PrismaService) + eventEmitter = moduleRef.get(EventEmitter2) config = moduleRef.get(baseConfigFactory.KEY) ownerId = faker.string.uuid() @@ -252,7 +252,7 @@ describeWithArgoCD('ArgoCDService (e2e)', () => { const staleAction = await gitlab.generateCreateOrUpdateAction(infraProject, 'main', staleFilePath, 'stale: true\n') await gitlab.maybeCreateCommit(infraProject, 'ci: :robot_face: Seed stale values', staleAction ? [staleAction] : []) - await argocdService.handleUpsert(project) + await eventEmitter.emitAsync('project.upsert', project) const expectedFilePath = `${project.name}/${clusterLabel}/${envDevName}/values.yaml` const file = await gitlabClient.RepositoryFiles.show(infraRepoId, expectedFilePath, 'main') @@ -294,7 +294,7 @@ describeWithArgoCD('ArgoCDService (e2e)', () => { select: projectSelect, }) - await argocdService.handleUpsert(after) + await eventEmitter.emitAsync('project.upsert', after) const updatedDev = await gitlabClient.RepositoryFiles.show(infraRepoId, devFilePath, 'main') const devRaw = Buffer.from(updatedDev.content, 'base64').toString('utf8') diff --git a/apps/server-nestjs/test/gitlab.e2e-spec.ts b/apps/server-nestjs/test/gitlab.e2e-spec.ts index 01ca74d515..b0de8db850 100644 --- a/apps/server-nestjs/test/gitlab.e2e-spec.ts +++ b/apps/server-nestjs/test/gitlab.e2e-spec.ts @@ -3,6 +3,7 @@ import type { ConfigType } from '@nestjs/config' import type { TestingModule } from '@nestjs/testing' import { faker } from '@faker-js/faker' import { ConfigModule } from '@nestjs/config' +import { EventEmitter2 } from '@nestjs/event-emitter' import { Test } from '@nestjs/testing' import { afterAll, beforeAll, describe, expect, it, vi } from 'vitest' import z from 'zod' @@ -10,7 +11,6 @@ import { baseConfigFactory } from '../src/config/base.config' import { GITLAB_REST_CLIENT, GitlabClientService } from '../src/modules/gitlab/gitlab-client.service' import { projectSelect } from '../src/modules/gitlab/gitlab-datastore.service' import { GitlabModule } from '../src/modules/gitlab/gitlab.module' -import { GitlabService } from '../src/modules/gitlab/gitlab.service' import { AuthModule } from '../src/modules/infrastructure/auth/auth.module' import { DatabaseModule } from '../src/modules/infrastructure/database/database.module' import { PrismaService } from '../src/modules/infrastructure/database/prisma.service' @@ -27,7 +27,7 @@ const describeWithGitLab = describe.runIf(canRunGitlabE2E) describeWithGitLab('GitlabService (e2e)', () => { let moduleRef: TestingModule - let gitlabService: GitlabService + let eventEmitter: EventEmitter2 let gitlabClientService: GitlabClientService let gitlabClient: Gitlab let vaultService: VaultClientService @@ -46,11 +46,11 @@ describeWithGitLab('GitlabService (e2e)', () => { await moduleRef.init() - gitlabService = moduleRef.get(GitlabService) gitlabClientService = moduleRef.get(GitlabClientService) gitlabClient = moduleRef.get(GITLAB_REST_CLIENT) vaultService = moduleRef.get(VaultClientService) prisma = moduleRef.get(PrismaService) + eventEmitter = moduleRef.get(EventEmitter2) config = moduleRef.get(baseConfigFactory.KEY) ownerId = faker.string.uuid() @@ -146,7 +146,7 @@ describeWithGitLab('GitlabService (e2e)', () => { }) // Act - await gitlabService.handleUpsert(project) + await eventEmitter.emitAsync('project.upsert', project) // Assert const groupPath = `${config.projectsRootDir}/${testProjectSlug}` @@ -219,7 +219,7 @@ describeWithGitLab('GitlabService (e2e)', () => { select: projectSelect, }) - await gitlabService.handleUpsert(project) + await eventEmitter.emitAsync('project.upsert', project) const groupPath = `${config.projectsRootDir}/${testProjectSlug}` const group = z.object({ @@ -240,7 +240,7 @@ describeWithGitLab('GitlabService (e2e)', () => { select: projectSelect, }) - await gitlabService.handleDelete(project) + await eventEmitter.emitAsync('project.delete', project) const groupPath = `${config.projectsRootDir}/${testProjectSlug}` const group = await gitlabClientService.getGroupByPath(groupPath) diff --git a/apps/server-nestjs/test/keycloak.e2e-spec.ts b/apps/server-nestjs/test/keycloak.e2e-spec.ts index c45458fc18..79bf1cf9c0 100644 --- a/apps/server-nestjs/test/keycloak.e2e-spec.ts +++ b/apps/server-nestjs/test/keycloak.e2e-spec.ts @@ -3,6 +3,7 @@ import type { TestingModule } from '@nestjs/testing' import { faker } from '@faker-js/faker' import { Logger } from '@nestjs/common' import { ConfigModule } from '@nestjs/config' +import { EventEmitter2 } from '@nestjs/event-emitter' import { Test } from '@nestjs/testing' import { afterAll, beforeAll, describe, expect, it, vi } from 'vitest' import z from 'zod' @@ -16,7 +17,6 @@ import { PermissionModule } from '../src/modules/infrastructure/permission/permi import { KEYCLOAK_ADMIN_CLIENT, KeycloakClientService } from '../src/modules/keycloak/keycloak-client.service' import { projectSelect } from '../src/modules/keycloak/keycloak-datastore.service' import { KeycloakModule } from '../src/modules/keycloak/keycloak.module' -import { KeycloakService } from '../src/modules/keycloak/keycloak.service' import { getDotenvPaths } from '../src/utils/dotenv.utils' const canRunKeycloakE2E @@ -26,7 +26,7 @@ const describeWithKeycloak = describe.runIf(canRunKeycloakE2E) describeWithKeycloak('KeycloakService (e2e)', () => { let moduleRef: TestingModule - let keycloakService: KeycloakService + let eventEmitter: EventEmitter2 let keycloak: KeycloakClientService let keycloakAdminClient: KcAdminClient let prisma: PrismaService @@ -44,10 +44,10 @@ describeWithKeycloak('KeycloakService (e2e)', () => { await moduleRef.init() - keycloakService = moduleRef.get(KeycloakService) keycloak = moduleRef.get(KeycloakClientService) keycloakAdminClient = moduleRef.get(KEYCLOAK_ADMIN_CLIENT) prisma = moduleRef.get(PrismaService) + eventEmitter = moduleRef.get(EventEmitter2) ownerId = faker.string.uuid() testProjectId = faker.string.uuid() @@ -147,7 +147,7 @@ describeWithKeycloak('KeycloakService (e2e)', () => { }) // Act - await keycloakService.handleUpsert(project) + await eventEmitter.emitAsync('project.upsert', project) // Assert // Check main project group @@ -215,7 +215,7 @@ describeWithKeycloak('KeycloakService (e2e)', () => { }) // Act - await keycloakService.handleUpsert(project) + await eventEmitter.emitAsync('project.upsert', project) // Assert const projectGroup = z.object({ @@ -278,7 +278,7 @@ describeWithKeycloak('KeycloakService (e2e)', () => { }) // Sync add - await keycloakService.handleUpsert(project) + await eventEmitter.emitAsync('project.upsert', project) // Verify added const projectGroup = z.object({ @@ -303,7 +303,7 @@ describeWithKeycloak('KeycloakService (e2e)', () => { }) // Sync remove - await keycloakService.handleUpsert(project) + await eventEmitter.emitAsync('project.upsert', project) // Verify removed members = await keycloak.getGroupMembers(projectGroup.id) @@ -343,7 +343,7 @@ describeWithKeycloak('KeycloakService (e2e)', () => { }) // Act - should not throw - await expect(keycloakService.handleUpsert(project)).resolves.not.toThrow() + await expect(eventEmitter.emitAsync('project.upsert', project)).resolves.not.toThrow() // Cleanup await prisma.projectMembers.deleteMany({ where: { userId: fakeUserId } }) @@ -387,7 +387,7 @@ describeWithKeycloak('KeycloakService (e2e)', () => { }) // Sync to ensure they are added initially - await keycloakService.handleUpsert(project) + await eventEmitter.emitAsync('project.upsert', project) const projectGroup = z.object({ id: z.string(), @@ -401,7 +401,7 @@ describeWithKeycloak('KeycloakService (e2e)', () => { expect(members.some(m => m.id === kcUser.id)).toBe(false) // Sync again - await keycloakService.handleUpsert(project) + await eventEmitter.emitAsync('project.upsert', project) // Verify added back members = await keycloak.getGroupMembers(projectGroup.id) @@ -447,7 +447,7 @@ describeWithKeycloak('KeycloakService (e2e)', () => { }) // Sync to create group - await keycloakService.handleUpsert(project) + await eventEmitter.emitAsync('project.upsert', project) // Manually add user to Keycloak group const projectGroup = z.object({ @@ -460,7 +460,7 @@ describeWithKeycloak('KeycloakService (e2e)', () => { expect(members.some(m => m.id === kcUser.id)).toBe(true) // Sync again to remove user - await keycloakService.handleUpsert(project) + await eventEmitter.emitAsync('project.upsert', project) // Verify removed members = await keycloak.getGroupMembers(projectGroup.id) @@ -478,7 +478,7 @@ describeWithKeycloak('KeycloakService (e2e)', () => { where: { id: testProjectId }, select: projectSelect, }) - await keycloakService.handleUpsert(project) + await eventEmitter.emitAsync('project.upsert', project) const projectGroup = z.object({ id: z.string(), @@ -492,7 +492,7 @@ describeWithKeycloak('KeycloakService (e2e)', () => { expect(deletedProjectGroup).toBeUndefined() // Sync - await keycloakService.handleUpsert(project) + await eventEmitter.emitAsync('project.upsert', project) // Verify recreated const recreatedProjectGroup = z.object({ @@ -507,7 +507,7 @@ describeWithKeycloak('KeycloakService (e2e)', () => { where: { id: testProjectId }, select: projectSelect, }) - await keycloakService.handleUpsert(project) + await eventEmitter.emitAsync('project.upsert', project) const roleGroup = z.object({ id: z.string(), @@ -521,7 +521,7 @@ describeWithKeycloak('KeycloakService (e2e)', () => { expect(deletedRoleGroup).toBeUndefined() // Sync - await keycloakService.handleUpsert(project) + await eventEmitter.emitAsync('project.upsert', project) // Verify recreated const recreatedRoleGroup = z.object({ @@ -536,7 +536,7 @@ describeWithKeycloak('KeycloakService (e2e)', () => { select: projectSelect, }) - await keycloakService.handleDelete(project) + await eventEmitter.emitAsync('project.delete', project) const deletedProjectGroup = await keycloak.getGroupByPath(`/${testProjectSlug}`) expect(deletedProjectGroup).toBeUndefined() diff --git a/apps/server-nestjs/test/nexus.e2e-spec.ts b/apps/server-nestjs/test/nexus.e2e-spec.ts index bf63f947f2..da7c63b2fd 100644 --- a/apps/server-nestjs/test/nexus.e2e-spec.ts +++ b/apps/server-nestjs/test/nexus.e2e-spec.ts @@ -3,6 +3,7 @@ import type { TestingModule } from '@nestjs/testing' import { ENABLED } from '@cpn-console/shared' import { faker } from '@faker-js/faker' import { ConfigModule } from '@nestjs/config' +import { EventEmitter2 } from '@nestjs/event-emitter' import { Test } from '@nestjs/testing' import { afterAll, beforeAll, describe, expect, it, vi } from 'vitest' import { baseConfigFactory } from '../src/config/base.config' @@ -17,7 +18,6 @@ import { projectSelect } from '../src/modules/nexus/nexus-datastore.service' import { makeProjectWithDetails } from '../src/modules/nexus/nexus-testing.utils' import { NEXUS_CONFIG_KEY_ACTIVATE_MAVEN_REPO, NEXUS_CONFIG_KEY_ACTIVATE_NPM_REPO, PLUGIN_NAME } from '../src/modules/nexus/nexus.constants' import { NexusModule } from '../src/modules/nexus/nexus.module' -import { NexusService } from '../src/modules/nexus/nexus.service' import { generateNexusCredPath } from '../src/modules/nexus/nexus.utils' import { VaultClientService } from '../src/modules/vault/vault-client.service' import { VaultModule } from '../src/modules/vault/vault.module' @@ -30,7 +30,7 @@ const describeWithNexus = describe.runIf(canRunNexusE2E) describeWithNexus('NexusService (e2e)', () => { let moduleRef: TestingModule - let nexusService: NexusService + let eventEmitter: EventEmitter2 let nexusClient: NexusClientService let vaultService: VaultClientService let config: ConfigType @@ -47,11 +47,11 @@ describeWithNexus('NexusService (e2e)', () => { await moduleRef.init() - nexusService = moduleRef.get(NexusService) nexusClient = moduleRef.get(NexusClientService) vaultService = moduleRef.get(VaultClientService) config = moduleRef.get(baseConfigFactory.KEY) prisma = moduleRef.get(PrismaService) + eventEmitter = moduleRef.get(EventEmitter2) ownerId = faker.string.uuid() testProjectId = faker.string.uuid() @@ -70,7 +70,7 @@ describeWithNexus('NexusService (e2e)', () => { afterAll(async () => { if (testProjectSlug) { - await nexusService.handleDelete(makeProjectWithDetails({ slug: testProjectSlug })).catch(() => {}) + await eventEmitter.emitAsync('project.delete', makeProjectWithDetails({ slug: testProjectSlug })).catch(() => {}) } if (prisma) { @@ -112,7 +112,7 @@ describeWithNexus('NexusService (e2e)', () => { select: projectSelect, }) - await nexusService.handleUpsert(project) + await eventEmitter.emitAsync('project.upsert', project) const mavenReleaseRepo = `${testProjectSlug}-repository-release` const mavenSnapshotRepo = `${testProjectSlug}-repository-snapshot` @@ -154,7 +154,7 @@ describeWithNexus('NexusService (e2e)', () => { select: projectSelect, }) - await nexusService.handleDelete(project) + await eventEmitter.emitAsync('project.delete', project) const mavenReleaseRepo = `${testProjectSlug}-repository-release` const repo = await nexusClient.getRepositoriesMavenHosted(mavenReleaseRepo) diff --git a/apps/server-nestjs/test/registry.e2e-spec.ts b/apps/server-nestjs/test/registry.e2e-spec.ts index cf2d0e982a..13200f8500 100644 --- a/apps/server-nestjs/test/registry.e2e-spec.ts +++ b/apps/server-nestjs/test/registry.e2e-spec.ts @@ -2,10 +2,12 @@ import type { ConfigType } from '@nestjs/config' import type { TestingModule } from '@nestjs/testing' import { faker } from '@faker-js/faker' import { ConfigModule } from '@nestjs/config' +import { EventEmitter2 } from '@nestjs/event-emitter' import { Test } from '@nestjs/testing' import { afterAll, beforeAll, describe, expect, it } from 'vitest' import { baseConfigFactory } from '../src/config/base.config' import { harborConfigFactory } from '../src/config/harbor.config' +import { EventsModule } from '../src/modules/infrastructure/events/events.module' import { RegistryClientService } from '../src/modules/registry/registry-client.service' import { makeProjectWithDetails } from '../src/modules/registry/registry-testing.utils' import { ROBOT_NAME_PROJECT, ROBOT_NAME_RO, ROBOT_NAME_RW } from '../src/modules/registry/registry.constants' @@ -23,6 +25,7 @@ const describeWithRegistry = describe.runIf(canRunRegistryE2E) describeWithRegistry('RegistryService (e2e)', () => { let moduleRef: TestingModule + let eventEmitter: EventEmitter2 let registry: RegistryService let client: RegistryClientService let vault: VaultClientService @@ -32,13 +35,14 @@ describeWithRegistry('RegistryService (e2e)', () => { beforeAll(async () => { moduleRef = await Test.createTestingModule({ - imports: [ConfigModule.forRoot({ envFilePath: getDotenvPaths(), isGlobal: true, load: [baseConfigFactory, harborConfigFactory] }), RegistryModule], + imports: [ConfigModule.forRoot({ envFilePath: getDotenvPaths(), isGlobal: true, load: [baseConfigFactory, harborConfigFactory] }), RegistryModule, EventsModule], }) .compile() await moduleRef.init() registry = moduleRef.get(RegistryService) + eventEmitter = moduleRef.get(EventEmitter2) client = moduleRef.get(RegistryClientService) vault = moduleRef.get(VaultClientService) config = moduleRef.get(baseConfigFactory.KEY) @@ -84,9 +88,7 @@ describeWithRegistry('RegistryService (e2e)', () => { }) it('should remove project from Harbor on delete', async () => { - const result = await registry.handleDelete(makeProjectWithDetails({ slug: projectSlug })) - - expect(result.harbor?.status).toBe('OK') + await eventEmitter.emitAsync('project.delete', makeProjectWithDetails({ slug: projectSlug })) const project = await client.getProjectByName(projectSlug) expect(project.status).toBe(404) diff --git a/apps/server-nestjs/test/sonarqube.e2e-spec.ts b/apps/server-nestjs/test/sonarqube.e2e-spec.ts index 21a287aa8f..ca09865732 100644 --- a/apps/server-nestjs/test/sonarqube.e2e-spec.ts +++ b/apps/server-nestjs/test/sonarqube.e2e-spec.ts @@ -2,6 +2,7 @@ import type { TestingModule } from '@nestjs/testing' import { generateProjectKey } from '@cpn-console/hooks' import { faker } from '@faker-js/faker' import { ConfigModule } from '@nestjs/config' +import { EventEmitter2 } from '@nestjs/event-emitter' import { Test } from '@nestjs/testing' import { afterAll, beforeAll, describe, expect, it, vi } from 'vitest' import { baseConfigFactory } from '../src/config/base.config' @@ -28,6 +29,7 @@ const describeWithSonarqube = describe.runIf(canRunSonarqubeE2E) describeWithSonarqube('SonarqubeService (e2e)', () => { let moduleRef: TestingModule + let eventEmitter: EventEmitter2 let sonarqubeService: SonarqubeService let sonarqubeClient: SonarqubeClientService let vaultService: VaultClientService @@ -49,6 +51,7 @@ describeWithSonarqube('SonarqubeService (e2e)', () => { sonarqubeClient = moduleRef.get(SonarqubeClientService) vaultService = moduleRef.get(VaultClientService) prisma = moduleRef.get(PrismaService) + eventEmitter = moduleRef.get(EventEmitter2) ownerId = faker.string.uuid() testProjectId = faker.string.uuid() @@ -68,9 +71,7 @@ describeWithSonarqube('SonarqubeService (e2e)', () => { afterAll(async () => { if (sonarqubeService && testProjectSlug) { - await sonarqubeService.handleDelete( - makeProjectWithDetails({ slug: testProjectSlug, repositories: [] }), - ).catch(() => {}) + await eventEmitter.emitAsync('project.delete', makeProjectWithDetails({ slug: testProjectSlug, repositories: [] })).catch(() => {}) } if (prisma) { @@ -128,7 +129,7 @@ describeWithSonarqube('SonarqubeService (e2e)', () => { select: projectSelect, }) - await sonarqubeService.handleUpsert(project) + await eventEmitter.emitAsync('project.upsert', project) // All 5 project role groups should exist in SonarQube const projectGroupNames = [ @@ -165,7 +166,7 @@ describeWithSonarqube('SonarqubeService (e2e)', () => { select: projectSelect, }) - await sonarqubeService.handleDelete(project) + await eventEmitter.emitAsync('project.delete', project) // SonarQube analysis project should be removed const projectKey = generateProjectKey(testProjectSlug, testRepoName) diff --git a/apps/server-nestjs/test/vault.e2e-spec.ts b/apps/server-nestjs/test/vault.e2e-spec.ts index b20cae90a8..b9ff961370 100644 --- a/apps/server-nestjs/test/vault.e2e-spec.ts +++ b/apps/server-nestjs/test/vault.e2e-spec.ts @@ -1,6 +1,7 @@ import type { TestingModule } from '@nestjs/testing' import { faker } from '@faker-js/faker' import { ConfigModule } from '@nestjs/config' +import { EventEmitter2 } from '@nestjs/event-emitter' import { Test } from '@nestjs/testing' import { afterAll, beforeAll, describe, expect, it, vi } from 'vitest' import { baseConfigFactory } from '../src/config/base.config' @@ -14,7 +15,6 @@ import { VaultClientService } from '../src/modules/vault/vault-client.service' import { projectSelect } from '../src/modules/vault/vault-datastore.service' import { makeProjectWithDetails } from '../src/modules/vault/vault-testing.utils' import { VaultModule } from '../src/modules/vault/vault.module' -import { VaultService } from '../src/modules/vault/vault.service' import { getDotenvPaths } from '../src/utils/dotenv.utils' const canRunVaultE2E @@ -24,7 +24,7 @@ const describeWithVault = describe.runIf(canRunVaultE2E) describeWithVault('VaultService (e2e)', () => { let moduleRef: TestingModule - let vaultService: VaultService + let eventEmitter: EventEmitter2 let vaultClient: VaultClientService let prisma: PrismaService @@ -39,9 +39,9 @@ describeWithVault('VaultService (e2e)', () => { await moduleRef.init() - vaultService = moduleRef.get(VaultService) vaultClient = moduleRef.get(VaultClientService) prisma = moduleRef.get(PrismaService) + eventEmitter = moduleRef.get(EventEmitter2) ownerId = faker.string.uuid() testProjectId = faker.string.uuid() @@ -60,7 +60,7 @@ describeWithVault('VaultService (e2e)', () => { afterAll(async () => { if (testProjectSlug) { - await vaultService.handleDelete(makeProjectWithDetails({ slug: testProjectSlug })).catch(() => {}) + await eventEmitter.emitAsync('project.delete', makeProjectWithDetails({ slug: testProjectSlug })).catch(() => {}) } if (prisma) { @@ -95,7 +95,7 @@ describeWithVault('VaultService (e2e)', () => { select: projectSelect, }) - await vaultService.handleUpsert(project) + await eventEmitter.emitAsync('project.upsert', project) const adminGroupName = `project-${testProjectSlug}-admin` const group = await vaultClient.getIdentityGroupName(adminGroupName) @@ -109,7 +109,7 @@ describeWithVault('VaultService (e2e)', () => { select: projectSelect, }) - await vaultService.handleDelete(project) + await eventEmitter.emitAsync('project.delete', project) const adminGroupName = `project-${testProjectSlug}-admin` await expect(vaultClient.getIdentityGroupName(adminGroupName)).rejects.toThrow('Not Found') diff --git a/apps/server-nestjs/test/zone.e2e-spec.ts b/apps/server-nestjs/test/zone.e2e-spec.ts index 98e29e4932..b801fce4ff 100644 --- a/apps/server-nestjs/test/zone.e2e-spec.ts +++ b/apps/server-nestjs/test/zone.e2e-spec.ts @@ -1,6 +1,7 @@ import type { TestingModule } from '@nestjs/testing' import { faker } from '@faker-js/faker' import { ConfigModule } from '@nestjs/config' +import { EventEmitter2 } from '@nestjs/event-emitter' import { Test } from '@nestjs/testing' import { afterAll, beforeAll, describe, expect, it, vi } from 'vitest' import { baseConfigFactory } from '../src/config/base.config' @@ -22,6 +23,7 @@ const describeWithZone = describe.runIf(canRunZoneE2E) describeWithZone('Zone lifecycle (e2e)', () => { let moduleRef: TestingModule + let eventEmitter: EventEmitter2 let vaultService: VaultService let vaultClient: VaultClientService let prisma: PrismaService @@ -39,6 +41,7 @@ describeWithZone('Zone lifecycle (e2e)', () => { vaultService = moduleRef.get(VaultService) vaultClient = moduleRef.get(VaultClientService) prisma = moduleRef.get(PrismaService) + eventEmitter = moduleRef.get(EventEmitter2) zoneId = faker.string.uuid() zoneSlug = faker.helpers.slugify(`test-zone-${faker.string.alphanumeric({ length: 10 }).toLowerCase()}`) @@ -61,7 +64,7 @@ describeWithZone('Zone lifecycle (e2e)', () => { it('should provision zone secrets space in Vault (mount, policy, approle)', async () => { const zone = makeZoneWithDetails({ id: zoneId, slug: zoneSlug }) - await vaultService.handleUpsertZone(zone) + await eventEmitter.emitAsync('zone.upsert', zone) const kvName = `zone-${zoneSlug}` const roleId = await vaultClient.getAuthApproleRoleRoleId(kvName) @@ -71,7 +74,7 @@ describeWithZone('Zone lifecycle (e2e)', () => { it('should remove zone from Vault on delete', async () => { const zone = makeZoneWithDetails({ id: zoneId, slug: zoneSlug }) - await vaultService.handleDeleteZone(zone) + await eventEmitter.emitAsync('zone.delete', zone) const kvName = `zone-${zoneSlug}` await expect(vaultClient.getAuthApproleRoleRoleId(kvName)).rejects.toThrow() From 0c3f69431dc310b9573ac0160ceb5551f2688d99 Mon Sep 17 00:00:00 2001 From: William Phetsinorath Date: Thu, 6 Aug 2026 15:17:16 +0200 Subject: [PATCH 4/6] test(server-nestjs): centralize e2e timeouts by operation Co-Authored-By: Operator 21O Signed-off-by: William Phetsinorath Change-Id: If984ba74aba5bdccd08e3a40c9deb29f6a6a6964 --- apps/server-nestjs/test/e2e-timeout.ts | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 apps/server-nestjs/test/e2e-timeout.ts diff --git a/apps/server-nestjs/test/e2e-timeout.ts b/apps/server-nestjs/test/e2e-timeout.ts new file mode 100644 index 0000000000..b8e803cc9b --- /dev/null +++ b/apps/server-nestjs/test/e2e-timeout.ts @@ -0,0 +1,9 @@ +// e2e specs hit real external services; the latency lives in the operation, not the test shape, +// so name the budget by what the call actually does instead of a bare size. +export const E2E_TIMEOUT = { + provision: 30_000, // single small resource: sonarqube user + project + syncGroups: 60_000, // keycloak group/role reconciliation + syncExternal: 72_000, // gitlab group+member sync, nexus/registry external teardown + gitReconcile: 144_000, // argocd commit + sync to git + provisionHeavy: 180_000, // vault mount/policy/approle, zone secrets space +} as const From 12af8cc23b35368676fc7640efcc0da04621c57f Mon Sep 17 00:00:00 2001 From: William Phetsinorath Date: Thu, 6 Aug 2026 15:17:16 +0200 Subject: [PATCH 5/6] test(server-nestjs): assert resource exists before on-delete checks Co-Authored-By: Operator 21O Signed-off-by: William Phetsinorath Change-Id: I30a27e79378d3fccad2b94d058e09de86a6a6964 --- apps/server-nestjs/test/argocd.e2e-spec.ts | 7 ++++--- apps/server-nestjs/test/gitlab.e2e-spec.ts | 11 ++++++---- apps/server-nestjs/test/keycloak.e2e-spec.ts | 21 +++++++++++-------- apps/server-nestjs/test/nexus.e2e-spec.ts | 4 +++- apps/server-nestjs/test/sonarqube.e2e-spec.ts | 10 ++++++--- apps/server-nestjs/test/vault.e2e-spec.ts | 9 +++++--- apps/server-nestjs/test/zone.e2e-spec.ts | 9 +++++--- 7 files changed, 45 insertions(+), 26 deletions(-) diff --git a/apps/server-nestjs/test/argocd.e2e-spec.ts b/apps/server-nestjs/test/argocd.e2e-spec.ts index 9f8a256ab8..0ea5c669ef 100644 --- a/apps/server-nestjs/test/argocd.e2e-spec.ts +++ b/apps/server-nestjs/test/argocd.e2e-spec.ts @@ -19,6 +19,7 @@ import { LoggerModule } from '../src/modules/infrastructure/logger/logger.module import { PermissionModule } from '../src/modules/infrastructure/permission/permission.module' import { VaultClientService } from '../src/modules/vault/vault-client.service' import { getDotenvPaths } from '../src/utils/dotenv.utils' +import { E2E_TIMEOUT } from './e2e-timeout' const canRunArgoCDE2E = Boolean(process.env.E2E) @@ -212,7 +213,7 @@ describeWithArgoCD('ArgoCDService (e2e)', () => { vaultProjectValuesPath = `${config.projectsRootDir}/${testProjectId}` await vault.write({ e2e: true }, vaultProjectValuesPath) - }, 144000) + }, E2E_TIMEOUT.gitReconcile) afterAll(async () => { if (vaultProjectValuesPath) { @@ -267,7 +268,7 @@ describeWithArgoCD('ArgoCDService (e2e)', () => { const shouldBeDeleted = await gitlab.getFile(infraProject, staleFilePath, 'main') expect(shouldBeDeleted).toBeUndefined() - }, 144000) + }, E2E_TIMEOUT.gitReconcile) it('should update existing values and delete values of a removed environment', async () => { const before = await prisma.project.findUniqueOrThrow({ @@ -304,5 +305,5 @@ describeWithArgoCD('ArgoCDService (e2e)', () => { const prodFile = await gitlab.getFile(infraProject, prodFilePath, 'main') expect(prodFile).toBeUndefined() - }, 72000) + }, E2E_TIMEOUT.syncExternal) }) diff --git a/apps/server-nestjs/test/gitlab.e2e-spec.ts b/apps/server-nestjs/test/gitlab.e2e-spec.ts index b0de8db850..d5dc4ac21f 100644 --- a/apps/server-nestjs/test/gitlab.e2e-spec.ts +++ b/apps/server-nestjs/test/gitlab.e2e-spec.ts @@ -19,6 +19,7 @@ import { LoggerModule } from '../src/modules/infrastructure/logger/logger.module import { PermissionModule } from '../src/modules/infrastructure/permission/permission.module' import { VaultClientService } from '../src/modules/vault/vault-client.service' import { getDotenvPaths } from '../src/utils/dotenv.utils' +import { E2E_TIMEOUT } from './e2e-timeout' const canRunGitlabE2E = Boolean(process.env.E2E) @@ -167,7 +168,7 @@ describeWithGitLab('GitlabService (e2e)', () => { const repoSecret = await vaultService.read(repoVaultPath) expect(repoSecret?.data?.GIT_OUTPUT_USER).toBeTruthy() expect(repoSecret?.data?.GIT_OUTPUT_PASSWORD).toBeTruthy() - }, 72000) + }, E2E_TIMEOUT.syncExternal) describe('project members', () => { let newUserId: string | undefined @@ -231,7 +232,7 @@ describeWithGitLab('GitlabService (e2e)', () => { const members = await gitlabClientService.getGroupMembers(group) const isNewMemberPresent = members.some(m => m.id === newUserGitlabId) expect(isNewMemberPresent).toBe(true) - }, 72000) + }, E2E_TIMEOUT.extended) }) it('should remove project group from GitLab on delete', async () => { @@ -240,10 +241,12 @@ describeWithGitLab('GitlabService (e2e)', () => { select: projectSelect, }) + const groupPath = `${config.projectsRootDir}/${testProjectSlug}` + expect(await gitlabClientService.getGroupByPath(groupPath)).toBeTruthy() + await eventEmitter.emitAsync('project.delete', project) - const groupPath = `${config.projectsRootDir}/${testProjectSlug}` const group = await gitlabClientService.getGroupByPath(groupPath) expect(group).toBeUndefined() - }, 72000) + }, E2E_TIMEOUT.extended) }) diff --git a/apps/server-nestjs/test/keycloak.e2e-spec.ts b/apps/server-nestjs/test/keycloak.e2e-spec.ts index 79bf1cf9c0..8bfd6f7e02 100644 --- a/apps/server-nestjs/test/keycloak.e2e-spec.ts +++ b/apps/server-nestjs/test/keycloak.e2e-spec.ts @@ -18,6 +18,7 @@ import { KEYCLOAK_ADMIN_CLIENT, KeycloakClientService } from '../src/modules/key import { projectSelect } from '../src/modules/keycloak/keycloak-datastore.service' import { KeycloakModule } from '../src/modules/keycloak/keycloak.module' import { getDotenvPaths } from '../src/utils/dotenv.utils' +import { E2E_TIMEOUT } from './e2e-timeout' const canRunKeycloakE2E = Boolean(process.env.E2E) @@ -173,7 +174,7 @@ describeWithKeycloak('KeycloakService (e2e)', () => { const members = await keycloak.getGroupMembers(projectGroup.id) const isMember = members.some(m => m.id === ownerId) expect(isMember).toBe(true) - }, 60000) + }, E2E_TIMEOUT.syncGroups) it('should add member to project group when added in DB', async () => { // Create another user in Keycloak and DB @@ -237,7 +238,7 @@ describeWithKeycloak('KeycloakService (e2e)', () => { await keycloakAdminClient.users.del({ id: kcUser.id }) await prisma.projectMembers.deleteMany({ where: { userId: kcUser.id } }) await prisma.user.delete({ where: { id: kcUser.id } }) - }, 60000) + }, E2E_TIMEOUT.syncGroups) it('should remove member from project group when removed in DB', async () => { const newUserId = faker.string.uuid() @@ -313,7 +314,7 @@ describeWithKeycloak('KeycloakService (e2e)', () => { await keycloakAdminClient.users.del({ id: kcUser.id }) await prisma.projectMembers.deleteMany({ where: { userId: kcUser.id } }) await prisma.user.delete({ where: { id: kcUser.id } }) - }, 60000) + }, E2E_TIMEOUT.syncGroups) it('should handle non-existent users gracefully', async () => { // Add a member in DB that does not exist in Keycloak @@ -348,7 +349,7 @@ describeWithKeycloak('KeycloakService (e2e)', () => { // Cleanup await prisma.projectMembers.deleteMany({ where: { userId: fakeUserId } }) await prisma.user.delete({ where: { id: fakeUserId } }) - }, 60000) + }, E2E_TIMEOUT.syncGroups) it('should add user back to Keycloak group if missing but present in DB', async () => { // Create user and add to project in DB @@ -411,7 +412,7 @@ describeWithKeycloak('KeycloakService (e2e)', () => { await keycloakAdminClient.users.del({ id: kcUser.id }) await prisma.projectMembers.deleteMany({ where: { userId: kcUser.id } }) await prisma.user.delete({ where: { id: kcUser.id } }) - }, 60000) + }, E2E_TIMEOUT.syncGroups) it('should remove user from Keycloak group if present but missing in DB', async () => { // Create user @@ -470,7 +471,7 @@ describeWithKeycloak('KeycloakService (e2e)', () => { await keycloakAdminClient.users.del({ id: kcUser.id }) await prisma.projectMembers.deleteMany({ where: { userId: kcUser.id } }) await prisma.user.delete({ where: { id: kcUser.id } }) - }, 60000) + }, E2E_TIMEOUT.syncGroups) it('should recreate project group if deleted in Keycloak', async () => { // Ensure project exists and is synced @@ -499,7 +500,7 @@ describeWithKeycloak('KeycloakService (e2e)', () => { name: z.string(), }).parse(await keycloak.getGroupByPath(`/${testProjectSlug}`)) expect(recreatedProjectGroup?.name).toBe(testProjectSlug) - }, 60000) + }, E2E_TIMEOUT.syncGroups) it('should recreate role group if deleted in Keycloak', async () => { // Ensure project exists and is synced @@ -528,7 +529,7 @@ describeWithKeycloak('KeycloakService (e2e)', () => { name: z.string(), }).parse(await keycloak.getGroupByPath(`/${testProjectSlug}/console/${testRoleName}`)) expect(recreatedRoleGroup?.name).toBe(testRoleName) - }, 60000) + }, E2E_TIMEOUT.syncGroups) it('should remove project groups from Keycloak on delete', async () => { const project = await prisma.project.findUniqueOrThrow({ @@ -538,10 +539,12 @@ describeWithKeycloak('KeycloakService (e2e)', () => { await eventEmitter.emitAsync('project.delete', project) + expect(await keycloak.getGroupByPath(`/${testProjectSlug}`)).toBeTruthy() + const deletedProjectGroup = await keycloak.getGroupByPath(`/${testProjectSlug}`) expect(deletedProjectGroup).toBeUndefined() const deletedConsoleGroup = await keycloak.getGroupByPath(`/${testProjectSlug}/console`) expect(deletedConsoleGroup).toBeUndefined() - }, 60000) + }, E2E_TIMEOUT.syncGroups) }) diff --git a/apps/server-nestjs/test/nexus.e2e-spec.ts b/apps/server-nestjs/test/nexus.e2e-spec.ts index da7c63b2fd..5a680a404c 100644 --- a/apps/server-nestjs/test/nexus.e2e-spec.ts +++ b/apps/server-nestjs/test/nexus.e2e-spec.ts @@ -154,9 +154,11 @@ describeWithNexus('NexusService (e2e)', () => { select: projectSelect, }) + const mavenReleaseRepo = `${testProjectSlug}-repository-release` + expect(await nexusClient.getRepositoriesMavenHosted(mavenReleaseRepo)).not.toBeNull() + await eventEmitter.emitAsync('project.delete', project) - const mavenReleaseRepo = `${testProjectSlug}-repository-release` const repo = await nexusClient.getRepositoriesMavenHosted(mavenReleaseRepo) expect(repo).toBeNull() diff --git a/apps/server-nestjs/test/sonarqube.e2e-spec.ts b/apps/server-nestjs/test/sonarqube.e2e-spec.ts index ca09865732..397ea43d06 100644 --- a/apps/server-nestjs/test/sonarqube.e2e-spec.ts +++ b/apps/server-nestjs/test/sonarqube.e2e-spec.ts @@ -21,6 +21,7 @@ import { VaultClientService } from '../src/modules/vault/vault-client.service' import { VaultModule } from '../src/modules/vault/vault.module' import { getDotenvPaths } from '../src/utils/dotenv.utils' import { getAll } from '../src/utils/iterable.utils' +import { E2E_TIMEOUT } from './e2e-timeout' const canRunSonarqubeE2E = Boolean(process.env.E2E) @@ -158,7 +159,7 @@ describeWithSonarqube('SonarqubeService (e2e)', () => { expect(vaultSecret?.data?.SONAR_USERNAME).toBe(testProjectSlug) expect(vaultSecret?.data?.SONAR_TOKEN).toBeTruthy() expect(vaultSecret?.data?.SONAR_PASSWORD).toBeTruthy() - }, 30000) + }, E2E_TIMEOUT.provision) it('should delete the project from SonarQube and remove vault credentials', async () => { const project = await prisma.project.findUniqueOrThrow({ @@ -166,15 +167,18 @@ describeWithSonarqube('SonarqubeService (e2e)', () => { select: projectSelect, }) + const projectKey = generateProjectKey(testProjectSlug, testRepoName) + const projectsBefore = await getAll(sonarqubeClient.searchProject({ q: testProjectSlug })) + expect(projectsBefore.some(p => p.key === projectKey)).toBe(true) + await eventEmitter.emitAsync('project.delete', project) // SonarQube analysis project should be removed - const projectKey = generateProjectKey(testProjectSlug, testRepoName) const projectsResult = await getAll(sonarqubeClient.searchProject({ q: testProjectSlug })) expect(projectsResult.some(p => p.key === projectKey)).toBe(false) // Vault credentials should be removed const vaultSecret = await vaultService.readSonarqubeUser(testProjectSlug) expect(vaultSecret).toBeNull() - }, 30000) + }, E2E_TIMEOUT.provision) }) diff --git a/apps/server-nestjs/test/vault.e2e-spec.ts b/apps/server-nestjs/test/vault.e2e-spec.ts index b9ff961370..bc3823a6a6 100644 --- a/apps/server-nestjs/test/vault.e2e-spec.ts +++ b/apps/server-nestjs/test/vault.e2e-spec.ts @@ -16,6 +16,7 @@ import { projectSelect } from '../src/modules/vault/vault-datastore.service' import { makeProjectWithDetails } from '../src/modules/vault/vault-testing.utils' import { VaultModule } from '../src/modules/vault/vault.module' import { getDotenvPaths } from '../src/utils/dotenv.utils' +import { E2E_TIMEOUT } from './e2e-timeout' const canRunVaultE2E = Boolean(process.env.E2E) @@ -101,7 +102,7 @@ describeWithVault('VaultService (e2e)', () => { const group = await vaultClient.getIdentityGroupName(adminGroupName) expect(group.data?.id).toBeTruthy() expect(group.data?.name).toBe(adminGroupName) - }, 180000) + }, E2E_TIMEOUT.provisionHeavy) it('should remove project from Vault on delete', async () => { const project = await prisma.project.findUniqueOrThrow({ @@ -109,9 +110,11 @@ describeWithVault('VaultService (e2e)', () => { select: projectSelect, }) + const adminGroupName = `project-${testProjectSlug}-admin` + expect(await vaultClient.getIdentityGroupName(adminGroupName)).toBeTruthy() + await eventEmitter.emitAsync('project.delete', project) - const adminGroupName = `project-${testProjectSlug}-admin` await expect(vaultClient.getIdentityGroupName(adminGroupName)).rejects.toThrow('Not Found') - }, 180000) + }, E2E_TIMEOUT.provisionHeavy) }) diff --git a/apps/server-nestjs/test/zone.e2e-spec.ts b/apps/server-nestjs/test/zone.e2e-spec.ts index b801fce4ff..0f552ec79a 100644 --- a/apps/server-nestjs/test/zone.e2e-spec.ts +++ b/apps/server-nestjs/test/zone.e2e-spec.ts @@ -16,6 +16,7 @@ import { makeZoneWithDetails } from '../src/modules/vault/vault-testing.utils' import { VaultModule } from '../src/modules/vault/vault.module' import { VaultService } from '../src/modules/vault/vault.service' import { getDotenvPaths } from '../src/utils/dotenv.utils' +import { E2E_TIMEOUT } from './e2e-timeout' const canRunZoneE2E = Boolean(process.env.E2E) @@ -69,14 +70,16 @@ describeWithZone('Zone lifecycle (e2e)', () => { const kvName = `zone-${zoneSlug}` const roleId = await vaultClient.getAuthApproleRoleRoleId(kvName) expect(roleId).toBeTruthy() - }, 180000) + }, E2E_TIMEOUT.provisionHeavy) it('should remove zone from Vault on delete', async () => { const zone = makeZoneWithDetails({ id: zoneId, slug: zoneSlug }) + const kvName = `zone-${zoneSlug}` + expect(await vaultClient.getAuthApproleRoleRoleId(kvName)).toBeTruthy() + await eventEmitter.emitAsync('zone.delete', zone) - const kvName = `zone-${zoneSlug}` await expect(vaultClient.getAuthApproleRoleRoleId(kvName)).rejects.toThrow() - }, 180000) + }, E2E_TIMEOUT.provisionHeavy) }) From f3d6a2ae37bfd25f1dfe794e4c62f1b74c2f6331 Mon Sep 17 00:00:00 2001 From: William Phetsinorath Date: Thu, 6 Aug 2026 16:03:11 +0200 Subject: [PATCH 6/6] refactor(server-nestjs): make e2e timeout composable and fix undefined gitlab timeout Signed-off-by: William Phetsinorath Change-Id: I4d11cbd9ae5679c8e9593aac6e2653696a6a6964 --- apps/server-nestjs/test/argocd.e2e-spec.ts | 8 ++++---- apps/server-nestjs/test/e2e-timeout.ts | 16 +++++++-------- apps/server-nestjs/test/gitlab.e2e-spec.ts | 8 ++++---- apps/server-nestjs/test/keycloak.e2e-spec.ts | 20 +++++++++---------- apps/server-nestjs/test/sonarqube.e2e-spec.ts | 6 +++--- apps/server-nestjs/test/vault.e2e-spec.ts | 6 +++--- apps/server-nestjs/test/zone.e2e-spec.ts | 6 +++--- 7 files changed, 34 insertions(+), 36 deletions(-) diff --git a/apps/server-nestjs/test/argocd.e2e-spec.ts b/apps/server-nestjs/test/argocd.e2e-spec.ts index 0ea5c669ef..9835165475 100644 --- a/apps/server-nestjs/test/argocd.e2e-spec.ts +++ b/apps/server-nestjs/test/argocd.e2e-spec.ts @@ -19,7 +19,7 @@ import { LoggerModule } from '../src/modules/infrastructure/logger/logger.module import { PermissionModule } from '../src/modules/infrastructure/permission/permission.module' import { VaultClientService } from '../src/modules/vault/vault-client.service' import { getDotenvPaths } from '../src/utils/dotenv.utils' -import { E2E_TIMEOUT } from './e2e-timeout' +import { ARGOCD_RECONCILE_TIMEOUT, EXTERNAL_SYNC_TIMEOUT } from './e2e-timeout' const canRunArgoCDE2E = Boolean(process.env.E2E) @@ -213,7 +213,7 @@ describeWithArgoCD('ArgoCDService (e2e)', () => { vaultProjectValuesPath = `${config.projectsRootDir}/${testProjectId}` await vault.write({ e2e: true }, vaultProjectValuesPath) - }, E2E_TIMEOUT.gitReconcile) + }, ARGOCD_RECONCILE_TIMEOUT) afterAll(async () => { if (vaultProjectValuesPath) { @@ -268,7 +268,7 @@ describeWithArgoCD('ArgoCDService (e2e)', () => { const shouldBeDeleted = await gitlab.getFile(infraProject, staleFilePath, 'main') expect(shouldBeDeleted).toBeUndefined() - }, E2E_TIMEOUT.gitReconcile) + }, ARGOCD_RECONCILE_TIMEOUT) it('should update existing values and delete values of a removed environment', async () => { const before = await prisma.project.findUniqueOrThrow({ @@ -305,5 +305,5 @@ describeWithArgoCD('ArgoCDService (e2e)', () => { const prodFile = await gitlab.getFile(infraProject, prodFilePath, 'main') expect(prodFile).toBeUndefined() - }, E2E_TIMEOUT.syncExternal) + }, EXTERNAL_SYNC_TIMEOUT) }) diff --git a/apps/server-nestjs/test/e2e-timeout.ts b/apps/server-nestjs/test/e2e-timeout.ts index b8e803cc9b..d4787dac14 100644 --- a/apps/server-nestjs/test/e2e-timeout.ts +++ b/apps/server-nestjs/test/e2e-timeout.ts @@ -1,9 +1,7 @@ -// e2e specs hit real external services; the latency lives in the operation, not the test shape, -// so name the budget by what the call actually does instead of a bare size. -export const E2E_TIMEOUT = { - provision: 30_000, // single small resource: sonarqube user + project - syncGroups: 60_000, // keycloak group/role reconciliation - syncExternal: 72_000, // gitlab group+member sync, nexus/registry external teardown - gitReconcile: 144_000, // argocd commit + sync to git - provisionHeavy: 180_000, // vault mount/policy/approle, zone secrets space -} as const +// e2e specs hit real external services; the latency lives in the operation, not the test shape. +// Each timeout names the task it bounds so a reader knows which system and operation it covers. +export const SONARQUBE_PROJECT_TIMEOUT = 30_000 // provision + delete a SonarQube project/user +export const KEYCLOAK_GROUP_SYNC_TIMEOUT = 60_000 // reconcile Keycloak groups/roles +export const EXTERNAL_SYNC_TIMEOUT = 72_000 // sync GitLab groups/members, teardown Nexus/registry +export const ARGOCD_RECONCILE_TIMEOUT = 144_000 // ArgoCD commit + sync to git +export const VAULT_PROVISION_TIMEOUT = 180_000 // provision Vault mounts/policies/approles, zone secrets diff --git a/apps/server-nestjs/test/gitlab.e2e-spec.ts b/apps/server-nestjs/test/gitlab.e2e-spec.ts index d5dc4ac21f..884dddc781 100644 --- a/apps/server-nestjs/test/gitlab.e2e-spec.ts +++ b/apps/server-nestjs/test/gitlab.e2e-spec.ts @@ -19,7 +19,7 @@ import { LoggerModule } from '../src/modules/infrastructure/logger/logger.module import { PermissionModule } from '../src/modules/infrastructure/permission/permission.module' import { VaultClientService } from '../src/modules/vault/vault-client.service' import { getDotenvPaths } from '../src/utils/dotenv.utils' -import { E2E_TIMEOUT } from './e2e-timeout' +import { EXTERNAL_SYNC_TIMEOUT } from './e2e-timeout' const canRunGitlabE2E = Boolean(process.env.E2E) @@ -168,7 +168,7 @@ describeWithGitLab('GitlabService (e2e)', () => { const repoSecret = await vaultService.read(repoVaultPath) expect(repoSecret?.data?.GIT_OUTPUT_USER).toBeTruthy() expect(repoSecret?.data?.GIT_OUTPUT_PASSWORD).toBeTruthy() - }, E2E_TIMEOUT.syncExternal) + }, EXTERNAL_SYNC_TIMEOUT) describe('project members', () => { let newUserId: string | undefined @@ -232,7 +232,7 @@ describeWithGitLab('GitlabService (e2e)', () => { const members = await gitlabClientService.getGroupMembers(group) const isNewMemberPresent = members.some(m => m.id === newUserGitlabId) expect(isNewMemberPresent).toBe(true) - }, E2E_TIMEOUT.extended) + }, EXTERNAL_SYNC_TIMEOUT) }) it('should remove project group from GitLab on delete', async () => { @@ -248,5 +248,5 @@ describeWithGitLab('GitlabService (e2e)', () => { const group = await gitlabClientService.getGroupByPath(groupPath) expect(group).toBeUndefined() - }, E2E_TIMEOUT.extended) + }, EXTERNAL_SYNC_TIMEOUT) }) diff --git a/apps/server-nestjs/test/keycloak.e2e-spec.ts b/apps/server-nestjs/test/keycloak.e2e-spec.ts index 8bfd6f7e02..cb384a9870 100644 --- a/apps/server-nestjs/test/keycloak.e2e-spec.ts +++ b/apps/server-nestjs/test/keycloak.e2e-spec.ts @@ -18,7 +18,7 @@ import { KEYCLOAK_ADMIN_CLIENT, KeycloakClientService } from '../src/modules/key import { projectSelect } from '../src/modules/keycloak/keycloak-datastore.service' import { KeycloakModule } from '../src/modules/keycloak/keycloak.module' import { getDotenvPaths } from '../src/utils/dotenv.utils' -import { E2E_TIMEOUT } from './e2e-timeout' +import { KEYCLOAK_GROUP_SYNC_TIMEOUT } from './e2e-timeout' const canRunKeycloakE2E = Boolean(process.env.E2E) @@ -174,7 +174,7 @@ describeWithKeycloak('KeycloakService (e2e)', () => { const members = await keycloak.getGroupMembers(projectGroup.id) const isMember = members.some(m => m.id === ownerId) expect(isMember).toBe(true) - }, E2E_TIMEOUT.syncGroups) + }, KEYCLOAK_GROUP_SYNC_TIMEOUT) it('should add member to project group when added in DB', async () => { // Create another user in Keycloak and DB @@ -238,7 +238,7 @@ describeWithKeycloak('KeycloakService (e2e)', () => { await keycloakAdminClient.users.del({ id: kcUser.id }) await prisma.projectMembers.deleteMany({ where: { userId: kcUser.id } }) await prisma.user.delete({ where: { id: kcUser.id } }) - }, E2E_TIMEOUT.syncGroups) + }, KEYCLOAK_GROUP_SYNC_TIMEOUT) it('should remove member from project group when removed in DB', async () => { const newUserId = faker.string.uuid() @@ -314,7 +314,7 @@ describeWithKeycloak('KeycloakService (e2e)', () => { await keycloakAdminClient.users.del({ id: kcUser.id }) await prisma.projectMembers.deleteMany({ where: { userId: kcUser.id } }) await prisma.user.delete({ where: { id: kcUser.id } }) - }, E2E_TIMEOUT.syncGroups) + }, KEYCLOAK_GROUP_SYNC_TIMEOUT) it('should handle non-existent users gracefully', async () => { // Add a member in DB that does not exist in Keycloak @@ -349,7 +349,7 @@ describeWithKeycloak('KeycloakService (e2e)', () => { // Cleanup await prisma.projectMembers.deleteMany({ where: { userId: fakeUserId } }) await prisma.user.delete({ where: { id: fakeUserId } }) - }, E2E_TIMEOUT.syncGroups) + }, KEYCLOAK_GROUP_SYNC_TIMEOUT) it('should add user back to Keycloak group if missing but present in DB', async () => { // Create user and add to project in DB @@ -412,7 +412,7 @@ describeWithKeycloak('KeycloakService (e2e)', () => { await keycloakAdminClient.users.del({ id: kcUser.id }) await prisma.projectMembers.deleteMany({ where: { userId: kcUser.id } }) await prisma.user.delete({ where: { id: kcUser.id } }) - }, E2E_TIMEOUT.syncGroups) + }, KEYCLOAK_GROUP_SYNC_TIMEOUT) it('should remove user from Keycloak group if present but missing in DB', async () => { // Create user @@ -471,7 +471,7 @@ describeWithKeycloak('KeycloakService (e2e)', () => { await keycloakAdminClient.users.del({ id: kcUser.id }) await prisma.projectMembers.deleteMany({ where: { userId: kcUser.id } }) await prisma.user.delete({ where: { id: kcUser.id } }) - }, E2E_TIMEOUT.syncGroups) + }, KEYCLOAK_GROUP_SYNC_TIMEOUT) it('should recreate project group if deleted in Keycloak', async () => { // Ensure project exists and is synced @@ -500,7 +500,7 @@ describeWithKeycloak('KeycloakService (e2e)', () => { name: z.string(), }).parse(await keycloak.getGroupByPath(`/${testProjectSlug}`)) expect(recreatedProjectGroup?.name).toBe(testProjectSlug) - }, E2E_TIMEOUT.syncGroups) + }, KEYCLOAK_GROUP_SYNC_TIMEOUT) it('should recreate role group if deleted in Keycloak', async () => { // Ensure project exists and is synced @@ -529,7 +529,7 @@ describeWithKeycloak('KeycloakService (e2e)', () => { name: z.string(), }).parse(await keycloak.getGroupByPath(`/${testProjectSlug}/console/${testRoleName}`)) expect(recreatedRoleGroup?.name).toBe(testRoleName) - }, E2E_TIMEOUT.syncGroups) + }, KEYCLOAK_GROUP_SYNC_TIMEOUT) it('should remove project groups from Keycloak on delete', async () => { const project = await prisma.project.findUniqueOrThrow({ @@ -546,5 +546,5 @@ describeWithKeycloak('KeycloakService (e2e)', () => { const deletedConsoleGroup = await keycloak.getGroupByPath(`/${testProjectSlug}/console`) expect(deletedConsoleGroup).toBeUndefined() - }, E2E_TIMEOUT.syncGroups) + }, KEYCLOAK_GROUP_SYNC_TIMEOUT) }) diff --git a/apps/server-nestjs/test/sonarqube.e2e-spec.ts b/apps/server-nestjs/test/sonarqube.e2e-spec.ts index 397ea43d06..af31d85b58 100644 --- a/apps/server-nestjs/test/sonarqube.e2e-spec.ts +++ b/apps/server-nestjs/test/sonarqube.e2e-spec.ts @@ -21,7 +21,7 @@ import { VaultClientService } from '../src/modules/vault/vault-client.service' import { VaultModule } from '../src/modules/vault/vault.module' import { getDotenvPaths } from '../src/utils/dotenv.utils' import { getAll } from '../src/utils/iterable.utils' -import { E2E_TIMEOUT } from './e2e-timeout' +import { SONARQUBE_PROJECT_TIMEOUT } from './e2e-timeout' const canRunSonarqubeE2E = Boolean(process.env.E2E) @@ -159,7 +159,7 @@ describeWithSonarqube('SonarqubeService (e2e)', () => { expect(vaultSecret?.data?.SONAR_USERNAME).toBe(testProjectSlug) expect(vaultSecret?.data?.SONAR_TOKEN).toBeTruthy() expect(vaultSecret?.data?.SONAR_PASSWORD).toBeTruthy() - }, E2E_TIMEOUT.provision) + }, SONARQUBE_PROJECT_TIMEOUT) it('should delete the project from SonarQube and remove vault credentials', async () => { const project = await prisma.project.findUniqueOrThrow({ @@ -180,5 +180,5 @@ describeWithSonarqube('SonarqubeService (e2e)', () => { // Vault credentials should be removed const vaultSecret = await vaultService.readSonarqubeUser(testProjectSlug) expect(vaultSecret).toBeNull() - }, E2E_TIMEOUT.provision) + }, SONARQUBE_PROJECT_TIMEOUT) }) diff --git a/apps/server-nestjs/test/vault.e2e-spec.ts b/apps/server-nestjs/test/vault.e2e-spec.ts index bc3823a6a6..73c484cafb 100644 --- a/apps/server-nestjs/test/vault.e2e-spec.ts +++ b/apps/server-nestjs/test/vault.e2e-spec.ts @@ -16,7 +16,7 @@ import { projectSelect } from '../src/modules/vault/vault-datastore.service' import { makeProjectWithDetails } from '../src/modules/vault/vault-testing.utils' import { VaultModule } from '../src/modules/vault/vault.module' import { getDotenvPaths } from '../src/utils/dotenv.utils' -import { E2E_TIMEOUT } from './e2e-timeout' +import { VAULT_PROVISION_TIMEOUT } from './e2e-timeout' const canRunVaultE2E = Boolean(process.env.E2E) @@ -102,7 +102,7 @@ describeWithVault('VaultService (e2e)', () => { const group = await vaultClient.getIdentityGroupName(adminGroupName) expect(group.data?.id).toBeTruthy() expect(group.data?.name).toBe(adminGroupName) - }, E2E_TIMEOUT.provisionHeavy) + }, VAULT_PROVISION_TIMEOUT) it('should remove project from Vault on delete', async () => { const project = await prisma.project.findUniqueOrThrow({ @@ -116,5 +116,5 @@ describeWithVault('VaultService (e2e)', () => { await eventEmitter.emitAsync('project.delete', project) await expect(vaultClient.getIdentityGroupName(adminGroupName)).rejects.toThrow('Not Found') - }, E2E_TIMEOUT.provisionHeavy) + }, VAULT_PROVISION_TIMEOUT) }) diff --git a/apps/server-nestjs/test/zone.e2e-spec.ts b/apps/server-nestjs/test/zone.e2e-spec.ts index 0f552ec79a..462359a575 100644 --- a/apps/server-nestjs/test/zone.e2e-spec.ts +++ b/apps/server-nestjs/test/zone.e2e-spec.ts @@ -16,7 +16,7 @@ import { makeZoneWithDetails } from '../src/modules/vault/vault-testing.utils' import { VaultModule } from '../src/modules/vault/vault.module' import { VaultService } from '../src/modules/vault/vault.service' import { getDotenvPaths } from '../src/utils/dotenv.utils' -import { E2E_TIMEOUT } from './e2e-timeout' +import { VAULT_PROVISION_TIMEOUT } from './e2e-timeout' const canRunZoneE2E = Boolean(process.env.E2E) @@ -70,7 +70,7 @@ describeWithZone('Zone lifecycle (e2e)', () => { const kvName = `zone-${zoneSlug}` const roleId = await vaultClient.getAuthApproleRoleRoleId(kvName) expect(roleId).toBeTruthy() - }, E2E_TIMEOUT.provisionHeavy) + }, VAULT_PROVISION_TIMEOUT) it('should remove zone from Vault on delete', async () => { const zone = makeZoneWithDetails({ id: zoneId, slug: zoneSlug }) @@ -81,5 +81,5 @@ describeWithZone('Zone lifecycle (e2e)', () => { await eventEmitter.emitAsync('zone.delete', zone) await expect(vaultClient.getAuthApproleRoleRoleId(kvName)).rejects.toThrow() - }, E2E_TIMEOUT.provisionHeavy) + }, VAULT_PROVISION_TIMEOUT) })