commit
94325aea10
1
.gitignore
vendored
1
.gitignore
vendored
@ -26,3 +26,4 @@ dir.txt
|
|||||||
release/
|
release/
|
||||||
build/
|
build/
|
||||||
|
|
||||||
|
coverage/
|
17
.travis.yml
Normal file
17
.travis.yml
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
language: node_js
|
||||||
|
dist: trusty
|
||||||
|
addons:
|
||||||
|
chrome: stable
|
||||||
|
node_js:
|
||||||
|
- node
|
||||||
|
#addons:
|
||||||
|
# sauce_connect: true
|
||||||
|
sudo: false
|
||||||
|
cache:
|
||||||
|
directories:
|
||||||
|
- node_modules
|
||||||
|
script:
|
||||||
|
- npm run test:cov
|
||||||
|
#- npm run test:sauce
|
||||||
|
after_script:
|
||||||
|
- npm install coveralls && cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js && rm -rf ./coverage
|
125
karma.conf.base.js
Normal file
125
karma.conf.base.js
Normal file
@ -0,0 +1,125 @@
|
|||||||
|
/**
|
||||||
|
* @file karma自动化测试配置
|
||||||
|
* @author fe.xiaowu@gmail.com
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 源文件
|
||||||
|
*
|
||||||
|
* @type {Array}
|
||||||
|
*/
|
||||||
|
var sourceFileMap = [
|
||||||
|
'src/layui.js',
|
||||||
|
'src/lay/modules/jquery.js',
|
||||||
|
'src/lay/modules/carousel.js',
|
||||||
|
'src/lay/modules/code.js',
|
||||||
|
'src/lay/modules/element.js',
|
||||||
|
'src/lay/modules/flow.js',
|
||||||
|
'src/lay/modules/form.js',
|
||||||
|
'src/lay/modules/laydate.js',
|
||||||
|
'src/lay/modules/layedit.js',
|
||||||
|
'src/lay/modules/layer.js',
|
||||||
|
'src/lay/modules/laypage.js',
|
||||||
|
'src/lay/modules/laytpl.js',
|
||||||
|
'src/lay/modules/table.js',
|
||||||
|
'src/lay/modules/tree.js',
|
||||||
|
'src/lay/modules/upload.js',
|
||||||
|
'src/lay/modules/util.js',
|
||||||
|
'src/lay/modules/mobile/zepto.js',
|
||||||
|
'src/lay/modules/mobile/layer-mobile.js',
|
||||||
|
'src/lay/modules/mobile/upload-mobile.js'
|
||||||
|
];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 测试覆盖率文件, 要忽略 jquery.js、zepto.js
|
||||||
|
*
|
||||||
|
* @type {Object}
|
||||||
|
*/
|
||||||
|
var coverageFileMap = {};
|
||||||
|
sourceFileMap.filter(function (uri) {
|
||||||
|
return !/(jquery|zepto)\.js$/.test(uri);
|
||||||
|
}).forEach(function (uri) {
|
||||||
|
coverageFileMap[uri] = ['coverage'];
|
||||||
|
});
|
||||||
|
|
||||||
|
module.exports = function (config) {
|
||||||
|
return {
|
||||||
|
// base path that will be used to resolve all patterns (eg. files, exclude)
|
||||||
|
basePath: '',
|
||||||
|
|
||||||
|
// Important: 所有插件必须在此声明
|
||||||
|
plugins: ['karma-*'],
|
||||||
|
|
||||||
|
// frameworks to use
|
||||||
|
// available frameworks: https://npmjs.org/browse/keyword/karma-adapter
|
||||||
|
// Important: 下列数组中文件将『逆序载入』
|
||||||
|
frameworks: ['mocha', 'chai', 'chai-sinon'],
|
||||||
|
|
||||||
|
|
||||||
|
// list of files / patterns to load in the browser
|
||||||
|
files: sourceFileMap.concat('test/**/*.js'),
|
||||||
|
|
||||||
|
|
||||||
|
// list of files to exclude
|
||||||
|
exclude: [],
|
||||||
|
|
||||||
|
|
||||||
|
// preprocess matching files before serving them to the browser
|
||||||
|
// available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
|
||||||
|
preprocessors: coverageFileMap,
|
||||||
|
|
||||||
|
|
||||||
|
// test results reporter to use
|
||||||
|
// possible values: 'dots', 'progress'
|
||||||
|
// available reporters: https://npmjs.org/browse/keyword/karma-reporter
|
||||||
|
reporters: [
|
||||||
|
'mocha'
|
||||||
|
// 'coverage'
|
||||||
|
],
|
||||||
|
|
||||||
|
coverageReporter: {
|
||||||
|
// specify a common output directory
|
||||||
|
dir: '.',
|
||||||
|
reporters: [
|
||||||
|
// { type: 'html', subdir: 'report-html' },
|
||||||
|
{
|
||||||
|
type: 'lcov',
|
||||||
|
subdir: 'coverage'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'text-summary'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
// web server port
|
||||||
|
port: 9876,
|
||||||
|
|
||||||
|
|
||||||
|
// enable / disable colors in the output (reporters and logs)
|
||||||
|
colors: true,
|
||||||
|
|
||||||
|
|
||||||
|
// level of logging
|
||||||
|
// possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
|
||||||
|
// Note: 如果要调试Karma,请设置为DEBUG
|
||||||
|
logLevel: config.LOG_INFO,
|
||||||
|
|
||||||
|
// start these browsers
|
||||||
|
// available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
|
||||||
|
browsers: [
|
||||||
|
'PhantomJS'
|
||||||
|
],
|
||||||
|
|
||||||
|
|
||||||
|
// enable / disable watching file and executing tests whenever any file changes
|
||||||
|
// Note: 代码改动自动运行测试,需要singleRun为false
|
||||||
|
autoWatch: false,
|
||||||
|
|
||||||
|
// Continuous Integration mode
|
||||||
|
// if true, Karma captures browsers, runs the tests and exits
|
||||||
|
// 脚本调用请设为 true
|
||||||
|
singleRun: true
|
||||||
|
};
|
||||||
|
};
|
105
karma.conf.sauce.js
Normal file
105
karma.conf.sauce.js
Normal file
@ -0,0 +1,105 @@
|
|||||||
|
/**
|
||||||
|
* @file karma配置
|
||||||
|
* @author fe.xiaowu@gmail.com
|
||||||
|
*/
|
||||||
|
|
||||||
|
var base = require('./karma.conf.base.js');
|
||||||
|
|
||||||
|
var customLaunchers = {
|
||||||
|
// Safari
|
||||||
|
sl_ios_safari: {
|
||||||
|
base: 'SauceLabs',
|
||||||
|
browserName: 'Safari'
|
||||||
|
},
|
||||||
|
|
||||||
|
// 安卓浏览器
|
||||||
|
sl_android_4_4: {
|
||||||
|
base: 'SauceLabs',
|
||||||
|
browserName: 'android',
|
||||||
|
version: '4.4'
|
||||||
|
},
|
||||||
|
sl_android_5: {
|
||||||
|
base: 'SauceLabs',
|
||||||
|
browserName: 'android',
|
||||||
|
version: '5'
|
||||||
|
},
|
||||||
|
sl_android_6: {
|
||||||
|
base: 'SauceLabs',
|
||||||
|
browserName: 'android',
|
||||||
|
version: '6'
|
||||||
|
},
|
||||||
|
|
||||||
|
// chrome
|
||||||
|
sl_ios_chrome: {
|
||||||
|
base: 'SauceLabs',
|
||||||
|
browserName: 'chrome'
|
||||||
|
},
|
||||||
|
|
||||||
|
sl_ie_8: {
|
||||||
|
base: 'SauceLabs',
|
||||||
|
browserName: 'internet explorer',
|
||||||
|
version: '8'
|
||||||
|
},
|
||||||
|
sl_ie_9: {
|
||||||
|
base: 'SauceLabs',
|
||||||
|
browserName: 'internet explorer',
|
||||||
|
platform: 'Windows 7',
|
||||||
|
version: '9'
|
||||||
|
},
|
||||||
|
sl_ie_10: {
|
||||||
|
base: 'SauceLabs',
|
||||||
|
browserName: 'internet explorer',
|
||||||
|
platform: 'Windows 8',
|
||||||
|
version: '10'
|
||||||
|
},
|
||||||
|
sl_ie_11: {
|
||||||
|
base: 'SauceLabs',
|
||||||
|
browserName: 'internet explorer',
|
||||||
|
platform: 'Windows 8.1',
|
||||||
|
version: '11'
|
||||||
|
},
|
||||||
|
|
||||||
|
sl_firefox: {
|
||||||
|
base: 'SauceLabs',
|
||||||
|
browserName: 'firefox',
|
||||||
|
platform: 'Windows 7'
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 不支持本地运行
|
||||||
|
if (!process.env.TRAVIS) {
|
||||||
|
console.error('不支持本地运行, 请使用 npm run test!');
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 变量检查
|
||||||
|
if (!process.env.SAUCE_USERNAME || !process.env.SAUCE_ACCESS_KEY) {
|
||||||
|
console.error('---------------');
|
||||||
|
console.error('Make sure the SAUCE_USERNAME and SAUCE_ACCESS_KEY environment variables are set.');
|
||||||
|
console.error('---------------');
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = function (config) {
|
||||||
|
var options = Object.assign(base(config), {
|
||||||
|
reporters: ['mocha', 'saucelabs'],
|
||||||
|
sauceLabs: {
|
||||||
|
'testName': 'layui test case',
|
||||||
|
'recordVideo': false,
|
||||||
|
'recordScreenshots': false,
|
||||||
|
'startConnect': false,
|
||||||
|
'connectOptions': {
|
||||||
|
'no-ssl-bump-domains': 'all'
|
||||||
|
},
|
||||||
|
'public': 'public',
|
||||||
|
'build': process.env.CIRCLE_BUILD_NUM || process.env.SAUCE_BUILD_ID || 'build-' + Date.now(),
|
||||||
|
'tunnelIdentifier': process.env.TRAVIS_JOB_NUMBER
|
||||||
|
},
|
||||||
|
customLaunchers: customLaunchers,
|
||||||
|
browsers: Object.keys(customLaunchers),
|
||||||
|
captureTimeout: 1000 * 60 * 5,
|
||||||
|
browserNoActivityTimeout: 1000 * 60 * 5
|
||||||
|
});
|
||||||
|
|
||||||
|
config.set(options);
|
||||||
|
};
|
12
karma.conf.unit.js
Normal file
12
karma.conf.unit.js
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
/**
|
||||||
|
* @file karma配置
|
||||||
|
* @author fe.xiaowu@gmail.com
|
||||||
|
*/
|
||||||
|
|
||||||
|
var base = require('./karma.conf.base.js');
|
||||||
|
|
||||||
|
module.exports = function (config) {
|
||||||
|
var options = Object.assign(base(config), {});
|
||||||
|
|
||||||
|
config.set(options);
|
||||||
|
};
|
28
package.json
28
package.json
@ -5,7 +5,10 @@
|
|||||||
"main": "layui.js",
|
"main": "layui.js",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"test": "echo \"Error: no test specified\" && exit 1"
|
"test": "karma start karma.conf.unit.js",
|
||||||
|
"test:cov": "npm test -- --reporters mocha,coverage",
|
||||||
|
"test:sauce": "karma start karma.conf.sauce.js",
|
||||||
|
"test:watch": "npm test -- --auto-watch --no-single-run"
|
||||||
},
|
},
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
@ -23,7 +26,19 @@
|
|||||||
"gulp-rename": "^1.2.2",
|
"gulp-rename": "^1.2.2",
|
||||||
"gulp-uglify": "^1.5.4",
|
"gulp-uglify": "^1.5.4",
|
||||||
"gulp-zip": "^4.0.0",
|
"gulp-zip": "^4.0.0",
|
||||||
"minimist": "^1.2.0"
|
"minimist": "^1.2.0",
|
||||||
|
"chai": "^3.5.0",
|
||||||
|
"karma": "^1.5.0",
|
||||||
|
"karma-chai": "^0.1.0",
|
||||||
|
"karma-chai-sinon": "^0.1.5",
|
||||||
|
"karma-coverage": "^1.1.1",
|
||||||
|
"karma-mocha": "^1.3.0",
|
||||||
|
"karma-sauce-launcher": "^1.1.0",
|
||||||
|
"karma-mocha-reporter": "^2.2.3",
|
||||||
|
"karma-phantomjs-launcher": "^1.0.4",
|
||||||
|
"mocha": "^3.2.0",
|
||||||
|
"sinon": "^2.0.0",
|
||||||
|
"sinon-chai": "^2.8.0"
|
||||||
},
|
},
|
||||||
"bugs": {
|
"bugs": {
|
||||||
"url": "https://github.com/sentsin/layui/issues"
|
"url": "https://github.com/sentsin/layui/issues"
|
||||||
@ -33,15 +48,6 @@
|
|||||||
"test": "test"
|
"test": "test"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"gulp": "^3.9.1",
|
|
||||||
"gulp-uglify": "^1.5.4",
|
|
||||||
"gulp-minify-css": "^1.2.4",
|
|
||||||
"gulp-concat": "^2.6.0",
|
|
||||||
"gulp-header": "^1.8.8",
|
|
||||||
"gulp-if": "^2.0.1",
|
|
||||||
"gulp-rename": "^1.2.2",
|
|
||||||
"del": "^2.2.2",
|
|
||||||
"minimist": "^1.2.0"
|
|
||||||
},
|
},
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"layui",
|
"layui",
|
||||||
|
227
test/laytpl.js
Normal file
227
test/laytpl.js
Normal file
@ -0,0 +1,227 @@
|
|||||||
|
/**
|
||||||
|
* @file laytpl - 测试
|
||||||
|
* @author xuexb <fe.xiaowu@gmail.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* global layui */
|
||||||
|
|
||||||
|
var laytpl = layui.laytpl;
|
||||||
|
|
||||||
|
describe('laytpl', function () {
|
||||||
|
it('param is error', function () {
|
||||||
|
[
|
||||||
|
[], {},
|
||||||
|
null,
|
||||||
|
1,
|
||||||
|
true
|
||||||
|
].forEach(function (key) {
|
||||||
|
expect(laytpl(key)).to.have.string('Laytpl Error');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('async render callback', function (done) {
|
||||||
|
expect(laytpl('').render()).to.have.string('Laytpl Error');
|
||||||
|
|
||||||
|
laytpl('{{ d.name }}是一位公猿').render({
|
||||||
|
name: '贤心'
|
||||||
|
}, function (result) {
|
||||||
|
expect(result).to.equal('贤心是一位公猿');
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('sync result', function () {
|
||||||
|
var result = laytpl('{{ d.name }}是一位公猿').render({
|
||||||
|
name: '贤心'
|
||||||
|
});
|
||||||
|
expect(result).to.equal('贤心是一位公猿');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('cached', function () {
|
||||||
|
var compile = laytpl('{{ d.name }}');
|
||||||
|
|
||||||
|
expect(compile.render({
|
||||||
|
name: 1
|
||||||
|
})).to.equal('1');
|
||||||
|
|
||||||
|
expect(compile.render({
|
||||||
|
name: 2
|
||||||
|
})).to.equal('2');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('unescape result', function () {
|
||||||
|
var result = laytpl('{{ d.name }}<div></div>').render({
|
||||||
|
name: '<em>laytpl</em>'
|
||||||
|
});
|
||||||
|
expect(result).to.equal('<em>laytpl</em><div></div>');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('escape result', function () {
|
||||||
|
var result = laytpl('{{= d.name }}<div></div>').render({
|
||||||
|
name: '<em>laytpl</em>'
|
||||||
|
});
|
||||||
|
expect(result).to.equal('<em>laytpl</em><div></div>');
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('typeof result', function () {
|
||||||
|
it('string', function () {
|
||||||
|
expect(laytpl('{{ d.name }}').render({
|
||||||
|
name: 1
|
||||||
|
})).to.be.a('string');
|
||||||
|
|
||||||
|
expect(laytpl([
|
||||||
|
'{{# ',
|
||||||
|
' if (true) {',
|
||||||
|
' return "1";',
|
||||||
|
' }',
|
||||||
|
'}}'
|
||||||
|
].join('')).render({})).to.be.a('string');
|
||||||
|
});
|
||||||
|
|
||||||
|
// 表达式返回boolean
|
||||||
|
it('boolean', function () {
|
||||||
|
expect(laytpl([
|
||||||
|
'{{# ',
|
||||||
|
' if (true) {',
|
||||||
|
' return true;',
|
||||||
|
' }',
|
||||||
|
'}}'
|
||||||
|
].join('')).render({})).to.be.a('boolean');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('number', function () {
|
||||||
|
expect(laytpl([
|
||||||
|
'{{# ',
|
||||||
|
' if (true) {',
|
||||||
|
' return 1;',
|
||||||
|
' }',
|
||||||
|
'}}'
|
||||||
|
].join('')).render({})).to.be.a('number');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('method config', function () {
|
||||||
|
// reset
|
||||||
|
afterEach(function () {
|
||||||
|
laytpl.config({
|
||||||
|
open: '{{',
|
||||||
|
close: '}}'
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('typeof', function () {
|
||||||
|
expect(laytpl.config).to.be.a('function');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('param is empty', function () {
|
||||||
|
expect(laytpl.config()).to.be.undefined;
|
||||||
|
});
|
||||||
|
|
||||||
|
it('set open', function () {
|
||||||
|
laytpl.config({
|
||||||
|
open: '<%'
|
||||||
|
});
|
||||||
|
|
||||||
|
var result = laytpl([
|
||||||
|
'<%# var name = "laytpl"; }}',
|
||||||
|
'你好, <% name }}, <% d.date }}'
|
||||||
|
].join('')).render({
|
||||||
|
date: '2017'
|
||||||
|
});
|
||||||
|
expect(result).to.equal('你好, laytpl, 2017');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('set open and close', function () {
|
||||||
|
laytpl.config({
|
||||||
|
open: '<%',
|
||||||
|
close: '%>'
|
||||||
|
});
|
||||||
|
|
||||||
|
var result = laytpl([
|
||||||
|
'<%# var name = "laytpl"; %>',
|
||||||
|
'你好, <% name %>, <% d.date %>'
|
||||||
|
].join('')).render({
|
||||||
|
date: '2017'
|
||||||
|
});
|
||||||
|
expect(result).to.equal('你好, laytpl, 2017');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('js expression', function () {
|
||||||
|
it('var', function () {
|
||||||
|
var result = laytpl('{{# var type = 1; }}{{ type }}{{ d.name }}').render({
|
||||||
|
name: 2
|
||||||
|
});
|
||||||
|
expect(result).to.equal('12');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('function', function () {
|
||||||
|
var result = laytpl('{{# var fn = function () {return "ok"}; }}{{ fn() }}').render({});
|
||||||
|
expect(result).to.equal('ok');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('for', function () {
|
||||||
|
var result = laytpl([
|
||||||
|
'{{# ',
|
||||||
|
' var fn = function () {',
|
||||||
|
' var num = 0;',
|
||||||
|
' for (var i = 0; i < 10;i++) {',
|
||||||
|
' num += 1;',
|
||||||
|
' }',
|
||||||
|
' return num',
|
||||||
|
' };',
|
||||||
|
'}}',
|
||||||
|
'{{# ',
|
||||||
|
' var name = "laytpl";',
|
||||||
|
'}}',
|
||||||
|
'你好, {{ name }}, {{ d.name }}, {{ fn() }}'
|
||||||
|
].join('')).render({
|
||||||
|
name: 'ok'
|
||||||
|
});
|
||||||
|
expect(result).to.equal('你好, laytpl, ok, 10');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('if else', function () {
|
||||||
|
var result;
|
||||||
|
result = laytpl([
|
||||||
|
'{{# ',
|
||||||
|
' if (true) {',
|
||||||
|
' return true;',
|
||||||
|
' }',
|
||||||
|
' else {',
|
||||||
|
' return false',
|
||||||
|
' }',
|
||||||
|
'}}'
|
||||||
|
].join('')).render({});
|
||||||
|
expect(result).to.be.true;
|
||||||
|
|
||||||
|
result = laytpl([
|
||||||
|
'{{# ',
|
||||||
|
' if (!true) {',
|
||||||
|
' return true;',
|
||||||
|
' }',
|
||||||
|
' else {',
|
||||||
|
' return false',
|
||||||
|
' }',
|
||||||
|
'}}'
|
||||||
|
].join('')).render({});
|
||||||
|
expect(result).to.be.false;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('parse error', function () {
|
||||||
|
it('error var', function () {
|
||||||
|
var result = laytpl('{{ data.xxoo }}').render({});
|
||||||
|
|
||||||
|
expect(result).to.have.string('Can\'t find variable: data');
|
||||||
|
expect(result).to.have.string('Laytpl Error');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('error expression', function () {
|
||||||
|
var result = laytpl('{{# var xxoo = ; }}').render({});
|
||||||
|
|
||||||
|
expect(result).to.have.string('Laytpl Error');
|
||||||
|
expect(result).to.have.string('Unexpected token \';\'');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
Loading…
Reference in New Issue
Block a user