brave / browser-laptop

[DEPRECATED] Please see https://github.com/brave/brave-browser for the current version of Brave
https://www.brave.com
Other
7.95k stars 974 forks source link

Error in undefined: "getWalletProperties" on master #11251

Closed srirambv closed 7 years ago

srirambv commented 7 years ago

Test plan

  1. Enable payments,
  2. visit couple of verified publishers site
  3. Console should not show the error below

Description

Error in undefined: "getWalletProperties" on master ### Steps to Reproduce
  1. Build from master
  2. Enable payments, visit couple of verified publishers site
  3. Console shows error

Actual result:

image

Expected result:

Reproduces how often: [What percentage of the time does it reproduce?]

Brave Version

about:brave info:

Brave 0.21.0
V8 6.1.534.41
rev de5f381
Muon 4.4.25

Reproducible on current live release:

Additional Information

cc: @NejcZdovc
luixxiul commented 7 years ago

@srirambv would you mind running npm run unittest and making sure there are many failed tests?

srirambv commented 7 years ago

@luixxiul This is what I see for npm run unittest

$ npm run unittest

> brave@0.21.0 unittest E:\srirambv\master\browser-laptop
> cross-env NODE_ENV=test mocha "test/unit/**/*Test.js"

  NewTab component unit tests
    Object properties
      showImages
        √ returns true when `showImages` and `backgroundImage` are true
        √ returns false when `showImages` is falsey
        √ returns false when `backgroundImage` is falsey
      randomBackgroundImage
        √ calls random to get a random index
        √ returns an object which has a value set for `style.backgroundImage`
      fallbackImage
        √ returns an object which has a value set for `style.backgroundImage`
    Rendering
      empty new tab
        √ renders an empty div if `this.state.showEmptyPage` is true
        √ renders newPrivateTab page if isIncognito props is true
      dashboard
        √ returns null if newTabData is not set
        √ renders the Stats component
        √ renders the Clock component
        √ renders the FooterInfo component
        when `this.showImages` is true
          √ sets backgroundImage for root element to the URL of the image
          √ includes div element with class bgGradient
          √ includes img element (used to detect onError)
        when `this.showImages` is false
          √ includes element with class gradient
          √ does NOT include img element (used to detect onError)
    Time saved stats, when time saved
      √ == 1 second
      √ == 1.5 seconds
      √ == 1 minute
      √ == 1.5 minutes
      √ == 1 hour
      √ == 1.55 hours
      √ == 1 day
      √ == 2.555 days

  Preferences component
    loads
Warning: Using Maps as children is not yet fully supported. It is an experimental feature that might be removed. Convert it to a sequence / iterable of keyed ReactElements instead.
      √ Changes pref pane on popstate event (156ms)
      √ Changes pref pane by hash on mount (141ms)
    General
      Default path
        √ call appActions.defaultDownloadPath when pencil is clicked

  AboutWelcome component
    Rendering
      √ renders an iframe

  adBlockUtil test
    shouldDoAdBlockCheck
      √ http protocol allows ad block checks
      √ https protocol allows ad block checks
      √ ftp protocol does not allow ad block checks
      √ should check third party urls
      √ should check first party urls
      √ Avoid checks with unknown resource types
      √ should check first party hosts on youtube
      √ diqus is allowed as third party, for now
      √ should NOT check third party urls for main frame

  topSites api
    calculateTopSites
      √ respects position of pinned items when populating results
      √ only includes one result for a domain (the one with the highest count)
      when fetching unpinned results
        √ sorts results by `count` DESC
        √ sorts results by `lastAccessedTime` DESC if `count` is the same
        √ only returns the last `maxSites` results (54ms)
        √ does not include items marked as ignored

  Bookmarks export
    √ personal array
    √ other array
    √ generated html

  isThirdPartyHost test
    √ A URL should not be third party to itself
    √ A subdomain URL should not be third party
    √ Unrelated URLs should be third party
    √ Checks subdomains properly

  menu reducer unit tests
    APP_SET_STATE
      √ state is returned unchanged
    WINDOW_SET_FOCUSED_FRAME
      √ state is returned unchanged
    APP_CHANGE_SETTING
      √ state is returned unchanged
    WINDOW_UNDO_CLOSED_FRAME
      √ state is returned unchanged
    WINDOW_CLEAR_CLOSED_FRAMES
      √ state is returned unchanged
    APP_TAB_CLOSE_REQUESTED
      √ state is returned unchanged
    APP_APPLY_SITE_RECORDS
      √ state is returned unchanged
    APP_ADD_SITE
      √ state is returned unchanged
    APP_REMOVE_SITE
      √ state is returned unchanged
    APP_ON_CLEAR_BROWSING_DATA
      √ state is returned unchanged
    WINDOW_CLICK_MENUBAR_SUBMENU
      √ state is returned unchanged

  autoplayReducer unit tests
    Allow autoplay once
      √ calls local.translation
      √ calls appActions.showNotification
      √ calls appActions.hideNotification
      √ calls appActions.changeSiteSetting
      √ calls appActions.removeSiteSetting
      √ calls ipcMain.removeListener
    Allow autoplay and remember
      √ calls local.translation
      √ calls appActions.showNotification
      √ calls appActions.hideNotification
      √ calls appActions.changeSiteSetting
      √ calls ipcMain.removeListener
    Deny autoplay once
      √ calls local.translation
      √ calls appActions.showNotification
      √ calls appActions.hideNotification
      √ calls ipcMain.removeListener
    Deny autoplay and remember
      √ calls local.translation
      √ calls appActions.showNotification
      √ calls appActions.hideNotification
      √ calls appActions.changeSiteSetting
      √ calls ipcMain.removeListener
    APP_AUTOPLAY_DISMISSED
      √ calls local.translation
      √ calls appActions.hideNotification
      √ calls ipcMain.removeListener

  bookmarkFoldersReducer unit test
    APP_ADD_BOOKMARK_FOLDER
      √ null case
      √ folder data is map (single folder)
      √ folder data is list (multiple folders)
    APP_EDIT_BOOKMARK_FOLDER
      √ null case
      √ folder data is missing
      √ folder key is missing
      √ folder data is correct
    APP_MOVE_BOOKMARK_FOLDER
      √ null case
      √ check if move is working
      √ destination key is not on bookmark toolbar
    APP_REMOVE_BOOKMARK_FOLDER
      √ null case
      √ folder key is list (multiple folders)
      √ folder key is map (single folder)
    APP_ON_BOOKMARK_FOLDER_WIDTH_CHANGED
      √ null case
      √ we update multiple items
      √ we update one and dont trigger toolbar update (parentFolderId is not 0)

  bookmarkToolbarReducer unit test
    APP_SET_STATE
      √ we are upgrading from version 0.20 to 0.21
      √ we are on version 0.21

  bookmarksReducer unit test
    APP_SET_STATE
      √ function is called
    APP_ADD_BOOKMARK
      √ null case
      √ bookmark data is map (single bookmark)
      √ bookmark data is list (multiple bookmarks)
      √ add a bookmark with a close bookmark prepending
    APP_EDIT_BOOKMARK
      √ null case
      √ bookmark data is missing
      √ bookmark key is missing
      √ bookmark data is correct
    APP_MOVE_BOOKMARK
      √ null case
      √ data is correct
      √ destination key is not on bookmark toolbar
    APP_REMOVE_BOOKMARK
      √ null case
      √ check if delete is working
    APP_ON_BOOKMARK_WIDTH_CHANGED
      √ null case
      √ we update multiple items
      √ we update one and trigger toolbar update

  clipboardReducer
    APP_CLIPBOARD_TEXT_UPDATED
      √ Does not modify state
      √ Copies text into electron.clipboard

  downloadsReducer
    √ returns original state for unhandled actions
    APP_DOWNLOAD_REVEALED
      √ Reveals file for paths that does not exist exist
      √ Reveals file for paths that does not exist exist
    APP_DOWNLOAD_OPENED
      √ Opens a downloaded file
      √ Beeps when a downloaded file is trying to be opened
    APP_DOWNLOAD_ACTION_PERFORMED
      √ CANCEL causes CANCELLED state
    APP_DOWNLOAD_COPIED_TO_CLIPBOARD
      √ copies the download URL to the clipboard
    APP_DOWNLOAD_DELETED
      √ deletes a downloadId that exists
      √ does nothing for a downloadId that does not exist
    APP_DOWNLOAD_CLEARED
      √ clears download item
      √ does nothing for a downloadId that does not exist
    APP_DOWNLOAD_REDOWNLOADED
      √ should redownload the same URL
    APP_MERGE_DOWNLOAD_DETAIL
      √ should update downloads
      √ should not update for invalid download Ids
      √ should add new download IDs as needed
    APP_CLEAR_COMPLETED_DOWNLOADS
      √ should clear completed downloads
      √ should not clear downloads when they are still in progress
    APP_DOWNLOAD_DEFAULT_PATH
      when showing folder selection dialog
        √ calls dialog.showOpenDialog
        √ passes the correct defaultPath
        √ passes the correct properties object

  dragDropReducer
    APP_DRAG_STARTED
      √ sets drag data from the action
    APP_DRAG_ENDED
      √ deletes drag data from the action
    APP_DRAG_CANCELLED
      √ deletes drag data from the action
    APP_DRAG_DROPPED
      √ sets the drop window ID
      √ does not overwrite existing dragData
    APP_DRAG_OVER
      √ sets the drag over data
      √ does not overwrite existing dragData

  extensionsReducer
    EXTENSION_UNINSTALLED
      - calls rimraf to remove the folder
      - sets excluded state to true

  historyReducer unit test
    APP_ON_CLEAR_BROWSING_DATA
      √ null case
      √ clearBrowsingDataDefaults is provided
      √ tempClearBrowsingData is provided
      √ both are provided
    APP_ADD_HISTORY_SITE
      √ null case
      √ siteDetail is a list
      √ siteDetail is a map
    APP_REMOVE_HISTORY_SITE
      √ null case
      √ historyKey is a list
      √ historyKey is a map
    APP_POPULATE_HISTORY
      √ is working

  ledgerReducer unit tests
    APP_SET_STATE
      √ calls ledgerApi.migration
      √ calls ledgerApi.init
      √ returns a modified state
    APP_BACKUP_KEYS
      √ calls ledgerApi.backupKeys
      √ returns an ununmodified state
    APP_RECOVER_WALLET
      √ calls ledgerApi.recoverKeys
      √ returns a modified state
    APP_SHUTTING_DOWN
      √ calls ledgerApi.quit
      √ returns a modified state
    APP_ON_CLEAR_BROWSING_DATA
      when clearData.browserHistory is true and payments is disabled
        √ calls ledgerState.resetSynopsis
        √ returns a modified state
      else
        √ does not call ledgerState.resetSynopsis
        √ returns an ununmodified state
    APP_IDLE_STATE_CHANGED
      √ calls ledgerApi.pageDataChanged
      √ calls ledgerApi.addVisit
      √ returns a modified state
    APP_ON_LEDGER_WALLET_CREATE
      √ calls ledgerApi.boot
      √ returns an ununmodified state
    APP_ON_BOOT_STATE_FILE
      √ calls ledgerApi.onBootStateFile
      √ returns a modified state
    APP_ON_LEDGER_BALANCE_RECEIVED
      √ calls ledgerApi.balanceReceived
      √ returns a modified state
    APP_ON_WALLET_PROPERTIES
      √ calls ledgerApi.onWalletProperties
      √ returns a modified state
    APP_LEDGER_PAYMENTS_PRESENT
      √ calls ledgerApi.paymentPresent
      √ returns an ununmodified state
    APP_ON_ADD_FUNDS_CLOSED
      √ calls ledgerApi.addFoundClosed
      √ returns an ununmodified state
    APP_ON_WALLET_RECOVERY
      √ calls ledgerApi.onWalletRecovery
      √ returns a modified state
    APP_ON_BRAVERY_PROPERTIES
      √ calls ledgerApi.onBraveryProperties
      √ returns a modified state
    APP_ON_FIRST_LEDGER_SYNC
      √ calls ledgerApi.onLedgerFirstSync
      √ returns a modified state
    APP_ON_LEDGER_CALLBACK
      √ calls ledgerApi.onCallback
      √ returns a modified state
    APP_ON_TIME_UNTIL_RECONCILE
      √ calls ledgerApi.onTimeUntilReconcile
      √ returns a modified state
    APP_ON_LEDGER_RUN
      √ calls ledgerApi.run
      √ returns an ununmodified state
    APP_ON_NETWORK_CONNECTED
      √ calls ledgerApi.onNetworkConnected
      √ returns a modified state
    APP_ON_RESET_RECOVERY_STATUS
      √ calls ledgerApi.setRecoveryStatus
      √ returns a modified state

  pageDataReducer unit tests
    WINDOW_SET_FOCUSED_FRAME
      √ null case
      √ data is ok
    APP_WINDOW_BLURRED
      √ there is one focused window
      √ there is no focused windows
    APP_IDLE_STATE_CHANGED
      √ null case
      √ idleState is active
      √ idleState is not active
    APP_WINDOW_CLOSED
      √ data is ok
    event-set-page-info
      √ data is ok
    WINDOW_GOT_RESPONSE_DETAILS
      √ null case
      √ add view if we dont have last active tab
      √ add view if tabId is the same as last active tab
      √ dont add view if tabId is different as last active tab
      √ dont add load if response is not successful
      √ dont add load if URL is about page
      √ add load

  pinnedSitesReducer unit test
    APP_TAB_UPDATED
      √ null case
