Remove deprecated helpers and fix release script (#2128)

* Remove deprecated helpers
* Use more idiomatic assertions
* Fix release script
This commit is contained in:
Igor Savin
2026-03-03 22:52:28 +02:00
committed by GitHub
parent d65683434d
commit 169ef75066
18 changed files with 340 additions and 543 deletions
+1 -1
View File
@@ -76,7 +76,7 @@
"scripts": {
"build": "grunt build",
"release": "grunt release",
"publish:aws": "npm run test:tasks && grunt && grunt publish-to-aws",
"publish:aws": "grunt && npm run test:tasks && grunt publish-to-aws",
"format": "prettier --write '**/*.{js,css,json,md}' && eslint --fix .",
"lint": "npm run lint:eslint && npm run lint:prettier && npm run lint:types",
"lint:eslint": "eslint --max-warnings 0 .",
-6
View File
@@ -3,14 +3,8 @@ module.exports = {
CompilerContext: true,
Handlebars: true,
handlebarsEnv: true,
shouldCompileTo: true,
shouldCompileToWithPartials: true,
shouldThrow: true,
expectTemplate: true,
compileWithPartials: true,
suite: true,
equal: true,
equals: true,
test: true,
testBoth: true,
raises: true,
+50 -52
View File
@@ -7,102 +7,100 @@ describe('ast', function () {
describe('BlockStatement', function () {
it('should throw on mustache mismatch', function () {
shouldThrow(
function () {
expect(function () {
handlebarsEnv.parse('\n {{#foo}}{{/bar}}');
},
Handlebars.Exception,
"foo doesn't match bar - 2:5"
);
}).toThrow("foo doesn't match bar - 2:5");
});
});
describe('helpers', function () {
describe('#helperExpression', function () {
it('should handle mustache statements', function () {
equals(
expect(
AST.helpers.helperExpression({
type: 'MustacheStatement',
params: [],
hash: undefined,
}),
false
);
equals(
})
).toBe(false);
expect(
AST.helpers.helperExpression({
type: 'MustacheStatement',
params: [1],
hash: undefined,
}),
true
);
equals(
})
).toBe(true);
expect(
AST.helpers.helperExpression({
type: 'MustacheStatement',
params: [],
hash: {},
}),
true
);
})
).toBe(true);
});
it('should handle block statements', function () {
equals(
expect(
AST.helpers.helperExpression({
type: 'BlockStatement',
params: [],
hash: undefined,
}),
false
);
equals(
})
).toBe(false);
expect(
AST.helpers.helperExpression({
type: 'BlockStatement',
params: [1],
hash: undefined,
}),
true
);
equals(
})
).toBe(true);
expect(
AST.helpers.helperExpression({
type: 'BlockStatement',
params: [],
hash: {},
}),
})
).toBe(true);
});
it('should handle subexpressions', function () {
expect(AST.helpers.helperExpression({ type: 'SubExpression' })).toBe(
true
);
});
it('should handle subexpressions', function () {
equals(AST.helpers.helperExpression({ type: 'SubExpression' }), true);
});
it('should work with non-helper nodes', function () {
equals(AST.helpers.helperExpression({ type: 'Program' }), false);
expect(AST.helpers.helperExpression({ type: 'Program' })).toBe(false);
equals(
AST.helpers.helperExpression({ type: 'PartialStatement' }),
expect(AST.helpers.helperExpression({ type: 'PartialStatement' })).toBe(
false
);
equals(
AST.helpers.helperExpression({ type: 'ContentStatement' }),
expect(AST.helpers.helperExpression({ type: 'ContentStatement' })).toBe(
false
);
equals(
AST.helpers.helperExpression({ type: 'CommentStatement' }),
expect(AST.helpers.helperExpression({ type: 'CommentStatement' })).toBe(
false
);
equals(AST.helpers.helperExpression({ type: 'PathExpression' }), false);
equals(AST.helpers.helperExpression({ type: 'StringLiteral' }), false);
equals(AST.helpers.helperExpression({ type: 'NumberLiteral' }), false);
equals(AST.helpers.helperExpression({ type: 'BooleanLiteral' }), false);
equals(
AST.helpers.helperExpression({ type: 'UndefinedLiteral' }),
expect(AST.helpers.helperExpression({ type: 'PathExpression' })).toBe(
false
);
equals(AST.helpers.helperExpression({ type: 'NullLiteral' }), false);
equals(AST.helpers.helperExpression({ type: 'Hash' }), false);
equals(AST.helpers.helperExpression({ type: 'HashPair' }), false);
expect(AST.helpers.helperExpression({ type: 'StringLiteral' })).toBe(
false
);
expect(AST.helpers.helperExpression({ type: 'NumberLiteral' })).toBe(
false
);
expect(AST.helpers.helperExpression({ type: 'BooleanLiteral' })).toBe(
false
);
expect(AST.helpers.helperExpression({ type: 'UndefinedLiteral' })).toBe(
false
);
expect(AST.helpers.helperExpression({ type: 'NullLiteral' })).toBe(
false
);
expect(AST.helpers.helperExpression({ type: 'Hash' })).toBe(false);
expect(AST.helpers.helperExpression({ type: 'HashPair' })).toBe(false);
});
});
});
@@ -111,10 +109,10 @@ describe('ast', function () {
var ast, body;
function testColumns(node, firstLine, lastLine, firstColumn, lastColumn) {
equals(node.loc.start.line, firstLine);
equals(node.loc.start.column, firstColumn);
equals(node.loc.end.line, lastLine);
equals(node.loc.end.column, lastColumn);
expect(node.loc.start.line).toBe(firstLine);
expect(node.loc.start.column).toBe(firstColumn);
expect(node.loc.end.line).toBe(lastLine);
expect(node.loc.end.column).toBe(lastColumn);
}
/* eslint-disable no-multi-spaces */
+12 -16
View File
@@ -381,26 +381,26 @@ describe('blocks', function () {
var run;
expectTemplate('{{*decorator "success"}}')
.withDecorator('decorator', function (fn, props, container, options) {
equals(options.args[0], 'success');
expect(options.args[0]).toBe('success');
run = true;
return fn;
})
.withInput({ foo: 'success' })
.toCompileTo('');
equals(run, true);
expect(run).toBe(true);
});
it('should fail when accessing variables from root', function () {
var run;
expectTemplate('{{*decorator foo}}')
.withDecorator('decorator', function (fn, props, container, options) {
equals(options.args[0], undefined);
expect(options.args[0]).toBeUndefined();
run = true;
return fn;
})
.withInput({ foo: 'fail' })
.toCompileTo('');
equals(run, true);
expect(run).toBe(true);
});
describe('registration', function () {
@@ -411,9 +411,9 @@ describe('blocks', function () {
return 'fail';
});
equals(!!handlebarsEnv.decorators.foo, true);
expect(handlebarsEnv.decorators.foo).toBeTruthy();
handlebarsEnv.unregisterDecorator('foo');
equals(handlebarsEnv.decorators.foo, undefined);
expect(handlebarsEnv.decorators.foo).toBeUndefined();
});
it('allows multiple globals', function () {
@@ -424,17 +424,16 @@ describe('blocks', function () {
bar: function () {},
});
equals(!!handlebarsEnv.decorators.foo, true);
equals(!!handlebarsEnv.decorators.bar, true);
expect(handlebarsEnv.decorators.foo).toBeTruthy();
expect(handlebarsEnv.decorators.bar).toBeTruthy();
handlebarsEnv.unregisterDecorator('foo');
handlebarsEnv.unregisterDecorator('bar');
equals(handlebarsEnv.decorators.foo, undefined);
equals(handlebarsEnv.decorators.bar, undefined);
expect(handlebarsEnv.decorators.foo).toBeUndefined();
expect(handlebarsEnv.decorators.bar).toBeUndefined();
});
it('fails with multiple and args', function () {
shouldThrow(
function () {
expect(function () {
handlebarsEnv.registerDecorator(
{
world: function () {
@@ -446,10 +445,7 @@ describe('blocks', function () {
},
{}
);
},
Error,
'Arg not supported with multiple decorators'
);
}).toThrow('Arg not supported with multiple decorators');
});
});
});
+23 -27
View File
@@ -257,17 +257,13 @@ describe('builtin helpers', function () {
// Object property iteration order is undefined according to ECMA spec,
// so we need to check both possible orders
// @see http://stackoverflow.com/questions/280713/elements-order-in-a-for-in-loop
var actual = compileWithPartials(string, hash);
var actual = CompilerContext.compile(string)(hash);
var expected1 =
'<b>#1</b>. goodbye! 2. GOODBYE! cruel world!';
var expected2 =
'2. GOODBYE! <b>#1</b>. goodbye! cruel world!';
equals(
actual === expected1 || actual === expected2,
true,
'each with object argument iterates over the contents when not empty'
);
expect([expected1, expected2]).toContain(actual);
expectTemplate(string)
.withInput({
@@ -630,8 +626,8 @@ describe('builtin helpers', function () {
.withInput({ blah: 'whee' })
.withMessage('log should not display')
.toCompileTo('');
equals(1, levelArg, 'should call log with 1');
equals('whee', logArg, "should call log with 'whee'");
expect(levelArg).toBe(1);
expect(logArg).toBe('whee');
});
it('should call logger at data level', function () {
@@ -646,21 +642,21 @@ describe('builtin helpers', function () {
.withRuntimeOptions({ data: { level: '03' } })
.withCompileOptions({ data: true })
.toCompileTo('');
equals('03', levelArg);
equals('whee', logArg);
expect(levelArg).toBe('03');
expect(logArg).toBe('whee');
});
it('should output to info', function () {
var called;
console.info = function (info) {
equals('whee', info);
expect(info).toBe('whee');
called = true;
console.info = $info;
console.log = $log;
};
console.log = function (log) {
equals('whee', log);
expect(log).toBe('whee');
called = true;
console.info = $info;
console.log = $log;
@@ -669,14 +665,14 @@ describe('builtin helpers', function () {
expectTemplate('{{log blah}}')
.withInput({ blah: 'whee' })
.toCompileTo('');
equals(true, called);
expect(called).toBe(true);
});
it('should log at data level', function () {
var called;
console.error = function (log) {
equals('whee', log);
expect(log).toBe('whee');
called = true;
console.error = $error;
};
@@ -686,7 +682,7 @@ describe('builtin helpers', function () {
.withRuntimeOptions({ data: { level: '03' } })
.withCompileOptions({ data: true })
.toCompileTo('');
equals(true, called);
expect(called).toBe(true);
});
it('should handle missing logger', function () {
@@ -694,7 +690,7 @@ describe('builtin helpers', function () {
console.error = undefined;
console.log = function (log) {
equals('whee', log);
expect(log).toBe('whee');
called = true;
console.log = $log;
};
@@ -704,14 +700,14 @@ describe('builtin helpers', function () {
.withRuntimeOptions({ data: { level: '03' } })
.withCompileOptions({ data: true })
.toCompileTo('');
equals(true, called);
expect(called).toBe(true);
});
it('should handle string log levels', function () {
var called;
console.error = function (log) {
equals('whee', log);
expect(log).toBe('whee');
called = true;
};
@@ -720,7 +716,7 @@ describe('builtin helpers', function () {
.withRuntimeOptions({ data: { level: 'error' } })
.withCompileOptions({ data: true })
.toCompileTo('');
equals(true, called);
expect(called).toBe(true);
called = false;
@@ -729,21 +725,21 @@ describe('builtin helpers', function () {
.withRuntimeOptions({ data: { level: 'ERROR' } })
.withCompileOptions({ data: true })
.toCompileTo('');
equals(true, called);
expect(called).toBe(true);
});
it('should handle hash log levels', function () {
var called;
console.error = function (log) {
equals('whee', log);
expect(log).toBe('whee');
called = true;
};
expectTemplate('{{log blah level="error"}}')
.withInput({ blah: 'whee' })
.toCompileTo('');
equals(true, called);
expect(called).toBe(true);
});
it('should handle hash log levels', function () {
@@ -761,16 +757,16 @@ describe('builtin helpers', function () {
expectTemplate('{{log blah level="debug"}}')
.withInput({ blah: 'whee' })
.toCompileTo('');
equals(false, called);
expect(called).toBe(false);
});
it('should pass multiple log arguments', function () {
var called;
console.info = console.log = function (log1, log2, log3) {
equals('whee', log1);
equals('foo', log2);
equals(1, log3);
expect(log1).toBe('whee');
expect(log2).toBe('foo');
expect(log3).toBe(1);
called = true;
console.log = $log;
};
@@ -778,7 +774,7 @@ describe('builtin helpers', function () {
expectTemplate('{{log blah "foo" 1}}')
.withInput({ blah: 'whee' })
.toCompileTo('');
equals(true, called);
expect(called).toBe(true);
});
it('should pass zero log arguments', function () {
+55 -100
View File
@@ -10,69 +10,56 @@ describe('compiler', function () {
}
it('should treat as equal', function () {
equal(compile('foo').equals(compile('foo')), true);
equal(compile('{{foo}}').equals(compile('{{foo}}')), true);
equal(compile('{{foo.bar}}').equals(compile('{{foo.bar}}')), true);
equal(
expect(compile('foo').equals(compile('foo'))).toBe(true);
expect(compile('{{foo}}').equals(compile('{{foo}}'))).toBe(true);
expect(compile('{{foo.bar}}').equals(compile('{{foo.bar}}'))).toBe(true);
expect(
compile('{{foo.bar baz "foo" true false bat=1}}').equals(
compile('{{foo.bar baz "foo" true false bat=1}}')
),
true
);
equal(
)
).toBe(true);
expect(
compile('{{foo.bar (baz bat=1)}}').equals(
compile('{{foo.bar (baz bat=1)}}')
),
true
);
equal(
compile('{{#foo}} {{/foo}}').equals(compile('{{#foo}} {{/foo}}')),
true
);
)
).toBe(true);
expect(
compile('{{#foo}} {{/foo}}').equals(compile('{{#foo}} {{/foo}}'))
).toBe(true);
});
it('should treat as not equal', function () {
equal(compile('foo').equals(compile('bar')), false);
equal(compile('{{foo}}').equals(compile('{{bar}}')), false);
equal(compile('{{foo.bar}}').equals(compile('{{bar.bar}}')), false);
equal(
expect(compile('foo').equals(compile('bar'))).toBe(false);
expect(compile('{{foo}}').equals(compile('{{bar}}'))).toBe(false);
expect(compile('{{foo.bar}}').equals(compile('{{bar.bar}}'))).toBe(false);
expect(
compile('{{foo.bar baz bat=1}}').equals(
compile('{{foo.bar bar bat=1}}')
),
false
);
equal(
)
).toBe(false);
expect(
compile('{{foo.bar (baz bat=1)}}').equals(
compile('{{foo.bar (bar bat=1)}}')
),
false
);
equal(
compile('{{#foo}} {{/foo}}').equals(compile('{{#bar}} {{/bar}}')),
false
);
equal(
compile('{{#foo}} {{/foo}}').equals(
compile('{{#foo}} {{foo}}{{/foo}}')
),
false
);
)
).toBe(false);
expect(
compile('{{#foo}} {{/foo}}').equals(compile('{{#bar}} {{/bar}}'))
).toBe(false);
expect(
compile('{{#foo}} {{/foo}}').equals(compile('{{#foo}} {{foo}}{{/foo}}'))
).toBe(false);
});
});
describe('#compile', function () {
it('should fail with invalid input', function () {
shouldThrow(
function () {
expect(function () {
Handlebars.compile(null);
},
Error,
}).toThrow(
'You must pass a string or Handlebars AST to Handlebars.compile. You passed null'
);
shouldThrow(
function () {
expect(function () {
Handlebars.compile({});
},
Error,
}).toThrow(
'You must pass a string or Handlebars AST to Handlebars.compile. You passed [object Object]'
);
});
@@ -80,71 +67,52 @@ describe('compiler', function () {
it('should include the location in the error (row and column)', function () {
try {
Handlebars.compile(' \n {{#if}}\n{{/def}}')();
equal(
true,
false,
'Statement must throw exception. This line should not be executed.'
);
expect.unreachable('Statement must throw exception');
} catch (err) {
equal(
err.message,
"if doesn't match def - 2:5",
'Checking error message'
);
expect(err.message).toBe("if doesn't match def - 2:5");
if (Object.getOwnPropertyDescriptor(err, 'column').writable) {
// In Safari 8, the column-property is read-only. This means that even if it is set with defineProperty,
// its value won't change (https://github.com/jquery/esprima/issues/1290#issuecomment-132455482)
// Since this was neither working in Handlebars 3 nor in 4.0.5, we only check the column for other browsers.
equal(err.column, 5, 'Checking error column');
expect(err.column).toBe(5);
}
equal(err.lineNumber, 2, 'Checking error row');
expect(err.lineNumber).toBe(2);
}
});
it('should include the location as enumerable property', function () {
try {
Handlebars.compile(' \n {{#if}}\n{{/def}}')();
equal(
true,
false,
'Statement must throw exception. This line should not be executed.'
);
expect.unreachable('Statement must throw exception');
} catch (err) {
equal(
Object.prototype.propertyIsEnumerable.call(err, 'column'),
true,
'Checking error column'
expect(Object.prototype.propertyIsEnumerable.call(err, 'column')).toBe(
true
);
}
});
it('can utilize AST instance', function () {
equal(
expect(
Handlebars.compile({
type: 'Program',
body: [{ type: 'ContentStatement', value: 'Hello' }],
})(),
'Hello'
);
})()
).toBe('Hello');
});
it('can pass through an empty string', function () {
equal(Handlebars.compile('')(), '');
expect(Handlebars.compile('')()).toBe('');
});
it('throws on desupported options', function () {
shouldThrow(
function () {
expect(function () {
Handlebars.compile('Dudes', { trackIds: true });
},
Error,
}).toThrow(
'TrackIds and stringParams are no longer supported. See Github #1145'
);
shouldThrow(
function () {
expect(function () {
Handlebars.compile('Dudes', { stringParams: true });
},
Error,
}).toThrow(
'TrackIds and stringParams are no longer supported. See Github #1145'
);
});
@@ -152,54 +120,41 @@ describe('compiler', function () {
it('should not modify the options.data property(GH-1327)', function () {
var options = { data: [{ a: 'foo' }, { a: 'bar' }] };
Handlebars.compile('{{#each data}}{{@index}}:{{a}} {{/each}}', options)();
equal(
JSON.stringify(options, 0, 2),
JSON.stringify({ data: [{ a: 'foo' }, { a: 'bar' }] }, 0, 2)
);
expect(options).toStrictEqual({ data: [{ a: 'foo' }, { a: 'bar' }] });
});
it('should not modify the options.knownHelpers property(GH-1327)', function () {
var options = { knownHelpers: {} };
Handlebars.compile('{{#each data}}{{@index}}:{{a}} {{/each}}', options)();
equal(
JSON.stringify(options, 0, 2),
JSON.stringify({ knownHelpers: {} }, 0, 2)
);
expect(options).toStrictEqual({ knownHelpers: {} });
});
});
describe('#precompile', function () {
it('should fail with invalid input', function () {
shouldThrow(
function () {
expect(function () {
Handlebars.precompile(null);
},
Error,
}).toThrow(
'You must pass a string or Handlebars AST to Handlebars.compile. You passed null'
);
shouldThrow(
function () {
expect(function () {
Handlebars.precompile({});
},
Error,
}).toThrow(
'You must pass a string or Handlebars AST to Handlebars.compile. You passed [object Object]'
);
});
it('can utilize AST instance', function () {
equal(
/return "Hello"/.test(
expect(
Handlebars.precompile({
type: 'Program',
body: [{ type: 'ContentStatement', value: 'Hello' }],
})
),
true
);
).toMatch(/return "Hello"/);
});
it('can pass through an empty string', function () {
equal(/return ""/.test(Handlebars.precompile('')), true);
expect(Handlebars.precompile('')).toMatch(/return ""/);
});
});
});
-91
View File
@@ -1,96 +1,5 @@
var global = globalThis;
/**
* @deprecated Use "expectTemplate(template)...toCompileTo(output)" instead
*/
global.shouldCompileTo = function (string, hashOrArray, expected, message) {
shouldCompileToWithPartials(string, hashOrArray, false, expected, message);
};
/**
* @deprecated Use "expectTemplate(template)...toCompileTo(output)" instead
*/
global.shouldCompileToWithPartials = function shouldCompileToWithPartials(
string,
hashOrArray,
partials,
expected,
message // eslint-disable-line no-unused-vars
) {
var result = compileWithPartials(string, hashOrArray, partials);
expect(result).toBe(expected);
};
/**
* @deprecated Use "expectTemplate(template)...toCompileTo(output)" instead
*/
global.compileWithPartials = function (string, hashOrArray, partials) {
var template, ary, options;
if (hashOrArray && hashOrArray.hash) {
ary = [hashOrArray.hash, hashOrArray];
delete hashOrArray.hash;
} else if (Object.prototype.toString.call(hashOrArray) === '[object Array]') {
ary = [];
ary.push(hashOrArray[0]); // input
ary.push({ helpers: hashOrArray[1], partials: hashOrArray[2] });
options =
typeof hashOrArray[3] === 'object'
? hashOrArray[3]
: { compat: hashOrArray[3] };
if (hashOrArray[4] != null) {
options.data = !!hashOrArray[4];
ary[1].data = hashOrArray[4];
}
} else {
ary = [hashOrArray];
}
template = CompilerContext[partials ? 'compileWithPartial' : 'compile'](
string,
options
);
return template.apply(this, ary);
};
/**
* @deprecated Use vitest's expect API instead
*/
// eslint-disable-next-line no-unused-vars
global.equals = global.equal = function equals(a, b, msg) {
expect(a).toBe(b);
};
/**
* @deprecated Use vitest's expect API instead
*/
global.shouldThrow = function (callback, type, msg) {
var failed;
try {
callback();
failed = true;
} catch (caught) {
if (type && !(caught instanceof type)) {
throw new Error('Type failure: ' + caught);
}
if (
msg &&
!(msg.test ? msg.test(caught.message) : msg === caught.message)
) {
throw new Error(
'Throw mismatch: Expected ' +
caught.message +
' to match ' +
msg +
'\n\n' +
caught.stack
);
}
}
if (failed) {
throw new Error('It failed to throw');
}
};
global.expectTemplate = function (templateAsString) {
return new HandlebarsTestBench(templateAsString);
};
+7 -11
View File
@@ -392,7 +392,7 @@ describe('helpers', function () {
return 'fail';
});
handlebarsEnv.unregisterHelper('foo');
equals(handlebarsEnv.helpers.foo, undefined);
expect(handlebarsEnv.helpers.foo).toBeUndefined();
});
it('allows multiple globals', function () {
@@ -417,8 +417,7 @@ describe('helpers', function () {
});
it('fails with multiple and args', function () {
shouldThrow(
function () {
expect(function () {
handlebarsEnv.registerHelper(
{
world: function () {
@@ -430,10 +429,7 @@ describe('helpers', function () {
},
{}
);
},
Error,
'Arg not supported with multiple helpers'
);
}).toThrow('Arg not supported with multiple helpers');
});
});
@@ -920,7 +916,7 @@ describe('helpers', function () {
expectTemplate('{{#goodbyes as |value|}}{{value}}{{/goodbyes}}{{value}}')
.withInput({ value: 'foo' })
.withHelper('goodbyes', function (options) {
equals(options.fn.blockParams, 1);
expect(options.fn.blockParams).toBe(1);
return options.fn({ value: 'bar' }, { blockParams: [1, 2] });
})
.toCompileTo('1foo');
@@ -932,7 +928,7 @@ describe('helpers', function () {
return 'foo';
})
.withHelper('goodbyes', function (options) {
equals(options.fn.blockParams, 1);
expect(options.fn.blockParams).toBe(1);
return options.fn({}, { blockParams: [1, 2] });
})
.toCompileTo('1foo');
@@ -947,7 +943,7 @@ describe('helpers', function () {
return 'foo';
})
.withHelper('goodbyes', function (options) {
equals(options.fn.blockParams, 1);
expect(options.fn.blockParams).toBe(1);
return options.fn(this, { blockParams: [1, 2] });
})
.toCompileTo('barfoo');
@@ -977,7 +973,7 @@ describe('helpers', function () {
)
.withInput({ value: 'foo' })
.withHelper('goodbyes', function (options) {
equals(options.fn.blockParams, 1);
expect(options.fn.blockParams).toBe(1);
return options.fn({ value: 'bar' }, { blockParams: [1, 2] });
})
.toCompileTo('1foo');
+4 -6
View File
@@ -164,12 +164,10 @@ describe('partials', function () {
});
it('registering undefined partial throws an exception', function () {
shouldThrow(
function () {
expect(function () {
var undef;
handlebarsEnv.registerPartial('undefined_test', undef);
},
Handlebars.Exception,
}).toThrow(
'Attempting to register a partial called "undefined_test" as undefined'
);
});
@@ -231,7 +229,7 @@ describe('partials', function () {
.toCompileTo('Dudes: Jeepers Creepers');
handlebarsEnv.unregisterPartial('globalTest');
equals(handlebarsEnv.partials.globalTest, undefined);
expect(handlebarsEnv.partials.globalTest).toBeUndefined();
});
it('Multiple partial registration', function () {
@@ -556,7 +554,7 @@ describe('partials', function () {
var env = Handlebars.create();
env.registerPartial('partial', '{{foo}}');
var template = env.compile('{{foo}} {{> partial}}', { noEscape: true });
equal(template({ foo: '<' }), '< <');
expect(template({ foo: '<' })).toBe('< <');
}
});
+57 -82
View File
@@ -85,33 +85,24 @@ describe('precompiler', function () {
it('should output version', function () {
Precompiler.cli({ templates: [], version: true });
equals(log, Handlebars.VERSION);
expect(log).toBe(Handlebars.VERSION);
});
it('should throw if lacking templates', function () {
shouldThrow(
function () {
expect(function () {
Precompiler.cli({ templates: [] });
},
Handlebars.Exception,
'Must define at least one template or directory.'
);
}).toThrow('Must define at least one template or directory.');
});
it('should handle empty/filtered directories', function () {
Precompiler.cli({ hasDirectory: true, templates: [] });
// Success is not throwing
});
it('should throw when combining simple and minimized', function () {
shouldThrow(
function () {
expect(function () {
Precompiler.cli({ templates: [__dirname], simple: true, min: true });
},
Handlebars.Exception,
'Unable to minimize simple output'
);
}).toThrow('Unable to minimize simple output');
});
it('should throw when combining simple and multiple templates', function () {
shouldThrow(
function () {
expect(function () {
Precompiler.cli({
templates: [
__dirname + '/artifacts/empty.handlebars',
@@ -119,28 +110,17 @@ describe('precompiler', function () {
],
simple: true,
});
},
Handlebars.Exception,
'Unable to output multiple templates in simple mode'
);
}).toThrow('Unable to output multiple templates in simple mode');
});
it('should throw when missing name', function () {
shouldThrow(
function () {
expect(function () {
Precompiler.cli({ templates: [{ source: '' }], amd: true });
},
Handlebars.Exception,
'Name missing for template'
);
}).toThrow('Name missing for template');
});
it('should throw when combining simple and directories', function () {
shouldThrow(
function () {
expect(function () {
Precompiler.cli({ hasDirectory: true, templates: [1], simple: true });
},
Handlebars.Exception,
'Unable to output multiple templates in simple mode'
);
}).toThrow('Unable to output multiple templates in simple mode');
});
it('should output simple templates', function () {
@@ -148,21 +128,21 @@ describe('precompiler', function () {
return 'simple';
};
Precompiler.cli({ templates: [emptyTemplate], simple: true });
equal(log, 'simple\n');
expect(log).toBe('simple\n');
});
it('should default to simple templates', function () {
Handlebars.precompile = function () {
return 'simple';
};
Precompiler.cli({ templates: [{ source: '' }] });
equal(log, 'simple\n');
expect(log).toBe('simple\n');
});
it('should output amd templates', function () {
Handlebars.precompile = function () {
return 'amd';
};
Precompiler.cli({ templates: [emptyTemplate], amd: true });
equal(/template\(amd\)/.test(log), true);
expect(log).toMatch(/template\(amd\)/);
});
it('should output multiple amd', function () {
Handlebars.precompile = function () {
@@ -173,17 +153,17 @@ describe('precompiler', function () {
amd: true,
namespace: 'foo',
});
equal(/templates = foo = foo \|\|/.test(log), true);
equal(/return templates/.test(log), true);
equal(/template\(amd\)/.test(log), true);
expect(log).toMatch(/templates = foo = foo \|\|/);
expect(log).toMatch(/return templates/);
expect(log).toMatch(/template\(amd\)/);
});
it('should output amd partials', function () {
Handlebars.precompile = function () {
return 'amd';
};
Precompiler.cli({ templates: [emptyTemplate], amd: true, partial: true });
equal(/return Handlebars\.partials\['empty'\]/.test(log), true);
equal(/template\(amd\)/.test(log), true);
expect(log).toMatch(/return Handlebars\.partials\['empty'\]/);
expect(log).toMatch(/template\(amd\)/);
});
it('should output multiple amd partials', function () {
Handlebars.precompile = function () {
@@ -194,33 +174,33 @@ describe('precompiler', function () {
amd: true,
partial: true,
});
equal(/return Handlebars\.partials\[/.test(log), false);
equal(/template\(amd\)/.test(log), true);
expect(log).not.toMatch(/return Handlebars\.partials\[/);
expect(log).toMatch(/template\(amd\)/);
});
it('should output commonjs templates', function () {
Handlebars.precompile = function () {
return 'commonjs';
};
Precompiler.cli({ templates: [emptyTemplate], commonjs: true });
equal(/template\(commonjs\)/.test(log), true);
expect(log).toMatch(/template\(commonjs\)/);
});
it('should set data flag', function () {
Handlebars.precompile = function (data, options) {
equal(options.data, true);
expect(options.data).toBe(true);
return 'simple';
};
Precompiler.cli({ templates: [emptyTemplate], simple: true, data: true });
equal(log, 'simple\n');
expect(log).toBe('simple\n');
});
it('should set known helpers', function () {
Handlebars.precompile = function (data, options) {
equal(options.knownHelpers.foo, true);
expect(options.knownHelpers.foo).toBe(true);
return 'simple';
};
Precompiler.cli({ templates: [emptyTemplate], simple: true, known: 'foo' });
equal(log, 'simple\n');
expect(log).toBe('simple\n');
});
it('should output to file system', function () {
Handlebars.precompile = function () {
@@ -231,9 +211,9 @@ describe('precompiler', function () {
simple: true,
output: 'file!',
});
equal(file, 'file!');
equal(content, 'simple\n');
equal(log, '');
expect(file).toBe('file!');
expect(content).toBe('simple\n');
expect(log).toBe('');
});
it('should output minimized templates', function () {
@@ -244,7 +224,7 @@ describe('precompiler', function () {
return { code: 'min' };
};
Precompiler.cli({ templates: [emptyTemplate], min: true });
equal(log, 'min');
expect(log).toBe('min');
});
it('should omit minimization gracefully, if uglify-js is missing', function () {
@@ -256,33 +236,29 @@ describe('precompiler', function () {
return 'amd';
};
Precompiler.cli({ templates: [emptyTemplate], min: true });
equal(/template\(amd\)/.test(log), true);
equal(/\n/.test(log), true);
equal(/Code minimization is disabled/.test(errorLog), true);
expect(log).toMatch(/template\(amd\)/);
expect(log).toMatch(/\n/);
expect(errorLog).toMatch(/Code minimization is disabled/);
});
});
it('should fail on errors (other than missing module) while loading uglify-js', function () {
mockRequireUglify(new Error('Mock Error'), function () {
shouldThrow(
function () {
expect(function () {
var Precompiler = require('../dist/cjs/precompiler');
Handlebars.precompile = function () {
return 'amd';
};
Precompiler.cli({ templates: [emptyTemplate], min: true });
},
Error,
'Mock Error'
);
}).toThrow('Mock Error');
});
});
it('should output map', function () {
Precompiler.cli({ templates: [emptyTemplate], map: 'foo.js.map' });
equal(file, 'foo.js.map');
equal(log.match(/sourceMappingURL=/g).length, 1);
expect(file).toBe('foo.js.map');
expect(log.match(/sourceMappingURL=/g).length).toBe(1);
});
it('should output map', function () {
@@ -292,8 +268,8 @@ describe('precompiler', function () {
map: 'foo.js.map',
});
equal(file, 'foo.js.map');
equal(log.match(/sourceMappingURL=/g).length, 1);
expect(file).toBe('foo.js.map');
expect(log.match(/sourceMappingURL=/g).length).toBe(1);
});
describe('#loadTemplates', function () {
@@ -315,7 +291,7 @@ describe('precompiler', function () {
await loadTemplatesAsync({ files: ['foo'] });
throw new Error('should have thrown');
} catch (err) {
equal(err.message, 'Unable to open template file "foo"');
expect(err.message).toBe('Unable to open template file "foo"');
}
});
it('should enumerate directories by extension', async function () {
@@ -323,18 +299,18 @@ describe('precompiler', function () {
files: [__dirname + '/artifacts'],
extension: 'hbs',
});
equal(opts.templates.length, 2);
equal(opts.templates[0].name, 'example_2');
expect(opts.templates.length).toBe(2);
expect(opts.templates[0].name).toBe('example_2');
});
it('should enumerate all templates by extension', async function () {
var opts = await loadTemplatesAsync({
files: [__dirname + '/artifacts'],
extension: 'handlebars',
});
equal(opts.templates.length, 5);
equal(opts.templates[0].name, 'bom');
equal(opts.templates[1].name, 'empty');
equal(opts.templates[2].name, 'example_1');
expect(opts.templates.length).toBe(5);
expect(opts.templates[0].name).toBe('bom');
expect(opts.templates[1].name).toBe('empty');
expect(opts.templates[2].name).toBe('example_1');
});
it('should handle regular expression characters in extensions', async function () {
await loadTemplatesAsync({
@@ -349,7 +325,7 @@ describe('precompiler', function () {
extension: 'handlebars',
bom: true,
});
equal(opts.templates[0].source, 'a');
expect(opts.templates[0].source).toBe('a');
});
it('should handle different root', async function () {
@@ -358,23 +334,23 @@ describe('precompiler', function () {
simple: true,
root: 'foo/',
});
equal(opts.templates[0].name, __dirname + '/artifacts/empty');
expect(opts.templates[0].name).toBe(__dirname + '/artifacts/empty');
});
it('should accept string inputs', async function () {
var opts = await loadTemplatesAsync({ string: '' });
equal(opts.templates[0].name, undefined);
equal(opts.templates[0].source, '');
expect(opts.templates[0].name).toBeUndefined();
expect(opts.templates[0].source).toBe('');
});
it('should accept string array inputs', async function () {
var opts = await loadTemplatesAsync({
string: ['', 'bar'],
name: ['beep', 'boop'],
});
equal(opts.templates[0].name, 'beep');
equal(opts.templates[0].source, '');
equal(opts.templates[1].name, 'boop');
equal(opts.templates[1].source, 'bar');
expect(opts.templates[0].name).toBe('beep');
expect(opts.templates[0].source).toBe('');
expect(opts.templates[1].name).toBe('boop');
expect(opts.templates[1].source).toBe('bar');
});
it('should accept stdin input', async function () {
var stdin = require('mock-stdin').stdin();
@@ -383,15 +359,14 @@ describe('precompiler', function () {
stdin.send('o');
stdin.end();
var opts = await promise;
equal(opts.templates[0].source, 'foo');
expect(opts.templates[0].source).toBe('foo');
});
it('error on name missing', async function () {
try {
await loadTemplatesAsync({ string: ['', 'bar'] });
throw new Error('should have thrown');
} catch (err) {
equal(
err.message,
expect(err.message).toBe(
'Number of names did not match the number of string inputs'
);
}
@@ -399,7 +374,7 @@ describe('precompiler', function () {
it('should complete when no args are passed', async function () {
var opts = await loadTemplatesAsync({});
equal(opts.templates.length, 0);
expect(opts.templates.length).toBe(0);
});
});
});
+7 -8
View File
@@ -337,7 +337,10 @@ describe('Regressions', function () {
},
};
shouldCompileTo('{{helpa length="foo"}}', [obj, helpers], 'foo');
expectTemplate('{{helpa length="foo"}}')
.withInput(obj)
.withHelpers(helpers)
.toCompileTo('foo');
});
it('GH-1319: "unless" breaks when "each" value equals "null"', function () {
@@ -373,20 +376,16 @@ describe('Regressions', function () {
var result = newHandlebarsInstance.templates['test.hbs']({
name: 'yehuda',
});
equals(result.trim(), 'YEHUDA');
expect(result.trim()).toBe('YEHUDA');
});
it('should call "helperMissing" if a helper is missing', function () {
var newHandlebarsInstance = Handlebars.create();
shouldThrow(
function () {
expect(function () {
registerTemplate(newHandlebarsInstance, compiledTemplateVersion7());
newHandlebarsInstance.templates['test.hbs']({});
},
Handlebars.Exception,
'Missing helper: "loud"'
);
}).toThrow('Missing helper: "loud"');
});
it('should pass "options.lookupProperty" to "lookup"-helper, even with old templates', function () {
+4 -4
View File
@@ -2,22 +2,22 @@ if (typeof require !== 'undefined' && require.extensions['.handlebars']) {
describe('Require', function () {
it('Load .handlebars files with require()', function () {
var template = require('./artifacts/example_1');
equal(template, require('./artifacts/example_1.handlebars'));
expect(template).toBe(require('./artifacts/example_1.handlebars'));
var expected = 'foo\n';
var result = template({ foo: 'foo' });
equal(result, expected);
expect(result).toBe(expected);
});
it('Load .hbs files with require()', function () {
var template = require('./artifacts/example_2');
equal(template, require('./artifacts/example_2.hbs'));
expect(template).toBe(require('./artifacts/example_2.hbs'));
var expected = 'Hello, World!\n';
var result = template({ name: 'World' });
equal(result, expected);
expect(result).toBe(expected);
});
});
}
+14 -32
View File
@@ -1,56 +1,38 @@
describe('runtime', function () {
describe('#template', function () {
it('should throw on invalid templates', function () {
shouldThrow(
function () {
expect(function () {
Handlebars.template({});
},
Error,
'Unknown template object: object'
);
shouldThrow(
function () {
}).toThrow('Unknown template object: object');
expect(function () {
Handlebars.template();
},
Error,
'Unknown template object: undefined'
);
shouldThrow(
function () {
}).toThrow('Unknown template object: undefined');
expect(function () {
Handlebars.template('');
},
Error,
'Unknown template object: string'
);
}).toThrow('Unknown template object: string');
});
it('should throw on version mismatch', function () {
shouldThrow(
function () {
expect(function () {
Handlebars.template({
main: {},
compiler: [Handlebars.COMPILER_REVISION + 1],
});
},
Error,
}).toThrow(
/Template was precompiled with a newer version of Handlebars than the current runtime/
);
shouldThrow(
function () {
expect(function () {
Handlebars.template({
main: {},
compiler: [Handlebars.LAST_COMPATIBLE_COMPILER_REVISION - 1],
});
},
Error,
}).toThrow(
/Template was precompiled with an older version of Handlebars than the current runtime/
);
shouldThrow(
function () {
expect(function () {
Handlebars.template({
main: {},
});
},
Error,
}).toThrow(
/Template was precompiled with an older version of Handlebars than the current runtime/
);
});
@@ -63,11 +45,11 @@ describe('runtime', function () {
}
var reset = Handlebars;
Handlebars.noConflict();
equal(Handlebars, 'no-conflict');
expect(Handlebars).toBe('no-conflict');
Handlebars = 'really, none';
reset.noConflict();
equal(Handlebars, 'really, none');
expect(Handlebars).toBe('really, none');
Handlebars = reset;
});
+1 -1
View File
@@ -96,7 +96,7 @@ describe('security issues', function () {
},
{ allowCallsToHelperMissing: true }
);
equals(functionCalls.length, 1);
expect(functionCalls.length).toBe(1);
});
it('should not throw an exception when calling "{{#blockHelperMissing .}}{{/blockHelperMissing}}"', function () {
+8 -4
View File
@@ -18,8 +18,12 @@ describe('source-map', function () {
srcName: 'src.hbs',
});
equal(!!template.code, true);
equal(!!template.map, !CompilerContext.browser);
expect(template.code).toBeTruthy();
if (CompilerContext.browser) {
expect(template.map).toBeFalsy();
} else {
expect(template.map).toBeTruthy();
}
});
it('should map source properly', function () {
var templateSource =
@@ -37,8 +41,8 @@ describe('source-map', function () {
source = grepLine(' b', srcLines);
var mapped = consumer.originalPositionFor(generated);
equal(mapped.line, source.line);
equal(mapped.column, source.column);
expect(mapped.line).toBe(source.line);
expect(mapped.column).toBe(source.column);
}
});
});
+6 -6
View File
@@ -92,8 +92,8 @@ describe('strict', function () {
})
.withHelpers({
helper: function (options) {
equals('value' in options.hash, true);
equals(options.hash.value, undefined);
expect(options.hash).toHaveProperty('value');
expect(options.hash.value).toBeUndefined();
return 'success';
},
})
@@ -113,10 +113,10 @@ describe('strict', function () {
});
template({});
} catch (error) {
equals(error.lineNumber, 4);
equals(error.endLineNumber, 4);
equals(error.column, 5);
equals(error.endColumn, 10);
expect(error.lineNumber).toBe(4);
expect(error.endLineNumber).toBe(4);
expect(error.column).toBe(5);
expect(error.endColumn).toBe(10);
}
});
});
+3 -3
View File
@@ -1,11 +1,11 @@
function shouldMatchTokens(result, tokens) {
for (var index = 0; index < result.length; index++) {
equals(result[index].name, tokens[index]);
expect(result[index].name).toBe(tokens[index]);
}
}
function shouldBeToken(result, name, text) {
equals(result.name, name);
equals(result.text, text);
expect(result.name).toBe(name);
expect(result.text).toBe(text);
}
describe('Tokenizer', function () {
+23 -28
View File
@@ -5,11 +5,7 @@ describe('utils', function () {
if (!(safe instanceof Handlebars.SafeString)) {
throw new Error('Must be instance of SafeString');
}
equals(
safe.toString(),
'testing 1, 2, 3',
'SafeString is equivalent to its underlying string'
);
expect(safe.toString()).toBe('testing 1, 2, 3');
});
it('it should not escape SafeString properties', function () {
@@ -23,51 +19,50 @@ describe('utils', function () {
describe('#escapeExpression', function () {
it('should escape html', function () {
equals(
Handlebars.Utils.escapeExpression('foo<&"\'>'),
expect(Handlebars.Utils.escapeExpression('foo<&"\'>')).toBe(
'foo&lt;&amp;&quot;&#x27;&gt;'
);
equals(Handlebars.Utils.escapeExpression('foo='), 'foo&#x3D;');
expect(Handlebars.Utils.escapeExpression('foo=')).toBe('foo&#x3D;');
});
it('should not escape SafeString', function () {
var string = new Handlebars.SafeString('foo<&"\'>');
equals(Handlebars.Utils.escapeExpression(string), 'foo<&"\'>');
expect(Handlebars.Utils.escapeExpression(string)).toBe('foo<&"\'>');
var obj = {
toHTML: function () {
return 'foo<&"\'>';
},
};
equals(Handlebars.Utils.escapeExpression(obj), 'foo<&"\'>');
expect(Handlebars.Utils.escapeExpression(obj)).toBe('foo<&"\'>');
});
it('should handle falsy', function () {
equals(Handlebars.Utils.escapeExpression(''), '');
equals(Handlebars.Utils.escapeExpression(undefined), '');
equals(Handlebars.Utils.escapeExpression(null), '');
expect(Handlebars.Utils.escapeExpression('')).toBe('');
expect(Handlebars.Utils.escapeExpression(undefined)).toBe('');
expect(Handlebars.Utils.escapeExpression(null)).toBe('');
equals(Handlebars.Utils.escapeExpression(false), 'false');
equals(Handlebars.Utils.escapeExpression(0), '0');
expect(Handlebars.Utils.escapeExpression(false)).toBe('false');
expect(Handlebars.Utils.escapeExpression(0)).toBe('0');
});
it('should handle empty objects', function () {
equals(Handlebars.Utils.escapeExpression({}), {}.toString());
equals(Handlebars.Utils.escapeExpression([]), [].toString());
expect(Handlebars.Utils.escapeExpression({})).toBe({}.toString());
expect(Handlebars.Utils.escapeExpression([])).toBe([].toString());
});
});
describe('#isEmpty', function () {
it('should not be empty', function () {
equals(Handlebars.Utils.isEmpty(undefined), true);
equals(Handlebars.Utils.isEmpty(null), true);
equals(Handlebars.Utils.isEmpty(false), true);
equals(Handlebars.Utils.isEmpty(''), true);
equals(Handlebars.Utils.isEmpty([]), true);
expect(Handlebars.Utils.isEmpty(undefined)).toBe(true);
expect(Handlebars.Utils.isEmpty(null)).toBe(true);
expect(Handlebars.Utils.isEmpty(false)).toBe(true);
expect(Handlebars.Utils.isEmpty('')).toBe(true);
expect(Handlebars.Utils.isEmpty([])).toBe(true);
});
it('should be empty', function () {
equals(Handlebars.Utils.isEmpty(0), false);
equals(Handlebars.Utils.isEmpty([1]), false);
equals(Handlebars.Utils.isEmpty('foo'), false);
equals(Handlebars.Utils.isEmpty({ bar: 1 }), false);
expect(Handlebars.Utils.isEmpty(0)).toBe(false);
expect(Handlebars.Utils.isEmpty([1])).toBe(false);
expect(Handlebars.Utils.isEmpty('foo')).toBe(false);
expect(Handlebars.Utils.isEmpty({ bar: 1 })).toBe(false);
});
});
@@ -82,8 +77,8 @@ describe('utils', function () {
Handlebars.Utils.extend(b, new A());
equals(b.a, 1);
equals(b.b, 2);
expect(b.a).toBe(1);
expect(b.b).toBe(2);
});
});