From 1ff4d2068b592a4fc1e0baab9ed0de4be53aeb6f Mon Sep 17 00:00:00 2001 From: NejcZdovc Date: Sun, 6 Aug 2017 21:03:40 +0200 Subject: [PATCH] Follow up for sites splits PR #10296 Resolves #10296 Resolves #12378 Auditors: Test Plan: --- app/common/lib/historyUtil.js | 44 +- app/common/state/bookmarkFoldersState.js | 65 +- app/common/state/bookmarksState.js | 55 +- test/unit/app/common/lib/historyUtilTest.js | 172 ++- .../app/common/state/aboutHistoryStateTest.js | 39 +- .../app/common/state/aboutNewTabStateTest.js | 34 +- .../common/state/bookmarkFoldersStateTest.js | 766 +++++++++++++ .../app/common/state/bookmarksStateTest.js | 1004 +++++++++++++++-- 8 files changed, 2040 insertions(+), 139 deletions(-) create mode 100644 test/unit/app/common/state/bookmarkFoldersStateTest.js diff --git a/app/common/lib/historyUtil.js b/app/common/lib/historyUtil.js index 2145c5c61fe..5082b2f72d6 100644 --- a/app/common/lib/historyUtil.js +++ b/app/common/lib/historyUtil.js @@ -15,13 +15,21 @@ const sortTimeDescending = (left, right) => { } const getHistory = (sites) => { - sites = makeImmutable(sites) ? makeImmutable(sites).toList() : new Immutable.List() + if (sites == null) { + return Immutable.List() + } + + sites = makeImmutable(sites) ? makeImmutable(sites).toList() : Immutable.List() return sites .sort(sortTimeDescending) .slice(0, aboutHistoryMaxEntries) } const getDayString = (entry, locale) => { + if (entry == null) { + return '' + } + const lastAccessedTime = entry.get('lastAccessedTime') return lastAccessedTime ? new Date(lastAccessedTime).toLocaleDateString(locale, { weekday: 'long', month: 'long', day: 'numeric', year: 'numeric' }) @@ -29,6 +37,10 @@ const getDayString = (entry, locale) => { } const groupEntriesByDay = (history, locale) => { + if (history == null) { + return Immutable.List() + } + const reduced = history.reduce((previousValue, currentValue, currentIndex) => { const result = currentIndex === 1 ? [] : previousValue if (currentIndex === 1) { @@ -44,6 +56,7 @@ const groupEntriesByDay = (history, locale) => { } return result }) + if (reduced) { return Immutable.fromJS( Array.isArray(reduced) @@ -51,7 +64,7 @@ const groupEntriesByDay = (history, locale) => { : [{date: getDayString(reduced, locale), entries: [reduced]}] ) } - return Immutable.fromJS([]) + return Immutable.List() } /** @@ -59,16 +72,22 @@ const groupEntriesByDay = (history, locale) => { * Format is expected to be array containing one array per day. */ const totalEntries = (entriesByDay) => { - entriesByDay = makeImmutable(entriesByDay) || new Immutable.List() + if (entriesByDay == null) { + return Immutable.List() + } + + entriesByDay = makeImmutable(entriesByDay) - let result = new Immutable.List() - entriesByDay.forEach((entry) => { - result = result.push(entry.get('entries')) + return entriesByDay.map((entry) => { + return entry.get('entries') }) - return result } const prepareHistoryEntry = (siteDetail) => { + if (siteDetail == null) { + return Immutable.Map() + } + const time = siteDetail.has('lastAccessedTime') ? siteDetail.get('lastAccessedTime') : new Date().getTime() @@ -82,7 +101,7 @@ const prepareHistoryEntry = (siteDetail) => { count: 1, themeColor: siteDetail.get('themeColor'), favicon: siteDetail.get('favicon', siteDetail.get('icon')), - key: getKey(siteDetail), + key: module.exports.getKey(siteDetail), skipSync: siteDetail.get('skipSync', null) }) } @@ -115,16 +134,20 @@ const mergeSiteDetails = (oldDetail, newDetail) => { site = site.set('favicon', favicon) } - site = site.set('key', getKey(site)) + site = site.set('key', module.exports.getKey(site)) return site } const getDetailFromFrame = (frame) => { + if (frame == null) { + return Immutable.Map() + } + return makeImmutable({ location: frame.get('location'), title: frame.get('title'), - partitionNumber: frame.get('partitionNumber'), + partitionNumber: frame.get('partitionNumber') || 0, favicon: frame.get('icon'), themeColor: frame.get('themeColor') || frame.get('computedThemeColor') }) @@ -142,6 +165,7 @@ const getKey = (siteDetail) => { return location + '|' + (siteDetail.get('partitionNumber') || 0) } + return null } diff --git a/app/common/state/bookmarkFoldersState.js b/app/common/state/bookmarkFoldersState.js index f3a44bff39d..52488c4222f 100644 --- a/app/common/state/bookmarkFoldersState.js +++ b/app/common/state/bookmarkFoldersState.js @@ -36,6 +36,11 @@ const bookmarkFoldersState = { getFolder: (state, folderKey) => { state = validateState(state) + + if (folderKey == null) { + return Immutable.Map() + } + folderKey = folderKey.toString() return state.getIn([STATE_SITES.BOOKMARK_FOLDERS, folderKey], Immutable.Map()) }, @@ -43,6 +48,10 @@ const bookmarkFoldersState = { getFoldersByParentId: (state, parentFolderId) => { state = validateState(state) + if (parentFolderId == null) { + return Immutable.List() + } + const folders = bookmarkOrderCache.getFoldersByParentId(state, parentFolderId) return folders.map(folder => bookmarkFoldersState.getFolder(state, folder.get('key'))) }, @@ -50,6 +59,16 @@ const bookmarkFoldersState = { addFolder: (state, folderDetails, destinationKey) => { state = validateState(state) + if (folderDetails == null) { + return state + } + + folderDetails = makeImmutable(folderDetails) + + if (folderDetails.get('key') == null) { + return state + } + state = state.setIn([STATE_SITES.BOOKMARK_FOLDERS, folderDetails.get('key')], folderDetails) state = bookmarkOrderCache.addFolderToCache(state, folderDetails.get('parentFolderId'), folderDetails.get('key'), destinationKey) return state @@ -78,24 +97,23 @@ const bookmarkFoldersState = { }, removeFolder: (state, folderKey) => { - const bookmarksState = require('./bookmarksState') - const folders = bookmarkFoldersState.getFolders(state) + state = validateState(state) const folder = bookmarkFoldersState.getFolder(state, folderKey) if (folder.isEmpty()) { return state } + const bookmarksState = require('./bookmarksState') + const folders = bookmarkFoldersState.getFolders(state) + if (getSetting(settings.SYNC_ENABLED) === true) { syncActions.removeSites([folder.toJS()]) } folders.filter(folder => folder.get('parentFolderId') === Number(folderKey)) .map(folder => { - state = bookmarksState.removeBookmarksByParentId(state, folder.get('folderId')) state = bookmarkFoldersState.removeFolder(state, folder.get('folderId')) - state = bookmarkOrderCache.removeCacheParent(state, folder.get('folderId')) - state = bookmarkOrderCache.removeCacheKey(state, folder.get('parentFolderId'), folderKey) }) state = bookmarksState.removeBookmarksByParentId(state, folderKey) @@ -105,14 +123,15 @@ const bookmarkFoldersState = { }, /** - * Get all folders except provided folder + * Get a list of all folders except provided folder * @param state - * @param folderKey + * @param {number} folderKey * @param parentFolderId * @param labelPrefix - * @returns {Array} + * @returns {Array} - each entry with folder id and label (title) */ getFoldersWithoutKey: (state, folderKey, parentFolderId = 0, labelPrefix = '') => { + state = validateState(state) let folders = [] const results = bookmarkFoldersState.getFoldersByParentId(state, parentFolderId) @@ -128,27 +147,36 @@ const bookmarkFoldersState = { folderId: folder.get('folderId'), label }) - const subSites = bookmarkFoldersState.getFoldersWithoutKey(state, folderKey, folder.get('folderId'), (label || '') + ' / ') - folders = folders.concat(subSites) + const subFolders = bookmarkFoldersState.getFoldersWithoutKey(state, folderKey, folder.get('folderId'), (label || '') + ' / ') + folders = folders.concat(subFolders) } return folders }, moveFolder: (state, folderKey, destinationKey, append, moveIntoParent) => { - const bookmarksState = require('./bookmarksState') + state = validateState(state) let folder = bookmarkFoldersState.getFolder(state, folderKey) - let destinationItem = bookmarksState.findBookmark(state, destinationKey) - if (folder.isEmpty()) { return state } + const bookmarksState = require('./bookmarksState') + let destinationItem = bookmarksState.findBookmark(state, destinationKey) + const numKey = Number(destinationKey) + if (destinationItem.isEmpty() && numKey !== -1 && numKey !== 0) { + return state + } + if (moveIntoParent || destinationItem.get('parentFolderId') !== folder.get('parentFolderId')) { - const parentFolderId = destinationItem.get('type') === siteTags.BOOKMARK + let parentFolderId = destinationItem.get('type') === siteTags.BOOKMARK ? destinationItem.get('parentFolderId') : destinationItem.get('folderId') + if (parentFolderId == null) { + parentFolderId = destinationKey + } + state = bookmarkOrderCache.removeCacheKey(state, folder.get('parentFolderId'), folderKey) folder = folder.set('parentFolderId', Number(parentFolderId)) const newKey = bookmarkFoldersUtil.getKey(folder) @@ -169,7 +197,14 @@ const bookmarkFoldersState = { }, setWidth: (state, key, width) => { - return state.setIn([STATE_SITES.BOOKMARK_FOLDERS, key, 'width'], parseFloat(width)) + state = validateState(state) + width = parseFloat(width) + + if (key == null || isNaN(width)) { + return state + } + + return state.setIn([STATE_SITES.BOOKMARK_FOLDERS, key, 'width'], width) } } diff --git a/app/common/state/bookmarksState.js b/app/common/state/bookmarksState.js index 8e3ea1dfb8a..878e30e7144 100644 --- a/app/common/state/bookmarksState.js +++ b/app/common/state/bookmarksState.js @@ -33,11 +33,16 @@ const validateState = function (state) { const bookmarksState = { getBookmarks: (state) => { state = validateState(state) - return state.get(STATE_SITES.BOOKMARKS) + return state.get(STATE_SITES.BOOKMARKS) || Immutable.Map() }, getBookmark: (state, key) => { state = validateState(state) + + if (key == null) { + return Immutable.Map() + } + return state.getIn([STATE_SITES.BOOKMARKS, key], Immutable.Map()) }, @@ -48,6 +53,11 @@ const bookmarksState = { */ findBookmark: (state, key) => { state = validateState(state) + + if (key == null) { + return Immutable.Map() + } + let bookmark = bookmarksState.getBookmark(state, key) if (bookmark.isEmpty()) { bookmark = bookmarkFoldersState.getFolder(state, key) @@ -75,8 +85,15 @@ const bookmarksState = { addBookmark: (state, bookmarkDetail, destinationKey, isLeftSide) => { state = validateState(state) + + if (bookmarkDetail == null) { + return state + } + + bookmarkDetail = makeImmutable(bookmarkDetail) + const key = bookmarkDetail.get('key') - if (key === null) { + if (key == null) { return state } @@ -92,6 +109,13 @@ const bookmarksState = { editBookmark: (state, oldBookmark, bookmarkDetail) => { state = validateState(state) + if (oldBookmark == null || bookmarkDetail == null) { + return state + } + + bookmarkDetail = makeImmutable(bookmarkDetail) + oldBookmark = makeImmutable(oldBookmark) + const newKey = bookmarkDetail.get('key') const editKey = oldBookmark.get('key') @@ -111,6 +135,10 @@ const bookmarksState = { removeBookmark: (state, bookmarkKey) => { state = validateState(state) + if (bookmarkKey == null) { + return state + } + const bookmark = bookmarksState.getBookmark(state, bookmarkKey) if (bookmark.isEmpty()) { @@ -140,24 +168,29 @@ const bookmarksState = { return state } + parentFolderId = Number(parentFolderId) + const syncEnabled = getSetting(settings.SYNC_ENABLED) === true const removedBookmarks = [] const bookmarks = bookmarksState.getBookmarks(state) .filter(bookmark => { - if (bookmark.get('parentFolderId') !== Number(parentFolderId)) { + if (bookmark.get('parentFolderId') !== parentFolderId) { return true } + if (syncEnabled) { removedBookmarks.push(bookmark.toJS()) } state = bookmarkLocationCache.removeCacheKey(state, bookmark.get('location'), bookmark.get('key')) + state = bookmarkOrderCache.removeCacheKey(state, bookmark.get('parentFolderId'), bookmark.get('key')) return false }) if (syncEnabled && removedBookmarks.length) { syncActions.removeSites(removedBookmarks) } + return state.set(STATE_SITES.BOOKMARKS, bookmarks) }, @@ -195,12 +228,16 @@ const bookmarksState = { const bookmarkUtil = require('../lib/bookmarkUtil') let bookmark = bookmarksState.getBookmark(state, bookmarkKey) - let destinationItem = bookmarksState.findBookmark(state, destinationKey) - if (bookmark.isEmpty()) { return state } + let destinationItem = bookmarksState.findBookmark(state, destinationKey) + const numKey = Number(destinationKey) + if (destinationItem.isEmpty() && numKey !== -1 && numKey !== 0) { + return state + } + // move bookmark into a new folder if (moveIntoParent || destinationItem.get('parentFolderId') !== bookmark.get('parentFolderId')) { let parentFolderId = destinationItem.get('type') === siteTags.BOOKMARK @@ -251,7 +288,13 @@ const bookmarksState = { }, setWidth: (state, key, width) => { - return state.setIn([STATE_SITES.BOOKMARKS, key, 'width'], parseFloat(width)) + width = parseFloat(width) + + if (key == null || isNaN(width)) { + return state + } + + return state.setIn([STATE_SITES.BOOKMARKS, key, 'width'], width) } } diff --git a/test/unit/app/common/lib/historyUtilTest.js b/test/unit/app/common/lib/historyUtilTest.js index 726f2cc5db6..fce727c1a3f 100644 --- a/test/unit/app/common/lib/historyUtilTest.js +++ b/test/unit/app/common/lib/historyUtilTest.js @@ -1,11 +1,12 @@ -/* global describe, it */ +/* global describe, it, after, afterEach, before */ +const sinon = require('sinon') const assert = require('assert') const Immutable = require('immutable') const historyUtil = require('../../../../../app/common/lib/historyUtil') require('../../../braveUnit') -describe('historyUtil', function () { +describe('historyUtil unit tests', function () { const historyDayOne = Immutable.fromJS({ lastAccessedTime: 1477944718876, location: 'https://brave.com/page1', @@ -32,10 +33,16 @@ describe('historyUtil', function () { const historyMultipleDays = historyDayThree.push(historyDayTwo, historyDayOne) describe('getHistory', function () { + it('null case', function () { + const result = historyUtil.getHistory() + assert.deepEqual(result.toJS(), []) + }) + it('returns the result as an Immutable.List', function () { const result = historyUtil.getHistory(historyMultipleDays) assert.equal(Immutable.List.isList(result), true) }) + it('sorts the items by date/time DESC', function () { const result = historyUtil.getHistory(historyMultipleDays) const expectedResult = historyDayThree.toJS().reverse() @@ -43,6 +50,7 @@ describe('historyUtil', function () { expectedResult.push(historyDayOne.toJS()) assert.deepEqual(result.toJS(), expectedResult) }) + it('only returns `historyUtil.maxEntries` results', function () { let tooManyEntries = new Immutable.List().push(historyDayOne) for (let i = 0; i < historyUtil.maxEntries; i++) { @@ -55,23 +63,32 @@ describe('historyUtil', function () { }) describe('groupEntriesByDay', function () { + it('null case', function () { + const result = historyUtil.groupEntriesByDay() + assert.deepEqual(result.toJS(), []) + }) + it('returns the result as an Immutable.List', function () { const result = historyUtil.groupEntriesByDay(historyDayThree) assert.equal(Immutable.List.isList(result), true) }) + it('has one object for each day', function () { const result = historyUtil.groupEntriesByDay(historyDayThree) assert.equal(result.size, 1) }) + it('can handle multiple days', function () { const result = historyUtil.groupEntriesByDay(historyMultipleDays) assert.equal(result.size, 3) }) + describe('with the object representing a day', function () { it('formats a readable `date` field', function () { const result = historyUtil.groupEntriesByDay(historyDayThree, 'en-US') assert.equal(result.getIn([0, 'date']), 'Thursday, November 3, 2016') }) + it('has an entry for each history item', function () { const result = historyUtil.groupEntriesByDay(historyDayThree, 'en-US') const entries = result.getIn([0, 'entries']) @@ -81,11 +98,17 @@ describe('historyUtil', function () { }) describe('totalEntries', function () { + it('null case', function () { + const result = historyUtil.totalEntries() + assert.deepEqual(result.toJS(), []) + }) + it('returns the result as an Immutable.List', function () { const result1 = historyUtil.groupEntriesByDay(historyMultipleDays) const result2 = historyUtil.totalEntries(result1) assert.equal(Immutable.List.isList(result2), true) }) + it('combines entries for multiple days into one response', function () { const result1 = historyUtil.groupEntriesByDay(historyMultipleDays) const result2 = historyUtil.totalEntries(result1) @@ -97,4 +120,149 @@ describe('historyUtil', function () { assert.deepEqual(result2.toJS(), expectedResult) }) }) + + describe('prepareHistoryEntry', function () { + let getKeySpy + let siteDetailsSlim = Immutable.fromJS({ + title: 'ok', + location: 'https://brave.com' + }) + const siteDetails = Immutable.fromJS({ + title: 'ok', + location: 'https://brave.com', + lastAccessedTime: 1234, + objectId: null, + partitionNumber: 1, + count: 1, + themeColor: '#FFF', + favicon: undefined, + key: 'https://brave.com|1', + skipSync: null + }) + before(function () { + getKeySpy = sinon.spy(historyUtil, 'getKey') + this.clock = sinon.useFakeTimers() + this.clock.tick(100) + }) + + afterEach(function () { + getKeySpy.reset() + }) + + after(function () { + getKeySpy.restore() + this.clock.restore() + }) + + it('null case', function () { + const result = historyUtil.prepareHistoryEntry() + assert.deepEqual(result, Immutable.Map()) + assert(getKeySpy.notCalled) + }) + + it('set current time when lastAccessedTime is missing', function () { + const result = historyUtil.prepareHistoryEntry(siteDetailsSlim) + const expectedResult = { + title: 'ok', + location: 'https://brave.com', + lastAccessedTime: 100, + objectId: null, + partitionNumber: 0, + count: 1, + themeColor: undefined, + favicon: undefined, + key: 'https://brave.com|0', + skipSync: null + } + assert.deepEqual(result.toJS(), expectedResult) + assert(getKeySpy.calledOnce) + }) + + it('generates history entry', function () { + const result = historyUtil.prepareHistoryEntry(siteDetails) + const expectedResult = { + title: 'ok', + location: 'https://brave.com', + lastAccessedTime: 1234, + objectId: null, + partitionNumber: 1, + count: 1, + themeColor: '#FFF', + favicon: undefined, + key: 'https://brave.com|1', + skipSync: null + } + assert.deepEqual(result.toJS(), expectedResult) + assert(getKeySpy.calledOnce) + }) + }) + + describe('mergeSiteDetails', function () { + + }) + + describe('getDetailFromFrame', function () { + it('null case', function () { + const result = historyUtil.getDetailFromFrame() + assert.deepEqual(result, Immutable.Map()) + }) + + it('returns details', function () { + const frame = Immutable.fromJS({ + guestInstanceId: '1', + hasBeenActivated: true, + hrefPreview: '', + isFullScreen: false, + isPrivate: false, + key: 1, + lastZoomPercentage: 1, + loading: true, + location: 'https://brave.com', + title: 'Brave' + }) + const expectedResult = { + location: 'https://brave.com', + title: 'Brave', + partitionNumber: 0, + favicon: undefined, + themeColor: undefined + } + const result = historyUtil.getDetailFromFrame(frame) + assert.deepEqual(result.toJS(), expectedResult) + }) + }) + + describe('getKey', function () { + it('null case', function () { + const result = historyUtil.getKey() + assert.equal(result, null) + }) + + it('location is missing', function () { + const detail = Immutable.fromJS({ + title: 'working' + }) + const result = historyUtil.getKey(detail) + assert.equal(result, null) + }) + + it('key is generated, with the default partition', function () { + const detail = Immutable.fromJS({ + title: 'working', + location: 'https://brave.com' + }) + const result = historyUtil.getKey(detail) + assert.equal(result, 'https://brave.com|0') + }) + + it('key is generated', function () { + const detail = Immutable.fromJS({ + title: 'working', + location: 'https://brave.com', + partitionNumber: 1 + }) + const result = historyUtil.getKey(detail) + assert.equal(result, 'https://brave.com|1') + }) + }) }) diff --git a/test/unit/app/common/state/aboutHistoryStateTest.js b/test/unit/app/common/state/aboutHistoryStateTest.js index ac40ae6c82f..f3cea453609 100644 --- a/test/unit/app/common/state/aboutHistoryStateTest.js +++ b/test/unit/app/common/state/aboutHistoryStateTest.js @@ -1,29 +1,39 @@ -/* global describe, it */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* global describe, it, before, after */ const aboutHistoryState = require('../../../../../app/common/state/aboutHistoryState') const Immutable = require('immutable') const assert = require('assert') +const sinon = require('sinon') const defaultAppState = Immutable.fromJS({ about: { history: { - entries: [], - updatedStamp: undefined + entries: {}, + updatedStamp: 0 } } }) const arbitraryTimeInThePast = 1450000000000 +const historyItems = Immutable.fromJS({ + 'https://brave.com/|0': { + location: 'https://brave.com' + } +}) + const assertTimeUpdated = (state) => { const updatedStamp = state.getIn(['about', 'history', 'updatedStamp']) assert.equal(typeof updatedStamp === 'number' && updatedStamp > arbitraryTimeInThePast, true) } -describe('aboutHistoryState', function () { +describe('aboutHistoryState unit test', function () { describe('getHistory', function () { it('reads the history from the state', function () { - const fakeHistoryEntries = [1, 2, 3] - const state = defaultAppState.setIn(['about', 'history', 'entries'], fakeHistoryEntries) + const state = defaultAppState.setIn(['about', 'history', 'entries'], historyItems) const history = aboutHistoryState.getHistory(state) assert.deepEqual(state.getIn(['about', 'history']).toJS(), history.toJS()) }) @@ -35,4 +45,21 @@ describe('aboutHistoryState', function () { assertTimeUpdated(state) }) }) + + describe('clearHistory', function () { + before(function () { + this.clock = sinon.useFakeTimers() + this.clock.tick(0) + }) + + after(function () { + this.clock.restore() + }) + + it('history is cleared', function () { + const state = defaultAppState.setIn(['about', 'history', 'entries'], historyItems) + const history = aboutHistoryState.clearHistory(state) + assert.deepEqual(history.toJS(), defaultAppState.toJS()) + }) + }) }) diff --git a/test/unit/app/common/state/aboutNewTabStateTest.js b/test/unit/app/common/state/aboutNewTabStateTest.js index 83a23f46ede..b41f854d6bc 100644 --- a/test/unit/app/common/state/aboutNewTabStateTest.js +++ b/test/unit/app/common/state/aboutNewTabStateTest.js @@ -1,7 +1,12 @@ -/* global describe, it */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* global describe, it, before, after */ const aboutNewTabState = require('../../../../../app/common/state/aboutNewTabState') const Immutable = require('immutable') const assert = require('assert') +const sinon = require('sinon') const defaultAppState = Immutable.fromJS({ about: { @@ -10,7 +15,7 @@ const defaultAppState = Immutable.fromJS({ sites: [], ignoredTopSites: [], pinnedTopSites: [], - updatedStamp: undefined + updatedStamp: 0 } } }) @@ -26,10 +31,10 @@ const assertTimeUpdated = (state) => { const assertNoChange = (state) => { const updatedStamp = state.getIn(['about', 'newtab', 'updatedStamp']) assert.deepEqual(state, defaultAppState) - assert.equal(updatedStamp, undefined) + assert.equal(updatedStamp, 0) } -describe('aboutNewTabState', function () { +describe('aboutNewTabState unit test', function () { describe('getSites', function () { it('returns the contents of about.newtab.sites', function () { const expectedSites = Immutable.List().push(1).push(2).push(3) @@ -87,4 +92,25 @@ describe('aboutNewTabState', function () { assert.equal(updatedValue, 'TEST STRING') }) }) + + describe('clearTopSites', function () { + before(function () { + this.clock = sinon.useFakeTimers() + this.clock.tick(0) + }) + + after(function () { + this.clock.restore() + }) + + it('is cleared', function () { + const state = defaultAppState.setIn(['about', 'newtab', 'sites'], Immutable.fromJS([ + { + location: 'https://brave.com' + } + ])) + const topSItes = aboutNewTabState.clearTopSites(state) + assert.deepEqual(topSItes.toJS(), defaultAppState.toJS()) + }) + }) }) diff --git a/test/unit/app/common/state/bookmarkFoldersStateTest.js b/test/unit/app/common/state/bookmarkFoldersStateTest.js new file mode 100644 index 00000000000..914c8753fa6 --- /dev/null +++ b/test/unit/app/common/state/bookmarkFoldersStateTest.js @@ -0,0 +1,766 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* global describe, it, before, after, afterEach */ +const mockery = require('mockery') +const Immutable = require('immutable') +const assert = require('assert') +const sinon = require('sinon') + +const settings = require('../../../../../js/constants/settings') +const siteTags = require('../../../../../js/constants/siteTags') +const {STATE_SITES} = require('../../../../../js/constants/stateConstants') +require('../../../braveUnit') + +describe('bookmarkFoldersState unit test', function () { + let bookmarkFoldersState, bookmarkOrderCache, bookmarksState, syncActions + + // Settings + let settingSyncEnabled = false + + const state = Immutable.fromJS({ + bookmarks: {}, + bookmarkFolders: {}, + cache: { + bookmarkOrder: {} + } + }) + + const stateWithData = Immutable.fromJS({ + bookmarks: {}, + bookmarkFolders: { + '1': { + title: 'folder1', + folderId: 1, + key: '1', + parentFolderId: 0, + partitionNumber: 0, + objectId: null, + type: siteTags.BOOKMARK_FOLDER + }, + '2': { + title: 'folder2', + folderId: 2, + key: '2', + parentFolderId: 1, + partitionNumber: 0, + objectId: null, + type: siteTags.BOOKMARK_FOLDER + }, + '69': { + title: 'folder69', + folderId: 69, + key: '69', + parentFolderId: 0, + partitionNumber: 0, + objectId: null, + type: siteTags.BOOKMARK_FOLDER + } + }, + cache: { + bookmarkOrder: { + '0': [ + { + key: '1', + order: 0, + type: siteTags.BOOKMARK_FOLDER + }, + { + key: '69', + order: 1, + type: siteTags.BOOKMARK_FOLDER + } + ], + '1': [ + { + key: '2', + order: 0, + type: siteTags.BOOKMARK_FOLDER + } + ] + } + } + }) + + before(function () { + mockery.enable({ + warnOnReplace: false, + warnOnUnregistered: false, + useCleanCache: true + }) + mockery.registerMock('../../../js/settings', { + getSetting: (settingKey) => { + switch (settingKey) { + case settings.SYNC_ENABLED: + return settingSyncEnabled + } + return false + } + }) + bookmarkOrderCache = require('../../../../../app/common/cache/bookmarkOrderCache') + bookmarksState = require('../../../../../app/common/state/bookmarksState') + syncActions = require('../../../../../js/actions/syncActions') + bookmarkFoldersState = require('../../../../../app/common/state/bookmarkFoldersState') + }) + + after(function () { + mockery.disable() + }) + + describe('getFolders', function () { + it('return folders', function () { + const newState = bookmarkFoldersState.getFolders(stateWithData) + assert.deepEqual(newState.toJS(), stateWithData.get(STATE_SITES.BOOKMARK_FOLDERS).toJS()) + }) + }) + + describe('getFolder', function () { + it('null case', function () { + const newState = bookmarkFoldersState.getFolder(stateWithData) + assert.deepEqual(newState, Immutable.Map()) + }) + + it('folder key is not found', function () { + const newState = bookmarkFoldersState.getFolder(stateWithData, '100') + assert.deepEqual(newState, Immutable.Map()) + }) + + it('folder key is found', function () { + const newState = bookmarkFoldersState.getFolder(stateWithData, '1') + assert.deepEqual(newState.toJS(), stateWithData.getIn([STATE_SITES.BOOKMARK_FOLDERS, '1']).toJS()) + }) + }) + + describe('getFoldersByParentId', function () { + it('null case', function () { + const newState = bookmarkFoldersState.getFoldersByParentId(stateWithData) + assert.deepEqual(newState, Immutable.List()) + }) + + it('parent folder is not found', function () { + const newState = bookmarkFoldersState.getFoldersByParentId(stateWithData, '1000') + assert.deepEqual(newState, Immutable.List()) + }) + + it('parent folder is found, but dont have any items', function () { + const newState = bookmarkFoldersState.getFoldersByParentId(stateWithData, '69') + assert.deepEqual(newState, Immutable.List()) + }) + + it('parent folder has child item', function () { + const newState = bookmarkFoldersState.getFoldersByParentId(stateWithData, '1') + assert.deepEqual(newState, Immutable.fromJS([ + { + title: 'folder2', + folderId: 2, + key: '2', + parentFolderId: 1, + partitionNumber: 0, + objectId: null, + type: siteTags.BOOKMARK_FOLDER + } + ])) + }) + }) + + describe('addFolder', function () { + let addFolderToCacheSpy + before(function () { + addFolderToCacheSpy = sinon.spy(bookmarkOrderCache, 'addFolderToCache') + }) + + afterEach(function () { + addFolderToCacheSpy.reset() + }) + + after(function () { + addFolderToCacheSpy.restore() + }) + + it('null case', function () { + const newState = bookmarkFoldersState.addFolder(state) + assert.deepEqual(newState.toJS(), state.toJS()) + assert(addFolderToCacheSpy.notCalled) + }) + + it('folder key is not provided', function () { + const newState = bookmarkFoldersState.addFolder(stateWithData, { + title: 'Brave' + }) + assert.deepEqual(newState.toJS(), stateWithData.toJS()) + assert(addFolderToCacheSpy.notCalled) + }) + + it('folder key is provided', function () { + const newState = bookmarkFoldersState.addFolder(state, { + title: 'Brave', + key: 10 + }) + const expectedState = state + .setIn(['bookmarkFolders', '10'], Immutable.fromJS({ + title: 'Brave', + key: '10' + })) + .setIn(['cache', 'bookmarkOrder', '0'], Immutable.fromJS([ + { + key: '10', + order: 0, + type: siteTags.BOOKMARK_FOLDER + } + ])) + assert.deepEqual(newState.toJS(), expectedState.toJS()) + assert(addFolderToCacheSpy.calledOnce) + }) + }) + + describe('editFolder', function () { + let addFolderToCacheSpy, removeCacheKeySpy + before(function () { + addFolderToCacheSpy = sinon.spy(bookmarkOrderCache, 'addFolderToCache') + removeCacheKeySpy = sinon.spy(bookmarkOrderCache, 'removeCacheKey') + }) + + afterEach(function () { + addFolderToCacheSpy.reset() + removeCacheKeySpy.reset() + }) + + after(function () { + addFolderToCacheSpy.restore() + removeCacheKeySpy.restore() + }) + + it('edit folder is missing', function () { + const result = bookmarkFoldersState.editFolder(state) + assert.deepEqual(result.toJS(), result.toJS()) + assert(addFolderToCacheSpy.notCalled) + assert(removeCacheKeySpy.notCalled) + }) + + it('old parent id is not the same as provided one', function () { + const result = bookmarkFoldersState.editFolder(stateWithData, '1', Immutable.fromJS({ + title: 'New folder name', + parentFolderId: 1 + })) + const expectedState = stateWithData + .setIn(['bookmarkFolders', '1', 'parentFolderId'], 1) + .setIn(['bookmarkFolders', '1', 'title'], 'New folder name') + .setIn(['cache', 'bookmarkOrder', '0'], Immutable.fromJS([ + { + key: '69', + order: 0, + type: siteTags.BOOKMARK_FOLDER + } + ])) + .setIn(['cache', 'bookmarkOrder', '1'], Immutable.fromJS([ + { + key: '2', + order: 0, + type: siteTags.BOOKMARK_FOLDER + }, + { + key: '1', + order: 1, + type: siteTags.BOOKMARK_FOLDER + } + ])) + assert.deepEqual(result.toJS(), expectedState.toJS()) + assert(addFolderToCacheSpy.calledOnce) + assert(removeCacheKeySpy.calledOnce) + }) + + it('old parent id is the same as provided one', function () { + const result = bookmarkFoldersState.editFolder(stateWithData, '1', Immutable.fromJS({ + title: 'New folder name' + })) + const expectedState = stateWithData + .setIn(['bookmarkFolders', '1', 'title'], 'New folder name') + assert.deepEqual(result.toJS(), expectedState.toJS()) + assert(addFolderToCacheSpy.notCalled) + assert(removeCacheKeySpy.notCalled) + }) + }) + + describe('removeFolder', function () { + let removeBookmarksByParentIdSpy, removeCacheParentSpy, removeCacheKeySpy, removeFolderSpy, removeSitesSpy + before(function () { + removeCacheParentSpy = sinon.spy(bookmarkOrderCache, 'removeCacheParent') + removeCacheKeySpy = sinon.spy(bookmarkOrderCache, 'removeCacheKey') + removeBookmarksByParentIdSpy = sinon.spy(bookmarksState, 'removeBookmarksByParentId') + removeFolderSpy = sinon.spy(bookmarkFoldersState, 'removeFolder') + removeSitesSpy = sinon.spy(syncActions, 'removeSites') + }) + + afterEach(function () { + removeCacheParentSpy.reset() + removeCacheKeySpy.reset() + removeBookmarksByParentIdSpy.reset() + removeFolderSpy.reset() + removeSitesSpy.reset() + }) + + after(function () { + removeCacheParentSpy.restore() + removeCacheKeySpy.restore() + removeBookmarksByParentIdSpy.restore() + removeFolderSpy.restore() + removeSitesSpy.restore() + }) + + it('null case', function () { + const result = bookmarkFoldersState.removeFolder(state) + assert.deepEqual(result.toJS(), result.toJS()) + }) + + it('check if sync is called when sync is enabled', function () { + settingSyncEnabled = true + bookmarkFoldersState.removeFolder(stateWithData, '69') + assert(removeSitesSpy.calledOnce) + settingSyncEnabled = false + }) + + it('with no child folders', function () { + const result = bookmarkFoldersState.removeFolder(stateWithData, '69') + const expectedState = stateWithData + .deleteIn(['bookmarkFolders', '69']) + .setIn(['cache', 'bookmarkOrder', '0'], Immutable.fromJS([ + { + key: '1', + order: 0, + type: siteTags.BOOKMARK_FOLDER + } + ])) + assert.deepEqual(result.toJS(), expectedState.toJS()) + assert(removeCacheParentSpy.calledOnce) + assert(removeCacheKeySpy.calledOnce) + assert(removeBookmarksByParentIdSpy.calledOnce) + }) + + it('with one child folder', function () { + const result = bookmarkFoldersState.removeFolder(stateWithData, '1') + const expectedState = stateWithData + .deleteIn(['bookmarkFolders', '1']) + .deleteIn(['bookmarkFolders', '2']) + .deleteIn(['cache', 'bookmarkOrder', '1']) + .setIn(['cache', 'bookmarkOrder', '0'], Immutable.fromJS([ + { + key: '69', + order: 0, + type: siteTags.BOOKMARK_FOLDER + } + ])) + assert.deepEqual(result.toJS(), expectedState.toJS()) + assert(removeCacheParentSpy.calledTwice) + assert(removeCacheKeySpy.calledTwice) + assert(removeBookmarksByParentIdSpy.calledTwice) + // we call removeFolderSpy once on line 341 in this file and once in bookmarkFolderState + assert(removeFolderSpy.calledTwice) + }) + }) + + describe('getFoldersWithoutKey', function () { + let getFoldersWithoutKeySpy + before(function () { + getFoldersWithoutKeySpy = sinon.spy(bookmarkFoldersState, 'getFoldersWithoutKey') + }) + + afterEach(function () { + getFoldersWithoutKeySpy.reset() + }) + + after(function () { + getFoldersWithoutKeySpy.restore() + }) + + it('null case', function () { + const result = bookmarkFoldersState.getFoldersWithoutKey(state) + assert.deepEqual(result, []) + assert(getFoldersWithoutKeySpy.calledOnce) + }) + + it('default parentId', function () { + const result = bookmarkFoldersState.getFoldersWithoutKey(stateWithData, 1) + assert.deepEqual(result, [ + { + folderId: '69', + label: 'folder69' + } + ]) + assert.equal(getFoldersWithoutKeySpy.callCount, 2) + }) + + it('multi level folders', function () { + const result = bookmarkFoldersState.getFoldersWithoutKey(stateWithData, 69) + assert.deepEqual(result, [ + { + folderId: 1, + label: 'folder1' + }, + { + folderId: 2, + label: 'folder1 / folder2' + } + ]) + assert.equal(getFoldersWithoutKeySpy.callCount, 3) + }) + + it('custom label', function () { + const result = bookmarkFoldersState.getFoldersWithoutKey(stateWithData, '2', 1, 'hi - ') + assert.deepEqual(result, [{ + folderId: 2, + label: 'hi - folder2' + }]) + assert(getFoldersWithoutKeySpy.calledTwice) + }) + }) + + describe('moveFolder', function () { + let addFolderToCacheSpy, removeCacheKeySpy, findBookmarkSpy + + const moveState = stateWithData + .setIn(['bookmarkFolders', '70'], Immutable.fromJS({ + title: 'folder70', + folderId: 70, + key: '70', + parentFolderId: 0, + partitionNumber: 0, + objectId: null, + type: siteTags.BOOKMARK_FOLDER + })) + .set('bookmarks', Immutable.fromJS({ + 'https://brave.com/|0|1': { + favicon: undefined, + title: 'Brave', + location: 'https://brave.com/', + key: 'https://brave.com/|0|1', + parentFolderId: 1, + partitionNumber: 0, + objectId: null, + themeColor: undefined, + type: siteTags.BOOKMARK + } + })) + .setIn(['cache', 'bookmarkOrder', '0'], Immutable.fromJS([ + { + key: '1', + order: 0, + type: siteTags.BOOKMARK_FOLDER + }, + { + key: '69', + order: 1, + type: siteTags.BOOKMARK_FOLDER + }, + { + key: '70', + order: 2, + type: siteTags.BOOKMARK_FOLDER + } + ])) + .setIn(['cache', 'bookmarkOrder', '1'], Immutable.fromJS([ + { + key: '2', + order: 0, + type: siteTags.BOOKMARK_FOLDER + }, + { + key: 'https://brave.com/|0|0', + order: 1, + type: siteTags.BOOKMARK + } + ])) + .setIn(['cache', 'bookmarkLocation'], Immutable.fromJS({ + 'https://brave.com/': [ + 'https://brave.com/|0|1' + ] + })) + + before(function () { + removeCacheKeySpy = sinon.spy(bookmarkOrderCache, 'removeCacheKey') + addFolderToCacheSpy = sinon.spy(bookmarkOrderCache, 'addFolderToCache') + findBookmarkSpy = sinon.spy(bookmarksState, 'findBookmark') + }) + + afterEach(function () { + removeCacheKeySpy.reset() + addFolderToCacheSpy.reset() + findBookmarkSpy.reset() + }) + + after(function () { + removeCacheKeySpy.restore() + addFolderToCacheSpy.restore() + findBookmarkSpy.restore() + }) + + it('null case', function () { + const result = bookmarkFoldersState.moveFolder(state) + assert.deepEqual(result.toJS(), state.toJS()) + }) + + it('destination is not found', function () { + const result = bookmarkFoldersState.moveFolder(moveState, '69') + assert.deepEqual(result.toJS(), moveState.toJS()) + }) + + it('destination is bookmark toolbar (destination key is 0)', function () { + const result = bookmarkFoldersState.moveFolder(moveState, '2', 0) + const expectedState = moveState + .setIn(['bookmarkFolders', '2', 'parentFolderId'], 0) + .setIn(['cache', 'bookmarkOrder', '0'], Immutable.fromJS([ + { + key: '1', + order: 0, + type: siteTags.BOOKMARK_FOLDER + }, + { + key: '69', + order: 1, + type: siteTags.BOOKMARK_FOLDER + }, + { + key: '70', + order: 2, + type: siteTags.BOOKMARK_FOLDER + }, + { + key: '2', + order: 3, + type: siteTags.BOOKMARK_FOLDER + } + ])) + .setIn(['cache', 'bookmarkOrder', '1'], Immutable.fromJS([ + { + key: 'https://brave.com/|0|0', + order: 0, + type: siteTags.BOOKMARK + } + ])) + + assert.deepEqual(result.toJS(), expectedState.toJS()) + assert(removeCacheKeySpy.calledOnce) + assert(addFolderToCacheSpy.calledOnce) + assert(findBookmarkSpy.calledOnce) + }) + + it('destination is other bookmarks (destination key is -1)', function () { + const result = bookmarkFoldersState.moveFolder(moveState, '2', '-1') + const expectedState = moveState + .setIn(['bookmarkFolders', '2', 'parentFolderId'], -1) + .setIn(['cache', 'bookmarkOrder', '0'], Immutable.fromJS([ + { + key: '1', + order: 0, + type: siteTags.BOOKMARK_FOLDER + }, + { + key: '69', + order: 1, + type: siteTags.BOOKMARK_FOLDER + }, + { + key: '70', + order: 2, + type: siteTags.BOOKMARK_FOLDER + } + ])) + .setIn(['cache', 'bookmarkOrder', '1'], Immutable.fromJS([ + { + key: 'https://brave.com/|0|0', + order: 0, + type: siteTags.BOOKMARK + } + ])) + .setIn(['cache', 'bookmarkOrder', '-1'], Immutable.fromJS([ + { + key: '2', + order: 0, + type: siteTags.BOOKMARK_FOLDER + } + ])) + + assert.deepEqual(result.toJS(), expectedState.toJS()) + assert(removeCacheKeySpy.calledOnce) + assert(addFolderToCacheSpy.calledOnce) + assert(findBookmarkSpy.calledOnce) + }) + + it('folder is moved (destination is bookmark)', function () { + const result = bookmarkFoldersState.moveFolder(moveState, '69', 'https://brave.com/|0|1') + const expectedState = moveState + .setIn(['bookmarkFolders', '69', 'parentFolderId'], 1) + .setIn(['cache', 'bookmarkOrder', '0'], Immutable.fromJS([ + { + key: '1', + order: 0, + type: siteTags.BOOKMARK_FOLDER + }, + { + key: '70', + order: 1, + type: siteTags.BOOKMARK_FOLDER + } + ])) + .setIn(['cache', 'bookmarkOrder', '1'], Immutable.fromJS([ + { + key: '2', + order: 0, + type: siteTags.BOOKMARK_FOLDER + }, + { + key: 'https://brave.com/|0|0', + order: 1, + type: siteTags.BOOKMARK + }, + { + key: '69', + order: 2, + type: siteTags.BOOKMARK_FOLDER + } + ])) + assert.deepEqual(result.toJS(), expectedState.toJS()) + assert(removeCacheKeySpy.calledOnce) + assert(addFolderToCacheSpy.calledOnce) + assert(findBookmarkSpy.calledOnce) + }) + + it('folder is moved (destination is bookmark folder and parentID is the same)', function () { + const result = bookmarkFoldersState.moveFolder(moveState, '69', '1', true, true) + const expectedState = moveState + .setIn(['bookmarkFolders', '69', 'parentFolderId'], 1) + .setIn(['cache', 'bookmarkOrder', '0'], Immutable.fromJS([ + { + key: '1', + order: 0, + type: siteTags.BOOKMARK_FOLDER + }, + { + key: '70', + order: 1, + type: siteTags.BOOKMARK_FOLDER + } + ])) + .setIn(['cache', 'bookmarkOrder', '1'], Immutable.fromJS([ + { + key: '2', + order: 0, + type: siteTags.BOOKMARK_FOLDER + }, + { + key: 'https://brave.com/|0|0', + order: 1, + type: siteTags.BOOKMARK + }, + { + key: '69', + order: 2, + type: siteTags.BOOKMARK_FOLDER + } + ])) + assert.deepEqual(result.toJS(), expectedState.toJS()) + assert(removeCacheKeySpy.calledOnce) + assert(addFolderToCacheSpy.calledOnce) + assert(findBookmarkSpy.calledOnce) + }) + + it('destination parent ID is different then current parent ID', function () { + const result = bookmarkFoldersState.moveFolder(moveState, '69', '2') + const expectedState = moveState + .setIn(['bookmarkFolders', '69', 'parentFolderId'], 2) + .setIn(['cache', 'bookmarkOrder', '0'], Immutable.fromJS([ + { + key: '1', + order: 0, + type: siteTags.BOOKMARK_FOLDER + }, + { + key: '70', + order: 1, + type: siteTags.BOOKMARK_FOLDER + } + ])) + .setIn(['cache', 'bookmarkOrder', '2'], Immutable.fromJS([ + { + key: '69', + order: 0, + type: siteTags.BOOKMARK_FOLDER + } + ])) + assert.deepEqual(result.toJS(), expectedState.toJS()) + assert(removeCacheKeySpy.calledOnce) + assert(addFolderToCacheSpy.calledOnce) + assert(findBookmarkSpy.calledOnce) + }) + + it('we have the same parent ID (destination and current)', function () { + const result = bookmarkFoldersState.moveFolder(moveState, '70', '1') + const expectedState = moveState + .setIn(['cache', 'bookmarkOrder', '0'], Immutable.fromJS([ + { + key: '1', + order: 0, + type: siteTags.BOOKMARK_FOLDER + }, + { + key: '70', + order: 1, + type: siteTags.BOOKMARK_FOLDER + }, + { + key: '69', + order: 2, + type: siteTags.BOOKMARK_FOLDER + } + ])) + assert.deepEqual(result.toJS(), expectedState.toJS()) + assert(removeCacheKeySpy.calledOnce) + assert(addFolderToCacheSpy.calledOnce) + assert(findBookmarkSpy.calledOnce) + }) + + it('we want to prepend folder', function () { + const result = bookmarkFoldersState.moveFolder(moveState, '69', '1', false) + const expectedState = moveState + .setIn(['cache', 'bookmarkOrder', '0'], Immutable.fromJS([ + { + key: '69', + order: 0, + type: siteTags.BOOKMARK_FOLDER + }, + { + key: '1', + order: 1, + type: siteTags.BOOKMARK_FOLDER + }, + { + key: '70', + order: 2, + type: siteTags.BOOKMARK_FOLDER + } + ])) + assert.deepEqual(result.toJS(), expectedState.toJS()) + assert(removeCacheKeySpy.calledOnce) + assert(addFolderToCacheSpy.calledOnce) + assert(findBookmarkSpy.calledOnce) + }) + }) + + describe('setWidth', function () { + it('null case', function () { + const result = bookmarkFoldersState.setWidth(stateWithData) + assert.deepEqual(result.toJS(), stateWithData.toJS()) + }) + + it('parse width', function () { + const result = bookmarkFoldersState.setWidth(stateWithData, '1', 'dsfsdfds') + assert.deepEqual(result.toJS(), stateWithData.toJS()) + }) + + it('set width', function () { + const result = bookmarkFoldersState.setWidth(stateWithData, '1', 100) + const expectedResult = stateWithData.setIn(['bookmarkFolders', '1', 'width'], 100) + assert.deepEqual(result.toJS(), expectedResult.toJS()) + }) + }) +}) diff --git a/test/unit/app/common/state/bookmarksStateTest.js b/test/unit/app/common/state/bookmarksStateTest.js index 9b32eccd45c..b64c34a9765 100644 --- a/test/unit/app/common/state/bookmarksStateTest.js +++ b/test/unit/app/common/state/bookmarksStateTest.js @@ -2,70 +2,168 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. */ -/* global describe, it */ +/* global describe, it, before, after, afterEach */ const assert = require('assert') const Immutable = require('immutable') +const mockery = require('mockery') +const sinon = require('sinon') const siteTags = require('../../../../../js/constants/siteTags') +const settings = require('../../../../../js/constants/settings') require('../../../braveUnit') -const bookmarksState = require('../../../../../app/common/state/bookmarksState') - -const stateWithData = Immutable.fromJS({ - windows: [], - bookmarks: { - 'https://brave.com/|0|0': { - favicon: undefined, - title: 'Brave', - location: 'https://brave.com/', - key: 'https://brave.com/|0|0', - parentFolderId: 0, - partitionNumber: 0, - objectId: null, - themeColor: undefined, - type: siteTags.BOOKMARK + +describe('bookmarkState unit test', function () { + let bookmarkOrderCache, bookmarksState, bookmarkFoldersState, bookmarkLocationCache, syncActions + + const emptyState = Immutable.fromJS({ + windows: [], + bookmarks: {}, + bookmarkFolders: {}, + cache: { + bookmarkOrder: {}, + bookmarkLocation: {} }, - 'https://clifton.io/|0|0': { - favicon: undefined, - title: 'Clifton', - location: 'https://clifton.io/', - key: 'https://clifton.io/|0|0', - parentFolderId: 0, - partitionNumber: 0, - objectId: null, - themeColor: undefined, - type: siteTags.BOOKMARK - } - }, - bookmarkFolders: {}, - cache: { - bookmarkOrder: { - '0': [ - { - key: 'https://brave.com/|0|0', - order: 0, - type: siteTags.BOOKMARK - }, - { - key: 'https://clifton.io/|0|0', - order: 1, - type: siteTags.BOOKMARK - } - ] + historySites: {}, + tabs: [] + }) + + const bookmark1 = { + favicon: undefined, + title: 'Brave', + location: 'https://brave.com/', + key: 'https://brave.com/|0|0', + parentFolderId: 0, + partitionNumber: 0, + objectId: null, + themeColor: undefined, + type: siteTags.BOOKMARK + } + + const bookmark2 = { + favicon: undefined, + title: 'Clifton', + location: 'https://clifton.io/', + key: 'https://clifton.io/|0|0', + parentFolderId: 0, + partitionNumber: 0, + objectId: null, + themeColor: undefined, + type: siteTags.BOOKMARK + } + + const bookmark3 = { + favicon: undefined, + title: 'BBondy', + location: 'https://brianbondy.com/', + key: 'https://brianbondy.com/|0|1', + parentFolderId: 1, + partitionNumber: 0, + objectId: null, + themeColor: undefined, + type: siteTags.BOOKMARK + } + + const folder1 = { + title: 'folder1', + folderId: 1, + key: '1', + parentFolderId: 0, + partitionNumber: 0, + objectId: null, + type: siteTags.BOOKMARK_FOLDER + } + + const folder2 = { + title: 'folder2', + folderId: 2, + key: '2', + parentFolderId: 1, + partitionNumber: 0, + objectId: null, + type: siteTags.BOOKMARK_FOLDER + } + + const stateWithData = Immutable.fromJS({ + windows: [], + bookmarks: { + 'https://brave.com/|0|0': bookmark1, + 'https://clifton.io/|0|0': bookmark2, + 'https://brianbondy.com/|0|1': bookmark3 }, - bookmarkLocation: { - 'https://brave.com/': [ - 'https://brave.com/|0|0' - ], - 'https://clifton.io/': [ - 'https://clifton.io/|0|0' - ] - } - }, - historySites: {}, - tabs: [] -}) + bookmarkFolders: { + '1': folder1, + '2': folder2 + }, + cache: { + bookmarkOrder: { + '0': [ + { + key: 'https://brave.com/|0|0', + order: 0, + type: siteTags.BOOKMARK + }, + { + key: 'https://clifton.io/|0|0', + order: 1, + type: siteTags.BOOKMARK + }, + { + key: '1', + order: 2, + type: siteTags.BOOKMARK_FOLDER + } + ], + '1': [ + { + key: 'https://brianbondy.com/|0|1', + order: 0, + type: siteTags.BOOKMARK + }, + { + key: '2', + order: 1, + type: siteTags.BOOKMARK_FOLDER + } + ] + }, + bookmarkLocation: { + 'https://brave.com/': [ + 'https://brave.com/|0|0' + ], + 'https://clifton.io/': [ + 'https://clifton.io/|0|0' + ] + } + }, + historySites: {}, + tabs: [] + }) + + // Settings + let settingSyncEnabled = false + + before(function () { + mockery.enable({ + warnOnReplace: false, + warnOnUnregistered: false, + useCleanCache: true + }) + mockery.registerMock('../../../js/settings', { + getSetting: (settingKey) => { + switch (settingKey) { + case settings.SYNC_ENABLED: + return settingSyncEnabled + } + return false + } + }) + syncActions = require('../../../../../js/actions/syncActions') + bookmarkOrderCache = require('../../../../../app/common/cache/bookmarkOrderCache') + bookmarkLocationCache = require('../../../../../app/common/cache/bookmarkLocationCache') + bookmarkFoldersState = require('../../../../../app/common/state/bookmarkFoldersState') + bookmarksState = require('../../../../../app/common/state/bookmarksState') + }) -describe('bookmarkState unit test', function () { describe('updateFavicon', function () { it('updates the favicon for all matching entries', function () { const processedState = bookmarksState.updateFavicon(stateWithData, 'https://brave.com/', 'https://brave.com/favicon.ico') @@ -113,60 +211,774 @@ describe('bookmarkState unit test', function () { } }) const processedState = bookmarksState.updateFavicon(stateWithNoEntries, testUrl, 'https://brave.com/favicon.ico') - const expectedState = stateWithNoEntries - assert.deepEqual(processedState.get('bookmarks').toJS(), expectedState.get('bookmarks').toJS()) + assert.deepEqual(processedState.get('bookmarks').toJS(), stateWithNoEntries.get('bookmarks').toJS()) }) }) describe('getBookmarksByParentId', function () { + let getBookmarksByParentIdSpy + before(function () { + getBookmarksByParentIdSpy = sinon.spy(bookmarkOrderCache, 'getBookmarksByParentId') + }) + + afterEach(function () { + getBookmarksByParentIdSpy.reset() + }) + + after(function () { + getBookmarksByParentIdSpy.restore() + }) + it('null case', function () { const result = bookmarksState.getBookmarksByParentId(stateWithData) - assert.equal(result, Immutable.List()) + assert(getBookmarksByParentIdSpy.notCalled) + assert.deepEqual(result.toJS(), []) }) it('cache is empty', function () { - const state = Immutable.fromJS({ - windows: [], - bookmarks: {}, - bookmarkFolders: {}, - cache: { - bookmarkOrder: {}, - bookmarkLocation: {} - }, - historySites: {}, - tabs: [] - }) - - const result = bookmarksState.getBookmarksByParentId(state, 1) - assert.deepEqual(result, Immutable.List()) + const result = bookmarksState.getBookmarksByParentId(emptyState, 1) + assert(getBookmarksByParentIdSpy.calledOnce) + assert.deepEqual(result.toJS(), []) }) it('bookmarks are returned', function () { const result = bookmarksState.getBookmarksByParentId(stateWithData, 0) - assert.deepEqual(result, Immutable.fromJS([ - { - favicon: undefined, - title: 'Brave', + assert(getBookmarksByParentIdSpy.calledOnce) + assert.deepEqual(result.toJS(), [ + bookmark1, + bookmark2 + ]) + }) + }) + + describe('getBookmarks', function () { + it('return', function () { + const result = bookmarksState.getBookmarks(stateWithData) + assert.deepEqual(result.toJS(), stateWithData.get('bookmarks').toJS()) + }) + }) + + describe('getBookmark', function () { + it('null case', function () { + const result = bookmarksState.getBookmark(stateWithData) + assert.deepEqual(result.toJS(), {}) + }) + + it('return', function () { + const result = bookmarksState.getBookmark(stateWithData, 'https://brave.com/|0|0') + assert.deepEqual(result.toJS(), bookmark1) + }) + }) + + describe('findBookmark', function () { + let getBookmarkSpy, getFolderSpy + before(function () { + getBookmarkSpy = sinon.spy(bookmarksState, 'getBookmark') + getFolderSpy = sinon.spy(bookmarkFoldersState, 'getFolder') + }) + + afterEach(function () { + getBookmarkSpy.reset() + getFolderSpy.reset() + }) + + after(function () { + getBookmarkSpy.restore() + getFolderSpy.restore() + }) + + it('null case', function () { + const result = bookmarksState.findBookmark(stateWithData) + assert.deepEqual(result.toJS(), {}) + assert(getBookmarkSpy.notCalled) + assert(getFolderSpy.notCalled) + }) + + it('we are looking for bookmark', function () { + const result = bookmarksState.findBookmark(stateWithData, 'https://brave.com/|0|0') + assert.deepEqual(result.toJS(), bookmark1) + assert(getBookmarkSpy.calledOnce) + assert(getFolderSpy.notCalled) + }) + + it('we are looking for bookmark folder', function () { + const result = bookmarksState.findBookmark(stateWithData, '1') + assert.deepEqual(result.toJS(), stateWithData.getIn(['bookmarkFolders', '1']).toJS()) + assert(getBookmarkSpy.calledOnce) + assert(getFolderSpy.calledOnce) + }) + }) + + describe('setWidth', function () { + it('null case', function () { + const result = bookmarksState.setWidth(stateWithData) + assert.deepEqual(result.toJS(), stateWithData.toJS()) + }) + + it('parse width', function () { + const result = bookmarksState.setWidth(stateWithData, '1', 'dsfsdfds') + assert.deepEqual(result.toJS(), stateWithData.toJS()) + }) + + it('set width', function () { + const result = bookmarksState.setWidth(stateWithData, '1', 100) + const expectedResult = stateWithData.setIn(['bookmarks', '1', 'width'], 100) + assert.deepEqual(result.toJS(), expectedResult.toJS()) + }) + }) + + describe('getBookmarksWithFolders', function () { + let getBookmarksWithFoldersSpy + before(function () { + getBookmarksWithFoldersSpy = sinon.spy(bookmarkOrderCache, 'getBookmarksWithFolders') + }) + + afterEach(function () { + getBookmarksWithFoldersSpy.reset() + }) + + after(function () { + getBookmarksWithFoldersSpy.restore() + }) + + it('null case (default to parent id 0)', function () { + const result = bookmarksState.getBookmarksWithFolders(stateWithData) + const expectedResult = Immutable.fromJS([ + bookmark1, + bookmark2, + folder1 + ]) + assert.deepEqual(result.toJS(), expectedResult.toJS()) + assert(getBookmarksWithFoldersSpy.calledOnce) + }) + + it('with parent id', function () { + const result = bookmarksState.getBookmarksWithFolders(stateWithData, 1) + const expectedResult = Immutable.fromJS([ + bookmark3, + folder2 + ]) + assert.deepEqual(result.toJS(), expectedResult.toJS()) + assert(getBookmarksWithFoldersSpy.calledOnce) + }) + }) + + describe('addBookmark', function () { + let addCacheKeySpy, addBookmarkToCacheSpy + before(function () { + addCacheKeySpy = sinon.spy(bookmarkLocationCache, 'addCacheKey') + addBookmarkToCacheSpy = sinon.spy(bookmarkOrderCache, 'addBookmarkToCache') + }) + + afterEach(function () { + addCacheKeySpy.reset() + addBookmarkToCacheSpy.reset() + }) + + after(function () { + addCacheKeySpy.restore() + addBookmarkToCacheSpy.restore() + }) + + it('null case', function () { + const result = bookmarksState.addBookmark(emptyState) + assert(addCacheKeySpy.notCalled) + assert(addBookmarkToCacheSpy.notCalled) + assert.deepEqual(result.toJS(), emptyState.toJS()) + }) + + it('completely new bookmark', function () { + const bookmark = Immutable.fromJS({ + location: 'https://page.com', + parentFolderId: 2, + title: 'Page', + key: 'https://page.com|0|2' + }) + const result = bookmarksState.addBookmark(emptyState, bookmark) + const expectedState = emptyState + .setIn(['bookmarks'], Immutable.fromJS({ + 'https://page.com|0|2': { + location: 'https://page.com', + parentFolderId: 2, + title: 'Page', + key: 'https://page.com|0|2' + } + })) + .setIn(['cache', 'bookmarkOrder', '2'], Immutable.fromJS([ + { + order: 0, + key: 'https://page.com|0|2', + type: siteTags.BOOKMARK + } + ])) + .setIn(['cache', 'bookmarkLocation', 'https://page.com'], Immutable.fromJS([ + 'https://page.com|0|2' + ])) + + assert(addCacheKeySpy.calledOnce) + assert(addBookmarkToCacheSpy.calledOnce) + assert.deepEqual(result.toJS(), expectedState.toJS()) + }) + + it('we already have cache for this bookmark', function () { + const bookmark = Immutable.fromJS(bookmark1).set('title', 'New Brave') + const result = bookmarksState.addBookmark(stateWithData, bookmark) + const expectedState = stateWithData + .setIn(['bookmarks', 'https://brave.com/|0|0', 'title'], 'New Brave') + + assert(addCacheKeySpy.notCalled) + assert(addBookmarkToCacheSpy.notCalled) + assert.deepEqual(result.toJS(), expectedState.toJS()) + }) + }) + + describe('editBookmark', function () { + let addCacheKeySpy, addBookmarkToCacheSpy, removeCacheKeySpy, removeCacheOrderSpy + before(function () { + addCacheKeySpy = sinon.spy(bookmarkLocationCache, 'addCacheKey') + removeCacheKeySpy = sinon.spy(bookmarkLocationCache, 'removeCacheKey') + removeCacheOrderSpy = sinon.spy(bookmarkOrderCache, 'removeCacheKey') + addBookmarkToCacheSpy = sinon.spy(bookmarkOrderCache, 'addBookmarkToCache') + }) + + afterEach(function () { + addCacheKeySpy.reset() + addBookmarkToCacheSpy.reset() + removeCacheKeySpy.reset() + removeCacheOrderSpy.reset() + }) + + after(function () { + addCacheKeySpy.restore() + addBookmarkToCacheSpy.restore() + removeCacheKeySpy.restore() + removeCacheOrderSpy.restore() + }) + + it('null case', function () { + const result = bookmarksState.editBookmark(stateWithData) + assert(addCacheKeySpy.notCalled) + assert(removeCacheOrderSpy.notCalled) + assert(addBookmarkToCacheSpy.notCalled) + assert(removeCacheKeySpy.notCalled) + assert(result.toJS(), stateWithData.toJS()) + }) + + it('edit key is different then old bookmark', function () { + const bookmark = Immutable.fromJS({ + location: 'https://brave.com/', + parentFolderId: 2, + title: 'Page', + key: 'https://brave.com/|0|2' + }) + + const expectedState = stateWithData + .deleteIn(['bookmarks', 'https://brave.com/|0|0']) + .setIn(['bookmarks', 'https://brave.com/|0|2'], Immutable.fromJS({ location: 'https://brave.com/', - key: 'https://brave.com/|0|0', - parentFolderId: 0, - partitionNumber: 0, - objectId: null, - themeColor: undefined, - type: siteTags.BOOKMARK - }, - { - favicon: undefined, - title: 'Clifton', - location: 'https://clifton.io/', - key: 'https://clifton.io/|0|0', - parentFolderId: 0, - partitionNumber: 0, - objectId: null, - themeColor: undefined, - type: siteTags.BOOKMARK - } - ])) + parentFolderId: 2, + title: 'Page', + key: 'https://brave.com/|0|2' + })) + .setIn(['cache', 'bookmarkOrder', '0'], Immutable.fromJS([ + { + key: 'https://clifton.io/|0|0', + order: 0, + type: siteTags.BOOKMARK + }, + { + key: '1', + order: 1, + type: siteTags.BOOKMARK_FOLDER + } + ])) + .setIn(['cache', 'bookmarkOrder', '2'], Immutable.fromJS([ + { + order: 0, + key: 'https://brave.com/|0|2', + type: siteTags.BOOKMARK + } + ])) + .setIn(['cache', 'bookmarkLocation', 'https://brave.com/'], Immutable.fromJS([ + 'https://brave.com/|0|2' + ])) + const result = bookmarksState.editBookmark(stateWithData, bookmark1, bookmark) + assert(addCacheKeySpy.calledOnce) + assert(removeCacheOrderSpy.calledOnce) + assert(addBookmarkToCacheSpy.calledOnce) + assert(removeCacheKeySpy.calledOnce) + assert.deepEqual(result.toJS(), expectedState.toJS()) + }) + + it('edit key is the same as old bookmark', function () { + const bookmark = Immutable.fromJS({ + location: 'https://brave.com/', + parentFolderId: 0, + title: 'Page Title', + key: 'https://brave.com/|0|0' + }) + + const expectedState = stateWithData + .setIn(['bookmarks', 'https://brave.com/|0|0'], bookmark) + const result = bookmarksState.editBookmark(stateWithData, bookmark1, bookmark) + + assert(addCacheKeySpy.calledOnce) + assert(removeCacheKeySpy.calledOnce) + assert(removeCacheOrderSpy.notCalled) + assert(addBookmarkToCacheSpy.notCalled) + assert.deepEqual(result.toJS(), expectedState.toJS()) + }) + }) + + describe('removeBookmark', function () { + let removeCacheOrderSpy, removeCacheKeySpy, getBookmarkSpy, removeSitesSpy + before(function () { + removeCacheOrderSpy = sinon.spy(bookmarkOrderCache, 'removeCacheKey') + removeCacheKeySpy = sinon.spy(bookmarkLocationCache, 'removeCacheKey') + getBookmarkSpy = sinon.spy(bookmarksState, 'getBookmark') + removeSitesSpy = sinon.spy(syncActions, 'removeSites') + }) + + afterEach(function () { + removeCacheOrderSpy.reset() + removeCacheKeySpy.reset() + getBookmarkSpy.reset() + removeSitesSpy.reset() + }) + + after(function () { + removeCacheOrderSpy.restore() + removeCacheKeySpy.restore() + getBookmarkSpy.restore() + removeSitesSpy.restore() + }) + + it('null case', function () { + const result = bookmarksState.removeBookmark(stateWithData) + assert.deepEqual(result.toJS(), stateWithData.toJS()) + assert(removeCacheOrderSpy.notCalled) + assert(removeCacheKeySpy.notCalled) + assert(getBookmarkSpy.notCalled) + assert(removeSitesSpy.notCalled) + }) + + it('bookmark does not exist', function () { + const result = bookmarksState.removeBookmark(stateWithData, 'https://brave.com/|0|1') + assert.deepEqual(result.toJS(), stateWithData.toJS()) + assert(getBookmarkSpy.calledOnce) + assert(removeCacheOrderSpy.notCalled) + assert(removeCacheKeySpy.notCalled) + assert(removeSitesSpy.notCalled) + }) + + it('call sync if enabled', function () { + settingSyncEnabled = true + bookmarksState.removeBookmark(stateWithData, 'https://brave.com/|0|0') + assert(removeSitesSpy.calledOnce) + settingSyncEnabled = false + }) + + it('remove bookmark', function () { + const result = bookmarksState.removeBookmark(stateWithData, 'https://brave.com/|0|0') + const expectedState = stateWithData + .deleteIn(['bookmarks', 'https://brave.com/|0|0']) + .deleteIn(['cache', 'bookmarkLocation', 'https://brave.com/']) + .setIn(['cache', 'bookmarkOrder', '0'], Immutable.fromJS([ + { + key: 'https://clifton.io/|0|0', + order: 0, + type: siteTags.BOOKMARK + }, + { + key: '1', + order: 1, + type: siteTags.BOOKMARK_FOLDER + } + ])) + assert.deepEqual(result.toJS(), expectedState.toJS()) + assert(removeCacheOrderSpy.calledOnce) + assert(removeCacheKeySpy.calledOnce) + assert(getBookmarkSpy.calledOnce) + assert(removeSitesSpy.notCalled) + }) + }) + + describe('removeBookmarksByParentId', function () { + let removeCacheOrderSpy, removeCacheKeySpy, getBookmarkSpy, removeSitesSpy + before(function () { + removeCacheKeySpy = sinon.spy(bookmarkLocationCache, 'removeCacheKey') + removeCacheOrderSpy = sinon.spy(bookmarkOrderCache, 'removeCacheKey') + getBookmarkSpy = sinon.spy(bookmarksState, 'getBookmarks') + removeSitesSpy = sinon.spy(syncActions, 'removeSites') + }) + + afterEach(function () { + removeCacheKeySpy.reset() + getBookmarkSpy.reset() + removeCacheOrderSpy.reset() + removeSitesSpy.reset() + }) + + after(function () { + removeCacheKeySpy.restore() + getBookmarkSpy.restore() + removeCacheOrderSpy.restore() + removeSitesSpy.restore() + }) + + it('null case', function () { + const result = bookmarksState.removeBookmarksByParentId(stateWithData) + assert.deepEqual(result.toJS(), stateWithData.toJS()) + assert(removeCacheKeySpy.notCalled) + assert(getBookmarkSpy.notCalled) + assert(removeSitesSpy.notCalled) + assert(removeCacheOrderSpy.notCalled) + }) + + it('bookmark map is empty', function () { + const result = bookmarksState.removeBookmarksByParentId(emptyState, '1') + assert.deepEqual(result.toJS(), emptyState.toJS()) + assert(getBookmarkSpy.calledOnce) + assert(removeCacheKeySpy.notCalled) + assert(removeSitesSpy.notCalled) + assert(removeCacheOrderSpy.notCalled) + }) + + it('there is no bookmark for provided parent ID', function () { + const result = bookmarksState.removeBookmarksByParentId(stateWithData, '3') + assert.deepEqual(result.toJS(), stateWithData.toJS()) + assert(getBookmarkSpy.calledOnce) + assert(removeCacheKeySpy.notCalled) + assert(removeSitesSpy.notCalled) + assert(removeCacheOrderSpy.notCalled) + }) + + it('we remove some bookmarks', function () { + const result = bookmarksState.removeBookmarksByParentId(stateWithData, '0') + const expectedState = stateWithData + .deleteIn(['bookmarks', 'https://brave.com/|0|0']) + .deleteIn(['bookmarks', 'https://clifton.io/|0|0']) + .deleteIn(['cache', 'bookmarkLocation', 'https://brave.com/']) + .deleteIn(['cache', 'bookmarkLocation', 'https://clifton.io/']) + .setIn(['cache', 'bookmarkOrder', '0'], Immutable.fromJS([ + { + key: '1', + order: 0, + type: siteTags.BOOKMARK_FOLDER + } + ])) + assert.deepEqual(result.toJS(), expectedState.toJS()) + assert(getBookmarkSpy.calledOnce) + assert(removeCacheKeySpy.calledTwice) + assert(removeCacheOrderSpy.calledTwice) + assert(removeSitesSpy.notCalled) + }) + + it('sync is enabled', function () { + settingSyncEnabled = true + bookmarksState.removeBookmarksByParentId(stateWithData, '0') + const expectedState = [ + stateWithData.getIn(['bookmarks', 'https://brave.com/|0|0']).toJS(), + stateWithData.getIn(['bookmarks', 'https://clifton.io/|0|0']).toJS() + ] + assert(removeSitesSpy.withArgs(expectedState).calledOnce) + settingSyncEnabled = false + }) + }) + + describe('moveBookmark', function () { + let addFolderToCacheSpy, removeCacheKeySpy, findBookmarkSpy, bookmarkLocationCacheSpy + + before(function () { + removeCacheKeySpy = sinon.spy(bookmarkOrderCache, 'removeCacheKey') + addFolderToCacheSpy = sinon.spy(bookmarkOrderCache, 'addBookmarkToCache') + bookmarkLocationCacheSpy = sinon.spy(bookmarkLocationCache, 'addCacheKey') + findBookmarkSpy = sinon.spy(bookmarksState, 'findBookmark') + }) + + afterEach(function () { + removeCacheKeySpy.reset() + addFolderToCacheSpy.reset() + bookmarkLocationCacheSpy.reset() + findBookmarkSpy.reset() + }) + + after(function () { + removeCacheKeySpy.restore() + addFolderToCacheSpy.restore() + bookmarkLocationCacheSpy.restore() + findBookmarkSpy.restore() + }) + + it('null case', function () { + const result = bookmarksState.moveBookmark(stateWithData) + assert.deepEqual(result.toJS(), stateWithData.toJS()) + assert(removeCacheKeySpy.notCalled) + assert(addFolderToCacheSpy.notCalled) + assert(bookmarkLocationCacheSpy.notCalled) + assert(findBookmarkSpy.notCalled) + }) + + it('destination folder is not found', function () { + const result = bookmarksState.moveBookmark(stateWithData, '69') + assert.deepEqual(result.toJS(), stateWithData.toJS()) + assert(removeCacheKeySpy.notCalled) + assert(addFolderToCacheSpy.notCalled) + assert(bookmarkLocationCacheSpy.notCalled) + assert(findBookmarkSpy.notCalled) + }) + + it('bookmark is moved (destination is bookmark)', function () { + const result = bookmarksState.moveBookmark(stateWithData, 'https://brave.com/|0|0', 'https://brianbondy.com/|0|1') + const expectedState = stateWithData + .deleteIn(['bookmarks', 'https://brave.com/|0|0']) + .setIn(['bookmarks', 'https://brave.com/|0|1'], Immutable.fromJS(bookmark1)) + .setIn(['bookmarks', 'https://brave.com/|0|1', 'parentFolderId'], 1) + .setIn(['bookmarks', 'https://brave.com/|0|1', 'key'], 'https://brave.com/|0|1') + .setIn(['cache', 'bookmarkOrder', '0'], Immutable.fromJS([ + { + key: 'https://clifton.io/|0|0', + order: 0, + type: siteTags.BOOKMARK + }, + { + key: '1', + order: 1, + type: siteTags.BOOKMARK_FOLDER + } + ])) + .setIn(['cache', 'bookmarkOrder', '1'], Immutable.fromJS([ + { + key: 'https://brianbondy.com/|0|1', + order: 0, + type: siteTags.BOOKMARK + }, + { + key: '2', + order: 1, + type: siteTags.BOOKMARK_FOLDER + }, + { + key: 'https://brave.com/|0|1', + order: 2, + type: siteTags.BOOKMARK + } + ])) + .setIn(['cache', 'bookmarkLocation', 'https://brave.com/'], Immutable.fromJS([ + 'https://brave.com/|0|1' + ])) + assert(removeCacheKeySpy.calledOnce) + assert(addFolderToCacheSpy.calledOnce) + assert(bookmarkLocationCacheSpy.calledOnce) + assert(findBookmarkSpy.calledOnce) + assert.deepEqual(result.toJS(), expectedState.toJS()) + }) + + it('bookmark is moved (destination is bookmark folder, and parentID is the same)', function () { + const result = bookmarksState.moveBookmark(stateWithData, 'https://brave.com/|0|0', '1', true, true) + const expectedState = stateWithData + .deleteIn(['bookmarks', 'https://brave.com/|0|0']) + .setIn(['bookmarks', 'https://brave.com/|0|1'], Immutable.fromJS(bookmark1)) + .setIn(['bookmarks', 'https://brave.com/|0|1', 'parentFolderId'], 1) + .setIn(['bookmarks', 'https://brave.com/|0|1', 'key'], 'https://brave.com/|0|1') + .setIn(['cache', 'bookmarkOrder', '0'], Immutable.fromJS([ + { + key: 'https://clifton.io/|0|0', + order: 0, + type: siteTags.BOOKMARK + }, + { + key: '1', + order: 1, + type: siteTags.BOOKMARK_FOLDER + } + ])) + .setIn(['cache', 'bookmarkOrder', '1'], Immutable.fromJS([ + { + key: 'https://brianbondy.com/|0|1', + order: 0, + type: siteTags.BOOKMARK + }, + { + key: '2', + order: 1, + type: siteTags.BOOKMARK_FOLDER + }, + { + key: 'https://brave.com/|0|1', + order: 2, + type: siteTags.BOOKMARK + } + ])) + .setIn(['cache', 'bookmarkLocation', 'https://brave.com/'], Immutable.fromJS([ + 'https://brave.com/|0|1' + ])) + assert.deepEqual(result.toJS(), expectedState.toJS()) + assert(removeCacheKeySpy.calledOnce) + assert(addFolderToCacheSpy.calledOnce) + assert(findBookmarkSpy.calledOnce) + }) + + it('bookmark is moved (destination is bookmark toolbar)', function () { + const result = bookmarksState.moveBookmark(stateWithData, 'https://brianbondy.com/|0|1', '0', true, true) + const expectedState = stateWithData + .deleteIn(['bookmarks', 'https://brianbondy.com/|0|1']) + .setIn(['bookmarks', 'https://brianbondy.com/|0|0'], Immutable.fromJS(bookmark3)) + .setIn(['bookmarks', 'https://brianbondy.com/|0|0', 'parentFolderId'], 0) + .setIn(['bookmarks', 'https://brianbondy.com/|0|0', 'key'], 'https://brianbondy.com/|0|0') + .setIn(['cache', 'bookmarkOrder', '0'], Immutable.fromJS([ + { + key: 'https://brave.com/|0|0', + order: 0, + type: siteTags.BOOKMARK + }, + { + key: 'https://clifton.io/|0|0', + order: 1, + type: siteTags.BOOKMARK + }, + { + key: '1', + order: 2, + type: siteTags.BOOKMARK_FOLDER + }, + { + key: 'https://brianbondy.com/|0|0', + order: 3, + type: siteTags.BOOKMARK + } + ])) + .setIn(['cache', 'bookmarkOrder', '1'], Immutable.fromJS([ + { + key: '2', + order: 0, + type: siteTags.BOOKMARK_FOLDER + } + ])) + .setIn(['cache', 'bookmarkLocation', 'https://brianbondy.com/'], Immutable.fromJS([ + 'https://brianbondy.com/|0|0' + ])) + assert.deepEqual(result.toJS(), expectedState.toJS()) + assert(removeCacheKeySpy.calledOnce) + assert(addFolderToCacheSpy.calledOnce) + assert(findBookmarkSpy.calledOnce) + }) + + it('bookmark is moved (destination is other bookmarks)', function () { + const result = bookmarksState.moveBookmark(stateWithData, 'https://brianbondy.com/|0|1', -1, true, true) + const expectedState = stateWithData + .deleteIn(['bookmarks', 'https://brianbondy.com/|0|1']) + .setIn(['bookmarks', 'https://brianbondy.com/|0|-1'], Immutable.fromJS(bookmark3)) + .setIn(['bookmarks', 'https://brianbondy.com/|0|-1', 'parentFolderId'], -1) + .setIn(['bookmarks', 'https://brianbondy.com/|0|-1', 'key'], 'https://brianbondy.com/|0|-1') + .setIn(['cache', 'bookmarkOrder', '-1'], Immutable.fromJS([ + { + key: 'https://brianbondy.com/|0|-1', + order: 0, + type: siteTags.BOOKMARK + } + ])) + .setIn(['cache', 'bookmarkOrder', '1'], Immutable.fromJS([ + { + key: '2', + order: 0, + type: siteTags.BOOKMARK_FOLDER + } + ])) + .setIn(['cache', 'bookmarkLocation', 'https://brianbondy.com/'], Immutable.fromJS([ + 'https://brianbondy.com/|0|-1' + ])) + assert.deepEqual(result.toJS(), expectedState.toJS()) + assert(removeCacheKeySpy.calledOnce) + assert(addFolderToCacheSpy.calledOnce) + assert(findBookmarkSpy.calledOnce) + }) + + it('destination parent ID is different then current parent ID', function () { + const result = bookmarksState.moveBookmark(stateWithData, 'https://brave.com/|0|0', '2') + const expectedState = stateWithData + .deleteIn(['bookmarks', 'https://brave.com/|0|0']) + .setIn(['bookmarks', 'https://brave.com/|0|2'], Immutable.fromJS(bookmark1)) + .setIn(['bookmarks', 'https://brave.com/|0|2', 'parentFolderId'], 2) + .setIn(['bookmarks', 'https://brave.com/|0|2', 'key'], 'https://brave.com/|0|2') + .setIn(['cache', 'bookmarkOrder', '0'], Immutable.fromJS([ + { + key: 'https://clifton.io/|0|0', + order: 0, + type: siteTags.BOOKMARK + }, + { + key: '1', + order: 1, + type: siteTags.BOOKMARK_FOLDER + } + ])) + .setIn(['cache', 'bookmarkOrder', '2'], Immutable.fromJS([ + { + key: 'https://brave.com/|0|2', + order: 0, + type: siteTags.BOOKMARK + } + ])) + .setIn(['cache', 'bookmarkLocation', 'https://brave.com/'], Immutable.fromJS([ + 'https://brave.com/|0|2' + ])) + assert.deepEqual(result.toJS(), expectedState.toJS()) + assert(removeCacheKeySpy.calledOnce) + assert(addFolderToCacheSpy.calledOnce) + assert(findBookmarkSpy.calledOnce) + }) + + it('we have the same parent ID (destination and current)', function () { + const result = bookmarksState.moveBookmark(stateWithData, 'https://brave.com/|0|0', 'https://clifton.io/|0|0') + const expectedState = stateWithData + .setIn(['cache', 'bookmarkOrder', '0'], Immutable.fromJS([ + { + key: 'https://clifton.io/|0|0', + order: 0, + type: siteTags.BOOKMARK + }, + { + key: 'https://brave.com/|0|0', + order: 1, + type: siteTags.BOOKMARK + }, + { + key: '1', + order: 2, + type: siteTags.BOOKMARK_FOLDER + } + ])) + assert.deepEqual(result.toJS(), expectedState.toJS()) + assert(removeCacheKeySpy.calledOnce) + assert(addFolderToCacheSpy.calledOnce) + assert(findBookmarkSpy.calledOnce) + }) + + it('we want to prepend folder', function () { + const result = bookmarksState.moveBookmark(stateWithData, 'https://brave.com/|0|0', '1', false) + const expectedState = stateWithData + .setIn(['cache', 'bookmarkOrder', '0'], Immutable.fromJS([ + { + key: 'https://clifton.io/|0|0', + order: 0, + type: siteTags.BOOKMARK + }, + { + key: 'https://brave.com/|0|0', + order: 1, + type: siteTags.BOOKMARK + }, + { + key: '1', + order: 2, + type: siteTags.BOOKMARK_FOLDER + } + ])) + assert.deepEqual(result.toJS(), expectedState.toJS()) + assert(removeCacheKeySpy.calledOnce) + assert(addFolderToCacheSpy.calledOnce) + assert(findBookmarkSpy.calledOnce) }) }) })