Skip to content

Commit

Permalink
Merge pull request #1696 from hey-api/test/sanitize-plus-operator
Browse files Browse the repository at this point in the history
test: add tests for operationToId method
  • Loading branch information
mrlubos authored Feb 10, 2025
2 parents 1de7641 + 1878c69 commit de79917
Show file tree
Hide file tree
Showing 236 changed files with 5,627 additions and 475 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
"test:coverage": "turbo run test:coverage",
"test:e2e": "turbo run test:e2e",
"test:update": "turbo run test:update",
"test:watch": "turbo run test:watch",
"test": "turbo run test",
"typecheck": "turbo run typecheck --filter=\"!@example/openapi-ts-sample\"",
"vitepress": "turbo run $1 --filter=\"@docs/openapi-ts\""
Expand Down
8 changes: 7 additions & 1 deletion packages/openapi-ts/src/getSpec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@ export const getSpec = async ({
let hasChanged: boolean | undefined;
let response: Response | undefined;

// no support for watching files and objects for now
if (resolvedInput.type === 'url') {
// do NOT send HEAD request on first run or if unsupported
if (watch.lastValue && watch.isHeadMethodSupported !== false) {
Expand Down Expand Up @@ -129,6 +128,13 @@ export const getSpec = async ({
hasChanged = content !== watch.lastValue;
watch.lastValue = content;
}
} else {
// we do not support watch mode for files or raw spec data
if (!watch.lastValue) {
watch.lastValue = resolvedInput.type;
} else {
hasChanged = false;
}
}

if (hasChanged === false) {
Expand Down
2 changes: 1 addition & 1 deletion packages/openapi-ts/src/openApi/common/parser/operation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,7 @@ export const operationNameFn = ({
urlWithoutPlaceholders = urlWithoutPlaceholders
.replace(/{(.*?)}/g, 'by-$1')
// replace slashes with hyphens for camelcase method at the end
.replace(/[/:]/g, '-');
.replace(/[/:+]/g, '-');

return stringCase({
case: 'camelCase',
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import { describe, expect, it } from 'vitest';

import type { IR } from '../../../../ir/types';
import { operationToId } from '../operation';

describe('operationToId', () => {
const scenarios: Array<{
id?: string;
method: string;
output: string;
path: string;
}> = [
{
method: 'post',
output: 'postFoo',
path: '/foo',
},
{
id: 'Post-foo',
method: 'post',
output: 'postFoo',
path: '/foo',
},
{
method: 'post',
output: 'postFooByFooId',
path: '/foo/{foo_id}',
},
{
method: 'post',
output: 'postFooByFooIdBarBazQux',
path: '/foo/{foo_id}/bar+baz:qux',
},
];

it.each(scenarios)(
'transforms $method $path ($id) -> $output',
async ({ id, method, output, path }) => {
const context: Partial<IR.Context> = {
config: {
plugins: {
// @ts-expect-error
'@hey-api/sdk': {
operationId: true,
},
},
},
};
expect(
operationToId({
context: context as IR.Context,
id,
method,
path,
}),
).toEqual(output);
},
);
});
2 changes: 1 addition & 1 deletion packages/openapi-ts/src/openApi/shared/utils/operation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ export const operationToId = ({
const urlWithoutPlaceholders = path
.replace(/{(.*?)}/g, 'by-$1')
// replace slashes with hyphens for camelcase method at the end
.replace(/[/:]/g, '-');
.replace(/[/:+]/g, '-');

return stringCase({
case: 'camelCase',
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// This file is auto-generated by @hey-api/openapi-ts

import type { Options as ClientOptions, TDataShape, Client } from '@hey-api/client-fetch';
import type { ServiceWithEmptyTagData, DeleteCallWithoutParametersAndResponseData, GetCallWithoutParametersAndResponseData, HeadCallWithoutParametersAndResponseData, OptionsCallWithoutParametersAndResponseData, PatchCallWithoutParametersAndResponseData, PostCallWithoutParametersAndResponseData, PutCallWithoutParametersAndResponseData, CallWithDescriptionsData, CallWithParametersData, CallWithWeirdParameterNamesData, CallWithDefaultParametersData, CallWithDefaultOptionalParametersData, CallToTestOrderOfParamsData, DuplicateNameData, DuplicateName2Data, DuplicateName3Data, DuplicateName4Data, CallWithNoContentResponseData, CallWithResponseAndNoContentResponseData, CallWithResponseAndNoContentResponseResponse, DummyAData, DummyBData, CallWithResponseData, CallWithResponseResponse, CallWithDuplicateResponsesData, CallWithDuplicateResponsesResponse, CallWithDuplicateResponsesError, CallWithResponsesData, CallWithResponsesResponse, CallWithResponsesError, CollectionFormatData, TypesData, TypesResponse, ComplexTypesData, ComplexTypesResponse, CallWithResultFromHeaderData, TestErrorCodeData, NonAsciiæøåÆøÅöôêÊ字符串Data, NonAsciiæøåÆøÅöôêÊ字符串Response, PostApiVbyApiVersionBodyData, PostApiVbyApiVersionBodyResponse, PostApiVbyApiVersionBodyError } from './types.gen';
import type { ServiceWithEmptyTagData, PatchApiVbyApiVersionNoTagData, FooWowData, DeleteCallWithoutParametersAndResponseData, GetCallWithoutParametersAndResponseData, HeadCallWithoutParametersAndResponseData, OptionsCallWithoutParametersAndResponseData, PatchCallWithoutParametersAndResponseData, PostCallWithoutParametersAndResponseData, PutCallWithoutParametersAndResponseData, CallWithDescriptionsData, CallWithParametersData, CallWithWeirdParameterNamesData, CallWithDefaultParametersData, CallWithDefaultOptionalParametersData, CallToTestOrderOfParamsData, DuplicateNameData, DuplicateName2Data, DuplicateName3Data, DuplicateName4Data, CallWithNoContentResponseData, CallWithResponseAndNoContentResponseData, CallWithResponseAndNoContentResponseResponse, DummyAData, DummyBData, CallWithResponseData, CallWithResponseResponse, CallWithDuplicateResponsesData, CallWithDuplicateResponsesResponse, CallWithDuplicateResponsesError, CallWithResponsesData, CallWithResponsesResponse, CallWithResponsesError, CollectionFormatData, TypesData, TypesResponse, ComplexTypesData, ComplexTypesResponse, CallWithResultFromHeaderData, TestErrorCodeData, NonAsciiæøåÆøÅöôêÊ字符串Data, NonAsciiæøåÆøÅöôêÊ字符串Response, PostApiVbyApiVersionBodyData, PostApiVbyApiVersionBodyResponse, PostApiVbyApiVersionBodyError } from './types.gen';
import { client as _heyApiClient } from './client.gen';

export type Options<TData extends TDataShape = TDataShape, ThrowOnError extends boolean = boolean> = ClientOptions<TData, ThrowOnError> & {
Expand All @@ -15,7 +15,21 @@ export type Options<TData extends TDataShape = TDataShape, ThrowOnError extends

export const serviceWithEmptyTag = <ThrowOnError extends boolean = false>(options?: Options<ServiceWithEmptyTagData, ThrowOnError>) => {
return (options?.client ?? _heyApiClient).get<unknown, unknown, ThrowOnError>({
url: '/api/v{api-version}/no-tag',
url: '/api/v{api-version}/no+tag',
...options
});
};

export const patchApiVbyApiVersionNoTag = <ThrowOnError extends boolean = false>(options?: Options<PatchApiVbyApiVersionNoTagData, ThrowOnError>) => {
return (options?.client ?? _heyApiClient).patch<unknown, unknown, ThrowOnError>({
url: '/api/v{api-version}/no+tag',
...options
});
};

export const fooWow = <ThrowOnError extends boolean = false>(options?: Options<FooWowData, ThrowOnError>) => {
return (options?.client ?? _heyApiClient).put<unknown, unknown, ThrowOnError>({
url: '/api/v{api-version}/no+tag',
...options
});
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -410,7 +410,35 @@ export type ServiceWithEmptyTagData = {
body?: never;
path?: never;
query?: never;
url: '/api/v{api-version}/no-tag';
url: '/api/v{api-version}/no+tag';
};

export type PatchApiVbyApiVersionNoTagData = {
body?: never;
path?: never;
query?: never;
url: '/api/v{api-version}/no+tag';
};

export type PatchApiVbyApiVersionNoTagResponses = {
/**
* OK
*/
default: unknown;
};

export type FooWowData = {
body?: never;
path?: never;
query?: never;
url: '/api/v{api-version}/no+tag';
};

export type FooWowResponses = {
/**
* OK
*/
default: unknown;
};

export type DeleteCallWithoutParametersAndResponseData = {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// This file is auto-generated by @hey-api/openapi-ts

import type { Options as ClientOptions, TDataShape, Client } from '@hey-api/client-fetch';
import type { ServiceWithEmptyTagData, DeleteCallWithoutParametersAndResponseData, GetCallWithoutParametersAndResponseData, HeadCallWithoutParametersAndResponseData, OptionsCallWithoutParametersAndResponseData, PatchCallWithoutParametersAndResponseData, PostCallWithoutParametersAndResponseData, PutCallWithoutParametersAndResponseData, CallWithDescriptionsData, CallWithParametersData, CallWithWeirdParameterNamesData, CallWithDefaultParametersData, CallWithDefaultOptionalParametersData, CallToTestOrderOfParamsData, DuplicateNameData, DuplicateName2Data, DuplicateName3Data, DuplicateName4Data, CallWithNoContentResponseData, CallWithResponseAndNoContentResponseData, CallWithResponseAndNoContentResponseResponse, DummyAData, DummyBData, CallWithResponseData, CallWithResponseResponse, CallWithDuplicateResponsesData, CallWithDuplicateResponsesResponse, CallWithDuplicateResponsesError, CallWithResponsesData, CallWithResponsesResponse, CallWithResponsesError, CollectionFormatData, TypesData, TypesResponse, ComplexTypesData, ComplexTypesResponse, CallWithResultFromHeaderData, TestErrorCodeData, NonAsciiæøåÆøÅöôêÊ字符串Data, NonAsciiæøåÆøÅöôêÊ字符串Response, PostApiVbyApiVersionBodyData, PostApiVbyApiVersionBodyResponse, PostApiVbyApiVersionBodyError } from './types.gen';
import type { ServiceWithEmptyTagData, PatchApiVbyApiVersionNoTagData, FooWowData, DeleteCallWithoutParametersAndResponseData, GetCallWithoutParametersAndResponseData, HeadCallWithoutParametersAndResponseData, OptionsCallWithoutParametersAndResponseData, PatchCallWithoutParametersAndResponseData, PostCallWithoutParametersAndResponseData, PutCallWithoutParametersAndResponseData, CallWithDescriptionsData, CallWithParametersData, CallWithWeirdParameterNamesData, CallWithDefaultParametersData, CallWithDefaultOptionalParametersData, CallToTestOrderOfParamsData, DuplicateNameData, DuplicateName2Data, DuplicateName3Data, DuplicateName4Data, CallWithNoContentResponseData, CallWithResponseAndNoContentResponseData, CallWithResponseAndNoContentResponseResponse, DummyAData, DummyBData, CallWithResponseData, CallWithResponseResponse, CallWithDuplicateResponsesData, CallWithDuplicateResponsesResponse, CallWithDuplicateResponsesError, CallWithResponsesData, CallWithResponsesResponse, CallWithResponsesError, CollectionFormatData, TypesData, TypesResponse, ComplexTypesData, ComplexTypesResponse, CallWithResultFromHeaderData, TestErrorCodeData, NonAsciiæøåÆøÅöôêÊ字符串Data, NonAsciiæøåÆøÅöôêÊ字符串Response, PostApiVbyApiVersionBodyData, PostApiVbyApiVersionBodyResponse, PostApiVbyApiVersionBodyError } from './types.gen';
import { client as _heyApiClient } from './client.gen';

export type Options<TData extends TDataShape = TDataShape, ThrowOnError extends boolean = boolean> = ClientOptions<TData, ThrowOnError> & {
Expand All @@ -15,7 +15,21 @@ export type Options<TData extends TDataShape = TDataShape, ThrowOnError extends

export const serviceWithEmptyTag = <ThrowOnError extends boolean = true>(options?: Options<ServiceWithEmptyTagData, ThrowOnError>) => {
return (options?.client ?? _heyApiClient).get<unknown, unknown, ThrowOnError>({
url: '/api/v{api-version}/no-tag',
url: '/api/v{api-version}/no+tag',
...options
});
};

export const patchApiVbyApiVersionNoTag = <ThrowOnError extends boolean = true>(options?: Options<PatchApiVbyApiVersionNoTagData, ThrowOnError>) => {
return (options?.client ?? _heyApiClient).patch<unknown, unknown, ThrowOnError>({
url: '/api/v{api-version}/no+tag',
...options
});
};

export const fooWow = <ThrowOnError extends boolean = true>(options?: Options<FooWowData, ThrowOnError>) => {
return (options?.client ?? _heyApiClient).put<unknown, unknown, ThrowOnError>({
url: '/api/v{api-version}/no+tag',
...options
});
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -410,7 +410,35 @@ export type ServiceWithEmptyTagData = {
body?: never;
path?: never;
query?: never;
url: '/api/v{api-version}/no-tag';
url: '/api/v{api-version}/no+tag';
};

export type PatchApiVbyApiVersionNoTagData = {
body?: never;
path?: never;
query?: never;
url: '/api/v{api-version}/no+tag';
};

export type PatchApiVbyApiVersionNoTagResponses = {
/**
* OK
*/
default: unknown;
};

export type FooWowData = {
body?: never;
path?: never;
query?: never;
url: '/api/v{api-version}/no+tag';
};

export type FooWowResponses = {
/**
* OK
*/
default: unknown;
};

export type DeleteCallWithoutParametersAndResponseData = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import { type Options, DefaultService, SimpleService, DescriptionsService, ParametersService, DefaultsService, DuplicateService, NoContentService, ResponseService, MultipleTags1Service, CollectionFormatService, TypesService, ComplexService, HeaderService, ErrorService, NonAsciiÆøåÆøÅöôêÊService } from '../sdk.gen';
import { queryOptions, type MutationOptions, type DefaultError } from '@tanstack/angular-query-experimental';
import type { ServiceWithEmptyTagData, DeleteCallWithoutParametersAndResponseData, GetCallWithoutParametersAndResponseData, PatchCallWithoutParametersAndResponseData, PostCallWithoutParametersAndResponseData, PutCallWithoutParametersAndResponseData, CallWithDescriptionsData, CallWithParametersData, CallWithWeirdParameterNamesData, CallWithDefaultParametersData, CallWithDefaultOptionalParametersData, CallToTestOrderOfParamsData, DuplicateNameData, DuplicateName2Data, DuplicateName3Data, DuplicateName4Data, CallWithNoContentResponseData, CallWithResponseAndNoContentResponseData, DummyAData, DummyBData, CallWithResponseData, CallWithDuplicateResponsesData, CallWithDuplicateResponsesError, CallWithDuplicateResponsesResponse, CallWithResponsesData, CallWithResponsesError, CallWithResponsesResponse, CollectionFormatData, TypesData, ComplexTypesData, CallWithResultFromHeaderData, TestErrorCodeData, NonAsciiæøåÆøÅöôêÊ字符串Data, NonAsciiæøåÆøÅöôêÊ字符串Response, PostApiVbyApiVersionBodyData, PostApiVbyApiVersionBodyError, PostApiVbyApiVersionBodyResponse } from '../types.gen';
import type { ServiceWithEmptyTagData, PatchApiVbyApiVersionNoTagData, FooWowData, DeleteCallWithoutParametersAndResponseData, GetCallWithoutParametersAndResponseData, PatchCallWithoutParametersAndResponseData, PostCallWithoutParametersAndResponseData, PutCallWithoutParametersAndResponseData, CallWithDescriptionsData, CallWithParametersData, CallWithWeirdParameterNamesData, CallWithDefaultParametersData, CallWithDefaultOptionalParametersData, CallToTestOrderOfParamsData, DuplicateNameData, DuplicateName2Data, DuplicateName3Data, DuplicateName4Data, CallWithNoContentResponseData, CallWithResponseAndNoContentResponseData, DummyAData, DummyBData, CallWithResponseData, CallWithDuplicateResponsesData, CallWithDuplicateResponsesError, CallWithDuplicateResponsesResponse, CallWithResponsesData, CallWithResponsesError, CallWithResponsesResponse, CollectionFormatData, TypesData, ComplexTypesData, CallWithResultFromHeaderData, TestErrorCodeData, NonAsciiæøåÆøÅöôêÊ字符串Data, NonAsciiæøåÆøÅöôêÊ字符串Response, PostApiVbyApiVersionBodyData, PostApiVbyApiVersionBodyError, PostApiVbyApiVersionBodyResponse } from '../types.gen';
import { client as _heyApiClient } from '../client.gen';

type QueryKey<TOptions extends Options> = [
Expand Down Expand Up @@ -51,6 +51,34 @@ export const serviceWithEmptyTagOptions = (options?: Options<ServiceWithEmptyTag
});
};

export const patchApiVbyApiVersionNoTagMutation = (options?: Partial<Options<PatchApiVbyApiVersionNoTagData>>) => {
const mutationOptions: MutationOptions<unknown, DefaultError, Options<PatchApiVbyApiVersionNoTagData>> = {
mutationFn: async (localOptions) => {
const { data } = await DefaultService.patchApiVbyApiVersionNoTag({
...options,
...localOptions,
throwOnError: true
});
return data;
}
};
return mutationOptions;
};

export const fooWowMutation = (options?: Partial<Options<FooWowData>>) => {
const mutationOptions: MutationOptions<unknown, DefaultError, Options<FooWowData>> = {
mutationFn: async (localOptions) => {
const { data } = await DefaultService.fooWow({
...options,
...localOptions,
throwOnError: true
});
return data;
}
};
return mutationOptions;
};

export const deleteCallWithoutParametersAndResponseMutation = (options?: Partial<Options<DeleteCallWithoutParametersAndResponseData>>) => {
const mutationOptions: MutationOptions<unknown, DefaultError, Options<DeleteCallWithoutParametersAndResponseData>> = {
mutationFn: async (localOptions) => {
Expand Down
Loading

0 comments on commit de79917

Please sign in to comment.