349 lines
16 KiB
JavaScript
Raw Normal View History

/// <reference path="../Scripts/References.js" />
(function (upshot, ko, undefined) {
module("ChangeTracking");
var observability = upshot.observability;
test("Explicit commit multiple property edits", 5, function () {
var submitCount = 0;
var propertyChangedCount = 0;
var dc = createTestContext(function () {
submitCount++;
}, true);
var entitySet = dc.getEntitySet("Product");
var prod = entitySet.getEntities()[0];
var state = entitySet.getEntityState(prod);
equal(state, upshot.EntityState.Unmodified);
entitySet.bind("propertyChanged", function () {
propertyChangedCount++;
});
$.observable(prod).property("Name", "xyz");
$.observable(prod).property("Name", "foo");
$.observable(prod).property("Price", 9.99);
equal(propertyChangedCount, 3);
state = entitySet.getEntityState(prod);
equal(state, upshot.EntityState.ClientUpdated);
equal(submitCount, 0);
dc.commitChanges();
equal(submitCount, 1);
});
asyncTest("Implicit commit multiple property edits", 5, function () {
var submitCount = 0;
var propertyChangedCount = 0;
var dc = createTestContext(function () {
submitCount++;
}, false);
var entitySet = dc.getEntitySet("Product");
var prod = entitySet.getEntities()[0];
var state = entitySet.getEntityState(prod);
equal(state, upshot.EntityState.Unmodified);
entitySet.bind("propertyChanged", function () {
propertyChangedCount++;
});
$.observable(prod).property("Name", "xyz");
$.observable(prod).property("Name", "foo");
$.observable(prod).property("Price", 9.99);
// before the timeout has expired we shouldn't have committed anything
equal(submitCount, 0);
equal(propertyChangedCount, 3);
state = entitySet.getEntityState(prod);
equal(state, upshot.EntityState.ClientUpdated);
// Here we queue the test verification and start so that it runs
// AFTER the queued commit
setTimeout(function () {
equal(submitCount, 1);
start();
}, 0);
});
asyncTest("Implicit commit multiple array operations", 5, function () {
var submitCount = 0;
var dc = createTestContext(function (options, editedEntities) {
submitCount++;
equal(editedEntities.length, 2);
}, false);
var entitySet = dc.getEntitySet("Product");
var prod = entitySet.getEntities()[0];
// do an insert
var newProd = {
ID: 2,
Name: "Frish Gnarbles",
Category: "Snacks",
Price: 7.99
};
$.observable(entitySet.getEntities()).insert(newProd);
var state = entitySet.getEntityState(newProd);
equal(state, upshot.EntityState.ClientAdded);
// do a delete
entitySet.deleteEntity(prod);
state = entitySet.getEntityState(prod);
equal(state, upshot.EntityState.ClientDeleted);
// before the timeout has expired we shouldn't have committed anything
equal(submitCount, 0);
// Here we queue the test verification and start so that it runs
// AFTER the queued commit
setTimeout(function () {
equal(submitCount, 1);
start();
}, 0);
});
/* TODO: We forced managed associations on for Dev11 beta, since unmanaged associations are broken.
test("Nested entities can be added to an entity, and navigation properties are untracked", 16, function () {
try {
upshot.observability.configuration = observability.knockout;
var manageAssociations = false;
var dc = createKoTestContext(function () { }, false, manageAssociations);
var orders = dc.getEntitySet("Order"),
orderDetails = dc.getEntitySet("OrderDetail"),
order = orders.getEntities()()[0],
order2 = orders.getEntities()()[1],
orderDetail = orderDetails.getEntities()()[0];
order.OrderDetails.remove(orderDetail);
equal(1, order.OrderDetails().length, "There should only be a single order detail");
equal(upshot.EntityState.Unmodified, orders.getEntityState(order), "The order should not be modified");
equal(upshot.EntityState.Unmodified, orderDetails.getEntityState(orderDetail), "The order detail should not be modified");
order.OrderDetails.push(orderDetail);
equal(2, order.OrderDetails().length, "There should be two order details");
equal(upshot.EntityState.Unmodified, orders.getEntityState(order), "The order should not be modified");
equal(upshot.EntityState.Unmodified, orderDetails.getEntityState(orderDetail), "The order detail should not be modified");
orderDetail.Order(order2);
equal(orderDetail.OrderId(), order2.Id(), "Ids should be equal");
equal(upshot.EntityState.Unmodified, orders.getEntityState(order2), "The order should not be modified");
equal(upshot.EntityState.ClientUpdated, orderDetails.getEntityState(orderDetail), "The order detail should not be modified");
equal(true, orderDetails.isUpdated(orderDetail, "OrderId"), "The OrderId should be modified");
equal(false, orderDetails.isUpdated(orderDetail, "Order"), "The Order should not be tracked");
var properties = [];
$.each(observability.knockout.unmap(orderDetail, "OrderDetail"), function (key, value) {
properties.push(key);
equal(ko.utils.unwrapObservable(orderDetail[key]), value, "Properties should be equal");
});
equal(properties.length, 4, "The should be 4 serialized properties");
} finally {
upshot.observability.configuration = observability.jquery;
}
});
*/
test("Nested entities can be added to an entity, and navigation properties are computed", 39, function () {
try {
upshot.observability.configuration = observability.knockout;
var dc = createKoTestContext(function () { }, false);
var orders = dc.getEntitySet("Order"),
orderDetails = dc.getEntitySet("OrderDetail"),
order = orders.getEntities()()[0],
order2 = orders.getEntities()()[1],
orderDetail = orderDetails.getEntities()()[0];
ok(order.OrderDetails.indexOf(orderDetail) >= 0 && order2.OrderDetails.indexOf(orderDetail) < 0 && orderDetail.Order() === order, "The order detail is a child of order1");
equal(orders.getEntityState(order), upshot.EntityState.Unmodified, "order1 should not be modified");
equal(orders.getEntityState(order2), upshot.EntityState.Unmodified, "order2 should not be modified");
equal(orderDetails.getEntityState(orderDetail), upshot.EntityState.Unmodified, "The order detail should not be modified");
equal(orderDetails.isUpdated(orderDetail, "OrderId"), false, "The OrderId should not be modified");
equal(orderDetails.isUpdated(orderDetail, "Order"), false, "The Order should not be tracked");
orderDetail.OrderId(order2.Id());
ok(order2.OrderDetails.indexOf(orderDetail) >= 0 && order.OrderDetails.indexOf(orderDetail) < 0 && orderDetail.Order() === order2, "The order detail is a child of order2");
equal(orders.getEntityState(order), upshot.EntityState.Unmodified, "order1 should not be modified");
equal(orders.getEntityState(order2), upshot.EntityState.Unmodified, "order2 should not be modified");
equal(orderDetails.getEntityState(orderDetail), upshot.EntityState.ClientUpdated, "The order detail should be ClientUpdated");
equal(orderDetails.isUpdated(orderDetail, "OrderId"), true, "The OrderId should be modified");
equal(orderDetails.isUpdated(orderDetail, "Order"), false, "The Order should not be tracked");
orderDetails.revertUpdates(orderDetail);
ok(order.OrderDetails.indexOf(orderDetail) >= 0 && order2.OrderDetails.indexOf(orderDetail) < 0 && orderDetail.Order() === order, "The order detail is a child of order1");
equal(orders.getEntityState(order), upshot.EntityState.Unmodified, "order1 should not be modified");
equal(orders.getEntityState(order2), upshot.EntityState.Unmodified, "order2 should not be modified");
equal(orderDetails.getEntityState(orderDetail), upshot.EntityState.Unmodified, "The order detail should not be modified");
equal(orderDetails.isUpdated(orderDetail, "OrderId"), false, "The OrderId should not be modified");
equal(orderDetails.isUpdated(orderDetail, "Order"), false, "The Order should not be tracked");
orderDetail.Order(order2);
ok(orderDetail.OrderId() === order2.Id(), "Ids should be equal");
equal(orders.getEntityState(order2), upshot.EntityState.Unmodified, "The order should not be modified");
equal(orderDetails.getEntityState(orderDetail), upshot.EntityState.ClientUpdated, "The order detail should be ClientUpdated");
equal(orderDetails.isUpdated(orderDetail, "OrderId"), true, "The OrderId should be modified");
equal(orderDetails.isUpdated(orderDetail, "Order"), false, "The Order should not be tracked");
orderDetails.revertUpdates(orderDetail);
ok(order.OrderDetails.indexOf(orderDetail) >= 0 && order2.OrderDetails.indexOf(orderDetail) < 0 && orderDetail.Order() === order, "The order detail is a child of order1");
equal(orders.getEntityState(order), upshot.EntityState.Unmodified, "order1 should not be modified");
equal(orders.getEntityState(order2), upshot.EntityState.Unmodified, "order2 should not be modified");
equal(orderDetails.getEntityState(orderDetail), upshot.EntityState.Unmodified, "The order detail should not be modified");
equal(orderDetails.isUpdated(orderDetail, "OrderId"), false, "The OrderId should not be modified");
equal(orderDetails.isUpdated(orderDetail, "Order"), false, "The Order should not be tracked");
orderDetail.Order(null);
equal(orderDetail.OrderId(), null, "FK should be null");
equal(orders.getEntityState(order), upshot.EntityState.Unmodified, "The old order should not be modified");
equal(orderDetails.getEntityState(orderDetail), upshot.EntityState.ClientUpdated, "The order detail should be ClientUpdated");
equal(orderDetails.isUpdated(orderDetail, "OrderId"), true, "The OrderId should be modified");
equal(orderDetails.isUpdated(orderDetail, "Order"), false, "The Order should not be tracked");
var properties = [];
$.each(observability.knockout.unmap(orderDetail, "OrderDetail"), function (key, value) {
properties.push(key);
equal(ko.utils.unwrapObservable(orderDetail[key]), value, "Properties should be equal");
});
equal(properties.length, 4, "The should be 4 serialized properties");
} finally {
upshot.observability.configuration = observability.jquery;
}
});
test("Nested entities can be added to an entity, and property changes do not bubble to the parent", 2, function () {
try {
upshot.observability.configuration = observability.knockout;
var dc = createKoTestContext(function () { }, false);
var orders = dc.getEntitySet("Order"),
orderDetails = dc.getEntitySet("OrderDetail"),
order = orders.getEntities()()[0],
orderDetail = orderDetails.getEntities()()[0];
orderDetail.Name("asdf");
equal(orders.getEntityState(order), upshot.EntityState.Unmodified, "The order should not be modified");
equal(orderDetails.getEntityState(orderDetail), upshot.EntityState.ClientUpdated, "The order detail should not be modified");
} finally {
upshot.observability.configuration = observability.jquery;
}
});
// Create and return a context using the specified submitChanges mock
function createTestContext(submitChangesMock, bufferChanges) {
var dataProvider = new upshot.DataProvider();
var implicitCommitHandler;
if (!bufferChanges) {
implicitCommitHandler = function () {
dc._commitChanges({ providerParameters: {} });
}
}
var dc = new upshot.DataContext(dataProvider, implicitCommitHandler);
dc._submitChanges = submitChangesMock;
// add a single product to the context
var type = "Product";
var products = [];
products.push({
ID: 1,
Name: "Crispy Snarfs",
Category: "Snacks",
Price: 12.99
});
products.push({
ID: 2,
Name: "Cheezy Snax",
Category: "Snacks",
Price: 1.99
});
// mock out enough metadata to do the attach
upshot.metadata(type, { key: ["ID"] });
dc.merge(products, type, null);
return dc;
}
function createKoTestContext(submitChangesMock, bufferChanges) {
var dataProvider = new upshot.DataProvider();
var implicitCommitHandler;
if (!bufferChanges) {
implicitCommitHandler = function () {
dc._commitChanges({ providerParameters: {} });
}
}
var dc = new upshot.DataContext(dataProvider, implicitCommitHandler);
dc._submitChanges = submitChangesMock;
// add a single product to the context
var manageAssociations = true; // TODO: Lift this to a createKoTestContext parameter when unmanaged associations is supported.
var OrderDetail = function (data) {
this.Id = ko.observable(data.Id);
this.Name = ko.observable(data.Name);
this.Order = ko.observable();
this.OrderId = manageAssociations ? ko.observable(data.OrderId) : ko.computed(function () {
return this.Order() ? this.Order().Id() : data.OrderId;
}, this);
this.Extra = ko.observable("extra");
};
var Order = function (data) {
this.Id = ko.observable(data.Id);
this.Name = ko.observable(data.Name);
this.OrderDetails = ko.observableArray(ko.utils.arrayMap(data.OrderDetails, function (od) { return new OrderDetail(od); }));
this.Extra = ko.observable("extra");
};
var orders = [],
order = {
Id: 1,
Name: "Order 1",
OrderDetails: []
};
orders.push(new Order(order));
orders.push(new Order({
Id: 2,
Name: "Order 2",
OrderDetails: []
}));
var orderDetails = [];
orderDetails.push(new OrderDetail({
Id: 1,
Name: "Order Detail 1",
OrderId: order.Id
}));
orderDetails.push(new OrderDetail({
Id: 2,
Name: "Order Detail 2",
OrderId: order.Id
}));
orders[0].OrderDetails(orderDetails);
// mock out enough metadata to do the attach
upshot.metadata("Order", { key: ["Id"], fields: { Id: { type: "Int32:#System" }, Name: { type: "String:#System" }, OrderDetails: { type: "OrderDetail", association: { Name: "O_OD", isForeignKey: false, thisKey: ["Id"], otherKey: ["OrderId"] }, array: true } } });
upshot.metadata("OrderDetail", { key: ["Id"], fields: { Id: { type: "Int32:#System" }, Name: { type: "String:#System" }, Order: { type: "Order", association: { Name: "O_OD", isForeignKey: true, thisKey: ["OrderId"], otherKey: ["Id"]} }, OrderId: { type: "Int32:#System"}} });
dc.merge(orders, "Order", null);
return dc;
}
})(upshot, ko);