Re-order and wordsmith tests.

Re-order and wordsmith tests.

--- test/TinyMock.test.coffee
+++ test/TinyMock.test.coffee
@@ -4,9 +4,10 @@
 messages  = require("../messages/messages.en.json")

+
 describe "assumptions", ->

-  describe "class Object", ->
+  describe "Object", ->

     it "does not have the property or method 'expects'", ->
       should.not.exist(Object.expects)
@@ -20,7 +21,7 @@
       should.not.exist(Object.my_method)
       should.not.exist(Object.prototype.my_method)

-  describe "instance of Object", ->
+  describe "an instance of Object", ->

     it "does not have the property or method 'my_method'", ->
       o = new Object()
@@ -33,11 +34,12 @@
         m.should.not.respondTo("my_method")

+
 describe "general behaviour", ->

-  describe "class method", ->
-
-    it "allows different expectations of the same class method on a class", ->
+  describe "mocking a class method", ->
+
+    it "allows different expectations of the same method on a class", ->
       class Klass
         @class_method: -> "class method"
       mock ->
@@ -46,7 +48,7 @@
         Klass.class_method(1).should.equal("one")             # forces a check for duplicate expectations
         Klass.class_method(2).should.equal("two")             # otherwise we'll get a 'class_method not called' error

-    it "allows the same expectation of the same class method on different classes", ->
+    it "allows the same expectation of the same method on different classes", ->
       class Klass1
         @class_method: -> "class method 1"
       class Klass2
@@ -57,7 +59,7 @@
         Klass1.class_method(1).should.equal("one")            # forces a check for duplicate expectations
         Klass2.class_method(1).should.equal("one")            # otherwise we'll get a 'class_method not called' error

-    it "allows different expectations of the same class method on different classes", ->
+    it "allows different expectations of the same method on different classes", ->
       class Klass1
         @class_method: -> "class method 1"
       class Klass2
@@ -68,7 +70,7 @@
         Klass1.class_method(1).should.equal("one")            # forces a check for duplicate expectations
         Klass2.class_method(2).should.equal("two")            # otherwise we'll get a 'class_method not called' error

-    it "allows different expectations of different class methods on different classes", ->
+    it "allows different expectations of different methods on different classes", ->
       class Klass1
         @class_method1: -> "class method 1"
       class Klass2
@@ -79,9 +81,9 @@
         Klass1.class_method1(1).should.equal("one")           # forces a check for duplicate expectations
         Klass2.class_method2(2).should.equal("two")           # otherwise we'll get a 'class_method not called' error

-  describe "instance method", ->
-
-    it "allows different expectations of the same instance method on an class", ->
+  describe "mocking an instance method", ->
+
+    it "allows different expectations of the same method on an class", ->
       class Klass
         instance_method: -> "instance method"
       k = new Klass()
@@ -90,16 +92,6 @@
         Klass.prototype.expects("instance_method").args(2).returns("two")
         k.instance_method(1).should.equal("one")              # forces a check for duplicate expectations
         k.instance_method(2).should.equal("two")              # otherwise we'll get a 'class_method not called' error
-
-    it "throws an error if an expectation of an instance method on a class does not exist", ->
-      class Klass
-        instance_method: -> "instance method"
-      k = new Klass()
-      (->
-        mock ->
-          Klass.prototype.expects("instance_method").args(1)
-          k.instance_method(2)
-      ).should.throw(format(messages.UnknownExpectation, "instance_method", "2"))

     it "allows the same expectation of the same method on different classes", ->
       class Klass1
@@ -140,30 +132,30 @@
         k1.instance_method1(1).should.equal("one")            # forces a check for duplicate expectations
         k2.instance_method2(2).should.equal("two")            # otherwise we'll get an 'instance_method not called' error

-  describe "object method", ->
-
-    it "allows different expectations of the same object method on an object", ->
+  describe "mocking an object method", ->
+
+    it "allows different expectations of the same method on an object", ->
       mock (m) ->
         m.expects("object_method").args(1).returns("one")
         m.expects("object_method").args("two").returns(2)
         m.object_method(1).should.equal("one")                # forces a check for duplicate expectations
         m.object_method("two").should.equal(2)                # otherwise we'll get a 'object_method not called' error

-    it "allows the same expectation of the same object method on different objects", ->
+    it "allows the same expectation of the same method on different objects", ->
       mock (m1, m2) ->
         m1.expects("object_method").args(1).returns("one")
         m2.expects("object_method").args(1).returns("one")
         m1.object_method(1).should.equal("one")               # forces a check for duplicate expectations
         m2.object_method(1).should.equal("one")               # otherwise we'll get a 'object_method not called' error

-    it "allows the different expectations of the same object method on different objects", ->
+    it "allows the different expectations of the same method on different objects", ->
       mock (m1, m2) ->
         m1.expects("object_method").args(1).returns("one")
         m2.expects("object_method").args(2).returns("two")
         m1.object_method(1).should.equal("one")               # forces a check for duplicate expectations
         m2.object_method(2).should.equal("two")               # otherwise we'll get a 'object_method not called' error

-    it "allows the different expectations of different object methods on different objects", ->
+    it "allows the different expectations of different methods on different objects", ->
       mock (m1, m2) ->
         m1.expects("object_method1").args(1).returns("one")
         m2.expects("object_method2").args(2).returns("two")
@@ -171,341 +163,340 @@
         m2.object_method2(2).should.equal("two")              # otherwise we'll get a 'object_method not called' error

-describe "mock( [ options ], ( [ mock_object, ... ] ) -> )", ->
-
-  it "adds an expects() method to Object.prototype", ->
-    mock ->
-      should.exist(Object.prototype.expects)
-    # TODO: test that expects() gets removed
-
-  it "passes five mock objects to the callback test function", ->
-    mock (mocks...) ->
-      mocks.length.should.equal(5)
-
-  it "throws an error if there are no arguments", ->
-    (->
-      mock()  # need parenthesis to coerce function call
-    ).should.throw(messages.MockUsage)
-
-  it "throws an error if there are more than two arguments", ->
-    (->
-      mock 1, 2, 3
-    ).should.throw(messages.MockUsage)
-
-  it "throws an error if there is one argument and it is not a function", ->
-    (->
-      mock 1
-    ).should.throw(messages.MockUsage)
-
-  it "throws an error if there are two arguments and the second one is not a function", ->
-    (->
-      mock expects_method_name: "expects", 1
-    ).should.throw(messages.MockUsage)
-
-  it "throws an error if the options arguments has neither the expects_method_name nor the mock_count properties", ->
-    (->
-      mock a: "expects", b: 3, -> 0
-    ).should.throw(messages.MockBadUsage)
-
-  it "adds expects() to Object so that it is available on all objects", ->
-    mock ->
-      Object.should.respondTo("expects")
-
-  it "adds the expects method name that was passed as an option to mock()", ->
-    mock expects_method_name: "my_expects", ->
-      Object.should.respondTo("my_expects")
-
-  it "does not affect existing expects() methods if an alternate name was passed as an option to mock()", ->
-    class Klass
-      expects: -> "pre-existing expects() method"
-    k = new Klass()
-    mock expects_method_name: "my_expects", ->
-      k.my_expects("expects").returns("overridden expects() method")
-      k.expects().should.equal("overridden expects() method")
-
-  it "removes expects() from Object after running the passed function", ->
-    mock ->
-      # empty
-    Object.should.not.respondTo("expects")
-
-  it "removes the expects method name that was passed as an option to mock()", ->
-    mock expects_method_name: "my_expects", ->
-      # empty
-    Object.should.not.respondTo("my_expects")
-
-  it "removes expects() from Object when the passed function throws an error", ->
-    try
-      mock ->
-        throw new Error("an error")
-    catch error
-      # ignore
-    Object.should.not.respondTo("expects")
-
-  it "removes the expects method name that was passed as an option to mock() when the passed function throws an error", ->
-    try
+
+describe "mock", ->
+
+  describe "mock test_function", ->
+
+    it "adds expects() to Object so that it is available on all objects", ->
+      mock ->
+        Object.should.respondTo("expects")
+
+    it "removes expects() from Object after running test_function", ->
+      mock ->
+        # empty
+      Object.should.not.respondTo("expects")
+
+    it "removes expects() from Object even if test_function throws an error", ->
+      try
+        mock ->
+          throw new Error("an error")
+      catch
+        # ignore
+      Object.should.not.respondTo("expects")
+
+    it "throws an error if expects() is already a method of Object", ->
+      try
+        Object.prototype.expects = -> "existing expects method"
+        (->
+          mock ->
+            # empty
+        ).should.throw(format(messages.ExpectsMethodAlreadyExists, "expects"))
+      finally
+        delete Object.prototype.expects
+
+  describe "mock expects_method_name: 'expects2', test_function", ->
+
+    it "adds the expects_method_name (e.g. 'expects2') to Object", ->
       mock expects_method_name: "my_expects", ->
-        throw new Error("an error")
-    catch error
-      # ignore
-    Object.should.not.respondTo("my_expects")
-
-  it "throws an error if expects() is already a method of Object", ->
-    try
-      Object.prototype.expects = -> "existing expects method"
+        Object.should.respondTo("my_expects")
+
+    it "removes the expects_method_name from Object after running test_function", ->
+      mock expects_method_name: "my_expects", ->
+        # empty
+      Object.should.not.respondTo("my_expects")
+
+    it "removes the expects_method_name from Object even if test_function throws an error", ->
+      try
+        mock expects_method_name: "my_expects", ->
+          throw new Error("an error")
+      catch
+        # ignore
+      Object.should.not.respondTo("my_expects")
+
+    it "throws an error if the expects_method_name is already a method of Object", ->
+      try
+        Object.prototype.my_expects = -> "existing my_expects method"
+        (->
+          mock expects_method_name: "my_expects", ->
+            # empty
+        ).should.throw(format(messages.ExpectsMethodAlreadyExists, "my_expects"))
+      finally
+        delete Object.prototype.my_expects
+
+    it "does not affect a pre-existing expects() method", ->
+      class Klass
+        expects: -> "pre-existing expects() method"
+      k = new Klass()
+      mock expects_method_name: "my_expects", ->
+        k.my_expects("expects").returns("overridden expects() method")
+        k.expects().should.equal("overridden expects() method")
+
+  describe "mock test_function( mock_object [, ...] )", ->
+
+    it "passes pre-created MockObjects to test_function", ->
+      mock (m) ->
+        m.constructor.name.should.equal("MockObject")
+
+    it "passes five mock objects to test_function", ->
+      mock (mocks...) ->
+        mocks.length.should.equal(5)
+
+    it "allows one mock object to use another", ->
+      mock (m1, m2) ->
+        m1.expects("my_method").returns(m2)
+        m1.my_method().should.equal(m2)
+
+  describe "mock mock_count: 10, test_function( mock_objects... )", ->
+
+    it "passes mock_count mock objects to test_function", ->
+      mock mock_count: 17, (m...) ->
+        m.length.should.equal(17)
+
+  describe "expectation validation", ->
+
+    it "does nothing if all expectations are met", ->
+      mock (m1, m2) ->
+          m1.expects("my_method1").args(1,2,3)
+          m2.expects("my_method2")
+          m1.my_method1(1,2,3)
+          m2.my_method2()
+
+    it "reports all unmet expectations", ->
+      (->
+        mock (m1, m2) ->
+          m1.expects("my_method1").args(1,2,3)
+          m2.expects("my_method2")
+      ).should.throw("#{format(messages.ExpectationNeverCalled, 'my_method1', '1,2,3')}\n#{format(messages.ExpectationNeverCalled, 'my_method2', '')}\n")
+
+    it "does not report unmet expectations if test_function throws an error", ->
+      (->
+        mock (m) ->
+          m.expects("my_method").throws(new Error("an error"))
+          m.my_method()
+      ).should.throw(/^an error$/)
+
+    it "does not eat errors thrown by test_function", ->
       (->
         mock ->
-          # empty
+          throw new Error("an error")
+      ).should.throw("an error")
+
+  describe "cleanup", ->
+
+    it "restores the original class method", ->
+      original_method = -> "original method"
+      class Klass
+        @class_method: original_method
+      mock ->
+        Klass.expects("class_method")
+        Klass.class_method()    # otherwise we'll get a 'class_method() not called' error
+      Klass.class_method.should.equal(original_method)
+
+    it "restores the original instance method", ->
+      original_method = -> "original method"
+      class Klass
+        instance_method: original_method
+      mock ->
+        Klass.prototype.expects("instance_method")
+        (new Klass()).instance_method()   # otherwise we'll get an 'instance_method() not called' error
+      Klass.prototype.instance_method.should.equal(original_method)
+
+    it "restores the original object method", ->
+      original_method = -> "original method"
+      o = { object_method: original_method }
+      mock ->
+        o.expects("object_method")
+        o.object_method()     # otherwise we'll get a 'class_method() not called' error
+      o.object_method.should.equal(original_method)
+
+    it "restores the orginal method even if the same method has more than one expectation", ->
+      original_method = -> "anything"
+      o = { object_method: original_method }
+      mock ->
+        o.expects("object_method").args(1)
+        o.expects("object_method").args(2)
+        o.object_method(1)    # otherwise we'll get a 'class_method() not called' error
+        o.object_method(2)    # -- ditto --
+      o.object_method.should.equal(original_method)
+
+  describe "usage errors", ->
+
+    it "throws an error if there are no arguments", ->
+      (->
+        mock()  # need parenthesis to coerce function call
+      ).should.throw(messages.MockUsage)
+
+    it "throws an error if there are more than two arguments", ->
+      (->
+        mock 1, 2, 3
+      ).should.throw(messages.MockUsage)
+
+    it "throws an error if there is one argument and it is not a function", ->
+      (->
+        mock 1
+      ).should.throw(messages.MockUsage)
+
+    it "throws an error if there are two arguments and the second one is not a function", ->
+      (->
+        mock expects_method_name: "expects", 1
+      ).should.throw(messages.MockUsage)
+
+    it "throws an error if the options arguments has neither the expects_method_name nor the mock_count properties", ->
+      (->
+        mock a: "expects", b: 3, -> 0
+      ).should.throw(messages.MockBadUsage)
+
+  describe "miscellaneous", ->
+
+    it "cannot be nested without specifying expects_method_name (no reason to do this but we'll test it anyway)", ->
+      (->
+        mock (m1) ->
+          mock (m2) ->
+            # empty
       ).should.throw(format(messages.ExpectsMethodAlreadyExists, "expects"))
