Compare commits

...

4 Commits

Author SHA1 Message Date
Nils Knappmeier b7aa22efc3 wip: only run "require"-test, if "require-extensions" exists
"require" does not mean "amd" in this case...
2020-06-02 00:11:10 +02:00
Nils Knappmeier 416d8d810a wip 2020-06-02 00:10:37 +02:00
Nils Knappmeier 6b1a4070c2 wip 2020-06-01 22:28:13 +02:00
Nils Knappmeier 55f65eaa2e backup 2020-05-31 23:38:23 +02:00
14 changed files with 1189 additions and 669 deletions
+1 -1
View File
@@ -60,7 +60,7 @@ module.exports = {
},
parserOptions: {
sourceType: 'module',
ecmaVersion: 6,
ecmaVersion: 2018,
ecmaFeatures: {}
}
};
+27 -4
View File
@@ -165,6 +165,29 @@ module.exports = function(grunt) {
}
}
},
karma: {
options: {
configFile: 'karma.conf.js'
},
saucelabs: {
build: process.env.TRAVIS_JOB_ID || 'non-travis',
configFile: 'karma-setup/default/karma.conf.js',
...require('./karma-setup/shared/saucelabs'),
singleRun: true
},
default: {
browsers: [],
configFile: 'karma-setup/default/karma.conf.js',
singleRun: false,
autoWatch: true
},
amd: {
configFile: 'karma-setup/amd/karma.conf.js',
browsers: [],
singleRun: false,
autoWatch: true
}
},
'saucelabs-mocha': {
all: {
options: {
@@ -178,8 +201,8 @@ module.exports = function(grunt) {
browsers: [
{ browserName: 'chrome' },
{ browserName: 'firefox', platform: 'Linux' },
// {browserName: 'safari', version: 9, platform: 'OS X 10.11'},
// {browserName: 'safari', version: 8, platform: 'OS X 10.10'},
{ browserName: 'safari', version: 9, platform: 'OS X 10.11' },
{ browserName: 'safari', version: 8, platform: 'OS X 10.10' },
{
browserName: 'internet explorer',
version: 11,
@@ -238,7 +261,7 @@ module.exports = function(grunt) {
grunt.loadNpmTasks('grunt-contrib-watch');
grunt.loadNpmTasks('grunt-babel');
grunt.loadNpmTasks('grunt-bg-shell');
grunt.loadNpmTasks('@knappi/grunt-saucelabs');
grunt.loadNpmTasks('grunt-karma');
grunt.loadNpmTasks('grunt-webpack');
grunt.task.loadTasks('tasks');
@@ -268,7 +291,7 @@ module.exports = function(grunt) {
grunt.registerTask('bench', ['metrics']);
if (process.env.SAUCE_ACCESS_KEY) {
grunt.registerTask('sauce', ['concat:tests', 'connect', 'saucelabs-mocha']);
grunt.registerTask('sauce', ['karma:saucelabs']);
} else {
grunt.registerTask('sauce', []);
}
+56
View File
@@ -0,0 +1,56 @@
{
"extends": [
"../.eslintrc.js"
],
"overrides": [
{
"extends": [
"plugin:es5/no-es2015",
"prettier"
],
"files": ["**/*.browser.js"],
"plugins": [
"es5"
],
"globals": {
"TODO: clean this up": true,
"CompilerContext": true,
"Handlebars": true,
"handlebarsEnv": true,
"shouldCompileTo": true,
"shouldCompileToWithPartials": true,
"shouldThrow": true,
"expectTemplate": true,
"compileWithPartials": true,
"console": true,
"require": true,
"suite": true,
"equal": true,
"equals": true,
"test": true,
"testBoth": true,
"raises": true,
"deepEqual": true,
"start": true,
"stop": true,
"ok": true,
"sinon": true,
"strictEqual": true,
"define": true,
"expect": true,
"chai": true
},
"env": {
"mocha": true
},
"rules": {
// Disabling for tests, for now.
"no-path-concat": "off",
"no-var": "off",
"dot-notation": "off"
}
},
]
}
+19
View File
@@ -0,0 +1,19 @@
module.exports = function(config) {
config.set({
basePath: '../..',
reporters: ['dots'],
frameworks: ['mocha', 'requirejs'],
browsers: ['Chrome'],
files: [
{ pattern: 'node_modules/sinon/pkg/sinon.js', included: false },
{ pattern: 'node_modules/chai/chai.js', included: false },
{ pattern: 'node_modules/dirty-chai/lib/dirty-chai.js', included: false },
{ pattern: 'dist/handlebars.amd.js', included: false },
'karma-setup/shared/*.browser.js',
'karma-setup/amd/*.browser.js',
'spec/vendor/json2.js',
'spec/env/common.js',
{ pattern: 'spec/*.js', included: false }
]
});
};
+38
View File
@@ -0,0 +1,38 @@
/* global requirejs */
var tests = Object.keys(window.__karma__.files).filter(function(file) {
return file.match(/^\/base\/spec\/[^/]*\.js/);
});
requirejs.config({
// Karma serves files from '/base'
baseUrl: '/base',
paths: {
handlebars: 'dist/handlebars.amd',
sinon: 'node_modules/sinon/pkg/sinon',
chai: 'node_modules/chai/chai',
dirtyChai: 'node_modules/dirty-chai/lib/dirty-chai'
},
// start test run, once Require.js is done
callback: function() {
require(['handlebars', 'chai', 'dirtyChai', 'sinon'], function(
Handlebars,
chai,
dirtyChai,
sinon
) {
window.Handlebars = Handlebars;
chai.use(dirtyChai);
window.expect = chai.expect;
window.sinon = sinon;
require(tests, function() {
window.__karma__.start();
});
});
}
});
@@ -0,0 +1 @@
window.expect = chai.expect;
+20
View File
@@ -0,0 +1,20 @@
module.exports = function(config) {
config.set({
basePath: '../..',
reporters: ['dots'],
frameworks: ['mocha'],
browsers: ['Chrome'],
files: [
'node_modules/sinon/pkg/sinon.js',
'node_modules/chai/chai.js',
'node_modules/dirty-chai/lib/dirty-chai.js',
'karma-setup/shared/*.browser.js',
'karma-setup/default/*.browser.js',
'spec/vendor/json2.js',
'spec/env/common.js',
'dist/handlebars.js',
'spec/*.js'
]
});
};
@@ -0,0 +1,22 @@
window.CompilerContext = {
compile: function(template, options) {
var templateSpec = handlebarsEnv.precompile(template, options);
return handlebarsEnv.template(safeEval(templateSpec));
},
compileWithPartial: function(template, options) {
return handlebarsEnv.compile(template, options);
}
};
function safeEval(templateSpec) {
try {
var ret;
// eslint-disable-next-line no-eval
eval('ret = ' + templateSpec);
return ret;
} catch (err) {
// eslint-disable-next-line no-console
console.error(templateSpec);
throw err;
}
}
+47
View File
@@ -0,0 +1,47 @@
// Example set of browsers to run on Sauce Labs
// Check out https://saucelabs.com/platforms for all browser/platform combos
const customLaunchers = {
sl_chrome: {
base: 'SauceLabs',
browserName: 'chrome'
},
sl_firefox: {
base: 'SauceLabs',
browserName: 'firefox',
platform: 'Linux'
},
sl_safari_9: {
base: 'SauceLabs',
browserName: 'safari',
version: 9,
platform: 'OS X 10.11'
},
sl_safari_8: {
base: 'SauceLabs',
browserName: 'safari',
version: 8,
platform: 'OS X 10.10'
},
sl_ie_10: {
base: 'SauceLabs',
browserName: 'internet explorer',
version: 10,
platform: 'Windows 8'
},
sl_ie_11: {
base: 'SauceLabs',
browserName: 'internet explorer',
platform: 'Windows 8.1',
version: '11'
}
};
const browsers = Object.keys(customLaunchers);
module.exports = {
customLaunchers,
browsers,
sauceLabs: {
testName: 'handlebars-unit-tests'
}
};
+914 -626
View File
File diff suppressed because it is too large Load Diff
+6
View File
@@ -58,9 +58,15 @@
"grunt-contrib-requirejs": "^1",
"grunt-contrib-uglify": "^1",
"grunt-contrib-watch": "^1.1.0",
"grunt-karma": "^4.0.0",
"grunt-webpack": "^1.0.8",
"husky": "^3.1.0",
"jison": "~0.3.0",
"karma": "^5.0.5",
"karma-chrome-launcher": "^3.1.0",
"karma-mocha": "^2.0.1",
"karma-requirejs": "^1.1.0",
"karma-sauce-launcher": "^4.1.4",
"lint-staged": "^9.5.0",
"mocha": "^5",
"mock-stdin": "^0.3.0",
+1 -2
View File
@@ -112,8 +112,7 @@
failedTests.push({
name: test.title,
result: false,
message: err.message,
stack: err.stack,
message: err.message, stack: err.stack,
titles: flattenTitles(test)
});
}
+5 -1
View File
@@ -1,4 +1,8 @@
if (typeof require !== 'undefined' && require.extensions['.handlebars']) {
if (
typeof require !== 'undefined' &&
require.extensions &&
require.extensions['.handlebars']
) {
describe('Require', function() {
it('Load .handlebars files with require()', function() {
var template = require('./artifacts/example_1');
+32 -35
View File
@@ -1,4 +1,15 @@
describe('security issues', function() {
var consoleErrorFake = null;
beforeEach(function() {
consoleErrorFake = sinon.fake();
sinon.replace(console, 'error', consoleErrorFake);
});
afterEach(function() {
sinon.restore();
});
describe('GH-1495: Prevent Remote Code Execution via constructor', function() {
it('should not allow constructors to be accessed', function() {
expectTemplate('{{lookup (lookup this "constructor") "name"}}')
@@ -88,17 +99,15 @@ describe('security issues', function() {
});
it('should not throw an exception when calling "{{blockHelperMissing "abc" .}}" ', function() {
var functionCalls = [];
var fakeFunction = sinon.fake();
var template = Handlebars.compile('{{blockHelperMissing "abc" .}}');
template(
{
fn: function() {
functionCalls.push('called');
}
fn: fakeFunction
},
{ allowCallsToHelperMissing: true }
);
equals(functionCalls.length, 1);
expect(fakeFunction.calledOnce).to.be.true();
});
it('should not throw an exception when calling "{{#blockHelperMissing .}}{{/blockHelperMissing}}"', function() {
@@ -185,20 +194,18 @@ describe('security issues', function() {
function checkProtoMethodAccess(compileOptions) {
it('should be prohibited by default and log a warning', function() {
var spy = sinon.spy(console, 'error');
expectTemplate('{{aMethod}}')
.withInput(new TestClass())
.withCompileOptions(compileOptions)
.toCompileTo('');
expect(spy.calledOnce).to.be.true();
expect(spy.args[0][0]).to.match(/Handlebars: Access has been denied/);
expect(consoleErrorFake.calledOnce).to.be.true();
expect(consoleErrorFake.args[0][0]).to.match(
/Handlebars: Access has been denied/
);
});
it('should only log the warning once', function() {
var spy = sinon.spy(console, 'error');
expectTemplate('{{aMethod}}')
.withInput(new TestClass())
.withCompileOptions(compileOptions)
@@ -209,13 +216,13 @@ describe('security issues', function() {
.withCompileOptions(compileOptions)
.toCompileTo('');
expect(spy.calledOnce).to.be.true();
expect(spy.args[0][0]).to.match(/Handlebars: Access has been denied/);
expect(consoleErrorFake.calledOnce).to.be.true();
expect(consoleErrorFake.args[0][0]).to.match(
/Handlebars: Access has been denied/
);
});
it('can be allowed, which disables the warning', function() {
var spy = sinon.spy(console, 'error');
expectTemplate('{{aMethod}}')
.withInput(new TestClass())
.withCompileOptions(compileOptions)
@@ -226,12 +233,10 @@ describe('security issues', function() {
})
.toCompileTo('returnValue');
expect(spy.callCount).to.equal(0);
expect(consoleErrorFake.callCount).to.equal(0);
});
it('can be turned on by default, which disables the warning', function() {
var spy = sinon.spy(console, 'error');
expectTemplate('{{aMethod}}')
.withInput(new TestClass())
.withCompileOptions(compileOptions)
@@ -240,12 +245,10 @@ describe('security issues', function() {
})
.toCompileTo('returnValue');
expect(spy.callCount).to.equal(0);
expect(consoleErrorFake.callCount).to.equal(0);
});
it('can be turned off by default, which disables the warning', function() {
var spy = sinon.spy(console, 'error');
expectTemplate('{{aMethod}}')
.withInput(new TestClass())
.withCompileOptions(compileOptions)
@@ -254,7 +257,7 @@ describe('security issues', function() {
})
.toCompileTo('');
expect(spy.callCount).to.equal(0);
expect(consoleErrorFake.callCount).to.equal(0);
});
it('can be turned off, if turned on by default', function() {
@@ -300,20 +303,18 @@ describe('security issues', function() {
function checkProtoPropertyAccess(compileOptions) {
it('should be prohibited by default and log a warning', function() {
var spy = sinon.spy(console, 'error');
expectTemplate('{{aProperty}}')
.withInput(new TestClass())
.withCompileOptions(compileOptions)
.toCompileTo('');
expect(spy.calledOnce).to.be.true();
expect(spy.args[0][0]).to.match(/Handlebars: Access has been denied/);
expect(consoleErrorFake.calledOnce).to.be.true();
expect(consoleErrorFake.args[0][0]).to.match(
/Handlebars: Access has been denied/
);
});
it('can be explicitly prohibited by default, which disables the warning', function() {
var spy = sinon.spy(console, 'error');
expectTemplate('{{aProperty}}')
.withInput(new TestClass())
.withCompileOptions(compileOptions)
@@ -322,12 +323,10 @@ describe('security issues', function() {
})
.toCompileTo('');
expect(spy.callCount).to.equal(0);
expect(consoleErrorFake.callCount).to.equal(0);
});
it('can be turned on, which disables the warning', function() {
var spy = sinon.spy(console, 'error');
expectTemplate('{{aProperty}}')
.withInput(new TestClass())
.withCompileOptions(compileOptions)
@@ -338,12 +337,10 @@ describe('security issues', function() {
})
.toCompileTo('propertyValue');
expect(spy.callCount).to.equal(0);
expect(consoleErrorFake.callCount).to.equal(0);
});
it('can be turned on by default, which disables the warning', function() {
var spy = sinon.spy(console, 'error');
expectTemplate('{{aProperty}}')
.withInput(new TestClass())
.withCompileOptions(compileOptions)
@@ -352,7 +349,7 @@ describe('security issues', function() {
})
.toCompileTo('propertyValue');
expect(spy.callCount).to.equal(0);
expect(consoleErrorFake.callCount).to.equal(0);
});
it('can be turned off, if turned on by default', function() {