1
0
Fork 0
mirror of https://github.com/Oreolek/raconteur.git synced 2024-06-26 03:30:47 +03:00

Add Karma testing + partial specs

This commit is contained in:
Bruno Dias 2015-04-12 22:23:33 -03:00
parent 9a071c2999
commit 3c1102d9de
8 changed files with 318 additions and 11 deletions

74
karma.conf.js Normal file
View file

@ -0,0 +1,74 @@
// Karma configuration
// Generated on Sun Apr 12 2015 20:11:32 GMT-0300 (BRT)
module.exports = function(config) {
config.set({
// base path that will be used to resolve all patterns (eg. files, exclude)
basePath: '',
// frameworks to use
// available frameworks: https://npmjs.org/browse/keyword/karma-adapter
frameworks: ['browserify', 'jasmine'],
// list of files / patterns to load in the browser
files: [
'lib/*.js',
'spec/*.js'
],
// list of files to exclude
exclude: [
],
// preprocess matching files before serving them to the browser
// available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
preprocessors: {
"lib/*.js": ['browserify'],
"spec/*.js": ['browserify']
},
// test results reporter to use
// possible values: 'dots', 'progress'
// available reporters: https://npmjs.org/browse/keyword/karma-reporter
reporters: ['progress'],
// web server port
port: 9876,
// enable / disable colors in the output (reporters and logs)
colors: true,
// level of logging
// possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
logLevel: config.LOG_INFO,
// enable / disable watching file and executing tests whenever any file changes
autoWatch: true,
// start these browsers
// available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
browsers: ['Chrome'],
// Continuous Integration mode
// if true, Karma captures browsers, runs the tests and exits
browserify: {
debug: true,
transform: ['babelify']
}
});
};

View file

@ -105,9 +105,15 @@ elementHelper.prototype.toString = function () {
if (this._classes) {
classes += this._classes.join(' ');
}
if (this._linkType) {
classes += (' ' + this._linkType);
if (classes) {
classes += (' ' + this._linkType);
} else {
classes = this._linkType;
}
}
if (classes) {
classString = ` class="${classes}"`;
}
@ -129,18 +135,18 @@ elementHelper.prototype.toString = function () {
}
if (this._src) {
srcString = `src="${this._src}"`;
srcString = ` src="${this._src}"`;
}
if (this._alt) {
altString = `alt="${this._alt}"`;
altString = ` alt="${this._alt}"`;
}
if (this._content) {
contentString = markdown.renderInline(this._content);
}
return `<${this.element}${classString}${idString}${hrefString}${srcString}>${contentString}</${this.element}>`;
return `<${this.element}${classString}${idString}${hrefString}${srcString}${altString}>${contentString}</${this.element}>`;
};
var a_proto = Object.freeze(new elementHelper("a"));

View file

