blob: 3b7854b68fd7cb7c804bb969035226753ae871c8 [file] [log] [blame]
/// <reference path="../src/odata-net.js" />
/// <reference path="../src/odata.js" />
/// <reference path="common/djstest.js" />
/// <reference path="common/mockHttpClient.js" />
// odata-tests.js
(function (window, undefined) {
var northwindService = "http://services.odata.org/Northwind/Northwind.svc/";
var localFeed = "./endpoints/FoodStoreDataService.svc/Foods";
var northwindFeed = northwindService + "Suppliers";
var countIFrames = function () {
/// <summary>Count the number of IFRAMES in the page</summary>
/// <returns type="Integer">The number of IFRAMES</returns>
return document.getElementsByTagName("IFRAME").length;
}
module("Unit");
var originalEnableJsonpCallback = OData.defaultHttpClient.enableJsonpCallback;
var restoreJsonpCallback = function () {
/// <summary>Restores OData.defaultHttpClient.enableJsonpCallback to the library default.</summary>
OData.defaultHttpClient.enableJsonpCallback = originalEnableJsonpCallback;
};
djstest.addTest(function checkApiTest() {
var internals = window.OData.canUseJSONP !== undefined;
if (internals) {
// Don't even bother - there is a very long list for inter-module communication.
// {targetName: "OData", names: "..." }
djstest.pass("Do not test public api's when internals are visible");
} else {
var apis = [
{ targetName: "datajs", names: "createDataCache,createStore,defaultStoreMechanism" },
{ targetName: "OData", names: "atomHandler,batchHandler,defaultError,defaultHandler,defaultHttpClient,defaultMetadata,defaultSuccess,jsonHandler,metadataHandler,read,request,textHandler,xmlHandler,parseMetadata" }
];
for (var i = 0; i < apis.length; i++) {
var target = window[apis[i].targetName];
var actuals = [];
for (var actual in target) {
actuals.push(actual);
}
actuals.sort();
var names = apis[i].names.split(",");
names.sort();
djstest.assertAreEqual(actuals.join(), names.join(), "actual names for " + apis[i].targetName);
}
}
djstest.done();
});
djstest.addTest(function simpleLocalReadTest() {
OData.read(localFeed, function (data, request) {
djstest.assert(data !== null, "data !== null");
djstest.assert(request !== null, "request !== null");
djstest.done();
});
});
djstest.addTest(function simpleLocalReadWithRequestTest() {
OData.read({ requestUri: localFeed, headers: { Accept: "application/json"} }, function (data, response) {
djstest.assert(data !== null, "data !== null");
djstest.assert(response !== null, "response !== null");
djstest.assertAreEqual(data, response.data, "data === response.data");
// Typically application/json;charset=utf-8, but browser may change the request charset (and thus response).
var contentType = response.headers["Content-Type"];
contentType = contentType.split(';')[0];
djstest.assertAreEqual(contentType, "application/json", 'contentType === "application/json"');
djstest.done();
});
});
djstest.addTest(function simpleReadTest() {
var oldEnableJsonpCallback = OData.defaultHttpClient.enableJsonpCallback;
OData.defaultHttpClient.enableJsonpCallback = true;
var iframesBefore = countIFrames();
OData.read(northwindService + "Regions", function (data, request) {
djstest.assert(data !== null, "data !== null");
djstest.assert(request !== null, "request !== null");
// IFRAME recycling does not work in Opera because as soon as the IFRAME is added to the body, all variables
// go out of scope
if (!window.opera) {
djstest.assertAreEqual(countIFrames() - iframesBefore, 0, "extra IFRAMEs (baseline: " + iframesBefore + ")");
}
OData.defaultHttpClient.enableJsonpCallback = oldEnableJsonpCallback;
djstest.done();
});
});
djstest.addTest(function simpleReadWithParamsTest() {
OData.defaultHttpClient.enableJsonpCallback = true;
OData.read(northwindFeed + "?$top=3", function (data, request) {
djstest.assert(data !== null, "data !== null");
djstest.assert(request !== null, "request !== null");
restoreJsonpCallback();
djstest.done();
}, djstest.failAndDoneCallback("Unable to read from " + northwindFeed, restoreJsonpCallback));
});
djstest.addTest(function simpleReadWithNoParamsTest() {
OData.defaultHttpClient.enableJsonpCallback = true;
OData.read(northwindFeed + "?", function (data, request) {
djstest.assert(data !== null, "data !== null");
djstest.assert(request !== null, "request !== null");
restoreJsonpCallback();
djstest.done();
}, djstest.failAndDoneCallback("Unable to read from " + northwindFeed, restoreJsonpCallback));
});
djstest.addTest(function jsonpTimeoutTest() {
// Verifies that JSONP will timeout, and that the
// enableJsonpCallback flag can be set on the request itself.
var iframesBefore = countIFrames();
OData.request({
requestUri: northwindFeed + "?$fail=true",
timeoutMS: 100,
enableJsonpCallback: true
}, function (data, request) {
djstest.fail("expected an error callback");
djstest.done();
}, function (err) {
djstest.assert(err.message.indexOf("timeout") !== 1, "err.message[" + err.message + "].indexOf('timeout') !== 1");
djstest.assertAreEqual(countIFrames() - iframesBefore, 0, "extra script tags (baseline: " + iframesBefore + ")");
djstest.done();
});
});
djstest.addTest(function requestDefaultsTest() {
// Save current defaults.
var oldError = OData.defaultError;
var oldSuccess = OData.defaultSuccess;
var oldDefaultHandler = OData.defaultHandler;
var oldHttpClient = OData.defaultHttpClient;
OData.defaultSuccess = function (data, response) {
djstest.assertAreEqual(response.statusCode, 299, "success method reached when expected");
};
OData.defaultError = function (error) {
var response = error.response;
djstest.assertAreEqual(response.statusCode, 500, "error method reached when expected");
};
OData.defaultHandler = {
read: function (response) {
djstest.assertAreEqual(response.statusCode, 299, "default handler read method reached when expected");
},
accept: "test accept string"
};
OData.defaultHttpClient = MockHttpClient.clear();
var testUris = [
"requestDefaultsTest/request",
"requestDefaultsTest/request1",
"requestDefaultsTest/error"
];
MockHttpClient.addRequestVerifier(testUris[0], function (request) {
djstest.assertAreEqual(request.method, "GET", "request.method is GET");
djstest.assert(request.headers, "request.headers is defined and not null");
djstest.assertAreEqual(request.headers.Accept, "test accept string");
});
MockHttpClient.addResponse(testUris[1], { statusCode: 299, body: "test response" });
MockHttpClient.addResponse(testUris[2], { statusCode: 500, body: "error response" });
try {
var i, len;
for (i = 0, len = testUris.length; i < len; i++) {
OData.request({ requestUri: testUris[i] });
}
}
finally {
// Restore defaults.
OData.defaultError = oldError;
OData.defaultSuccess = oldSuccess;
OData.defaultHandler = oldDefaultHandler;
OData.defaultHttpClient = oldHttpClient;
}
djstest.assertsExpected(6);
djstest.done();
});
djstest.addTest(function requestUpdateTest() {
// Save current defaults.
var testHandler = {
read: function (response) {
response.data = response.body;
},
write: function (request) {
djstest.assertAreEqual(request.method, "POST", "handler write method, request has the correct method");
}
};
var testSuccess = function (data, response) {
djstest.assertAreEqual(data, "test response", "success callback has the correct data");
djstest.assertAreEqual(response.status, 200, "success method reached when expected");
};
var testError = function (error) {
var response = error.response;
djstest.assertAreEqual(response.status, 500, "error method reached when expected");
};
MockHttpClient.addResponse("requestUpdateTest", { status: 200, body: "test response" });
MockHttpClient.addResponse("requestUpdateTest", { status: 500, body: "error response" });
OData.request({ requestUri: "requestUpdateTest", method: "POST" }, testSuccess, testError, testHandler, MockHttpClient);
djstest.done();
});
djstest.addTest(function parseMetadataTest() {
var metadata = '<?xml version="1.0" encoding="utf-8"?>' +
'<edmx:Edmx Version="1.0" xmlns:edmx="http://schemas.microsoft.com/ado/2007/06/edmx">' +
'<edmx:DataServices m:DataServiceVersion="3.0" m:MaxDataServiceVersion="3.0" xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata">' +
'<Schema Namespace="ODataDemo" xmlns="http://schemas.microsoft.com/ado/2009/11/edm">' +
'<EntityType Name="Product">' +
'<Key><PropertyRef Name="ID" /></Key>' +
'<Property Name="ID" Type="Edm.Int32" Nullable="false" />' +
'<Property Name="Name" Type="Edm.String" m:FC_TargetPath="SyndicationTitle" m:FC_ContentKind="text" m:FC_KeepInContent="false" />' +
'<Property Name="Description" Type="Edm.String" m:FC_TargetPath="SyndicationSummary" m:FC_ContentKind="text" m:FC_KeepInContent="false" />' +
'<Property Name="ReleaseDate" Type="Edm.DateTime" Nullable="false" />' +
'<Property Name="DiscontinuedDate" Type="Edm.DateTime" />' +
'<Property Name="Rating" Type="Edm.Int32" Nullable="false" />' +
'<Property Name="Price" Type="Edm.Decimal" Nullable="false" />' +
'<NavigationProperty Name="Category" Relationship="ODataDemo.Product_Category_Category_Products" ToRole="Category_Products" FromRole="Product_Category" />' +
'</EntityType>' +
'<EntityType Name="Category">' +
'<Key>' +
'<PropertyRef Name="ID" />' +
'</Key>' +
'<Property Name="ID" Type="Edm.Int32" Nullable="false" />' +
'<Property Name="Name" Type="Edm.String" m:FC_TargetPath="SyndicationTitle" m:FC_ContentKind="text" m:FC_KeepInContent="true" />' +
'<NavigationProperty Name="Products" Relationship="ODataDemo.Product_Category_Category_Products" ToRole="Product_Category" FromRole="Category_Products" />' +
'</EntityType>' +
'<Association Name="Product_Category_Category_Products"><End Type="ODataDemo.Category" Role="Category_Products" Multiplicity="0..1" />' +
'<End Type="ODataDemo.Product" Role="Product_Category" Multiplicity="*" />' +
'</Association>' +
'<EntityContainer Name="DemoService" m:IsDefaultEntityContainer="true">' +
'<EntitySet Name="Products" EntityType="ODataDemo.Product" />' +
'<EntitySet Name="Categories" EntityType="ODataDemo.Category" />' +
'<FunctionImport Name="Discount" IsBindable="true" m:IsAlwaysBindable="true">' +
'<Parameter Name="product" Type="ODataDemo.Product" />' +
'<Parameter Name="discountPercentage" Type="Edm.Int32" Nullable="false" />' +
'</FunctionImport>' +
'<AssociationSet Name="Products_Category_Categories" Association="ODataDemo.Product_Category_Category_Products">' +
'<End Role="Product_Category" EntitySet="Products" />' +
'<End Role="Category_Products" EntitySet="Categories" />' +
'</AssociationSet>' +
'</EntityContainer>' +
'</Schema></edmx:DataServices></edmx:Edmx>';
var parsedMetadata = OData.parseMetadata(metadata);
var expected =
{
"version": "1.0",
"dataServices":
{
"maxDataServiceVersion": "3.0",
"dataServiceVersion": "3.0",
"schema": [
{
"namespace": "ODataDemo",
"entityType": [
{
"name": "Product",
"key": { "propertyRef": [{ "name": "ID"}] },
"property": [
{ "name": "ID", "nullable": "false", "type": "Edm.Int32" },
{ "name": "Name", "type": "Edm.String", "FC_KeepInContent": "false", "FC_ContentKind": "text", "FC_TargetPath": "SyndicationTitle" },
{ "name": "Description", "type": "Edm.String", "FC_KeepInContent": "false", "FC_ContentKind": "text", "FC_TargetPath": "SyndicationSummary" },
{ "name": "ReleaseDate", "nullable": "false", "type": "Edm.DateTime" }, { "name": "DiscontinuedDate", "type": "Edm.DateTime" },
{ "name": "Rating", "nullable": "false", "type": "Edm.Int32" }, { "name": "Price", "nullable": "false", "type": "Edm.Decimal"}],
"navigationProperty": [
{ "name": "Category", "fromRole": "Product_Category", "toRole": "Category_Products", "relationship": "ODataDemo.Product_Category_Category_Products" }
]
}, {
"name": "Category",
"key": { "propertyRef": [{ "name": "ID"}] },
"property": [{ "name": "ID", "nullable": "false", "type": "Edm.Int32" }, { "name": "Name", "type": "Edm.String", "FC_KeepInContent": "true", "FC_ContentKind": "text", "FC_TargetPath": "SyndicationTitle"}],
"navigationProperty": [{ "name": "Products", "fromRole": "Category_Products", "toRole": "Product_Category", "relationship": "ODataDemo.Product_Category_Category_Products"}]
}],
"association": [{ "name": "Product_Category_Category_Products", "end": [{ "type": "ODataDemo.Category", "multiplicity": "0..1", "role": "Category_Products" }, { "type": "ODataDemo.Product", "multiplicity": "*", "role": "Product_Category"}]}],
"entityContainer": [{ "name": "DemoService", "isDefaultEntityContainer": "true", "entitySet": [{ "name": "Products", "entityType": "ODataDemo.Product" }, { "name": "Categories", "entityType": "ODataDemo.Category"}], "functionImport": [{ "name": "Discount", "isAlwaysBindable": "true", "isBindable": "true", "parameter": [{ "name": "product", "type": "ODataDemo.Product" }, { "name": "discountPercentage", "nullable": "false", "type": "Edm.Int32"}]}], "associationSet": [{ "name": "Products_Category_Categories", "association": "ODataDemo.Product_Category_Category_Products", "end": [{ "role": "Product_Category", "entitySet": "Products" }, { "role": "Category_Products", "entitySet": "Categories"}]}]}]
}]
}
};
djstest.assertAreEqualDeep(expected, parsedMetadata, "metadata should be parsed to datajs format");
djstest.done();
});
})(this);