mirror of
https://github.com/gristlabs/grist-core.git
synced 2024-10-27 20:44:07 +00:00
bcbf57d590
Summary: This uses a newer version of mocha in grist-core so that tests can be run in parallel. That allows more tests to be moved without slowing things down overall. Tests moved are venerable browser tests; only the ones that "just work" or worked without too much trouble to are moved, in order to keep the diff from growing too large. Will wrestle with more in follow up. Parallelism is at the file level, rather than the individual test. The newer version of mocha isn't needed for grist-saas repo; tests are parallelized in our internal CI by other means. I've chosen to allocate files to workers in a cruder way than our internal CI, based on initial characters rather than an automated process. The automated process would need some reworking to be compatible with mocha running in parallel mode. Test Plan: this diff was tested first on grist-core, then ported to grist-saas so saas repo history will correctly track history of moved files. Reviewers: jarek Reviewed By: jarek Subscribers: jarek Differential Revision: https://phab.getgrist.com/D3927
276 lines
8.7 KiB
JavaScript
276 lines
8.7 KiB
JavaScript
var assert = require('chai').assert;
|
|
var ko = require('knockout');
|
|
|
|
var kf = require('app/client/lib/koForm');
|
|
var koArray = require('app/client/lib/koArray');
|
|
var clientUtil = require('../clientUtil');
|
|
|
|
var G = require('app/client/lib/browserGlobals').get('$');
|
|
|
|
describe('koForm', function() {
|
|
|
|
clientUtil.setTmpMochaGlobals();
|
|
|
|
function triggerInput(input, property, value) {
|
|
input[property] = value;
|
|
G.$(input).trigger('input');
|
|
}
|
|
|
|
function triggerChange(input, property, value) {
|
|
input[property] = value;
|
|
G.$(input).trigger('change');
|
|
}
|
|
|
|
function triggerClick(elem) {
|
|
G.$(elem).trigger('click');
|
|
}
|
|
|
|
describe("button", function() {
|
|
it("should call a function", function() {
|
|
var calls = 0;
|
|
var btn = kf.button(function() { calls++; }, 'Test');
|
|
triggerClick(btn);
|
|
triggerClick(btn);
|
|
triggerClick(btn);
|
|
assert.equal(calls, 3);
|
|
});
|
|
});
|
|
|
|
describe("checkButton", function() {
|
|
it("should bind an observable", function() {
|
|
var obs = ko.observable(false);
|
|
|
|
// Test observable->widget binding.
|
|
var btn = kf.checkButton(obs, "Test");
|
|
assert(!btn.classList.contains('active'));
|
|
obs(true);
|
|
assert(btn.classList.contains('active'));
|
|
|
|
btn = kf.checkButton(obs, "Test2");
|
|
assert(btn.classList.contains('active'));
|
|
obs(false);
|
|
assert(!btn.classList.contains('active'));
|
|
|
|
// Test widget->observable binding.
|
|
assert.equal(obs(), false);
|
|
triggerClick(btn);
|
|
assert.equal(obs(), true);
|
|
triggerClick(btn);
|
|
assert.equal(obs(), false);
|
|
});
|
|
});
|
|
|
|
describe("buttonSelect", function() {
|
|
it("should bind an observable", function() {
|
|
var obs = ko.observable('b');
|
|
var a, b, c;
|
|
|
|
kf.buttonSelect(obs,
|
|
a = kf.optionButton('a', 'Test A'),
|
|
b = kf.optionButton('b', 'Test B'),
|
|
c = kf.optionButton('c', 'Test C')
|
|
);
|
|
|
|
// Test observable->widget binding.
|
|
assert(!a.classList.contains('active'));
|
|
assert(b.classList.contains('active'));
|
|
assert(!c.classList.contains('active'));
|
|
obs('a');
|
|
assert(a.classList.contains('active'));
|
|
assert(!b.classList.contains('active'));
|
|
obs('c');
|
|
assert(!a.classList.contains('active'));
|
|
assert(!b.classList.contains('active'));
|
|
assert(c.classList.contains('active'));
|
|
|
|
// Test widget->observable binding.
|
|
assert.equal(obs(), 'c');
|
|
triggerClick(b);
|
|
assert.equal(obs(), 'b');
|
|
});
|
|
});
|
|
|
|
describe("checkbox", function() {
|
|
it("should bind an observable", function() {
|
|
var obs = ko.observable(false);
|
|
var check = kf.checkbox(obs, "Foo").querySelector('input');
|
|
|
|
// Test observable->widget binding.
|
|
assert.equal(check.checked, false);
|
|
obs(true);
|
|
assert.equal(check.checked, true);
|
|
|
|
check = kf.checkbox(obs, "Foo").querySelector('input');
|
|
assert.equal(check.checked, true);
|
|
obs(false);
|
|
assert.equal(check.checked, false);
|
|
|
|
// Test widget->observable binding.
|
|
triggerChange(check, 'checked', true);
|
|
assert.equal(obs(), true);
|
|
assert.equal(check.checked, true);
|
|
|
|
triggerChange(check, 'checked', false);
|
|
assert.equal(obs(), false);
|
|
assert.equal(check.checked, false);
|
|
});
|
|
});
|
|
|
|
describe("text", function() {
|
|
it("should bind an observable", function() {
|
|
var obs = ko.observable('hello');
|
|
var input = kf.text(obs).querySelector('input');
|
|
|
|
// Test observable->widget binding.
|
|
assert.equal(input.value, 'hello');
|
|
obs('world');
|
|
assert.equal(input.value, 'world');
|
|
|
|
// Test widget->observable binding.
|
|
triggerChange(input, 'value', 'foo');
|
|
assert.equal(obs(), 'foo');
|
|
});
|
|
});
|
|
|
|
describe("text debounce", function() {
|
|
it("should bind an observable", function() {
|
|
var obs = ko.observable('hello');
|
|
var input = kf.text(obs, {delay: 300}).querySelector('input');
|
|
|
|
// Test observable->widget binding.
|
|
assert.equal(input.value, 'hello');
|
|
obs('world');
|
|
assert.equal(input.value, 'world');
|
|
|
|
// Test widget->observable binding using interrupted by 'Enter' or loosing focus debounce.
|
|
triggerInput(input, 'value', 'bar');
|
|
assert.equal(input.value, 'bar');
|
|
// Ensure that observable value wasn't changed immediately
|
|
assert.equal(obs(), 'world');
|
|
// Simulate 'change' event (hitting 'Enter' or loosing focus)
|
|
triggerChange(input, 'value', 'bar');
|
|
// Ensure that observable value was changed on 'change' event
|
|
assert.equal(obs(), 'bar');
|
|
|
|
// Test widget->observable binding using debounce.
|
|
triggerInput(input, 'value', 'helloworld');
|
|
input.selectionStart = 3;
|
|
input.selectionEnd = 7;
|
|
assert.equal(input.value.substring(input.selectionStart, input.selectionEnd), 'lowo');
|
|
assert.equal(input.value, 'helloworld');
|
|
|
|
// Ensure that observable value wasn't changed immediately, needs to wait 300 ms
|
|
assert.equal(obs(), 'bar');
|
|
|
|
// Ensure that after delay value were changed
|
|
return clientUtil.waitForChange(obs, 350)
|
|
.then(() => {
|
|
assert.equal(obs(), 'helloworld');
|
|
assert.equal(input.value, 'helloworld');
|
|
// Ensure that selection is the same and cursor didn't jump to the end
|
|
assert.equal(input.value.substring(input.selectionStart, input.selectionEnd), 'lowo');
|
|
});
|
|
});
|
|
});
|
|
|
|
describe("numText", function() {
|
|
it("should bind an observable", function() {
|
|
var obs = ko.observable(1234);
|
|
var input = kf.numText(obs).querySelector('input');
|
|
|
|
// Test observable->widget binding.
|
|
assert.equal(input.value, '1234');
|
|
obs('-987.654');
|
|
assert.equal(input.value, '-987.654');
|
|
|
|
// Test widget->observable binding.
|
|
triggerInput(input, 'value', '-1.2');
|
|
assert.strictEqual(obs(), -1.2);
|
|
});
|
|
});
|
|
|
|
describe("select", function() {
|
|
it("should bind an observable", function() {
|
|
var obs = ko.observable("b");
|
|
var input = kf.select(obs, ["a", "b", "c"]).querySelector('select');
|
|
var options = Array.prototype.slice.call(input.querySelectorAll('option'), 0);
|
|
function selected() {
|
|
return options.map(function(option) { return option.selected; });
|
|
}
|
|
|
|
// Test observable->widget binding.
|
|
assert.deepEqual(selected(), [false, true, false]);
|
|
obs("a");
|
|
assert.deepEqual(selected(), [true, false, false]);
|
|
obs("c");
|
|
assert.deepEqual(selected(), [false, false, true]);
|
|
|
|
// Test widget->observable binding.
|
|
triggerChange(options[0], 'selected', true);
|
|
assert.deepEqual(selected(), [true, false, false]);
|
|
assert.equal(obs(), "a");
|
|
|
|
triggerChange(options[1], 'selected', true);
|
|
assert.deepEqual(selected(), [false, true, false]);
|
|
assert.equal(obs(), "b");
|
|
});
|
|
|
|
it("should work with option array of objects", function() {
|
|
var obs = ko.observable();
|
|
var foo = ko.observable('foo');
|
|
var bar = ko.observable('bar');
|
|
var values = koArray([
|
|
{ label: foo, value: 'a1' },
|
|
{ label: bar, value: 'b1' },
|
|
]);
|
|
|
|
var select = kf.select(obs, values);
|
|
var options = Array.from(select.querySelectorAll('option'));
|
|
assert.deepEqual(options.map(el => el.textContent), ['foo', 'bar']);
|
|
|
|
triggerChange(options[0], 'selected', true);
|
|
assert.equal(obs(), 'a1');
|
|
|
|
foo('foo2');
|
|
bar('bar2');
|
|
|
|
options = Array.from(select.querySelectorAll('option'));
|
|
assert.deepEqual(options.map(el => el.textContent), ['foo2', 'bar2']);
|
|
|
|
triggerChange(options[1], 'selected', true);
|
|
assert.equal(obs(), 'b1');
|
|
});
|
|
|
|
it("should store actual, non-stringified values", function() {
|
|
let obs = ko.observable();
|
|
let values = [
|
|
{ label: 'a', value: 1 },
|
|
{ label: 'b', value: '2' },
|
|
{ label: 'c', value: true },
|
|
{ label: 'd', value: { hello: 'world' } },
|
|
{ label: 'e', value: new Date() },
|
|
];
|
|
let options = Array.from(kf.select(obs, values).querySelectorAll('option'));
|
|
|
|
for (let i = 0; i < values.length; i++) {
|
|
triggerChange(options[i], 'selected', true);
|
|
assert.strictEqual(obs(), values[i].value);
|
|
}
|
|
});
|
|
|
|
it("should allow multi-select and save sorted values", function() {
|
|
let obs = ko.observable();
|
|
let foo = { foo: 'bar' };
|
|
let values = [{ label: 'a', value: foo }, 'd', { label: 'c', value: 1 }, 'b'];
|
|
let options = Array.from(
|
|
kf.select(obs, values, { multiple: true}).querySelectorAll('option'));
|
|
|
|
triggerChange(options[0], 'selected', true);
|
|
triggerChange(options[2], 'selected', true);
|
|
triggerChange(options[3], 'selected', true);
|
|
|
|
assert.deepEqual(obs(), [1, foo, 'b']);
|
|
});
|
|
});
|
|
});
|