Compare commits
4 Commits
fix-1838-2
...
karma
| Author | SHA1 | Date | |
|---|---|---|---|
| b7aa22efc3 | |||
| 416d8d810a | |||
| 6b1a4070c2 | |||
| 55f65eaa2e |
+1
-1
@@ -60,7 +60,7 @@ module.exports = {
|
||||
},
|
||||
parserOptions: {
|
||||
sourceType: 'module',
|
||||
ecmaVersion: 6,
|
||||
ecmaVersion: 2018,
|
||||
ecmaFeatures: {}
|
||||
}
|
||||
};
|
||||
|
||||
+27
-4
@@ -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', []);
|
||||
}
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
},
|
||||
]
|
||||
|
||||
}
|
||||
@@ -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 }
|
||||
]
|
||||
});
|
||||
};
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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'
|
||||
}
|
||||
};
|
||||
Generated
+914
-626
File diff suppressed because it is too large
Load Diff
@@ -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
@@ -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
@@ -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
@@ -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() {
|
||||
|
||||
Reference in New Issue
Block a user