Browse Source

* qunit

tests
RubaXa 9 years ago
parent
commit
548460afec
  1. 29
      Gruntfile.js
  2. 35
      tests/index.html
  3. 103
      tests/sortable.tests.js
  4. 28
      tests/src/polyfills.js
  5. 13
      tests/src/qunit.ext.js
  6. 26
      tests/src/simulate.js

29
Gruntfile.js

@ -18,7 +18,11 @@ module.exports = function (grunt) {
},
jshint: {
all: ['*.js', '!*.min.js'],
all: [
'*.js',
'!*.min.js',
'tests/**/*.js'
],
options: {
jshintrc: true
@ -48,7 +52,25 @@ module.exports = function (grunt) {
}
},
jquery: {}
jquery: {},
qunit: {
all: ['tests/index.html'],
options: {
'--web-security': 'no',
coverage: {
src: ['Sortable.js'],
instrumentedFiles: 'temp/',
htmlReport: 'report/coverage/',
coberturaReport: 'report/',
baseUrl: "./coverage",
linesThresholdPct: 99,
functionsThresholdPct: 100,
branchesThresholdPct: 90,
statementsThresholdPct: 90
}
}
}
});
@ -91,6 +113,7 @@ module.exports = function (grunt) {
grunt.loadNpmTasks('grunt-version');
grunt.loadNpmTasks('grunt-contrib-jshint');
grunt.loadNpmTasks('grunt-contrib-uglify');
grunt.loadNpmTasks('grunt-qunit-istanbul');
grunt.loadNpmTasks('grunt-exec');
// Meteor tasks
@ -98,6 +121,6 @@ module.exports = function (grunt) {
grunt.registerTask('meteor-publish', 'exec:meteor-publish');
grunt.registerTask('meteor', ['meteor-test', 'meteor-publish']);
grunt.registerTask('tests', ['jshint']);
grunt.registerTask('tests', ['jshint', 'qunit']);
grunt.registerTask('default', ['tests', 'version', 'uglify:dist']);
};

35
tests/index.html

@ -8,32 +8,27 @@
<title>Sortable :: Tests</title>
</head>
<body>
<div id="canvas">
<ul id="simple">
<li>item 1</li>
<li>item 2</li>
<li>item 3</li>
</ul>
</div>
<style>
.styled {
margin: 0;
padding: 0;
list-style: none;
}
.styled > * {
padding: 5px 10px;
}
</style>
<div id="fixture"></div>
<div id="qunit"></div>
<div id="qunit-fixture"></div>
<link rel="stylesheet" href="//code.jquery.com/qunit/qunit-1.21.0.css"/>
<script src="//code.jquery.com/qunit/qunit-1.21.0.js"></script>
<link href="http://code.jquery.com/qunit/qunit-1.21.0.css" rel="stylesheet"/>
<script src="http://code.jquery.com/qunit/qunit-1.21.0.js"></script>
<script src="./src/raf.js"></script>
<script src="./src/polyfills.js"></script>
<script src="./src/simulate.js"></script>
<script src="./src/qunit.ext.js"></script>
<script src="../Sortable.js"></script>
<script>
Sortable.create(simple);
</script>
<script src="./sortable.tests.js"></script>
</body>
</html>

103
tests/sortable.tests.js

@ -1,18 +1,99 @@
/* global QUnit, fixture, Sortable, simulateDrag */
'use strict';
QUnit.module('Sortable');
QUnit.sortableTest('simple', {
from: {
el: '#simple',
index: 0
},
function createSortableList(options) {
var listEl = document.createElement('div');
var length = options.length;
var withHandle = options.withHandle;
if (withHandle) {
options.handle = withHandle;
}
listEl.className = 'js-list';
for (var i = 0; i < length; i++) {
var el = document.createElement('div');
to: {
el: '#simple',
index: 'last'
el.appendChild(document.createTextNode('Item ' + (i + 1)));
el.className = 'js-list-item';
listEl.appendChild(el);
}
}, function (assert, scope) {
assert.ok(scope.toList.contains(scope.target), 'container');
assert.equal(scope.target, scope.toList.lastElementChild, 'position');
fixture.appendChild(listEl);
return {
el: listEl,
sortable: Sortable.create(listEl, options),
destroy: function () {
this.sortable.destroy();
fixture.removeChild(this.el);
this.el = null;
this.sortable = null;
}
};
}
QUnit.test('core', function (assert) {
var done = assert.async();
var events = {};
var logEvent = function (evt) { events[this + evt.type] = true; };
var list = createSortableList({
length: 3,
onStart: logEvent.bind('on'),
onMove: logEvent.bind('on'),
onUpdate: logEvent.bind('on'),
onEnd: logEvent.bind('on')
});
list.el.addEventListener('start', logEvent.bind(''));
list.el.addEventListener('move', logEvent.bind(''));
list.el.addEventListener('update', logEvent.bind(''));
list.el.addEventListener('end', logEvent.bind(''));
simulateDrag({
from: {
el: list.el,
index: 0
},
to: {index: 'last'},
ontap: function () {
assert.ok(list.el.firstChild.className.indexOf('sortable-chosen') > -1, 'sortable-choose');
},
ondragstart: function () {
setTimeout(function () {
assert.ok(list.el.firstChild.className.indexOf('sortable-ghost') > -1, 'sortable-ghost');
}, 0);
}
}, function () {
assert.deepEqual(Object.keys(events), [
'start', 'onstart',
'move', 'onmove',
'update', 'onupdate',
'end', 'onend'
]);
list.destroy();
done();
});
});
//QUnit.test('handle', function (assert) {
// var done = assert.async();
// var list = createSortableList({
// length: 3,
// withHandle: true,
// onStart: function () { assert.ok(false, 'start'); },
// onEnd: function () { assert.ok(false, 'end'); }
// });
//});

28
tests/src/raf.js → tests/src/polyfills.js

@ -36,3 +36,31 @@
};
}
}());
if (!Function.prototype.bind) {
Function.prototype.bind = function (oThis) {
'use strict';
if (typeof this !== 'function') {
// ближайший аналог внутренней функции
// IsCallable в ECMAScript 5
throw new TypeError('Function.prototype.bind - what is trying to be bound is not callable');
}
var aArgs = Array.prototype.slice.call(arguments, 1),
fToBind = this,
fNOP = function () {},
fBound = function () {
return fToBind.apply(this instanceof fNOP && oThis
? this
: oThis,
aArgs.concat(Array.prototype.slice.call(arguments)));
};
fNOP.prototype = this.prototype;
fBound.prototype = new fNOP();
return fBound;
};
}

