diff --git a/demo/search.html b/demo/search.html
index d0c34550..dc92aae1 100644
--- a/demo/search.html
+++ b/demo/search.html
@@ -182,7 +182,7 @@
threadIdObj = JSON.parse(threadIdEl.value);
}
let _has = has.value || null;
- search.searchQuery(queryEl.value, senderIdObj, threadIdObj, _has, startDate, endDate, limitEl.value, offsetEl.value, 0).then(function (result) {
+ search.searchQuery(queryEl.value, senderIdObj, threadIdObj, _has, startDate, endDate, parseInt(limitEl.value, 10), parseInt(offsetEl.value, 10), 0).then(function (result) {
if (result.messages.length < 1) {
resultsEl.innerHTML = "No results found"
}
@@ -220,7 +220,6 @@
});
sendMessage.addEventListener('click', function () {
- search.deleteRealTimeFolder();
if (realTimeIndexing.value !== "") {
let message = realTimeIndexing.value;
search.batchRealTimeIndexing(JSON.parse(message));
diff --git a/installer/mac/SymphonySettingsPlugin.bundle/Contents/Info.plist b/installer/mac/SymphonySettingsPlugin.bundle/Contents/Info.plist
index 091a38ee..6c807c3a 100644
--- a/installer/mac/SymphonySettingsPlugin.bundle/Contents/Info.plist
+++ b/installer/mac/SymphonySettingsPlugin.bundle/Contents/Info.plist
@@ -3,7 +3,7 @@
BuildMachineOSBuild
- 17B48
+ 17C88
CFBundleDevelopmentRegion
en
CFBundleExecutable
@@ -27,17 +27,17 @@
DTCompiler
com.apple.compilers.llvm.clang.1_0
DTPlatformBuild
- 9B55
+ 9C40b
DTPlatformVersion
GM
DTSDKBuild
- 17B41
+ 17C76
DTSDKName
macosx10.13
DTXcode
- 0910
+ 0920
DTXcodeBuild
- 9B55
+ 9C40b
InstallerSectionTitle
Pod Settings
NSHumanReadableCopyright
diff --git a/installer/mac/SymphonySettingsPlugin.bundle/Contents/MacOS/SymphonySettingsPlugin b/installer/mac/SymphonySettingsPlugin.bundle/Contents/MacOS/SymphonySettingsPlugin
index b5565571..bc7b725a 100755
Binary files a/installer/mac/SymphonySettingsPlugin.bundle/Contents/MacOS/SymphonySettingsPlugin and b/installer/mac/SymphonySettingsPlugin.bundle/Contents/MacOS/SymphonySettingsPlugin differ
diff --git a/installer/mac/SymphonySettingsPlugin/SymphonySettingsPlugin.xcodeproj/project.pbxproj b/installer/mac/SymphonySettingsPlugin/SymphonySettingsPlugin.xcodeproj/project.pbxproj
index 715569dd..1cadf319 100644
--- a/installer/mac/SymphonySettingsPlugin/SymphonySettingsPlugin.xcodeproj/project.pbxproj
+++ b/installer/mac/SymphonySettingsPlugin/SymphonySettingsPlugin.xcodeproj/project.pbxproj
@@ -97,7 +97,7 @@
TargetAttributes = {
3A10EBCE1ED4336D0083702F = {
CreatedOnToolsVersion = 8.3.2;
- DevelopmentTeam = 2CWJ37D7FB;
+ DevelopmentTeam = NG92SF5D2E;
ProvisioningStyle = Automatic;
};
};
@@ -279,7 +279,7 @@
buildSettings = {
CODE_SIGN_IDENTITY = "Mac Developer";
COMBINE_HIDPI_IMAGES = YES;
- DEVELOPMENT_TEAM = 2CWJ37D7FB;
+ DEVELOPMENT_TEAM = NG92SF5D2E;
INFOPLIST_FILE = SymphonySettingsPlugin/Info.plist;
INSTALL_PATH = "$(HOME)/Library/Bundles";
MACOSX_DEPLOYMENT_TARGET = 10.7;
@@ -295,7 +295,7 @@
buildSettings = {
CODE_SIGN_IDENTITY = "Mac Developer";
COMBINE_HIDPI_IMAGES = YES;
- DEVELOPMENT_TEAM = 2CWJ37D7FB;
+ DEVELOPMENT_TEAM = NG92SF5D2E;
INFOPLIST_FILE = SymphonySettingsPlugin/Info.plist;
INSTALL_PATH = "$(HOME)/Library/Bundles";
MACOSX_DEPLOYMENT_TARGET = 10.7;
diff --git a/installer/mac/SymphonySettingsPlugin/SymphonySettingsPlugin/MyInstallerPane.m b/installer/mac/SymphonySettingsPlugin/SymphonySettingsPlugin/MyInstallerPane.m
index acb51799..1ad998be 100644
--- a/installer/mac/SymphonySettingsPlugin/SymphonySettingsPlugin/MyInstallerPane.m
+++ b/installer/mac/SymphonySettingsPlugin/SymphonySettingsPlugin/MyInstallerPane.m
@@ -24,9 +24,10 @@
NSString *podUrl = [_podUrlTextBox stringValue];
// Check if the url contains a protocol, if not, prepend https to it
- NSString *prefix = @"https://";
- if (![podUrl hasPrefix:prefix]) {
- podUrl = [prefix stringByAppendingString:podUrl];
+ NSString *securePrefix = @"https://";
+ NSString *prefix = @"http://";
+ if (![podUrl hasPrefix:securePrefix] && ![podUrl hasPrefix:prefix]) {
+ podUrl = [securePrefix stringByAppendingString:podUrl];
[_podUrlTextBox setStringValue:podUrl];
}
diff --git a/installer/win/Symphony-x64.aip b/installer/win/Symphony-x64.aip
index 7ad2734c..7663bb00 100644
--- a/installer/win/Symphony-x64.aip
+++ b/installer/win/Symphony-x64.aip
@@ -24,7 +24,7 @@
-
+
@@ -642,7 +642,7 @@
-
+
diff --git a/js/basicAuth/basic-auth.html b/js/basicAuth/basic-auth.html
index 8eee4110..fd5ea733 100644
--- a/js/basicAuth/basic-auth.html
+++ b/js/basicAuth/basic-auth.html
@@ -87,7 +87,7 @@
-
+
diff --git a/js/downloadManager/index.js b/js/downloadManager/index.js
index 5ef5ed9e..3f1fbba5 100644
--- a/js/downloadManager/index.js
+++ b/js/downloadManager/index.js
@@ -56,7 +56,7 @@ function showInFinder(id) {
function createDOM(arg) {
if (arg && arg._id) {
-
+
let fileDisplayName = arg.fileName;
let downloadItemKey = arg._id;
diff --git a/js/main.js b/js/main.js
index 8d3184de..8a93340a 100644
--- a/js/main.js
+++ b/js/main.js
@@ -291,17 +291,14 @@ function getUrlAndCreateMainWindow() {
* @param urlFromConfig
*/
function createWin(urlFromConfig) {
- let protocol = '';
// add https protocol if none found.
let parsedUrl = nodeURL.parse(urlFromConfig);
+
if (!parsedUrl.protocol) {
- protocol = 'https';
+ parsedUrl.protocol = 'https:';
+ parsedUrl.slashes = true
}
- let url = nodeURL.format({
- protocol: protocol,
- slahes: true,
- pathname: parsedUrl.href
- });
+ let url = nodeURL.format(parsedUrl);
windowMgr.createMainWindow(url);
}
diff --git a/js/notify/electron-notify.js b/js/notify/electron-notify.js
index 769b30e7..6bfb7cfb 100644
--- a/js/notify/electron-notify.js
+++ b/js/notify/electron-notify.js
@@ -165,6 +165,7 @@ function updateConfig(customConfig) {
if (customConfig.display) {
displayId = customConfig.display;
}
+ closeAll();
}
/**
@@ -477,6 +478,13 @@ function setNotificationContents(notfWindow, notfObj) {
*/
function buildCloseNotification(notificationWindow, notificationObj, getTimeoutId) {
return function(event) {
+
+ // safety check to prevent from using an
+ // already destroyed notification window
+ if (notificationWindow.isDestroyed()) {
+ return new Promise(function(exitEarly) { exitEarly() })
+ }
+
if (closedNotifications[notificationObj.id]) {
delete closedNotifications[notificationObj.id];
return new Promise(function(exitEarly) { exitEarly() });
@@ -711,6 +719,28 @@ function cleanUpInactiveWindow() {
inactiveWindows = [];
}
+/**
+ * Closes all the notifications and windows
+ */
+function closeAll() {
+ // Clear out animation Queue and close windows
+ animationQueue.clear();
+
+ activeNotifications.forEach(function(window) {
+ if (window.displayTimer) {
+ clearTimeout(window.displayTimer);
+ }
+ window.close();
+ });
+
+ cleanUpInactiveWindow();
+
+ // Reset certain vars
+ nextInsertPos = {};
+ activeNotifications = [];
+}
+
+
module.exports.notify = notify;
module.exports.updateConfig = updateConfig;
module.exports.reset = setupConfig;
diff --git a/js/search/queue.js b/js/search/queue.js
index 65452808..ab635167 100644
--- a/js/search/queue.js
+++ b/js/search/queue.js
@@ -6,7 +6,7 @@ let makeBoundTimedCollector = function(isIndexing, timeout, callback) {
return function (...args) {
if (!timer){
timer = setTimeout(function(){
- if (!isIndexing) {
+ if (!isIndexing()) {
flush(getQueue());
}
}, timeout);
@@ -24,7 +24,9 @@ let makeBoundTimedCollector = function(isIndexing, timeout, callback) {
clearTimeout(timer);
timer = null;
resetQueue();
- callback(JSON.stringify(queue));
+ if (queue) {
+ callback(JSON.stringify(queue));
+ }
}
function getQueue(){
diff --git a/js/search/search.js b/js/search/search.js
index 239a9eba..d394990b 100644
--- a/js/search/search.js
+++ b/js/search/search.js
@@ -92,7 +92,7 @@ class Search {
return new Promise((resolve, reject) => {
if (!messages) {
log.send(logLevels.ERROR, 'Batch Indexing: Messages not provided');
- reject(new Error('Batch Indexing: Messages is required'));
+ reject(new Error('Batch Indexing: Messages are required'));
return;
}
@@ -169,10 +169,6 @@ class Search {
* @param message
*/
realTimeIndexing(message) {
- if (!message) {
- log.send(logLevels.ERROR, 'RealTime Indexing: Messages not provided');
- return new Error('RealTime Indexing: Messages is required');
- }
try {
let msg = JSON.parse(message);
@@ -182,12 +178,12 @@ class Search {
}
} catch(e) {
log.send(logLevels.ERROR, 'RealTime Indexing: parse error -> ' + e);
- return (new Error(e));
+ throw (new Error(e));
}
if (!this.isInitialized) {
log.send(logLevels.ERROR, 'Library not initialized');
- return new Error('Library not initialized');
+ throw new Error('Library not initialized');
}
this.isRealTimeIndexing = true;
@@ -195,7 +191,7 @@ class Search {
this.isRealTimeIndexing = false;
if (err) {
log.send(logLevels.ERROR, 'RealTime Indexing: error -> ' + err);
- return new Error(err);
+ throw new Error(err);
}
return result;
});
@@ -268,7 +264,7 @@ class Search {
if (!fs.existsSync(this.indexFolderName) || !fs.existsSync(this.realTimeIndex)) {
log.send(logLevels.ERROR, 'Index folder does not exist.');
- reject('Index folder does not exist.');
+ reject(new Error('Index folder does not exist.'));
return;
}
@@ -296,15 +292,15 @@ class Search {
}
}
- if (!_limit && _limit === "" && typeof _limit !== 'number' && Math.round(_limit) !== _limit) {
+ if (!_limit || _limit === "" || typeof _limit !== 'number' || Math.round(_limit) !== _limit) {
_limit = 25;
}
- if (!_offset && _offset === "" && typeof _offset !== 'number' && Math.round(_offset) !== _offset) {
+ if (!_offset || _offset === "" || typeof _offset !== 'number' || Math.round(_offset) !== _offset) {
_offset = 0
}
- if (!_sortOrder && _sortOrder === "" && typeof _sortOrder !== 'number' && Math.round(_sortOrder) !== _sortOrder) {
+ if (!_sortOrder || _sortOrder === "" || typeof _sortOrder !== 'number' || Math.round(_sortOrder) !== _sortOrder) {
_sortOrder = searchConfig.SORT_BY_SCORE;
}
@@ -327,13 +323,13 @@ class Search {
return new Promise((resolve, reject) => {
if (!this.isInitialized) {
log.send(logLevels.ERROR, 'Library not initialized');
- reject('Not initialized');
+ reject(new Error('Not initialized'));
return;
}
if (!fs.existsSync(this.indexFolderName)) {
log.send(logLevels.ERROR, 'Index folder does not exist.');
- reject('Index folder does not exist.');
+ reject(new Error('Index folder does not exist.'));
return;
}
diff --git a/js/search/searchUtils.js b/js/search/searchUtils.js
index 3ab3985f..4269f0f3 100644
--- a/js/search/searchUtils.js
+++ b/js/search/searchUtils.js
@@ -23,14 +23,7 @@ class SearchUtils {
if (!isMac) {
this.path = this.path.substring(0, 2);
}
- checkDiskSpace(this.path, function (error, res) {
-
- if (error) {
- return reject(new Error(error));
- }
-
- return resolve(res >= searchConfig.MINIMUM_DISK_SPACE);
- });
+ checkDiskSpace(this.path, resolve, reject);
});
}
@@ -120,7 +113,13 @@ function createUser(userId, oldConfig) {
function createUserConfigFile(userId, data) {
let createStream = fs.createWriteStream(searchConfig.FOLDERS_CONSTANTS.USER_CONFIG_FILE);
if (data) {
- createStream.write(`{"${userId}": ${JSON.stringify(data)}}`);
+ let jsonData;
+ try {
+ jsonData = JSON.stringify(data);
+ createStream.write(`{"${userId}": ${jsonData}}`);
+ } catch (e) {
+ createStream.write(`{"${userId}": {}}`);
+ }
} else {
createStream.write(`{"${userId}": {}}`);
}
@@ -149,7 +148,7 @@ function updateConfig(userId, data, resolve, reject) {
oldConfig = JSON.parse(oldData);
} catch (e) {
createUserConfigFile(userId, data);
- return reject('can not parse user config file data: ' + e);
+ return reject(new Error('can not parse user config file data: ' + e));
}
let newConfig = Object.assign({}, oldConfig);
diff --git a/js/search/utils/checkDiskSpace.js b/js/search/utils/checkDiskSpace.js
index 08fd297e..f8d1c729 100644
--- a/js/search/utils/checkDiskSpace.js
+++ b/js/search/utils/checkDiskSpace.js
@@ -1,42 +1,43 @@
const { exec } = require('child_process');
const { isMac } = require('../../utils/misc');
+const searchConfig = require('../searchConfig.js');
-function checkDiskSpace(path, callback) {
+function checkDiskSpace(path, resolve, reject) {
if (!path) {
- return "Please provide path"
+ reject(new Error("Please provide path"));
+ return;
}
if (isMac) {
exec("df -k '" + path.replace(/'/g,"'\\''") + "'", (error, stdout, stderr) => {
if (error) {
if (stderr.indexOf("No such file or directory") !== -1) {
- return callback("No such file or directory : " + error)
+ return reject(new Error("No such file or directory : " + error))
}
- return callback("Error : " + error)
+ return reject(new Error("Error : " + error));
}
let data = stdout.trim().split("\n");
let disk_info_str = data[data.length - 1].replace( /[\s\n\r]+/g,' ');
let freeSpace = disk_info_str.split(' ');
- return callback(null, freeSpace[3] * 1024);
+ let space = freeSpace[3] * 1024;
+ return resolve(space >= searchConfig.MINIMUM_DISK_SPACE);
});
} else {
exec(`fsutil volume diskfree ${path}`, (error, stdout, stderr) => {
if (error) {
if (stderr.indexOf("No such file or directory") !== -1) {
- return callback("No such file or directory : " + error)
+ return reject(new Error("No such file or directory : " + error));
}
- return callback("Error : " + error)
+ return reject(new Error("Error : " + error));
}
let data = stdout.trim().split("\n");
let disk_info_str = data[data.length - 1].split(':');
- return callback(null, disk_info_str[1]);
+ return resolve(disk_info_str[1] >= searchConfig.MINIMUM_DISK_SPACE);
});
}
-
- return null;
}
module.exports = {
diff --git a/js/windowMgr.js b/js/windowMgr.js
index d756c179..1bfb4431 100644
--- a/js/windowMgr.js
+++ b/js/windowMgr.js
@@ -145,7 +145,7 @@ function doCreateMainWindow(initialUrl, initialBounds) {
}
// will set the main window on top as per the user prefs
- if (alwaysOnTop){
+ if (alwaysOnTop) {
newWinOpts.alwaysOnTop = alwaysOnTop;
}
@@ -179,7 +179,7 @@ function doCreateMainWindow(initialUrl, initialBounds) {
loadErrors.showNetworkConnectivityError(mainWindow, url, retry);
} else {
// updates the notify config with user preference
- notify.updateConfig({position: position, display: display});
+ notify.updateConfig({ position: position, display: display });
// removes all existing notifications when main window reloads
notify.reset();
log.send(logLevels.INFO, 'loaded main window url: ' + url);
@@ -188,7 +188,7 @@ function doCreateMainWindow(initialUrl, initialBounds) {
});
mainWindow.webContents.on('did-fail-load', function (event, errorCode,
- errorDesc, validatedURL) {
+ errorDesc, validatedURL) {
loadErrors.showLoadFailure(mainWindow, validatedURL, errorDesc, errorCode, retry, false);
});
@@ -218,7 +218,7 @@ function doCreateMainWindow(initialUrl, initialBounds) {
const menu = electron.Menu.buildFromTemplate(getTemplate(app));
electron.Menu.setApplicationMenu(menu);
- mainWindow.on('close', function(e) {
+ mainWindow.on('close', function (e) {
if (willQuitApp) {
destroyAllWindows();
return;
@@ -259,7 +259,7 @@ function doCreateMainWindow(initialUrl, initialBounds) {
// When download is in progress, send necessary data to indicate the same
webContents.send('downloadProgress');
-
+
// An extra check to see if the user created downloads directory has been deleted
// This scenario can occur when user doesn't quit electron and continues using it
// across days and then deletes the folder.
@@ -267,21 +267,17 @@ function doCreateMainWindow(initialUrl, initialBounds) {
downloadsDirectory = defaultDownloadsDirectory;
updateConfigField("downloadsDirectory", downloadsDirectory);
}
-
+
// We check the downloads directory to see if a file with the similar name
// already exists and get a unique filename if that's the case
let newFileName = getUniqueFileName(item.getFilename());
- item.setSavePath(downloadsDirectory + "/" + newFileName);
-
- // Send file path to construct the DOM in the UI when the download is complete
-
- // if the user has set a custom downloads directory, save file to that directory
- // if otherwise, we save it to the operating system's default downloads directory
- if (downloadsDirectory) {
- item.setSavePath(downloadsDirectory + "/" + item.getFilename());
+ if (isMac) {
+ item.setSavePath(downloadsDirectory + "/" + newFileName);
+ } else {
+ item.setSavePath(downloadsDirectory + "\\" + newFileName);
}
- // Send file path when download is complete
+ // Send file path to construct the DOM in the UI when the download is complete
item.once('done', (e, state) => {
if (state === 'completed') {
let data = {
@@ -296,35 +292,37 @@ function doCreateMainWindow(initialUrl, initialBounds) {
});
getConfigField('url')
- .then(initializeCrashReporter)
- .catch(app.quit);
-
- function initializeCrashReporter(podUrl) {
+ .then(initializeCrashReporter)
+ .catch(app.quit);
+
+ function initializeCrashReporter(podUrl) {
getConfigField('crashReporter')
- .then((crashReporterConfig) => {
- log.send(logLevels.INFO, 'Initializing crash reporter on the main window!');
- crashReporter.start({companyName: crashReporterConfig.companyName, submitURL: crashReporterConfig.submitURL, uploadToServer: crashReporterConfig.uploadToServer, extra: {'process': 'renderer / main window', podUrl: podUrl}});
- log.send(logLevels.INFO, 'initialized crash reporter on the main window!');
- mainWindow.webContents.send('register-crash-reporter', {companyName: crashReporterConfig.companyName, submitURL: crashReporterConfig.submitURL, uploadToServer: crashReporterConfig.uploadToServer, process: 'preload script / main window renderer'});
- })
- .catch((err) => {
- log.send(logLevels.ERROR, 'Unable to initialize crash reporter in the main window. Error is -> ' + err);
- });
- }
+ .then((crashReporterConfig) => {
+ log.send(logLevels.INFO, 'Initializing crash reporter on the main window!');
+ crashReporter.start({ companyName: crashReporterConfig.companyName, submitURL: crashReporterConfig.submitURL, uploadToServer: crashReporterConfig.uploadToServer, extra: { 'process': 'renderer / main window', podUrl: podUrl } });
+ log.send(logLevels.INFO, 'initialized crash reporter on the main window!');
+ mainWindow.webContents.send('register-crash-reporter', { companyName: crashReporterConfig.companyName, submitURL: crashReporterConfig.submitURL, uploadToServer: crashReporterConfig.uploadToServer, process: 'preload script / main window renderer' });
+ })
+ .catch((err) => {
+ log.send(logLevels.ERROR, 'Unable to initialize crash reporter in the main window. Error is -> ' + err);
+ });
+ }
// open external links in default browser - a tag with href='_blank' or window.open
mainWindow.webContents.on('new-window', function (event, newWinUrl,
- frameName, disposition, newWinOptions) {
-
+ frameName, disposition, newWinOptions) {
+
let newWinParsedUrl = getParsedUrl(newWinUrl);
let mainWinParsedUrl = getParsedUrl(url);
let newWinHost = newWinParsedUrl && newWinParsedUrl.host;
let mainWinHost = mainWinParsedUrl && mainWinParsedUrl.host;
+ let emptyUrlString = 'about:blank';
+
// only allow window.open to succeed is if coming from same hsot,
// otherwise open in default browser.
- if (disposition === 'new-window' && newWinHost === mainWinHost) {
+ if (disposition === 'new-window' && ((newWinHost === mainWinHost) || newWinUrl === emptyUrlString)) {
// handle: window.open
if (!frameName) {
@@ -346,7 +344,7 @@ function doCreateMainWindow(initialUrl, initialBounds) {
let newX = Number.parseInt(query.x, 10);
let newY = Number.parseInt(query.y, 10);
- let newWinRect = {x: newX, y: newY, width, height};
+ let newWinRect = { x: newX, y: newY, width, height };
// only accept if both are successfully parsed.
if (Number.isInteger(newX) && Number.isInteger(newY) &&
@@ -359,7 +357,7 @@ function doCreateMainWindow(initialUrl, initialBounds) {
}
} else {
// create new window at slight offset from main window.
- ({x, y} = getWindowSizeAndPosition(mainWindow));
+ ({ x, y } = getWindowSizeAndPosition(mainWindow));
x += 50;
y += 50;
}
@@ -393,18 +391,18 @@ function doCreateMainWindow(initialUrl, initialBounds) {
}
getConfigField('url')
- .then((podUrl) => {
- getConfigField('crashReporter')
- .then((crashReporterConfig) => {
- crashReporter.start({companyName: crashReporterConfig.companyName, submitURL: crashReporterConfig.submitURL, uploadToServer: crashReporterConfig.uploadToServer, extra: {'process': 'renderer / child window', podUrl: podUrl}});
- log.send(logLevels.INFO, 'initialized crash reporter on a child window!');
- browserWin.webContents.send('register-crash-reporter', {companyName: crashReporterConfig.companyName, submitURL: crashReporterConfig.submitURL, uploadToServer: crashReporterConfig.uploadToServer, process: 'preload script / child window renderer'});
+ .then((podUrl) => {
+ getConfigField('crashReporter')
+ .then((crashReporterConfig) => {
+ crashReporter.start({ companyName: crashReporterConfig.companyName, submitURL: crashReporterConfig.submitURL, uploadToServer: crashReporterConfig.uploadToServer, extra: { 'process': 'renderer / child window', podUrl: podUrl } });
+ log.send(logLevels.INFO, 'initialized crash reporter on a child window!');
+ browserWin.webContents.send('register-crash-reporter', { companyName: crashReporterConfig.companyName, submitURL: crashReporterConfig.submitURL, uploadToServer: crashReporterConfig.uploadToServer, process: 'preload script / child window renderer' });
+ })
+ .catch((err) => {
+ log.send(logLevels.ERROR, 'Unable to initialize crash reporter in the child window. Error is -> ' + err);
+ });
})
- .catch((err) => {
- log.send(logLevels.ERROR, 'Unable to initialize crash reporter in the child window. Error is -> ' + err);
- });
- })
- .catch(app.quit);
+ .catch(app.quit);
browserWin.winName = frameName;
browserWin.setAlwaysOnTop(alwaysOnTop);
@@ -412,7 +410,7 @@ function doCreateMainWindow(initialUrl, initialBounds) {
let handleChildWindowClosed = () => {
removeWindowKey(newWinKey);
browserWin.removeListener('move', throttledBoundsChange);
- browserWin.removeListener('resize', throttledBoundsChange);
+ browserWin.removeListener('resize', throttledBoundsChange);
};
browserWin.once('closed', () => {
@@ -448,11 +446,11 @@ function doCreateMainWindow(initialUrl, initialBounds) {
childEvent.preventDefault();
openUrlInDefaultBrowser(childWinUrl);
};
-
+
// In case we navigate to an external link from inside a pop-out,
// we open that link in an external browser rather than creating
// a new window
- browserWin.webContents.on('new-window', handleChildNewWindowEvent);
+ browserWin.webContents.on('new-window', handleChildNewWindowEvent);
addWindowKey(newWinKey, browserWin);
@@ -465,7 +463,7 @@ function doCreateMainWindow(initialUrl, initialBounds) {
let throttledBoundsChange = throttle(1000,
sendChildWinBoundsChange.bind(null, browserWin));
browserWin.on('move', throttledBoundsChange);
- browserWin.on('resize', throttledBoundsChange);
+ browserWin.on('resize', throttledBoundsChange);
}
});
} else {
@@ -475,14 +473,14 @@ function doCreateMainWindow(initialUrl, initialBounds) {
});
// whenever the main window is navigated for ex: window.location.href or url redirect
- mainWindow.webContents.on('will-navigate', function(event, navigatedURL) {
+ mainWindow.webContents.on('will-navigate', function (event, navigatedURL) {
deleteIndexFolder();
isWhitelisted(navigatedURL)
.catch(() => {
event.preventDefault();
electron.dialog.showMessageBox(mainWindow, {
type: 'warning',
- buttons: [ 'Ok' ],
+ buttons: ['Ok'],
title: 'Not Allowed',
message: `Sorry, you are not allowed to access this website (${navigatedURL}), please contact your administrator for more details`,
});
@@ -628,7 +626,7 @@ function sendChildWinBoundsChange(window) {
* @param urlToOpen
*/
function openUrlInDefaultBrowser(urlToOpen) {
- if (urlToOpen) {
+ if (urlToOpen) {
electron.shell.openExternal(urlToOpen);
}
}
@@ -677,7 +675,7 @@ eventEmitter.on('notificationSettings', (notificationSettings) => {
function verifyDisplays() {
// This is only for Windows, macOS handles this by itself
- if (!mainWindow || isMac){
+ if (!mainWindow || isMac) {
return;
}
@@ -687,14 +685,14 @@ function verifyDisplays() {
let isYAxisValid = true;
// checks to make sure the x,y are valid pairs
- if ((bounds.x === undefined && (bounds.y || bounds.y === 0))){
+ if ((bounds.x === undefined && (bounds.y || bounds.y === 0))) {
isXAxisValid = false;
}
- if ((bounds.y === undefined && (bounds.x || bounds.x === 0))){
+ if ((bounds.y === undefined && (bounds.x || bounds.x === 0))) {
isYAxisValid = false;
}
- if (!isXAxisValid && !isYAxisValid){
+ if (!isXAxisValid && !isYAxisValid) {
return;
}
@@ -725,7 +723,7 @@ function checkExternalDisplay(appBounds) {
// Loops through all the available displays and
// verifies if the wrapper exists within the display bounds
// returns false if not exists otherwise true
- return !!screen.getAllDisplays().find(({bounds}) => {
+ return !!screen.getAllDisplays().find(({ bounds }) => {
const leftMost = x + (width * factor);
const topMost = y + (height * factor);
@@ -748,7 +746,7 @@ function checkExternalDisplay(appBounds) {
function repositionMainWindow() {
const screen = electron.screen;
- const {workArea} = screen.getPrimaryDisplay();
+ const { workArea } = screen.getPrimaryDisplay();
const bounds = workArea;
if (!bounds) {
@@ -765,10 +763,10 @@ function repositionMainWindow() {
const x = Math.round(centerX - (windowWidth / 2.0));
const y = Math.round(centerY - (windowHeight / 2.0));
- let rectangle = {x, y, width: windowWidth, height: windowHeight};
+ let rectangle = { x, y, width: windowWidth, height: windowHeight };
// resetting the main window bounds
- if (mainWindow){
+ if (mainWindow) {
if (!mainWindow.isVisible()) {
mainWindow.show();
}
@@ -790,33 +788,33 @@ function repositionMainWindow() {
* @returns {String} the new filename
*/
function getUniqueFileName(filename) {
-
+
// By default, we assume that the file exists
const fileExists = true;
-
+
// We break the file from it's extension to get the name
const actualFilename = filename.substr(0, filename.lastIndexOf('.')) || filename;
const fileType = filename.split('.').pop();
-
+
// We use this to set the new file name with an increment on the previous existing file
let fileNumber = 0;
let newPath;
-
+
while (fileExists) {
-
+
let fileNameString = fileNumber.toString();
-
+
// By default, we know if the file doesn't exist,
// we can use the filename sent by the remote server
let current = filename;
-
+
// If the file already exists, we know that the
// file number variable is increased, so,
// we construct a new file name with the file number
if (fileNumber > 0) {
current = actualFilename + " (" + fileNameString + ")." + fileType;
}
-
+
// If the file exists, increment the file number and repeat the loop
if (fs.existsSync(downloadsDirectory + "/" + current)) {
fileNumber++;
@@ -824,9 +822,9 @@ function getUniqueFileName(filename) {
newPath = current;
break;
}
-
+
}
-
+
return newPath;
}
diff --git a/tests/Search.test.js b/tests/Search.test.js
new file mode 100644
index 00000000..637afd42
--- /dev/null
+++ b/tests/Search.test.js
@@ -0,0 +1,525 @@
+const childProcess = require('child_process');
+const path = require('path');
+const fs = require('fs');
+
+let executionPath = null;
+let userConfigDir = null;
+
+let searchConfig;
+let SearchApi;
+
+jest.mock('electron', function() {
+ return {
+ app: {
+ getPath: mockedGetPath
+ }
+ }
+});
+
+function mockedGetPath(type) {
+ if (type === 'exe') {
+ return executionPath;
+ }
+
+ if (type === 'userData') {
+ return userConfigDir
+ }
+ return '';
+}
+
+describe('Tests for Search', function() {
+
+ let userId;
+ let key;
+ let dataFolderPath;
+ let realTimeIndexPath;
+ let tempBatchPath;
+ let currentDate = new Date().getTime();
+
+ jasmine.DEFAULT_TIMEOUT_INTERVAL = 90000;
+
+ beforeAll(function (done) {
+ childProcess.exec(`npm rebuild --target=${process.version} --build-from-source`, function(err) {
+
+ userId = 12345678910112;
+ key = 'jjjehdnctsjyieoalskcjdhsnahsadndfnusdfsdfsd=';
+
+ executionPath = path.join(__dirname, 'library');
+ userConfigDir = path.join(__dirname, '..');
+
+ searchConfig = require('../js/search/searchConfig.js');
+ const { Search } = require('../js/search/search.js');
+ SearchApi = new Search(userId, key);
+
+ realTimeIndexPath = path.join(userConfigDir, 'data', 'temp_realtime_index');
+ tempBatchPath = path.join(userConfigDir, 'data', 'temp_batch_indexes');
+ dataFolderPath = path.join(searchConfig.FOLDERS_CONSTANTS.EXEC_PATH, '..', 'data');
+
+ done();
+ });
+ });
+
+ afterAll(function (done) {
+ setTimeout(function () {
+
+ deleteIndexFolders(dataFolderPath);
+ let root = path.join(searchConfig.FOLDERS_CONSTANTS.EXEC_PATH, '..', `${searchConfig.FOLDERS_CONSTANTS.PREFIX_NAME}_${userId}_${searchConfig.INDEX_VERSION}.enc`);
+ if (fs.existsSync(root)) {
+ fs.unlinkSync(root);
+ }
+
+ done();
+ }, 3000);
+ });
+
+ function deleteIndexFolders(location) {
+ if (fs.existsSync(location)) {
+ fs.readdirSync(location).forEach(function(file) {
+ let curPath = location + "/" + file;
+ if (fs.lstatSync(curPath).isDirectory()) {
+ deleteIndexFolders(curPath);
+ } else {
+ fs.unlinkSync(curPath);
+ }
+ });
+ fs.rmdirSync(location);
+ }
+ }
+
+ describe('Search Initial checks', function() {
+
+ it('should be initialized', function (done) {
+ setTimeout(function () {
+
+ expect(SearchApi.isInitialized).toBe(true);
+ expect(SearchApi.indexFolderName).toBe(`${searchConfig.FOLDERS_CONSTANTS.PREFIX_NAME_PATH}_${userId}_${searchConfig.INDEX_VERSION}`);
+ expect(SearchApi.dataFolder).toBe(searchConfig.FOLDERS_CONSTANTS.INDEX_PATH);
+ expect(SearchApi.realTimeIndex).toBe(searchConfig.FOLDERS_CONSTANTS.TEMP_REAL_TIME_INDEX);
+ expect(SearchApi.batchIndex).toBe(searchConfig.FOLDERS_CONSTANTS.TEMP_BATCH_INDEX_FOLDER);
+ expect(SearchApi.messageData).toEqual([]);
+ expect(SearchApi.isRealTimeIndexing).toBe(false);
+
+ done();
+ }, 3000)
+ });
+
+ it('should isLibInit to true', function () {
+ let init = SearchApi.isLibInit();
+ expect(init).toEqual(true);
+ });
+
+ it('should isLibInit to false', function () {
+ SearchApi.isInitialized = false;
+ let init = SearchApi.isLibInit();
+ expect(init).toEqual(false);
+ SearchApi.isInitialized = true;
+ });
+
+ it('should exist index folder', function() {
+ expect(fs.existsSync(path.join(userConfigDir, 'data', 'search_index_12345678910112_v1'))).toBe(true);
+ expect(fs.existsSync(realTimeIndexPath)).toBe(true);
+ });
+
+ it('should not exist index folder', function() {
+ expect(fs.existsSync(tempBatchPath)).toBe(false);
+ });
+ });
+
+ describe('Batch indexing process tests', function () {
+
+ it('should index in a batch', function (done) {
+ let messages = [{
+ messageId: "Jc+4K8RtPxHJfyuDQU9atX///qN3KHYXdA==",
+ threadId: "Au8O2xKHyX1LtE6zW019GX///rZYegAtdA==",
+ ingestionDate: currentDate.toString(),
+ senderId: "71811853189212",
+ chatType: "CHATROOM",
+ isPublic: "false",
+ sendingApp: "lc",
+ text: "it works"
+ }, {
+ messageId: "Jc+4K8RtPxHJfyuDQU9atX///qN3KHYXdA==",
+ threadId: "Au8O2xKHyX1LtE6zW019GX///rZYegAtdA==",
+ ingestionDate: currentDate.toString(),
+ senderId: "71811853189212",
+ chatType: "CHATROOM",
+ isPublic: "false",
+ sendingApp: "lc",
+ text: "it works"
+ }, {
+ messageId: "Jc+4K8RtPxHJfyuDQU9atX///qN3KHYXdA==",
+ threadId: "Au8O2xKHyX1LtE6zW019GX///rZYegAtdA==",
+ ingestionDate: currentDate.toString(),
+ senderId: "71811853189212",
+ chatType: "CHATROOM",
+ isPublic: "false",
+ sendingApp: "lc",
+ text: "it works"
+ }];
+ const indexBatch = jest.spyOn(SearchApi, 'indexBatch');
+ SearchApi.indexBatch(JSON.stringify(messages)).then(function () {
+ expect(fs.existsSync(tempBatchPath)).toBe(true);
+ expect(indexBatch).toHaveBeenCalledWith(JSON.stringify(messages));
+ done();
+ });
+ });
+
+ it('should not batch index', function (done) {
+ const indexBatch = jest.spyOn(SearchApi, 'indexBatch');
+ SearchApi.indexBatch().catch(function (err) {
+ expect(indexBatch).toHaveBeenCalled();
+ expect(err).toBeTruthy();
+ done();
+ });
+ });
+
+ it('should not batch index invalid object', function (done) {
+ const indexBatch = jest.spyOn(SearchApi, 'indexBatch');
+ SearchApi.indexBatch('message').catch(function (err) {
+ expect(err).toBeTruthy();
+ expect(indexBatch).toHaveBeenCalledWith('message');
+ done();
+ });
+ });
+
+ it('should not batch index parse error', function (done) {
+ let message = {
+ messageId: "Jc+4K8RtPxHJfyuDQU9atX///qN3KHYXdA==",
+ threadId: "Au8O2xKHyX1LtE6zW019GX///rZYegAtdA==",
+ ingestionDate: currentDate.toString(),
+ senderId: "71811853189212",
+ chatType: "CHATROOM",
+ isPublic: "false",
+ sendingApp: "lc",
+ text: "it works"
+ };
+ const indexBatch = jest.spyOn(SearchApi, 'indexBatch');
+ SearchApi.indexBatch(JSON.stringify(message)).catch(function (err) {
+ expect(err).toBeTruthy();
+ expect(indexBatch).toHaveBeenCalled();
+ done();
+ });
+ });
+
+ it('should not batch index isInitialized is false', function (done) {
+ SearchApi.isInitialized = false;
+ let message = [ {
+ messageId: "Jc+4K8RtPxHJfyuDQU9atX///qN3KHYXdA==",
+ threadId: "Au8O2xKHyX1LtE6zW019GX///rZYegAtdA==",
+ ingestionDate: currentDate.toString(),
+ senderId: "71811853189212",
+ chatType: "CHATROOM",
+ isPublic: "false",
+ sendingApp: "lc",
+ text: "it fails"
+ } ];
+ const indexBatch = jest.spyOn(SearchApi, 'indexBatch');
+ SearchApi.indexBatch(JSON.stringify(message)).catch(function (err) {
+ expect(err).toBeTruthy();
+ expect(indexBatch).toHaveBeenCalledWith(JSON.stringify(message));
+ SearchApi.isInitialized = true;
+ done();
+ });
+ });
+
+ it('should match messages length after batch indexing', function (done) {
+ const searchQuery = jest.spyOn(SearchApi, 'searchQuery');
+ SearchApi.searchQuery('it works', [], [], '', undefined, undefined, 25, 0, 0).then(function (res) {
+ expect(res.messages.length).toEqual(0);
+ expect(searchQuery).toHaveBeenCalled();
+ done()
+ });
+ });
+
+ it('should merge batch index to user index', function (done) {
+ const mergeIndexBatches = jest.spyOn(SearchApi, 'mergeIndexBatches');
+ SearchApi.mergeIndexBatches().then(function () {
+ expect(fs.existsSync(tempBatchPath)).toBe(false);
+ expect(mergeIndexBatches).toHaveBeenCalled();
+ done();
+ });
+ });
+
+ it('should match messages length after batch indexing', function (done) {
+ const searchQuery = jest.spyOn(SearchApi, 'searchQuery');
+ SearchApi.searchQuery('it works', [], [], '', undefined, undefined, 25, 0, 0).then(function (res) {
+ expect(res.messages.length).toEqual(3);
+ expect(searchQuery).toHaveBeenCalled();
+ done();
+ });
+ });
+ });
+
+ describe('RealTime indexing process', function () {
+
+ it('should index realTime message', function () {
+ let message = [{
+ messageId: "Jc+4K8RtPxHJfyuDQU9atX///qN3KHYXdA==",
+ threadId: "Au8O2xKHyX1LtE6zW019GX///rZYegAtdA==",
+ ingestionDate: currentDate.toString(),
+ senderId: "71811853189212",
+ chatType: "CHATROOM",
+ isPublic: "false",
+ sendingApp: "lc",
+ text: "realtime working"
+ }];
+
+ const batchRealTimeIndexing = jest.spyOn(SearchApi, 'batchRealTimeIndexing');
+ SearchApi.batchRealTimeIndexing(message);
+ expect(batchRealTimeIndexing).toHaveBeenCalled();
+ });
+
+ it('should match message length', function (done) {
+ const searchQuery = jest.spyOn(SearchApi, 'searchQuery');
+ SearchApi.searchQuery('realtime working', ["71811853189212"], ["Au8O2xKHyX1LtE6zW019GX///rZYegAtdA=="], '', undefined, undefined, 25, 0, 0).then(function (res) {
+ expect(res.messages.length).toEqual(3);
+ expect(fs.existsSync(realTimeIndexPath)).toBe(true);
+ expect(searchQuery).toHaveBeenCalled();
+ done();
+ })
+ });
+
+ it('should not index realTime message', function (done) {
+ let message = [{
+ messageId: "Jc+4K8RtPxHJfyuDQU9atX///qN3KHYXdA==",
+ threadId: "Au8O2xKHyX1LtE6zW019GX///rZYegAtdA==",
+ ingestionDate: currentDate.toString(),
+ senderId: "71811853189212",
+ chatType: "CHATROOM",
+ isPublic: "false",
+ sendingApp: "lc",
+ text: "isRealTimeIndexing"
+ }];
+
+ const batchRealTimeIndexing = jest.spyOn(SearchApi, 'batchRealTimeIndexing');
+ const realTimeIndexing = jest.spyOn(SearchApi, 'realTimeIndexing');
+ SearchApi.isRealTimeIndexing = true;
+ expect(SearchApi.checkIsRealTimeIndexing()).toBe(true);
+ SearchApi.batchRealTimeIndexing(message);
+ expect(batchRealTimeIndexing).toHaveBeenCalled();
+ expect(realTimeIndexing).not.toBeCalled();
+ setTimeout(function () {
+
+ SearchApi.searchQuery('isRealTimeIndexing', [], [], '', undefined, undefined, 25, 0, 0).then(function (res) {
+ expect(res.messages.length).toEqual(0);
+ expect(fs.existsSync(realTimeIndexPath)).toBe(true);
+
+ done();
+ });
+ }, 6000)
+ });
+
+ it('should not call the real-time index', function () {
+ let message = [{
+ messageId: "Jc+4K8RtPxHJfyuDQU9atX///qN3KHYXdA==",
+ threadId: "Au8O2xKHyX1LtE6zW019GX///rZYegAtdA==",
+ ingestionDate: currentDate.toString(),
+ senderId: "71811853189212",
+ chatType: "CHATROOM",
+ isPublic: "false",
+ sendingApp: "lc",
+ text: "isRealTimeIndexing"
+ }];
+
+ const batchRealTimeIndexing = jest.spyOn(SearchApi, 'batchRealTimeIndexing');
+ const realTimeIndexing = jest.spyOn(SearchApi, 'realTimeIndexing');
+ SearchApi.isRealTimeIndexing = true;
+ SearchApi.batchRealTimeIndexing(message);
+ expect(batchRealTimeIndexing).toHaveBeenCalled();
+ expect(realTimeIndexing).not.toBeCalled();
+ });
+
+ it('should not realTime index invalid object', function () {
+ let message = [{
+ messageId: "Jc+4K8RtPxHJfyuDQU9atX///qN3KHYXdA==",
+ threadId: "Au8O2xKHyX1LtE6zW019GX///rZYegAtdA==",
+ ingestionDate: currentDate.toString(),
+ senderId: "71811853189212",
+ chatType: "CHATROOM",
+ isPublic: "false",
+ sendingApp: "lc",
+ text: "isRealTimeIndexing"
+ }];
+ const realTimeIndexing = jest.spyOn(SearchApi, 'realTimeIndexing');
+ expect(function () {
+ SearchApi.realTimeIndexing('message')
+ }).toThrow();
+
+ expect(function () {
+ SearchApi.realTimeIndexing()
+ }).toThrow(new Error('RealTime Indexing: Messages is required'));
+
+ SearchApi.isInitialized = false;
+ expect(function () {
+ SearchApi.realTimeIndexing(JSON.stringify(message))
+ }).toThrow(new Error('Library not initialized'));
+ SearchApi.isInitialized = true;
+ expect(realTimeIndexing).toHaveBeenCalled();
+ expect(realTimeIndexing).toHaveBeenCalledTimes(3);
+ });
+
+ it('should return realTime bool', function () {
+ const checkIsRealTimeIndexing = jest.spyOn(SearchApi, 'checkIsRealTimeIndexing');
+ SearchApi.isRealTimeIndexing = true;
+ expect(SearchApi.checkIsRealTimeIndexing()).toBe(true);
+ SearchApi.isRealTimeIndexing = false;
+ expect(SearchApi.checkIsRealTimeIndexing()).toBe(false);
+ expect(checkIsRealTimeIndexing).toHaveBeenCalled();
+ expect(checkIsRealTimeIndexing).toHaveBeenCalledTimes(2);
+ });
+
+ it('should delete realtime index', function () {
+ const deleteRealTimeFolder = jest.spyOn(SearchApi, 'deleteRealTimeFolder');
+ SearchApi.deleteRealTimeFolder();
+ expect(fs.existsSync(realTimeIndexPath)).toBe(true);
+ expect(deleteRealTimeFolder).toHaveBeenCalled();
+ });
+ });
+
+ describe('Test for encryption of the index', function () {
+
+ it('should encrypt user index', function (done) {
+ const encryptIndex = jest.spyOn(SearchApi, 'encryptIndex');
+ SearchApi.encryptIndex(key);
+ expect(encryptIndex).toHaveBeenCalled();
+ done();
+ });
+
+ it('should exist encrypted file', function (done) {
+ setTimeout(function () {
+
+ expect(fs.existsSync(path.join(userConfigDir, 'search_index_12345678910112_v1.enc'))).toBe(true);
+ expect(fs.existsSync(path.join(userConfigDir, 'search_index_12345678910112_v1.tar.lz4'))).toBe(false);
+
+ done();
+ }, 3000);
+ });
+ });
+
+ describe('Test for latest timestamp', function () {
+
+ it('should get the latest timestamp', function (done) {
+ const getLatestMessageTimestamp = jest.spyOn(SearchApi, 'getLatestMessageTimestamp');
+ SearchApi.getLatestMessageTimestamp().then(function (res) {
+ expect(res).toEqual(currentDate.toString());
+ expect(getLatestMessageTimestamp).toHaveBeenCalled();
+ done();
+ });
+ });
+
+ it('should not get the latest timestamp', function (done) {
+ const getLatestMessageTimestamp = jest.spyOn(SearchApi, 'getLatestMessageTimestamp');
+ SearchApi.isInitialized = false;
+ SearchApi.getLatestMessageTimestamp().catch(function (err) {
+ expect(err).toEqual(new Error('Not initialized'));
+ expect(getLatestMessageTimestamp).toHaveBeenCalled();
+ SearchApi.isInitialized = true;
+ done();
+ });
+ });
+
+ it('should not get the latest timestamp', function (done) {
+ SearchApi.indexFolderName = '';
+ const getLatestMessageTimestamp = jest.spyOn(SearchApi, 'getLatestMessageTimestamp');
+ SearchApi.getLatestMessageTimestamp().catch(function (err) {
+ expect(err).toEqual(new Error('Index folder does not exist.'));
+ SearchApi.indexFolderName = `${dataFolderPath}/${searchConfig.FOLDERS_CONSTANTS.PREFIX_NAME}_${userId}_${searchConfig.INDEX_VERSION}`;
+ expect(getLatestMessageTimestamp).toHaveBeenCalled();
+ expect(getLatestMessageTimestamp).toHaveBeenCalledTimes(3);
+ done();
+ });
+ });
+ });
+
+ describe('Test to decrypt the index', function () {
+
+ it('should decrypt the index', function () {
+ deleteIndexFolders(dataFolderPath);
+ const decryptAndInit = jest.spyOn(SearchApi, 'decryptAndInit');
+ SearchApi.decryptAndInit();
+ expect(decryptAndInit).toHaveBeenCalled();
+ });
+
+ it('should get message from the decrypted index', function (done) {
+ setTimeout(function () {
+ const searchQuery = jest.spyOn(SearchApi, 'searchQuery');
+ let endTime = new Date().getTime();
+ let startTime = new Date().getTime() - (4 * 31 * 24 * 60 * 60 * 1000);
+ SearchApi.searchQuery('it works', [], [], '', startTime.toString(), endTime.toString(), '0', 0.2, 0.1).then(function (res) {
+ expect(res.messages.length).toEqual(3);
+ expect(searchQuery).toHaveBeenCalled();
+ done()
+ });
+ }, 3000)
+ });
+ });
+
+ describe('Test for search functions', function () {
+
+ it('should search fail isInitialized is false', function (done) {
+ const searchQuery = jest.spyOn(SearchApi, 'searchQuery');
+ SearchApi.isInitialized = false;
+ SearchApi.searchQuery('it works', [], [], '', '', '', 25, 0, 0).catch(function (err) {
+ expect(err).toEqual(new Error('Library not initialized'));
+ expect(searchQuery).toHaveBeenCalled();
+ SearchApi.isInitialized = true;
+ done();
+ });
+ });
+
+ it('should filter search limit ', function (done) {
+ const searchQuery = jest.spyOn(SearchApi, 'searchQuery');
+ SearchApi.searchQuery('works', [], [], '', '', '', 2, 0, 0).then(function (res) {
+ expect(res.messages.length).toBe(2);
+ expect(searchQuery).toHaveBeenCalledTimes(7);
+ expect(searchQuery).toHaveBeenCalled();
+ done();
+ });
+ });
+
+ it('should search fails index folder not fund', function (done) {
+ const searchQuery = jest.spyOn(SearchApi, 'searchQuery');
+ deleteIndexFolders(dataFolderPath);
+ SearchApi.searchQuery('it works', [], [], '', '', '', 25, 0, 0).catch(function (err) {
+ expect(err).toEqual(new Error('Index folder does not exist.'));
+ expect(searchQuery).toHaveBeenCalledTimes(8);
+ expect(searchQuery).toHaveBeenCalled();
+ SearchApi = undefined;
+ const { Search } = require('../js/search/search.js');
+ SearchApi = new Search(userId, key);
+ done();
+ });
+ });
+
+ it('should search fails query is undefined', function (done) {
+ setTimeout(function () {
+ const searchQuery = jest.spyOn(SearchApi, 'searchQuery');
+ expect(SearchApi.isInitialized).toBe(true);
+ SearchApi.searchQuery(undefined, [], [], '', '', '', 25, 0, 0).catch(function (err) {
+ expect(err).toEqual(new Error('Search query error'));
+ expect(searchQuery).toHaveBeenCalled();
+ done();
+ });
+ }, 3000);
+ });
+
+ it('should search for hashtag', function (done) {
+ const searchQuery = jest.spyOn(SearchApi, 'searchQuery');
+ SearchApi.searchQuery('#123 "testing"', [], [], 'attachment', '', '', 25, 0, 0).then(function (res) {
+ expect(res.messages.length).toEqual(0);
+ expect(searchQuery).toHaveBeenCalled();
+ done();
+ });
+ });
+
+ it('should search for pdf', function (done) {
+ const searchQuery = jest.spyOn(SearchApi, 'searchQuery');
+ SearchApi.searchQuery('', [], [], 'pdf', '', '', 25, 0, 0).then(function (res) {
+ expect(res.messages.length).toEqual(0);
+ expect(searchQuery).toHaveBeenCalled();
+ expect(searchQuery).toHaveBeenCalledTimes(3);
+ done();
+ });
+ });
+ });
+});
\ No newline at end of file
diff --git a/tests/SearchUtils.test.js b/tests/SearchUtils.test.js
new file mode 100644
index 00000000..fc3ccb0c
--- /dev/null
+++ b/tests/SearchUtils.test.js
@@ -0,0 +1,152 @@
+const fs = require('fs');
+const path = require('path');
+
+let executionPath = null;
+let userConfigDir = null;
+
+let SearchUtilsAPI;
+let searchConfig;
+
+jest.mock('electron', function() {
+ return {
+ app: {
+ getPath: mockedGetPath
+ }
+ }
+});
+
+function mockedGetPath(type) {
+ switch (type) {
+ case 'exe':
+ return executionPath;
+ case 'userData':
+ return userConfigDir;
+ default:
+ return ''
+ }
+}
+
+describe('Tests for Search Utils', function() {
+
+ jasmine.DEFAULT_TIMEOUT_INTERVAL = 90000;
+
+ beforeAll(function (done) {
+ executionPath = path.join(__dirname, 'library');
+ userConfigDir = path.join(__dirname, '..');
+ searchConfig = require('../js/search/searchConfig.js');
+ const { SearchUtils } = require('../js/search/searchUtils.js');
+ SearchUtilsAPI = new SearchUtils();
+ SearchUtilsAPI.path = userConfigDir;
+ if (fs.existsSync(searchConfig.FOLDERS_CONSTANTS.USER_CONFIG_FILE)) {
+ fs.unlinkSync(searchConfig.FOLDERS_CONSTANTS.USER_CONFIG_FILE);
+ }
+ done();
+ });
+
+ afterAll(function (done) {
+ fs.unlinkSync(searchConfig.FOLDERS_CONSTANTS.USER_CONFIG_FILE);
+ done();
+ });
+
+ describe('Tests for checking disk space', function () {
+
+ it('should return free space', function (done) {
+ const checkFreeSpace = jest.spyOn(SearchUtilsAPI, 'checkFreeSpace');
+ SearchUtilsAPI.checkFreeSpace().then(function () {
+ expect(checkFreeSpace).toHaveBeenCalled();
+ done();
+ });
+ });
+
+ it('should return error', function (done) {
+ const checkFreeSpace = jest.spyOn(SearchUtilsAPI, 'checkFreeSpace');
+ SearchUtilsAPI.path = undefined;
+ SearchUtilsAPI.checkFreeSpace().catch(function (err) {
+ expect(err).toEqual(new Error("Please provide path"));
+ expect(checkFreeSpace).toHaveBeenCalled();
+ done();
+ });
+ });
+
+ it('should return error invalid path', function (done) {
+ const checkFreeSpace = jest.spyOn(SearchUtilsAPI, 'checkFreeSpace');
+ SearchUtilsAPI.path = './tp';
+ SearchUtilsAPI.checkFreeSpace().catch(function (err) {
+ expect(checkFreeSpace).toHaveBeenCalled();
+ expect(err).toEqual(err);
+ done();
+ });
+ });
+ });
+
+ describe('Test for search users config', function () {
+
+ it('should return null for new user config', function (done) {
+ SearchUtilsAPI.getSearchUserConfig(1234567891011).then(function (res) {
+ expect(res).toEqual(null);
+ done();
+ });
+ });
+
+ it('should exist users config file', function (done) {
+ setTimeout(function () {
+ expect(fs.existsSync(searchConfig.FOLDERS_CONSTANTS.USER_CONFIG_FILE)).toEqual(true);
+ done();
+ }, 2000)
+ });
+
+ it('should exist users config file', function (done) {
+ setTimeout(function () {
+ SearchUtilsAPI.getSearchUserConfig(1234567891011).then(function (res) {
+ expect(res).toEqual({});
+ done();
+ });
+ }, 3000)
+ });
+
+ it('should update user config file', function (done) {
+ let data = {
+ rotationId: 0,
+ version: 1,
+ language: 'en'
+ };
+ SearchUtilsAPI.updateUserConfig(1234567891011, data).then(function (res) {
+ expect(res).toEqual(data);
+ done();
+ })
+ });
+
+ it('should modify user config file', function (done) {
+ let data = {
+ rotationId: 1,
+ version: 1,
+ language: 'en'
+ };
+ SearchUtilsAPI.updateUserConfig(1234567891011, data).then(function (res) {
+ expect(res.rotationId).toEqual(1);
+ done();
+ })
+ });
+
+ it('should create user if not exist', function (done) {
+ SearchUtilsAPI.getSearchUserConfig(2234567891011).catch(function (err) {
+ expect(err).toEqual(null);
+ done();
+ })
+ });
+
+ it('should create file on update', function (done) {
+ fs.unlinkSync(searchConfig.FOLDERS_CONSTANTS.USER_CONFIG_FILE);
+ let data = {
+ rotationId: 0,
+ version: 2,
+ language: 'en'
+ };
+ SearchUtilsAPI.updateUserConfig(2234567891011, data).catch(function (err) {
+ expect(err).toEqual(null);
+ done();
+ })
+ });
+ });
+
+});
\ No newline at end of file