From cb5f162babe577ede5a113b49d072b51a97ecaad Mon Sep 17 00:00:00 2001 From: =?utf8?q?Aleksander=20=C5=81ukasz?= Date: Tue, 17 Dec 2013 14:52:24 +0100 Subject: [PATCH 01/16] wlxml: Remove "meta-" prefix for defined (aka "meta") attributes This change unifies structure type returned by getOtherAttributes with the one returned by getMetaAttributes so that these two can be easily merged if necessary. --- src/wlxml/wlxml.js | 21 +++++++++------------ src/wlxml/wlxml.test.js | 13 +++++++++---- 2 files changed, 18 insertions(+), 16 deletions(-) diff --git a/src/wlxml/wlxml.js b/src/wlxml/wlxml.js index a320da3..7f6e931 100644 --- a/src/wlxml/wlxml.js +++ b/src/wlxml/wlxml.js @@ -9,13 +9,6 @@ define([ /* globals Node */ -// utils - -var isMetaAttribute = function(attrName) { - return attrName.substr(0, 5) === 'meta-'; -}; - -// var AttributesList = function() {}; AttributesList.prototype = Object.create({}); @@ -62,24 +55,28 @@ $.extend(WLXMLElementNode.prototype, smartxml.ElementNode.prototype, { classDesc = this.document.options.wlxmlClasses[classCurrent]; if(classDesc) { _.keys(classDesc.attrs).forEach(function(attrName) { - toret[attrName] = _.extend({value: this.getAttr('meta-' + attrName)}, classDesc.attrs[attrName]); + toret[attrName] = _.extend({value: this.getAttr(attrName)}, classDesc.attrs[attrName]); }.bind(this)); } }.bind(this)); return toret; }, setMetaAttribute: function(key, value) { - this.setAttr('meta-'+key, value); + this.setAttr(key, value); }, getOtherAttributes: function() { - var toret = {}; + var toret = {}, + node = this; this.getAttrs().forEach(function(attr) { - if(attr.name !== 'class' && !isMetaAttribute(attr.name)) { - toret[attr.name] = attr.value; + if(attr.name !== 'class' && !node.isMetaAttribute(attr.name)) { + toret[attr.name] = {value: attr.value}; } }); return toret; }, + isMetaAttribute: function(attrName) { + return attrName !== 'class' &&_.contains(_.keys(this.getMetaAttributes()), attrName); + }, _getXMLDOMToDump: function() { var DOM = this._$.clone(true, true); diff --git a/src/wlxml/wlxml.test.js b/src/wlxml/wlxml.test.js index 9f846f6..516b47c 100644 --- a/src/wlxml/wlxml.test.js +++ b/src/wlxml/wlxml.test.js @@ -27,9 +27,14 @@ describe('WLXMLDocument', function() { expect(node.getClass()).to.equal('class.subclass'); }); - it('returns attributes other than class and meta-* as other attributes', function() { - var node = nodeFromXML(''); - expect(node.getOtherAttributes()).to.eql({attr1: 'val1', attr2: 'val2'}); + it('returns unregistered attributes', function() { + var testClasses = { + 'testClass': { + attrs: {'attr1': {type: 'string'}} + } + }, + doc = getDocumentFromXML('', {wlxmlClasses: testClasses}); + expect(doc.root.getOtherAttributes()).to.eql({attr: {value:'val'}}); }); }); @@ -76,7 +81,7 @@ describe('WLXMLDocument', function() { } }, node = getDocumentFromXML( - '', + '', {wlxmlClasses: testClasses} ).root, attrs = node.getMetaAttributes(); -- 2.20.1 From 2bb3ace4395ece36636f8b6b8a46b974a17d4a6f Mon Sep 17 00:00:00 2001 From: =?utf8?q?Aleksander=20=C5=81ukasz?= Date: Tue, 17 Dec 2013 14:53:02 +0100 Subject: [PATCH 02/16] editor: nodePane handles meta/unregistered node attributes --- src/editor/modules/nodePane/nodePane.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/editor/modules/nodePane/nodePane.js b/src/editor/modules/nodePane/nodePane.js index b4b3424..02ae2cc 100644 --- a/src/editor/modules/nodePane/nodePane.js +++ b/src/editor/modules/nodePane/nodePane.js @@ -42,7 +42,8 @@ return function(sandbox) { var escapedClassName = (wlxmlNodeElement.getClass() || '').replace(/\./g, '-'); view.find('.rng-module-nodePane-classSelect').val(escapedClassName); - var widget = metaWidget.create({attrs:wlxmlNodeElement.getMetaAttributes()}); + var attrs = _.extend(wlxmlNodeElement.getMetaAttributes(), wlxmlNodeElement.getOtherAttributes()); + var widget = metaWidget.create({attrs:attrs}); widget.on('valueChanged', function(key, value) { wlxmlNodeElement.setMetaAttribute(key, value); //wlxmlNodeElement.setMetaAttribute(key, value); -- 2.20.1 From 2978c060aed20c464c376acf47c02b91c3db19e8 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Aleksander=20=C5=81ukasz?= Date: Tue, 17 Dec 2013 16:38:03 +0100 Subject: [PATCH 03/16] editor: configurable document diff and revert urls --- src/editor/modules/data/data.js | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/editor/modules/data/data.js b/src/editor/modules/data/data.js index 8757389..bce9582 100644 --- a/src/editor/modules/data/data.js +++ b/src/editor/modules/data/data.js @@ -9,7 +9,6 @@ define([ 'use strict'; return function(sandbox) { - /* global gettext */ var document_id = sandbox.getBootstrappedData().document_id; var document_version = sandbox.getBootstrappedData().version; @@ -114,7 +113,7 @@ return function(sandbox) { fetchDiff: function(ver1, ver2) { $.ajax({ method: 'get', - url: '/' + gettext('editor') + '/diff/' + document_id, + url: sandbox.getConfig().documentDiffUrl(document_id), data: {from: ver1, to: ver2}, success: function(data) { sandbox.publish('diffFetched', {table: data, ver1: ver1, ver2: ver2}); @@ -127,7 +126,7 @@ return function(sandbox) { $.ajax({ method: 'post', dataType: 'json', - url: '/' + gettext('editor') + '/' + document_id + '/revert', + url: sandbox.getConfig().documentRestoreUrl(document_id), data: JSON.stringify(options), success: function(data) { document_version = data.current_version; -- 2.20.1 From e68778f27b18c21c23387d7609d825ab3a192af7 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Aleksander=20=C5=81ukasz?= Date: Tue, 17 Dec 2013 17:09:51 +0100 Subject: [PATCH 04/16] editor: bring back restore dialog after integration Both save and restore dialog are now handled by more generalized dialog object, based on previous dialog object implementation. --- src/editor/modules/data/data.js | 45 ++++++++++---- src/editor/modules/data/data.less | 2 +- .../data/{saveDialog.html => dialog.html} | 6 +- .../modules/data/{saveDialog.js => dialog.js} | 4 +- .../data/{saveDialog.less => dialog.less} | 2 +- .../documentHistory/documentHistory.js | 10 +--- .../modules/documentHistory/restoreDialog.js | 58 ------------------- .../templates/restoreDialog.html | 14 ----- src/editor/modules/rng/rng.js | 10 ++-- 9 files changed, 48 insertions(+), 103 deletions(-) rename src/editor/modules/data/{saveDialog.html => dialog.html} (60%) rename src/editor/modules/data/{saveDialog.js => dialog.js} (95%) rename src/editor/modules/data/{saveDialog.less => dialog.less} (91%) delete mode 100644 src/editor/modules/documentHistory/restoreDialog.js delete mode 100644 src/editor/modules/documentHistory/templates/restoreDialog.html diff --git a/src/editor/modules/data/data.js b/src/editor/modules/data/data.js index bce9582..4a9bc72 100644 --- a/src/editor/modules/data/data.js +++ b/src/editor/modules/data/data.js @@ -1,12 +1,12 @@ define([ 'libs/jquery', - './saveDialog', + './dialog', 'wlxml/wlxml', 'wlxml/extensions/list/list' - -], function($, saveDialog, wlxml, listExtension) { +], function($, Dialog, wlxml, listExtension) { 'use strict'; +/* global gettext */ return function(sandbox) { @@ -75,7 +75,11 @@ return function(sandbox) { }, sandbox.getConfig().documentSaveForm ), - dialog = saveDialog.create({fields: documentSaveForm.fields}); + dialog = Dialog.create({ + fields: documentSaveForm.fields, + title: gettext('Save Document'), + submitButtonText: gettext('Save') + }); dialog.on('save', function(event) { sandbox.publish('savingStarted'); @@ -120,22 +124,41 @@ return function(sandbox) { }, }); }, - restoreVersion: function(options) { - if(options.version && options.description) { - sandbox.publish('restoringStarted', {version: options.version}); + restoreVersion: function(version) { + var documentRestoreForm = $.extend({ + fields: [], + version_field_name: 'version' + }, + sandbox.getConfig().documentRestoreForm + ), + dialog = Dialog.create({ + fields: documentRestoreForm.fields, + title: gettext('Restore Version'), + submitButtonText: gettext('Restore') + }); + + dialog.on('save', function(event) { + var formData = event.formData; + formData[documentRestoreForm.version_field_name] = version; + sandbox.publish('restoringStarted', {version: version}); + if(sandbox.getConfig().jsonifySentData) { + formData = JSON.stringify(formData); + } $.ajax({ method: 'post', dataType: 'json', url: sandbox.getConfig().documentRestoreUrl(document_id), - data: JSON.stringify(options), + data: formData, success: function(data) { - document_version = data.current_version; + document_version = data.version; reloadHistory(); wlxmlDocument.loadXML(data.document); - sandbox.publish('documentReverted', data); + sandbox.publish('documentReverted', data.version); + event.success(); }, }); - } + }); + dialog.show(); }, getDocumentId: function() { return document_id; diff --git a/src/editor/modules/data/data.less b/src/editor/modules/data/data.less index 1beb090..2a21630 100644 --- a/src/editor/modules/data/data.less +++ b/src/editor/modules/data/data.less @@ -1 +1 @@ -@import 'saveDialog.less'; \ No newline at end of file +@import 'dialog.less'; \ No newline at end of file diff --git a/src/editor/modules/data/saveDialog.html b/src/editor/modules/data/dialog.html similarity index 60% rename from src/editor/modules/data/saveDialog.html rename to src/editor/modules/data/dialog.html index d0238e0..844a6ff 100644 --- a/src/editor/modules/data/saveDialog.html +++ b/src/editor/modules/data/dialog.html @@ -1,12 +1,12 @@ - \ No newline at end of file diff --git a/src/editor/modules/mainBar/template.html b/src/editor/modules/mainBar/template.html index 3c43ee6..e3c971b 100644 --- a/src/editor/modules/mainBar/template.html +++ b/src/editor/modules/mainBar/template.html @@ -1,7 +1,7 @@
\ No newline at end of file diff --git a/src/editor/modules/rng/rng.js b/src/editor/modules/rng/rng.js index 4e7ff0c..4a01b7b 100644 --- a/src/editor/modules/rng/rng.js +++ b/src/editor/modules/rng/rng.js @@ -60,9 +60,9 @@ return function(sandbox) { }; views.visualEditing.setView('rightColumn', views.visualEditingSidebar.getAsView()); - addMainTab('Edytor', 'editor', views.visualEditing.getAsView()); + addMainTab(gettext('Editor'), 'editor', views.visualEditing.getAsView()); addMainTab(gettext('Source'), 'sourceEditor', ''); - addMainTab('Historia', 'history', views.diffLayout.getAsView()); + addMainTab(gettext('History'), 'history', views.diffLayout.getAsView()); sandbox.getDOM().append(views.mainLayout.getAsView()); -- 2.20.1 From 471681497ab6e3ae9919f4e67f8edfc5e63a0670 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Aleksander=20=C5=81ukasz?= Date: Wed, 18 Dec 2013 11:40:24 +0100 Subject: [PATCH 08/16] editor: remove new line characters from pasted text --- src/editor/modules/documentCanvas/canvas/canvas.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/editor/modules/documentCanvas/canvas/canvas.js b/src/editor/modules/documentCanvas/canvas/canvas.js index 60782c2..70c0f49 100644 --- a/src/editor/modules/documentCanvas/canvas/canvas.js +++ b/src/editor/modules/documentCanvas/canvas/canvas.js @@ -102,7 +102,7 @@ $.extend(Canvas.prototype, { return; // TODO: alert } - var text = clipboardData.getData('text/plain'), + var text = clipboardData.getData('text/plain').replace(/\r?\n|\r/g, ' '), cursor = canvas.getCursor(), element = cursor.getPosition().element, lhs, rhs; -- 2.20.1 From dc8e2e1f8da0f76030d4a4d3c2acf432c9896779 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Aleksander=20=C5=81ukasz?= Date: Wed, 18 Dec 2013 12:22:45 +0100 Subject: [PATCH 09/16] wlxml: lists fix The default sort order used by Array.prototype.sort is lexicographic. This broke node selection for include/exclude for/from a list. --- src/wlxml/extensions/list/list.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/wlxml/extensions/list/list.js b/src/wlxml/extensions/list/list.js index 6d7b251..99cacb1 100644 --- a/src/wlxml/extensions/list/list.js +++ b/src/wlxml/extensions/list/list.js @@ -35,7 +35,7 @@ extension.document.transformations.createList = { /* globals Node */ var parent = params.node1.parent(), parentContents = parent.contents(), - nodeIndexes = [params.node1.getIndex(), params.node2.getIndex()].sort(), + nodeIndexes = [params.node1.getIndex(), params.node2.getIndex()].sort(function(a,b) { return a-b; }), nodesToWrap = [], listNode = params.node1.document.createDocumentNode({tagName: 'div', attrs: {'class': 'list'}}), node, i; @@ -78,7 +78,7 @@ extension.document.transformations.extractItems = { impl: function(params) { params = _.extend({}, {merge: true}, params); var list = params.item1.parent(), - indexes = [params.item1.getIndex(), params.item2.getIndex()].sort(), + indexes = [params.item1.getIndex(), params.item2.getIndex()].sort(function(a,b) { return a-b;}), precedingItems = [], extractedItems = [], succeedingItems = [], -- 2.20.1 From 13e0905b3f1950510b0bb5621e74d888650cbff1 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Aleksander=20=C5=81ukasz?= Date: Wed, 18 Dec 2013 12:35:18 +0100 Subject: [PATCH 10/16] editor: fixing invalid new node construction in ctrl+enter handler --- src/editor/modules/documentCanvas/canvas/keyboard.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/editor/modules/documentCanvas/canvas/keyboard.js b/src/editor/modules/documentCanvas/canvas/keyboard.js index 603249e..cd12a02 100644 --- a/src/editor/modules/documentCanvas/canvas/keyboard.js +++ b/src/editor/modules/documentCanvas/canvas/keyboard.js @@ -52,7 +52,7 @@ handlers.push({key: KEYS.ENTER, if(currentElement) { canvas.wlxmlDocument.startTransaction(); added = currentElement.data('wlxmlNode').after({ - tag: currentElement.getWlxmlTag() || 'div', + tagName: currentElement.getWlxmlTag() || 'div', attrs: {'class': currentElement.getWlxmlClass() || 'p'} }); added.append({text:''}); -- 2.20.1 From ab6c87178faf8a1c3a783a241dfbdd987bae604c Mon Sep 17 00:00:00 2001 From: =?utf8?q?Aleksander=20=C5=81ukasz?= Date: Wed, 18 Dec 2013 12:37:51 +0100 Subject: [PATCH 11/16] smartxml: throw exception on missing tagName property sent to createDocumentNode --- src/smartxml/smartxml.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/smartxml/smartxml.js b/src/smartxml/smartxml.js index f92bf01..d42dcbf 100644 --- a/src/smartxml/smartxml.js +++ b/src/smartxml/smartxml.js @@ -276,6 +276,9 @@ $.extend(Document.prototype, Backbone.Events, { /* globals document */ from = document.createTextNode(from.text); } else { + if(!from.tagName) { + throw new Error('tagName missing'); + } var node = $('<' + from.tagName + '>'); _.keys(from.attrs || {}).forEach(function(key) { -- 2.20.1 From 94e3767f1597835ac82361d7d04be1347fe40942 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Aleksander=20=C5=81ukasz?= Date: Thu, 19 Dec 2013 12:49:26 +0100 Subject: [PATCH 12/16] wlxml/editor: rename class uri to link --- src/editor/modules/documentCanvas/nodes.less | 2 +- src/editor/modules/documentToolbar/template.html | 4 ++-- src/editor/modules/nodePane/template.html | 2 +- src/wlxml/wlxml.js | 4 ++-- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/editor/modules/documentCanvas/nodes.less b/src/editor/modules/documentCanvas/nodes.less index 35c7ece..f41363b 100644 --- a/src/editor/modules/documentCanvas/nodes.less +++ b/src/editor/modules/documentCanvas/nodes.less @@ -63,7 +63,7 @@ padding: 10px; } -[wlxml-class|="uri"] { +[wlxml-class|="link"] { color: blue; text-decoration: underline; } diff --git a/src/editor/modules/documentToolbar/template.html b/src/editor/modules/documentToolbar/template.html index f91e1e8..f0a3682 100644 --- a/src/editor/modules/documentToolbar/template.html +++ b/src/editor/modules/documentToolbar/template.html @@ -3,7 +3,7 @@ - + - <% var options = ['', 'author', 'title', 'comment', 'cite', 'cite.code', 'cite.code.xml', 'list.items', 'list.items.enum', 'item', 'uri', 'p', 'footnote', 'todo', 'emp'] %> + <% var options = ['', 'author', 'title', 'comment', 'cite', 'cite.code', 'cite.code.xml', 'list.items', 'list.items.enum', 'item', 'link', 'p', 'footnote', 'todo', 'emp'] %> <% options.forEach(function(option) { %> <% }); %> diff --git a/src/wlxml/wlxml.js b/src/wlxml/wlxml.js index 7f6e931..820b95f 100644 --- a/src/wlxml/wlxml.js +++ b/src/wlxml/wlxml.js @@ -286,8 +286,8 @@ $.extend(WLXMLDocument.prototype, { }); var wlxmlClasses = { - 'uri': { - attrs: {uri: {type: 'string'}} + 'link': { + attrs: {href: {type: 'string'}} } }; -- 2.20.1 From 04a5eed6cdef64afab50c5e49112864069cf1dcd Mon Sep 17 00:00:00 2001 From: =?utf8?q?Aleksander=20=C5=81ukasz?= Date: Thu, 19 Dec 2013 15:41:19 +0100 Subject: [PATCH 13/16] editor: fix styling of the emp wlxml class --- src/editor/modules/documentCanvas/nodes.less | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/editor/modules/documentCanvas/nodes.less b/src/editor/modules/documentCanvas/nodes.less index f41363b..b6335a8 100644 --- a/src/editor/modules/documentCanvas/nodes.less +++ b/src/editor/modules/documentCanvas/nodes.less @@ -72,7 +72,7 @@ text-indent: 1.5em; } -[wlxml-class|="emph-tech"] { +[wlxml-class|="emp"] { font-style: italic; } -- 2.20.1 From 6bdd7735b0e90323e1b3fc94cc2844ed00208fa6 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Aleksander=20=C5=81ukasz?= Date: Fri, 20 Dec 2013 13:45:15 +0100 Subject: [PATCH 14/16] gitignore update: node_modules/ --- .gitignore | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index d163863..3e2e84b 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ -build/ \ No newline at end of file +build/ +node_modules/ -- 2.20.1 From db58e0a751440706b5e0407e5a4a9ebb6cb0f8aa Mon Sep 17 00:00:00 2001 From: =?utf8?q?Aleksander=20=C5=81ukasz?= Date: Fri, 20 Dec 2013 13:46:26 +0100 Subject: [PATCH 15/16] build: don't strip 'use strict' --- Gruntfile.js | 1 + 1 file changed, 1 insertion(+) diff --git a/Gruntfile.js b/Gruntfile.js index 4f15a55..ca08c79 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -12,6 +12,7 @@ module.exports = function(grunt) { requirejs: { compile: { options: { + useStrict: true, baseUrl: 'src/editor', mainConfigFile: 'src/editor/entrypoint.js', out: build_output_dir + '/rng.js', -- 2.20.1 From a4e92f85f83046cef29d4ce0f71cea6250ce8df6 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Aleksander=20=C5=81ukasz?= Date: Mon, 30 Dec 2013 13:09:55 +0100 Subject: [PATCH 16/16] Simple logging api inspired by Python logging module --- src/fnpjs/logging/handlers.js | 8 ++ src/fnpjs/logging/logging.js | 81 +++++++++++++++++++ src/fnpjs/logging/logging.test.js | 128 ++++++++++++++++++++++++++++++ 3 files changed, 217 insertions(+) create mode 100644 src/fnpjs/logging/handlers.js create mode 100644 src/fnpjs/logging/logging.js create mode 100644 src/fnpjs/logging/logging.test.js diff --git a/src/fnpjs/logging/handlers.js b/src/fnpjs/logging/handlers.js new file mode 100644 index 0000000..c15d17f --- /dev/null +++ b/src/fnpjs/logging/handlers.js @@ -0,0 +1,8 @@ +define(function() { + +'use strict'; + + +return {}; + +}); \ No newline at end of file diff --git a/src/fnpjs/logging/logging.js b/src/fnpjs/logging/logging.js new file mode 100644 index 0000000..e68302d --- /dev/null +++ b/src/fnpjs/logging/logging.js @@ -0,0 +1,81 @@ +define(function(require) { + +'use strict'; + +var _ = require('libs/underscore'), + handlers = require('fnpjs/logging/handlers'), + config = {}, + levels = ['debug', 'info', 'warning', 'error', 'critical']; + + +var Logger = function(name) { + this.name = name; + Object.defineProperty(this, 'config', { + get: function() { + return _.extend({ + propagate: true, + level: 'warn', + handlers: [] + }, config.loggers[name] || {}); + } + }); +}; + +_.extend(Logger.prototype, { + log: function(level, message, data) { + if(levels.indexOf(level) !== -1 && levels.indexOf(level) >= levels.indexOf(this.config.level)) { + this.config.handlers.forEach(function(handlerName) { + var handlerConfig = config.handlers[handlerName], + handler = handlerConfig.handler, + handlerLevel = handlerConfig.level || 'info'; + + if(typeof handler === 'string') { + handler = handlers[handlerConfig.handler]; + } + if(!handler) { + throw new Error('Unknown handler: ' + handlerName); + } + + if(levels.indexOf(handlerLevel) !== -1 && levels.indexOf(level) >= levels.indexOf(handlerLevel)) { + handler(message, level, data); + } + }); + } + if(this.config.propagate && this.name) { + var logger = new Logger(this.name.split('.').slice(0, -1).join('.')); + logger.log(level, message, data); + } + }, + exception: function(e) { + this.log('error', e.toString(), {exception: e}); + } +}); + +levels.forEach(function(level) { + Logger.prototype[level] = function(message, data) { + return this.log(level, message, data); + }; +}); + + +var api = { + getLogger: function(name) { + return new Logger(name); + }, + setConfig: function(_config) { + config = _.extend({ + handlers: [], + loggers: [] + } ,_config); + }, + clearConfig: function() { + this.setConfig({}); + } +}; + +api.clearConfig(); + + +return api; + +}); diff --git a/src/fnpjs/logging/logging.test.js b/src/fnpjs/logging/logging.test.js new file mode 100644 index 0000000..5876f5a --- /dev/null +++ b/src/fnpjs/logging/logging.test.js @@ -0,0 +1,128 @@ +define(function(require) { + +'use strict'; +/* global describe, it, beforeEach */ +var chai = require('libs/chai'), + logging = require('./logging.js'), + expect = chai.expect; + + +// Global log object for defining expectations +var log = { + _msgs: [], + clear: function() { + this._msgs = []; + }, + append: function(msg) { + this._msgs.push(msg); + }, + contains: function(msg) { + return this._msgs.indexOf(msg) !== -1; + }, + getLast: function() { + return this._msgs.length ? this._msgs[this._msgs.length] : undefined; + }, + isEmpty: function() { + return this._msgs.length === 0; + }, + getMessages: function() { + return this._msgs; + } +}; + +// Loggin handler that just writes to the global logger object +var testLoggingHandler = function(msg) { + log.append(msg); +}; + +describe('Logging', function() { + + + beforeEach(function() { + log.clear(); + logging.clearConfig(); + }); + + var setConfig = function(loggerLevel, handlerLevel) { + logging.setConfig({ + handlers: { + testHandler: { + handler: testLoggingHandler, + level: handlerLevel + } + }, + loggers: { + '': { + level: loggerLevel, + handlers: ['testHandler'] + } + } + }); + }; + + it('works with sample config', function() { + setConfig('debug', 'debug'); + var logger = logging.getLogger('some.name'); + logger.debug('debug msg'); + expect(log.contains('debug msg')).to.equal(true); + }); + + it('filters level on loggers', function() { + setConfig('info', 'debug'); + var logger = logging.getLogger('some.name'); + logger.debug('debug msg'); + expect(log.isEmpty()).to.equal(true, 'debug message filtered out'); + logger.info('info msg'); + expect(log.contains('info msg')).to.equal(true, 'info message passed'); + }); + + it('filters level on handlers', function() { + setConfig('debug', 'info'); + var logger = logging.getLogger('some.name'); + logger.debug('debug msg'); + expect(log.isEmpty()).to.equal(true, 'debug message filtered out'); + logger.info('info msg'); + expect(log.contains('info msg')).to.equal(true, 'info message passed'); + }); + + it('propagates message to upper logger depending on the propagate flag', function() { + var config = { + handlers: { + testHandler: { + handler: testLoggingHandler, + level: 'debug' + } + }, + loggers: { + '': { + level: 'debug', + handlers: ['testHandler'] + }, + 'logger1': { + level: 'debug', + handlers: ['testHandler'] + } + } + }, + logger; + + config.loggers.logger1.propagate = false; + logging.setConfig(config); + + logger = logging.getLogger('logger1'); + + logger.debug('msg1'); + expect(log.contains('msg1')).to.equal(true, 'first message logged'); + expect(log.getMessages().length === 1).to.equal(true, 'logger didn\'t propagate its message'); + + log.clear(); + config.loggers.logger1.propagate = true; + logging.setConfig(config); + + logger.debug('msg2'); + expect(log.contains('msg2')).to.equal(true, 'second message logged'); + expect(log.getMessages().length === 2).to.equal(true, 'second message propagated to upper logger'); + }); +}); + +}); -- 2.20.1