-    finally
-      delete Object.prototype.expects
-
-  it "throws an error if the expects method name that was passed as an option to mock() is already a method of Object", ->
-    try
-      Object.prototype.my_expects = -> "existing my_expects method"
-      (->
-        mock expects_method_name: "my_expects", ->
-          # empty
-      ).should.throw(format(messages.ExpectsMethodAlreadyExists, "my_expects"))
-    finally
-      delete Object.prototype.my_expects
-
-  it "does not eat errors thrown by the passed function", ->
-    (->
-      mock ->
-        throw new Error("an error")
-    ).should.throw("an error")
-
-  it "passes pre-created convenience Mock objects to the function argument", ->
-    mock (m) ->
-      m.constructor.name.should.equal("MockObject")
-
-  it "passes 5 mock objects to the function argument", ->
-    mock (m...) ->
-      m.length.should.equal(5)
-
-  it "passes mock_count mock objects to the function argument when the mock_count option is used", ->
-    mock mock_count: 17, (m...) ->
-      m.length.should.equal(17)
-
-  it "cannot be nested without specifying expects_method_name (no reason to do this but we'll test it anyway)", ->
-    (->
-      mock (m1) ->
-        mock (m2) ->
-          # empty
-    ).should.throw(format(messages.ExpectsMethodAlreadyExists, "expects"))
-
-  it "can be nested if expects_method_name is specified (no reason to do this but we'll test it anyway)", ->
-    mock (m0) ->
-      mock expects_method_name: "my_expects1", (m1) ->
-        mock expects_method_name: "my_expects2", (m2) ->
-          m0.expects("my_method0")
-          m1.my_expects1("my_method1")
-          m2.my_expects2("my_method2")
-          m0.my_method0()
-          m1.my_method1()
-          m2.my_method2()
-
-  it "allows one mock object to use another", ->
-    mock (m1, m2) ->
-      m1.expects("my_method").returns(m2)
-      m1.my_method().should.equal(m2)
-
-  it "reports all unmet expectations", ->
-    (->
-      mock (m1, m2) ->
-        m1.expects("my_method1").args(1,2,3)
-        m2.expects("my_method2")
-    ).should.throw("#{format(messages.ExpectationNeverCalled, 'my_method1', '1,2,3')}\n#{format(messages.ExpectationNeverCalled, 'my_method2', '')}\n")
-
-  it "restores the original class method", ->
-    original_method = -> "original method"
-    class Klass
-      @class_method: original_method
-    mock ->
-      Klass.expects("class_method")
-      Klass.class_method()    # otherwise we'll get a 'class_method() not called' error
-    Klass.class_method.should.equal(original_method)
-
-  it "restores the original instance method", ->
-    original_method = -> "original method"
-    class Klass
-      instance_method: original_method
-    mock ->
-      Klass.prototype.expects("instance_method")
-      (new Klass()).instance_method()   # otherwise we'll get an 'instance_method() not called' error
-    Klass.prototype.instance_method.should.equal(original_method)
-
-  it "restores the original object method", ->
-    original_method = -> "original method"
-    o = { object_method: original_method }
-    mock ->
-      o.expects("object_method")
-      o.object_method()     # otherwise we'll get a 'class_method() not called' error
-    o.object_method.should.equal(original_method)
-
-  it "restores the orginal method when the same method has more than one expectation", ->
-    original_method = -> "anything"
-    o = { object_method: original_method }
-    mock ->
-      o.expects("object_method").args(1)
-      o.expects("object_method").args(2)
-      o.object_method(1)    # otherwise we'll get a 'class_method() not called' error
-      o.object_method(2)    # -- ditto --
-    o.object_method.should.equal(original_method)
-
-  it "checks expectations for errors if the passed function did not throw an error", ->
-    (->
-      mock (m) ->
-        m.expects("my_method")
-    ).should.throw(format(messages.ExpectationNeverCalled, "my_method", ""))
-
-  it "does not check expectations for errors if the passed function throws an error", ->
-    (->
-      mock (m) ->
-        m.expects("my_method").throws(new Error("an error"))
-        m.my_method()
-    ).should.throw(/^an error$/)
+
+    it "can be nested if expects_method_name is specified (no reason to do this but we'll test it anyway)", ->
+      mock (m0) ->
+        mock expects_method_name: "my_expects1", (m1) ->
+          mock expects_method_name: "my_expects2", (m2) ->
+            m0.expects("my_method0")
+            m1.my_expects1("my_method1")
+            m2.my_expects2("my_method2")
+            m0.my_method0()
+            m1.my_method1()
+            m2.my_method2()
+

 describe "expects( method_name )", ->

-  it "can mock a class method", ->
-    class Klass
-      @class_method: -> "class method"
-    mock ->
-      Klass.expects("class_method").returns("mock method")
-      Klass.class_method().should.equal("mock method")
-    # TODO: test that the original method is restored
-
-  it "can mock an instance method", ->
-    class Klass
-      instance_method: -> "instance method"
-    mock ->
-      Klass.prototype.expects("instance_method").returns("mock method")
-      (new Klass()).instance_method().should.equal("mock method")
-    # TODO: test that the original method is restored
-
-  it "can mock an object method", ->
-    o = { object_method: -> "object method" }
-    mock ->
-      o.expects("object_method").returns("mock method")
-      o.object_method().should.equal("mock method")
-    # TODO: test that the original method is restored
-
-  it "throws an error if called on an object that does not inherit from Object", ->
-    o = Object.create(null)
-    o.my_method = -> "my method"
-    (->
-      mock ->
-        o.expects("my_method")
-    ).should.throw("Object object has no method 'expects'")
-
-  it "adds method_name to mock object instances passed in by mock()", ->
-    mock (m) ->
-      m.expects("my_method")
-      (typeof m.my_method).should.equal('function')
-      m.my_method()                 # otherwise we'll get a 'my_method not called' error
-
-  it "mocks method_name on instances of classes that were not passed in by mock()", ->
-    existing_method = -> "existing method"
-    class Klass
-      my_method: existing_method
-    k = new Klass()
-    mock ->
-      k.expects("my_method")
-      k.my_method.should.not.equal(existing_method)
-      k.my_method()                 # otherwise we'll get a 'my_method not called' error
-
-  it "mocks method_name on instances that were not passed in by mock()", ->
-    existing_method = -> "existing method"
-    o = new Object()
-    o.my_method = existing_method
-    mock ->
-      o.expects("my_method")
-      o.my_method.should.not.equal(existing_method)
-      o.my_method()                 # otherwise we'll get a 'my_method not called' error
-
-  it "throws an error if method_name does not already exist on an instance of a class that was not passed in by mock()", ->
-    class Klass
-      some_method: -> "some method"
-    k = new Klass()
-    (->
-      mock ->
-        k.expects("my_method")
-    ).should.throw(format(messages.NotAnExistingMethod, "my_method"))
-
-  it "throws an error if method_name does not already exist on an instance that was not passed in by mock()", ->
-    o = new Object()
-    o.some_method = "some method"
-    (->
-      mock ->
-        o.expects("my_method")
-    ).should.throw(format(messages.NotAnExistingMethod, "my_method"))
-
-  # TODO: expects() should throw an error, stubs() should not?
-  it "throws an error if method_name does not already exist on a class", ->
-    class Klass
-      # empty
-    (->
-      mock ->
-        Klass.expects("my_method")
-    ).should.throw(format(messages.NotAnExistingMethod, "my_method"))
-
-  it "throws an error if method_name is already a property on an instance", ->
-    o = new Object()
-    o.my_method = "a property"
-    (->
-      mock ->
-        o.expects("my_method")
-    ).should.throw(format(messages.PreExistingProperty, "my_method"))
-
-  it "throws an error if method_name is already a property on a class", ->
-    try
-      Object.prototype.my_method = "a property"
+  describe "on regular objects", ->
+
+    it "can mock a class method", ->
+      class Klass
+        @class_method: -> "class method"
+      mock ->
+        Klass.expects("class_method").returns("mock method")
+        Klass.class_method().should.equal("mock method")
+      # TODO: test that the original method is restored
+
+    it "can mock an instance method", ->
+      class Klass
+        instance_method: -> "instance method"
+      mock ->
+        Klass.prototype.expects("instance_method").returns("mock method")
+        (new Klass()).instance_method().should.equal("mock method")
+      # TODO: test that the original method is restored
+
+    it "can mock an object method", ->
+      o = { object_method: -> "object method" }
+      mock ->
+        o.expects("object_method").returns("mock method")
+        o.object_method().should.equal("mock method")
+      # TODO: test that the original method is restored
+
+  describe "on mock objects (those passed in by mock())", ->
+
+    it "can mock an object method", ->
+      mock (m) ->
+        m.expects("my_method").returns("mock method")
+        m.my_method().should.equal("mock method")
+
+  describe "usage errors", ->
+
+    it "throws an error if method_name is missing", ->
+      (->
+        mock (m) ->
+          m.expects()
+      ).should.throw(format(messages.ExpectsUsage, "my_method"))
+
+    it "throws an error if more than one argument is specified", ->
+      (->
+        mock (m) ->
+          m.expects("my_method1", "my_method2")
+      ).should.throw(format(messages.ExpectsUsage))
+
+    it "throws an error if method_name is the reserved name 'expects' and no expects_method_name was specified to mock()", ->
+      (->
+        mock (m) ->
+          m.expects("expects")
+      ).should.throw(format(messages.ReservedMethodName, "expects"))
+
+    it "throws an error if method_name is the same as expects_method_name specified to mock()", ->
+      (->
+        mock expects_method_name: "my_expects", (m) ->
+          m.my_expects("my_expects")
+      ).should.throw(format(messages.ReservedMethodName, "my_expects"))
+
+    it "throws an error if called on an object that does not inherit from Object", ->
+      o = Object.create(null)
+      o.my_method = -> "my method"
       (->
         mock ->
-          Object.expects("my_method")
+          o.expects("my_method")
+      ).should.throw("Object object has no method 'expects'")
+
+    it "throws an error if method_name does not already exist on an instance of a class that was not passed in by mock()", ->
+      class Klass
+        some_method: -> "some method"
+      k = new Klass()
+      (->
+        mock ->
+          k.expects("my_method")
+      ).should.throw(format(messages.NotAnExistingMethod, "my_method"))
+
+    it "throws an error if method_name does not already exist on an instance that was not passed in by mock()", ->
+      o = new Object()
+      o.some_method = "some method"
+      (->
+        mock ->
+          o.expects("my_method")
+      ).should.throw(format(messages.NotAnExistingMethod, "my_method"))
+
+    # TODO: expects() should throw an error, stubs() should not?
+    it "throws an error if method_name does not already exist on a class", ->
+      class Klass
+        # empty
+      (->
+        mock ->
+          Klass.expects("my_method")
+      ).should.throw(format(messages.NotAnExistingMethod, "my_method"))
+
+    it "throws an error if method_name is already a property on an instance", ->
+      o = new Object()
+      o.my_method = "a property"
+      (->
+        mock ->
+          o.expects("my_method")
       ).should.throw(format(messages.PreExistingProperty, "my_method"))
