
* First pass * [MM-47801] Added support for security-scoped bookmarks to allow the MAS build to save files wherever needed
198 lines
6.2 KiB
JavaScript
198 lines
6.2 KiB
JavaScript
// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
|
|
// See LICENSE.txt for license information.
|
|
import path from 'path';
|
|
import fs from 'fs';
|
|
|
|
import {shell} from 'electron';
|
|
|
|
import {getDoNotDisturb as getDarwinDoNotDisturb} from 'macos-notification-state';
|
|
|
|
import {DownloadsManager} from 'main/downloadsManager';
|
|
|
|
const downloadLocationMock = '/path/to/downloads';
|
|
const locationMock = '/some/dir/file.txt';
|
|
const locationMock1 = '/downloads/file1.txt';
|
|
jest.mock('electron', () => {
|
|
class NotificationMock {
|
|
static isSupported = jest.fn();
|
|
static didConstruct = jest.fn();
|
|
constructor() {
|
|
NotificationMock.didConstruct();
|
|
}
|
|
on = jest.fn();
|
|
show = jest.fn();
|
|
click = jest.fn();
|
|
close = jest.fn();
|
|
}
|
|
return {
|
|
app: {
|
|
getAppPath: jest.fn(),
|
|
},
|
|
BrowserView: jest.fn().mockImplementation(() => ({
|
|
webContents: {
|
|
loadURL: jest.fn(),
|
|
focus: jest.fn(),
|
|
send: jest.fn(),
|
|
},
|
|
setBounds: jest.fn(),
|
|
})),
|
|
ipcMain: {
|
|
emit: jest.fn(),
|
|
handle: jest.fn(),
|
|
on: jest.fn(),
|
|
},
|
|
Menu: {
|
|
getApplicationMenu: () => ({
|
|
getMenuItemById: jest.fn(),
|
|
}),
|
|
},
|
|
Notification: NotificationMock,
|
|
session: {
|
|
defaultSession: {
|
|
on: jest.fn(),
|
|
},
|
|
},
|
|
shell: {
|
|
showItemInFolder: jest.fn(),
|
|
openPath: jest.fn(),
|
|
},
|
|
};
|
|
});
|
|
jest.mock('path', () => {
|
|
const original = jest.requireActual('path');
|
|
return {
|
|
...original,
|
|
resolve: jest.fn(),
|
|
parse: jest.fn(),
|
|
};
|
|
});
|
|
jest.mock('fs', () => ({
|
|
existsSync: jest.fn().mockReturnValue(false),
|
|
readFileSync: jest.fn().mockImplementation((text) => text),
|
|
writeFile: jest.fn(),
|
|
}));
|
|
jest.mock('macos-notification-state', () => ({
|
|
getDoNotDisturb: jest.fn(),
|
|
}));
|
|
jest.mock('main/windows/windowManager', () => ({
|
|
sendToRenderer: jest.fn(),
|
|
}));
|
|
jest.mock('common/config', () => {
|
|
const original = jest.requireActual('common/config');
|
|
return {
|
|
...original,
|
|
downloadLocation: downloadLocationMock,
|
|
};
|
|
});
|
|
|
|
const downloadsJson = {
|
|
'file1.txt': {
|
|
addedAt: 1662545584346,
|
|
filename: 'file1.txt',
|
|
mimeType: 'text/plain',
|
|
location: '/downloads/file1.txt',
|
|
progress: 100,
|
|
receivedBytes: 5425,
|
|
state: 'completed',
|
|
totalBytes: 5425,
|
|
type: 'file',
|
|
},
|
|
'file2.txt': {
|
|
addedAt: 1662545588346,
|
|
filename: 'file2.txt',
|
|
mimeType: 'text/plain',
|
|
location: '/downloads/file2.txt',
|
|
progress: 100,
|
|
receivedBytes: 5425,
|
|
state: 'cancelled',
|
|
totalBytes: 5425,
|
|
type: 'file',
|
|
},
|
|
};
|
|
const nowSeconds = Date.now() / 1000;
|
|
const item = {
|
|
getFilename: () => 'file.txt',
|
|
getMimeType: () => 'text/plain',
|
|
getReceivedBytes: () => 2121,
|
|
getStartTime: () => nowSeconds,
|
|
getTotalBytes: () => 4242,
|
|
getSavePath: () => locationMock,
|
|
getURL: () => 'http://some-url.com/some-text.txt',
|
|
hasUserGesture: jest.fn().mockReturnValue(true),
|
|
setSavePath: jest.fn(),
|
|
on: jest.fn(),
|
|
setSaveDialogOptions: jest.fn(),
|
|
once: jest.fn(),
|
|
location: locationMock,
|
|
};
|
|
const item1 = {
|
|
...item,
|
|
getFilename: () => 'file1.txt',
|
|
getSavePath: () => locationMock1,
|
|
location: locationMock1,
|
|
};
|
|
describe('main/downloadsManager', () => {
|
|
beforeEach(() => {
|
|
getDarwinDoNotDisturb.mockReturnValue(false);
|
|
});
|
|
|
|
it('should be initialized', () => {
|
|
expect(new DownloadsManager({})).toHaveProperty('downloads', {});
|
|
});
|
|
it('should mark "completed" files that were deleted as "deleted"', () => {
|
|
expect(new DownloadsManager(JSON.stringify(downloadsJson))).toHaveProperty('downloads', {...downloadsJson, 'file1.txt': {...downloadsJson['file1.txt'], state: 'deleted'}});
|
|
});
|
|
it('should handle a new download', () => {
|
|
const dl = new DownloadsManager({});
|
|
path.parse.mockImplementation(() => ({base: 'file.txt'}));
|
|
dl.willDownloadURLs.set('http://some-url.com/some-text.txt', {filePath: locationMock});
|
|
dl.handleNewDownload({preventDefault: jest.fn()}, item, {id: 0, getURL: jest.fn(), downloadURL: jest.fn()});
|
|
expect(dl).toHaveProperty('downloads', {'file.txt': {
|
|
addedAt: nowSeconds * 1000,
|
|
filename: 'file.txt',
|
|
mimeType: 'text/plain',
|
|
location: '/some/dir/file.txt',
|
|
progress: 50,
|
|
receivedBytes: 2121,
|
|
state: 'progressing',
|
|
totalBytes: 4242,
|
|
type: 'file',
|
|
}});
|
|
});
|
|
|
|
it('should monitor network to retrieve the file size of downloading items', () => {
|
|
const dl = new DownloadsManager({});
|
|
const details = {
|
|
responseHeaders: {
|
|
'content-encoding': ['gzip'],
|
|
'x-uncompressed-content-length': ['4242'],
|
|
'content-disposition': ['attachment; filename="file.txt"; foobar'],
|
|
},
|
|
};
|
|
dl.webRequestOnHeadersReceivedHandler(details, jest.fn());
|
|
expect(dl.fileSizes.get('file.txt')).toBe('4242');
|
|
});
|
|
|
|
it('should clear the downloads list', () => {
|
|
const dl = new DownloadsManager(JSON.stringify(downloadsJson));
|
|
dl.clearDownloadsDropDown();
|
|
expect(dl).toHaveProperty('downloads', {});
|
|
});
|
|
|
|
it('should open downloads folder if file deleted', () => {
|
|
const dl = new DownloadsManager(JSON.stringify(downloadsJson));
|
|
path.parse.mockImplementation(() => ({base: 'file1.txt'}));
|
|
dl.showFileInFolder(item1);
|
|
expect(shell.openPath).toHaveBeenCalledWith(downloadLocationMock);
|
|
});
|
|
|
|
it('should show the file in the downloads folder', () => {
|
|
const dl = new DownloadsManager(JSON.stringify(downloadsJson));
|
|
fs.existsSync.mockReturnValueOnce(true);
|
|
path.parse.mockImplementation(() => ({base: 'file1.txt'}));
|
|
dl.showFileInFolder(item1);
|
|
expect(shell.showItemInFolder).toHaveBeenCalledWith(locationMock1);
|
|
});
|
|
});
|
|
|