Jo Shields a575963da9 Imported Upstream version 3.6.0
Former-commit-id: da6be194a6b1221998fc28233f2503bd61dd9d14
2014-08-13 10:39:27 +01:00

1526 lines
78 KiB
JavaScript

/// <reference path="../Scripts/References.js" />
(function (global, $, upshot, undefined) {
module("EntitySet.tests.js");
var datasets = upshot.test.datasets,
observability = upshot.observability;
// direct tests against the default identity algorithm
test("Compute identity tests", 14, function () {
var metadata = {
A: { key: ["k1"] },
B: { key: ["k1", "k2", "k3"] },
C: {}, // missing key metadata
D: { key: ["a.b.k1", "a.b.k2"] }
};
var dc = new upshot.DataContext(new upshot.riaDataProvider());
upshot.metadata(metadata);
// valid single part key scenarios
equal(upshot.EntitySet.__getIdentity({ k1: "1" }, "A"), "1");
equal(upshot.EntitySet.__getIdentity({ k1: 1234 }, "A"), "1234");
equal(upshot.EntitySet.__getIdentity({ k1: 1.234 }, "A"), "1.234");
equal(upshot.EntitySet.__getIdentity({ k1: "E93CF47D-E7A6-44B2-8E30-0869B187BFB4" }, "A"), "E93CF47D-E7A6-44B2-8E30-0869B187BFB4");
// valid multipart key scenarios
equal(upshot.EntitySet.__getIdentity({ k1: "1", k2: "2", k3: "3" }, "B"), "1,2,3");
equal(upshot.EntitySet.__getIdentity({ k1: 1, k2: 2, k3: 3 }, "B"), "1,2,3");
equal(upshot.EntitySet.__getIdentity({ k1: true, k2: "E93CF47D-E7A6-44B2-8E30-0869B187BFB4", k3: 5 }, "B"), "true,E93CF47D-E7A6-44B2-8E30-0869B187BFB4,5");
equal(upshot.EntitySet.__getIdentity({ k1: 1, k2: null, k3: undefined }, "B"), "1,null,undefined");
// verify pathing scenarios (e.g. used by the OData provider)
equal(upshot.EntitySet.__getIdentity({ a: { b: { k1: "1", k2: "2"}} }, "D"), "1,2");
// no key metadata specified
try {
upshot.EntitySet.__getIdentity({ k1: "1", k2: "2", k3: "3" }, "C", "C");
}
catch (e) {
equal(e, "No key metadata specified for entity type 'C'");
}
// invalid key member specification - missing member
try {
upshot.EntitySet.__getIdentity({ k1: "1", k2: "2" /* missing k3 member */ }, "B");
}
catch (e) {
equal(e, "Key member 'k3' doesn't exist on entity type 'B'");
}
// invalid path specification - missing member
try {
upshot.EntitySet.__getIdentity({ a: { b: { k1: "1" /* k2 member missing */}} }, "D");
}
catch (e) {
equal(e, "Key member 'a.b.k2' doesn't exist on entity type 'D'");
}
// invalid path specification - null path part
try {
upshot.EntitySet.__getIdentity({ a: { b: null} }, "D");
}
catch (e) {
equal(e, "Key member 'a.b.k1' doesn't exist on entity type 'D'");
}
// no metadata registered for type
try {
upshot.EntitySet.__getIdentity({}, "E");
}
catch (e) {
equal(e, "No metadata available for type 'E'. Register metadata using 'upshot.metadata(...)'.");
}
});
test("Load entities with multipart keys", 4, function () {
var metadata = {
A: { key: ["k1"] },
B: { key: ["k1", "k2", "k3"] }
};
var dc = new upshot.DataContext(new upshot.riaDataProvider());
upshot.metadata(metadata);
var entities = [{ k1: "1" }, { k1: 1234 }, { k1: 1.234 }, { k1: "E93CF47D-E7A6-44B2-8E30-0869B187BFB4"}];
dc.merge(entities, "A", null);
entities = [
{ k1: "1", k2: "2", k3: "3" },
{ k1: 1, k2: 2, k3: 3 },
{ k1: true, k2: "E93CF47D-E7A6-44B2-8E30-0869B187BFB4", k3: 5 }
];
dc.merge(entities, "B", null);
// verify the entities are in the cache
equal(dc.getEntitySet("A")._entityStates["1"], upshot.EntityState.Unmodified);
equal(dc.getEntitySet("A")._entityStates["E93CF47D-E7A6-44B2-8E30-0869B187BFB4"], upshot.EntityState.Unmodified);
equal(dc.getEntitySet("B")._entityStates["1,2,3"], upshot.EntityState.Unmodified);
equal(dc.getEntitySet("B")._entityStates["true,E93CF47D-E7A6-44B2-8E30-0869B187BFB4,5"], upshot.EntityState.Unmodified);
});
test("Raises events when primitive values change", 10, function () {
var es = createEntitySet(),
entity = loadEntities(es, datasets.primitives.create(1));
equal(es.getEntities().length, 1, "There should be a single entity loaded");
var tracker = createEventTracker(es);
$.observable(entity).property("B", false);
equal(tracker.events.length, 2, "There should have been two events");
equal(tracker.events[0].type, "propertyChanged", "The event should be 'propertyChanged'");
equal(tracker.events[0].entity, entity, "The entity should have been modified");
equal(tracker.events[0].path, "B", "Property 'B' should have been set");
equal(tracker.events[0].value, entity.B, "The new value should be false");
equal(tracker.events[1].type, "entityUpdated", "The event should be 'entityUpdated'");
equal(tracker.events[1].entity, entity, "The entity should have been modified");
equal(tracker.events[1].path, "", "The event should have occured on the entity");
notEqual(tracker.events[1].eventArgs, null, "The event args should not be null");
});
test("Raises events when scalar values change", 10, function () {
var es = createEntitySet(),
entity = loadEntities(es, datasets.scalars.create(1));
equal(es.getEntities().length, 1, "There should be a single entity loaded");
var tracker = createEventTracker(es);
$.observable(entity).property("D", new Date());
equal(tracker.events.length, 2, "There should have been two events");
equal(tracker.events[0].type, "propertyChanged", "The event should be 'propertyChanged'");
equal(tracker.events[0].entity, entity, "The entity should have been modified");
equal(tracker.events[0].path, "D", "Property 'D' should have been set");
equal(tracker.events[0].value, entity.D, "The new value should be false");
equal(tracker.events[1].type, "entityUpdated", "The event should be 'entityUpdated'");
equal(tracker.events[1].entity, entity, "The entity should have been modified");
equal(tracker.events[1].path, "", "The event should have occured on the entity");
notEqual(tracker.events[1].eventArgs, null, "The event args should not be null");
});
test("Raises event when nested values change", 6, function () {
var es = createEntitySet(),
entity = loadEntities(es, datasets.nested.create(1));
equal(es.getEntities().length, 1, "There should be a single entity loaded");
var tracker = createEventTracker(es);
$.observable(entity.O).property("B", false);
equal(tracker.events.length, 1, "There should have been one event");
equal(tracker.events[0].type, "entityUpdated", "The event should be 'entityUpdated'");
equal(tracker.events[0].entity, entity, "The entity should have been modified");
equal(tracker.events[0].path, "O", "The event should have occured on 'O'");
notEqual(tracker.events[0].eventArgs, null, "The event args should not be null");
});
test("Raises event when tree values change", 6, function () {
var es = createEntitySet(),
entity = loadEntities(es, datasets.tree.create(1));
equal(es.getEntities().length, 1, "There should be a single entity loaded");
var tracker = createEventTracker(es);
$.observable(entity.O.O1).property("B", false);
equal(tracker.events.length, 1, "There should have been one event");
equal(tracker.events[0].type, "entityUpdated", "The event should be 'entityUpdated'");
equal(tracker.events[0].entity, entity, "The entity should have been modified");
equal(tracker.events[0].path, "O.O1", "The event should have occured on 'O.O1'");
notEqual(tracker.events[0].eventArgs, null, "The event args should not be null");
});
test("Raises event when array values change", 6, function () {
var es = createEntitySet(),
entity = loadEntities(es, datasets.array.create(1));
equal(es.getEntities().length, 1, "There should be a single entity loaded");
var tracker = createEventTracker(es);
$.observable(entity.A[0]).property("B", false);
equal(tracker.events.length, 1, "There should have been one event");
equal(tracker.events[0].type, "entityUpdated", "The event should be 'entityUpdated'");
equal(tracker.events[0].entity, entity, "The entity should have been modified");
equal(tracker.events[0].path, "A[0]", "The event should have occured on 'A[0]'");
notEqual(tracker.events[0].eventArgs, null, "The event args should not be null");
});
test("Raises event when nested array values change", 6, function () {
var es = createEntitySet(),
entity = loadEntities(es, datasets.nestedArrays.create(1));
equal(es.getEntities().length, 1, "There should be a single entity loaded");
var tracker = createEventTracker(es);
$.observable(entity.A[0].A[0]).property("B", false);
equal(tracker.events.length, 1, "There should have been one event");
equal(tracker.events[0].type, "entityUpdated", "The event should be 'entityUpdated'");
equal(tracker.events[0].entity, entity, "The entity should have been modified");
equal(tracker.events[0].path, "A[0].A[0]", "The event should have occured on 'A[0].A[0]'");
notEqual(tracker.events[0].eventArgs, null, "The event args should not be null");
});
test("Raises events on revertChanges", 11, function () {
var es = createEntitySet(),
entity = loadEntities(es, datasets.primitives.create(1));
equal(es.getEntities().length, 1, "There should be a single entity loaded");
var tracker = createEventTracker(es);
$.observable(entity).property("B", false);
equal(tracker.events.length, 2, "There should have been two events");
tracker.events.length = 0;
es.revertChanges();
equal(tracker.events.length, 2, "There should have been two events");
equal(tracker.events[0].type, "propertyChanged", "The event should be 'propertyChanged'");
equal(tracker.events[0].entity, entity, "The entity should have been modified");
equal(tracker.events[0].path, "B", "Property 'B' should have been set");
equal(tracker.events[0].value, entity.B, "The reverted value should be true");
equal(tracker.events[1].type, "entityUpdated", "The event should be 'entityUpdated'");
equal(tracker.events[1].entity, entity, "The entity should have been modified");
equal(tracker.events[1].path, undefined, "The event path should be undefined");
equal(tracker.events[1].eventArgs, undefined, "The event args should be undefined");
});
test("Raises events on revertChanges with entity", 11, function () {
var es = createEntitySet(),
entity = loadEntities(es, datasets.primitives.create(1));
equal(es.getEntities().length, 1, "There should be a single entity loaded");
var tracker = createEventTracker(es);
$.observable(entity).property("B", false);
equal(tracker.events.length, 2, "There should have been two events");
tracker.events.length = 0;
es.revertChanges(entity);
equal(tracker.events.length, 2, "There should have been two events");
equal(tracker.events[0].type, "propertyChanged", "The event should be 'propertyChanged'");
equal(tracker.events[0].entity, entity, "The entity should have been modified");
equal(tracker.events[0].path, "B", "Property 'B' should have been set");
equal(tracker.events[0].value, entity.B, "The reverted value should be true");
equal(tracker.events[1].type, "entityUpdated", "The event should be 'entityUpdated'");
equal(tracker.events[1].entity, entity, "The entity should have been modified");
equal(tracker.events[1].path, undefined, "The event path should be undefined");
equal(tracker.events[1].eventArgs, undefined, "The event args should be undefined");
});
test("Raises events on revertUpdates", 11, function () {
var es = createEntitySet(),
entity = loadEntities(es, datasets.primitives.create(1));
equal(es.getEntities().length, 1, "There should be a single entity loaded");
var tracker = createEventTracker(es);
$.observable(entity).property("B", false);
equal(tracker.events.length, 2, "There should have been two events");
tracker.events.length = 0;
es.revertUpdates(entity);
equal(tracker.events.length, 2, "There should have been two events");
equal(tracker.events[0].type, "propertyChanged", "The event should be 'propertyChanged'");
equal(tracker.events[0].entity, entity, "The entity should have been modified");
equal(tracker.events[0].path, "B", "Property 'B' should have been set");
equal(tracker.events[0].value, entity.B, "The reverted value should be true");
equal(tracker.events[1].type, "entityUpdated", "The event should be 'entityUpdated'");
equal(tracker.events[1].entity, entity, "The entity should have been modified");
equal(tracker.events[1].path, undefined, "The event path should be undefined");
equal(tracker.events[1].eventArgs, undefined, "The event args should be undefined");
});
test("Raises events on revertUpdates for property", 11, function () {
var es = createEntitySet(),
entity = loadEntities(es, datasets.primitives.create(1));
equal(es.getEntities().length, 1, "There should be a single entity loaded");
var tracker = createEventTracker(es);
$.observable(entity).property("B", false);
equal(tracker.events.length, 2, "There should have been two events");
tracker.events.length = 0;
es.revertUpdates(entity, "B");
equal(tracker.events.length, 2, "There should have been two events");
equal(tracker.events[0].type, "propertyChanged", "The event should be 'propertyChanged'");
equal(tracker.events[0].entity, entity, "The entity should have been modified");
equal(tracker.events[0].path, "B", "Property 'B' should have been set");
equal(tracker.events[0].value, entity.B, "The reverted value should be true");
equal(tracker.events[1].type, "entityUpdated", "The event should be 'entityUpdated'");
equal(tracker.events[1].entity, entity, "The entity should have been modified");
equal(tracker.events[1].path, undefined, "The event path should be undefined");
equal(tracker.events[1].eventArgs, undefined, "The event args should be undefined");
});
test("Raises event when knockout array values change", 6, function () {
try {
upshot.observability.configuration = observability.knockout;
var es = createEntitySet(),
entity = loadEntities(es, datasets.ko_array(1));
equal(es.getEntities()().length, 1, "There should be a single entity loaded");
var tracker = createEventTracker(es);
entity.A()[0].B(false);
equal(tracker.events.length, 1, "There should have been one event");
equal(tracker.events[0].type, "entityUpdated", "The event should be 'entityUpdated'");
equal(tracker.events[0].entity, entity, "The entity should have been modified");
equal(tracker.events[0].path, "A[0]", "The event should have occured on 'A[0]'");
notEqual(tracker.events[0].eventArgs, null, "The event args should not be null");
} finally {
upshot.observability.configuration = observability.jquery;
}
});
test("Subscriptions are adjusted when nested values change", 5, function () {
var es = createEntitySet(),
entity = loadEntities(es, datasets.nested.create(1));
equal(es.getEntities().length, 1, "There should be a single entity loaded");
var original = entity.O,
_new = { B: false };
var tracker = createEventTracker(es);
$.observable(original).property("B", false);
equal(tracker.events.length, 1, "There should have been one event");
tracker.events.length = 0;
$.observable(entity).property("O", _new);
equal(tracker.events.length, 2, "There should have been two events");
tracker.events.length = 0;
$.observable(original).property("B", true);
equal(tracker.events.length, 0, "There should not have been any events");
$.observable(_new).property("B", true);
equal(tracker.events.length, 1, "There should have been one event");
});
test("Subscriptions are adjusted when tree values change", 5, function () {
var es = createEntitySet(),
entity = loadEntities(es, datasets.tree.create(1));
equal(es.getEntities().length, 1, "There should be a single entity loaded");
var original = entity.O,
_new = { O1: { B: false} };
var tracker = createEventTracker(es);
$.observable(original.O1).property("B", false);
equal(tracker.events.length, 1, "There should have been one event");
tracker.events.length = 0;
$.observable(entity).property("O", _new);
equal(tracker.events.length, 2, "There should have been two events");
tracker.events.length = 0;
$.observable(original.O1).property("B", true);
equal(tracker.events.length, 0, "There should not have been any events");
tracker.events.length = 0;
$.observable(_new.O1).property("B", true);
equal(tracker.events.length, 1, "There should have been one event");
});
test("Subscriptions are added on array insert", 3, function () {
var es = createEntitySet(),
entity = loadEntities(es, datasets.array.create(1));
equal(es.getEntities().length, 1, "There should be a single entity loaded");
var _new = { B: false };
var tracker = createEventTracker(es);
$.observable(entity.A).insert(entity.A.length, _new);
equal(tracker.events.length, 1, "There should have been one event");
tracker.events.length = 0;
$.observable(_new).property("B", true);
equal(tracker.events.length, 1, "There should have been one event");
});
test("Subscriptions are removed on array remove", 4, function () {
var es = createEntitySet(),
entity = loadEntities(es, datasets.array.create(1));
equal(es.getEntities().length, 1, "There should be a single entity loaded");
var original = entity.A[0];
var tracker = createEventTracker(es);
$.observable(original).property("B", false);
equal(tracker.events.length, 1, "There should have been one event");
tracker.events.length = 0;
$.observable(entity.A).remove(0, 1);
equal(tracker.events.length, 1, "There should have been one event");
tracker.events.length = 0;
$.observable(original).property("B", true);
equal(tracker.events.length, 0, "There should not have been any events");
});
test("Subscriptions are adjusted on array replaceAll", 5, function () {
var es = createEntitySet(),
entity = loadEntities(es, datasets.array.create(1));
equal(es.getEntities().length, 1, "There should be a single entity loaded");
var original = entity.A[0],
_new = { B: false };
var tracker = createEventTracker(es);
$.observable(original).property("B", false);
equal(tracker.events.length, 1, "There should have been one event");
tracker.events.length = 0;
$.observable(entity.A).replaceAll([_new]);
equal(tracker.events.length, 1, "There should have been one event");
tracker.events.length = 0;
$.observable(original).property("B", true);
equal(tracker.events.length, 0, "There should not have been any events");
tracker.events.length = 0;
$.observable(_new).property("B", true);
equal(tracker.events.length, 1, "There should have been one event");
});
testWithRevertVariations(function (revertFn) {
test("isUpdated returns true when primitive values change", 17, function () {
var es = createEntitySet(),
entity = loadEntities(es, datasets.primitives.create(1));
equal(es.getEntities().length, 1, "There should be a single entity loaded");
equal(es.getEntityState(entity), upshot.EntityState.Unmodified, "The entity state should be 'Unmodified'");
equal(es.isUpdated(entity), false, "The entity should not have changes");
equal(es.isUpdated(entity, "B"), false, "The entity should not have changes for 'B'");
$.observable(entity).property("B", false);
equal(es.getEntityState(entity), upshot.EntityState.ClientUpdated, "The entity state should be 'ClientUpdated'");
equal(es.isUpdated(entity), true, "The entity should have changes");
equal(es.isUpdated(entity, "B"), true, "The entity should have changes for 'B'");
equal(es.isUpdated(entity, "N"), false, "The entity should not have changes for 'N'");
$.observable(entity).property("B", true);
equal(es.getEntityState(entity), upshot.EntityState.ClientUpdated, "The entity state should still be 'ClientUpdated'");
equal(es.isUpdated(entity), true, "The entity should still have changes");
equal(es.isUpdated(entity, "B"), true, "The entity should still have changes for 'B'");
equal(es.isUpdated(entity, "N"), false, "The entity should still not have changes for 'N'");
revertFn(es, entity, "B");
equal(es.isUpdated(entity, "B"), false, "The entity should no longer have changes for 'B'");
dataEqual(entity, datasets.primitives.create(1), "The entity should be reverted");
});
});
testWithRevertVariations(function (revertFn) {
test("isUpdated returns true when scalar values change", 12, function () {
var es = createEntitySet(),
entity = loadEntities(es, datasets.scalars.create(1));
equal(es.getEntities().length, 1, "There should be a single entity loaded");
equal(es.getEntityState(entity), upshot.EntityState.Unmodified, "The entity state should be 'Unmodified'");
equal(es.isUpdated(entity), false, "The entity should not have changes");
equal(es.isUpdated(entity, "D"), false, "The entity should not have changes for 'D'");
$.observable(entity).property("D", new Date());
equal(es.getEntityState(entity), upshot.EntityState.ClientUpdated, "The entity state should be 'ClientUpdated'");
equal(es.isUpdated(entity), true, "The entity should have changes");
equal(es.isUpdated(entity, "D"), true, "The entity should have changes for 'D'");
revertFn(es, entity, "D");
equal(es.isUpdated(entity, "D"), false, "The entity should no longer have changes for 'D'");
dataEqual(entity, datasets.scalars.create(1), "The entity should be reverted");
});
});
testWithRevertVariations(true, function (revertFn) {
test("isUpdated returns true when nested values change", 15, function () {
var es = createEntitySet(),
entity = loadEntities(es, datasets.nested.create(1));
equal(es.getEntities().length, 1, "There should be a single entity loaded");
equal(es.getEntityState(entity), upshot.EntityState.Unmodified, "The entity state should be 'Unmodified'");
equal(es.isUpdated(entity), false, "The entity should not have changes");
equal(es.isUpdated(entity, "O"), false, "The nested object 'O' should not have changes");
equal(es.isUpdated(entity, "O.B"), false, "The nested object 'O' should not have changes for 'B'");
$.observable(entity.O).property("B", false);
equal(es.getEntityState(entity), upshot.EntityState.ClientUpdated, "The entity state should be 'ClientUpdated'");
equal(es.isUpdated(entity), true, "The entity should have changes");
equal(es.isUpdated(entity, "O"), true, "The nested object 'O' should have changes");
equal(es.isUpdated(entity, "O.B"), true, "The nested object 'O' should have changes for 'B'");
equal(es.isUpdated(entity, "O", true), false, "The entity should not have changes for 'O'");
revertFn(es, entity, "O");
equal(es.isUpdated(entity, "O"), false, "The nested object 'O' should no longer have changes");
equal(es.isUpdated(entity, "O.B"), false, "The nested object 'O' should no longer have changes for 'B'");
dataEqual(entity, datasets.nested.create(1), "The entity should be reverted");
});
});
testWithRevertVariations(true, function (revertFn) {
test("isUpdated returns true when tree values change", 19, function () {
var es = createEntitySet(),
entity = loadEntities(es, datasets.tree.create(1));
equal(es.getEntities().length, 1, "There should be a single entity loaded");
equal(es.getEntityState(entity), upshot.EntityState.Unmodified, "The entity state should be 'Unmodified'");
equal(es.isUpdated(entity), false, "The entity should not have changes");
equal(es.isUpdated(entity, "O"), false, "The nested object 'O' should not have changes");
equal(es.isUpdated(entity, "O.O1"), false, "The nested object 'O.O1' should not have changes");
equal(es.isUpdated(entity, "O.O1.B"), false, "The nested object 'O.O1' should not have changes for 'B'");
$.observable(entity.O.O1).property("B", false);
equal(es.getEntityState(entity), upshot.EntityState.ClientUpdated, "The entity state should be 'ClientUpdated'");
equal(es.isUpdated(entity), true, "The entity should have changes");
equal(es.isUpdated(entity, "O"), true, "The nested object 'O' should have changes");
equal(es.isUpdated(entity, "O.O1"), true, "The nested object 'O.O1' should have changes");
equal(es.isUpdated(entity, "O.O1.B"), true, "The nested object 'O.O1' should have changes for 'B'");
equal(es.isUpdated(entity, "O", true), false, "The entity should not have changes for 'O'");
equal(es.isUpdated(entity, "O.O1", true), false, "The nested object 'O' should not have changes for 'O1'");
revertFn(es, entity, "O");
equal(es.isUpdated(entity, "O"), false, "The nested object 'O' should no longer have changes");
equal(es.isUpdated(entity, "O.O1"), false, "The nested object 'O.O1' should no longer have changes");
equal(es.isUpdated(entity, "O.O1.B"), false, "The nested object 'O.O1' should no longer have changes for 'B'");
dataEqual(entity, datasets.tree.create(1), "The entity should be reverted");
});
});
testWithRevertVariations(true, function (revertFn) {
test("isUpdated returns true when array values change", 18, function () {
var es = createEntitySet(),
entity = loadEntities(es, datasets.array.create(1));
equal(es.getEntities().length, 1, "There should be a single entity loaded");
equal(es.getEntityState(entity), upshot.EntityState.Unmodified, "The entity state should be 'Unmodified'");
equal(es.isUpdated(entity), false, "The entity should not have changes");
equal(es.isUpdated(entity, "A"), false, "The array should not have changes");
equal(es.isUpdated(entity, "A[0]"), false, "The object at index 0 should not have changes");
equal(es.isUpdated(entity, "A[0].B"), false, "The object at index 0 should not have changes for 'B'");
$.observable(entity.A[0]).property("B", false);
equal(es.getEntityState(entity), upshot.EntityState.ClientUpdated, "The entity state should be 'ClientUpdated'");
equal(es.isUpdated(entity), true, "The entity should have changes");
equal(es.isUpdated(entity, "A"), true, "The array should have changes");
equal(es.isUpdated(entity, "A[0]"), true, "The object at index 0 should have changes");
equal(es.isUpdated(entity, "A[0].B"), true, "The object at index 0 should have changes for 'B'");
equal(es.isUpdated(entity, "A", true), false, "The entity should not have changes for 'A'");
revertFn(es, entity, "A");
equal(es.isUpdated(entity, "A"), false, "The array should no longer have changes");
equal(es.isUpdated(entity, "A[0]"), false, "The object at index 0 should no longer have changes");
equal(es.isUpdated(entity, "A[0].B"), false, "The object at index 0 should no longer have changes for 'B'");
dataEqual(entity, datasets.array.create(1), "The entity should be reverted");
});
});
testWithRevertVariations(true, function (revertFn) {
test("isUpdated returns true when nested array values change", 25, function () {
var es = createEntitySet(),
entity = loadEntities(es, datasets.nestedArrays.create(1));
equal(es.getEntities().length, 1, "There should be a single entity loaded");
equal(es.getEntityState(entity), upshot.EntityState.Unmodified, "The entity state should be 'Unmodified'");
equal(es.isUpdated(entity), false, "The entity should not have changes");
equal(es.isUpdated(entity, "A"), false, "The array should not have changes");
equal(es.isUpdated(entity, "A[0]"), false, "The object at index 0 should not have changes");
equal(es.isUpdated(entity, "A[0].A"), false, "The nested array should not have changes");
equal(es.isUpdated(entity, "A[0].A[0]"), false, "The nested object at index 0 should not have changes");
equal(es.isUpdated(entity, "A[0].A[0].B"), false, "The nested object at index 0 should not have changes for 'B'");
$.observable(entity.A[0].A[0]).property("B", false);
equal(es.getEntityState(entity), upshot.EntityState.ClientUpdated, "The entity state should be 'ClientUpdated'");
equal(es.isUpdated(entity), true, "The entity should have changes");
equal(es.isUpdated(entity, "A"), true, "The array should have changes");
equal(es.isUpdated(entity, "A[0]"), true, "The object at index 0 should have changes");
equal(es.isUpdated(entity, "A[0].A"), true, "The nested array should have changes");
equal(es.isUpdated(entity, "A[0].A[0]"), true, "The nested object at index 0 should have changes");
equal(es.isUpdated(entity, "A[0].A[0].B"), true, "The nested object at index 0 should have changes for 'B'");
equal(es.isUpdated(entity, "A", true), false, "The entity should not have changes for 'A'");
equal(es.isUpdated(entity, "A[0].A", true), false, "The object at index 0 not have changes for 'A'");
revertFn(es, entity, "A");
equal(es.isUpdated(entity, "A"), false, "The array should no longer have changes");
equal(es.isUpdated(entity, "A[0]"), false, "The object at index 0 should no longer have changes");
equal(es.isUpdated(entity, "A[0].A"), false, "The nested array should no longer have changes");
equal(es.isUpdated(entity, "A[0].A[0]"), false, "The nested object at index 0 should no longer have changes");
equal(es.isUpdated(entity, "A[0].A[0].B"), false, "The nested object at index 0 should no longer have changes for 'B'");
dataEqual(entity, datasets.nestedArrays.create(1), "The entity should be reverted");
});
});
testWithRevertVariations(function (revertFn) {
test("isUpdated returns true when knockout primitive values change", 27, function () {
try {
upshot.observability.configuration = observability.knockout;
var es = createEntitySet(),
entity = loadEntities(es, datasets.ko_primitives(1, true));
equal(es.getEntities()().length, 1, "There should be a single entity loaded");
equal(es.getEntityState(entity), upshot.EntityState.Unmodified, "The entity state should be 'Unmodified'");
equal(es.isUpdated(entity), false, "The entity should not have changes");
equal(es.isUpdated(entity, "B"), false, "The entity should not have changes for 'B'");
equal(entity.IsUpdated(), false, "The entity should not be changed");
equal(entity.B.IsUpdated(), false, "The entity should not be changed for 'B'");
entity.B(false);
equal(es.getEntityState(entity), upshot.EntityState.ClientUpdated, "The entity state should be 'ClientUpdated'");
equal(es.isUpdated(entity), true, "The entity should have changes");
equal(es.isUpdated(entity, "B"), true, "The entity should have changes for 'B'");
equal(es.isUpdated(entity, "N"), false, "The entity should not have changes for 'N'");
equal(entity.IsUpdated(), true, "The entity should be changed");
equal(entity.B.IsUpdated(), true, "The entity should be changed for 'B'");
equal(entity.N.IsUpdated(), false, "The entity should not be changed for 'N'");
entity.B(true);
equal(es.getEntityState(entity), upshot.EntityState.ClientUpdated, "The entity state should still be 'ClientUpdated'");
equal(es.isUpdated(entity), true, "The entity should still have changes");
equal(es.isUpdated(entity, "B"), true, "The entity should still have changes for 'B'");
equal(es.isUpdated(entity, "N"), false, "The entity should still not have changes for 'N'");
equal(entity.IsUpdated(), true, "The entity should still be changed");
equal(entity.B.IsUpdated(), true, "The entity should still be changed for 'B'");
equal(entity.N.IsUpdated(), false, "The entity should still not be changed for 'N'");
revertFn(es, entity, "B");
equal(es.isUpdated(entity, "B"), false, "The entity should no longer have changes for 'B'");
equal(entity.IsUpdated(), false, "The entity should no longer be changed");
equal(entity.B.IsUpdated(), false, "The entity should no longer be changed for 'B'");
dataEqual(entity, datasets.ko_primitives(1), "The entity should be reverted");
} finally {
upshot.observability.configuration = observability.jquery;
}
});
});
testWithRevertVariations(true, function (revertFn) {
test("isUpdated returns true when knockout tree values change", 29, function () {
try {
upshot.observability.configuration = observability.knockout;
var es = createEntitySet(),
entity = loadEntities(es, datasets.ko_tree(1, true));
equal(es.getEntities()().length, 1, "There should be a single entity loaded");
equal(es.getEntityState(entity), upshot.EntityState.Unmodified, "The entity state should be 'Unmodified'");
equal(es.isUpdated(entity), false, "The entity should not have changes");
equal(es.isUpdated(entity, "O"), false, "The nested object 'O' should not have changes");
equal(es.isUpdated(entity, "O.O1"), false, "The nested object 'O.O1' should not have changes");
equal(es.isUpdated(entity, "O.O1.B"), false, "The nested object 'O.O1' should not have changes for 'B'");
equal(entity.IsUpdated(), false, "The entity should not be changed");
equal(entity.O.IsUpdated(), false, "The nested object 'O' should not be changed");
equal(entity.O().O1.IsUpdated(), false, "The nested object 'O.O1' should not be changed");
equal(entity.O().O1().B.IsUpdated(), false, "The nested object 'O.O1' should not be changed for 'B'");
entity.O().O1().B(false);
equal(es.getEntityState(entity), upshot.EntityState.ClientUpdated, "The entity state should be 'ClientUpdated'");
equal(es.isUpdated(entity), true, "The entity should have changes");
equal(es.isUpdated(entity, "O"), true, "The nested object 'O' should have changes");
equal(es.isUpdated(entity, "O.O1"), true, "The nested object 'O.O1' should have changes");
equal(es.isUpdated(entity, "O.O1.B"), true, "The nested object 'O.O1' should have changes for 'B'");
equal(es.isUpdated(entity, "O", true), false, "The entity should not have changes for 'O'");
equal(es.isUpdated(entity, "O.O1", true), false, "The nested object 'O' should not have changes for 'O1'");
equal(entity.IsUpdated(), true, "The entity should be changed");
equal(entity.O.IsUpdated(), false, "The nested object 'O' should still not be changed");
equal(entity.O().O1.IsUpdated(), false, "The nested object 'O.O1' should still not be changed");
equal(entity.O().O1().B.IsUpdated(), true, "The nested object 'O.O1' should be changed for 'B'");
revertFn(es, entity, "O");
equal(es.isUpdated(entity, "O"), false, "The nested object 'O' should no longer have changes");
equal(es.isUpdated(entity, "O.O1"), false, "The nested object 'O.O1' should no longer have changes");
equal(es.isUpdated(entity, "O.O1.B"), false, "The nested object 'O.O1' should no longer have changes for 'B'");
equal(entity.IsUpdated(), false, "The entity should no longer be changed");
equal(entity.O().O1().B.IsUpdated(), false, "The nested object 'O.O1' should no longer be changed for 'B'");
dataEqual(entity, datasets.ko_tree(1), "The entity should be reverted");
} finally {
upshot.observability.configuration = observability.jquery;
}
});
});
testWithRevertVariations(true, function (revertFn) {
test("isUpdated returns true when knockout array values change", 23, function () {
try {
upshot.observability.configuration = observability.knockout;
var es = createEntitySet(),
entity = loadEntities(es, datasets.ko_array(1, true));
equal(es.getEntities()().length, 1, "There should be a single entity loaded");
equal(es.getEntityState(entity), "Unmodified", "The entity state should be 'Unmodified'");
equal(es.isUpdated(entity), false, "The entity should not have changes");
equal(es.isUpdated(entity, "A[0]"), false, "The object at index 0 should not have changes");
equal(es.isUpdated(entity, "A[0].B"), false, "The object at index 0 should not have changes for 'B'");
equal(entity.IsUpdated(), false, "The entity should not be changed");
equal(entity.A.IsUpdated(), false, "The entity should not be changed for 'A'");
equal(entity.A()[0].B.IsUpdated(), false, "The object at index 0 should not be changed for 'B'");
entity.A()[0].B(false);
equal(es.getEntityState(entity), "ClientUpdated", "The entity state should be 'ClientUpdated'");
equal(es.isUpdated(entity), true, "The entity should have changes");
equal(es.isUpdated(entity, "A[0]"), true, "The object at index 0 should have changes");
equal(es.isUpdated(entity, "A[0].B"), true, "The object at index 0 should have changes for 'B'");
equal(es.isUpdated(entity, "A", true), false, "The entity should not have changes for 'A'");
equal(entity.IsUpdated(), true, "The entity should be changed");
equal(entity.A.IsUpdated(), false, "The entity should not be changed for 'A'");
equal(entity.A()[0].B.IsUpdated(), true, "The object at index 0 should be changed for 'B'");
revertFn(es, entity, "A");
equal(es.isUpdated(entity, "A[0]"), false, "The object at index 0 should no longer have changes");
equal(es.isUpdated(entity, "A[0].B"), false, "The object at index 0 should no longer have changes for 'B'");
equal(entity.IsUpdated(), false, "The entity should no longer be changed");
equal(entity.A()[0].B.IsUpdated(), false, "The object at index 0 should no longer be changed for 'B'");
dataEqual(entity, datasets.ko_array(1), "The entity should be reverted");
} finally {
upshot.observability.configuration = observability.jquery;
}
});
});
testWithRevertVariations(true, function (revertFn) {
test("isUpdated returns true when knockout nested array values change", 35, function () {
try {
upshot.observability.configuration = observability.knockout;
var es = createEntitySet(),
entity = loadEntities(es, datasets.ko_nestedArrays(1, true));
equal(es.getEntities()().length, 1, "There should be a single entity loaded");
equal(es.getEntityState(entity), upshot.EntityState.Unmodified, "The entity state should be 'Unmodified'");
equal(es.isUpdated(entity), false, "The entity should not have changes");
equal(es.isUpdated(entity, "A"), false, "The array should not have changes");
equal(es.isUpdated(entity, "A[0]"), false, "The object at index 0 should not have changes");
equal(es.isUpdated(entity, "A[0].A"), false, "The nested array should not have changes");
equal(es.isUpdated(entity, "A[0].A[0]"), false, "The nested object at index 0 should not have changes");
equal(es.isUpdated(entity, "A[0].A[0].B"), false, "The nested object at index 0 should not have changes for 'B'");
equal(entity.IsUpdated(), false, "The entity should not be changed");
equal(entity.A.IsUpdated(), false, "The entity should not be changed for 'A'");
equal(entity.A()[0].A.IsUpdated(), false, "The object at index 0 should not be changed for 'A'");
equal(entity.A()[0].A()[0].B.IsUpdated(), false, "The nested object at index 0 should not be changed for 'B'");
entity.A()[0].A()[0].B(false);
equal(es.getEntityState(entity), upshot.EntityState.ClientUpdated, "The entity state should be 'ClientUpdated'");
equal(es.isUpdated(entity), true, "The entity should have changes");
equal(es.isUpdated(entity, "A"), true, "The array should have changes");
equal(es.isUpdated(entity, "A[0]"), true, "The object at index 0 should have changes");
equal(es.isUpdated(entity, "A[0].A"), true, "The nested array should have changes");
equal(es.isUpdated(entity, "A[0].A[0]"), true, "The nested object at index 0 should have changes");
equal(es.isUpdated(entity, "A[0].A[0].B"), true, "The nested object at index 0 should have changes for 'B'");
equal(es.isUpdated(entity, "A", true), false, "The entity should not have changes for 'A'");
equal(es.isUpdated(entity, "A[0].A", true), false, "The object at index 0 not have changes for 'A'");
equal(entity.IsUpdated(), true, "The entity should not be changed");
equal(entity.A.IsUpdated(), false, "The entity should still not be changed for 'A'");
equal(entity.A()[0].A.IsUpdated(), false, "The object at index 0 should still not be changed for 'A'");
equal(entity.A()[0].A()[0].B.IsUpdated(), true, "The nested object at index 0 should be changed for 'B'");
revertFn(es, entity, "A");
equal(es.isUpdated(entity, "A"), false, "The array should no longer have changes");
equal(es.isUpdated(entity, "A[0]"), false, "The object at index 0 should no longer have changes");
equal(es.isUpdated(entity, "A[0].A"), false, "The nested array should no longer have changes");
equal(es.isUpdated(entity, "A[0].A[0]"), false, "The nested object at index 0 should no longer have changes");
equal(es.isUpdated(entity, "A[0].A[0].B"), false, "The nested object at index 0 should no longer have changes for 'B'");
equal(entity.IsUpdated(), false, "The entity should no longer be changed");
equal(entity.A()[0].A()[0].B.IsUpdated(), false, "The nested object at index 0 should no longer be changed for 'B'");
dataEqual(entity, datasets.ko_nestedArrays(1), "The entity should be reverted");
} finally {
upshot.observability.configuration = observability.jquery;
}
});
});
testWithRevertVariations(function (revertFn) {
test("isUpdated returns true when multiple properties are updated", 16, function () {
var es = createEntitySet(),
entity = loadEntities(es, datasets.primitives.create(1));
equal(es.getEntities().length, 1, "There should be a single entity loaded");
equal(es.isUpdated(entity, "B"), false, "The entity should not have changes for 'B'");
equal(es.isUpdated(entity, "N"), false, "The entity should not have changes for 'N'");
$.observable(entity).property("B", false);
equal(es.isUpdated(entity, "B"), true, "The entity should have changes for 'B'");
equal(es.isUpdated(entity, "N"), false, "The entity should still not have changes for 'N'");
$.observable(entity).property("N", -1);
equal(es.isUpdated(entity, "B"), true, "The entity should still have changes for 'B'");
equal(es.isUpdated(entity, "N"), true, "The entity should have changes for 'N'");
revertFn(es, entity, "B", true);
revertFn(es, entity, "N");
equal(es.isUpdated(entity, "B"), false, "The entity should no longer have changes for 'B'");
equal(es.isUpdated(entity, "N"), false, "The entity should no longer have changes for 'N'");
dataEqual(entity, datasets.primitives.create(1), "The entity should be reverted");
});
});
testWithRevertVariations(true, function (revertFn) {
test("isUpdated returns true when multiple nested properties are updated", 14, function () {
var es = createEntitySet(),
entity = loadEntities(es, datasets.nested.create(1));
equal(es.getEntities().length, 1, "There should be a single entity loaded");
equal(es.isUpdated(entity, "B"), false, "The entity should not have changes for 'B'");
equal(es.isUpdated(entity, "O.B"), false, "The nested object 'O' should not have changes for 'B'");
$.observable(entity).property("B", false);
equal(es.isUpdated(entity, "B"), true, "The entity should have changes for 'B'");
equal(es.isUpdated(entity, "O.B"), false, "The nested object 'O' should still not have changes for 'B'");
$.observable(entity.O).property("B", false);
equal(es.isUpdated(entity, "B"), true, "The entity should still have changes for 'B'");
equal(es.isUpdated(entity, "O.B"), true, "The nested object 'O' should have changes for 'B'");
revertFn(es, entity, "B", true);
revertFn(es, entity, "O");
equal(es.isUpdated(entity, "B"), false, "The entity should no longer have changes for 'B'");
equal(es.isUpdated(entity, "O.B"), false, "The nested object 'O' should no longer have changes for 'B'");
dataEqual(entity, datasets.nested.create(1), "The entity should be reverted");
});
});
test("_clearChanges resets tracking on multiple nested properties updates", 11, function () {
var es = createEntitySet(),
entity = loadEntities(es, datasets.nested.create(1));
equal(es.getEntities().length, 1, "There should be a single entity loaded");
equal(es.isUpdated(entity, "B"), false, "The entity should not have changes for 'B'");
equal(es.isUpdated(entity, "O.B"), false, "The nested object 'O' should not have changes for 'B'");
$.observable(entity).property("B", false);
equal(es.isUpdated(entity, "B"), true, "The entity should have changes for 'B'");
equal(es.isUpdated(entity, "O.B"), false, "The nested object 'O' should still not have changes for 'B'");
$.observable(entity.O).property("B", false);
equal(es.isUpdated(entity, "B"), true, "The entity should still have changes for 'B'");
equal(es.isUpdated(entity, "O.B"), true, "The nested object 'O' should have changes for 'B'");
es._clearChanges(entity, false);
equal(es.isUpdated(entity), false, "The entity should no longer have changes");
equal(es.isUpdated(entity, "O"), false, "The nested object should no longer have changes");
equal(es.isUpdated(entity, "B"), false, "The entity should no longer have changes for 'B'");
equal(es.isUpdated(entity, "O.B"), false, "The nested object 'O' should no longer have changes for 'B'");
});
testWithRevertVariations(true, function (revertFn) {
test("isUpdated returns true when multiple knockout nested properties are updated", 23, function () {
try {
upshot.observability.configuration = observability.knockout;
var es = createEntitySet(),
entity = loadEntities(es, datasets.ko_tree(1, true));
equal(es.getEntities()().length, 1, "There should be a single entity loaded");
equal(es.isUpdated(entity, "B"), false, "The entity should not have changes for 'B'");
equal(es.isUpdated(entity, "O.B"), false, "The nested object 'O' should not have changes for 'B'");
equal(entity.B.IsUpdated(), false, "The entity should not be changed for 'B'");
equal(entity.O().B.IsUpdated(), false, "The nested object 'O' should not be changed for 'B'");
entity.B(false);
equal(es.isUpdated(entity, "B"), true, "The entity should have changes for 'B'");
equal(es.isUpdated(entity, "O.B"), false, "The nested object 'O' should still not have changes for 'B'");
equal(entity.B.IsUpdated(), true, "The entity should be changed for 'B'");
equal(entity.O().B.IsUpdated(), false, "The nested object 'O' should still not be changed for 'B'");
entity.O().B(false);
equal(es.isUpdated(entity, "B"), true, "The entity should still have changes for 'B'");
equal(es.isUpdated(entity, "O.B"), true, "The nested object 'O' should have changes for 'B'");
equal(entity.B.IsUpdated(), true, "The entity should still be changed for 'B'");
equal(entity.O().B.IsUpdated(), true, "The nested object 'O' should be changed for 'B'");
revertFn(es, entity, "B", true);
revertFn(es, entity, "O");
equal(es.isUpdated(entity, "B"), false, "The entity should no longer have changes for 'B'");
equal(es.isUpdated(entity, "O.B"), false, "The nested object 'O' should no longer have changes for 'B'");
equal(entity.IsUpdated(), false, "The entity should no longer be changed");
equal(entity.B.IsUpdated(), false, "The entity should no longer be changed for 'B'");
equal(entity.O().B.IsUpdated(), false, "The nested object 'O' should no longer be changed for 'B'");
dataEqual(entity, datasets.ko_tree(1), "The entity should be reverted");
} finally {
upshot.observability.configuration = observability.jquery;
}
});
});
test("_clearChanges resets tracking on multiple knockout nested properties updates", 19, function () {
try {
upshot.observability.configuration = observability.knockout;
var es = createEntitySet(),
entity = loadEntities(es, datasets.ko_tree(1, true));
equal(es.getEntities()().length, 1, "There should be a single entity loaded");
equal(es.isUpdated(entity, "B"), false, "The entity should not have changes for 'B'");
equal(es.isUpdated(entity, "O.B"), false, "The nested object 'O' should not have changes for 'B'");
equal(entity.B.IsUpdated(), false, "The entity should not be changed for 'B'");
equal(entity.O().B.IsUpdated(), false, "The nested object 'O' should not be changed for 'B'");
entity.B(false);
equal(es.isUpdated(entity, "B"), true, "The entity should have changes for 'B'");
equal(es.isUpdated(entity, "O.B"), false, "The nested object 'O' should still not have changes for 'B'");
equal(entity.B.IsUpdated(), true, "The entity should be changed for 'B'");
equal(entity.O().B.IsUpdated(), false, "The nested object 'O' should still not be changed for 'B'");
entity.O().B(false);
equal(es.isUpdated(entity, "B"), true, "The entity should still have changes for 'B'");
equal(es.isUpdated(entity, "O.B"), true, "The nested object 'O' should have changes for 'B'");
equal(entity.B.IsUpdated(), true, "The entity should still be changed for 'B'");
equal(entity.O().B.IsUpdated(), true, "The nested object 'O' should be changed for 'B'");
es._clearChanges(entity, false);
equal(es.isUpdated(entity), false, "The entity should no longer have changes");
equal(es.isUpdated(entity, "O"), false, "The nested object should no longer have changes");
equal(es.isUpdated(entity, "B"), false, "The entity should no longer have changes for 'B'");
equal(es.isUpdated(entity, "O.B"), false, "The nested object 'O' should no longer have changes for 'B'");
equal(entity.B.IsUpdated(), false, "The entity should no longer be changed for 'B'");
equal(entity.O().B.IsUpdated(), false, "The nested object 'O' should no longer be changed for 'B'");
} finally {
upshot.observability.configuration = observability.jquery;
}
});
testWithRevertVariations(true, function (revertFn) {
test("isUpdated returns true on array insert", 13, function () {
var es = createEntitySet(),
entity = loadEntities(es, datasets.array.create(1));
equal(es.getEntities().length, 1, "There should be a single entity loaded");
equal(es.getEntityState(entity), upshot.EntityState.Unmodified, "The entity state should be 'Unmodified'");
equal(es.isUpdated(entity), false, "The entity should not have changes");
equal(es.isUpdated(entity, "A"), false, "The array should not have changes");
var length = entity.A.length,
_new = { B: false };
$.observable(entity.A).insert(length, _new);
equal(es.getEntityState(entity), upshot.EntityState.ClientUpdated, "The entity state should be 'ClientUpdated'");
equal(es.isUpdated(entity), true, "The entity should have changes");
equal(es.isUpdated(entity, "A"), true, "The array should have changes");
equal(es.isUpdated(entity, "A[1]"), false, "The last object should not have changes");
equal(entity.A.length, length + 1, "The updated array lengths should be equal");
revertFn(es, entity, "A");
equal(es.isUpdated(entity, "A"), false, "The array should no longer have changes");
dataEqual(entity, datasets.array.create(1), "The entity should be reverted");
});
});
testWithRevertVariations(true, function (revertFn) {
test("isUpdated returns true on array remove", 12, function () {
var es = createEntitySet(),
entity = loadEntities(es, datasets.array.create(1));
equal(es.getEntities().length, 1, "There should be a single entity loaded");
equal(es.getEntityState(entity), upshot.EntityState.Unmodified, "The entity state should be 'Unmodified'");
equal(es.isUpdated(entity), false, "The entity should not have changes");
equal(es.isUpdated(entity, "A"), false, "The array should not have changes");
var length = entity.A.length;
$.observable(entity.A).remove(0, 1);
equal(es.getEntityState(entity), upshot.EntityState.ClientUpdated, "The entity state should be 'ClientUpdated'");
equal(es.isUpdated(entity), true, "The entity should have changes");
equal(es.isUpdated(entity, "A"), true, "The array should have changes");
equal(entity.A.length, length - 1, "The updated array lengths should be equal");
revertFn(es, entity, "A");
equal(es.isUpdated(entity, "A"), false, "The array should no longer have changes");
dataEqual(entity, datasets.array.create(1), "The entity should be reverted");
});
});
testWithRevertVariations(true, function (revertFn) {
test("isUpdated returns true on array replaceAll", 13, function () {
var es = createEntitySet(),
entity = loadEntities(es, datasets.array.create(1));
equal(es.getEntities().length, 1, "There should be a single entity loaded");
equal(es.getEntityState(entity), upshot.EntityState.Unmodified, "The entity state should be 'Unmodified'");
equal(es.isUpdated(entity), false, "The entity should not have changes");
equal(es.isUpdated(entity, "A"), false, "The array should not have changes");
var length = entity.A.length,
_new = { B: false };
$.observable(entity.A).replaceAll([_new]);
equal(es.getEntityState(entity), upshot.EntityState.ClientUpdated, "The entity state should be 'ClientUpdated'");
equal(es.isUpdated(entity), true, "The entity should have changes");
equal(es.isUpdated(entity, "A"), true, "The array should have changes");
equal(es.isUpdated(entity, "A[0]"), false, "The object at index '0' should not have changes");
equal(entity.A.length, 1, "The updated array lengths should be equal");
revertFn(es, entity, "A");
equal(es.isUpdated(entity, "A"), false, "The array should no longer have changes");
dataEqual(entity, datasets.array.create(1), "The entity should be reverted");
});
});
testWithRevertVariations(true, function (revertFn) {
test("isUpdated returns true on multiple array updates", 16, function () {
var es = createEntitySet(),
entity = loadEntities(es, datasets.array.create(1));
equal(es.getEntities().length, 1, "There should be a single entity loaded");
equal(es.getEntityState(entity), upshot.EntityState.Unmodified, "The entity state should be 'Unmodified'");
equal(es.isUpdated(entity), false, "The entity should not have changes");
equal(es.isUpdated(entity, "A"), false, "The array should not have changes");
var length = entity.A.length,
_new = { B: false };
$.observable(entity.A).insert(length, _new);
equal(es.getEntityState(entity), upshot.EntityState.ClientUpdated, "The entity state should be 'ClientUpdated'");
equal(es.isUpdated(entity), true, "The entity should have changes");
equal(es.isUpdated(entity, "A"), true, "The array should have changes");
equal(es.isUpdated(entity, "A[2]"), false, "The last object should not have changes");
equal(entity.A.length, length + 1, "The updated array lengths should be equal");
$.observable(entity.A).remove(1, 2);
equal(es.isUpdated(entity), true, "The entity should still have changes");
equal(es.isUpdated(entity, "A"), true, "The array should still have changes");
equal(entity.A.length, length - 1, "The updated array lengths should be equal");
revertFn(es, entity, "A");
equal(es.isUpdated(entity, "A"), false, "The array should no longer have changes");
dataEqual(entity, datasets.array.create(1), "The entity should be reverted");
});
});
testWithRevertVariations(true, function (revertFn) {
test("isUpdated returns true on knockout array insert", 17, function () {
try {
upshot.observability.configuration = observability.knockout;
var es = createEntitySet(),
entity = loadEntities(es, datasets.ko_array(1, true));
equal(es.getEntities()().length, 1, "There should be a single entity loaded");
equal(es.getEntityState(entity), "Unmodified", "The entity state should be 'Unmodified'");
equal(es.isUpdated(entity), false, "The entity should not have changes");
equal(es.isUpdated(entity, "A"), false, "The array should not have changes");
equal(entity.A.IsUpdated(), false, "The entity should not be changed for 'A'");
var length = entity.A().length,
_new = { B: ko.observable(false) };
entity.A.push(_new);
equal(es.getEntityState(entity), "ClientUpdated", "The entity state should be 'ClientUpdated'");
equal(es.isUpdated(entity), true, "The entity should have changes");
equal(es.isUpdated(entity, "A"), true, "The array should have changes");
equal(es.isUpdated(entity, "A[1]"), false, "The last object should not have changes");
equal(entity.A().length, length + 1, "The updated array lengths should be equal");
equal(entity.A.IsUpdated(), true, "The entity should be changed for 'A'");
revertFn(es, entity, "A");
equal(es.isUpdated(entity, "A"), false, "The array should no longer have changes");
equal(entity.IsUpdated(), false, "The entity should no longer be changed");
equal(entity.A.IsUpdated(), false, "The entity should no longer be changed for 'A'");
dataEqual(entity, datasets.ko_array(1), "The entity should be reverted");
} finally {
upshot.observability.configuration = observability.jquery;
}
});
});
testWithRevertVariations(true, function (revertFn) {
test("isUpdated returns true on knockout array remove", 16, function () {
try {
upshot.observability.configuration = observability.knockout;
var es = createEntitySet(),
entity = loadEntities(es, datasets.ko_array(1, true));
equal(es.getEntities()().length, 1, "There should be a single entity loaded");
equal(es.getEntityState(entity), "Unmodified", "The entity state should be 'Unmodified'");
equal(es.isUpdated(entity), false, "The entity should not have changes");
equal(es.isUpdated(entity, "A"), false, "The array should not have changes");
equal(entity.A.IsUpdated(), false, "The entity should not be changed for 'A'");
var length = entity.A().length;
entity.A.shift();
equal(es.getEntityState(entity), "ClientUpdated", "The entity state should be 'ClientUpdated'");
equal(es.isUpdated(entity), true, "The entity should have changes");
equal(es.isUpdated(entity, "A"), true, "The array should have changes");
equal(entity.A().length, length - 1, "The updated array lengths should be equal");
equal(entity.A.IsUpdated(), true, "The entity should be changed for 'A'");
revertFn(es, entity, "A");
equal(es.isUpdated(entity, "A"), false, "The array should no longer have changes");
equal(entity.IsUpdated(), false, "The entity should no longer be changed");
equal(entity.A.IsUpdated(), false, "The entity should no longer be changed for 'A'");
dataEqual(entity, datasets.ko_array(1), "The entity should be reverted");
} finally {
upshot.observability.configuration = observability.jquery;
}
});
});
testWithRevertVariations(true, function (revertFn) {
test("isUpdated returns true on multiple knockout array updates", 21, function () {
try {
upshot.observability.configuration = observability.knockout;
var es = createEntitySet(),
entity = loadEntities(es, datasets.ko_array(1, true));
equal(es.getEntities()().length, 1, "There should be a single entity loaded");
equal(es.getEntityState(entity), upshot.EntityState.Unmodified, "The entity state should be 'Unmodified'");
equal(es.isUpdated(entity), false, "The entity should not have changes");
equal(es.isUpdated(entity, "A"), false, "The array should not have changes");
equal(entity.A.IsUpdated(), false, "The entity should not be changed for 'A'");
var length = entity.A().length,
_new = { B: false };
entity.A.push(_new);
equal(es.getEntityState(entity), upshot.EntityState.ClientUpdated, "The entity state should be 'ClientUpdated'");
equal(es.isUpdated(entity), true, "The entity should have changes");
equal(es.isUpdated(entity, "A"), true, "The array should have changes");
equal(es.isUpdated(entity, "A[1]"), false, "The last object should not have changes");
equal(entity.A().length, length + 1, "The updated array lengths should be equal");
equal(entity.A.IsUpdated(), true, "The entity should be changed for 'A'");
entity.A.pop();
entity.A.pop();
equal(es.isUpdated(entity), true, "The entity should still have changes");
equal(es.isUpdated(entity, "A"), true, "The array should still have changes");
equal(entity.A().length, length - 1, "The updated array lengths should be equal");
equal(entity.A.IsUpdated(), true, "The entity should still be changed for 'A'");
revertFn(es, entity, "A");
equal(es.isUpdated(entity, "A"), false, "The array should no longer have changes");
equal(entity.IsUpdated(), false, "The entity should no longer be changed");
equal(entity.A.IsUpdated(), false, "The entity should no longer be changed for 'A'");
dataEqual(entity, datasets.ko_array(1), "The entity should be reverted");
} finally {
upshot.observability.configuration = observability.jquery;
}
});
});
testWithRevertVariations(true, function (revertFn) {
test("changes to a nested object are cleared on revert changes", 14, function () {
var es = createEntitySet(),
entity = loadEntities(es, datasets.nested.create(1));
equal(es.getEntities().length, 1, "There should be a single entity loaded");
equal(es.getEntityState(entity), upshot.EntityState.Unmodified, "The entity state should be 'Unmodified'");
equal(es.isUpdated(entity), false, "The entity should not have changes");
equal(es.isUpdated(entity, "O"), false, "The nested object should not have changes");
$.observable(entity.O).property("B", false);
equal(es.getEntityState(entity), upshot.EntityState.ClientUpdated, "The entity state should be 'ClientUpdated'");
equal(es.isUpdated(entity), true, "The entity should have changes");
equal(es.isUpdated(entity, "O"), true, "The nested object should have changes");
equal(es.isUpdated(entity, "O.B"), true, "The nested object should have changes for 'B'");
var original = entity.O;
$.observable(entity).property("O", null);
equal(es.isUpdated(entity), true, "The entity should have changes");
equal(es.isUpdated(entity, "O"), true, "The entity should have changes for 'O'");
revertFn(es, entity, "O");
equal(es.isUpdated(entity, "O"), false, "The nested object should no longer have changes");
dataEqual(entity, datasets.nested.create(1), "The entity should be reverted");
});
});
testWithRevertVariations(true, function (revertFn) {
test("changes to an array are cleared on revert changes", 20, function () {
var es = createEntitySet(),
entity = loadEntities(es, datasets.nestedArrays.create(1));
equal(es.getEntities().length, 1, "There should be a single entity loaded");
equal(es.getEntityState(entity), upshot.EntityState.Unmodified, "The entity state should be 'Unmodified'");
equal(es.isUpdated(entity), false, "The entity should not have changes");
equal(es.isUpdated(entity, "A"), false, "The array should not have changes");
equal(es.isUpdated(entity, "A[0]"), false, "The object at index 0 should not have changes");
equal(es.isUpdated(entity, "A[0].A"), false, "The nested array should not have changes");
$.observable(entity.A[0].A).remove(0, 1);
equal(es.getEntityState(entity), upshot.EntityState.ClientUpdated, "The entity state should be 'ClientUpdated'");
equal(es.isUpdated(entity), true, "The entity should have changes");
equal(es.isUpdated(entity, "A"), true, "The array should have changes");
equal(es.isUpdated(entity, "A[0]"), true, "The object at index 0 should have changes");
equal(es.isUpdated(entity, "A[0].A"), true, "The nested array should have changes");
var original = entity.A[0];
$.observable(entity.A).remove(0, 1);
equal(es.isUpdated(entity), true, "The entity should have changes");
equal(es.isUpdated(entity, "A"), true, "The array should have changes");
equal(es.isUpdated(entity, "A[0]"), false, "The object at index 0 should not have changes");
revertFn(es, entity, "A");
equal(es.isUpdated(entity, "A"), false, "The array should no longer have changes");
equal(es.isUpdated(entity, "A[0]"), false, "The object at index 0 should no longer have changes");
equal(es.isUpdated(entity, "A[0].A"), false, "The nested array should no longer have changes");
dataEqual(entity, datasets.nestedArrays.create(1), "The entity should be reverted");
});
});
test("_getOriginalValue returns the original value", 4, function () {
var es = createEntitySet(),
entity = loadEntities(es, datasets.nestedArrays.create(1));
equal(es.getEntities().length, 1, "There should be a single entity loaded");
equal(es.getEntityState(entity), upshot.EntityState.Unmodified, "The entity state should be 'Unmodified'");
$.observable(entity).property("B", false);
$.observable(entity).property("S", "S");
$.observable(entity.A).insert(entity.A.length, [{ B: true}]);
$.observable(entity.A[1]).property("N", -1);
$.observable(entity.A[0].A).replaceAll([{ B: true }, { B: true}]);
equal(es.isUpdated(entity), true, "The entity should have changes");
dataEqual(es._getOriginalValue(entity), datasets.nestedArrays.create(1), "Original values should be equal.");
});
test("_merge sets new values into entity", 2, function () {
var es = createEntitySet(),
entity = loadEntities(es, datasets.nestedArrays.create(1));
equal(es.getEntities().length, 1, "There should be a single entity loaded");
var _new = datasets.nestedArrays.create(1);
_new.B = false;
_new.N = 3;
_new.A[0].B = false;
_new.A[1].A.push({ B: true });
es._merge(entity, _new);
dataEqual(entity, _new, "The entity should equal new values");
});
testWithRevertVariations(function (revertFn) {
test("_merge does not update a modified entity", 15, function () {
var es = createEntitySet(),
entity = loadEntities(es, datasets.nestedArrays.create(1));
equal(es.getEntities().length, 1, "There should be a single entity loaded");
equal(es.getEntityState(entity), upshot.EntityState.Unmodified, "The entity state should be 'Unmodified'");
$.observable(entity).property("N", -1);
equal(es.isUpdated(entity), true, "The entity should have changes");
equal(es.isUpdated(entity, "N"), true, "The entity should have changes for 'N'");
var original = es._getOriginalValue(entity),
_new = datasets.nestedArrays.create(1);
_new.B = false;
es._merge(entity, _new);
equal(es.isUpdated(entity), true, "The entity should have changes");
equal(es.isUpdated(entity, "N"), true, "The entity should have changes for 'N'");
equal(entity.B, original.B, "The value of 'B' should match the original value");
notEqual(entity.B, _new.B, "The value of 'B' should not match the new value");
revertFn(es, entity, "N");
equal(es.isUpdated(entity, "N"), false, "The entity should no longer have changes for 'N'");
equal(entity.B, original.B, "The value of 'B' should match the original value");
notEqual(entity.B, _new.B, "The value of 'B' should not match the new value");
dataEqual(entity, original, "The entity should equal the original values");
});
});
function createEntitySet() {
var dataContext = new upshot.DataContext(new upshot.riaDataProvider()),
entitySet = new upshot.EntitySet(dataContext, "entityType");
upshot.metadata("entityType", {
key: ["Id"]
});
return entitySet;
}
function loadEntities(entitySet, entities) {
var entities2 = entities;
if (!upshot.isArray(entities)) {
entities2 = [entities];
}
entities2 = entitySet.__loadEntities(entities2);
if (!upshot.isArray(entities)) {
return entities2[0];
}
return entities2;
}
function createEventTracker(entitySet) {
var e = [],
tracker = {
events: e,
propertyChanged: function (entity, path, value) {
e.push({ type: "propertyChanged", entity: entity, path: path, value: value });
},
entityUpdated: function (entity, path, eventArgs) {
e.push({ type: "entityUpdated", entity: entity, path: path, eventArgs: eventArgs });
}
};
entitySet.bind("propertyChanged", tracker.propertyChanged);
entitySet.bind("entityUpdated", tracker.entityUpdated);
return tracker;
}
function dataEqual(actual, expected, message) {
var count = 0;
function compare(actualValue, expectedValue, property) {
count++;
if (actualValue !== expectedValue) {
return count + ": property '" + property + "' with value '" + actualValue + "' does not equal expected value '" + expectedValue + "'.\n";
}
return "";
}
equal(dataEqualRecursive(actual, expected, compare), "", message);
}
function dataEqualRecursive(actual, expected, compare, property) {
var difference = "";
if (upshot.isArray(actual) && upshot.isArray(expected)) {
$.each(expected, function (index, value) {
difference += dataEqualRecursive(actual[index], value, compare, index);
});
} else if (upshot.isObject(actual) && upshot.isObject(expected)) {
$.each(expected, function (key, value) {
difference += dataEqualRecursive(actual[key], value, compare, key);
});
} else if (ko.isObservable(actual) && ko.isObservable(expected)) {
difference = dataEqualRecursive(ko.utils.unwrapObservable(actual), ko.utils.unwrapObservable(expected), compare, property);
} else if (upshot.isDate(actual) && upshot.isDate(expected)) {
difference = compare(actual.toString(), expected.toString(), property);
} else {
difference = compare(actual, expected, property);
}
return difference;
}
function testWithRevertVariations(nested, testFn) {
if ($.isFunction(nested)) {
testFn = nested;
nested = false;
}
testFn(function (es, entity, propertyName) {
var observer;
if (!nested) {
observer = function () {
equal(es.isUpdated(entity, propertyName), false, "The entity should not have property changes during callbacks");
};
es.bind("propertyChanged", observer);
}
es.revertChanges();
if (!nested) {
es.unbind("propertyChanged", observer);
}
equal(es.getEntityState(entity), upshot.EntityState.Unmodified, "The entity state should be 'Unmodified' again");
equal(es.isUpdated(entity), false, "The entity should no longer have changes");
});
testFn(function (es, entity, propertyName, isUpdated) {
var observer;
if (!nested) {
observer = function () {
equal(es.isUpdated(entity, propertyName), false, "The entity should not have property changes during callbacks");
};
es.bind("propertyChanged", observer);
}
es.revertUpdates(entity, propertyName);
if (!nested) {
es.unbind("propertyChanged", observer);
}
var expectedState = !!isUpdated ? upshot.EntityState.ClientUpdated : upshot.EntityState.Unmodified;
equal(es.getEntityState(entity), expectedState, "The entity state should still be '" + expectedState + "'");
equal(es.isUpdated(entity), !!isUpdated, "The entity should " + (!!isUpdated ? "" : "no longer") + " have changes");
});
}
})(this, jQuery, upshot);