-    finally
-      delete Object.prototype.my_method
-
-  it "can be used many times to expect different methods", ->
-    mock (m) ->
-      m.expects("my_method1")
-      m.expects("my_method2")
-      m.my_method1()                # otherwise we'll get a 'my_method1 not called' error
-      m.my_method2()                # -- ditto --
-
-  it "can be used after expected methods have been used (harmless but bad form)", ->
-    mock (m) ->
-      m.expects("my_method1")
-      m.my_method1()
-      m.expects("my_method2")
-      m.my_method2()                # otherwise we'll get a 'my_method2 not called' error
-
-  it "throws an error if method_name is missing", ->
-    (->
-      mock (m) ->
-        m.expects()
-    ).should.throw(format(messages.ExpectsUsage, "my_method"))
-
-  it "throws an error if more than one argument is specified", ->
-    (->
-      mock (m) ->
-        m.expects("my_method1", "my_method2")
-    ).should.throw(format(messages.ExpectsUsage))
-
-  it "throws an error if method_name is the reserved name 'expects'", ->
-    (->
-      mock (m) ->
-        m.expects("expects")
-    ).should.throw(format(messages.ReservedMethodName, "expects"))
-
-  it "throws an error if method_name is the alternate name for 'expects' that is specified to mocks()", ->
-    (->
-      mock expects_method_name: "my_expects", (m) ->
-        m.my_expects("my_expects")
-    ).should.throw(format(messages.ReservedMethodName, "my_expects"))
+
+    it "throws an error if method_name is already a property on a class", ->
+      try
+        Object.prototype.my_method = "a property"
+        (->
+          mock ->
+            Object.expects("my_method")
+        ).should.throw(format(messages.PreExistingProperty, "my_method"))
+      finally
+        delete Object.prototype.my_method
+
+  describe "miscellaneous", ->
+
+    it "can be used many times to expect different methods", ->
+      mock (m) ->
+        m.expects("my_method1")
+        m.expects("my_method2")
+        m.my_method1()                # otherwise we'll get a 'my_method1 not called' error
+        m.my_method2()                # -- ditto --
+
+    it "can be used after expectations have been met (harmless but bad form)", ->
+      mock (m) ->
+        m.expects("my_method1")
+        m.my_method1()
+        m.expects("my_method2")
+        m.my_method2()                # otherwise we'll get a 'my_method2 not called' error
+

 describe "args( arg [, arg ... ] )", ->
@@ -516,39 +507,37 @@
       expectation.args(1).should.equal(expectation)
       m.my_method(1)  # otherwise we'll get a 'my_method() not called' error

-  it "throws an error if no arguments are specified", ->
-    (->
-      mock (m) ->
-        m.expects("my_method").args()
-    ).should.throw(format(messages.ArgsUsage))
-
-  it "throws an error if args() has already been specified", ->
-    (->
-      mock (m) ->
-        m.expects("my_method").args(1,2,3).args("a","b","c")
-    ).should.throw(format(messages.ArgsUsedMoreThanOnce))
-
-  it "throws an error if called after returns()", ->
-    (->
-      mock (m) ->
-        m.expects("my_method").returns(42).args(1,2,3)
-    ).should.throw(format(messages.ArgsUsedAfterReturnsOrThrows))
-
-  it "throws an error if called after throws()", ->
-    (->
-      mock (m) ->
-        m.expects("my_method").throws(new Error("an error")).args(1,2,3)
-    ).should.throw(format(messages.ArgsUsedAfterReturnsOrThrows))
-
-  it "wraps strings with quotes in expection messages"
+  describe "usage errors", ->
+
+    it "throws an error if no arguments are specified", ->
+      (->
+        mock (m) ->
+          m.expects("my_method").args()
+      ).should.throw(format(messages.ArgsUsage))
+
+    it "throws an error if args() has already been specified", ->
+      (->
+        mock (m) ->
+          m.expects("my_method").args(1,2,3).args("a","b","c")
+      ).should.throw(format(messages.ArgsUsedMoreThanOnce))
+
+    it "throws an error if called after returns()", ->
+      (->
+        mock (m) ->
+          m.expects("my_method").returns(42).args(1,2,3)
+      ).should.throw(format(messages.ArgsUsedAfterReturnsOrThrows))
+
+    it "throws an error if called after throws()", ->
+      (->
+        mock (m) ->
+          m.expects("my_method").throws(new Error("an error")).args(1,2,3)
+      ).should.throw(format(messages.ArgsUsedAfterReturnsOrThrows))
+
+    it "wraps strings with quotes in expection messages"
+

 describe "returns( value )", ->
-
-  it "causes the mock method to return the specified value", ->
-    mock (m) ->
-      m.expects("my_method").returns("return value")
-      m.my_method().should.equal("return value")

   it "returns itself", ->
     mock (m) ->
@@ -556,51 +545,54 @@
       expectation.returns(1).should.equal(expectation)
       m.my_method()   # otherwise we'll get a 'my_method() not called' error

-  it "throws an error if no 'value' argument is specified", ->
-    (->
-      mock (m) ->
-        m.expects("my_method").returns()
-    ).should.throw(format(messages.ReturnsUsage))
-
-  it "throws an error if more than one argument is specified", ->
-    (->
-      mock (m) ->
-        m.expects("my_method").returns(1, 2)
-    ).should.throw(format(messages.ReturnsUsage))
-
-  it "throws an error if returns() has already been specified", ->
-    (->
-      mock (m) ->
-        m.expects("my_method").returns(42).returns("abc")
-    ).should.throw(format(messages.ReturnsUsedMoreThanOnce))
-
-  it "throws an error if a throws error has already been specified", ->
-    (->
-      mock (m) ->
-        m.expects("my_method").throws(new Error("an error")).returns(42)
-    ).should.throw(format(messages.ReturnsAndThrowsBothUsed))
+  it "causes the mock method to return the specified value", ->
+    mock (m) ->
+      m.expects("my_method").returns("return value")
+      m.my_method().should.equal("return value")

   it "can be called after args()", ->
     mock (m) ->
       m.expects("my_method").args(1,2,3).returns(42)
       m.my_method(1,2,3)

-  it "cannot be called more than once on the same expectation", ->
-    (->
-      mock (m) ->
-        m.expects("my_method").returns(1)
-        m.expects("my_method").returns(2)
-        m.my_method()
-    ).should.throw(format(messages.DuplicateExpectation, "my_method", ""))
-
-
+  describe "usage errors", ->
+
+    it "throws an error if no 'value' argument is specified", ->
+      (->
+        mock (m) ->
+          m.expects("my_method").returns()
+      ).should.throw(format(messages.ReturnsUsage))
+
+    it "throws an error if more than one argument is specified", ->
+      (->
+        mock (m) ->
+          m.expects("my_method").returns(1, 2)
+      ).should.throw(format(messages.ReturnsUsage))
+
+    it "throws an error if returns() has already been used", ->
+      (->
+        mock (m) ->
+          m.expects("my_method").returns(42).returns("abc")
+      ).should.throw(format(messages.ReturnsUsedMoreThanOnce))
+
+    it "throws an error if a throws error has already been specified", ->
+      (->
+        mock (m) ->
+          m.expects("my_method").throws(new Error("an error")).returns(42)
+      ).should.throw(format(messages.ReturnsAndThrowsBothUsed))
+
+    it "throws an error if called more than once on the same expectation", ->
+      (->
+        mock (m) ->
+          m.expects("my_method").returns(1)
+          m.expects("my_method").returns(2)
+          m.my_method()
+      ).should.throw(format(messages.DuplicateExpectation, "my_method", ""))
+
+
+
 describe "throws( error )", ->
-
-  it "causes the mock method to throw the specified error", ->
-    mock (m) ->
-      m.expects("my_method").throws(new Error("an error"))
-      (-> m.my_method() ).should.throw("an error")
-
+
   it "returns itself", ->
     try
       mock (m) ->
@@ -609,92 +601,73 @@
         m.my_method()   # otherwise we'll get a 'my_method() not called' error
     catch
       # eat the error thrown by throws()
-
-  it "throws an error if no 'error' argument is specified", ->
-    (->
-      mock (m) ->
-        m.expects("my_method").throws()
-    ).should.throw(format(messages.ThrowsUsage))
-
-  it "throws an error if more than one argument is specified", ->
-    (->
-      mock (m) ->
-        m.expects("my_method").throws(new Error("error 1"), new Error("error 2"))
-    ).should.throw(format(messages.ThrowsUsage))
-
-  it "throws an error if throws() has already been specified", ->
-    (->
-      mock (m) ->
-        m.expects("my_method").throws("an error").throws("another error")
-    ).should.throw(format(messages.ThrowsUsedMoreThanOnce))
-
-  it "throws an error if a return value has already been specified", ->
-    (->
-      mock (m) ->
-        m.expects("my_method").returns(42).throws(new Error("an error"))
-    ).should.throw(format(messages.ReturnsAndThrowsBothUsed))
-
-  it "does not throw an error if a return value has been previously set on the same method with a different expectation", ->
+
+  it "causes the mock method to throw the specified error", ->
+    mock (m) ->
+      m.expects("my_method").throws(new Error("an error"))
+      (-> m.my_method() ).should.throw("an error")
+
+  it "can be called after args()", ->
+    (->
+      mock (m) ->
+        m.expects("my_method").args(1,2,3).throws(new Error("an error"))
+        m.my_method(1,2,3)
+    ).should.throw("an error")
+
+  it "can be called even if a return value has been previously set on the same method with a different expectation", ->
     mock (m) ->
       m.expects("my_method").args(1,2,3).returns(42)
       m.expects("my_method").args(4,5,6).throws(new Error("an error"))
       m.my_method(1,2,3)
       (-> m.my_method(4,5,6) ).should.throw("an error")

-  it "can be called after args()", ->
-    (->
-      mock (m) ->
-        m.expects("my_method").args(1,2,3).throws(new Error("an error"))
-        m.my_method(1,2,3)
-    ).should.throw("an error")
-
-  it "cannot be called more than once on the same expectation", ->
-    (->
-      mock (m) ->
-        m.expects("my_method").throws(new Error("error1"))
-        m.expects("my_method").throws(new Error("error1"))
-        m.my_method()
-    ).should.throw(format(messages.DuplicateExpectation, "my_method", ""))
+  describe "usage errors", ->
+
+    it "throws an error if no 'error' argument is specified", ->
+      (->
+        mock (m) ->
+          m.expects("my_method").throws()
+      ).should.throw(format(messages.ThrowsUsage))
+
+    it "throws an error if more than one argument is specified", ->
+      (->
+        mock (m) ->
+          m.expects("my_method").throws(new Error("error 1"), new Error("error 2"))
+      ).should.throw(format(messages.ThrowsUsage))
+
+    it "throws an error if throws() has already been used", ->
+      (->
+        mock (m) ->
+          m.expects("my_method").throws("an error").throws("another error")
+      ).should.throw(format(messages.ThrowsUsedMoreThanOnce))
+
+    it "throws an error if a return value has already been specified", ->
+      (->
+        mock (m) ->
+          m.expects("my_method").returns(42).throws(new Error("an error"))
+      ).should.throw(format(messages.ReturnsAndThrowsBothUsed))
+
+    it "throws an error if called more than once on the same expectation", ->
+      (->
+        mock (m) ->
+          m.expects("my_method").throws(new Error("error1"))
+          m.expects("my_method").throws(new Error("error1"))
+          m.my_method()
+      ).should.throw(format(messages.DuplicateExpectation, "my_method", ""))
+

 describe "my_method( [ arg ... ] )", ->
