diff --git a/lib/template.js b/lib/template.js index 64eadcad..aac78d77 100644 --- a/lib/template.js +++ b/lib/template.js @@ -7,11 +7,17 @@ module.exports = function(template) { if(!template.hasOwnProperty(expr)) throw new Error("\"" + expr + "\" not found in language template."); + else if(typeof template[expr] !== "string" || + /\$\d+/.test(template[expr])) + throw new Error("\"" + expr + "\" was used in a value context, but is expected in a template context."); + else return template[expr]; } - else if(Array.isArray(expr)) { + else if(Array.isArray(expr) && + expr.length && + typeof expr[0] === "string") { if(!template.hasOwnProperty(expr[0])) throw new Error("\"" + expr[0] + "\" not found in language template."); diff --git a/test.js b/test.js index 18bb2e3d..eeb0d46d 100644 --- a/test.js +++ b/test.js @@ -1,31 +1,92 @@ var expect = require("chai").expect, fs = require("fs"), path = require("path"), + template = require("./lib/template"), translation = require("./"), util = require("util"); describe("translation", function() { - fs.readdirSync(path.join(__dirname, "test-cases")).forEach(function(lang) { - if(lang.charAt(0) === ".") - return; + describe("template", function() { + var convert = template({ + "foo": "bar", + "bar": "meeple $2", + "baz": function(a, b) { return "meeple " + b; } + }); - var name = path.basename(lang, ".json"), - translate = translation[name]; + it("should return a number in string form", function() { + expect(convert(42)).to.equal("42"); + }); + + it("should throw an error given an unrecognized string", function() { + expect(function() { convert("42"); }).to.throw(); + }); + + it("should apply an expected value conversion", function() { + expect(convert("foo")).to.equal("bar"); + }); + + it("should throw an error given a value that's expected to be a string template", function() { + expect(function() { convert("bar"); }).to.throw(); + }); + + it("should throw an error given a value that's expected to be a function template", function() { + expect(function() { convert("baz"); }).to.throw(); + }); + + it("should throw an error given an empty array", function() { + expect(function() { convert([]); }).to.throw(); + }); + + it("should apply a string template", function() { + expect(convert(["bar", 10, 20])).to.equal("meeple 20"); + }); + + it("should apply a function template", function() { + expect(convert(["baz", 10, 20])).to.equal("meeple 20"); + }); + + it("should recursively apply function templates", function() { + /* Actually, a "meeple meeple bar" sounds like it'd be a pretty tasty + * candy treat. */ + expect(convert(["bar", 10, ["baz", 20, "foo"]])).to.equal("meeple meeple bar"); + }); + + it("should throw an error given undefined", function() { + expect(function() { convert(undefined); }).to.throw(); + }); + + it("should throw an error given null", function() { + expect(function() { convert(null); }).to.throw(); + }); + + it("should throw an error given an object", function() { + expect(function() { convert({}); }).to.throw(); + }); + }); + + describe("language", function() { + fs.readdirSync(path.join(__dirname, "test-cases")).forEach(function(lang) { + if(lang.charAt(0) === ".") + return; + + var name = path.basename(lang, ".json"), + translate = translation[name]; + + describe(name, function() { + var cases = JSON.parse( + fs.readFileSync(path.join(__dirname, "test-cases", lang)) + ); + + Object.keys(cases).forEach(function(summary) { + var source = cases[summary]; - describe(name, function() { - var cases = JSON.parse( - fs.readFileSync(path.join(__dirname, "test-cases", lang)) + it( + util.format("should translate %j to \"%s\"", source, summary), + function() { + expect(translate(source)).to.equal(summary); + } ); - - Object.keys(cases).forEach(function(summary) { - var source = cases[summary]; - - it( - util.format("should translate %j to \"%s\"", source, summary), - function() { - expect(translate(source)).to.equal(summary); - } - ); + }); }); }); });