Trying to pin a tabId which does not exist: undefined tabs:  [ { tabId: 1,
    windowId: 1,
    windowUUID: 'uuid',
    url: 'https://brave.com/',
    title: 'Brave' } ]
      √ tab doesnt exist
      √ add pinned site
      √ remove pinned site
    APP_CREATE_TAB_REQUESTED
      √ null case
      √ add pinned site
    APP_ON_PINNED_TAB_REORDER
      √ null case
      √ check if works

  shareReducer
    APP_SIMPLE_SHARE_ACTIVE_TAB_REQUESTED
      √ calls simpleShareActiveTab once with the correct args

  siteSettingsReducer unit tests
    APP_ALLOW_FLASH_ONCE
      √ merges setting into siteSettings if regular tab
      √ merges setting into temporarySiteSettings if private tab
    APP_ALLOW_FLASH_ALWAYS
      √ merges setting into siteSettings if regular tab
      √ merges setting into temporarySiteSettings if private tab
    APP_CHANGE_SITE_SETTING
      √ merges setting into siteSettings
      √ merges setting into temporarySiteSettings if temporary
      with skipSync
        √ sets skipSync when action includes it
        √ does not set skipSync when action does not include it
    APP_REMOVE_SITE_SETTING
      √ merges setting into siteSettings
      √ merges setting into temporarySiteSettings if temporary
      with skipSync
        √ sets skipSync when action includes it
        √ does not set skipSync when action does not include it
    APP_CLEAR_SITE_SETTINGS
      √ removes the site from siteSettings
      √ removes the site from temporarySiteSettings if temporary
      with skipSync
        √ sets skipSync when action includes it
        √ does not set skipSync when action does not include it
    APP_ADD_NOSCRIPT_EXCEPTIONS
      √ adds the `noScriptExceptions` entry to siteSettings
      √ adds the `noScriptExceptions` entry to temporarySiteSettings if temporary

  spellCheckerReducer unit tests
    APP_SPELLING_SUGGESTED
      √ gets the webcontents by tabId
      √ calls webcontents.replaceMisspelling
    APP_LEARN_SPELLING
      √ calls spellChecker.addWord
      √ gets the webcontents by tabId
      √ calls webcontents.replaceMisspelling
    APP_FORGET_LEARNED_SPELLING
      √ calls spellChecker.removeWord
      √ gets the webcontents by tabId
      √ calls webcontents.replace

  tabContentReducer
    WINDOW_SET_TAB_CONTENT_INTERSECTION_STATE
      √ sets the intersection ratio if current tab is the first in the first tabPage
      √ does not set the intersection if current tab is not the first in a tab page

  tabsReducer unit tests
    tabActions.reload
      √ calls `tabs.reload` for `action.tabId`
    tabActions.didFinishNavigation
      √ sets the navigation state to the value of `action.navigationState`
      √ updates the setWebRTCIPHandlingPolicy
    tabActions.didStartNavigation
      √ sets the navigation state to the value of `action.navigationState`
    APP_SET_STATE
      - initializes a tab
    APP_TAB_CREATED
      - creates a tab
    APP_TAB_DETACH_MENU_ITEM_CLICKED
      - Someone clicked the detach menu item
    APP_TAB_MOVED
      - A tab has moved
    APP_CREATE_TAB_REQUESTED
      - creates a new tab
    APP_CREATE_TAB_REQUESTED
      - creates a tab that does not exist yet
      - does not create a tab that already exists
    APP_TAB_UPDATED
      - updates a tab?
    APP_TAB_CLOSED
      √ calls tabState.removeTabByTabId
      √ does nothing if tabId is TAB_ID_NONE
      when updating active tab
        when TAB_CLOSE_ACTION is set to LAST_ACTIVE
          √ chooses the last active tab
        when TAB_CLOSE_ACTION is set to NEXT
          √ chooses the next tab
          √ chooses next unpinned tab
          √ chooses previous unpinned tab
          if no unpinned tabs come after this
            √ considers pinned tabs which come after this
        when TAB_CLOSE_ACTION is set to PARENT
          √ chooses parent tab id (if parent tab was last active)
          √ chooses parent tab id (even if parent tab was NOT last active)
    APP_ALLOW_FLASH_ONCE
      - allows flash once
    APP_ALLOW_FLASH_ALWAYS
      - allows flash always
    APP_TAB_CLONED
      - clones a tab
    APP_TAB_PINNED
      - pins a tab
    WINDOW_SET_AUDIO_MUTED
      - mutes audio
    APP_TAB_ACTIVATED
      - sets the frame as active
    APP_TAB_TOGGLE_DEV_TOOLS
      - toggles dev tools for the tab
    APP_TAB_CLOSE_REQUESTED
      when tabId == TAB_ID_ACTIVE
        √ calls getActiveTabId to get the actual tabId
      when tabId == TAB_ID_NONE
        √ exits without taking action
      with isDevToolsFocused
        when true
          √ closes devtools when opened and focused
        when false
          when more than 1 tab exists
            √ closes tab
          when there are no tabs left
            when pinnedTabs.size > 0
              √ closes tab
    APP_LOAD_URL_REQUESTED
      - loads the specified URL
    APP_LOAD_URL_IN_ACTIVE_TAB_REQUESTED
      - loads the specified URL in the active tab
    APP_FRAME_CHANGED
      - updates frame data
    APP_WINDOW_READY
      when showOnLoad is true
        √ calls tabs.create
        √ sets tabs.create url argument to welcome screen
        √ sets senderWindowId as the windowId when none is found
      when showOnLoad is false
        √ does not call tabs.create
    APP_DRAG_ENDED
      √ calls into tabs.moveTo for tabs
      √ does not call into tabs.moveTo for other drop types

  topSitesReducerTest
    APP_TOP_SITE_DATA_AVAILABLE
      √ sets the data in new tab state

  updatesReducer
    APP_UPDATE_LOG_OPENED
      √ Does not modify state
      √ Opens update log path

  urlBarSuggestionsReducer unit test
    APP_SET_STATE
      √ inits the suggestions lib with sites
    APP_ADD_BOOKMARK
      √ adds a site in the suggestions lib
    APP_REMOVE_BOOKMARK
      √ null case
      √ bookmark key is list (multiple bookmarks)
      √ bookmark key is map (single bookmark)
      √ bookmark key is map and history with the same site exists
      √ bookmark key is list and history with the same site exists
    APP_REMOVE_HISTORY_SITE
      √ null case
      √ history key is list (multiple history sites)
      √ history key is map (single history site)
      √ history key is list and bookmark with the same site exists
      √ history key is map and bookmark with the same site exists
    APP_ADD_HISTORY_SITE
      √ adds a site in the suggestions lib
    APP_EDIT_BOOKMARK
      √ adds a site in the suggestions lib
    APP_URL_BAR_TEXT_CHANGED
      √ regenerates suggestions

  windowsReducer unit test
    APP_WINDOW_CREATED
      √ check if functions are called
    APP_WINDOW_RESIZED
      √ check if functions are called

  windowsReducer unit test
    APP_WINDOW_UPDATED
      √ null case
      √ updateDefault is false (we shouldnt update it)
      √ updateDefault is true

  setting observer unit test
    - observes setting changes and unregisters

  share API
    simpleShareActiveTab
      email
        √ calls openExternal with the correct args
        √ takes active tab windowId into consideration
      other
        √ calls createTabRequested with correct args

  tabMessageBox unit tests
    show
      √ registers a callback
      √ calls appActions.tabMessageBoxShown
    close
      √ calls `tabMessageBoxState.removeDetail` to remove the detail record
      √ unregisters the callback
      when calling the callback
        √ defaults `result` to true and `suppress` to false
        √ reads `result` from detail object
        √ reads `suppress` from detail object
        when detail is falsey
          √ defaults `result` to false and `suppress` to false
    onTabUpdated
      √ calls `tabMessageBoxState.getDetail` to get the detail record
      when tab url matches `opener` in detail object
        √ does NOT call `tabMessageBoxState.removeDetail`
        √ does NOT call the callback
        √ does NOT unregister the callback
      when tab url does not match `opener` in detail object
        √ calls `tabMessageBoxState.removeDetail` to remove the detail record
        √ calls the callback with default params (false, '', false)
        √ unregisters the callback

  tabs API unit tests
    toggleDevTools
      √ opens dev tools if closed
      √ closes dev tools if opened
    isDevToolsFocused
      √ returns false if devtools are opened but not focused
      √ returns false if devtools are not opened
      √ returns true if devtools are opened and focused
    moveTo
      √ moves tab to a new window
      √ moves tab to an existing window
      √ does not move pinned tabs
      √ does not move pinned tabs to alt window
      √ does not move single tab windows into new window
      √ allows combining single tab into alt window
    init
      - todo
    sendToAll
      - todo
    toggleDevTools
      - todo
    setActive
      - todo
    loadURL
      - todo
    loadURLInActiveTab
      - todo
    setAudioMuted
      - todo
    clone
      - todo
    pin
      - todo
    isDevToolsFocused
      - todo
    closeTab
      - todo
    create
      √ calls electron.extensions.createTab (47ms)
    executeScriptInBackground
      - todo
    createTab
      - todo
    maybeCreateTab
      - todo
    goBack
      - todo
    goForward
      - todo
    goToIndex
      - todo
    getHistoryEntries
      - todo

  telemetry
    √ records checkpoints
    √ formats and sends telemetry object correctly
    √ records events correctly

  window API unit tests
    privateMethods
      updatePinnedTabs
        √ takes no action if pinnedSites list matches tab state
        √ calls `appActions.createTabRequested` for pinnedSites not in tab state
        √ calls `appActions.tabCloseRequested` for items in tab state but not in pinnedSites

  bookmarkLocationCache unit test
    generateCache
      √ creates cache based on sites with location
      √ dont generate cache if already exists
    getCacheKey
      √ returns cached siteKeys
      √ returns null when location is not cached
      √ returns null when location is undefined
    addCacheKey
      √ when location is already cached, it appends
      √ when location is new, it creates a list with the key
      √ when location is undefined, it no-ops
      √ when siteKey is undefined, it no-ops
      √ when location is already cached and key already exists
    removeCacheKey
      √ removes cached siteKeys
      √ when removing the last siteKey, removes location
      √ when location is undefined, it no-ops
      √ when siteKey is undefined, it no-ops
      √ when siteKey is not in the cache

  bookmarkOrderCache unit test
    addBookmarkToCache
      √ key is not provided
      √ parentId doesnt exist in the list
      √ destination key is not provided, but parentId exist in the list
      √ dont add cache if key already exist, but destination is not provided
      √ destination key is provided
      √ destination key is provided, item should be prepend
    addFolderToCache
      √ null case
      √ parentId doesnt exist in the list
      √ destination key is not provided, but parentId exist in the list
      √ dont add cache if key already exist, but destination is not provided
      √ destination key is provided
      √ destination key is provided, item should be prepend
    removeCacheKey
      √ key is not provided
      √ cache is empty
      √ cache has only one key
      √ cache has multiple keys
    getFoldersByParentId
      √ parentId is not provided (default is used)
      √ if not found return empty list
      √ parentId is provided
    getBookmarksByParentId
      √ parentId is not provided (default is used)
      √ if not found return empty list
      √ parentId is provided
    getBookmarksWithFolders
      √ parentId is not provided (default is used)
      √ if not found return empty list
      √ parentId is provided
    removeCacheParent
      √ null case
      √ parentId is provided
    getOrderCache
      √ cache doesnt exist
      √ cache exists

  Common menu module unit tests
    quitMenuItem
      √ has the expected defaults set
      when clicked
        √ calls appAction.shuttingDown
    newTabMenuItem
      √ has the expected defaults set
    newPrivateTabMenuItem
      √ has the expected defaults set
    newWindowMenuItem
      √ has the expected defaults set
    reopenLastClosedTabItem
      √ has the expected defaults set
    printMenuItem
      √ has the expected defaults set
    simpleShareActiveTabMenuItem
      √ has the expected defaults set
    findOnPageMenuItem
      √ has the expected defaults set
    checkForUpdateMenuItem
      √ has the expected defaults set
    preferencesMenuItem
      √ has the expected defaults set
    bookmarksManagerMenuItem
      √ has the expected defaults set
    historyMenuItem
      √ has the expected defaults set
    downloadsMenuItem
      √ has the expected defaults set
    passwordsMenuItem
      √ has the expected defaults set
    extensionsMenuItem
      √ has the expected defaults set
    importBrowserDataMenuItem
      √ has the expected defaults set
    exportBookmarksMenuItem
      √ has the expected defaults set
    submitFeedbackMenuItem
      √ has the expected defaults set
    bookmarksToolbarMenuItem
      √ has the expected defaults set
    autoHideMenuBarMenuItem
      √ has the expected defaults set
    aboutBraveMenuItem
      √ has the expected defaults set
    braverySiteMenuItem
      √ has the expected defaults set
    braveryGlobalMenuItem
      √ has the expected defaults set
    braveryPaymentsMenuItem
      √ has the expected defaults set
    reloadPageMenuItem
      √ has the expected defaults set
    cleanReloadMenuItem
      √ has the expected defaults set

  topSites
    topSites
      √ exports an array with top sites
    getSiteOrder
      √ obtains the first site's order
      √ obtains an arbitrary site's order
      √ orders unknown sites as max int

  bookmarkFoldersUtil unit test
    isFolderNameValid
      √ null check
      √ title is an empty string
      √ title is correct
    getNextFolderId
      √ null check
      √ folders list is empty
      √ folder list is ok
    getNextFolderName
      √ null check
      √ name doesnt exist
      √ name already exist
      √ returns non first duplicate name from duplicate name
      √ multiple names exist
    isFolder
      √ null check
      √ type is bookmark
      √ type is bookmark folder
    getKey
      √ null check
      √ returns key if folderId matches
      √ returns null if folderId is missing
    isMoveAllowed
      √ null check
      √ folder cant be its own parent
      √ ancestor folder cant be moved into a descendant
      √ move is allow
    buildFolder
      √ uses all default values
      √ folderId is provided
      √ all values are provided

  bookmarkToolbarUtil unit test
    getToolbarBookmarks
      √ null scenario
      √ we only have bookmark for the toolbar
      √ we have bookmarks for toolbar and other
      √ other limit is set to 100

  bookmarkUtil unit test
    bookmarkHangerHeading
      √ returns default if isFolder and editKey are not provided
      √ if bookmark was newly added
      is bookmark
        √ returns create mode when not in edit mode
        √ returns edit mode when in edit mode
    isBookmarkNameValid
      √ location is not provided
      √ location is null
      √ location is empty string
      √ location is provided
    showOnlyFavicon
      √ BOOKMARKS_TOOLBAR_MODE is FAVICONS_ONLY
      √ BOOKMARKS_TOOLBAR_MODE is not FAVICONS_ONLY
    showFavicon
      √ BOOKMARKS_TOOLBAR_MODE is FAVICONS_ONLY
      √ BOOKMARKS_TOOLBAR_MODE is TEXT_AND_FAVICONS
      √ BOOKMARKS_TOOLBAR_MODE is not TEXT_AND_FAVICONS nor FAVICONS_ONLY
    showOnlyText
      √ BOOKMARKS_TOOLBAR_MODE is TEXT_ONLY
      √ BOOKMARKS_TOOLBAR_MODE is not TEXT_ONLY
    showTextAndFavicon
      √ BOOKMARKS_TOOLBAR_MODE is TEXT_AND_FAVICONS
      √ BOOKMARKS_TOOLBAR_MODE is not TEXT_AND_FAVICONS
    getDNDBookmarkData
      √ dragOverData is missing
      √ draggingOverType is BOOKMARK, but draggingOverKey is missing
      √ draggingOverType is TAB
      √ draggingOverType is BOOKMARK and bookmark is the same
      √ draggingOverType is BOOKMARK and bookmark is different
    getDetailFromFrame
      √ null check
      √ returns an Immutable object with all expected properties
    isLocationBookmarked
      √ null case
      √ cache key is not found
      √ cache key is found
    toCreateProperties
      √ null check
      √ returns a plain javascript object with location and partitionNumber
    isBookmark
      √ null check
      √ type is bookmark
      √ type is bookmark folder
    updateTabBookmarked
      √ null check
      √ tab is updated
    updateActiveTabBookmarked
      √ null check
      √ check if updateTabBookmarked is called
    getKey
      √ returns key if location and partitionNumber match
      √ returns key if location matches and partitionNumber is NOT present
      √ returns null if location is missing
      prevent collision
        √ partition number
        √ parent folder id
    buildBookmark
      √ use only defaults
      √ bookmark data is in history
      √ bookmark data is in active tab
      √ bookmark data is in topSites
    buildEditBookmark
      √ bookmarkDetail is null
      √ old and new are merged, but key is the same
      √ old and new data is merged and new key is generated

  braveryPanelUtil test
    getRedirectedResources
      √ returns empty Immutable list if you dont provide resources
      √ merge all resources into one list

  formatUtil
    formatAccelerator
      when platform is Windows
        √ puts the modifiers in the correct order
        √ leaves modifiers alone if order is correct
      when platform is macOS
        √ replaces the key names with the correct symbols
    toLocaleString
      √ formats the date as a string (126ms)
      √ falls back to provided default value if epoch is falsey
      √ falls back to empty string if no default provided and epoch is falsey
      √ falls back to default value if invalid date is passed
      √ falls back to default value if a non-number is passed
    wrappingClamp
      √ does not change value if within bounds
      √ wraps negatively
      √ wraps positively

  historyUtil
    getHistory
      √ returns the result as an Immutable.List
      √ sorts the items by date/time DESC
      √ only returns `historyUtil.maxEntries` results
    groupEntriesByDay
      √ returns the result as an Immutable.List
      √ has one object for each day
      √ can handle multiple days
      with the object representing a day
        √ formats a readable `date` field
        √ has an entry for each history item
    totalEntries
      √ returns the result as an Immutable.List
      √ combines entries for multiple days into one response

  httpUtil test
    responseHasContent
      expected success codes
        √ returns true for various success responses (200, 203, 206)
        √ returns true for a cached response (304)
      expected failure codes
        √ returns false for non-content success codes (used for REST apis, etc)
        √ returns false for various client error responses (400+)
        √ returns false for various server side error responses (500-504)

  jsonUtil test
    unescapeJSONPointer
      √ Unescapes ~1 and ~0
      √ Can do nothing

  ledger export utilities test
    example transaction data ("exampleLedgerData.js")
      √ there should be example transactions to test with
      √ the first example transaction should have a "ballots" object
      √ the first example transaction's "ballots" object should contain >= 1 publisher / vote-count KV pairs
    transactionsToCSVDataURL
      √ returns a properly formatted data URL string with expected content-type (text/csv)
      √ for empty input, returns a CSV data URL containing only a header row
      √ given transactions, it returns a data URL containing the expected CSV
    getTransactionCSVText
      √ for empty input, returns a CSV string containing only the expected header row
      √ returns a CSV with the expected header row up to variable currency column
      √ returns a CSV with the same number of columns in every row
      √ returns a CSV with expected data types for each column in every row
      √ returns same CSV for an array containing one transaction and a single transaction object
      √ given a transaction, returns a CSV containing the right number of rows: 1 header row, 1 row per publisher, and if addTotalRow===true, 1 row with totals
      √ returns CSV text matching the CSV rows returned by getTransactionCSVRows
      √ when argument addTotalRow===true, there should be a total row with correct totals for each numeric column
      √ returns the same output for a single transaction input as an array of 1 element and a plain transaction object
    getTransactionCSVRows
      √ returns a CSV row array, where the first row is the expected header row up to the currency column (which varies)
      √ returns a CSV row array with the same number of columns in every row
      √ returns a CSV row array with expected data types for each column in every row
      with invalid input
        √ returns an array w/ header if undefined
        √ returns an array w/ header if null
        √ returns an array w/ header if empty
      with `addTotalRow` == false
        √ returns an array w/ correct # of rows
      with `addTotalRow` == true
        √ returns an array w/ correct # of rows (1 header, 1 per publisher, and 1 with totals)
        √ returns a `total row` entry with correct totals for each numeric column
      with `sortByContribution` == false
        √ sort publishers alphabetically (per spec)
      with `sortByContribution` == true
        √ sort publishers by contribution
    getPublisherVoteData
      √ should return a publisher data object with 1 key per publisher
      √ the sum of the "fraction" value across all publisher entries should be 1
      √ the sum of the "votes" value across all publisher entries should be equal to the overall "votes" entry for the transaction object given as input
      each publisher value
        √ should have "votes" (type number, >= 0) defined
        √ should have "fraction" (type number, >= 0) defined
        √ should have "contribution" (type object) defined
        each publisher->contribution entry
          √ should have "satoshis" (type number, >= 0) defined
          √ should have "fiat" (type number, >= 0) defined
          √ should have "currency" (type string) defined
    getTransactionsByViewingIds
      √ given a single viewingId as a string, it returns an array containing just that transaction (if it exists)
      √ given viewingIds as an array, it filters a transactions array for those transactions
    getTotalContribution
      √ returns a total contribution object
      total contribution object
        √ has a key "satoshis" with value of type number (>= 0)
        √ has a key "fiat" associated with an object containing two subkeys, "amount" (number) and "currency" (string)
        √ has a key, fee with value of type number (>= 0)
    addExportFilenamePrefixToTransactions
      √ should return an empty array if not passed any transactions (empty array, null, or undefined input)
      √ should return the same output for a single transaction given as an array or single object
      √ should add a field "exportFilenamePrefix" to each transaction with correct form ("Brave_Payments_${YYYY-MM-DD}")
      √ should add a distinct suffix ("_<n>") to "exportFilenamePrefix" when multiple transactions occur on same day to ensure the field value is unique

  ledgerUtil test
    shouldTrackView
      input validation
        √ returns false if view is falsey
        √ returns false if view.url is falsey
        √ returns false if view.tabId is falsey
        √ returns false if responseList is falsey
        √ returns false if responseList is not an array
        √ returns false if responseList is a 0 length array
      when finding a matching response based on tabId and url
        √ returns false if no match found
        √ returns false if match is found BUT response code is a failure (ex: 404)
        √ returns true when match is found AND response code is a success (ex: 200)
    btcToCurrencyString
      √ defaults to 0 as balance and "USD" as currency symbol
      √ will mark currency with different symbol (if present)
      √ will convert value to USD
      when rounding values
        √ will round 4.97 down to 4.75 (cent values greater than .74)
        √ will round 4.64 down to 4.50 (cent values greater than .49)
        √ will round 4.33 down to 4.25 (cent values greater than .24)
        √ will round 4.08 down to 4.00 (cent values less than .24)
      when ledgerData does not contain exchange information
        √ returns the raw balance formatted as BTC

  menuUtil tests
    getMenuItem
      √ returns the electron MenuItem based on the label
      √ returns null if label is not found
      √ searches the menu recursively based on the label
    setTemplateItemChecked
      √ returns the new template when checked status is updated
      √ returns null when no change is made
    createBookmarkTemplateItems
      √ returns an array of items w/ the bookmark tag
      √ only returns bookmarks that have a location set
      √ returns empty array if no bookmarks present
      √ processes folders
    createRecentlyClosedTemplateItems
      √ returns an array of closedFrames preceded by a separator and "Recently Closed" items
      √ shows the last 10 items in reverse order (top == last closed)
      √ returns hidden heading menu items if lastClosedFrames is null, empty, or undefined
    updateRecentlyClosedMenuItems
      √ inserts new closed frames, with more recent frames appearing first
      √ does not insert duplicate frames
      √ hides closed frames which have been reopened
    sanitizeTemplateItems
      √ removes entries which are falsey
      √ removes duplicate menu separators
      √ allows l10nLabelId instead of label
      √ checks submenus recursively
      √ removes items which are missing label or type
      √ removes items which have non-string values for label or type
      √ always returns an array (even for one item)
      √ does not allow the list to start with a separator
      √ does not allow the list to end with a separator
      √ does not allow only a separator
      √ supports empty arrays

  pageDataUtil unit tests
    getInfoKey
      √ null case
      √ url is converted to location

  pinnedSitesUtil
    getPinnedSiteProps
      √ returns object with necessary fields
      √ set partitionNumber field to 0 in case of missing this field

  platformUtil
    getPlatformStyles
      √ prepends style with platform--
      √ returns the style "win7" for Windows 7
      √ returns the style "win10" for Windows 8
      √ returns the style "win10" for Windows 10
    getPathFromFileURI
      √ return path for window
      √ return path for non window
    isDarwin
      √ returns true if using macOS
      √ returns false if not using macOS
    isWindows
      √ returns true if using Windows
      √ returns false if not using Windows

  publisherUtil test
    shouldShowAddPublisherButton
      √ location is empty
      √ location is about page
      √ location is file
      √ payment is disabled
      √ everything is ok

  siteSuggestions lib
    tokenizeInput
      √ empty string has no tokens
      √ undefined has no tokens
      √ null has no tokens
      √ lowercases tokens
      √ includes protocol
      √ includes query
      √ does not include hash
      √ spaces get tokenized
      √ periods get tokenized
      √ / gets tokenized
      √ \ gets tokenized
      √ can tokenize site objects
      √ non URLs get tokenized
    not initialized query
      √ returns no results if not initialized
    query
      √ can query with empty string (312ms)
      √ can query with null
      √ can query with undefined
      √ returns an empty array when there are no matches
      √ returns matched result on an exact token
      √ returns matched result on a token prefix
      √ returns no results on input that has a token as a prefix
      √ can query on title
      √ can query on multiple tokens in different order
      √ all tokens must match, not just some
    query
      sorts results by location
        √ orders shortest match first
        √ matches prefixes first
        √ closest to the left match wins
        √ matches based on tokens and not exactly
      sorts results by count
        with lastAccessedTime
          √ highest count first
        without last access time
          √ highest count first
      sorts results by lastAccessTime
        with counts
          √ items with lastAccessTime of 1 get ignored (signifies preloaded default)
          √ most recently accessed get sorted first
        without counts
          √ items with lastAccessTime of 1 get ignored (signifies preloaded default)
          √ most recently accessed get sorted first
    add sites after init
      √ can be found
      √ adding twice results in 1 result only with latest results
      √ can add simple strings
      √ can add Immutable objects

  suggestion unit tests
    normalizeLocation
      √ does nothing when input is not a string
      √ normalizes location
    sortingPriority
      √ sorts sites correctly
    isSimpleDomainNameValue
      √ sorts simple sites higher than complex sites
      √ URLs that end in a slash are simple
      √ URLs that end in a hash are simple
    shouldNormalizeLocation
      √ Determines prefixes which should be normalized
      √ Determines prefixes which should NOT be normalized
    createVirtualHistoryItems
      √ handles input being null/undefined
      √ handles entries with unparseable "location" field
      √ shows virtual history item
      √ filters virtual sites to only matching input
    sorting functions
      getSortByPath
        √ returns 0 when both paths contain the string
        √ returns 0 when neihter path contain the string
        √ returns -1 when the first site contains the string only
        √ returns 1 when the second site contains the string only
        √ matches even domain name for input string
        √ sorts shortest path when one is a prefix of another and they have a match
      sortBySimpleURL
        √ returns 0 when both paths are simple
        √ returns 0 when neihter path is simple
        √ returns -1 when the first site is simple only
        √ returns 1 when the second site is simple only
        √ trailing slash is considered simple
        √ trailing hash is considered simple
        √ Prefers https sipmle URLs
        √ sorts better matched domains based on more simple domains
        √ sorts better matched domains based on more simple domains ignoring www.
      getSortByDomainForSites
        √ negative if only first has a matching domain
        √ positive if only second has a matching domain
        √ 0 if both have a matching domain from index 0
        √ 0 if neither has a matching domain
        √ negative if first site has a match from the start of domain
        √ negative if there is a pos 0 match not including www.
        √ simple domain gets matched higher
        √ does not throw error for file:// URL
        √ does not throw error for javascript: bookmarklets
        √ sorts simple domains that match equally on subdomains as the same
        √ sorts simple domains that match equally but have different activity based on activity
      getSortByDomainForHosts
        √ negative if only first has a matching domain
        √ positive if only second has a matching domain
        √ 0 if both have a matching domain from index 0
        √ 0 if neither has a matching domain
        √ negative if first site has a match from the start of domain
        √ negative if there is a pos 0 match not including www.
        √ sorts based on top sites data file order first
        √ user input does not change order
      getSortForSearchSuggestions
        √ 0 if suggestions are not URLs
        √ 0 if suggestions are the same
        √ 0 if user input starts with HTTP
        √ negative if second suggestion is HTTP
        √ positive if first suggestion is HTTP
      getSortForSuggestions
        √ sorts better matched domains based on more simple domains ignoring www.
        √ sorts better matched domains based on more simple with paths ignoring www.
        √ hierarchical input does not select shortest match domain
        √ prefix matches1
        with url entered as path
          √ returns 0 when both urls are the same
          √ matches exact path if more specific path is specified
        with single string entered
          √ matches on domain name first
          √ matches with or without protocol
          √ non-wwww. matches before www.
    getNormalizedSuggestion
      √ suggestion list is empty
      √ active index is not provided
      √ everything is provided

  aboutHistoryState
    getHistory
      √ reads the history from the state
    setHistory
      √ updates the `updatedStamp` value on success

  aboutNewTabState
    getSites
      √ returns the contents of about.newtab.sites
    setSites
      √ updates the `updatedStamp` value on success
      √ does not update state or `updatedStamp` if input is falsey
      √ sets the provided data for top sites
    mergeDetails
      √ updates the `updatedStamp` value on success
      √ does not update state or `updatedStamp` if input is falsey
      √ merges the provided data into about.newtab

  basicAuthState unit tests
    setLoginResponseDetail
      `tabId` exists in appState with loginRequiredDetail
        √ removes the login detail
      `tabId` exists in appState with no loginRequiredDetail
        √ returns the unmodified appState
      `tabId` does not exist in appState
        √ returns the unmodified appState
    setLoginRequiredDetail
      - error for missing required fields
      with null detail
        √ removes the login detail
      with empty detail
        √ removes the login detail
      `tabId` exists in appState
        √ sets the login detail for `tabId` in the appState
      `tabId` does not exist in appState
        √ returns the state
    getLoginRequiredDetail
      `tabId` exists in appState with loginRequiredDetail
        √ returns the login detail for `tabId`
      `tabId` exists in appState with no loginRequiredDetail
        √ returns null
      `tabId` does not exist in appState
        √ returns null

  bookmarkToolbarState unit test
    setToolbars
      √ null case
      √ set data
    setToolbar
      √ null case
      √ set data
    getToolbar
      √ null case
      √ return data
    getOther
      √ null case
      √ return data

  bookmarkState unit test
    updateFavicon
      √ updates the favicon for all matching entries
      √ returns the state unchanged if location is not a URL
      √ throws an error if bookmarks are not an Immutable.Map
      √ returns the state unchanged if key is not found in sites
      √ works even if null/undefined entries are present
      √ returns the object unchanged if the entry does not exist but found in cache
    getBookmarksByParentId
      √ null case
      √ cache is empty
      √ bookmarks are returned

  contextMenuState
    selectedIndex
      √ returns null if selectedIndex is not set
      √ returns null if selectedIndex is only number
      √ returns array of selected index

  extensionState
    browserActionRegistered
      extensionId has been installed
        browser action already exists
          √ should overwrite the existing browserAction
          √ should not change any other extensions
          √ should not change other props in the state
        browser action does not exist
          √ should create the browserAction
          √ should add default values
          √ should not change any other extensions
          √ should not change other props in the state
      extensionId has not been installed
        √ should not update the state
    browserActionUpdated
      extensionId has been installed
        with tabId
          browser action has been registered
            browser action for tab already exists
              √ should update the existing tab browserAction
              √ should not change any properties of the non-tab browserAction
              √ should not change any other extensions
              √ should not change other props in the state
            browser action for tab does not exist
              √ should create the tab browserAction
              √ should not change any properties of the non-tab browserAction
              √ should not change any other extensions
              √ should not change other props in the state
          browser action has not been registered
            √ should not update the state
            √ should not update the state
        browser action already exists
          √ should update the existing browserAction
          √ should not change any other extensions
          √ should not change other props in the state
        browser action does not exist
          √ should not update the state
      extensionId has not been installed
        √ should not update the state
    getEnabledExtensions
      without tab-specific properties
        √ return extensions where enabled === true
    getBrowserActionByTabId
      without tab-specific properties
        √ should return the default browserAction properties
      with tab-specific properties
        √ should merge the tab-specific properties into the default browserAction properties
      no browser action for the extensionId
        √ should return null
    extensionInstalled
      extensionId has been installed
        √ should overwrite the existing extension
        √ should not change any other extensions
        √ should not change other props in the state
      extensionId has not been installed
        √ should add the extension to the state
        √ should not change any other extensions
        √ should not change other props in the state
    extensionEnabled
      extensionId has been installed
        extensionId has not been enabled
          √ should set the enabled property to true
          √ should not alter any other properties
          √ should not change any other extensions
          √ should not change other props in the state
        extensionId is enabled
          √ should not update the state
        extensionId is disabled
          √ should set the enabled property to true
          √ should not alter any other properties
          √ should not change any other extensions
          √ should not change other props in the state
      extensionId has not been installed
        √ should not update the state
        √ should not change any other extensions
        √ should not change other props in the state
    extensionDisabled
      extensionId has been installed
        extensionId has not been enabled
          √ should set the enabled property to false
          √ should not alter any other properties
          √ should not change any other extensions
          √ should not change other props in the state
        extensionId is disabled
          √ should not update the state
        extensionId is enabled
          √ should set the enabled property to false
          √ should not alter any other properties
          √ should not change any other extensions
          √ should not change other props in the state
      extensionId has not been installed
        √ should not update the state
        √ should not change any other extensions
        √ should not change other props in the state
    extensionUninstalled
      extensionId has been uninstalled
        √ should set the excluded property to true
        √ should not alter any other properties
        √ should not change any other extensions
        √ should not change other props in the state

  frameState
    getTabIdByFrameKey
      √ returns the tabId for the frameKey
      √ returns -1 if the tabId is missing
      √ throws an AssertionError if key is not a number
      √ throws an AssertionError if key < 1 and !== -1
    getPathByTabId
      √ returns the path to the frame for `tabId` if it exists
      √ returns null if the frame for `tabId` does not exist
      √ throws an AssertionError if tabId is not a number
      √ throws an AssertionError if tabId < 1 and !== -1

  immutableUtil unit test
    isImmutable
      √ false when Array
      √ falsy when non-array Object
      √ falsy when null
      √ falsy when undewfined
      √ falsy when boolean
      √ truthy when Immutable.Map
      √ truthy when Immutable.List
    isMap
      √ Immutable.Map returns true
      √ Immutable.List returns false
      √ Array returns false
      √ Object returns false
      √ null returns false
      √ undefined returns false
    isList
      √ Immutable.List returns true
      √ Immutable.Map returns false
      √ Array returns false
      √ Object returns false
      √ null returns false
      √ undefined returns false
    isSameHashCode
      √ returns true if both undefined or null
      √ returns true for 2 identical but different Immutable objects
      √ returns false for 2 different Immutable objects
    makeImmutable
      √ converts an Object Map to Immutable.Map
      √ converts an Array Immutable.List
      √ converts an Object Immutable.Map to Immutable.Map
      √ converts an Array Immutable.List
    makeJS
      √ converts an Object an Object
      √ converts an Array to an Array
      √ converts an Immutable.Map Object to an Object
      √ converts an Immutable.List to an Array
      √ converts a string to a string
      √ converts a boolean to a boolean
      √ converts a number to a number
      √ converts undefined to undefined
      √ converts null to null
      √ converts null to null
      √ converts null to default value if a deafult value is specified
      √ converts undefined to default value if a deafult value is specified
      √ converts false to false when a default value is specified
    deleteImmutablePaths
      √ removes properties with simple strings
      √ removes properties with array string paths

  pageDataState unit tests
    addView
      √ null case
      √ url is the same as last one
      √ url is private
      √ url is about page
      √ url is ok
    addInfo
      √ null case
      √ data is ok
    addLoad
      √ null case
      √ data is ok
      √ we only take last 100 views
    getView
      √ null case
      √ data is ok
    getLastInfo
      √ null case
      √ key is provided, but data is not there
      √ key is provided and data is there
    getLoad
      √ null case
      √ data is there
    getLastActiveTabId
      √ null case
      √ data is there
    setLastActiveTabId
      √ id is saved
    setPublisher
      √ null case
      √ data is ok

  audioState unit tests
    canPlayAudio
      √ returns false if frame is null/undefined
      √ returns true if audioPlaybackActive is true
      √ returns true if audioMuted is true
      √ returns true if both provided
    isAudioMuted
      √ returns false if frame is null/undefined
      √ returns true if audioMuted is true
      √ returns false if audioMuted is false
    showAudioIcon
      √ returns false if frame is null/undefined
      √ returns true if tab can play audio and tab is not intercected
      √ returns false if tab can play audio and tab is intercected
      √ returns false if tab can not play audio and tab is not intercected
    showAudioTopBorder
      √ returns false if frame is null/undefined
      √ returns true if tab can play audio and tab is not pinned but is intercected
      √ returns true if tab can play audio and is pinned
      √ returns false if tab can play audio and tab is not pinned and is not intercected
      √ returns false if tab can not play audio, not pinned and tab is intercected

  closeState unit tests
    hasFixedCloseIcon
      √ returns false if frame is null/undefined
      √ returns true if tab is active and is intersected at 75% size
      √ returns false if tab is not active and is intersected at 75% size
      √ returns false if tab is active and is not intersected
      √ returns true if tab is active and intersected below 75% size
    hasRelativeCloseIcon
      √ returns false if frame is null/undefined
      √ returns true if tab index is being hovered
      √ returns false if tab is not being hovered
      √ returns false if tab is being intersected
    showCloseTabIcon
      √ returns false if frame is null/undefined
      √ returns false if tab is being intersected at 15% size
      √ returns false if tab not intersected and not hovered
      √ returns true if tab not intersected and hovered
      √ returns false if tab is intersected and not active
      √ returns true if tab is intersected and active

  faviconState unit tests
    showFavicon
      √ returns false if frame is null/undefined
      √ returns true if tab is only 35% visible and is not active
      √ returns true if tab is not intercected and is not about:newtab
      √ returns false if tab is not intercected and is about:newtab
    getFavicon
      √ returns false if frame is null/undefined
      √ returns false if loading icon is visible
      √ returns the favicon if loading is not visible
    showLoadingIcon
      √ returns false if frame is null/undefined
      √ returns false if source is about page
      √ returns true if source is not about page
      √ returns false if page is not loading
      √ returns false if loading is undefined
      √ returns true if page is loading
    showIconWithLessMargin
      √ returns false if frame is null/undefined
      √ returns true if tab is intersected at 20% size
      √ returns true if tab is intersected at smaller size
      √ returns false if tab is intersected at a larger size
    showFaviconAtReducedSize
      √ returns false if frame is null/undefined
      √ returns true if tab is intersected at 15% size
      √ returns false if tab is intersected at larger size

  partitionState unit tests
    isPartitionTab
      √ returns false if frame is null/undefined
      √ returns true if partition number is defined
      √ returns false if partition number is undefined
    getPartitionNumber
      √ returns zero if frame is null/undefined
      √ returns zero if frame is null/undefined
      √ can remove _partition_ string and keep the partition number
      √ returns the partition number
    getMaxAllowedPartitionNumber
      √ returns false if frame is null/undefined
      √ returns partition number
      √ returns the max allowed partition number if current number is bigger

  privateState unit tests
    isPrivateTab
      √ returns an empty string if frame is null/undefined
      √ returns true if tab is private
      √ returns false if tab is not private

  titleState unit tests
    showTabTitle
      √ returns an empty string if frame is null/undefined
      √ returns false if tab is intersected at 45% size and is active
      √ returns false if tab is intersected at 45% size and is partitioned
      √ returns false if tab is intersected at 45% size and is private
      √ returns true if tab is intersected at 45% size and is about:newtab
      √ returns true if tab is intersected at 45% size and has no secondary icon
      √ returns false if tab is intersected at 35% size
      √ returns true if tab is intersected above 35% size
    getDisplayTitle
      √ returns an empty string if frame is null/undefined
      √ translates about:blank
      √ translates about:newtab
      √ returns the title
      √ returns the location if title is not defined
      √ retuns an empty string if both title and location are not defined

  tabMessageBoxState unit tests
    show
      when a detail object does not exist
        √ creates the detail record (including setting opener)
      when a detail object exists
        √ removes the detail if null
        √ removes the detail if empty
        √ overwrites the existing record
      when data is missing
        √ does nothing when tabId is missing
        √ does nothing when tab value is not found
    hasMessageBoxDetail
      √ returns true if detail exists
      √ returns false if tabId is not found
    getDetail
      √ returns null if tabId is falsey
      √ returns null if tabId is not a number
      √ returns detail object from tab value (if found)
      √ returns null if detail object does not exist in tab value
      √ returns null if tab value is not found
    update
      √ calls show
    removeDetail
      when a detail object exists
        √ removes the detail
      when a detail object does not exist
        √ does nothing (does not crash)
      when data is missing
        √ does nothing when tabId is missing
        √ does nothing when tab value is not found
    getSuppress
      √ when data exists
      √ when tab is missing
      √ when data is missing
    getShowSuppress
      √ when data exists
      √ when tab is missing
      √ when data is missing
    getTitle
      √ when data exists
      √ when tab is missing
      √ when data is missing
    getButtons
      √ when data exists
      √ when tab is missing
      √ when data is missing
    getPropertyByTabId
      √ when everything is correct
      √ when tab is wrong
      √ when property is missing

  tabState unit tests
    getPathByTabId
      √ returns null if tab is not found
      √ returns path if index found (as mutable array)
    getByTabId
      √ returns the tab for `tabId` if it exists
      √ returns null if the tab for `tabId` does not exist
      √ throws an AssertionError if tabId is not a number
      √ throws an AssertionError if tabId < 1 and !== -1 and !== -2
      √ throws an AssertionError if state does not contain a `tabs` array
      √ throws an AssertionError if state is not convertable to an Immutable.Map
    removeTabByTabId
      √ returns a new immutable state with the tab for `tabId` removed if it exists
      √ returns the state unmodified if the tab for `tabId` does not exist
      √ throws an AssertionError if tabId is not a number
      √ throws an AssertionError if tabId < 1 and !== -1 and !== -2
      √ throws an AssertionError if state does not contain a `tabs` array
      √ throws an AssertionError if state is not convertable to an Immutable.Map
    removeTabByIndex
      √ returns a new immutable state with the tab at `index` removed if it exists
      √ returns the state unmodified if `index` is out of bounds
      √ throws an AssertionError if `index` < 0
      √ throws an AssertionError if `index` is not a number
      √ throws an AssertionError if state does not contain a `tabs` array
      √ throws an AssertionError if state is not convertable to an Immutable.Map
    insertTab
      √ returns a new immutable state with the tabValue appended to the end of the list
      √ throws an AssertionError if there is already a tab with the tabId
      √ throws an AssertionError if action does not contain a `tabValue` that is convertable to an Immutable.Map
      √ throws an AssertionError if `action` is not convertable to an Immutable.Map
      √ throws an AssertionError if `tabValue` does not contain a valid `tabId`
      √ throws an AssertionError if state does not contain a `tabs` array
      √ throws an AssertionError if state is not convertable to an Immutable.Map
    updateTab
      √ returns a new immutable state with the tabValue updated if it already exists
      √ returns a new immutable state with the tabValue replaced if it already exists and `replace` is true
      √ does not change other values in the appState
      √ throws an AssertionError if action does not contain a `tabValue` that is convertable to an Immutable.Map
      √ throws an AssertionError if `action` is not convertable to an Immutable.Map
      √ throws an AssertionError if `tabValue` does not contain a valid `tabId`
      √ throws an AssertionError if state does not contain a `tabs` array
      √ throws an AssertionError if state is not convertable to an Immutable.Map
    removeTabField
      √ removes the field specified
      √ returns the state (unchanged) if tabs is falsey
    getPersistentState
      √ removes message box data
    maybeCreateTab
      √ returns a new immutable state with the tabValue appended to the end of the list if it does not already exist
      √ returns a new immutable state with the tabValue updated if it already exists
      √ throws an AssertionError if action does not contain a `tabValue` that is convertable to an Immutable.Map
      √ throws an AssertionError if `action` is not convertable to an Immutable.Map
      √ throws an AssertionError if `tabValue` does not contain a valid `tabId`
      √ throws an AssertionError if state does not contain a `tabs` array
      √ throws an AssertionError if state is not convertable to an Immutable.Map
    getTabsByWindowId
      √ returns the tabs with `windowId`
      √ throws an AssertionError if state does not contain a `tabs` array
      √ throws an AssertionError if state is not convertable to an Immutable.Map
      √ throws an AssertionError if tabId is not a number
      √ throws an AssertionError if tabId < 1 and !== -1 and !== -2
    getTabsForWindow
      √ returns the tabs with matching the `windowId`
      √ throws an AssertionError if `windowValue` does not contain a valid `windowId`
      √ throws an AssertionError if state does not contain a `tabs` array
      √ throws an AssertionError if state is not convertable to an Immutable.Map
    getTabs
      √ throws an AssertionError if state does not contain a `tabs` array
      √ throws an AssertionError if state is not convertable to an Immutable.Map
    setTabs
      √ returns a new immutable state with state.tabs set to the tab list
      √ throws an AssertionError if `tabs` does not contain an Immutable.List of valid tabValue
      √ throws an AssertionError if state does not contain a `tabs` array
      √ throws an AssertionError if state is not convertable to an Immutable.Map
    getTabPropertyByTabId
      √ returns the value for `tabId`.`key`
      √ returns null if `key` does not exist for `tabId`
      √ throws assertion error if `tabId` does not exist
    getOpenerTabId
      √ returns tabId of the opener
      √ defaults to TAB_ID_NONE if not found
      √ returns TAB_ID_NONE if tabId is invalid
    getActiveTabId
      √ obtains active tabId when window is specified
      √ obtains active tabId when no window is specified based on focused window
    resolveTabId
      √ resolves numeric tabs
      √ resolves active tab
    navigationState
      setNavigationState
        √ sets appState.tabs.`tabId`.navigationState to the specified value
        √ does not change other tabs ids
      getVisibleOrigin
        √ returns the value from appState.tabs.`tabId`.navigationState.visibleEntry.origin with trailing slash removed
      getVisibleEntry
        √ returns the value from appState.tabs.`tabId`.navigationState.visibleEntry
      getVisibleURL
        √ returns the value from appState.tabs.`tabId`.navigationState.visibleEntry.url
      getVisibleVirtualURL
        √ returns the value from appState.tabs.`tabId`.navigationState.visibleEntry.virtualURL

  tabUIState unit tests
    getThemeColor
      √ returns an empty string if frame is null/undefined
      √ returns the themeColor when PAINT_TABS is true
      √ returns computedThemeColor when PAINT_TABS is true and themeColor is empty
      √ returns false when PAINT_TABS is false
    getTabIconColor
      √ returns an empty string if frame is null/undefined
      √ returns black if tab background is lighter, has themeColor, paintTabs is enabled and is active but not private
      √ returns black if tab background is darker, has themeColor, paintTabs is enabled and is active but not private
      √ returns white if tab is active and private
      √ returns black if tab is active, not private but has no themeColor
    checkIfTextColor
      √ returns an empty string if frame is null/undefined
      √ returns true if colors match
      √ returns false if colors does not match
    showTabEndIcon
      √ returns false if frame is null/undefined
      √ returns true for regular tabs
      when tab is partitioned
        √ returns false if intersection is above 35% of tab size and has relative close icon
        √ returns false if intersection is above 35% of tab size and has fixed close icon
        √ returns false if intersection is below 35% of tab size
        √ returns true if not hovering and intersection is above 35% of tab size
        √ returns true if not active and intersection is above 35% of tab size
      when tab is private
        √ returns false if intersection is above 35% of tab size and has relative close icon
        √ returns false if intersection is above 35% of tab size and has fixed close icon
        √ returns false if intersection is below 35% of tab size
        √ returns true if not hovering and intersection is above 35% of tab size
        √ returns true if not active and intersection is above 35% of tab size
    addExtraGutterToTitle
      √ returns false if frame is null/undefined
      √ returns true for about:newtab
      √ returns false for other locations
    centralizeTabIcons
      √ returns false if frame is null/undefined
      √ returns false if intersection is above 15% of tab size
      √ returns true if intersection is below or equal 15% of tab size
    getTabEndIconBackgroundColor
      when tab is private
        √ returns `tab.private.background` color if not active
        √ returns `tab.active.private.background` if tab is active
        √ retuns active private color if tab is being hovered
      when tab is not private
        √ returns the themeColor if tab is active
        √ returns `theme.tab.background` if tab is not active
      returns `linear gradient` size
        √ at 10px/40px if tab is partitioned
        √ at 10px/40px gradient size if tab has a visible close icon
        √ at 0/12px gradient size if is neither private, partition or has close icon visible

  updateUtil test
    getUpdateStatus
      √ update is not available
      √ update status is UPDATE_AVAILABLE_DEFERRED
      √ update status is returned normally
    isUpdateVisible
      √ update is not available
      √ status is not available
      √ update is not verbose and status is different then UPDATE_AVAILABLE
      √ update is verbose and status is UPDATE_AVAILABLE
      √ update status is UPDATE_AVAILABLE
      √ update status is UPDATE_NONE
      √ update status is UPDATE_APPLYING_RESTART
      √ update status is UPDATE_APPLYING_NO_RESTART

  urlParse
    √ parsing a URL once gives the same result as node
    √ parsing a URL once gives the same result as node
    √ returns the same result on repeated parsing
    √ returns the correct result when exceeding cache

  filtering unit tests
    applyCookieSetting
      when cookieSetting === "blockAllCookies"
        √ clears cookie field
        when there is a cookie exception
          √ keeps the cookie field
          √ wildcard cookie exception
      when cookieSetting === "block3rdPartyCookie"
        √ sets the referer to the origin
        when there is a referer exception
          √ keeps the referer field

  ContextMenuItem unit test
    getYAxis
      √ target is contextMenuItem and parentNode is contextMenu
      √ target is contextMenuItem and parentNode is second contextMenu
      √ target is second contextMenuItem and parentNode is second contextMenu

  MessageBox component unit tests
    Rendering
      √ renders itself inside a dialog component
      √ renders the suppress checkbox if showSuppress is true
      √ renders the button index 0 as primaryButton
      √ renders the button index 1 as secondaryButton
      √ hides the suppress checkbox if showSuppress is false
    Events
      √ calls appActions.tabMessageBoxUpdated when SwitchControl is toggled
      √ calls appActions.tabMessageBoxDismissed with result=true when OK is clicked
      √ calls appActions.tabMessageBoxDismissed with result=false when cancel is clicked

  downloadsBar component
    multiple downloads with space
      √ renders each download as a DownloadItem
      √ renders more recent items first
      √ hide downloads button is shown
    no downloads
      √ renders no DownloadItems when there are no downloads
      √ hide downloads button is shown
    very narrow downloads bar with items
      √ renders no downloads
      √ but still shows hide downloads button

  downloadItem component
    pending download local item
      √ filename exists and matches download filename
      √ has local origin i.e file: and matches to "Local file" origin
    pending download item
      √ filename exists and matches download filename
      √ origin exists and matches download origin
      √ progress bar should not exist
      √ [data-test-id="pauseButton"] is not shown
      √ [data-test-id="resumeButton"] is not shown
      √ [data-test-id="cancelButton"] is not shown
      √ [data-test-id="redownloadButton"] is not shown
      √ [data-test-id="copyLinkButton"] button in state pending performs the correct action
      √ [data-test-id="revealButton"] is not shown
      √ [data-test-id="deleteButton"] is not shown
    in-progress download local item
      √ filename exists and matches download filename
      √ has local origin i.e file: and matches to "Local file" origin
    in-progress download item
      √ filename exists and matches download filename
      √ origin exists and matches download origin
      √ progress bar should exist
      √ [data-test-id="pauseButton"] button in state in-progress performs the correct action
      √ [data-test-id="resumeButton"] is not shown
      √ [data-test-id="cancelButton"] button in state in-progress performs the correct action
      √ [data-test-id="redownloadButton"] is not shown
      √ [data-test-id="copyLinkButton"] button in state in-progress performs the correct action
      √ [data-test-id="revealButton"] button in state in-progress performs the correct action
      √ [data-test-id="deleteButton"] is not shown
    resuming download local item
      √ filename exists and matches download filename
      √ has local origin i.e file: and matches to "Local file" origin
    resuming download item
      √ filename exists and matches download filename
      √ origin exists and matches download origin
      √ progress bar should not exist
      √ [data-test-id="pauseButton"] is not shown
      √ [data-test-id="resumeButton"] is not shown
      √ [data-test-id="cancelButton"] is not shown
      √ [data-test-id="redownloadButton"] is not shown
      √ [data-test-id="copyLinkButton"] button in state resuming performs the correct action
      √ [data-test-id="revealButton"] is not shown
      √ [data-test-id="deleteButton"] is not shown
    paused download local item
      √ filename exists and matches download filename
      √ has local origin i.e file: and matches to "Local file" origin
    paused download item
      √ filename exists and matches download filename
      √ origin exists and matches download origin
      √ progress bar should exist
      √ [data-test-id="pauseButton"] is not shown
      √ [data-test-id="resumeButton"] button in state paused performs the correct action
      √ [data-test-id="cancelButton"] button in state paused performs the correct action
      √ [data-test-id="redownloadButton"] is not shown
      √ [data-test-id="copyLinkButton"] button in state paused performs the correct action
      √ [data-test-id="revealButton"] button in state paused performs the correct action
      √ [data-test-id="deleteButton"] is not shown
    completed download local item
      √ filename exists and matches download filename
      √ has local origin i.e file: and matches to "Local file" origin
    completed download item
      √ filename exists and matches download filename
      √ origin exists and matches download origin
      √ progress bar should not exist
      √ [data-test-id="pauseButton"] is not shown
      √ [data-test-id="resumeButton"] is not shown
      √ [data-test-id="cancelButton"] is not shown
      √ [data-test-id="redownloadButton"] button in state completed performs the correct action
      √ [data-test-id="copyLinkButton"] button in state completed performs the correct action
      √ [data-test-id="revealButton"] button in state completed performs the correct action
      √ [data-test-id="deleteButton"] button in state completed performs the correct action
    completed download item when delete button has been clicked
