Skip to content

Commit 2bc7dc4

Browse files
committed
Implemented associate and disassociate
1 parent c690ca0 commit 2bc7dc4

File tree

4 files changed

+224
-6
lines changed

4 files changed

+224
-6
lines changed

src/js/WebApiClient.js

Lines changed: 58 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,10 @@
2727

2828
var ApiVersion = "8.0";
2929

30+
// Override promise locally. This is for ensuring that we use bluebird internally, so that calls to WebApiClient have no differing set of
31+
// functions that can be applied to the Promise. For example Promise.finally would not be available without Bluebird.
32+
var Promise = require("bluebird");
33+
3034
function GetCrmContext() {
3135
if (typeof (GetGlobalContext) !== "undefined") {
3236
return GetGlobalContext();
@@ -159,6 +163,10 @@
159163
return promise;
160164
}
161165

166+
function GetRecordUrl (entityName, entityId) {
167+
return WebApiClient.GetApiUrl() + WebApiClient.GetSetName(entityName) + "(" + RemoveIdBrackets(entityId) + ")";
168+
}
169+
162170
WebApiClient.GetApiUrl = function() {
163171
return GetClientUrl() + "/api/data/v" + ApiVersion + "/";
164172
};
@@ -202,7 +210,7 @@
202210
throw new Error("Entity name, ID and entity update object have to be passed!");
203211
}
204212

205-
var url = WebApiClient.GetApiUrl() + WebApiClient.GetSetName(params.entityName) + "(" + RemoveIdBrackets(params.entityId) + ")";
213+
var url = GetRecordUrl(params.entityName, params.entityId);
206214

207215
return SendRequest("PATCH", url, params.entity, params.headers);
208216
};
@@ -214,8 +222,56 @@
214222
throw new Error("Entity name and entity id have to be passed!");
215223
}
216224

217-
var url = WebApiClient.GetApiUrl() + WebApiClient.GetSetName(params.entityName) + "(" + RemoveIdBrackets(params.entityId) + ")";
225+
var url = GetRecordUrl(params.entityName, params.entityId);
226+
227+
return SendRequest("DELETE", url, null, params.headers);
228+
};
229+
230+
WebApiClient.Associate = function(parameters) {
231+
var params = parameters || {};
232+
233+
if (!params.relationShip) {
234+
throw new Error("Relationship has to be passed!");
235+
}
236+
237+
if (!params.source || !params.target) {
238+
throw new Error("Source and target have to be passed!");
239+
}
240+
241+
if (!params.source.entityName || !params.target.entityName || !params.source.entityId || !params.target.entityId) {
242+
throw new Error("Source and target both need to have entityName and entityId set!");
243+
}
244+
245+
var targetUrl = GetRecordUrl(params.target.entityName, params.target.entityId);
246+
var relationShip = "/" + params.relationShip + "/$ref";
218247

248+
var url = targetUrl + relationShip;
249+
250+
var payload = { "@odata.id": GetRecordUrl(params.source.entityName, params.source.entityId) };
251+
252+
return SendRequest("POST", url, payload, params.headers);
253+
};
254+
255+
WebApiClient.Disassociate = function(parameters) {
256+
var params = parameters || {};
257+
258+
if (!params.relationShip) {
259+
throw new Error("Relationship has to be passed!");
260+
}
261+
262+
if (!params.source || !params.target) {
263+
throw new Error("Source and target have to be passed!");
264+
}
265+
266+
if (!params.source.entityName || !params.target.entityName || !params.source.entityId || !params.target.entityId) {
267+
throw new Error("Source and target both need to have entityName and entityId set!");
268+
}
269+
270+
var targetUrl = GetRecordUrl(params.target.entityName, params.target.entityId);
271+
var relationShip = "/" + params.relationShip + "(" + RemoveIdBrackets(params.source.entityId) + ")/$ref";
272+
273+
var url = targetUrl + relationShip;
274+
219275
return SendRequest("DELETE", url, null, params.headers);
220276
};
221277
} (window.WebApiClient = window.WebApiClient || {}));

src/js/globals.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
(function(undefined){
22
var bluebird = require("bluebird");
33

4-
global.Promise = global.Promise || bluebird;
4+
global.Promise = bluebird;
55
}());

src/spec/SpecRunner.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313

1414
<!-- include source files here... -->
1515
<script src="../../node_modules/sinon/pkg/sinon.js"></script>
16-
<script src="../../Publish/WebApiClient.js"></script>
16+
<script src="../../Publish/WebApiClient.min.js"></script>
1717

1818
<!-- include spec files here... -->
1919
<script src="WebApiClientSpec.js"></script>

src/spec/WebApiClientSpec.js