@ -114,7 +114,7 @@ var oneOf = function (...ary) {
},
randomly (system) {
var rng = (system) ? system.random : Math.random,
var rng = (system) ? system.rnd.random : Math.random,
last;
if (ary.length<2) {
@ -122,19 +122,29 @@ var oneOf = function (...ary) {
"attempted to make randomly() iterator with a 1-length array");
}
return stringish(function () {
var i;
var i, offset;
if (last === undefined) {
i = Math.floor(rng() * ary.length)
} else {
/*
Let offset be a random number between 1 and the length of the
array, minus one. We jump offset items ahead on the array,
wrapping around to the beginning. This gives us a random item
other than the one we just chose.
*/
do {
i = Math.floor(rng() * ary.length);
} while (i === last);
offset = Math.floor(rng() * (ary.length -1) + 1);
i = (last + offset) % ary.length;
}
last = i;
return ary[i];
});
},
trulyAtRandom (system) {
var rng = (system) ? system.random : Math.random;
var rng = (system) ? system.rnd.random : Math.random;
return stringish(function () {
return ary[Math.floor(rng() * ary.length)];
});

View file

@ -238,5 +238,5 @@ RaconteurSituation.prototype.act = function (character, system, action) {
module.exports = function (name, spec) {
spec.name = name;
undum.game.situations[name] = new RaconteurSituation(spec);
return (undum.game.situations[name] = new RaconteurSituation(spec));
};

View file

@ -22,6 +22,12 @@
"gulp-less": "~3.0.2",
"gulp-sourcemaps": "^1.5.1",
"gulp-util": "^3.0.4",
"jasmine-core": "^2.2.0",
"karma": "^0.12.31",
"karma-babel-preprocessor": "^5.0.1",
"karma-browserify": "^4.1.2",
"karma-chrome-launcher": "^0.1.7",
"karma-jasmine": "^0.3.5",
"lodash": "^3.6.0",
"vinyl-buffer": "^1.0.0",
"vinyl-source-stream": "~1.1.0",

68
spec/elementsSpec.js Normal file
View file

@ -0,0 +1,68 @@
var elements = require('raconteur/elements.js');
var a = elements.a, span = elements.span;
describe('elementHelper', function() {
it('stringifies as a tag', function() {
var elem = elements.element('span');
expect('' + elem).toBe('<span></span>')
});
it('supplies monadic methods', function () {
var elem = elements.element('span');
var elem_ = elem.class('foo').id('my_span');
expect('' + elem_).toBe('<span class="foo" id="my_span"></span>');
});
it('allows redefining previously set attributes', function () {
var elem = elements.element('span').content('foo');
expect('' + elem).toBe('<span>foo</span>');
expect('' + elem.content('bar')).toBe('<span>bar</span>');
expect('' + elem).toBe('<span>foo</span>');
});
it('adds classes with class()', function () {
expect('' + span().class('foo').class('bar'))
.toBe('<span class="foo bar"></span>');
});
it('redefines classes with class()', function () {
expect('' + span().class('foo').classes(['bar', 'baz']))
.toBe('<span class="bar baz"></span>');
});
it('allows setting most tag attributes', function () {
expect('' +
a('content').class('class').id('id').url('ref').src('src').alt('alt'))
.toBe('<a class="class" id="id" href="ref" src="src" alt="alt">content</a>')
});
it('is immutable', function() {
var span = elements.element('span');
var shouldBreak = function () {
span._content = "foo";
};
expect(shouldBreak).toThrowError();
});
});
describe('a', function() {
it('creates an <a> element', function() {
expect('' + a('foo').url('http://example.com'))
.toBe('<a href="http://example.com">foo</a>');
});
it('supplies shorthand for common action links', function (){
expect('' + a('foo').action('bar'))
.toBe('<a class="action" href="./bar">foo</a>');
expect('' + a('foo').writer('bar'))
.toBe('<a class="writer" href="./_writer_bar">foo</a>');
});
});

93
spec/oneOfSpec.js Normal file
View file

@ -0,0 +1,93 @@
var oneOf = require('raconteur/oneOf.js');
describe('oneOf', function() {
var oneOfObj;
beforeEach(function () {
oneOfObj = oneOf('foo', 'bar', 'baz');
});
it('creates an object that supplies certain methods', function () {
expect(typeof oneOfObj).toBe('object');
expect(oneOfObj.cycling).toBeDefined;
expect(oneOfObj.stopping).toBeDefined;
expect(oneOfObj.randomly).toBeDefined;
expect(oneOfObj.trulyAtRandom).toBeDefined;
expect(oneOfObj.inRandomOrder).toBeDefined;
});
it('produces functions with those methods', function () {
expect(typeof oneOfObj.cycling()).toBe('function');
expect(typeof oneOfObj.stopping()).toBe('function');
expect(typeof oneOfObj.randomly()).toBe('function');
expect(typeof oneOfObj.trulyAtRandom()).toBe('function');
expect(typeof oneOfObj.inRandomOrder()).toBe('function');
});
it('allows stringifying those functions directly', function () {
expect('' + oneOfObj.cycling()).toBe('foo');
});
it('creates a closure that cycles', function () {
var cycler = oneOfObj.cycling();
expect(cycler(), cycler(), cycler(), cycler())
.toBe('foo', 'bar', 'baz', 'foo', 'bar', 'baz');
});
it('is agnostic about values', function () {
var cycler = oneOf('foo', 1, null, {}).cycling();
expect(cycler(), cycler(), cycler(), cycler())
.toBe('foo', 1, null, {});
});
it('creates a closure that stops', function () {
var stopper = oneOfObj.stopping();
expect(stopper(), stopper(), stopper(), stopper())
.toBe('foo', 'bar', 'baz', 'baz');
});
describe('using random numbers', function () {
/* This expects a System object supplying system.rnd.random(); */
var randomStub;
beforeEach(function () {
randomStub = {
rnd: {
random: (function () {
var i = 0,
outputs = [0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9];
return function () {
if (i >= outputs.length) i = 0;
return outputs[i];
}
})()
}
};
oneOfObj = oneOf('foo', 'bar', 'baz');
spyOn(randomStub.rnd, 'random').and.callThrough();
});
it('creates a closure that returns a random item', function () {
var snippet = oneOfObj.trulyAtRandom(randomStub);
expect(snippet(), snippet(), snippet()).toBe('foo', 'foo', 'foo');
expect(randomStub.rnd.random).toHaveBeenCalled();
});
it('will not return the same item twice with randomly()', function () {
var snippet = oneOfObj.randomly(randomStub);
expect(snippet() !== snippet()).toBe(true);
});
it('can cycle through a random list', function () {
var snippet = oneOfObj.inRandomOrder(randomStub);
var snippets = [snippet(), snippet(), snippet(), snippet()];
expect(snippets[0]).toBe(snippets[3]);
});
});
});

50
spec/situationSpec.js Normal file
View file

@ -0,0 +1,50 @@
var situation = require('raconteur/situation.js');
describe ('situation', function () {
var test_situation = situation('test-situation', {
content: "This is the content of the *testing* situation.",
choices: ['#foo']
});
var system_spy;
beforeEach(function () {
system_spy = {
write: function () {return;},
getSituationIdChoices: function () {return;},
writeChoices: function () {return;}
};
spyOn(system_spy, 'write');
spyOn(system_spy, 'getSituationIdChoices').and.returnValue(['foo', 'foo-bar']);
spyOn(system_spy, 'writeChoices');
});
it('has a name', function () {
expect(test_situation.name).toBe('test-situation');
});
it('parses its content as markdown', function () {
test_situation.enter({}, system_spy, '');
expect(system_spy.write)
.toHaveBeenCalledWith("<p>This is the content of the <em>testing</em> situation.</p>\n");
});
it('is agnostic about whether content is a string or a function', function () {
test_situation.content = function () {return "Foo and bar."};
test_situation.enter({}, system_spy, '');
expect(system_spy.write)
.toHaveBeenCalledWith("<p>Foo and bar.</p>\n");
});
it('generates a list of choices', function () {
test_situation.enter({}, system_spy, '');
expect(system_spy.getSituationIdChoices)
.toHaveBeenCalledWith(['#foo'], undefined, undefined);
expect(system_spy.writeChoices).toHaveBeenCalledWith(['foo', 'foo-bar']);
});
});