diff --git a/.chronus/changes/fix_client_version_params-2024-4-3-14-57-7.md b/.chronus/changes/fix_client_version_params-2024-4-3-14-57-7.md new file mode 100644 index 0000000000..5438ce4f1a --- /dev/null +++ b/.chronus/changes/fix_client_version_params-2024-4-3-14-57-7.md @@ -0,0 +1,7 @@ +--- +changeKind: fix +packages: + - "@azure-tools/typespec-client-generator-core" +--- + +tie api version information to clients so we can have diff api version information per client \ No newline at end of file diff --git a/packages/typespec-client-generator-core/src/decorators.ts b/packages/typespec-client-generator-core/src/decorators.ts index 89cdf9e2b7..8192692d09 100644 --- a/packages/typespec-client-generator-core/src/decorators.ts +++ b/packages/typespec-client-generator-core/src/decorators.ts @@ -596,6 +596,9 @@ export function createSdkContext< diagnostics: diagnostics.diagnostics, apiVersion: context.options["api-version"], originalProgram: context.program, + __namespaceToApiVersionParameter: new Map(), + __namespaceToApiVersions: new Map(), + __namespaceToApiVersionClientDefaultValue: new Map(), }; sdkContext.experimental_sdkPackage = getSdkPackage(sdkContext); if (sdkContext.diagnostics) { diff --git a/packages/typespec-client-generator-core/src/http.ts b/packages/typespec-client-generator-core/src/http.ts index fef2e7be41..64b5894a05 100644 --- a/packages/typespec-client-generator-core/src/http.ts +++ b/packages/typespec-client-generator-core/src/http.ts @@ -1,6 +1,7 @@ import { Diagnostic, ModelProperty, + Operation, Type, createDiagnosticCollector, ignoreDiagnostics, @@ -41,6 +42,7 @@ import { TCGCContext, getAvailableApiVersions, getDocHelper, + getLocationOfOperation, isAcceptHeader, isNullable, isSubscriptionId, @@ -106,7 +108,9 @@ function getSdkHttpParameters( bodyParam: undefined, }; retval.parameters = httpOperation.parameters.parameters - .map((x) => diagnostics.pipe(getSdkHttpParameter(context, x.param, x.type))) + .map((x) => + diagnostics.pipe(getSdkHttpParameter(context, x.param, httpOperation.operation, x.type)) + ) .filter( (x): x is SdkHeaderParameter | SdkQueryParameter | SdkPathParameter => x.kind === "header" || x.kind === "query" || x.kind === "path" @@ -122,7 +126,7 @@ function getSdkHttpParameters( // if there's a param on the body, we can just rely on getSdkHttpParameter if (tspBody.parameter) { const getParamResponse = diagnostics.pipe( - getSdkHttpParameter(context, tspBody.parameter, "body") + getSdkHttpParameter(context, tspBody.parameter, httpOperation.operation, "body") ); if (getParamResponse.kind !== "body") { diagnostics.add( @@ -155,7 +159,11 @@ function getSdkHttpParameters( contentTypes: [], defaultContentType: "application/json", // actual content type info is added later isApiVersionParam: false, - apiVersions: getAvailableApiVersions(context, tspBody.type), + apiVersions: getAvailableApiVersions( + context, + tspBody.type, + httpOperation.operation.namespace + ), type, optional: false, nullable: isNullable(tspBody.type), @@ -166,7 +174,7 @@ function getSdkHttpParameters( retval.bodyParam.correspondingMethodParams = diagnostics.pipe( getCorrespondingMethodParams( context, - httpOperation.operation.name, + httpOperation.operation, methodParameters, retval.bodyParam ) @@ -214,7 +222,7 @@ function getSdkHttpParameters( } for (const param of retval.parameters) { param.correspondingMethodParams = diagnostics.pipe( - getCorrespondingMethodParams(context, httpOperation.operation.name, methodParameters, param) + getCorrespondingMethodParams(context, httpOperation.operation, methodParameters, param) ); } return diagnostics.wrap(retval); @@ -287,10 +295,11 @@ function addContentTypeInfoToBodyParam( export function getSdkHttpParameter( context: TCGCContext, type: ModelProperty, + operation?: Operation, location?: "path" | "query" | "header" | "body" ): [SdkHttpParameter, readonly Diagnostic[]] { const diagnostics = createDiagnosticCollector(); - const base = diagnostics.pipe(getSdkModelPropertyTypeBase(context, type)); + const base = diagnostics.pipe(getSdkModelPropertyTypeBase(context, type, operation)); const program = context.program; const correspondingMethodParams: SdkParameter[] = []; // we set it later in the operation if (isPathParam(context.program, type) || location === "path") { @@ -419,7 +428,11 @@ function getSdkHttpResponseAndExceptions( defaultContentType: contentTypes.includes("application/json") ? "application/json" : contentTypes[0], - apiVersions: getAvailableApiVersions(context, httpOperation.operation), + apiVersions: getAvailableApiVersions( + context, + httpOperation.operation, + httpOperation.operation.namespace + ), nullable: body ? isNullable(body) : true, }; if (response.statusCodes === "*" || (body && isErrorModel(context.program, body))) { @@ -433,13 +446,16 @@ function getSdkHttpResponseAndExceptions( export function getCorrespondingMethodParams( context: TCGCContext, - methodName: string, + operation: Operation, methodParameters: SdkParameter[], serviceParam: SdkHttpParameter ): [SdkModelPropertyType[], readonly Diagnostic[]] { const diagnostics = createDiagnosticCollector(); + + const operationLocation = getLocationOfOperation(operation); if (serviceParam.isApiVersionParam) { - if (!context.__api_version_parameter) { + const existingApiVersion = context.__namespaceToApiVersionParameter.get(operationLocation); + if (!existingApiVersion) { const apiVersionParam = methodParameters.find((x) => x.name.includes("apiVersion")); if (!apiVersionParam) { diagnostics.add( @@ -448,22 +464,24 @@ export function getCorrespondingMethodParams( target: serviceParam.__raw!, format: { paramName: "apiVersion", - methodName: methodName, + methodName: operation.name, }, }) ); return diagnostics.wrap([]); } - context.__api_version_parameter = { + const apiVersionParamUpdated: SdkParameter = { ...apiVersionParam, name: "apiVersion", nameInClient: "apiVersion", isGeneratedName: apiVersionParam.name !== "apiVersion", optional: false, - clientDefaultValue: context.__api_version_client_default_value, + clientDefaultValue: + context.__namespaceToApiVersionClientDefaultValue.get(operationLocation), }; + context.__namespaceToApiVersionParameter.set(operationLocation, apiVersionParamUpdated); } - return diagnostics.wrap([context.__api_version_parameter]); + return diagnostics.wrap([context.__namespaceToApiVersionParameter.get(operationLocation)!]); } if (isSubscriptionId(context, serviceParam)) { if (!context.__subscriptionIdParameter) { @@ -475,7 +493,7 @@ export function getCorrespondingMethodParams( target: serviceParam.__raw!, format: { paramName: "subscriptionId", - methodName: methodName, + methodName: operation.name, }, }) ); @@ -526,7 +544,7 @@ export function getCorrespondingMethodParams( target: serviceParam.__raw!, format: { paramName: serviceParam.name, - methodName: methodName, + methodName: operation.name, }, }) ); @@ -547,7 +565,7 @@ export function getCorrespondingMethodParams( target: serviceParam.__raw!, format: { paramName: serviceParam.name, - methodName: methodName, + methodName: operation.name, }, }) ); diff --git a/packages/typespec-client-generator-core/src/internal-utils.ts b/packages/typespec-client-generator-core/src/internal-utils.ts index e82aa05b31..e407576aaf 100644 --- a/packages/typespec-client-generator-core/src/internal-utils.ts +++ b/packages/typespec-client-generator-core/src/internal-utils.ts @@ -1,6 +1,7 @@ import { getUnionAsEnum } from "@azure-tools/typespec-azure-core"; import { Diagnostic, + Interface, Model, Namespace, Operation, @@ -97,7 +98,8 @@ export function getClientNamespaceStringHelper( */ export function updateWithApiVersionInformation( context: TCGCContext, - type: { name: string } + type: { name: string }, + namespace?: Namespace | Interface ): { isApiVersionParam: boolean; clientDefaultValue?: unknown; @@ -106,24 +108,19 @@ export function updateWithApiVersionInformation( const isApiVersionParam = isApiVersion(context, type); return { isApiVersionParam, - clientDefaultValue: isApiVersionParam ? context.__api_version_client_default_value : undefined, + clientDefaultValue: + isApiVersionParam && namespace + ? context.__namespaceToApiVersionClientDefaultValue.get(namespace) + : undefined, onClient: onClient(context, type), }; } -/** - * - * @param context - * @param type - * @returns All api versions the type is available on - */ -export function getAvailableApiVersions(context: TCGCContext, type: Type): string[] { - const apiVersions = - context.__api_versions || - getVersions(context.program, type)[1] - ?.getVersions() - .map((x) => x.value); - if (!apiVersions) return []; +export function filterApiVersionsWithDecorators( + context: TCGCContext, + type: Type, + apiVersions: string[] +): string[] { const addedOnVersions = getAddedOnVersions(context.program, type)?.map((x) => x.value) ?? []; const removedOnVersions = getRemovedOnVersions(context.program, type)?.map((x) => x.value) ?? []; let added: boolean = addedOnVersions.length ? false : true; @@ -155,6 +152,32 @@ export function getAvailableApiVersions(context: TCGCContext, type: Type): strin return retval; } +/** + * + * @param context + * @param type + * @param client If it's associated with a client, meaning it's a param etc, we can see if it's available on that client + * @returns All api versions the type is available on + */ +export function getAvailableApiVersions( + context: TCGCContext, + type: Type, + namespace?: Namespace | Interface +): string[] { + let cachedApiVersions: string[] = []; + if (namespace) { + cachedApiVersions = context.__namespaceToApiVersions.get(namespace) || []; + } + + const apiVersions = + cachedApiVersions || + getVersions(context.program, type)[1] + ?.getVersions() + .map((x) => x.value); + if (!apiVersions) return []; + return filterApiVersionsWithDecorators(context, type, apiVersions); +} + interface DocWrapper { description?: string; details?: string; @@ -267,9 +290,9 @@ export interface TCGCContext { generatedNames?: Map; httpOperationCache?: Map; unionsMap?: Map; - __api_version_parameter?: SdkParameter; - __api_version_client_default_value?: string; - __api_versions?: string[]; + __namespaceToApiVersionParameter: Map; + __namespaceToApiVersions: Map; + __namespaceToApiVersionClientDefaultValue: Map; knownScalars?: Record; diagnostics: readonly Diagnostic[]; __subscriptionIdParameter?: SdkParameter; @@ -285,6 +308,9 @@ export function createTCGCContext(program: Program): TCGCContext { emitterName: "__TCGC_INTERNAL__", diagnostics: [], originalProgram: program, + __namespaceToApiVersionParameter: new Map(), + __namespaceToApiVersions: new Map(), + __namespaceToApiVersionClientDefaultValue: new Map(), }; } @@ -372,3 +398,8 @@ export function isSubscriptionId(context: TCGCContext, parameter: { name: string export function onClient(context: TCGCContext, parameter: { name: string }): boolean { return isSubscriptionId(context, parameter) || isApiVersion(context, parameter); } + +export function getLocationOfOperation(operation: Operation): Namespace | Interface { + // have to check interface first, because interfaces are more granular than namespaces + return (operation.interface || operation.namespace)!; +} diff --git a/packages/typespec-client-generator-core/src/package.ts b/packages/typespec-client-generator-core/src/package.ts index 6768e29111..1f80b252f1 100644 --- a/packages/typespec-client-generator-core/src/package.ts +++ b/packages/typespec-client-generator-core/src/package.ts @@ -48,13 +48,16 @@ import { import { TCGCContext, createGeneratedName, + filterApiVersionsWithDecorators, getAllResponseBodies, getAvailableApiVersions, getClientNamespaceStringHelper, getDocHelper, getHashForType, + getLocationOfOperation, getSdkTypeBaseHelper, isNullable, + updateWithApiVersionInformation, } from "./internal-utils.js"; import { createDiagnostic } from "./lib.js"; import { @@ -238,12 +241,12 @@ function getSdkBasicServiceMethod< const parameters = httpOperation.parameters; // path/query/header parameters for (const param of parameters.parameters) { - methodParameters.push(diagnostics.pipe(getSdkMethodParameter(context, param.param))); + methodParameters.push(diagnostics.pipe(getSdkMethodParameter(context, param.param, operation))); } // body parameters if (parameters.body?.parameter) { methodParameters.push( - diagnostics.pipe(getSdkMethodParameter(context, parameters.body?.parameter)) + diagnostics.pipe(getSdkMethodParameter(context, parameters.body?.parameter, operation)) ); } else if (parameters.body) { if (parameters.body.type.kind === "Model") { @@ -251,13 +254,15 @@ function getSdkBasicServiceMethod< // spread case if (type.name === "") { for (const prop of type.properties.values()) { - methodParameters.push(diagnostics.pipe(getSdkMethodParameter(context, prop))); + methodParameters.push(diagnostics.pipe(getSdkMethodParameter(context, prop, operation))); } } else { - methodParameters.push(diagnostics.pipe(getSdkMethodParameter(context, type))); + methodParameters.push(diagnostics.pipe(getSdkMethodParameter(context, type, operation))); } } else { - methodParameters.push(diagnostics.pipe(getSdkMethodParameter(context, parameters.body.type))); + methodParameters.push( + diagnostics.pipe(getSdkMethodParameter(context, parameters.body.type, operation)) + ); } } @@ -276,12 +281,12 @@ function getSdkBasicServiceMethod< details: getDocHelper(context, operation).details, operation: serviceOperation, response, - apiVersions: getAvailableApiVersions(context, operation), + apiVersions: getAvailableApiVersions(context, operation, getLocationOfOperation(operation)), getParameterMapping: function getParameterMapping( serviceParam: SdkServiceParameter ): SdkModelPropertyType[] { return ignoreDiagnostics( - getCorrespondingMethodParams(context, name, methodParameters, serviceParam) + getCorrespondingMethodParams(context, operation, methodParameters, serviceParam) ); }, getResponseMapping: function getResponseMapping(): string | undefined { @@ -343,8 +348,17 @@ function getSdkInitializationType< if (credentialParam) { properties.push(credentialParam); } - if (context.__api_version_parameter) { - properties.push(context.__api_version_parameter); + let apiVersionParam = context.__namespaceToApiVersionParameter.get(client.type); + if (!apiVersionParam) { + for (const operationGroup of listOperationGroups(context, client)) { + // if any sub operation groups have an api version param, the top level needs + // the api version param as well + apiVersionParam = context.__namespaceToApiVersionParameter.get(operationGroup.type); + if (apiVersionParam) break; + } + } + if (apiVersionParam) { + properties.push(apiVersionParam); } if (context.__subscriptionIdParameter) { properties.push(context.__subscriptionIdParameter); @@ -362,7 +376,7 @@ function getSdkInitializationType< usage: UsageFlags.Input, nullable: false, crossLanguageDefinitionId: `${getNamespaceFullName(client.service.namespace!)}.${name}`, - apiVersions: getAvailableApiVersions(context, client.service), + apiVersions: getAvailableApiVersions(context, client.service, client.type), isFormDataType: false, isError: false, }); @@ -370,18 +384,19 @@ function getSdkInitializationType< function getSdkMethodParameter( context: TCGCContext, - type: Type + type: Type, + operation: Operation ): [SdkMethodParameter, readonly Diagnostic[]] { const diagnostics = createDiagnosticCollector(); if (type.kind !== "ModelProperty") { const libraryName = getLibraryName(context, type); const name = camelCase(libraryName ?? "body"); - const propertyType = diagnostics.pipe(getClientTypeWithDiagnostics(context, type)); + const propertyType = diagnostics.pipe(getClientTypeWithDiagnostics(context, type, operation)); return diagnostics.wrap({ kind: "method", description: getDocHelper(context, type).description, details: getDocHelper(context, type).details, - apiVersions: getAvailableApiVersions(context, type), + apiVersions: getAvailableApiVersions(context, type, getLocationOfOperation(operation)), type: propertyType, nameInClient: name, name, @@ -395,7 +410,7 @@ function getSdkMethodParameter( }); } return diagnostics.wrap({ - ...diagnostics.pipe(getSdkModelPropertyType(context, type)), + ...diagnostics.pipe(getSdkModelPropertyType(context, type, operation)), kind: "method", }); } @@ -423,7 +438,7 @@ function getSdkMethods x.rootVersion) - .map((x) => x.rootVersion!.value); - context.__api_version_client_default_value = getClientDefaultApiVersion(context, client); // NOTE: getSdkMethods recursively calls createSdkClientType const methods = diagnostics.pipe(getSdkMethods(context, client)); @@ -538,7 +553,7 @@ function createSdkClientType< description: docWrapper.description, details: docWrapper.details, methods: methods, - apiVersions: getAvailableApiVersions(context, client.type), + apiVersions: getAvailableApiVersions(context, client.type, client.type), nameSpace: getClientNamespaceStringHelper(context, client.service)!, initialization: diagnostics.pipe( getSdkInitializationType(context, client) @@ -550,13 +565,45 @@ function createSdkClientType< return diagnostics.wrap(sdkClientType); } +function populateApiVersionInformation(context: SdkContext): void { + for (const client of listClients(context)) { + let clientApiVersions = resolveVersions(context.program, client.service) + .filter((x) => x.rootVersion) + .map((x) => x.rootVersion!.value); + context.__namespaceToApiVersions.set( + client.type, + filterApiVersionsWithDecorators(context, client.type, clientApiVersions) + ); + + context.__namespaceToApiVersionClientDefaultValue.set( + client.type, + getClientDefaultApiVersion(context, client) + ); + for (const og of listOperationGroups(context, client)) { + clientApiVersions = resolveVersions(context.program, og.service) + .filter((x) => x.rootVersion) + .map((x) => x.rootVersion!.value); + context.__namespaceToApiVersions.set( + og.type, + filterApiVersionsWithDecorators(context, og.type, clientApiVersions) + ); + + context.__namespaceToApiVersionClientDefaultValue.set( + og.type, + getClientDefaultApiVersion(context, og) + ); + } + } +} + export function getSdkPackage< TOptions extends object, TServiceOperation extends SdkServiceOperation, >(context: SdkContext): SdkPackage { const diagnostics = createDiagnosticCollector(); - const modelsAndEnums = diagnostics.pipe(getAllModelsWithDiagnostics(context)); context.__clients = new Array>(); + populateApiVersionInformation(context); + const modelsAndEnums = diagnostics.pipe(getAllModelsWithDiagnostics(context)); for (const client of listClients(context)) { createSdkClientType(context, client); } diff --git a/packages/typespec-client-generator-core/src/types.ts b/packages/typespec-client-generator-core/src/types.ts index 57f28668b2..3d6286c4b6 100644 --- a/packages/typespec-client-generator-core/src/types.ts +++ b/packages/typespec-client-generator-core/src/types.ts @@ -492,8 +492,8 @@ function addDiscriminatorToModelType( isGeneratedName: false, onClient: false, apiVersions: discriminatorProperty - ? getAvailableApiVersions(context, discriminatorProperty.__raw!) - : getAvailableApiVersions(context, type), + ? getAvailableApiVersions(context, discriminatorProperty.__raw!, type.namespace) + : getAvailableApiVersions(context, type, type.namespace), isApiVersionParam: false, isMultipartFileInput: false, // discriminator property cannot be a file flatten: false, // discriminator properties can not be flattened @@ -537,7 +537,7 @@ export function getSdkModelWithDiagnostics( access: undefined, // dummy value since we need to update models map before we can set this usage: UsageFlags.None, // dummy value since we need to update models map before we can set this crossLanguageDefinitionId: getCrossLanguageDefinitionId(type, name), - apiVersions: getAvailableApiVersions(context, type), + apiVersions: getAvailableApiVersions(context, type, type.namespace), isFormDataType: isMultipartFormData(context, type, operation), isError: isErrorModel(context.program, type), }; @@ -662,7 +662,7 @@ export function getSdkEnum(context: TCGCContext, type: Enum, operation?: Operati usage: UsageFlags.None, // We will add usage as we loop through the operations access: undefined, // Dummy value until we update models map crossLanguageDefinitionId: getCrossLanguageDefinitionId(type), - apiVersions: getAvailableApiVersions(context, type), + apiVersions: getAvailableApiVersions(context, type, type.namespace), isUnionAsEnum: false, }; for (const member of type.members.values()) { @@ -718,7 +718,7 @@ function getSdkUnionEnum(context: TCGCContext, type: UnionEnum, operation?: Oper usage: UsageFlags.None, // We will add usage as we loop through the operations access: undefined, // Dummy value until we update models map crossLanguageDefinitionId: getCrossLanguageDefinitionId(union, name), - apiVersions: getAvailableApiVersions(context, type.union), + apiVersions: getAvailableApiVersions(context, type.union, type.union.namespace), isUnionAsEnum: true, }; sdkType.values = getSdkUnionEnumValues(context, type, sdkType); @@ -756,7 +756,7 @@ function getKnownValuesEnum( usage: UsageFlags.None, // We will add usage as we loop through the operations access: undefined, // Dummy value until we update models map crossLanguageDefinitionId: getCrossLanguageDefinitionId(type), - apiVersions: getAvailableApiVersions(context, type), + apiVersions: getAvailableApiVersions(context, type, type.namespace), isUnionAsEnum: false, }; for (const member of knownValues.members.values()) { @@ -946,7 +946,7 @@ export function getSdkCredentialParameter( name, isGeneratedName: true, description: "Credential used to authenticate requests to the service.", - apiVersions: getAvailableApiVersions(context, client.service), + apiVersions: getAvailableApiVersions(context, client.service, client.type), onClient: true, optional: false, isApiVersionParam: false, @@ -973,14 +973,18 @@ export function getSdkModelPropertyTypeBase( __raw: type, description: docWrapper.description, details: docWrapper.details, - apiVersions: getAvailableApiVersions(context, type), + apiVersions: getAvailableApiVersions( + context, + type, + operation?.interface || operation?.namespace || type.model?.namespace + ), type: propertyType, nameInClient: name, name, isGeneratedName: false, optional: type.optional, nullable: isNullable(type.type), - ...updateWithApiVersionInformation(context, type), + ...updateWithApiVersionInformation(context, type, operation?.namespace), }); } @@ -990,9 +994,9 @@ export function getSdkModelPropertyType( operation?: Operation ): [SdkModelPropertyType, readonly Diagnostic[]] { const diagnostics = createDiagnosticCollector(); - const base = diagnostics.pipe(getSdkModelPropertyTypeBase(context, type)); + const base = diagnostics.pipe(getSdkModelPropertyTypeBase(context, type, operation)); - if (isSdkHttpParameter(context, type)) return getSdkHttpParameter(context, type); + if (isSdkHttpParameter(context, type)) return getSdkHttpParameter(context, type, operation!); // I'm a body model property let operationIsMultipart = false; if (operation) { @@ -1022,7 +1026,7 @@ export function getSdkModelPropertyType( serializedName: getPropertyNames(context, type)[1], isMultipartFileInput: isBytesInput && operationIsMultipart, flatten: shouldFlattenProperty(context, type), - ...updateWithApiVersionInformation(context, type), + ...updateWithApiVersionInformation(context, type, operation?.namespace), }); } diff --git a/packages/typespec-client-generator-core/test/decorators.test.ts b/packages/typespec-client-generator-core/test/decorators.test.ts index 29fffb8951..c1bcb447a3 100644 --- a/packages/typespec-client-generator-core/test/decorators.test.ts +++ b/packages/typespec-client-generator-core/test/decorators.test.ts @@ -3270,6 +3270,74 @@ describe("typespec-client-generator-core: decorators", () => { strictEqual(runnerWithVersion.context.experimental_sdkPackage.models.length, 1); strictEqual(runnerWithVersion.context.experimental_sdkPackage.models[0].name, "StableModel"); }); + it("add client", async () => { + await runner.compile( + ` + @service + @versioned(Versions) + @server( + "{endpoint}", + "Testserver endpoint", + { + endpoint: url, + } + ) + namespace Versioning; + enum Versions { + v1: "v1", + v2: "v2", + } + op test(): void; + + @added(Versions.v2) + @route("/interface-v2") + interface InterfaceV2 { + @post + @route("/v2") + test2(): void; + } + ` + ); + const sdkPackage = runner.context.experimental_sdkPackage; + strictEqual(sdkPackage.clients.length, 2); + const versioningClient = sdkPackage.clients.find((x) => x.name === "VersioningClient"); + ok(versioningClient); + strictEqual(versioningClient.methods.length, 2); + + strictEqual(versioningClient.initialization.properties.length, 1); + const versioningClientEndpoint = versioningClient.initialization.properties.find( + (x) => x.kind === "endpoint" + ); + ok(versioningClientEndpoint); + deepStrictEqual(versioningClientEndpoint.apiVersions, ["v1", "v2"]); + + const serviceMethod = versioningClient.methods.find((x) => x.kind === "basic"); + ok(serviceMethod); + strictEqual(serviceMethod.name, "test"); + deepStrictEqual(serviceMethod.apiVersions, ["v1", "v2"]); + + const clientAccessor = versioningClient.methods.find((x) => x.kind === "clientaccessor"); + ok(clientAccessor); + strictEqual(clientAccessor.name, "getInterfaceV2"); + deepStrictEqual(clientAccessor.apiVersions, ["v2"]); + + const interfaceV2 = sdkPackage.clients.find((x) => x.name === "InterfaceV2"); + ok(interfaceV2); + strictEqual(interfaceV2.methods.length, 1); + + strictEqual(interfaceV2.initialization.properties.length, 1); + const interfaceV2Endpoint = interfaceV2.initialization.properties.find( + (x) => x.kind === "endpoint" + ); + ok(interfaceV2Endpoint); + deepStrictEqual(interfaceV2Endpoint.apiVersions, ["v2"]); + + strictEqual(interfaceV2.methods.length, 1); + const test2Method = interfaceV2.methods.find((x) => x.kind === "basic"); + ok(test2Method); + strictEqual(test2Method.name, "test2"); + deepStrictEqual(test2Method.apiVersions, ["v2"]); + }); }); describe("versioning impact for apis", () => {