/// (function (upshot, $, ko, undefined) { var obsOld = upshot.observability.configuration; module("mapping.tests.js", { teardown: function () { upshot.observability.configuration = obsOld; testHelper.unmockAjax(); } }); function createRemoteDataSource(options) { options = $.extend({ providerParameters: { url: "unused", operationName: ""} }, options); return new upshot.RemoteDataSource(options); } function createCustomersResult() { return [ { ID: 1, Name: "Joe", Orders: [ { ID: 97, ProductName: "Smarties", CustomerID: 1 } ] }, { ID: 2, Name: "Stan", Orders: [ { ID: 99, ProductName: "Shreddies", CustomerID: 2 } ] }, { ID: 3, Name: "Fred", Orders: [ { ID: 98, ProductName: "Wheatabix", CustomerID: 3 }, { ID: 96, ProductName: "Red Rose Tea", CustomerID: 3 } ] } ]; } var customersMetadata = { Customer_Mapping: { key: ["ID"], fields: { ID: { type: "Int32:#System" }, Name: { type: "String:#System" }, Orders: { type: "Order_Mapping", array: true, association: { thisKey: ["ID"], otherKey: ["CustomerID"] } } } }, Order_Mapping: { key: ["ID"], fields: { ID: { type: "Int32:#System" }, ProductName: { type: "String:#System" }, CustomerID: { type: "Int32:#System" }, Customer: { type: "Customer_Mapping", association: { isForeignKey: true, thisKey: ["CustomerID"], otherKey: ["ID"] } } } }, Entity_Mapping: { key: ["Id"], fields: { Id: { type: "Int32:#System" }, String: { type: "String:#System" }, Number: { type: "Int32:#System" } } }, CT_Mapping: { fields: { String: { type: "String:#System" }, Number: { type: "Int32:#System" }, CT: { type: "CT_Mapping" } } } }; function happyMapper(entityType) { return function (data) { var mapped = upshot.map(data, entityType); mapped.Happy = true; return mapped; } } (function () { var mappingOptions = [ { entityType: "Customer_Mapping", mapping: happyMapper("Customer_Mapping") }, { entityType: "Customer_Mapping", mapping: { map: happyMapper("Customer_Mapping"), unmap: function () { throw "Not reached"; } } }, { entityType: "Customer_Mapping", mapping: { Customer_Mapping: happyMapper("Customer_Mapping") } }, { entityType: "Customer_Mapping", mapping: { Customer_Mapping: { map: happyMapper("Customer_Mapping"), unmap: function () { throw "Not reached"; } } } } ]; for (var i = 0; i < mappingOptions.length; i++) { (function (options) { test("Verify customer parent mapping, default child mapping", 3, function () { stop(); upshot.observability.configuration = upshot.observability.knockout; upshot.metadata(customersMetadata); dsTestDriver.simulateSuccessService(createCustomersResult()); var rds = createRemoteDataSource(options); rds.refresh(function (entities) { equal(entities[1].Orders()[0].ProductName(), "Shreddies", "Mapping and associations applied"); equal($.grep(entities, function (entity) { return entity.Happy; }).length, 3, "Customers mapped with custom mapping"); equal($.grep(rds.getDataContext().getEntitySet("Order_Mapping").getEntities()(), function (entity) { return entity.Happy; }).length, 0, "Orders mapped with default mapping"); start(); }); }); })(mappingOptions[i]); } })(); (function () { var mappingOptions = [ { entityType: "Customer_Mapping", mapping: { Order_Mapping: happyMapper("Order_Mapping") } }, { entityType: "Customer_Mapping", mapping: { Order_Mapping: { map: happyMapper("Order_Mapping"), unmap: function () { throw "Not reached"; } } } } ]; for (var i = 0; i < mappingOptions.length; i++) { (function (options) { test("Verify default parent mapping, custom child mapping", 3, function () { stop(); upshot.observability.configuration = upshot.observability.knockout; upshot.metadata(customersMetadata); dsTestDriver.simulateSuccessService(createCustomersResult()); var rds = createRemoteDataSource(options); rds.refresh(function (entities) { equal(entities[1].Orders()[0].ProductName(), "Shreddies", "Mapping and associations applied"); equal($.grep(entities, function (entity) { return entity.Happy; }).length, 0, "Customers mapped with default mapping"); equal($.grep(rds.getDataContext().getEntitySet("Order_Mapping").getEntities()(), function (entity) { return entity.Happy; }).length, 4, "Orders mapped with custom mapping"); start(); }); }); })(mappingOptions[i]); } })(); function Customer(data) { this.ID = ko.observable(data.ID); this.Orders = upshot.map(data.Orders, "Order_Mapping"); this.Happy = true; } test("Verify use of ctor as map", 3, function () { stop(); upshot.observability.configuration = upshot.observability.knockout; upshot.metadata(customersMetadata); dsTestDriver.simulateSuccessService(createCustomersResult()); var rds = createRemoteDataSource({ entityType: "Customer_Mapping", mapping: Customer }); rds.refresh(function (entities) { equal(entities[1].Orders()[0].ProductName(), "Shreddies", "Mapping and associations applied"); equal($.grep(entities, function (entity) { return entity.Happy; }).length, 3, "Customers mapped with custom mapping"); equal($.grep(rds.getDataContext().getEntitySet("Order_Mapping").getEntities()(), function (entity) { return entity.Happy; }).length, 0, "Orders mapped with default mapping"); start(); }); }); // TODO: Factor our KO test setup elsewhere and move this test to a better home. test("LDS over ASEV produces correct filtered result", 2, function () { stop(); upshot.observability.configuration = upshot.observability.knockout; upshot.metadata(customersMetadata); dsTestDriver.simulateSuccessService(createCustomersResult()); var rds = createRemoteDataSource({ entityType: "Customer_Mapping", mapping: Customer }); rds.refresh(function (entities) { var lds = new upshot.LocalDataSource({ source: entities[2].Orders, filter: { property: "ProductName", value: "Wheatabix" } }); lds.refresh(function (entities2) { ok(entities2.length === 1 && entities2[0].ProductName() === "Wheatabix", "Correct LDS refresh result"); var lds2 = new upshot.LocalDataSource({ source: upshot.EntitySource.as(entities[2].Orders), filter: { property: "ProductName", value: "Wheatabix" } }); lds2.refresh(function (entities3) { ok(entities3.length === 1 && entities3[0].ProductName() === "Wheatabix", "Correct LDS refresh result"); start(); }); }); }); }); test("Default knockout mapping adds entity and updated properties", 2, function () { upshot.observability.configuration = upshot.observability.knockout; upshot.metadata(customersMetadata); var entity = upshot.map({ Id: 1, String: "String", Number: 1 }, "Entity_Mapping"); equal(entity.hasOwnProperty("EntityState"), true, "Entity should have 'EntityState' property"); equal(entity.String.hasOwnProperty("IsUpdated"), true, "String should have 'IsUpdated' property"); }); test("Default knockout mapping for a complex type adds updated properties", 4, function () { upshot.observability.configuration = upshot.observability.knockout; upshot.metadata(customersMetadata); var ct = upshot.map({ String: "String", Number: 1, CT: { String: "String2", Number: 2, CT: null } }, "CT_Mapping"); equal(ct.hasOwnProperty("EntityState"), false, "CT should not have 'EntityState' property"); equal(ct.String.hasOwnProperty("IsUpdated"), true, "String should have 'IsUpdated' property"); equal(ct.CT().hasOwnProperty("EntityState"), false, "Nested CT should not have 'EntityState' property"); equal(ct.CT().String.hasOwnProperty("IsUpdated"), true, "Nested String should have 'IsUpdated' property"); }); test("upshot.addEntityProperties for knockout adds entity properties", 12, function () { upshot.observability.configuration = upshot.observability.knockout; upshot.metadata(customersMetadata); var entity = upshot.map({ Id: 1, String: "String", Number: 1 }, "Entity_Mapping"); equal(entity.hasOwnProperty("EntityState"), true, "Entity should have 'EntityState' property"); equal(entity.EntityState(), upshot.EntityState.Unmodified, "EntityState should be unmodified"); equal(entity.hasOwnProperty("EntityError"), true, "Entity should have 'EntityError' property"); equal(entity.EntityError(), null, "EntityError should be null"); equal(entity.hasOwnProperty("IsUpdated"), true, "Entity should have 'IsUpdated' property"); equal(entity.IsUpdated(), false, "IsUpdated should be false"); equal(entity.hasOwnProperty("IsAdded"), true, "Entity should have 'IsAdded' property"); equal(entity.IsAdded(), false, "IsAdded should be false"); equal(entity.hasOwnProperty("IsDeleted"), true, "Entity should have 'IsDeleted' property"); equal(entity.IsDeleted(), false, "IsDeleted should be false"); equal(entity.hasOwnProperty("IsChanged"), true, "Entity should have 'IsChanged' property"); equal(entity.IsChanged(), false, "IsChanged should be false"); }); test("upshot.addUpdatedProperties for knockout adds updated properties", 6, function () { upshot.observability.configuration = upshot.observability.knockout; upshot.metadata(customersMetadata); var entity = upshot.map({ Id: 1, String: "String", Number: 1 }, "Entity_Mapping"); equal(entity.Id.hasOwnProperty("IsUpdated"), true, "Id should have 'IsUpdated' property"); equal(entity.Id.IsUpdated(), false, "Id.IsUpdated should be false"); equal(entity.String.hasOwnProperty("IsUpdated"), true, "String should have 'IsUpdated' property"); equal(entity.String.IsUpdated(), false, "String.IsUpdated should be false"); equal(entity.Number.hasOwnProperty("IsUpdated"), true, "Number should have 'IsUpdated' property"); equal(entity.Number.IsUpdated(), false, "Number.IsUpdated should be false"); }); function getEntityStates() { var states = {}; $.each(upshot.EntityState, function (key, value) { if (typeof value === "string") { states[value] = false; } }); return states; } test("knockout entity.IsUpdated should reflect EntityState", 8, function () { upshot.observability.configuration = upshot.observability.knockout; upshot.metadata(customersMetadata); var entity = upshot.map({ Id: 1, String: "String", Number: 1 }, "Entity_Mapping"); var states = getEntityStates(); states[upshot.EntityState.ClientUpdated] = true; states[upshot.EntityState.ServerUpdating] = true; $.each(states, function (key, value) { entity.EntityState(key); equal(entity.IsUpdated(), value, "IsUpdated should be " + value + " for state " + key); }); }); test("knockout entity.IsAdded should reflect EntityState", 8, function () { upshot.observability.configuration = upshot.observability.knockout; upshot.metadata(customersMetadata); var entity = upshot.map({ Id: 1, String: "String", Number: 1 }, "Entity_Mapping"); var states = getEntityStates(); states[upshot.EntityState.ClientAdded] = true; states[upshot.EntityState.ServerAdding] = true; $.each(states, function (key, value) { entity.EntityState(key); equal(entity.IsAdded(), value, "IsAdded should be " + value + " for state " + key); }); }); test("knockout entity.IsDeleted should reflect EntityState", 8, function () { upshot.observability.configuration = upshot.observability.knockout; upshot.metadata(customersMetadata); var entity = upshot.map({ Id: 1, String: "String", Number: 1 }, "Entity_Mapping"); var states = getEntityStates(); states[upshot.EntityState.ClientDeleted] = true; states[upshot.EntityState.ServerDeleting] = true; states[upshot.EntityState.Deleted] = true; $.each(states, function (key, value) { entity.EntityState(key); equal(entity.IsDeleted(), value, "IsDeleted should be " + value + " for state " + key); }); }); test("knockout entity.IsChanged should reflect EntityState", 8, function () { upshot.observability.configuration = upshot.observability.knockout; upshot.metadata(customersMetadata); var entity = upshot.map({ Id: 1, String: "String", Number: 1 }, "Entity_Mapping"); var states = getEntityStates(); states[upshot.EntityState.Unmodified] = true; states[upshot.EntityState.Deleted] = true; $.each(states, function (key, value) { entity.EntityState(key); equal(entity.IsChanged(), !value, "IsChanged should be " + !value + " for state " + key); }); }); test("upshot.registerType and upshot.type use", 4, function () { upshot.registerType("FooType", function () { return Foo; }); function Foo() {}; equal(upshot.type(Foo), "FooType", "upshot.registerType works before key declaration"); function Foo2() {}; upshot.registerType("FooType", function () { return Foo2; }); equal(upshot.type(Foo2), "FooType", "upshot.registerType works after key declaration"); upshot.registerType({ Bar1Type: function () { return Bar1; }, Bar2Type: function () { return Bar2; } }); function Bar1() {}; function Bar2() {}; ok(upshot.type(Bar1) === "Bar1Type" && upshot.type(Bar2) === "Bar2Type", "upshot.registerType supports multiple registrations"); var exception; try { function Zip() {}; upshot.type(Zip); } catch (ex) { exception = true; } ok(!!exception, "upshot.type with no preceding upshot.registerType throws exception"); }); })(upshot, jQuery, ko);