From fb2b95ffa26373ce6d25c839684f04dc67aaaade Mon Sep 17 00:00:00 2001 From: Miha Jakovac Date: Tue, 17 Aug 2021 21:33:47 +0200 Subject: [PATCH 1/5] nuget updates --- Directory.Build.props | 2 +- .../QAToolKit.Source.Swagger.Test.csproj | 8 ++++---- .../QAToolKit.Source.Swagger.csproj | 4 ++-- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/Directory.Build.props b/Directory.Build.props index e97debe..14df131 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -1,5 +1,5 @@ - 0.3.9 + 0.3.10 \ No newline at end of file diff --git a/src/QAToolKit.Source.Swagger.Test/QAToolKit.Source.Swagger.Test.csproj b/src/QAToolKit.Source.Swagger.Test/QAToolKit.Source.Swagger.Test.csproj index 56128a2..32bb618 100644 --- a/src/QAToolKit.Source.Swagger.Test/QAToolKit.Source.Swagger.Test.csproj +++ b/src/QAToolKit.Source.Swagger.Test/QAToolKit.Source.Swagger.Test.csproj @@ -7,20 +7,20 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive - + - + all runtime; build; native; contentfiles; analyzers; buildtransitive - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/src/QAToolKit.Source.Swagger/QAToolKit.Source.Swagger.csproj b/src/QAToolKit.Source.Swagger/QAToolKit.Source.Swagger.csproj index d7389b3..dd40309 100644 --- a/src/QAToolKit.Source.Swagger/QAToolKit.Source.Swagger.csproj +++ b/src/QAToolKit.Source.Swagger/QAToolKit.Source.Swagger.csproj @@ -36,8 +36,8 @@ - - + + From 36e06fd6620f2e171df70285816020d0c56aebdf Mon Sep 17 00:00:00 2001 From: Miha Jakovac Date: Sun, 10 Oct 2021 17:25:26 +0200 Subject: [PATCH 2/5] Nullable checks and additional registers --- Directory.Build.props | 2 +- .../QAToolKit.Source.Swagger.csproj | 2 +- .../SwaggerProcessor.cs | 70 ++++++++++++++++--- 3 files changed, 63 insertions(+), 11 deletions(-) diff --git a/Directory.Build.props b/Directory.Build.props index 14df131..9d37d92 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -1,5 +1,5 @@ - 0.3.10 + 0.3.11 \ No newline at end of file diff --git a/src/QAToolKit.Source.Swagger/QAToolKit.Source.Swagger.csproj b/src/QAToolKit.Source.Swagger/QAToolKit.Source.Swagger.csproj index dd40309..554ee47 100644 --- a/src/QAToolKit.Source.Swagger/QAToolKit.Source.Swagger.csproj +++ b/src/QAToolKit.Source.Swagger/QAToolKit.Source.Swagger.csproj @@ -37,7 +37,7 @@ - + diff --git a/src/QAToolKit.Source.Swagger/SwaggerProcessor.cs b/src/QAToolKit.Source.Swagger/SwaggerProcessor.cs index 18cc581..604f032 100644 --- a/src/QAToolKit.Source.Swagger/SwaggerProcessor.cs +++ b/src/QAToolKit.Source.Swagger/SwaggerProcessor.cs @@ -55,7 +55,8 @@ public IEnumerable MapFromOpenApiDocument(Uri baseUri, OpenApiDocum { if (baseUri == null) { - throw new QAToolKitSwaggerException("Swagger from file source needs BaseUrl defined. Inject baseUrl with AddBaseUrl in your SwaggerSource instantiation."); + throw new QAToolKitSwaggerException( + "Swagger from file source needs BaseUrl defined. Inject baseUrl with AddBaseUrl in your SwaggerSource instantiation."); } baseUri = new Uri(baseUri, tempUri); @@ -106,6 +107,16 @@ private IEnumerable GetRestRequestsForPath(Uri baseUri, KeyValuePai { var testType = new List(); + if (operation.Value == null) + { + return testType; + } + + if (operation.Value.Description == null) + { + return testType; + } + if (operation.Value.Description.Contains(TestType.IntegrationTest.Value())) { testType.Add(TestType.Enumeration.IntegrationTest); @@ -129,10 +140,21 @@ private IEnumerable GetRestRequestsForPath(Uri baseUri, KeyValuePai return testType; } - private List GetAuthenticationTypes(KeyValuePair operation) + private List GetAuthenticationTypes( + KeyValuePair operation) { var authenticationTypes = new List(); + if (operation.Value == null) + { + return authenticationTypes; + } + + if (operation.Value.Description == null) + { + return authenticationTypes; + } + if (operation.Value.Description.Contains(AuthenticationType.Administrator.Value())) { authenticationTypes.Add(AuthenticationType.Enumeration.Administrator); @@ -158,11 +180,31 @@ private IEnumerable GetRestRequestsForPath(Uri baseUri, KeyValuePai private string GetDescription(KeyValuePair operation) { + if (operation.Value == null) + { + return String.Empty; + } + + if (operation.Value.Description == null) + { + return String.Empty; + } + return operation.Value.Description; } private string[] GetTags(KeyValuePair operation) { + if (operation.Value == null) + { + return Array.Empty(); + } + + if (operation.Value.Tags == null) + { + return Array.Empty(); + } + return operation.Value.Tags.Select(t => t.Name).ToArray(); } @@ -221,8 +263,10 @@ private HttpMethod GetHttpMethod(KeyValuePair o "403" => HttpStatusCode.Forbidden, "404" => HttpStatusCode.NotFound, "405" => HttpStatusCode.MethodNotAllowed, + "406" => HttpStatusCode.NotAcceptable, "409" => HttpStatusCode.Conflict, "500" => HttpStatusCode.InternalServerError, + "503" => HttpStatusCode.ServiceUnavailable, "default" => null, _ => throw new QAToolKitSwaggerException($"HttpStatusCode not found '{statusCode}'."), }; @@ -332,6 +376,7 @@ private List GetPropertiesRecursively(KeyValuePair(); #region Items + Property itemsProperty = null; if (source.Value.Items != null) @@ -359,13 +404,16 @@ private List GetPropertiesRecursively(KeyValuePair(); } + itemsProperty.Properties.AddRange(recursiveProperties); } } } + #endregion #region enums + Property enumProperty = null; if (source.Value.Enum != null && source.Value.Enum.Count > 0) { @@ -396,6 +444,7 @@ private List GetPropertiesRecursively(KeyValuePair GetPropertiesRecursively(KeyValuePair(); } + prop.Properties.AddRange(propsTem); } @@ -491,17 +541,19 @@ private List GetResponses(KeyValuePair - ContentType.From(contentType.Key) == ContentType.Json)) + ContentType.From(contentType.Key) == ContentType.Json)) { if (contentType.Value.Schema.Items != null && - (contentType.Value.Schema.Items.Type == "array" || contentType.Value.Schema.Items.Type != "object") && + (contentType.Value.Schema.Items.Type == "array" || + contentType.Value.Schema.Items.Type != "object") && contentType.Value.Schema.Type == "array") { return ResponseType.Array; } else if (contentType.Value.Schema.Items != null && - (contentType.Value.Schema.Items.Type == "array" || contentType.Value.Schema.Items.Type == "object") && - contentType.Value.Schema.Type == "array") + (contentType.Value.Schema.Items.Type == "array" || + contentType.Value.Schema.Items.Type == "object") && + contentType.Value.Schema.Type == "array") { return ResponseType.Objects; } @@ -510,7 +562,7 @@ private ResponseType GetResponseType(OpenApiResponse value) return ResponseType.Object; } else if (contentType.Value.Schema.Items == null && - (contentType.Value.Schema.Type != "object" || contentType.Value.Schema.Type != "array")) + (contentType.Value.Schema.Type != "object" || contentType.Value.Schema.Type != "array")) { return ResponseType.Primitive; } @@ -539,7 +591,7 @@ private List GetResponseProperties(OpenApiResponse openApiResponse) //TODO: support other content types foreach (var contentType in openApiResponse.Content.Where(contentType => - ContentType.From(contentType.Key) == ContentType.Json)) + ContentType.From(contentType.Key) == ContentType.Json)) { if (contentType.Value.Schema.Properties != null && contentType.Value.Schema.Properties.Count > 0) { @@ -561,4 +613,4 @@ private List GetResponseProperties(OpenApiResponse openApiResponse) return properties; } } -} +} \ No newline at end of file From 77347f5bba15b8979908832f7223febd2bc02f62 Mon Sep 17 00:00:00 2001 From: Miha Jakovac Date: Sat, 29 Jan 2022 11:50:58 +0100 Subject: [PATCH 3/5] improved swagger processor, net 6 update --- .github/workflows/codeql-analysis.yml | 4 +- .github/workflows/dotnet-core.yml | 8 +- .github/workflows/sonarqube-analysis.yml | 6 +- Directory.Build.props | 2 +- LICENSE | 2 +- README.md | 2 +- .../Assets/invalid-swagger.json | 3 + .../Assets/support-tickets-ok.yaml | 807 +++++++++++ .../swagger-pets-test-unsuppoted-v1.0.json | 1225 +++++++++++++++++ .../swagger-pets-test-unsuppoted-v3.1.json | 1225 +++++++++++++++++ .../InvalidSwaggerExceptionTests.cs | 27 + .../UnsupportedSwaggerExceptionTests.cs | 27 + .../Get/Helpers/BicyclesParameters.cs | 2 + .../PetApi/Delete/DeletePetParameters.cs | 4 + .../Get/Helpers/PetObjectWithExampleValues.cs | 4 +- .../Helpers/PetObjectWithoutExampleValues.cs | 4 +- .../Fixtures/PetApi/PetResponse400.cs | 3 +- .../Fixtures/PetApi/Post/AddNewPetBody.cs | 4 +- .../PetApi/Post/UploadPetImageBody.cs | 2 +- .../PetApi/Post/UploadPetImageParameters.cs | 2 + .../Fixtures/PetApi/Put/UpdatePetBody.cs | 4 +- .../QAToolKit.Source.Swagger.Test.csproj | 20 +- .../SwaggerFileSourceIntegrationTest.cs | 81 +- .../SwaggerRequestFilterTests.cs | 7 +- .../SwaggerProcessorGetBicycleByIdTests.cs | 25 +- .../Get/SwaggerProcessorFindByTagsTests.cs | 5 +- .../Post/SwaggerProcessorAddNewPetTests.cs | 23 +- .../SwaggerProcessorUploadPetImageTests.cs | 35 +- .../Put/SwaggerProcessorUpdatePetTests.cs | 29 +- .../SwaggerUrlSourceIntegrationTests.cs | 5 +- .../Exceptions/InvalidSwaggerException.cs | 33 + .../Exceptions/SwaggerValidationException.cs | 43 + .../Exceptions/UnsupportedSwaggerException.cs | 33 + src/QAToolKit.Source.Swagger/PropertyType.cs | 118 ++ .../QAToolKit.Source.Swagger.csproj | 6 +- .../SwaggerFileSource.cs | 15 +- .../SwaggerOptions.cs | 16 +- src/QAToolKit.Source.Swagger/SwaggerParser.cs | 113 ++ .../SwaggerProcessor.cs | 312 ++++- .../SwaggerUrlSource.cs | 28 +- 40 files changed, 4099 insertions(+), 215 deletions(-) create mode 100644 src/QAToolKit.Source.Swagger.Test/Assets/invalid-swagger.json create mode 100644 src/QAToolKit.Source.Swagger.Test/Assets/support-tickets-ok.yaml create mode 100644 src/QAToolKit.Source.Swagger.Test/Assets/swagger-pets-test-unsuppoted-v1.0.json create mode 100644 src/QAToolKit.Source.Swagger.Test/Assets/swagger-pets-test-unsuppoted-v3.1.json create mode 100644 src/QAToolKit.Source.Swagger.Test/Exceptions/InvalidSwaggerExceptionTests.cs create mode 100644 src/QAToolKit.Source.Swagger.Test/Exceptions/UnsupportedSwaggerExceptionTests.cs create mode 100644 src/QAToolKit.Source.Swagger/Exceptions/InvalidSwaggerException.cs create mode 100644 src/QAToolKit.Source.Swagger/Exceptions/SwaggerValidationException.cs create mode 100644 src/QAToolKit.Source.Swagger/Exceptions/UnsupportedSwaggerException.cs create mode 100644 src/QAToolKit.Source.Swagger/PropertyType.cs create mode 100644 src/QAToolKit.Source.Swagger/SwaggerParser.cs diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 80734df..d61fb6d 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -22,10 +22,10 @@ jobs: uses: actions/setup-dotnet@v1 with: dotnet-version: '3.1.x' - - name: Setup .NET Core 5.0 + - name: Setup .NET Core 6.0 uses: actions/setup-dotnet@v1 with: - dotnet-version: '5.0.x' + dotnet-version: '6.0.x' - name: Initialize CodeQL uses: github/codeql-action/init@v1 with: diff --git a/.github/workflows/dotnet-core.yml b/.github/workflows/dotnet-core.yml index d1dd63b..1eacfe0 100644 --- a/.github/workflows/dotnet-core.yml +++ b/.github/workflows/dotnet-core.yml @@ -20,10 +20,10 @@ jobs: uses: actions/setup-dotnet@v1 with: dotnet-version: '3.1.x' - - name: Setup .NET Core 5.0 + - name: Setup .NET Core 6.0 uses: actions/setup-dotnet@v1 with: - dotnet-version: '5.0.x' + dotnet-version: '6.0.x' - name: Install dependencies run: dotnet restore - name: Build @@ -48,10 +48,10 @@ jobs: uses: actions/setup-dotnet@v1 with: dotnet-version: '3.1.x' - - name: Setup .NET Core 5.0 + - name: Setup .NET Core 6.0 uses: actions/setup-dotnet@v1 with: - dotnet-version: '5.0.x' + dotnet-version: '6.0.x' - name: Pack NuGet uses: brandedoutcast/publish-nuget@v2.5.5 with: diff --git a/.github/workflows/sonarqube-analysis.yml b/.github/workflows/sonarqube-analysis.yml index 368a396..ced25e6 100644 --- a/.github/workflows/sonarqube-analysis.yml +++ b/.github/workflows/sonarqube-analysis.yml @@ -16,12 +16,12 @@ jobs: uses: actions/setup-dotnet@v1 with: dotnet-version: '3.1.x' - - name: Setup .NET Core 5.0 + - name: Setup .NET Core 6.0 uses: actions/setup-dotnet@v1 with: - dotnet-version: '5.0.x' + dotnet-version: '6.0.x' - name: SonarScanner for .NET Core with pull request decoration support - uses: highbyte/sonarscan-dotnet@2.0 + uses: highbyte/sonarscan-dotnet@v2.1.2 with: sonarProjectKey: qatoolkit_qatoolkit-source-swagger-net sonarProjectName: qatoolkit_qatoolkit-source-swagger-net diff --git a/Directory.Build.props b/Directory.Build.props index 9d37d92..8f74366 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -1,5 +1,5 @@ - 0.3.11 + 0.4.0 \ No newline at end of file diff --git a/LICENSE b/LICENSE index b4bc1c7..2ee8f53 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2020-2021 Miha Jakovac +Copyright (c) 2020-2022 Miha Jakovac Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/README.md b/README.md index 5464176..07407fb 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ ## Description `QAToolKit.Source.Swagger` is a .NET library, which generates `IEnumerable` object that is the input for other components. -Supported .NET frameworks and standards: `netstandard2.0`, `netstandard2.1`, `netcoreapp3.1`, `net5.0` +Supported .NET frameworks and standards: `netstandard2.0`, `netstandard2.1`, `netcoreapp3.1`, `net6.0` Major features: diff --git a/src/QAToolKit.Source.Swagger.Test/Assets/invalid-swagger.json b/src/QAToolKit.Source.Swagger.Test/Assets/invalid-swagger.json new file mode 100644 index 0000000..f2f2a7f --- /dev/null +++ b/src/QAToolKit.Source.Swagger.Test/Assets/invalid-swagger.json @@ -0,0 +1,3 @@ +11111111111 +22222222222 +33333333333 \ No newline at end of file diff --git a/src/QAToolKit.Source.Swagger.Test/Assets/support-tickets-ok.yaml b/src/QAToolKit.Source.Swagger.Test/Assets/support-tickets-ok.yaml new file mode 100644 index 0000000..8970325 --- /dev/null +++ b/src/QAToolKit.Source.Swagger.Test/Assets/support-tickets-ok.yaml @@ -0,0 +1,807 @@ +openapi: 3.0.1 +info: + title: Helpdesk API v2 + description: | + Resource API contains methods + version: "1.0" +servers: +- url: api/support/v2 +paths: + /SupportTicket: + get: + tags: + - helpdesk + description: | + Get a list of helpdesks and their attachments + + Affected systems: DSystem + operationId: getSupportTicketsList + parameters: + - name: CaseId + in: query + description: Case id of helpdesks to be returned + required: true + schema: + type: string + format: guid + example: "4c5cfc0c-cd11-ea11-a2bd-00155d685d2c" + - name: Area + in: query + description: Area the request is related to + schema: + type: string + enum: ["Company","Company2"] + default: "Company" + example: "Company" + responses: + 200: + description: Response from helpdesks process + content: + 'application/json': + schema: + type: array + items: + $ref: '#/components/schemas/GetSupportTicketResponse' + 400: + $ref: '#/components/responses/CompanyErrorClientResponse' + 404: + $ref: '#/components/responses/CompanyErrorNotFoundResponse' + 500: + $ref: '#/components/responses/CompanyErrorServerResponse' + post: + tags: + - helpdesk + description: | + Create helpdesk + + Affected systems: DSystem + operationId: postSupportTicket + requestBody: + description: Data used to create a new helpdesk + content: + application/json: + schema: + $ref: '#/components/schemas/CreateSupportTicket' + required: true + responses: + 200: + description: helpdesk successfully created + content: + 'application/json': + schema: + type: array + items: + $ref: '#/components/schemas/CreateSupportTicketResponse' + 400: + $ref: '#/components/responses/CompanyErrorClientResponse' + 404: + $ref: '#/components/responses/CompanyErrorNotFoundResponse' + 500: + $ref: '#/components/responses/CompanyErrorServerResponse' + /SupportTicketCase: + get: + tags: + - helpdesk Case + description: | + Get a list of helpdesk cases. + + Affected systems: DSystem + operationId: getSupportTicketCasesList + parameters: + - name: IdentityId + in: query + description: Identity id of helpdesk cases to be returned + required: true + schema: + type: string + format: guid + example: "4c5cfc0c-cd11-ea11-a2bd-00155d685d2c" + - name: Area + in: query + description: Area the request is related to + schema: + type: string + enum: ["Company","Company2"] + default: "Company" + example: "Company" + responses: + 200: + description: Response from helpdesk cases process + content: + 'application/json': + schema: + type: array + items: + $ref: '#/components/schemas/GetSupportTicketCaseResponse' + 400: + $ref: '#/components/responses/CompanyErrorClientResponse' + 404: + $ref: '#/components/responses/CompanyErrorNotFoundResponse' + 500: + $ref: '#/components/responses/CompanyErrorServerResponse' + /SupportTicketCase/{CaseId}: + patch: + tags: + - helpdesk Case + operationId: patchSupportTicketCase + description: | + Patch SupportTicketCase. + + Affected systems: DSystem + parameters: + - name: CaseId + in: path + description: Case id to update + required: true + example: "cfc0c-cd11-ea11-a2bd-00155d685d2c" + schema: + type: string + format: guid + - name: Area + in: query + description: Area the request is related to + schema: + type: string + enum: ["Company","Company2"] + default: "Company" + example: "Company" + requestBody: + description: SupportTicketCase patch data + content: + application/json: + schema: + $ref: '#/components/schemas/PatchSupportTicketCase' + required: true + responses: + 200: + description: Response from helpdesk cases process + content: + 'application/json': + schema: + type: array + items: + $ref: '#/components/schemas/GetSupportTicketCaseResponse' + 400: + $ref: '#/components/responses/CompanyErrorClientResponse' + 404: + $ref: '#/components/responses/CompanyErrorNotFoundResponse' + 500: + $ref: '#/components/responses/CompanyErrorServerResponse' + /ScheduledCall: + post: + tags: + - ScheduledCall + description: | + Create scheduled call + + Affected systems: DSystem + operationId: postScheduledCall + requestBody: + description: Data used to create a new scheduled call record + content: + application/json: + schema: + $ref: '#/components/schemas/CreateScheduledCall' + required: true + responses: + 200: + description: Scheduled call record successfully created + content: + 'application/json': + schema: + type: array + items: + $ref: '#/components/responses/CreateScheduledCallResponse' + 400: + $ref: '#/components/responses/CompanyErrorClientResponse' + 404: + $ref: '#/components/responses/CompanyErrorNotFoundResponse' + 500: + $ref: '#/components/responses/CompanyErrorServerResponse' + /DirectDebitNotification: + post: + tags: + - DirectDebitNotification + description: | + Sends an email to the salda konte department with information about direct debit request + + Affected systems: + operationId: postDirectDebitNotification + requestBody: + description: Data used to send a direct debit email + content: + application/json: + schema: + $ref: '#/components/schemas/SendDiretDebitNotification' + required: true + responses: + 200: + $ref: '#/components/responses/DirectDebitNotificationResponse' + 400: + $ref: '#/components/responses/CompanyErrorClientResponse' + 404: + $ref: '#/components/responses/CompanyErrorNotFoundResponse' + 500: + $ref: '#/components/responses/CompanyErrorServerResponse' + /Contact: + post: + tags: + - Contact + description: | + Create or update a contact + + Affected systems: DSystem + operationId: postContact + requestBody: + description: Data used to create a new contact or update existing + content: + application/json: + schema: + $ref: '#/components/schemas/CreateContact' + required: true + responses: + 200: + description: Contact successfully created or updated + content: + 'application/json': + schema: + type: array + items: + $ref: '#/components/responses/CreateContactResponse' + 400: + $ref: '#/components/responses/CompanyErrorClientResponse' + 404: + $ref: '#/components/responses/CompanyErrorNotFoundResponse' + 500: + $ref: '#/components/responses/CompanyErrorServerResponse' +components: + responses: + CompanyErrorClientResponse: + description: Client error + content: + application/json: + schema: + type: object + description: Client Error + properties: + ErrorMessage: + type: string + description: Error Message + readOnly: true + example: "Agreement Id is not in correct format" + ErrorCode: + type: string + description: Error code + readOnly: true + example: "1-1001" + Identifier: + type: string + description: Identifier, internal identifier + readOnly: true + example: "ResponseHandlingPublisher | Error response | System Test Err response" + Details: + type: string + description: Error details + readOnly: true + example: "Error: Agreement Id must start with a letter A followed by 6 digits." + CompanyErrorNotFoundResponse: + description: Not found error + content: + application/json: + schema: + type: object + description: NotFound Error + properties: + ErrorMessage: + type: string + description: Error Message + readOnly: true + example: "Invalid path" + ErrorCode: + type: string + description: Error code + readOnly: true + example: "0-5" + Identifier: + type: string + description: Identifier, internal identifier + readOnly: true + example: "ResponseHandlingPublisher | Error response | System Test Err response" + Details: + type: string + description: Error details + readOnly: true + example: "Wrong path provided! This connector accepts only /Person or /Agreement" + CompanyErrorServerResponse: + description: Server error + content: + application/json: + schema: + type: object + description: Server Error + properties: + ErrorMessage: + type: string + description: Error Message + readOnly: true + example: "System not available" + ErrorCode: + type: string + description: Error code + readOnly: true + example: "0-2" + Identifier: + type: string + description: Identifier, internal identifier + readOnly: true + example: "ResponseHandlingPublisher | Error response | System Test Err response" + Details: + type: string + description: Error details + readOnly: true + example: "Error: The server was not found or was not accessible." + CreateScheduledCallResponse: + description: Scheduled call data + content: + application/json: + schema: + type: object + properties: + Success: + type: boolean + description: Endpoint response success + example: true + CaseIdOutput: + type: string + description: GUID of the case created that serves as a container for the helpdesks + example: "15E93CE6-10E1-E911-A2B7-00155D685D2C" + DirectDebitNotificationResponse: + description: Notification sent successfully + content: + application/json: + schema: + type: object + description: Data that was sent to SMTP + properties: + From: + type: string + example: "my@Agent.si" + To: + type: array + items: + type: string + example: "receivables@Agent.eu" + Cc: + type: array + items: + type: string + Subject: + type: string + example: "example" + Body: + type: string + example: "HI!" + Attachments: + type: array + items: + type: string + IsBodyHtml: + type: boolean + example: false + CreateContactResponse: + description: Contact data + content: + application/json: + schema: + type: object + properties: + Success: + type: boolean + description: Endpoint response success + example: true + ContactIdOutput: + type: string + description: GUID of the contact + example: "15E93CE6-10E1-E911-A2B7-00155D685D2C" + schemas: + GetSupportTicketResponse: + type: object + properties: + CaseId: + type: string + format: guid + description: Case id + example: "4c5cfc0c-cd11-ea11-a2bd-00155d685d2c" + Title: + type: string + description: Case title + example: "Contract | Changes" + Status: + type: string + description: Case status + example: "Solving" + IdentityId: + type: string + format: guid + description: Identity id + example: "78b6f9b7-30df-e711-80c4-00155d101f1b" + CreatedOn: + type: string + format: date + description: Datetime the case was created on + example: '2019-09-03T00:00:00.000Z' + Tickets: + type: array + items: + type: object + properties: + ParentCase: + type: string + format: guid + description: Case id this helpdesk is connected + example: "4c5cfc0c-cd11-ea11-a2bd-00155d685d2c" + Subject: + type: string + description: helpdesk subject + example: "Wrong 2019" + Message: + type: string + description: helpdesk message + example: "Call me maybe." + Direction: + type: integer + enum: [0,1] + description: Message direction:0-Inbound (Portal -> System) or 1-Outbound (System -> Portal) + example: 0 + Attachments: + type: array + items: + type: object + properties: + FileId: + type: string + format: guid + description: Attachment file id + example: "90f7cad8-dbc0-41e2-b64e-e290e064b19f" + FileUri: + type: string + format: uri + description: Attachment file uri + example: "/folder/Lorem-Ipsum.pdf" + FileName: + type: string + description: Attachment file name + example: "Lorem-Ipsum.pdf" + CreateSupportTicket: + description: Data used to create a new helpdesk + required: + - Area + - Direction + - IdentityId + - Message + - CaseType + type: object + properties: + Area: + description: Area the request is related to + type: string + enum: ["Company","Company2"] + example: "Company" + Direction: + type: integer + enum: [0, 1] + description: 0-Inbound (Portal -> System) or 1-Outbound (System -> Portal) + example: 0 + IdentityId: + type: string + description: Identity id + example: "4205FFFE-179B-E411-80C0-00155D788951" + CaseIdInput: + type: string + description: Case GUID. A new case and helpdesk is created if empty, otherwise only support ticker is created. + example: "4205FFFE-179B-E411-80C0-00155D788951" + Subject: + type: string + description: Initial helpdesk title + example: "Wrong 11111" + Message: + type: string + description: helpdesk message + example: "Error 11111." + CaseType: + type: string + description: Case type + enum: ["SupportTicket","InvoiceSettingsChange","BillingAddressChange"] + example: "SupportTicket" + ConsolidationGroupId: + type: string + description: Consolidation group id + example: "24562456245624" + ConnectionId: + type: string + description: Metering point + example: "1-6245624562456" + IBAN: + type: string + description: Mandatory when Case type is InvoiceSettingsChange + example: "SI245624562464256" + Description: + type: string + description: Mandatory when Case type is InvoiceSettingsChange + example: "Bank" + InvoiceType: + type: string + description: Mandatory when Case type is InvoiceSettingsChange + example: "PaperInvoice" + BillingAddressesChanges: + type: array + description: Mandatory when Case type is BillingAddressChange + items: + type: object + properties: + AgreementId: + type: string + example: "008" + ConnectionId: + type: string + example: "4564-4564564" + FirstName: + type: string + example: "John" + LastName: + type: string + example: "Doe" + Street: + type: string + example: "My street" + StreetNumber: + type: string + example: "21" + City: + type: string + example: "London" + PostCode: + type: string + example: "1111" + Country: + type: string + example: "UK" + Attachments: + type: array + items: + type: object + properties: + FileId: + type: string + format: guid + description: Attachment file id + example: "90f7cad8-dbc0-41e2-b64e-e290e064b19f" + FileUri: + type: string + format: uri + description: Attachment file uri + example: "/folder/Lorem-Ipsum.pdf" + FileName: + type: string + description: Attachment file name + example: "Lorem-Ipsum.pdf" + CreateSupportTicketResponse: + type: object + description: helpdesk data + properties: + Success: + type: boolean + description: Endpoint response success + example: true + CaseIdOutput: + type: string + description: GUID of the case created that serves as a container for the helpdesks + example: "15E93CE6-10E1-E911-A2B7-00155D685D2C" + GetSupportTicketCaseResponse: + type: object + properties: + CaseId: + type: string + format: guid + description: Case id + example: "4c5cfc0c-cd11-ea11-a2bd-00155d685d2c" + ConnectionId: + type: string + description: Metering point + example: 12-324523 + Title: + type: string + description: Case title + example: "Contract management | Changes" + Status: + type: string + description: Case status + example: "Suitable For Solving" + StatusCode: + type: string + description: Case status code + example: "23453245254" + HandedTo: + type: string + example: "Claim Dept" + HandedToCode: + type: string + example: "23453245235" + CreatedOn: + type: string + format: date + description: Datetime the case was created on + example: "2019-12-06T11:36:58Z" + ModifiedOn: + type: string + format: date + description: Datetime the case was modified on + example: "2019-12-06T09:40:36Z" + ModifiedBy: + type: string + description: Name of the person who modified the case + example: "Agent" + CaseType: + type: string + description: Case type + enum: ["helpdesk","Scheduled Call"] + example: helpdesk + IsRead: + type: boolean + example: false + LastSupportTicketDirection: + type: integer + enum: [0, 1] + description: 0-Inbound (Portal -> System) or 1-Outbound (System -> Portal) + example: 0 + PatchSupportTicketCase: + description: Patch SupportTicketCase data + required: + - IsRead + type: object + properties: + IsRead: + type: boolean + description: Is SupportTicketCase read + example: true + CreateScheduledCall: + description: Data used to create a new scheduled call record + required: + - Area + - Direction + - IdentityId + - Message + type: object + properties: + Area: + description: Area the request is related to + type: string + enum: ["Company","Company2"] + example: "Company" + Direction: + type: integer + enum: [0, 1] + description: 0-Inbound (Portal -> System) or 1-Outbound (System -> Portal) + example: 0 + IdentityId: + type: string + description: Identity id + example: "4205FFFE-179B-E411-80C0-00155D788951" + CaseIdInput: + type: string + description: Case id + example: "4205FFFE-179B-E411-80C0-00155D788951" + Message: + type: string + description: Scheduled call message + example: "Error 1111." + PhoneNumber: + type: string + example: "999 999 999" + CallDateTime: + type: string + format: date-time + example: "2019-12-18T04:00:00.000Z" + ConnectionId: + type: string + description: Metering point + example: 1-1345145 + ConsolidationGroupId: + type: string + description: Consolidation group id + example: "2345135345134" + Attachments: + type: array + items: + type: object + properties: + FileId: + type: string + format: guid + description: Attachment file id + example: "90f7cad8-dbc0-41e2-b64e-e290e064b19f" + FileUri: + type: string + format: uri + description: Attachment file uri + example: "/folder/Lorem-Ipsum.pdf" + FileName: + type: string + description: Attachment file name + example: "Lorem-Ipsum.pdf" + SendDiretDebitNotification: + type: object + description: helpdesk data + required: + - Subject + - Body + properties: + Subject: + type: string + description: Email subject + example: "dfg" + Body: + type: string + description: Email body + example: "Hi" + IsBodyHtml: + type: boolean + default: false + description: Is body in html format + example: false + CreateContact: + description: Data used to create a new contact or update existing + required: + - Area + - FirstName + - LastName + - Email + type: object + properties: + Area: + description: Area the request is related to + type: string + enum: ["Company","Company2"] + example: "Company" + IdentityId: + type: string + format: guid + description: null when creating a new contact, otherwise existing identity id + example: "B9CD737F-BA3E-EA11-A2C2-00155D685D2C" + StatusCode: + type: integer + description: Status code + example: 1 + FirstName: + type: string + description: First name + example: "John" + LastName: + type: string + description: Last name + example: "Doe" + Email: + type: string + example: "john.doe@Agent.si" + TelephoneNumber: + type: string + example: "356735673567" + MobileNumber: + type: string + example: "356735863583" + Address: + type: string + description: Address + example: "My street 1" + PostName: + type: string + description: Post name + example: "London" + PostNumber: + type: string + description: Post number + example: "1111" + Country: + type: string + description: Country + example: "UK" \ No newline at end of file diff --git a/src/QAToolKit.Source.Swagger.Test/Assets/swagger-pets-test-unsuppoted-v1.0.json b/src/QAToolKit.Source.Swagger.Test/Assets/swagger-pets-test-unsuppoted-v1.0.json new file mode 100644 index 0000000..6b74fa2 --- /dev/null +++ b/src/QAToolKit.Source.Swagger.Test/Assets/swagger-pets-test-unsuppoted-v1.0.json @@ -0,0 +1,1225 @@ +{ + "openapi": "1.0.0", + "info": { + "title": "Swagger Petstore - OpenAPI 3.0", + "description": "This is a sample Pet Store Server based on the OpenAPI 3.0 specification. You can find out more about\nSwagger at [http://swagger.io](http://swagger.io). In the third iteration of the pet store, we've switched to the design first approach!\nYou can now help us improve the API whether it's by making changes to the definition itself or to the code.\nThat way, with time, we can improve the API in general, and expose some of the new features in OAS3.\n\nSome useful links:\n- [The Pet Store repository](https://github.com/swagger-api/swagger-petstore)\n- [The source API definition for the Pet Store](https://github.com/swagger-api/swagger-petstore/blob/master/src/main/resources/openapi.yaml)", + "termsOfService": "http://swagger.io/terms/", + "contact": { + "email": "apiteam@swagger.io" + }, + "license": { + "name": "Apache 2.0", + "url": "http://www.apache.org/licenses/LICENSE-2.0.html" + }, + "version": "1.0.5" + }, + "externalDocs": { + "description": "Find out more about Swagger", + "url": "http://swagger.io" + }, + "servers": [ + { + "url": "/api/v3" + } + ], + "tags": [ + { + "name": "pet", + "description": "Everything about your Pets", + "externalDocs": { + "description": "Find out more", + "url": "http://swagger.io" + } + }, + { + "name": "store", + "description": "Operations about user" + }, + { + "name": "user", + "description": "Access to Petstore orders", + "externalDocs": { + "description": "Find out more about our store", + "url": "http://swagger.io" + } + } + ], + "paths": { + "/pet": { + "put": { + "tags": [ + "pet" + ], + "summary": "Update an existing pet", + "description": "Update an existing pet by Id", + "operationId": "updatePet", + "requestBody": { + "description": "Update an existent pet in the store", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + }, + "application/xml": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + }, + "application/x-www-form-urlencoded": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "Successful operation", + "content": { + "application/xml": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + }, + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + } + } + }, + "400": { + "description": "Invalid ID supplied" + }, + "404": { + "description": "Pet not found" + }, + "405": { + "description": "Validation exception" + } + }, + "security": [ + { + "petstore_auth": [ + "write:pets", + "read:pets" + ] + } + ] + }, + "post": { + "tags": [ + "pet" + ], + "summary": "Add a new pet to the store", + "description": "Add a new pet to the store", + "operationId": "addPet", + "requestBody": { + "description": "Create a new pet in the store", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + }, + "application/xml": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + }, + "application/x-www-form-urlencoded": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "Successful operation", + "content": { + "application/xml": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + }, + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + } + } + }, + "405": { + "description": "Invalid input" + } + }, + "security": [ + { + "petstore_auth": [ + "write:pets", + "read:pets" + ] + } + ] + } + }, + "/pet/findByStatus": { + "get": { + "tags": [ + "pet" + ], + "summary": "Finds Pets by status", + "description": "Multiple status values can be provided with comma separated strings", + "operationId": "findPetsByStatus", + "parameters": [ + { + "name": "status", + "in": "query", + "description": "Status values that need to be considered for filter", + "required": false, + "explode": true, + "schema": { + "type": "string", + "default": "available", + "enum": [ + "available", + "pending", + "sold" + ] + } + } + ], + "responses": { + "200": { + "description": "successful operation", + "content": { + "application/xml": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Pet" + } + } + }, + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Pet" + } + } + } + } + }, + "400": { + "description": "Invalid status value" + } + }, + "security": [ + { + "petstore_auth": [ + "write:pets", + "read:pets" + ] + } + ] + } + }, + "/pet/findByTags": { + "get": { + "tags": [ + "pet" + ], + "summary": "Finds Pets by tags", + "description": "Multiple tags can be provided with comma separated strings. Use tag1, tag2, tag3 for testing.", + "operationId": "findPetsByTags", + "parameters": [ + { + "name": "tags", + "in": "query", + "description": "Tags to filter by", + "required": false, + "explode": true, + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + } + ], + "responses": { + "200": { + "description": "successful operation", + "content": { + "application/xml": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Pet" + } + } + }, + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Pet" + } + } + } + } + }, + "400": { + "description": "Invalid tag value" + } + }, + "security": [ + { + "petstore_auth": [ + "write:pets", + "read:pets" + ] + } + ] + } + }, + "/pet/{petId}": { + "get": { + "tags": [ + "pet" + ], + "summary": "Find pet by ID", + "description": "Returns a single pet", + "operationId": "getPetById", + "parameters": [ + { + "name": "petId", + "in": "path", + "description": "ID of pet to return", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + ], + "responses": { + "200": { + "description": "successful operation", + "content": { + "application/xml": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + }, + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + } + } + }, + "400": { + "description": "Invalid ID supplied" + }, + "404": { + "description": "Pet not found" + } + }, + "security": [ + { + "api_key": [] + }, + { + "petstore_auth": [ + "write:pets", + "read:pets" + ] + } + ] + }, + "post": { + "tags": [ + "pet" + ], + "summary": "Updates a pet in the store with form data", + "description": "", + "operationId": "updatePetWithForm", + "parameters": [ + { + "name": "petId", + "in": "path", + "description": "ID of pet that needs to be updated", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + }, + { + "name": "name", + "in": "query", + "description": "Name of pet that needs to be updated", + "schema": { + "type": "string" + } + }, + { + "name": "status", + "in": "query", + "description": "Status of pet that needs to be updated", + "schema": { + "type": "string" + } + } + ], + "responses": { + "405": { + "description": "Invalid input" + } + }, + "security": [ + { + "petstore_auth": [ + "write:pets", + "read:pets" + ] + } + ] + }, + "delete": { + "tags": [ + "pet" + ], + "summary": "Deletes a pet", + "description": "", + "operationId": "deletePet", + "parameters": [ + { + "name": "api_key", + "in": "header", + "description": "", + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "petId", + "in": "path", + "description": "Pet id to delete", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + ], + "responses": { + "400": { + "description": "Invalid pet value" + } + }, + "security": [ + { + "petstore_auth": [ + "write:pets", + "read:pets" + ] + } + ] + } + }, + "/pet/{petId}/uploadImage": { + "post": { + "tags": [ + "pet" + ], + "summary": "uploads an image", + "description": "", + "operationId": "uploadFile", + "parameters": [ + { + "name": "petId", + "in": "path", + "description": "ID of pet to update", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + }, + { + "name": "additionalMetadata", + "in": "query", + "description": "Additional Metadata", + "required": false, + "schema": { + "type": "string" + } + } + ], + "requestBody": { + "content": { + "application/octet-stream": { + "schema": { + "type": "string", + "format": "binary" + } + } + } + }, + "responses": { + "200": { + "description": "successful operation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ApiResponse" + } + } + } + } + }, + "security": [ + { + "petstore_auth": [ + "write:pets", + "read:pets" + ] + } + ] + } + }, + "/store/inventory": { + "get": { + "tags": [ + "store" + ], + "summary": "Returns pet inventories by status", + "description": "Returns a map of status codes to quantities", + "operationId": "getInventory", + "responses": { + "200": { + "description": "successful operation", + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": { + "type": "integer", + "format": "int32" + } + } + } + } + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/store/order": { + "post": { + "tags": [ + "store" + ], + "summary": "Place an order for a pet", + "description": "Place a new order in the store", + "operationId": "placeOrder", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Order" + } + }, + "application/xml": { + "schema": { + "$ref": "#/components/schemas/Order" + } + }, + "application/x-www-form-urlencoded": { + "schema": { + "$ref": "#/components/schemas/Order" + } + } + } + }, + "responses": { + "200": { + "description": "successful operation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Order" + } + } + } + }, + "405": { + "description": "Invalid input" + } + } + } + }, + "/store/order/{orderId}": { + "get": { + "tags": [ + "store" + ], + "summary": "Find purchase order by ID", + "description": "For valid response try integer IDs with value <= 5 or > 10. Other values will generated exceptions", + "operationId": "getOrderById", + "parameters": [ + { + "name": "orderId", + "in": "path", + "description": "ID of order that needs to be fetched", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + ], + "responses": { + "200": { + "description": "successful operation", + "content": { + "application/xml": { + "schema": { + "$ref": "#/components/schemas/Order" + } + }, + "application/json": { + "schema": { + "$ref": "#/components/schemas/Order" + } + } + } + }, + "400": { + "description": "Invalid ID supplied" + }, + "404": { + "description": "Order not found" + } + } + }, + "delete": { + "tags": [ + "store" + ], + "summary": "Delete purchase order by ID", + "description": "For valid response try integer IDs with value < 1000. Anything above 1000 or nonintegers will generate API errors", + "operationId": "deleteOrder", + "parameters": [ + { + "name": "orderId", + "in": "path", + "description": "ID of the order that needs to be deleted", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + ], + "responses": { + "400": { + "description": "Invalid ID supplied" + }, + "404": { + "description": "Order not found" + } + } + } + }, + "/user": { + "post": { + "tags": [ + "user" + ], + "summary": "Create user", + "description": "This can only be done by the logged in user.", + "operationId": "createUser", + "requestBody": { + "description": "Created user object", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/User" + } + }, + "application/xml": { + "schema": { + "$ref": "#/components/schemas/User" + } + }, + "application/x-www-form-urlencoded": { + "schema": { + "$ref": "#/components/schemas/User" + } + } + } + }, + "responses": { + "default": { + "description": "successful operation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/User" + } + }, + "application/xml": { + "schema": { + "$ref": "#/components/schemas/User" + } + } + } + } + } + } + }, + "/user/createWithList": { + "post": { + "tags": [ + "user" + ], + "summary": "Creates list of users with given input array", + "description": "Creates list of users with given input array", + "operationId": "createUsersWithListInput", + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/User" + } + } + } + } + }, + "responses": { + "200": { + "description": "Successful operation", + "content": { + "application/xml": { + "schema": { + "$ref": "#/components/schemas/User" + } + }, + "application/json": { + "schema": { + "$ref": "#/components/schemas/User" + } + } + } + }, + "default": { + "description": "successful operation" + } + } + } + }, + "/user/login": { + "get": { + "tags": [ + "user" + ], + "summary": "Logs user into the system", + "description": "", + "operationId": "loginUser", + "parameters": [ + { + "name": "username", + "in": "query", + "description": "The user name for login", + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "password", + "in": "query", + "description": "The password for login in clear text", + "required": false, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "successful operation", + "headers": { + "X-Rate-Limit": { + "description": "calls per hour allowed by the user", + "schema": { + "type": "integer", + "format": "int32" + } + }, + "X-Expires-After": { + "description": "date in UTC when toekn expires", + "schema": { + "type": "string", + "format": "date-time" + } + } + }, + "content": { + "application/xml": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "Invalid username/password supplied" + } + } + } + }, + "/user/logout": { + "get": { + "tags": [ + "user" + ], + "summary": "Logs out current logged in user session", + "description": "", + "operationId": "logoutUser", + "parameters": [], + "responses": { + "default": { + "description": "successful operation" + } + } + } + }, + "/user/{username}": { + "get": { + "tags": [ + "user" + ], + "summary": "Get user by user name", + "description": "", + "operationId": "getUserByName", + "parameters": [ + { + "name": "username", + "in": "path", + "description": "The name that needs to be fetched. Use user1 for testing. ", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "successful operation", + "content": { + "application/xml": { + "schema": { + "$ref": "#/components/schemas/User" + } + }, + "application/json": { + "schema": { + "$ref": "#/components/schemas/User" + } + } + } + }, + "400": { + "description": "Invalid username supplied" + }, + "404": { + "description": "User not found" + } + } + }, + "put": { + "tags": [ + "user" + ], + "summary": "Update user", + "description": "This can only be done by the logged in user.", + "operationId": "updateUser", + "parameters": [ + { + "name": "username", + "in": "path", + "description": "name that need to be deleted", + "required": true, + "schema": { + "type": "string" + } + } + ], + "requestBody": { + "description": "Update an existent user in the store", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/User" + } + }, + "application/xml": { + "schema": { + "$ref": "#/components/schemas/User" + } + }, + "application/x-www-form-urlencoded": { + "schema": { + "$ref": "#/components/schemas/User" + } + } + } + }, + "responses": { + "default": { + "description": "successful operation" + } + } + }, + "delete": { + "tags": [ + "user" + ], + "summary": "Delete user", + "description": "This can only be done by the logged in user.", + "operationId": "deleteUser", + "parameters": [ + { + "name": "username", + "in": "path", + "description": "The name that needs to be deleted", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "400": { + "description": "Invalid username supplied" + }, + "404": { + "description": "User not found" + } + } + } + } + }, + "components": { + "schemas": { + "Order": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "format": "int64", + "example": 10 + }, + "petId": { + "type": "integer", + "format": "int64", + "example": 198772 + }, + "quantity": { + "type": "integer", + "format": "int32", + "example": 7 + }, + "shipDate": { + "type": "string", + "format": "date-time" + }, + "status": { + "type": "string", + "description": "Order Status", + "example": "approved", + "enum": [ + "placed", + "approved", + "delivered" + ] + }, + "complete": { + "type": "boolean" + } + }, + "xml": { + "name": "order" + } + }, + "Customer": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "format": "int64", + "example": 100000 + }, + "username": { + "type": "string", + "example": "fehguy" + }, + "address": { + "type": "array", + "xml": { + "name": "addresses", + "wrapped": true + }, + "items": { + "$ref": "#/components/schemas/Address" + } + } + }, + "xml": { + "name": "customer" + } + }, + "Address": { + "type": "object", + "properties": { + "street": { + "type": "string", + "example": "437 Lytton" + }, + "city": { + "type": "string", + "example": "Palo Alto" + }, + "state": { + "type": "string", + "example": "CA" + }, + "zip": { + "type": "string", + "example": "94301" + } + }, + "xml": { + "name": "address" + } + }, + "Category": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "format": "int64", + "example": 1 + }, + "name": { + "type": "string", + "example": "Dogs" + } + }, + "xml": { + "name": "category" + } + }, + "User": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "format": "int64", + "example": 10 + }, + "username": { + "type": "string", + "example": "theUser" + }, + "firstName": { + "type": "string", + "example": "John" + }, + "lastName": { + "type": "string", + "example": "James" + }, + "email": { + "type": "string", + "example": "john@email.com" + }, + "password": { + "type": "string", + "example": "12345" + }, + "phone": { + "type": "string", + "example": "12345" + }, + "userStatus": { + "type": "integer", + "description": "User Status", + "format": "int32", + "example": 1 + } + }, + "xml": { + "name": "user" + } + }, + "Tag": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "format": "int64" + }, + "name": { + "type": "string" + } + }, + "xml": { + "name": "tag" + } + }, + "Pet": { + "required": [ + "name", + "photoUrls" + ], + "type": "object", + "properties": { + "id": { + "type": "integer", + "format": "int64", + "example": 10 + }, + "name": { + "type": "string", + "example": "doggie" + }, + "category": { + "$ref": "#/components/schemas/Category" + }, + "photoUrls": { + "type": "array", + "xml": { + "wrapped": true + }, + "items": { + "type": "string", + "xml": { + "name": "photoUrl" + } + } + }, + "tags": { + "type": "array", + "xml": { + "wrapped": true + }, + "items": { + "$ref": "#/components/schemas/Tag" + } + }, + "status": { + "type": "string", + "description": "pet status in the store", + "enum": [ + "available", + "pending", + "sold" + ] + } + }, + "xml": { + "name": "pet" + } + }, + "ApiResponse": { + "type": "object", + "properties": { + "code": { + "type": "integer", + "format": "int32" + }, + "type": { + "type": "string" + }, + "message": { + "type": "string" + } + }, + "xml": { + "name": "##default" + } + } + }, + "requestBodies": { + "Pet": { + "description": "Pet object that needs to be added to the store", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + }, + "application/xml": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + } + } + }, + "UserArray": { + "description": "List of user object", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/User" + } + } + } + } + } + }, + "securitySchemes": { + "petstore_auth": { + "type": "oauth2", + "flows": { + "implicit": { + "authorizationUrl": "https://petstore3.swagger.io/oauth/authorize", + "scopes": { + "write:pets": "modify pets in your account", + "read:pets": "read your pets" + } + } + } + }, + "api_key": { + "type": "apiKey", + "name": "api_key", + "in": "header" + } + } + } +} \ No newline at end of file diff --git a/src/QAToolKit.Source.Swagger.Test/Assets/swagger-pets-test-unsuppoted-v3.1.json b/src/QAToolKit.Source.Swagger.Test/Assets/swagger-pets-test-unsuppoted-v3.1.json new file mode 100644 index 0000000..25b86c8 --- /dev/null +++ b/src/QAToolKit.Source.Swagger.Test/Assets/swagger-pets-test-unsuppoted-v3.1.json @@ -0,0 +1,1225 @@ +{ + "openapi": "3.1.0", + "info": { + "title": "Swagger Petstore - OpenAPI 3.0", + "description": "This is a sample Pet Store Server based on the OpenAPI 3.0 specification. You can find out more about\nSwagger at [http://swagger.io](http://swagger.io). In the third iteration of the pet store, we've switched to the design first approach!\nYou can now help us improve the API whether it's by making changes to the definition itself or to the code.\nThat way, with time, we can improve the API in general, and expose some of the new features in OAS3.\n\nSome useful links:\n- [The Pet Store repository](https://github.com/swagger-api/swagger-petstore)\n- [The source API definition for the Pet Store](https://github.com/swagger-api/swagger-petstore/blob/master/src/main/resources/openapi.yaml)", + "termsOfService": "http://swagger.io/terms/", + "contact": { + "email": "apiteam@swagger.io" + }, + "license": { + "name": "Apache 2.0", + "url": "http://www.apache.org/licenses/LICENSE-2.0.html" + }, + "version": "1.0.5" + }, + "externalDocs": { + "description": "Find out more about Swagger", + "url": "http://swagger.io" + }, + "servers": [ + { + "url": "/api/v3" + } + ], + "tags": [ + { + "name": "pet", + "description": "Everything about your Pets", + "externalDocs": { + "description": "Find out more", + "url": "http://swagger.io" + } + }, + { + "name": "store", + "description": "Operations about user" + }, + { + "name": "user", + "description": "Access to Petstore orders", + "externalDocs": { + "description": "Find out more about our store", + "url": "http://swagger.io" + } + } + ], + "paths": { + "/pet": { + "put": { + "tags": [ + "pet" + ], + "summary": "Update an existing pet", + "description": "Update an existing pet by Id", + "operationId": "updatePet", + "requestBody": { + "description": "Update an existent pet in the store", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + }, + "application/xml": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + }, + "application/x-www-form-urlencoded": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "Successful operation", + "content": { + "application/xml": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + }, + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + } + } + }, + "400": { + "description": "Invalid ID supplied" + }, + "404": { + "description": "Pet not found" + }, + "405": { + "description": "Validation exception" + } + }, + "security": [ + { + "petstore_auth": [ + "write:pets", + "read:pets" + ] + } + ] + }, + "post": { + "tags": [ + "pet" + ], + "summary": "Add a new pet to the store", + "description": "Add a new pet to the store", + "operationId": "addPet", + "requestBody": { + "description": "Create a new pet in the store", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + }, + "application/xml": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + }, + "application/x-www-form-urlencoded": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "Successful operation", + "content": { + "application/xml": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + }, + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + } + } + }, + "405": { + "description": "Invalid input" + } + }, + "security": [ + { + "petstore_auth": [ + "write:pets", + "read:pets" + ] + } + ] + } + }, + "/pet/findByStatus": { + "get": { + "tags": [ + "pet" + ], + "summary": "Finds Pets by status", + "description": "Multiple status values can be provided with comma separated strings", + "operationId": "findPetsByStatus", + "parameters": [ + { + "name": "status", + "in": "query", + "description": "Status values that need to be considered for filter", + "required": false, + "explode": true, + "schema": { + "type": "string", + "default": "available", + "enum": [ + "available", + "pending", + "sold" + ] + } + } + ], + "responses": { + "200": { + "description": "successful operation", + "content": { + "application/xml": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Pet" + } + } + }, + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Pet" + } + } + } + } + }, + "400": { + "description": "Invalid status value" + } + }, + "security": [ + { + "petstore_auth": [ + "write:pets", + "read:pets" + ] + } + ] + } + }, + "/pet/findByTags": { + "get": { + "tags": [ + "pet" + ], + "summary": "Finds Pets by tags", + "description": "Multiple tags can be provided with comma separated strings. Use tag1, tag2, tag3 for testing.", + "operationId": "findPetsByTags", + "parameters": [ + { + "name": "tags", + "in": "query", + "description": "Tags to filter by", + "required": false, + "explode": true, + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + } + ], + "responses": { + "200": { + "description": "successful operation", + "content": { + "application/xml": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Pet" + } + } + }, + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Pet" + } + } + } + } + }, + "400": { + "description": "Invalid tag value" + } + }, + "security": [ + { + "petstore_auth": [ + "write:pets", + "read:pets" + ] + } + ] + } + }, + "/pet/{petId}": { + "get": { + "tags": [ + "pet" + ], + "summary": "Find pet by ID", + "description": "Returns a single pet", + "operationId": "getPetById", + "parameters": [ + { + "name": "petId", + "in": "path", + "description": "ID of pet to return", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + ], + "responses": { + "200": { + "description": "successful operation", + "content": { + "application/xml": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + }, + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + } + } + }, + "400": { + "description": "Invalid ID supplied" + }, + "404": { + "description": "Pet not found" + } + }, + "security": [ + { + "api_key": [] + }, + { + "petstore_auth": [ + "write:pets", + "read:pets" + ] + } + ] + }, + "post": { + "tags": [ + "pet" + ], + "summary": "Updates a pet in the store with form data", + "description": "", + "operationId": "updatePetWithForm", + "parameters": [ + { + "name": "petId", + "in": "path", + "description": "ID of pet that needs to be updated", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + }, + { + "name": "name", + "in": "query", + "description": "Name of pet that needs to be updated", + "schema": { + "type": "string" + } + }, + { + "name": "status", + "in": "query", + "description": "Status of pet that needs to be updated", + "schema": { + "type": "string" + } + } + ], + "responses": { + "405": { + "description": "Invalid input" + } + }, + "security": [ + { + "petstore_auth": [ + "write:pets", + "read:pets" + ] + } + ] + }, + "delete": { + "tags": [ + "pet" + ], + "summary": "Deletes a pet", + "description": "", + "operationId": "deletePet", + "parameters": [ + { + "name": "api_key", + "in": "header", + "description": "", + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "petId", + "in": "path", + "description": "Pet id to delete", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + ], + "responses": { + "400": { + "description": "Invalid pet value" + } + }, + "security": [ + { + "petstore_auth": [ + "write:pets", + "read:pets" + ] + } + ] + } + }, + "/pet/{petId}/uploadImage": { + "post": { + "tags": [ + "pet" + ], + "summary": "uploads an image", + "description": "", + "operationId": "uploadFile", + "parameters": [ + { + "name": "petId", + "in": "path", + "description": "ID of pet to update", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + }, + { + "name": "additionalMetadata", + "in": "query", + "description": "Additional Metadata", + "required": false, + "schema": { + "type": "string" + } + } + ], + "requestBody": { + "content": { + "application/octet-stream": { + "schema": { + "type": "string", + "format": "binary" + } + } + } + }, + "responses": { + "200": { + "description": "successful operation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ApiResponse" + } + } + } + } + }, + "security": [ + { + "petstore_auth": [ + "write:pets", + "read:pets" + ] + } + ] + } + }, + "/store/inventory": { + "get": { + "tags": [ + "store" + ], + "summary": "Returns pet inventories by status", + "description": "Returns a map of status codes to quantities", + "operationId": "getInventory", + "responses": { + "200": { + "description": "successful operation", + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": { + "type": "integer", + "format": "int32" + } + } + } + } + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/store/order": { + "post": { + "tags": [ + "store" + ], + "summary": "Place an order for a pet", + "description": "Place a new order in the store", + "operationId": "placeOrder", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Order" + } + }, + "application/xml": { + "schema": { + "$ref": "#/components/schemas/Order" + } + }, + "application/x-www-form-urlencoded": { + "schema": { + "$ref": "#/components/schemas/Order" + } + } + } + }, + "responses": { + "200": { + "description": "successful operation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Order" + } + } + } + }, + "405": { + "description": "Invalid input" + } + } + } + }, + "/store/order/{orderId}": { + "get": { + "tags": [ + "store" + ], + "summary": "Find purchase order by ID", + "description": "For valid response try integer IDs with value <= 5 or > 10. Other values will generated exceptions", + "operationId": "getOrderById", + "parameters": [ + { + "name": "orderId", + "in": "path", + "description": "ID of order that needs to be fetched", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + ], + "responses": { + "200": { + "description": "successful operation", + "content": { + "application/xml": { + "schema": { + "$ref": "#/components/schemas/Order" + } + }, + "application/json": { + "schema": { + "$ref": "#/components/schemas/Order" + } + } + } + }, + "400": { + "description": "Invalid ID supplied" + }, + "404": { + "description": "Order not found" + } + } + }, + "delete": { + "tags": [ + "store" + ], + "summary": "Delete purchase order by ID", + "description": "For valid response try integer IDs with value < 1000. Anything above 1000 or nonintegers will generate API errors", + "operationId": "deleteOrder", + "parameters": [ + { + "name": "orderId", + "in": "path", + "description": "ID of the order that needs to be deleted", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + ], + "responses": { + "400": { + "description": "Invalid ID supplied" + }, + "404": { + "description": "Order not found" + } + } + } + }, + "/user": { + "post": { + "tags": [ + "user" + ], + "summary": "Create user", + "description": "This can only be done by the logged in user.", + "operationId": "createUser", + "requestBody": { + "description": "Created user object", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/User" + } + }, + "application/xml": { + "schema": { + "$ref": "#/components/schemas/User" + } + }, + "application/x-www-form-urlencoded": { + "schema": { + "$ref": "#/components/schemas/User" + } + } + } + }, + "responses": { + "default": { + "description": "successful operation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/User" + } + }, + "application/xml": { + "schema": { + "$ref": "#/components/schemas/User" + } + } + } + } + } + } + }, + "/user/createWithList": { + "post": { + "tags": [ + "user" + ], + "summary": "Creates list of users with given input array", + "description": "Creates list of users with given input array", + "operationId": "createUsersWithListInput", + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/User" + } + } + } + } + }, + "responses": { + "200": { + "description": "Successful operation", + "content": { + "application/xml": { + "schema": { + "$ref": "#/components/schemas/User" + } + }, + "application/json": { + "schema": { + "$ref": "#/components/schemas/User" + } + } + } + }, + "default": { + "description": "successful operation" + } + } + } + }, + "/user/login": { + "get": { + "tags": [ + "user" + ], + "summary": "Logs user into the system", + "description": "", + "operationId": "loginUser", + "parameters": [ + { + "name": "username", + "in": "query", + "description": "The user name for login", + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "password", + "in": "query", + "description": "The password for login in clear text", + "required": false, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "successful operation", + "headers": { + "X-Rate-Limit": { + "description": "calls per hour allowed by the user", + "schema": { + "type": "integer", + "format": "int32" + } + }, + "X-Expires-After": { + "description": "date in UTC when toekn expires", + "schema": { + "type": "string", + "format": "date-time" + } + } + }, + "content": { + "application/xml": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "Invalid username/password supplied" + } + } + } + }, + "/user/logout": { + "get": { + "tags": [ + "user" + ], + "summary": "Logs out current logged in user session", + "description": "", + "operationId": "logoutUser", + "parameters": [], + "responses": { + "default": { + "description": "successful operation" + } + } + } + }, + "/user/{username}": { + "get": { + "tags": [ + "user" + ], + "summary": "Get user by user name", + "description": "", + "operationId": "getUserByName", + "parameters": [ + { + "name": "username", + "in": "path", + "description": "The name that needs to be fetched. Use user1 for testing. ", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "successful operation", + "content": { + "application/xml": { + "schema": { + "$ref": "#/components/schemas/User" + } + }, + "application/json": { + "schema": { + "$ref": "#/components/schemas/User" + } + } + } + }, + "400": { + "description": "Invalid username supplied" + }, + "404": { + "description": "User not found" + } + } + }, + "put": { + "tags": [ + "user" + ], + "summary": "Update user", + "description": "This can only be done by the logged in user.", + "operationId": "updateUser", + "parameters": [ + { + "name": "username", + "in": "path", + "description": "name that need to be deleted", + "required": true, + "schema": { + "type": "string" + } + } + ], + "requestBody": { + "description": "Update an existent user in the store", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/User" + } + }, + "application/xml": { + "schema": { + "$ref": "#/components/schemas/User" + } + }, + "application/x-www-form-urlencoded": { + "schema": { + "$ref": "#/components/schemas/User" + } + } + } + }, + "responses": { + "default": { + "description": "successful operation" + } + } + }, + "delete": { + "tags": [ + "user" + ], + "summary": "Delete user", + "description": "This can only be done by the logged in user.", + "operationId": "deleteUser", + "parameters": [ + { + "name": "username", + "in": "path", + "description": "The name that needs to be deleted", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "400": { + "description": "Invalid username supplied" + }, + "404": { + "description": "User not found" + } + } + } + } + }, + "components": { + "schemas": { + "Order": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "format": "int64", + "example": 10 + }, + "petId": { + "type": "integer", + "format": "int64", + "example": 198772 + }, + "quantity": { + "type": "integer", + "format": "int32", + "example": 7 + }, + "shipDate": { + "type": "string", + "format": "date-time" + }, + "status": { + "type": "string", + "description": "Order Status", + "example": "approved", + "enum": [ + "placed", + "approved", + "delivered" + ] + }, + "complete": { + "type": "boolean" + } + }, + "xml": { + "name": "order" + } + }, + "Customer": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "format": "int64", + "example": 100000 + }, + "username": { + "type": "string", + "example": "fehguy" + }, + "address": { + "type": "array", + "xml": { + "name": "addresses", + "wrapped": true + }, + "items": { + "$ref": "#/components/schemas/Address" + } + } + }, + "xml": { + "name": "customer" + } + }, + "Address": { + "type": "object", + "properties": { + "street": { + "type": "string", + "example": "437 Lytton" + }, + "city": { + "type": "string", + "example": "Palo Alto" + }, + "state": { + "type": "string", + "example": "CA" + }, + "zip": { + "type": "string", + "example": "94301" + } + }, + "xml": { + "name": "address" + } + }, + "Category": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "format": "int64", + "example": 1 + }, + "name": { + "type": "string", + "example": "Dogs" + } + }, + "xml": { + "name": "category" + } + }, + "User": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "format": "int64", + "example": 10 + }, + "username": { + "type": "string", + "example": "theUser" + }, + "firstName": { + "type": "string", + "example": "John" + }, + "lastName": { + "type": "string", + "example": "James" + }, + "email": { + "type": "string", + "example": "john@email.com" + }, + "password": { + "type": "string", + "example": "12345" + }, + "phone": { + "type": "string", + "example": "12345" + }, + "userStatus": { + "type": "integer", + "description": "User Status", + "format": "int32", + "example": 1 + } + }, + "xml": { + "name": "user" + } + }, + "Tag": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "format": "int64" + }, + "name": { + "type": "string" + } + }, + "xml": { + "name": "tag" + } + }, + "Pet": { + "required": [ + "name", + "photoUrls" + ], + "type": "object", + "properties": { + "id": { + "type": "integer", + "format": "int64", + "example": 10 + }, + "name": { + "type": "string", + "example": "doggie" + }, + "category": { + "$ref": "#/components/schemas/Category" + }, + "photoUrls": { + "type": "array", + "xml": { + "wrapped": true + }, + "items": { + "type": "string", + "xml": { + "name": "photoUrl" + } + } + }, + "tags": { + "type": "array", + "xml": { + "wrapped": true + }, + "items": { + "$ref": "#/components/schemas/Tag" + } + }, + "status": { + "type": "string", + "description": "pet status in the store", + "enum": [ + "available", + "pending", + "sold" + ] + } + }, + "xml": { + "name": "pet" + } + }, + "ApiResponse": { + "type": "object", + "properties": { + "code": { + "type": "integer", + "format": "int32" + }, + "type": { + "type": "string" + }, + "message": { + "type": "string" + } + }, + "xml": { + "name": "##default" + } + } + }, + "requestBodies": { + "Pet": { + "description": "Pet object that needs to be added to the store", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + }, + "application/xml": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + } + } + }, + "UserArray": { + "description": "List of user object", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/User" + } + } + } + } + } + }, + "securitySchemes": { + "petstore_auth": { + "type": "oauth2", + "flows": { + "implicit": { + "authorizationUrl": "https://petstore3.swagger.io/oauth/authorize", + "scopes": { + "write:pets": "modify pets in your account", + "read:pets": "read your pets" + } + } + } + }, + "api_key": { + "type": "apiKey", + "name": "api_key", + "in": "header" + } + } + } +} \ No newline at end of file diff --git a/src/QAToolKit.Source.Swagger.Test/Exceptions/InvalidSwaggerExceptionTests.cs b/src/QAToolKit.Source.Swagger.Test/Exceptions/InvalidSwaggerExceptionTests.cs new file mode 100644 index 0000000..73e2950 --- /dev/null +++ b/src/QAToolKit.Source.Swagger.Test/Exceptions/InvalidSwaggerExceptionTests.cs @@ -0,0 +1,27 @@ +using System; +using QAToolKit.Source.Swagger.Exceptions; +using Xunit; + +namespace QAToolKit.Source.Swagger.Test.Exceptions +{ + public class InvalidSwaggerExceptionTests + { + [Fact] + public void CreateExceptionTest_Successful() + { + var exception = new InvalidSwaggerException("my error"); + + Assert.Equal("my error", exception.Message); + } + + [Fact] + public void CreateExceptionWithInnerExceptionTest_Successful() + { + var innerException = new Exception("Inner"); + var exception = new InvalidSwaggerException("my error", innerException); + + Assert.Equal("my error", exception.Message); + Assert.Equal("Inner", innerException.Message); + } + } +} \ No newline at end of file diff --git a/src/QAToolKit.Source.Swagger.Test/Exceptions/UnsupportedSwaggerExceptionTests.cs b/src/QAToolKit.Source.Swagger.Test/Exceptions/UnsupportedSwaggerExceptionTests.cs new file mode 100644 index 0000000..a9fe080 --- /dev/null +++ b/src/QAToolKit.Source.Swagger.Test/Exceptions/UnsupportedSwaggerExceptionTests.cs @@ -0,0 +1,27 @@ +using System; +using QAToolKit.Source.Swagger.Exceptions; +using Xunit; + +namespace QAToolKit.Source.Swagger.Test.Exceptions +{ + public class UnsupportedSwaggerExceptionTests + { + [Fact] + public void CreateExceptionTest_Successful() + { + var exception = new UnsupportedSwaggerException("my error"); + + Assert.Equal("my error", exception.Message); + } + + [Fact] + public void CreateExceptionWithInnerExceptionTest_Successful() + { + var innerException = new Exception("Inner"); + var exception = new UnsupportedSwaggerException("my error", innerException); + + Assert.Equal("my error", exception.Message); + Assert.Equal("Inner", innerException.Message); + } + } +} \ No newline at end of file diff --git a/src/QAToolKit.Source.Swagger.Test/Fixtures/BicycleApi/Get/Helpers/BicyclesParameters.cs b/src/QAToolKit.Source.Swagger.Test/Fixtures/BicycleApi/Get/Helpers/BicyclesParameters.cs index 034664d..7a08e4d 100644 --- a/src/QAToolKit.Source.Swagger.Test/Fixtures/BicycleApi/Get/Helpers/BicyclesParameters.cs +++ b/src/QAToolKit.Source.Swagger.Test/Fixtures/BicycleApi/Get/Helpers/BicyclesParameters.cs @@ -16,6 +16,7 @@ public static List Get(bool exampleValues) Location = Location.Query, Nullable = false, Type = "integer", + Format = "int32", Required = false, Value = null }, @@ -24,6 +25,7 @@ public static List Get(bool exampleValues) Location = Location.Query, Nullable = false, Type = "string", + Format = null, Required = false, Value = "1" }, diff --git a/src/QAToolKit.Source.Swagger.Test/Fixtures/PetApi/Delete/DeletePetParameters.cs b/src/QAToolKit.Source.Swagger.Test/Fixtures/PetApi/Delete/DeletePetParameters.cs index a5c24b2..28b0c3b 100644 --- a/src/QAToolKit.Source.Swagger.Test/Fixtures/PetApi/Delete/DeletePetParameters.cs +++ b/src/QAToolKit.Source.Swagger.Test/Fixtures/PetApi/Delete/DeletePetParameters.cs @@ -16,6 +16,7 @@ public static List Get(bool exampleValues) Location = Location.Header, Nullable = false, Type = "string", + Format = null, Required = false, Value = null }, @@ -24,6 +25,7 @@ public static List Get(bool exampleValues) Location = Location.Path, Nullable = false, Type = "integer", + Format = "int64", Required = true, Value = null } @@ -38,6 +40,7 @@ public static List Get(bool exampleValues) Location = Location.Header, Nullable = false, Type = "string", + Format = null, Required = false, Value = null }, @@ -46,6 +49,7 @@ public static List Get(bool exampleValues) Location = Location.Path, Nullable = false, Type = "integer", + Format = "int64", Required = true, Value = null } diff --git a/src/QAToolKit.Source.Swagger.Test/Fixtures/PetApi/Get/Helpers/PetObjectWithExampleValues.cs b/src/QAToolKit.Source.Swagger.Test/Fixtures/PetApi/Get/Helpers/PetObjectWithExampleValues.cs index 07153a9..33bc80e 100644 --- a/src/QAToolKit.Source.Swagger.Test/Fixtures/PetApi/Get/Helpers/PetObjectWithExampleValues.cs +++ b/src/QAToolKit.Source.Swagger.Test/Fixtures/PetApi/Get/Helpers/PetObjectWithExampleValues.cs @@ -60,7 +60,7 @@ public static List GetProperties() new Property(){ Name = "photoUrls", Description = null, - Format = null, + Format = "string", Required = false, Properties = new List(){ new Property() @@ -80,7 +80,7 @@ public static List GetProperties() new Property(){ Name = "tags", Description = null, - Format = null, + Format = "object", Required = false, Properties = new List() { diff --git a/src/QAToolKit.Source.Swagger.Test/Fixtures/PetApi/Get/Helpers/PetObjectWithoutExampleValues.cs b/src/QAToolKit.Source.Swagger.Test/Fixtures/PetApi/Get/Helpers/PetObjectWithoutExampleValues.cs index cf5a7f5..92ac657 100644 --- a/src/QAToolKit.Source.Swagger.Test/Fixtures/PetApi/Get/Helpers/PetObjectWithoutExampleValues.cs +++ b/src/QAToolKit.Source.Swagger.Test/Fixtures/PetApi/Get/Helpers/PetObjectWithoutExampleValues.cs @@ -60,7 +60,7 @@ public static List GetProperties() new Property(){ Name = "photoUrls", Description = null, - Format = null, + Format = "string", Required = false, Properties = new List(){ new Property() @@ -80,7 +80,7 @@ public static List GetProperties() new Property(){ Name = "tags", Description = null, - Format = null, + Format = "object", Required = false, Properties = new List() { diff --git a/src/QAToolKit.Source.Swagger.Test/Fixtures/PetApi/PetResponse400.cs b/src/QAToolKit.Source.Swagger.Test/Fixtures/PetApi/PetResponse400.cs index 5d39e80..21d8bc4 100644 --- a/src/QAToolKit.Source.Swagger.Test/Fixtures/PetApi/PetResponse400.cs +++ b/src/QAToolKit.Source.Swagger.Test/Fixtures/PetApi/PetResponse400.cs @@ -1,4 +1,5 @@ -using QAToolKit.Core.Models; +using System.Collections.Generic; +using QAToolKit.Core.Models; using System.Net; namespace QAToolKit.Source.Swagger.Test.Fixtures.PetApi diff --git a/src/QAToolKit.Source.Swagger.Test/Fixtures/PetApi/Post/AddNewPetBody.cs b/src/QAToolKit.Source.Swagger.Test/Fixtures/PetApi/Post/AddNewPetBody.cs index 32296ad..88c16d5 100644 --- a/src/QAToolKit.Source.Swagger.Test/Fixtures/PetApi/Post/AddNewPetBody.cs +++ b/src/QAToolKit.Source.Swagger.Test/Fixtures/PetApi/Post/AddNewPetBody.cs @@ -13,7 +13,7 @@ public static List Get(bool exampleValues) return new List() { new RequestBody() { - ContentType = ContentType.ToEnum(ContentType.Json), + ContentType = ContentType.Json.Value(), Name = "Pet", Required = true, Properties = PetObjectWithExampleValues.GetProperties() @@ -25,7 +25,7 @@ public static List Get(bool exampleValues) return new List() { new RequestBody() { - ContentType = ContentType.ToEnum(ContentType.Json), + ContentType = ContentType.Json.Value(), Name = "Pet", Required = true, Properties = PetObjectWithoutExampleValues.GetProperties() diff --git a/src/QAToolKit.Source.Swagger.Test/Fixtures/PetApi/Post/UploadPetImageBody.cs b/src/QAToolKit.Source.Swagger.Test/Fixtures/PetApi/Post/UploadPetImageBody.cs index a9d5d3b..2f50275 100644 --- a/src/QAToolKit.Source.Swagger.Test/Fixtures/PetApi/Post/UploadPetImageBody.cs +++ b/src/QAToolKit.Source.Swagger.Test/Fixtures/PetApi/Post/UploadPetImageBody.cs @@ -10,7 +10,7 @@ public static List Get() return new List() { new RequestBody() { - ContentType = ContentType.ToEnum(ContentType.OctetStream), + ContentType = ContentType.OctetStream.Value(), Name = null, Required = false, Properties = null diff --git a/src/QAToolKit.Source.Swagger.Test/Fixtures/PetApi/Post/UploadPetImageParameters.cs b/src/QAToolKit.Source.Swagger.Test/Fixtures/PetApi/Post/UploadPetImageParameters.cs index 7d295c1..eac6b3d 100644 --- a/src/QAToolKit.Source.Swagger.Test/Fixtures/PetApi/Post/UploadPetImageParameters.cs +++ b/src/QAToolKit.Source.Swagger.Test/Fixtures/PetApi/Post/UploadPetImageParameters.cs @@ -16,6 +16,7 @@ public static List Get(bool exampleValues) Location = Location.Path, Nullable = false, Type = "integer", + Format = "int64", Required = true, Value = null }, @@ -24,6 +25,7 @@ public static List Get(bool exampleValues) Location = Location.Query, Nullable = false, Type = "string", + Format = null, Required = false, Value = null } diff --git a/src/QAToolKit.Source.Swagger.Test/Fixtures/PetApi/Put/UpdatePetBody.cs b/src/QAToolKit.Source.Swagger.Test/Fixtures/PetApi/Put/UpdatePetBody.cs index 00108af..d0f3c17 100644 --- a/src/QAToolKit.Source.Swagger.Test/Fixtures/PetApi/Put/UpdatePetBody.cs +++ b/src/QAToolKit.Source.Swagger.Test/Fixtures/PetApi/Put/UpdatePetBody.cs @@ -13,7 +13,7 @@ public static List Get(bool exampleValues) return new List() { new RequestBody() { - ContentType = ContentType.ToEnum(ContentType.Json), + ContentType = ContentType.Json.Value(), Name = "Pet", Required = true, Properties = PetObjectWithExampleValues.GetProperties() @@ -25,7 +25,7 @@ public static List Get(bool exampleValues) return new List() { new RequestBody() { - ContentType = ContentType.ToEnum(ContentType.Json), + ContentType = ContentType.Json.Value(), Name = "Pet", Required = true, Properties = PetObjectWithoutExampleValues.GetProperties() diff --git a/src/QAToolKit.Source.Swagger.Test/QAToolKit.Source.Swagger.Test.csproj b/src/QAToolKit.Source.Swagger.Test/QAToolKit.Source.Swagger.Test.csproj index 32bb618..36dede8 100644 --- a/src/QAToolKit.Source.Swagger.Test/QAToolKit.Source.Swagger.Test.csproj +++ b/src/QAToolKit.Source.Swagger.Test/QAToolKit.Source.Swagger.Test.csproj @@ -1,7 +1,7 @@  - net5.0 + net6.0 latest false @@ -11,10 +11,11 @@ all runtime; build; native; contentfiles; analyzers; buildtransitive - - - - + + + + + all @@ -37,6 +38,15 @@ Always + + Always + + + Always + + + Always + diff --git a/src/QAToolKit.Source.Swagger.Test/SwaggerFileSourceIntegrationTest.cs b/src/QAToolKit.Source.Swagger.Test/SwaggerFileSourceIntegrationTest.cs index 0cd868a..e1a8777 100644 --- a/src/QAToolKit.Source.Swagger.Test/SwaggerFileSourceIntegrationTest.cs +++ b/src/QAToolKit.Source.Swagger.Test/SwaggerFileSourceIntegrationTest.cs @@ -31,7 +31,8 @@ public async void SwaggerFileSourceWithOptionsTest_Successfull() options.AddBaseUrl(new Uri("https://petstore3.swagger.io/")); }); - var requests = await fileSource.Load(new List() { + var requests = await fileSource.Load(new List() + { new FileInfo("Assets/swagger-pets-test.json") }); @@ -44,23 +45,26 @@ public async void SwaggerFileSourceWithoutOptionsTest_Fails() { var fileSource = new SwaggerFileSource(); - var exception = await Assert.ThrowsAsync(async () => await fileSource.Load(new List() { - new FileInfo("Assets/swagger-pets-test.json") - })); + var exception = await Assert.ThrowsAsync(async () => + await fileSource.Load(new List() + { + new FileInfo("Assets/swagger-pets-test.json") + })); _logger.LogInformation(exception.Message); } [Fact] - public async void SwaggerFileSourceYamlWithoutWhitelistTest_Fails() + public async void SwaggerFileSourceYamlWithoutWhitelistTest() { var fileSource = new SwaggerFileSource(options => { options.AddBaseUrl(new Uri("https://petstore3.swagger.io/")); }); - var requests = await fileSource.Load(new List() { - new FileInfo("Assets/support-tickets.yaml") + var requests = await fileSource.Load(new List() + { + new FileInfo("Assets/support-tickets-ok.yaml") }); _logger.LogInformation(JsonConvert.SerializeObject(requests)); @@ -71,7 +75,7 @@ public async void SwaggerFileSourceYamlWithoutWhitelistTest_Fails() } [Fact] - public async void SwaggerFileSourceYamlWithWhitelistTest_Fails() + public async void SwaggerFileSourceYamlWithWhitelistTest() { var fileSource = new SwaggerFileSource(options => { @@ -82,8 +86,9 @@ public async void SwaggerFileSourceYamlWithWhitelistTest_Fails() }); }); - var requests = await fileSource.Load(new List() { - new FileInfo("Assets/support-tickets.yaml") + var requests = await fileSource.Load(new List() + { + new FileInfo("Assets/support-tickets-ok.yaml") }); _logger.LogInformation(JsonConvert.SerializeObject(requests)); @@ -99,7 +104,7 @@ public async void SwaggerFileSourceYamlWithWhitelistTest_Fails() } [Fact] - public async void SwaggerFileSourceYamlWithWhitelistAndExampleTest_Fails() + public async void SwaggerFileSourceYamlWithWhitelistAndExampleTest() { var fileSource = new SwaggerFileSource(options => { @@ -109,10 +114,12 @@ public async void SwaggerFileSourceYamlWithWhitelistAndExampleTest_Fails() EndpointNameWhitelist = new string[] { "getSupportTicketsList" } }); options.UseSwaggerExampleValues = true; + options.UseStrictParsing = true; }); - var requests = await fileSource.Load(new List() { - new FileInfo("Assets/support-tickets.yaml") + var requests = await fileSource.Load(new List() + { + new FileInfo("Assets/support-tickets-ok.yaml") }); _logger.LogInformation(JsonConvert.SerializeObject(requests)); @@ -127,5 +134,51 @@ public async void SwaggerFileSourceYamlWithWhitelistAndExampleTest_Fails() Assert.Single(requests); } + [Fact] + public async void SwaggerFileSourceYamlWithoutWhitelistTest_Fails() + { + var fileSource = new SwaggerFileSource(options => + { + options.AddBaseUrl(new Uri("https://petstore3.swagger.io/")); + }); + + Assert.ThrowsAsync(async () => await fileSource.Load(new List() + { + new FileInfo("Assets/support-tickets.yaml") + })); + } + + [Fact] + public async void InvalidSwaggerFile_Fails() + { + var fileSource = new SwaggerFileSource(); + + Assert.ThrowsAsync(async () => await fileSource.Load(new List() + { + new FileInfo("Assets/invalid.swagger.json") + })); + } + + [Fact] + public async void UnsupportedSwaggerFilev1_Fails() + { + var fileSource = new SwaggerFileSource(); + + Assert.ThrowsAsync(async () => await fileSource.Load(new List() + { + new FileInfo("Assets/swagger-pets-test-unsuppoted-v1.0.json") + })); + } + + [Fact] + public async void UnsupportedSwaggerFilev3_1_Fails() + { + var fileSource = new SwaggerFileSource(); + + Assert.ThrowsAsync(async () => await fileSource.Load(new List() + { + new FileInfo("Assets/swagger-pets-test-unsuppoted-v3.1.json") + })); + } } -} +} \ No newline at end of file diff --git a/src/QAToolKit.Source.Swagger.Test/SwaggerRequestFilterTests.cs b/src/QAToolKit.Source.Swagger.Test/SwaggerRequestFilterTests.cs index 5c697e4..447470b 100644 --- a/src/QAToolKit.Source.Swagger.Test/SwaggerRequestFilterTests.cs +++ b/src/QAToolKit.Source.Swagger.Test/SwaggerRequestFilterTests.cs @@ -1,15 +1,10 @@ -using Microsoft.Extensions.Logging; -using Newtonsoft.Json; -using QAToolKit.Core.Models; -using QAToolKit.Source.Swagger.Exceptions; +using QAToolKit.Core.Models; using System; using System.Collections.Generic; -using System.IO; using System.Linq; using System.Net.Http; using System.Threading.Tasks; using Xunit; -using Xunit.Abstractions; namespace QAToolKit.Source.Swagger.Test { diff --git a/src/QAToolKit.Source.Swagger.Test/SwaggerTests/BicycleApi/Get/SwaggerProcessorGetBicycleByIdTests.cs b/src/QAToolKit.Source.Swagger.Test/SwaggerTests/BicycleApi/Get/SwaggerProcessorGetBicycleByIdTests.cs index 153e96d..fd295f9 100644 --- a/src/QAToolKit.Source.Swagger.Test/SwaggerTests/BicycleApi/Get/SwaggerProcessorGetBicycleByIdTests.cs +++ b/src/QAToolKit.Source.Swagger.Test/SwaggerTests/BicycleApi/Get/SwaggerProcessorGetBicycleByIdTests.cs @@ -7,6 +7,7 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Net; using System.Net.Http; using System.Threading.Tasks; using Xunit; @@ -55,12 +56,12 @@ public async Task PetsSwaggerGetPetByIdWithExampleValuesTestV1_Successfull() Assert.Equal("/api/bicycles", requests.FirstOrDefault().Path); Assert.Empty(requests.FirstOrDefault().RequestBodies); Assert.Equal(2, requests.FirstOrDefault().Responses.Count); - - var getBikesParameters = BicyclesParameters.Get(true).ToExpectedObject(); - getBikesParameters.ShouldEqual(requests.FirstOrDefault().Parameters); - - var expectedPetsResponse = GetBicycleByIdResponse.Get().ToExpectedObject(); - expectedPetsResponse.ShouldEqual(requests.FirstOrDefault().Responses); + + var getBikesParameters = JsonConvert.SerializeObject(BicyclesParameters.Get(true), Formatting.None); + Assert.Equal(getBikesParameters.ToLower(), JsonConvert.SerializeObject(requests.FirstOrDefault().Parameters, Formatting.None).ToLower()); + + var expectedPetsResponse = JsonConvert.SerializeObject( GetBicycleByIdResponse.Get().OrderBy(x => x.StatusCode), Formatting.None); + Assert.Equal(expectedPetsResponse.ToLower(), JsonConvert.SerializeObject(requests.FirstOrDefault().Responses.OrderBy(x => x.StatusCode), Formatting.None).ToLower()); Assert.Equal("Get all bikes by filter", requests.FirstOrDefault().Summary); Assert.Collection(requests.FirstOrDefault().Tags, item => @@ -101,12 +102,12 @@ public async Task PetsSwaggerGetPetByIdWithExampleValuesAndDifferentBaseAddressT Assert.Empty(requests.FirstOrDefault().RequestBodies); Assert.Equal(2, requests.FirstOrDefault().Responses.Count); - var getBikesParameters = BicyclesParameters.Get(true).ToExpectedObject(); - getBikesParameters.ShouldEqual(requests.FirstOrDefault().Parameters); - - var expectedPetsResponse = GetBicycleByIdResponse.Get().ToExpectedObject(); - expectedPetsResponse.ShouldEqual(requests.FirstOrDefault().Responses); - + var getBikesParameters = JsonConvert.SerializeObject(BicyclesParameters.Get(true), Formatting.None); + Assert.Equal(getBikesParameters.ToLower(), JsonConvert.SerializeObject(requests.FirstOrDefault().Parameters, Formatting.None).ToLower()); + + var expectedPetsResponse = JsonConvert.SerializeObject( GetBicycleByIdResponse.Get().OrderBy(x => x.StatusCode), Formatting.None); + Assert.Equal(expectedPetsResponse.ToLower(), JsonConvert.SerializeObject(requests.FirstOrDefault().Responses.OrderBy(x => x.StatusCode), Formatting.None).ToLower()); + Assert.Equal("Get all bikes by filter", requests.FirstOrDefault().Summary); Assert.Collection(requests.FirstOrDefault().Tags, item => { diff --git a/src/QAToolKit.Source.Swagger.Test/SwaggerTests/PetApi/Get/SwaggerProcessorFindByTagsTests.cs b/src/QAToolKit.Source.Swagger.Test/SwaggerTests/PetApi/Get/SwaggerProcessorFindByTagsTests.cs index 60448f2..adccec4 100644 --- a/src/QAToolKit.Source.Swagger.Test/SwaggerTests/PetApi/Get/SwaggerProcessorFindByTagsTests.cs +++ b/src/QAToolKit.Source.Swagger.Test/SwaggerTests/PetApi/Get/SwaggerProcessorFindByTagsTests.cs @@ -62,8 +62,9 @@ public async Task PetsSwaggerGetByPetByIdWithExcampleValuesTest_Successfull() Assert.Empty(requests.FirstOrDefault().RequestBodies); Assert.Equal(2, requests.FirstOrDefault().Responses.Count); - var expectedPetsResponse = FindPetsByTagsResponses.Get(true).ToExpectedObject(); - expectedPetsResponse.ShouldEqual(requests.FirstOrDefault().Responses); + var expectedPetsResponse = JsonConvert.SerializeObject( FindPetsByTagsResponses.Get(true).OrderBy(x => x.StatusCode), Formatting.None); + Assert.Equal(expectedPetsResponse.ToLower(), JsonConvert.SerializeObject(requests.FirstOrDefault().Responses.OrderBy(x => x.StatusCode), Formatting.None).ToLower()); + Assert.Equal("Finds Pets by tags", requests.FirstOrDefault().Summary); Assert.Collection(requests.FirstOrDefault().Tags, item => diff --git a/src/QAToolKit.Source.Swagger.Test/SwaggerTests/PetApi/Post/SwaggerProcessorAddNewPetTests.cs b/src/QAToolKit.Source.Swagger.Test/SwaggerTests/PetApi/Post/SwaggerProcessorAddNewPetTests.cs index 1413a21..949dbdd 100644 --- a/src/QAToolKit.Source.Swagger.Test/SwaggerTests/PetApi/Post/SwaggerProcessorAddNewPetTests.cs +++ b/src/QAToolKit.Source.Swagger.Test/SwaggerTests/PetApi/Post/SwaggerProcessorAddNewPetTests.cs @@ -54,13 +54,13 @@ public async Task AddNewPetWithoutExampleValuesTest_Successfull() Assert.Empty(requests.FirstOrDefault().Parameters); Assert.Equal("/pet", requests.FirstOrDefault().Path); Assert.Equal(2, requests.FirstOrDefault().Responses.Count); - - var expectedPetsBody = AddNewPetBody.Get(false).ToExpectedObject(); - expectedPetsBody.ShouldEqual(requests.FirstOrDefault().RequestBodies - .Where(c => c.ContentType == ContentType.Enumeration.Json).ToList()); - - var expectedPetsResponse = AddNewPetResponse.Get(false).ToExpectedObject(); - expectedPetsResponse.ShouldEqual(requests.FirstOrDefault().Responses); + + var expectedPetsBody = JsonConvert.SerializeObject(AddNewPetBody.Get(false).FirstOrDefault(), Formatting.None); + Assert.Equal(expectedPetsBody.ToLower(), JsonConvert.SerializeObject(requests.FirstOrDefault().RequestBodies + .SingleOrDefault(c => c.ContentType == ContentType.Json.Value()), Formatting.None).ToLower()); + + var expectedPetsResponse = JsonConvert.SerializeObject(AddNewPetResponse.Get(false), Formatting.None); + Assert.Equal(expectedPetsResponse.ToLower(), JsonConvert.SerializeObject(requests.FirstOrDefault().Responses, Formatting.None).ToLower()); Assert.Equal("Add a new pet to the store", requests.FirstOrDefault().Summary); Assert.Collection(requests.FirstOrDefault().Tags, item => @@ -101,12 +101,9 @@ public async Task AddNewPetWithExampleValuesTest_Successfull() Assert.Equal("/pet", requests.FirstOrDefault().Path); Assert.Equal(2, requests.FirstOrDefault().Responses.Count); - var expectedPetsBody = AddNewPetBody.Get(true).ToExpectedObject(); - expectedPetsBody.ShouldEqual(requests.FirstOrDefault().RequestBodies - .Where(c => c.ContentType == ContentType.Enumeration.Json).ToList()); - - var expectedPetsResponse = AddNewPetResponse.Get(true).ToExpectedObject(); - expectedPetsResponse.ShouldEqual(requests.FirstOrDefault().Responses); + var expectedPetsBody = JsonConvert.SerializeObject(AddNewPetBody.Get(true).FirstOrDefault(), Formatting.None); + Assert.Equal(expectedPetsBody.ToLower(), JsonConvert.SerializeObject(requests.FirstOrDefault().RequestBodies + .SingleOrDefault(c => c.ContentType == ContentType.Json.Value()), Formatting.None).ToLower()); Assert.Equal("Add a new pet to the store", requests.FirstOrDefault().Summary); Assert.Collection(requests.FirstOrDefault().Tags, item => diff --git a/src/QAToolKit.Source.Swagger.Test/SwaggerTests/PetApi/Post/SwaggerProcessorUploadPetImageTests.cs b/src/QAToolKit.Source.Swagger.Test/SwaggerTests/PetApi/Post/SwaggerProcessorUploadPetImageTests.cs index f799f8f..0ba1849 100644 --- a/src/QAToolKit.Source.Swagger.Test/SwaggerTests/PetApi/Post/SwaggerProcessorUploadPetImageTests.cs +++ b/src/QAToolKit.Source.Swagger.Test/SwaggerTests/PetApi/Post/SwaggerProcessorUploadPetImageTests.cs @@ -1,5 +1,4 @@ -using ExpectedObjects; -using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging; using Newtonsoft.Json; using QAToolKit.Core.Models; using QAToolKit.Source.Swagger.Test.Fixtures.PetApi.Post; @@ -54,16 +53,15 @@ public async Task UploadPetImageWithoutExampleValuesTest_Successfull() Assert.Equal("/pet/{petId}/uploadImage", requests.FirstOrDefault().Path); Assert.Single(requests.FirstOrDefault().Responses); Assert.Equal(2, requests.FirstOrDefault().Parameters.Count); - - var expectedUploadPetImageParameters = UploadPetImageParameters.Get(true).ToExpectedObject(); - expectedUploadPetImageParameters.ShouldEqual(requests.FirstOrDefault().Parameters); - - var expectedUploadPetImageBody = UploadPetImageBody.Get().ToExpectedObject(); - expectedUploadPetImageBody.ShouldEqual(requests.FirstOrDefault().RequestBodies - .Where(c => c.ContentType == ContentType.Enumeration.OctetStream).ToList()); - - var expectedUploadPetImageResponse = UploadPetImageResponse.Get().ToExpectedObject(); - expectedUploadPetImageResponse.ShouldEqual(requests.FirstOrDefault().Responses); + + var expectedUploadPetImageParameters = JsonConvert.SerializeObject(UploadPetImageParameters.Get(true), Formatting.None); + Assert.Equal(expectedUploadPetImageParameters.ToLower(), JsonConvert.SerializeObject(requests.FirstOrDefault().Parameters, Formatting.None).ToLower()); + + var expectedUploadPetImageBody = JsonConvert.SerializeObject( UploadPetImageBody.Get(), Formatting.None); + Assert.Equal(expectedUploadPetImageBody.ToLower(), JsonConvert.SerializeObject(requests.FirstOrDefault().RequestBodies.Where(c => c.ContentType == ContentType.OctetStream.Value()), Formatting.None).ToLower()); + + var expectedUploadPetImageResponse = JsonConvert.SerializeObject( UploadPetImageResponse.Get().OrderBy(x => x.StatusCode), Formatting.None); + Assert.Equal(expectedUploadPetImageResponse.ToLower(), JsonConvert.SerializeObject(requests.FirstOrDefault().Responses.OrderBy(x => x.StatusCode), Formatting.None).ToLower()); Assert.Equal("uploads an image", requests.FirstOrDefault().Summary); Assert.Collection(requests.FirstOrDefault().Tags, item => @@ -104,15 +102,24 @@ public async Task UploadPetImageWithExampleValuesTest_Successfull() Assert.Single(requests.FirstOrDefault().Responses); Assert.Equal(2, requests.FirstOrDefault().Parameters.Count); - var expectedUploadPetImageParameters = UploadPetImageParameters.Get(true).ToExpectedObject(); + /* var expectedUploadPetImageParameters = UploadPetImageParameters.Get(true).ToExpectedObject(); expectedUploadPetImageParameters.ShouldEqual(requests.FirstOrDefault().Parameters); var expectedUploadPetImageBody = UploadPetImageBody.Get().ToExpectedObject(); expectedUploadPetImageBody.ShouldEqual(requests.FirstOrDefault().RequestBodies - .Where(c => c.ContentType == ContentType.Enumeration.OctetStream).ToList()); + .Where(c => c.ContentType == ContentType.OctetStream.Value()).ToList()); var expectedUploadPetImageResponse = UploadPetImageResponse.Get().ToExpectedObject(); expectedUploadPetImageResponse.ShouldEqual(requests.FirstOrDefault().Responses); + */ + var expectedUploadPetImageParameters = JsonConvert.SerializeObject(UploadPetImageParameters.Get(true), Formatting.None); + Assert.Equal(expectedUploadPetImageParameters.ToLower(), JsonConvert.SerializeObject(requests.FirstOrDefault().Parameters, Formatting.None).ToLower()); + + var expectedUploadPetImageBody = JsonConvert.SerializeObject( UploadPetImageBody.Get(), Formatting.None); + Assert.Equal(expectedUploadPetImageBody.ToLower(), JsonConvert.SerializeObject(requests.FirstOrDefault().RequestBodies.Where(c => c.ContentType == ContentType.OctetStream.Value()), Formatting.None).ToLower()); + + var expectedUploadPetImageResponse = JsonConvert.SerializeObject( UploadPetImageResponse.Get().OrderBy(x => x.StatusCode), Formatting.None); + Assert.Equal(expectedUploadPetImageResponse.ToLower(), JsonConvert.SerializeObject(requests.FirstOrDefault().Responses.OrderBy(x => x.StatusCode), Formatting.None).ToLower()); Assert.Equal("uploads an image", requests.FirstOrDefault().Summary); Assert.Collection(requests.FirstOrDefault().Tags, item => diff --git a/src/QAToolKit.Source.Swagger.Test/SwaggerTests/PetApi/Put/SwaggerProcessorUpdatePetTests.cs b/src/QAToolKit.Source.Swagger.Test/SwaggerTests/PetApi/Put/SwaggerProcessorUpdatePetTests.cs index c7192f9..acfd1d4 100644 --- a/src/QAToolKit.Source.Swagger.Test/SwaggerTests/PetApi/Put/SwaggerProcessorUpdatePetTests.cs +++ b/src/QAToolKit.Source.Swagger.Test/SwaggerTests/PetApi/Put/SwaggerProcessorUpdatePetTests.cs @@ -53,14 +53,14 @@ public async Task UpdatePetWithoutExampleValuesTest_Successfull() Assert.Empty(requests.FirstOrDefault().Parameters); Assert.Equal("/pet", requests.FirstOrDefault().Path); Assert.Equal(4, requests.FirstOrDefault().Responses.Count); - - var expectedPetsBody = UpdatePetBody.Get(false).ToExpectedObject(); - expectedPetsBody.ShouldEqual(requests.FirstOrDefault().RequestBodies - .Where(c => c.ContentType == ContentType.Enumeration.Json).ToList()); - - var expectedPetsResponse = UpdatePetResponse.Get(false).ToExpectedObject(); - expectedPetsResponse.ShouldEqual(requests.FirstOrDefault().Responses); - + + var expectedPetsBody = JsonConvert.SerializeObject(UpdatePetBody.Get(false).FirstOrDefault(), Formatting.None); + Assert.Equal(expectedPetsBody.ToLower(), JsonConvert.SerializeObject(requests.FirstOrDefault().RequestBodies + .SingleOrDefault(c => c.ContentType == ContentType.Json.Value()), Formatting.None).ToLower()); + + var expectedPetsResponse = JsonConvert.SerializeObject( UpdatePetResponse.Get(false), Formatting.None); + Assert.Equal(expectedPetsResponse.ToLower(), JsonConvert.SerializeObject(requests.FirstOrDefault().Responses, Formatting.None).ToLower()); + Assert.Equal("Update an existing pet", requests.FirstOrDefault().Summary); Assert.Collection(requests.FirstOrDefault().Tags, item => { @@ -99,12 +99,13 @@ public async Task UpdatePetWithExampleValuesTest_Successfull() Assert.Equal("/pet", requests.FirstOrDefault().Path); Assert.Equal(4, requests.FirstOrDefault().Responses.Count); - var expectedPetsBody = UpdatePetBody.Get(true).ToExpectedObject(); - expectedPetsBody.ShouldEqual(requests.FirstOrDefault().RequestBodies - .Where(c => c.ContentType == ContentType.Enumeration.Json).ToList()); - - var expectedPetsResponse = UpdatePetResponse.Get(true).ToExpectedObject(); - expectedPetsResponse.ShouldEqual(requests.FirstOrDefault().Responses); + var expectedPetsBody = JsonConvert.SerializeObject(UpdatePetBody.Get(true).FirstOrDefault(), Formatting.None); + Assert.Equal(expectedPetsBody.ToLower(), JsonConvert.SerializeObject(requests.FirstOrDefault().RequestBodies + .SingleOrDefault(c => c.ContentType == ContentType.Json.Value()), Formatting.None).ToLower()); + + var expectedPetsResponse = JsonConvert.SerializeObject( UpdatePetResponse.Get(true), Formatting.None); + Assert.Equal(expectedPetsResponse.ToLower(), JsonConvert.SerializeObject(requests.FirstOrDefault().Responses, Formatting.None).ToLower()); + Assert.Equal("Update an existing pet", requests.FirstOrDefault().Summary); Assert.Collection(requests.FirstOrDefault().Tags, item => diff --git a/src/QAToolKit.Source.Swagger.Test/SwaggerUrlSourceIntegrationTests.cs b/src/QAToolKit.Source.Swagger.Test/SwaggerUrlSourceIntegrationTests.cs index 06dba03..b2d6b27 100644 --- a/src/QAToolKit.Source.Swagger.Test/SwaggerUrlSourceIntegrationTests.cs +++ b/src/QAToolKit.Source.Swagger.Test/SwaggerUrlSourceIntegrationTests.cs @@ -3,6 +3,7 @@ using QAToolKit.Core.Models; using System; using System.Threading.Tasks; +using QAToolKit.Source.Swagger.Exceptions; using Xunit; using Xunit.Abstractions; @@ -69,7 +70,7 @@ await Assert.ThrowsAsync(async () => await urlSource.Load( public async Task WrongSwaggerUrlSourceArgumentNullExceptionTest_Fails() { var urlSource = new SwaggerUrlSource(); - await Assert.ThrowsAsync(async () => await urlSource.Load( + await Assert.ThrowsAsync(async () => await urlSource.Load( new Uri[] { new Uri("https://qatoolkitapi.azurewebsites.net/swagger/index.html") @@ -80,7 +81,7 @@ await Assert.ThrowsAsync(async () => await urlSource.Load public async Task WrongSwaggerUrlSourceArgumentNullException2Test_Fails() { var urlSource = new SwaggerUrlSource(); - await Assert.ThrowsAsync(async () => await urlSource.Load( + await Assert.ThrowsAsync(async () => await urlSource.Load( new Uri[] { new Uri("https://github.com") diff --git a/src/QAToolKit.Source.Swagger/Exceptions/InvalidSwaggerException.cs b/src/QAToolKit.Source.Swagger/Exceptions/InvalidSwaggerException.cs new file mode 100644 index 0000000..03a9a84 --- /dev/null +++ b/src/QAToolKit.Source.Swagger/Exceptions/InvalidSwaggerException.cs @@ -0,0 +1,33 @@ +using System; +using System.Runtime.Serialization; + +namespace QAToolKit.Source.Swagger.Exceptions +{ + /// + /// InvalidSwagger exception + /// + [Serializable] + public class InvalidSwaggerException : Exception + { + /// + /// InvalidSwagger exception + /// + public InvalidSwaggerException(string message) : base(message) + { + } + + /// + /// InvalidSwagger exception + /// + public InvalidSwaggerException(string message, Exception innerException) : base(message, innerException) + { + } + + /// + /// InvalidSwagger exception + /// + protected InvalidSwaggerException(SerializationInfo info, StreamingContext context) : base(info, context) + { + } + } +} \ No newline at end of file diff --git a/src/QAToolKit.Source.Swagger/Exceptions/SwaggerValidationException.cs b/src/QAToolKit.Source.Swagger/Exceptions/SwaggerValidationException.cs new file mode 100644 index 0000000..7e05fe9 --- /dev/null +++ b/src/QAToolKit.Source.Swagger/Exceptions/SwaggerValidationException.cs @@ -0,0 +1,43 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.Serialization; +using Microsoft.OpenApi.Models; + +namespace QAToolKit.Source.Swagger.Exceptions; + +/// +/// InvalidSwagger exception +/// +[Serializable] +public class SwaggerValidationException : Exception +{ + /// + /// InvalidSwagger exception + /// + public SwaggerValidationException(string message) : base(message) + { + } + + /// s + /// InvalidSwagger exception + /// + public SwaggerValidationException(string message, IList errors) : base(message += string.Join(",", + errors.Select(s => new KeyValuePair(s.Message, s.Pointer)).ToList())) + { + } + + /// + /// InvalidSwagger exception + /// + public SwaggerValidationException(string message, Exception innerException) : base(message, innerException) + { + } + + /// + /// InvalidSwagger exception + /// + protected SwaggerValidationException(SerializationInfo info, StreamingContext context) : base(info, context) + { + } +} \ No newline at end of file diff --git a/src/QAToolKit.Source.Swagger/Exceptions/UnsupportedSwaggerException.cs b/src/QAToolKit.Source.Swagger/Exceptions/UnsupportedSwaggerException.cs new file mode 100644 index 0000000..453e285 --- /dev/null +++ b/src/QAToolKit.Source.Swagger/Exceptions/UnsupportedSwaggerException.cs @@ -0,0 +1,33 @@ +using System; +using System.Runtime.Serialization; + +namespace QAToolKit.Source.Swagger.Exceptions +{ + /// + /// UnsupportedSwagger Exception + /// + [Serializable] + public class UnsupportedSwaggerException : Exception + { + /// + /// UnsupportedSwagger Exception + /// + public UnsupportedSwaggerException(string message) : base(message) + { + } + + /// + /// UnsupportedSwagger Exception + /// + public UnsupportedSwaggerException(string message, Exception innerException) : base(message, innerException) + { + } + + /// + /// UnsupportedSwagger Exception + /// + protected UnsupportedSwaggerException(SerializationInfo info, StreamingContext context) : base(info, context) + { + } + } +} \ No newline at end of file diff --git a/src/QAToolKit.Source.Swagger/PropertyType.cs b/src/QAToolKit.Source.Swagger/PropertyType.cs new file mode 100644 index 0000000..af7a70c --- /dev/null +++ b/src/QAToolKit.Source.Swagger/PropertyType.cs @@ -0,0 +1,118 @@ +namespace QAToolKit.Source.Swagger +{ + /// + /// QAToolkit Swagger types + /// + public enum PropertyType + { + /// + /// Unknown property type + /// + Unknown, + + /// + /// 32 bit Integer + /// + Int32, + + /// + /// 64 bit integer + /// + Int64, + + /// + /// Sting type + /// + String, + + /// + /// Binary type + /// + Binary, + + /// + /// Date time type + /// + DateTime, + + /// + /// Date type + /// + Date, + + /// + /// Boolean type + /// + Boolean, + + /// + /// Numeric double type + /// + Double, + + /// + /// Numeric float type + /// + Float, + + /// + /// Object type + /// + Object, + + /// + /// String array type + /// + StringArray, + + /// + /// 32 bit Integer array type + /// + Int32Array, + + /// + /// 64 bit Integer array type + /// + Int64Array, + + /// + /// Binary array type + /// + BooleanArray, + + /// + /// Double array type + /// + DoubleArray, + + /// + /// Float array type + /// + FloatArray, + + /// + /// Object array type + /// + ObjectArray, + + /// + /// Date time array type + /// + DateTimeArray, + + /// + /// Date array type + /// + DateArray, + + /// + /// Binary array type + /// + BinaryArray, + + /// + /// Url/Uri string type + /// + Uri + } +} \ No newline at end of file diff --git a/src/QAToolKit.Source.Swagger/QAToolKit.Source.Swagger.csproj b/src/QAToolKit.Source.Swagger/QAToolKit.Source.Swagger.csproj index 554ee47..1eab65d 100644 --- a/src/QAToolKit.Source.Swagger/QAToolKit.Source.Swagger.csproj +++ b/src/QAToolKit.Source.Swagger/QAToolKit.Source.Swagger.csproj @@ -1,7 +1,7 @@  - netstandard2.0;netstandard2.1;netcoreapp3.1;net5.0 + netstandard2.0;netstandard2.1;netcoreapp3.1;net6.0 true latest ee940718-945a-4c34-8ce6-0790972ada44 @@ -19,7 +19,7 @@ https://github.com/qatoolkit/qatoolkit-source-swagger-net qatoolkit-64x64.png https://github.com/qatoolkit/qatoolkit-source-swagger-net - qatoolkit-source-swagger-net;.net;c#;f#;swagger;dotnet;netstandard;net5 + qatoolkit-source-swagger-net;.net;c#;f#;swagger;dotnet;netstandard;net6 Debug;Release @@ -37,7 +37,7 @@ - + diff --git a/src/QAToolKit.Source.Swagger/SwaggerFileSource.cs b/src/QAToolKit.Source.Swagger/SwaggerFileSource.cs index b5e851c..bc4cf50 100644 --- a/src/QAToolKit.Source.Swagger/SwaggerFileSource.cs +++ b/src/QAToolKit.Source.Swagger/SwaggerFileSource.cs @@ -1,6 +1,4 @@ -using Microsoft.OpenApi.Readers; -using Microsoft.OpenApi.Writers; -using QAToolKit.Core.Interfaces; +using QAToolKit.Core.Interfaces; using QAToolKit.Core.Models; using System; using System.Collections.Generic; @@ -28,7 +26,7 @@ public SwaggerFileSource(Action options = null) } /// - /// Load swagger file sources from storage + /// Load swagger file sources from a files on a disk /// /// /// @@ -41,12 +39,9 @@ public Task> Load(IEnumerable source) foreach (var filePath in source) { - using (FileStream SourceStream = File.OpenRead(filePath.FullName)) + using (var sourceStream = File.OpenRead(filePath.FullName)) { - var openApiDocument = new OpenApiStreamReader().Read(SourceStream, out var diagnostic); - - var textWritter = new OpenApiJsonWriter(new StringWriter()); - openApiDocument.SerializeAsV3(textWritter); + var openApiDocument = SwaggerParser.GenerateOpenApiDocument(sourceStream, _swaggerOptions.UseStrictParsing); var requests = processor.MapFromOpenApiDocument(_swaggerOptions.BaseUrl, openApiDocument); @@ -57,4 +52,4 @@ public Task> Load(IEnumerable source) return Task.FromResult(restRequests.AsEnumerable()); } } -} +} \ No newline at end of file diff --git a/src/QAToolKit.Source.Swagger/SwaggerOptions.cs b/src/QAToolKit.Source.Swagger/SwaggerOptions.cs index 32d2771..7a155e6 100644 --- a/src/QAToolKit.Source.Swagger/SwaggerOptions.cs +++ b/src/QAToolKit.Source.Swagger/SwaggerOptions.cs @@ -3,6 +3,7 @@ using System.Runtime.CompilerServices; [assembly: InternalsVisibleTo("QAToolKit.Source.Swagger.Test")] + namespace QAToolKit.Source.Swagger { /// @@ -14,39 +15,52 @@ public class SwaggerOptions /// Request filter for filtering out the swagger endpoints /// internal RequestFilter RequestFilter { get; private set; } + /// /// Is Swagger protected with Basic authentication /// internal bool UseBasicAuth { get; private set; } = false; + /// /// Is Swagger protected with NTLM authentication /// internal bool UseNTLMAuth { get; private set; } = false; + /// /// Use request filters, to process only selected endpoints. /// internal bool UseRequestFilter { get; private set; } = false; + /// /// Swagger basic authentication user name /// internal string UserName { get; private set; } + /// /// Swagger basic authentication password /// internal string Password { get; private set; } + /// /// Set custom base API URL to the resulting HttpRequest list. /// internal Uri BaseUrl { get; private set; } + /// /// Use Swagger example values that come with Swagger file. Default us 'false'. /// public bool UseSwaggerExampleValues { get; set; } = false; + /// /// Disable SSL validation when accessing swagger.json file. Default is 'false'. /// public bool DisableSSLValidation { get; set; } = false; + /// + /// Prevent processing if any parsing errors are present + /// + public bool UseStrictParsing { get; set; } = false; + /// /// Add basic authentication to access swagger.json file. /// @@ -123,4 +137,4 @@ public SwaggerOptions AddBaseUrl(Uri baseUrl) return this; } } -} +} \ No newline at end of file diff --git a/src/QAToolKit.Source.Swagger/SwaggerParser.cs b/src/QAToolKit.Source.Swagger/SwaggerParser.cs new file mode 100644 index 0000000..b1d21a2 --- /dev/null +++ b/src/QAToolKit.Source.Swagger/SwaggerParser.cs @@ -0,0 +1,113 @@ +using System.IO; +using Microsoft.OpenApi; +using Microsoft.OpenApi.Models; +using Microsoft.OpenApi.Readers; +using Microsoft.OpenApi.Readers.Exceptions; +using Microsoft.OpenApi.Writers; +using QAToolKit.Source.Swagger.Exceptions; + +namespace QAToolKit.Source.Swagger +{ + /// + /// Swagger parser based on Microsoft OpenApi library + /// + public static partial class SwaggerParser + { + /// + /// Parse Swagger document (JSON, YML) from stream to the OpenApiDocument + /// + /// + /// + /// + /// + /// + public static OpenApiDocument GenerateOpenApiDocument(Stream sourceStream, bool strictParsing) + { + OpenApiDocument openApiDocument; + OpenApiSpecVersion openApiSpecVersion; + try + { + openApiDocument = new OpenApiStreamReader().Read(sourceStream, out var diagnostic); + + if (strictParsing) + { + if (diagnostic.Errors is { Count: > 0 }) + { + throw new SwaggerValidationException("Swagger validation failed.", diagnostic.Errors); + } + } + + openApiSpecVersion = diagnostic.SpecificationVersion; + } + catch (OpenApiUnsupportedSpecVersionException e) + { + throw new UnsupportedSwaggerException("Unsupported Swagger version.", e); + } + + var writer = new OpenApiJsonWriter(new StringWriter()); + + switch (openApiSpecVersion) + { + case OpenApiSpecVersion.OpenApi2_0: + openApiDocument.SerializeAsV2(writer); + break; + case OpenApiSpecVersion.OpenApi3_0: + openApiDocument.SerializeAsV3(writer); + break; + default: + throw new UnsupportedSwaggerException("Unsupported Swagger version."); + } + + if (openApiDocument.IsOpenApiDocumentEmpty()) + { + throw new InvalidSwaggerException("Swagger document is invalid, check the input."); + } + + return openApiDocument; + } + + private static bool IsOpenApiDocumentEmpty(this OpenApiDocument openApiDocument) + { + return openApiDocument?.Components == null || openApiDocument?.Paths == null; + } + + /// + /// Swagger types to QAToolKit Swagger types mapper + /// + /// + /// + /// + public static PropertyType MapFromSwaggerType(string swaggerType, string swaggerFormat) + { + return swaggerType switch + { + "string" when swaggerFormat == "binary" => PropertyType.Binary, + "string" when swaggerFormat == "date-time" => PropertyType.DateTime, + "string" when swaggerFormat == "date" => PropertyType.Date, + "string" when swaggerFormat == "url" => PropertyType.Uri, + "string" when swaggerFormat == "uri" => PropertyType.Uri, + "string" when swaggerFormat == null => PropertyType.String, + "string" => PropertyType.String, + "boolean" => PropertyType.Boolean, + "integer" when swaggerFormat == "int32" => PropertyType.Int32, + "integer" when swaggerFormat == "int64" => PropertyType.Int64, + "integer" => PropertyType.Int32, + "object" => PropertyType.Object, + "number" when swaggerFormat == null => PropertyType.Int32, + "number" when swaggerFormat == "float" => PropertyType.Float, + "number" when swaggerFormat == "double" => PropertyType.Double, + "array" when swaggerFormat == "double" => PropertyType.DoubleArray, + "array" when swaggerFormat == "float" => PropertyType.FloatArray, + "array" when swaggerFormat == "int32" => PropertyType.Int32Array, + "array" when swaggerFormat == "int64" => PropertyType.Int64Array, + "array" when swaggerFormat == "date" => PropertyType.DateArray, + "array" when swaggerFormat == "date-time" => PropertyType.DateTimeArray, + "array" when swaggerFormat == "binary" => PropertyType.BinaryArray, + "array" when swaggerFormat == "string" => PropertyType.StringArray, + "array" when swaggerFormat == "boolean" => PropertyType.BooleanArray, + "array" when swaggerFormat == "object" => PropertyType.ObjectArray, + _ => PropertyType.Unknown + }; + } + } +} \ No newline at end of file diff --git a/src/QAToolKit.Source.Swagger/SwaggerProcessor.cs b/src/QAToolKit.Source.Swagger/SwaggerProcessor.cs index 604f032..b8be58d 100644 --- a/src/QAToolKit.Source.Swagger/SwaggerProcessor.cs +++ b/src/QAToolKit.Source.Swagger/SwaggerProcessor.cs @@ -43,10 +43,36 @@ public IEnumerable MapFromOpenApiDocument(Uri baseUri, OpenApiDocum var restRequests = new List(); - var server = openApiDocument.Servers.FirstOrDefault(); - if (server != null) + baseUri = ParseBaseUri(baseUri, openApiDocument.Servers.FirstOrDefault()); + + foreach (var path in openApiDocument.Paths) { - var tempUri = new Uri(server.Url, UriKind.RelativeOrAbsolute); + restRequests.AddRange(GetRestRequestsForPath(baseUri, path, openApiDocument.Components?.RequestBodies)); + } + + if (_swaggerOptions.UseRequestFilter) + { + var filters = new SwaggerRequestFilter(restRequests); + restRequests = filters.FilterRequests(_swaggerOptions.RequestFilter).ToList(); + } + + return restRequests; + } + + private static Uri ParseBaseUri(Uri baseUri, OpenApiServer openApiServer) + { + if (openApiServer != null) + { + Uri tempUri; + try + { + tempUri = new Uri(openApiServer.Url, UriKind.RelativeOrAbsolute); + } + catch (Exception) + { + tempUri = baseUri; + } + if (tempUri.IsAbsoluteUri) { baseUri = tempUri; @@ -56,28 +82,26 @@ public IEnumerable MapFromOpenApiDocument(Uri baseUri, OpenApiDocum if (baseUri == null) { throw new QAToolKitSwaggerException( - "Swagger from file source needs BaseUrl defined. Inject baseUrl with AddBaseUrl in your SwaggerSource instantiation."); + "Swagger needs BaseUrl defined. Inject baseUrl with AddBaseUrl in your SwaggerSource instantiation."); } baseUri = new Uri(baseUri, tempUri); } } - - foreach (var path in openApiDocument.Paths) - { - restRequests.AddRange(GetRestRequestsForPath(baseUri, path)); - } - - if (_swaggerOptions.UseRequestFilter) + else { - var filters = new SwaggerRequestFilter(restRequests); - restRequests = filters.FilterRequests(_swaggerOptions.RequestFilter).ToList(); + if (baseUri == null) + { + throw new QAToolKitSwaggerException( + "Swagger needs BaseUrl defined. Inject baseUrl with AddBaseUrl in your SwaggerSource instantiation."); + } } - return restRequests; + return baseUri; } - private IEnumerable GetRestRequestsForPath(Uri baseUri, KeyValuePair path) + private IEnumerable GetRestRequestsForPath(Uri baseUri, KeyValuePair path, + IDictionary schemas = null) { var requests = new List(); @@ -92,7 +116,7 @@ private IEnumerable GetRestRequestsForPath(Uri baseUri, KeyValuePai Description = GetDescription(operation), OperationId = GetOperationId(operation), Parameters = GetParameters(operation).ToList(), - RequestBodies = GetRequestBodies(operation), + RequestBodies = GetRequestBodies(operation, schemas), Responses = GetResponses(operation), Tags = GetTags(operation), AuthenticationTypes = GetAuthenticationTypes(operation), @@ -241,7 +265,7 @@ private HttpMethod GetHttpMethod(KeyValuePair o #elif NETCOREAPP3_1 case "patch": return HttpMethod.Patch; -#elif NET5_0 +#elif NET6_0 case "patch": return HttpMethod.Patch; #endif @@ -254,10 +278,12 @@ private HttpMethod GetHttpMethod(KeyValuePair o { return statusCode switch { + "2XX" => HttpStatusCode.OK, "200" => HttpStatusCode.OK, "201" => HttpStatusCode.Created, "202" => HttpStatusCode.Accepted, "204" => HttpStatusCode.NoContent, + "302" => HttpStatusCode.Found, "400" => HttpStatusCode.BadRequest, "401" => HttpStatusCode.Unauthorized, "403" => HttpStatusCode.Forbidden, @@ -265,10 +291,28 @@ private HttpMethod GetHttpMethod(KeyValuePair o "405" => HttpStatusCode.MethodNotAllowed, "406" => HttpStatusCode.NotAcceptable, "409" => HttpStatusCode.Conflict, + "410" => (HttpStatusCode)410, + "413" => HttpStatusCode.RequestEntityTooLarge, + "415" => HttpStatusCode.UnsupportedMediaType, + "429" => (HttpStatusCode)429, + "5XX" => HttpStatusCode.InternalServerError, "500" => HttpStatusCode.InternalServerError, + "501" => HttpStatusCode.NotImplemented, + "502" => HttpStatusCode.BadGateway, "503" => HttpStatusCode.ServiceUnavailable, + "504" => HttpStatusCode.GatewayTimeout, + "505" => HttpStatusCode.HttpVersionNotSupported, +#if NETSTANDARD2_0 + "422" => throw new QAToolKitSwaggerException($"HttpStatusCode not supported '{statusCode}'."), +#elif NETSTANDARD2_1 + "422" => HttpStatusCode.UnprocessableEntity, +#elif NETCOREAPP3_1 + "422" => HttpStatusCode.UnprocessableEntity, +#elif NET6_0 + "422" => HttpStatusCode.UnprocessableEntity, +#endif "default" => null, - _ => throw new QAToolKitSwaggerException($"HttpStatusCode not found '{statusCode}'."), + _ => (HttpStatusCode)Convert.ToInt16(statusCode)//throw new QAToolKitSwaggerException($"HttpStatusCode not found '{statusCode}'."), }; } @@ -292,6 +336,7 @@ private IEnumerable GetParameters(KeyValuePair GetRequestBodies(KeyValuePair openApiOperation) + private List GetRequestBodies(KeyValuePair openApiOperation, + IDictionary schemas = null) { try { var requests = new List(); + var schema = new KeyValuePair(); if (openApiOperation.Value.RequestBody == null) { @@ -333,33 +380,51 @@ private List GetRequestBodies(KeyValuePair(); - } - - //TODO: support other content types - foreach (var contentType in openApiOperation.Value.RequestBody.Content) - { - var requestBody = new RequestBody + if (openApiOperation.Value.RequestBody.Reference == null) { - Name = contentType.Value.Schema.Reference?.Id, - ContentType = ContentType.ToEnum(contentType.Key), - Properties = null, - Required = openApiOperation.Value.RequestBody.Required - }; + return new List(); + } - foreach (KeyValuePair property in contentType.Value.Schema.Properties) + if (schemas != null) { - var temp = GetPropertiesRecursively(property); - if (temp != null) - { - if (requestBody.Properties == null) - requestBody.Properties = new List(); + schema = schemas.FirstOrDefault(x => x.Key == openApiOperation.Value.RequestBody.Reference.Id); - requestBody.Properties.AddRange(temp); + foreach (var contentType in schema.Value.Content) + { + var requestBody = new RequestBody + { + Name = contentType.Value.Schema.Reference?.Id, + ContentType = contentType.Key, + Properties = null, + Required = openApiOperation.Value.RequestBody.Required + }; + + ExtractOpenApiSchema(contentType.Value.Schema.AllOf, requestBody); + ExtractOpenApiSchema(contentType.Value.Schema.AnyOf, requestBody); + ExtractOpenApiSchema(contentType.Value.Schema.OneOf, requestBody); + ExtractProperties(contentType, requestBody); + + requests.Add(requestBody); } } + } + else + { + //TODO: support other content types + foreach (var contentType in openApiOperation.Value.RequestBody.Content) + { + var requestBody = new RequestBody + { + Name = contentType.Value.Schema.Reference?.Id, + ContentType = contentType.Key, + Properties = null, + Required = openApiOperation.Value.RequestBody.Required + }; + + ExtractProperties(contentType, requestBody); - requests.Add(requestBody); + requests.Add(requestBody); + } } return requests; @@ -370,8 +435,40 @@ private List GetRequestBodies(KeyValuePair contentType, RequestBody requestBody) + { + foreach (var property in contentType.Value.Schema.Properties) + { + var temp = GetPropertiesRecursively(property); + if (temp != null) + { + if (requestBody.Properties == null) + requestBody.Properties = new List(); + + requestBody.Properties.AddRange(temp); + } + } + } + + private void ExtractOpenApiSchema(IList schemas, RequestBody requestBody) + { + foreach (var schema in schemas) + { + foreach (var property in schema.Properties) + { + var temp = GetPropertiesRecursively(property); + if (temp != null) + { + if (requestBody.Properties == null) + requestBody.Properties = new List(); + + requestBody.Properties.AddRange(temp); + } + } + } + } - private List GetPropertiesRecursively(KeyValuePair source) + private List GetPropertiesRecursively(KeyValuePair source, int counter = 0) { var properties = new List(); @@ -384,7 +481,7 @@ private List GetPropertiesRecursively(KeyValuePair GetPropertiesRecursively(KeyValuePair(); - } + if (itemsProperty.Properties == null) + { + itemsProperty.Properties = new List(); + } - itemsProperty.Properties.AddRange(recursiveProperties); + itemsProperty.Properties.AddRange(recursiveProperties); + } } } } @@ -415,7 +514,7 @@ private List GetPropertiesRecursively(KeyValuePair 0) + if (source.Value.Enum is { Count: > 0 }) { enumProperty = new Property { @@ -452,7 +551,7 @@ private List GetPropertiesRecursively(KeyValuePair GetPropertiesRecursively(KeyValuePair(); - } + var propsTem = GetPropertiesRecursively(property, ++counter); - prop.Properties.AddRange(propsTem); + if (propsTem != null && prop.Properties == null) + { + prop.Properties = new List(); + } + + prop.Properties.AddRange(propsTem); + } } properties.Add(prop); @@ -541,28 +643,34 @@ private List GetResponses(KeyValuePair - ContentType.From(contentType.Key) == ContentType.Json)) - { - if (contentType.Value.Schema.Items != null && - (contentType.Value.Schema.Items.Type == "array" || - contentType.Value.Schema.Items.Type != "object") && - contentType.Value.Schema.Type == "array") - { + contentType.Key == ContentType.Json.Value())) + { + if (contentType.Value.Schema != null + && contentType.Value.Schema.Items != null + && (contentType.Value.Schema.Items.Type == "array" || + contentType.Value.Schema.Items.Type != "object") && + contentType.Value.Schema.Type == "array") + { return ResponseType.Array; } - else if (contentType.Value.Schema.Items != null && - (contentType.Value.Schema.Items.Type == "array" || - contentType.Value.Schema.Items.Type == "object") && - contentType.Value.Schema.Type == "array") + else if (contentType.Value.Schema != null + && contentType.Value.Schema.Items != null + && (contentType.Value.Schema.Items.Type == "array" || + contentType.Value.Schema.Items.Type == "object") && + contentType.Value.Schema.Type == "array") { return ResponseType.Objects; } - else if (contentType.Value.Schema.Items == null && contentType.Value.Schema.Type == "object") + else if (contentType.Value.Schema != null + && contentType.Value.Schema.Items == null + && contentType.Value.Schema.Type == "object") { return ResponseType.Object; } - else if (contentType.Value.Schema.Items == null && - (contentType.Value.Schema.Type != "object" || contentType.Value.Schema.Type != "array")) + else if (contentType.Value.Schema != null + && contentType.Value.Schema.Items == null + && (contentType.Value.Schema.Type != "object" || + contentType.Value.Schema.Type != "array")) { return ResponseType.Primitive; } @@ -591,9 +699,10 @@ private List GetResponseProperties(OpenApiResponse openApiResponse) //TODO: support other content types foreach (var contentType in openApiResponse.Content.Where(contentType => - ContentType.From(contentType.Key) == ContentType.Json)) + contentType.Key == ContentType.Json.Value())) { - if (contentType.Value.Schema.Properties != null && contentType.Value.Schema.Properties.Count > 0) + if (contentType.Value.Schema != null && contentType.Value.Schema.Properties != null && + contentType.Value.Schema.Properties.Count > 0) { foreach (KeyValuePair property in contentType.Value.Schema.Properties) { @@ -601,11 +710,64 @@ private List GetResponseProperties(OpenApiResponse openApiResponse) } } - if (contentType.Value.Schema.Items != null) + if (contentType.Value.Schema != null && contentType.Value.Schema.AllOf != null && + contentType.Value.Schema.AllOf.Count > 0) { - foreach (KeyValuePair property in contentType.Value.Schema.Items.Properties) + foreach (var schema in contentType.Value.Schema.AllOf) { - properties.AddRange(GetPropertiesRecursively(property)); + foreach (var property in schema.Properties) + { + properties.AddRange(GetPropertiesRecursively(property)); + } + } + } + + if (contentType.Value.Schema != null && contentType.Value.Schema.AnyOf != null && + contentType.Value.Schema.AnyOf.Count > 0) + { + foreach (var schema in contentType.Value.Schema.AnyOf) + { + foreach (var property in schema.Properties) + { + properties.AddRange(GetPropertiesRecursively(property)); + } + } + } + + if (contentType.Value.Schema != null && contentType.Value.Schema.OneOf != null && + contentType.Value.Schema.OneOf.Count > 0) + { + foreach (var schema in contentType.Value.Schema.OneOf) + { + foreach (var property in schema.Properties) + { + properties.AddRange(GetPropertiesRecursively(property)); + } + } + } + + if (contentType.Value.Schema != null && contentType.Value.Schema.Items != null) + { + if (contentType.Value.Schema.Items != null + && contentType.Value.Schema.Items.Properties != null + && contentType.Value.Schema.Items.Properties.Count > 0) + { + foreach (KeyValuePair property in contentType.Value.Schema.Items + .Properties) + { + properties.AddRange(GetPropertiesRecursively(property)); + } + } + else if (contentType.Value.Schema.Items != null + && contentType.Value.Schema.Items.Properties != null + && contentType.Value.Schema.Items.Properties.Count == 0) + { + properties.Add(new Property() + { + Name = $"_{contentType.Value.Schema.Type}", + Format = contentType.Value.Schema.Items.Type, + Type = contentType.Value.Schema.Type + }); } } } diff --git a/src/QAToolKit.Source.Swagger/SwaggerUrlSource.cs b/src/QAToolKit.Source.Swagger/SwaggerUrlSource.cs index aa1c5fe..b9aaa4a 100644 --- a/src/QAToolKit.Source.Swagger/SwaggerUrlSource.cs +++ b/src/QAToolKit.Source.Swagger/SwaggerUrlSource.cs @@ -1,10 +1,7 @@ -using Microsoft.OpenApi.Readers; -using Microsoft.OpenApi.Writers; -using QAToolKit.Core.Interfaces; +using QAToolKit.Core.Interfaces; using QAToolKit.Core.Models; using System; using System.Collections.Generic; -using System.IO; using System.Net; using System.Net.Http; using System.Net.Http.Headers; @@ -53,7 +50,7 @@ private async Task> LoadInternal(Uri[] source) { if (_swaggerOptions.UseNTLMAuth) { - var credentials = new NetworkCredential(); + NetworkCredential credentials; if (string.IsNullOrEmpty(_swaggerOptions.UserName) || string.IsNullOrEmpty(_swaggerOptions.Password)) { credentials = CredentialCache.DefaultNetworkCredentials; @@ -71,10 +68,7 @@ private async Task> LoadInternal(Uri[] source) { handler.ClientCertificateOptions = ClientCertificateOption.Manual; handler.ServerCertificateCustomValidationCallback = - (httpRequestMessage, cert, cetChain, policyErrors) => - { - return true; - }; + (httpRequestMessage, cert, cetChain, policyErrors) => true; } using (var httpClient = new HttpClient(handler)) @@ -88,19 +82,9 @@ private async Task> LoadInternal(Uri[] source) var stream = await httpClient.GetStreamAsync(uri); - var openApiDocument = new OpenApiStreamReader().Read(stream, out var diagnostic); - var textWritter = new OpenApiJsonWriter(new StringWriter()); - openApiDocument.SerializeAsV3(textWritter); - - Uri url; - if (_swaggerOptions.BaseUrl != null) - { - url = _swaggerOptions.BaseUrl; - } - else - { - url = new Uri($"{uri.Scheme}://{uri.Host}"); - } + var openApiDocument = SwaggerParser.GenerateOpenApiDocument(stream, _swaggerOptions.UseStrictParsing); + + var url = _swaggerOptions.BaseUrl != null ? _swaggerOptions.BaseUrl : new Uri($"{uri.Scheme}://{uri.Host}"); var requests = processor.MapFromOpenApiDocument(url, openApiDocument); From ed84dbf21335a97a25ea345098257cba8ae6d577 Mon Sep 17 00:00:00 2001 From: Miha Jakovac Date: Sat, 14 Jan 2023 09:53:06 +0100 Subject: [PATCH 4/5] Upgrade to .NET 7 --- .github/workflows/codeql-analysis.yml | 8 ++------ .github/workflows/dotnet-core.yml | 16 ++++------------ .github/workflows/sonarqube-analysis.yml | 10 +++------- .gitignore | 1 + Directory.Build.props | 2 +- README.md | 4 ++-- .../QAToolKit.Source.Swagger.Test.csproj | 2 +- .../QAToolKit.Source.Swagger.csproj | 4 ++-- src/QAToolKit.Source.Swagger/SwaggerProcessor.cs | 2 +- 9 files changed, 17 insertions(+), 32 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index d61fb6d..7d72101 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -18,14 +18,10 @@ jobs: steps: - name: Checkout repository uses: actions/checkout@v2 - - name: Setup .NET Core 3.1 + - name: Setup .NET Core 7.0 uses: actions/setup-dotnet@v1 with: - dotnet-version: '3.1.x' - - name: Setup .NET Core 6.0 - uses: actions/setup-dotnet@v1 - with: - dotnet-version: '6.0.x' + dotnet-version: '7.0.x' - name: Initialize CodeQL uses: github/codeql-action/init@v1 with: diff --git a/.github/workflows/dotnet-core.yml b/.github/workflows/dotnet-core.yml index 1eacfe0..5eed2da 100644 --- a/.github/workflows/dotnet-core.yml +++ b/.github/workflows/dotnet-core.yml @@ -16,14 +16,10 @@ jobs: steps: - uses: actions/checkout@v2 - - name: Setup .NET Core 3.1 + - name: Setup .NET Core 7.0 uses: actions/setup-dotnet@v1 with: - dotnet-version: '3.1.x' - - name: Setup .NET Core 6.0 - uses: actions/setup-dotnet@v1 - with: - dotnet-version: '6.0.x' + dotnet-version: '7.0.x' - name: Install dependencies run: dotnet restore - name: Build @@ -44,14 +40,10 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - - name: Setup .NET Core 3.1 - uses: actions/setup-dotnet@v1 - with: - dotnet-version: '3.1.x' - - name: Setup .NET Core 6.0 + - name: Setup .NET Core 7.0 uses: actions/setup-dotnet@v1 with: - dotnet-version: '6.0.x' + dotnet-version: '7.0.x' - name: Pack NuGet uses: brandedoutcast/publish-nuget@v2.5.5 with: diff --git a/.github/workflows/sonarqube-analysis.yml b/.github/workflows/sonarqube-analysis.yml index ced25e6..f6f86ee 100644 --- a/.github/workflows/sonarqube-analysis.yml +++ b/.github/workflows/sonarqube-analysis.yml @@ -12,16 +12,12 @@ jobs: - uses: actions/checkout@v2 with: fetch-depth: 0 - - name: Setup .NET Core 3.1 + - name: Setup .NET Core 7.0 uses: actions/setup-dotnet@v1 with: - dotnet-version: '3.1.x' - - name: Setup .NET Core 6.0 - uses: actions/setup-dotnet@v1 - with: - dotnet-version: '6.0.x' + dotnet-version: '7.0.x' - name: SonarScanner for .NET Core with pull request decoration support - uses: highbyte/sonarscan-dotnet@v2.1.2 + uses: highbyte/sonarscan-dotnet@v2.2.1 with: sonarProjectKey: qatoolkit_qatoolkit-source-swagger-net sonarProjectName: qatoolkit_qatoolkit-source-swagger-net diff --git a/.gitignore b/.gitignore index 15725df..583eb90 100644 --- a/.gitignore +++ b/.gitignore @@ -361,3 +361,4 @@ MigrationBackup/ # Fody - auto-generated XML schema FodyWeavers.xsd /src/QAToolKit.Source.Swagger.Test/global.json +.idea/ \ No newline at end of file diff --git a/Directory.Build.props b/Directory.Build.props index 8f74366..60b81f5 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -1,5 +1,5 @@ - 0.4.0 + 0.4.1 \ No newline at end of file diff --git a/README.md b/README.md index 07407fb..380dfd4 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ ## Description `QAToolKit.Source.Swagger` is a .NET library, which generates `IEnumerable` object that is the input for other components. -Supported .NET frameworks and standards: `netstandard2.0`, `netstandard2.1`, `netcoreapp3.1`, `net6.0` +Supported .NET frameworks and standards: `netstandard2.0`, `netstandard2.1`, `net7.0` Major features: @@ -182,7 +182,7 @@ By default this option is set to false. MIT License -Copyright (c) 2020-2021 Miha Jakovac +Copyright (c) 2020-2023 Miha Jakovac Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/src/QAToolKit.Source.Swagger.Test/QAToolKit.Source.Swagger.Test.csproj b/src/QAToolKit.Source.Swagger.Test/QAToolKit.Source.Swagger.Test.csproj index 36dede8..7ca55e3 100644 --- a/src/QAToolKit.Source.Swagger.Test/QAToolKit.Source.Swagger.Test.csproj +++ b/src/QAToolKit.Source.Swagger.Test/QAToolKit.Source.Swagger.Test.csproj @@ -1,7 +1,7 @@  - net6.0 + net7.0 latest false diff --git a/src/QAToolKit.Source.Swagger/QAToolKit.Source.Swagger.csproj b/src/QAToolKit.Source.Swagger/QAToolKit.Source.Swagger.csproj index 1eab65d..5b9284f 100644 --- a/src/QAToolKit.Source.Swagger/QAToolKit.Source.Swagger.csproj +++ b/src/QAToolKit.Source.Swagger/QAToolKit.Source.Swagger.csproj @@ -1,7 +1,7 @@  - netstandard2.0;netstandard2.1;netcoreapp3.1;net6.0 + netstandard2.0;netstandard2.1;net7.0 true latest ee940718-945a-4c34-8ce6-0790972ada44 @@ -19,7 +19,7 @@ https://github.com/qatoolkit/qatoolkit-source-swagger-net qatoolkit-64x64.png https://github.com/qatoolkit/qatoolkit-source-swagger-net - qatoolkit-source-swagger-net;.net;c#;f#;swagger;dotnet;netstandard;net6 + qatoolkit-source-swagger-net;.net;c#;f#;swagger;dotnet;netstandard;net7 Debug;Release diff --git a/src/QAToolKit.Source.Swagger/SwaggerProcessor.cs b/src/QAToolKit.Source.Swagger/SwaggerProcessor.cs index b8be58d..3c708ab 100644 --- a/src/QAToolKit.Source.Swagger/SwaggerProcessor.cs +++ b/src/QAToolKit.Source.Swagger/SwaggerProcessor.cs @@ -265,7 +265,7 @@ private HttpMethod GetHttpMethod(KeyValuePair o #elif NETCOREAPP3_1 case "patch": return HttpMethod.Patch; -#elif NET6_0 +#elif NET7_0 case "patch": return HttpMethod.Patch; #endif From 567e2616e217719b01ca575b8b6e397e41e130c2 Mon Sep 17 00:00:00 2001 From: mihaj Date: Sat, 14 Jan 2023 09:56:45 +0100 Subject: [PATCH 5/5] fixes --- .../QAToolKit.Source.Swagger.Test.csproj | 4 ---- .../QAToolKit.Source.Swagger.csproj | 11 ----------- src/QAToolKit.Source.Swagger/SwaggerProcessor.cs | 2 +- 3 files changed, 1 insertion(+), 16 deletions(-) diff --git a/src/QAToolKit.Source.Swagger.Test/QAToolKit.Source.Swagger.Test.csproj b/src/QAToolKit.Source.Swagger.Test/QAToolKit.Source.Swagger.Test.csproj index 7ca55e3..c7711a9 100644 --- a/src/QAToolKit.Source.Swagger.Test/QAToolKit.Source.Swagger.Test.csproj +++ b/src/QAToolKit.Source.Swagger.Test/QAToolKit.Source.Swagger.Test.csproj @@ -21,10 +21,6 @@ all runtime; build; native; contentfiles; analyzers; buildtransitive - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - diff --git a/src/QAToolKit.Source.Swagger/QAToolKit.Source.Swagger.csproj b/src/QAToolKit.Source.Swagger/QAToolKit.Source.Swagger.csproj index 9d0515c..5b9284f 100644 --- a/src/QAToolKit.Source.Swagger/QAToolKit.Source.Swagger.csproj +++ b/src/QAToolKit.Source.Swagger/QAToolKit.Source.Swagger.csproj @@ -1,11 +1,7 @@  -<<<<<<< HEAD netstandard2.0;netstandard2.1;net7.0 -======= - netstandard2.0;netstandard2.1;netcoreapp3.1;net6.0 ->>>>>>> main true latest ee940718-945a-4c34-8ce6-0790972ada44 @@ -23,11 +19,7 @@ https://github.com/qatoolkit/qatoolkit-source-swagger-net qatoolkit-64x64.png https://github.com/qatoolkit/qatoolkit-source-swagger-net -<<<<<<< HEAD qatoolkit-source-swagger-net;.net;c#;f#;swagger;dotnet;netstandard;net7 -======= - qatoolkit-source-swagger-net;.net;c#;f#;swagger;dotnet;netstandard;net6 ->>>>>>> main Debug;Release @@ -46,9 +38,6 @@ - netstandard2.0;netstandard2.1;net7.0 - qatoolkit-source-swagger-net;.net;c#;f#;swagger;dotnet;netstandard;net7 - diff --git a/src/QAToolKit.Source.Swagger/SwaggerProcessor.cs b/src/QAToolKit.Source.Swagger/SwaggerProcessor.cs index b8be58d..3c708ab 100644 --- a/src/QAToolKit.Source.Swagger/SwaggerProcessor.cs +++ b/src/QAToolKit.Source.Swagger/SwaggerProcessor.cs @@ -265,7 +265,7 @@ private HttpMethod GetHttpMethod(KeyValuePair o #elif NETCOREAPP3_1 case "patch": return HttpMethod.Patch; -#elif NET6_0 +#elif NET7_0 case "patch": return HttpMethod.Patch; #endif