diff --git a/comment/Makefile b/comment/Makefile deleted file mode 100644 index eceaff4..0000000 --- a/comment/Makefile +++ /dev/null @@ -1,23 +0,0 @@ -JSHINT = node_modules/.bin/jshint -BROWSERIFY = node_modules/.bin/browserify -CASPERJS = node_modules/.bin/casperjs -EXORCIST = node_modules/.bin/exorcist -CASPERJS = ./node_modules/.bin/casperjs --ssl-protocol=tlsv1 - -BUNDLE = ../public/comment.js -MAP = $(BUNDLE).map - -export SHELLOPTS:=errexit:pipefail - -.DELETE_ON_ERROR: - -all: $(BUNDLE) - -$(BUNDLE): comment.js Makefile - rm -f $(MAP) - $(BROWSERIFY) --standalone bcComment --debug -t brfs -t uglifyify $< | $(EXORCIST) $(MAP) > $@ - -test: - $(CASPERJS) test tests/stories/validation.js - -.PHONY: all diff --git a/comment/README.md b/comment/README.md deleted file mode 100644 index 00de5dd..0000000 --- a/comment/README.md +++ /dev/null @@ -1,21 +0,0 @@ -Comment form subproject. - -## Building - -Install dependencies (in comment directory): - - npm install - -Build bundle: - - make all - -## Testing - -Load Blog-Core tests (in main project root): - - swipl -s tests/tests.pl - -Run frontend tests (in comment directory): - - make test diff --git a/comment/comment.js b/comment/comment.js deleted file mode 100644 index 5e3265c..0000000 --- a/comment/comment.js +++ /dev/null @@ -1,424 +0,0 @@ -// Trim shim for IE8. - -if (typeof String.prototype.trim !== 'function') { - - String.prototype.trim = function() { - - return this.replace(/^\s+|\s+$/g, ''); - }; -} - -// Helper for API queries. - -var api = { - - // Retrieves captcha question. - - question: function(cb) { - - var xhr = new XMLHttpRequest(); - - xhr.open('GET', '/api/question', true); - - xhr.onreadystatechange = api.ready(xhr, cb); - - xhr.send(); - }, - - // Sends new comment. - - post: function(id, values, cb) { - - var xhr = new XMLHttpRequest(); - - var url = '/api/post/' + encodeURIComponent(id) + '/comment'; - - xhr.open('POST', url, true); - - xhr.setRequestHeader('Content-Type', 'application/json'); - - xhr.onreadystatechange = api.ready(xhr, cb); - - xhr.send(JSON.stringify(data)); - }, - - // Returns function for state change. - - ready: function(xhr, cb) { - - return function() { - - if (xhr.readyState === 4) { - - if (xhr.status === 200) { - - cb(null, JSON.parse(xhr.responseText)); - - } else { - - cb(new Error('API error.')); - } - } - } - } -}; - -// Helper to extract values from input elements. - -var input = { - - string: function(element) { - - return element ? element.value.trim() : undefined; - }, - - check: function(element) { - - return element ? element.checked : false; - }, - - int: function(element) { - - return element ? parseInt(element.value, 10) : undefined; - } -}; - -// Helpers to validate data. - -var validator = { - - // String validators. - - string: { - - is_set: function(value, list) { - - if (typeof value === 'undefined' || - value.length === 0) { - - list.push('__ must be set.'); - } - }, - - email: function(value, list) { - - if (typeof value === 'string' && - value !== '' && - !value.match(/[^@]+@[^@]+/)) { - - list.push('__ must match email pattern.'); - } - }, - - site: function(value, list) { - - if (typeof value === 'string' && - value !== '' && - !value.match(/https?:\/\//)) { - - list.push('__ must match URL pattern.'); - } - } - }, - - // Checks array of validators. - - check: function(row, key, value) { - - var list = []; - - var validators = row.validators || []; - - for (var i = 0; i < validators.length; i++) { - - validators[i].call(null, value, list); - } - - var label = key.substring(0, 1).toUpperCase() + - key.substring(1); - - for (var j = 0; j < list.length; j++) { - - list[j] = list[j].replace('__', label); - } - - return list; - } -}; - -// Helper to work with DOM classes. - -var clazz = { - - list: function(element) { - - return element.className.split(/\s+/); - }, - - // Removes element class. - - remove: function(element, cls) { - - var list = clazz.list(element); - - var removed = []; - - for (var i = 0; i < list.length; i++) { - - if (list[i] !== cls && list[i] !== '') { - - removed.push(list[i]); - } - } - - element.className = removed.join(' '); - }, - - // Adds element class. - - add: function(element, cls) { - - var list = clazz.list(element); - - var found = false; - - for (var i = 0; i < list.length; i++) { - - if (list[i] === cls) { - - found = true; - } - } - - if (!found) { - - list.push(cls); - } - - element.className = list.join(' '); - } -}; - -// Helper to manage form errors. - -var errors = { - - // Adds new error. - - display: function(row, message) { - - clazz.add(row.element.parentNode, 'error'); - - row.error = document.createElement('div'); - - row.error.innerHTML = message; - - row.element.parentNode.appendChild(row.error); - }, - - // Removes all errors. - - remove: function(row) { - - var type = row.element.getAttribute('type'); - - // Ignore hidden inputs. - - if (type !== 'hidden') { - - clazz.remove(row.element.parentNode, 'error'); - } - - if (row.error) { - - row.error.parentNode.removeChild(row.error); - - delete row.error; - } - } -}; - -// Helper that processes inputs object. - -var reader = { - - // Reads data from the form descriptor. - - read: function(desc) { - - var valid = true; - - var values = {}; - - reader.each(desc, function(row, key) { - - errors.remove(row); - - var value = input[row.type](row.element); - - var list = validator.check(row, key, value); - - if (list.length > 0) { - - valid = false; - - errors.display(row, list.join(' ')); - } - - if (typeof value !== 'undefined') { - - values[key] = value; - } - }); - - return { values: values, valid: valid }; - }, - - // Runs callback for each input. - - each: function(desc, cb) { - - for (var key in desc) { - - var row = desc[key]; - - // Consider only defined elements. - - if (row.element) { - - cb(row, key); - } - } - } -}; - -module.exports = function(options) { - - if (typeof options.form === 'string') { - - options.form = document.querySelector(options.form); - } - - if (typeof options.question === 'string') { - - options.question = document.querySelector(options.question); - } - - if (!options.form) { - - throw new Error('Comment form element not specified.'); - } - - if (!options.question) { - - throw new Error('Verification question element not specified.'); - } - - if (!options.message) { - - throw new Error('Feedback message/error element not specified.'); - } - - var form = options.form; - - var elements = form.elements; - - var data = { - - post_id: { - - type: 'string', - - element: elements.post_id - }, - - reply_to: { - - type: 'string', - - element: elements.reply_to - }, - - author: { - - type: 'string', - - validators: [ validator.string.is_set ], - - element: elements.author - }, - - email: { - - type: 'string', - - validators: [ validator.string.email ], - - element: elements.email - }, - - site: { - - type: 'string', - - validators: [ validator.string.site ], - - element: elements.site - }, - - content: { - - type: 'string', - - validators: [ validator.string.is_set ], - - element: elements.content - }, - - notify: { - - type: 'check', - - element: elements.notify - }, - - question: { - - type: 'int', - - element: elements.question - }, - - answer: { - - type: 'string', - - validators: [ validator.string.is_set ], - - element: elements.answer - } - }; - - api.question(function(err, response) { - - if (err) { - - - } else { - - // TODO check that question element is set. - // TODO check response status - - options.question.innerHTML = response.data.question; - } - }); - - form.onsubmit = function() { - - var result = reader.read(data); - - console.log(JSON.stringify(result, null, 2)); - - return false; - }; -}; diff --git a/comment/package.json b/comment/package.json deleted file mode 100644 index 76d0c46..0000000 --- a/comment/package.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "name": "blog-core-comment", - "version": "0.0.1", - "private": true, - "devDependencies": { - "browserify": "4.x", - "exorcist": "^0.3.0", - "jshint": "~2.5.5", - "uglifyify": "^3.0.1", - "brfs": "~1.2.0", - "casperjs": "~1.1.0-beta3" - } -} diff --git a/comment/tests/host.js b/comment/tests/host.js deleted file mode 100644 index 74dc6cd..0000000 --- a/comment/tests/host.js +++ /dev/null @@ -1 +0,0 @@ -module.exports = 'http://localhost:18008'; diff --git a/comment/tests/stories/validation.js b/comment/tests/stories/validation.js deleted file mode 100644 index 9079603..0000000 --- a/comment/tests/stories/validation.js +++ /dev/null @@ -1,101 +0,0 @@ -var host = require('../host'); - -casper.test.begin('Check validation', function(test) { - - // The start page. Should be quick to load. - - casper.start(host + '/comment.html', function() { - - test.assertTitle('Blog-Core comment system test'); - - casper.viewport(1366, 1200); - }); - - // Checks that no validation error exists. - - casper.then(function() { - - test.assertTextDoesntExist('Email must match email pattern.'); - test.assertTextDoesntExist('Site must match URL pattern.'); - test.assertTextDoesntExist('Author must be set.'); - test.assertTextDoesntExist('Content must be set.'); - test.assertTextDoesntExist('Answer must be set.'); - }); - - casper.thenClick('button[type="submit"]'); - - // Default inputs. - - casper.then(function() { - - test.assertTextExists('Author must be set.'); - test.assertTextExists('Content must be set.'); - test.assertTextExists('Answer must be set.'); - }); - - // Insert author. - - casper.then(function() { - - this.fill('#comment-form', { author: 'Raivo' }, true); - }); - - casper.then(function() { - - test.assertTextExists('Content must be set.'); - test.assertTextExists('Answer must be set.'); - }); - - // Insert invalid mail. - - casper.then(function() { - - this.fill('#comment-form', { email: 'invalid'}, true); - }); - - casper.then(function() { - - test.assertTextExists('Email must match email pattern.'); - }); - - // Insert valid mail. - - casper.then(function() { - - this.fill('#comment-form', { email: 'info@infdot.com'}, true); - }); - - casper.then(function() { - - test.assertTextDoesntExist('Email must match email pattern.'); - }); - - // Insert invalid site. - - casper.then(function() { - - this.fill('#comment-form', { site: 'invalid'}, true); - }); - - casper.then(function() { - - test.assertTextExists('Site must match URL pattern.'); - }); - - // Insert valid site. - - casper.then(function() { - - this.fill('#comment-form', { site: 'http://example.com'}, true); - }); - - casper.then(function() { - - test.assertTextDoesntExist('Site must match URL pattern.'); - }); - - casper.run(function() { - - test.done(); - }); -}); diff --git a/public/comment.html b/public/comment.html deleted file mode 100644 index 2deefe2..0000000 --- a/public/comment.html +++ /dev/null @@ -1,86 +0,0 @@ - - -
- -