From a7e838fe0cb330c8550e0e539ff7455f27e1b3d1 Mon Sep 17 00:00:00 2001 From: Keerthi Niranjan Date: Fri, 22 Dec 2017 15:46:10 +0530 Subject: [PATCH 01/21] SEARCH-538 - Working on electron unit tests --- tests/Search.test.js | 137 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 137 insertions(+) create mode 100644 tests/Search.test.js diff --git a/tests/Search.test.js b/tests/Search.test.js new file mode 100644 index 00000000..ce429efb --- /dev/null +++ b/tests/Search.test.js @@ -0,0 +1,137 @@ +const electron = require('./__mocks__/electron'); +const childProcess = require('child_process'); +const path = require('path'); +const fs = require('fs'); + +const { isMac } = require('../js/utils/misc.js'); + +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; + jasmine.DEFAULT_TIMEOUT_INTERVAL = 900000; + + beforeAll(function (done) { + childProcess.exec(`npm rebuild --target=${process.version} --build-from-source`, function(err) { + userId = 12345678910112; + key = 'abcdefghijklmnopqrstuvwxyz123456789!@#$%^&*='; + 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); + done(); + }); + }); + + describe('Search Initial checks', function() { + + it('Should be initialized', 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); + }); + + it('Should exist index folder', function() { + expect(fs.existsSync(path.join(userConfigDir, 'data', 'search_index_12345678910112_v1'))).toBe(true); + expect(fs.existsSync(path.join(userConfigDir, 'data', 'temp_realtime_index'))).toBe(true); + }); + + it('Should not exist index folder', function() { + expect(fs.existsSync(path.join(userConfigDir, 'data', 'temp_batch_indexes'))).toBe(false); + }); + + it('Should index in a batch', function () { + let messages = [ + { + messageId: "Jc+4K8RtPxHJfyuDQU9atX///qN3KHYXdA==", + threadId: "Au8O2xKHyX1LtE6zW019GX///rZYegAtdA==", + ingestionDate: "1510684200000", + senderId: "71811853189212", + chatType: "CHATROOM", + isPublic: "false", + sendingApp: "lc", + text: "it works" + } + ]; + SearchApi.indexBatch(JSON.stringify(messages)).then(function () { + expect(fs.existsSync(path.join(userConfigDir, 'data', 'temp_batch_indexes'))).toBe(true); + }); + }); + + it('Should not batch index', function () { + + SearchApi.indexBatch().catch(function (err) { + expect(err).toThrow(err); + }); + + let message = { + messageId: "Jc+4K8RtPxHJfyuDQU9atX///qN3KHYXdA==", + threadId: "Au8O2xKHyX1LtE6zW019GX///rZYegAtdA==", + ingestionDate: "1510684200000", + senderId: "71811853189212", + chatType: "CHATROOM", + isPublic: "false", + sendingApp: "lc", + text: "it fails" + }; + SearchApi.indexBatch(JSON.stringify(message)).catch(function (err) { + expect(err).toThrow(err); + }); + + SearchApi.isInitialized = false; + SearchApi.indexBatch(JSON.stringify(message)).catch(function (err) { + expect(err).toThrow(err); + }); + SearchApi.isInitialized = true; + }); + + it('Should match messages length after batch indexing', function () { + SearchApi.searchQuery('', [], [], '', undefined, undefined, 25, 0, 0).then(function (res) { + expect(res.messages.length).toEqual(0); + }); + }); + + it('Should merge batch index to user index', function () { + SearchApi.mergeIndexBatches().then(function () { + expect(fs.existsSync(path.join(userConfigDir, 'data', 'temp_batch_indexes'))).toBe(false); + }); + }); + + it('Should match messages length after batch indexing', function () { + SearchApi.searchQuery('', [], [], '', undefined, undefined, 25, 0, 0).then(function (res) { + expect(res.messages.length).toEqual(2); + }); + }); + + }); +}); \ No newline at end of file From 316744acafcd08c534148631061d6d14e1b3f37c Mon Sep 17 00:00:00 2001 From: Keerthi Niranjan Date: Tue, 26 Dec 2017 17:34:18 +0530 Subject: [PATCH 02/21] Working on unit tests --- js/search/search.js | 8 +- tests/Search.test.js | 292 ++++++++++++++++++++++++++++++++++++++----- 2 files changed, 264 insertions(+), 36 deletions(-) diff --git a/js/search/search.js b/js/search/search.js index 6f0ad02b..79221e89 100644 --- a/js/search/search.js +++ b/js/search/search.js @@ -171,7 +171,7 @@ class Search { realTimeIndexing(message) { if (!message) { log.send(logLevels.ERROR, 'RealTime Indexing: Messages not provided'); - return new Error('RealTime Indexing: Messages is required'); + throw new Error('RealTime Indexing: Messages is required'); } try { @@ -182,12 +182,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 +195,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; }); diff --git a/tests/Search.test.js b/tests/Search.test.js index ce429efb..e8a743bb 100644 --- a/tests/Search.test.js +++ b/tests/Search.test.js @@ -34,10 +34,12 @@ describe('Tests for Search', function() { let userId; let key; + let realTimeIndexPath; + let tempBatchPath; jasmine.DEFAULT_TIMEOUT_INTERVAL = 900000; beforeAll(function (done) { - childProcess.exec(`npm rebuild --target=${process.version} --build-from-source`, function(err) { + /*childProcess.exec(`npm rebuild --target=${process.version} --build-from-source`, function(err) { userId = 12345678910112; key = 'abcdefghijklmnopqrstuvwxyz123456789!@#$%^&*='; executionPath = path.join(__dirname, 'library'); @@ -45,13 +47,51 @@ describe('Tests for Search', function() { 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'); done(); - }); + });*/ + 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'); + done(); }); + afterAll(function (done) { + setTimeout(() => { + let dataPath = path.join(searchConfig.FOLDERS_CONSTANTS.EXEC_PATH, '..', 'data'); + deleteIndexFolders(dataPath); + let root = path.join(searchConfig.FOLDERS_CONSTANTS.EXEC_PATH, '..', `${searchConfig.FOLDERS_CONSTANTS.PREFIX_NAME}_${userId}_${searchConfig.INDEX_VERSION}.enc`); + if (fs.existsSync(root)) { + fs.unlink(root); + } + done(); + }, 3000); + }); + + function deleteIndexFolders(location) { + if (fs.existsSync(location)) { + fs.readdirSync(location).forEach((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 () { + it('should be initialized', 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); @@ -61,16 +101,32 @@ describe('Tests for Search', function() { expect(SearchApi.isRealTimeIndexing).toBe(false); }); - it('Should exist index folder', function() { + it('should isLibInit to true', function () { + let init = SearchApi.isLibInit(); + expect(init).toEqual(true); + }); + + it('should isLibInit to true', 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(path.join(userConfigDir, 'data', 'temp_realtime_index'))).toBe(true); + expect(fs.existsSync(realTimeIndexPath)).toBe(true); }); - it('Should not exist index folder', function() { - expect(fs.existsSync(path.join(userConfigDir, 'data', 'temp_batch_indexes'))).toBe(false); + it('should not exist index folder', function() { + expect(fs.existsSync(tempBatchPath)).toBe(false); }); - it('Should index in a batch', function () { + }); + + describe('Batch indexing process tests', function () { + + it('should index in a batch', function (done) { let messages = [ { messageId: "Jc+4K8RtPxHJfyuDQU9atX///qN3KHYXdA==", @@ -84,16 +140,26 @@ describe('Tests for Search', function() { } ]; SearchApi.indexBatch(JSON.stringify(messages)).then(function () { - expect(fs.existsSync(path.join(userConfigDir, 'data', 'temp_batch_indexes'))).toBe(true); + expect(fs.existsSync(tempBatchPath)).toBe(true); + done(); }); }); - it('Should not batch index', function () { - + it('should not batch index', function (done) { SearchApi.indexBatch().catch(function (err) { - expect(err).toThrow(err); + expect(err).toBeTruthy(); + done(); }); + }); + it('should not batch index invalid object', function (done) { + SearchApi.indexBatch('message').catch(function (err) { + expect(err).toBeTruthy(); + done(); + }); + }); + + it('should not batch index parse error', function (done) { let message = { messageId: "Jc+4K8RtPxHJfyuDQU9atX///qN3KHYXdA==", threadId: "Au8O2xKHyX1LtE6zW019GX///rZYegAtdA==", @@ -102,36 +168,198 @@ describe('Tests for Search', function() { chatType: "CHATROOM", isPublic: "false", sendingApp: "lc", - text: "it fails" + text: "it works" }; SearchApi.indexBatch(JSON.stringify(message)).catch(function (err) { - expect(err).toThrow(err); + expect(err).toBeTruthy(); + done(); }); + }); + + it('should not batch index isInitialized', function (done) { + SearchApi.isInitialized = false; + let message = [{ + messageId: "Jc+4K8RtPxHJfyuDQU9atX///qN3KHYXdA==", + threadId: "Au8O2xKHyX1LtE6zW019GX///rZYegAtdA==", + ingestionDate: "1510684200000", + senderId: "71811853189212", + chatType: "CHATROOM", + isPublic: "false", + sendingApp: "lc", + text: "it fails" + }]; + SearchApi.indexBatch(JSON.stringify(message)).catch(function (err) { + expect(err).toBeTruthy(); + SearchApi.isInitialized = true; + done(); + }); + }); + + it('should match messages length after batch indexing', function (done) { + SearchApi.searchQuery('it works', [], [], '', undefined, undefined, 25, 0, 0).then(function (res) { + expect(res.messages.length).toEqual(0); + done() + }); + }); + + it('should merge batch index to user index', function (done) { + SearchApi.mergeIndexBatches().then(function () { + expect(fs.existsSync(tempBatchPath)).toBe(false); + done(); + }); + }); + + it('should match messages length after batch indexing', function (done) { + SearchApi.searchQuery('it works', [], [], '', undefined, undefined, 25, 0, 0).then(function (res) { + expect(res.messages.length).toEqual(1); + done(); + }); + }); + }); + + describe('RealTime indexing process', function () { + + it('should index realTime message', function () { + let message = [{ + messageId: "Jc+4K8RtPxHJfyuDQU9atX///qN3KHYXdA==", + threadId: "Au8O2xKHyX1LtE6zW019GX///rZYegAtdA==", + ingestionDate: "1510684200000", + 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) { + SearchApi.searchQuery('realtime working', ["71811853189212"], ["Au8O2xKHyX1LtE6zW019GX///rZYegAtdA=="], '', undefined, undefined, 25, 0, 0).then(function (res) { + expect(res.messages.length).toEqual(1); + expect(fs.existsSync(realTimeIndexPath)).toBe(true); + done(); + }) + }); + + it('should not index realTime message', function (done) { + let message = [{ + messageId: "Jc+4K8RtPxHJfyuDQU9atX///qN3KHYXdA==", + threadId: "Au8O2xKHyX1LtE6zW019GX///rZYegAtdA==", + ingestionDate: "1510684200000", + senderId: "71811853189212", + chatType: "CHATROOM", + isPublic: "false", + sendingApp: "lc", + text: "isRealTimeIndexing" + }]; + const batchRealTimeIndexing = jest.spyOn(SearchApi, 'batchRealTimeIndexing'); + SearchApi.isRealTimeIndexing = false; + SearchApi.batchRealTimeIndexing(message); + expect(batchRealTimeIndexing).toHaveBeenCalled(); + SearchApi.searchQuery('isRealTimeIndexing', [], [], '', undefined, undefined, 25, 0, 0).then(function (res) { + expect(res.messages.length).toEqual(0); + expect(fs.existsSync(realTimeIndexPath)).toBe(true); + done(); + }); + }); + + it('should not realTime index invalid object', function () { + let message = [{ + messageId: "Jc+4K8RtPxHJfyuDQU9atX///qN3KHYXdA==", + threadId: "Au8O2xKHyX1LtE6zW019GX///rZYegAtdA==", + ingestionDate: "1510684200000", + senderId: "71811853189212", + chatType: "CHATROOM", + isPublic: "false", + sendingApp: "lc", + text: "isRealTimeIndexing" + }]; + + expect(function () { + SearchApi.realTimeIndexing('message') + }).toThrow(); + + expect(function () { + SearchApi.realTimeIndexing() + }).toThrow(new Error('RealTime Indexing: Messages is required')); SearchApi.isInitialized = false; - SearchApi.indexBatch(JSON.stringify(message)).catch(function (err) { - expect(err).toThrow(err); - }); + expect(function () { + SearchApi.realTimeIndexing(JSON.stringify(message)) + }).toThrow(new Error('Library not initialized')); SearchApi.isInitialized = true; }); - it('Should match messages length after batch indexing', function () { - SearchApi.searchQuery('', [], [], '', undefined, undefined, 25, 0, 0).then(function (res) { - expect(res.messages.length).toEqual(0); - }); + it('should return realTime bool', function () { + SearchApi.isRealTimeIndexing = true; + expect(SearchApi.checkIsRealTimeIndexing()).toBe(true); + SearchApi.isRealTimeIndexing = false; + expect(SearchApi.checkIsRealTimeIndexing()).toBe(false); }); - it('Should merge batch index to user index', function () { - SearchApi.mergeIndexBatches().then(function () { - expect(fs.existsSync(path.join(userConfigDir, 'data', 'temp_batch_indexes'))).toBe(false); - }); + it('should delete realtime index', function () { + SearchApi.deleteRealTimeFolder(); + expect(fs.existsSync(realTimeIndexPath)).toBe(true); }); - - it('Should match messages length after batch indexing', function () { - SearchApi.searchQuery('', [], [], '', undefined, undefined, 25, 0, 0).then(function (res) { - expect(res.messages.length).toEqual(2); - }); - }); - }); + + + describe('Test for encryption of the index', function () { + + it('should encrypt the user index', function (done) { + SearchApi.encryptIndex(key); + 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(); + },1000); + }); + }); + + describe('Test for latest timestamp', function () { + + it('should get the latest timestamp', function (done) { + SearchApi.getLatestMessageTimestamp().then(function (res) { + expect(res).toEqual('1510684200000'); + done(); + }); + }); + + it('should not get the latest timestamp', function (done) { + SearchApi.isInitialized = false; + SearchApi.getLatestMessageTimestamp().catch(function (err) { + expect(err).toEqual('Not initialized'); + SearchApi.isInitialized = true; + done(); + }); + }); + }); + + describe('Test to decrypt the index', function () { + + it('should decrypt the index', function () { + let dataPath = path.join(searchConfig.FOLDERS_CONSTANTS.EXEC_PATH, '..', 'data'); + deleteIndexFolders(dataPath); + SearchApi.decryptAndInit(); + }); + + it('should get message from the decrypted index', function (done) { + setTimeout(function () { + SearchApi.searchQuery('it works', [], [], '', undefined, undefined, 25, 0, 0).then(function (res) { + expect(res.messages.length).toEqual(1); + done() + }); + }, 3000) + }); + }); + + describe('Test for search functions', function () { + + }) }); \ No newline at end of file From 52c2078e9658024c3432ecc453d77214afa5e494 Mon Sep 17 00:00:00 2001 From: Keerthi Niranjan Date: Wed, 27 Dec 2017 11:57:49 +0530 Subject: [PATCH 03/21] Completed search.js tests --- js/search/queue.js | 2 +- js/search/search.js | 12 ++-- tests/Search.test.js | 144 ++++++++++++++++++++++++++++--------------- 3 files changed, 102 insertions(+), 56 deletions(-) diff --git a/js/search/queue.js b/js/search/queue.js index 65452808..7fb409f4 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); diff --git a/js/search/search.js b/js/search/search.js index 79221e89..836c7a19 100644 --- a/js/search/search.js +++ b/js/search/search.js @@ -273,7 +273,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; } @@ -301,15 +301,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; } @@ -332,13 +332,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/tests/Search.test.js b/tests/Search.test.js index e8a743bb..bcbdc2f0 100644 --- a/tests/Search.test.js +++ b/tests/Search.test.js @@ -1,10 +1,7 @@ -const electron = require('./__mocks__/electron'); const childProcess = require('child_process'); const path = require('path'); const fs = require('fs'); -const { isMac } = require('../js/utils/misc.js'); - let executionPath = null; let userConfigDir = null; @@ -34,14 +31,16 @@ describe('Tests for Search', function() { let userId; let key; + let dataFolderPath; let realTimeIndexPath; let tempBatchPath; - jasmine.DEFAULT_TIMEOUT_INTERVAL = 900000; + 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) { + childProcess.exec(`npm rebuild --target=${process.version} --build-from-source`, function(err) { userId = 12345678910112; - key = 'abcdefghijklmnopqrstuvwxyz123456789!@#$%^&*='; + key = 'jjjehdnctsjyieoalskcjdhsnahsadndfnusdfsdfsd='; executionPath = path.join(__dirname, 'library'); userConfigDir = path.join(__dirname, '..'); searchConfig = require('../js/search/searchConfig.js'); @@ -49,27 +48,17 @@ describe('Tests for Search', function() { 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(); - });*/ - 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'); - done(); + }); }); afterAll(function (done) { setTimeout(() => { - let dataPath = path.join(searchConfig.FOLDERS_CONSTANTS.EXEC_PATH, '..', 'data'); - deleteIndexFolders(dataPath); + 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.unlink(root); + fs.unlinkSync(root); } done(); }, 3000); @@ -91,14 +80,17 @@ describe('Tests for Search', function() { describe('Search Initial checks', function() { - it('should be initialized', 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); + 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 () { @@ -121,7 +113,6 @@ describe('Tests for Search', function() { it('should not exist index folder', function() { expect(fs.existsSync(tempBatchPath)).toBe(false); }); - }); describe('Batch indexing process tests', function () { @@ -131,7 +122,7 @@ describe('Tests for Search', function() { { messageId: "Jc+4K8RtPxHJfyuDQU9atX///qN3KHYXdA==", threadId: "Au8O2xKHyX1LtE6zW019GX///rZYegAtdA==", - ingestionDate: "1510684200000", + ingestionDate: currentDate.toString(), senderId: "71811853189212", chatType: "CHATROOM", isPublic: "false", @@ -163,7 +154,7 @@ describe('Tests for Search', function() { let message = { messageId: "Jc+4K8RtPxHJfyuDQU9atX///qN3KHYXdA==", threadId: "Au8O2xKHyX1LtE6zW019GX///rZYegAtdA==", - ingestionDate: "1510684200000", + ingestionDate: currentDate.toString(), senderId: "71811853189212", chatType: "CHATROOM", isPublic: "false", @@ -181,7 +172,7 @@ describe('Tests for Search', function() { let message = [{ messageId: "Jc+4K8RtPxHJfyuDQU9atX///qN3KHYXdA==", threadId: "Au8O2xKHyX1LtE6zW019GX///rZYegAtdA==", - ingestionDate: "1510684200000", + ingestionDate: currentDate.toString(), senderId: "71811853189212", chatType: "CHATROOM", isPublic: "false", @@ -223,7 +214,7 @@ describe('Tests for Search', function() { let message = [{ messageId: "Jc+4K8RtPxHJfyuDQU9atX///qN3KHYXdA==", threadId: "Au8O2xKHyX1LtE6zW019GX///rZYegAtdA==", - ingestionDate: "1510684200000", + ingestionDate: currentDate.toString(), senderId: "71811853189212", chatType: "CHATROOM", isPublic: "false", @@ -247,7 +238,7 @@ describe('Tests for Search', function() { let message = [{ messageId: "Jc+4K8RtPxHJfyuDQU9atX///qN3KHYXdA==", threadId: "Au8O2xKHyX1LtE6zW019GX///rZYegAtdA==", - ingestionDate: "1510684200000", + ingestionDate: currentDate.toString(), senderId: "71811853189212", chatType: "CHATROOM", isPublic: "false", @@ -255,21 +246,23 @@ describe('Tests for Search', function() { text: "isRealTimeIndexing" }]; const batchRealTimeIndexing = jest.spyOn(SearchApi, 'batchRealTimeIndexing'); - SearchApi.isRealTimeIndexing = false; + SearchApi.isRealTimeIndexing = true; SearchApi.batchRealTimeIndexing(message); expect(batchRealTimeIndexing).toHaveBeenCalled(); - SearchApi.searchQuery('isRealTimeIndexing', [], [], '', undefined, undefined, 25, 0, 0).then(function (res) { - expect(res.messages.length).toEqual(0); - expect(fs.existsSync(realTimeIndexPath)).toBe(true); - done(); - }); + 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 realTime index invalid object', function () { let message = [{ messageId: "Jc+4K8RtPxHJfyuDQU9atX///qN3KHYXdA==", threadId: "Au8O2xKHyX1LtE6zW019GX///rZYegAtdA==", - ingestionDate: "1510684200000", + ingestionDate: currentDate.toString(), senderId: "71811853189212", chatType: "CHATROOM", isPublic: "false", @@ -305,7 +298,6 @@ describe('Tests for Search', function() { }); }); - describe('Test for encryption of the index', function () { it('should encrypt the user index', function (done) { @@ -318,7 +310,7 @@ describe('Tests for Search', 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(); - },1000); + }, 3000); }); }); @@ -326,7 +318,7 @@ describe('Tests for Search', function() { it('should get the latest timestamp', function (done) { SearchApi.getLatestMessageTimestamp().then(function (res) { - expect(res).toEqual('1510684200000'); + expect(res).toEqual(currentDate.toString()); done(); }); }); @@ -334,24 +326,34 @@ describe('Tests for Search', function() { it('should not get the latest timestamp', function (done) { SearchApi.isInitialized = false; SearchApi.getLatestMessageTimestamp().catch(function (err) { - expect(err).toEqual('Not initialized'); + expect(err).toEqual(new Error('Not initialized')); SearchApi.isInitialized = true; done(); }); }); + + it('should not get the latest timestamp', function (done) { + SearchApi.indexFolderName = ''; + 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}`; + done(); + }); + }); }); describe('Test to decrypt the index', function () { it('should decrypt the index', function () { - let dataPath = path.join(searchConfig.FOLDERS_CONSTANTS.EXEC_PATH, '..', 'data'); - deleteIndexFolders(dataPath); + deleteIndexFolders(dataFolderPath); SearchApi.decryptAndInit(); }); it('should get message from the decrypted index', function (done) { setTimeout(function () { - SearchApi.searchQuery('it works', [], [], '', undefined, undefined, 25, 0, 0).then(function (res) { + 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(1); done() }); @@ -361,5 +363,49 @@ describe('Tests for Search', function() { describe('Test for search functions', function () { - }) + it('should search fail isInitialized', function (done) { + SearchApi.isInitialized = false; + SearchApi.searchQuery('it works', [], [], '', '', '', 25, 0, 0).catch(function (err) { + expect(err).toEqual(new Error('Library not initialized')); + SearchApi.isInitialized = true; + done(); + }); + }); + + it('should search fails index folder not fund', function (done) { + deleteIndexFolders(dataFolderPath); + SearchApi.searchQuery('it works', [], [], '', '', '', 25, 0, 0).catch(function (err) { + expect(err).toEqual(new Error('Index folder does not exist.')); + 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 () { + expect(SearchApi.isInitialized).toBe(true); + SearchApi.searchQuery(undefined, [], [], '', '', '', 25, 0, 0).catch(function (err) { + expect(err).toEqual(new Error('Search query error')); + done(); + }); + }, 3000); + }); + + it('should search for hashtag', function (done) { + SearchApi.searchQuery('#123 "testing"', [], [], 'attachment', '', '', 25, 0, 0).then(function (res) { + expect(res.messages.length).toEqual(0); + done(); + }); + }); + + it('should search for pdf', function (done) { + SearchApi.searchQuery('', [], [], 'pdf', '', '', 25, 0, 0).then(function (res) { + expect(res.messages.length).toEqual(0); + done(); + }); + }); + }); + }); \ No newline at end of file From d7b5c28e0f14e088c0847b6ecf21e11bf157874d Mon Sep 17 00:00:00 2001 From: Keerthi Niranjan Date: Wed, 27 Dec 2017 14:04:04 +0530 Subject: [PATCH 04/21] SEARCH-538 - Completed Unit tests for search.js --- tests/Search.test.js | 110 ++++++++++++++++++++++++++++++++++++++----- 1 file changed, 97 insertions(+), 13 deletions(-) diff --git a/tests/Search.test.js b/tests/Search.test.js index bcbdc2f0..916786bd 100644 --- a/tests/Search.test.js +++ b/tests/Search.test.js @@ -35,38 +35,46 @@ describe('Tests for Search', function() { 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(() => { + 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((file) => { + fs.readdirSync(location).forEach(function(file) { let curPath = location + "/" + file; if (fs.lstatSync(curPath).isDirectory()) { deleteIndexFolders(curPath); @@ -82,6 +90,7 @@ describe('Tests for Search', 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); @@ -89,6 +98,7 @@ describe('Tests for Search', function() { expect(SearchApi.batchIndex).toBe(searchConfig.FOLDERS_CONSTANTS.TEMP_BATCH_INDEX_FOLDER); expect(SearchApi.messageData).toEqual([]); expect(SearchApi.isRealTimeIndexing).toBe(false); + done(); }, 3000) }); @@ -98,7 +108,7 @@ describe('Tests for Search', function() { expect(init).toEqual(true); }); - it('should isLibInit to true', function () { + it('should isLibInit to false', function () { SearchApi.isInitialized = false; let init = SearchApi.isLibInit(); expect(init).toEqual(false); @@ -118,8 +128,7 @@ describe('Tests for Search', function() { describe('Batch indexing process tests', function () { it('should index in a batch', function (done) { - let messages = [ - { + let messages = [ { messageId: "Jc+4K8RtPxHJfyuDQU9atX///qN3KHYXdA==", threadId: "Au8O2xKHyX1LtE6zW019GX///rZYegAtdA==", ingestionDate: currentDate.toString(), @@ -128,24 +137,29 @@ describe('Tests for Search', function() { 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(); }); }); @@ -161,15 +175,17 @@ describe('Tests for Search', function() { 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', function (done) { + it('should not batch index isInitialized is false', function (done) { SearchApi.isInitialized = false; - let message = [{ + let message = [ { messageId: "Jc+4K8RtPxHJfyuDQU9atX///qN3KHYXdA==", threadId: "Au8O2xKHyX1LtE6zW019GX///rZYegAtdA==", ingestionDate: currentDate.toString(), @@ -178,31 +194,39 @@ describe('Tests for Search', function() { 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(1); + expect(searchQuery).toHaveBeenCalled(); done(); }); }); @@ -221,15 +245,18 @@ describe('Tests for Search', function() { 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(1); expect(fs.existsSync(realTimeIndexPath)).toBe(true); + expect(searchQuery).toHaveBeenCalled(); done(); }) }); @@ -245,19 +272,42 @@ describe('Tests for Search', function() { sendingApp: "lc", text: "isRealTimeIndexing" }]; + const batchRealTimeIndexing = jest.spyOn(SearchApi, 'batchRealTimeIndexing'); SearchApi.isRealTimeIndexing = true; SearchApi.batchRealTimeIndexing(message); expect(batchRealTimeIndexing).toHaveBeenCalled(); 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==", @@ -269,7 +319,7 @@ describe('Tests for Search', function() { sendingApp: "lc", text: "isRealTimeIndexing" }]; - + const realTimeIndexing = jest.spyOn(SearchApi, 'realTimeIndexing'); expect(function () { SearchApi.realTimeIndexing('message') }).toThrow(); @@ -283,32 +333,43 @@ describe('Tests for Search', 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 the user index', function (done) { + 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); }); @@ -317,16 +378,20 @@ describe('Tests for Search', function() { 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(); }); @@ -334,9 +399,12 @@ describe('Tests for Search', function() { 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(); }); }); @@ -346,15 +414,19 @@ describe('Tests for Search', 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(1); + expect(searchQuery).toHaveBeenCalled(); done() }); }, 3000) @@ -363,19 +435,24 @@ describe('Tests for Search', function() { describe('Test for search functions', function () { - it('should search fail isInitialized', function (done) { + 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 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(7); + expect(searchQuery).toHaveBeenCalled(); SearchApi = undefined; const { Search } = require('../js/search/search.js'); SearchApi = new Search(userId, key); @@ -385,24 +462,31 @@ describe('Tests for Search', function() { 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(); }); }); From fbf051b3a3423bc1181abb94d64bf673ce025be6 Mon Sep 17 00:00:00 2001 From: Keerthi Niranjan Date: Thu, 28 Dec 2017 15:29:37 +0530 Subject: [PATCH 05/21] Fixed tests --- demo/search.html | 1 - tests/Search.test.js | 4 +++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/demo/search.html b/demo/search.html index d0c34550..ce8084a0 100644 --- a/demo/search.html +++ b/demo/search.html @@ -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/tests/Search.test.js b/tests/Search.test.js index 916786bd..88ce0c96 100644 --- a/tests/Search.test.js +++ b/tests/Search.test.js @@ -274,9 +274,12 @@ describe('Tests for Search', function() { }]; 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) { @@ -491,5 +494,4 @@ describe('Tests for Search', function() { }); }); }); - }); \ No newline at end of file From c48bb2225e657f6f1c1b7b18ab837e910e4d53ec Mon Sep 17 00:00:00 2001 From: Keerthi Niranjan Date: Fri, 29 Dec 2017 12:04:40 +0530 Subject: [PATCH 06/21] SEARCH-538 - Test for search limit --- demo/search.html | 2 +- tests/Search.test.js | 75 ++++++++++++++++++++++++++++++++++---------- 2 files changed, 60 insertions(+), 17 deletions(-) diff --git a/demo/search.html b/demo/search.html index ce8084a0..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" } diff --git a/tests/Search.test.js b/tests/Search.test.js index 88ce0c96..1d271947 100644 --- a/tests/Search.test.js +++ b/tests/Search.test.js @@ -39,7 +39,7 @@ describe('Tests for Search', function() { jasmine.DEFAULT_TIMEOUT_INTERVAL = 90000; beforeAll(function (done) { - childProcess.exec(`npm rebuild --target=${process.version} --build-from-source`, function(err) { + /*childProcess.exec(`npm rebuild --target=${process.version} --build-from-source`, function(err) { userId = 12345678910112; key = 'jjjehdnctsjyieoalskcjdhsnahsadndfnusdfsdfsd='; @@ -56,7 +56,22 @@ describe('Tests for Search', function() { dataFolderPath = path.join(searchConfig.FOLDERS_CONSTANTS.EXEC_PATH, '..', 'data'); done(); - }); + });*/ + 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) { @@ -128,16 +143,34 @@ describe('Tests for Search', function() { 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" - } ]; + 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); @@ -225,7 +258,7 @@ describe('Tests for Search', function() { 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(1); + expect(res.messages.length).toEqual(3); expect(searchQuery).toHaveBeenCalled(); done(); }); @@ -254,7 +287,7 @@ describe('Tests for Search', function() { 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(1); + expect(res.messages.length).toEqual(3); expect(fs.existsSync(realTimeIndexPath)).toBe(true); expect(searchQuery).toHaveBeenCalled(); done(); @@ -428,7 +461,7 @@ describe('Tests for Search', function() { 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(1); + expect(res.messages.length).toEqual(3); expect(searchQuery).toHaveBeenCalled(); done() }); @@ -449,12 +482,22 @@ describe('Tests for Search', function() { }); }); + 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(7); + expect(searchQuery).toHaveBeenCalledTimes(8); expect(searchQuery).toHaveBeenCalled(); SearchApi = undefined; const { Search } = require('../js/search/search.js'); From d1e760489529bcfaff75ec153d45ce2e00a516e4 Mon Sep 17 00:00:00 2001 From: Keerthi Niranjan Date: Fri, 29 Dec 2017 12:06:19 +0530 Subject: [PATCH 07/21] SEARCH-538 - Removed comment --- tests/Search.test.js | 19 ++----------------- 1 file changed, 2 insertions(+), 17 deletions(-) diff --git a/tests/Search.test.js b/tests/Search.test.js index 1d271947..637afd42 100644 --- a/tests/Search.test.js +++ b/tests/Search.test.js @@ -39,7 +39,7 @@ describe('Tests for Search', function() { jasmine.DEFAULT_TIMEOUT_INTERVAL = 90000; beforeAll(function (done) { - /*childProcess.exec(`npm rebuild --target=${process.version} --build-from-source`, function(err) { + childProcess.exec(`npm rebuild --target=${process.version} --build-from-source`, function(err) { userId = 12345678910112; key = 'jjjehdnctsjyieoalskcjdhsnahsadndfnusdfsdfsd='; @@ -56,22 +56,7 @@ describe('Tests for Search', function() { dataFolderPath = path.join(searchConfig.FOLDERS_CONSTANTS.EXEC_PATH, '..', 'data'); done(); - });*/ - 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) { From 988439b780a16a2bfebc41be6f4840af09a005b5 Mon Sep 17 00:00:00 2001 From: Keerthi Niranjan Date: Fri, 29 Dec 2017 17:36:40 +0530 Subject: [PATCH 08/21] SEARCH-538 - User config unit tests --- js/search/searchUtils.js | 19 +++-- js/search/utils/checkDiskSpace.js | 21 ++--- tests/SearchUtils.test.js | 129 ++++++++++++++++++++++++++++++ 3 files changed, 149 insertions(+), 20 deletions(-) create mode 100644 tests/SearchUtils.test.js 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/tests/SearchUtils.test.js b/tests/SearchUtils.test.js new file mode 100644 index 00000000..76172c7c --- /dev/null +++ b/tests/SearchUtils.test.js @@ -0,0 +1,129 @@ +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) { + if (type === 'exe') { + return executionPath; + } + + if (type === 'userData') { + return userConfigDir + } + 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; + done(); + }); + + afterAll(function (done) { + fs.unlinkSync(searchConfig.FOLDERS_CONSTANTS.USER_CONFIG_FILE); + done(); + }); + + describe('Tests for checking disk space', function () { + + it('should return free sapce', 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(); + }) + }); + }); + +}); \ No newline at end of file From 4322615e6b29e32dcf8dba975dca4071ced769ef Mon Sep 17 00:00:00 2001 From: Keerthi Niranjan Date: Tue, 2 Jan 2018 10:12:14 +0530 Subject: [PATCH 09/21] SEARCH-538 - Included two new tests --- tests/SearchUtils.test.js | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/tests/SearchUtils.test.js b/tests/SearchUtils.test.js index 76172c7c..d1b95d11 100644 --- a/tests/SearchUtils.test.js +++ b/tests/SearchUtils.test.js @@ -124,6 +124,26 @@ describe('Tests for Search Utils', function() { 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 From 0edc3d01e20bf66ecf80d3ad751b74f3c3c4b1d7 Mon Sep 17 00:00:00 2001 From: Vishwas Shashidhar Date: Tue, 2 Jan 2018 17:00:12 +0530 Subject: [PATCH 10/21] electron-258: fixes the pop out issue for meetings and supports undefined urls in case of new window events as per the html dom specs --- js/windowMgr.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/js/windowMgr.js b/js/windowMgr.js index ff1e144a..8f65c209 100644 --- a/js/windowMgr.js +++ b/js/windowMgr.js @@ -311,7 +311,7 @@ function doCreateMainWindow(initialUrl, initialBounds) { // 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) { - + let newWinParsedUrl = getParsedUrl(newWinUrl); let mainWinParsedUrl = getParsedUrl(url); @@ -320,7 +320,7 @@ function doCreateMainWindow(initialUrl, initialBounds) { // 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 === 'about:blank')) { // handle: window.open if (!frameName) { From f250185067fbca91d5d3702fa0382111231b9f1e Mon Sep 17 00:00:00 2001 From: Vishwas Shashidhar Date: Thu, 4 Jan 2018 23:00:08 +0530 Subject: [PATCH 11/21] electron-258: made changes as per the PR recommendation --- js/windowMgr.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/js/windowMgr.js b/js/windowMgr.js index 8f65c209..1bfb4431 100644 --- a/js/windowMgr.js +++ b/js/windowMgr.js @@ -318,9 +318,11 @@ function doCreateMainWindow(initialUrl, initialBounds) { 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) || newWinUrl === 'about:blank')) { + if (disposition === 'new-window' && ((newWinHost === mainWinHost) || newWinUrl === emptyUrlString)) { // handle: window.open if (!frameName) { From 252047891ed34f8aa85483a4f369ea0c094278a3 Mon Sep 17 00:00:00 2001 From: Keerthi Niranjan Date: Mon, 8 Jan 2018 16:57:18 +0530 Subject: [PATCH 12/21] SEARCH-538 - Review comments --- js/search/search.js | 2 +- tests/SearchUtils.test.js | 19 +++++++++++-------- 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/js/search/search.js b/js/search/search.js index 3f360a2b..45cefc3f 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; } diff --git a/tests/SearchUtils.test.js b/tests/SearchUtils.test.js index d1b95d11..fc3ccb0c 100644 --- a/tests/SearchUtils.test.js +++ b/tests/SearchUtils.test.js @@ -16,14 +16,14 @@ jest.mock('electron', function() { }); function mockedGetPath(type) { - if (type === 'exe') { - return executionPath; + switch (type) { + case 'exe': + return executionPath; + case 'userData': + return userConfigDir; + default: + return '' } - - if (type === 'userData') { - return userConfigDir - } - return ''; } describe('Tests for Search Utils', function() { @@ -37,6 +37,9 @@ describe('Tests for Search Utils', function() { 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(); }); @@ -47,7 +50,7 @@ describe('Tests for Search Utils', function() { describe('Tests for checking disk space', function () { - it('should return free sapce', function (done) { + it('should return free space', function (done) { const checkFreeSpace = jest.spyOn(SearchUtilsAPI, 'checkFreeSpace'); SearchUtilsAPI.checkFreeSpace().then(function () { expect(checkFreeSpace).toHaveBeenCalled(); From 63b2fe25bd8d5a855e5941443ba1defc83a45405 Mon Sep 17 00:00:00 2001 From: Keerthi Niranjan Date: Mon, 8 Jan 2018 17:38:58 +0530 Subject: [PATCH 13/21] SEARCH-538 - Review comments --- js/search/queue.js | 4 +++- js/search/search.js | 4 ---- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/js/search/queue.js b/js/search/queue.js index 7fb409f4..ab635167 100644 --- a/js/search/queue.js +++ b/js/search/queue.js @@ -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 45cefc3f..d394990b 100644 --- a/js/search/search.js +++ b/js/search/search.js @@ -169,10 +169,6 @@ class Search { * @param message */ realTimeIndexing(message) { - if (!message) { - log.send(logLevels.ERROR, 'RealTime Indexing: Messages not provided'); - throw new Error('RealTime Indexing: Messages is required'); - } try { let msg = JSON.parse(message); From 77ac2102d493eec1c287ff1e6e677f37227a0756 Mon Sep 17 00:00:00 2001 From: Keerthi Niranjan Date: Tue, 9 Jan 2018 13:37:03 +0530 Subject: [PATCH 14/21] SEARCH-563 - Deleting the tmp files --- js/cryptoLib/crypto.js | 7 ++++++- js/cryptoLib/index.js | 31 ++++++++++++++++++++++++++++--- 2 files changed, 34 insertions(+), 4 deletions(-) diff --git a/js/cryptoLib/crypto.js b/js/cryptoLib/crypto.js index ada68415..89b149b6 100644 --- a/js/cryptoLib/crypto.js +++ b/js/cryptoLib/crypto.js @@ -10,6 +10,9 @@ let Transform = stream.Transform; let util = require('util'); let crypto = require('crypto'); +const log = require('../log.js'); +const logLevels = require('../enums/logLevels.js'); + let KEY_LENGTH = 32; // bytes let GCM_NONCE_LENGTH = 12; //bytes let GCM_MAC_LENGTH = 16; //bytes @@ -151,7 +154,8 @@ DecryptionStream.prototype._transform = function(chunk, enc, cb) { DecryptionStream.prototype._flush = function(cb) { let mac = pullOutMac(this._cipherTextChunks); if (!mac) { - return this.emit('error', new Error('Decryption failed: bad cipher text.')); + log.send(logLevels.ERROR, 'Crypto: Decryption failed: bad cipher text.'); + return cb(); } this._decipher.setAuthTag(mac); let decrypted = this._cipherTextChunks.map(function(item) { @@ -160,6 +164,7 @@ DecryptionStream.prototype._flush = function(cb) { try { this._decipher.final(); } catch (e) { + log.send(logLevels.ERROR, 'Crypto: Decryption Failed: ' + e); return cb(); } decrypted.forEach(function(item) { diff --git a/js/cryptoLib/index.js b/js/cryptoLib/index.js index 6a393328..2c9cd442 100644 --- a/js/cryptoLib/index.js +++ b/js/cryptoLib/index.js @@ -56,17 +56,32 @@ class Crypto { let config = { key: key }; - const encrypt = crypto.encrypt(config); + let encrypt; + try { + encrypt = crypto.encrypt(config); + } catch (e) { + log.send(logLevels.ERROR, 'Error decrypting : ' + e); + if (fs.existsSync(`${this.dump}/${this.permanentIndexName}${searchConfig.TAR_LZ4_EXT}`)) { + fs.unlinkSync(`${this.dump}/${this.permanentIndexName}${searchConfig.TAR_LZ4_EXT}`); + } + reject(); + return; + } let encryptionProcess = input.pipe(encrypt).pipe(outputEncryption); encryptionProcess.on('finish', (err) => { if (err) { log.send(logLevels.ERROR, 'Crypto: Error while encrypting the compressed file: ' + err); + if (fs.existsSync(`${this.dump}/${this.permanentIndexName}${searchConfig.TAR_LZ4_EXT}`)) { + fs.unlinkSync(`${this.dump}/${this.permanentIndexName}${searchConfig.TAR_LZ4_EXT}`); + } reject(new Error(err)); return; } - fs.unlinkSync(`${this.dump}/${this.permanentIndexName}${searchConfig.TAR_LZ4_EXT}`); + if (fs.existsSync(`${this.dump}/${this.permanentIndexName}${searchConfig.TAR_LZ4_EXT}`)) { + fs.unlinkSync(`${this.dump}/${this.permanentIndexName}${searchConfig.TAR_LZ4_EXT}`); + } resolve('Success'); }); }); @@ -92,7 +107,17 @@ class Crypto { let config = { key: this.key }; - const decrypt = crypto.decrypt(config); + let decrypt; + try { + decrypt = crypto.decrypt(config); + } catch (e) { + log.send(logLevels.ERROR, 'Error decrypting : ' + e); + if (fs.existsSync(`${this.dump}/decrypted${searchConfig.TAR_LZ4_EXT}`)) { + fs.unlinkSync(`${this.dump}/decrypted${searchConfig.TAR_LZ4_EXT}`); + } + reject(); + return; + } let decryptionProcess = input.pipe(decrypt).pipe(output); From b32c7784eab7e908cfbe0519ff7cf62101a4172f Mon Sep 17 00:00:00 2001 From: Keerthi Niranjan Date: Tue, 9 Jan 2018 14:20:29 +0530 Subject: [PATCH 15/21] SEARCH-563 - Fixed unit tests --- js/search/search.js | 18 ++++++++++++++++++ tests/Search.test.js | 6 ++++-- 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/js/search/search.js b/js/search/search.js index d394990b..8df13a32 100644 --- a/js/search/search.js +++ b/js/search/search.js @@ -115,6 +115,12 @@ class Search { return; } + if (!fs.existsSync(this.dataFolder)) { + log.send(logLevels.ERROR, 'User index folder not found'); + reject(new Error('User index folder not found')); + return; + } + const indexId = randomString.generate(searchConfig.BATCH_RANDOM_INDEX_PATH_LENGTH); libSymphonySearch.symSECreatePartialIndexAsync(this.batchIndex, indexId, messages, (err, res) => { if (err) { @@ -133,6 +139,13 @@ class Search { */ mergeIndexBatches() { return new Promise((resolve, reject) => { + + if (!fs.existsSync(this.dataFolder)) { + log.send(logLevels.ERROR, 'User index folder not found'); + reject(new Error('User index folder not found')); + return; + } + libSymphonySearch.symSEMergePartialIndexAsync(this.indexFolderName, this.batchIndex, (err, res) => { if (err) { log.send(logLevels.ERROR, 'Error merging the index ->' + err); @@ -186,6 +199,11 @@ class Search { throw new Error('Library not initialized'); } + if (!fs.existsSync(this.dataFolder)) { + log.send(logLevels.ERROR, 'User index folder not found'); + throw new Error('User index folder not found'); + } + this.isRealTimeIndexing = true; return libSymphonySearch.symSEIndexRealTimeAsync(this.realTimeIndex, message, (err, result) => { this.isRealTimeIndexing = false; diff --git a/tests/Search.test.js b/tests/Search.test.js index 637afd42..9ebf7b17 100644 --- a/tests/Search.test.js +++ b/tests/Search.test.js @@ -54,7 +54,9 @@ describe('Tests for Search', function() { 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'); - + if (fs.existsSync(dataFolderPath)) { + fs.unlinkSync(dataFolderPath) + } done(); }); }); @@ -347,7 +349,7 @@ describe('Tests for Search', function() { expect(function () { SearchApi.realTimeIndexing() - }).toThrow(new Error('RealTime Indexing: Messages is required')); + }).toThrow(); SearchApi.isInitialized = false; expect(function () { From 761875559c512a74c315f7d3d9a63ff5fde6fb96 Mon Sep 17 00:00:00 2001 From: Keerthi Niranjan Date: Tue, 9 Jan 2018 14:25:30 +0530 Subject: [PATCH 16/21] SEARCH-563 - Typo --- js/cryptoLib/crypto.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/cryptoLib/crypto.js b/js/cryptoLib/crypto.js index 89b149b6..031f16b4 100644 --- a/js/cryptoLib/crypto.js +++ b/js/cryptoLib/crypto.js @@ -164,7 +164,7 @@ DecryptionStream.prototype._flush = function(cb) { try { this._decipher.final(); } catch (e) { - log.send(logLevels.ERROR, 'Crypto: Decryption Failed: ' + e); + log.send(logLevels.ERROR, 'Crypto: Decryption failed: ' + e); return cb(); } decrypted.forEach(function(item) { From 603d74c5b9c1ddd321b30ecd1ba1b4866bc98c21 Mon Sep 17 00:00:00 2001 From: Keerthi Niranjan Date: Tue, 9 Jan 2018 16:16:59 +0530 Subject: [PATCH 17/21] SEARCH-569 - Removing the version information from user index folder --- js/cryptoLib/index.js | 4 ++-- js/search/search.js | 2 +- js/search/searchConfig.js | 1 - tests/Search.test.js | 6 +++--- 4 files changed, 6 insertions(+), 7 deletions(-) diff --git a/js/cryptoLib/index.js b/js/cryptoLib/index.js index 6a393328..59e7f80e 100644 --- a/js/cryptoLib/index.js +++ b/js/cryptoLib/index.js @@ -18,8 +18,8 @@ class Crypto { * @param key */ constructor(userId, key) { - this.indexDataFolder = `${searchConfig.FOLDERS_CONSTANTS.PREFIX_NAME_PATH}_${userId}_${searchConfig.INDEX_VERSION}`; - this.permanentIndexName = `${searchConfig.FOLDERS_CONSTANTS.PREFIX_NAME}_${userId}_${searchConfig.INDEX_VERSION}`; + this.indexDataFolder = `${searchConfig.FOLDERS_CONSTANTS.PREFIX_NAME_PATH}_${userId}`; + this.permanentIndexName = `${searchConfig.FOLDERS_CONSTANTS.PREFIX_NAME}_${userId}`; this.dump = DUMP_PATH; this.key = key; this.encryptedIndex = `${DUMP_PATH}/${this.permanentIndexName}.enc`; diff --git a/js/search/search.js b/js/search/search.js index d394990b..49d05ff1 100644 --- a/js/search/search.js +++ b/js/search/search.js @@ -31,7 +31,7 @@ class Search { this.isInitialized = false; this.userId = userId; this.key = key; - this.indexFolderName = `${searchConfig.FOLDERS_CONSTANTS.PREFIX_NAME_PATH}_${this.userId}_${searchConfig.INDEX_VERSION}`; + this.indexFolderName = `${searchConfig.FOLDERS_CONSTANTS.PREFIX_NAME_PATH}_${this.userId}`; this.dataFolder = searchConfig.FOLDERS_CONSTANTS.INDEX_PATH; this.realTimeIndex = searchConfig.FOLDERS_CONSTANTS.TEMP_REAL_TIME_INDEX; this.batchIndex = searchConfig.FOLDERS_CONSTANTS.TEMP_BATCH_INDEX_FOLDER; diff --git a/js/search/searchConfig.js b/js/search/searchConfig.js index 9be1bf89..3f38ad64 100644 --- a/js/search/searchConfig.js +++ b/js/search/searchConfig.js @@ -51,7 +51,6 @@ const searchConfig = { REAL_TIME_INDEXING_TIME: 60000, MINIMUM_DATE: '0000000000000', MAXIMUM_DATE: '9999999999999', - INDEX_VERSION: 'v1', SORT_BY_SCORE: 0, BATCH_RANDOM_INDEX_PATH_LENGTH: 20, LIBRARY_CONSTANTS: libraryPaths, diff --git a/tests/Search.test.js b/tests/Search.test.js index 637afd42..9e8d7dd1 100644 --- a/tests/Search.test.js +++ b/tests/Search.test.js @@ -63,7 +63,7 @@ describe('Tests for Search', function() { setTimeout(function () { deleteIndexFolders(dataFolderPath); - let root = path.join(searchConfig.FOLDERS_CONSTANTS.EXEC_PATH, '..', `${searchConfig.FOLDERS_CONSTANTS.PREFIX_NAME}_${userId}_${searchConfig.INDEX_VERSION}.enc`); + let root = path.join(searchConfig.FOLDERS_CONSTANTS.EXEC_PATH, '..', `${searchConfig.FOLDERS_CONSTANTS.PREFIX_NAME}_${userId}.enc`); if (fs.existsSync(root)) { fs.unlinkSync(root); } @@ -92,7 +92,7 @@ describe('Tests for Search', function() { setTimeout(function () { expect(SearchApi.isInitialized).toBe(true); - expect(SearchApi.indexFolderName).toBe(`${searchConfig.FOLDERS_CONSTANTS.PREFIX_NAME_PATH}_${userId}_${searchConfig.INDEX_VERSION}`); + expect(SearchApi.indexFolderName).toBe(`${searchConfig.FOLDERS_CONSTANTS.PREFIX_NAME_PATH}_${userId}`); 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); @@ -423,7 +423,7 @@ describe('Tests for Search', function() { 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}`; + SearchApi.indexFolderName = `${dataFolderPath}/${searchConfig.FOLDERS_CONSTANTS.PREFIX_NAME}_${userId}`; expect(getLatestMessageTimestamp).toHaveBeenCalled(); expect(getLatestMessageTimestamp).toHaveBeenCalledTimes(3); done(); From 181fa7b76772de74cb0fce7cddeb84bc95b9b22c Mon Sep 17 00:00:00 2001 From: Keerthi Niranjan Date: Tue, 9 Jan 2018 19:59:00 +0530 Subject: [PATCH 18/21] SEARCH-569 - Review comments fix --- js/cryptoLib/index.js | 31 ++++++++++++++++--------------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/js/cryptoLib/index.js b/js/cryptoLib/index.js index 2c9cd442..b300c3cb 100644 --- a/js/cryptoLib/index.js +++ b/js/cryptoLib/index.js @@ -20,10 +20,11 @@ class Crypto { constructor(userId, key) { this.indexDataFolder = `${searchConfig.FOLDERS_CONSTANTS.PREFIX_NAME_PATH}_${userId}_${searchConfig.INDEX_VERSION}`; this.permanentIndexName = `${searchConfig.FOLDERS_CONSTANTS.PREFIX_NAME}_${userId}_${searchConfig.INDEX_VERSION}`; - this.dump = DUMP_PATH; this.key = key; this.encryptedIndex = `${DUMP_PATH}/${this.permanentIndexName}.enc`; this.dataFolder = searchConfig.FOLDERS_CONSTANTS.INDEX_PATH; + this.lz4Temp = `${DUMP_PATH}/${this.permanentIndexName}${searchConfig.TAR_LZ4_EXT}`; + this.decryptedTemp = `${DUMP_PATH}/decrypted${searchConfig.TAR_LZ4_EXT}`; } /** @@ -51,7 +52,7 @@ class Crypto { if (response && response.stderr) { log.send(logLevels.WARN, 'Crypto: Child process stderr while compression, ' + response.stderr); } - const input = fs.createReadStream(`${this.dump}/${this.permanentIndexName}${searchConfig.TAR_LZ4_EXT}`); + const input = fs.createReadStream(this.lz4Temp); const outputEncryption = fs.createWriteStream(this.encryptedIndex); let config = { key: key @@ -60,9 +61,9 @@ class Crypto { try { encrypt = crypto.encrypt(config); } catch (e) { - log.send(logLevels.ERROR, 'Error decrypting : ' + e); - if (fs.existsSync(`${this.dump}/${this.permanentIndexName}${searchConfig.TAR_LZ4_EXT}`)) { - fs.unlinkSync(`${this.dump}/${this.permanentIndexName}${searchConfig.TAR_LZ4_EXT}`); + log.send(logLevels.ERROR, 'Error encrypting : ' + e); + if (fs.existsSync(this.lz4Temp)) { + fs.unlinkSync(this.lz4Temp); } reject(); return; @@ -73,14 +74,14 @@ class Crypto { encryptionProcess.on('finish', (err) => { if (err) { log.send(logLevels.ERROR, 'Crypto: Error while encrypting the compressed file: ' + err); - if (fs.existsSync(`${this.dump}/${this.permanentIndexName}${searchConfig.TAR_LZ4_EXT}`)) { - fs.unlinkSync(`${this.dump}/${this.permanentIndexName}${searchConfig.TAR_LZ4_EXT}`); + if (fs.existsSync(this.lz4Temp)) { + fs.unlinkSync(this.lz4Temp); } reject(new Error(err)); return; } - if (fs.existsSync(`${this.dump}/${this.permanentIndexName}${searchConfig.TAR_LZ4_EXT}`)) { - fs.unlinkSync(`${this.dump}/${this.permanentIndexName}${searchConfig.TAR_LZ4_EXT}`); + if (fs.existsSync(this.lz4Temp)) { + fs.unlinkSync(this.lz4Temp); } resolve('Success'); }); @@ -103,7 +104,7 @@ class Crypto { } const input = fs.createReadStream(this.encryptedIndex); - const output = fs.createWriteStream(`${this.dump}/decrypted${searchConfig.TAR_LZ4_EXT}`); + const output = fs.createWriteStream(this.decryptedTemp); let config = { key: this.key }; @@ -112,8 +113,8 @@ class Crypto { decrypt = crypto.decrypt(config); } catch (e) { log.send(logLevels.ERROR, 'Error decrypting : ' + e); - if (fs.existsSync(`${this.dump}/decrypted${searchConfig.TAR_LZ4_EXT}`)) { - fs.unlinkSync(`${this.dump}/decrypted${searchConfig.TAR_LZ4_EXT}`); + if (fs.existsSync(this.decryptedTemp)) { + fs.unlinkSync(this.decryptedTemp); } reject(); return; @@ -123,13 +124,13 @@ class Crypto { decryptionProcess.on('finish', () => { - if (!fs.existsSync(`${this.dump}/decrypted${searchConfig.TAR_LZ4_EXT}`)){ + if (!fs.existsSync(this.decryptedTemp)){ log.send(logLevels.ERROR, 'decrypted.tar.lz4 file not found'); reject(); return; } - lz4.deCompression(`${this.dump}/decrypted${searchConfig.TAR_LZ4_EXT}`,(error, response) => { + lz4.deCompression(this.decryptedTemp,(error, response) => { if (error) { log.send(logLevels.ERROR, 'Crypto: Error while deCompression, ' + error); // no return, need to unlink if error @@ -138,7 +139,7 @@ class Crypto { if (response && response.stderr) { log.send(logLevels.WARN, 'Crypto: Child process stderr while deCompression, ' + response.stderr); } - fs.unlink(`${this.dump}/decrypted${searchConfig.TAR_LZ4_EXT}`, () => { + fs.unlink(this.decryptedTemp, () => { resolve('success'); }); }) From e9a89ff429fb95e7d35cdc546d99919a891711a9 Mon Sep 17 00:00:00 2001 From: Keerthi Niranjan Date: Wed, 10 Jan 2018 10:15:03 +0530 Subject: [PATCH 19/21] SEARCH-569 - Fixed tests --- tests/Search.test.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/Search.test.js b/tests/Search.test.js index 9e8d7dd1..4b907570 100644 --- a/tests/Search.test.js +++ b/tests/Search.test.js @@ -116,7 +116,7 @@ describe('Tests for Search', function() { }); it('should exist index folder', function() { - expect(fs.existsSync(path.join(userConfigDir, 'data', 'search_index_12345678910112_v1'))).toBe(true); + expect(fs.existsSync(path.join(userConfigDir, 'data', 'search_index_12345678910112'))).toBe(true); expect(fs.existsSync(realTimeIndexPath)).toBe(true); }); @@ -388,8 +388,8 @@ describe('Tests for Search', function() { 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); + expect(fs.existsSync(path.join(userConfigDir, 'search_index_12345678910112.enc'))).toBe(true); + expect(fs.existsSync(path.join(userConfigDir, 'search_index_12345678910112.tar.lz4'))).toBe(false); done(); }, 3000); From a3af9abdf9dfc89b801a36ea0d2fb9dc01328492 Mon Sep 17 00:00:00 2001 From: kiranniranjan Date: Wed, 10 Jan 2018 16:48:43 +0530 Subject: [PATCH 20/21] Electron-262 Implemented a method to reset badge count on window navigation/reload --- js/preload/preloadMain.js | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/js/preload/preloadMain.js b/js/preload/preloadMain.js index 165dd10b..35b5c2e8 100644 --- a/js/preload/preloadMain.js +++ b/js/preload/preloadMain.js @@ -367,8 +367,17 @@ function createAPI() { }); } + // reset the badge count when ever user refresh + function resetBadgeCount() { + local.ipcRenderer.send(apiName, { + cmd: apiCmds.setBadgeCount, + count: 0 + }); + } + window.addEventListener('offline', updateOnlineStatus, false); window.addEventListener('online', updateOnlineStatus, false); + window.addEventListener('beforeunload', resetBadgeCount, false); updateOnlineStatus(); } \ No newline at end of file From 26c1bc91dd02764d05b3c625c712075a13481f9d Mon Sep 17 00:00:00 2001 From: kiranniranjan Date: Wed, 10 Jan 2018 18:14:06 +0530 Subject: [PATCH 21/21] Electron-262 Updated the code comment --- js/preload/preloadMain.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/preload/preloadMain.js b/js/preload/preloadMain.js index 35b5c2e8..da43694d 100644 --- a/js/preload/preloadMain.js +++ b/js/preload/preloadMain.js @@ -367,7 +367,7 @@ function createAPI() { }); } - // reset the badge count when ever user refresh + // reset the badge count whenever an user refreshes the electron client function resetBadgeCount() { local.ipcRenderer.send(apiName, { cmd: apiCmds.setBadgeCount,