diff --git a/package-lock.json b/package-lock.json index 214ca115f7..57c0351e53 100644 --- a/package-lock.json +++ b/package-lock.json @@ -134,9 +134,9 @@ } }, "@azure/core-http": { - "version": "1.2.0-alpha.20201030.2", - "resolved": "https://registry.npmjs.org/@azure/core-http/-/core-http-1.2.0-alpha.20201030.2.tgz", - "integrity": "sha512-d3tXi2lPb7kRV74PtIfICSGI9OxSovzXt0My6BrM3xwRF6RI46CbGE0QN14g2cY+uCaEEmFeff1lUPsUN8JD8Q==", + "version": "1.2.0-alpha.20201105.1", + "resolved": "https://registry.npmjs.org/@azure/core-http/-/core-http-1.2.0-alpha.20201105.1.tgz", + "integrity": "sha512-dgtg3SZ2DMYaBoItd/QwypW7Pu4CNjH3EZOjwpc21hiJGWdrj6olYYIDqmcO1PZT4PmtMe9TZXra7qCC/FuZ4g==", "requires": { "@azure/abort-controller": "^1.0.0", "@azure/core-auth": "^1.1.3", @@ -1578,9 +1578,9 @@ "dev": true }, "@microsoft.azure/autorest.testserver": { - "version": "2.10.61", - "resolved": "https://registry.npmjs.org/@microsoft.azure/autorest.testserver/-/autorest.testserver-2.10.61.tgz", - "integrity": "sha512-5TPFqejMTrqiCA+V+Tjd6sNCQjnq/SDnv9KOH7BxUJOppDUda4S4A/0ZgI3+wtyp5R9I6uGyjG0W5i59voMzRA==", + "version": "2.10.62", + "resolved": "https://registry.npmjs.org/@microsoft.azure/autorest.testserver/-/autorest.testserver-2.10.62.tgz", + "integrity": "sha512-CYf/S9zbZNGnrKbLiN8XqYzG/99Yl1pY1+n2GylX85TEmxjgyLjUOqp88VWOtlEbYx1drese6S3B2LAaZoxB/w==", "dev": true, "requires": { "azure-storage": "^2.4.0", diff --git a/package.json b/package.json index d9568d9f2f..04352c9c1c 100755 --- a/package.json +++ b/package.json @@ -33,7 +33,7 @@ "@azure-tools/autorest-extension-base": "^3.1.246", "@azure-tools/codegen": "^2.4.267", "@azure-tools/codemodel": "^4.13.339", - "@azure/core-http": "1.2.0-alpha.20201030.2", + "@azure/core-http": "1.2.0-alpha.20201105.1", "@azure/core-lro": "^1.0.1", "@azure/core-paging": "^1.0.0", "@azure/logger": "^1.0.0", @@ -47,7 +47,7 @@ "devDependencies": { "@autorest/test-server": "^3.0.27", "@azure/abort-controller": "^1.0.1", - "@microsoft.azure/autorest.testserver": "^2.10.61", + "@microsoft.azure/autorest.testserver": "^2.10.62", "@types/chai": "^4.2.8", "@types/express": "^4.17.2", "@types/js-yaml": "3.12.1", diff --git a/test/integration/generated/lroParametrizedEndpoints/LICENSE.txt b/test/integration/generated/lroParametrizedEndpoints/LICENSE.txt new file mode 100644 index 0000000000..4c529f375c --- /dev/null +++ b/test/integration/generated/lroParametrizedEndpoints/LICENSE.txt @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2020 Microsoft + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file diff --git a/test/integration/generated/lroParametrizedEndpoints/README.md b/test/integration/generated/lroParametrizedEndpoints/README.md new file mode 100644 index 0000000000..978a66b0bb --- /dev/null +++ b/test/integration/generated/lroParametrizedEndpoints/README.md @@ -0,0 +1,27 @@ +## Azure LroParametrizedEndpointsClient SDK for JavaScript + +This package contains an isomorphic SDK for LroParametrizedEndpointsClient. + +### Currently supported environments + +- Node.js version 8.x.x or higher +- Browser JavaScript + +### How to Install + +```bash +npm install lro-parameterized-endpoints +``` + +### How to use + +#### Sample code + +Refer the sample code in the [azure-sdk-for-js-samples](https://github.com/Azure/azure-sdk-for-js-samples) repository. + +## Related projects + +- [Microsoft Azure SDK for Javascript](https://github.com/Azure/azure-sdk-for-js) + + +![Impressions](https://azure-sdk-impressions.azurewebsites.net/api/impressions/azure-sdk-for-js%2Fsdk%2Fcdn%2Farm-cdn%2FREADME.png) \ No newline at end of file diff --git a/test/integration/generated/lroParametrizedEndpoints/api-extractor.json b/test/integration/generated/lroParametrizedEndpoints/api-extractor.json new file mode 100644 index 0000000000..5fb5b21b56 --- /dev/null +++ b/test/integration/generated/lroParametrizedEndpoints/api-extractor.json @@ -0,0 +1,18 @@ +{ + "$schema": "https://developer.microsoft.com/json-schemas/api-extractor/v7/api-extractor.schema.json", + "mainEntryPointFilePath": "./esm/index.d.ts", + "docModel": { "enabled": true }, + "apiReport": { "enabled": true, "reportFolder": "./review" }, + "dtsRollup": { + "enabled": true, + "untrimmedFilePath": "", + "publicTrimmedFilePath": "./esm/index.d.ts" + }, + "messages": { + "tsdocMessageReporting": { "default": { "logLevel": "none" } }, + "extractorMessageReporting": { + "ae-missing-release-tag": { "logLevel": "none" }, + "ae-unresolved-link": { "logLevel": "none" } + } + } +} diff --git a/test/integration/generated/lroParametrizedEndpoints/package.json b/test/integration/generated/lroParametrizedEndpoints/package.json new file mode 100644 index 0000000000..0447c2ba4a --- /dev/null +++ b/test/integration/generated/lroParametrizedEndpoints/package.json @@ -0,0 +1,52 @@ +{ + "name": "lro-parameterized-endpoints", + "author": "Microsoft Corporation", + "description": "Test Infrastructure for AutoRest", + "version": "1.0.0-preview1", + "dependencies": { + "@azure/core-lro": "^1.0.1", + "@azure/core-http": "^1.1.4", + "tslib": "^1.9.3" + }, + "keywords": ["node", "azure", "typescript", "browser", "isomorphic"], + "license": "MIT", + "main": "./dist/lro-parameterized-endpoints.js", + "module": "./esm/index.js", + "types": "./esm/index.d.ts", + "devDependencies": { + "typescript": "^3.1.1", + "rollup": "^0.66.2", + "rollup-plugin-node-resolve": "^3.4.0", + "rollup-plugin-sourcemaps": "^0.4.2", + "uglify-js": "^3.4.9", + "@microsoft/api-extractor": "7.9.10" + }, + "homepage": "https://github.com/Azure/azure-sdk-for-js", + "repository": { + "type": "git", + "url": "https://github.com/Azure/azure-sdk-for-js.git" + }, + "bugs": { "url": "https://github.com/Azure/azure-sdk-for-js/issues" }, + "files": [ + "dist/**/*.js", + "dist/**/*.js.map", + "dist/**/*.d.ts", + "dist/**/*.d.ts.map", + "esm/**/*.js", + "esm/**/*.js.map", + "esm/**/*.d.ts", + "esm/**/*.d.ts.map", + "src/**/*.ts", + "README.md", + "rollup.config.js", + "tsconfig.json" + ], + "scripts": { + "build": "tsc && rollup -c rollup.config.js && npm run minify && npm run extract-api", + "minify": "uglifyjs -c -m --comments --source-map \"content='./dist/lro-parameterized-endpoints.js.map'\" -o ./dist/lro-parameterized-endpoints.min.js ./dist/lro-parameterized-endpoints.js", + "prepack": "npm install && npm run build", + "extract-api": "api-extractor run --local" + }, + "sideEffects": false, + "autoPublish": true +} diff --git a/test/integration/generated/lroParametrizedEndpoints/rollup.config.js b/test/integration/generated/lroParametrizedEndpoints/rollup.config.js new file mode 100644 index 0000000000..1a73925e07 --- /dev/null +++ b/test/integration/generated/lroParametrizedEndpoints/rollup.config.js @@ -0,0 +1,39 @@ +/* + * Copyright (c) Microsoft Corporation. + * Licensed under the MIT License. + * + * Code generated by Microsoft (R) AutoRest Code Generator. + * Changes may cause incorrect behavior and will be lost if the code is regenerated. + */ + +import rollup from "rollup"; +import nodeResolve from "rollup-plugin-node-resolve"; +import sourcemaps from "rollup-plugin-sourcemaps"; + +/** + * @type {rollup.RollupFileOptions} + */ +const config = { + input: "./esm/lroParametrizedEndpointsClient.js", + external: ["@azure/core-http", "@azure/core-arm"], + output: { + file: "./dist/lro-parameterized-endpoints.js", + format: "umd", + name: "LroParameterizedEndpoints", + sourcemap: true, + globals: { + "@azure/core-http": "coreHttp", + "@azure/core-arm": "coreArm" + }, + banner: `/* + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + * + * Code generated by Microsoft (R) AutoRest Code Generator. + * Changes may cause incorrect behavior and will be lost if the code is regenerated. + */ ` + }, + plugins: [nodeResolve({ module: true }), sourcemaps()] +}; + +export default config; diff --git a/test/integration/generated/lroParametrizedEndpoints/src/index.ts b/test/integration/generated/lroParametrizedEndpoints/src/index.ts new file mode 100644 index 0000000000..1364a5cdbc --- /dev/null +++ b/test/integration/generated/lroParametrizedEndpoints/src/index.ts @@ -0,0 +1,11 @@ +/* + * Copyright (c) Microsoft Corporation. + * Licensed under the MIT License. + * + * Code generated by Microsoft (R) AutoRest Code Generator. + * Changes may cause incorrect behavior and will be lost if the code is regenerated. + */ + +export * from "./models"; +export { LroParametrizedEndpointsClient } from "./lroParametrizedEndpointsClient"; +export { LroParametrizedEndpointsClientContext } from "./lroParametrizedEndpointsClientContext"; diff --git a/test/integration/generated/lroParametrizedEndpoints/src/lro/azureAsyncOperationStrategy.ts b/test/integration/generated/lroParametrizedEndpoints/src/lro/azureAsyncOperationStrategy.ts new file mode 100644 index 0000000000..f54ccc954f --- /dev/null +++ b/test/integration/generated/lroParametrizedEndpoints/src/lro/azureAsyncOperationStrategy.ts @@ -0,0 +1,239 @@ +/* + * Copyright (c) Microsoft Corporation. + * Licensed under the MIT License. + * + * Code generated by Microsoft (R) AutoRest Code Generator. + * Changes may cause incorrect behavior and will be lost if the code is regenerated. + */ + +import { + LROStrategy, + BaseResult, + LROOperationStep, + LROResponseInfo, + FinalStateVia, + LROSYM +} from "./models"; +import { + OperationSpec, + OperationArguments, + OperationResponse +} from "@azure/core-http"; +import { terminalStates } from "./constants"; +import { SendOperationFn } from "."; + +export function createAzureAsyncOperationStrategy( + initialOperation: LROOperationStep, + sendOperationFn: SendOperationFn, + finalStateVia?: FinalStateVia +): LROStrategy { + const lroData = initialOperation.result._response[LROSYM]; + if (!lroData) { + throw new Error( + "Expected lroData to be defined for Azure-AsyncOperation strategy" + ); + } + + let currentOperation = initialOperation; + let lastKnownPollingUrl = + lroData.azureAsyncOperation || lroData.operationLocation; + + return { + isTerminal: () => { + const currentResult = currentOperation.result._response[LROSYM]; + + if (!currentResult) { + throw new Error("Expected lroData to determine terminal status"); + } + + if (currentOperation === initialOperation) { + // Azure-AsyncOperations don't need to check for terminal state + // on originalOperation result, always need to poll + return false; + } + + const { status = "succeeded" } = currentResult; + return terminalStates.includes(status.toLowerCase()); + }, + sendFinalRequest: async () => { + if (!initialOperation.result._response[LROSYM]) { + throw new Error("Expected lroData to determine terminal status"); + } + + if (!currentOperation.result._response[LROSYM]) { + throw new Error("Expected lroData to determine terminal status"); + } + + const initialOperationResult = initialOperation.result._response[LROSYM]; + const currentOperationResult = currentOperation.result._response[LROSYM]; + + if ( + !shouldPerformFinalGet(initialOperationResult, currentOperationResult) + ) { + return currentOperation; + } + + if (initialOperationResult?.requestMethod === "PUT") { + currentOperation = await sendFinalGet( + initialOperation, + sendOperationFn + ); + + return currentOperation; + } + + if (initialOperationResult?.location) { + switch (finalStateVia) { + case "original-uri": + currentOperation = await sendFinalGet( + initialOperation, + sendOperationFn + ); + return currentOperation; + + case "azure-async-operation": + return currentOperation; + case "location": + default: + const location = + initialOperationResult.location || + currentOperationResult?.location; + + if (!location) { + throw new Error("Couldn't determine final GET URL from location"); + } + + return await sendFinalGet( + initialOperation, + sendOperationFn, + location + ); + } + } + + // All other cases return the last operation + return currentOperation; + }, + poll: async () => { + if (!lastKnownPollingUrl) { + throw new Error("Unable to determine polling url"); + } + + const pollingArgs = currentOperation.args; + // Make sure we don't send any body to the get request + const { requestBody, responses, ...restSpec } = currentOperation.spec; + + const pollingSpec: OperationSpec = { + ...restSpec, + responses: getCompositeMappers(responses), + httpMethod: "GET", + path: lastKnownPollingUrl + }; + + const result = await sendOperationFn(pollingArgs, pollingSpec); + + // Update latest polling url + lastKnownPollingUrl = + result._response[LROSYM]?.azureAsyncOperation || + result._response[LROSYM]?.operationLocation || + lastKnownPollingUrl; + + // Update lastOperation result + currentOperation = { + args: pollingArgs, + spec: pollingSpec, + result + }; + + return currentOperation; + } + }; +} + +/** + * Polling calls will always return a status object i.e. {"status": "success"} + * these intermediate responses are not described in the swagger so we need to + * pass custom mappers at runtime. + * This function replaces all the existing mappers to be able to deserialize a status object + * @param responses Original set of responses defined in the operation + */ +function getCompositeMappers(responses: { + [responseCode: string]: OperationResponse; +}): { + [responseCode: string]: OperationResponse; +} { + return Object.keys(responses).reduce((acc, statusCode) => { + return { + ...acc, + [statusCode]: { + ...responses[statusCode], + bodyMapper: { + type: { + name: "Composite", + modelProperties: { + status: { + serializedName: "status", + type: { + name: "String" + } + } + } + } + } + } + }; + }, {} as { [responseCode: string]: OperationResponse }); +} + +function shouldPerformFinalGet( + initialResult?: LROResponseInfo, + currentResult?: LROResponseInfo +) { + const { status } = currentResult || {}; + const { requestMethod: initialRequestMethod, location } = initialResult || {}; + if (status && status.toLowerCase() !== "succeeded") { + return false; + } + + if (initialRequestMethod === "DELETE") { + return false; + } + + if (initialRequestMethod !== "PUT" && !location) { + return false; + } + + return true; +} + +async function sendFinalGet( + initialOperation: LROOperationStep, + sendOperationFn: SendOperationFn, + path?: string +): Promise> { + // Make sure we don't send any body to the get request + const { requestBody, ...restSpec } = initialOperation.spec; + const finalGetSpec: OperationSpec = { + ...restSpec, + httpMethod: "GET" + }; + + // Send final GET request to the Original URL + const spec = { + ...finalGetSpec, + ...(path && { path }) + }; + + let operationArgs: OperationArguments = initialOperation.args; + if (operationArgs.options) { + operationArgs.options.shouldDeserialize = true; + } + + const finalResult = await sendOperationFn(initialOperation.args, spec); + + return { + args: initialOperation.args, + spec, + result: finalResult + }; +} diff --git a/test/integration/generated/lroParametrizedEndpoints/src/lro/bodyPollingStrategy.ts b/test/integration/generated/lroParametrizedEndpoints/src/lro/bodyPollingStrategy.ts new file mode 100644 index 0000000000..c9404330ed --- /dev/null +++ b/test/integration/generated/lroParametrizedEndpoints/src/lro/bodyPollingStrategy.ts @@ -0,0 +1,62 @@ +/* + * Copyright (c) Microsoft Corporation. + * Licensed under the MIT License. + * + * Code generated by Microsoft (R) AutoRest Code Generator. + * Changes may cause incorrect behavior and will be lost if the code is regenerated. + */ + +import { LROStrategy, BaseResult, LROOperationStep, LROSYM } from "./models"; +import { OperationSpec } from "@azure/core-http"; +import { terminalStates } from "./constants"; +import { SendOperationFn } from "./lroPoller"; + +/** + * Creates a polling strategy based on BodyPolling which uses the provisioning state + * from the result to determine the current operation state + */ +export function createBodyPollingStrategy( + initialOperation: LROOperationStep, + sendOperation: SendOperationFn +): LROStrategy { + if (!initialOperation.result._response[LROSYM]) { + throw new Error("Expected lroData to be defined for BodyPolling strategy"); + } + + let currentOperation = initialOperation; + + return { + isTerminal: () => { + const currentResult = currentOperation.result._response[LROSYM]; + if (!currentResult) { + throw new Error("Expected lroData to determine terminal status"); + } + + const { provisioningState = "succeeded" } = currentResult; + // If provisioning state is missing, default to Success + + return terminalStates.includes(provisioningState.toLowerCase()); + }, + sendFinalRequest: () => { + // BodyPolling doesn't require a final get so return the lastOperation + return Promise.resolve(currentOperation); + }, + poll: async () => { + // When doing BodyPolling, we need to poll to the original url with a + // GET http method + const { requestBody, ...restSpec } = initialOperation.spec; + const pollingSpec: OperationSpec = { + // Make sure we don't send any body to the get request + ...restSpec, + httpMethod: "GET" + }; + + // Execute the polling operation + initialOperation.result = await sendOperation( + initialOperation.args, + pollingSpec + ); + return initialOperation; + } + }; +} diff --git a/test/integration/generated/lroParametrizedEndpoints/src/lro/constants.ts b/test/integration/generated/lroParametrizedEndpoints/src/lro/constants.ts new file mode 100644 index 0000000000..fa0ee2d994 --- /dev/null +++ b/test/integration/generated/lroParametrizedEndpoints/src/lro/constants.ts @@ -0,0 +1,9 @@ +/* + * Copyright (c) Microsoft Corporation. + * Licensed under the MIT License. + * + * Code generated by Microsoft (R) AutoRest Code Generator. + * Changes may cause incorrect behavior and will be lost if the code is regenerated. + */ + +export const terminalStates = ["succeeded", "failed", "canceled", "cancelled"]; diff --git a/test/integration/generated/lroParametrizedEndpoints/src/lro/index.ts b/test/integration/generated/lroParametrizedEndpoints/src/lro/index.ts new file mode 100644 index 0000000000..f605ce7ee3 --- /dev/null +++ b/test/integration/generated/lroParametrizedEndpoints/src/lro/index.ts @@ -0,0 +1,23 @@ +/* + * Copyright (c) Microsoft Corporation. + * Licensed under the MIT License. + * + * Code generated by Microsoft (R) AutoRest Code Generator. + * Changes may cause incorrect behavior and will be lost if the code is regenerated. + */ + +export { shouldDeserializeLRO } from "./requestUtils"; +export { createBodyPollingStrategy } from "./bodyPollingStrategy"; +export { terminalStates } from "./constants"; +export { lroPolicy } from "./lroPolicy"; +export { LROPoller, LROPollerOptions, SendOperationFn } from "./lroPoller"; +export { + LROResponseInfo, + BaseResult, + LROOperationStep, + LROOperationState, + LROStrategy, + LROOperation +} from "./models"; +export { makeOperation } from "./operation"; +export * from "./locationStrategy"; diff --git a/test/integration/generated/lroParametrizedEndpoints/src/lro/locationStrategy.ts b/test/integration/generated/lroParametrizedEndpoints/src/lro/locationStrategy.ts new file mode 100644 index 0000000000..6a763e37ec --- /dev/null +++ b/test/integration/generated/lroParametrizedEndpoints/src/lro/locationStrategy.ts @@ -0,0 +1,75 @@ +/* + * Copyright (c) Microsoft Corporation. + * Licensed under the MIT License. + * + * Code generated by Microsoft (R) AutoRest Code Generator. + * Changes may cause incorrect behavior and will be lost if the code is regenerated. + */ + +import { BaseResult, LROOperationStep, LROStrategy, LROSYM } from "./models"; +import { SendOperationFn } from "./lroPoller"; +import { OperationSpec } from "@azure/core-http"; + +export function createLocationStrategy( + initialOperation: LROOperationStep, + sendOperationFn: SendOperationFn +): LROStrategy { + const lroData = initialOperation.result._response[LROSYM]; + if (!lroData) { + throw new Error( + "Expected lroData to be defined for Azure-AsyncOperation strategy" + ); + } + + let currentOperation = initialOperation; + let lastKnownPollingUrl = lroData.location; + + return { + isTerminal: () => { + const currentResult = currentOperation.result._response[LROSYM]; + if (!currentResult) { + throw new Error("Expected lroData to determine terminal status"); + } + + if (currentOperation === initialOperation) { + return false; + } + + if (currentResult.statusCode === 202) { + return false; + } + + return true; + }, + sendFinalRequest: () => Promise.resolve(currentOperation), + poll: async () => { + if (!lastKnownPollingUrl) { + throw new Error("Unable to determine polling url"); + } + + const pollingArgs = currentOperation.args; + // Make sure we don't send any body to the get request + const { requestBody, ...restSpec } = currentOperation.spec; + const pollingSpec: OperationSpec = { + ...restSpec, + httpMethod: "GET", + path: lastKnownPollingUrl + }; + + const result = await sendOperationFn(pollingArgs, pollingSpec); + + // Update latest polling url + lastKnownPollingUrl = + result._response[LROSYM]?.location || lastKnownPollingUrl; + + // Update lastOperation result + currentOperation = { + args: pollingArgs, + spec: pollingSpec, + result + }; + + return currentOperation; + } + }; +} diff --git a/test/integration/generated/lroParametrizedEndpoints/src/lro/lroPolicy.ts b/test/integration/generated/lroParametrizedEndpoints/src/lro/lroPolicy.ts new file mode 100644 index 0000000000..4d18c3b7f0 --- /dev/null +++ b/test/integration/generated/lroParametrizedEndpoints/src/lro/lroPolicy.ts @@ -0,0 +1,44 @@ +/* + * Copyright (c) Microsoft Corporation. + * Licensed under the MIT License. + * + * Code generated by Microsoft (R) AutoRest Code Generator. + * Changes may cause incorrect behavior and will be lost if the code is regenerated. + */ + +import { + RequestPolicy, + RequestPolicyOptions, + BaseRequestPolicy, + HttpOperationResponse, + WebResource +} from "@azure/core-http"; +import { LROOperationResponse, LROSYM } from "./models"; +import { getLROData } from "./requestUtils"; + +export function lroPolicy() { + return { + create: (nextPolicy: RequestPolicy, options: RequestPolicyOptions) => { + return new LROPolicy(nextPolicy, options); + } + }; +} + +class LROPolicy extends BaseRequestPolicy { + constructor(nextPolicy: RequestPolicy, options: RequestPolicyOptions) { + super(nextPolicy, options); + } + + public async sendRequest( + webResource: WebResource + ): Promise { + let result: LROOperationResponse = await this._nextPolicy.sendRequest( + webResource + ); + const _lroData = getLROData(result); + + result[LROSYM] = _lroData; + + return result; + } +} diff --git a/test/integration/generated/lroParametrizedEndpoints/src/lro/lroPoller.ts b/test/integration/generated/lroParametrizedEndpoints/src/lro/lroPoller.ts new file mode 100644 index 0000000000..8c0406cf24 --- /dev/null +++ b/test/integration/generated/lroParametrizedEndpoints/src/lro/lroPoller.ts @@ -0,0 +1,155 @@ +/* + * Copyright (c) Microsoft Corporation. + * Licensed under the MIT License. + * + * Code generated by Microsoft (R) AutoRest Code Generator. + * Changes may cause incorrect behavior and will be lost if the code is regenerated. + */ + +import { Poller } from "@azure/core-lro"; +import { + OperationSpec, + OperationArguments, + delay, + RestError +} from "@azure/core-http"; +import { + BaseResult, + LROOperationState, + LROOperationStep, + FinalStateVia, + LROSYM +} from "./models"; +import { makeOperation } from "./operation"; +import { createBodyPollingStrategy } from "./bodyPollingStrategy"; +import { createAzureAsyncOperationStrategy } from "./azureAsyncOperationStrategy"; +import { createLocationStrategy } from "./locationStrategy"; +import { createPassthroughStrategy } from "./passthroughStrategy"; + +export type SendOperationFn = ( + args: OperationArguments, + spec: OperationSpec +) => Promise; + +export interface LROPollerOptions { + /** + * Defines how much time the poller is going to wait before making a new request to the service. + */ + intervalInMs?: number; + /** + * Arguments used to send the initial operation + */ + initialOperationArguments: OperationArguments; + /** + * Operation spec provided for the initial operation + */ + initialOperationSpec: OperationSpec; + /** + * Result from the initial operation + */ + initialOperationResult: TResult; + /** + * Function to execute an operation based on an operation spec and arguments + */ + sendOperation: SendOperationFn; + /** + * Optional information on where to poll. When not defined it defaults to "Location" + */ + finalStateVia?: FinalStateVia; +} + +export class LROPoller extends Poller< + LROOperationState, + TResult +> { + private intervalInMs: number; + + constructor({ + initialOperationArguments, + initialOperationResult, + initialOperationSpec, + sendOperation, + finalStateVia, + intervalInMs = 2000 + }: LROPollerOptions) { + const initialOperation = { + args: initialOperationArguments, + spec: initialOperationSpec, + result: initialOperationResult + }; + + const pollingStrategy = getPollingStrategy( + initialOperation, + sendOperation, + finalStateVia + ); + + const state: LROOperationState = { + // Initial operation will become the last operation + initialOperation, + lastOperation: initialOperation, + pollingStrategy, + finalStateVia + }; + + const operation = makeOperation(state); + super(operation); + + this.intervalInMs = intervalInMs; + } + + /** + * The method used by the poller to wait before attempting to update its operation. + */ + delay(): Promise { + return delay(this.intervalInMs); + } +} + +/** + * This function determines which strategy to use based on the response from + * the last operation executed, this last operation can be an initial operation + * or a polling operation. The 3 possible strategies are described below: + * + * A) Azure-AsyncOperation or Operation-Location + * B) Location + * C) BodyPolling (provisioningState) + * - This strategy is used when: + * - Response doesn't contain any of the following headers Location, Azure-AsyncOperation or Operation-Location + * - Last operation method is PUT + */ +function getPollingStrategy( + initialOperation: LROOperationStep, + sendOperationFn: SendOperationFn, + finalStateVia?: FinalStateVia +) { + const lroData = initialOperation.result._response[LROSYM]; + + if (!lroData) { + const error = new RestError( + "Service response doesn't include the required LRO data to continue polling" + ); + error.statusCode = initialOperation.result._response.status; + error.response = initialOperation.result._response; + throw error; + } + + if (lroData.azureAsyncOperation || lroData.operationLocation) { + return createAzureAsyncOperationStrategy( + initialOperation, + sendOperationFn, + finalStateVia + ); + } + + if (lroData.location) { + return createLocationStrategy(initialOperation, sendOperationFn); + } + + if (["PUT", "PATCH"].includes(lroData.requestMethod || "")) { + return createBodyPollingStrategy(initialOperation, sendOperationFn); + } + + // Default strategy is just a passthrough returning the initial operation + return createPassthroughStrategy(initialOperation); +} diff --git a/test/integration/generated/lroParametrizedEndpoints/src/lro/models.ts b/test/integration/generated/lroParametrizedEndpoints/src/lro/models.ts new file mode 100644 index 0000000000..c4b96664f6 --- /dev/null +++ b/test/integration/generated/lroParametrizedEndpoints/src/lro/models.ts @@ -0,0 +1,75 @@ +/* + * Copyright (c) Microsoft Corporation. + * Licensed under the MIT License. + * + * Code generated by Microsoft (R) AutoRest Code Generator. + * Changes may cause incorrect behavior and will be lost if the code is regenerated. + */ + +import { + OperationArguments, + OperationSpec, + RestResponse, + HttpMethods, + HttpOperationResponse +} from "@azure/core-http"; +import { PollOperationState, PollOperation } from "@azure/core-lro"; +export const LROSYM = Symbol("LROData"); + +export type FinalStateVia = + | "azure-async-operation" + | "location" + | "original-uri"; + +export interface LROResponseInfo { + requestMethod: HttpMethods; + statusCode: number; + isInitialRequest?: boolean; + azureAsyncOperation?: string; + operationLocation?: string; + location?: string; + provisioningState?: string; + status?: string; +} + +/** + * Extended operation response for LROs + */ +export type LROOperationResponse = HttpOperationResponse & { + /** + * Symbol that contains LRO details + */ + [LROSYM]?: LROResponseInfo; +}; + +export interface BaseResult extends RestResponse { + /** + * The underlying HTTP response containing both raw and deserialized response data. + */ + _response: LROOperationResponse; +} + +export interface LROOperationStep { + args: OperationArguments; + spec: OperationSpec; + result: TResult; +} + +export interface LROOperationState + extends PollOperationState { + lastOperation: LROOperationStep; + initialOperation: LROOperationStep; + pollingStrategy: LROStrategy; + finalStateVia?: FinalStateVia; +} + +export interface LROStrategy { + isTerminal: () => boolean; + sendFinalRequest: () => Promise>; + poll: () => Promise>; +} + +export type LROOperation = PollOperation< + LROOperationState, + TResult +>; diff --git a/test/integration/generated/lroParametrizedEndpoints/src/lro/operation.ts b/test/integration/generated/lroParametrizedEndpoints/src/lro/operation.ts new file mode 100644 index 0000000000..0860f07df0 --- /dev/null +++ b/test/integration/generated/lroParametrizedEndpoints/src/lro/operation.ts @@ -0,0 +1,82 @@ +/* + * Copyright (c) Microsoft Corporation. + * Licensed under the MIT License. + * + * Code generated by Microsoft (R) AutoRest Code Generator. + * Changes may cause incorrect behavior and will be lost if the code is regenerated. + */ + +import { BaseResult, LROOperationState, LROOperation, LROSYM } from "./models"; + +/** + * Creates a copy of the operation from a given State + */ +export function makeOperation( + state: LROOperationState +): LROOperation { + return { + state: { ...state }, + update, + cancel, + toString: function(this: LROOperation) { + return JSON.stringify(this.state); + } + }; +} + +/** + * General update function for LROPoller, the general process is as follows + * 1. Check initial operation result to determine the strategy to use + * - Strategies: Location, Azure-AsyncOperation, Original Uri + * 2. Check if the operation result has a terminal state + * - Terminal state will be determined by each strategy + * 2.1 If it is terminal state Check if a final GET request is required, if so + * send final GET request and return result from operation. If no final GET + * is required, just return the result from operation. + * - Determining what to call for final request is responsibility of each strategy + * 2.2 If it is not terminal state, call the polling operation call it and go to step 1 + * - Determining what to call for polling is responsibility of each strategy + * - Strategies will always use the latest URI for polling if provided otherwise + * the last known one + */ +async function update( + this: LROOperation +): Promise> { + const state = { ...this.state }; + + const { sendFinalRequest, poll, isTerminal } = state.pollingStrategy; + const currentResponse = state.lastOperation; + const currentLroData = currentResponse.result._response[LROSYM]; + + if (!currentLroData) { + throw new Error( + "Expected lroData to be defined for updating LRO operation" + ); + } + + if (state.result) { + state.isCompleted = true; + return makeOperation(state); + } + + // Check if last result is terminal + if (isTerminal()) { + state.lastOperation = await sendFinalRequest(); + state.result = state.lastOperation.result; + } else { + state.lastOperation = await poll(); + } + + // Return operation + return makeOperation(state); +} + +/** + * Swagger doesn't support defining a cancel operation, we'll just mark + * the operation state as cancelled + */ +async function cancel( + this: LROOperation +): Promise> { + return makeOperation({ ...this.state, isCancelled: true }); +} diff --git a/test/integration/generated/lroParametrizedEndpoints/src/lro/passthroughStrategy.ts b/test/integration/generated/lroParametrizedEndpoints/src/lro/passthroughStrategy.ts new file mode 100644 index 0000000000..23342c2e4e --- /dev/null +++ b/test/integration/generated/lroParametrizedEndpoints/src/lro/passthroughStrategy.ts @@ -0,0 +1,30 @@ +/* + * Copyright (c) Microsoft Corporation. + * Licensed under the MIT License. + * + * Code generated by Microsoft (R) AutoRest Code Generator. + * Changes may cause incorrect behavior and will be lost if the code is regenerated. + */ + +import { LROStrategy, BaseResult, LROOperationStep } from "./models"; + +/** + * Creates a polling strategy based on BodyPolling which uses the provisioning state + * from the result to determine the current operation state + */ +export function createPassthroughStrategy( + initialOperation: LROOperationStep +): LROStrategy { + return { + isTerminal: () => { + return true; + }, + sendFinalRequest: () => { + // BodyPolling doesn't require a final get so return the lastOperation + return Promise.resolve(initialOperation); + }, + poll: async () => { + throw new Error("Passthrough strategy should never poll"); + } + }; +} diff --git a/test/integration/generated/lroParametrizedEndpoints/src/lro/requestUtils.ts b/test/integration/generated/lroParametrizedEndpoints/src/lro/requestUtils.ts new file mode 100644 index 0000000000..e9af4cde5e --- /dev/null +++ b/test/integration/generated/lroParametrizedEndpoints/src/lro/requestUtils.ts @@ -0,0 +1,117 @@ +/* + * Copyright (c) Microsoft Corporation. + * Licensed under the MIT License. + * + * Code generated by Microsoft (R) AutoRest Code Generator. + * Changes may cause incorrect behavior and will be lost if the code is regenerated. + */ + +import { HttpOperationResponse } from "@azure/core-http"; +import { terminalStates } from "./constants"; +import { LROResponseInfo } from "./models"; + +/** + * We need to selectively deserialize our responses, only deserializing if we + * are in a final LRO response, not deserializing any polling non-terminal responses + */ +export function shouldDeserializeLRO(finalStateVia?: string) { + let initialOperationInfo: LROResponseInfo | undefined; + let isInitialRequest = true; + + return (response: HttpOperationResponse) => { + if (response.status < 200 || response.status >= 300) { + return true; + } + + if (!initialOperationInfo) { + initialOperationInfo = getLROData(response); + } else { + isInitialRequest = false; + } + + if ( + initialOperationInfo.azureAsyncOperation || + initialOperationInfo.operationLocation + ) { + return ( + !isInitialRequest && + isAsyncOperationFinalResponse( + response, + initialOperationInfo, + finalStateVia + ) + ); + } + + if (initialOperationInfo.location) { + return isLocationFinalResponse(response); + } + + if (initialOperationInfo.requestMethod === "PUT") { + return isBodyPollingFinalResponse(response); + } + + return true; + }; +} + +function isAsyncOperationFinalResponse( + response: HttpOperationResponse, + initialOperationInfo: LROResponseInfo, + finalStateVia?: string +): boolean { + const status: string = response.parsedBody?.status || "Succeeded"; + if (!terminalStates.includes(status.toLowerCase())) { + return false; + } + + if (initialOperationInfo.requestMethod === "DELETE") { + return true; + } + + if ( + initialOperationInfo.requestMethod === "PUT" && + finalStateVia && + finalStateVia.toLowerCase() === "azure-asyncoperation" + ) { + return true; + } + + if ( + initialOperationInfo.requestMethod !== "PUT" && + !initialOperationInfo.location + ) { + return true; + } + + return false; +} + +function isLocationFinalResponse(response: HttpOperationResponse): boolean { + return response.status !== 202; +} + +function isBodyPollingFinalResponse(response: HttpOperationResponse): boolean { + const provisioningState: string = + response.parsedBody?.properties?.provisioningState || "Succeeded"; + + if (terminalStates.includes(provisioningState.toLowerCase())) { + return true; + } + + return false; +} + +export function getLROData(result: HttpOperationResponse): LROResponseInfo { + const statusCode = result.status; + const { status, properties } = result.parsedBody || {}; + return { + statusCode, + azureAsyncOperation: result.headers.get("azure-asyncoperation"), + operationLocation: result.headers.get("operation-location"), + location: result.headers.get("location"), + requestMethod: result.request.method, + status, + provisioningState: properties?.provisioningState + }; +} diff --git a/test/integration/generated/lroParametrizedEndpoints/src/lroParametrizedEndpointsClient.ts b/test/integration/generated/lroParametrizedEndpoints/src/lroParametrizedEndpointsClient.ts new file mode 100644 index 0000000000..6e66b86671 --- /dev/null +++ b/test/integration/generated/lroParametrizedEndpoints/src/lroParametrizedEndpointsClient.ts @@ -0,0 +1,110 @@ +/* + * Copyright (c) Microsoft Corporation. + * Licensed under the MIT License. + * + * Code generated by Microsoft (R) AutoRest Code Generator. + * Changes may cause incorrect behavior and will be lost if the code is regenerated. + */ + +import * as coreHttp from "@azure/core-http"; +import { LROPoller, shouldDeserializeLRO } from "./lro"; +import * as Parameters from "./models/parameters"; +import * as Mappers from "./models/mappers"; +import { LroParametrizedEndpointsClientContext } from "./lroParametrizedEndpointsClientContext"; +import { + LroParametrizedEndpointsClientOptionalParams, + LroParametrizedEndpointsClientPollWithParameterizedEndpointsResponse +} from "./models"; + +export class LroParametrizedEndpointsClient extends LroParametrizedEndpointsClientContext { + /** + * Initializes a new instance of the LroParametrizedEndpointsClient class. + * @param options The parameter options + */ + constructor(options?: LroParametrizedEndpointsClientOptionalParams) { + super(options); + } + + private getOperationOptions( + options: TOptions | undefined, + finalStateVia?: string + ): coreHttp.RequestOptionsBase { + const operationOptions: coreHttp.OperationOptions = options || {}; + operationOptions.requestOptions = { + ...operationOptions.requestOptions, + shouldDeserialize: shouldDeserializeLRO(finalStateVia) + }; + return coreHttp.operationOptionsToRequestOptionsBase(operationOptions); + } + + /** + * Poll with method and client level parameters in endpoint + * @param accountName Account Name. Pass in 'local' to pass test. + * @param options The options parameters. + */ + async pollWithParameterizedEndpoints( + accountName: string, + options?: coreHttp.OperationOptions + ): Promise< + LROPoller< + LroParametrizedEndpointsClientPollWithParameterizedEndpointsResponse + > + > { + const operationOptions: coreHttp.RequestOptionsBase = this.getOperationOptions( + options, + "location" + ); + + const args: coreHttp.OperationArguments = { + accountName, + options: operationOptions + }; + const sendOperation = ( + args: coreHttp.OperationArguments, + spec: coreHttp.OperationSpec + ) => + this.sendOperationRequest(args, spec) as Promise< + LroParametrizedEndpointsClientPollWithParameterizedEndpointsResponse + >; + const initialOperationResult = await sendOperation( + args, + pollWithParameterizedEndpointsOperationSpec + ); + + return new LROPoller({ + initialOperationArguments: args, + initialOperationSpec: pollWithParameterizedEndpointsOperationSpec, + initialOperationResult, + sendOperation, + finalStateVia: "location" + }); + } +} +// Operation Specifications + +const serializer = new coreHttp.Serializer(Mappers, /* isXml */ false); + +const pollWithParameterizedEndpointsOperationSpec: coreHttp.OperationSpec = { + path: "/lroParameterizedEndpoints", + httpMethod: "POST", + responses: { + 200: { + bodyMapper: { type: { name: "String" } } + }, + 201: { + bodyMapper: { type: { name: "String" } } + }, + 202: { + bodyMapper: { type: { name: "String" } } + }, + 204: { + bodyMapper: { type: { name: "String" } } + }, + default: { + bodyMapper: Mappers.ErrorModel + } + }, + urlParameters: [Parameters.accountName, Parameters.host], + headerParameters: [Parameters.accept], + serializer +}; diff --git a/test/integration/generated/lroParametrizedEndpoints/src/lroParametrizedEndpointsClientContext.ts b/test/integration/generated/lroParametrizedEndpoints/src/lroParametrizedEndpointsClientContext.ts new file mode 100644 index 0000000000..ff43e8ea44 --- /dev/null +++ b/test/integration/generated/lroParametrizedEndpoints/src/lroParametrizedEndpointsClientContext.ts @@ -0,0 +1,51 @@ +/* + * Copyright (c) Microsoft Corporation. + * Licensed under the MIT License. + * + * Code generated by Microsoft (R) AutoRest Code Generator. + * Changes may cause incorrect behavior and will be lost if the code is regenerated. + */ + +import * as coreHttp from "@azure/core-http"; +import { LroParametrizedEndpointsClientOptionalParams } from "./models"; +import { lroPolicy } from "./lro"; + +const packageName = "lro-parameterized-endpoints"; +const packageVersion = "1.0.0-preview1"; + +export class LroParametrizedEndpointsClientContext extends coreHttp.ServiceClient { + host: string; + + /** + * Initializes a new instance of the LroParametrizedEndpointsClientContext class. + * @param options The parameter options + */ + constructor(options?: LroParametrizedEndpointsClientOptionalParams) { + // Initializing default values for options + if (!options) { + options = {}; + } + + if (!options.userAgent) { + const defaultUserAgent = coreHttp.getDefaultUserAgentValue(); + options.userAgent = `${packageName}/${packageVersion} ${defaultUserAgent}`; + } + + const defaultPipelines = coreHttp.createPipelineFromOptions(options) + .requestPolicyFactories as coreHttp.RequestPolicyFactory[]; + + options = { + ...options, + requestPolicyFactories: [lroPolicy(), ...defaultPipelines] + }; + + super(undefined, options); + + this.requestContentType = "application/json; charset=utf-8"; + + this.baseUri = options.endpoint || "http://{accountName}{host}"; + + // Assigning values to Constant parameters + this.host = options.host || "host"; + } +} diff --git a/test/integration/generated/lroParametrizedEndpoints/src/models/index.ts b/test/integration/generated/lroParametrizedEndpoints/src/models/index.ts new file mode 100644 index 0000000000..3d71b764a1 --- /dev/null +++ b/test/integration/generated/lroParametrizedEndpoints/src/models/index.ts @@ -0,0 +1,69 @@ +/* + * Copyright (c) Microsoft Corporation. + * Licensed under the MIT License. + * + * Code generated by Microsoft (R) AutoRest Code Generator. + * Changes may cause incorrect behavior and will be lost if the code is regenerated. + */ + +import * as coreHttp from "@azure/core-http"; +import { LROSYM, LROResponseInfo } from "../lro/models"; + +export interface ErrorModel { + status?: number; + message?: string; +} + +/** + * Defines headers for LroParametrizedEndpointsClient_pollWithParameterizedEndpoints operation. + */ +export interface LroParametrizedEndpointsClientPollWithParameterizedEndpointsHeaders { + /** + * Url to retrieve the final update resource. Is a relative link + */ + location?: string; +} + +/** + * Contains response data for the pollWithParameterizedEndpoints operation. + */ +export type LroParametrizedEndpointsClientPollWithParameterizedEndpointsResponse = { + /** + * The parsed response body. + */ + body: string; + + /** + * The underlying HTTP response. + */ + _response: coreHttp.HttpResponse & { + /** + * The response body as text (string format) + */ + bodyAsText: string; + + /** + * The response body as parsed JSON or XML + */ + parsedBody: string; + /** + * The parsed HTTP response headers. + */ + [LROSYM]: LROResponseInfo; + }; +}; + +/** + * Optional parameters. + */ +export interface LroParametrizedEndpointsClientOptionalParams + extends coreHttp.ServiceClientOptions { + /** + * A string value that is used as a global part of the parameterized host. Pass in 'host:3000' to pass test. + */ + host?: string; + /** + * Overrides client endpoint. + */ + endpoint?: string; +} diff --git a/test/integration/generated/lroParametrizedEndpoints/src/models/mappers.ts b/test/integration/generated/lroParametrizedEndpoints/src/models/mappers.ts new file mode 100644 index 0000000000..150db97854 --- /dev/null +++ b/test/integration/generated/lroParametrizedEndpoints/src/models/mappers.ts @@ -0,0 +1,46 @@ +/* + * Copyright (c) Microsoft Corporation. + * Licensed under the MIT License. + * + * Code generated by Microsoft (R) AutoRest Code Generator. + * Changes may cause incorrect behavior and will be lost if the code is regenerated. + */ + +import * as coreHttp from "@azure/core-http"; + +export const ErrorModel: coreHttp.CompositeMapper = { + type: { + name: "Composite", + className: "ErrorModel", + modelProperties: { + status: { + serializedName: "status", + type: { + name: "Number" + } + }, + message: { + serializedName: "message", + type: { + name: "String" + } + } + } + } +}; + +export const LroParametrizedEndpointsClientPollWithParameterizedEndpointsHeaders: coreHttp.CompositeMapper = { + type: { + name: "Composite", + className: + "LroParametrizedEndpointsClientPollWithParameterizedEndpointsHeaders", + modelProperties: { + location: { + serializedName: "location", + type: { + name: "String" + } + } + } + } +}; diff --git a/test/integration/generated/lroParametrizedEndpoints/src/models/parameters.ts b/test/integration/generated/lroParametrizedEndpoints/src/models/parameters.ts new file mode 100644 index 0000000000..60a9b9c872 --- /dev/null +++ b/test/integration/generated/lroParametrizedEndpoints/src/models/parameters.ts @@ -0,0 +1,45 @@ +/* + * Copyright (c) Microsoft Corporation. + * Licensed under the MIT License. + * + * Code generated by Microsoft (R) AutoRest Code Generator. + * Changes may cause incorrect behavior and will be lost if the code is regenerated. + */ + +import { OperationParameter, OperationURLParameter } from "@azure/core-http"; + +export const accept: OperationParameter = { + parameterPath: "accept", + mapper: { + defaultValue: "application/json", + isConstant: true, + serializedName: "Accept", + type: { + name: "String" + } + } +}; + +export const accountName: OperationURLParameter = { + parameterPath: "accountName", + mapper: { + serializedName: "accountName", + required: true, + type: { + name: "String" + } + }, + skipEncoding: true +}; + +export const host: OperationURLParameter = { + parameterPath: "host", + mapper: { + serializedName: "host", + required: true, + type: { + name: "String" + } + }, + skipEncoding: true +}; diff --git a/test/integration/generated/lroParametrizedEndpoints/tsconfig.json b/test/integration/generated/lroParametrizedEndpoints/tsconfig.json new file mode 100644 index 0000000000..422b584abd --- /dev/null +++ b/test/integration/generated/lroParametrizedEndpoints/tsconfig.json @@ -0,0 +1,19 @@ +{ + "compilerOptions": { + "module": "es6", + "moduleResolution": "node", + "strict": true, + "target": "es5", + "sourceMap": true, + "declarationMap": true, + "esModuleInterop": true, + "allowSyntheticDefaultImports": true, + "forceConsistentCasingInFileNames": true, + "lib": ["es6", "dom"], + "declaration": true, + "outDir": "./esm", + "importHelpers": true + }, + "include": ["./src/**/*.ts"], + "exclude": ["node_modules"] +} diff --git a/test/integration/lroParametrizedEndpoints.spec.ts b/test/integration/lroParametrizedEndpoints.spec.ts new file mode 100644 index 0000000000..cfb7dbb7ca --- /dev/null +++ b/test/integration/lroParametrizedEndpoints.spec.ts @@ -0,0 +1,17 @@ +import { assert } from "chai"; +import { LroParametrizedEndpointsClient } from "./generated/lroParametrizedEndpoints/src"; + +describe("lroParametrizedEndpoints", () => { + let client: LroParametrizedEndpointsClient; + + beforeEach(() => { + client = new LroParametrizedEndpointsClient({ host: "host:3000" }); + }); + + it("should pollWithParameterizedEndpoints", async () => { + const poller = await client.pollWithParameterizedEndpoints("local"); + poller.delay = () => Promise.resolve(); + const result = await poller.pollUntilDone(); + assert.equal(result.body, "success"); + }); +}); diff --git a/test/integration/urlMulti.spec.ts b/test/integration/urlMulti.spec.ts index 37a6af5877..7ed2440971 100644 --- a/test/integration/urlMulti.spec.ts +++ b/test/integration/urlMulti.spec.ts @@ -8,8 +8,7 @@ describe("URLMultiCollectionFormat", () => { client = new UrlMultiClient(); }); - // TODO: Enable when https://github.com/Azure/azure-sdk-for-js/pull/12090 is merged - it.skip("should handle arrayStringMultiEmpty", async () => { + it("should handle arrayStringMultiEmpty", async () => { const result = await client.queries.arrayStringMultiEmpty({ arrayQuery: [] }); diff --git a/test/utils/test-swagger-gen.ts b/test/utils/test-swagger-gen.ts index b95892fbe4..f4273d76d5 100644 --- a/test/utils/test-swagger-gen.ts +++ b/test/utils/test-swagger-gen.ts @@ -169,6 +169,12 @@ const testSwaggers: { [name: string]: SwaggerConfig } = { packageName: "lro", licenseHeader: true }, + lroParametrizedEndpoints: { + swagger: "lro-parameterized-endpoints.json", + clientName: "LroParametrizedEndpointsClient", + packageName: "lro-parameterized-endpoints", + licenseHeader: true + }, mediaTypes: { swagger: "media_types.json", clientName: "MediaTypesClient",