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