(node:14268) MaxListenersExceededWarning: Possible EventEmitter memory leak detected. 11 app-state-change listeners added. Use emitter.setMaxListeners() to increase limit
(node:14268) MaxListenersExceededWarning: Possible EventEmitter memory leak detected. 11 change listeners added. Use emitter.setMaxListeners() to increase limit
      √ [data-test-id="confirmDeleteButton"] button in state completed performs the correct action
    cancelled download local item
      √ filename exists and matches download filename
      √ has local origin i.e file: and matches to "Local file" origin
    cancelled download item
      √ filename exists and matches download filename
      √ origin exists and matches download origin
      √ progress bar should not exist
      √ [data-test-id="pauseButton"] is not shown
      √ [data-test-id="resumeButton"] is not shown
      √ [data-test-id="cancelButton"] is not shown
      √ [data-test-id="redownloadButton"] button in state cancelled performs the correct action
      √ [data-test-id="copyLinkButton"] button in state cancelled performs the correct action
      √ [data-test-id="revealButton"] is not shown
      √ [data-test-id="deleteButton"] button in state cancelled performs the correct action
    cancelled download item when delete button has been clicked
      √ [data-test-id="confirmDeleteButton"] button in state cancelled performs the correct action
    interrupted download local item
      √ filename exists and matches download filename
      √ has local origin i.e file: and matches to "Local file" origin
    interrupted download item
      √ filename exists and matches download filename
      √ origin exists and matches download origin
      √ progress bar should not exist
      √ [data-test-id="pauseButton"] is not shown
      √ [data-test-id="resumeButton"] is not shown
      √ [data-test-id="cancelButton"] is not shown
      √ [data-test-id="redownloadButton"] button in state interrupted performs the correct action
      √ [data-test-id="copyLinkButton"] button in state interrupted performs the correct action
      √ [data-test-id="revealButton"] is not shown
      √ [data-test-id="deleteButton"] button in state interrupted performs the correct action
    interrupted download item when delete button has been clicked
      √ [data-test-id="confirmDeleteButton"] button in state interrupted performs the correct action

  Frame component unit tests
    handleShortcut
      - calls zoomIn when set to "zoom-in"
      - calls zoomOut when set to "zoom-out"
      - calls zoomReset when set to "zoom-reset"
      - calls windowActions.setFindbarShown when set to "show-findbar"
      - calls onFindAgain with true when set to "find-next"
      - calls onFindAgain with false when set to "find-prev"
      - calls windowActions.frameShortcutChanged when truthy
      - does not call windowActions.frameShortcutChanged if falsey

  NavigationBar component
    publisherToggle
      √ do not render if about page
      √ do not render if publisher is permanently hidden
      √ render if ok

  Navigator component unit tests
    when user has history going forwards and backwards
      √ both back/forward navigationButtonContainers are enabled
      √ back navigation button is enabled
      √ forward navigation button is enabled
    when active tab is showing a message box
      √ disables both back/forward navigationButtonContainers
      √ disables the back navigation button
      √ disables the forward navigation button
      √ disables the lion icon
    lion badge
      √ lion icon is shown by default
      √ counter is shown by default
