 
         expect(atom.config.get('foo.bar.baz', scope: ['.source.coffee'])).toBe 10
 
-  describe ".getSources()", ->
-    it "returns an array of all of the config's source names", ->
-      expect(atom.config.getSources()).toEqual([])
-
-      atom.config.set("a.b", 1, scopeSelector: ".x1", source: "source-1")
-      atom.config.set("a.c", 1, scopeSelector: ".x1", source: "source-1")
-      atom.config.set("a.b", 2, scopeSelector: ".x2", source: "source-2")
-      atom.config.set("a.b", 1, scopeSelector: ".x3", source: "source-3")
-
-      expect(atom.config.getSources()).toEqual([
-        "source-1"
-        "source-2"
-        "source-3"
-      ])
-
-  describe ".getSettings()", ->
-    it "returns all settings including defaults", ->
-      atom.config.setDefaults("foo", bar: baz: 10)
-      atom.config.set("foo.ok", 12)
-
-      jasmine.snapshotDeprecations()
-      expect(atom.config.getSettings().foo).toEqual
-        ok: 12
-        bar:
-          baz: 10
-      jasmine.restoreDeprecationsSnapshot()
-
-  describe ".pushAtKeyPath(keyPath, value)", ->
-    it "pushes the given value to the array at the key path and updates observers", ->
-      atom.config.set("foo.bar.baz", ["a"])
-      observeHandler = jasmine.createSpy "observeHandler"
-      atom.config.observe "foo.bar.baz", observeHandler
-      observeHandler.reset()
-
-      expect(atom.config.pushAtKeyPath("foo.bar.baz", "b")).toBe 2
-      expect(atom.config.get("foo.bar.baz")).toEqual ["a", "b"]
-      expect(observeHandler).toHaveBeenCalledWith atom.config.get("foo.bar.baz")
-
-  describe ".unshiftAtKeyPath(keyPath, value)", ->
-    it "unshifts the given value to the array at the key path and updates observers", ->
-      atom.config.set("foo.bar.baz", ["b"])
-      observeHandler = jasmine.createSpy "observeHandler"
-      atom.config.observe "foo.bar.baz", observeHandler
-      observeHandler.reset()
-
-      expect(atom.config.unshiftAtKeyPath("foo.bar.baz", "a")).toBe 2
-      expect(atom.config.get("foo.bar.baz")).toEqual ["a", "b"]
-      expect(observeHandler).toHaveBeenCalledWith atom.config.get("foo.bar.baz")
-
-  describe ".removeAtKeyPath(keyPath, value)", ->
-    it "removes the given value from the array at the key path and updates observers", ->
-      atom.config.set("foo.bar.baz", ["a", "b", "c"])
-      observeHandler = jasmine.createSpy "observeHandler"
-      atom.config.observe "foo.bar.baz", observeHandler
-      observeHandler.reset()
-
-      expect(atom.config.removeAtKeyPath("foo.bar.baz", "b")).toEqual ["a", "c"]
-      expect(atom.config.get("foo.bar.baz")).toEqual ["a", "c"]
-      expect(observeHandler).toHaveBeenCalledWith atom.config.get("foo.bar.baz")
-
-  describe ".getPositiveInt(keyPath, defaultValue)", ->
-    beforeEach ->
-      jasmine.snapshotDeprecations()
-
-    afterEach ->
-      jasmine.restoreDeprecationsSnapshot()
-
-    it "returns the proper coerced value", ->
-      atom.config.set('editor.preferredLineLength', 0)
-      expect(atom.config.getPositiveInt('editor.preferredLineLength', 80)).toBe 1
-
-    it "returns the proper coerced value", ->
-      atom.config.set('editor.preferredLineLength', -1234)
-      expect(atom.config.getPositiveInt('editor.preferredLineLength', 80)).toBe 1
-
-    it "returns the default value when a string is passed in", ->
-      atom.config.set('editor.preferredLineLength', 'abcd')
-      expect(atom.config.getPositiveInt('editor.preferredLineLength', 80)).toBe 80
-
-    it "returns the default value when null is passed in", ->
-      atom.config.set('editor.preferredLineLength', null)
-      expect(atom.config.getPositiveInt('editor.preferredLineLength', 80)).toBe 80
-
-  describe ".save()", ->
-    CSON = require 'season'
-
-    beforeEach ->
-      spyOn(CSON, 'writeFileSync')
-      jasmine.unspy atom.config, 'save'
-
-    describe "when ~/.atom/config.json exists", ->
-      it "writes any non-default properties to ~/.atom/config.json", ->
-        atom.config.configFilePath = path.join(atom.config.configDirPath, "atom.config.json")
-        atom.config.set("a.b.c", 1)
-        atom.config.set("a.b.d", 2)
-        atom.config.set("x.y.z", 3)
-        atom.config.setDefaults("a.b", e: 4, f: 5)
-
-        CSON.writeFileSync.reset()
-        atom.config.save()
-
-        expect(CSON.writeFileSync.argsForCall[0][0]).toBe path.join(atom.config.configDirPath, "atom.config.json")
-        writtenConfig = CSON.writeFileSync.argsForCall[0][1]
-        expect(writtenConfig).toEqual global: atom.config.settings
-
-    describe "when ~/.atom/config.json doesn't exist", ->
-      it "writes any non-default properties to ~/.atom/config.cson", ->
-        atom.config.configFilePath = path.join(atom.config.configDirPath, "atom.config.cson")
-        atom.config.set("a.b.c", 1)
-        atom.config.set("a.b.d", 2)
-        atom.config.set("x.y.z", 3)
-        atom.config.setDefaults("a.b", e: 4, f: 5)
-
-        CSON.writeFileSync.reset()
-        atom.config.save()
-
-        expect(CSON.writeFileSync.argsForCall[0][0]).toBe path.join(atom.config.configDirPath, "atom.config.cson")
-        writtenConfig = CSON.writeFileSync.argsForCall[0][1]
-        expect(writtenConfig).toEqual global: atom.config.settings
-
-    describe "when scoped settings are defined", ->
-      it 'writes out explicitly set config settings', ->
-        atom.config.set('foo.bar', 'ruby', scopeSelector: '.source.ruby')
-        atom.config.set('foo.omg', 'wow', scopeSelector: '.source.ruby')
-        atom.config.set('foo.bar', 'coffee', scopeSelector: '.source.coffee')
-
-        CSON.writeFileSync.reset()
-        atom.config.save()
-
-        writtenConfig = CSON.writeFileSync.argsForCall[0][1]
-        expect(writtenConfig).toEqualJson
-          global:
-            atom.config.settings
-          '.ruby.source':
-            foo:
-              bar: 'ruby'
-              omg: 'wow'
-          '.coffee.source':
-            foo:
-              bar: 'coffee'
-
-  describe ".setDefaults(keyPath, defaults)", ->
-    it "assigns any previously-unassigned keys to the object at the key path", ->
-      atom.config.set("foo.bar.baz", a: 1)
-      atom.config.setDefaults("foo.bar.baz", a: 2, b: 3, c: 4)
-      expect(atom.config.get("foo.bar.baz.a")).toBe 1
-      expect(atom.config.get("foo.bar.baz.b")).toBe 3
-      expect(atom.config.get("foo.bar.baz.c")).toBe 4
-
-      atom.config.setDefaults("foo.quux", x: 0, y: 1)
-      expect(atom.config.get("foo.quux.x")).toBe 0
-      expect(atom.config.get("foo.quux.y")).toBe 1
-
-    it "emits an updated event", ->
-      updatedCallback = jasmine.createSpy('updated')
-      atom.config.onDidChange('foo.bar.baz.a', updatedCallback)
-      expect(updatedCallback.callCount).toBe 0
-      atom.config.setDefaults("foo.bar.baz", a: 2)
-      expect(updatedCallback.callCount).toBe 1
-
-  describe ".onDidChange(keyPath)", ->
+  describe ".onDidChange(keyPath, {scope})", ->
     [observeHandler, observeSubscription] = []
 
     describe 'when a keyPath is specified', ->

              default: 'omg'
        atom.config.setSchema('foo.bar.str', schema)

      it 'it respects the scoped defaults', ->
        expect(atom.config.get('foo.bar.str')).toBe 'ok'
        expect(atom.config.get('foo.bar.str', scope: ['.source.js'])).toBe 'omg'
        expect(atom.config.get('foo.bar.str', scope: ['.source.coffee'])).toBe 'ok'

  describe "scoped settings", ->
    describe ".get(scopeDescriptor, keyPath)", ->
      it "returns the property with the most specific scope selector", ->
        atom.config.addScopedSettings("config", ".source.coffee .string.quoted.double.coffee", foo: bar: baz: 42)
        atom.config.addScopedSettings("config", ".source .string.quoted.double", foo: bar: baz: 22)
        atom.config.addScopedSettings("config", ".source", foo: bar: baz: 11)

        expect(atom.config.get("foo.bar.baz", scope: [".source.coffee", ".string.quoted.double.coffee"])).toBe 42
        expect(atom.config.get("foo.bar.baz", scope: [".source.js", ".string.quoted.double.js"])).toBe 22
        expect(atom.config.get("foo.bar.baz", scope: [".source.js", ".variable.assignment.js"])).toBe 11
        expect(atom.config.get("foo.bar.baz", scope: [".text"])).toBeUndefined()

      it "favors the most recently added properties in the event of a specificity tie", ->
        atom.config.addScopedSettings("config", ".source.coffee .string.quoted.single", foo: bar: baz: 42)
        atom.config.addScopedSettings("config", ".source.coffee .string.quoted.double", foo: bar: baz: 22)

        expect(atom.config.get("foo.bar.baz", scope: [".source.coffee", ".string.quoted.single"])).toBe 42
        expect(atom.config.get("foo.bar.baz", scope: [".source.coffee", ".string.quoted.single.double"])).toBe 22

      describe 'when there are global defaults', ->
        it 'falls back to the global when there is no scoped property specified', ->
          atom.config.setDefaults("foo", hasDefault: 'ok')
          expect(atom.config.get("foo.hasDefault", scope: [".source.coffee", ".string.quoted.single"])).toBe 'ok'

      describe 'setting priority', ->
        describe 'when package settings are added after user settings', ->
          it "returns the user's setting because the user's setting has higher priority", ->
            atom.config.set("foo.bar.baz", 100, scopeSelector: ".source.coffee")
            atom.config.addScopedSettings("some-package", ".source.coffee", foo: bar: baz: 1)
            expect(atom.config.get("foo.bar.baz", scope: [".source.coffee"])).toBe 100

    describe ".set(scope, keyPath, value)", ->
      it "sets the value and overrides the others", ->
        atom.config.addScopedSettings("config", ".source.coffee .string.quoted.double.coffee", foo: bar: baz: 42)
        atom.config.addScopedSettings("config", ".source .string.quoted.double", foo: bar: baz: 22)
        atom.config.addScopedSettings("config", ".source", foo: bar: baz: 11)

        expect(atom.config.get("foo.bar.baz", scope: [".source.coffee", ".string.quoted.double.coffee"])).toBe 42

        expect(atom.config.set("foo.bar.baz", 100, scopeSelector: ".source.coffee .string.quoted.double.coffee")).toBe true
        expect(atom.config.get("foo.bar.baz", scope: [".source.coffee", ".string.quoted.double.coffee"])).toBe 100

    describe ".removeScopedSettingsForName(name)", ->
      it "allows properties to be removed by name", ->
        disposable1 = atom.config.addScopedSettings("a", ".source.coffee .string.quoted.double.coffee", foo: bar: baz: 42)
        disposable2 = atom.config.addScopedSettings("b", ".source .string.quoted.double", foo: bar: baz: 22)

        disposable2.dispose()
        expect(atom.config.get("foo.bar.baz", scope: [".source.js", ".string.quoted.double.js"])).toBeUndefined()
        expect(atom.config.get("foo.bar.baz", scope: [".source.coffee", ".string.quoted.double.coffee"])).toBe 42

    describe ".observe(scopeDescriptor, keyPath)", ->
      it 'calls the supplied callback when the value at the descriptor/keypath changes', ->
        changeSpy = jasmine.createSpy()
        atom.config.observe("foo.bar.baz", scope: [".source.coffee", ".string.quoted.double.coffee"], changeSpy)
        expect(changeSpy).toHaveBeenCalledWith(undefined)
        changeSpy.reset()

        atom.config.set("foo.bar.baz", 12)
        expect(changeSpy).toHaveBeenCalledWith(12)
        changeSpy.reset()

        disposable1 = atom.config.addScopedSettings("a", ".source .string.quoted.double", foo: bar: baz: 22)
        expect(changeSpy).toHaveBeenCalledWith(22)
        changeSpy.reset()

        disposable2 = atom.config.addScopedSettings("b", ".source.coffee .string.quoted.double.coffee", foo: bar: baz: 42)
        expect(changeSpy).toHaveBeenCalledWith(42)
        changeSpy.reset()

        disposable2.dispose()
        expect(changeSpy).toHaveBeenCalledWith(22)
        changeSpy.reset()

        disposable1.dispose()
        expect(changeSpy).toHaveBeenCalledWith(12)
        changeSpy.reset()

        atom.config.set("foo.bar.baz", undefined)
        expect(changeSpy).toHaveBeenCalledWith(undefined)
        changeSpy.reset()

    describe ".onDidChange(scopeDescriptor, keyPath)", ->
      it 'calls the supplied callback when the value at the descriptor/keypath changes', ->
        keyPath = "foo.bar.baz"
        changeSpy = jasmine.createSpy('onDidChange callback')
        atom.config.onDidChange keyPath, scope: [".source.coffee", ".string.quoted.double.coffee"], changeSpy

        atom.config.set("foo.bar.baz", 12)
        expect(changeSpy).toHaveBeenCalledWith({oldValue: undefined, newValue: 12})
        changeSpy.reset()

        disposable1 = atom.config.addScopedSettings("a", ".source .string.quoted.double", foo: bar: baz: 22)
        expect(changeSpy).toHaveBeenCalledWith({oldValue: 12, newValue: 22})
        changeSpy.reset()

        disposable2 = atom.config.addScopedSettings("b", ".source.coffee .string.quoted.double.coffee", foo: bar: baz: 42)
        expect(changeSpy).toHaveBeenCalledWith({oldValue: 22, newValue: 42})
        changeSpy.reset()

        disposable2.dispose()
        expect(changeSpy).toHaveBeenCalledWith({oldValue: 42, newValue: 22})
        changeSpy.reset()

        disposable1.dispose()
        expect(changeSpy).toHaveBeenCalledWith({oldValue: 22, newValue: 12})
        changeSpy.reset()

        atom.config.set("foo.bar.baz", undefined)
        expect(changeSpy).toHaveBeenCalledWith({oldValue: 12, newValue: undefined})
        changeSpy.reset()

      it 'deprecates using a scope descriptor as an optional first argument', ->
        keyPath = "foo.bar.baz"
        spyOn(Grim, 'deprecate')
        atom.config.onDidChange [".source.coffee", ".string.quoted.double.coffee"], keyPath, changeSpy = jasmine.createSpy()
        expect(Grim.deprecate).toHaveBeenCalled()

        atom.config.set("foo.bar.baz", 12)
        expect(changeSpy).toHaveBeenCalledWith({oldValue: undefined, newValue: 12})
        changeSpy.reset()

        disposable1 = atom.config.addScopedSettings("a", ".source .string.quoted.double", foo: bar: baz: 22)
        expect(changeSpy).toHaveBeenCalledWith({oldValue: 12, newValue: 22})
        changeSpy.reset()

        disposable2 = atom.config.addScopedSettings("b", ".source.coffee .string.quoted.double.coffee", foo: bar: baz: 42)
        expect(changeSpy).toHaveBeenCalledWith({oldValue: 22, newValue: 42})
        changeSpy.reset()

        disposable2.dispose()
        expect(changeSpy).toHaveBeenCalledWith({oldValue: 42, newValue: 22})
        changeSpy.reset()

        disposable1.dispose()
        expect(changeSpy).toHaveBeenCalledWith({oldValue: 22, newValue: 12})
        changeSpy.reset()

        atom.config.set("foo.bar.baz", undefined)
        expect(changeSpy).toHaveBeenCalledWith({oldValue: 12, newValue: undefined})
        changeSpy.reset()

        expect(atom.config.get("x.y", excludeSources: ["b", "c", "a", atom.config.getUserConfigPath()], scope: [".foo"])).toBe 4
        expect(atom.config.get("x.y", excludeSources: [atom.config.getUserConfigPath()])).toBe 4

    describe "when a 'scope' option is given", ->
      it "returns the property with the most specific scope selector", ->
        atom.config.addScopedSettings("config", ".source.coffee .string.quoted.double.coffee", foo: bar: baz: 42)
        atom.config.addScopedSettings("config", ".source .string.quoted.double", foo: bar: baz: 22)
        atom.config.addScopedSettings("config", ".source", foo: bar: baz: 11)

        expect(atom.config.get("foo.bar.baz", scope: [".source.coffee", ".string.quoted.double.coffee"])).toBe 42
        expect(atom.config.get("foo.bar.baz", scope: [".source.js", ".string.quoted.double.js"])).toBe 22
        expect(atom.config.get("foo.bar.baz", scope: [".source.js", ".variable.assignment.js"])).toBe 11
        expect(atom.config.get("foo.bar.baz", scope: [".text"])).toBeUndefined()

      it "favors the most recently added properties in the event of a specificity tie", ->
        atom.config.addScopedSettings("config", ".source.coffee .string.quoted.single", foo: bar: baz: 42)
        atom.config.addScopedSettings("config", ".source.coffee .string.quoted.double", foo: bar: baz: 22)

        expect(atom.config.get("foo.bar.baz", scope: [".source.coffee", ".string.quoted.single"])).toBe 42
        expect(atom.config.get("foo.bar.baz", scope: [".source.coffee", ".string.quoted.single.double"])).toBe 22

      describe 'when there are global defaults', ->
        it 'falls back to the global when there is no scoped property specified', ->
          atom.config.setDefaults("foo", hasDefault: 'ok')
          expect(atom.config.get("foo.hasDefault", scope: [".source.coffee", ".string.quoted.single"])).toBe 'ok'

      describe 'when package settings are added after user settings', ->
        it "returns the user's setting because the user's setting has higher priority", ->
          atom.config.set("foo.bar.baz", 100, scopeSelector: ".source.coffee")
          atom.config.addScopedSettings("some-package", ".source.coffee", foo: bar: baz: 1)
          expect(atom.config.get("foo.bar.baz", scope: [".source.coffee"])).toBe 100

  describe ".set(keyPath, value, {source, scopeSelector})", ->
    it "allows a key path's value to be written", ->
      expect(atom.config.set("foo.bar.baz", 42)).toBe true
      expect(atom.config.get("foo.bar.baz")).toBe 42
