diff --git a/public/javascripts/content-updates.js b/public/javascripts/content-updates.js
new file mode 100644
index 0000000000000000000000000000000000000000..55eca2422e86648acc7565f9dd5322cbecc0f793
--- /dev/null
+++ b/public/javascripts/content-updates.js
@@ -0,0 +1,26 @@
+/*   Copyright (c) 2010, Diaspora Inc.  This file is
+*   licensed under the Affero General Public License version 3 or later.  See
+*   the COPYRIGHT file.
+*/
+
+var ContentUpdates = {
+  addPostToStream: function(postId, html) {
+    if( $(".stream_element[data-guid='" + postId + "']").length === 0 ) {
+      var streamElement = $(html);
+
+      if($("#no_posts").length) {
+        $("#no_posts").detach();
+      }
+
+      streamElement.prependTo("#main_stream:not('.show')").fadeIn("fast", function() {
+        streamElement.find("label").inFieldLabels();
+      });
+
+
+      Diaspora.widgets.publish("stream/postAdded", [postId]);
+      
+      Diaspora.widgets.timeago.updateTimeAgo();
+      Diaspora.widgets.directionDetector.updateBinds();
+    }
+  }
+};
\ No newline at end of file
diff --git a/public/javascripts/web-socket-receiver.js b/public/javascripts/web-socket-receiver.js
index 505afadfbe4736f5ae08af66c0a637fb48f2a48b..64e4c6ba85236be9a645bed048d862ae71eb3966 100644
--- a/public/javascripts/web-socket-receiver.js
+++ b/public/javascripts/web-socket-receiver.js
@@ -133,25 +133,7 @@ var WebSocketReceiver = {
   },
 
   addPostToStream: function(postId, html) {
-    if( $(".stream_element[data-guid='" + postId + "']").length === 0 ) {
-      var streamElement = $(html);
-
-      var showMessage = function() {
-        $("#main_stream:not('.show')").prepend(
-          streamElement.fadeIn("fast", function() {
-            streamElement.find("label").inFieldLabels();
-          })
-        );
-      };
-
-      if( $("#no_posts").is(":visible") ) {
-        $("#no_posts").fadeOut(400, showMessage()).hide();
-      } else {
-        showMessage();
-      }
-      Diaspora.widgets.timeago.updateTimeAgo();
-      Diaspora.widgets.directionDetector.updateBinds();
-    }
+    
   },
 
   onPageForClass: function(className) {
diff --git a/spec/controllers/aspects_controller_spec.rb b/spec/controllers/aspects_controller_spec.rb
index 9923d99e818b975480b023c496847e9f0f0da0cc..95d65af7a4c0ec6c5f847b5e403ca079351f3ce0 100644
--- a/spec/controllers/aspects_controller_spec.rb
+++ b/spec/controllers/aspects_controller_spec.rb
@@ -68,6 +68,8 @@ describe AspectsController do
       bob.comment("what", :on => message)
       get :index
       save_fixture(html_for("body"), "aspects_index_with_posts")
+      
+      save_fixture(html_for(".stream_element:first"), "status_message_in_stream")
     end
 
     context 'with getting_started = true' do
diff --git a/spec/javascripts/content-updates-spec.js b/spec/javascripts/content-updates-spec.js
new file mode 100644
index 0000000000000000000000000000000000000000..eea6abecfc31480332f871287644561cb8f9588d
--- /dev/null
+++ b/spec/javascripts/content-updates-spec.js
@@ -0,0 +1,32 @@
+/*   Copyright (c) 2010, Diaspora Inc.  This file is
+*   licensed under the Affero General Public License version 3 or later.  See
+*   the COPYRIGHT file.
+*/
+describe("ContentUpdates", function() {
+  describe("addPostToStream", function() {
+    beforeEach(function() {
+      $("#jasmine_content").empty();
+      spec.loadFixture("aspects_index_with_posts");
+    });
+
+    it("adds a post to the stream", function() {
+      var originalPostCount = $(".stream_element").length;
+      ContentUpdates.addPostToStream("guid", spec.fixtureHtml("status_message_in_stream"));
+      expect($(".stream_element").length).toBeGreaterThan(originalPostCount);
+    });
+
+    it("does not add duplicate posts", function() {
+      ContentUpdates.addPostToStream("guid", spec.fixtureHtml("status_message_in_stream"));
+      var originalPostCount = $(".stream_element").length;
+      ContentUpdates.addPostToStream("guid", spec.fixtureHtml("status_message_in_stream"));
+      expect($(".stream_element").length).toEqual(originalPostCount);
+    });
+
+    it("removes the div that says you have no posts if it exists", function() {
+      spec.loadFixture("aspects_index");
+      expect($("#no_posts").length).toEqual(1);
+      ContentUpdates.addPostToStream("guid", spec.fixtureHtml("status_message_in_stream"));
+      expect($("#no_posts").length).toEqual(0);
+    });
+  });
+});
diff --git a/spec/javascripts/support/jasmine.yml b/spec/javascripts/support/jasmine.yml
index dd353c96f3b4ce1a000517508c915f0f171823f0..9f56fb62b722aa072cb377142ed1ff3352aefa33 100644
--- a/spec/javascripts/support/jasmine.yml
+++ b/spec/javascripts/support/jasmine.yml
@@ -40,6 +40,7 @@ src_files:
   - public/javascripts/validation.js
   - public/javascripts/rails.js
   - public/javascripts/aspect-filters.js
+  - public/javascripts/content-updates.js
 # stylesheets
 #
 # Return an array of stylesheet filepaths relative to src_dir to include before jasmine specs.