rpg-table-randomizer
Version:
Module for random tables for use in roleplaying games
289 lines (247 loc) • 10.7 kB
JavaScript
;
import { describe, it } from 'mocha';
import { assert, expect } from 'chai';
import { stub } from 'sinon';
import DisplayOptions from '../src/DisplayOptions.js';
import RandomTable from '../src/RandomTable.js';
import RandomTableResult from '../src/RandomTableResult.js';
import RandomTableResultSet from '../src/RandomTableResultSet.js';
import TableError from '../src/TableError.js';
import TableRoller from '../src/TableRoller.js';
import TableErrorResult from '../src/TableErrorResult.js';
const roller = new TableRoller({
token_types: {
food: function (token_parts, full_token = '', curtable = null) {
return 'food token';
},
range_error: function (token_parts, full_token = '', curtable = null) {
throw new RangeError('out of memory');
}
}
});
const colorTable = new RandomTable({
key: 'colors',
title: 'Color Wheel',
tables: {
primary: [
'blue'
],
secondary: [
'green'
],
mixed: [
'{{table:this:primary}} {{table:this:secondary}}'
]
},
display_opt: [
new DisplayOptions({ table: 'secondary' })
]
});
const complicatedTable = new RandomTable({
key: 'complicated',
tables: {
sequence: [
{ subtable: ['foo', 'mark'], print: false }
],
foo: [
'bar'
],
mark: [
'down'
]
},
macro: ['colors:secondary', 'nonexistent']
});
const getTables = function (key) {
switch (key) {
case 'colors':
return colorTable;
case 'directions':
break;
default:
return null;
}
};
roller.setTableKeyLookup(getTables);
describe('TableRoller', function () {
describe('getTableByKey', function () {
it('should return error for no table lookup', function () {
const roller_error = new TableRoller({});
expect(() => { roller_error.getTableByKey(); }).to.throw(TableError, 'No table key');
expect(() => { roller_error.getTableByKey('colors'); }).to.throw(TableError, 'No table found');
});
});
describe('_selectFromTable', function () {
it('should return error on invalid subtable', function () {
const errorResult = roller._selectFromTable(colorTable, 'shades')[0];
expect(errorResult).to.be.instanceOf(TableErrorResult);
expect(errorResult.key).to.equal(colorTable.key);
expect(errorResult).to.deep.include({
table: 'shades',
result: 'Invalid subtable name.'
});
});
it('should return result for no subtables', function () {
expect(roller._selectFromTable(colorTable, 'primary')[0]).to.deep.include({
table: 'primary',
result: 'blue'
});
});
it('should return result for subtables', function () {
const results = roller._selectFromTable(complicatedTable, 'sequence');
expect(results.length).to.equal(2);
expect(results[0]).to.deep.include({
table: 'foo',
result: 'bar'
});
expect(results[1]).to.deep.include({
table: 'mark',
result: 'down'
});
});
});
describe('_getTableMacroResult', function () {
it('should return result for macro list', function () {
const results = roller._getTableMacroResult(complicatedTable);
expect(results.length).to.equal(2);
expect(results[0]).to.deep.include({
table: 'secondary',
result: 'green'
});
expect(results[1]).to.deep.include({
table: 'nonexistent',
result: 'No table found for key: nonexistent'
});
});
it('should throw error for self reference', function () {
const selfTable = new RandomTable({
key: 'self',
macro: ['colors', 'self']
});
expect(() => { roller._getTableMacroResult(selfTable); }).to.throw(TableError, 'self reference');
});
});
describe('findToken', function () {
it('should find dice tokens and convert them', function () {
expect(roller.findToken('{{roll:1d1}}')).to.equal('1');
expect(roller.findToken('from {{roll:1d1}} to {{roll:1d2/2}}')).to.equal('from 1 to 1');
});
it('should return the token for unknown tokens', function () {
expect(roller.findToken('{{foo:bar}}')).to.equal('{{foo:bar}}');
});
});
describe('convertToken', function () {
it('should convert tokens', function () {
// table handler
const actual = roller.convertToken('{{table:colors:primary}}');
expect(actual).to.be.instanceOf(RandomTableResultSet);
expect(actual.key).to.equal(colorTable.key);
expect(actual.results[0]).to.have.property('result', 'blue');
// custom token handler
expect(roller.convertToken('{{food:appetizer}}')).to.equal('food token');
});
it('should handle oneof token', function () {
const actual = roller.convertToken('{{oneof:dwarf|elf}}');
expect(actual).to.be.oneOf(['dwarf', 'elf']);
});
it('should return token for empty token', function () {
// empty token
const token1 = '{{ }}';
expect(roller.convertToken(token1)).to.equal(token1);
});
it('should return token for unknown token type', function () {
// unknown token type
const token2 = '{{foo:bar:gamma}}';
expect(roller.convertToken(token2)).to.equal(token2);
});
it('should return Error ResultSet for thrown range error', function () {
// Catch RangeError
const errorResult = roller.convertToken('{{range_error:foo:bar}}');
expect(errorResult.results[0]).to.be.instanceOf(TableErrorResult);
expect(errorResult.results[0]).to.deep.include({
result: 'out of memory'
});
});
});
describe('getResultSetForTable', function () {
it('should return error set on invalid table', function () {
const errorResult = roller.getResultSetForTable('table_string');
expect(errorResult.results[0]).to.be.instanceOf(TableErrorResult);
expect(errorResult.results[0]).to.deep.include({
result: 'Invalid table data.'
});
});
it('should return result set on valid table', function () {
const resultSet = roller.getResultSetForTable(colorTable);
expect(resultSet.title).to.equal('Color Wheel');
expect(resultSet.displayOptions.get('secondary')).to.be.an.instanceOf(DisplayOptions);
expect(resultSet.results[0]).to.deep.include({
table: 'primary',
result: 'blue'
});
});
});
describe('getTableResultSetByKey', function () {
it('should return error result on bad table', function () {
const errorResult = roller.getTableResultSetByKey('table_string');
expect(errorResult.results[0]).to.be.instanceOf(TableErrorResult);
});
it('should return result set', function () {
const resultSet = roller.getTableResultSetByKey('colors', 'primary');
expect(resultSet.title).to.equal('Color Wheel');
expect(resultSet.displayOptions.get('secondary')).to.be.an.instanceOf(DisplayOptions);
expect(resultSet.results[0]).to.deep.include({
table: 'primary',
result: 'blue'
});
});
});
describe('getTableResult', function () {
it('should handle macros in tables', function () {
const macroStub = stub(roller, '_getTableMacroResult');
const resultSet = new RandomTableResult({ key: complicatedTable.key, table: 'macro' });
macroStub.returns([resultSet]);
expect(roller.getTableResult(complicatedTable)).to.deep.equal([resultSet]);
macroStub.restore();
});
it('should handle no starting table', function () {
const selectStub = stub(roller, '_selectFromTable');
const resultSet = new RandomTableResultSet({ key: colorTable.key, title: 'colors' });
selectStub.withArgs(colorTable, 'primary').returns(resultSet);
expect(roller.getTableResult(colorTable)[0]).to.equal(resultSet);
selectStub.restore();
});
it('should handle with starting table', function () {
const selectStub = stub(roller, '_selectFromTable');
const resultSet = new RandomTableResultSet({ key: colorTable.key, title: 'colors' });
selectStub.withArgs(colorTable, 'secondary').returns(resultSet);
expect(roller.getTableResult(colorTable, 'secondary')[0]).to.equal(resultSet);
selectStub.restore();
});
it('should handle with multitable sequence', function () {
const selectStub = stub(roller, '_selectFromTable');
const resultSet = new RandomTableResultSet({ key: colorTable.key, title: 'colors' });
const resultSet2 = new RandomTableResultSet({ key: colorTable.key, title: 'colors primary' });
selectStub.withArgs(colorTable, 'secondary').returns(resultSet);
selectStub.withArgs(colorTable, 'primary').returns(resultSet2);
colorTable.sequence = ['secondary', 'primary'];
expect(roller.getTableResult(colorTable)).to.deep.equal([resultSet, resultSet2]);
colorTable.sequence = [];
selectStub.restore();
});
});
describe('_defaultOneOfToken', function () {
it('should return token for no arguments', function () {
expect(roller._defaultOneOfToken(['oneof'], '{{oneof:}}'))
.to.equal('{{oneof:}}');
});
it('should return option if only one', function () {
expect(roller._defaultOneOfToken(['oneof', 'bread'], '{{oneof:bread}}'))
.to.equal('bread');
});
it('should return one of the options', function () {
expect(roller._defaultOneOfToken(['oneof', 'bread|water'], '{{oneof:bread}}'))
.to.be.oneOf(['bread', 'water']);
});
});
});