1137 lines
38 KiB
JavaScript
1137 lines
38 KiB
JavaScript
describe("Restangular", function() {
|
|
// API
|
|
var Restangular, $httpBackend;
|
|
var accountsModel, restangularAccounts, restangularAccount0, restangularAccount1;
|
|
var accountsHalModel;
|
|
var messages, newAccount;
|
|
|
|
// Load required modules
|
|
beforeEach(angular.mock.module("restangular"));
|
|
|
|
// Init HTTP mock backend and Restangular resources
|
|
beforeEach(inject(function($injector) {
|
|
// Model
|
|
accountsModel = [
|
|
{id: 0, user: "Martin ", amount: 42, transactions: []},
|
|
{id: 1, user: "Paul", amount: 3.1416, transactions: [{from: "Martin", amount: 3, id: 0}, {from: "Anonymous", amount: 0.1416, id:1}]}
|
|
];
|
|
|
|
// HAL model (http://stateless.co/hal_specification.html)
|
|
accountsHalModel = [
|
|
{id: 0, user: "Martin", amount: 42, transaction: [], _links: {self: "/accountsHAL/martin"}},
|
|
{id: 1, user: "Paul", amount: 3.1416, transaction: [
|
|
{from: "Martin", amount: 3, id: 0, _links: {self: "/accountsHAL/paul/transactions/0"}},
|
|
{from: "Anonymous", amount: 0.1416, id: 1, _links: {self: "/accountsHAL/paul/transactions/1"}}
|
|
], _links: {self: "/accountsHAL/paul"}}
|
|
];
|
|
|
|
infoModel = {
|
|
id: 0, text: "Some additional account information"
|
|
}
|
|
|
|
newAccount = {id: 44, user: "First User", amount: 45, transactions: []};
|
|
|
|
messages = [{id: 23, name: "Gonto"}, {id: 45, name: "John"}]
|
|
|
|
accountsDoSomethingModel = { result: 1 };
|
|
|
|
$httpBackend = $injector.get("$httpBackend");
|
|
|
|
$httpBackend.when("HEAD", "/accounts").respond();
|
|
$httpBackend.when("TRACE", "/accounts").respond();
|
|
$httpBackend.when("OPTIONS", "/accounts").respond();
|
|
|
|
$httpBackend.whenGET("/accounts").respond(accountsModel);
|
|
$httpBackend.whenGET("/accounts/do-something").respond(accountsDoSomethingModel);
|
|
$httpBackend.whenJSONP("/accounts").respond(accountsModel);
|
|
$httpBackend.whenGET("/accounts/0,1").respond(accountsModel);
|
|
$httpBackend.whenGET("/accounts/messages").respond(messages);
|
|
$httpBackend.whenGET("/accounts/1/message").respond(messages[0]);
|
|
$httpBackend.whenGET("/accounts/1/messages").respond(messages);
|
|
$httpBackend.whenGET("/accounts/0").respond(accountsModel[0]);
|
|
$httpBackend.whenGET("/accounts/1").respond(accountsModel[1]);
|
|
$httpBackend.whenJSONP("/accounts/1").respond(accountsModel[1]);
|
|
$httpBackend.whenGET("/accounts/1/transactions").respond(accountsModel[1].transactions);
|
|
$httpBackend.whenGET("/accounts/1/transactions/1").respond(accountsModel[1].transactions[1]);
|
|
|
|
$httpBackend.whenGET("/info").respond(infoModel);
|
|
$httpBackend.whenGET("/accounts/1/info").respond(infoModel);
|
|
$httpBackend.whenPUT("/info").respond(function(method, url, data) {
|
|
return [200, data, ""];
|
|
});
|
|
|
|
$httpBackend.whenGET("/accountsHAL").respond(accountsHalModel);
|
|
$httpBackend.whenPUT("/accountsHAL/martin").respond(function(method, url, data) {
|
|
accountsHalModel[0] = angular.fromJson(data);
|
|
return [200, data, ""];
|
|
});
|
|
|
|
// Full URL
|
|
$httpBackend.whenGET('http://accounts.com/all').respond(accountsModel);
|
|
|
|
$httpBackend.whenPOST("/accounts").respond(function(method, url, data, headers) {
|
|
var newData = angular.fromJson(data);
|
|
newData.fromServer = true;
|
|
return [201, JSON.stringify(newData), ""];
|
|
});
|
|
|
|
$httpBackend.whenPOST("/accounts/1/transactions").respond(function(method, url, data, headers) {
|
|
return [201, "", ""];
|
|
});
|
|
|
|
$httpBackend.whenDELETE("/accounts/1/transactions/1").respond(function(method, url, data, headers) {
|
|
return [200, "", ""];
|
|
});
|
|
|
|
$httpBackend.whenDELETE("/accounts/1").respond(function(method, url, data, headers) {
|
|
return [200, "", ""];
|
|
});
|
|
|
|
$httpBackend.whenPOST("/accounts/1").respond(function(method, url, data, headers) {
|
|
return [200, "", ""];
|
|
});
|
|
|
|
$httpBackend.whenPUT("/accounts/1").respond(function(method, url, data, headers) {
|
|
accountsModel[1] = angular.fromJson(data);
|
|
return [201, data, ""];
|
|
});
|
|
|
|
$httpBackend.whenGET("/error").respond(function() {
|
|
return [500, {}, ""];
|
|
});
|
|
|
|
$httpBackend.whenPOST("/customs").respond(function(method, url, data, headers) {
|
|
if (JSON.parse(data).one) {
|
|
return [201, "", ""];
|
|
} else {
|
|
return [400, "", ""];
|
|
}
|
|
});
|
|
|
|
// return the status code given
|
|
// e.g.: /error/404 returns 404 Not Found
|
|
var urlRegex = /\/error\/(\d{3})/;
|
|
$httpBackend.whenGET(urlRegex).respond(function(method, url, data, headers) {
|
|
return [url.match(urlRegex)[1], {}, ""];
|
|
});
|
|
|
|
Restangular = $injector.get("Restangular");
|
|
restangularAccounts = Restangular.all("accounts");
|
|
restangularAccount0 = Restangular.one("accounts", 0);
|
|
restangularAccount1 = Restangular.one("accounts", 1);
|
|
|
|
|
|
// Another API for testing
|
|
customers = [
|
|
{
|
|
id: 0,
|
|
name: "Alice",
|
|
status: 'active',
|
|
credit: 4000.0
|
|
},
|
|
{
|
|
id: 1,
|
|
name: "Bob",
|
|
status: 'active',
|
|
credit: 4000.0
|
|
},
|
|
{
|
|
id: 2,
|
|
name: "Carl",
|
|
status: 'active',
|
|
credit: 4000.0
|
|
}
|
|
];
|
|
publications = [
|
|
{
|
|
id: 1,
|
|
title: "Sample",
|
|
content: "Rich data",
|
|
tags: [
|
|
'science',
|
|
'chemistry'
|
|
]
|
|
}
|
|
];
|
|
newCustomer = {
|
|
id: 3,
|
|
name: "New",
|
|
status: 'active',
|
|
credit: 4000.0
|
|
};
|
|
|
|
$httpBackend.whenGET("/customers/").respond(customers);
|
|
$httpBackend.whenGET("http://localhost:8080/customers/").respond(customers);
|
|
$httpBackend.whenGET("api.new.domain/customers/").respond(customers);
|
|
$httpBackend.whenGET("/customers/?active=true").respond(customers);
|
|
$httpBackend.whenGET("/customers/publications/?tags=chemistry").respond(publications);
|
|
$httpBackend.whenPUT("/customers/0").respond(function (method, url, data) {
|
|
customers[0] = angular.fromJson(data);
|
|
return [200, data, ""];
|
|
});
|
|
$httpBackend.whenPOST("/customers/").respond(function (method, url, data, headers) {
|
|
var newData = angular.fromJson(data);
|
|
newData.fromServer = true;
|
|
return [201, JSON.stringify(newData), ""];
|
|
});
|
|
|
|
}));
|
|
|
|
afterEach(function() {
|
|
$httpBackend.verifyNoOutstandingExpectation();
|
|
$httpBackend.verifyNoOutstandingRequest();
|
|
});
|
|
|
|
describe("Interceptors", function() {
|
|
it("Should add multiple request and response interceptors", function() {
|
|
Restangular.addRequestInterceptor(function(elem) {
|
|
var elemCopy = angular.copy(elem);
|
|
elemCopy.firstRequestInterceptor = true;
|
|
return elemCopy;
|
|
});
|
|
Restangular.addRequestInterceptor(function(elem) {
|
|
expect(elem.firstRequestInterceptor).toBeDefined();
|
|
var elemCopy = angular.copy(elem);
|
|
elemCopy.secondRequestInterceptor = true;
|
|
return elemCopy;
|
|
});
|
|
Restangular.addFullRequestInterceptor(function(elem) {
|
|
expect(elem.firstRequestInterceptor).toBeDefined();
|
|
expect(elem.secondRequestInterceptor).toBeDefined();
|
|
var elemCopy = angular.copy(elem);
|
|
elemCopy.thirdRequestInterceptor = true;
|
|
return {
|
|
element: elemCopy
|
|
};
|
|
});
|
|
|
|
Restangular.addResponseInterceptor(function(elem) {
|
|
var elemCopy = angular.copy(elem);
|
|
elemCopy.firstResponseInterceptor = true;
|
|
return elemCopy;
|
|
});
|
|
|
|
Restangular.addResponseInterceptor(function(elem) {
|
|
expect(elem.firstResponseInterceptor).toBeDefined();
|
|
var elemCopy = angular.copy(elem);
|
|
elemCopy.secondResponseInterceptor = true;
|
|
return elemCopy;
|
|
});
|
|
|
|
$httpBackend.whenPOST("/list").respond(function(method, url, data, headers) {
|
|
var elem = angular.fromJson(data);
|
|
expect(elem.firstRequestInterceptor).toBeDefined();
|
|
expect(elem.secondRequestInterceptor).toBeDefined();
|
|
expect(elem.thirdRequestInterceptor).toBeDefined();
|
|
return [200, elem, ""];
|
|
});
|
|
|
|
$httpBackend.expectPOST('/list');
|
|
|
|
Restangular.all('list').post({name: "Gonto"}).then(function(elem) {
|
|
expect(elem.firstResponseInterceptor).toBeDefined();
|
|
expect(elem.secondResponseInterceptor).toBeDefined();
|
|
});
|
|
|
|
$httpBackend.flush();
|
|
});
|
|
|
|
it("Should add multiple error interceptors", function() {
|
|
$httpBackend.expectGET("/error");
|
|
|
|
var CallbackManager = function() {};
|
|
CallbackManager.successCallback = function() {
|
|
expect(CallbackManager.successCallback).not.toHaveBeenCalled();
|
|
};
|
|
CallbackManager.errorCallback = function() {
|
|
expect(CallbackManager.firstErrorInterceptor).toHaveBeenCalled();
|
|
expect(CallbackManager.secondErrorInterceptor).toHaveBeenCalled();
|
|
};
|
|
|
|
CallbackManager.firstErrorInterceptor = function() {};
|
|
CallbackManager.secondErrorInterceptor = function() {};
|
|
|
|
spyOn(CallbackManager, "successCallback").andCallThrough();
|
|
spyOn(CallbackManager, "firstErrorInterceptor").andCallThrough();
|
|
spyOn(CallbackManager, "secondErrorInterceptor").andCallThrough();
|
|
|
|
Restangular.addErrorInterceptor(CallbackManager.firstErrorInterceptor);
|
|
Restangular.addErrorInterceptor(CallbackManager.secondErrorInterceptor);
|
|
|
|
Restangular.all("error").getList()
|
|
.then(CallbackManager.successCallback)
|
|
.catch(CallbackManager.errorCallback);
|
|
|
|
$httpBackend.flush();
|
|
});
|
|
|
|
it("Should add multiple error interceptors but don't reject the promise if one of them returns false", function() {
|
|
$httpBackend.expectGET("/error");
|
|
|
|
var CallbackManager = function() {};
|
|
CallbackManager.successCallback = function() {
|
|
expect(CallbackManager.successCallback).not.toHaveBeenCalled();
|
|
};
|
|
CallbackManager.errorCallback = function() {
|
|
expect(CallbackManager.errorCallback).not.toHaveBeenCalled();
|
|
};
|
|
|
|
CallbackManager.firstErrorInterceptor = function() {
|
|
return true;
|
|
};
|
|
CallbackManager.secondErrorInterceptor = function() {
|
|
return false; // prevent promise to be rejected
|
|
};
|
|
|
|
spyOn(CallbackManager, "successCallback").andCallThrough();
|
|
spyOn(CallbackManager, "errorCallback").andCallThrough();
|
|
|
|
Restangular.addErrorInterceptor(CallbackManager.firstErrorInterceptor);
|
|
Restangular.addErrorInterceptor(CallbackManager.secondErrorInterceptor);
|
|
|
|
Restangular.all("error").getList()
|
|
.then(CallbackManager.successCallback)
|
|
.catch(CallbackManager.errorCallback);
|
|
|
|
$httpBackend.flush();
|
|
});
|
|
|
|
it("Should add multiple error interceptors for a single get too", function() {
|
|
$httpBackend.expectGET("/error/404");
|
|
|
|
var CallbackManager = function() {};
|
|
CallbackManager.successCallback = function() {
|
|
expect(CallbackManager.successCallback).not.toHaveBeenCalled();
|
|
};
|
|
CallbackManager.errorCallback = function() {
|
|
expect(CallbackManager.firstErrorInterceptor).toHaveBeenCalled();
|
|
expect(CallbackManager.secondErrorInterceptor).toHaveBeenCalled();
|
|
};
|
|
|
|
CallbackManager.firstErrorInterceptor = function(response) {
|
|
expect(response.status).toEqual(404);
|
|
};
|
|
CallbackManager.secondErrorInterceptor = function() {};
|
|
|
|
spyOn(CallbackManager, "successCallback").andCallThrough();
|
|
spyOn(CallbackManager, "firstErrorInterceptor").andCallThrough();
|
|
spyOn(CallbackManager, "secondErrorInterceptor").andCallThrough();
|
|
|
|
Restangular.addErrorInterceptor(CallbackManager.firstErrorInterceptor);
|
|
Restangular.addErrorInterceptor(CallbackManager.secondErrorInterceptor);
|
|
|
|
Restangular.one("error", 404).get()
|
|
.then(CallbackManager.successCallback)
|
|
.catch(CallbackManager.errorCallback);
|
|
|
|
$httpBackend.flush();
|
|
});
|
|
});
|
|
|
|
describe("Transformers", function() {
|
|
it("Should decorate element both on server and local by default", function() {
|
|
|
|
Restangular.extendModel('accounts', function(account) {
|
|
account.extended = function() {return true;}
|
|
return account;
|
|
});
|
|
|
|
Restangular.one('accounts', 1).get().then(function(account) {
|
|
expect(account.extended).toBeDefined();
|
|
});
|
|
|
|
var local = {};
|
|
Restangular.restangularizeElement(null, local, 'accounts');
|
|
expect(local.extended).toBeDefined();
|
|
|
|
$httpBackend.flush();
|
|
});
|
|
|
|
});
|
|
|
|
describe("With Suffix", function() {
|
|
it("shouldn't add suffix to getRestangularUrl", function() {
|
|
var suffixRestangular = Restangular.withConfig(function(RestangularConfigurer) {
|
|
RestangularConfigurer.setRequestSuffix('.json');
|
|
});
|
|
var collection = suffixRestangular.all('accounts');
|
|
expect(collection.getRestangularUrl()).toBe('/accounts');
|
|
expect(collection.one('1').getRestangularUrl()).toBe('/accounts/1');
|
|
});
|
|
|
|
it("should add suffix to getRequestedUrl", function() {
|
|
var suffixRestangular = Restangular.withConfig(function(RestangularConfigurer) {
|
|
RestangularConfigurer.setRequestSuffix('.json');
|
|
});
|
|
var collection = suffixRestangular.all('accounts');
|
|
expect(collection.getRequestedUrl()).toBe('/accounts.json');
|
|
expect(collection.one('1').getRequestedUrl()).toBe('/accounts/1.json');
|
|
});
|
|
|
|
it("should add suffix to request", function() {
|
|
var suffixRestangular = Restangular.withConfig(function(RestangularConfigurer) {
|
|
RestangularConfigurer.setRequestSuffix('.json');
|
|
});
|
|
var collection = suffixRestangular.all('accounts');
|
|
$httpBackend.expectGET('/accounts.json').respond(200);
|
|
$httpBackend.expectGET('/accounts/1.json').respond(200);
|
|
collection.getList();
|
|
collection.get('1');
|
|
$httpBackend.flush();
|
|
});
|
|
|
|
it("shouldn't add suffix to allUrl", function() {
|
|
var suffixRestangular = Restangular.withConfig(function(RestangularConfigurer) {
|
|
RestangularConfigurer.setRequestSuffix('.json');
|
|
});
|
|
$httpBackend.expectGET('http://accounts.com/all');
|
|
suffixRestangular.allUrl('accounts', 'http://accounts.com/all').getList();
|
|
$httpBackend.flush();
|
|
});
|
|
});
|
|
|
|
describe("JSONp", function() {
|
|
it("should work for get", function() {
|
|
Restangular.setJsonp(true);
|
|
Restangular.one('accounts', 1).get();
|
|
|
|
$httpBackend.expectJSONP('/accounts/1');
|
|
$httpBackend.flush();
|
|
});
|
|
|
|
it("should work for getList", function() {
|
|
Restangular.setJsonp(true);
|
|
Restangular.all('accounts').getList();
|
|
|
|
$httpBackend.expectJSONP('/accounts');
|
|
$httpBackend.flush();
|
|
});
|
|
|
|
it("shouldn't override post", function() {
|
|
Restangular.setJsonp(true);
|
|
restangularAccounts.post({id: 2, user: "Someone"});
|
|
|
|
$httpBackend.expectPOST('/accounts').respond(201, '');
|
|
$httpBackend.flush();
|
|
});
|
|
|
|
|
|
});
|
|
|
|
describe("Local data", function() {
|
|
it("Should restangularize a collection OK", function() {
|
|
var collection = angular.copy(accountsModel);
|
|
|
|
Restangular.restangularizeCollection(null, collection, 'accounts');
|
|
|
|
expect(_.has(collection, 'get')).toBe(true);
|
|
expect(_.has(collection[0], 'get')).toBe(true);
|
|
|
|
expect(collection.getRestangularUrl()).toBe('/accounts');
|
|
expect(collection[0].getRestangularUrl()).toBe('/accounts/0');
|
|
|
|
});
|
|
});
|
|
|
|
describe("restangularizePromiseIntercept", function() {
|
|
it("should be invoked by restangularizePromise", function() {
|
|
var calledWithPromise;
|
|
|
|
Restangular.setRestangularizePromiseInterceptor(function(promise) {
|
|
calledWithPromise = promise;
|
|
|
|
promise.$object.$custom = true;
|
|
});
|
|
|
|
var promise = Restangular.one('accounts', 1).get();
|
|
|
|
expect(calledWithPromise).toBeDefined();
|
|
expect(promise.$object.$custom).toBeDefined();
|
|
|
|
$httpBackend.flush();
|
|
});
|
|
});
|
|
|
|
describe("$object", function() {
|
|
it("Should work for single get", function() {
|
|
var promise = Restangular.one('accounts', 1).get();
|
|
var obj = promise.$object;
|
|
expect(obj).toBeDefined();
|
|
expect(obj.amount).toBeUndefined();
|
|
|
|
$httpBackend.flush();
|
|
|
|
expect(obj.amount).toEqual(3.1416);
|
|
});
|
|
|
|
it("Shouldn't be restangularized by default", function() {
|
|
Restangular.extendModel('accounts', function(account) {
|
|
account.extended = function() {return true;}
|
|
return account;
|
|
});
|
|
|
|
var promise = Restangular.one('accounts', 1).get();
|
|
var obj = promise.$object;
|
|
expect(obj).toBeDefined();
|
|
expect(obj.extended).toBeUndefined();
|
|
|
|
$httpBackend.flush();
|
|
});
|
|
|
|
it("Should work for single get", function() {
|
|
var promise = Restangular.all('accounts').getList();
|
|
var list = promise.$object;
|
|
expect(list).toBeDefined();
|
|
expect(list.length).toEqual(0);
|
|
|
|
$httpBackend.flush();
|
|
|
|
expect(list.length).toEqual(2);
|
|
expect(list[1].amount).toEqual(3.1416);
|
|
});
|
|
});
|
|
|
|
describe("ALL", function() {
|
|
it("getList() should return an array of items", function() {
|
|
restangularAccounts.getList().then(function(accounts) {
|
|
expect(Restangular.stripRestangular(accounts)).toEqual(Restangular.stripRestangular(accountsModel));
|
|
});
|
|
|
|
$httpBackend.flush();
|
|
});
|
|
|
|
it("several getList() should return an array of items", function() {
|
|
$httpBackend.expectGET('/accounts/0,1');
|
|
Restangular.several("accounts", 0, 1).getList().then(function(accounts) {
|
|
expect(Restangular.stripRestangular(accounts)).toEqual(Restangular.stripRestangular(accountsModel));
|
|
});
|
|
|
|
$httpBackend.flush();
|
|
});
|
|
|
|
it("several remove() should work", function() {
|
|
$httpBackend.expectDELETE('/accounts/0,1').respond([200, "", ""]);
|
|
Restangular.several("accounts", 0, 1).remove();
|
|
|
|
$httpBackend.flush();
|
|
});
|
|
|
|
it("get(id) should return the item with given id", function() {
|
|
restangularAccounts.get(0).then(function(account) {
|
|
expect(Restangular.stripRestangular(account)).toEqual(Restangular.stripRestangular(accountsModel[0]));
|
|
});
|
|
|
|
$httpBackend.flush();
|
|
});
|
|
|
|
it('uses all to get the list without parameters', function() {
|
|
Restangular.one('accounts', 1).all('messages').getList();
|
|
$httpBackend.expectGET('/accounts/1/messages');
|
|
$httpBackend.flush();
|
|
});
|
|
|
|
it("Custom GET methods should work", function() {
|
|
restangularAccounts.customGETLIST("messages").then(function(msgs) {
|
|
expect(Restangular.stripRestangular(msgs)).toEqual(Restangular.stripRestangular(messages));
|
|
});
|
|
|
|
$httpBackend.flush();
|
|
});
|
|
|
|
it("post() should add a new item", function() {
|
|
restangularAccounts.post({id: 2, user: "Someone"}).then(function() {
|
|
expect(accountsModel.length).toEqual(2);
|
|
});
|
|
|
|
$httpBackend.expectPOST('/accounts').respond(201, '');
|
|
$httpBackend.flush();
|
|
});
|
|
|
|
it("customPOST() should add a new item", function() {
|
|
restangularAccounts.customPOST({id: 2, user: "Someone"}).then(function() {
|
|
expect(accountsModel.length).toEqual(2);
|
|
});
|
|
|
|
$httpBackend.expectPOST('/accounts').respond(201, '');
|
|
$httpBackend.flush();
|
|
});
|
|
|
|
it("post() should work with arrays", function() {
|
|
Restangular.all('places').post([{name: "Gonto"}, {name: 'John'}]).then(function(value) {
|
|
expect(value.length).toEqual(2);
|
|
});
|
|
|
|
$httpBackend.expectPOST('/places').respond(function(method, url, data, headers) {
|
|
return [201, angular.fromJson(data), ""];
|
|
});
|
|
|
|
$httpBackend.flush();
|
|
});
|
|
|
|
it("post() should add a new item with data and return the data from the server", function() {
|
|
restangularAccounts.post(newAccount).then(function(added) {
|
|
expect(added.fromServer).toEqual(true);
|
|
expect(added.id).toEqual(newAccount.id);
|
|
});
|
|
|
|
$httpBackend.expectPOST('/accounts');
|
|
$httpBackend.flush();
|
|
});
|
|
|
|
it("Doing a post and then other operation (delete) should call right URLs", function() {
|
|
restangularAccounts.post(newAccount).then(function(added) {
|
|
added.remove();
|
|
$httpBackend.expectDELETE('/accounts/44').respond(201, '');
|
|
});
|
|
|
|
$httpBackend.flush();
|
|
});
|
|
|
|
it("Doing a post to a server that returns no element will return undefined", function() {
|
|
restangularAccounts.getList().then(function(accounts) {
|
|
var newTransaction = {id: 1, name: "Gonto"};
|
|
accounts[1].post('transactions', newTransaction).then(function(transaction) {
|
|
expect(transaction).toBeUndefined();
|
|
});
|
|
});
|
|
|
|
$httpBackend.flush();
|
|
});
|
|
|
|
it("head() should safely return", function() {
|
|
restangularAccounts.head().then(function() {
|
|
expect(true).toBe(true);
|
|
});
|
|
$httpBackend.flush();
|
|
});
|
|
|
|
it("trace() should safely return", function() {
|
|
restangularAccounts.trace().then(function() {
|
|
expect(true).toBe(true);
|
|
});
|
|
|
|
$httpBackend.flush();
|
|
});
|
|
|
|
it("customPUT should work", function() {
|
|
$httpBackend.expectPUT('/accounts/hey').respond(accountsModel);
|
|
restangularAccounts.customPUT({key: 'value'}, 'hey');
|
|
|
|
$httpBackend.flush();
|
|
});
|
|
|
|
it("options() should safely return", function() {
|
|
restangularAccounts.options().then(function() {
|
|
expect(true).toBe(true);
|
|
});
|
|
|
|
$httpBackend.flush();
|
|
});
|
|
|
|
it("getList() should correctly handle params after customDELETE", function() {
|
|
$httpBackend.expectGET('/accounts?foo=1').respond(accountsModel);
|
|
restangularAccounts.getList({foo: 1}).then(function(){
|
|
$httpBackend.expectDELETE('/accounts?id=1').respond(201, '');
|
|
return restangularAccounts.customDELETE('', {id: 1});
|
|
}).then(function() {
|
|
$httpBackend.expectGET('/accounts?foo=1').respond(accountsModel);
|
|
return restangularAccounts.getList({foo: 1});
|
|
}).then(function(accounts) {
|
|
expect(Restangular.stripRestangular(accounts)).toEqual(Restangular.stripRestangular(accountsModel));
|
|
});
|
|
|
|
$httpBackend.flush();
|
|
});
|
|
});
|
|
|
|
describe("Scoped Service", function() {
|
|
|
|
it("should correctly work", function() {
|
|
var Accounts = Restangular.service('accounts');
|
|
Accounts.post(newAccount);
|
|
Accounts.one(0).get();
|
|
Accounts.getList();
|
|
|
|
$httpBackend.expectPOST('/accounts');
|
|
$httpBackend.expectGET('/accounts/0');
|
|
$httpBackend.expectGET('/accounts');
|
|
$httpBackend.flush();
|
|
});
|
|
|
|
it("should correctly work with children", function() {
|
|
var Transactions = Restangular.service('transactions', restangularAccount1);
|
|
Transactions.post(newAccount);
|
|
Transactions.one(1).get();
|
|
Transactions.getList();
|
|
|
|
$httpBackend.expectPOST('/accounts/1/transactions');
|
|
$httpBackend.expectGET('/accounts/1/transactions/1');
|
|
$httpBackend.expectGET('/accounts/1/transactions');
|
|
$httpBackend.flush();
|
|
});
|
|
|
|
it("should add custom collection method added with withConfig", function() {
|
|
var Accounts = Restangular.withConfig(function(RestangularConfigurer) {
|
|
RestangularConfigurer.addElementTransformer('accounts', true, function(worker) {
|
|
worker.addRestangularMethod('doSomething', 'get', 'do-something');
|
|
return worker;
|
|
});
|
|
}).service('accounts');
|
|
|
|
expect(Accounts.doSomething).toBeDefined();
|
|
expect(_.isFunction(Accounts.doSomething)).toBeTruthy();
|
|
|
|
Accounts.post(newAccount);
|
|
Accounts.one(0).get();
|
|
Accounts.getList();
|
|
Accounts.doSomething();
|
|
|
|
$httpBackend.expectPOST('/accounts');
|
|
$httpBackend.expectGET('/accounts/0');
|
|
$httpBackend.expectGET('/accounts');
|
|
$httpBackend.expectGET('/accounts/do-something');
|
|
$httpBackend.flush();
|
|
});
|
|
});
|
|
|
|
describe("ONE", function() {
|
|
it("get() should return a JSON item", function() {
|
|
restangularAccount1.get().then(function(account) {
|
|
expect(Restangular.stripRestangular(account))
|
|
.toEqual(Restangular.stripRestangular(accountsModel[1]));
|
|
});
|
|
|
|
$httpBackend.flush();
|
|
});
|
|
|
|
it("Should save as put correctly", function() {
|
|
restangularAccount1.get().then(function(account) {
|
|
$httpBackend.expectPUT('/accounts/1');
|
|
account.put();
|
|
});
|
|
|
|
$httpBackend.flush();
|
|
});
|
|
|
|
it("Should save as post correctly", function() {
|
|
var account1 = angular.copy(restangularAccount1);
|
|
$httpBackend.expectPOST('/accounts/1');
|
|
account1.name = "Hey";
|
|
account1.save();
|
|
|
|
$httpBackend.flush();
|
|
});
|
|
|
|
it("Should keep route property when element is created", function() {
|
|
var account1 = Restangular.restangularizeElement(null, {}, 'accounts');
|
|
$httpBackend.expectPOST('/accounts');
|
|
$httpBackend.expectPUT('/accounts/1');
|
|
account1.name = "Hey";
|
|
account1.save().then(function(accountFromServer) {
|
|
accountFromServer.id = 1;
|
|
return accountFromServer.save();
|
|
}).then(function(accountFromServer2) {
|
|
expect(accountFromServer2.route).toBe(account1.route);
|
|
});
|
|
$httpBackend.flush()
|
|
});
|
|
|
|
it("Should make RequestLess connections with one", function() {
|
|
restangularAccount1.one("transactions", 1).get().then(function(transaction) {
|
|
expect(Restangular.stripRestangular(transaction))
|
|
.toEqual(Restangular.stripRestangular(accountsModel[1].transactions[1]));
|
|
});
|
|
|
|
$httpBackend.flush();
|
|
});
|
|
|
|
it("Should make RequestLess connections with all", function() {
|
|
restangularAccount1.all("transactions").getList().then(function(transactions) {
|
|
expect(Restangular.stripRestangular(transactions))
|
|
.toEqual(Restangular.stripRestangular(accountsModel[1].transactions));
|
|
});
|
|
|
|
$httpBackend.flush();
|
|
});
|
|
|
|
|
|
it("Custom GET methods should work", function() {
|
|
restangularAccount1.customGET("message").then(function(msg) {
|
|
expect(Restangular.stripRestangular(msg)).toEqual(Restangular.stripRestangular(messages[0]));
|
|
});
|
|
|
|
$httpBackend.flush();
|
|
});
|
|
|
|
it("put() should update the value", function() {
|
|
restangularAccount1.get().then(function(account) {
|
|
account.amount = 1.618;
|
|
account.put().then(function(newAc) {
|
|
expect(accountsModel[1].amount).toEqual(1.618);
|
|
newAc.remove();
|
|
$httpBackend.expectDELETE("/accounts/1");
|
|
});
|
|
$httpBackend.expectPUT("/accounts/1");
|
|
|
|
|
|
});
|
|
|
|
$httpBackend.flush();
|
|
});
|
|
|
|
it("should return an array when accessing a subvalue", function() {
|
|
restangularAccount1.get().then(function(account) {
|
|
account.getList("transactions").then(function(transactions) {
|
|
expect(Restangular.stripRestangular(transactions))
|
|
.toEqual(Restangular.stripRestangular(accountsModel[1].transactions));
|
|
});
|
|
});
|
|
|
|
$httpBackend.flush();
|
|
});
|
|
});
|
|
|
|
describe("COPY", function() {
|
|
it("should copy an object and 'this' should reference the copied object", function() {
|
|
var copiedAccount = Restangular.copy(accountsModel[0]);
|
|
var that;
|
|
|
|
copiedAccount.user = "Copied string";
|
|
expect(copiedAccount).not.toBe(accountsModel[0]);
|
|
|
|
// create a spy for one of the methods to capture the value of 'this'
|
|
spyOn(copiedAccount, 'getRestangularUrl').andCallFake(function() {
|
|
that = this;
|
|
});
|
|
|
|
copiedAccount.getRestangularUrl(); // invoke the method we are spying on
|
|
expect(that).toBe(copiedAccount);
|
|
});
|
|
});
|
|
|
|
describe("getRestangularUrl", function() {
|
|
it("should return the generated URL when you chain Restangular methods together", function() {
|
|
var restangularSpaces = Restangular.one("accounts",123).one("buildings", 456).all("spaces");
|
|
expect(restangularSpaces.getRestangularUrl()).toEqual("/accounts/123/buildings/456/spaces");
|
|
});
|
|
});
|
|
|
|
describe("getRestangularUrl with useCannonicalId set to true", function() {
|
|
it("should return the generated URL when you chain Restangular methods together", function() {
|
|
var R = Restangular.withConfig(function(config) {
|
|
config.setUseCannonicalId(true);
|
|
});
|
|
var restangularSpaces = R.one("accounts",123).one("buildings", 456).all("spaces");
|
|
expect(restangularSpaces.getRestangularUrl()).toEqual("/accounts/123/buildings/456/spaces");
|
|
});
|
|
});
|
|
|
|
|
|
describe("addElementTransformer", function() {
|
|
it("should allow for a custom method to be placed at the collection level", function() {
|
|
var accountsPromise;
|
|
|
|
Restangular.addElementTransformer('accounts', true, function(collection) {
|
|
collection.totalAmount = function() {};
|
|
return collection;
|
|
});
|
|
|
|
accountsPromise = Restangular.all('accounts').getList();
|
|
|
|
accountsPromise.then(function(accounts) {
|
|
expect(typeof accounts.totalAmount).toEqual("function");
|
|
});
|
|
|
|
$httpBackend.flush();
|
|
});
|
|
|
|
it("should allow for a custom method to be placed at the model level when one model is requested", function() {
|
|
var accountPromise;
|
|
|
|
Restangular.addElementTransformer('accounts', false, function(model) {
|
|
model.prettifyAmount = function() {};
|
|
return model;
|
|
});
|
|
|
|
accountPromise = Restangular.one('accounts', 1).get();
|
|
|
|
accountPromise.then(function(account) {
|
|
expect(typeof account.prettifyAmount).toEqual("function");
|
|
});
|
|
|
|
$httpBackend.flush();
|
|
});
|
|
|
|
it("should allow for a custom method to be placed at the model level when several models are requested", function() {
|
|
var accountPromise;
|
|
|
|
Restangular.addElementTransformer('accounts', false, function(model) {
|
|
model.prettifyAmount = function() {};
|
|
return model;
|
|
});
|
|
|
|
accountsPromise = Restangular.all('accounts', 1).getList();
|
|
|
|
accountsPromise.then(function(accounts) {
|
|
accounts.forEach(function(account, index) {
|
|
expect(typeof account.prettifyAmount).toEqual("function");
|
|
});
|
|
});
|
|
|
|
$httpBackend.flush();
|
|
});
|
|
});
|
|
|
|
describe("extendCollection", function() {
|
|
it("should be an alias for a specific invocation of addElementTransformer", function() {
|
|
var spy = spyOn(Restangular, 'addElementTransformer');
|
|
|
|
var fn = function(collection) {
|
|
collection.totalAmount = function() {};
|
|
return collection;
|
|
};
|
|
|
|
Restangular.extendCollection('accounts', fn);
|
|
|
|
expect(spy).toHaveBeenCalledWith('accounts', true, fn);
|
|
});
|
|
});
|
|
|
|
describe("extendModel", function() {
|
|
it("should be an alias for a specific invocation of addElementTransformer", function() {
|
|
var spy = spyOn(Restangular, 'addElementTransformer');
|
|
|
|
var fn = function(model) {
|
|
model.prettifyAmount = function() {};
|
|
return model;
|
|
};
|
|
|
|
Restangular.extendModel('accounts', fn);
|
|
|
|
expect(spy).toHaveBeenCalledWith('accounts', false, fn);
|
|
});
|
|
});
|
|
|
|
describe("headers", function() {
|
|
it("should return defaultHeaders", function() {
|
|
var defaultHeaders = {testheader:'header value'};
|
|
Restangular.setDefaultHeaders(defaultHeaders);
|
|
expect(Restangular.defaultHeaders).toEqual(defaultHeaders);
|
|
});
|
|
|
|
it("should pass uppercase methods in X-HTTP-Method-Override", function() {
|
|
Restangular.setMethodOverriders(["put"]);
|
|
$httpBackend.expectPOST('/overriders/1').respond(function(method, url, data, headers) {
|
|
expect(headers['X-HTTP-Method-Override']).toBe('PUT');
|
|
return {};
|
|
});
|
|
Restangular.one('overriders', 1).put();
|
|
$httpBackend.flush();
|
|
});
|
|
});
|
|
|
|
describe("defaultRequestParams", function() {
|
|
it("should return defaultRequestParams", function() {
|
|
var defaultRequestParams = {param:'value'};
|
|
|
|
Restangular.setDefaultRequestParams(defaultRequestParams);
|
|
|
|
expect(Restangular.requestParams.common).toEqual(defaultRequestParams);
|
|
});
|
|
|
|
it("should be able to set default params for get, post, put.. methods separately", function() {
|
|
var postParams = {post:'value'},
|
|
putParams = {put:'value'};
|
|
|
|
Restangular.setDefaultRequestParams('post', postParams);
|
|
expect(Restangular.requestParams.post).toEqual(postParams);
|
|
|
|
Restangular.setDefaultRequestParams('put', putParams);
|
|
expect(Restangular.requestParams.put).toEqual(putParams);
|
|
|
|
expect(Restangular.requestParams.common).not.toEqual(putParams);
|
|
});
|
|
|
|
it("should be able to set default params for multiple methods with array", function() {
|
|
var defaultParams = {param:'value'};
|
|
|
|
Restangular.setDefaultRequestParams(['post', 'put'], defaultParams);
|
|
|
|
expect(Restangular.requestParams.post).toEqual(defaultParams);
|
|
expect(Restangular.requestParams.put).toEqual(defaultParams);
|
|
|
|
expect(Restangular.requestParams.common).not.toEqual(defaultParams);
|
|
});
|
|
});
|
|
|
|
describe("withConfig", function() {
|
|
it("should create new service with scoped configuration", function() {
|
|
var childRestangular = Restangular.withConfig(function(RestangularConfigurer){
|
|
RestangularConfigurer.setBaseUrl('/api/v1');
|
|
});
|
|
|
|
expect(Restangular.configuration.baseUrl).toEqual('');
|
|
expect(childRestangular.configuration.baseUrl).toEqual('/api/v1');
|
|
|
|
});
|
|
|
|
it("should allow nested configurations", function() {
|
|
var childRestangular = Restangular.withConfig(function(RestangularConfigurer){
|
|
RestangularConfigurer.setBaseUrl('/api/v1');
|
|
});
|
|
|
|
var grandchildRestangular = childRestangular.withConfig(function(RestangularConfigurer){
|
|
RestangularConfigurer.setRequestSuffix('.json');
|
|
});
|
|
|
|
expect(Restangular.configuration.baseUrl).toEqual('');
|
|
expect(Restangular.configuration.suffix).toEqual(null);
|
|
|
|
expect(childRestangular.configuration.baseUrl).toEqual('/api/v1');
|
|
expect(childRestangular.configuration.suffix).toEqual(null);
|
|
|
|
expect(grandchildRestangular.configuration.baseUrl).toEqual('/api/v1');
|
|
expect(grandchildRestangular.configuration.suffix).toEqual('.json');
|
|
});
|
|
});
|
|
|
|
describe("Self linking", function() {
|
|
it("Should request the link in HAL format", function() {
|
|
var linkRestangular = Restangular.withConfig(function(RestangularConfigurer) {
|
|
RestangularConfigurer.setRestangularFields({
|
|
selfLink: "_links.self"
|
|
});
|
|
});
|
|
|
|
var arr = linkRestangular.all('accountsHAL').getList().$object;
|
|
$httpBackend.flush();
|
|
|
|
var account = arr[0];
|
|
$httpBackend.expectPUT("/accountsHAL/martin");
|
|
account.name = "Updated";
|
|
account.put();
|
|
|
|
$httpBackend.flush();
|
|
});
|
|
});
|
|
|
|
describe("Singe one (endpoint not expecting an id)", function() {
|
|
it('does not use the id for single resource GET', function() {
|
|
Restangular.one('info', 0, true).get();
|
|
$httpBackend.expectGET('/info');
|
|
$httpBackend.flush();
|
|
});
|
|
|
|
it('getRestangularUrl() returns still the url without id after GET', function() {
|
|
record = Restangular.one('info', 0, true);
|
|
record.get().then(function(data){
|
|
expect(data.getRestangularUrl()).toEqual("/info")
|
|
});
|
|
$httpBackend.expectGET('/info');
|
|
$httpBackend.flush();
|
|
});
|
|
|
|
it('does not use the id for single nested resource GET', function() {
|
|
Restangular.one('accounts', 1).one('info', 0, true).get()
|
|
$httpBackend.expectGET('/accounts/1/info');
|
|
$httpBackend.flush();
|
|
});
|
|
|
|
it('does not use the id for single resource PUT', function() {
|
|
Restangular.one('info', 0, true).put();
|
|
$httpBackend.expectPUT('/info');
|
|
$httpBackend.flush();
|
|
});
|
|
});
|
|
|
|
describe("setSelfLinkAbsoluteUrl", function() {
|
|
it("works", function() {
|
|
var childRestangular = Restangular.withConfig(function(RestangularConfigurer){
|
|
RestangularConfigurer.setSelfLinkAbsoluteUrl(false);
|
|
});
|
|
|
|
expect(Restangular.configuration.absoluteUrl).toEqual(true);
|
|
expect(childRestangular.configuration.absoluteUrl).toEqual(false);
|
|
})
|
|
});
|
|
|
|
describe("Misc", function () {
|
|
it("should not strip [one] or [all] key from plain object", function () {
|
|
Restangular.all("customs").customPOST({one: 'I am here', two: 'I am also here'}).then(function () {
|
|
expect(1).toBe(1);
|
|
}, function () {
|
|
expect("Promise").toBe("correctly fulfilled");
|
|
});
|
|
$httpBackend.flush();
|
|
});
|
|
|
|
it("should not stip non-restangularized elements", function () {
|
|
expect(Restangular.stripRestangular(["test","test2"])).toEqual(["test","test2"]);
|
|
});
|
|
});
|
|
|
|
describe("testing normilize url", function () {
|
|
|
|
it("should get a list of objects", function () {
|
|
Restangular.all('customers/').getList().then(function(res){
|
|
res.getList({active: true});
|
|
$httpBackend.expectGET('/customers/?active=true');
|
|
//res.getList('publications/', {tags: 'chemistry'});
|
|
//$httpBackend.expectGET('/customers/publications/?tags=chemistry');
|
|
});
|
|
$httpBackend.expectGET('/customers/');
|
|
$httpBackend.flush();
|
|
});
|
|
|
|
it("should get a list of objects even if the path has extra slashes", function () {
|
|
Restangular.all('customers///').getList().then(function(res){
|
|
res.getList({active: true});
|
|
$httpBackend.expectGET('/customers/?active=true');
|
|
});
|
|
$httpBackend.expectGET('/customers/');
|
|
$httpBackend.flush();
|
|
});
|
|
|
|
it("should post with slash at the end", function () {
|
|
Restangular.all('customers/').getList().then(function(res){
|
|
res.post(newCustomer);
|
|
$httpBackend.expectPOST('/customers/');
|
|
});
|
|
$httpBackend.expectGET('/customers/');
|
|
$httpBackend.flush();
|
|
});
|
|
|
|
it("should put with slash at the end", function () {
|
|
Restangular.all('customers/').getList().then(function(customers){
|
|
customers[0].put();
|
|
$httpBackend.expectPUT('/customers/0');
|
|
});
|
|
$httpBackend.flush();
|
|
});
|
|
|
|
it("should return a normilized URL even it has extra slashes", function() {
|
|
var restangularSpaces = Restangular.one("accounts//", 123).one("buildings//", 456).all("spaces///");
|
|
expect(restangularSpaces.getRestangularUrl()).toEqual("/accounts/123/buildings/456/spaces/");
|
|
});
|
|
|
|
it("should create a new service and still working normilized URL", function() {
|
|
var newRes = Restangular.withConfig(function(RestangularConfigurer){
|
|
RestangularConfigurer.setBaseUrl('http://localhost:8080');
|
|
});
|
|
expect(newRes.configuration.baseUrl).toEqual('http://localhost:8080');
|
|
newRes.all("customers////").getList();
|
|
$httpBackend.expectGET('http://localhost:8080/customers/');
|
|
|
|
var newApi = Restangular.withConfig(function(RestangularConfigurer){
|
|
RestangularConfigurer.setBaseUrl('api.new.domain');
|
|
});
|
|
|
|
expect(newApi.configuration.baseUrl).toEqual('api.new.domain');
|
|
newApi.all("customers////").getList();
|
|
$httpBackend.expectGET('api.new.domain/customers/');
|
|
|
|
$httpBackend.flush();
|
|
});
|
|
});
|
|
});
|