@schukai/monster
Version:
Monster is a simple library for creating fast, robust and lightweight websites.
332 lines (236 loc) • 9.39 kB
JavaScript
import {expect} from "chai"
import {Formatter} from "../../../source/text/formatter.mjs";
describe('Formatter', function () {
// https://gitlab.schukai.com/oss/libraries/javascript/monster/-/issues/275
describe('change empty handling', function () {
it('modification 1', function () {
const formatter = new Formatter({
a: null,
b: undefined,
c : 0
})
expect(formatter.format("${a | tostring}")).to.be.equal('null');
expect(formatter.format("${b | tostring}")).to.be.equal('undefined');
expect(formatter.format("${c | tostring}")).to.be.equal('0');
})
})
// https://gitlab.schukai.com/oss/libraries/javascript/monster/-/issues/47
describe('examples', function () {
it('rfc example should run', function () {
expect(new Formatter({
a: {
b: {
c: "Hello"
},
d: "World",
e: 1
}
}).format("${a.b.c} ${a.d | toupper}!")).to.be.equal('Hello WORLD!');
})
it('doc example should run', function () {
expect(new Formatter({
a: {
b: {
c: "Hello"
},
d: "world",
}
}).format("${a.b.c} ${a.d | ucfirst}!")).to.be.equal('Hello World!');
})
})
describe('set marker()', function () {
[
['#a#', '#', undefined, 'test'],
['{a}', '{', '}', 'test'],
['i18n{a}', 'i18n{', '}', 'test'],
].forEach(function (data) {
let a = data.shift()
let b = data.shift()
let c = data.shift()
let d = data.shift()
it('format ' + a + ' with marker ' + b + ' and ' + c + ' should return ' + b, function () {
expect(
new Formatter({
a: "test"
}).setMarker(b, c).format(a)
).to.equal(d)
});
});
})
describe('examples()', function () {
[
['${a | tojson}', "{\"b\":{\"c\":\"Hello\"},\"d\":\"World\",\"e\":1}"],
['click ${a.d} times', "click World times"],
[' ${a.b.c} ', ' Hello '],
[' ${a.b.c}', ' Hello'],
['${a.b.c} ', 'Hello '],
['${a.b.c}', 'Hello'],
['${a.b.c}${a.b.c}', 'HelloHello'],
['${a.b.c} ${a.b.c}', 'Hello Hello'],
['${a.b.c} ${a.b.c} ', 'Hello Hello '],
[' ${a.b.c} ${a.b.c} ', ' Hello Hello '],
[' ${a.b.c} ${a.d} ', ' Hello World '],
[' ${a.b.c} ${a.b.c | toupper | length | tostring} ', ' Hello 5 '],
].forEach(function (data) {
let a = data.shift()
let b = data.shift()
it('format ' + a + ' should return ' + b, function () {
let obj = {
a: {
b: {
c: "Hello"
},
d: "World",
e: 1
}
}
expect(new Formatter(obj).format(a)).is.equal(b)
});
});
});
describe('Marker in marker', function () {
let text = '${mykey${subkey}}';
let expected = '1';
it('format ' + text + ' should ' + expected, function () {
let obj = {
mykey2: "1",
subkey: "2"
};
expect(new Formatter(obj).format(text)).is.equal(expected)
});
});
describe('setParameterChars()', function () {
it('setParameterChars() should return Instance', function () {
expect(new Formatter({}).setParameterChars('a', 'b')).is.instanceof(Formatter);
});
});
describe('with callbacks', function () {
it('add callback', function () {
const formatter = new Formatter({
x: '1'
}, {
callbacks: {
my: (value) => {
return "!" + value + "!"
}
}
});
expect(formatter.format('${x | call:my}')).is.equal('!1!');
});
});
describe('Marker in marker with parameter', function () {
let text = '${mykey::mykey=${subkey}}';
let expected = '2';
it('format ' + text + ' should ' + expected, function () {
let obj = {
subkey: "2"
};
expect(new Formatter(obj).format(text)).is.equal(expected)
});
});
describe('exceptions', function () {
[
['${a.b.x}', TypeError],
['${a.b.d | toupper | length}', TypeError],
['${a.b.d}', TypeError], // a.b.d return undefined by pathfinder
['${a.b.d | tolower}', TypeError], // a.b.d return undefined by pathfinder
['${a | }', Error],
].forEach(function (data) {
let a = data.shift()
let b = data.shift()
it('format ' + a + ' should throw ' + typeof b, function () {
expect(() => {
new Formatter({
a: {
b: {
c: "test",
d: 4
}
}
}).format(a)
}
).to.throw(b);
});
});
});
describe('Formatter', () => {
it('should format a basic string with object values', () => {
const formatter = new Formatter({name: 'John', age: 30});
const result = formatter.format('My name is ${name} and I am ${age | tostring} years old.');
expect(result).to.equal('My name is John and I am 30 years old.');
});
it('should format a string with nested markers', () => {
const text = '${mykey${subkey}}';
const obj = {mykey2: '1', subkey: '2'};
const formatter = new Formatter(obj);
expect(formatter.format(text)).to.equal('1');
});
it('should format a string with custom markers', () => {
const formatter = new Formatter({name: 'John', age: 30});
formatter.setMarker('[', ']');
const result = formatter.format('My name is [name] and I am [age | tostring] years old.');
expect(result).to.equal('My name is John and I am 30 years old.');
});
it('should format a string using callback', () => {
const formatter = new Formatter({x: '1'}, {
callbacks: {
quote: (value) => {
return '"' + value + '"';
},
},
});
expect(formatter.format('${x | call:quote}')).to.equal('"1"');
});
it('should format a string with parameters', () => {
const obj = {
a: {
b: {
c: 'Hello',
},
d: 'world',
},
};
const formatter = new Formatter(obj);
const result = formatter.format('${a.b.c} ${a.d | ucfirst}!');
expect(result).to.equal('Hello World!');
});
it('should throw a too deep nesting error', () => {
const formatter = new Formatter({name: 'John'});
const nestedText = '${name${name${name${name${name${name${name${name${name${name${name${name${name${name${name${name${name${name${name}}}}}}}}}}}}}}}}}}';
expect(() => formatter.format(nestedText)).to.throw('syntax error in formatter template');
});
it('should throw a too deep nesting error', () => {
const inputObj = {
mykey: '${mykey}',
};
const formatter = new Formatter(inputObj, {
recursion: {
detectCycles: false,
},
});
const text = '${mykey}';
let formattedText = text;
// Create a string with 21 levels of nesting
for (let i = 0; i < 21; i++) {
formattedText = '${' + formattedText + '}';
}
expect(() => formatter.format(formattedText)).to.throw('too deep nesting');
});
it('should detect recursion cycles by default', () => {
const formatter = new Formatter({
a: '${b}',
b: '${a}',
});
expect(() => formatter.format('${a}')).to.throw('cycle detected in formatter');
});
it('should allow configuring max depth', () => {
const formatter = new Formatter({value: '${value}'}, {
recursion: {
maxDepth: 3,
detectCycles: false,
},
});
expect(() => formatter.format('${value}')).to.throw('too deep nesting');
});
});
});