-
+
   it "does not throw an error if a method is called without arguments and none were expected", ->
     mock (m) ->
       m.expects("my_method")
       m.my_method()
-
+
   it "does not throw an error if a method is called with arguments that were expected", ->
     mock (m) ->
       m.expects("my_method").args(1,2,3)
       m.my_method(1,2,3)
-
-  it "throws an error if an unexpected method is called", ->
-    (->
-      mock (m) ->
-        m.my_method()
-    ).should.throw("has no method 'my_method'")
-
-  it "throws an error if a method is called without arguments but some were expected", ->
-    (->
-      mock (m) ->
-        m.expects("my_method").args(1,2,3)
-        m.my_method()
-    ).should.throw(format(messages.UnknownExpectation, "my_method", ""))
-
-  it "throws an error if a method is called with argments but none were expected", ->
-    (->
-      mock (m) ->
-        m.expects("my_method")
-        m.my_method(1,2,3)
-    ).should.throw(format(messages.UnknownExpectation, "my_method", "1,2,3"))
-
-  it "throws an error if a method is called with arguments but different arguments were expected", ->
-    (->
-      mock (m) ->
-        m.expects("my_method").args(1,2,3)
-        m.my_method(4,5,6)
-    ).should.throw(format(messages.UnknownExpectation, "my_method", "4,5,6"))

   it "returns the value specified in a returns()", ->
     mock (m) ->
@@ -720,6 +693,33 @@
       m.my_method(1,2,3)
       m.my_method()

+  it "throws an error if an unexpected method is called", ->
+    (->
+      mock (m) ->
+        m.my_method()
+    ).should.throw("has no method 'my_method'")
+
+  it "throws an error if a method is called without arguments but some were expected", ->
+    (->
+      mock (m) ->
+        m.expects("my_method").args(1,2,3)
+        m.my_method()
+    ).should.throw(format(messages.UnknownExpectation, "my_method", ""))
+
+  it "throws an error if a method is called with argments but none were expected", ->
+    (->
+      mock (m) ->
+        m.expects("my_method")
+        m.my_method(1,2,3)
+    ).should.throw(format(messages.UnknownExpectation, "my_method", "1,2,3"))
+
+  it "throws an error if a method is called with arguments but different arguments were expected", ->
+    (->
+      mock (m) ->
+        m.expects("my_method").args(1,2,3)
+        m.my_method(4,5,6)
+    ).should.throw(format(messages.UnknownExpectation, "my_method", "4,5,6"))
+
   it "throws an error if an expectation with no args is duplicated", ->
     (->
       mock (m) ->
@@ -736,7 +736,7 @@
         m.my_method(1,2,3)
     ).should.throw(format(messages.DuplicateExpectation, "my_method", "1,2,3"))

-  it "throws an error when the same method returns the same values", ->
+  it "throws an error if the same method returns the same values", ->
     (->
       mock (m) ->
         m.expects("my_method").returns(1)
@@ -744,7 +744,7 @@
         m.my_method()
     ).should.throw(format(messages.DuplicateExpectation, "my_method", ""))

-  it "throws an error when the same method returns different values", ->
+  it "throws an error if the same method returns different values", ->
     (->
       mock (m) ->
         m.expects("my_method").returns(1)
@@ -752,7 +752,7 @@
         m.my_method()
     ).should.throw(format(messages.DuplicateExpectation, "my_method", ""))

-  it "throws an error when the same method throws the same values", ->
+  it "throws an error if the same method throws the same values", ->
     (->
       mock (m) ->
         m.expects("my_method").throws("an error")
@@ -760,7 +760,7 @@
         m.my_method()
     ).should.throw(format(messages.DuplicateExpectation, "my_method", ""))

-  it "throws an error when the same method throws different values", ->
+  it "throws an error if the same method throws different values", ->
     (->
       mock (m) ->
         m.expects("my_method").throws("an error")
@@ -769,7 +769,8 @@
     ).should.throw(format(messages.DuplicateExpectation, "my_method", ""))

-# This is a duplicate of a function in TinyMock.coffee, but this application
+
+# This is a duplicate of a function in TinyMock.coffee, but this application
 # is currently so small that it is not worth worrying about.
 format = (message, args...) ->    # format("{0} + {1} = {2}", 2, 2, "four") => "2 + 2 = four"
   message.replace /{(\d)+}/g, (match, i) ->


Modified in browser at pixie.strd6.com

Modified in browser at pixie.strd6.com

--- test/active_bounds.coffee
+++ test/active_bounds.coffee
@@ -2,6 +2,8 @@

 test "should remove objects outside of activeBounds", ->
   obj = GameObject
-    x:
+    x: 50
+    y: 50
+    width: 3

 module()


Testing blasting old history in CommandStack

--- test/command_stack.coffee
+++ test/command_stack.coffee
@@ -78,4 +78,22 @@

   equals commandStack.redo(), command, "Redone command is returned"

+test "cannot redo an obsolete future", ->
+  Command = ->
+    execute: ->
+    undo: ->
+
+  commandStack = CommandStack()
+  commandStack.execute Command()
+  commandStack.execute Command()
+
+  commandStack.undo()
+  commandStack.undo()
+
+  equals commandStack.canRedo(), true
+
+  commandStack.execute Command()
+
+  equals commandStack.canRedo(), false
+
 module()


redis.subscribe(a, b, ..., cb), not redis.subscribe([a, b, ...], cb)

--- lib/index.coffee
+++ lib/index.coffee
@@ -248,6 +248,7 @@
           # Unprefix database name from the channel
           data.channel = msgChannel.slice msgChannel.indexOf(' ') + 1
           stream.push data
+        channelList = channels
       else
         channels = prefixChannel channels
         subscribeCounts[channels] = (subscribeCounts[channels] || 0) + 1
@@ -256,10 +257,11 @@
           return if !open || msgChannel isnt channels
           data = JSON.parse msg
           stream.push data
+        channelList = [channels]

       redisObserver.on 'message', onMessage

-      redisObserver.subscribe channels, (err) ->
+      redisObserver.subscribe channelList..., (err) ->
         if err
           stream.destroy()
           return callback err


track and use archiver instance

track and use archiver instance

--- lib/index.coffee
+++ lib/index.coffee
@@ -8,6 +8,7 @@
   options     = level: 9
   initialized = false
   type        = 'zip'
+  zip         = undefined
   zipPath     = undefined
   fileList    = []
   fileStack   = []


Adds entity to the list of exposed API

Adds entity to the list of exposed API

--- src/hull.api.coffee
+++ src/hull.api.coffee
@@ -1,11 +1,12 @@
 define [
   'lib/utils/emitter'
   'lib/api/api'
-  'lib/api/reporting'
-  ], (emitter, api, reporting) ->
+  'lib/api/reporting',
+  'lib/utils/entity'
+  ], (emitter, api, reporting, entity) ->
     success = (api)->
       reporting = reporting.init(api)
-      booted =
+      booted =
         events: emitter
         track: reporting.track
         flag: reporting.flag
@@ -16,6 +17,8 @@
           logout: api.auth.logout
         login: api.auth.login
         logout: api.auth.logout
+        util:
+          entity: entity

       # Execute Hull.init callback
       booted.events.emit('hull.init')


modified

modified

--- src/jsonsina.coffee
+++ src/jsonsina.coffee
@@ -70,7 +70,7 @@

       if arr?.length > 0 # 必須這樣寫,不能簡化為: for each in arr?
         for each in arr
-          each.date = each.day
+          #each.date = each.day
           each.day = new Date each.day
           each.open = Number each.open
           each.low = Number each.low


Send sync arguments to opener

Send sync arguments to opener

--- lib/latex.coffee
+++ lib/latex.coffee
@@ -133,7 +133,10 @@

   showResult: (result) ->
     if @shouldOpenResult() and opener = @getOpener()
-      opener.open(result.outputFilePath)
+      editor = atom.workspace.getActivePaneItem()
+      texFile = editor?.getPath()
+      lineNumber = editor?.getCursorBufferPosition().toArray()[0] + 1
+      opener.open(result.outputFilePath, texFile, lineNumber)

   showError: (error) ->
     # TODO: Introduce proper error and warning handling.


very very basic grammer parsing

very very basic grammer parsing

--- lib/lexer.coffee
+++ lib/lexer.coffee
@@ -20,9 +20,9 @@
                        @literalToken()
       throw new Error("NOTHING CONSUMED: Stopped at - '#{@chunk.slice(0,30)}'") if bytesConsumed < 1
       i += bytesConsumed
+    @token('EOF', '')

   token: (name, value) ->
-    console.log(name, value)
     @tokens.push([name, value, @currentLine])

   tokenizeFromRegex: (name, regex, part=0, lengthPart=part, output=true) ->


Modified in browser at pixie.strd6.com

Modified in browser at pixie.strd6.com

--- src/color2.coffee
+++ src/color2.coffee
@@ -50,6 +50,7 @@

   hslToRgb = (hsl) ->
     [h, s, l, a] = (parseFloat(channel) for channel in hsl)
+    h = h.floor()
     h /= 360.0
     a ||= 1.0


Modified in browser at pixie.strd6.com

Modified in browser at pixie.strd6.com

--- src/color2.coffee
+++ src/color2.coffee
@@ -238,7 +238,7 @@
           when g then hue = ((b - r) / chroma) + 2.0
           when b then hue = ((r - g) / chroma) + 4.0

-        hue *= 60
+        hue *= 60.0

       return [hue, saturation, lightness, @a]


adds slug to fulcrum export

adds slug to fulcrum export

--- scripts/daily_upload_s3.coffee
+++ scripts/daily_upload_s3.coffee
@@ -29,7 +29,7 @@
 writableStream = fs.createWriteStream( dir + filename)

 csvStream.pipe(writableStream)
-csvStream.write(["id", "author_id", "auction_id", "contributing_authors", "fair_id", "featured", "featured_artist_ids", "featured_artwork_ids", "partner_ids", "primary_featured_artist_ids", "slugs", "tags", "title", "tier", "published_at","show_ids","section_ids","thumbnail_image","thumbnail_title", "keywords"])
+csvStream.write(["id", "author_id", "auction_id", "contributing_authors", "fair_id", "featured", "featured_artist_ids", "featured_artwork_ids", "partner_ids", "primary_featured_artist_ids", "slugs", "tags", "title", "tier", "published_at","show_ids","section_ids","thumbnail_image","thumbnail_title", "keywords", "slug"])

 db.articles.find({ published: true })
   .on('data', (doc) ->


Since this is a mixin do not include the _loadComplex helper

--- scripts/mixins/loadable.coffee
+++ scripts/mixins/loadable.coffee
@@ -17,7 +17,7 @@
           promise = @fetch()

         # See if we need to daisy-chain loading
-        @_loading = @_loadComplex(promise)
+        @_loading = @_loadComplex?(promise) or promise

         @_loading.fail (err) =>
           # Since we failed clear the promise so we can try again later.
@@ -31,7 +31,7 @@
     # By overriding this method the subclass can load other files before
     # this model is considered loaded.
     # This method should only be called by `.load()`
-    _loadComplex: (fetchPromise) -> fetchPromise
+    # _loadComplex: (fetchPromise) -> fetchPromise

   return loadableMixin


Improved parsing library.

Improved parsing library.

--- lib/parse.coffee
+++ lib/parse.coffee
@@ -1,7 +1,3 @@
-require 'coffee-script'
-
-# ---
-
 to_value = (value) ->
 	return switch value
 		when 'none' then null
@@ -48,7 +44,7 @@

 		return JSON.parse("{#{line}}")

-	input.split('\n').map(to_item).reduce(to_object)
+	return input.split('\n').map(to_item).reduce(to_object)

 ###
 	* @param {string} input
@@ -57,8 +53,32 @@
 	to_item = (line) ->
 		line = line.replace(/^(.+)=/, '"$1"=') if line[0] != '"'
 		line = line.replace(/^(".+")=/, '$1:')
+		line = line.replace(/^(.+):\d+,/, '$1:0.')

 		return JSON.parse("{#{line}}")

 	return input.split('\n').map(to_item).reduce(to_object)
+
+###
+	* @param {string} input
+###
+exports.property_list = (input) ->
+	to_item = (line) ->
+		item = {}
+
+		return item if not line
+
+		match = line.match(/^Name:\s*(.*?),\s*value:\s*(.*?),\s*timestamp:\s*(.*?),\s*flags:\s*(.*?)$/)
+
+		return item if not match
+
+		item[match[1]] = {
+			value: to_value(match[2])
+			timestamp: parseInt(match[3])
+			flags: match[4].split(',').map((token) -> token.trim())
+		}
+
+		return item
+
+	return input.split('\n').map(to_item).reduce(to_object)


Fixed rss widget.

Fixed rss widget.

--- app/assets/javascripts/app/controllers/_dashboard/rss.js.coffee
+++ app/assets/javascripts/app/controllers/_dashboard/rss.js.coffee
@@ -15,6 +15,7 @@
     # get data from cache
     cache = App.Store.get( 'dashboard_rss' )
     if cache
+      cache.head = 'Heise ATOM'
       @render( cache )

     # init fetch via ajax, all other updates on time via websockets
@@ -36,6 +37,7 @@
             )
           else
             App.Store.write( 'dashboard_rss', data )
