From 7c59a82bf0c45f734d3d8f949038ad29f337711b Mon Sep 17 00:00:00 2001 From: Michael Loughry Date: Mon, 22 Oct 2018 19:51:10 -0700 Subject: [PATCH] Use `toUTCString()` on Date objects. Fixes #250 --- api/VsoClient.ts | 18 +++++++++++------- test/units/tests.ts | 31 ++++++++++++++++++++++++++----- 2 files changed, 37 insertions(+), 12 deletions(-) diff --git a/api/VsoClient.ts b/api/VsoClient.ts index fe77d8d2..131b505b 100644 --- a/api/VsoClient.ts +++ b/api/VsoClient.ts @@ -80,7 +80,7 @@ export class VsoClient { if (regExExecArray[3]) { // requesting preview isPreview = true; - if (regExExecArray[5]) { + if (regExExecArray[5]) { // we have a resource version resourceVersion = +regExExecArray[5]; } @@ -119,7 +119,7 @@ export class VsoClient { return this.beginGetLocation(area, locationId) .then((location: ifm.ApiResourceLocation): ClientVersioningData => { - if (!location) { + if (!location) { throw new Error("Failed to find api location for area: " + area + " id: " + locationId); } @@ -132,7 +132,7 @@ export class VsoClient { }; }); } - + /** * Sets a promise that is waited on before any requests are issued. Can be used to asynchronously * set the request url and auth token manager. @@ -142,10 +142,10 @@ export class VsoClient { this._initializationPromise = promise; } } - + /** * Gets information about an API resource location (route template, supported versions, etc.) - * + * * @param area resource area name * @param locationId Guid of the location to get */ @@ -162,7 +162,7 @@ export class VsoClient { if (!areaLocationsPromise) { let requestUrl = this.resolveUrl(VsoClient.APIS_RELATIVE_PATH + "/" + area); areaLocationsPromise = this.restClient.options(requestUrl) - .then((res:restm.IRestResponse) => { + .then((res:restm.IRestResponse) => { let locationsLookup: VssApiResourceLocationLookup = {}; let resourceLocations: ifm.ApiResourceLocation[] = res.result.value; let i; @@ -201,8 +201,12 @@ export class VsoClient { } if(queryString === '' && prefix.length > 0){ + // Date.prototype.toString() returns a string that is not valid for the REST API. + // Need to specially call `toUTCString()` instead for such cases + const queryValue = typeof queryParams === 'object' && 'toUTCString' in queryParams ? (queryParams as Date).toUTCString() : queryParams.toString(); + // Will always need to chop period off of end of prefix - queryString = prefix.slice(0,-1) + '=' + encodeURIComponent(queryParams.toString()) + '&'; + queryString = prefix.slice(0,-1) + '=' + encodeURIComponent(queryValue) + '&'; } return queryString; } diff --git a/test/units/tests.ts b/test/units/tests.ts index 7eeb5a94..84610a1f 100644 --- a/test/units/tests.ts +++ b/test/units/tests.ts @@ -11,7 +11,7 @@ describe('VSOClient Units', function () { let rest: rm.RestClient; let vsoClient: vsom.VsoClient const baseUrl: string = 'https://dev.azure.com/'; - + before(() => { const userAgent: string = "testAgent"; rest = new rm.RestClient(userAgent, null, []); @@ -162,6 +162,27 @@ describe('VSOClient Units', function () { assert.equal(res.requestUrl, 'https://dev.azure.com/testTemplate?status.innerstatus=2&version=1&nestedObject.nestedField=value&nestedObject.innerNestedObject.key=val2'); }); + it('gets versioning datafor dates', 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 = {min: new Date(Date.UTC(208, 9, 19))}; + 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?min=Wed%2C%2019%20Oct%200208%2000%3A00%3A00%20GMT'); + }); + it('gets versioning data after an initialization promise', async () => { //Arrange nock('https://newbase.com/_apis/testArea6', { @@ -207,7 +228,7 @@ describe('VSOClient Units', function () { }); describe('WebApi Units', function () { - const osName: string = os.platform(); + const osName: string = os.platform(); const osVersion: string = os.release(); const nodeApiName: string = 'azure-devops-node-api'; const nodeApiVersion: string = JSON.parse(fs.readFileSync('package.json', 'utf8')).version; @@ -245,7 +266,7 @@ describe('WebApi Units', function () { // Assert assert.equal(res.apiVersion, '1'); assert.equal(res.requestUrl, 'https://dev.azure.com/testTemplate'); - + }); it('connects to the server with the correct user agent when request settings are not specified', async () => { @@ -273,8 +294,8 @@ describe('WebApi Units', function () { it('supports no_proxy environment variable', async() => { const myWebApi: WebApi.WebApi = new WebApi.WebApi('https://dev.azure.com/', WebApi.getBasicHandler('user', 'password'), null); process.env.no_proxy='dev.azure.com,my-tfs-instance.host' - assert.equal(myWebApi.isNoProxyHost('https://dev.azure.com/myproject'), true); - assert.equal(myWebApi.isNoProxyHost('https://my-tfs-instance.host/myproject'), true); + assert.equal(myWebApi.isNoProxyHost('https://dev.azure.com/myproject'), true); + assert.equal(myWebApi.isNoProxyHost('https://my-tfs-instance.host/myproject'), true); assert.equal(myWebApi.isNoProxyHost('https://my-other-tfs-instance.host/myproject'), false); }); });