Lines changed: 164 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,13 +42,25 @@ describe("WebApiClient", function() {
4242
// Respond to update Request for account
4343
var updateAccountUrl = RegExp.escape(fakeUrl + "/api/data/v8.0/accounts(00000000-0000-0000-0000-000000000001)");
4444
xhr.respondWith("PATCH", new RegExp(updateAccountUrl, "g"),
45-
[204, { "Content-Type": "application/json" }, "{}"]
45+
[204, { "Content-Type": "application/json" }, "{operation: 'Update'}"]
4646
);
4747

4848
// Respond to Delete Request for account
4949
var deleteAccountUrl = RegExp.escape(fakeUrl + "/api/data/v8.0/accounts(00000000-0000-0000-0000-000000000001)");
5050
xhr.respondWith("DELETE", new RegExp(deleteAccountUrl, "g"),
51-
[204, { "Content-Type": "application/json" }, "{}"]
51+
[204, { "Content-Type": "application/json" }, "{operation: 'Delete'}"]
52+
);
53+
54+
// Respond to Associate Request for account
55+
var associateAccountUrl = RegExp.escape(fakeUrl + "/api/data/v8.0/accounts(00000000-0000-0000-0000-000000000002)/opportunity_customer_accounts/$ref");
56+
xhr.respondWith("POST", new RegExp(associateAccountUrl, "g"),
57+
[204, { "Content-Type": "application/json" }, "{operation: 'Associate'}"]
58+
);
59+
60+
// Respond to Delete Request for account
61+
var disassociateAccountUrl = RegExp.escape(fakeUrl + "/api/data/v8.0/accounts(00000000-0000-0000-0000-000000000002)/opportunity_customer_accounts(00000000-0000-0000-0000-000000000001)/$ref");
62+
xhr.respondWith("DELETE", new RegExp(disassociateAccountUrl, "g"),
63+
[204, { "Content-Type": "application/json" }, "{operation: 'Disassociate'}"]
5264
);
5365
});
5466

@@ -223,6 +235,156 @@ describe("WebApiClient", function() {
223235
});
224236
});
225237

238+
describe("Associate", function() {
239+
it("should fail if no target passed", function(){
240+
expect(function() {
241+
WebApiClient.Associate(
242+
{
243+
relationShip: "opportunity_customer_accounts",
244+
source:
245+
{
246+
entityName: "opportunity",
247+
entityId: "00000000-0000-0000-0000-000000000001"
248+
}
249+
});
250+
}).toThrow();
251+
});
252+
253+
it("should fail if no source passed", function(){
254+
expect(function() {
255+
WebApiClient.Associate(
256+
{
257+
relationShip: "opportunity_customer_accounts",
258+
target:
259+
{
260+
entityName: "account",
261+
entityId: "00000000-0000-0000-0000-000000000002"
262+
}
263+
});
264+
}).toThrow();
265+
});
266+
267+
it("should fail if no relationShip passed", function(){
268+
expect(function() {
269+
WebApiClient.Associate(
270+
{
271+
source:
272+
{
273+
entityName: "opportunity",
274+
entityId: "00000000-0000-0000-0000-000000000001"
275+
},
276+
target:
277+
{
278+
entityName: "account",
279+
entityId: "00000000-0000-0000-0000-000000000002"
280+
}
281+
});
282+
}).toThrow();
283+
});
284+
285+
it("should associate record and return", function(done){
286+
WebApiClient.Associate(
287+
{
288+
relationShip: "opportunity_customer_accounts",
289+
source:
290+
{
291+
entityName: "opportunity",
292+
entityId: "00000000-0000-0000-0000-000000000001"
293+
},
294+
target:
295+
{
296+
entityName: "account",
297+
entityId: "00000000-0000-0000-0000-000000000002"
298+
}
299+
})
300+
.then(function(response){
301+
expect(response).toBeDefined();
302+
})
303+
.catch(function(error) {
304+
expect(error).toBeUndefined();
305+
})
306+
// Wait for promise
307+
.finally(done);
308+
309+
xhr.respond();
310+
});
311+
});
312+
313+
describe("Disassociate", function() {
314+
it("should fail if no target passed", function(){
315+
expect(function() {
316+
WebApiClient.Disassociate(
317+
{
318+
relationShip: "opportunity_customer_accounts",
319+
source:
320+
{
321+
entityName: "opportunity",
322+
entityId: "00000000-0000-0000-0000-000000000001"
323+
}
324+
});
325+
}).toThrow();
326+
});
327+
328+
it("should fail if no source passed", function(){
329+
expect(function() {
330+
WebApiClient.Disassociate(
331+
{
332+
relationShip: "opportunity_customer_accounts",
333+
target:
334+
{
335+
entityName: "account",
336+
entityId: "00000000-0000-0000-0000-000000000002"
337+
}
338+
});
339+
}).toThrow();
340+
});
341+
342+
it("should fail if no relationShip passed", function(){
343+
expect(function() {
344+
WebApiClient.Disassociate(
345+
{
346+
source:
347+
{
348+
entityName: "opportunity",
349+
entityId: "00000000-0000-0000-0000-000000000001"
350+
},
351+
target:
352+
{
353+
entityName: "account",
354+
entityId: "00000000-0000-0000-0000-000000000002"
355+
}
356+
});
357+
}).toThrow();
358+
});
359+
360+
it("should disassociate record and return", function(done){
361+
WebApiClient.Disassociate(
362+
{
363+
relationShip: "opportunity_customer_accounts",
364+
source:
365+
{
366+
entityName: "opportunity",
367+
entityId: "00000000-0000-0000-0000-000000000001"
368+
},
369+
target:
370+
{
371+
entityName: "account",
372+
entityId: "00000000-0000-0000-0000-000000000002"
373+
}
374+
})
375+
.then(function(response){
376+
expect(response).toBeDefined();
377+
})
378+
.catch(function(error) {
379+
expect(error).toBeUndefined();
380+
})
381+
// Wait for promise
382+
.finally(done);
383+
384+
xhr.respond();
385+
});
386+
});
387+
226388
describe("Headers", function() {
227389
it("should set default headers", function(){
228390
expect(WebApiClient.GetDefaultHeaders()).toBeDefined();

0 commit comments

Comments
 (0)