diff --git a/package.json b/package.json
new file mode 100644
index 0000000..2dd5022
--- /dev/null
+++ b/package.json
@@ -0,0 +1,33 @@
+{
+ "name": "thoughter",
+ "version": "1.0.0",
+ "author": "Brian Fiala",
+ "license": "ISC",
+ "description": "Definitely not a Twitter clone.",
+ "main": "src/js/recent-thoughts.js",
+ "scripts": {
+ "test": "karma start test.conf.js"
+ },
+ "dependencies": {
+ "fetch-mock": "^5.9.4",
+ "jquery": "^3.2.0"
+ },
+ "devDependencies": {
+ "chai": "^3.5.0",
+ "fetch-mock": "^5.9.4",
+ "grunt": "^1.0.1",
+ "grunt-contrib-clean": "^1.0.0",
+ "grunt-contrib-copy": "^1.0.0",
+ "grunt-contrib-jshint": "^1.1.0",
+ "grunt-contrib-sass": "^1.0.0",
+ "grunt-karma": "^2.0.0",
+ "karma": "^1.5.0",
+ "karma-chai": "^0.1.0",
+ "karma-chrome-launcher": "^2.0.0",
+ "karma-mocha": "^1.3.0",
+ "karma-requirejs": "^1.1.0",
+ "load-grunt-tasks": "^3.5.2",
+ "mocha": "^3.2.0",
+ "requirejs": "^2.3.3"
+ }
+}
diff --git a/src/index.html b/src/index.html
new file mode 100644
index 0000000..cbfdaf1
--- /dev/null
+++ b/src/index.html
@@ -0,0 +1,22 @@
+
+
+
+
+ Thoughter
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/js/new-thought.js b/src/js/new-thought.js
new file mode 100644
index 0000000..f56e972
--- /dev/null
+++ b/src/js/new-thought.js
@@ -0,0 +1,36 @@
+(function() {
+
+ window.thoughter = window.thoughter || {};
+
+ /**
+ * Creates a new thought with the given text
+ *
+ * @param {String} text The text to use for the thought - this is REQUIRED!
+ * @return {Promise} The resolved promise will have the new thought data object in it
+ */
+ window.thoughter.createThought = function createThought(text) {
+ if (typeof(text) !== 'string' || !text.length) {
+ return Promise.reject('Please provide text for this new thought');
+ }
+
+ return fetch(
+ 'http://thoughter.herokuapp.com/api/Thoughts',
+ {
+ method: 'post',
+ headers: {
+ 'Content-Type': 'application/json'
+ },
+ body: JSON.stringify({ content: text })
+ }
+ )
+ .then(function handleResponse(res) {
+ if (res.status > 299) {
+ console.error('Looks like a bad status code:', res.status);
+ return Promise.reject('Sorry, but there was a problem with your request.');
+ } else {
+ return res.json()
+ }
+ });
+ };
+
+})();
diff --git a/src/js/recent-thoughts.js b/src/js/recent-thoughts.js
index c548e79..45edecf 100644
--- a/src/js/recent-thoughts.js
+++ b/src/js/recent-thoughts.js
@@ -14,7 +14,7 @@
return;
}
- recent = document.querySelector('.recent');
+ let recent = document.querySelector('.recent');
thoughts.forEach(function showThought(thought) {
if (!thought.content || !thought.createTime || !thought.id) {
return;
diff --git a/src/sass/header.scss b/src/sass/header.scss
new file mode 100644
index 0000000..aed64e2
--- /dev/null
+++ b/src/sass/header.scss
@@ -0,0 +1,10 @@
+
+header {
+ border-bottom: $themeBorder;
+
+ h1 {
+ font-size: $topHeaderFontSize;
+ font-weight: bold;
+ margin-left: $topHeaderShift;
+ }
+}
diff --git a/src/sass/login.scss b/src/sass/login.scss
new file mode 100644
index 0000000..2a0f74b
--- /dev/null
+++ b/src/sass/login.scss
@@ -0,0 +1,7 @@
+
+.login {
+ form {
+ width: $loginWidth;
+ margin: 0 auto;
+ }
+}
diff --git a/src/sass/main.scss b/src/sass/main.scss
new file mode 100644
index 0000000..4fd5a1e
--- /dev/null
+++ b/src/sass/main.scss
@@ -0,0 +1,6 @@
+
+@import 'variables';
+@import 'header';
+@import 'login';
+// @import 'new-thought';
+@import 'recent';
diff --git a/src/sass/recent.scss b/src/sass/recent.scss
new file mode 100644
index 0000000..938e465
--- /dev/null
+++ b/src/sass/recent.scss
@@ -0,0 +1,10 @@
+
+.recent {
+ width: $recentContainerWidth;
+ margin: 0 auto;
+ display: flex;
+
+ article {
+ flex: 0 0 calc((100% / $thoughtColumns) - $thoughtMargin);
+ }
+}
diff --git a/src/sass/variables.scss b/src/sass/variables.scss
new file mode 100644
index 0000000..85ac3f8
--- /dev/null
+++ b/src/sass/variables.scss
@@ -0,0 +1,11 @@
+
+$themeFontColor: #222222;
+$themeBorder: 1px solid #99bbff;
+$topHeaderFontSize: 1.2em;
+$topHeaderShift: 5em;
+
+$loginWidth: 60%;
+
+$recentContainerWidth: 90%;
+$thoughtColumns: 2;
+$thoughtMargin: 2em;
diff --git a/src/style.css b/src/style.css
new file mode 100644
index 0000000..094e806
--- /dev/null
+++ b/src/style.css
@@ -0,0 +1,19 @@
+header {
+ border-bottom: 1px solid #99bbff; }
+ header h1 {
+ font-size: 1.2em;
+ font-weight: bold;
+ margin-left: 5em; }
+
+.login form {
+ width: 60%;
+ margin: 0 auto; }
+
+.recent {
+ width: 90%;
+ margin: 0 auto;
+ display: flex; }
+ .recent article {
+ flex: 0 0 calc((100% / $thoughtColumns) - $thoughtMargin); }
+
+/*# sourceMappingURL=style.css.map */
diff --git a/src/style.css.map b/src/style.css.map
new file mode 100644
index 0000000..e31a746
--- /dev/null
+++ b/src/style.css.map
@@ -0,0 +1,7 @@
+{
+"version": 3,
+"mappings": "AACA,MAAO;EACH,aAAa,ECAH,iBAAiB;EDE3B,SAAG;IACC,SAAS,ECFG,KAAK;IDGjB,WAAW,EAAE,IAAI;IACjB,WAAW,ECHF,GAAG;;ACFhB,WAAK;EACD,KAAK,EDGA,GAAG;ECFR,MAAM,EAAE,MAAM;;ACHtB,OAAQ;EACJ,KAAK,EFMc,GAAG;EELtB,MAAM,EAAE,MAAM;EACd,OAAO,EAAE,IAAI;EAEb,eAAQ;IACJ,IAAI,EAAE,mDAAmD",
+"sources": ["sass/header.scss","sass/variables.scss","sass/login.scss","sass/recent.scss"],
+"names": [],
+"file": "style.css"
+}
diff --git a/test.conf.js b/test.conf.js
new file mode 100644
index 0000000..8c6cd14
--- /dev/null
+++ b/test.conf.js
@@ -0,0 +1,13 @@
+module.exports = function karmaConfig( config) {
+ config.set({
+ frameworks: ['mocha', 'chai'],
+ browsers: ['Chrome'],
+ singleRun: true,
+ files: [
+ // globbing pattern for searching src directory and any sub for any js
+ 'src/js/*.js',
+ 'node_modules/fetch-mock/es5/client-browserified.js',
+ 'test/specs/**/*.js'
+ ]
+ });
+};
diff --git a/test/specs/thoughter.spec.js b/test/specs/thoughter.spec.js
new file mode 100644
index 0000000..166571c
--- /dev/null
+++ b/test/specs/thoughter.spec.js
@@ -0,0 +1,67 @@
+(function() {
+ 'use strict';
+
+ window.thoughter = window.thoughter || {};
+
+ let expect = chai.expect;
+ let showRecent = window.thoughter.showRecent;
+ let getRecent = window.thoughter.getRecent;
+
+ describe('thoughterDisplayModule', function() {
+
+ describe('recent thought function', function() {
+
+ beforeEach(function () {
+ let thoughtList = document.createElement('section');
+ thoughtList.classList.add('recent');
+ console.info('this is where I am using the console' + document.querySelector('body'));
+ document.querySelector('body').appendChild(thoughtList);
+ });
+
+ afterEach(function() {
+ (document.querySelectorAll('.recent')).forEach(function (recentSection) {
+ recentSection.parentNode.removeChild(recentSection);
+ });
+ });
+
+ let result;
+
+ it('should be a function', function() {
+ expect(showRecent).to.be.a('function');
+ });
+
+ it('should not change the page if passed any non-array parameter', function() {
+ result = showRecent('paramString');
+ expect(result).to.be.undefined;
+ result = showRecent();
+ expect(result).to.be.undefined;
+ });
+
+ it('should not add anything to the page when passed an empty array', function() {
+ showRecent([]);
+ expect(document.querySelectorAll('article.panel').length).to.eq(0);
+ });
+
+ it('should display valid thoughts', function() {
+ let thought = {'id': 'someNum', 'createTime': '9million o\'clock', 'content': "No thoughts were harmed in the making of this thought object"};
+ showRecent([thought]);
+ expect(document.querySelectorAll('article.panel').length).to.eq(1);
+ });
+
+ it('should not display invalid thoughts', function() {
+ let thought = {'id': 'someNum', 'content': "My thought is in pain"};
+ showRecent([thought]);
+ expect(document.querySelectorAll('article.panel').length).to.eq(0);
+ });
+
+ it('should add a thought for only valid thought objects in the passed array parameter', function() {
+ let thoughts = [{'id': 'someNum', 'createTime': '9million o\'clock', 'content': 'No thoughts were harmed in the making of this thought object'},
+ {'id': 'someNum', 'createTime': '9million o\'clock', 'content': 'No thoughts were harmed in the making of this thought object'},
+ {'id': 'someNum', 'content': 'This is an invalid thought. A thought was harmed in the making of this thought object'}];
+ showRecent(thoughts);
+ let thoughtPanel = document.querySelectorAll('.panel');
+ expect(thoughtPanel.length).to.eq(2);
+ });
+ });
+ });
+})();