Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -405,7 +405,7 @@ describe('MicrosoftOutlookV2 - listSearch methods', () => {
$top: 100,
},
);
expect(mockTransport.getSubfolders).toHaveBeenCalledWith(mockResponse.value);
expect(mockTransport.getSubfolders).toHaveBeenCalledWith(mockResponse.value, true);
expect(result).toEqual({
results: [
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ describe('MicrosoftOutlookV2 - loadOptions methods', () => {
'/mailFolders',
{},
);
expect(mockTransport.getSubfolders).toHaveBeenCalledWith(mockResponse);
expect(mockTransport.getSubfolders).toHaveBeenCalledWith(mockResponse, true);
expect(result).toEqual([
{ name: 'Inbox', value: 'folder1' },
{ name: 'Sent Items', value: 'folder2' },
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
import { mockDeep } from 'jest-mock-extended';
import type { ILoadOptionsFunctions } from 'n8n-workflow';

import { getSubfolders } from '../../../v2/transport';

describe('MicrosoftOutlookV2 - getSubfolders', () => {
let mockLoadOptionsFunctions: jest.Mocked<ILoadOptionsFunctions>;

beforeEach(() => {
mockLoadOptionsFunctions = mockDeep<ILoadOptionsFunctions>();
mockLoadOptionsFunctions.getCredentials.mockResolvedValue({});
jest.clearAllMocks();
});

afterEach(() => {
jest.resetAllMocks();
});

it('should not request childFolders when childFolderCount is 0', async () => {
const folders = [
{ id: 'folder1', displayName: 'Inbox', childFolderCount: 0 },
{ id: 'folder2', displayName: 'Sent Items', childFolderCount: 0 },
];

const result = await getSubfolders.call(mockLoadOptionsFunctions, folders);

expect(
mockLoadOptionsFunctions.helpers.requestWithAuthentication as jest.Mock,
).not.toHaveBeenCalled();
expect(result).toEqual(folders);
});

it('should paginate child folder requests using nextLink', async () => {
const folders = [{ id: 'inbox', displayName: 'Inbox', childFolderCount: 2 }];

(mockLoadOptionsFunctions.helpers.requestWithAuthentication as jest.Mock)
.mockResolvedValueOnce({
value: [{ id: 'sub1', displayName: 'Work', childFolderCount: 0 }],
'@odata.nextLink':
'https://graph.microsoft.com/v1.0/me/mailFolders/inbox/childFolders?$skip=1',
})
.mockResolvedValueOnce({
value: [{ id: 'sub2', displayName: 'Projects', childFolderCount: 0 }],
});

const result = await getSubfolders.call(mockLoadOptionsFunctions, folders);

expect(
mockLoadOptionsFunctions.helpers.requestWithAuthentication as jest.Mock,
).toHaveBeenCalledTimes(2);
expect(result).toEqual([
{ id: 'inbox', displayName: 'Inbox', childFolderCount: 2 },
{ id: 'sub1', displayName: 'Work', childFolderCount: 0 },
{ id: 'sub2', displayName: 'Projects', childFolderCount: 0 },
]);
});

it('should prefix nested subfolder displayNames with full parent path', async () => {
const folders = [{ id: 'inbox', displayName: 'Inbox', childFolderCount: 1 }];

(mockLoadOptionsFunctions.helpers.requestWithAuthentication as jest.Mock)
.mockResolvedValueOnce({
value: [{ id: 'work', displayName: 'Work', childFolderCount: 1 }],
})
.mockResolvedValueOnce({
value: [{ id: 'q2', displayName: 'Q2', childFolderCount: 0 }],
});

const result = await getSubfolders.call(mockLoadOptionsFunctions, folders, true);

expect(result).toEqual([
{ id: 'inbox', displayName: 'Inbox', childFolderCount: 1 },
{ id: 'work', displayName: 'Inbox/Work', childFolderCount: 1 },
{ id: 'q2', displayName: 'Inbox/Work/Q2', childFolderCount: 0 },
]);
});

it('should return bare subfolder displayNames when addPathToDisplayName is false', async () => {
const folders = [{ id: 'inbox', displayName: 'Inbox', childFolderCount: 1 }];

(mockLoadOptionsFunctions.helpers.requestWithAuthentication as jest.Mock).mockResolvedValueOnce(
{
value: [{ id: 'work', displayName: 'Work', childFolderCount: 0 }],
},
);

const result = await getSubfolders.call(mockLoadOptionsFunctions, folders);

expect(result).toEqual([
{ id: 'inbox', displayName: 'Inbox', childFolderCount: 1 },
{ id: 'work', displayName: 'Work', childFolderCount: 0 },
]);
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -223,7 +223,7 @@ export async function searchFolders(
response = await microsoftApiRequest.call(this, 'GET', '/mailFolders', undefined, qs);
}

let folders = await getSubfolders.call(this, response.value as IDataObject[]);
let folders = await getSubfolders.call(this, response.value as IDataObject[], true);

if (filter) {
filter = filter.toLowerCase();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ export async function getCategoriesNames(
export async function getFolders(this: ILoadOptionsFunctions): Promise<INodePropertyOptions[]> {
const returnData: INodePropertyOptions[] = [];
const response = await microsoftApiRequestAllItems.call(this, 'value', 'GET', '/mailFolders', {});
const folders = await getSubfolders.call(this, response);
const folders = await getSubfolders.call(this, response, true);
for (const folder of folders) {
returnData.push({
name: folder.displayName as string,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -206,21 +206,20 @@ export async function getSubfolders(
const returnData: IDataObject[] = [...folders];
for (const folder of folders) {
if ((folder.childFolderCount as number) > 0) {
let subfolders = await microsoftApiRequest.call(
let subfolders = await microsoftApiRequestAllItems.call(
this,
'value',
'GET',
`/mailFolders/${folder.id}/childFolders`,
);

if (addPathToDisplayName) {
subfolders = subfolders.value.map((subfolder: IDataObject) => {
subfolders = subfolders.map((subfolder: IDataObject) => {
return {
...subfolder,
displayName: `${folder.displayName}/${subfolder.displayName}`,
};
});
} else {
subfolders = subfolders.value;
}

returnData.push(
Expand Down
Loading