diff --git a/opensans.patch b/opensans.patch
new file mode 100644
index 0000000000000000000000000000000000000000..12889b270003f0b8a2233e7211653255f7069127
--- /dev/null
+++ b/opensans.patch
@@ -0,0 +1,476 @@
+diff --git a/src/skins/vector/css/atoms/ImageView.css b/src/skins/vector/css/atoms/ImageView.css
+index 22ef343..9dd34f8 100644
+--- a/src/skins/vector/css/atoms/ImageView.css
++++ b/src/skins/vector/css/atoms/ImageView.css
+@@ -87,13 +87,13 @@ limitations under the License.
+ }
+ 
+ .mx_ImageView_name {
+-    font-size: 20px;
++    font-size: 18px;
+     margin-bottom: 6px;
+     pointer-events: all;
+ }
+ 
+ .mx_ImageView_metadata {
+-    font-size: 16px;
++    font-size: 15px;
+     opacity: 0.5;
+     pointer-events: all;
+ }
+@@ -105,13 +105,13 @@ limitations under the License.
+     margin-bottom: 6px;
+     border-radius: 5px;
+     background-color: #454545;
+-    font-size: 16px;
++    font-size: 14px;
+     padding: 9px;
+     border: 1px solid #fff;
+ }
+ 
+ .mx_ImageView_size {
+-    font-size: 12px;
++    font-size: 11px;
+ }
+ 
+ .mx_ImageView_link {
+@@ -121,7 +121,7 @@ limitations under the License.
+ 
+ .mx_ImageView_button {
+     pointer-events: all;
+-    font-size: 16px;
++    font-size: 15px;
+     opacity: 0.5;
+     margin-top: 18px;
+     cursor: pointer;
+diff --git a/src/skins/vector/css/common.css b/src/skins/vector/css/common.css
+index af2d4be..1e6db69 100644
+--- a/src/skins/vector/css/common.css
++++ b/src/skins/vector/css/common.css
+@@ -22,13 +22,13 @@ html {
+ }
+ 
+ body {
+-    /* Myriad Pro lacks combining diacritics, so these will fall through
++    /* Open Sans lacks combining diacritics, so these will fall through
+        to the next font.  Helevetica's diacritics however do not combine
+-       nicely with Myriad Pro (on OSX, at least) and result in a huge
++       nicely with Open Sans (on OSX, at least) and result in a huge
+        horizontal mess.  Arial empirically gets it right, hence prioritising
+        Arial here. */
+-    font-family: 'Myriad Pro', Arial, Helvetica, Sans-Serif;
+-    font-size: 16px;
++    font-family: 'Open Sans', Arial, Helvetica, Sans-Serif;
++    font-size: 15px;
+     color: #454545;
+     border: 0px;
+     margin: 0px;
+@@ -41,7 +41,7 @@ div.error {
+ h2 {
+     color: #454545;
+     font-weight: 400;
+-    font-size: 20px;
++    font-size: 18px;
+     margin-top: 16px;
+     margin-bottom: 16px;
+ }
+@@ -129,7 +129,7 @@ a:visited {
+     text-align: center;
+     z-index: 4010;
+     font-weight: 300;
+-    font-size: 16px;
++    font-size: 15px;
+     position: relative;
+     border-radius: 8px;
+     max-width: 80%;
+@@ -172,7 +172,7 @@ a:visited {
+     height: 36px;
+     border-radius: 36px;
+     font-weight: 400;
+-    font-size: 16px;
++    font-size: 15px;
+     color: #fff;
+     background-color: #76cfa6;
+     margin-left: 8px;
+@@ -187,6 +187,6 @@ a:visited {
+     padding: 12px;
+     border-bottom: 1px solid #a4a4a4;
+     font-weight: bold;
+-    font-size: 20px;
++    font-size: 18px;
+     line-height: 1.4;
+ }
+diff --git a/src/skins/vector/css/molecules/EventTile.css b/src/skins/vector/css/molecules/EventTile.css
+index 152fde1..2fcd832 100644
+--- a/src/skins/vector/css/molecules/EventTile.css
++++ b/src/skins/vector/css/molecules/EventTile.css
+@@ -42,7 +42,7 @@ limitations under the License.
+ .mx_EventTile .mx_SenderProfile {
+     color: #454545;
+     opacity: 0.5;
+-    font-size: 14px;
++    font-size: 13px;
+     margin-bottom: 4px;
+     display: block;
+     overflow-y: hidden;
+@@ -50,7 +50,7 @@ limitations under the License.
+ 
+ .mx_EventTile .mx_MessageTimestamp {
+     color: #acacac;
+-    font-size: 12px;
++    font-size: 11px;
+ }
+ 
+ .mx_EventTile_line {
+@@ -74,6 +74,7 @@ limitations under the License.
+     font-family: inherit ! important;
+     white-space: normal ! important;
+     line-height: inherit ! important;
++    font-size: 15px;
+ }
+ 
+ .mx_MessageTile_content .markdown-body h1,
+@@ -175,6 +176,6 @@ limitations under the License.
+ 
+ .mx_EventTile_readAvatarRemainder {
+     color: #acacac;
+-    font-size: 12px;
++    font-size: 11px;
+     position: absolute;
+ }
+diff --git a/src/skins/vector/css/molecules/MemberInfo.css b/src/skins/vector/css/molecules/MemberInfo.css
+index ac11dde..1c4ab38 100644
+--- a/src/skins/vector/css/molecules/MemberInfo.css
++++ b/src/skins/vector/css/molecules/MemberInfo.css
+@@ -38,7 +38,7 @@ limitations under the License.
+ 
+ .mx_MemberInfo_profileField {
+     font-color: #999999;    
+-    font-size: 14px;
++    font-size: 13px;
+     position: relative;
+     background-color: #fff;
+ }
+@@ -51,7 +51,7 @@ limitations under the License.
+     cursor: pointer;
+     width: 100px;
+     text-align: center;
+-    font-size: 12px;    
++    font-size: 11px;    
+     background-color: #888;
+     color: #fff;
+     font-weight: bold;
+diff --git a/src/skins/vector/css/molecules/MemberTile.css b/src/skins/vector/css/molecules/MemberTile.css
+index de34de5..df73904 100644
+--- a/src/skins/vector/css/molecules/MemberTile.css
++++ b/src/skins/vector/css/molecules/MemberTile.css
+@@ -55,13 +55,13 @@ limitations under the License.
+ }
+ 
+ .mx_MemberTile_userId {
+-    font-size: 14px;
++    font-size: 13px;
+     overflow: hidden;
+     text-overflow: ellipsis;
+ }
+ 
+ .mx_MemberTile_presence {
+-    font-size: 12px;
++    font-size: 11px;
+     opacity: 0.5;
+ }
+ 
+diff --git a/src/skins/vector/css/molecules/MessageComposer.css b/src/skins/vector/css/molecules/MessageComposer.css
+index 428d39e..7a767e1 100644
+--- a/src/skins/vector/css/molecules/MessageComposer.css
++++ b/src/skins/vector/css/molecules/MessageComposer.css
+@@ -59,7 +59,7 @@ limitations under the License.
+     box-shadow: none;
+ 
+     /* needed for FF */
+-    font-family: 'Myriad Pro', Arial, Helvetica, Sans-Serif;
++    font-family: 'Open Sans', Arial, Helvetica, Sans-Serif;
+ }
+ 
+ /* hack for FF as vertical alignment of custom placeholder text is broken */
+diff --git a/src/skins/vector/css/molecules/RoomDropTarget.css b/src/skins/vector/css/molecules/RoomDropTarget.css
+index 4eea49e..2e655c7 100644
+--- a/src/skins/vector/css/molecules/RoomDropTarget.css
++++ b/src/skins/vector/css/molecules/RoomDropTarget.css
+@@ -15,7 +15,7 @@ limitations under the License.
+ */
+ 
+ .mx_RoomDropTarget {
+-    font-size: 14px;
++    font-size: 13px;
+     margin-left: 10px;
+     margin-right: 15px;
+     padding-top: 5px;
+diff --git a/src/skins/vector/css/molecules/RoomHeader.css b/src/skins/vector/css/molecules/RoomHeader.css
+index 1a4fdbf..d2633bb 100644
+--- a/src/skins/vector/css/molecules/RoomHeader.css
++++ b/src/skins/vector/css/molecules/RoomHeader.css
+@@ -91,7 +91,7 @@ limitations under the License.
+ .mx_RoomHeader_simpleHeader {
+     line-height: 83px;
+     color: #454545;
+-    font-size: 24px;
++    font-size: 22px;
+     font-weight: bold;
+     overflow: hidden;
+     text-overflow: ellipsis;
+@@ -103,7 +103,7 @@ limitations under the License.
+     height: 28px;
+     color: #454545;
+     font-weight: bold;
+-    font-size: 24px;
++    font-size: 22px;
+     padding-left: 19px;
+     padding-right: 16px;
+     text-overflow: ellipsis;
+@@ -141,7 +141,7 @@ limitations under the License.
+     width: 260px;
+     border: 1px solid #c7c7c7;
+     font-weight: 300;
+-    font-size: 14px;
++    font-size: 13px;
+     padding: 9px;
+ }
+ 
+diff --git a/src/skins/vector/css/molecules/RoomSettings.css b/src/skins/vector/css/molecules/RoomSettings.css
+index a669c5b..dabdd55 100644
+--- a/src/skins/vector/css/molecules/RoomSettings.css
++++ b/src/skins/vector/css/molecules/RoomSettings.css
+@@ -39,7 +39,7 @@ limitations under the License.
+     border-radius: 3px;
+     border: 1px solid #c7c7c7;
+     font-weight: 300;
+-    font-size: 14px;
++    font-size: 13px;
+     padding: 9px;
+     margin-top: 6px;
+ }
+@@ -59,7 +59,7 @@ limitations under the License.
+     height: 36px;
+     border-radius: 36px;
+     font-weight: 400;
+-    font-size: 16px;
++    font-size: 15px;
+     color: #fff;
+     background-color: #76cfa6;
+     width: auto;
+diff --git a/src/skins/vector/css/molecules/RoomTile.css b/src/skins/vector/css/molecules/RoomTile.css
+index 37d2e1b..237c809 100644
+--- a/src/skins/vector/css/molecules/RoomTile.css
++++ b/src/skins/vector/css/molecules/RoomTile.css
+@@ -18,7 +18,7 @@ limitations under the License.
+     cursor: pointer;
+     /* This fixes wrapping of long room names, but breaks drag & drop previews */
+     /* display: table-row; */
+-    font-size: 14px;
++    font-size: 13px;
+ }
+ 
+ .mx_RoomTile_avatar {
+diff --git a/src/skins/vector/css/molecules/SearchBar.css b/src/skins/vector/css/molecules/SearchBar.css
+index b116674..762984f 100644
+--- a/src/skins/vector/css/molecules/SearchBar.css
++++ b/src/skins/vector/css/molecules/SearchBar.css
+@@ -25,7 +25,7 @@ limitations under the License.
+     display: inline block;
+     border-radius: 3px;
+     border: 1px solid #f0f0f0;
+-    font-size: 16px;
++    font-size: 15px;
+     padding: 9px;
+     padding-left: 11px;
+     margin-right: 17px;
+@@ -38,7 +38,7 @@ limitations under the License.
+     border: 0px;
+     border-radius: 36px;
+     font-weight: 400;
+-    font-size: 16px;
++    font-size: 15px;
+     color: #fff;
+     background-color: #76cfa6;
+     width: auto;
+diff --git a/src/skins/vector/css/molecules/ServerConfig.css b/src/skins/vector/css/molecules/ServerConfig.css
+index db0572c..58bdcfd 100644
+--- a/src/skins/vector/css/molecules/ServerConfig.css
++++ b/src/skins/vector/css/molecules/ServerConfig.css
+@@ -25,7 +25,7 @@ limitations under the License.
+ 
+ .mx_ServerConfig_help:link {
+     opacity: 0.8;
+-    font-size: 14px;
++    font-size: 13px;
+     font-weight: 300;
+     color: #4a4a4a;
+ }
+\ No newline at end of file
+diff --git a/src/skins/vector/css/organisms/CreateRoom.css b/src/skins/vector/css/organisms/CreateRoom.css
+index 578c79e..feb8bbf 100644
+--- a/src/skins/vector/css/organisms/CreateRoom.css
++++ b/src/skins/vector/css/organisms/CreateRoom.css
+@@ -26,7 +26,7 @@ limitations under the License.
+     border-radius: 3px;
+     border: 1px solid #c7c7c7;
+     font-weight: 300;
+-    font-size: 14px;
++    font-size: 13px;
+     padding: 9px;
+     margin-top: 6px;
+ }
+diff --git a/src/skins/vector/css/organisms/MemberList.css b/src/skins/vector/css/organisms/MemberList.css
+index 774f177..ce936d2 100644
+--- a/src/skins/vector/css/organisms/MemberList.css
++++ b/src/skins/vector/css/organisms/MemberList.css
+@@ -45,13 +45,13 @@ limitations under the License.
+ }
+ 
+ .mx_MemberList_invite {
+-    font-family: 'Myriad Pro', Arial, Helvetica, Sans-Serif;
++    font-family: 'Open Sans', Arial, Helvetica, Sans-Serif;
+     border-radius: 3px;
+     border: 1px solid #f0f0f0;
+     padding: 9px;
+     color: #454545;
+     margin-left: 3px;
+-    font-size: 16px;
++    font-size: 15px;
+     margin-bottom: 8px;
+     width: 180px;
+ }
+@@ -69,7 +69,7 @@ limitations under the License.
+     text-transform: uppercase;
+     color: #3d3b39;
+     font-weight: 600;
+-    font-size: 14px;
++    font-size: 13px;
+     padding-left: 3px;
+     padding-right: 12px;
+     margin-top: 8px;
+diff --git a/src/skins/vector/css/organisms/RightPanel.css b/src/skins/vector/css/organisms/RightPanel.css
+index bf473a4..7e60290 100644
+--- a/src/skins/vector/css/organisms/RightPanel.css
++++ b/src/skins/vector/css/organisms/RightPanel.css
+@@ -66,7 +66,7 @@ limitations under the License.
+ 
+ .mx_RightPanel_headerButton_badge {
+     position: absolute;
+-    top: 5px;
++    top: 4px;
+     left: 28px;
+     font-size: 12px;    
+     background-color: #76cfa6;
+diff --git a/src/skins/vector/css/organisms/RoomDirectory.css b/src/skins/vector/css/organisms/RoomDirectory.css
+index f53f055..61fcfa6 100644
+--- a/src/skins/vector/css/organisms/RoomDirectory.css
++++ b/src/skins/vector/css/organisms/RoomDirectory.css
+@@ -50,7 +50,7 @@ limitations under the License.
+     border-radius: 3px;
+     border: 1px solid #c7c7c7;
+     font-weight: 300;
+-    font-size: 14px;
++    font-size: 13px;
+     padding: 9px;
+     margin-top: 12px;
+     margin-bottom: 12px;
+@@ -70,7 +70,7 @@ limitations under the License.
+ 
+ .mx_RoomDirectory_table th {
+     font-weight: 400;
+-    font-size: 12px;
++    font-size: 11px;
+ }
+ 
+ .mx_RoomDirectory_table tbody {
+@@ -79,7 +79,6 @@ limitations under the License.
+ 
+ .mx_RoomDirectory_table td {
+     font-weight: 300;
+-    font-size: 16px;
+     overflow-x: hidden;
+     text-overflow: ellipsis;
+ }
+@@ -90,7 +89,7 @@ limitations under the License.
+ 
+ .mx_RoomDirectory_table .mx_RoomDirectory_topic {
+     font-weight: 400;
+-    font-size: 12px;
++    font-size: 11px;
+ }
+ 
+ .mx_RoomDirectory_table td,
+diff --git a/src/skins/vector/css/organisms/RoomSubList.css b/src/skins/vector/css/organisms/RoomSubList.css
+index 57d23a3..b143c99 100644
+--- a/src/skins/vector/css/organisms/RoomSubList.css
++++ b/src/skins/vector/css/organisms/RoomSubList.css
+@@ -29,7 +29,7 @@ limitations under the License.
+     text-transform: uppercase;
+     color: #3d3b39;
+     font-weight: 600;
+-    font-size: 14px;
++    font-size: 13px;
+     padding-left: 12px;
+     padding-right: 12px;
+     margin-top: 8px;
+diff --git a/src/skins/vector/css/organisms/RoomView.css b/src/skins/vector/css/organisms/RoomView.css
+index 94fff29..81b0ef2 100644
+--- a/src/skins/vector/css/organisms/RoomView.css
++++ b/src/skins/vector/css/organisms/RoomView.css
+@@ -204,7 +204,7 @@ limitations under the License.
+ 
+ .mx_RoomView_connectionLostBar_desc {
+     color: #454545;
+-    font-size: 14px;
++    font-size: 13px;
+     opacity: 0.5;
+ }
+ 
+diff --git a/src/skins/vector/css/templates/Login.css b/src/skins/vector/css/templates/Login.css
+index 11fba43..d1b28b1 100644
+--- a/src/skins/vector/css/templates/Login.css
++++ b/src/skins/vector/css/templates/Login.css
+@@ -55,7 +55,7 @@ limitations under the License.
+     border-radius: 3px;
+     border: 1px solid #c7c7c7;
+     font-weight: 300;
+-    font-size: 14px;
++    font-size: 13px;
+     padding: 9px;
+     margin-bottom: 14px;
+ }
+@@ -68,12 +68,12 @@ limitations under the License.
+     height: 40px;
+     border: 0px;
+     background-color: #76cfa6;
+-    font-size: 16px;
++    font-size: 15px;
+     color: #fff;
+ }
+ 
+ .mx_Login_label {
+-    font-size: 14px;
++    font-size: 13px;
+     opacity: 0.8;
+ }
+ 
+@@ -85,7 +85,7 @@ limitations under the License.
+     display: block;
+     text-align: center;
+     width: 100%;
+-    font-size: 14px;
++    font-size: 13px;
+     opacity: 0.8;
+ }
+ 
+@@ -97,7 +97,7 @@ limitations under the License.
+     display: block;
+     text-align: center;
+     width: 100%;
+-    font-size: 14px;
++    font-size: 13px;
+     opacity: 0.8;
+ }
+ 
diff --git a/package.json b/package.json
index ce376daebacc833d073a5c475d590f9e76a5608c..e22de47f8b644982c9c6ec744d209e6947e9ba2e 100644
--- a/package.json
+++ b/package.json
@@ -59,6 +59,14 @@
     "parallelshell": "^1.2.0",
     "rimraf": "^2.4.3",
     "source-map-loader": "^0.1.5",
-    "webpack": "^1.12.13"
+    "webpack": "^1.12.13",
+    "karma": ">=0.0.0",
+    "karma-cli": ">=0.0.0",
+    "karma-mocha": ">=0.0.0",
+    "karma-webpack": ">=0.0.0",
+    "karma-sourcemap-loader": ">=0.0.0",
+    "karma-chrome-launcher": ">=0.0.0",
+    "mocha": ">=0.0.0",
+    "expect": ">=0.0.0"
   }
 }
diff --git a/src/tests/components/structures/MatrixChat-test.js b/src/tests/components/structures/MatrixChat-test.js
new file mode 100644
index 0000000000000000000000000000000000000000..462b0cc7e26fbd00de97b3b568ce36f04a2581d6
--- /dev/null
+++ b/src/tests/components/structures/MatrixChat-test.js
@@ -0,0 +1,12 @@
+var React = require('react/addons'),
+    TestUtils = React.addons.TestUtils,
+    expect = require('expect'),
+    ScatterPlot = require('');
+
+var sdk = require("matrix-react-sdk");
+sdk.loadSkin(require('../../../component-index'));
+
+var MatrixChat = sdk.getComponent('structures.MatrixChat');
+
+describe('MatrixChat', function () {
+});
\ No newline at end of file
diff --git a/tests.webpack.js b/tests.webpack.js
new file mode 100644
index 0000000000000000000000000000000000000000..bdbcf555789774057b63e6a2de7f8ea5e3af0b60
--- /dev/null
+++ b/tests.webpack.js
@@ -0,0 +1,3 @@
+// tests.webpack.js
+var context = require.context('./src', true, /-test\.jsx?$/);
+context.keys().forEach(context);