+            data.head = 'Heise ATOM'
             @render(data)
         error: =>
           @render(
@@ -47,6 +49,6 @@
   render: (data) ->
     @html App.view('dashboard/rss')(
       head:  data.head,
-      items: data.item || []
+      items: data.items || []
       message: data.message
     )


Fixed this binding/proxy in callback.

Fixed this binding/proxy in callback.

--- app/assets/javascripts/app/lib/app_post/_collection_base.coffee
+++ app/assets/javascripts/app/lib/app_post/_collection_base.coffee
@@ -77,7 +77,7 @@

   callback: (data) =>
     for counter, attr of @callbacks
-      callback = ->
+      callback = =>
         attr.callback(data)
         if attr.one
           delete @callbacks[counter]


updated documentation about keys outside config schema

--- src/config.coffee
+++ src/config.coffee
@@ -335,6 +335,31 @@
 #     default: 4
 #     order: 2
 # ```
+#
+# ## Manipulating values outside your configuration schema
+#
+# It is possible to manipulate(`get`, `set`, `observe` etc) values that do not
+# appear in your configuration schema. For example, if the config schema of the
+# package 'some-package' is
+#
+# ```coffee
+# config:
+# someSetting:
+#   type: 'boolean'
+#   default: false
+# ```
+#
+# You can still do the following
+#
+# ```coffee
+# let otherSetting  = atom.config.get('some-package.otherSetting')
+# atom.config.set('some-package.stillAnotherSetting', otherSetting * 5)
+# ```
+#
+# In other words, if a function asks for a `key-path`, that path doesn't have to
+# be described in the config schema for the package or any package. However, as
+# highlighted in the best practices section, you are advised against doing the
+# above.
 #
 # ## Best practices
 #


set max-height, not height.

set max-height, not height.

--- app/assets/javascripts/jobs_list/views/jobs_list_view.js.coffee
+++ app/assets/javascripts/jobs_list/views/jobs_list_view.js.coffee
@@ -13,7 +13,7 @@

   setHeight: ->
     height = $(window).height() - 350;
-    $(@list).height(height)
+    $(@list).css(maxHeight: height)

   render: ->
     @list.empty()


If the server returns an error when loading feeds, the "loading" spinners in the sidebar will disappear.

Also an error alert will be temporarily displayed; this was already implemented.

--- app/assets/javascripts/ng-services/ng-FeedsFoldersSvc.js.coffee
+++ app/assets/javascripts/ng-services/ng-FeedsFoldersSvc.js.coffee
@@ -40,6 +40,7 @@
         # There is probably at least one more page of feeds available
         load_feeds page
     .error (data, status)->
+      $rootScope.feeds_loaded = true
       feedsPaginationSvc.set_busy false
       if status == 404
         # if a 404 is returned for the first page, there are no feeds at all. Set all unread counts to zero.
@@ -50,7 +51,6 @@
         # If a 404 is returned in a page >1, there are no more feeds and this is the last page.
         else
           feedsPaginationSvc.pagination_finished()
-        $rootScope.feeds_loaded = true
         favicoSvc.update_unread_badge()
         animationsSvc.show_stats()
       else if status!=0


Fix crash

Fix crash

--- lib/proxy.coffee
+++ lib/proxy.coffee
@@ -44,15 +44,15 @@
   return true if pathname.startsWith('/gadget/')
   return true if pathname.startsWith('/kcscontents/')
   # Kanpani
-  return true if hostname?.match('kanpani.jp').length > 0
+  return true if hostname?.match('kanpani.jp')?
   # ShiroPro
-  return true if hostname?.match('assets.shiropro-re.net').length > 0
+  return true if hostname?.match('assets.shiropro-re.net')?
   # Shinken
-  return true if hostname?.match('swordlogic.com').length > 0
+  return true if hostname?.match('swordlogic.com')?
   # FlowerKnightGirl
-  return true if hostname.match('dugrqaqinbtcq.cloudfront.net').length > 0
+  return true if hostname?.match('dugrqaqinbtcq.cloudfront.net')?
   # ToukenRanbu
-  return true if hostname.match('static.touken-ranbu.jp').length > 0
+  return true if hostname?.match('static.touken-ranbu.jp')?
   # Not Static Resource
   return false
 getCachePath = (pathname) ->
@@ -71,19 +71,19 @@
   catch
     return null
 findCache = (pathname, hostname) ->
-  if hostname.match('kanpani.jp').length > 0
+  if hostname?.match('kanpani.jp')?
     # Kanpani
     loc = getCachePath path.join 'kanpani', pathname
-  else if hostname.match('assets.shiropro-re.net').length > 0
+  else if hostname?.match('assets.shiropro-re.net')?
     # ShiroPro
     loc = getCachePath path.join 'shiropro', pathname
-  else if hostname.match('swordlogic.com').length > 0
+  else if hostname?.match('swordlogic.com')?
     # Shinken
     loc = getCachePath path.join 'Shinken', pathname.replace(/^\/[0-9]{10}/, '')
-  else if hostname.match('dugrqaqinbtcq.cloudfront.net').length > 0
+  else if hostname?.match('dugrqaqinbtcq.cloudfront.net')?
     # FlowerKnightGirl
     loc = getCachePath path.join 'flowerknight', pathname
-  else if hostname.match('static.touken-ranbu.jp').length > 0
+  else if hostname?.match('static.touken-ranbu.jp')?
     # ToukenRanbu
     loc = getCachePath path.join 'tokenranbu', pathname
   else


Remove strict check for required ServiceProvider options.

--- lib/saml2.coffee
+++ lib/saml2.coffee
@@ -447,9 +447,6 @@
     #
     # Rest of options can be set/overwritten by the identity provider and/or at function call.
     constructor: (options) ->
-      for option in ['entity_id', 'private_key', 'certificate', 'assert_endpoint']
-        throw new Error("#{option} is required") unless options[option]?
-
       {@entity_id, @private_key, @certificate, @assert_endpoint, @alt_private_keys, @alt_certs} = options

       @alt_private_keys = [].concat(@alt_private_keys or [])


webapp: treating *.jpeg fils like *.jpg

webapp: treating *.jpeg fils like *.jpg

--- src/smc-webapp/editor.coffee
+++ src/smc-webapp/editor.coffee
@@ -221,7 +221,7 @@
     opts   : {}
     name   : "jupyter notebook"

-for ext in ['png', 'jpg', 'gif', 'svg']
+for ext in ['png', 'jpg', 'jpeg', 'gif', 'svg']
     file_associations[ext] =
         editor : 'media'
         icon   : 'fa-file-image-o'
@@ -3099,7 +3099,7 @@
     register(false, HTML_MD_Editor,   html_md_exts)
     register(false, LatexEditor,      ['tex'])
     register(false, Terminal,         ['term', 'sage-term'])
-    register(false, Media,            ['png', 'jpg', 'gif', 'svg'].concat(VIDEO_EXTS))
+    register(false, Media,            ['png', 'jpg', 'jpeg', 'gif', 'svg'].concat(VIDEO_EXTS))

     {HistoryEditor} = require('./editor_history')
     register(false, HistoryEditor,    ['sage-history'])


Resolving merge conflicts.

Resolving merge conflicts.

--- src/device.coffee
+++ src/device.coffee
@@ -76,6 +76,9 @@

 device.cordova = ->
   window.cordova && location.protocol == 'file:'
+
+device.nodeWebkit = ->
+  typeof window.process == 'object'

 device.mobile = ->
   device.androidPhone() or device.iphone() or device.ipod() or device.windowsPhone() or device.blackberryPhone() or device.fxosPhone() or device.meego()
@@ -162,6 +165,9 @@
 else if device.meego()
   _addClass "meego mobile"

+else if device.nodeWebkit()
+  _addClass "node-webkit"
+
 else
   _addClass "desktop"


Add Editor::onDidRemoveCursor

Add Editor::onDidRemoveCursor

--- src/editor.coffee
+++ src/editor.coffee
@@ -324,6 +324,9 @@
   onDidAddCursor: (callback) ->
     @emitter.on 'did-add-cursor', callback

+  onDidRemoveCursor: (callback) ->
+    @emitter.on 'did-remove-cursor', callback
+
   # Retrieves the current {TextBuffer}.
   getBuffer: -> @buffer

@@ -1852,6 +1855,7 @@
   removeCursor: (cursor) ->
     _.remove(@cursors, cursor)
     @emit 'cursor-removed', cursor
+    @emitter.emit 'did-remove-cursor', cursor

   moveCursors: (fn) ->
     fn(cursor) for cursor in @getCursors()


Inline hidden input offset updating

Inline hidden input offset updating

--- src/editor.coffee
+++ src/editor.coffee
@@ -696,12 +696,10 @@
       else
         @gutter.addClass('drop-shadow')

-  updateHiddenInputOffset: ->
-    cursorView = @getCursorView()
-    @hiddenInput.offset(cursorView.offset()) if cursorView?.is(':visible')
-
   handleInputEvents: ->
-    @on 'cursor:moved', => @updateHiddenInputOffset()
+    @on 'cursor:moved', =>
+      cursorView = @getCursorView()
+      @hiddenInput.offset(cursorView.offset()) if cursorView.is(':visible')

     selectedText = null
     @hiddenInput.on 'compositionstart', =>


firefox fix

firefox fix

--- src/editor.coffee
+++ src/editor.coffee
@@ -150,6 +150,12 @@
     @id = _.uniqueId(Scribe.Editor.ID_PREFIX)
     @iframeContainer = document.getElementById(@iframeContainer) if _.isString(@iframeContainer)
     this.reset(true)
+    # Make sure we our selection is set to deepest textNode, prevent bug in Firefox when tabbing in
+    Scribe.DOM.addEventListener(@root, 'focus', =>
+      range = this.getSelection()
+      this.setSelection(null, true)
+      this.setSelection(range, true)
+    )
     this.enable() if @options.enabled

   disable: ->


Removed unneeded debugging line.

Removed unneeded debugging line.

--- src/engine.coffee
+++ src/engine.coffee
@@ -12,7 +12,6 @@
     fs.readFile path, 'utf8', (err, str) ->
         if callback
             return callback(err) if err
-            console.log(str, options);
             return callback(null, render(str, options, callback))
         throw err if err


Uses idiomatic coffeescript

Uses idiomatic coffeescript

Substitutes true/false with yes/no in appropriate cases

--- src/pathname.coffee
+++ src/pathname.coffee
@@ -44,8 +44,8 @@
     if cb?
       core.path.exists(@path, cb)
     else
-      try @stat(@path); true
-      catch e then      false
+      try @stat(@path); yes
+      catch e then      no

   # TODO
   # normalize
@@ -205,7 +205,7 @@
     if cb?
       @exists (exists) =>
         if not exists
-          cb(null, false)
+          cb(null, no)
         else
           @stat (err, stats) -> cb(err, stats.isFile())
     else
@@ -215,7 +215,7 @@
     if cb?
       @exists (exists) =>
         if not exists
-          cb(null, false)
+          cb(null, no)
         else
           @stat (err, stats) -> cb(err, stats.isDirectory())
     else


key-bindings that do not load get a warning

--- src/stdlib/key-binder.coffee
+++ src/stdlib/key-binder.coffee
@@ -10,14 +10,13 @@

   constructor: ->
     @load require.resolve "key-bindings.coffee"
-    if fs.isFile "~/.atomicity/key-bindings.coffee"
-      @load "~/.atomicity/key-bindings.coffee"
-
-  register: (name, scope) ->
+    @load "~/.atomicity/key-bindings.coffee"

   load: (path) ->
     path = require.resolve path
-    return if not fs.isFile path
+    if not fs.isFile path
+      console.warn "Could not find keyBinding file '#{path}'"
+      return

     try
 #       Watcher.watch path, =>


refactor(errors): take care of v8 errors without function name

--- src/errors.coffee
+++ src/errors.coffee
@@ -16,7 +16,7 @@
   match: (stack) -> /\s+at\s+/g.test stack
   filter: (line) -> /\s+at\s+/.test line
   details: (line) ->
-    re = ///(at\s*([^\s]*)\s*\(|\()#{URI_RE}#{LINE_RE}///
+    re = ///at\s*(([^\s]*)\s*\(|\()*#{URI_RE}#{LINE_RE}///
     [match, p, method, file, h, e, q, line, c, column] = re.exec line

     {file, line, column, method, params: q}


Adding option to omit description from merge requests

--- src/gitlab.coffee
+++ src/gitlab.coffee
@@ -37,6 +37,7 @@
 module.exports = (robot) ->
   gitlabChannel = process.env.GITLAB_CHANNEL or "#gitlab"
   showCommitsList = process.env.GITLAB_SHOW_COMMITS_LIST or "1"
+  showMergeDesc = process.env.GITLAB_SHOW_MERGE_DESCRIPTION or "1"
   debug = process.env.GITLAB_DEBUG?
   branches = ['all']
   if process.env.GITLAB_BRANCHES?
@@ -130,7 +131,10 @@
                   text += "\r\n" + splitted.join "\r\n"
                 robot.send user, text
             when "merge_request"
-              robot.send user, "Merge Request #{bold(hook.object_attributes.iid)}: #{hook.object_attributes.title} (#{hook.object_attributes.state}) between #{bold(hook.object_attributes.source_branch)} and #{bold(hook.object_attributes.target_branch)} \n>> #{hook.object_attributes.description}"
+              if showMergeDesc == "1"
+                robot.send user, "Merge Request #{bold(hook.object_attributes.iid)}: #{hook.object_attributes.title} (#{hook.object_attributes.state}) between #{bold(hook.object_attributes.source_branch)} and #{bold(hook.object_attributes.target_branch)} \n>> #{hook.object_attributes.description}"
+              else
+                robot.send user, "Merge Request #{bold(hook.object_attributes.iid)}: #{hook.object_attributes.title} (#{hook.object_attributes.state}) between #{bold(hook.object_attributes.source_branch)} and #{bold(hook.object_attributes.target_branch)}"

   robot.router.post "/gitlab/system", (req, res) ->
     handler "system", req, res


fix factory objects somewhat

fix factory objects somewhat

--- src/hinoki.coffee
+++ src/hinoki.coffee
@@ -262,11 +262,11 @@
         # supports nesting
         return hinoki.callFactoryObjectArray(path, f, dependenciesObject)

-    if Array.isArray factory
-      Promise.all(factory).map(iterator)
+    if Array.isArray factoryObject
+      Promise.all(factoryObject).map(iterator)
     # object !
     else
-      Promise.props _.mapValues factory, iterator
+      Promise.props _.mapValues factoryObject, iterator

   hinoki.callFactory = (path, factory, dependencyValues) ->
     if 'function' is typeof factory
@@ -362,7 +362,7 @@
       if cache
         factory.__inject = names
       return names
-    else if Array.isArray factory or 'object' is typeof factory
+    else if Array.isArray(factory) or ('object' is typeof factory)
       namesSet = {}
       _.forEach factory, (subFactory) ->
         subNames = hinoki.baseGetNamesToInject(subFactory, cache)


restructure and support async dependencies

--- src/hinoki.coffee
+++ src/hinoki.coffee
@@ -1,3 +1,5 @@
+q = require 'q'
+
 module.exports =

     parseFunctionArguments: (fun) ->
@@ -12,21 +14,59 @@

         return if dependencies[0] is '' then [] else dependencies

-    inject: (container, fun, chain = []) ->
+    inject: (container, fun) ->
         unless container.scope?
             container.scope = {}

-        dependencyIds = module.exports.parseFunctionArguments fun
+        ids = module.exports.parseFunctionArguments fun

-        dependencyIds.forEach (id) ->
+        module.exports.resolve container, ids, [], ->
+            fun.apply null, arguments
+
+    resolve: (container, ids, chain, cb) ->
+        hasErrorOccured = false
+        toBeResolved = 0
+
+        maybeDone = ->
+            if hasErrorOccured
+                return
+            if toBeResolved is 0
+                dependencies = ids.map (id) -> container.scope[id]
+                cb.apply null, dependencies
+
+        ids.forEach (id) ->
             unless container.scope[id]?
                 newChain = chain.concat([id])
+
                 if id in chain
                     throw new Error "circular dependency #{newChain.join(' <- ')}"
+
                 factory = container.factories?[id]
                 unless factory?
                     throw new Error "missing factory for service '#{id}'"
-                container.scope[id] =
-                    module.exports.inject container, factory, newChain
+                unless 'function' is typeof factory
+                    throw new Error "factory is not a function '#{id}'"

-        fun.apply null, dependencyIds.map (id) -> container.scope[id]
+                factoryIds = module.exports.parseFunctionArguments factory
+
+                toBeResolved++
+                module.exports.resolve container, factoryIds, newChain, ->
+                    try
+                        instance = factory.apply null, arguments
+                    catch err
+                        throw new Error "exception in factory '#{id}' #{err}"
+                    unless q.isPromise instance
+                        container.scope[id] = instance
+                        toBeResolved--
+                        return
+
+                    onSuccess = (value) ->
+                        container.scope[id] = value
+                        toBeResolved--
+                        maybeDone()
+                    onError = (err) ->
+                        hasErrorOccured = true
+                        throw new Error "error resolving promise returned from factory '#{id}'"
+                    instance.then onSuccess, onError
+
+        maybeDone()


atom: add language-graphql

atom: add language-graphql


Clean up some syntax

Clean up some syntax

--- src/reactive.coffee
+++ src/reactive.coffee
@@ -174,7 +174,7 @@
     @x = @x ? null
     @onSet = new Ev(=> [[null, @x]]) # [old, new]
   get: ->
-    recorder.sub((target) => rx.autoSub @onSet, -> target.refresh())
+    recorder.sub (target) => rx.autoSub @onSet, -> target.refresh()
     @x

 SrcCell = class rx.SrcCell extends ObsCell
@@ -244,18 +244,18 @@
     @xs = @xs ? []
     @onChange = new Ev(=> [[0, [], @xs]]) # [index, removed, added]
   all: ->
-    recorder.sub((target) => rx.autoSub @onChange, -> target.refresh())
+    recorder.sub (target) => rx.autoSub @onChange, -> target.refresh()
     _.clone(@xs)
   raw: ->
-    recorder.sub((target) => rx.autoSub @onChange, -> target.refresh())
+    recorder.sub (target) => rx.autoSub @onChange, -> target.refresh()
     @xs
   at: (i) ->
-    recorder.sub((target) => rx.autoSub @onChange, ([index, removed, added]) ->
-      target.refresh() if index == i)
+    recorder.sub (target) => rx.autoSub @onChange, ([index, removed, added]) ->
+      target.refresh() if index == i
     @xs[i]
   length: ->
-    recorder.sub((target) => rx.autoSub @onChange, ([index, removed, added]) ->
-      target.refresh() if removed.length != added.length)
+    recorder.sub (target) => rx.autoSub @onChange, ([index, removed, added]) ->
+      target.refresh() if removed.length != added.length
     @xs.length
   map: (f) ->
     ys = new MappedDepArray()
@@ -302,17 +302,17 @@
     @onRemove = new Ev() # [key, old]
     @onChange = new Ev() # [key, old, new]
   get: (key) ->
-    recorder.sub((target) => rx.autoSub @onAdd, ([subkey, val]) ->
-      target.refresh() if key == subkey)
-    recorder.sub((target) => rx.autoSub @onChange, ([subkey, old, val]) ->
-      target.refresh() if key == subkey)
-    recorder.sub((target) => rx.autoSub @onRemove, ([subkey, old]) ->
-      target.refresh() if key == subkey)
+    recorder.sub (target) => rx.autoSub @onAdd, ([subkey, val]) ->
+      target.refresh() if key == subkey
+    recorder.sub (target) => rx.autoSub @onChange, ([subkey, old, val]) ->
+      target.refresh() if key == subkey
+    recorder.sub (target) => rx.autoSub @onRemove, ([subkey, old]) ->
+      target.refresh() if key == subkey
     @x[key]
   all: ->
-    recorder.sub((target) => rx.autoSub @onAdd, -> target.refresh())
-    recorder.sub((target) => rx.autoSub @onChange, -> target.refresh())
-    recorder.sub((target) => rx.autoSub @onRemove, -> target.refresh())
+    recorder.sub (target) => rx.autoSub @onAdd, -> target.refresh()
+    recorder.sub (target) => rx.autoSub @onChange, -> target.refresh()
+    recorder.sub (target) => rx.autoSub @onRemove, -> target.refresh()
     _.clone(@x)
   realPut: (key, val) ->
     if key of @x


Store resourcePath as ivar

Store resourcePath as ivar

--- src/keymap.coffee
+++ src/keymap.coffee
@@ -30,7 +30,7 @@
   bindingSetsByFirstKeystroke: null
   queuedKeystrokes: null

-  constructor: ({resourcePath, @configDirPath})->
+  constructor: ({@resourcePath, @configDirPath})->
     @bindingSets = []
     @bindingSetsByFirstKeystroke = {}


Pass is declared in parent

Pass is declared in parent

--- lib/Parser.coffee
+++ lib/Parser.coffee
@@ -94,7 +94,7 @@

     target

-  @traverseCode: (parent, target, dests = []) ->
+  @traverseCode: (parent, target, isDeclaredInParent = false, dests = []) ->
     isFixed = false

     parent.eachChild (child) ->
@@ -103,7 +103,7 @@
         isContains = Parser.isContains child, target
         isDeclared = Parser.isDeclared child, target
         if isContains
-          [ childDests, isChildFixed ] = Parser.traverseCode child, target, null
+          [ childDests, isChildFixed ] = Parser.traverseCode child, target, isDeclaredInParent or isDeclared, null
           if isDeclared or isChildFixed
             dests = childDests
             isFixed = true
@@ -113,8 +113,6 @@
         else if isDeclared
           return true

-
-
       # Skip object key access
       if child.asKey
         return true
@@ -134,13 +132,16 @@
       if Parser.isSameLiteral child, target
         dests.push child

-      [ childDests, isChildFixed ] = Parser.traverseCode child, target, dests
+      [ childDests, isChildFixed ] = Parser.traverseCode child, target, isDeclaredInParent, dests
+      # console.log '------------'
+      # console.log inspect childDests
+      # console.log isChildFixed
       if isChildFixed
         dests = childDests
         isFixed = true
         return false
       else
-        dests.concat nodes
+        dests.concat nodes  #TODO `childDests` instead of `node`

     [ dests, isFixed ]

@@ -162,7 +163,8 @@
     code = new Code code.params, new Block(code.body), code.tag
     try
       code.compileNode code
-      return true for variable in code.scope.variables when variable.name is target.value
+      for variable in code.scope.variables when variable.name is target.value
+        return true
     catch err
     false


Move Total serie config to API, adding zones for projection

--- src/components/widgets/accounts-cash-balance/accounts-cash-balance.directive.coffee
+++ src/components/widgets/accounts-cash-balance/accounts-cash-balance.directive.coffee
@@ -24,17 +24,14 @@
   w.initContext = ->
     if $scope.isDataFound = w.content?

+      # Custom chart legend
       $scope.groupedTable = w.content.grouped_table

-      # TODO: theming config for positive/negative hex codes
+      # TODO: theming config for positive/negative hex codes (or move to API)
       # chartColors = ImpacTheming.get().chartColors
-      # Set account colors by group sub-type
+
+      # Set chart accounts series colors by account sub-type ('positive' / 'negative')
       setSeriesColors(w.content.chart.series, {'positive': '#3FC4FF', 'negative': '#e50228'})
-
-      # Custom settings for the 'totals' serie.
-      totals_serie = _.find(w.content.chart.series, (serie)-> serie.type == 'area')
-      # TODO: add configurable in theming svc
-      totals_serie.color = '#7badfc'

       # Wait for the next digest cycle to ensure the chart parent (.data-container) is shown.
       $timeout(->
@@ -91,9 +88,6 @@
         enabled: false
       scrollbar:
         enabled: true
-      plotOptions:
-        series:
-          fillOpacity: '0.3'
       xAxis:
         startOnTick: false
         minPadding: 0
@@ -103,12 +97,11 @@
           formatter: ()->
             $filter('mnoDate')(data.labels[this.value], getPeriod())
         plotLines: [{
-          # TODO: ImpacTheming config for today "plot" color.
-          color: '#0055ff'
+          color: 'rgba(0, 85, 255, 0.2)'
           value: getTodayMarker()
           width: 1
           label:
-            text: 'Today'
+            text: null
             verticalAlign: 'top'
             textAlign: 'center'
             rotation: 0


Remove a dummy test

Remove a dummy test

--- tests/unit/controllers/login-test.coffee
+++ tests/unit/controllers/login-test.coffee
@@ -16,10 +16,6 @@
   teardown: ->
     Ember.run App, App.destroy

-# Replace this with your real tests.
-test 'it exists', ->
-  controller = @subject()
-  ok controller

 test 'it redirects to login when the user is not authenticated', ->
   expect 1


Chance package has downcase name

Chance package has downcase name

--- lib/authorize_kinvey.coffee
+++ lib/authorize_kinvey.coffee
@@ -31,7 +31,7 @@
 #
 define [
   'kinvey',
-  'Chance'
+  'chance'
 ], (Kinvey, Chance) ->
   (route) ->
     $.Deferred (deferred) ->


feat (steroids) Use console.log instead of depreacted util.print.

--- src/steroids.coffee
+++ src/steroids.coffee
@@ -115,7 +115,7 @@
     else
       ""

-    util.print "#{prefix}#{tag}#{message}#{suffix}"
+    console.log "#{prefix}#{tag}#{message}#{suffix}"

     if refresh and @connect?.prompt?
       @connect?.prompt?.refresh()


Use the package's own copy of Babel

Use the package's own copy of Babel

`require('babel-core')` resolves to the one bundled with Atom, rather than the one installed as a dependency.  If we explicitly load the latter instead, the user can update it more easily when needed (e.g. I use some Babel 5.4 features in my codebase, while Atom ships 5.3.3).

--- lib/babel-transpiler.coffee
+++ lib/babel-transpiler.coffee
@@ -137,7 +137,7 @@
       babelOptions.whitelist = config.whitelistTransformers

     # babel-core seems to add a lot of time to atom loading so delay until needed
-    @babel ?= require('babel-core')
+    @babel ?= require('../node_modules/babel-core')
     @babel.transformFile fqName.sourceFile, babelOptions, (err,result) ->
       if err
         atom.notifications.addError 'Babel Transpiler Error', { dismissable: true, detail: err.message}


changed selector to options while getting results over Relationship

--- client/app/Applications/Members.kdapplication/AppController.coffee
+++ client/app/Applications/Members.kdapplication/AppController.coffee
@@ -42,12 +42,11 @@
             else
               group = KD.getSingleton('groupsController').getCurrentGroup()
               if group?
-                options = {
-                  options
-                  targetOptions: {selector}
+                relationshipOptions = {
+                  targetOptions: {options}
                 }
                 selector = {}
-                group.fetchMembers selector, options, callback
+                group.fetchMembers selector, relationshipOptions, callback
               else
                 JAccount.someWithRelationship selector, options, callback
               @setCurrentViewNumber 'all'


Moved geopoint handling code into DataModel class

--- frontend/coffeescript/app/models/data.coffee
+++ frontend/coffeescript/app/models/data.coffee
@@ -3,7 +3,29 @@
 ( Backbone ) ->

     class DataModel extends Backbone.Model
-            defaults:
-                data: []
+        defaults:
+            data: []
+
+        geopoint: ( field ) ->
+            # Converts the specified field(s) into a geopoint
+            point = { lat: null, lng: null }
+
+            geostring = @get( 'data' )[ field.name ]
+
+            if not geostring?
+                return null
+
+            # Split and convert into lat, lng
+            geostring = geostring.split( ' ' )[0..2]
+
+            point.lat = parseFloat( geostring[0] )
+            point.lng = parseFloat( geostring[1] )
+
+            if isNaN( point.lat ) or isNaN( point.lng )
+                return null
+
+            return point
+
+    return DataModel

 )


remove empty startup arguments

remove empty startup arguments

--- lib/connection/local.coffee
+++ lib/connection/local.coffee
@@ -89,6 +89,9 @@
     [path, args] = [paths.jlpath(), client.clargs()]
     check = paths.getVersion()

+    args = args.map (arg) => arg.trim()
+    args = args.filter (arg) => arg.length > 0
+
     if provider is 'Remote'
       check = Promise.resolve()
     else


landing: recover: added team create mode redirect

--- client/landing/site.landing/coffee/team/tabs/teamrecovertab.coffee
+++ client/landing/site.landing/coffee/team/tabs/teamrecovertab.coffee
@@ -68,7 +68,11 @@
           content  : 'We\'ve sent you a password recovery code.'
           duration : 4500

-        route = if mode is 'join' then '/Join' else '/'
+        route = switch mode
+          when 'join'   then '/Join'
+          when 'create' then '/Team/Username'
+          else ''
+
         kd.singletons.router.handleRoute route


fixed order of arguments for eachWithObject

--- test/array_extensions.coffee
+++ test/array_extensions.coffee
@@ -58,7 +58,7 @@
 test "#eachWithObject", ->
   array = [1, 2, 3]

-  result = array.eachWithObject {}, (hash, element) ->
+  result = array.eachWithObject {}, (element, hash) ->
     hash[element] = (element + 1).toString()

   equal result[1], "2"


add output to debug travis failure

add output to debug travis failure

--- test/bin/test-command.coffee
+++ test/bin/test-command.coffee
@@ -9,8 +9,9 @@
   it 'with defaults', (done) ->

     cwd = process.cwd()
-
-    process.chdir join 'test', 'helpers', 'module-only'
+    moduleOnlyDir = resolve 'test', 'helpers', 'module-only'
+    console.log "cwd = [#{cwd}]  chdir = [#{moduleOnlyDir}]"
+    process.chdir moduleOnlyDir

     check = (error) ->
       if error? then return done error


Handled non-array parameters for cursor

Handled non-array parameters for cursor

--- lib/cursor.coffee
+++ lib/cursor.coffee
@@ -7,6 +7,9 @@
     @[key] = value for key, value of options # mixin
     parsed_query = Cursor.parseQuery(query)
     @_find = parsed_query.find; @_cursor = parsed_query.cursor
+
+    # ensure arrays
+    @_cursor[key] = [@_cursor[key]] for key in ['$white_list', '$select', '$values'] when @_cursor[key] and not _.isArray(@_cursor[key])

   @parseQuery: (query) ->
     if not query


timeout handling fix

timeout handling fix

--- src/uploader.coffee
+++ src/uploader.coffee
@@ -106,31 +106,24 @@
           PartNumber: chunk.partNumber.toString()
           UploadId:   @uploadId
         , (err, data) =>
-
-          if not chunk.progress
-            callbackCalled = true
-
           chunk.progress = false
           chunk.finished = if err then false else true

           if err
-            if not callbackCalled
-              if err.code is 'RequestTimeout'
-                # create new client as old one died..and try again in next iteration
-                @createNewClient()
-                # do not propagate err as that whould kill rest of uploads
-                next null
-              else
-                next err
+            if err.code is 'RequestTimeout'
+              # create new client as old one died..and try again in next iteration
+              @createNewClient()
+              # do not propagate err as that whould kill rest of uploads
+              return next null
             else
-              console.error 'This callback was already called, WTF; chunk', chunk
-            @emit 'error', err
+              @emit 'error', err
+              return next err
+
           else
             @uploadedParts[chunk.partNumber] = data.ETag
-
             @emit 'uploaded', etag: data.ETag

-            return next()
+          return next()

     , (err) =>
       if err


fix image glyph

fix image glyph

--- static/coffee/renderers/image.coffee
+++ static/coffee/renderers/image.coffee
@@ -29,47 +29,45 @@
     x = (glyph_props.select('x', obj) for obj in data)
     y = (glyph_props.select('y', obj) for obj in data)
     [@sx, @sy] = @map_to_screen(x, glyph_props.x.units, y, glyph_props.y.units)
-    @image_src = (glyph_props.select('image', obj) for obj in data)
+    @image = (glyph_props.select('image', obj) for obj in data)
     @angle = (glyph_props.select('angle', obj) for obj in data) # TODO deg/rad
-
-    @img = new Array(@image_src.length)

     # fast and slow paths are the same
     for i in [0..@sx.length-1]
       if isNaN(@sx[i] + @sy[i]+ @angle[i])
         continue

-      @img[i] = new Image()
-      @img[i].onload = do (i) =>
+      img = new Image()
+      img.onload = do (img, i) =>
         return () =>
           if @angle[i]
             ctx.translate(@sx[i], @sy[i])
             ctx.rotate(@angle[i])
-            ctx.drawImage(@img[i], 0, 0);
+            ctx.drawImage(img, 0, 0);
             console.log @sx[i], @sy[i]
             ctx.rotate(-@angle[i])
             ctx.translate(-@sx[i], -@sy[i])
           else
-            ctx.drawImage(@img[i], @sx[i], @sy[i]);
-      @img[i].src = @image_src[i]
+            ctx.drawImage(img, @sx[i], @sy[i]);
+      img.src = @image[i]

     ctx.restore()

-
-class Image extends Glyph
+# name Image conflicts with js Image
+class ImageGlyph extends Glyph
   default_view: ImageView
   type: 'GlyphRenderer'

-Image::display_defaults = _.clone(Image::display_defaults)
-_.extend(Image::display_defaults, {})
+ImageGlyph::display_defaults = _.clone(ImageGlyph::display_defaults)
+_.extend(ImageGlyph::display_defaults, {})

 class Images extends Backbone.Collection
-  model: Image
+  model: ImageGlyph

 exports.images = new Images
-exports.Image = Image
+exports.Image = ImageGlyph
 exports.ImageView = ImageView


DateHelper requires a DD MMM YYYY format.

--- test/unit/helpersSpec.coffee
+++ test/unit/helpersSpec.coffee
@@ -55,35 +55,38 @@

         it 'should add camelCase aliases to underscore properties', ->
           expect('anInt' in Object.keys(obj),
-                 "the alias is not defined as an enumerable property").to.be.true
+                 "The alias is not defined as an enumerable property")
+            .to.be.true
           expect(obj.anInt, "the alias value is incorrect").to.equal(mock.an_int)
           obj.an_int = obj.an_int + 1
-          expect(obj.anInt, "the alias value does not reflect an underscore change")
+          expect(obj.anInt, "The alias value does not reflect an underscore change")
             .to.equal(obj.an_int)
           obj.anInt = obj.anInt + 1
-          expect(obj.an_int, "the underscore value does not reflect an alias change")
+          expect(obj.an_int, "The underscore value does not reflect an alias change")
             .to.equal(obj.anInt)

         it 'should make the camelCase alias enumerable', ->
           expect('anInt' in Object.keys(obj),
-                 "the underscore property is still enumerable").to.be.true
+                 "The underscore property is still enumerable").to.be.true

         it 'should make the underscore property non-enumerable', ->
           expect('an_int' in Object.keys(obj),
-                 "the underscore property is still enumerable").to.be.false
+                 "The underscore property is still enumerable").to.be.false

         it 'should make the underscore property nonenumerable', ->
           expect(obj.an_int, "an_int is incorrect").to.equal(mock.an_int)

         it 'should add camelCase aliases to inner objects', ->
           expect('anObj' in Object.keys(obj.inner),
-                 "the inner underscore scalar property is not aliased").to.be.true
-          expect(obj.inner.anObj.anInt, "the inner reference alias value is incorrect")
+                 "the inner underscore scalar property is not aliased")
+            .to.be.true
+          expect(obj.inner.anObj.anInt,
+                 "The inner reference alias value is incorrect")
             .to.eql(mock.inner.an_obj.an_int)

         it 'should add camelCase aliases to arrays', ->
           expect('anArray' in Object.keys(obj.inner.anObj),
-                 "the inner underscore array property is not aliased").to.be.true
+                 "The inner underscore array property is not aliased").to.be.true
           expect(obj.inner.anObj.anArray.length, "the inner array length is incorrect")
             .to.equal(1)
           item = obj.inner.anObj.anArray[0]
