add tests on workspace deletion logic (#10530)
closes [#424](https://github.com/twentyhq/core-team-issues/issues/424)
This commit is contained in:
@ -0,0 +1,228 @@
|
||||
import { Test, TestingModule } from '@nestjs/testing';
|
||||
import { getRepositoryToken } from '@nestjs/typeorm';
|
||||
|
||||
import { Repository } from 'typeorm';
|
||||
|
||||
import { BillingSubscriptionService } from 'src/engine/core-modules/billing/services/billing-subscription.service';
|
||||
import { BillingService } from 'src/engine/core-modules/billing/services/billing.service';
|
||||
import { CustomDomainService } from 'src/engine/core-modules/domain-manager/services/custom-domain.service';
|
||||
import { DomainManagerService } from 'src/engine/core-modules/domain-manager/services/domain-manager.service';
|
||||
import { EmailService } from 'src/engine/core-modules/email/email.service';
|
||||
import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service';
|
||||
import { ExceptionHandlerService } from 'src/engine/core-modules/exception-handler/exception-handler.service';
|
||||
import { FeatureFlagService } from 'src/engine/core-modules/feature-flag/services/feature-flag.service';
|
||||
import { MessageQueue } from 'src/engine/core-modules/message-queue/message-queue.constants';
|
||||
import { MessageQueueService } from 'src/engine/core-modules/message-queue/services/message-queue.service';
|
||||
import { getQueueToken } from 'src/engine/core-modules/message-queue/utils/get-queue-token.util';
|
||||
import { OnboardingService } from 'src/engine/core-modules/onboarding/onboarding.service';
|
||||
import { UserWorkspace } from 'src/engine/core-modules/user-workspace/user-workspace.entity';
|
||||
import { UserWorkspaceService } from 'src/engine/core-modules/user-workspace/user-workspace.service';
|
||||
import { UserService } from 'src/engine/core-modules/user/services/user.service';
|
||||
import { User } from 'src/engine/core-modules/user/user.entity';
|
||||
import { WorkspaceInvitationService } from 'src/engine/core-modules/workspace-invitation/services/workspace-invitation.service';
|
||||
import { WorkspaceService } from 'src/engine/core-modules/workspace/services/workspace.service';
|
||||
import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity';
|
||||
import { PermissionsService } from 'src/engine/metadata-modules/permissions/permissions.service';
|
||||
import { WorkspaceCacheStorageService } from 'src/engine/workspace-cache-storage/workspace-cache-storage.service';
|
||||
import { WorkspaceManagerService } from 'src/engine/workspace-manager/workspace-manager.service';
|
||||
|
||||
describe('WorkspaceService', () => {
|
||||
let service: WorkspaceService;
|
||||
let userWorkspaceRepository: Repository<UserWorkspace>;
|
||||
let userRepository: Repository<User>;
|
||||
let workspaceRepository: Repository<Workspace>;
|
||||
let workspaceCacheStorageService: WorkspaceCacheStorageService;
|
||||
let messageQueueService: MessageQueueService;
|
||||
|
||||
beforeEach(async () => {
|
||||
const module: TestingModule = await Test.createTestingModule({
|
||||
providers: [
|
||||
WorkspaceService,
|
||||
{
|
||||
provide: getRepositoryToken(Workspace, 'core'),
|
||||
useValue: {
|
||||
findOne: jest.fn(),
|
||||
softDelete: jest.fn(),
|
||||
delete: jest.fn(),
|
||||
},
|
||||
},
|
||||
{
|
||||
provide: getRepositoryToken(UserWorkspace, 'core'),
|
||||
useValue: {
|
||||
find: jest.fn(),
|
||||
softDelete: jest.fn(),
|
||||
delete: jest.fn(),
|
||||
},
|
||||
},
|
||||
{
|
||||
provide: getRepositoryToken(User, 'core'),
|
||||
useValue: {
|
||||
softDelete: jest.fn(),
|
||||
},
|
||||
},
|
||||
...[
|
||||
WorkspaceManagerService,
|
||||
WorkspaceManagerService,
|
||||
UserWorkspaceService,
|
||||
UserService,
|
||||
DomainManagerService,
|
||||
CustomDomainService,
|
||||
BillingSubscriptionService,
|
||||
BillingService,
|
||||
EnvironmentService,
|
||||
EmailService,
|
||||
OnboardingService,
|
||||
WorkspaceInvitationService,
|
||||
PermissionsService,
|
||||
FeatureFlagService,
|
||||
ExceptionHandlerService,
|
||||
PermissionsService,
|
||||
].map((service) => ({
|
||||
provide: service,
|
||||
useValue: {},
|
||||
})),
|
||||
{
|
||||
provide: WorkspaceCacheStorageService,
|
||||
useValue: {
|
||||
flush: jest.fn(),
|
||||
},
|
||||
},
|
||||
{
|
||||
provide: getQueueToken(MessageQueue.deleteCascadeQueue),
|
||||
useValue: {
|
||||
add: jest.fn(),
|
||||
},
|
||||
},
|
||||
],
|
||||
}).compile();
|
||||
|
||||
service = module.get<WorkspaceService>(WorkspaceService);
|
||||
userWorkspaceRepository = module.get<Repository<UserWorkspace>>(
|
||||
getRepositoryToken(UserWorkspace, 'core'),
|
||||
);
|
||||
userRepository = module.get<Repository<User>>(
|
||||
getRepositoryToken(User, 'core'),
|
||||
);
|
||||
workspaceRepository = module.get<Repository<Workspace>>(
|
||||
getRepositoryToken(Workspace, 'core'),
|
||||
);
|
||||
workspaceCacheStorageService = module.get<WorkspaceCacheStorageService>(
|
||||
WorkspaceCacheStorageService,
|
||||
);
|
||||
messageQueueService = module.get<MessageQueueService>(
|
||||
getQueueToken(MessageQueue.deleteCascadeQueue),
|
||||
);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
it('should be defined', () => {
|
||||
expect(service).toBeDefined();
|
||||
});
|
||||
|
||||
describe('handleRemoveWorkspaceMember', () => {
|
||||
it('should soft delete the user workspace record', async () => {
|
||||
jest.spyOn(userWorkspaceRepository, 'find').mockResolvedValue([]);
|
||||
|
||||
await service.handleRemoveWorkspaceMember(
|
||||
'workspace-id',
|
||||
'user-id',
|
||||
true,
|
||||
);
|
||||
|
||||
expect(userWorkspaceRepository.softDelete).toHaveBeenCalledWith({
|
||||
userId: 'user-id',
|
||||
workspaceId: 'workspace-id',
|
||||
});
|
||||
expect(userWorkspaceRepository.delete).not.toHaveBeenCalled();
|
||||
expect(userRepository.softDelete).toHaveBeenCalledWith('user-id');
|
||||
});
|
||||
it('should destroy the user workspace record', async () => {
|
||||
jest.spyOn(userWorkspaceRepository, 'find').mockResolvedValue([]);
|
||||
|
||||
await service.handleRemoveWorkspaceMember(
|
||||
'workspace-id',
|
||||
'user-id',
|
||||
false,
|
||||
);
|
||||
|
||||
expect(userWorkspaceRepository.delete).toHaveBeenCalledWith({
|
||||
userId: 'user-id',
|
||||
workspaceId: 'workspace-id',
|
||||
});
|
||||
expect(userWorkspaceRepository.softDelete).not.toHaveBeenCalled();
|
||||
expect(userRepository.softDelete).toHaveBeenCalledWith('user-id');
|
||||
});
|
||||
|
||||
it('should not soft delete the user record if there are other user workspace records', async () => {
|
||||
jest
|
||||
.spyOn(userWorkspaceRepository, 'find')
|
||||
.mockResolvedValue([
|
||||
{ id: 'remaining-user-workspace-id' } as UserWorkspace,
|
||||
]);
|
||||
|
||||
await service.handleRemoveWorkspaceMember(
|
||||
'workspace-id',
|
||||
'user-id',
|
||||
false,
|
||||
);
|
||||
|
||||
expect(userWorkspaceRepository.delete).toHaveBeenCalledWith({
|
||||
userId: 'user-id',
|
||||
workspaceId: 'workspace-id',
|
||||
});
|
||||
expect(userWorkspaceRepository.softDelete).not.toHaveBeenCalled();
|
||||
expect(userRepository.softDelete).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe('deleteWorkspace', () => {
|
||||
it('should delete the workspace', async () => {
|
||||
const mockWorkspace = {
|
||||
id: 'workspace-id',
|
||||
metadataVersion: 0,
|
||||
} as Workspace;
|
||||
|
||||
jest
|
||||
.spyOn(workspaceRepository, 'findOne')
|
||||
.mockResolvedValue(mockWorkspace);
|
||||
jest.spyOn(userWorkspaceRepository, 'find').mockResolvedValue([]);
|
||||
jest
|
||||
.spyOn(service, 'deleteMetadataSchemaCacheAndUserWorkspace')
|
||||
.mockResolvedValue({} as Workspace);
|
||||
|
||||
await service.deleteWorkspace(mockWorkspace.id, false);
|
||||
|
||||
expect(workspaceRepository.delete).toHaveBeenCalledWith(mockWorkspace.id);
|
||||
expect(
|
||||
service.deleteMetadataSchemaCacheAndUserWorkspace,
|
||||
).toHaveBeenCalled();
|
||||
expect(workspaceRepository.softDelete).not.toHaveBeenCalled();
|
||||
expect(workspaceCacheStorageService.flush).toHaveBeenCalledWith(
|
||||
mockWorkspace.id,
|
||||
mockWorkspace.metadataVersion,
|
||||
);
|
||||
expect(messageQueueService.add).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should soft delete the workspace', async () => {
|
||||
const mockWorkspace = {
|
||||
id: 'workspace-id',
|
||||
metadataVersion: 0,
|
||||
} as Workspace;
|
||||
|
||||
jest
|
||||
.spyOn(workspaceRepository, 'findOne')
|
||||
.mockResolvedValue(mockWorkspace);
|
||||
jest.spyOn(userWorkspaceRepository, 'find').mockResolvedValue([]);
|
||||
await service.deleteWorkspace(mockWorkspace.id, true);
|
||||
|
||||
expect(workspaceRepository.softDelete).toHaveBeenCalledWith({
|
||||
id: mockWorkspace.id,
|
||||
});
|
||||
expect(workspaceRepository.delete).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
});
|
||||
@ -1,119 +0,0 @@
|
||||
import { Test, TestingModule } from '@nestjs/testing';
|
||||
import { getRepositoryToken } from '@nestjs/typeorm';
|
||||
|
||||
import { BillingSubscriptionService } from 'src/engine/core-modules/billing/services/billing-subscription.service';
|
||||
import { BillingService } from 'src/engine/core-modules/billing/services/billing.service';
|
||||
import { CustomDomainService } from 'src/engine/core-modules/domain-manager/services/custom-domain.service';
|
||||
import { DomainManagerService } from 'src/engine/core-modules/domain-manager/services/domain-manager.service';
|
||||
import { EmailService } from 'src/engine/core-modules/email/email.service';
|
||||
import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service';
|
||||
import { ExceptionHandlerService } from 'src/engine/core-modules/exception-handler/exception-handler.service';
|
||||
import { FeatureFlagService } from 'src/engine/core-modules/feature-flag/services/feature-flag.service';
|
||||
import { MessageQueue } from 'src/engine/core-modules/message-queue/message-queue.constants';
|
||||
import { getQueueToken } from 'src/engine/core-modules/message-queue/utils/get-queue-token.util';
|
||||
import { OnboardingService } from 'src/engine/core-modules/onboarding/onboarding.service';
|
||||
import { UserWorkspace } from 'src/engine/core-modules/user-workspace/user-workspace.entity';
|
||||
import { UserWorkspaceService } from 'src/engine/core-modules/user-workspace/user-workspace.service';
|
||||
import { UserService } from 'src/engine/core-modules/user/services/user.service';
|
||||
import { User } from 'src/engine/core-modules/user/user.entity';
|
||||
import { WorkspaceInvitationService } from 'src/engine/core-modules/workspace-invitation/services/workspace-invitation.service';
|
||||
import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity';
|
||||
import { PermissionsService } from 'src/engine/metadata-modules/permissions/permissions.service';
|
||||
import { WorkspaceCacheStorageService } from 'src/engine/workspace-cache-storage/workspace-cache-storage.service';
|
||||
import { WorkspaceManagerService } from 'src/engine/workspace-manager/workspace-manager.service';
|
||||
|
||||
import { WorkspaceService } from './workspace.service';
|
||||
|
||||
describe('WorkspaceService', () => {
|
||||
let service: WorkspaceService;
|
||||
|
||||
beforeEach(async () => {
|
||||
const module: TestingModule = await Test.createTestingModule({
|
||||
providers: [
|
||||
WorkspaceService,
|
||||
{
|
||||
provide: getRepositoryToken(Workspace, 'core'),
|
||||
useValue: {},
|
||||
},
|
||||
{
|
||||
provide: getRepositoryToken(UserWorkspace, 'core'),
|
||||
useValue: {},
|
||||
},
|
||||
{
|
||||
provide: getRepositoryToken(User, 'core'),
|
||||
useValue: {},
|
||||
},
|
||||
{
|
||||
provide: WorkspaceManagerService,
|
||||
useValue: {},
|
||||
},
|
||||
{
|
||||
provide: UserWorkspaceService,
|
||||
useValue: {},
|
||||
},
|
||||
{
|
||||
provide: UserService,
|
||||
useValue: {},
|
||||
},
|
||||
{
|
||||
provide: DomainManagerService,
|
||||
useValue: {},
|
||||
},
|
||||
{
|
||||
provide: CustomDomainService,
|
||||
useValue: {},
|
||||
},
|
||||
{
|
||||
provide: BillingSubscriptionService,
|
||||
useValue: {},
|
||||
},
|
||||
{
|
||||
provide: BillingService,
|
||||
useValue: {},
|
||||
},
|
||||
{
|
||||
provide: EnvironmentService,
|
||||
useValue: {},
|
||||
},
|
||||
{
|
||||
provide: EmailService,
|
||||
useValue: {},
|
||||
},
|
||||
{
|
||||
provide: OnboardingService,
|
||||
useValue: {},
|
||||
},
|
||||
{
|
||||
provide: WorkspaceInvitationService,
|
||||
useValue: {},
|
||||
},
|
||||
{
|
||||
provide: FeatureFlagService,
|
||||
useValue: {},
|
||||
},
|
||||
{
|
||||
provide: ExceptionHandlerService,
|
||||
useValue: {},
|
||||
},
|
||||
{
|
||||
provide: PermissionsService,
|
||||
useValue: {},
|
||||
},
|
||||
{
|
||||
provide: WorkspaceCacheStorageService,
|
||||
useValue: {},
|
||||
},
|
||||
{
|
||||
provide: getQueueToken(MessageQueue.deleteCascadeQueue),
|
||||
useValue: {},
|
||||
},
|
||||
],
|
||||
}).compile();
|
||||
|
||||
service = module.get<WorkspaceService>(WorkspaceService);
|
||||
});
|
||||
|
||||
it('should be defined', () => {
|
||||
expect(service).toBeDefined();
|
||||
});
|
||||
});
|
||||
@ -0,0 +1,163 @@
|
||||
import { Test, TestingModule } from '@nestjs/testing';
|
||||
import { getRepositoryToken } from '@nestjs/typeorm';
|
||||
|
||||
import { Repository } from 'typeorm';
|
||||
|
||||
import { FeatureFlagService } from 'src/engine/core-modules/feature-flag/services/feature-flag.service';
|
||||
import { UserWorkspace } from 'src/engine/core-modules/user-workspace/user-workspace.entity';
|
||||
import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity';
|
||||
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 { FieldMetadataEntity } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity';
|
||||
import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
|
||||
import { ObjectMetadataService } from 'src/engine/metadata-modules/object-metadata/object-metadata.service';
|
||||
import { PermissionsService } from 'src/engine/metadata-modules/permissions/permissions.service';
|
||||
import { RelationMetadataEntity } from 'src/engine/metadata-modules/relation-metadata/relation-metadata.entity';
|
||||
import { RoleService } from 'src/engine/metadata-modules/role/role.service';
|
||||
import { UserRoleService } from 'src/engine/metadata-modules/user-role/user-role.service';
|
||||
import { WorkspaceMigrationEntity } from 'src/engine/metadata-modules/workspace-migration/workspace-migration.entity';
|
||||
import { WorkspaceMigrationService } from 'src/engine/metadata-modules/workspace-migration/workspace-migration.service';
|
||||
import { SeederService } from 'src/engine/seeder/seeder.service';
|
||||
import { WorkspaceDataSourceService } from 'src/engine/workspace-datasource/workspace-datasource.service';
|
||||
import { WorkspaceManagerService } from 'src/engine/workspace-manager/workspace-manager.service';
|
||||
import { WorkspaceSyncMetadataService } from 'src/engine/workspace-manager/workspace-sync-metadata/workspace-sync-metadata.service';
|
||||
|
||||
describe('WorkspaceManagerService', () => {
|
||||
let service: WorkspaceManagerService;
|
||||
let objectMetadataService: ObjectMetadataService;
|
||||
let workspaceMigrationRepository: Repository<WorkspaceMigrationEntity>;
|
||||
let dataSourceRepository: Repository<DataSourceEntity>;
|
||||
let workspaceRelationMetadataRepository: Repository<RelationMetadataEntity>;
|
||||
let workspaceFieldMetadataRepository: Repository<FieldMetadataEntity>;
|
||||
let workspaceDataSourceService: WorkspaceDataSourceService;
|
||||
|
||||
beforeEach(async () => {
|
||||
const module: TestingModule = await Test.createTestingModule({
|
||||
providers: [
|
||||
WorkspaceManagerService,
|
||||
WorkspaceMigrationService,
|
||||
DataSourceService,
|
||||
{
|
||||
provide: getRepositoryToken(Workspace, 'core'),
|
||||
useValue: {},
|
||||
},
|
||||
{
|
||||
provide: getRepositoryToken(UserWorkspace, 'core'),
|
||||
useValue: {},
|
||||
},
|
||||
{
|
||||
provide: getRepositoryToken(FieldMetadataEntity, 'metadata'),
|
||||
useValue: {
|
||||
delete: jest.fn(),
|
||||
},
|
||||
},
|
||||
{
|
||||
provide: getRepositoryToken(RelationMetadataEntity, 'metadata'),
|
||||
useValue: {
|
||||
delete: jest.fn(),
|
||||
},
|
||||
},
|
||||
{
|
||||
provide: getRepositoryToken(ObjectMetadataEntity, 'metadata'),
|
||||
useValue: {
|
||||
delete: jest.fn(),
|
||||
},
|
||||
},
|
||||
{
|
||||
provide: getRepositoryToken(WorkspaceMigrationEntity, 'metadata'),
|
||||
useValue: {
|
||||
delete: jest.fn(),
|
||||
},
|
||||
},
|
||||
{
|
||||
provide: getRepositoryToken(DataSourceEntity, 'metadata'),
|
||||
useValue: {
|
||||
delete: jest.fn(),
|
||||
},
|
||||
},
|
||||
{
|
||||
provide: PermissionsService,
|
||||
useValue: {},
|
||||
},
|
||||
{
|
||||
provide: FeatureFlagService,
|
||||
useValue: {},
|
||||
},
|
||||
{
|
||||
provide: RoleService,
|
||||
useValue: {},
|
||||
},
|
||||
{
|
||||
provide: UserRoleService,
|
||||
useValue: {},
|
||||
},
|
||||
{
|
||||
provide: WorkspaceDataSourceService,
|
||||
useValue: {
|
||||
deleteWorkspaceDBSchema: jest.fn(),
|
||||
},
|
||||
},
|
||||
{
|
||||
provide: WorkspaceSyncMetadataService,
|
||||
useValue: {},
|
||||
},
|
||||
{
|
||||
provide: SeederService,
|
||||
useValue: {},
|
||||
},
|
||||
{
|
||||
provide: ObjectMetadataService,
|
||||
useValue: {
|
||||
deleteObjectsMetadata: jest.fn(),
|
||||
},
|
||||
},
|
||||
],
|
||||
}).compile();
|
||||
|
||||
service = module.get<WorkspaceManagerService>(WorkspaceManagerService);
|
||||
objectMetadataService = module.get<ObjectMetadataService>(
|
||||
ObjectMetadataService,
|
||||
);
|
||||
workspaceMigrationRepository = module.get<
|
||||
Repository<WorkspaceMigrationEntity>
|
||||
>(getRepositoryToken(WorkspaceMigrationEntity, 'metadata'));
|
||||
dataSourceRepository = module.get<Repository<DataSourceEntity>>(
|
||||
getRepositoryToken(DataSourceEntity, 'metadata'),
|
||||
);
|
||||
workspaceRelationMetadataRepository = module.get<
|
||||
Repository<RelationMetadataEntity>
|
||||
>(getRepositoryToken(RelationMetadataEntity, 'metadata'));
|
||||
workspaceFieldMetadataRepository = module.get<
|
||||
Repository<FieldMetadataEntity>
|
||||
>(getRepositoryToken(FieldMetadataEntity, 'metadata'));
|
||||
workspaceDataSourceService = module.get<WorkspaceDataSourceService>(
|
||||
WorkspaceDataSourceService,
|
||||
);
|
||||
});
|
||||
|
||||
it('should be defined', () => {
|
||||
expect(service).toBeDefined();
|
||||
});
|
||||
|
||||
describe('delete', () => {
|
||||
it('should delete all the workspace metadata tables and workspace schema', async () => {
|
||||
await service.delete('workspace-id');
|
||||
expect(objectMetadataService.deleteObjectsMetadata).toHaveBeenCalled();
|
||||
expect(workspaceRelationMetadataRepository.delete).toHaveBeenCalledWith({
|
||||
workspaceId: 'workspace-id',
|
||||
});
|
||||
expect(workspaceFieldMetadataRepository.delete).toHaveBeenCalledWith({
|
||||
workspaceId: 'workspace-id',
|
||||
});
|
||||
expect(workspaceMigrationRepository.delete).toHaveBeenCalledWith({
|
||||
workspaceId: 'workspace-id',
|
||||
});
|
||||
expect(dataSourceRepository.delete).toHaveBeenCalledWith({
|
||||
workspaceId: 'workspace-id',
|
||||
});
|
||||
expect(
|
||||
workspaceDataSourceService.deleteWorkspaceDBSchema,
|
||||
).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user