mirror of
https://github.com/Abdulazizzn/n8n-enterprise-unlocked.git
synced 2025-12-20 03:12:15 +00:00
209 lines
5.5 KiB
TypeScript
209 lines
5.5 KiB
TypeScript
import { vi } from 'vitest';
|
|
import { setActivePinia, createPinia } from 'pinia';
|
|
import { faker } from '@faker-js/faker';
|
|
|
|
import { useFoldersStore } from '@/stores/folders.store';
|
|
import * as workflowsApi from '@/api/workflows';
|
|
import type { ChangeLocationSearchResponseItem, IUsedCredential } from '@/Interface';
|
|
import { useRootStore } from '@n8n/stores/useRootStore';
|
|
|
|
vi.mock('@/utils/apiUtils', () => ({
|
|
makeRestApiRequest: vi.fn(),
|
|
}));
|
|
|
|
const createFolder = (
|
|
overrides: Partial<ChangeLocationSearchResponseItem> = {},
|
|
): ChangeLocationSearchResponseItem => ({
|
|
createdAt: faker.date.recent().toISOString(),
|
|
updatedAt: faker.date.recent().toISOString(),
|
|
id: faker.string.alphanumeric(10),
|
|
name: faker.lorem.words(3),
|
|
tags: [],
|
|
parentFolder: {
|
|
id: faker.string.alphanumeric(10),
|
|
name: faker.lorem.words(2),
|
|
parentFolderId: null,
|
|
},
|
|
workflowCount: 2,
|
|
subFolderCount: 2,
|
|
path: [faker.lorem.word(), faker.lorem.word()],
|
|
...overrides,
|
|
});
|
|
|
|
describe('folders.store', () => {
|
|
let foldersStore: ReturnType<typeof useFoldersStore>;
|
|
let rootStore: ReturnType<typeof useRootStore>;
|
|
|
|
beforeEach(() => {
|
|
setActivePinia(createPinia());
|
|
rootStore = useRootStore();
|
|
foldersStore = useFoldersStore();
|
|
});
|
|
|
|
describe('fetchFoldersAvailableForMove', () => {
|
|
const projectId = faker.string.alphanumeric(10);
|
|
const folderId = faker.string.alphanumeric(10);
|
|
const selectFields = [
|
|
'id',
|
|
'name',
|
|
'createdAt',
|
|
'updatedAt',
|
|
'project',
|
|
'tags',
|
|
'parentFolder',
|
|
'workflowCount',
|
|
'subFolderCount',
|
|
'path',
|
|
];
|
|
|
|
it('should fetch folders in a single page, empty filter', async () => {
|
|
const folder = createFolder();
|
|
vi.spyOn(workflowsApi, 'getProjectFolders').mockResolvedValue({
|
|
count: 1,
|
|
data: [folder],
|
|
});
|
|
|
|
const available = await foldersStore.fetchFoldersAvailableForMove(projectId, folderId);
|
|
expect(available).toEqual([{ ...folder, resource: 'folder' }]);
|
|
expect(workflowsApi.getProjectFolders).toHaveBeenCalledTimes(1);
|
|
expect(workflowsApi.getProjectFolders).toHaveBeenCalledWith(
|
|
rootStore.restApiContext,
|
|
projectId,
|
|
{
|
|
skip: 0,
|
|
take: 100,
|
|
sortBy: 'updatedAt:desc',
|
|
},
|
|
{
|
|
excludeFolderIdAndDescendants: folderId,
|
|
},
|
|
selectFields,
|
|
);
|
|
});
|
|
|
|
it('should fetch folders in a single page with filter', async () => {
|
|
const folder = createFolder({ name: 'Test Folder' });
|
|
vi.spyOn(workflowsApi, 'getProjectFolders').mockResolvedValue({
|
|
count: 1,
|
|
data: [folder],
|
|
});
|
|
|
|
const available = await foldersStore.fetchFoldersAvailableForMove(projectId, folderId, {
|
|
name: 'Test',
|
|
});
|
|
expect(available).toEqual([{ ...folder, resource: 'folder' }]);
|
|
expect(workflowsApi.getProjectFolders).toHaveBeenCalledTimes(1);
|
|
expect(workflowsApi.getProjectFolders).toHaveBeenCalledWith(
|
|
rootStore.restApiContext,
|
|
projectId,
|
|
{
|
|
skip: 0,
|
|
take: 100,
|
|
sortBy: 'updatedAt:desc',
|
|
},
|
|
{
|
|
excludeFolderIdAndDescendants: folderId,
|
|
name: 'Test',
|
|
},
|
|
selectFields,
|
|
);
|
|
});
|
|
|
|
it('should fetch folders in multiple pages', async () => {
|
|
const folders = Array.from({ length: 150 }, (_, i) =>
|
|
createFolder({ name: `Folder ${i + 1}` }),
|
|
);
|
|
vi.spyOn(workflowsApi, 'getProjectFolders')
|
|
.mockResolvedValueOnce({
|
|
count: 150,
|
|
data: folders.slice(0, 100),
|
|
})
|
|
.mockResolvedValueOnce({
|
|
count: 150,
|
|
data: folders.slice(100),
|
|
});
|
|
|
|
const available = await foldersStore.fetchFoldersAvailableForMove(projectId, folderId, {
|
|
name: 'Test',
|
|
});
|
|
|
|
expect(available).toHaveLength(150);
|
|
expect(workflowsApi.getProjectFolders).toHaveBeenCalledTimes(2);
|
|
expect(workflowsApi.getProjectFolders).toHaveBeenNthCalledWith(
|
|
1,
|
|
rootStore.restApiContext,
|
|
projectId,
|
|
{
|
|
skip: 0,
|
|
take: 100,
|
|
sortBy: 'updatedAt:desc',
|
|
},
|
|
{
|
|
excludeFolderIdAndDescendants: folderId,
|
|
name: 'Test',
|
|
},
|
|
selectFields,
|
|
);
|
|
expect(workflowsApi.getProjectFolders).toHaveBeenNthCalledWith(
|
|
2,
|
|
rootStore.restApiContext,
|
|
projectId,
|
|
{
|
|
skip: 100,
|
|
take: 100,
|
|
sortBy: 'updatedAt:desc',
|
|
},
|
|
{
|
|
excludeFolderIdAndDescendants: folderId,
|
|
name: 'Test',
|
|
},
|
|
selectFields,
|
|
);
|
|
});
|
|
|
|
it('should cache the results on breadcrumbs cache', async () => {
|
|
const folder = createFolder();
|
|
vi.spyOn(workflowsApi, 'getProjectFolders').mockResolvedValue({
|
|
count: 1,
|
|
data: [folder],
|
|
});
|
|
|
|
const available = await foldersStore.fetchFoldersAvailableForMove(projectId, folderId);
|
|
expect(available).toEqual([{ ...folder, resource: 'folder' }]);
|
|
expect(foldersStore.breadcrumbsCache).toEqual({
|
|
[folder.id]: {
|
|
id: folder.id,
|
|
name: folder.name,
|
|
parentFolder: folder.parentFolder?.id,
|
|
},
|
|
});
|
|
});
|
|
});
|
|
|
|
describe('fetchFolderUsedCredentials', () => {
|
|
const projectId = faker.string.alphanumeric(10);
|
|
const folderId = faker.string.alphanumeric(10);
|
|
|
|
it('should fetch credentials used within a folder', async () => {
|
|
const usedCredential: IUsedCredential = {
|
|
id: faker.string.alphanumeric(10),
|
|
name: faker.lorem.words(2),
|
|
credentialType: faker.lorem.word(),
|
|
currentUserHasAccess: true,
|
|
sharedWithProjects: [],
|
|
};
|
|
|
|
vi.spyOn(workflowsApi, 'getFolderUsedCredentials').mockResolvedValue([usedCredential]);
|
|
|
|
const credentials = await foldersStore.fetchFolderUsedCredentials(projectId, folderId);
|
|
|
|
expect(credentials).toEqual([usedCredential]);
|
|
expect(workflowsApi.getFolderUsedCredentials).toHaveBeenCalledWith(
|
|
rootStore.restApiContext,
|
|
projectId,
|
|
folderId,
|
|
);
|
|
});
|
|
});
|
|
});
|