(node:14268) MaxListenersExceededWarning: Possible EventEmitter memory leak detected. 11 app-state-change listeners added. Use emitter.setMaxListeners() to increase limit
(node:14268) MaxListenersExceededWarning: Possible EventEmitter memory leak detected. 11 change listeners added. Use emitter.setMaxListeners() to increase limit
      √ counter is not shown when disabled via settings

  PublisherToggle component
    default behaviour (when autoSuggest is ON)
      √ Show as disabled if publisher is on exclusion list
      √ Show as verified if publisher is shown as verified on ledger locations list
    user interaction behaviour
      √ show as enabled if ledgerPayments is true for that publisher
      √ Show as disabled if ledgerPayments is false for that publisher

  UrlBarIcon component unit tests
    general things
      √ sets element as draggable
      √ shows site information when clicked
    when user is searching
      √ does not show site information when clicked
    when active tab is showing a message box
      √ does not set element as draggable
      √ does not respond to clicks

  UrlBarSuggestionItem component
    tabSuggestion suggestion item
      √ renders a list item
      √ renders the suggestion title
      √ renders a suggestion URL
      √ detects mouse click
      √ detects mouse over
    bookmarkSuggestion suggestion item
      √ renders a list item
      √ renders the suggestion title
      √ renders a suggestion URL
      √ detects mouse click
      √ detects mouse over
    historySuggestion suggestion item
      √ renders a list item
      √ renders the suggestion title
      √ renders a suggestion URL
      √ detects mouse click
      √ detects mouse over
    aboutPagesSuggestion suggestion item
      √ renders a list item
      √ renders the suggestion title
      √ renders a suggestion URL
      √ detects mouse click
      √ detects mouse over
    searchSuggestion suggestion item
      √ renders a list item
      √ renders the suggestion title
      √ renders a suggestion URL
      √ detects mouse click
      √ detects mouse over
    topSiteSuggestion suggestion item
      √ renders a list item
      √ renders the suggestion title
      √ renders a suggestion URL
      √ detects mouse click
      √ detects mouse over

  AdvancedTab component
    AdvancedTab
      previewReleases
        on macOS
          √ is shown
        on Linux
          √ is hidden

  ExtensionsTab component
    extensionsTab
      password managers extensions
        onepassword
          √ shows on UI by default
          - can be excluded
          √ can be enabled
          √ can be disabled
        lastpass
          √ shows on UI by default
          - can be excluded
          √ can be enabled
          √ can be disabled
        dashlane
          √ shows on UI by default
          - can be excluded
          √ can be enabled
          √ can be disabled
        bitwarden
          √ shows on UI by default
          √ can be enabled
          √ can be disabled
      common extensions
        brave
          √ do not show Brave extension
        pdfjs
          √ shows on UI by default
          - does not show if excluded
          √ can be enabled
          √ can be disabled
        pocket
          √ shows on UI by default
          - does not show if excluded
          √ can be enabled
          √ can be disabled
        torrent
          √ shows on UI by default
          - can not be excluded
          √ can be enabled
          √ can be disabled
        sync
          √ do not show sync extension

  LedgerTable component
    √ only non pinned tabs
    √ two pinned tabs, 1 unpinned tab (show all button is not necessary
    √ two pinned tabs, no un pinned (there shouldn't be any show all button
    √ pinned tabs should have exclude disabled
    √ two pinned tabs (1 banned), 3 unpinned (1 banned)
    √ 8 pinned tabs, 12 unpinned (show all button, 2 hidden unpinned) (94ms)

  PaymentsTab component
    wallet enabled and disabled state
      √ renders disabled content by default
      √ renders enabled content when enabled
    rendering functions
      √ renders a paymentsContainer
      √ does not render any dialogs by default
      √ renders the create wallet button by default
      √ renders the add funds button when wallet is created
      √ renders the creating wallet button when wallet is still being created
      √ renders payment history button (requires wallet and reconcileStamp)
      √ does not render payment history button when wallet is not created
      √ does not render payment history button when reconcileStamp is not set
    fundsamount functionality
      √ does not display if wallet not created
      √ handles expected balance
      √ renders full balance correctly
      √ renders partial balance correctly
    advanced ledger settings content
      √ defaults to an 8 second minimum visit duration (47ms)
      √ defaults to 1 minimum publisher visit

  TabsTab component
    rendering
      √ component should render
    number of tabs per tab set
      √ can switch to 6 tabs
      √ can switch to 8 tabs
      √ can switch to 10 tabs
      √ defaults to 20 tabs
      √ can switch to 100 tabs
      √ can not switch to other values
    when closing an active tab
      √ can select its parent tab
      √ can select the last viewed tab
      √ can select the next tab
      √ can not select other value
    tab preview functionality
      √ can show tab previews on hover
      √ show all 3 tab preview timing options if tab preview is on
      √ does not show tab preview timing options if tab preview is off
      √ can switch tab previews time to activate previews to LONG
      √ can switch tab previews time to activate previews to NORMAL
      √ can switch tab previews time to activate previews to SHORT
      √ can not switch to other values
    basic functionality
      √ can switch to new tabs immediately
      √ can show tabs in page theme color
      √ dashboard can show images

  Tabs content - AudioTabIcon
    should show icon
      √ volumeOn if page has audio enabled
      √ volumeOff if page has audio muted
    should not show icon
      √ if page has audio disabled
      √ if tab is intersected

  Tabs content - CloseTabIcon
    should show icon
      √ if not intersected and tab is hovered
      √ if intersection is at less than 75% size and tab is active
    should not show icon
      √ if tab is intersected at 15% size or less
      √ if not intersected and tab is not hovered
      √ if intersection is at less than 75% size and tab is not active

  Tabs content - Favicon
    loading icon
      √ shows when tab is loading
      √ does not show when tab is not loading
    default icon
      √ shows when tab has no icon
      √ does not show when tab has an icon
    favicon
      √ shows if page has a favicon
      √ does not show if page is loading
      √ does not show if page has no favicon

  Tabs content - NewSessionIcon
    should show icon
      √ if tab is not hovered
      √ if tab is not active and size is small
    should not show icon
      √ if tab is not partitioned
      √ if tab is being hovered
      √ if for active tab if size is small
      √ if tab is being intersected at 35% or less
      √ if partitionNumber is zero

  Tabs content - PrivateIcon
    should show icon
      √ if tab is not hovered
      √ if tab is not active and size is small
    should not show icon
      √ if tab is not private
      √ if tab is being hovered
      √ if for active tab if size is small
      √ if tab is being intersected at 35% or less

  Tabs content - TabTitle
    should show icon
      √ if is not intersected at 35% of tab size
      √ if not active and intersected at 45% of tab size with no private icon visible
      √ if not active and intersected at 45% of tab size with no partition icon visible
      √ if is intersected at 45% of tab size and is about:newtab
      √ if is intersected at 45% of tab size and is not active
    should not show icon
      √ if is intersected at 35% of tab size
      √ if active and intersected at 45% of tab size
      √ if not active and intersected at 45% of tab size with partition icon visible
      √ if not active and intersected at 45% of tab size with private icon visible

  currentWindow unit test
    isMaximized
      √ null case
      √ false case
      √ true case
    isFullScreen
      √ null case
      √ false case
      √ true case
    isFocused
      √ null case
      √ not provided
      √ false case
      √ true case

  tabUtil
    hasTabAsRelatedTarget
      √ null case
      √ dataset is not provided
      √ returns true if dataset is tab
      √ returns true if dataset is tabArea
      √ returns false if dataset is neither tab nor tabArea

  contextMenuReducer
    WINDOW_ON_TAB_PAGE_CONTEXT_MENU
      √ index is outside the scope
      √ index is correct

  frameReducer
    WINDOW_SET_NAVIGATED
      In page navigation
        √ sets the location for the specified `key`
        √ does not reset values
      Navigation
        √ sets the location for the specified `key`
        √ resets values for the active frame key
        √ does not reset values for other frames
    WINDOW_TAB_MOVE
      Can move last tab to first position
        √ calls appActions.tabIndexChangeRequested with the correct args
        √ does not change window state
      Can move last tab to the middle
        √ calls appActions.tabIndexChangeRequested with the correct args
        √ does not change window state
      Can move tabs to the end
        √ calls appActions.tabIndexChangeRequested with the correct args
        √ does not change window state
      Can move tabs to the middle from the left
        √ calls appActions.tabIndexChangeRequested with the correct args
        √ does not change window state
      Can move middle tab left
        √ calls appActions.tabIndexChangeRequested with the correct args
        √ does not change window state
      Can move middle tab right
        √ calls appActions.tabIndexChangeRequested with the correct args
        √ does not change window state
    APP_TAB_UPDATED
      when index changes
        √ re-orders frame index when index changes
        √ new frame has not showed up in frames
      when pinned status changes
        - (todo)
      when URL changes
        - (todo)
      when title changes
        - (todo)
      when active state changes
        - (todo)

  urlBarReducer
    APP_URL_BAR_TEXT_CHANGED
      √ Changes urlbar state for active frame key
      √ Does not change url bar state of non active frame key
    tabActions.didFinishNavigation
      √ sets the urlbar location to the navigationEntry visible entry virtualURL
      √ turns off suggestions
    suggestions
      WINDOW_SET_FINDBAR_SHOWN
        √ turns off suggestions
      WINDOW_PREVIOUS_URL_BAR_SUGGESTION_SELECTED
        √ turns off suggestions
      WINDOW_NEXT_URL_BAR_SUGGESTION_SELECTED
        √ turns off suggestions
      WINDOW_URL_BAR_AUTOCOMPLETE_ENABLED
        √ state is toggled
      APP_URL_BAR_SUGGESTIONS_CHANGED
        √ suggestion results can be updated
        when autocompleteEnabled
          √ handles a null urlbar location
          √ handles a suggestion that is not immutable
          √ handles a suggestion without location
      WINDOW_SET_URL_BAR_ACTIVE
        √ active state can be toggled
      WINDOW_SET_RENDER_URL_BAR_SUGGESTIONS
        √ turns off suggestions for not enabled
        √ turns on suggestions for enabled
      WINDOW_ACTIVE_URL_BAR_SUGGESTION_CLICKED
        √ callback is not called sync
        √ sets the urlbar to disabled

  sessionStoreShutdown unit tests
    windows all closed
      √ does not quit on macOS
      √ quits on Windows
      √ quits on linux
    undo close window
      √ works for first closed window
      √ works for subsequent windows
Action called before state was initialized: app-new-window
Action called before state was initialized: app-new-window
    app before-quit event
      with no windows
Action called before state was initialized: app-new-window
Action called before state was initialized: app-new-window
        √ saves when no windows
        √ remembers last closed window with no windows (Win32)
        √ remembers last closed window with no windows (Linux)
        √ remembers last closed window with no windows (macOS)
      with one window
        √ saves when all windows responds without the clock moving forward
        √ times out and saves app state anyway
      with multiple windows
        √ saves when all windows responds without the clock moving forward
        √ times out and saves app state anyway
        √ saves when only one of multiple windows respond and timeout happens
    startSessionSaveInterval
      √ does not call initiateSessionStateSave

  sessionStore unit tests
    saveAppState
      √ calls cleanAppData
      with isShutdown
        √ calls cleanSessionDataOnShutdown if true
        √ does not call cleanSessionDataOnShutdown if false
        √ sets cleanedOnShutdown for saveAppState
        √ sets lastAppVersion for saveAppState
    cleanPerWindowData
      √ clears pinned frames
    cleanAppData
      √ clears notifications from the last session
      √ deletes temp site settings
      when CHECK_DEFAULT_ON_STARTUP is true
        √ clears defaultBrowserCheckComplete
      with recovery status
        √ deletes status if present
        √ does not throw an exception if not present
      if perWindowState is present
        √ calls cleanPerWindowData for each item
      when clearAutocompleteData is true
        √ calls autofill.clearAutocompleteData
        exception is thrown
cleanAppData: error calling autofill.clearAutocompleteData:  { lame error
    at Object.throwsException (E:\srirambv\master\browser-laptop\node_modules\sinon\lib\sinon\behavior.js:38:30)
    at Function.throws (E:\srirambv\master\browser-laptop\node_modules\sinon\lib\sinon\stub.js:153:54)
    at Context.<anonymous> (E:/srirambv/master/browser-laptop/test/unit/app/sessionStoreTest.js:258:89)
    at callFn (E:\srirambv\master\browser-laptop\node_modules\mocha\lib\runnable.js:326:21)
    at Hook.Runnable.run (E:\srirambv\master\browser-laptop\node_modules\mocha\lib\runnable.js:319:7)
    at next (E:\srirambv\master\browser-laptop\node_modules\mocha\lib\runner.js:298:10)
    at Immediate.<anonymous> (E:\srirambv\master\browser-laptop\node_modules\mocha\lib\runner.js:320:5)
    at runCallback (timers.js:672:20)
    at tryOnImmediate (timers.js:645:5)
    at processImmediate [as _immediateCallback] (timers.js:617:5) name: 'lame error' }
          √ swallows exception
      when clearAutofillData is true
        happy path
          √ calls autofill.clearAutofillData
          √ sets the guid for addresses to []
          √ sets the timestamp for addresses to now
          √ sets the guid for creditCards to []
          √ sets the timestamp for creditCards to now
        malformed input
          √ does not throw an exception
      when clearSiteSettings is true
        √ clears siteSettings
      with siteSettings
        √ deletes Flash approval if expired
        √ leaves Flash approval alone if not expired
        √ deletes NoScript approval if set
        √ deletes NoScript exceptions
        √ deletes runInsecureContent
        √ deletes entry if empty
      when sites and clearHistory are truthy
        √ deletes temporary entries used in about:history
        √ deletes top site entries used in about:newtab
      when downloads is truthy
        when clearDownloads is true
          √ deletes downloads
        when clearDownloads is falsey
          √ deletes entries which are more than a week old
          √ leaves entries which are less than a week old
          with download state
            √ sets IN_PROGRESS to INTERRUPTED
            √ sets PAUSED to INTERRUPTED
            √ leaves other states alone
      with tabState
        √ calls getPersistentState
cleanAppData: error calling tabState.getPersistentState:  { oh noes
    at Object.throwsException (E:\srirambv\master\browser-laptop\node_modules\sinon\lib\sinon\behavior.js:38:30)
    at Function.throws (E:\srirambv\master\browser-laptop\node_modules\sinon\lib\sinon\stub.js:153:54)
    at Context.<anonymous> (E:/srirambv/master/browser-laptop/test/unit/app/sessionStoreTest.js:506:86)
    at callFn (E:\srirambv\master\browser-laptop\node_modules\mocha\lib\runnable.js:326:21)
    at Test.Runnable.run (E:\srirambv\master\browser-laptop\node_modules\mocha\lib\runnable.js:319:7)
    at Runner.runTest (E:\srirambv\master\browser-laptop\node_modules\mocha\lib\runner.js:422:10)
    at E:\srirambv\master\browser-laptop\node_modules\mocha\lib\runner.js:528:12
    at next (E:\srirambv\master\browser-laptop\node_modules\mocha\lib\runner.js:342:14)
    at E:\srirambv\master\browser-laptop\node_modules\mocha\lib\runner.js:352:7
    at next (E:\srirambv\master\browser-laptop\node_modules\mocha\lib\runner.js:284:14)
    at Immediate.<anonymous> (E:\srirambv\master\browser-laptop\node_modules\mocha\lib\runner.js:320:5)
    at runCallback (timers.js:672:20)
    at tryOnImmediate (timers.js:645:5)
    at processImmediate [as _immediateCallback] (timers.js:617:5) name: 'oh noes' }
        √ deletes tabState if an exception is thrown
      with windowState
        √ calls getPersistentState
cleanAppData: error calling windowState.getPersistentState:  { oh noes
    at Object.throwsException (E:\srirambv\master\browser-laptop\node_modules\sinon\lib\sinon\behavior.js:38:30)
    at Function.throws (E:\srirambv\master\browser-laptop\node_modules\sinon\lib\sinon\stub.js:153:54)
    at Context.<anonymous> (E:/srirambv/master/browser-laptop/test/unit/app/sessionStoreTest.js:524:89)
    at callFn (E:\srirambv\master\browser-laptop\node_modules\mocha\lib\runnable.js:326:21)
    at Test.Runnable.run (E:\srirambv\master\browser-laptop\node_modules\mocha\lib\runnable.js:319:7)
    at Runner.runTest (E:\srirambv\master\browser-laptop\node_modules\mocha\lib\runner.js:422:10)
    at E:\srirambv\master\browser-laptop\node_modules\mocha\lib\runner.js:528:12
    at next (E:\srirambv\master\browser-laptop\node_modules\mocha\lib\runner.js:342:14)
    at E:\srirambv\master\browser-laptop\node_modules\mocha\lib\runner.js:352:7
    at next (E:\srirambv\master\browser-laptop\node_modules\mocha\lib\runner.js:284:14)
    at Immediate.<anonymous> (E:\srirambv\master\browser-laptop\node_modules\mocha\lib\runner.js:320:5)
    at runCallback (timers.js:672:20)
    at tryOnImmediate (timers.js:645:5)
    at processImmediate [as _immediateCallback] (timers.js:617:5) name: 'oh noes' }
        √ deletes windowState if an exception is thrown
    loadAppState
      √ calls runPreMigrations
      √ calls defaultAppState
      √ calls runPostMigrations
      √ calls runImportDefaultSettings
      √ calls locale.init
      when reading the session file
        happy path
          √ calls fs.readFileSync
        when exception is thrown
          √ does not crash when exception thrown during read
      when calling JSON.parse
        exception is thrown
could not parse data:  this is not valid JSON SyntaxError: Unexpected token h in JSON at position 1
    at JSON.parse (<anonymous>)
    at Promise (E:/srirambv/master/browser-laptop/app/sessionStore.js:826:19)
    at Object.module.exports.loadAppState (E:/srirambv/master/browser-laptop/app/sessionStore.js:815:10)
    at Context.<anonymous> (E:/srirambv/master/browser-laptop/test/unit/app/sessionStoreTest.js:625:31)
    at callFn (E:\srirambv\master\browser-laptop\node_modules\mocha\lib\runnable.js:326:21)
    at Test.Runnable.run (E:\srirambv\master\browser-laptop\node_modules\mocha\lib\runnable.js:319:7)
    at Runner.runTest (E:\srirambv\master\browser-laptop\node_modules\mocha\lib\runner.js:422:10)
    at E:\srirambv\master\browser-laptop\node_modules\mocha\lib\runner.js:528:12
    at next (E:\srirambv\master\browser-laptop\node_modules\mocha\lib\runner.js:342:14)
    at E:\srirambv\master\browser-laptop\node_modules\mocha\lib\runner.js:352:7
    at next (E:\srirambv\master\browser-laptop\node_modules\mocha\lib\runner.js:284:14)
    at Immediate.<anonymous> (E:\srirambv\master\browser-laptop\node_modules\mocha\lib\runner.js:320:5)
    at runCallback (timers.js:672:20)
    at tryOnImmediate (timers.js:645:5)
    at processImmediate [as _immediateCallback] (timers.js:617:5)
          √ does not call runPreMigrations
could not parse data:  this is not valid JSON SyntaxError: Unexpected token h in JSON at position 1
    at JSON.parse (<anonymous>)
    at Promise (E:/srirambv/master/browser-laptop/app/sessionStore.js:826:19)
    at Object.module.exports.loadAppState (E:/srirambv/master/browser-laptop/app/sessionStore.js:815:10)
    at Context.<anonymous> (E:/srirambv/master/browser-laptop/test/unit/app/sessionStoreTest.js:635:31)
    at callFn (E:\srirambv\master\browser-laptop\node_modules\mocha\lib\runnable.js:326:21)
    at Test.Runnable.run (E:\srirambv\master\browser-laptop\node_modules\mocha\lib\runnable.js:319:7)
    at Runner.runTest (E:\srirambv\master\browser-laptop\node_modules\mocha\lib\runner.js:422:10)
    at E:\srirambv\master\browser-laptop\node_modules\mocha\lib\runner.js:528:12
    at next (E:\srirambv\master\browser-laptop\node_modules\mocha\lib\runner.js:342:14)
    at E:\srirambv\master\browser-laptop\node_modules\mocha\lib\runner.js:352:7
    at next (E:\srirambv\master\browser-laptop\node_modules\mocha\lib\runner.js:284:14)
    at Immediate.<anonymous> (E:\srirambv\master\browser-laptop\node_modules\mocha\lib\runner.js:320:5)
    at runCallback (timers.js:672:20)
    at tryOnImmediate (timers.js:645:5)
    at processImmediate [as _immediateCallback] (timers.js:617:5)
          √ does not call cleanAppData
could not parse data:  this is not valid JSON SyntaxError: Unexpected token h in JSON at position 1
    at JSON.parse (<anonymous>)
    at Promise (E:/srirambv/master/browser-laptop/app/sessionStore.js:826:19)
    at Object.module.exports.loadAppState (E:/srirambv/master/browser-laptop/app/sessionStore.js:815:10)
    at Context.<anonymous> (E:/srirambv/master/browser-laptop/test/unit/app/sessionStoreTest.js:645:31)
    at callFn (E:\srirambv\master\browser-laptop\node_modules\mocha\lib\runnable.js:326:21)
    at Test.Runnable.run (E:\srirambv\master\browser-laptop\node_modules\mocha\lib\runnable.js:319:7)
    at Runner.runTest (E:\srirambv\master\browser-laptop\node_modules\mocha\lib\runner.js:422:10)
    at E:\srirambv\master\browser-laptop\node_modules\mocha\lib\runner.js:528:12
    at next (E:\srirambv\master\browser-laptop\node_modules\mocha\lib\runner.js:342:14)
    at E:\srirambv\master\browser-laptop\node_modules\mocha\lib\runner.js:352:7
    at next (E:\srirambv\master\browser-laptop\node_modules\mocha\lib\runner.js:284:14)
    at Immediate.<anonymous> (E:\srirambv\master\browser-laptop\node_modules\mocha\lib\runner.js:320:5)
    at runCallback (timers.js:672:20)
    at tryOnImmediate (timers.js:645:5)
    at processImmediate [as _immediateCallback] (timers.js:617:5)
          √ calls defaultAppState to get a default app state
could not parse data:  this is not valid JSON SyntaxError: Unexpected token h in JSON at position 1
    at JSON.parse (<anonymous>)
    at Promise (E:/srirambv/master/browser-laptop/app/sessionStore.js:826:19)
    at Object.module.exports.loadAppState (E:/srirambv/master/browser-laptop/app/sessionStore.js:815:10)
    at Context.<anonymous> (E:/srirambv/master/browser-laptop/test/unit/app/sessionStoreTest.js:655:31)
    at callFn (E:\srirambv\master\browser-laptop\node_modules\mocha\lib\runnable.js:326:21)
    at Test.Runnable.run (E:\srirambv\master\browser-laptop\node_modules\mocha\lib\runnable.js:319:7)
    at Runner.runTest (E:\srirambv\master\browser-laptop\node_modules\mocha\lib\runner.js:422:10)
    at E:\srirambv\master\browser-laptop\node_modules\mocha\lib\runner.js:528:12
    at next (E:\srirambv\master\browser-laptop\node_modules\mocha\lib\runner.js:342:14)
    at E:\srirambv\master\browser-laptop\node_modules\mocha\lib\runner.js:352:7
    at next (E:\srirambv\master\browser-laptop\node_modules\mocha\lib\runner.js:284:14)
    at Immediate.<anonymous> (E:\srirambv\master\browser-laptop\node_modules\mocha\lib\runner.js:320:5)
    at runCallback (timers.js:672:20)
    at tryOnImmediate (timers.js:645:5)
    at processImmediate [as _immediateCallback] (timers.js:617:5)
          √ does not call runPostMigrations
could not parse data:  this is not valid JSON SyntaxError: Unexpected token h in JSON at position 1
    at JSON.parse (<anonymous>)
    at Promise (E:/srirambv/master/browser-laptop/app/sessionStore.js:826:19)
    at Object.module.exports.loadAppState (E:/srirambv/master/browser-laptop/app/sessionStore.js:815:10)
    at Context.<anonymous> (E:/srirambv/master/browser-laptop/test/unit/app/sessionStoreTest.js:665:31)
    at callFn (E:\srirambv\master\browser-laptop\node_modules\mocha\lib\runnable.js:326:21)
    at Test.Runnable.run (E:\srirambv\master\browser-laptop\node_modules\mocha\lib\runnable.js:319:7)
    at Runner.runTest (E:\srirambv\master\browser-laptop\node_modules\mocha\lib\runner.js:422:10)
    at E:\srirambv\master\browser-laptop\node_modules\mocha\lib\runner.js:528:12
    at next (E:\srirambv\master\browser-laptop\node_modules\mocha\lib\runner.js:342:14)
    at E:\srirambv\master\browser-laptop\node_modules\mocha\lib\runner.js:352:7
    at next (E:\srirambv\master\browser-laptop\node_modules\mocha\lib\runner.js:284:14)
    at Immediate.<anonymous> (E:\srirambv\master\browser-laptop\node_modules\mocha\lib\runner.js:320:5)
    at runCallback (timers.js:672:20)
    at tryOnImmediate (timers.js:645:5)
    at processImmediate [as _immediateCallback] (timers.js:617:5)
          √ calls backupSessionStub
could not parse data:  this is not valid JSON SyntaxError: Unexpected token h in JSON at position 1
    at JSON.parse (<anonymous>)
    at Promise (E:/srirambv/master/browser-laptop/app/sessionStore.js:826:19)
    at Object.module.exports.loadAppState (E:/srirambv/master/browser-laptop/app/sessionStore.js:815:10)
    at Context.<anonymous> (E:/srirambv/master/browser-laptop/test/unit/app/sessionStoreTest.js:675:31)
    at callFn (E:\srirambv\master\browser-laptop\node_modules\mocha\lib\runnable.js:326:21)
    at Test.Runnable.run (E:\srirambv\master\browser-laptop\node_modules\mocha\lib\runnable.js:319:7)
    at Runner.runTest (E:\srirambv\master\browser-laptop\node_modules\mocha\lib\runner.js:422:10)
    at E:\srirambv\master\browser-laptop\node_modules\mocha\lib\runner.js:528:12
    at next (E:\srirambv\master\browser-laptop\node_modules\mocha\lib\runner.js:342:14)
    at E:\srirambv\master\browser-laptop\node_modules\mocha\lib\runner.js:352:7
    at next (E:\srirambv\master\browser-laptop\node_modules\mocha\lib\runner.js:284:14)
    at Immediate.<anonymous> (E:\srirambv\master\browser-laptop\node_modules\mocha\lib\runner.js:320:5)
    at runCallback (timers.js:672:20)
    at tryOnImmediate (timers.js:645:5)
    at processImmediate [as _immediateCallback] (timers.js:617:5)
          √ calls runImportDefaultSettings
      when checking data.cleanedOnShutdown
        when true
calling mocked fs.remove
          √ does not call cleanAppData
        when NOT true
calling mocked fs.remove
          √ calls cleanAppData
      when checking data.lastAppVersion
        when it matches app.getVersion
calling mocked fs.remove
          √ does not call cleanAppData
        when it does NOT match app.getVersion
          √ calls cleanAppData
    backupSession
      when session exists
calling mocked fs.copySync
An error occurred. For support purposes, file "E:\srirambv\master\browser-laptop\userData\session-store-1" has been copied to "C:\Users\Sriram BV\.brave-test-session-store-backup-1507100893819".
        √ calls fs.existsSync
        √ calls fs.copySync
      when session does not exist
        √ calls fs.existsSync
        √ does not call fs.copySync
    defaultAppState
      when NODE_ENV is not `test`
        √ sets showOnLoad to true (which triggers about:welcome)
    runImportDefaultSettings
      √ check defaultSiteSettingsListImported
      √ import to default app state
      √ import to existing app state
    runPreMigrations
      when `data.autofill` exists
        migrate `data.autofill.addresses` from array to map
          √ copies the values into a field called guid
          √ converts the value to a map
        migrate `data.autofill.creditCards` from array to map
          √ copies the values into a field called guid
          √ converts the value to a map
      when `data.settings` exists
        migrate search engine settings
          √ updates settings.DEFAULT_SEARCH_ENGINE if set to google.xml
          √ updates settings.DEFAULT_SEARCH_ENGINE if set to duckduckgo.xml
        payments migration (0.21.x)
          √ sets PAYMENTS_SITES_AUTO_SUGGEST based on AUTO_SUGGEST_SITES
          √ sets PAYMENTS_MINIMUM_VISIT_TIME based on MINIMUM_VISIT_TIME
          √ sets PAYMENTS_MINIMUM_VISITS based on MINIMUM_VISITS
          √ sets PAYMENTS_SITES_SHOW_LESS based on HIDE_LOWER_SITES
          √ sets PAYMENTS_SITES_HIDE_EXCLUDED based on HIDE_EXCLUDED_SITES
          √ sets PAYMENTS_NOTIFICATION_TRY_PAYMENTS_DISMISSED based on payments.notificationTryPaymentsDismissed
          √ removes the old values
      when `data.sites` exists
        run split sites migration
          √ deletes `data.sites`
          when moving pinned sites
            √ copies lastAccessedTime
            √ copies order
            √ copies partitionNumber
            √ copies favicon
            √ copies location
            √ copies title
            √ copies themeColor
          default sites
            √ stores only the keys for ignoredTopSites
            √ stores the pinnedTopSites with key
            √ clears the sites

  siteHacks unit tests
    init
      √ calls Filtering.registerBeforeSendHeadersFilteringCB
      √ calls Filtering.registerBeforeRequestFilteringCB
      in the callback passed into registerBeforeSendHeadersFilteringCB
        √ calls Filtering.getMainFrameUrl
        when site hack is found for domain
          √ calls hack.onBeforeSendHeaders

  windowState
    getWindowIndexByWindowId
      √ returns the index of the tab for the windowId
      √ returns -1 if the windowId does not exist
      √ throws an AssertionError if windowId is not a number
      √ throws an AssertionError if windowId < 1 and windowId != -1
      √ throws an AssertionError if state does not contain a `windows` array
      √ throws an AssertionError if state is not convertable to an Immutable.Map
    getByWindowId
      √ returns the window for `windowId` if it exists
      √ returns null if the win for `windowId` does not exist
      √ throws an AssertionError if windowId is not a number
      √ throws an AssertionError if windowId < 1 and windowId != -1
      √ throws an AssertionError if state does not contain a `windows` array
      √ throws an AssertionError if state is not convertable to an Immutable.Map
    removeWindowByWindowId
      √ returns a new immutable state with the window for `windowId` removed if it exists
      √ returns the state unmodified if the window for `windowId` does not exist
      √ throws an AssertionError if windowId is not a number
      √ throws an AssertionError if windowId < 1 and windowId != -1
      √ throws an AssertionError if state does not contain a `windows` array
      √ throws an AssertionError if state is not convertable to an Immutable.Map
    removeWindowByIndex
      √ returns a new immutable state with the window at `index` removed if it exists
      √ returns the state unmodified if `index` is out of bounds
      √ throws an AssertionError if `index` < 0
      √ throws an AssertionError if `index` is not a number
      √ throws an AssertionError if state does not contain a `windows` array
      √ throws an AssertionError if state is not convertable to an Immutable.Map
    removeWindow
      √ returns a new immutable state with the window removed by `windowId`
      √ throws an AssertionError if action does not contain a `windowValue` that is convertable to an Immutable.Map
      √ throws an AssertionError if `action` is not convertable to an Immutable.Map
      √ throws an AssertionError if `windowValue` does not contain a valid `windowId`
      √ throws an AssertionError if windowId is not a number
      √ throws an AssertionError if windowId < 1 and windowId != -1
      √ throws an AssertionError if state does not contain a `windows` array
      √ throws an AssertionError if state is not convertable to an Immutable.Map
    insertWindow
      √ returns a new immutable state with the windowValue appended to the end of the list
      √ throws an AssertionError if there is already a tab with the windowId
      √ throws an AssertionError if action does not contain a `windowValue` that is convertable to an Immutable.Map
      √ throws an AssertionError if `action` is not convertable to an Immutable.Map
      √ throws an AssertionError if `windowValue` does not contain a valid `windowId`
      √ throws an AssertionError if state does not contain a `windows` array
      √ throws an AssertionError if state is not convertable to an Immutable.Map
    updateWindow
      √ returns a new immutable state with the windowValue updated if it already exists
      √ returns a new immutable state with the windowValue replaced if it already exists and `replace` is true
      √ does not change other values in the appState
      √ throws an AssertionError if action does not contain a `windowValue` that is convertable to an Immutable.Map
      √ throws an AssertionError if `action` is not convertable to an Immutable.Map
      √ throws an AssertionError if `windowValue` does not contain a valid `windowId`
      √ throws an AssertionError if state does not contain a `windows` array
      √ throws an AssertionError if state is not convertable to an Immutable.Map
    maybeCreateWindow
      √ returns a new immutable state with the windowValue appended to the end of the list if it does not already exist
      √ returns a new immutable state with the windowValue updated if it already exists
      √ throws an AssertionError if action does not contain a `windowValue` that is convertable to an Immutable.Map
      √ throws an AssertionError if `action` is not convertable to an Immutable.Map
      √ throws an AssertionError if `windowValue` does not contain a valid `windowId`
      √ throws an AssertionError if state does not contain a `windows` array
      √ throws an AssertionError if state is not convertable to an Immutable.Map
    getWindows
      √ throws an AssertionError if state does not contain a `windows` array
      √ throws an AssertionError if state is not convertable to an Immutable.Map
    getActiveWindowId
      √ obtains active windowId

  settings constants
    √ All settings have default values

  dndData
    hasBraveDragData
      √ returns false for empty transfer
      √ returns false for regular transfer
      √ returns true for brave transfer

  ContextMenus unit tests
    onMainContextMenu
      when calling mainTemplateInit
        √ calls clipboard.readText
        √ calls Menu.buildFromTemplate
        √ calls menu.popup

  eventUtil
    elementHasDataset
      √ returns false if node dataset do not match
      √ returns true if node dataset match the provided dataset array
      √ can accept strings for the dataset to match against
      √ can not accept partial string match
      √ returns false if node do not provide a dataset

  Window store unit tests
    doAction
      WINDOW_WEBVIEW_LOAD_START
        security state
          √ resets security state
        update loading UI
          for frames
            √ sets loading=true
            √ sets startLoadTime to current time
            √ sets endLoadTime=null
      APP_NEW_WEB_CONTENTS_ADDED
        when tab being opened is active
          √ sets activeFrameKey
        when tab being opened is not active
          √ does not set activeFrameKey

  appUrlUtil test
    getBraveExtUrl
      √ arg
      √ no arg
    getTorrentExtUrl
      √ arg
      √ no arg
    aboutUrls
      √ about:about
    magnet url translation
      √ getTargetMagnetUrl
      √ getSourceMagnetUrl
      √ isTargetMagnetUrl
      √ isSourceMagnetUrl
    fileUrl
      √ can convert Windows paths to file URLS
      √ can convert unix paths
    newFrameUrl
      when NEWTAB_MODE = HOMEPAGE
        √ returns the configured home page (66ms)
        √ returns about:blank when home page is falsey (62ms)
      when NEWTAB_MODE = DEFAULT_SEARCH_ENGINE
        √ returns the default search engine URL (63ms)
      when NEWTAB_MODE = EMPTY_NEW_TAB
        √ returns about:newtab (78ms)
      when NEWTAB_MODE = NEW_TAB_PAGE
        √ returns about:newtab (62ms)
      when NEWTAB_MODE is null or has other values
        √ returns about:newtab

  extensionsUtil
    bravifyText
      √ fixes `Chrome`
      √ fixes `GoogleChrome`
      √ fixes `Google Chrome`
      √ does a global replace (more than one occurrence)
      √ does not replace Google
      √ does not replace lowercase c `chrome`

  promisify
    √ resolves node function from a promise
    √ rejects node function from a promise
    √ can chain and ignore
    √ catches errors in between a chain

  urlutil
    getScheme
      √ null for empty
      √ localhost: for localhost
      √ gets scheme with :
      √ host:port is not recognized as a scheme
      √ gets scheme with ://
    prependScheme
      √ returns null when input is null
      √ returns undefined when input is undefined
      √ prepends file:// to absolute file path
      √ defaults to http://
      √ keeps schema if already exists
    isNotURL
      returns false when input:
        √ is a valid URL
        √ is an absolute file path without scheme
        √ is an absolute file path with scheme
        √ contains a hostname and port number
        √ starts or ends with whitespace
        √ is a URL which contains basic auth user/pass
        √ is localhost (case-insensitive)
        √ is a hostname (not a domain)
        √ ends with period (input contains a forward slash and domain)
        √ is a string with whitespace but has schema
        √ has custom protocol
        for special pages
          √ is a data URI
          √ is a view source URL
          √ is a mailto link
          √ is an about page
          √ is a chrome-extension page
          √ is a magnet URL
          √ is a chrome page
      returns true when input:
        √ is null or undefined
        √ is not a string
        √ is a quoted string
        √ is a pure string (no TLD)
        √ is a string with schema but invalid domain name
        √ contains more than one word
        √ is not an about page / view source / data URI / mailto / etc
        √ is a URL (without protocol) which contains basic auth user/pass
        √ has space in schema
        search query
          √ starts with ?
          √ has a question mark followed by a space
          √ starts with .
          √ ends with . (input does NOT contain a forward slash)
          √ ends with period (input contains only a forward slash)
    getUrlFromInput
      √ returns empty string when input is null
      √ returns empty string when input is undefined
      √ calls prependScheme
    isURL
      √ returns !isNotURL
    isFileType
      √ relative file
      √ relative path
      √ JPG URL
      √ non-JPG URL
      √ invalid URL
    toPDFJSLocation
      √ pdf
      √ non-pdf
      √ file url
      √ empty
    getHostname
      √ returns undefined if the URL is invalid
      √ returns the host field (including port number)
      √ allows you to exclude the port number
    getHostnamePatterns
      √ gets bare domain hostname patterns
      √ gets subdomain hostname patterns
    getLocationIfPDF
      √ gets location for PDF JS URL
      √ gets location for PDF JS viewer URL
      √ does not remove wayback machine url location for PDF JS URL
      √ does not modify location for non-pdf URL
      √ gets location for file: PDF URL
    getDefaultFaviconUrl
      √ returns empty string if input is not a URL
      √ returns the default favicon URL when given a valid URL
      √ includes the port in the response when given a valid URL with a port number
    getPunycodeUrl
      √ returns original string if input is ASCII
      √ returns punycode ASCII string if input is non-ASCII
      √ returns the punycode URL when given a valid URL
    isPotentialPhishingUrl
      √ returns false if input is not a URL
      √ returns false if input is a regular URL
      √ returns true if input is a data URL
      √ returns true if input is a blob URL
    isFileScheme
      returns true when input:
        √ is an absolute file path with scheme
      returns false when input:
        √ is an absolute file path without scheme
        √ is a URL
        √ has custom protocol
    getDisplayHost
      √ url is http
      √ url is https
      √ url is file
    getOrigin
      √ returns file:/// for any file url
      √ gets URL origin for simple url
      √ gets URL origin for url with port
      √ gets URL origin for IP host
      √ gets URL origin for slashless protocol URL
      √ returns null for invalid URL
      √ returns null for empty URL
      √ returns null for null URL
      √ returns correct result for URL with hostname that is a scheme
    stripLocation
      √ null scenario
      √ empty string
      √ normal url without # or /
      √ normal url with # but not at the end
      √ normal url with # at the end
      √ normal url with / at the end
      √ normal url with /# at the end
      √ normal url with white space at the end

  zoom
    getZoomPercentage
      √ formats 0 t0 100%
      √ formats positive 20% increments
      √ formats negative 20% decrements
    getNextZoomLevel
      √ zoomOut respects minimum
      √ zoomIn at minimum goest up
      √ zoomIn respects maximum
      √ zooOut at maximum goes down

  settings unit test
    getSetting
      √ returns value from collection if one is provided
      √ returns value from appConfig if both collection and appStore not found (78ms)
      √ returns value from appStore if collection not found
      when setting default value for new config entries (based on previous session data)
        ACTIVE_PASSWORD_MANAGER
          √ returns `1Password` if ONE_PASSWORD_ENABLED was true
          √ returns `Dashlane` if DASHLANE_ENABLED was true
          √ returns `LastPass` if LAST_PASS_ENABLED was true
          √ returns `BuiltIn` if PASSWORD_MANAGER_ENABLED was true
          √ returns `1Password`/`Dashlane`/`LastPass`, even if PASSWORD_MANAGER_ENABLED was true
          √ returns `Unmanaged` if PASSWORD_MANAGER_ENABLED was false
          √ defaults to `BuiltIn` if no other conditions are met
        BOOKMARKS_TOOLBAR_MODE
          √ returns `FAVICONS_ONLY` if SHOW_BOOKMARKS_TOOLBAR_ONLY_FAVICON was true
          √ returns `TEXT_AND_FAVICONS` if SHOW_BOOKMARKS_TOOLBAR_FAVICON was true
          √ defaults to `TEXT_ONLY` if no other conditions are met
    getActivePasswordManager
      √ returns the active password manager details
      √ calls getSetting to get the value (providing a default if none exists)

  downloadUtil
    shouldAllowPause
      √ handles falsey input
      √ returns true if state is `downloadStates.IN_PROGRESS`
    getPercentageComplete
      √ handles falsey input
      √ returns percentage complete for nonzero totalBytes
      √ returns percentage complete for falsey totalBytes
    shouldAllowCopyLink
      √ returns false if input is falsey
      √ returns false if `download.url` does not have a value
      √ returns true if `download.url` has a value
    getDownloadItems
      √ returns an empty Immutable.List if intput is falsey
      √ returns an empty Immutable.List if `state.downloads` is falsey

  frameStateUtil
    getFrameIndex
      √ returns the index by frame key
    frameStatePath
      √ returns the index by frame key
    getIndexByTabId
      √ returns the index by frame key
    query
      √ returns frames that match the queryInfo properties
    find
      √ returns the first frame that matches the queryInfo properties
    removeFrame
      √ removed frame is added to `closedFrames`
      √ sets isFullScreen=false for the removed frame
      √ removed frame is NOT added to `closedFrames` if private
      √ removes the frame from `frames`
    getTotalBlocks
      √ returns false if there are no units blocked
      √ returns total of items (ads / trackers / scripts / fingerprints) blocked
      √ defaults values to 0 if element is not a list or is not present
      √ returns false if the input is falsey
      √ converts the input to an immutable object
      √ returns "99+" if tracker count is > 99
    getTabPageCount
      √ returns two pages when we have more tabs then the tab page limit
      √ returns one pages when we have exactly the same tabs as the tab page limit
      √ returns one pages when we have less tabs then the tab page limit
    frameLocationMatch
      √ returns false if frame is empty
      √ returns false if frame is not an Immutable map
      √ returns false if location is empty
      √ returns false if location is a partial match
      √ returns true if location match

  siteSettings
    simple URL host pattern
      √ can obtain a site setting from a host pattern
      √ can obtain a site setting from an exact URL
      √ can obtain a site setting from a URL at that host
    any port pattern
      √ can obtain with a wildcard port for host pattern
      √ can obtain without a port
      √ can obtain with a specific port
    all https protocol pattern
      √ Can obtain from https url
      √ Cannot obtain from http url
    http or https specific URLs
      √ Can obtain from https url
      √ Can obtain from http url
    subdomain wildcards
      √ Can obtain from no subdomain
      √ Can obtain from a single subdomain
      √ Can obtain from multiple subdomains
      √ Can obtain from multiple subdomains and a different port
      √ Cannot obtain from a diff domain
    Overwriting a setting works
      √ can overwrites what is needed but does not
      √ merging settings does not lose other data
    More specific rules override
      √ can obtain a site setting from a host pattern
      √ can obtain properly combined settings

  syncUtil
    getSiteDataFromRecord
      with customTitle
        - if assigned value, it copies field to title
        - deletes field if empty
      with objectData
        when "bookmark"
          √ update bookmark parent folder to null -> overrides existing parent folder
    now
      √ returns seconds (truncating milliseconds)
    newObjectId
      √ generates a 16 byte id
      √ calls appActions.setObjectId
      √ returns the 16 byte id
    create{collection}SiteData
      createBookmarkData
        √ bookmarks
        √ bookmark with undefined custom title
        √ bookmark containing data url
        √ bookmark in Other Bookmarks folder
      createHistorySiteData
        √ history sites
        √ site without lastAccessedTime
    deepArrayify
      √ does nothing with objects already safe
      √ does nothing with Arrays
      √ converts Uint8Array to Array
    ipcSafeObject
      √ calls deepArrayify

  1858 passing (28s)
  60 pending