@@ -131,7 +134,8 @@
           src = {a: 1}
           dest = {}
           ObjectHelper.aliasPublicDataProperties(src, dest)
-          expect(dest.a, 'The public value property was not aliased').to.equal(src.a)
+          expect(dest.a, 'The public value property was not aliased')
+            .to.equal(src.a)

         it 'should alias public virtual properties', ->
           src = {a: 1}
@@ -140,7 +144,8 @@
             get: -> src.a
           dest = {}
           ObjectHelper.aliasPublicDataProperties(src, dest)
-          expect(dest.b, 'The public virtual property was not aliased').to.equal(src.b)
+          expect(dest.b, 'The public virtual property was not aliased')
+            .to.equal(src.b)

         it 'should alias non-eumerable public properties', ->
           src = {}
@@ -149,7 +154,8 @@
             value: 1
           dest = {}
           ObjectHelper.aliasPublicDataProperties(src, dest)
-          expect(dest.a, 'The public virtual property was not aliased').to.equal(src.a)
+          expect(dest.a, 'The public virtual property was not aliased')
+            .to.equal(src.a)

         it 'should not alias private properties', ->
           src = {_a: 2}
@@ -175,26 +181,30 @@

       describe 'asMoment', ->
         it 'should parse a string date', ->
-          dateStr = 'Aug 14, 2012'
-          expected = moment(dateStr)
+          dateStr = '14 Aug 2012'
+          expected = moment(dateStr, 'DD MMM YYYY')
           actual = DateHelper.asMoment(dateStr)
