n8n/packages/cli/test/unit/services/ownership.service.test.ts

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

196 lines
6 KiB
TypeScript
Raw Normal View History

import { OwnershipService } from '@/services/ownership.service';
import { SharedWorkflowRepository } from '@db/repositories/sharedWorkflow.repository';
import { SharedWorkflow } from '@db/entities/SharedWorkflow';
import { User } from '@db/entities/User';
import type { SharedCredentials } from '@db/entities/SharedCredentials';
import { mockInstance } from '../../shared/mocking';
import { WorkflowEntity } from '@/databases/entities/WorkflowEntity';
2023-12-11 04:35:09 -08:00
import { UserRepository } from '@/databases/repositories/user.repository';
import { mock } from 'jest-mock-extended';
import { Project } from '@/databases/entities/Project';
import { ProjectRelationRepository } from '@/databases/repositories/projectRelation.repository';
import { ProjectRelation } from '@/databases/entities/ProjectRelation';
import { mockCredential, mockProject } from '../shared/mockObjects';
describe('OwnershipService', () => {
2023-12-11 04:35:09 -08:00
const userRepository = mockInstance(UserRepository);
const sharedWorkflowRepository = mockInstance(SharedWorkflowRepository);
const projectRelationRepository = mockInstance(ProjectRelationRepository);
const ownershipService = new OwnershipService(
mock(),
userRepository,
mock(),
projectRelationRepository,
sharedWorkflowRepository,
);
beforeEach(() => {
jest.clearAllMocks();
});
describe('getWorkflowProjectCached()', () => {
test('should retrieve a workflow owner project', async () => {
const mockProject = new Project();
const sharedWorkflow = Object.assign(new SharedWorkflow(), {
role: 'workflow:owner',
project: mockProject,
});
sharedWorkflowRepository.findOneOrFail.mockResolvedValueOnce(sharedWorkflow);
const returnedProject = await ownershipService.getWorkflowProjectCached('some-workflow-id');
expect(returnedProject).toBe(mockProject);
});
test('should throw if no workflow owner project found', async () => {
sharedWorkflowRepository.findOneOrFail.mockRejectedValue(new Error());
await expect(ownershipService.getWorkflowProjectCached('some-workflow-id')).rejects.toThrow();
});
});
describe('getProjectOwnerCached()', () => {
test('should retrieve a project owner', async () => {
const mockProject = new Project();
const mockOwner = new User();
const projectRelation = Object.assign(new ProjectRelation(), {
role: 'project:personalOwner',
project: mockProject,
user: mockOwner,
});
projectRelationRepository.getPersonalProjectOwners.mockResolvedValueOnce([projectRelation]);
const returnedOwner = await ownershipService.getProjectOwnerCached('some-project-id');
expect(returnedOwner).toBe(mockOwner);
});
test('should not throw if no project owner found, should return null instead', async () => {
projectRelationRepository.getPersonalProjectOwners.mockResolvedValueOnce([]);
const owner = await ownershipService.getProjectOwnerCached('some-project-id');
expect(owner).toBeNull();
});
});
describe('getProjectOwnerCached()', () => {
test('should retrieve a project owner', async () => {
const mockProject = new Project();
const mockOwner = new User();
const projectRelation = Object.assign(new ProjectRelation(), {
role: 'project:personalOwner',
project: mockProject,
user: mockOwner,
});
projectRelationRepository.getPersonalProjectOwners.mockResolvedValueOnce([projectRelation]);
const returnedOwner = await ownershipService.getProjectOwnerCached('some-project-id');
expect(returnedOwner).toBe(mockOwner);
});
test('should not throw if no project owner found, should return null instead', async () => {
projectRelationRepository.getPersonalProjectOwners.mockResolvedValueOnce([]);
const owner = await ownershipService.getProjectOwnerCached('some-project-id');
expect(owner).toBeNull();
});
});
describe('addOwnedByAndSharedWith()', () => {
test('should add `ownedBy` and `sharedWith` to credential', async () => {
const ownerProject = mockProject();
const editorProject = mockProject();
const credential = mockCredential();
credential.shared = [
{ role: 'credential:owner', project: ownerProject },
{ role: 'credential:editor', project: editorProject },
] as SharedCredentials[];
const { homeProject, sharedWithProjects } =
ownershipService.addOwnedByAndSharedWith(credential);
expect(homeProject).toMatchObject({
id: ownerProject.id,
name: ownerProject.name,
type: ownerProject.type,
});
expect(sharedWithProjects).toMatchObject([
{
id: editorProject.id,
name: editorProject.name,
type: editorProject.type,
},
]);
});
test('should add `ownedBy` and `sharedWith` to workflow', async () => {
const projectOwner = mockProject();
const projectEditor = mockProject();
const workflow = new WorkflowEntity();
workflow.shared = [
{ role: 'workflow:owner', project: projectOwner },
{ role: 'workflow:editor', project: projectEditor },
] as SharedWorkflow[];
const { homeProject, sharedWithProjects } =
ownershipService.addOwnedByAndSharedWith(workflow);
expect(homeProject).toMatchObject({
id: projectOwner.id,
name: projectOwner.name,
type: projectOwner.type,
});
expect(sharedWithProjects).toMatchObject([
{
id: projectEditor.id,
name: projectEditor.name,
type: projectEditor.type,
},
]);
});
test('should produce an empty sharedWith if no sharee', async () => {
const credential = mockCredential();
const project = mockProject();
credential.shared = [{ role: 'credential:owner', project }] as SharedCredentials[];
const { homeProject, sharedWithProjects } =
ownershipService.addOwnedByAndSharedWith(credential);
expect(homeProject).toMatchObject({
id: project.id,
name: project.name,
type: project.type,
});
2023-12-11 04:35:09 -08:00
expect(sharedWithProjects).toHaveLength(0);
});
});
2023-12-11 04:35:09 -08:00
describe('getInstanceOwner()', () => {
test('should find owner using global owner role ID', async () => {
await ownershipService.getInstanceOwner();
2023-12-11 04:35:09 -08:00
expect(userRepository.findOneOrFail).toHaveBeenCalledWith({
where: { role: 'global:owner' },
2023-12-11 04:35:09 -08:00
});
});
});
});