diff --git a/.gitignore b/.gitignore
index 9d80f26..13ccd15 100644
--- a/.gitignore
+++ b/.gitignore
@@ -17,6 +17,6 @@ results
npm-debug.log
node_modules
public/index.html
-public/main.css
-public/main.css.map
-public/main.js
\ No newline at end of file
+public/style.css
+public/style.css.map
+public/script.js
\ No newline at end of file
diff --git a/clientSrc/corpus.js b/clientSrc-old/corpus.js
similarity index 100%
rename from clientSrc/corpus.js
rename to clientSrc-old/corpus.js
diff --git a/clientSrc/editor.js b/clientSrc-old/editor.js
similarity index 100%
rename from clientSrc/editor.js
rename to clientSrc-old/editor.js
diff --git a/clientSrc/keycode.js b/clientSrc-old/keycode.js
similarity index 100%
rename from clientSrc/keycode.js
rename to clientSrc-old/keycode.js
diff --git a/clientSrc/log.js b/clientSrc-old/log.js
similarity index 100%
rename from clientSrc/log.js
rename to clientSrc-old/log.js
diff --git a/clientSrc/main.js b/clientSrc-old/main.js
similarity index 100%
rename from clientSrc/main.js
rename to clientSrc-old/main.js
diff --git a/clientSrc/main.less b/clientSrc-old/main.less
similarity index 100%
rename from clientSrc/main.less
rename to clientSrc-old/main.less
diff --git a/clientSrc/menu.js b/clientSrc-old/menu.js
similarity index 100%
rename from clientSrc/menu.js
rename to clientSrc-old/menu.js
diff --git a/clientSrc/navigate.js b/clientSrc-old/navigate.js
similarity index 100%
rename from clientSrc/navigate.js
rename to clientSrc-old/navigate.js
diff --git a/clientSrc/render-term.js b/clientSrc-old/render-term.js
similarity index 100%
rename from clientSrc/render-term.js
rename to clientSrc-old/render-term.js
diff --git a/clientSrc/render-validity.js b/clientSrc-old/render-validity.js
similarity index 100%
rename from clientSrc/render-validity.js
rename to clientSrc-old/render-validity.js
diff --git a/clientSrc/view.js b/clientSrc-old/view.js
similarity index 100%
rename from clientSrc/view.js
rename to clientSrc-old/view.js
diff --git a/clientSrc/TODO.js b/clientSrc/TODO.js
deleted file mode 100644
index 6ace329..0000000
--- a/clientSrc/TODO.js
+++ /dev/null
@@ -1,16 +0,0 @@
-'use strict';
-
-/** @constructor */
-var TodoException = function (message) {
- this.message = message || '(unfinished code)';
-};
-
-TodoException.prototype.toString = function () {
- return 'TODO: ' + this.message;
-};
-
-var TODO = function (message) {
- throw new TodoException(message);
-};
-
-module.exports = TODO;
diff --git a/clientSrc/app/app.js b/clientSrc/app/app.js
new file mode 100644
index 0000000..2fb25ba
--- /dev/null
+++ b/clientSrc/app/app.js
@@ -0,0 +1,41 @@
+'use strict';
+
+//This is an entry point into application.
+//App consists of folowing modules:
+//Corpus - corpus binding REST/Socket <=> HTML DOM + updates from either side.
+//Logger -
+//Navigator -
+
+
+var angular = require('angular');
+var uiRouter = require('angular-ui-router');
+var socket = global.io = require('socket.io-client')();
+var debug = global.debug = require('debug');
+var log = debug('puddle:client:init');
+
+//this will register ng-modules into angular namespace.
+require('angular-socket-io');
+require('./corpus.js');
+
+
+//require all modules.
+var puddle = angular.module('puddle', [uiRouter, 'corpus']);
+
+//Define default route where to redirect all unknown URL's
+//Outher routes defined witin other modules.
+puddle.config(function ($stateProvider, $urlRouterProvider) {
+ $urlRouterProvider.otherwise('/corpus');
+});
+
+
+socket.on('connect', function () {
+ log('Socket IO connection estabilished');
+});
+socket.on('corpus', function (method, args) {
+ log('Corpus API incoming call: ', method, args);
+});
+
+socket.emit('corpus', 'findAll');
+socket.emit('corpus', 'findById', ['540448b62711b16e9a6c7132']);
+
+log('Puddle init complete.');
\ No newline at end of file
diff --git a/clientSrc/app/corpus.js b/clientSrc/app/corpus.js
new file mode 100644
index 0000000..7f725f3
--- /dev/null
+++ b/clientSrc/app/corpus.js
@@ -0,0 +1,47 @@
+'use strict';
+
+
+var log = require('debug')('puddle:client:corpus');
+var angular = require('angular');
+var _ = require('lodash');
+var uiRouter = require('angular-ui-router');
+var corpus = angular.module('corpus', [uiRouter, 'btford.socket-io']);
+
+corpus.config(function ($stateProvider) {
+ $stateProvider
+ .state('corpus', {
+ url: '/corpus',
+ templateUrl: 'corpus.html',
+ controller: 'corpus'
+ });
+});
+
+corpus.factory('Socket', function (socketFactory) {
+ return socketFactory();
+});
+
+corpus.controller('corpus', function ($scope, CorpusDB) {
+ $scope.corpus = CorpusDB.corpus;
+});
+
+corpus.factory('CorpusDB', function (Socket) {
+ var codes = [];
+ Socket.on('corpus', function (method, args) {
+ switch (method) {
+ case 'findAll':
+ var corpus = args[0];
+ if (_.isArray(corpus)) {
+ codes.length = 0;
+ corpus.forEach(function (a) {
+ codes.push(a);
+ });
+ }
+ break;
+ }
+ });
+
+ return {corpus: codes};
+});
+
+log('Corpus module init complete');
+
diff --git a/clientSrc/assert.js b/clientSrc/assert.js
deleted file mode 100644
index 7f84896..0000000
--- a/clientSrc/assert.js
+++ /dev/null
@@ -1,30 +0,0 @@
-'use strict';
-
-var _ = require('underscore');
-
-/** @constructor */
-var AssertException = function (message) {
- this.message = message || '(unspecified)';
-};
-
-AssertException.prototype.toString = function () {
- return 'Assertion Failed: ' + this.message;
-};
-
-var assert = function (condition, message) {
- if (!condition) {
- throw new AssertException(message);
- }
-};
-
-assert.Exception = AssertException;
-
-// This is better than node's builtin assert comparison
-assert.equal = function (actual, expected, message) {
- assert(_.isEqual(actual, expected),
- (message || '') +
- '\n actual = ' + JSON.stringify(actual) +
- '\n expected = ' + JSON.stringify(expected));
-};
-
-module.exports = assert;
diff --git a/clientSrc/index.html b/clientSrc/index.html
index b0207e6..b118f8f 100755
--- a/clientSrc/index.html
+++ b/clientSrc/index.html
@@ -1,14 +1,21 @@
-
+
Pomagma Editor
-
-
-
+
+
+
+
+
+
+
-
-
+Corpus editor
+
+
diff --git a/clientSrc/styles/style.less b/clientSrc/styles/style.less
new file mode 100644
index 0000000..e69de29
diff --git a/doc/using.md b/doc/using.md
index 7b90744..4689639 100644
--- a/doc/using.md
+++ b/doc/using.md
@@ -15,7 +15,7 @@ To start a server that:
- builds with JS sourcemaps
- npm run dev # alias for gulp serve --dev=true
+ npm run dev # alias for gulp develop
## Debugging Puddle
@@ -24,9 +24,12 @@ To run headless unit tests in various debug modes:
npm test
DEBUG=* npm test
DEBUG=express:*,puddle:* npm test
+
+## To debug browserside
-To run in-browser unit tests, start Pomagam+Puddle servers as above and
-navigate to http://localhost:34934#test
+Run following command in console.
+
+ debug.enable('puddle:*')
## Continous testing and code quality
diff --git a/gulpfile.js b/gulpfile.js
index 77c5bc5..729d84d 100644
--- a/gulpfile.js
+++ b/gulpfile.js
@@ -2,6 +2,7 @@
var gulp = require('gulp');
var gulpif = require('gulp-if');
+var ngAnnotate = require('gulp-ng-annotate');
var uglify = require('gulp-uglify');
var jshint = require('gulp-jshint');
var gutil = require('gulp-util');
@@ -11,6 +12,7 @@ var nodemon = require('gulp-nodemon');
var less = require('gulp-less-sourcemap');
var exec = require('child_process').exec;
var LIVERELOAD_PORT = 34939;
+var rename = require('gulp-rename');
var lr = require('tiny-lr')();
var watcher = function (tasks, paths) {
@@ -19,7 +21,8 @@ var watcher = function (tasks, paths) {
gulp.watch(paths, tasks)
.on('change', function (event) {
gutil.log(
- 'File ' + event.path + ' was ' + event.type + ', refreshing'
+ 'File ' + event.path + ' was ' + event.type +
+ ', refreshing'
);
}).on('error', function swallowError() {
this.emit('end');
@@ -45,7 +48,7 @@ gulp.task('mocha', function (cb) {
gulp.task('less', function () {
//process LESS -> CSS
- return gulp.src('./clientSrc/main.less')
+ return gulp.src('./clientSrc/styles/style.less')
.pipe(less())
.pipe(gulp.dest('./public'));
});
@@ -58,13 +61,14 @@ gulp.task('copyHtml', function () {
gulp.task('browserify', function () {
//Browserify
- return gulp.src('./clientSrc/main.js')
+ return gulp.src('./clientSrc/app/app.js')
.pipe(browserify({
- insertGlobals: true,
exclude: ['mocha'],
debug: argv.dev
}))
+ .pipe(ngAnnotate())
.pipe(gulpif(!argv.dev, uglify()))
+ .pipe(rename('script.js'))
.pipe(gulp.dest('./public'));
});
@@ -99,9 +103,10 @@ gulp.task('startLiveReload', function () {
gulp.task('nodemon', function () {
nodemon({
- script: 'server.js',
+ script: './server/server.js',
ext: 'js',
- watch: ['./lib', 'server.js']
+ args: argv.dev ? ['--withLiveReload=true'] : null,
+ watch: ['./server']
}).on('restart', function () {
console.log('Restarted server');
});
@@ -109,10 +114,24 @@ gulp.task('nodemon', function () {
gulp.task('trackLiveReload', ['default'], function () {
lr.changed({body: {
- files: ['main.js', 'index.html', 'main.css']
+ files: ['static/script.js', 'static/index.html', 'static/style.css']
}});
});
-gulp.task('serve', ['startLiveReload', 'default', 'nodemon'], function () {
- watcher(['trackLiveReload'], ['./clientSrc/**/*'])();
+gulp.task('serve', ['default'], function () {
+ require('./server/server');
});
+
+gulp.task('develop', function () {
+ argv.dev = true;
+ gulp.start('developStart');
+});
+
+gulp.task('developStart', ['startLiveReload', 'default' , 'nodemon'],
+ function () {
+ watcher(['trackLiveReload'], [
+ './clientSrc/**/*.js',
+ './clientSrc/**/*.html',
+ './clientSrc/**/*.less'
+ ])();
+ });
diff --git a/lib/corpus.js b/lib/corpus.js
deleted file mode 100644
index 7eb1c6a..0000000
--- a/lib/corpus.js
+++ /dev/null
@@ -1,100 +0,0 @@
-/* jshint node:true */
-'use strict';
-
-var debug = require('debug')('puddle:corpus');
-var assert = require('assert');
-var path = require('path');
-var fs = require('fs');
-var _ = require('underscore');
-
-var DUMP_FILE = path.join(__dirname, '..', 'corpus.dump');
-var TEMP_FILE = path.join(__dirname, '..', 'temp.corpus.dump');
-
-var statements = {};
-var nextId = 0;
-
-var loadStatement = (function () {
- var switch_ = {
- 'ASSERT': function (body) {
- return {'name': null, 'code': body};
- },
- 'DEFINE': function (body) {
- var varName = body.split(' ', 2);
- assert.deepEqual(varName[0], 'VAR');
- var name = varName[1];
- var code = body.slice(4 + name.length + 1);
- return {'name': name, 'code': code};
- }
- };
- return function (string) {
- var prefix = string.split(' ', 1)[0];
- var body = string.slice(prefix.length + 1);
- return switch_[prefix](body);
- };
-})();
-
-var dumpStatement = function (statement) {
- if (statement.name === null) {
- return 'ASSERT ' + statement.code;
- } else {
- return 'DEFINE VAR ' + statement.name + ' ' + statement.code;
- }
-};
-
-
-var load = function () {
- debug('loading corpus...');
- statements = {};
- nextId = 0;
- fs.readFileSync(DUMP_FILE).toString().split('\n').forEach(function (line) {
- line = line.replace(/#.*/, '').trim();
- if (line) {
- var statement = loadStatement(line);
- statements[nextId++] = statement;
- }
- });
- debug('...corpus loaded');
-};
-
-var dump = function () {
- debug('dumping corpus...');
- var lines = _.map(statements, dumpStatement);
- lines.sort();
- lines.splice(0, 0, '# this file is managed by corpus.js');
- fs.writeFileSync(TEMP_FILE, lines.join('\n'));
- fs.renameSync(TEMP_FILE, DUMP_FILE);
- debug('...corpus dumped');
- return lines.join('\n');
-};
-
-
-exports.load = load;
-exports.dump = dump;
-
-exports.findAll = function () {
- return _.map(statements, function (value, id) {
- var line = _.clone(value);
- line.id = id;
- return line;
- });
-};
-
-exports.findOne = function (id) {
- return _.clone(statements[id]);
-};
-
-exports.create = function (statement) {
- var id = nextId++;
- statements[id] = statement;
- return id;
-};
-
-exports.update = function (id, statement) {
- assert(_.has(statements, id), 'object cannot be set');
- statements[id] = _.clone(statement);
-};
-
-exports.remove = function (id) {
- assert(_.has(statements, id), 'object cannot be set');
- delete statements[id];
-};
diff --git a/package.json b/package.json
index c5437a5..fbe3f85 100644
--- a/package.json
+++ b/package.json
@@ -2,32 +2,39 @@
"name": "puddle",
"version": "0.1.8",
"description": "A responsive editor built on Pomagma",
- "main": "server.js",
+ "main": "server/server.js",
"dependencies": {
- "amdefine": "=0.1.0",
+ "angular": "^1.2.21",
+ "angular-socket-io": "^0.6.0",
+ "angular-ui-router": "^0.2.10",
"body-parser": "^1.6.1",
"debug": "^1.0.4",
"express": "^4.8.3",
- "gulp": "^3.8.7",
- "gulp-browserify": "^0.5.0",
- "gulp-if": "^1.2.4",
- "gulp-jshint": "^1.8.4",
- "gulp-less-sourcemap": "^1.3.3",
- "gulp-nodemon": "^1.0.4",
- "gulp-uglify": "^0.3.1",
- "jquery": "^2.1.1",
"less": "^1.7.4",
+ "lodash": "^2.4.1",
"mongoose": "~3.8.15",
"pomagma": ">=0.1.8",
"puddle-syntax": "~0.1.0",
+ "q": "^1.0.1",
"socket.io": "^1.0.6",
"socket.io-client": "^1.0.6",
"underscore": "^1.6.0",
"yargs": "^1.3.1"
},
"devDependencies": {
+ "chai": "^1.9.1",
+ "chai-as-promised": "^4.1.1",
"connect-livereload": "^0.4.0",
+ "gulp": "^3.8.7",
+ "gulp-browserify": "^0.5.0",
+ "gulp-if": "^1.2.4",
+ "gulp-jshint": "^1.8.4",
+ "gulp-less-sourcemap": "^1.3.3",
"gulp-mocha": "^1.0.0",
+ "gulp-ng-annotate": "^0.3.0",
+ "gulp-nodemon": "^1.0.4",
+ "gulp-rename": "^1.2.0",
+ "gulp-uglify": "^0.3.1",
"gulp-util": "^3.0.0",
"jshint": "^2.5.4",
"karma": "^0.12.22",
@@ -36,6 +43,7 @@
"karma-mocha": "^0.1.9",
"karma-phantomjs-launcher": "^0.1.4",
"mocha": "^1.21.4",
+ "mockgoose": "^1.10.2",
"phantomjs": "^1.9.7-15",
"rewire": "^2.1.0",
"sinon": "^1.10.3",
@@ -48,7 +56,7 @@
"mocha": "./node_modules/gulp/bin/gulp.js mocha",
"test": "npm run gulp && npm run lint && npm run mocha",
"start": "./node_modules/gulp/bin/gulp.js serve",
- "dev": "./node_modules/gulp/bin/gulp.js serve --dev=true",
+ "dev": "./node_modules/gulp/bin/gulp.js develop",
"clean": "cd public && rm -f index.html main.css* main.js"
},
"repository": {
diff --git a/server/lib/corpus.js b/server/lib/corpus.js
new file mode 100644
index 0000000..ad69a03
--- /dev/null
+++ b/server/lib/corpus.js
@@ -0,0 +1,35 @@
+'use strict';
+
+var debug = require('debug')('puddle:corpus');
+var assert = require('chai').assert;
+
+module.exports = function (mongoose) {
+ assert(mongoose);
+ debug('Corpus init');
+
+ var Corpus = mongoose.model('Corpus', mongoose.Schema({
+ code: String
+ }));
+
+ return {
+ findAll: function () {
+ return Corpus.find({}).exec();
+ },
+ findById: function (id) {
+ return Corpus.findById(id).exec();
+ },
+ create: function (code) {
+ assert.isString(code);
+ return Corpus.create({code: code});
+ },
+ update: function (id, code) {
+ assert.isString(code);
+ return Corpus.findByIdAndUpdate(id, {code: code}).exec();
+ },
+ remove: function (id) {
+ return Corpus.findByIdAndRemove(id).exec();
+ }
+ };
+};
+
+
diff --git a/corpus.dump b/server/main.corpus
similarity index 100%
rename from corpus.dump
rename to server/main.corpus
diff --git a/server.js b/server/server.js
similarity index 63%
rename from server.js
rename to server/server.js
index d69ff63..23eb0f1 100644
--- a/server.js
+++ b/server/server.js
@@ -3,13 +3,13 @@
var debug = require('debug')('puddle:server');
var assert = require('assert');
var path = require('path');
-var _ = require('underscore');
+var _ = require('lodash');
+var argv = require('yargs').argv;
var express = require('express');
-var bodyParser = require('body-parser');
-var corpus = require('./lib/corpus');
var pomagma = require('pomagma');
var socketio = require('socket.io');
var mongoose = require('mongoose');
+var corpus = require('./lib/corpus')(mongoose);
var db = mongoose.connection;
var LIVERELOAD_PORT = 34939;
var liveReload = require('connect-livereload')({port: LIVERELOAD_PORT});
@@ -32,43 +32,11 @@ db.once('open', function () {
});
var app = express();
-app.use(liveReload);
-app.use(bodyParser.urlencoded({extended: false}));
-app.use('/', express.static(path.join(__dirname, 'public'))); // HACK for index
-app.use('/static', express.static(path.join(__dirname, 'public')));
+if (argv.withLiveReload) {
+ app.use(liveReload);
+}
+app.use('/', express.static(path.join(__dirname, '../public')));
-app.get('/corpus/lines', function (req, res) {
- debug('GET lines');
- res.send({'data': corpus.findAll()});
-});
-
-app.get('/corpus/line/:id', function (req, res) {
- debug('GET line ' + req.params.id);
- res.send({'data': corpus.findOne(req.params.id)});
-});
-
-app.post('/corpus/line', function (req, res) {
- debug('POST ' + JSON.stringify(req.body));
- var line = req.body;
- var statement = {
- 'name': line.name,
- 'code': line.code
- };
- var id = corpus.create(statement);
- res.send({'id': id});
-});
-
-app.put('/corpus/line/:id', function (req, res) {
- debug('PUT line ' + req.params.id + ': ' + JSON.stringify(req.body));
- corpus.update(req.params.id, req.body);
- res.status(200).end();
-});
-
-app.delete('/corpus/line/:id', function (req, res) {
- debug('DELETE line ' + req.params.id);
- corpus.remove(req.params.id);
- res.status(200).end();
-});
app.get('/corpus/validities', function (req, res) {
debug('GET validities');
@@ -88,10 +56,9 @@ app.get('/corpus/validities', function (req, res) {
});
});
-corpus.load();
+
process.on('SIGINT', function () {
analyst.close();
- corpus.dump();
process.exit();
});
@@ -118,13 +85,34 @@ var userId = 0;
io.on('connection', function (socket) {
var id = userId++;
var logAction = function (action) {
- console.log('Logger: user:', id, ' action:', action);
+ debug('Logger: user:', id, ' action:', action);
var log = new Log({user: id, action: action});
log.save();
};
- logAction('connected');
- socket.on('disconnect', function () {
- logAction('disconnected');
+
+ //send user whatever latest corpus we have;
+ corpus.findAll().then(function (corpus) {
+ socket.emit('corpusUpdate', corpus);
});
- socket.on('action', logAction);
+
+ //define methods of API
+ var serverAPI = {
+ 'log': logAction,
+ 'disconnect': function () {
+ logAction('disconnected');
+ },
+ 'corpus': function (method, args) {
+ debug('Socket method: ', method, ' called');
+ corpus[method].apply(null, args).then(function () {
+ socket.emit('corpus', method, _.toArray(arguments));
+ });
+ }
+ };
+
+ //bind methods of API
+ _.each(serverAPI, function (method, event) {
+ socket.on(event, method);
+ });
+
+ logAction('connected');
});
diff --git a/test/server/corpusTest.js b/test/server/corpusTest.js
index 87b800c..a31756c 100644
--- a/test/server/corpusTest.js
+++ b/test/server/corpusTest.js
@@ -1,63 +1,134 @@
'use strict';
-var assert = require('assert');
-var sinon = require('sinon');
-var rewire = require('rewire');
-
-//Note that below it is 'rewire' not 'require' !
-var corpus = rewire('../../lib/corpus');
-
-
-describe('Server', function () {
- describe('Corpus', function () {
- var corpusFile = [
- '# this file is managed by corpus.js',
- 'ASSERT EQUAL APP APP C APP APP C' +
- ' VAR util.pair BOT VAR util.join I',
- 'ASSERT EQUAL APP APP C APP VAR util.pair BOT VAR util.join I']
- .join('\n');
-
- it('initialised with empty array', function () {
- assert.equal(corpus.findAll().length, 0);
- });
-
- it('.load() tries to read from file', function () {
- var spy = sinon.stub().returns(corpusFile);
- var revert = corpus.__set__('fs', {readFileSync: spy});
-
- corpus.load();
- assert(spy.calledOnce);
-
- revert();
- });
-
- it('After .load(), findAll() returns right amount of lines',
- function () {
- assert.equal(corpus.findAll().length, 2);
- });
-
- describe('.dump()', function () {
- var writeSpy = sinon.stub();
- var renameSpy = sinon.stub();
- var revert = corpus.__set__('fs', {
- writeFileSync: writeSpy,
- renameSync: renameSpy
- });
- var lines;
-
- before(function () {
- lines = corpus.dump();
- revert();
- });
-
- it('writes to the file and moves it', function () {
- assert(writeSpy.calledOnce);
- assert(renameSpy.calledOnce);
- });
-
- it('writes correct data to the file', function () {
- assert.equal(lines, corpusFile);
- });
-
- });
- });
-});
\ No newline at end of file
+var chai = require('chai');
+var chaiAsPromised = require('chai-as-promised');
+chai.use(chaiAsPromised);
+var assert = chai.assert;
+var Q = require('q');
+var _ = require('lodash');
+var testData = require('./testData');
+var debug = require('debug')('puddle:mocha');
+debug.log = function () {
+ //workaround for debug library to add newline char for each string;
+ console.log.apply(console,
+ ['\n'].concat(Array.prototype.slice.call(arguments))
+ );
+};
+var Mongoose = require('mongoose');
+
+debug('Testing server:');
+
+
+describe('Corpus', function () {
+ var mongoose;
+ var corpusUninitialized;
+ var corpus;
+ var mockgoose = require('mockgoose');
+
+ beforeEach(function () {
+ debug('Reinit mongoose');
+ mongoose = new Mongoose.Mongoose();
+ mockgoose(mongoose);
+ corpusUninitialized = require('../../server/lib/corpus');
+ });
+
+ describe('initialiszation',
+ function () {
+ it('throws if not passed a mongoose as init parameter',
+ function () {
+ assert.throws(function () {
+ corpusUninitialized();
+ });
+ });
+ it('returns an object if passed a mongoose', function () {
+ assert.isObject(corpusUninitialized(mongoose));
+ });
+ });
+
+ describe('after init ', function () {
+ beforeEach(function () {
+ debug('Reset DB data');
+ corpus = corpusUninitialized(mongoose);
+ mockgoose.reset();
+ });
+
+ it('.create() returns created object',
+ function () {
+ return assert.eventually.equal(
+ corpus.create(testData.codes[1]).then(function (code) {
+ return code.code;
+ }),
+ testData.codes[1]
+ );
+ });
+
+ it('.create() throws if not string given', function () {
+ assert.throws(function () {
+ corpus.create(1);
+ });
+ assert.throws(function () {
+ corpus.create([]);
+ });
+ assert.throws(function () {
+ corpus.create({});
+ });
+ });
+
+ describe('given test data', function () {
+ beforeEach(function () {
+ debug('Add test data to DB');
+ return Q.all(testData.codes.map(function (code) {
+ return corpus.create(code);
+ }));
+ });
+
+ it('.findAll() returns correct amount of lines',
+ function () {
+ return assert.eventually.equal(
+ corpus.findAll().then(function (codes) {
+ return codes.length;
+ }), testData.codes.length
+ );
+ }
+ );
+ it('.findAll() returns an array',
+ function () {
+ return assert.eventually.isArray(corpus.findAll());
+ }
+ );
+ it('.findAll() return objects with ID and code',
+ function () {
+ return assert.eventually.ok(corpus.findAll().then(
+ function (codes) {
+ return _.all(codes, function (code) {
+ return _.isString(code.id.toString()) &&
+ _.isString(code.code);
+ });
+ })
+ );
+ }
+ );
+ describe('and known ID',
+ function () {
+ var id;
+ beforeEach(function (done) {
+ corpus.create(testData.codes[1]).then(function (code) {
+ id = code.id;
+ done();
+ });
+ });
+ it('.findById() returns object', function () {
+ return assert.eventually.isObject(corpus.findById(id));
+ });
+ it('.remove() removes an object', function () {
+ return assert.eventually.isObject(corpus.remove(id));
+ });
+ it('.update() returns new object', function () {
+ return assert.eventually.isObject(
+ corpus.update(id, testData.codes[1])
+ );
+ });
+ }
+ );
+ });
+ });
+});
diff --git a/test/server/testData.js b/test/server/testData.js
new file mode 100644
index 0000000..eae1f30
--- /dev/null
+++ b/test/server/testData.js
@@ -0,0 +1,12 @@
+module.exports = {
+ codes: [
+ 'ASSERT EQUAL APP VAR types.semi I I',
+ 'DEFINE VAR types.div APP VAR types.type K',
+ 'DEFINE VAR types.forall.push APP APP C I TOP',
+ 'DEFINE VAR util.join J',
+ 'ASSERT EQUAL APP APP C APP VAR util.pair BOT VAR' +
+ ' util.join I',
+ 'ASSERT EQUAL APP APP C APP APP C VAR util.pair' +
+ ' BOT VAR util.join I'
+ ]
+};
\ No newline at end of file