-          expect(actual, 'A string date was not parsed').to.eql(expected)
+          expect(actual, 'The string date was not parsed accurately')
+            .to.eql(expected)

         it 'should parse an integer date', ->
           dateInt = moment().valueOf()
-          actual = DateHelper.asMoment(dateInt)
-          expect(actual.valueOf(), 'An integer date was not parsed').to.eql(dateInt)
+          actual = DateHelper.asMoment(dateInt).valueOf()
+          expect(actual.valueOf(), 'The integer date was not parsed')
+            .to.eql(dateInt)

         it 'should not parse null', ->
-          expect(DateHelper.asMoment(null), 'A null date was parsed').to.be.null
+          expect(DateHelper.asMoment(null), 'The null date was parsed')
+            .to.be.null

       describe 'anonymize', ->
         it 'should set the month to July', ->
-          date = moment('Aug 14, 2012')
+          date = moment('14 Aug 2012', 'DD MMM YYYY')
           anon = DateHelper.anonymize(date)
           expect(anon.month(), 'The anonymized month is not July').to.equal(6)

-        it 'should seet the day of the month to 7', ->
-          date = moment('Aug 14, 2012')
+        it 'should set the day of the month to 7', ->
+          date = moment('14 Aug 2012', 'MMM DD, YYYY')
           anon = DateHelper.anonymize(date)
