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 + + + + + + +
+

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); + }); + }); + }); +})();