Skip to content

Commit

Permalink
Fixing conversion from nested objects to url (#226)
Browse files Browse the repository at this point in the history
* Fixing serialization

* Missed file, still fixing serialization

* Removing js file added on accident

* Responding to feedback

* Responding to feedback
  • Loading branch information
damccorm authored Sep 24, 2018
1 parent 7b66ae5 commit ab5bc50
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 41 deletions.
64 changes: 25 additions & 39 deletions api/VsoClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -183,41 +183,37 @@ export class VsoClient {
return url.resolve(this.baseUrl, path.join(this.basePath, relativeUrl));
}

private getSerializedObject(queryValue: any, object: any): string {
let value:string = "";
let first:boolean = true;

for (let property in object) {
if (object.hasOwnProperty(property)) {
let prop = object[property];
let valueString = this.getValueString(property, prop);
if (first && prop !== undefined) {
value += valueString;
first = false;
} else if (prop !== undefined) {
value += "&" + valueString;
private queryParamsToStringHelper(queryParams: any, prefix: string): string {
if (queryParams === undefined) {
return '';
}
let queryString: string = '';

if(typeof(queryParams) !== 'string') {
for (let property in queryParams) {
if (queryParams.hasOwnProperty(property)) {
const prop = queryParams[property];
const newPrefix = prefix + encodeURIComponent(property.toString()) + '.';
queryString += this.queryParamsToStringHelper(prop, newPrefix);
}
}
}

if (value == ""){
value += queryValue + "=" + object.toString();
if(queryString === '' && prefix.length > 0){
// Will always need to chop period off of end of prefix
queryString = prefix.slice(0,-1) + '=' + encodeURIComponent(queryParams.toString()) + '&';
}
return value;
return queryString;
}

private getValueString(queryValue, value) {
let valueString = null;
if (typeof(value) === 'object') {
valueString = this.getSerializedObject(queryValue, value);
} else {
valueString = queryValue + "=" + encodeURIComponent(value);
}
return valueString;
private queryParamsToString(queryParams: any): string {
const queryString: string = '?' + this.queryParamsToStringHelper(queryParams, '');

// Will always need to slice either a ? or & off of the end
return queryString.slice(0,-1);
}

protected getRequestUrl(routeTemplate: string, area: string, resource: string, routeValues: any, queryParams?: any): string {

// Add area/resource route values (based on the location)
routeValues = routeValues || {};
if (!routeValues.area) {
Expand All @@ -230,22 +226,12 @@ export class VsoClient {
// Replace templated route values
let relativeUrl = this.replaceRouteValues(routeTemplate, routeValues);

//append query parameters to the end
let first = true;
for (let queryValue in queryParams) {
if (queryParams[queryValue] != null) {
let value = queryParams[queryValue];
let valueString = this.getValueString(queryValue, value);
if (first) {
relativeUrl += "?" + valueString;
first = false;
} else {
relativeUrl += "&" + valueString;
}
}
// Append query parameters to the end
if (queryParams) {
relativeUrl += this.queryParamsToString(queryParams);
}

//resolve the relative url with the base
// Resolve the relative url with the base
return url.resolve(this.baseUrl, path.join(this.basePath, relativeUrl));
}

Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "azure-devops-node-api",
"description": "Node client for Azure DevOps and TFS REST APIs",
"version": "6.6.1",
"version": "6.6.2",
"main": "./WebApi.js",
"types": "./WebApi.d.ts",
"scripts": {
Expand Down
23 changes: 22 additions & 1 deletion test/units/tests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,28 @@ describe('VSOClient Units', function () {

//Assert
assert(res.apiVersion === '1');
assert(res.requestUrl === 'https://dev.azure.com/testTemplate?innerstatus=2');
assert(res.requestUrl === 'https://dev.azure.com/testTemplate?status.innerstatus=2');
});

it('gets versioning data with complex nested query params', async () => {
//Arrange
nock('https://dev.azure.com/_apis/testArea5', {
reqheaders: {
'accept': 'application/json',
'user-agent': 'testAgent'
}})
.options('')
.reply(200, {
value: [{id: 'testLocation', maxVersion: '1', releasedVersion: '1', routeTemplate: 'testTemplate', area: 'testArea5', resourceName: 'testName', resourceVersion: '1'}]
});

//Act
const queryParams = {status: {innerstatus: 2}, version: '1', nestedObject: {nestedField: 'value', innerNestedObject: {key: 'val2'}}};
const res: vsom.ClientVersioningData = await vsoClient.getVersioningData('1', 'testArea5', 'testLocation', {'testKey': 'testValue'}, queryParams);

//Assert
assert.equal(res.apiVersion, '1');
assert.equal(res.requestUrl, 'https://dev.azure.com/testTemplate?status.innerstatus=2&version=1&nestedObject.nestedField=value&nestedObject.innerNestedObject.key=val2');
});

it('gets versioning data after an initialization promise', async () => {
Expand Down

0 comments on commit ab5bc50

Please sign in to comment.