-          expect(anon.date(), 'The anonymized day of the month is not 7').to.equal(7)
+          expect(anon.date(), 'The anonymized day of the month is not 7')
+            .to.equal(7)


resolve if data is undefined. fixes #179

--- lib/linter.coffee
+++ lib/linter.coffee
@@ -22,7 +22,7 @@
       text = textEditor.getText()
       @manager.client?.update(textEditor).then =>
         @manager.client.lint(URI, text).then (data) =>
-          return resolve [] unless data.messages
+          return resolve [] unless data?.messages
           for message in data.messages
             positionFrom = buffer.positionForCharacterIndex(message.from)
             positionTo = buffer.positionForCharacterIndex(message.to)


Better view dir normalization

Better view dir normalization

--- lib/server.coffee
+++ lib/server.coffee
@@ -56,7 +56,8 @@
     if config.server.view
       config.server.view.engine ?= 'jade'
       config.server.view.options ?= {}
-      config.server.view.options.root ?= config.projectRoot
+      config.server.view.options.root ?= './views'
+      config.server.view.options.root = path.resolve config.projectRoot, config.server.view.options.root
       server.set 'view engine', config.server.view.engine
       server.set 'view options', config.server.view.options
       server.set 'views', config.server.view.options.root


Simplify mtime check.

Simplify mtime check.

--- src/module.coffee
+++ src/module.coffee
@@ -71,7 +71,7 @@
     fs.stat @absolutePath, (err, stat) =>
       return callback err if err?

-      if @mtime? and @mtime >= stat.mtime
+      if @mtime? and stat.mtime < @mtime
         return callback()

       @mtime = stat.mtime


Swap O with o in "skipoffset" attribute to match the VAST 3.0 spec

--- src/parser.coffee
+++ src/parser.coffee
@@ -150,7 +150,7 @@
         if creative.duration == -1
             return null # can't parse duration, element is required

-        skipOffset = creativeElement.getAttribute("skipOffset")
+        skipOffset = creativeElement.getAttribute("skipoffset")
         if skipOffset? and skipOffset[skipOffset.length - 1] is "%"
             percent = parseInt(skipOffset)
             creative.skipOffset = creative.duration * (percent / 100)


Comment out console logging for plugin() method

--- src/plugin.coffee
+++ src/plugin.coffee
@@ -45,7 +45,7 @@

 			# Log a signature on the console log to indicate who published what to who.
 			# It's best to comment this line out before deploying for production service.
-			console.log @, (if ret is false then " |#{channel}> " else " |#{channel}>> "), sub.subscriber
+			#console.log @, (if ret is false then " |#{channel}> " else " |#{channel}>> "), sub.subscriber
 		return @

 	# >FIXME; the above publish/subscribe mechanism should be replaced by jQuery's custom event mechanism.


Add section display options.

Add section display options.

Also add default section properties.

--- src/prompt.coffee
+++ src/prompt.coffee
@@ -35,19 +35,32 @@
     @_orderedSections = []

-  section: (key, options) =>
+  section: (key, properties) =>
     # Create the section if it doesn't already exist.
     unless @_sections[key]
-      @_sections[key] = {}
+      @_sections[key] =
+        background: 'default'
+        foreground: 'default'
+        options:
+          newlines: false
+          prePadding: true
+          postPadding: true
+
       @_orderedSections.push @_sections[key]

     section = @_sections[key]

     # `when` is always an array.
-    if options.when? and not _.isArray options.when
-      options.when = [options.when]
+    if properties.when? and not _.isArray properties.when
+      properties.when = [properties.when]

-    _.extend section, options
+    # Apply changes to the `options` object to prevent
+    # it from being overwritten below.
+    _.extend section.options, properties.options
+    delete properties.options
+
+    # Apply changes to the section properties.
+    _.extend section, properties

   # Build the prompt.
@@ -66,16 +79,20 @@
           content = section._formattedContent
           return value unless content

+          options = section.options
+
           # If two sections have the same background color, link them with a single space.
           # Otherwise, pad both sides of the content with spaces.
-          content = "#{content} "
-          content = " #{content}" unless section.background is lastBackground
+          if options.postPadding
+            content = "#{content} "
+          if section.background isnt lastBackground and options.prePadding
+            content = " #{content}"

           content = Impromptu.color content,
             foreground: section.foreground
             background: section.background

-          lastBackground = section.background
+          lastBackground = if options.postPadding then section.background else null

           value + content
         , ''


cleanup

cleanup

--- src/sentry.coffee
+++ src/sentry.coffee
@@ -11,6 +11,7 @@
 # @param {String} filename File path to watch, optionally pass /* or /**/* wildcards
 # @param {String} [task] Optionally run a child process
 # @param {Function} callback
+
 @watch = (filename, task, callback) =>

   callback = task if _.isFunction task
@@ -33,6 +34,7 @@
 # @param {RegExp} regex
 # @param {String} [task] Optionally run a child process
 # @param {Function} callback
+
 @watchRegExp = (dir, regex, task, callback) ->

   callback = task if _.isFunction task
@@ -54,6 +56,7 @@
 # @param {String} filename
 # @param {String} [task]
 # @param {Function} callback
+
 watchFile = (filename, task, callback) ->
   fs.watchFile filename, (curr, prev) ->
     return if curr.size is prev.size and curr.mtime.getTime() is prev.mtime.getTime()
@@ -71,6 +74,7 @@
 #
 # @param {String} filename
 # @return {Array} An array of file path strings
+
 @findWildcards = (filename) ->

   files = []


Try to clear timeout inside timer

Try to clear timeout inside timer

--- src/server.coffee
+++ src/server.coffee
@@ -50,7 +50,11 @@
   # if buffer has content, at 30ms resolution. recursively call this function on success
   #
   _write_pipe: ->
-    setTimeout (=>
+    timer = setTimeout (=>
+      # clear timer (memory leak!)
+      clearTimeout(timer)
+
+      # recurse
       if @buffer.length == 0
         @_write_pipe()
       else


Remove compatibility with Node 0.6

Remove compatibility with Node 0.6

pg is not compatible with 0.6 anymore, so we don't need to bother
either.

--- src/server.coffee
+++ src/server.coffee
@@ -8,14 +8,11 @@
 NS         = require('./xmpp/ns')
 version    = require('./version')

-# In Node.js 0.8.x, existsSync moved from path to fs.
-existsSync = fs.existsSync or path.existsSync
-
 exports.getConfig = (cb) ->
     # Config
     config = require('jsconfig')
     defaultConfigFile = path.join(__dirname,"..","config.js")
-    if existsSync(defaultConfigFile)
+    if fs.existsSync(defaultConfigFile)
         config.defaults defaultConfigFile

     config.set 'ignore unknown', yes
@@ -42,7 +39,7 @@
                 opts.config = path.join(process.cwd(), opts.config)
             # Always reload config for -c argument
             config.merge(opts.config)
-        else if existsSync("/etc/buddycloud-server/config.js")
+        else if fs.existsSync("/etc/buddycloud-server/config.js")
             config.merge("/etc/buddycloud-server/config.js")

         # Kludge:


typos

typos

--- src/server.coffee
+++ src/server.coffee
@@ -71,8 +71,8 @@
     io.sockets.emit "refbox_packet", packet

   socket.on "cmd_packet", (packet) ->
-    #if debug
-    console.log packet
+    if debug
+      console.log packet

     # Forward packet to zmq
-    zmq_publisher.send(packet);
+    zmq_publisher.send(packet)


Fix calculation of audit message length prefix

--- src/server.coffee
+++ src/server.coffee
@@ -454,8 +454,9 @@
           logger.info "[Auditing #{type}] No length supplied"
           sock.destroy()

+        logger.debug "Length prefix is: #{length} and message length so far is #{Buffer.byteLength(message)}"
         # if sourced length equals message length then full message received
-        if length == message.length
+        if length == Buffer.byteLength(message)
           logger.info "[Auditing #{type}] Received message from #{sock.remoteAddress}"
           auditing.processAudit message, -> logger.info "[Auditing #{type}] Processed audit"