diff options
| author | Stephen Blott | 2015-05-29 12:47:23 +0100 | 
|---|---|---|
| committer | Stephen Blott | 2015-05-29 12:47:23 +0100 | 
| commit | c5babceec0178f02233446d6a3ad4c19c176b564 (patch) | |
| tree | e0475c5f97fa5e868863fe0cd609584fa14a152e | |
| parent | df4bd23474beb6b59a712acfe8611292d1ce507d (diff) | |
| parent | 5b24b564a42ac5533bbb031f24b07c42beebd65e (diff) | |
| download | vimium-c5babceec0178f02233446d6a3ad4c19c176b564.tar.bz2 | |
Merge pull request #1599 from mrmr1993/settings-refactor
Separate Settings from the background page, and use it directly in options.html/popup.html
| -rw-r--r-- | background_scripts/commands.coffee | 6 | ||||
| -rw-r--r-- | background_scripts/exclusions.coffee | 4 | ||||
| -rw-r--r-- | background_scripts/main.coffee | 2 | ||||
| -rw-r--r-- | background_scripts/settings.coffee | 126 | ||||
| -rw-r--r-- | background_scripts/sync.coffee | 74 | ||||
| -rw-r--r-- | lib/settings.coffee | 202 | ||||
| -rw-r--r-- | lib/utils.coffee | 7 | ||||
| -rw-r--r-- | manifest.json | 3 | ||||
| -rw-r--r-- | pages/options.coffee | 10 | ||||
| -rw-r--r-- | pages/options.html | 1 | ||||
| -rw-r--r-- | pages/popup.html | 2 | ||||
| -rw-r--r-- | tests/unit_tests/commands_test.coffee | 1 | ||||
| -rw-r--r-- | tests/unit_tests/exclusion_test.coffee | 5 | ||||
| -rw-r--r-- | tests/unit_tests/settings_test.coffee | 20 | ||||
| -rw-r--r-- | tests/unit_tests/test_chrome_stubs.coffee | 3 | ||||
| -rw-r--r-- | tests/unit_tests/utils_test.coffee | 5 | 
16 files changed, 247 insertions, 224 deletions
| diff --git a/background_scripts/commands.coffee b/background_scripts/commands.coffee index abfbd9e2..5857665c 100644 --- a/background_scripts/commands.coffee +++ b/background_scripts/commands.coffee @@ -359,5 +359,11 @@ commandDescriptions =  Commands.init() +# Register postUpdateHook for keyMappings setting. +Settings.postUpdateHooks["keyMappings"] = (value) -> +  Commands.clearKeyMappingsAndSetDefaults() +  Commands.parseCustomKeyMappings value +  refreshCompletionKeysAfterMappingSave() +  root = exports ? window  root.Commands = Commands diff --git a/background_scripts/exclusions.coffee b/background_scripts/exclusions.coffee index 5ec76e2a..21342d61 100644 --- a/background_scripts/exclusions.coffee +++ b/background_scripts/exclusions.coffee @@ -73,3 +73,7 @@ if not Settings.has("exclusionRules") and Settings.has("excludedUrls")    # We'll keep a backup of the "excludedUrls" setting, just in case.    Settings.set("excludedUrlsBackup", Settings.get("excludedUrls")) if not Settings.has("excludedUrlsBackup")    Settings.clear("excludedUrls") + +# Register postUpdateHook for exclusionRules setting. +Settings.postUpdateHooks["exclusionRules"] = (value) -> +  Exclusions.postUpdateHook value diff --git a/background_scripts/main.coffee b/background_scripts/main.coffee index a13d9d98..edcdf3b2 100644 --- a/background_scripts/main.coffee +++ b/background_scripts/main.coffee @@ -744,5 +744,5 @@ chrome.windows.getAll { populate: true }, (windows) ->        chrome.tabs.sendMessage(tab.id, { name: "getScrollPosition" }, createScrollPositionHandler())  # Start pulling changes from synchronized storage. -Sync.init() +Settings.init()  showUpgradeMessage() diff --git a/background_scripts/settings.coffee b/background_scripts/settings.coffee deleted file mode 100644 index d23649ee..00000000 --- a/background_scripts/settings.coffee +++ /dev/null @@ -1,126 +0,0 @@ -# -# Used by all parts of Vimium to manipulate localStorage. -# - -root = exports ? window -root.Settings = Settings = -  get: (key) -> -    if (key of localStorage) then JSON.parse(localStorage[key]) else @defaults[key] - -  set: (key, value) -> -    # Don't store the value if it is equal to the default, so we can change the defaults in the future -    if (value == @defaults[key]) -      @clear(key) -    else -      jsonValue = JSON.stringify value -      localStorage[key] = jsonValue -      Sync.set key, jsonValue - -  clear: (key) -> -    if @has key -      delete localStorage[key] -    Sync.clear key - -  has: (key) -> key of localStorage - -  # For settings which require action when their value changes, add hooks here called from -  # options/options.coffee (when the options page is saved), and from background_scripts/sync.coffee (when an -  # update propagates from chrome.storage.sync). -  postUpdateHooks: -    keyMappings: (value) -> -      root.Commands.clearKeyMappingsAndSetDefaults() -      root.Commands.parseCustomKeyMappings value -      root.refreshCompletionKeysAfterMappingSave() - -    exclusionRules: (value) -> -      root.Exclusions.postUpdateHook value - -  # postUpdateHooks convenience wrapper -  performPostUpdateHook: (key, value) -> -    @postUpdateHooks[key] value if @postUpdateHooks[key] - -  # options.coffee and options.html only handle booleans and strings; therefore all defaults must be booleans -  # or strings -  defaults: -    scrollStepSize: 60 -    smoothScroll: true -    keyMappings: "# Insert your preferred key mappings here." -    linkHintCharacters: "sadfjklewcmpgh" -    linkHintNumbers: "0123456789" -    filterLinkHints: false -    hideHud: false -    userDefinedLinkHintCss: -      """ -      div > .vimiumHintMarker { -      /* linkhint boxes */ -      background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#FFF785), -        color-stop(100%,#FFC542)); -      border: 1px solid #E3BE23; -      } - -      div > .vimiumHintMarker span { -      /* linkhint text */ -      color: black; -      font-weight: bold; -      font-size: 12px; -      } - -      div > .vimiumHintMarker > .matchingCharacter { -      } -      """ -    # Default exclusion rules. -    exclusionRules: -      [ -        # Disable Vimium on Gmail. -        { pattern: "http*://mail.google.com/*", passKeys: "" } -      ] - -    # NOTE: If a page contains both a single angle-bracket link and a double angle-bracket link, then in -    # most cases the single bracket link will be "prev/next page" and the double bracket link will be -    # "first/last page", so we put the single bracket first in the pattern string so that it gets searched -    # for first. - -    # "\bprev\b,\bprevious\b,\bback\b,<,←,«,≪,<<" -    previousPatterns: "prev,previous,back,<,\u2190,\xab,\u226a,<<" -    # "\bnext\b,\bmore\b,>,→,»,≫,>>" -    nextPatterns: "next,more,>,\u2192,\xbb,\u226b,>>" -    # default/fall back search engine -    searchUrl: "https://www.google.com/search?q=" -    # put in an example search engine -    searchEngines: [ -      "w: http://www.wikipedia.org/w/index.php?title=Special:Search&search=%s Wikipedia" -      "" -      "# More examples." -      "#" -      "# (Vimium has built-in completion for these.)" -      "#" -      "# g: http://www.google.com/search?q=%s Google" -      "# l: http://www.google.com/search?q=%s&btnI I'm feeling lucky..." -      "# y: http://www.youtube.com/results?search_query=%s Youtube" -      "# b: https://www.bing.com/search?q=%s Bing" -      "# d: https://duckduckgo.com/?q=%s DuckDuckGo" -      "# az: http://www.amazon.com/s/?field-keywords=%s Amazon" -      "#" -      "# Another example (for Vimium does not have completion)." -      "#" -      "# m: https://www.google.com/maps/search/%s Google Maps" -      ].join "\n" -    newTabUrl: "chrome://newtab" -    grabBackFocus: false - -    settingsVersion: Utils.getCurrentVersion() - - -# We use settingsVersion to coordinate any necessary schema changes. -if Utils.compareVersions("1.42", Settings.get("settingsVersion")) != -1 -  Settings.set("scrollStepSize", parseFloat Settings.get("scrollStepSize")) -Settings.set("settingsVersion", Utils.getCurrentVersion()) - -# Migration (after 1.49, 2015/2/1). -# Legacy setting: findModeRawQuery (a string). -# New setting: findModeRawQueryList (a list of strings), now stored in chrome.storage.local (not localStorage). -chrome.storage.local.get "findModeRawQueryList", (items) -> -  unless chrome.runtime.lastError or items.findModeRawQueryList -    rawQuery = Settings.get "findModeRawQuery" -    chrome.storage.local.set findModeRawQueryList: (if rawQuery then [ rawQuery ] else []) - diff --git a/background_scripts/sync.coffee b/background_scripts/sync.coffee deleted file mode 100644 index d0d501d3..00000000 --- a/background_scripts/sync.coffee +++ /dev/null @@ -1,74 +0,0 @@ -# -# * Sync.set() and Sync.clear() propagate local changes to chrome.storage.sync. -# * Sync.handleStorageUpdate() listens for changes to chrome.storage.sync and propagates those -#   changes to localStorage and into vimium's internal state. -# * Sync.fetchAsync() polls chrome.storage.sync at startup, similarly propagating -#   changes to localStorage and into vimium's internal state. -# -# Changes are propagated into vimium's state using the same mechanism -# (Settings.performPostUpdateHook) that is used when options are changed on -# the options page. -# -# The effect is best-effort synchronization of vimium options/settings between -# chrome/vimium instances. -# -# NOTE: -#   Values handled within this module are ALWAYS already JSON.stringifed, so -#   they're always non-empty strings. -# - -root = exports ? window -root.Sync = Sync = - -  storage: chrome.storage.sync -  doNotSync: ["settingsVersion", "previousVersion"] - -  # This is called in main.coffee. -  init: -> -    chrome.storage.onChanged.addListener (changes, area) -> Sync.handleStorageUpdate changes, area -    @fetchAsync() - -  # Asynchronous fetch from synced storage, called only at startup. -  fetchAsync: -> -    @storage.get null, (items) => -      unless chrome.runtime.lastError -        for own key, value of items -          @storeAndPropagate key, value - -  # Asynchronous message from synced storage. -  handleStorageUpdate: (changes, area) -> -    for own key, change of changes -      @storeAndPropagate key, change?.newValue - -  # Only ever called from asynchronous synced-storage callbacks (fetchAsync and handleStorageUpdate). -  storeAndPropagate: (key, value) -> -    return unless key of Settings.defaults -    return if not @shouldSyncKey key -    return if value and key of localStorage and localStorage[key] is value -    defaultValue = Settings.defaults[key] -    defaultValueJSON = JSON.stringify(defaultValue) - -    if value and value != defaultValueJSON -      # Key/value has been changed to non-default value at remote instance. -      localStorage[key] = value -      Settings.performPostUpdateHook key, JSON.parse(value) -    else -      # Key has been reset to default value at remote instance. -      if key of localStorage -        delete localStorage[key] -      Settings.performPostUpdateHook key, defaultValue - -  # Only called synchronously from within vimium, never on a callback. -  # No need to propagate updates to the rest of vimium, that's already been done. -  set: (key, value) -> -    if @shouldSyncKey key -      setting = {}; setting[key] = value -      @storage.set setting - -  # Only called synchronously from within vimium, never on a callback. -  clear: (key) -> -    @storage.remove key if @shouldSyncKey key - -  # Should we synchronize this key? -  shouldSyncKey: (key) -> key not in @doNotSync - diff --git a/lib/settings.coffee b/lib/settings.coffee new file mode 100644 index 00000000..dd667dbd --- /dev/null +++ b/lib/settings.coffee @@ -0,0 +1,202 @@ +# +# * Sync.set() and Sync.clear() propagate local changes to chrome.storage.sync. +# * Sync.handleStorageUpdate() listens for changes to chrome.storage.sync and propagates those +#   changes to localStorage and into vimium's internal state. +# * Sync.fetchAsync() polls chrome.storage.sync at startup, similarly propagating +#   changes to localStorage and into vimium's internal state. +# +# The effect is best-effort synchronization of vimium options/settings between +# chrome/vimium instances. +# +# NOTE: +#   Values handled within this module are ALWAYS already JSON.stringifed, so +#   they're always non-empty strings. +# + +root = exports ? window +Sync = + +  storage: chrome.storage.sync +  doNotSync: ["settingsVersion", "previousVersion"] + +  # This is called in main.coffee. +  init: -> +    chrome.storage.onChanged.addListener (changes, area) -> Sync.handleStorageUpdate changes, area +    @fetchAsync() + +  # Asynchronous fetch from synced storage, called only at startup. +  fetchAsync: -> +    @storage.get null, (items) => +      unless chrome.runtime.lastError +        for own key, value of items +          Settings.storeAndPropagate key, value if @shouldSyncKey key + +  # Asynchronous message from synced storage. +  handleStorageUpdate: (changes, area) -> +    for own key, change of changes +      Settings.storeAndPropagate key, change?.newValue if @shouldSyncKey key + +  # Only called synchronously from within vimium, never on a callback. +  # No need to propagate updates to the rest of vimium, that's already been done. +  set: (key, value) -> +    if @shouldSyncKey key +      setting = {}; setting[key] = value +      @storage.set setting + +  # Only called synchronously from within vimium, never on a callback. +  clear: (key) -> +    @storage.remove key if @shouldSyncKey key + +  # Should we synchronize this key? +  shouldSyncKey: (key) -> key not in @doNotSync + +# +# Used by all parts of Vimium to manipulate localStorage. +# + +# Select the object to use as the cache for settings. +if Utils.isExtensionPage() +  if Utils.isBackgroundPage() +    settingsCache = localStorage +  else +    settingsCache = extend {}, localStorage # Make a copy of the cached settings from localStorage +else +  settingsCache = {} + +root.Settings = Settings = +  cache: settingsCache +  init: -> Sync.init() +  get: (key) -> +    if (key of @cache) then JSON.parse(@cache[key]) else @defaults[key] + +  set: (key, value) -> +    # Don't store the value if it is equal to the default, so we can change the defaults in the future +    if (value == @defaults[key]) +      @clear(key) +    else +      jsonValue = JSON.stringify value +      @cache[key] = jsonValue +      Sync.set key, jsonValue + +  clear: (key) -> +    if @has key +      delete @cache[key] +    Sync.clear key + +  has: (key) -> key of @cache + +  # For settings which require action when their value changes, add hooks to this object, to be called from +  # options/options.coffee (when the options page is saved), and by Settings.storeAndPropagate (when an +  # update propagates from chrome.storage.sync). +  postUpdateHooks: {} + +  # postUpdateHooks convenience wrapper +  performPostUpdateHook: (key, value) -> +    @postUpdateHooks[key]? value + +  # Only ever called from asynchronous synced-storage callbacks (fetchAsync and handleStorageUpdate). +  storeAndPropagate: (key, value) -> +    return unless key of @defaults +    return if value and key of @cache and @cache[key] is value +    defaultValue = @defaults[key] +    defaultValueJSON = JSON.stringify(defaultValue) + +    if value and value != defaultValueJSON +      # Key/value has been changed to non-default value at remote instance. +      @cache[key] = value +      @performPostUpdateHook key, JSON.parse(value) +    else +      # Key has been reset to default value at remote instance. +      if key of @cache +        delete @cache[key] +      @performPostUpdateHook key, defaultValue + +  # options.coffee and options.html only handle booleans and strings; therefore all defaults must be booleans +  # or strings +  defaults: +    scrollStepSize: 60 +    smoothScroll: true +    keyMappings: "# Insert your preferred key mappings here." +    linkHintCharacters: "sadfjklewcmpgh" +    linkHintNumbers: "0123456789" +    filterLinkHints: false +    hideHud: false +    userDefinedLinkHintCss: +      """ +      div > .vimiumHintMarker { +      /* linkhint boxes */ +      background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#FFF785), +        color-stop(100%,#FFC542)); +      border: 1px solid #E3BE23; +      } + +      div > .vimiumHintMarker span { +      /* linkhint text */ +      color: black; +      font-weight: bold; +      font-size: 12px; +      } + +      div > .vimiumHintMarker > .matchingCharacter { +      } +      """ +    # Default exclusion rules. +    exclusionRules: +      [ +        # Disable Vimium on Gmail. +        { pattern: "http*://mail.google.com/*", passKeys: "" } +      ] + +    # NOTE: If a page contains both a single angle-bracket link and a double angle-bracket link, then in +    # most cases the single bracket link will be "prev/next page" and the double bracket link will be +    # "first/last page", so we put the single bracket first in the pattern string so that it gets searched +    # for first. + +    # "\bprev\b,\bprevious\b,\bback\b,<,←,«,≪,<<" +    previousPatterns: "prev,previous,back,<,\u2190,\xab,\u226a,<<" +    # "\bnext\b,\bmore\b,>,→,»,≫,>>" +    nextPatterns: "next,more,>,\u2192,\xbb,\u226b,>>" +    # default/fall back search engine +    searchUrl: "https://www.google.com/search?q=" +    # put in an example search engine +    searchEngines: [ +      "w: http://www.wikipedia.org/w/index.php?title=Special:Search&search=%s Wikipedia" +      "" +      "# More examples." +      "#" +      "# (Vimium has built-in completion for these.)" +      "#" +      "# g: http://www.google.com/search?q=%s Google" +      "# l: http://www.google.com/search?q=%s&btnI I'm feeling lucky..." +      "# y: http://www.youtube.com/results?search_query=%s Youtube" +      "# b: https://www.bing.com/search?q=%s Bing" +      "# d: https://duckduckgo.com/?q=%s DuckDuckGo" +      "# az: http://www.amazon.com/s/?field-keywords=%s Amazon" +      "#" +      "# Another example (for Vimium does not have completion)." +      "#" +      "# m: https://www.google.com/maps/search/%s Google Maps" +      ].join "\n" +    newTabUrl: "chrome://newtab" +    grabBackFocus: false + +    settingsVersion: Utils.getCurrentVersion() + +# Export Sync via Settings for tests. +root.Settings.Sync = Sync + +# Perform migration from old settings versions, if this is the background page. +if Utils.isBackgroundPage() + +  # We use settingsVersion to coordinate any necessary schema changes. +  if Utils.compareVersions("1.42", Settings.get("settingsVersion")) != -1 +    Settings.set("scrollStepSize", parseFloat Settings.get("scrollStepSize")) +  Settings.set("settingsVersion", Utils.getCurrentVersion()) + +  # Migration (after 1.49, 2015/2/1). +  # Legacy setting: findModeRawQuery (a string). +  # New setting: findModeRawQueryList (a list of strings), now stored in chrome.storage.local (not localStorage). +  chrome.storage.local.get "findModeRawQueryList", (items) -> +    unless chrome.runtime.lastError or items.findModeRawQueryList +      rawQuery = Settings.get "findModeRawQuery" +      chrome.storage.local.set findModeRawQueryList: (if rawQuery then [ rawQuery ] else []) diff --git a/lib/utils.coffee b/lib/utils.coffee index 65e26b7a..835b0359 100644 --- a/lib/utils.coffee +++ b/lib/utils.coffee @@ -2,6 +2,13 @@ Utils =    getCurrentVersion: ->      chrome.runtime.getManifest().version +  # Returns true whenever the current page is from the extension's origin (and thus can access the +  # extension's localStorage). +  isExtensionPage: -> document.location?.origin + "/" == chrome.extension.getURL "" + +  # Returns true whenever the current page is the extension's background page. +  isBackgroundPage: -> @isExtensionPage() and chrome.extension.getBackgroundPage() == window +    # Takes a dot-notation object string and call the function    # that it points to with the correct value for 'this'.    invokeCommandString: (str, argArray) -> diff --git a/manifest.json b/manifest.json index fe5c69ca..f0c51117 100644 --- a/manifest.json +++ b/manifest.json @@ -9,10 +9,9 @@    "background": {      "scripts": [        "lib/utils.js", +      "lib/settings.js",        "background_scripts/commands.js",        "lib/clipboard.js", -      "background_scripts/sync.js", -      "background_scripts/settings.js",        "background_scripts/exclusions.js",        "background_scripts/completion_engines.js",        "background_scripts/completion_search.js", diff --git a/pages/options.coffee b/pages/options.coffee index 18ff226d..110f869c 100644 --- a/pages/options.coffee +++ b/pages/options.coffee @@ -1,7 +1,6 @@  $ = (id) -> document.getElementById id -bgUtils = chrome.extension.getBackgroundPage().Utils -bgSettings = chrome.extension.getBackgroundPage().Settings +Settings.init()  bgExclusions = chrome.extension.getBackgroundPage().Exclusions  # @@ -22,21 +21,20 @@ class Option    # Fetch a setting from localStorage, remember the @previous value and populate the DOM element.    # Return the fetched value.    fetch: -> -    @populateElement @previous = bgSettings.get @field +    @populateElement @previous = Settings.get @field      @previous    # Write this option's new value back to localStorage, if necessary.    save: ->      value = @readValueFromElement()      if not @areEqual value, @previous -      bgSettings.set @field, @previous = value -      bgSettings.performPostUpdateHook @field, value +      Settings.set @field, @previous = value    # Compare values; this is overridden by sub-classes.    areEqual: (a,b) -> a == b    restoreToDefault: -> -    bgSettings.clear @field +    Settings.clear @field      @fetch()    # Static method. diff --git a/pages/options.html b/pages/options.html index 0fa5b18d..67e2b16d 100644 --- a/pages/options.html +++ b/pages/options.html @@ -3,6 +3,7 @@      <title>Vimium Options</title>      <link rel="stylesheet" type="text/css" href="options.css">      <script src="content_script_loader.js"></script> +    <script type="text/javascript" src="../lib/settings.js"></script>      <script type="text/javascript" src="options.js"></script>    </head> diff --git a/pages/popup.html b/pages/popup.html index c7e2fd6f..fdf116e5 100644 --- a/pages/popup.html +++ b/pages/popup.html @@ -48,6 +48,8 @@        }      </style> +    <script src="../lib/utils.js"></script> +    <script src="../lib/settings.js"></script>      <script src="options.js"></script>    </head>    <body> diff --git a/tests/unit_tests/commands_test.coffee b/tests/unit_tests/commands_test.coffee index daaef016..e55dc0f2 100644 --- a/tests/unit_tests/commands_test.coffee +++ b/tests/unit_tests/commands_test.coffee @@ -1,5 +1,6 @@  require "./test_helper.js"  extend global, require "./test_chrome_stubs.js" +global.Settings = {postUpdateHooks: {}}  {Commands} = require "../../background_scripts/commands.js"  context "Key mappings", diff --git a/tests/unit_tests/exclusion_test.coffee b/tests/unit_tests/exclusion_test.coffee index b3ed7194..28c17a2f 100644 --- a/tests/unit_tests/exclusion_test.coffee +++ b/tests/unit_tests/exclusion_test.coffee @@ -14,9 +14,8 @@ root.Marks =  extend(global, require "../../lib/utils.js")  Utils.getCurrentVersion = -> '1.44' -extend(global,require "../../background_scripts/sync.js") -extend(global,require "../../background_scripts/settings.js") -Sync.init() +extend(global,require "../../lib/settings.js") +Settings.init()  extend(global, require "../../background_scripts/exclusions.js")  extend(global, require "../../background_scripts/commands.js")  extend(global, require "../../background_scripts/main.js") diff --git a/tests/unit_tests/settings_test.coffee b/tests/unit_tests/settings_test.coffee index 4cd20211..ded7b5f8 100644 --- a/tests/unit_tests/settings_test.coffee +++ b/tests/unit_tests/settings_test.coffee @@ -3,15 +3,18 @@ extend global, require "./test_chrome_stubs.js"  extend(global, require "../../lib/utils.js")  Utils.getCurrentVersion = -> '1.44' +Utils.isBackgroundPage = -> true +Utils.isExtensionPage = -> true  global.localStorage = {} -extend(global,require "../../background_scripts/sync.js") -extend(global,require "../../background_scripts/settings.js") -Sync.init() +extend(global,require "../../lib/settings.js")  context "settings",    setup ->      stub global, 'localStorage', {} +    Settings.cache = global.localStorage # Point the settings cache to the new localStorage object. +    Settings.postUpdateHooks = {} # Avoid running update hooks which include calls to outside of settings. +    Settings.init()    should "save settings in localStorage as JSONified strings", ->      Settings.set 'dummy', "" @@ -39,24 +42,22 @@ context "settings",    should "propagate non-default value via synced storage listener", ->      Settings.set 'scrollStepSize', 20      assert.equal Settings.get('scrollStepSize'), 20 -    Sync.handleStorageUpdate { scrollStepSize: { newValue: "40" } } +    Settings.Sync.handleStorageUpdate { scrollStepSize: { newValue: "40" } }      assert.equal Settings.get('scrollStepSize'), 40    should "propagate default value via synced storage listener", ->      Settings.set 'scrollStepSize', 20      assert.equal Settings.get('scrollStepSize'), 20 -    Sync.handleStorageUpdate { scrollStepSize: { newValue: "60" } } +    Settings.Sync.handleStorageUpdate { scrollStepSize: { newValue: "60" } }      assert.isFalse Settings.has 'scrollStepSize'    should "propagate non-default values from synced storage", ->      chrome.storage.sync.set { scrollStepSize: JSON.stringify(20) } -    Sync.fetchAsync()      assert.equal Settings.get('scrollStepSize'), 20    should "propagate default values from synced storage", ->      Settings.set 'scrollStepSize', 20      chrome.storage.sync.set { scrollStepSize: JSON.stringify(60) } -    Sync.fetchAsync()      assert.isFalse Settings.has 'scrollStepSize'    should "clear a setting from synced storage", -> @@ -66,9 +67,10 @@ context "settings",    should "trigger a postUpdateHook", ->      message = "Hello World" -    Settings.postUpdateHooks['scrollStepSize'] = (value) -> Sync.message = value +    receivedMessage = "" +    Settings.postUpdateHooks['scrollStepSize'] = (value) -> receivedMessage = value      chrome.storage.sync.set { scrollStepSize: JSON.stringify(message) } -    assert.equal message, Sync.message +    assert.equal message, receivedMessage    should "sync a key which is not a known setting (without crashing)", ->      chrome.storage.sync.set { notASetting: JSON.stringify("notAUsefullValue") } diff --git a/tests/unit_tests/test_chrome_stubs.coffee b/tests/unit_tests/test_chrome_stubs.coffee index 60f3a890..16f0e144 100644 --- a/tests/unit_tests/test_chrome_stubs.coffee +++ b/tests/unit_tests/test_chrome_stubs.coffee @@ -19,6 +19,9 @@ exports.chrome =      onInstalled:        addListener: -> +  extension: +    getURL: (path) -> path +    tabs:      onSelectionChanged:        addListener: () -> true diff --git a/tests/unit_tests/utils_test.coffee b/tests/unit_tests/utils_test.coffee index bfe066c3..f9ed3636 100644 --- a/tests/unit_tests/utils_test.coffee +++ b/tests/unit_tests/utils_test.coffee @@ -2,9 +2,8 @@ require "./test_helper.js"  extend global, require "./test_chrome_stubs.js"  extend(global, require "../../lib/utils.js")  Utils.getCurrentVersion = -> '1.43' -extend(global, require "../../background_scripts/sync.js") -extend(global, require "../../background_scripts/settings.js") -Sync.init() +extend(global, require "../../lib/settings.js") +Settings.init()  context "isUrl",    should "accept valid URLs", -> | 
