From 489dab333ab7ef1b89c41484b020f59da441b446 Mon Sep 17 00:00:00 2001
From: Wojciech Zawistowski <wojciech.zawistowski@gmail.com>
Date: Wed, 30 Oct 2013 21:56:48 +0100
Subject: [PATCH] extracts logo component from header

---
 .../discourse/components/logo_component.js    |  21 +++
 .../components/discourse-logo.js.handlebars   |  17 ++
 .../discourse/templates/header.js.handlebars  |   2 +-
 .../discourse/views/header_view.js            |  25 ---
 .../components/logo_component_test.js         | 148 ++++++++++++++++++
 test/javascripts/integration/header_test.js   |  42 +++--
 6 files changed, 215 insertions(+), 40 deletions(-)
 create mode 100644 app/assets/javascripts/discourse/components/logo_component.js
 create mode 100644 app/assets/javascripts/discourse/templates/components/discourse-logo.js.handlebars
 create mode 100644 test/javascripts/components/logo_component_test.js

diff --git a/app/assets/javascripts/discourse/components/logo_component.js b/app/assets/javascripts/discourse/components/logo_component.js
new file mode 100644
index 000000000..3091ff096
--- /dev/null
+++ b/app/assets/javascripts/discourse/components/logo_component.js
@@ -0,0 +1,21 @@
+Discourse.DiscourseLogoComponent = Ember.Component.extend({
+  linkUrl: function() {
+    return Discourse.getURL("/");
+  }.property(),
+
+  showSmallLogo: function() {
+    return !Discourse.Mobile.mobileView && this.get("minimized");
+  }.property("minimized"),
+
+  smallLogoUrl: function() {
+    return Discourse.SiteSettings.logo_small_url;
+  }.property(),
+
+  bigLogoUrl: function() {
+    return Discourse.SiteSettings.logo_url;
+  }.property(),
+
+  title: function() {
+    return Discourse.SiteSettings.title;
+  }.property()
+});
diff --git a/app/assets/javascripts/discourse/templates/components/discourse-logo.js.handlebars b/app/assets/javascripts/discourse/templates/components/discourse-logo.js.handlebars
new file mode 100644
index 000000000..eef0c2c92
--- /dev/null
+++ b/app/assets/javascripts/discourse/templates/components/discourse-logo.js.handlebars
@@ -0,0 +1,17 @@
+<div class="title">
+  <a href="{{unbound linkUrl}}">
+    {{#if showSmallLogo}}
+      {{#if smallLogoUrl}}
+        <img class="logo-small" src="{{unbound smallLogoUrl}}" width="33" height="33">
+      {{else}}
+        <i class="icon-home"></i>
+      {{/if}}
+    {{else}}
+      {{#if bigLogoUrl}}
+        <img id="site-logo" class="logo-big" src="{{unbound bigLogoUrl}}" alt="{{unbound title}}">
+      {{else}}
+        <h2 id="site-text-logo" class="text-logo">{{unbound title}}</h2>
+      {{/if}}
+    {{/if}}
+  </a>
+</div>
diff --git a/app/assets/javascripts/discourse/templates/header.js.handlebars b/app/assets/javascripts/discourse/templates/header.js.handlebars
index 0dbe0e517..5e59f0c83 100644
--- a/app/assets/javascripts/discourse/templates/header.js.handlebars
+++ b/app/assets/javascripts/discourse/templates/header.js.handlebars
@@ -1,7 +1,7 @@
 <div class='container'>
   <div class='contents clearfix'>
 
-    {{view.logoHTML}}
+    {{discourse-logo minimized=showExtraInfo}}
 
     {{#if showExtraInfo}}
       <div class="extra-info-wrapper">
diff --git a/app/assets/javascripts/discourse/views/header_view.js b/app/assets/javascripts/discourse/views/header_view.js
index 458385466..6ecc9fea3 100644
--- a/app/assets/javascripts/discourse/views/header_view.js
+++ b/app/assets/javascripts/discourse/views/header_view.js
@@ -91,31 +91,6 @@ Discourse.HeaderView = Discourse.View.extend({
     });
 
   },
-  /**
-    Display the correct logo in the header, showing a custom small icon if it exists.
-    In case the logo_url setting is empty, shows the site title as the logo.
-    @property logoHTML
-  **/
-  logoHTML: function() {
-    var result = "<div class='title'><a href='" + Discourse.getURL("/") + "'>";
-    if (!Discourse.Mobile.mobileView && this.get('controller.showExtraInfo')) {
-      var logoSmall = Discourse.SiteSettings.logo_small_url;
-      if (logoSmall && logoSmall.length > 1) {
-        result += "<img class='logo-small' src='" + logoSmall + "' width='33' height='33'>";
-      } else {
-        result += "<i class='icon-home'></i>";
-      }
-    } else {
-      var logo = Discourse.SiteSettings.logo_url;
-      if(logo && logo.length > 1) {
-        result += "<img class='logo-big' src=\"" + logo + "\" alt=\"" + Discourse.SiteSettings.title + "\" id='site-logo'>";
-      } else {
-        result += "<h2 class='text-logo' id='site-text-logo'>" + Discourse.SiteSettings.title + "</h2>";
-      }
-    }
-    result += "</a></div>";
-    return new Handlebars.SafeString(result);
-  }.property('controller.showExtraInfo'),
 
   willDestroyElement: function() {
     $(window).unbind('scroll.discourse-dock');
diff --git a/test/javascripts/components/logo_component_test.js b/test/javascripts/components/logo_component_test.js
new file mode 100644
index 000000000..d086b648f
--- /dev/null
+++ b/test/javascripts/components/logo_component_test.js
@@ -0,0 +1,148 @@
+var view, oldMobileView;
+
+var View = Ember.View.extend({
+  template: Ember.Handlebars.compile("{{discourse-logo minimized=view.minimized}}")
+});
+
+
+var setSmallLogoUrl = function(url) {
+  Discourse.SiteSettings.logo_small_url = url;
+};
+
+var setBigLogoUrl = function(url) {
+  Discourse.SiteSettings.logo_url = url;
+};
+
+var setTitle = function(title) {
+  Discourse.SiteSettings.title = title;
+};
+
+var setMobileView = function(value) {
+  Discourse.Mobile.mobileView = value;
+};
+
+var setMinimized = function(value) {
+  Ember.run(function() {
+    view.set("minimized", value);
+  });
+};
+
+
+var smallLogoSelector = "img.logo-small";
+var bigLogoSelector = "img#site-logo.logo-big";
+var homeIconSelector = "i.icon-home";
+var headerSelector = "h2#site-text-logo.text-logo";
+
+
+var appendView = function() {
+  Ember.run(function() {
+    view.appendTo(Ember.$("#qunit-fixture"));
+  });
+};
+
+var exists = function(selector) {
+  return Ember.$(selector).length > 0;
+};
+
+
+module("Discourse.DiscourseLogoComponent", {
+  setup: function() {
+    oldMobileView = Discourse.Mobile.mobileView;
+
+    setSmallLogoUrl("small-logo-url");
+    setBigLogoUrl("big-logo-url");
+
+    view = View.create();
+  },
+
+  teardown: function() {
+    Discourse.Mobile.mobileView = oldMobileView;
+  }
+});
+
+test("displays small logo when 'minimized' version is chosen and application is not in mobile mode", function() {
+  setMobileView(false);
+  setMinimized(true);
+
+  appendView();
+
+  ok(exists(smallLogoSelector), "small logo image is present");
+  equal(Ember.$(smallLogoSelector).attr("src"), "small-logo-url", "small logo image has correct source");
+  ok(!exists(homeIconSelector), "default home icon is not present");
+  ok(!exists(bigLogoSelector), "big logo image is not present");
+});
+
+test("displays default home icon when small logo image should be displayed but its url is not configured", function() {
+  setMobileView(false);
+  setMinimized(true);
+  setSmallLogoUrl("");
+
+  appendView();
+
+  ok(exists(homeIconSelector), "default home icon is present");
+  ok(!exists(smallLogoSelector), "small logo image is not present");
+  ok(!exists(bigLogoSelector), "big logo image is not present");
+});
+
+test("displays big logo when 'minimized' version is not chosen", function() {
+  setMobileView(false);
+  setMinimized(false);
+
+  appendView();
+
+  ok(exists(bigLogoSelector), "big logo image is present");
+  ok(!exists(smallLogoSelector), "small logo image is not present");
+});
+
+test("displays big logo when application is in mobile mode", function() {
+  setMobileView(true);
+  setMinimized(true);
+
+  appendView();
+
+  ok(exists(bigLogoSelector), "big logo image is present");
+  ok(!exists(smallLogoSelector), "small logo image is not present");
+});
+
+test("displays big logo image with alt title when big logo url is configured", function() {
+  setMobileView(true);
+  setMinimized(false);
+  setTitle("site-title");
+
+  appendView();
+
+  ok(exists(bigLogoSelector), "big logo image is present");
+  equal(Ember.$(bigLogoSelector).attr("src"), "big-logo-url", "big logo image has correct source");
+  equal(Ember.$(bigLogoSelector).attr("alt"), "site-title", "big logo image has correct alt text");
+  ok(!exists(headerSelector), "header with title is not present");
+});
+
+test("displays header with site title when big logo image should be displayed but its url is not configured", function() {
+  setMobileView(true);
+  setMinimized(false);
+  setTitle("site-title");
+  setBigLogoUrl("");
+
+  appendView();
+
+  ok(exists(headerSelector), "header with title is present");
+  equal(Ember.$(headerSelector).text(), "site-title", "header with title has correct text");
+  ok(!exists(bigLogoSelector), "big logo image is not present");
+});
+
+test("dynamically toggles logo size when 'minimized' property changes", function() {
+  setMobileView(false);
+  setMinimized(true);
+
+  appendView();
+  ok(exists(smallLogoSelector), "initially small logo is shown");
+
+  setMinimized(false);
+  ok(exists(bigLogoSelector), "when 'minimized' version is turned off, small logo is replaced with the big one");
+});
+
+test("links logo to the site root", function() {
+  appendView();
+
+  equal(Ember.$(".title > a").attr("href"), "/");
+});
diff --git a/test/javascripts/integration/header_test.js b/test/javascripts/integration/header_test.js
index d725033d1..f8c395dc6 100644
--- a/test/javascripts/integration/header_test.js
+++ b/test/javascripts/integration/header_test.js
@@ -12,9 +12,11 @@ test("/", function() {
 test("displays small logo when extra info is shown and it is not mobile view", function() {
   expect(4);
 
+  Discourse.SiteSettings.logo_small_url = "logo-small-url";
+  Discourse.Mobile.mobileView = false;
+  Discourse.reset();
+
   Ember.run(function() {
-    Discourse.SiteSettings.logo_small_url = "logo-small-url";
-    Discourse.Mobile.mobileView = false;
     controllerFor("header").set("showExtraInfo", true);
   });
 
@@ -29,9 +31,11 @@ test("displays small logo when extra info is shown and it is not mobile view", f
 test("displays default home icon when small logo image source is not configured", function() {
   expect(3);
 
+  Discourse.SiteSettings.logo_small_url = "";
+  Discourse.Mobile.mobileView = false;
+  Discourse.reset();
+
   Ember.run(function() {
-    Discourse.SiteSettings.logo_small_url = "";
-    Discourse.Mobile.mobileView = false;
     controllerFor("header").set("showExtraInfo", true);
   });
 
@@ -45,8 +49,10 @@ test("displays default home icon when small logo image source is not configured"
 test("displays normal (big) logo when extra info is not shown", function() {
   expect(2);
 
+  Discourse.Mobile.mobileView = false;
+  Discourse.reset();
+
   Ember.run(function() {
-    Discourse.Mobile.mobileView = false;
     controllerFor("header").set("showExtraInfo", false);
   });
 
@@ -59,8 +65,10 @@ test("displays normal (big) logo when extra info is not shown", function() {
 test("displays normal (big) logo when it is mobile view", function() {
   expect(2);
 
+  Discourse.Mobile.mobileView = true;
+  Discourse.reset();
+
   Ember.run(function() {
-    Discourse.Mobile.mobileView = true;
     controllerFor("header").set("showExtraInfo", true);
   });
 
@@ -73,10 +81,12 @@ test("displays normal (big) logo when it is mobile view", function() {
 test("displays normal (big) logo image with alt title when big logo image source is configured", function() {
   expect(4);
 
+  Discourse.SiteSettings.logo_url = "logo-big-url";
+  Discourse.SiteSettings.title = "site-title";
+  Discourse.Mobile.mobileView = true;
+  Discourse.reset();
+
   Ember.run(function() {
-    Discourse.SiteSettings.logo_url = "logo-big-url";
-    Discourse.SiteSettings.title = "site-title";
-    Discourse.Mobile.mobileView = true;
     controllerFor("header").set("showExtraInfo", false);
   });
 
@@ -91,10 +101,12 @@ test("displays normal (big) logo image with alt title when big logo image source
 test("displays header with site title when big logo image source is not configured", function() {
   expect(3);
 
+  Discourse.SiteSettings.logo_url = "";
+  Discourse.SiteSettings.title = "site-title";
+  Discourse.Mobile.mobileView = true;
+  Discourse.reset();
+
   Ember.run(function() {
-    Discourse.SiteSettings.logo_url = "";
-    Discourse.SiteSettings.title = "site-title";
-    Discourse.Mobile.mobileView = true;
     controllerFor("header").set("showExtraInfo", false);
   });
 
@@ -108,9 +120,11 @@ test("displays header with site title when big logo image source is not configur
 test("dynamically toggles logo size when showing or hiding extra info", function() {
   expect(2);
 
+  Discourse.SiteSettings.logo_small_url = "logo-small-url";
+  Discourse.Mobile.mobileView = false;
+  Discourse.reset();
+
   Ember.run(function() {
-    Discourse.SiteSettings.logo_small_url = "logo-small-url";
-    Discourse.Mobile.mobileView = false;
     controllerFor("header").set("showExtraInfo", true);
   });