13
tests/src/qunit.ext.js

@ -1,13 +0,0 @@
(function () {
'use strict';
QUnit.sortableTest = function sortableTest(name, options, fn) {
QUnit.test(name, function (assert) {
var done = assert.async();
var data = simulateDrag(options, function () {
fn(assert, data, options);
done();
});
});
};
})();

26
tests/src/simulate.js

@ -42,7 +42,9 @@
}
function getTraget(target) {
var children = document.getElementById(target.el.substr(1)).children;
var el = typeof target.el === 'string' ? document.getElementById(target.el.substr(1)) : target.el;
var children = el.children;
return (
children[target.index] ||
children[target.index === 'first' ? 0 : -1] ||
@ -58,16 +60,18 @@
return {
x: rect.left,
y: rect.top,
cx: rect.left + width/2,
cy: rect.top + height/2,
cx: rect.left + width / 2,
cy: rect.top + height / 2,
w: width,
h: height,
hw: width/2,
wh: height/2
}
hw: width / 2,
wh: height / 2
};
}
function simulateDrag(options, callback) {
options.to.el = options.to.el || options.from.el;
var fromEl = getTraget(options.from);
var toEl = getTraget(options.to);
@ -83,10 +87,16 @@
var duration = options.duration || 1000;
simulateEvent(fromEl, 'mousedown', {button: 0});
options.ontap && options.ontap();
simulateEvent(toEl, 'dragstart');
requestAnimationFrame(function () {
options.ondragstart && options.ondragstart();
});
requestAnimationFrame(function loop() {
var progress = (new Date().getTime() - startTime)/duration;
var progress = (new Date().getTime() - startTime) / duration;
var x = fromRect.cx + (toRect.cx - fromRect.cx) * progress;
var y = fromRect.cy + (toRect.cy - fromRect.cy) * progress;
var overEl = fromEl.ownerDocument.elementFromPoint(x, y);
@ -95,6 +105,7 @@
dotEl.style.left = x + 'px';
dotEl.style.top = y + 'px';
//console.log(overEl.parentNode.parentNode.parentNode.id, overEl.className, x, y);
overEl && simulateEvent(overEl, 'dragover', {
clientX: x,
clientY: y
@ -104,6 +115,7 @@
dotEl.style.display = '';
requestAnimationFrame(loop);
} else {
options.ondragend && options.ondragend();
simulateEvent(toEl, 'drop');
callback();
}

Loading…
Cancel
Save