").addClass("custom-edit-row").append($("| ").text(itemIndex + ":" + item.value));
},
fields: [
{ name: "value" }
]
},
grid = new Grid($element, gridOptions);
grid.editItem(data[0]);
var $editRow = grid._content.find(".custom-edit-row");
equal($editRow.length, 1, "edit row rendered");
equal($editRow.text(), "0:test", "custom edit row renderer rendered");
});
module("deleting");
test("delete item", function() {
var $element = $("#jsGrid"),
deleted = false,
deletingArgs,
deletedArgs,
data = [{
field: "value"
}],
gridOptions = {
confirmDeleting: false,
fields: [
{ name: "field" }
],
controller: {
deleteItem: function(deletingItem) {
deleted = true;
}
},
onItemDeleting: function(e) {
deletingArgs = $.extend(true, {}, e);
},
onItemDeleted: function(e) {
deletedArgs = $.extend(true, {}, e);
}
},
grid = new Grid($element, gridOptions);
grid.option("data", data);
grid.deleteItem(data[0]);
deepEqual(deletingArgs.item, { field: "value" }, "field and value is provided in deleting event args");
equal(deletingArgs.itemIndex, 0, "itemIndex is provided in updating event args");
equal(deletingArgs.row.length, 1, "row element is provided in updating event args");
ok(deleted, "controller deleteItem called");
equal(grid.option("data").length, 0, "data row deleted");
deepEqual(deletedArgs.item, { field: "value" }, "item is provided in updating event args");
equal(deletedArgs.itemIndex, 0, "itemIndex is provided in updating event args");
equal(deletedArgs.row.length, 1, "row element is provided in updating event args");
});
test("deleteItem accepts row", function() {
var $element = $("#jsGrid"),
deletedItem,
itemToDelete = {
field: "value"
},
data = [itemToDelete],
gridOptions = {
confirmDeleting: false,
fields: [
{ name: "field" }
],
controller: {
deleteItem: function(deletingItem) {
deletedItem = deletingItem;
}
}
},
grid = new Grid($element, gridOptions);
grid.option("data", data);
var $row = $element.find("." + grid.oddRowClass).eq(0);
grid.deleteItem($row);
deepEqual(deletedItem, itemToDelete, "controller deleteItem called correctly");
equal(grid.option("data").length, 0, "data row deleted");
});
module("paging");
test("pager is rendered if necessary", function() {
var $element = $("#jsGrid"),
grid = new Grid($element, {
data: [{}, {}, {}],
paging: false,
pageSize: 2
});
ok(grid._pagerContainer.is(":hidden"), "pager is hidden when paging=false");
equal(grid._pagerContainer.html(), "", "pager is not rendered when paging=false");
grid.option("paging", true);
ok(grid._pagerContainer.is(":visible"), "pager is visible when paging=true");
ok(grid._pagerContainer.html(), "pager is rendered when paging=true");
grid.option("data", [{}, {}]);
ok(grid._pagerContainer.is(":hidden"), "pager is hidden for single page");
ok(grid._pagerContainer.html(), "pager is rendered for single page when paging=true");
});
test("external pagerContainer", function() {
var $pagerContainer = $(" ").appendTo("#qunit-fixture").hide(),
$element = $("#jsGrid");
new Grid($element, {
data: [{}, {}, {}],
pagerContainer: $pagerContainer,
paging: true,
pageSize: 2
});
ok($pagerContainer.is(":visible"), "external pager shown");
ok($pagerContainer.html(), "external pager rendered");
});
test("pager functionality", function() {
var $element = $("#jsGrid"),
pager,
pageChangedArgs,
grid = new Grid($element, {
data: [{}, {}, {}, {}, {}, {}, {}, {}, {}],
onPageChanged: function(args) {
pageChangedArgs = args;
},
paging: true,
pageSize: 2,
pageButtonCount: 3
});
equal(grid._pagesCount(), 5, "correct page count");
equal(grid.option("pageIndex"), 1, "pageIndex is initialized");
equal(grid._firstDisplayingPage, 1, "_firstDisplayingPage is initialized");
pager = grid._pagerContainer;
equal(pager.find("." + grid.currentPageClass).length, 1, "there is one current page");
ok(pager.find("." + grid.pageClass).eq(0).hasClass(grid.currentPageClass), "first page is current");
equal(pager.find("." + grid.pageClass).length, 3, "three pages displayed");
equal(pager.find("." + grid.pagerNavButtonClass).length, 5, "five nav buttons displayed: Fisrt Prev Next Last ...");
equal(pager.find("." + grid.pagerNavButtonInactiveClass).length, 2, "two nav buttons inactive: Fisrt Prev");
grid.openPage(2);
equal(pager.find("." + grid.currentPageClass).length, 1, "there is one current page");
ok(pager.find("." + grid.pageClass).eq(1).hasClass(grid.currentPageClass), "second page is current");
equal(pager.find("." + grid.pageClass).length, 3, "three pages displayed");
equal(pager.find("." + grid.pagerNavButtonClass).length, 5, "five nav buttons displayed: First Prev Next Last and ...");
equal(pageChangedArgs.pageIndex, 2, "onPageChanged callback provides pageIndex in arguments");
grid.showNextPages();
equal(grid._firstDisplayingPage, 3, "navigate by pages forward");
grid.showPrevPages();
equal(grid._firstDisplayingPage, 1, "navigate by pages backward");
grid.openPage(5);
equal(grid._firstDisplayingPage, 3, "opening next non-visible page moves first displaying page forward");
grid.openPage(2);
equal(grid._firstDisplayingPage, 2, "opening prev non-visible page moves first displaying page backward");
});
test("pager format", function() {
var $element = $("#jsGrid"),
grid = new Grid($element, {
data: [{}, {}, {}, {}, {}, {}],
paging: true,
pageSize: 2,
pageIndex: 2,
pageButtonCount: 1,
pagerFormat: "a {pageIndex} {first} {prev} {pages} {next} {last} {pageCount} {itemCount} z",
pagePrevText: "<",
pageNextText: ">",
pageFirstText: "<<",
pageLastText: ">>",
pageNavigatorNextText: "np",
pageNavigatorPrevText: "pp"
});
grid._firstDisplayingPage = 2;
grid._refreshPager();
equal($.trim(grid._pagerContainer.text()), "a 2 << < pp2np > >> 3 6 z", "pager text follows the format specified");
});
test("pagerRenderer", function() {
var $element = $("#jsGrid");
var pagerRendererConfig;
var pageSize = 2;
var items = [{}, {}, {}, {}, {}, {}, {}];
var pageCount = Math.ceil(items.length / pageSize);
var grid = new Grid($element, {
data: items,
paging: true,
pageSize: pageSize,
pagerRenderer: function(pagerConfig) {
pagerRendererConfig = pagerConfig;
}
});
deepEqual(pagerRendererConfig, { pageIndex: 1, pageCount: pageCount });
grid.openPage(2);
deepEqual(pagerRendererConfig, { pageIndex: 2, pageCount: pageCount });
});
test("loading by page", function() {
var $element = $("#jsGrid"),
data = [],
itemCount = 20;
for(var i = 1; i <= itemCount; i += 1) {
data.push({
value: i
});
}
var gridOptions = {
pageLoading: true,
paging: true,
pageSize: 7,
fields: [
{ name: "value" }
],
controller: {
loadData: function(filter) {
var startIndex = (filter.pageIndex - 1) * filter.pageSize,
result = data.slice(startIndex, startIndex + filter.pageSize);
return {
data: result,
itemsCount: data.length
};
}
}
};
var grid = new Grid($element, gridOptions);
grid.loadData();
var pager = grid._pagerContainer;
var gridData = grid.option("data");
equal(gridData.length, 7, "loaded one page of data");
equal(gridData[0].value, 1, "loaded right data start value");
equal(gridData[gridData.length - 1].value, 7, "loaded correct data end value");
ok(pager.find("." + grid.pageClass).eq(0).hasClass(grid.currentPageClass), "first page is current");
equal(pager.find("." + grid.pageClass).length, 3, "three pages displayed");
grid.openPage(3);
gridData = grid.option("data");
equal(gridData.length, 6, "loaded last page of data");
equal(gridData[0].value, 15, "loaded right data start value");
equal(gridData[gridData.length - 1].value, 20, "loaded right data end value");
ok(pager.find("." + grid.pageClass).eq(2).hasClass(grid.currentPageClass), "third page is current");
equal(pager.find("." + grid.pageClass).length, 3, "three pages displayed");
});
test("'openPage' method ignores indexes out of range", function() {
var $element = $("#jsGrid"),
grid = new Grid($element, {
data: [{}, {}],
paging: true,
pageSize: 1
});
grid.openPage(0);
equal(grid.option("pageIndex"), 1, "too small index is ignored");
grid.openPage(3);
equal(grid.option("pageIndex"), 1, "too big index is ignored");
});
module("sorting");
test("sorting", function() {
var $element = $("#jsGrid"),
gridOptions = {
sorting: true,
data: [
{ value: 3 },
{ value: 2 },
{ value: 1 }
],
fields: [
{ name: "value", sorter: "number" }
]
},
grid = new Grid($element, gridOptions);
var gridData = grid.option("data");
var $th = grid._headerRow.find("th").eq(0);
$th.trigger("click");
equal(grid._sortOrder, "asc", "asc sorting order for first click");
equal(grid._sortField, grid.fields[0], "sort field is set");
equal(gridData[0].value, 1);
equal(gridData[1].value, 2);
equal(gridData[2].value, 3);
ok($th.hasClass(grid.sortableClass));
ok($th.hasClass(grid.sortAscClass));
$th.trigger("click");
equal(grid._sortOrder, "desc", "desc sorting order for second click");
equal(grid._sortField, grid.fields[0], "sort field is set");
equal(gridData[0].value, 3);
equal(gridData[1].value, 2);
equal(gridData[2].value, 1);
ok(!$th.hasClass(grid.sortAscClass));
ok($th.hasClass(grid.sortDescClass));
});
test("sorting with pageLoading", function() {
var $element = $("#jsGrid"),
loadFilter,
gridOptions = {
sorting: true,
pageLoading: true,
data: [
{ value: 3 },
{ value: 2 },
{ value: 1 }
],
controller: {
loadData: function(filter) {
loadFilter = filter;
return {
itemsCount: 0,
data: []
};
}
},
fields: [
{ name: "value", sorter: "number" }
]
},
grid = new Grid($element, gridOptions);
var $th = grid._headerRow.find("th").eq(0);
$th.trigger("click");
equal(grid._sortOrder, "asc", "asc sorting order for first click");
equal(grid._sortField, grid.fields[0], "sort field is set");
equal(loadFilter.sortOrder, "asc", "sort direction is provided in loadFilter");
equal(loadFilter.sortField, "value", "sort field is provided in loadFilter");
$th.trigger("click");
equal(grid._sortOrder, "desc", "desc sorting order for second click");
equal(grid._sortField, grid.fields[0], "sort field is set");
equal(loadFilter.sortOrder, "desc", "sort direction is provided in loadFilter");
equal(loadFilter.sortField, "value", "sort field is provided in loadFilter");
});
test("no sorting for column with sorting = false", function() {
var $element = $("#jsGrid");
var gridOptions = {
sorting: true,
data: [
{ value: 3 },
{ value: 2 },
{ value: 1 }
],
fields: [
{ name: "value", sorting: false }
]
};
var grid = new Grid($element, gridOptions);
var gridData = grid.option("data");
var $th = grid._headerRow.find("th").eq(0);
$th.trigger("click");
equal(grid._sortField, null, "sort field is not set for the field with sorting=false");
equal(gridData[0].value, 3);
equal(gridData[1].value, 2);
equal(gridData[2].value, 1);
equal($th.hasClass(grid.sortableClass), false, "no sorting css for field with sorting=false");
equal($th.hasClass(grid.sortAscClass), false, "no sorting css for field with sorting=false");
});
test("sort accepts sorting config", function() {
var $element = $("#jsGrid"),
gridOptions = {
sorting: true,
data: [
{ value: 3 },
{ value: 2 },
{ value: 1 }
],
fields: [
{ name: "value", sorter: "number" }
]
},
grid = new Grid($element, gridOptions);
var gridData = grid.option("data");
grid.sort({ field: "value", order: "asc" });
equal(grid._sortOrder, "asc", "asc sorting order is set");
equal(grid._sortField, grid.fields[0], "sort field is set");
equal(gridData[0].value, 1);
equal(gridData[1].value, 2);
equal(gridData[2].value, 3);
grid.sort({ field: 0 });
equal(grid._sortOrder, "desc", "desc sorting order for already set asc sorting");
equal(grid._sortField, grid.fields[0], "sort field is set");
equal(gridData[0].value, 3);
equal(gridData[1].value, 2);
equal(gridData[2].value, 1);
grid.sort("value", "asc");
equal(grid._sortOrder, "asc", "asc sorting order is set");
equal(grid._sortField, grid.fields[0], "sort field is set");
grid.sort(0);
equal(grid._sortOrder, "desc", "desc sorting order for already set asc sorting");
equal(grid._sortField, grid.fields[0], "sort field is set");
});
test("getSorting returns current sorting", function() {
var $element = $("#jsGrid"),
gridOptions = {
sorting: true,
data: [
{ value: 3 },
{ value: 2 },
{ value: 1 }
],
fields: [
{ name: "value", sorter: "number" }
]
},
grid = new Grid($element, gridOptions);
deepEqual(grid.getSorting(), { field: undefined, order: undefined }, "undefined field and order before sorting");
grid.sort("value");
deepEqual(grid.getSorting(), { field: "value", order: "asc" }, "current sorting returned");
});
test("sorting css attached correctly when a field is hidden", function() {
var $element = $("#jsGrid");
var gridOptions = {
sorting: true,
data: [],
fields: [
{ name: "field1", visible: false },
{ name: "field2" }
]
};
var grid = new Grid($element, gridOptions);
var gridData = grid.option("data");
var $th = grid._headerRow.find("th").eq(0);
$th.trigger("click");
equal($th.hasClass(grid.sortAscClass), true, "sorting css is attached to first field");
});
module("canceling events");
test("cancel item edit", function() {
var $element = $("#jsGrid");
var data = [{}];
var gridOptions = {
editing: true,
onItemEditing: function(e) {
e.cancel = true;
},
controller: {
loadData: function() {
return data;
}
},
fields: [
{ name: "test" }
]
};
var grid = new Grid($element, gridOptions);
grid.loadData();
grid.editItem(data[0]);
strictEqual(grid._editingRow, null, "no editing row");
});
test("cancel controller.loadData", function() {
var $element = $("#jsGrid");
var gridOptions = {
onDataLoading: function(e) {
e.cancel = true;
},
controller: {
loadData: function() {
return [{}];
}
},
fields: [
{ name: "test" }
]
};
var grid = new Grid($element, gridOptions);
grid.loadData();
equal(grid.option("data").length, 0, "no data loaded");
});
test("cancel controller.insertItem", function() {
var $element = $("#jsGrid");
var insertedItem = null;
var gridOptions = {
onItemInserting: function(e) {
e.cancel = true;
},
controller: {
insertItem: function(item) {
insertedItem = item;
}
},
fields: [
{ name: "test" }
]
};
var grid = new Grid($element, gridOptions);
grid.insertItem({ test: "value" });
strictEqual(insertedItem, null, "item was not inserted");
});
test("cancel controller.updateItem", function() {
var $element = $("#jsGrid");
var updatedItem = null;
var existingItem = { test: "value" };
var gridOptions = {
data: [
existingItem
],
onItemUpdating: function(e) {
e.cancel = true;
},
controller: {
updateItem: function(item) {
updatedItem = item;
}
},
fields: [
{ name: "test" }
]
};
var grid = new Grid($element, gridOptions);
grid.updateItem(existingItem, { test: "new_value" });
strictEqual(updatedItem, null, "item was not updated");
});
test("cancel controller.deleteItem", function() {
var $element = $("#jsGrid");
var deletingItem = { test: "value" };
var deletedItem = null;
var gridOptions = {
data: [
deletingItem
],
confirmDeleting: false,
onItemDeleting: function(e) {
e.cancel = true;
},
controller: {
deleteItem: function(item) {
deletedItem = item;
}
},
fields: [
{ name: "test" }
]
};
var grid = new Grid($element, gridOptions);
grid.deleteItem(deletingItem);
strictEqual(deletedItem, null, "item was not deleted");
});
module("complex properties binding");
test("rendering", function() {
var $element = $("#jsGrid");
var gridOptions = {
loadMessage: "",
data: [
{ complexProp: { prop: "test" } }
],
fields: [
{ name: "complexProp.prop", title: "" }
]
};
new Grid($element, gridOptions);
equal($element.text(), "test", "complex property value rendered");
});
test("editing", function() {
var $element = $("#jsGrid");
var gridOptions = {
editing: true,
data: [
{ complexProp: { prop: "test" } }
],
fields: [
{ type: "text", name: "complexProp.prop" }
]
};
var grid = new Grid($element, gridOptions);
grid.editItem(gridOptions.data[0]);
equal(grid.fields[0].editControl.val(), "test", "complex property value set in editor");
});
test("should not fail if property is absent", function() {
var $element = $("#jsGrid");
var gridOptions = {
loadMessage: "",
data: [
{ complexProp: { } }
],
fields: [
{ name: "complexProp.subprop.prop", title: "" }
]
};
new Grid($element, gridOptions);
equal($element.text(), "", "rendered empty value");
});
test("inserting", function() {
var $element = $("#jsGrid");
var insertingItem;
var gridOptions = {
inserting: true,
fields: [
{ type: "text", name: "complexProp.prop" }
],
onItemInserting: function(args) {
insertingItem = args.item;
}
};
var grid = new Grid($element, gridOptions);
grid.fields[0].insertControl.val("test");
grid.insertItem();
deepEqual(insertingItem, { complexProp: { prop: "test" } }, "inserting item has complex properties");
});
test("filtering", function() {
var $element = $("#jsGrid");
var loadFilter;
var gridOptions = {
filtering: true,
fields: [
{ type: "text", name: "complexProp.prop" }
],
controller: {
loadData: function(filter) {
loadFilter = filter;
}
}
};
var grid = new Grid($element, gridOptions);
grid.fields[0].filterControl.val("test");
grid.search();
deepEqual(loadFilter, { complexProp: { prop: "test" } }, "filter has complex properties");
});
test("updating", function() {
var $element = $("#jsGrid");
var updatingItem;
var gridOptions = {
editing: true,
data: [
{ complexProp: { } }
],
fields: [
{ type: "text", name: "complexProp.prop" }
],
onItemUpdating: function(args) {
updatingItem = args.item;
}
};
var grid = new Grid($element, gridOptions);
grid.editItem(gridOptions.data[0]);
grid.fields[0].editControl.val("test");
grid.updateItem();
deepEqual(updatingItem, { complexProp: { prop: "test" } }, "updating item has complex properties");
});
test("update nested prop", function() {
var $element = $("#jsGrid");
var updatingItem;
var previousItem;
var gridOptions = {
editing: true,
data: [
{ prop: { subprop1: "test1", subprop2: "test2" } }
],
fields: [
{ type: "text", name: "prop.subprop1" },
{ type: "text", name: "prop.subprop2" }
],
onItemUpdating: function(args) {
updatingItem = args.item;
}
};
var grid = new Grid($element, gridOptions);
grid.editItem(gridOptions.data[0]);
grid.fields[0].editControl.val("new_test1");
grid.updateItem();
var expectedUpdatingItem = {
prop: {
subprop1: "new_test1",
subprop2: "test2"
}
};
deepEqual(updatingItem, expectedUpdatingItem, "updating item has nested properties");
});
test("updating deeply nested prop", function() {
var $element = $("#jsGrid");
var updatingItem;
var previousItem;
var gridOptions = {
editing: true,
data: [
{ complexProp: { subprop1: { another_prop: "test" } } }
],
fields: [
{ type: "text", name: "complexProp.subprop1.prop1" },
{ type: "text", name: "complexProp.subprop1.subprop2.prop12" }
],
onItemUpdating: function(args) {
updatingItem = $.extend(true, {}, args.item);
previousItem = $.extend(true, {}, args.previousItem);
}
};
var grid = new Grid($element, gridOptions);
grid.editItem(gridOptions.data[0]);
grid.fields[0].editControl.val("test1");
grid.fields[1].editControl.val("test2");
grid.updateItem();
var expectedUpdatingItem = {
complexProp: {
subprop1: {
another_prop: "test",
prop1: "test1",
subprop2: { prop12: "test2" }
}
}
};
var expectedPreviousItem = {
complexProp: {
subprop1: {
another_prop: "test"
}
}
};
deepEqual(updatingItem, expectedUpdatingItem, "updating item has deeply nested properties");
deepEqual(previousItem, expectedPreviousItem, "previous item preserved correctly");
});
module("validation");
test("insertItem should call validation.validate", function() {
var $element = $("#jsGrid");
var fieldValidationRules = { test: "value" };
var validatingArgs;
var gridOptions = {
data: [],
inserting: true,
invalidNotify: $.noop,
validation: {
validate: function(args) {
validatingArgs = args;
return [];
}
},
fields: [
{ type: "text", name: "Name", validate: fieldValidationRules }
]
};
var grid = new Grid($element, gridOptions);
grid.fields[0].insertControl.val("test");
grid.insertItem();
deepEqual(validatingArgs, { value: "test", item: { Name: "test" }, itemIndex: -1,
row: grid._insertRow, rules: fieldValidationRules }, "validating args is provided");
});
test("insertItem rejected when data is not valid", function() {
var $element = $("#jsGrid");
var gridOptions = {
data: [],
inserting: true,
invalidNotify: $.noop,
validation: {
validate: function() {
return ["Error"];
}
},
fields: [
{ type: "text", name: "Name", validate: true }
]
};
var grid = new Grid($element, gridOptions);
grid.fields[0].insertControl.val("test");
grid.insertItem().done(function() {
ok(false, "insertItem should not be completed");
}).fail(function() {
ok(true, "insertItem should fail");
});
});
test("invalidClass is attached on invalid cell on inserting", function() {
var $element = $("#jsGrid");
var gridOptions = {
data: [],
inserting: true,
invalidNotify: $.noop,
validation: {
validate: function() {
return ["Error"];
}
},
fields: [
{ type: "text", name: "Id", visible: false },
{ type: "text", name: "Name", validate: true }
]
};
var grid = new Grid($element, gridOptions);
var $insertCell = grid._insertRow.children().eq(0);
grid.insertItem();
ok($insertCell.hasClass(grid.invalidClass), "invalid class is attached");
equal($insertCell.attr("title"), "Error", "cell tooltip contains error message");
});
test("onItemInvalid callback", function() {
var $element = $("#jsGrid");
var errors = ["Error"];
var onItemInvalidCalled = 0;
var onItemInvalidArgs;
var gridOptions = {
data: [],
inserting: true,
invalidNotify: $.noop,
onItemInvalid: function(args) {
onItemInvalidCalled++;
onItemInvalidArgs = args;
},
validation: {
validate: function(args) {
return !args.value ? errors : [];
}
},
fields: [
{ type: "text", name: "Name", validate: true }
]
};
var grid = new Grid($element, gridOptions);
grid.insertItem();
equal(onItemInvalidCalled, 1, "onItemInvalid is called, when item data is invalid");
deepEqual(onItemInvalidArgs, { grid: grid, errors: [{ field: grid.fields[0], message: "Error" }],
item: { Name: "" }, itemIndex: -1, row: grid._insertRow }, "arguments provided");
grid.fields[0].insertControl.val("test");
grid.insertItem();
equal(onItemInvalidCalled, 1, "onItemInvalid was not called, when data is valid");
});
test("invalidNotify", function() {
var $element = $("#jsGrid");
var errors = ["Error"];
var invalidNotifyCalled = 0;
var invalidNotifyArgs;
var gridOptions = {
data: [],
inserting: true,
invalidNotify: function(args) {
invalidNotifyCalled++;
invalidNotifyArgs = args;
},
validation: {
validate: function(args) {
return !args.value ? errors : [];
}
},
fields: [
{ type: "text", name: "Name", validate: true }
]
};
var grid = new Grid($element, gridOptions);
grid.insertItem();
equal(invalidNotifyCalled, 1, "invalidNotify is called, when item data is invalid");
deepEqual(invalidNotifyArgs, { grid: grid, errors: [{ field: grid.fields[0], message: "Error" }],
row: grid._insertRow, item: { Name: "" }, itemIndex: -1 }, "arguments provided");
grid.fields[0].insertControl.val("test");
grid.insertItem();
equal(invalidNotifyCalled, 1, "invalidNotify was not called, when data is valid");
});
test("invalidMessage", function() {
var $element = $("#jsGrid");
var invalidMessage;
var originalAlert = window.alert;
window.alert = function(message) {
invalidMessage = message;
};
try {
Grid.prototype.invalidMessage = "InvalidTest";
Grid.prototype.invalidNotify({ errors: [{ message: "Message1" }, { message: "Message2" }] });
var expectedInvalidMessage = ["InvalidTest", "Message1", "Message2"].join("\n");
equal(invalidMessage, expectedInvalidMessage, "message contains invalidMessage and field error messages");
} finally {
window.alert = originalAlert;
}
});
test("updateItem should call validation.validate", function() {
var $element = $("#jsGrid");
var validatingArgs;
var gridOptions = {
data: [{ Name: "" }],
editing: true,
invalidNotify: $.noop,
validation: {
validate: function(args) {
validatingArgs = args;
return ["Error"];
}
},
fields: [
{ type: "text", name: "Name", validate: "required" }
]
};
var grid = new Grid($element, gridOptions);
grid.editItem(gridOptions.data[0]);
grid.fields[0].editControl.val("test");
grid.updateItem();
deepEqual(validatingArgs, { value: "test", item: { Name: "test" }, itemIndex: 0,
row: grid._getEditRow(), rules: "required" }, "validating args is provided");
});
test("invalidClass is attached on invalid cell on updating", function() {
var $element = $("#jsGrid");
var gridOptions = {
data: [{}],
editing: true,
invalidNotify: $.noop,
validation: {
validate: function() {
return ["Error"];
}
},
fields: [
{ type: "text", name: "Name", validate: true }
]
};
var grid = new Grid($element, gridOptions);
grid.editItem(gridOptions.data[0]);
var $editCell = grid._getEditRow().children().eq(0);
grid.updateItem();
ok($editCell.hasClass(grid.invalidClass), "invalid class is attached");
equal($editCell.attr("title"), "Error", "cell tooltip contains error message");
});
test("validation should ignore not editable fields", function() {
var invalidNotifyCalled = 0;
var $element = $("#jsGrid");
var validatingArgs;
var gridOptions = {
data: [{ Name: "" }],
editing: true,
invalidNotify: function() {
invalidNotifyCalled++;
},
validation: {
validate: function() {
return ["Error"];
}
},
fields: [
{ type: "text", name: "Name", editing: false, validate: "required" }
]
};
var grid = new Grid($element, gridOptions);
grid.editItem(gridOptions.data[0]);
grid.updateItem();
equal(invalidNotifyCalled, 0, "data is valid");
});
module("api");
test("reset method should go the first page when pageLoading is truned on", function() {
var items = [{ Name: "1" }, { Name: "2" }];
var $element = $("#jsGrid");
var gridOptions = {
paging: true,
pageSize: 1,
pageLoading: true,
autoload: true,
controller: {
loadData: function(args) {
return {
data: [items[args.pageIndex - 1]],
itemsCount: items.length
};
}
},
fields: [
{ type: "text", name: "Name" }
]
};
var grid = new Grid($element, gridOptions);
grid.openPage(2);
grid.reset();
equal(grid._bodyGrid.text(), "1", "grid content reset");
});
module("i18n");
test("set locale by name", function() {
jsGrid.locales.my_lang = {
grid: {
test: "test_text"
}
};
jsGrid.locale("my_lang");
var $element = $("#jsGrid").jsGrid({});
equal($element.jsGrid("option", "test"), "test_text", "option localized");
});
test("set locale by config", function() {
jsGrid.locale( {
grid: {
test: "test_text"
}
});
var $element = $("#jsGrid").jsGrid({});
equal($element.jsGrid("option", "test"), "test_text", "option localized");
});
test("locale throws exception for unknown locale", function() {
throws(function() {
jsGrid.locale("unknown_lang");
}, /unknown_lang/, "locale threw an exception");
});
module("controller promise");
asyncTest("should support jQuery promise success callback", 1, function() {
var data = [];
var gridOptions = {
autoload: false,
controller: {
loadData: function() {
var d = $.Deferred();
setTimeout(function() {
d.resolve(data);
start();
});
return d.promise();
}
}
};
var grid = new Grid($("#jsGrid"), gridOptions);
var promise = grid._controllerCall("loadData", {}, false, $.noop);
promise.done(function(result) {
equal(result, data, "data provided to done callback");
});
});
asyncTest("should support jQuery promise fail callback", 1, function() {
var failArgs = {};
var gridOptions = {
autoload: false,
controller: {
loadData: function() {
var d = $.Deferred();
setTimeout(function() {
d.reject(failArgs);
start();
});
return d.promise();
}
}
};
var grid = new Grid($("#jsGrid"), gridOptions);
var promise = grid._controllerCall("loadData", {}, false, $.noop);
promise.fail(function(result) {
equal(result, failArgs, "fail args provided to fail callback");
});
});
asyncTest("should support JS promise success callback", 1, function() {
if(typeof Promise === "undefined") {
ok(true, "Promise not supported");
start();
return;
}
var data = [];
var gridOptions = {
autoload: false,
controller: {
loadData: function() {
return new Promise(function(resolve, reject) {
setTimeout(function() {
resolve(data);
start();
});
});
}
}
};
var grid = new Grid($("#jsGrid"), gridOptions);
var promise = grid._controllerCall("loadData", {}, false, $.noop);
promise.done(function(result) {
equal(result, data, "data provided to done callback");
});
});
asyncTest("should support JS promise fail callback", 1, function() {
if(typeof Promise === "undefined") {
ok(true, "Promise not supported");
start();
return;
}
var failArgs = {};
var gridOptions = {
autoload: false,
controller: {
loadData: function() {
return new Promise(function(resolve, reject) {
setTimeout(function() {
reject(failArgs);
start();
});
});
}
}
};
var grid = new Grid($("#jsGrid"), gridOptions);
var promise = grid._controllerCall("loadData", {}, false, $.noop);
promise.fail(function(result) {
equal(result, failArgs, "fail args provided to fail callback");
});
});
test("should support non-promise result", 1, function() {
var data = [];
var gridOptions = {
autoload: false,
controller: {
loadData: function() {
return data;
}
}
};
var grid = new Grid($("#jsGrid"), gridOptions);
var promise = grid._controllerCall("loadData", {}, false, $.noop);
promise.done(function(result) {
equal(result, data, "data provided to done callback");
});
});
module("renderTemplate");
test("should pass undefined and null arguments to the renderer", function() {
var rendererArgs;
var rendererContext;
var context = {};
var renderer = function() {
rendererArgs = arguments;
rendererContext = this;
};
Grid.prototype.renderTemplate(renderer, context, { arg1: undefined, arg2: null, arg3: "test" });
equal(rendererArgs.length, 3);
strictEqual(rendererArgs[0], undefined, "undefined passed");
strictEqual(rendererArgs[1], null, "null passed");
strictEqual(rendererArgs[2], "test", "null passed");
strictEqual(rendererContext, context, "context is preserved");
});
});
|