From 18b57d5661534942495377f78314c27d92d39634 Mon Sep 17 00:00:00 2001 From: dvonthenen Date: Thu, 21 Mar 2024 20:43:57 -0700 Subject: [PATCH] Custom Headers and Better Timeout --- .../ClientTests/AbstractRestClientTests.cs | 93 ++-- .../ClientTests/AnalyzeClientTests.cs | 227 +++++---- .../UnitTests/ClientTests/LiveClientTests.cs | 37 +- .../UnitTests/ClientTests/ManageClientTest.cs | 323 ++++++++----- .../ClientTests/OnPremClientTests.cs | 53 ++- .../ClientTests/PrerecordedClientTests.cs | 225 +++++---- .../UnitTests/ClientTests/SpeakClientTests.cs | 92 ++-- .../HttpClientExtensionTests.cs | 10 +- .../LoggerProviderTests/LogProviderTest.cs | 2 +- .../UtilitiesTests/QueryParameterUtilTests.cs | 49 +- .../UtilitiesTests/RequestContentUtilTests.cs | 12 +- Deepgram/Abstractions/AbstractRestClient.cs | 444 ++++++++++++++---- Deepgram/Abstractions/Constants.cs | 17 + .../Abstractions/LocalFileWithMetadata.cs | 12 + .../Utilities.cs} | 6 +- Deepgram/Clients/Analyze/v1/Client.cs | 56 +-- Deepgram/Clients/Live/v1/Client.cs | 60 ++- Deepgram/Clients/Manage/v1/Client.cs | 163 ++++--- Deepgram/Clients/OnPrem/v1/Client.cs | 28 +- Deepgram/Clients/PreRecorded/v1/Client.cs | 58 +-- Deepgram/Clients/Speak/v1/Client.cs | 33 +- Deepgram/Clients/Speak/v1/Constants.cs | 2 +- Deepgram/Deepgram.csproj | 12 + Deepgram/Factory/HttpClientFactory.cs | 7 +- Deepgram/Models/Analyze/v1/NoopSchema.cs | 10 + Deepgram/Models/Live/v1/NoopSchema.cs | 10 + Deepgram/Models/Manage/v1/NoopSchema.cs | 10 + Deepgram/Models/OnPrem/v1/NoopSchema.cs | 10 + Deepgram/Models/PreRecorded/v1/NoopSchema.cs | 10 + Deepgram/Models/Speak/v1/NoopSchema.cs | 10 + Deepgram/Utilities/QueryParameterUtil.cs | 128 ++--- examples/prerecorded/Prerecorded.csproj | 2 +- examples/prerecorded/Program.cs | 1 + examples/speak/Program.cs | 1 + examples/speak/Speak.csproj | 2 +- examples/streaming/Program.cs | 5 +- 36 files changed, 1393 insertions(+), 827 deletions(-) create mode 100644 Deepgram/Abstractions/Constants.cs create mode 100644 Deepgram/Abstractions/LocalFileWithMetadata.cs rename Deepgram/{Utilities/RequestContentUtil.cs => Abstractions/Utilities.cs} (93%) create mode 100644 Deepgram/Models/Analyze/v1/NoopSchema.cs create mode 100644 Deepgram/Models/Live/v1/NoopSchema.cs create mode 100644 Deepgram/Models/Manage/v1/NoopSchema.cs create mode 100644 Deepgram/Models/OnPrem/v1/NoopSchema.cs create mode 100644 Deepgram/Models/PreRecorded/v1/NoopSchema.cs create mode 100644 Deepgram/Models/Speak/v1/NoopSchema.cs diff --git a/Deepgram.Tests/UnitTests/ClientTests/AbstractRestClientTests.cs b/Deepgram.Tests/UnitTests/ClientTests/AbstractRestClientTests.cs index c145e906..177a5d38 100644 --- a/Deepgram.Tests/UnitTests/ClientTests/AbstractRestClientTests.cs +++ b/Deepgram.Tests/UnitTests/ClientTests/AbstractRestClientTests.cs @@ -27,26 +27,30 @@ public void Setup() [Test] public void GetAsync_Should_Throws_HttpRequestException_On_UnsuccessfulResponse() { - // Arrange + // Input and Output var expectedResponse = new AutoFaker().Generate(); - var httpClient = MockHttpClient.CreateHttpClientWithException(new HttpRequestException()); + // Fake Clients + var httpClient = MockHttpClient.CreateHttpClientWithException(new HttpRequestException()); var client = new ConcreteRestClient(_apiKey, _clientOptions); + // Act & Assert - client.Invoking(y => y.GetAsync(UriSegments.PROJECTS)) + client.Invoking(y => y.GetAsync($"{Defaults.DEFAULT_URI}/{UriSegments.PROJECTS}")) .Should().ThrowAsync(); } [Test] public void GetAsync_Should_Throws_Exception_On_UnsuccessfulResponse() { - // Arrange + // Input and Output var expectedResponse = new AutoFaker().Generate(); - var httpClient = MockHttpClient.CreateHttpClientWithException(new Exception()); + // Fake Clients + var httpClient = MockHttpClient.CreateHttpClientWithException(new Exception()); var client = new ConcreteRestClient(_apiKey, _clientOptions); + // Act & Assert - client.Invoking(y => y.GetAsync(UriSegments.PROJECTS)) + client.Invoking(y => y.GetAsync($"{Defaults.DEFAULT_URI}/{UriSegments.PROJECTS}")) .Should().ThrowAsync(); } @@ -54,15 +58,16 @@ public void GetAsync_Should_Throws_Exception_On_UnsuccessfulResponse() [Test] public void PostAsync_Which_Handles_HttpContent_Should_Throw_Exception_On_UnsuccessfulResponse() { - // Arrange + // Input and Output var response = new AutoFaker().Generate(); var httpContent = Substitute.For(); - var httpClient = MockHttpClient.CreateHttpClientWithException(new Exception()); + // Fake Clients + var httpClient = MockHttpClient.CreateHttpClientWithException(new Exception()); var client = new ConcreteRestClient(_apiKey, _clientOptions); // Act & Assert - client.Invoking(y => y.PostAsync(UriSegments.PROJECTS, httpContent)) + client.Invoking(y => y.PostAsync(UriSegments.PROJECTS, httpContent)) .Should().ThrowAsync(); } @@ -70,14 +75,16 @@ public void PostAsync_Which_Handles_HttpContent_Should_Throw_Exception_On_Unsucc [Test] public void PostAsync_Which_Handles_HttpContent_Should_Throw_HttpRequestException_On_UnsuccessfulResponse() { - // Arrange + // Input and Output var response = new AutoFaker().Generate(); var httpContent = Substitute.For(); + + // Fake Clients var httpClient = MockHttpClient.CreateHttpClientWithException(new HttpRequestException()); var client = new ConcreteRestClient(_apiKey, _clientOptions); // Act & Assert - client.Invoking(y => y.PostAsync(UriSegments.PROJECTS, httpContent)) + client.Invoking(y => y.PostAsync(UriSegments.PROJECTS, httpContent)) .Should().ThrowAsync(); } @@ -85,30 +92,32 @@ public void PostAsync_Which_Handles_HttpContent_Should_Throw_HttpRequestExceptio [Test] public void PostAsync_Should_Throw_Exception_On_UnsuccessfulResponse() { - // Arrange + // Input and Output var response = new AutoFaker().Generate(); - var httpClient = MockHttpClient.CreateHttpClientWithException(new Exception()); + // Fake Clients + var httpClient = MockHttpClient.CreateHttpClientWithException(new Exception()); var client = new ConcreteRestClient(_apiKey, _clientOptions); // Act & Assert client.Invoking(y => - y.PostAsync(UriSegments.PROJECTS, new StringContent(string.Empty))) + y.PostAsync(UriSegments.PROJECTS, new StringContent(string.Empty))) .Should().ThrowAsync(); } [Test] public void PostAsync_Should_Throw_HttpRequestException_On_UnsuccessfulResponse() { - // Arrange + // Input and Output var response = new AutoFaker().Generate(); - var httpClient = MockHttpClient.CreateHttpClientWithException(new HttpRequestException()); + // Fake Clients + var httpClient = MockHttpClient.CreateHttpClientWithException(new HttpRequestException()); var client = new ConcreteRestClient(_apiKey, _clientOptions); // Act & Assert client.Invoking(y => - y.PostAsync(UriSegments.PROJECTS, new StringContent(string.Empty))) + y.PostAsync(UriSegments.PROJECTS, new StringContent(string.Empty))) .Should().ThrowAsync(); } @@ -117,13 +126,14 @@ public void PostAsync_Should_Throw_HttpRequestException_On_UnsuccessfulResponse( [Test] public async Task Delete_Should_Throws_HttpRequestException_On_Response_Containing_Error() { - // Arrange + // Input and Output var httpClient = MockHttpClient.CreateHttpClientWithException(new HttpRequestException()); + // Fake Clients var client = new ConcreteRestClient(_apiKey, _clientOptions); // Act & Assert - await client.Invoking(async y => await y.DeleteAsync(UriSegments.PROJECTS)) + await client.Invoking(async y => await y.DeleteAsync($"{Defaults.DEFAULT_URI}/{UriSegments.PROJECTS}")) .Should().ThrowAsync(); } @@ -131,13 +141,14 @@ await client.Invoking(async y => await y.DeleteAsync(UriSegments.PROJECTS)) [Test] public async Task Delete_Should_Throws_Exception_On_Response_Containing_Error() { - // Arrange + // Input and Output var httpClient = MockHttpClient.CreateHttpClientWithException(new Exception()); + // Fake Clients var client = new ConcreteRestClient(_apiKey, _clientOptions); // Act & Assert - await client.Invoking(async y => await y.DeleteAsync(UriSegments.PROJECTS)) + await client.Invoking(async y => await y.DeleteAsync($"{Defaults.DEFAULT_URI}/{UriSegments.PROJECTS}")) .Should().ThrowAsync(); } @@ -145,82 +156,88 @@ await client.Invoking(async y => await y.DeleteAsync(UriSegments.PROJECTS)) [Test] public void DeleteAsync_TResponse_Should_Throws_HttpRequestException_On_UnsuccessfulResponse() { - // Arrange + // Input and Output var expectedResponse = new AutoFaker().Generate(); - var httpClient = MockHttpClient.CreateHttpClientWithException(new HttpRequestException()); + // Fake Clients + var httpClient = MockHttpClient.CreateHttpClientWithException(new HttpRequestException()); var client = new ConcreteRestClient(_apiKey, _clientOptions); // Act & Assert - client.Invoking(y => y.DeleteAsync(UriSegments.PROJECTS)) + client.Invoking(y => y.DeleteAsync($"{Defaults.DEFAULT_URI}/{UriSegments.PROJECTS}")) .Should().ThrowAsync(); } [Test] public void DeleteAsync_TResponse_Should_Throws_Exception_On_UnsuccessfulResponse() { - // Arrange + // Input and Output var expectedResponse = new AutoFaker().Generate(); - var httpClient = MockHttpClient.CreateHttpClientWithException(new Exception()); + // Fake Clients + var httpClient = MockHttpClient.CreateHttpClientWithException(new Exception()); var client = new ConcreteRestClient(_apiKey, _clientOptions); // Act & Assert - client.Invoking(y => y.DeleteAsync(UriSegments.PROJECTS)) + client.Invoking(y => y.DeleteAsync($"{Defaults.DEFAULT_URI}/{UriSegments.PROJECTS}")) .Should().ThrowAsync(); } [Test] public void PatchAsync_TResponse_Should_Throws_HttpRequestException_On_UnsuccessfulResponse() { - // Arrange + // Input and Output var expectedResponse = new AutoFaker().Generate(); - var httpClient = MockHttpClient.CreateHttpClientWithException(new HttpRequestException()); + // Fake Clients + var httpClient = MockHttpClient.CreateHttpClientWithException(new HttpRequestException()); var client = new ConcreteRestClient(_apiKey, _clientOptions); //Act & Assert - client.Invoking(y => y.PatchAsync(UriSegments.PROJECTS, new StringContent(string.Empty))) + client.Invoking(y => y.PatchAsync(UriSegments.PROJECTS, new StringContent(string.Empty))) .Should().ThrowAsync(); } [Test] public void PatchAsync_TResponse_Should_Throws_Exception_On_UnsuccessfulResponse() { - // Arrange + // Input and Output var expectedResponse = new AutoFaker().Generate(); - var httpClient = MockHttpClient.CreateHttpClientWithException(new Exception()); + // Fake Clients + var httpClient = MockHttpClient.CreateHttpClientWithException(new Exception()); var client = new ConcreteRestClient(_apiKey, _clientOptions); //Act & Assert - client.Invoking(y => y.PatchAsync(UriSegments.PROJECTS, new StringContent(string.Empty))) + client.Invoking(y => y.PatchAsync(UriSegments.PROJECTS, new StringContent(string.Empty))) .Should().ThrowAsync(); } - [Test] public void PutAsync_TResponse_Should_Throws_HttpRequestException_On_UnsuccessfulResponse() { - // Arrange + /// Input and Output var httpClient = MockHttpClient.CreateHttpClientWithException(new HttpRequestException()); + // Fake Clients var client = new ConcreteRestClient(_apiKey, _clientOptions); // Act & Assert - client.Invoking(y => y.PutAsync(UriSegments.PROJECTS, new StringContent(string.Empty))) + client.Invoking(y => y.PutAsync(UriSegments.PROJECTS, new StringContent(string.Empty))) .Should().ThrowAsync(); } [Test] public void PutAsync_TResponse_Should_Throws_Exception_On_UnsuccessfulResponse() { - // Arrange + // Input and Output var httpClient = MockHttpClient.CreateHttpClientWithException(new Exception()); + // Fake Clients var client = new ConcreteRestClient(_apiKey, _clientOptions); + // Act & Assert - client.Invoking(y => y.PutAsync(UriSegments.PROJECTS, new StringContent(string.Empty))) + client.Invoking(y => y.PutAsync(UriSegments.PROJECTS, new StringContent(string.Empty))) .Should().ThrowAsync(); } } diff --git a/Deepgram.Tests/UnitTests/ClientTests/AnalyzeClientTests.cs b/Deepgram.Tests/UnitTests/ClientTests/AnalyzeClientTests.cs index 7103fcf6..e848f3f9 100644 --- a/Deepgram.Tests/UnitTests/ClientTests/AnalyzeClientTests.cs +++ b/Deepgram.Tests/UnitTests/ClientTests/AnalyzeClientTests.cs @@ -2,9 +2,9 @@ // Use of this source code is governed by a MIT license that can be found in the LICENSE file. // SPDX-License-Identifier: MIT -using Deepgram.Models.Analyze.v1; using Deepgram.Models.Authenticate.v1; using Deepgram.Clients.Analyze.v1; +using Deepgram.Models.Analyze.v1; namespace Deepgram.Tests.UnitTests.ClientTests; @@ -23,24 +23,26 @@ public void Setup() [Test] public async Task AnalyzeUrl_Should_Call_PostAsync_Returning_SyncResponse() { - //Arrange + // Input and Output + var url = AbstractRestClient.GetUri(_options, $"{UriSegments.READ}"); var expectedResponse = new AutoFaker().Generate(); var analyzeSchema = new AutoFaker().Generate(); analyzeSchema.CallBack = null; - var stringedOptions = QueryParameterUtil.GetParameters(analyzeSchema); var source = new AutoFaker().Generate(); - var httpClient = MockHttpClient.CreateHttpClientWithResult(expectedResponse); + // Fake Clients + var httpClient = MockHttpClient.CreateHttpClientWithResult(expectedResponse); var analyzeClient = Substitute.For(_apiKey, _options); - analyzeClient.When(x => x.PostAsync(Arg.Any(), Arg.Any())).DoNotCallBase(); - analyzeClient.PostAsync($"{UriSegments.READ}?{stringedOptions}", Arg.Any()).Returns(expectedResponse); + // Mock methods + analyzeClient.When(x => x.PostAsync(Arg.Any(), Arg.Any(), Arg.Any())).DoNotCallBase(); + analyzeClient.PostAsync(url, Arg.Any(), Arg.Any()).Returns(expectedResponse); // Act var result = await analyzeClient.AnalyzeUrl(source, analyzeSchema); // Assert - await analyzeClient.Received().PostAsync($"{UriSegments.READ}?{stringedOptions}", Arg.Any()); + await analyzeClient.Received().PostAsync(url, Arg.Any(), Arg.Any()); using (new AssertionScope()) { @@ -53,50 +55,54 @@ public async Task AnalyzeUrl_Should_Call_PostAsync_Returning_SyncResponse() [Test] public async Task AnalyzeUrl_Should_Throw_ArgumentException_If_CallBack_Not_Null() { - //Arrange - var expectedResponse = new AutoFaker().Generate(); + // Input and Output + var url = AbstractRestClient.GetUri(_options, $"{UriSegments.READ}"); + var expectedResponse = new AutoFaker().Generate(); var analyzeSchema = new AutoFaker().Generate(); - var stringedOptions = QueryParameterUtil.GetParameters(analyzeSchema); var source = new AutoFaker().Generate(); - var httpClient = MockHttpClient.CreateHttpClientWithResult(expectedResponse); + // Fake Clients + var httpClient = MockHttpClient.CreateHttpClientWithResult(expectedResponse); var analyzeClient = Substitute.For(_apiKey, _options); - analyzeClient.When(x => x.PostAsync(Arg.Any(), Arg.Any())).DoNotCallBase(); - analyzeClient.PostAsync($"{UriSegments.READ}?{stringedOptions}", Arg.Any()).Returns(expectedResponse); + // Mock methods + analyzeClient.When(x => x.PostAsync(Arg.Any(), Arg.Any())).DoNotCallBase(); + analyzeClient.PostAsync(url, Arg.Any()).Returns(expectedResponse); // Act and Assert await analyzeClient.Invoking(y => y.AnalyzeUrl(source, analyzeSchema)) .Should().ThrowAsync(); - await analyzeClient.DidNotReceive().PostAsync($"{UriSegments.READ}?{stringedOptions}", Arg.Any()); + await analyzeClient.DidNotReceive().PostAsync(url, Arg.Any()); } [Test] public async Task AnalyzeUrlCallBack_Should_Call_PostAsync_Returning_SyncResponse_With_CallBack_Parameter() { - //Arrange + // Input and Output + var url = AbstractRestClient.GetUri(_options, $"{UriSegments.READ}"); var expectedResponse = new AutoFaker().Generate(); var source = new AutoFaker().Generate(); var analyzeSchema = new AutoFaker().Generate(); // analyzeSchema is not null here as we first need to get the querystring with the callBack included - var stringedQuery = QueryParameterUtil.GetParameters(analyzeSchema); + + // Fake Clients var httpClient = MockHttpClient.CreateHttpClientWithResult(expectedResponse); - var analyzeClient = Substitute.For(_apiKey, _options); - analyzeClient.When(x => x.PostAsync(Arg.Any(), Arg.Any())).DoNotCallBase(); - analyzeClient.PostAsync($"{UriSegments.READ}?{stringedQuery}", Arg.Any()).Returns(expectedResponse); - var callBackParameter = analyzeSchema.CallBack; + // Mock methods + analyzeClient.When(x => x.PostAsync(Arg.Any(), Arg.Any(), Arg.Any())).DoNotCallBase(); + analyzeClient.PostAsync(url, Arg.Any(), Arg.Any()).Returns(expectedResponse); + //before we act to test this call with the callBack parameter and not the callBack property we need to null the callBack property + var callBackParameter = analyzeSchema.CallBack; analyzeSchema.CallBack = null; - // Act var result = await analyzeClient.AnalyzeUrlCallBack(source, callBackParameter, analyzeSchema); // Assert - await analyzeClient.Received().PostAsync($"{UriSegments.READ}?{stringedQuery}", Arg.Any()); + await analyzeClient.Received().PostAsync(url, Arg.Any(), Arg.Any()); using (new AssertionScope()) { result.Should().NotBeNull(); @@ -108,23 +114,25 @@ public async Task AnalyzeUrlCallBack_Should_Call_PostAsync_Returning_SyncRespons [Test] public async Task AnalyzeUrlCallBack_Should_Call_PostAsync_Returning_SyncResponse_With_CallBack_Property() { - //Arrange + // Input and Output + var url = AbstractRestClient.GetUri(_options, $"{UriSegments.READ}"); var expectedResponse = new AutoFaker().Generate(); var source = new AutoFaker().Generate(); var analyzeSchema = new AutoFaker().Generate(); - var stringedQuery = QueryParameterUtil.GetParameters(analyzeSchema); + + // Fake Clients var httpClient = MockHttpClient.CreateHttpClientWithResult(expectedResponse); - var analyzeClient = Substitute.For(_apiKey, _options); - analyzeClient.When(x => x.PostAsync(Arg.Any(), Arg.Any())).DoNotCallBase(); - analyzeClient.PostAsync($"{UriSegments.READ}?{stringedQuery}", Arg.Any()).Returns(expectedResponse); + // Mock methods + analyzeClient.When(x => x.PostAsync(Arg.Any(), Arg.Any(), Arg.Any())).DoNotCallBase(); + analyzeClient.PostAsync(url, Arg.Any(), Arg.Any()).Returns(expectedResponse); // Act var result = await analyzeClient.AnalyzeUrlCallBack(source, null, analyzeSchema); // Assert - await analyzeClient.Received().PostAsync($"{UriSegments.READ}?{stringedQuery}", Arg.Any()); + await analyzeClient.Received().PostAsync(url, Arg.Any(), Arg.Any()); using (new AssertionScope()) { result.Should().NotBeNull(); @@ -136,71 +144,76 @@ public async Task AnalyzeUrlCallBack_Should_Call_PostAsync_Returning_SyncRespons [Test] public async Task AnalyzeUrlCallBack_Should_Throw_ArgumentException_With_CallBack_Property_And_CallBack_Parameter_Set() { - //Arrange + // Input and Output + var url = AbstractRestClient.GetUri(_options, $"{UriSegments.READ}"); var expectedResponse = new AutoFaker().Generate(); var source = new AutoFaker().Generate(); var analyzeSchema = new AutoFaker().Generate(); - var stringedQuery = QueryParameterUtil.GetParameters(analyzeSchema); - + + // Fake Clients var httpClient = MockHttpClient.CreateHttpClientWithResult(expectedResponse); var analyzeClient = Substitute.For(_apiKey, _options); - analyzeClient.When(x => x.PostAsync(Arg.Any(), Arg.Any())).DoNotCallBase(); - analyzeClient.PostAsync($"{UriSegments.READ}?{stringedQuery}", Arg.Any()).Returns(expectedResponse); + // Mock methods + analyzeClient.When(x => x.PostAsync(Arg.Any(), Arg.Any())).DoNotCallBase(); + analyzeClient.PostAsync(url, Arg.Any()).Returns(expectedResponse); var callBackParameter = analyzeSchema.CallBack; - // Act Assert + // Act and Assert await analyzeClient.Invoking(y => y.AnalyzeUrlCallBack(source, callBackParameter, analyzeSchema)) .Should().ThrowAsync(); - await analyzeClient.DidNotReceive().PostAsync($"{UriSegments.READ}?{stringedQuery}", Arg.Any()); + await analyzeClient.DidNotReceive().PostAsync(url, Arg.Any()); } [Test] public async Task AnalyzeUrlCallBack_Should_Throw_ArgumentException_With_No_CallBack_Set() { - //Arrange - var expectedResponse = new AutoFaker().Generate(); + // Input and Output + var url = AbstractRestClient.GetUri(_options, $"{UriSegments.READ}"); + var expectedResponse = new AutoFaker().Generate(); var source = new AutoFaker().Generate(); var analyzeSchema = new AutoFaker().Generate(); analyzeSchema.CallBack = null; - var stringedQuery = QueryParameterUtil.GetParameters(analyzeSchema); - + + // Fake Clients var httpClient = MockHttpClient.CreateHttpClientWithResult(expectedResponse); var analyzeClient = Substitute.For(_apiKey, _options); - analyzeClient.When(x => x.PostAsync(Arg.Any(), Arg.Any())).DoNotCallBase(); - analyzeClient.PostAsync($"{UriSegments.READ}?{stringedQuery}", Arg.Any()).Returns(expectedResponse); - + // Mock methods + analyzeClient.When(x => x.PostAsync(Arg.Any(), Arg.Any())).DoNotCallBase(); + analyzeClient.PostAsync(url, Arg.Any()).Returns(expectedResponse); - // Act Assert + // Act and Assert await analyzeClient.Invoking(y => y.AnalyzeUrlCallBack(source, null, analyzeSchema)) .Should().ThrowAsync(); - await analyzeClient.DidNotReceive().PostAsync($"{UriSegments.READ}?{stringedQuery}", Arg.Any()); + await analyzeClient.DidNotReceive().PostAsync(url, Arg.Any()); } [Test] public async Task AnalyzeFile_With_Stream_Should_Call_PostAsync_Returning_SyncResponse() { - //Arrange + // Input and Output + var url = AbstractRestClient.GetUri(_options, $"{UriSegments.READ}"); var expectedResponse = new AutoFaker().Generate(); var analyzeSchema = new AutoFaker().Generate(); analyzeSchema.CallBack = null; - var stringedOptions = QueryParameterUtil.GetParameters(analyzeSchema); var source = GetFakeStream(GetFakeByteArray()); - var httpClient = MockHttpClient.CreateHttpClientWithResult(expectedResponse); + // Fake Clients + var httpClient = MockHttpClient.CreateHttpClientWithResult(expectedResponse); var analyzeClient = Substitute.For(_apiKey, _options); - analyzeClient.When(x => x.PostAsync(Arg.Any(), Arg.Any())).DoNotCallBase(); - analyzeClient.PostAsync($"{UriSegments.READ}?{stringedOptions}", Arg.Any()).Returns(expectedResponse); + // Mock methods + analyzeClient.When(x => x.PostAsync(Arg.Any(), Arg.Any(), Arg.Any())).DoNotCallBase(); + analyzeClient.PostAsync(url, Arg.Any(), Arg.Any()).Returns(expectedResponse); // Act var result = await analyzeClient.AnalyzeFile(source, analyzeSchema); // Assert - await analyzeClient.Received().PostAsync($"{UriSegments.READ}?{stringedOptions}", Arg.Any()); + await analyzeClient.Received().PostAsync(url, Arg.Any(), Arg.Any()); using (new AssertionScope()) { result.Should().NotBeNull(); @@ -212,24 +225,26 @@ public async Task AnalyzeFile_With_Stream_Should_Call_PostAsync_Returning_SyncRe [Test] public async Task AnalyzeFile_With_Bytes_Should_Call_PostAsync_Returning_SyncResponse() { - //Arrange + // Input and Output + var url = AbstractRestClient.GetUri(_options, $"{UriSegments.READ}"); var expectedResponse = new AutoFaker().Generate(); var analyzeSchema = new AutoFaker().Generate(); analyzeSchema.CallBack = null; - var stringedOptions = QueryParameterUtil.GetParameters(analyzeSchema); var source = GetFakeByteArray(); - var httpClient = MockHttpClient.CreateHttpClientWithResult(expectedResponse); + // Fake Clients + var httpClient = MockHttpClient.CreateHttpClientWithResult(expectedResponse); var analyzeClient = Substitute.For(_apiKey, _options); - analyzeClient.When(x => x.PostAsync(Arg.Any(), Arg.Any())).DoNotCallBase(); - analyzeClient.PostAsync($"{UriSegments.READ}?{stringedOptions}", Arg.Any()).Returns(expectedResponse); + // Mock methods + analyzeClient.When(x => x.PostAsync(Arg.Any(), Arg.Any(), Arg.Any())).DoNotCallBase(); + analyzeClient.PostAsync(url, Arg.Any(), Arg.Any()).Returns(expectedResponse); // Act var result = await analyzeClient.AnalyzeFile(source, analyzeSchema); // Assert - await analyzeClient.Received().PostAsync($"{UriSegments.READ}?{stringedOptions}", Arg.Any()); + await analyzeClient.Received().PostAsync(url, Arg.Any(), Arg.Any()); using (new AssertionScope()) { result.Should().NotBeNull(); @@ -241,23 +256,25 @@ public async Task AnalyzeFile_With_Bytes_Should_Call_PostAsync_Returning_SyncRes [Test] public async Task AnalyzeFileCallBack_With_Stream_With_CallBack_Property_Should_Call_PostAsync_Returning_SyncResponse() { - //Arrange + // Input and Output + var url = AbstractRestClient.GetUri(_options, $"{UriSegments.READ}"); var expectedResponse = new AutoFaker().Generate(); var analyzeSchema = new AutoFaker().Generate(); - var stringedOptions = QueryParameterUtil.GetParameters(analyzeSchema); var source = GetFakeStream(GetFakeByteArray()); - var httpClient = MockHttpClient.CreateHttpClientWithResult(expectedResponse); + // Fake Clients + var httpClient = MockHttpClient.CreateHttpClientWithResult(expectedResponse); var analyzeClient = Substitute.For(_apiKey, _options); - analyzeClient.When(x => x.PostAsync(Arg.Any(), Arg.Any())).DoNotCallBase(); - analyzeClient.PostAsync($"{UriSegments.READ}?{stringedOptions}", Arg.Any()).Returns(expectedResponse); + // Mock methods + analyzeClient.When(x => x.PostAsync(Arg.Any(), Arg.Any(), Arg.Any())).DoNotCallBase(); + analyzeClient.PostAsync(url, Arg.Any(), Arg.Any()).Returns(expectedResponse); // Act var result = await analyzeClient.AnalyzeFileCallBack(source, null, analyzeSchema); // Assert - await analyzeClient.Received().PostAsync($"{UriSegments.READ}?{stringedOptions}", Arg.Any()); + await analyzeClient.Received().PostAsync(url, Arg.Any(), Arg.Any()); using (new AssertionScope()) { result.Should().NotBeNull(); @@ -269,23 +286,25 @@ public async Task AnalyzeFileCallBack_With_Stream_With_CallBack_Property_Should_ [Test] public async Task AnalyzeFileCallBack_With_Bytes_With_CallBack_Property_Should_Call_PostAsync_Returning_SyncResponse() { - //Arrange + // Input and Output + var url = AbstractRestClient.GetUri(_options, $"{UriSegments.READ}"); var expectedResponse = new AutoFaker().Generate(); var analyzeSchema = new AutoFaker().Generate(); - var stringedOptions = QueryParameterUtil.GetParameters(analyzeSchema); var source = GetFakeByteArray(); - var httpClient = MockHttpClient.CreateHttpClientWithResult(expectedResponse); + // Fake Clients + var httpClient = MockHttpClient.CreateHttpClientWithResult(expectedResponse); var analyzeClient = Substitute.For(_apiKey, _options); - analyzeClient.When(x => x.PostAsync(Arg.Any(), Arg.Any())).DoNotCallBase(); - analyzeClient.PostAsync($"{UriSegments.READ}?{stringedOptions}", Arg.Any()).Returns(expectedResponse); + // Mock methods + analyzeClient.When(x => x.PostAsync(Arg.Any(), Arg.Any(), Arg.Any())).DoNotCallBase(); + analyzeClient.PostAsync(url, Arg.Any(), Arg.Any()).Returns(expectedResponse); // Act var result = await analyzeClient.AnalyzeFileCallBack(source, null, analyzeSchema); // Assert - await analyzeClient.Received().PostAsync($"{UriSegments.READ}?{stringedOptions}", Arg.Any()); + await analyzeClient.Received().PostAsync(url, Arg.Any(), Arg.Any()); using (new AssertionScope()) { @@ -298,29 +317,29 @@ public async Task AnalyzeFileCallBack_With_Bytes_With_CallBack_Property_Should_C [Test] public async Task AnalyzeFileCallBack_With_Stream_With_CallBack_Parameter_Should_Call_PostAsync_Returning_SyncResponse() { - //Arrange + // Input and Output + var url = AbstractRestClient.GetUri(_options, $"{UriSegments.READ}"); var expectedResponse = new AutoFaker().Generate(); var analyzeSchema = new AutoFaker().Generate(); - // analyzeSchema is not null here as we first need to get the querystring with the callBack included - var stringedOptions = QueryParameterUtil.GetParameters(analyzeSchema); var source = GetFakeStream(GetFakeByteArray()); - var httpClient = MockHttpClient.CreateHttpClientWithResult(expectedResponse); + // Fake Clients + var httpClient = MockHttpClient.CreateHttpClientWithResult(expectedResponse); var analyzeClient = Substitute.For(_apiKey, _options); - analyzeClient.When(x => x.PostAsync(Arg.Any(), Arg.Any())).DoNotCallBase(); - analyzeClient.PostAsync($"{UriSegments.READ}?{stringedOptions}", Arg.Any()).Returns(expectedResponse); - - var callBack = analyzeSchema.CallBack; + // Mock methods + analyzeClient.When(x => x.PostAsync(Arg.Any(), Arg.Any(), Arg.Any())).DoNotCallBase(); + analyzeClient.PostAsync(url, Arg.Any(), Arg.Any()).Returns(expectedResponse); //before we act to test this call with the callBack parameter and not the callBack property we need to null the callBack property + var callBack = analyzeSchema.CallBack; analyzeSchema.CallBack = null; // Act var result = await analyzeClient.AnalyzeFileCallBack(source, callBack, analyzeSchema); // Assert - await analyzeClient.Received().PostAsync($"{UriSegments.READ}?{stringedOptions}", Arg.Any()); + await analyzeClient.Received().PostAsync(url, Arg.Any(), Arg.Any()); using (new AssertionScope()) { result.Should().NotBeNull(); @@ -332,29 +351,29 @@ public async Task AnalyzeFileCallBack_With_Stream_With_CallBack_Parameter_Should [Test] public async Task AnalyzeFileCallBack_With_Bytes_With_CallBack_Parameter_Should_Call_PostAsync_Returning_SyncResponse() { - //Arrange + // Input and Output + var url = AbstractRestClient.GetUri(_options, $"{UriSegments.READ}"); var expectedResponse = new AutoFaker().Generate(); var analyzeSchema = new AutoFaker().Generate(); - // analyzeSchema is not null here as we first need to get the querystring with the callBack included - var stringedOptions = QueryParameterUtil.GetParameters(analyzeSchema); var source = GetFakeByteArray(); + // Fake Clients var httpClient = MockHttpClient.CreateHttpClientWithResult(expectedResponse); var analyzeClient = Substitute.For(_apiKey, _options); - analyzeClient.When(x => x.PostAsync(Arg.Any(), Arg.Any())).DoNotCallBase(); - analyzeClient.PostAsync($"{UriSegments.READ}?{stringedOptions}", Arg.Any()).Returns(expectedResponse); - - var callBack = analyzeSchema.CallBack; + // Mock methods + analyzeClient.When(x => x.PostAsync(Arg.Any(), Arg.Any(), Arg.Any())).DoNotCallBase(); + analyzeClient.PostAsync(url, Arg.Any(), Arg.Any()).Returns(expectedResponse); //before we act to test this call with the callBack parameter and not the callBack property we need to null the callBack property + var callBack = analyzeSchema.CallBack; analyzeSchema.CallBack = null; // Act var result = await analyzeClient.AnalyzeFileCallBack(source, callBack, analyzeSchema); // Assert - await analyzeClient.Received().PostAsync($"{UriSegments.READ}?{stringedOptions}", Arg.Any()); + await analyzeClient.Received().PostAsync(url, Arg.Any(), Arg.Any()); using (new AssertionScope()) { result.Should().NotBeNull(); @@ -366,51 +385,53 @@ public async Task AnalyzeFileCallBack_With_Bytes_With_CallBack_Parameter_Should_ [Test] public async Task AnalyzeFileCallBack_With_Stream_Throw_ArgumentException_With_CallBack_Property_And_CallBack_Parameter_Set() { - //Arrange + // Input and Output + var url = AbstractRestClient.GetUri(_options, $"{UriSegments.READ}"); var expectedResponse = new AutoFaker().Generate(); var analyzeSchema = new AutoFaker().Generate(); - var stringedOptions = QueryParameterUtil.GetParameters(analyzeSchema); var source = GetFakeStream(GetFakeByteArray()); - var httpClient = MockHttpClient.CreateHttpClientWithResult(expectedResponse); + // Fake Clients + var httpClient = MockHttpClient.CreateHttpClientWithResult(expectedResponse); var analyzeClient = Substitute.For(_apiKey, _options); - analyzeClient.When(x => x.PostAsync(Arg.Any(), Arg.Any())).DoNotCallBase(); - analyzeClient.PostAsync($"{UriSegments.READ}?{stringedOptions}", Arg.Any()).Returns(expectedResponse); + // Mock methods + analyzeClient.When(x => x.PostAsync(Arg.Any(), Arg.Any(), Arg.Any())).DoNotCallBase(); + analyzeClient.PostAsync(url, Arg.Any(), Arg.Any()).Returns(expectedResponse); + var callBack = analyzeSchema.CallBack; - - // Act Assert + // Act and Assert await analyzeClient.Invoking(y => y.AnalyzeFileCallBack(source, callBack, analyzeSchema)) .Should().ThrowAsync(); - await analyzeClient.DidNotReceive().PostAsync($"{UriSegments.READ}?{stringedOptions}", Arg.Any()); - - + await analyzeClient.DidNotReceive().PostAsync(url, Arg.Any(), Arg.Any()); } [Test] public async Task AnalyzeFileCallBack_With_Bytes_Should_Throw_ArgumentException_With_No_CallBack_Set() { - //Arrange + // Input and Output + var url = AbstractRestClient.GetUri(_options, $"{UriSegments.READ}"); var expectedResponse = new AutoFaker().Generate(); - var analyzeSchema = new AutoFaker().Generate(); - // analyzeSchema is not null here as we first need to get the querystring with the callBack included - var stringedOptions = QueryParameterUtil.GetParameters(analyzeSchema); + var analyzeSchema = new AutoFaker().Generate(); var source = GetFakeByteArray(); + // Fake Clients var httpClient = MockHttpClient.CreateHttpClientWithResult(expectedResponse); var analyzeClient = Substitute.For(_apiKey, _options); - analyzeClient.When(x => x.PostAsync(Arg.Any(), Arg.Any())).DoNotCallBase(); - analyzeClient.PostAsync($"{UriSegments.READ}?{stringedOptions}", Arg.Any()).Returns(expectedResponse); + // Mock methods + analyzeClient.When(x => x.PostAsync(Arg.Any(), Arg.Any(), Arg.Any())).DoNotCallBase(); + analyzeClient.PostAsync(url, Arg.Any(), Arg.Any()).Returns(expectedResponse); + analyzeSchema.CallBack = null; - // Act Assert + // Act and Assert await analyzeClient.Invoking(y => y.AnalyzeFileCallBack(source, null, analyzeSchema)) .Should().ThrowAsync(); - await analyzeClient.DidNotReceive().PostAsync($"{UriSegments.READ}?{stringedOptions}", Arg.Any()); + await analyzeClient.DidNotReceive().PostAsync(url, Arg.Any(), Arg.Any()); } private static Stream GetFakeStream(byte[] source) diff --git a/Deepgram.Tests/UnitTests/ClientTests/LiveClientTests.cs b/Deepgram.Tests/UnitTests/ClientTests/LiveClientTests.cs index c86b5a3c..0be41896 100644 --- a/Deepgram.Tests/UnitTests/ClientTests/LiveClientTests.cs +++ b/Deepgram.Tests/UnitTests/ClientTests/LiveClientTests.cs @@ -28,27 +28,31 @@ public void Setup() [TearDown] public void Teardown() - { _liveClient.Dispose(); } + { + if (_liveClient != null) + _liveClient.Dispose(); + } [Test] public void ProcessDataReceived_Should_Raise_TranscriptReceived_Event_When_Response_Contains_Type_TranscriptionResponse() { - //Arrange + // Input and Output var liveTranscriptionResponse = new AutoFaker().Generate(); + // ensure the right type is set for testing liveTranscriptionResponse.Type = LiveType.Results; var json = JsonSerializer.Serialize(liveTranscriptionResponse); var memoryStream = new MemoryStream(Encoding.UTF8.GetBytes(json)); - ResponseEventArgs? eventArgs = null; + // Eventing + ResponseEventArgs? eventArgs = null; _liveClient.EventResponseReceived += (sender, args) => eventArgs = args; - //Act _liveClient.ProcessDataReceived(_webSocketReceiveResult, memoryStream); Task.Delay(5000); - //Assert + //Assert eventArgs.Should().NotBeNull(); eventArgs!.Response.Transcription.Should().NotBeNull(); eventArgs.Response.Transcription.Should().BeAssignableTo(); @@ -57,15 +61,16 @@ public void ProcessDataReceived_Should_Raise_TranscriptReceived_Event_When_Respo [Test] public void ProcessDataReceived_Should_Raise_MetaDataReceived_Event_When_Response_Contains_Type_MetadataResponse() { - //Arrange + // Input and Output var liveMetadataResponse = new AutoFaker().Generate(); + // ensure the right type is set for testing liveMetadataResponse.Type = LiveType.Metadata; var json = JsonSerializer.Serialize(liveMetadataResponse); var memoryStream = new MemoryStream(Encoding.UTF8.GetBytes(json)); + // Eventing ResponseEventArgs? eventArgs = null; - _liveClient.EventResponseReceived += (sender, args) => eventArgs = args; //Act @@ -83,13 +88,13 @@ public void ProcessDataReceived_Should_Raise_MetaDataReceived_Event_When_Respons [Test] public void ProcessDataReceived_Should_Raise_LiveError_Event_When_Response_Contains_Unknown_Type() { - //Arrange + // Input and Output var unknownDataResponse = new Dictionary() { { "Wiley", "coyote" } }; var json = JsonSerializer.Serialize(unknownDataResponse); var memoryStream = new MemoryStream(Encoding.UTF8.GetBytes(json)); + // Eventing ResponseEventArgs? eventArgs = null; - _liveClient.EventResponseReceived += (sender, args) => eventArgs = args; //Act @@ -109,31 +114,28 @@ public void ProcessDataReceived_Should_Raise_LiveError_Event_When_Response_Conta [Test] public void GetBaseUrl_Should_Return_WSS_Protocol_When_DeepgramClientOptions_BaseAddress_Contains_No_Protocol() { - //Arrange + // Input and Output var expectedUrl = $"wss://{Defaults.DEFAULT_URI}"; //Act var result = LiveClient.GetBaseUrl(_options); //Assert - result.Should().NotBeNullOrEmpty(); result.Should().StartWith("wss://"); result.Should().BeEquivalentTo(expectedUrl); - } [Test] public void GetBaseUrl_Should_Return_WSS_Protocol_When_BaseAddress_Contains_WSS_Protocol() { - //Arrange + // Input and Output var expectedUrl = $"wss://{Defaults.DEFAULT_URI}"; _options.BaseAddress = $"wss://{Defaults.DEFAULT_URI}"; //Act var result = LiveClient.GetBaseUrl(_options); - //Assert using (new AssertionScope()) { @@ -146,7 +148,7 @@ public void GetBaseUrl_Should_Return_WSS_Protocol_When_BaseAddress_Contains_WSS_ [Test] public void GetUri_Should_Return_Correctly_Formatted_Uri() { - //Arrange + // Input and Output var liveSchema = new LiveSchema() { Diarize = true, @@ -155,8 +157,9 @@ public void GetUri_Should_Return_Correctly_Formatted_Uri() var expectedUriStart = $"wss://{Defaults.DEFAULT_URI}/v1"; var expectedQuery = $"{UriSegments.LISTEN}?diarize=true"; var expectedCompleteUri = new Uri($"{expectedUriStart}/{expectedQuery}"); + //Act - var result = LiveClient.GetUri(liveSchema, _options); + var result = LiveClient.GetUri(_options, liveSchema); //Assert using (new AssertionScope()) @@ -167,8 +170,6 @@ public void GetUri_Should_Return_Correctly_Formatted_Uri() result.ToString().Should().Contain(expectedQuery); result.ToString().Should().BeEquivalentTo(expectedCompleteUri.ToString()); } - } - #endregion } \ No newline at end of file diff --git a/Deepgram.Tests/UnitTests/ClientTests/ManageClientTest.cs b/Deepgram.Tests/UnitTests/ClientTests/ManageClientTest.cs index 05ea5087..e3d80621 100644 --- a/Deepgram.Tests/UnitTests/ClientTests/ManageClientTest.cs +++ b/Deepgram.Tests/UnitTests/ClientTests/ManageClientTest.cs @@ -5,6 +5,8 @@ using Deepgram.Models.Authenticate.v1; using Deepgram.Models.Manage.v1; using Deepgram.Clients.Manage.v1; +using Microsoft.VisualStudio.TestPlatform.ObjectModel.DataCollection; +using NSubstitute; namespace Deepgram.Tests.UnitTests.ClientTests; @@ -25,48 +27,52 @@ public void Setup() [Test] public async Task GetProjects_Should_Call_GetAsync_Returning_ProjectsResponse() { - // Arrange + // Input and Output + var url = AbstractRestClient.GetUri(_options, $"{UriSegments.PROJECTS}"); var expectedResponse = new AutoFaker().Generate(); - var httpClient = MockHttpClient.CreateHttpClientWithResult(expectedResponse); + // Fake Client + var httpClient = MockHttpClient.CreateHttpClientWithResult(expectedResponse); var manageClient = Substitute.For(_apiKey, _options); + // Mock methods manageClient.When(x => x.GetAsync(Arg.Any())).DoNotCallBase(); - manageClient.GetAsync(UriSegments.PROJECTS).Returns(expectedResponse); + manageClient.GetAsync(url).Returns(expectedResponse); // Act var result = await manageClient.GetProjects(); // Assert - await manageClient.Received().GetAsync(UriSegments.PROJECTS); + await manageClient.Received().GetAsync(url); using (new AssertionScope()) { result.Should().NotBeNull(); result.Should().BeAssignableTo(); result.Should().BeEquivalentTo(expectedResponse); - } } [Test] public async Task GetProject_Should_Call_GetAsync_Returning_ProjectResponse() { - - // Arrange + // Input and Output + var url = AbstractRestClient.GetUri(_options, $"{UriSegments.PROJECTS}/{_projectId}"); var expectedResponse = new AutoFaker().Generate(); expectedResponse.ProjectId = _projectId; - var httpClient = MockHttpClient.CreateHttpClientWithResult(expectedResponse); + // Fake Client + var httpClient = MockHttpClient.CreateHttpClientWithResult(expectedResponse); var manageClient = Substitute.For(_apiKey, _options); + // Mock methods manageClient.When(x => x.GetAsync(Arg.Any())).DoNotCallBase(); - manageClient.GetAsync($"{UriSegments.PROJECTS}/{_projectId}").Returns(expectedResponse); + manageClient.GetAsync(url).Returns(expectedResponse); // Act var result = await manageClient.GetProject(_projectId); // Assert - await manageClient.Received().GetAsync($"projects/{_projectId}"); + await manageClient.Received().GetAsync(url); using (new AssertionScope()) { result.Should().NotBeNull(); @@ -78,21 +84,24 @@ public async Task GetProject_Should_Call_GetAsync_Returning_ProjectResponse() [Test] public async Task UpdateProject_Should_Call_PatchAsync_Returning_MessageResponse() { - //Arrange + // Input and Output + var url = AbstractRestClient.GetUri(_options, $"{UriSegments.PROJECTS}/{_projectId}"); var expectedResponse = new AutoFaker().Generate(); var updateProjectSchema = new AutoFaker().Generate(); - var httpClient = MockHttpClient.CreateHttpClientWithResult(expectedResponse); + // Fake Client + var httpClient = MockHttpClient.CreateHttpClientWithResult(expectedResponse); var manageClient = Substitute.For(_apiKey, _options); - manageClient.When(x => x.PatchAsync(Arg.Any(), Arg.Any())).DoNotCallBase(); - manageClient.PatchAsync($"{UriSegments.PROJECTS}/{_projectId}", Arg.Any()).Returns(expectedResponse); + // Mock methods + manageClient.When(x => x.PatchAsync(Arg.Any(), Arg.Any())).DoNotCallBase(); + manageClient.PatchAsync(url, Arg.Any()).Returns(expectedResponse); //Act var result = await manageClient.UpdateProject(_projectId, updateProjectSchema); //Assert - await manageClient.Received().PatchAsync($"{UriSegments.PROJECTS}/{_projectId}", Arg.Any()); + await manageClient.Received().PatchAsync(url, Arg.Any()); using (new AssertionScope()) { result.Should().NotBeNull(); @@ -104,20 +113,23 @@ public async Task UpdateProject_Should_Call_PatchAsync_Returning_MessageResponse [Test] public async Task LeaveProject_Should_Call_DeleteAsync_Returning_MessageResponse() { - //Arrange + // Input and Output + var url = AbstractRestClient.GetUri(_options, $"{UriSegments.PROJECTS}/{_projectId}/leave"); var expectedResponse = new AutoFaker().Generate(); - var httpClient = MockHttpClient.CreateHttpClientWithResult(expectedResponse); + // Fake Client + var httpClient = MockHttpClient.CreateHttpClientWithResult(expectedResponse); var manageClient = Substitute.For(_apiKey, _options); + // Mock methods manageClient.When(x => x.DeleteAsync(Arg.Any())).DoNotCallBase(); - manageClient.DeleteAsync($"{UriSegments.PROJECTS}/{_projectId}/leave").Returns(expectedResponse); + manageClient.DeleteAsync(url).Returns(expectedResponse); //Act var result = await manageClient.LeaveProject(_projectId); //Assert - await manageClient.Received().DeleteAsync($"{UriSegments.PROJECTS}/{_projectId}/leave"); + await manageClient.Received().DeleteAsync(url); using (new AssertionScope()) { @@ -130,19 +142,23 @@ public async Task LeaveProject_Should_Call_DeleteAsync_Returning_MessageResponse [Test] public async Task DeleteProject_Should_Call_DeleteAsync() { - //Arrange - var httpClient = MockHttpClient.CreateHttpClientWithResult(new VoidResponse()); + // Input and Output + var url = AbstractRestClient.GetUri(_options, $"{UriSegments.PROJECTS}/{_projectId}"); + var expectedResponse = new AutoFaker().Generate(); + // Fake Client + var httpClient = MockHttpClient.CreateHttpClientWithResult(expectedResponse); var manageClient = Substitute.For(_apiKey, _options); - manageClient.When(x => x.DeleteAsync(Arg.Any())).DoNotCallBase(); - manageClient.DeleteAsync($"{UriSegments.PROJECTS}/{_projectId}").Returns(Task.CompletedTask); + // Mock methods + manageClient.When(x => x.DeleteAsync< MessageResponse>(Arg.Any())).DoNotCallBase(); + manageClient.DeleteAsync(url).Returns(expectedResponse); // Act await manageClient.DeleteProject(_projectId); // Assert - await manageClient.Received().DeleteAsync($"{UriSegments.PROJECTS}/{_projectId}"); + await manageClient.Received().DeleteAsync(url); } #endregion @@ -151,20 +167,23 @@ public async Task DeleteProject_Should_Call_DeleteAsync() [Test] public async Task GetKeys_Should_Call_GetAsync_Returning_KeysResponse() { - //Arrange + // Input and Output + var url = AbstractRestClient.GetUri(_options, $"{UriSegments.PROJECTS}/{_projectId}/keys"); var expectedResponse = new AutoFaker().Generate(); - var httpClient = MockHttpClient.CreateHttpClientWithResult(expectedResponse); + // Fake Client + var httpClient = MockHttpClient.CreateHttpClientWithResult(expectedResponse); var manageClient = Substitute.For(_apiKey, _options); + // Mock methods manageClient.When(x => x.GetAsync(Arg.Any())).DoNotCallBase(); - manageClient.GetAsync($"{UriSegments.PROJECTS}/{_projectId}/keys").Returns(expectedResponse); + manageClient.GetAsync(url).Returns(expectedResponse); //Act var result = await manageClient.GetKeys(_projectId); //Assert - await manageClient.Received().GetAsync($"{UriSegments.PROJECTS}/{_projectId}/keys"); + await manageClient.Received().GetAsync(url); using (new AssertionScope()) { result.Should().NotBeNull(); @@ -176,20 +195,22 @@ public async Task GetKeys_Should_Call_GetAsync_Returning_KeysResponse() [Test] public async Task GetKey_Should_Call_GetAsync_Returning_KeyResponse() { - //Arrange - var expectedResponse = new AutoFaker().Generate(); + // Input and Output var keyId = new Faker().Random.Guid().ToString(); - var httpClient = MockHttpClient.CreateHttpClientWithResult(expectedResponse); + var url = AbstractRestClient.GetUri(_options, $"{UriSegments.PROJECTS}/{_projectId}/keys/{keyId}"); + var expectedResponse = new AutoFaker().Generate(); + // Fake Client + var httpClient = MockHttpClient.CreateHttpClientWithResult(expectedResponse); var manageClient = Substitute.For(_apiKey, _options); + // Mock methods manageClient.When(x => x.GetAsync(Arg.Any())).DoNotCallBase(); - manageClient.GetAsync($"{UriSegments.PROJECTS}/{_projectId}/keys/{keyId}").Returns(expectedResponse); - + manageClient.GetAsync(url).Returns(expectedResponse); //Act var result = await manageClient.GetKey(_projectId, keyId); - await manageClient.Received().GetAsync($"{UriSegments.PROJECTS}/{_projectId}/keys/{keyId}"); + await manageClient.Received().GetAsync(url); //Assert using (new AssertionScope()) @@ -203,25 +224,26 @@ public async Task GetKey_Should_Call_GetAsync_Returning_KeyResponse() [Test] public async Task CreateKey_Should_Call_PostAsync_Returning_KeyResponse_Without_Expiration_TimeToLive_Set() { - //Arrange + // Input and Output + var url = AbstractRestClient.GetUri(_options, $"{UriSegments.PROJECTS}/{_projectId}/keys"); var expectedResponse = new AutoFaker().Generate(); var createKeySchema = new AutoFaker().Generate(); createKeySchema.ExpirationDate = null; createKeySchema.TimeToLiveInSeconds = null; + // Fake Client var httpClient = MockHttpClient.CreateHttpClientWithResult(expectedResponse); var manageClient = Substitute.For(_apiKey, _options); - manageClient.When(x => x.PostAsync(Arg.Any(), Arg.Any())).DoNotCallBase(); - manageClient.PostAsync($"{UriSegments.PROJECTS}/{_projectId}/keys", Arg.Any()).Returns(expectedResponse); - - + // Mock methods + manageClient.When(x => x.PostAsync(Arg.Any(), Arg.Any())).DoNotCallBase(); + manageClient.PostAsync(url, Arg.Any()).Returns(expectedResponse); //Act var result = await manageClient.CreateKey(_projectId, createKeySchema); //Assert - await manageClient.Received().PostAsync($"{UriSegments.PROJECTS}/{_projectId}/keys", Arg.Any()); + await manageClient.Received().PostAsync(url, Arg.Any()); using (new AssertionScope()) { @@ -234,24 +256,25 @@ public async Task CreateKey_Should_Call_PostAsync_Returning_KeyResponse_Without_ [Test] public async Task CreateKey_Should_Call_PostAsync_Returning_KeyResponse_With_Expiration_Set() { - //Arrange + // Input and Output + var url = AbstractRestClient.GetUri(_options, $"{UriSegments.PROJECTS}/{_projectId}/keys"); var expectedResponse = new AutoFaker().Generate(); var createKeySchema = new AutoFaker().Generate(); createKeySchema.TimeToLiveInSeconds = null; - var httpClient = MockHttpClient.CreateHttpClientWithResult(expectedResponse); + // Fake Client + var httpClient = MockHttpClient.CreateHttpClientWithResult(expectedResponse); var manageClient = Substitute.For(_apiKey, _options); - - manageClient.When(x => x.PostAsync(Arg.Any(), Arg.Any())).DoNotCallBase(); - manageClient.PostAsync($"{UriSegments.PROJECTS}/{_projectId}/keys", Arg.Any()).Returns(expectedResponse); - + // Mock methods + manageClient.When(x => x.PostAsync(Arg.Any(), Arg.Any())).DoNotCallBase(); + manageClient.PostAsync(url, Arg.Any()).Returns(expectedResponse); //Act var result = await manageClient.CreateKey(_projectId, createKeySchema); //Assert - await manageClient.Received().PostAsync($"{UriSegments.PROJECTS}/{_projectId}/keys", Arg.Any()); + await manageClient.Received().PostAsync(url, Arg.Any()); using (new AssertionScope()) { @@ -264,22 +287,25 @@ public async Task CreateKey_Should_Call_PostAsync_Returning_KeyResponse_With_Exp [Test] public async Task CreateKey_Should_Return_KeyResponse_Without_TimeToLive_Set() { - //Arrange + // Input and Output + var url = AbstractRestClient.GetUri(_options, $"{UriSegments.PROJECTS}/{_projectId}/keys"); var expectedResponse = new AutoFaker().Generate(); var createKeySchema = new AutoFaker().Generate(); createKeySchema.ExpirationDate = null; - var httpClient = MockHttpClient.CreateHttpClientWithResult(expectedResponse); + // Fake Client + var httpClient = MockHttpClient.CreateHttpClientWithResult(expectedResponse); var manageClient = Substitute.For(_apiKey, _options); - manageClient.When(x => x.PostAsync(Arg.Any(), Arg.Any())).DoNotCallBase(); - manageClient.PostAsync($"{UriSegments.PROJECTS}/{_projectId}/keys", Arg.Any()).Returns(expectedResponse); + // Mock methods + manageClient.When(x => x.PostAsync(Arg.Any(), Arg.Any())).DoNotCallBase(); + manageClient.PostAsync(url, Arg.Any()).Returns(expectedResponse); //Act var result = await manageClient.CreateKey(_projectId, createKeySchema); //Assert - await manageClient.Received().PostAsync($"{UriSegments.PROJECTS}/{_projectId}/keys", Arg.Any()); + await manageClient.Received().PostAsync(url, Arg.Any()); using (new AssertionScope()) { @@ -292,56 +318,64 @@ public async Task CreateKey_Should_Return_KeyResponse_Without_TimeToLive_Set() [Test] public async Task CreateKey_Should_Throw_ArgumentException_When_Both_Expiration_And_TimeToLive_Set() { - //Arrange + // Input and Output + var url = AbstractRestClient.GetUri(_options, $"{UriSegments.PROJECTS}"); var createKeySchema = new AutoFaker().Generate(); + // Fake Client var manageClient = new ManageClient(_apiKey, _options); //Act & Assert - await manageClient.Invoking(y => y.CreateKey(UriSegments.PROJECTS, createKeySchema)) + await manageClient.Invoking(y => y.CreateKey(url, createKeySchema)) .Should().ThrowAsync(); } [Test] public async Task DeleteKey_Should_Call_DeleteAsync() { - //Arrange + // Input and Output var keyId = new Faker().Random.Guid().ToString(); - var httpClient = MockHttpClient.CreateHttpClientWithResult(new VoidResponse()); + var url = AbstractRestClient.GetUri(_options, $"{UriSegments.PROJECTS}/{_projectId}/keys/{keyId}"); + var expectedResponse = new AutoFaker().Generate(); + // Fake Client + var httpClient = MockHttpClient.CreateHttpClientWithResult(expectedResponse); var manageClient = Substitute.For(_apiKey, _options); - manageClient.When(x => x.DeleteAsync(Arg.Any())).DoNotCallBase(); - manageClient.DeleteAsync($"{UriSegments.PROJECTS}/{_projectId}/keys/{keyId}").Returns(Task.CompletedTask); + // Mock methods + manageClient.When(x => x.DeleteAsync(Arg.Any())).DoNotCallBase(); + manageClient.DeleteAsync(url).Returns(expectedResponse); // Act await manageClient.DeleteKey(_projectId, keyId); // Assert - await manageClient.Received().DeleteAsync($"{UriSegments.PROJECTS}/{_projectId}/keys/{keyId}"); + await manageClient.Received().DeleteAsync(url); } #endregion #region ProjectInvites - [Test] public async Task GetInvites_Should_Call_GetAsync_Returning_InvitesResponse() { - //Arrange + // Input and Output + var url = AbstractRestClient.GetUri(_options, $"{UriSegments.PROJECTS}/{_projectId}/invites"); var expectedResponse = new AutoFaker().Generate(); - var httpClient = MockHttpClient.CreateHttpClientWithResult(expectedResponse); + // Fake Client + var httpClient = MockHttpClient.CreateHttpClientWithResult(expectedResponse); var manageClient = Substitute.For(_apiKey, _options); + // Mock methods manageClient.When(x => x.GetAsync(Arg.Any())).DoNotCallBase(); - manageClient.GetAsync($"{UriSegments.PROJECTS}/{_projectId}/invites").Returns(expectedResponse); + manageClient.GetAsync(url).Returns(expectedResponse); // Act var result = await manageClient.GetInvites(_projectId); // Assert - await manageClient.Received().GetAsync($"{UriSegments.PROJECTS}/{_projectId}/invites"); + await manageClient.Received().GetAsync(url); using (new AssertionScope()) { result.Should().NotBeNull(); @@ -353,21 +387,24 @@ public async Task GetInvites_Should_Call_GetAsync_Returning_InvitesResponse() [Test] public async Task SendInvite_Should_Call_PostAsync_Returning_MessageResponse() { - //Arrange + // Input and Output + var url = AbstractRestClient.GetUri(_options, $"{UriSegments.PROJECTS}/{_projectId}/invites"); var expectedResponse = new AutoFaker().Generate(); var inviteSchema = new AutoFaker().Generate(); - var httpClient = MockHttpClient.CreateHttpClientWithResult(expectedResponse); + // Fake Client + var httpClient = MockHttpClient.CreateHttpClientWithResult(expectedResponse); var manageClient = Substitute.For(_apiKey, _options); - manageClient.When(x => x.PostAsync(Arg.Any(), Arg.Any())).DoNotCallBase(); - manageClient.PostAsync($"{UriSegments.PROJECTS}/{_projectId}/invites", Arg.Any()).Returns(expectedResponse); + // Mock methods + manageClient.When(x => x.PostAsync(Arg.Any(), Arg.Any())).DoNotCallBase(); + manageClient.PostAsync(url, Arg.Any()).Returns(expectedResponse); // Act var result = await manageClient.SendInvite(_projectId, inviteSchema); // Assert - await manageClient.Received().PostAsync($"{UriSegments.PROJECTS}/{_projectId}/invites", Arg.Any()); + await manageClient.Received().PostAsync(url, Arg.Any()); using (new AssertionScope()) { result.Should().NotBeNull(); @@ -379,20 +416,24 @@ public async Task SendInvite_Should_Call_PostAsync_Returning_MessageResponse() [Test] public async Task DeleteInvite_Should_Call_DeleteAsync() { - //Arrange + // Input and Output var email = new Faker().Internet.Email(); - var httpClient = MockHttpClient.CreateHttpClientWithResult(new VoidResponse()); + var url = AbstractRestClient.GetUri(_options, $"{UriSegments.PROJECTS}/{_projectId}/invites/{email}"); + var expectedResponse = new AutoFaker().Generate(); + // Fake Client + var httpClient = MockHttpClient.CreateHttpClientWithResult(expectedResponse); var manageClient = Substitute.For(_apiKey, _options); - manageClient.When(x => x.DeleteAsync(Arg.Any())).DoNotCallBase(); - manageClient.DeleteAsync($"{UriSegments.PROJECTS}/{_projectId}/invites/{email}").Returns(Task.CompletedTask); + // Mock methods + manageClient.When(x => x.DeleteAsync(Arg.Any())).DoNotCallBase(); + manageClient.DeleteAsync(url).Returns(expectedResponse); // Act await manageClient.DeleteInvite(_projectId, email); // Assert - await manageClient.Received().DeleteAsync($"{UriSegments.PROJECTS}/{_projectId}/invites/{email}"); + await manageClient.Received().DeleteAsync(url); } #endregion @@ -401,20 +442,23 @@ public async Task DeleteInvite_Should_Call_DeleteAsync() [Test] public async Task GetMembers_Should_Call_GetAsync_Returning_MembersResponse() { - //Arrange + // Input and Output + var url = AbstractRestClient.GetUri(_options, $"{UriSegments.PROJECTS}/{_projectId}/members"); var expectedResponse = new AutoFaker().Generate(); - var httpClient = MockHttpClient.CreateHttpClientWithResult(expectedResponse); + // Fake Client + var httpClient = MockHttpClient.CreateHttpClientWithResult(expectedResponse); var manageClient = Substitute.For(_apiKey, _options); + // Mock methods manageClient.When(x => x.GetAsync(Arg.Any())).DoNotCallBase(); - manageClient.GetAsync($"{UriSegments.PROJECTS}/{_projectId}/members").Returns(expectedResponse); + manageClient.GetAsync(url).Returns(expectedResponse); // Act var result = await manageClient.GetMembers(_projectId); // Assert - await manageClient.Received().GetAsync($"{UriSegments.PROJECTS}/{_projectId}/members"); + await manageClient.Received().GetAsync(url); using (new AssertionScope()) { result.Should().NotBeNull(); @@ -426,22 +470,24 @@ public async Task GetMembers_Should_Call_GetAsync_Returning_MembersResponse() [Test] public async Task GetMemberScopes_Should_Call_GetAsync_Returning_MemberScopesResponse() { - //Arrange - var expectedResponse = new AutoFaker().Generate(); + // Input and Output var memberId = new Faker().Random.Guid().ToString(); + var url = AbstractRestClient.GetUri(_options, $"{UriSegments.PROJECTS}/{_projectId}/members/{memberId}/scopes"); + var expectedResponse = new AutoFaker().Generate(); + + // Fake Client var httpClient = MockHttpClient.CreateHttpClientWithResult(expectedResponse); - - var manageClient = Substitute.For(_apiKey, _options); + // Mock methods manageClient.When(x => x.GetAsync(Arg.Any())).DoNotCallBase(); - manageClient.GetAsync($"{UriSegments.PROJECTS}/{_projectId}/members/{memberId}/scopes").Returns(expectedResponse); + manageClient.GetAsync(url).Returns(expectedResponse); // Act var result = await manageClient.GetMemberScopes(_projectId, memberId); // Assert - await manageClient.Received().GetAsync($"{UriSegments.PROJECTS}/{_projectId}/members/{memberId}/scopes"); + await manageClient.Received().GetAsync(url); using (new AssertionScope()) { result.Should().NotBeNull(); @@ -453,22 +499,25 @@ public async Task GetMemberScopes_Should_Call_GetAsync_Returning_MemberScopesRes [Test] public async Task UpdateMemberScope_Should_Call_PutAsync_Returning_MessageResponse() { - //Arrange + // Input and Output + var memberId = new Faker().Random.Guid().ToString(); + var url = AbstractRestClient.GetUri(_options, $"{UriSegments.PROJECTS}/{_projectId}/members/{memberId}/scopes"); var expectedResponse = new AutoFaker().Generate(); var memberScopeSchema = new AutoFaker().Generate(); - var memberId = new Faker().Random.Guid().ToString(); - var httpClient = MockHttpClient.CreateHttpClientWithResult(expectedResponse); + // Fake Client + var httpClient = MockHttpClient.CreateHttpClientWithResult(expectedResponse); var manageClient = Substitute.For(_apiKey, _options); - manageClient.When(x => x.PutAsync(Arg.Any(), Arg.Any())).DoNotCallBase(); - manageClient.PutAsync($"{UriSegments.PROJECTS}/{_projectId}/members/{memberId}/scopes", Arg.Any()).Returns(expectedResponse); + // Mock methods + manageClient.When(x => x.PutAsync(Arg.Any(), Arg.Any())).DoNotCallBase(); + manageClient.PutAsync(url, Arg.Any()).Returns(expectedResponse); // Act var result = await manageClient.UpdateMemberScope(_projectId, memberId, memberScopeSchema); // Assert - await manageClient.Received().PutAsync($"{UriSegments.PROJECTS}/{_projectId}/members/{memberId}/scopes", Arg.Any()); + await manageClient.Received().PutAsync(url, Arg.Any()); using (new AssertionScope()) { result.Should().NotBeNull(); @@ -480,20 +529,24 @@ public async Task UpdateMemberScope_Should_Call_PutAsync_Returning_MessageRespon [Test] public async Task RemoveMember_Should_Call_DeleteAsync() { - //Arrange + // Input and Output var memberId = new Faker().Random.Guid().ToString(); - var httpClient = MockHttpClient.CreateHttpClientWithResult(new VoidResponse()); + var url = AbstractRestClient.GetUri(_options, $"{UriSegments.PROJECTS}/{_projectId}/members/{memberId}"); + var expectedResponse = new AutoFaker().Generate(); + // Fake Client + var httpClient = MockHttpClient.CreateHttpClientWithResult(expectedResponse); var manageClient = Substitute.For(_apiKey, _options); - manageClient.When(x => x.DeleteAsync(Arg.Any())).DoNotCallBase(); - manageClient.DeleteAsync($"{UriSegments.PROJECTS}/{_projectId}/members/{memberId}").Returns(Task.CompletedTask); + // Mock methods + manageClient.When(x => x.DeleteAsync(Arg.Any())).DoNotCallBase(); + manageClient.DeleteAsync(url).Returns(expectedResponse); // Act await manageClient.RemoveMember(_projectId, memberId); // Assert - await manageClient.Received().DeleteAsync($"{UriSegments.PROJECTS}/{_projectId}/members/{memberId}"); + await manageClient.Received().DeleteAsync(url); } #endregion @@ -502,22 +555,24 @@ public async Task RemoveMember_Should_Call_DeleteAsync() [Test] public async Task GetUsageRequests_Should_Call_GetAsync_Returning_UsageRequestsResponse() { - //Arrange + // Input and Output + var url = AbstractRestClient.GetUri(_options, $"{UriSegments.PROJECTS}/{_projectId}/requests"); var expectedResponse = new AutoFaker().Generate(); var UsageRequestsSchema = new AutoFaker().Generate(); - var stringedOptions = QueryParameterUtil.GetParameters(UsageRequestsSchema); - var httpClient = MockHttpClient.CreateHttpClientWithResult(expectedResponse); + // Fake Client + var httpClient = MockHttpClient.CreateHttpClientWithResult(expectedResponse); var manageClient = Substitute.For(_apiKey, _options); - manageClient.When(x => x.GetAsync(Arg.Any())).DoNotCallBase(); - manageClient.GetAsync($"{UriSegments.PROJECTS}/{_projectId}/requests?{stringedOptions}").Returns(expectedResponse); + // Mock methods + manageClient.When(x => x.GetAsync(Arg.Any(), Arg.Any())).DoNotCallBase(); + manageClient.GetAsync(url, Arg.Any()).Returns(expectedResponse); // Act var result = await manageClient.GetUsageRequests(_projectId, UsageRequestsSchema); // Assert - await manageClient.Received().GetAsync($"{UriSegments.PROJECTS}/{_projectId}/requests?{stringedOptions}"); + await manageClient.Received().GetAsync(url, Arg.Any()); using (new AssertionScope()) { @@ -530,21 +585,24 @@ public async Task GetUsageRequests_Should_Call_GetAsync_Returning_UsageRequestsR [Test] public async Task GetsUsageRequest_Should_Call_GetAsync_Returning_UsageRequestResponse() { - //Arrange + // Input and Output var requestId = new Faker().Random.Guid().ToString(); + var url = AbstractRestClient.GetUri(_options, $"{UriSegments.PROJECTS}/{_projectId}/requests/{requestId}"); var expectedResponse = new AutoFaker().Generate(); - var httpClient = MockHttpClient.CreateHttpClientWithResult(expectedResponse); + // Fake Client + var httpClient = MockHttpClient.CreateHttpClientWithResult(expectedResponse); var manageClient = Substitute.For(_apiKey, _options); + // Mock methods manageClient.When(x => x.GetAsync(Arg.Any())).DoNotCallBase(); - manageClient.GetAsync($"{UriSegments.PROJECTS}/{_projectId}/requests/{requestId}").Returns(expectedResponse); + manageClient.GetAsync(url).Returns(expectedResponse); // Act var result = await manageClient.GetUsageRequest(_projectId, requestId); // Assert - await manageClient.Received().GetAsync($"{UriSegments.PROJECTS}/{_projectId}/requests/{requestId}"); + await manageClient.Received().GetAsync(url); using (new AssertionScope()) { result.Should().NotBeNull(); @@ -556,22 +614,24 @@ public async Task GetsUsageRequest_Should_Call_GetAsync_Returning_UsageRequestRe [Test] public async Task GetsUsageSummary_Should_Call_GetAsync_Returning_UsageSummaryResponse() { - //Arrange + // Input and Output + var url = AbstractRestClient.GetUri(_options, $"{UriSegments.PROJECTS}/{_projectId}/usage"); var expectedResponse = new AutoFaker().Generate(); var getProjectUsageSummarySchema = new AutoFaker().Generate(); - var stringedOptions = QueryParameterUtil.GetParameters(getProjectUsageSummarySchema); - var httpClient = MockHttpClient.CreateHttpClientWithResult(expectedResponse); + // Fake Client + var httpClient = MockHttpClient.CreateHttpClientWithResult(expectedResponse); var manageClient = Substitute.For(_apiKey, _options); - manageClient.When(x => x.GetAsync(Arg.Any())).DoNotCallBase(); - manageClient.GetAsync($"{UriSegments.PROJECTS}/{_projectId}/usage?{stringedOptions}").Returns(expectedResponse); + // Mock methods + manageClient.When(x => x.GetAsync(Arg.Any(), Arg.Any())).DoNotCallBase(); + manageClient.GetAsync(url, Arg.Any()).Returns(expectedResponse); // Act var result = await manageClient.GetUsageSummary(_projectId, getProjectUsageSummarySchema); // Assert - await manageClient.Received().GetAsync($"{UriSegments.PROJECTS}/{_projectId}/usage?{stringedOptions}"); + await manageClient.Received().GetAsync(url, Arg.Any()); using (new AssertionScope()) { @@ -584,22 +644,24 @@ public async Task GetsUsageSummary_Should_Call_GetAsync_Returning_UsageSummaryRe [Test] public async Task GetUsageFields_Should_GetAsync_Returning_UsageSummaryResponse() { - //Arrange + // Input and Output + var url = AbstractRestClient.GetUri(_options, $"{UriSegments.PROJECTS}/{_projectId}/usage/fields"); var expectedResponse = new AutoFaker().Generate(); var getProjectUsageFieldsSchema = new AutoFaker().Generate(); - var stringedOptions = QueryParameterUtil.GetParameters(getProjectUsageFieldsSchema); - var httpClient = MockHttpClient.CreateHttpClientWithResult(expectedResponse); + // Fake Client + var httpClient = MockHttpClient.CreateHttpClientWithResult(expectedResponse); var manageClient = Substitute.For(_apiKey, _options); - manageClient.When(x => x.GetAsync(Arg.Any())).DoNotCallBase(); - manageClient.GetAsync($"{UriSegments.PROJECTS}/{_projectId}/usage/fields?{stringedOptions}").Returns(expectedResponse); + // Mock methods + manageClient.When(x => x.GetAsync(Arg.Any(), Arg.Any())).DoNotCallBase(); + manageClient.GetAsync(url, Arg.Any()).Returns(expectedResponse); // Act var result = await manageClient.GetUsageFields(_projectId, getProjectUsageFieldsSchema); // Assert - await manageClient.Received().GetAsync($"{UriSegments.PROJECTS}/{_projectId}/usage/fields?{stringedOptions}"); + await manageClient.Received().GetAsync(url, Arg.Any()); using (new AssertionScope()) { @@ -616,20 +678,23 @@ public async Task GetUsageFields_Should_GetAsync_Returning_UsageSummaryResponse( [Test] public async Task GetBalances_Should_Call_GetAsync_Returning_BalancesResponse() { - //Arrange + // Input and Output + var url = AbstractRestClient.GetUri(_options, $"{UriSegments.PROJECTS}/{_projectId}/balances"); var expectedResponse = new AutoFaker().Generate(); - var httpClient = MockHttpClient.CreateHttpClientWithResult(expectedResponse); + // Fake Client + var httpClient = MockHttpClient.CreateHttpClientWithResult(expectedResponse); var manageClient = Substitute.For(_apiKey, _options); + // Mock methods manageClient.When(x => x.GetAsync(Arg.Any())).DoNotCallBase(); - manageClient.GetAsync($"{UriSegments.PROJECTS}/{_projectId}/balances").Returns(expectedResponse); + manageClient.GetAsync(url).Returns(expectedResponse); // Act var result = await manageClient.GetBalances(_projectId); // Assert - await manageClient.Received().GetAsync($"{UriSegments.PROJECTS}/{_projectId}/balances"); + await manageClient.Received().GetAsync(url); using (new AssertionScope()) { result.Should().NotBeNull(); @@ -641,20 +706,24 @@ public async Task GetBalances_Should_Call_GetAsync_Returning_BalancesResponse() [Test] public async Task GetBalance_Should_Call_GetAsync_Returning_BalanceResponse() { - //Arrange + // Input and Output + var balanceId = new Faker().Random.Guid().ToString(); + var url = AbstractRestClient.GetUri(_options, $"{UriSegments.PROJECTS}/{_projectId}/balances/{balanceId}"); var expectedResponse = new AutoFaker().Generate(); + + // Fake Client var httpClient = MockHttpClient.CreateHttpClientWithResult(expectedResponse); var manageClient = Substitute.For(_apiKey, _options); - var balanceId = new Faker().Random.Guid().ToString(); + // Mock methods manageClient.When(x => x.GetAsync(Arg.Any())).DoNotCallBase(); - manageClient.GetAsync($"{UriSegments.PROJECTS}/{_projectId}/balances/{balanceId}").Returns(expectedResponse); + manageClient.GetAsync(url).Returns(expectedResponse); // Act var result = await manageClient.GetBalance(_projectId, balanceId); // Assert - await manageClient.Received().GetAsync($"{UriSegments.PROJECTS}/{_projectId}/balances/{balanceId}"); + await manageClient.Received().GetAsync(url); using (new AssertionScope()) { result.Should().NotBeNull(); @@ -662,9 +731,5 @@ public async Task GetBalance_Should_Call_GetAsync_Returning_BalanceResponse() result.Should().BeEquivalentTo(expectedResponse); } } - - #endregion - - } diff --git a/Deepgram.Tests/UnitTests/ClientTests/OnPremClientTests.cs b/Deepgram.Tests/UnitTests/ClientTests/OnPremClientTests.cs index 9cbb27c1..45eb1885 100644 --- a/Deepgram.Tests/UnitTests/ClientTests/OnPremClientTests.cs +++ b/Deepgram.Tests/UnitTests/ClientTests/OnPremClientTests.cs @@ -24,21 +24,23 @@ public void Setup() [Test] public async Task ListCredentials_Should_Call_GetAsync_Returning_CredentialsResponse() { - //Arrange + // Input and Output + var url = AbstractRestClient.GetUri(_options, $"{UriSegments.PROJECTS}/{_projectId}/{UriSegments.ONPREM}"); var expectedResponse = new AutoFaker().Generate(); - var httpClient = MockHttpClient.CreateHttpClientWithResult(expectedResponse); + // Fake client + var httpClient = MockHttpClient.CreateHttpClientWithResult(expectedResponse); var onPremClient = Substitute.For(_apiKey, _options); + // Mock methods onPremClient.When(x => x.GetAsync(Arg.Any())).DoNotCallBase(); - onPremClient.GetAsync($"{UriSegments.PROJECTS}/{_projectId}/{UriSegments.ONPREM}").Returns(expectedResponse); + onPremClient.GetAsync(url).Returns(expectedResponse); // Act - var result = await onPremClient.ListCredentials(_projectId); // Assert - await onPremClient.Received().GetAsync($"{UriSegments.PROJECTS}/{_projectId}/{UriSegments.ONPREM}"); + await onPremClient.Received().GetAsync(url); using (new AssertionScope()) { result.Should().NotBeNull(); @@ -50,21 +52,24 @@ public async Task ListCredentials_Should_Call_GetAsync_Returning_CredentialsResp [Test] public async Task GetCredentials_Should_Call_GetAsync_Returning_CredentialResponse() { - //Arrange - var expectedResponse = new AutoFaker().Generate(); + // Input and Output var credentialsId = new Faker().Random.Guid().ToString(); - var httpClient = MockHttpClient.CreateHttpClientWithResult(expectedResponse); + var url = AbstractRestClient.GetUri(_options, $"{UriSegments.PROJECTS}/{_projectId}/{UriSegments.ONPREM}/{credentialsId}"); + var expectedResponse = new AutoFaker().Generate(); + // Fake client + var httpClient = MockHttpClient.CreateHttpClientWithResult(expectedResponse); var onPremClient = Substitute.For(_apiKey, _options); + // Mock methods onPremClient.When(x => x.GetAsync(Arg.Any())).DoNotCallBase(); - onPremClient.GetAsync($"{UriSegments.PROJECTS}/{_projectId}/{UriSegments.ONPREM}/{credentialsId}").Returns(expectedResponse); + onPremClient.GetAsync(url).Returns(expectedResponse); // Act var result = await onPremClient.GetCredentials(_projectId, credentialsId); // Assert - await onPremClient.Received().GetAsync($"{UriSegments.PROJECTS}/{_projectId}/{UriSegments.ONPREM}/{credentialsId}"); + await onPremClient.Received().GetAsync(url); using (new AssertionScope()) { result.Should().NotBeNull(); @@ -76,22 +81,24 @@ public async Task GetCredentials_Should_Call_GetAsync_Returning_CredentialRespon [Test] public async Task DeleteCredentials_Should_Call_DeleteAsync_Returning_MessageResponse() { - //Arrange - var expectedResponse = new AutoFaker().Generate(); + // Input and Output var credentialsId = new Faker().Random.Guid().ToString(); + var url = AbstractRestClient.GetUri(_options, $"{UriSegments.PROJECTS}/{_projectId}/{UriSegments.ONPREM}/{credentialsId}"); + var expectedResponse = new AutoFaker().Generate(); + + // Fake client var httpClient = MockHttpClient.CreateHttpClientWithResult(expectedResponse); - var onPremClient = Substitute.For(_apiKey, _options); + // Mock methods onPremClient.When(x => x.DeleteAsync(Arg.Any())).DoNotCallBase(); - onPremClient.DeleteAsync($"{UriSegments.PROJECTS}/{_projectId}/{UriSegments.ONPREM}/{credentialsId}").Returns(expectedResponse); + onPremClient.DeleteAsync(url).Returns(expectedResponse); // Act - var result = await onPremClient.DeleteCredentials(_projectId, credentialsId); // Assert - await onPremClient.Received().DeleteAsync($"{UriSegments.PROJECTS}/{_projectId}/{UriSegments.ONPREM}/{credentialsId}"); + await onPremClient.Received().DeleteAsync(url); using (new AssertionScope()) { result.Should().NotBeNull(); @@ -104,22 +111,24 @@ public async Task DeleteCredentials_Should_Call_DeleteAsync_Returning_MessageRes [Test] public async Task CreateCredentials_Should_Return_CredentialResponse() { - //Arrange + // Input and Output + var url = AbstractRestClient.GetUri(_options, $"{UriSegments.PROJECTS}/{_projectId}/{UriSegments.ONPREM}"); var expectedResponse = new AutoFaker().Generate(); var createOnPremCredentialsSchema = new CredentialsSchema(); - var httpClient = MockHttpClient.CreateHttpClientWithResult(expectedResponse); + // Fake client + var httpClient = MockHttpClient.CreateHttpClientWithResult(expectedResponse); var onPremClient = Substitute.For(_apiKey, _options); - onPremClient.When(x => x.PostAsync(Arg.Any(), Arg.Any())).DoNotCallBase(); - onPremClient.PostAsync($"{UriSegments.PROJECTS}/{_projectId}/{UriSegments.ONPREM}", Arg.Any()).Returns(expectedResponse); + // Mock methods + onPremClient.When(x => x.PostAsync(Arg.Any(), Arg.Any())).DoNotCallBase(); + onPremClient.PostAsync(url, Arg.Any()).Returns(expectedResponse); // Act - var result = await onPremClient.CreateCredentials(_projectId, createOnPremCredentialsSchema); // Assert - await onPremClient.Received().PostAsync($"{UriSegments.PROJECTS}/{_projectId}/{UriSegments.ONPREM}", Arg.Any()); + await onPremClient.Received().PostAsync(url, Arg.Any()); using (new AssertionScope()) { diff --git a/Deepgram.Tests/UnitTests/ClientTests/PrerecordedClientTests.cs b/Deepgram.Tests/UnitTests/ClientTests/PrerecordedClientTests.cs index 37200522..dfde6521 100644 --- a/Deepgram.Tests/UnitTests/ClientTests/PrerecordedClientTests.cs +++ b/Deepgram.Tests/UnitTests/ClientTests/PrerecordedClientTests.cs @@ -3,8 +3,8 @@ // SPDX-License-Identifier: MIT using Deepgram.Models.Authenticate.v1; -using Deepgram.Models.PreRecorded.v1; using Deepgram.Clients.PreRecorded.v1; +using Deepgram.Models.PreRecorded.v1; namespace Deepgram.Tests.UnitTests.ClientTests; @@ -23,25 +23,26 @@ public void Setup() [Test] public async Task TranscribeUrl_Should_Call_PostAsync_Returning_SyncResponse() { - //Arrange + // Input and Output + var url = AbstractRestClient.GetUri(_options, $"{UriSegments.LISTEN}"); var expectedResponse = new AutoFaker().Generate(); var prerecordedSchema = new AutoFaker().Generate(); prerecordedSchema.CallBack = null; - var stringedOptions = QueryParameterUtil.GetParameters(prerecordedSchema); var source = new AutoFaker().Generate(); - var httpClient = MockHttpClient.CreateHttpClientWithResult(expectedResponse); + // Fake Client + var httpClient = MockHttpClient.CreateHttpClientWithResult(expectedResponse); var prerecordedClient = Substitute.For(_apiKey, _options); - - prerecordedClient.When(x => x.PostAsync(Arg.Any(), Arg.Any())).DoNotCallBase(); - prerecordedClient.PostAsync($"{UriSegments.LISTEN}?{stringedOptions}", Arg.Any()).Returns(expectedResponse); + // Mock Methods + prerecordedClient.When(x => x.PostAsync(Arg.Any(), Arg.Any(), Arg.Any())).DoNotCallBase(); + prerecordedClient.PostAsync(url, Arg.Any(), Arg.Any()).Returns(expectedResponse); // Act var result = await prerecordedClient.TranscribeUrl(source, prerecordedSchema); // Assert - await prerecordedClient.Received().PostAsync($"{UriSegments.LISTEN}?{stringedOptions}", Arg.Any()); + await prerecordedClient.Received().PostAsync(url, Arg.Any(), Arg.Any()); using (new AssertionScope()) { @@ -54,50 +55,53 @@ public async Task TranscribeUrl_Should_Call_PostAsync_Returning_SyncResponse() [Test] public async Task TranscribeUrl_Should_Throw_ArgumentException_If_CallBack_Not_Null() { - //Arrange + // Input and Output + var url = AbstractRestClient.GetUri(_options, $"{UriSegments.LISTEN}"); var expectedResponse = new AutoFaker().Generate(); var prerecordedSchema = new AutoFaker().Generate(); - var stringedOptions = QueryParameterUtil.GetParameters(prerecordedSchema); var source = new AutoFaker().Generate(); + + // Fake Client var httpClient = MockHttpClient.CreateHttpClientWithResult(expectedResponse); - var prerecordedClient = Substitute.For(_apiKey, _options); - prerecordedClient.When(x => x.PostAsync(Arg.Any(), Arg.Any())).DoNotCallBase(); - prerecordedClient.PostAsync($"{UriSegments.LISTEN}?{stringedOptions}", Arg.Any()).Returns(expectedResponse); + // Mock Methods + prerecordedClient.When(x => x.PostAsync(Arg.Any(), Arg.Any(), Arg.Any())).DoNotCallBase(); + prerecordedClient.PostAsync(url, Arg.Any(), Arg.Any()).Returns(expectedResponse); // Act and Assert await prerecordedClient.Invoking(y => y.TranscribeUrl(source, prerecordedSchema)) .Should().ThrowAsync(); - await prerecordedClient.DidNotReceive().PostAsync($"{UriSegments.LISTEN}?{stringedOptions}", Arg.Any()); + await prerecordedClient.DidNotReceive().PostAsync(url, Arg.Any(), Arg.Any()); } [Test] public async Task TranscribeUrlCallBack_Should_Call_PostAsync_Returning_SyncResponse_With_CallBack_Parameter() { - //Arrange + // Input and Output + var url = AbstractRestClient.GetUri(_options, $"{UriSegments.LISTEN}"); var expectedResponse = new AutoFaker().Generate(); var source = new AutoFaker().Generate(); var prerecordedSchema = new AutoFaker().Generate(); - // prerecordedSchema is not null here as we first need to get the querystring with the callBack included - var stringedQuery = QueryParameterUtil.GetParameters(prerecordedSchema); + + // Fake Client var httpClient = MockHttpClient.CreateHttpClientWithResult(expectedResponse); - var prerecordedClient = Substitute.For(_apiKey, _options); - prerecordedClient.When(x => x.PostAsync(Arg.Any(), Arg.Any())).DoNotCallBase(); - prerecordedClient.PostAsync($"{UriSegments.LISTEN}?{stringedQuery}", Arg.Any()).Returns(expectedResponse); - var callBackParameter = prerecordedSchema.CallBack; + // Mock Methods + prerecordedClient.When(x => x.PostAsync(Arg.Any(), Arg.Any(), Arg.Any())).DoNotCallBase(); + prerecordedClient.PostAsync(url, Arg.Any(), Arg.Any()).Returns(expectedResponse); + //before we act to test this call with the callBack parameter and not the callBack property we need to null the callBack property + var callBackParameter = prerecordedSchema.CallBack; prerecordedSchema.CallBack = null; - // Act var result = await prerecordedClient.TranscribeUrlCallBack(source, callBackParameter, prerecordedSchema); // Assert - await prerecordedClient.Received().PostAsync($"{UriSegments.LISTEN}?{stringedQuery}", Arg.Any()); + await prerecordedClient.Received().PostAsync(url, Arg.Any(), Arg.Any()); using (new AssertionScope()) { result.Should().NotBeNull(); @@ -109,23 +113,25 @@ public async Task TranscribeUrlCallBack_Should_Call_PostAsync_Returning_SyncResp [Test] public async Task TranscribeUrlCallBack_Should_Call_PostAsync_Returning_SyncResponse_With_CallBack_Property() { - //Arrange + // Input and Output + var url = AbstractRestClient.GetUri(_options, $"{UriSegments.LISTEN}"); var expectedResponse = new AutoFaker().Generate(); var source = new AutoFaker().Generate(); var prerecordedSchema = new AutoFaker().Generate(); - var stringedQuery = QueryParameterUtil.GetParameters(prerecordedSchema); - var httpClient = MockHttpClient.CreateHttpClientWithResult(expectedResponse); + // Fake Client + var httpClient = MockHttpClient.CreateHttpClientWithResult(expectedResponse); var prerecordedClient = Substitute.For(_apiKey, _options); - prerecordedClient.When(x => x.PostAsync(Arg.Any(), Arg.Any())).DoNotCallBase(); - prerecordedClient.PostAsync($"{UriSegments.LISTEN}?{stringedQuery}", Arg.Any()).Returns(expectedResponse); + // Mock Methods + prerecordedClient.When(x => x.PostAsync(Arg.Any(), Arg.Any(), Arg.Any())).DoNotCallBase(); + prerecordedClient.PostAsync(url, Arg.Any(), Arg.Any()).Returns(expectedResponse); // Act var result = await prerecordedClient.TranscribeUrlCallBack(source, null, prerecordedSchema); // Assert - await prerecordedClient.Received().PostAsync($"{UriSegments.LISTEN}?{stringedQuery}", Arg.Any()); + await prerecordedClient.Received().PostAsync(url, Arg.Any(), Arg.Any()); using (new AssertionScope()) { result.Should().NotBeNull(); @@ -137,71 +143,77 @@ public async Task TranscribeUrlCallBack_Should_Call_PostAsync_Returning_SyncResp [Test] public async Task TranscribeUrlCallBack_Should_Throw_ArgumentException_With_CallBack_Property_And_CallBack_Parameter_Set() { - //Arrange + // Input and Output + var url = AbstractRestClient.GetUri(_options, $"{UriSegments.LISTEN}"); var expectedResponse = new AutoFaker().Generate(); var source = new AutoFaker().Generate(); var prerecordedSchema = new AutoFaker().Generate(); - var stringedQuery = QueryParameterUtil.GetParameters(prerecordedSchema); + // Fake Client var httpClient = MockHttpClient.CreateHttpClientWithResult(expectedResponse); var prerecordedClient = Substitute.For(_apiKey, _options); - prerecordedClient.When(x => x.PostAsync(Arg.Any(), Arg.Any())).DoNotCallBase(); - prerecordedClient.PostAsync($"{UriSegments.LISTEN}?{stringedQuery}", Arg.Any()).Returns(expectedResponse); + // Mock Methods + prerecordedClient.When(x => x.PostAsync(Arg.Any(), Arg.Any())).DoNotCallBase(); + prerecordedClient.PostAsync(url, Arg.Any()).Returns(expectedResponse); + var callBackParameter = prerecordedSchema.CallBack; - // Act Assert + // Act and Assert await prerecordedClient.Invoking(y => y.TranscribeUrlCallBack(source, callBackParameter, prerecordedSchema)) .Should().ThrowAsync(); - await prerecordedClient.DidNotReceive().PostAsync($"{UriSegments.LISTEN}?{stringedQuery}", Arg.Any()); + await prerecordedClient.DidNotReceive().PostAsync(url, Arg.Any()); } [Test] public async Task TranscribeUrlCallBack_Should_Throw_ArgumentException_With_No_CallBack_Set() { - //Arrange + // Input and Output + var url = AbstractRestClient.GetUri(_options, $"{UriSegments.LISTEN}"); var expectedResponse = new AutoFaker().Generate(); var source = new AutoFaker().Generate(); var prerecordedSchema = new AutoFaker().Generate(); prerecordedSchema.CallBack = null; - var stringedQuery = QueryParameterUtil.GetParameters(prerecordedSchema); + // Fake Client var httpClient = MockHttpClient.CreateHttpClientWithResult(expectedResponse); var prerecordedClient = Substitute.For(_apiKey, _options); - prerecordedClient.When(x => x.PostAsync(Arg.Any(), Arg.Any())).DoNotCallBase(); - prerecordedClient.PostAsync($"{UriSegments.LISTEN}?{stringedQuery}", Arg.Any()).Returns(expectedResponse); - + // Mock Methods + prerecordedClient.When(x => x.PostAsync(Arg.Any(), Arg.Any())).DoNotCallBase(); + prerecordedClient.PostAsync(url, Arg.Any(), Arg.Any()).Returns(expectedResponse); - // Act Assert + // Act and Assert await prerecordedClient.Invoking(y => y.TranscribeUrlCallBack(source, null, prerecordedSchema)) .Should().ThrowAsync(); - await prerecordedClient.DidNotReceive().PostAsync($"{UriSegments.LISTEN}?{stringedQuery}", Arg.Any()); + await prerecordedClient.DidNotReceive().PostAsync(url, Arg.Any()); } [Test] public async Task TranscribeFile_With_Stream_Should_Call_PostAsync_Returning_SyncResponse() { - //Arrange + // Input and Output + var url = AbstractRestClient.GetUri(_options, $"{UriSegments.LISTEN}"); var expectedResponse = new AutoFaker().Generate(); var prerecordedSchema = new AutoFaker().Generate(); prerecordedSchema.CallBack = null; - var stringedOptions = QueryParameterUtil.GetParameters(prerecordedSchema); + + // Fake Client var source = GetFakeStream(GetFakeByteArray()); var httpClient = MockHttpClient.CreateHttpClientWithResult(expectedResponse); - var prerecordedClient = Substitute.For(_apiKey, _options); - - prerecordedClient.When(x => x.PostAsync(Arg.Any(), Arg.Any())).DoNotCallBase(); - prerecordedClient.PostAsync($"{UriSegments.LISTEN}?{stringedOptions}", Arg.Any()).Returns(expectedResponse); + + // Mock Methods + prerecordedClient.When(x => x.PostAsync(Arg.Any(), Arg.Any(), Arg.Any())).DoNotCallBase(); + prerecordedClient.PostAsync(url, Arg.Any(), Arg.Any()).Returns(expectedResponse); // Act var result = await prerecordedClient.TranscribeFile(source, prerecordedSchema); // Assert - await prerecordedClient.Received().PostAsync($"{UriSegments.LISTEN}?{stringedOptions}", Arg.Any()); + await prerecordedClient.Received().PostAsync(url, Arg.Any(), Arg.Any()); using (new AssertionScope()) { result.Should().NotBeNull(); @@ -213,24 +225,26 @@ public async Task TranscribeFile_With_Stream_Should_Call_PostAsync_Returning_Syn [Test] public async Task TranscribeFile_With_Bytes_Should_Call_PostAsync_Returning_SyncResponse() { - //Arrange + // Input and Output + var url = AbstractRestClient.GetUri(_options, $"{UriSegments.LISTEN}"); var expectedResponse = new AutoFaker().Generate(); var prerecordedSchema = new AutoFaker().Generate(); prerecordedSchema.CallBack = null; - var stringedOptions = QueryParameterUtil.GetParameters(prerecordedSchema); var source = GetFakeByteArray(); - var httpClient = MockHttpClient.CreateHttpClientWithResult(expectedResponse); + // Fake Client + var httpClient = MockHttpClient.CreateHttpClientWithResult(expectedResponse); var prerecordedClient = Substitute.For(_apiKey, _options); - - prerecordedClient.When(x => x.PostAsync(Arg.Any(), Arg.Any())).DoNotCallBase(); - prerecordedClient.PostAsync($"{UriSegments.LISTEN}?{stringedOptions}", Arg.Any()).Returns(expectedResponse); + + // Mock Methods + prerecordedClient.When(x => x.PostAsync(Arg.Any(), Arg.Any(), Arg.Any())).DoNotCallBase(); + prerecordedClient.PostAsync(url, Arg.Any(), Arg.Any()).Returns(expectedResponse); // Act var result = await prerecordedClient.TranscribeFile(source, prerecordedSchema); // Assert - await prerecordedClient.Received().PostAsync($"{UriSegments.LISTEN}?{stringedOptions}", Arg.Any()); + await prerecordedClient.Received().PostAsync(url, Arg.Any(), Arg.Any()); using (new AssertionScope()) { result.Should().NotBeNull(); @@ -242,23 +256,25 @@ public async Task TranscribeFile_With_Bytes_Should_Call_PostAsync_Returning_Sync [Test] public async Task TranscribeFileCallBack_With_Stream_With_CallBack_Property_Should_Call_PostAsync_Returning_SyncResponse() { - //Arrange + // Input and Output + var url = AbstractRestClient.GetUri(_options, $"{UriSegments.LISTEN}"); var expectedResponse = new AutoFaker().Generate(); var prerecordedSchema = new AutoFaker().Generate(); - var stringedOptions = QueryParameterUtil.GetParameters(prerecordedSchema); var source = GetFakeStream(GetFakeByteArray()); - var httpClient = MockHttpClient.CreateHttpClientWithResult(expectedResponse); + // Fake Client + var httpClient = MockHttpClient.CreateHttpClientWithResult(expectedResponse); var prerecordedClient = Substitute.For(_apiKey, _options); - prerecordedClient.When(x => x.PostAsync(Arg.Any(), Arg.Any())).DoNotCallBase(); - prerecordedClient.PostAsync($"{UriSegments.LISTEN}?{stringedOptions}", Arg.Any()).Returns(expectedResponse); + // Mock Methods + prerecordedClient.When(x => x.PostAsync(Arg.Any(), Arg.Any(), Arg.Any())).DoNotCallBase(); + prerecordedClient.PostAsync(url, Arg.Any(), Arg.Any()).Returns(expectedResponse); // Act var result = await prerecordedClient.TranscribeFileCallBack(source, null, prerecordedSchema); // Assert - await prerecordedClient.Received().PostAsync($"{UriSegments.LISTEN}?{stringedOptions}", Arg.Any()); + await prerecordedClient.Received().PostAsync(url, Arg.Any(), Arg.Any()); using (new AssertionScope()) { result.Should().NotBeNull(); @@ -270,23 +286,25 @@ public async Task TranscribeFileCallBack_With_Stream_With_CallBack_Property_Shou [Test] public async Task TranscribeFileCallBack_With_Bytes_With_CallBack_Property_Should_Call_PostAsync_Returning_SyncResponse() { - //Arrange + // Input and Output + var url = AbstractRestClient.GetUri(_options, $"{UriSegments.LISTEN}"); var expectedResponse = new AutoFaker().Generate(); var prerecordedSchema = new AutoFaker().Generate(); - var stringedOptions = QueryParameterUtil.GetParameters(prerecordedSchema); var source = GetFakeByteArray(); - var httpClient = MockHttpClient.CreateHttpClientWithResult(expectedResponse); + // Fake Client + var httpClient = MockHttpClient.CreateHttpClientWithResult(expectedResponse); var prerecordedClient = Substitute.For(_apiKey, _options); - prerecordedClient.When(x => x.PostAsync(Arg.Any(), Arg.Any())).DoNotCallBase(); - prerecordedClient.PostAsync($"{UriSegments.LISTEN}?{stringedOptions}", Arg.Any()).Returns(expectedResponse); + // Mock Methods + prerecordedClient.When(x => x.PostAsync(Arg.Any(), Arg.Any(), Arg.Any())).DoNotCallBase(); + prerecordedClient.PostAsync(url, Arg.Any(), Arg.Any()).Returns(expectedResponse); // Act var result = await prerecordedClient.TranscribeFileCallBack(source, null, prerecordedSchema); // Assert - await prerecordedClient.Received().PostAsync($"{UriSegments.LISTEN}?{stringedOptions}", Arg.Any()); + await prerecordedClient.Received().PostAsync(url, Arg.Any(), Arg.Any()); using (new AssertionScope()) { @@ -299,29 +317,29 @@ public async Task TranscribeFileCallBack_With_Bytes_With_CallBack_Property_Shoul [Test] public async Task TranscribeFileCallBack_With_Stream_With_CallBack_Parameter_Should_Call_PostAsync_Returning_SyncResponse() { - //Arrange + // Input and Output + var url = AbstractRestClient.GetUri(_options, $"{UriSegments.LISTEN}"); var expectedResponse = new AutoFaker().Generate(); var prerecordedSchema = new AutoFaker().Generate(); - // prerecordedSchema is not null here as we first need to get the querystring with the callBack included - var stringedOptions = QueryParameterUtil.GetParameters(prerecordedSchema); var source = GetFakeStream(GetFakeByteArray()); - var httpClient = MockHttpClient.CreateHttpClientWithResult(expectedResponse); + // Fake Client + var httpClient = MockHttpClient.CreateHttpClientWithResult(expectedResponse); var prerecordedClient = Substitute.For(_apiKey, _options); - prerecordedClient.When(x => x.PostAsync(Arg.Any(), Arg.Any())).DoNotCallBase(); - prerecordedClient.PostAsync($"{UriSegments.LISTEN}?{stringedOptions}", Arg.Any()).Returns(expectedResponse); - - var callBack = prerecordedSchema.CallBack; + // Mock Methods + prerecordedClient.When(x => x.PostAsync(Arg.Any(), Arg.Any(), Arg.Any())).DoNotCallBase(); + prerecordedClient.PostAsync(url, Arg.Any(), Arg.Any()).Returns(expectedResponse); //before we act to test this call with the callBack parameter and not the callBack property we need to null the callBack property + var callBack = prerecordedSchema.CallBack; prerecordedSchema.CallBack = null; // Act var result = await prerecordedClient.TranscribeFileCallBack(source, callBack, prerecordedSchema); // Assert - await prerecordedClient.Received().PostAsync($"{UriSegments.LISTEN}?{stringedOptions}", Arg.Any()); + await prerecordedClient.Received().PostAsync(url, Arg.Any(), Arg.Any()); using (new AssertionScope()) { result.Should().NotBeNull(); @@ -333,29 +351,29 @@ public async Task TranscribeFileCallBack_With_Stream_With_CallBack_Parameter_Sho [Test] public async Task TranscribeFileCallBack_With_Bytes_With_CallBack_Parameter_Should_Call_PostAsync_Returning_SyncResponse() { - //Arrange + // Input and Output + var url = AbstractRestClient.GetUri(_options, $"{UriSegments.LISTEN}"); var expectedResponse = new AutoFaker().Generate(); var prerecordedSchema = new AutoFaker().Generate(); - // prerecordedSchema is not null here as we first need to get the querystring with the callBack included - var stringedOptions = QueryParameterUtil.GetParameters(prerecordedSchema); var source = GetFakeByteArray(); + // Fake Client var httpClient = MockHttpClient.CreateHttpClientWithResult(expectedResponse); var prerecordedClient = Substitute.For(_apiKey, _options); - prerecordedClient.When(x => x.PostAsync(Arg.Any(), Arg.Any())).DoNotCallBase(); - prerecordedClient.PostAsync($"{UriSegments.LISTEN}?{stringedOptions}", Arg.Any()).Returns(expectedResponse); - - var callBack = prerecordedSchema.CallBack; + // Mock Methods + prerecordedClient.When(x => x.PostAsync(Arg.Any(), Arg.Any(), Arg.Any())).DoNotCallBase(); + prerecordedClient.PostAsync(url, Arg.Any(), Arg.Any()).Returns(expectedResponse); //before we act to test this call with the callBack parameter and not the callBack property we need to null the callBack property + var callBack = prerecordedSchema.CallBack; prerecordedSchema.CallBack = null; // Act var result = await prerecordedClient.TranscribeFileCallBack(source, callBack, prerecordedSchema); // Assert - await prerecordedClient.Received().PostAsync($"{UriSegments.LISTEN}?{stringedOptions}", Arg.Any()); + await prerecordedClient.Received().PostAsync(url, Arg.Any(), Arg.Any()); using (new AssertionScope()) { result.Should().NotBeNull(); @@ -367,51 +385,53 @@ public async Task TranscribeFileCallBack_With_Bytes_With_CallBack_Parameter_Shou [Test] public async Task TranscribeFileCallBack_With_Stream_Throw_ArgumentException_With_CallBack_Property_And_CallBack_Parameter_Set() { - //Arrange + // Input and Output + var url = AbstractRestClient.GetUri(_options, $"{UriSegments.LISTEN}"); var expectedResponse = new AutoFaker().Generate(); var prerecordedSchema = new AutoFaker().Generate(); - var stringedOptions = QueryParameterUtil.GetParameters(prerecordedSchema); var source = GetFakeStream(GetFakeByteArray()); - var httpClient = MockHttpClient.CreateHttpClientWithResult(expectedResponse); + // Fake Client + var httpClient = MockHttpClient.CreateHttpClientWithResult(expectedResponse); var prerecordedClient = Substitute.For(_apiKey, _options); - prerecordedClient.When(x => x.PostAsync(Arg.Any(), Arg.Any())).DoNotCallBase(); - prerecordedClient.PostAsync($"{UriSegments.LISTEN}?{stringedOptions}", Arg.Any()).Returns(expectedResponse); + // Mock Methods + prerecordedClient.When(x => x.PostAsync(Arg.Any(), Arg.Any(), Arg.Any())).DoNotCallBase(); + prerecordedClient.PostAsync(url, Arg.Any(), Arg.Any()).Returns(expectedResponse); + var callBack = prerecordedSchema.CallBack; - - // Act Assert + // Act and Assert await prerecordedClient.Invoking(y => y.TranscribeFileCallBack(source, callBack, prerecordedSchema)) .Should().ThrowAsync(); - await prerecordedClient.DidNotReceive().PostAsync($"{UriSegments.LISTEN}?{stringedOptions}", Arg.Any()); - - + await prerecordedClient.DidNotReceive().PostAsync(url, Arg.Any(), Arg.Any()); } [Test] public async Task TranscribeFileCallBack_With_Bytes_Should_Throw_ArgumentException_With_No_CallBack_Set() { - //Arrange + // Input and Output + var url = AbstractRestClient.GetUri(_options, $"{UriSegments.LISTEN}"); var expectedResponse = new AutoFaker().Generate(); var prerecordedSchema = new AutoFaker().Generate(); - // prerecordedSchema is not null here as we first need to get the querystring with the callBack included - var stringedOptions = QueryParameterUtil.GetParameters(prerecordedSchema); var source = GetFakeByteArray(); + // Fake Client var httpClient = MockHttpClient.CreateHttpClientWithResult(expectedResponse); var prerecordedClient = Substitute.For(_apiKey, _options); - prerecordedClient.When(x => x.PostAsync(Arg.Any(), Arg.Any())).DoNotCallBase(); - prerecordedClient.PostAsync($"{UriSegments.LISTEN}?{stringedOptions}", Arg.Any()).Returns(expectedResponse); + // Mock Methods + prerecordedClient.When(x => x.PostAsync(Arg.Any(), Arg.Any(), Arg.Any())).DoNotCallBase(); + prerecordedClient.PostAsync(url, Arg.Any(), Arg.Any()).Returns(expectedResponse); + prerecordedSchema.CallBack = null; - // Act Assert + // Act and Assert await prerecordedClient.Invoking(y => y.TranscribeFileCallBack(source, null, prerecordedSchema)) .Should().ThrowAsync(); - await prerecordedClient.DidNotReceive().PostAsync($"{UriSegments.LISTEN}?{stringedOptions}", Arg.Any()); + await prerecordedClient.DidNotReceive().PostAsync(url, Arg.Any(), Arg.Any()); } private static Stream GetFakeStream(byte[] source) @@ -422,5 +442,4 @@ private static Stream GetFakeStream(byte[] source) } private static byte[] GetFakeByteArray() => new Faker().Random.Bytes(10); - } diff --git a/Deepgram.Tests/UnitTests/ClientTests/SpeakClientTests.cs b/Deepgram.Tests/UnitTests/ClientTests/SpeakClientTests.cs index fcee2454..25cac224 100644 --- a/Deepgram.Tests/UnitTests/ClientTests/SpeakClientTests.cs +++ b/Deepgram.Tests/UnitTests/ClientTests/SpeakClientTests.cs @@ -5,7 +5,6 @@ using Deepgram.Models.Authenticate.v1; using Deepgram.Models.Speak.v1; using Deepgram.Clients.Speak.v1; -using NSubstitute; namespace Deepgram.Tests.UnitTests.ClientTests; @@ -24,54 +23,57 @@ public void Setup() //[Test] //public async Task SpeakStream_Should_Call_PostFileAsync_Returning_SyncResponse() //{ - // //Arrange - // var expectedResponse = new AutoFaker, MemoryStream)>>().Generate(); + // // Input and Output + // var url = AbstractRestClient.GetUri(_options, $"{UriSegments.SPEAK}"); + // var expectedResponse = Arg.Any(); // var speakSchema = new AutoFaker().Generate(); // speakSchema.CallBack = null; // var source = new TextSource("Hello World!"); - // var keys = new List { "key1", "key2" }; - // var stringedOptions = QueryParameterUtil.GetParameters(speakSchema); - // var httpClient = MockHttpClient.CreateHttpClientWithResult(expectedResponse); + // var keys = new List { "model" }; + // // Fake Client + // var httpClient = MockHttpClient.CreateHttpClientWithResult(expectedResponse); // var speakClient = Substitute.For(_apiKey, _options); + // // Mock Methods + // speakClient.When(x => x.PostRetrieveLocalFileAsync(Arg.Any(), Arg.Any(), Arg.Any())).DoNotCallBase(); + // speakClient.PostRetrieveLocalFileAsync(url, Arg.Any(), Arg.Any()).Returns(expectedResponse); - // speakClient.When(x => x.PostFileAsync<(Dictionary, MemoryStream)>(Arg.Any(), Arg.Any(), Arg.Any>())).DoNotCallBase(); - // speakClient.PostFileAsync, MemoryStream)>>($"{UriSegments.SPEAK}?{stringedOptions}", Arg.Any(), keys).Returns(expectedResponse); - // // Act - // var result = await speakClient.Stream(source, speakSchema); + // var result = await speakClient.ToStream(source, speakSchema); // // Assert - // await speakClient.Received().PostFileAsync<(Dictionary, MemoryStream)>($"{UriSegments.SPEAK}?{stringedOptions}", Arg.Any(), keys); + // await speakClient.Received().PostRetrieveLocalFileAsync(url, Arg.Any(), Arg.Any()); // using (new AssertionScope()) // { // result.Should().NotBeNull(); - // // result.Should().BeAssignableTo(); - // // result.Should().BeEquivalentTo(expectedResponse); + // result.Should().BeAssignableTo(); + // result.Should().BeEquivalentTo(expectedResponse); // } //} [Test] public async Task StreamCallBack_With_CallBack_Property_Should_Call_PostAsync_Returning_SyncResponse() { - //Arrange + // Input and Output + var url = AbstractRestClient.GetUri(_options, $"{UriSegments.SPEAK}"); var expectedResponse = new AutoFaker().Generate(); var speakSchema = new AutoFaker().Generate(); var source = new TextSource("Hello World!"); - var stringedOptions = QueryParameterUtil.GetParameters(speakSchema); - var httpClient = MockHttpClient.CreateHttpClientWithResult(expectedResponse); + // Fake Client + var httpClient = MockHttpClient.CreateHttpClientWithResult(expectedResponse); var speakClient = Substitute.For(_apiKey, _options); - speakClient.When(x => x.PostAsync(Arg.Any(), Arg.Any())).DoNotCallBase(); - speakClient.PostAsync($"{UriSegments.SPEAK}?{stringedOptions}", Arg.Any()).Returns(expectedResponse); + // Mock Methods + speakClient.When(x => x.PostAsync(Arg.Any(), Arg.Any(), Arg.Any())).DoNotCallBase(); + speakClient.PostAsync(url, Arg.Any(), Arg.Any()).Returns(expectedResponse); // Act var result = await speakClient.StreamCallBack(source, null, speakSchema); // Assert - await speakClient.Received().PostAsync($"{UriSegments.SPEAK}?{stringedOptions}", Arg.Any()); + await speakClient.Received().PostAsync(url, Arg.Any(), Arg.Any()); using (new AssertionScope()) { result.Should().NotBeNull(); @@ -83,29 +85,29 @@ public async Task StreamCallBack_With_CallBack_Property_Should_Call_PostAsync_Re [Test] public async Task StreamCallBack_With_CallBack_Parameter_Should_Call_PostAsync_Returning_SyncResponse() { - //Arrange + // Input and Output + var url = AbstractRestClient.GetUri(_options, $"{UriSegments.SPEAK}"); var expectedResponse = new AutoFaker().Generate(); var speakSchema = new AutoFaker().Generate(); - // speakSchema is not null here as we first need to get the querystring with the callBack included - var stringedOptions = QueryParameterUtil.GetParameters(speakSchema); var source = new TextSource("Hello World!"); - var httpClient = MockHttpClient.CreateHttpClientWithResult(expectedResponse); + // Fake Client + var httpClient = MockHttpClient.CreateHttpClientWithResult(expectedResponse); var speakClient = Substitute.For(_apiKey, _options); - speakClient.When(x => x.PostAsync(Arg.Any(), Arg.Any())).DoNotCallBase(); - speakClient.PostAsync($"{UriSegments.SPEAK}?{stringedOptions}", Arg.Any()).Returns(expectedResponse); - - var callBack = speakSchema.CallBack; + // Mock Methods + speakClient.When(x => x.PostAsync(Arg.Any(), Arg.Any(), Arg.Any())).DoNotCallBase(); + speakClient.PostAsync(url, Arg.Any(), Arg.Any()).Returns(expectedResponse); //before we act to test this call with the callBack parameter and not the callBack property we need to null the callBack property + var callBack = speakSchema.CallBack; speakSchema.CallBack = null; // Act var result = await speakClient.StreamCallBack(source, callBack, speakSchema); // Assert - await speakClient.Received().PostAsync($"{UriSegments.SPEAK}?{stringedOptions}", Arg.Any()); + await speakClient.Received().PostAsync(url, Arg.Any(), Arg.Any()); using (new AssertionScope()) { result.Should().NotBeNull(); @@ -114,52 +116,54 @@ public async Task StreamCallBack_With_CallBack_Parameter_Should_Call_PostAsync_R } } - [Test] public async Task StreamCallBack_Throw_ArgumentException_With_CallBack_Property_And_CallBack_Parameter_Set() { - //Arrange + // Input and Output + var url = AbstractRestClient.GetUri(_options, $"{UriSegments.SPEAK}"); var expectedResponse = new AutoFaker().Generate(); var speakSchema = new AutoFaker().Generate(); - var stringedOptions = QueryParameterUtil.GetParameters(speakSchema); var source = new TextSource("Hello World!"); - var httpClient = MockHttpClient.CreateHttpClientWithResult(expectedResponse); + // Fake Client + var httpClient = MockHttpClient.CreateHttpClientWithResult(expectedResponse); var speakClient = Substitute.For(_apiKey, _options); - speakClient.When(x => x.PostAsync(Arg.Any(), Arg.Any())).DoNotCallBase(); - speakClient.PostAsync($"{UriSegments.SPEAK}?{stringedOptions}", Arg.Any()).Returns(expectedResponse); + // Mock Methods + speakClient.When(x => x.PostAsync(Arg.Any(), Arg.Any(), Arg.Any())).DoNotCallBase(); + speakClient.PostAsync(url, Arg.Any(), Arg.Any()).Returns(expectedResponse); var callBack = speakSchema.CallBack; - - // Act Assert + // Act and Assert await speakClient.Invoking(y => y.StreamCallBack(source, callBack, speakSchema)) .Should().ThrowAsync(); - await speakClient.DidNotReceive().PostAsync($"{UriSegments.SPEAK}?{stringedOptions}", Arg.Any()); + await speakClient.DidNotReceive().PostAsync(url, Arg.Any(), Arg.Any()); } [Test] public async Task StreamCallBack_Should_Throw_ArgumentException_With_No_CallBack_Set() { - //Arrange + // Input and Output + var url = AbstractRestClient.GetUri(_options, $"{UriSegments.SPEAK}"); var expectedResponse = new AutoFaker().Generate(); var speakSchema = new AutoFaker().Generate(); var source = new TextSource("Hello World!"); - // speakSchema is not null here as we first need to get the querystring with the callBack included - var stringedOptions = QueryParameterUtil.GetParameters(speakSchema); + // Fake Client var httpClient = MockHttpClient.CreateHttpClientWithResult(expectedResponse); var speakClient = Substitute.For(_apiKey, _options); - speakClient.When(x => x.PostAsync(Arg.Any(), Arg.Any())).DoNotCallBase(); - speakClient.PostAsync($"{UriSegments.SPEAK}?{stringedOptions}", Arg.Any()).Returns(expectedResponse); + // Mock Methods + speakClient.When(x => x.PostAsync(Arg.Any(), Arg.Any(), Arg.Any())).DoNotCallBase(); + speakClient.PostAsync(url, Arg.Any(), Arg.Any()).Returns(expectedResponse); + speakSchema.CallBack = null; - // Act Assert + // Act and Assert await speakClient.Invoking(y => y.StreamCallBack(source, null, speakSchema)) .Should().ThrowAsync(); - await speakClient.DidNotReceive().PostAsync($"{UriSegments.SPEAK}?{stringedOptions}", Arg.Any()); + await speakClient.DidNotReceive().PostAsync(url, Arg.Any(), Arg.Any()); } } diff --git a/Deepgram.Tests/UnitTests/HttpExtensionsTests/HttpClientExtensionTests.cs b/Deepgram.Tests/UnitTests/HttpExtensionsTests/HttpClientExtensionTests.cs index 17cbff4a..63d8e70a 100644 --- a/Deepgram.Tests/UnitTests/HttpExtensionsTests/HttpClientExtensionTests.cs +++ b/Deepgram.Tests/UnitTests/HttpExtensionsTests/HttpClientExtensionTests.cs @@ -27,7 +27,7 @@ public void Setup() [Test] public void Should_Return_HttpClient_With_Default_BaseAddress() { - //Arrange + // Input and Output var httpClient = MockHttpClient.CreateHttpClientWithResult(new MessageResponse(), HttpStatusCode.OK); _httpClientFactory.CreateClient().Returns(httpClient); @@ -45,7 +45,7 @@ public void Should_Return_HttpClient_With_Default_BaseAddress() [Test] public void Should_Return_HttpClient_With_Custom_BaseAddress() { - //Arrange + // Input and Output var expectedBaseAddress = $"https://{_customUrl}/v1/"; var customBaseAddress = $"https://{_customUrl}"; _clientOptions.BaseAddress = customBaseAddress; @@ -66,7 +66,7 @@ public void Should_Return_HttpClient_With_Custom_BaseAddress() [Test] public void Should_Return_HttpClient_With_Default_BaseAddress_And_Custom_Headers() { - //Arrange + // Input and Output _clientOptions.Headers = FakeHeaders(); var httpClient = MockHttpClient.CreateHttpClientWithResult(new MessageResponse(), HttpStatusCode.OK); _httpClientFactory.CreateClient().Returns(httpClient); @@ -86,7 +86,7 @@ public void Should_Return_HttpClient_With_Default_BaseAddress_And_Custom_Headers [Test] public void Should_Return_HttpClient_With_Custom_BaseAddress_And_Custom_Headers() { - //Arrange + // Input and Output _clientOptions.Headers = FakeHeaders(); var httpClient = MockHttpClient.CreateHttpClientWithResult(new MessageResponse(), HttpStatusCode.OK); @@ -113,7 +113,7 @@ public void Should_Return_HttpClient_With_Custom_BaseAddress_And_Custom_Headers( [Test] public void Should_Return_HttpClient_With_Predefined_values() { - //Arrange + // Input and Output _clientOptions.Headers = FakeHeaders(); var expectedBaseAddress = $"https://{_customUrl}/v1/"; var customBaseAddress = $"https://{_customUrl}"; diff --git a/Deepgram.Tests/UnitTests/LoggerProviderTests/LogProviderTest.cs b/Deepgram.Tests/UnitTests/LoggerProviderTests/LogProviderTest.cs index 6140d296..551bd783 100644 --- a/Deepgram.Tests/UnitTests/LoggerProviderTests/LogProviderTest.cs +++ b/Deepgram.Tests/UnitTests/LoggerProviderTests/LogProviderTest.cs @@ -11,7 +11,7 @@ public class LogProviderTest [Test] public void SetLogFactory_Should_Set_LoggerFactory() { - //Arrange + // Input and Output var loggerFactory = Substitute.For(); //Act diff --git a/Deepgram.Tests/UnitTests/UtilitiesTests/QueryParameterUtilTests.cs b/Deepgram.Tests/UnitTests/UtilitiesTests/QueryParameterUtilTests.cs index 6e076990..b7b499b2 100644 --- a/Deepgram.Tests/UnitTests/UtilitiesTests/QueryParameterUtilTests.cs +++ b/Deepgram.Tests/UnitTests/UtilitiesTests/QueryParameterUtilTests.cs @@ -12,25 +12,26 @@ public class QueryParameterUtilTests [Test] public void GetParameters_Should_Return_EmptyString_When_Parameters_Is_Null() { - - //Arrange + // Input and Output PrerecordedSchema? para = null; + var expected = $"https://{Defaults.DEFAULT_URI}"; + //Act - var result = QueryParameterUtil.GetParameters(para); + var result = QueryParameterUtil.FormatURL(Defaults.DEFAULT_URI, para); //Assert - result.Should().BeEmpty(); + result.Should().Contain(expected); } [Test] public void GetParameters_Should_Return_String_When_Passing_String_Parameter() { - //Arrange + // Input and Output var prerecordedOptions = new AutoFaker().Generate(); var expectedModel = HttpUtility.UrlEncode(prerecordedOptions.Model)!; var expected = $"{nameof(prerecordedOptions.Model).ToLower()}={expectedModel}"; //Act - var result = QueryParameterUtil.GetParameters(prerecordedOptions); + var result = QueryParameterUtil.FormatURL(Defaults.DEFAULT_URI, prerecordedOptions); //Assert result.Should().NotBeNull(); @@ -40,12 +41,12 @@ public void GetParameters_Should_Return_String_When_Passing_String_Parameter() [Test] public void GetParameters_Should_Return_String_Respecting_CallBack_Casing() { - //Arrange + // Input and Output var prerecordedOptions = new AutoFaker().Generate(); prerecordedOptions.CallBack = "https://Signed23.com"; var expected = $"{nameof(prerecordedOptions.CallBack).ToLower()}={HttpUtility.UrlEncode("https://Signed23.com")}"; //Act - var result = QueryParameterUtil.GetParameters(prerecordedOptions); + var result = QueryParameterUtil.FormatURL(Defaults.DEFAULT_URI, prerecordedOptions); //Assert result.Should().NotBeNull(); @@ -55,12 +56,12 @@ public void GetParameters_Should_Return_String_Respecting_CallBack_Casing() [Test] public void GetParameters_Should_Return_String_When_Passing_Int_Parameter() { - //Arrange + // Input and Output var obj = new PrerecordedSchema() { Alternatives = 1 }; var expected = $"alternatives={obj.Alternatives}"; //Act - var result = QueryParameterUtil.GetParameters(obj); + var result = QueryParameterUtil.FormatURL(Defaults.DEFAULT_URI, obj); //Assert result.Should().NotBeNull(); @@ -70,7 +71,7 @@ public void GetParameters_Should_Return_String_When_Passing_Int_Parameter() [Test] public void GetParameters_Should_Return_String_When_Passing_Array_Parameter() { - //Arrange + // Input and Output var prerecordedOptions = new PrerecordedSchema { Keywords = ["test", "acme"] @@ -78,7 +79,7 @@ public void GetParameters_Should_Return_String_When_Passing_Array_Parameter() var expected = $"keywords={prerecordedOptions.Keywords[0].ToLower()}"; //Act - var result = QueryParameterUtil.GetParameters(prerecordedOptions); + var result = QueryParameterUtil.FormatURL(Defaults.DEFAULT_URI, prerecordedOptions); //Assert result.Should().NotBeNull(); @@ -87,7 +88,7 @@ public void GetParameters_Should_Return_String_When_Passing_Array_Parameter() public void GetParameters_Should_Return_String_When_Passing_Dictonary_Parameter() { - //Arrange + // Input and Output var prerecordedOptions = new PrerecordedSchema() { Extra = new Dictionary @@ -99,7 +100,7 @@ public void GetParameters_Should_Return_String_When_Passing_Dictonary_Parameter( var expected = $"extra={HttpUtility.UrlEncode("KeyOne:ValueOne")}&extra={HttpUtility.UrlEncode("KeyTwo:ValueTwo")}"; //Act - var result = QueryParameterUtil.GetParameters(prerecordedOptions); + var result = QueryParameterUtil.FormatURL(Defaults.DEFAULT_URI, prerecordedOptions); //Assert result.Should().NotBeNull(); @@ -109,14 +110,14 @@ public void GetParameters_Should_Return_String_When_Passing_Dictonary_Parameter( [Test] public void GetParameters_Should_Return_String_When_Passing_Decimal_Parameter() { - //Arrange + // Input and Output var prerecordedOptions = new PrerecordedSchema() { UttSplit = 2.3 }; var expected = $"utt_split={HttpUtility.UrlEncode(prerecordedOptions.UttSplit.ToString())}"; //Act // need to set manual as the precision can be very long and gets trimmed from autogenerated value - var result = QueryParameterUtil.GetParameters(prerecordedOptions); + var result = QueryParameterUtil.FormatURL(Defaults.DEFAULT_URI, prerecordedOptions); //Assert result.Should().NotBeNull(); @@ -126,11 +127,11 @@ public void GetParameters_Should_Return_String_When_Passing_Decimal_Parameter() [Test] public void GetParameters_Should_Return_String_When_Passing_Boolean_Parameter() { - //Arrange + // Input and Output var obj = new PrerecordedSchema() { Paragraphs = true }; var expected = $"{nameof(obj.Paragraphs).ToLower()}=true"; //Act - var result = QueryParameterUtil.GetParameters(obj); + var result = QueryParameterUtil.FormatURL(Defaults.DEFAULT_URI, obj); //Assert result.Should().NotBeNull(); @@ -140,7 +141,7 @@ public void GetParameters_Should_Return_String_When_Passing_Boolean_Parameter() [Test] public void GetParameters_Should_Return_String_When_Passing_DateTime_Parameter() { - //Arrange + // Input and Output var options = new AutoFaker().Generate(); var time = DateTime.Now; options.ExpirationDate = time; @@ -148,7 +149,7 @@ public void GetParameters_Should_Return_String_When_Passing_DateTime_Parameter() var expected = $"expiration_date={HttpUtility.UrlEncode(time.ToString("yyyy-MM-dd"))}"; //Act - var result = QueryParameterUtil.GetParameters(options); + var result = QueryParameterUtil.FormatURL(Defaults.DEFAULT_URI, options); //Assert result.Should().NotBeNull(); @@ -158,12 +159,12 @@ public void GetParameters_Should_Return_String_When_Passing_DateTime_Parameter() [Test] public void GetParameters_Should_Return_Valid_String_When_CallBack_Set() { - //Arrange + // Input and Output var signedCallBackUrl = "As$Ssw.com"; var expected = HttpUtility.UrlEncode(signedCallBackUrl); //Act - var result = QueryParameterUtil.GetParameters(new PrerecordedSchema() { CallBack = signedCallBackUrl, Diarize = true }); + var result = QueryParameterUtil.FormatURL(Defaults.DEFAULT_URI, new PrerecordedSchema() { CallBack = signedCallBackUrl, Diarize = true }); //Assert result.Should().NotBeNull(); @@ -174,11 +175,11 @@ public void GetParameters_Should_Return_Valid_String_When_CallBack_Set() public void GetParameters_Should_Return_Empty_String_When_Parameter_Has_No_Values() { //Act - var result = QueryParameterUtil.GetParameters(new PrerecordedSchema()); + var result = QueryParameterUtil.FormatURL(Defaults.DEFAULT_URI, new PrerecordedSchema()); //Assert result.Should().NotBeNull(); - result.Should().Be(string.Empty); + result.Should().Be($"https://{Defaults.DEFAULT_URI}"); } } \ No newline at end of file diff --git a/Deepgram.Tests/UnitTests/UtilitiesTests/RequestContentUtilTests.cs b/Deepgram.Tests/UnitTests/UtilitiesTests/RequestContentUtilTests.cs index 2c5e4802..cdba2d3e 100644 --- a/Deepgram.Tests/UnitTests/UtilitiesTests/RequestContentUtilTests.cs +++ b/Deepgram.Tests/UnitTests/UtilitiesTests/RequestContentUtilTests.cs @@ -3,19 +3,21 @@ // SPDX-License-Identifier: MIT using Deepgram.Models.Manage.v1; +using Deepgram.Abstractions; namespace Deepgram.Tests.UnitTests.UtilitiesTests; -public class RequestContentUtilTests + +public class HttpRequestUtilTests { [Test] public void CreatePayload_Should_Return_StringContent() { - //Arrange + // Input and Output var project = new AutoFaker().Generate(); //Act - var result = RequestContentUtil.CreatePayload(project); + var result = HttpRequestUtil.CreatePayload(project); //Assert using (new AssertionScope()) @@ -29,12 +31,12 @@ public void CreatePayload_Should_Return_StringContent() [Test] public void CreateStreamPayload_Should_Return_HttpContent() { - //Arrange + // Input and Output var source = System.Text.Encoding.ASCII.GetBytes("Acme Unit Testing"); var stream = new MemoryStream(source); //Act - var result = RequestContentUtil.CreateStreamPayload(stream); + var result = HttpRequestUtil.CreateStreamPayload(stream); //Assert using (new AssertionScope()) diff --git a/Deepgram/Abstractions/AbstractRestClient.cs b/Deepgram/Abstractions/AbstractRestClient.cs index 43a22956..e8926a86 100644 --- a/Deepgram/Abstractions/AbstractRestClient.cs +++ b/Deepgram/Abstractions/AbstractRestClient.cs @@ -3,6 +3,7 @@ // SPDX-License-Identifier: MIT using Deepgram.Encapsulations; +using Deepgram.Models.Analyze.v1; using Deepgram.Models.Authenticate.v1; namespace Deepgram.Abstractions; @@ -18,6 +19,11 @@ public abstract class AbstractRestClient /// internal ILogger _logger => LogProvider.GetLogger(this.GetType().Name); + /// + /// Copy of the options for the client + /// + internal DeepgramClientOptions _options; + /// /// Constructor that take the options and a httpClient /// @@ -28,6 +34,7 @@ internal AbstractRestClient(string apiKey = "", DeepgramClientOptions? options = options ??= new DeepgramClientOptions(); _httpClient = HttpClientFactory.Create(); _httpClient = HttpClientFactory.ConfigureDeepgram(_httpClient, apiKey, options); + _options = options; } /// @@ -36,15 +43,74 @@ internal AbstractRestClient(string apiKey = "", DeepgramClientOptions? options = /// Type of class of response expected /// request uri Endpoint /// Instance of T - public virtual async Task GetAsync(string uriSegment, CancellationToken cancellationToken = default, Dictionary? addons = null) + public virtual async Task GetAsync(string uriSegment, CancellationTokenSource? cancellationToken = null, + Dictionary? addons = null, Dictionary? headers = null) { try { - var req = new HttpRequestMessage(HttpMethod.Get, QueryParameterUtil.AppendQueryParameters(uriSegment, addons)); + // if not defined, use default timeout + if (cancellationToken == null) + { + cancellationToken = new CancellationTokenSource(); + cancellationToken.CancelAfter(Constants.DefaultRESTTimeout); + } + + // create request message and add custom query parameters + NoopSchema? parameter = null; + var request = new HttpRequestMessage(HttpMethod.Get, QueryParameterUtil.FormatURL(uriSegment, parameter, addons)); - var response = await _httpClient.SendAsync(req, cancellationToken); + // add custom headers + if (headers != null) + { + foreach (var header in headers) + { + request.Headers.Add(header.Key, header.Value); + } + } + + // do the request + var response = await _httpClient.SendAsync(request, cancellationToken.Token); response.EnsureSuccessStatusCode(); - var result = await RequestContentUtil.DeserializeAsync(response); + var result = await HttpRequestUtil.DeserializeAsync(response); + + return result; + } + catch (Exception ex) + { + Log.Exception(_logger, "GET", ex); + throw; + } + } + + public virtual async Task GetAsync(string uriSegment, S? parameter, CancellationTokenSource? cancellationToken = null, + Dictionary? addons = null, Dictionary? headers = null) + { + try + { + // if not defined, use default timeout + if (cancellationToken == null) + { + cancellationToken = new CancellationTokenSource(); + cancellationToken.CancelAfter(Constants.DefaultRESTTimeout); + } + + // create request message and add custom query parameters + var request = new HttpRequestMessage(HttpMethod.Get, QueryParameterUtil.FormatURL(uriSegment, parameter, addons)); + + // add custom headers + if (headers != null) + { + foreach (var header in headers) + { + request.Headers.Add(header.Key, header.Value); + } + } + + // do the request + var response = await _httpClient.SendAsync(request, cancellationToken.Token); + response.EnsureSuccessStatusCode(); + var result = await HttpRequestUtil.DeserializeAsync(response); + return result; } catch (Exception ex) @@ -61,56 +127,89 @@ public virtual async Task GetAsync(string uriSegment, CancellationToken ca /// Uri for the api including the query parameters /// HttpContent as content for HttpRequestMessage /// Instance of T - public virtual async Task<(Dictionary, MemoryStream)> PostFileAsync(string uriSegment, HttpContent content, List keys, CancellationToken cancellationToken = default, Dictionary? addons = null) + public virtual async Task PostRetrieveLocalFileAsync(string uriSegment, S? parameter, R? content, + List? keys = null, CancellationTokenSource? cancellationToken = null, Dictionary? addons = null, + Dictionary? headers = null + ) { try { - var req = new HttpRequestMessage(HttpMethod.Post, QueryParameterUtil.AppendQueryParameters(uriSegment, addons)) { Content = content }; - var response = await _httpClient.SendAsync(req, cancellationToken); + // if not defined, use default timeout + if (cancellationToken == null) + { + cancellationToken = new CancellationTokenSource(); + cancellationToken.CancelAfter(Constants.DefaultRESTTimeout); + } + + // create request message and add custom query parameters + var request = new HttpRequestMessage(HttpMethod.Post, QueryParameterUtil.FormatURL(uriSegment, parameter, addons)) + { + Content = HttpRequestUtil.CreatePayload(content) + }; + + // add custom headers + if (headers != null) + { + foreach (var header in headers) + { + request.Headers.Add(header.Key, header.Value); + } + } + + // do the request + var response = await _httpClient.SendAsync(request, cancellationToken.Token); response.EnsureSuccessStatusCode(); var result = new Dictionary(); - for (int i = 0; i < response.Headers.Count(); i++) + if (keys != null) { - var key = response.Headers.ElementAt(i).Key.ToLower(); - var value = response.Headers.GetValues(key).FirstOrDefault() ?? ""; - - var index = key.IndexOf("x-dg-"); - if (index == 0) + for (int i = 0; i < response.Headers.Count(); i++) { - var newKey = key.Substring(5); - if (keys.Contains(newKey)) + var key = response.Headers.ElementAt(i).Key.ToLower(); + var value = response.Headers.GetValues(key).FirstOrDefault() ?? ""; + + var index = key.IndexOf("x-dg-"); + if (index == 0) { - result.Add(newKey, value); - continue; + var newKey = key.Substring(5); + if (keys.Contains(newKey)) + { + result.Add(newKey, value); + continue; + } } - } - index = key.IndexOf("dg-"); - if (index == 0) - { - var newKey = key.Substring(3); - if (keys.Contains(newKey)) + index = key.IndexOf("dg-"); + if (index == 0) + { + var newKey = key.Substring(3); + if (keys.Contains(newKey)) + { + result.Add(newKey, value); + continue; + } + } + if (keys.Contains(key)) { - result.Add(newKey, value); - continue; + result.Add(key, value); } } - if (keys.Contains(key)) + + if (keys.Contains("content-type")) { - result.Add(key, value); + result.Add("content-type", response.Content.Headers.ContentType?.MediaType ?? ""); } } - if (keys.Contains("content-type")) - { - result.Add("content-type", response.Content.Headers.ContentType?.MediaType ?? ""); - } - MemoryStream stream = new MemoryStream(); await response.Content.CopyToAsync(stream); - return (result, stream); + return new LocalFileWithMetadata() + { + Metadata = result, + Content = stream, + }; + } catch (Exception ex) { @@ -126,14 +225,37 @@ public virtual async Task GetAsync(string uriSegment, CancellationToken ca /// Uri for the api including the query parameters /// HttpContent as content for HttpRequestMessage /// Instance of T - public virtual async Task PostAsync(string uriSegment, HttpContent content, CancellationToken cancellationToken = default, Dictionary? addons = null) + public virtual async Task PostAsync(string uriSegment, S? parameter, CancellationTokenSource? cancellationToken = null, + Dictionary? addons = null, Dictionary? headers = null) { try { - var req = new HttpRequestMessage(HttpMethod.Post, QueryParameterUtil.AppendQueryParameters(uriSegment, addons)) { Content = content }; - var response = await _httpClient.SendAsync(req, cancellationToken); + // if not defined, use default timeout + if (cancellationToken == null) + { + cancellationToken = new CancellationTokenSource(); + cancellationToken.CancelAfter(Constants.DefaultRESTTimeout); + } + + // create request message and add custom query parameters + var request = new HttpRequestMessage(HttpMethod.Post, QueryParameterUtil.FormatURL(uriSegment, parameter, addons)) + { + Content = HttpRequestUtil.CreatePayload(parameter) + }; + + // add custom headers + if (headers != null) + { + foreach (var header in headers) + { + request.Headers.Add(header.Key, header.Value); + } + } + + // do the request + var response = await _httpClient.SendAsync(request, cancellationToken.Token); response.EnsureSuccessStatusCode(); - var result = await RequestContentUtil.DeserializeAsync(response); + var result = await HttpRequestUtil.DeserializeAsync(response); return result; } @@ -142,49 +264,55 @@ public virtual async Task PostAsync(string uriSegment, HttpContent content Log.Exception(_logger, "POST", ex); throw; } - } - - /// - /// Delete Method for use with calls that do not expect a response - /// - /// Uri for the api including the query parameters - public virtual async Task DeleteAsync(string uriSegment, CancellationToken cancellationToken = default, Dictionary? addons = null) + public virtual async Task PostAsync(string uriSegment, S? parameter, R? content, CancellationTokenSource? cancellationToken = null, + Dictionary? addons = null, Dictionary? headers = null) { try { - var req = new HttpRequestMessage(HttpMethod.Delete, QueryParameterUtil.AppendQueryParameters(uriSegment, addons)); - var response = await _httpClient.SendAsync(req, cancellationToken); - response.EnsureSuccessStatusCode(); - } - catch (Exception ex) - { - Log.Exception(_logger, "DELETE", ex); - throw; - } - } + // if not defined, use default timeout + if (cancellationToken == null) + { + cancellationToken = new CancellationTokenSource(); + cancellationToken.CancelAfter(Constants.DefaultRESTTimeout); + } - /// - /// Delete method that returns the type of response specified - /// - /// Class Type of expected response - /// Uri for the api including the query parameters - /// Instance of T or throws Exception - public virtual async Task DeleteAsync(string uriSegment, CancellationToken cancellationToken = default, Dictionary? addons = null) - { - try - { - var req = new HttpRequestMessage(HttpMethod.Delete, QueryParameterUtil.AppendQueryParameters(uriSegment, addons)); - var response = await _httpClient.SendAsync(req, cancellationToken); + // create request message and add custom query parameters + var request = new HttpRequestMessage(HttpMethod.Post, QueryParameterUtil.FormatURL(uriSegment, parameter, addons)); + if (typeof(R) == typeof(Stream)) + { + Stream? stream = content as Stream; + if (stream == null) + { + stream = new MemoryStream(); + } + request.Content = HttpRequestUtil.CreateStreamPayload(stream); + } + else + { + request.Content = HttpRequestUtil.CreatePayload(content); + } + + // add custom headers + if (headers != null) + { + foreach (var header in headers) + { + request.Headers.Add(header.Key, header.Value); + } + } + + // do the request + var response = await _httpClient.SendAsync(request, cancellationToken.Token); response.EnsureSuccessStatusCode(); - var result = await RequestContentUtil.DeserializeAsync(response); + var result = await HttpRequestUtil.DeserializeAsync(response); return result; } catch (Exception ex) { - Log.Exception(_logger, "DELETE ASYNC", ex); + Log.Exception(_logger, "POST", ex); throw; } } @@ -195,20 +323,45 @@ public virtual async Task DeleteAsync(string uriSegment, CancellationToken /// Class type of what return type is expected /// Uri for the api including the query parameters /// Instance of T - public virtual async Task PatchAsync(string uriSegment, StringContent content, CancellationToken cancellationToken = default, Dictionary? addons = null) + public virtual async Task PatchAsync(string uriSegment, S? parameter, CancellationTokenSource? cancellationToken = null, + Dictionary? addons = null, Dictionary? headers = null) { try { + // if not defined, use default timeout + if (cancellationToken == null) + { + cancellationToken = new CancellationTokenSource(); + cancellationToken.CancelAfter(Constants.DefaultRESTTimeout); + } + + // create request message and add custom query parameters #if NETSTANDARD2_0 - var request = new HttpRequestMessage(new HttpMethod("PATCH"), QueryParameterUtil.AppendQueryParameters(uriSegment, addons)) { Content = content }; - var response = await _httpClient.SendAsync(request, cancellationToken); + var request = new HttpRequestMessage(new HttpMethod("PATCH"), QueryParameterUtil.FormatURL(uriSegment, parameter, addons)) + { + Content = HttpRequestUtil.CreatePayload(parameter) + }; #else - var request = new HttpRequestMessage(HttpMethod.Patch, QueryParameterUtil.AppendQueryParameters(uriSegment, addons)) { Content = content }; - var response = await _httpClient.SendAsync(request, cancellationToken); - + var request = new HttpRequestMessage(HttpMethod.Patch, QueryParameterUtil.FormatURL(uriSegment, parameter, addons)) + { + Content = HttpRequestUtil.CreatePayload(parameter) + }; #endif + + // add custom headers + if (headers != null) + { + foreach (var header in headers) + { + request.Headers.Add(header.Key, header.Value); + } + } + + // do the request + var response = await _httpClient.SendAsync(request, cancellationToken.Token); response.EnsureSuccessStatusCode(); - var result = await RequestContentUtil.DeserializeAsync(response); + var result = await HttpRequestUtil.DeserializeAsync(response); + return result; } @@ -226,17 +379,37 @@ public virtual async Task PatchAsync(string uriSegment, StringContent cont /// Class type of what return type is expected /// Uri for the api /// Instance of T - public virtual async Task PutAsync(string uriSegment, StringContent content, CancellationToken cancellationToken = default, Dictionary? addons = null) + public virtual async Task PutAsync(string uriSegment, S? parameter, CancellationTokenSource? cancellationToken = null, + Dictionary? addons = null, Dictionary? headers = null) { try { - var req = new HttpRequestMessage(HttpMethod.Put, QueryParameterUtil.AppendQueryParameters(uriSegment, addons)) + // if not defined, use default timeout + if (cancellationToken == null) + { + cancellationToken = new CancellationTokenSource(); + cancellationToken.CancelAfter(Constants.DefaultRESTTimeout); + } + + // create request message and add custom query parameters + var request = new HttpRequestMessage(HttpMethod.Put, QueryParameterUtil.FormatURL(uriSegment, parameter, addons)) { - Content = content + Content = HttpRequestUtil.CreatePayload(parameter) }; - var response = await _httpClient.SendAsync(req, cancellationToken); + + // add custom headers + if (headers != null) + { + foreach (var header in headers) + { + request.Headers.Add(header.Key, header.Value); + } + } + + // do the request + var response = await _httpClient.SendAsync(request, cancellationToken.Token); response.EnsureSuccessStatusCode(); - var result = await RequestContentUtil.DeserializeAsync(response); + var result = await HttpRequestUtil.DeserializeAsync(response); return result; } @@ -247,15 +420,116 @@ public virtual async Task PutAsync(string uriSegment, StringContent conten } } + /// + /// Delete Method for use with calls that do not expect a response + /// + /// Uri for the api including the query parameters + public virtual async Task DeleteAsync(string uriSegment, CancellationTokenSource? cancellationToken = null, Dictionary? addons = null, + Dictionary? headers = null) + { + try + { + // if not defined, use default timeout + if (cancellationToken == null) + { + cancellationToken = new CancellationTokenSource(); + cancellationToken.CancelAfter(Constants.DefaultRESTTimeout); + } + + // create request message and add custom query parameters + var request = new HttpRequestMessage(HttpMethod.Delete, QueryParameterUtil.FormatURL(uriSegment, new NoopSchema(), addons)); + + // add custom headers + if (headers != null) + { + foreach (var header in headers) + { + request.Headers.Add(header.Key, header.Value); + } + } + + // do the request + var response = await _httpClient.SendAsync(request, cancellationToken.Token); + response.EnsureSuccessStatusCode(); + var result = await HttpRequestUtil.DeserializeAsync(response); + + return result; + } + catch (Exception ex) + { + Log.Exception(_logger, "DELETE", ex); + throw; + } + } /// - /// Allow for the setting of a HttpClient timeout, timeout will change for any future calls - /// calls that are currently running will not be affected + /// Delete method that returns the type of response specified /// - /// - public void SpecifyTimeOut(TimeSpan timeout) + /// Class Type of expected response + /// Uri for the api including the query parameters + /// Instance of T or throws Exception + public virtual async Task DeleteAsync(string uriSegment, S? parameter, CancellationTokenSource? cancellationToken = null, Dictionary? addons = null, + Dictionary? headers = null) + { + try + { + // if not defined, use default timeout + if (cancellationToken == null) + { + cancellationToken = new CancellationTokenSource(); + cancellationToken.CancelAfter(Constants.DefaultRESTTimeout); + } + + // create request message and add custom query parameters + var request = new HttpRequestMessage(HttpMethod.Delete, QueryParameterUtil.FormatURL(uriSegment, parameter, addons)); + + // add custom headers + if (headers != null) + { + foreach (var header in headers) + { + request.Headers.Add(header.Key, header.Value); + } + } + + // do the request + var response = await _httpClient.SendAsync(request, cancellationToken.Token); + response.EnsureSuccessStatusCode(); + var result = await HttpRequestUtil.DeserializeAsync(response); + + return result; + } + catch (Exception ex) + { + Log.Exception(_logger, "DELETE ASYNC", ex); + throw; + } + } + + internal static string GetUri(DeepgramClientOptions options, string path) + { + var baseUrl = GetBaseUrl(options); + return $"{baseUrl}/{options.APIVersion}/{path}"; + } + + internal static string GetBaseUrl(DeepgramClientOptions options) { - _httpClient.Timeout = timeout; + string baseAddress = Defaults.DEFAULT_URI; + if (options.BaseAddress != null) + { + baseAddress = options.BaseAddress; + } + + //checks for ws:// wss:// ws wss - wss:// is include to ensure it is all stripped out and correctly formatted + Regex regex = new Regex(@"\b(http:\/\/|https:\/\/|http|https)\b", RegexOptions.IgnoreCase); + if (!regex.IsMatch(baseAddress)) + { + //if no protocol in the address then https:// is added + // TODO: log + baseAddress = $"https://{baseAddress}"; + } + + return baseAddress; } } diff --git a/Deepgram/Abstractions/Constants.cs b/Deepgram/Abstractions/Constants.cs new file mode 100644 index 00000000..fa730a45 --- /dev/null +++ b/Deepgram/Abstractions/Constants.cs @@ -0,0 +1,17 @@ +// Copyright 2021-2024 Deepgram .NET SDK contributors. All Rights Reserved. +// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// SPDX-License-Identifier: MIT + +namespace Deepgram.Abstractions; + +/// +/// Defaults for the REST Client +/// +public static class Constants +{ + // For Speak Headers + public const int OneSecond = 1000; + public const int OneMinute = 60 * OneSecond; + public const int DefaultRESTTimeout = 5 * OneMinute; +} + diff --git a/Deepgram/Abstractions/LocalFileWithMetadata.cs b/Deepgram/Abstractions/LocalFileWithMetadata.cs new file mode 100644 index 00000000..5cbb5008 --- /dev/null +++ b/Deepgram/Abstractions/LocalFileWithMetadata.cs @@ -0,0 +1,12 @@ +// Copyright 2021-2024 Deepgram .NET SDK contributors. All Rights Reserved. +// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// SPDX-License-Identifier: MIT + +namespace Deepgram.Abstractions; + +public class LocalFileWithMetadata +{ + public Dictionary Metadata { get; set; } + + public MemoryStream Content { get; set; } +} diff --git a/Deepgram/Utilities/RequestContentUtil.cs b/Deepgram/Abstractions/Utilities.cs similarity index 93% rename from Deepgram/Utilities/RequestContentUtil.cs rename to Deepgram/Abstractions/Utilities.cs index 0957eaba..050efb3a 100644 --- a/Deepgram/Utilities/RequestContentUtil.cs +++ b/Deepgram/Abstractions/Utilities.cs @@ -2,13 +2,13 @@ // Use of this source code is governed by a MIT license that can be found in the LICENSE file. // SPDX-License-Identifier: MIT -namespace Deepgram.Utilities; +namespace Deepgram.Abstractions; -internal static class RequestContentUtil +internal static class HttpRequestUtil { public const string DEFAULT_CONTENT_TYPE = "application/json"; - static ILogger logger => LogProvider.GetLogger(nameof(RequestContentUtil)); + static ILogger logger => LogProvider.GetLogger(nameof(HttpRequestUtil)); static readonly JsonSerializerOptions _jsonSerializerOptions = new() { DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull, diff --git a/Deepgram/Clients/Analyze/v1/Client.cs b/Deepgram/Clients/Analyze/v1/Client.cs index 4dd087a1..931a54ca 100644 --- a/Deepgram/Clients/Analyze/v1/Client.cs +++ b/Deepgram/Clients/Analyze/v1/Client.cs @@ -22,25 +22,26 @@ public class Client(string apiKey, DeepgramClientOptions? deepgramClientOptions /// Url to the file that is to be analyzed /// Options for the transcription /// - public async Task AnalyzeUrl(UrlSource source, AnalyzeSchema? analyzeSchema, Dictionary? addons = null, CancellationToken cancellationToken = default) + public async Task AnalyzeUrl(UrlSource source, AnalyzeSchema? analyzeSchema, CancellationTokenSource? cancellationToken = default, Dictionary? addons = null, Dictionary? headers = null) { VerifyNoCallBack(nameof(AnalyzeUrl), analyzeSchema); - var stringedOptions = QueryParameterUtil.GetParameters(analyzeSchema, addons); - return await PostAsync( - $"{UriSegments.READ}?{stringedOptions}", - RequestContentUtil.CreatePayload(source), cancellationToken); + return await PostAsync( + GetUri(_options, UriSegments.READ), analyzeSchema, source, cancellationToken, addons, headers + ); } + + /// /// Analyzes a file using the provided byte array /// /// file is the form of a byte[] /// Options for the transcription /// - public async Task AnalyzeFile(byte[] source, AnalyzeSchema? analyzeSchema, CancellationToken cancellationToken = default, Dictionary? addons = null) + public async Task AnalyzeFile(byte[] source, AnalyzeSchema? analyzeSchema, CancellationTokenSource? cancellationToken = default, Dictionary? addons = null, Dictionary? headers = null) { MemoryStream stream = new MemoryStream(source); - return await AnalyzeFile(stream, analyzeSchema, cancellationToken, addons); + return await AnalyzeFile(stream, analyzeSchema, cancellationToken, addons, headers); } /// @@ -49,14 +50,13 @@ public async Task AnalyzeFile(byte[] source, AnalyzeSchema? analyz /// file is the form of a stream /// Options for the transcription /// - public async Task AnalyzeFile(Stream source, AnalyzeSchema? analyzeSchema, CancellationToken cancellationToken = default, Dictionary? addons = null) + public async Task AnalyzeFile(Stream source, AnalyzeSchema? analyzeSchema, CancellationTokenSource? cancellationToken = default, Dictionary? addons = null, Dictionary? headers = null) { VerifyNoCallBack(nameof(AnalyzeFile), analyzeSchema); - var stringedOptions = QueryParameterUtil.GetParameters(analyzeSchema, addons); - return await PostAsync( - $"{UriSegments.READ}?{stringedOptions}", - RequestContentUtil.CreateStreamPayload(source), cancellationToken); + return await PostAsync( + GetUri(_options, UriSegments.READ), analyzeSchema, source, cancellationToken, addons, headers + ); } #endregion @@ -69,18 +69,10 @@ public async Task AnalyzeFile(Stream source, AnalyzeSchema? analyz /// CallBack url /// Options for the transcription /// - public async Task AnalyzeFileCallBack(byte[] source, string? callBack, AnalyzeSchema? analyzeSchema, CancellationToken cancellationToken = default, Dictionary? addons = null) + public async Task AnalyzeFileCallBack(byte[] source, string? callBack, AnalyzeSchema? analyzeSchema, CancellationTokenSource? cancellationToken = default, Dictionary? addons = null, Dictionary? headers = null) { - VerifyOneCallBackSet(nameof(AnalyzeFileCallBack), callBack, analyzeSchema); - if (callBack != null) - analyzeSchema.CallBack = callBack; - - var stringedOptions = QueryParameterUtil.GetParameters(analyzeSchema, addons); - var stream = new MemoryStream(); - stream.Write(source, 0, source.Length); - return await PostAsync( - $"{UriSegments.READ}?{stringedOptions}", - RequestContentUtil.CreateStreamPayload(stream), cancellationToken); + MemoryStream stream = new MemoryStream(source); + return await AnalyzeFileCallBack(stream, callBack, analyzeSchema, cancellationToken, addons, headers); } /// @@ -90,16 +82,15 @@ public async Task AnalyzeFileCallBack(byte[] source, string? call /// CallBack url /// Options for the transcription /// - public async Task AnalyzeFileCallBack(Stream source, string? callBack, AnalyzeSchema? analyzeSchema, CancellationToken cancellationToken = default, Dictionary? addons = null) + public async Task AnalyzeFileCallBack(Stream source, string? callBack, AnalyzeSchema? analyzeSchema, CancellationTokenSource? cancellationToken = default, Dictionary? addons = null, Dictionary? headers = null) { VerifyOneCallBackSet(nameof(AnalyzeFileCallBack), callBack, analyzeSchema); if (callBack != null) analyzeSchema.CallBack = callBack; - var stringedOptions = QueryParameterUtil.GetParameters(analyzeSchema, addons); - return await PostAsync( - $"{UriSegments.READ}?{stringedOptions}", - RequestContentUtil.CreateStreamPayload(source), cancellationToken); + return await PostAsync( + GetUri(_options, UriSegments.READ), analyzeSchema, source, cancellationToken, addons, headers + ); } /// @@ -109,16 +100,15 @@ public async Task AnalyzeFileCallBack(Stream source, string? call /// CallBack url /// Options for the transcription /// - public async Task AnalyzeUrlCallBack(UrlSource source, string? callBack, AnalyzeSchema? analyzeSchema, CancellationToken cancellationToken = default, Dictionary? addons = null) + public async Task AnalyzeUrlCallBack(UrlSource source, string? callBack, AnalyzeSchema? analyzeSchema, CancellationTokenSource? cancellationToken = default, Dictionary? addons = null, Dictionary? headers = null) { VerifyOneCallBackSet(nameof(AnalyzeUrlCallBack), callBack, analyzeSchema); if (callBack != null) analyzeSchema.CallBack = callBack; - var stringedOptions = QueryParameterUtil.GetParameters(analyzeSchema, addons); - return await PostAsync( - $"{UriSegments.READ}?{stringedOptions}", - RequestContentUtil.CreatePayload(source), cancellationToken); + return await PostAsync( + GetUri(_options, UriSegments.READ), analyzeSchema, source, cancellationToken, addons, headers + ); } #endregion diff --git a/Deepgram/Clients/Live/v1/Client.cs b/Deepgram/Clients/Live/v1/Client.cs index fd1eb173..a48a80cc 100644 --- a/Deepgram/Clients/Live/v1/Client.cs +++ b/Deepgram/Clients/Live/v1/Client.cs @@ -17,7 +17,7 @@ public class Client : IDisposable internal readonly DeepgramClientOptions _deepgramClientOptions; internal readonly string _apiKey; internal ClientWebSocket? _clientWebSocket; - internal readonly CancellationTokenSource _tokenSource = new(); + internal CancellationTokenSource _cancellationTokenSource; internal bool _isDisposed; #endregion @@ -63,7 +63,7 @@ public Client(string apiKey = "", DeepgramClientOptions? options = null) /// /// Options to use when transcribing audio /// The task object representing the asynchronous operation. - public async Task Connect(LiveSchema options, CancellationToken ? cancellationToken = null, Dictionary? addons = null) + public async Task Connect(LiveSchema options, CancellationTokenSource? cancellationToken = null, Dictionary? addons = null) { // create client _clientWebSocket = new ClientWebSocket(); @@ -78,11 +78,17 @@ public async Task Connect(LiveSchema options, CancellationToken ? cancellationTo } // cancelation token - var cancelToken = cancellationToken ?? _tokenSource.Token; + if (cancellationToken != null) + { + _cancellationTokenSource = cancellationToken; + } else + { + _cancellationTokenSource = new CancellationTokenSource(); + } try { - await _clientWebSocket.ConnectAsync(GetUri(options, _deepgramClientOptions, addons),cancelToken).ConfigureAwait(false); + await _clientWebSocket.ConnectAsync(GetUri(_deepgramClientOptions, options, addons), _cancellationTokenSource.Token).ConfigureAwait(false); StartSenderBackgroundThread(); StartReceiverBackgroundThread(); } @@ -93,13 +99,11 @@ public async Task Connect(LiveSchema options, CancellationToken ? cancellationTo void StartSenderBackgroundThread() => _ = Task.Factory.StartNew( _ => ProcessSendQueue(), - TaskCreationOptions.LongRunning, - cancelToken); + TaskCreationOptions.LongRunning); void StartReceiverBackgroundThread() => _ = Task.Factory.StartNew( _ => ProcessReceiveQueue(), - TaskCreationOptions.LongRunning, - cancelToken); + TaskCreationOptions.LongRunning); } /// @@ -121,7 +125,7 @@ internal void EnqueueSendMessage(WebSocketMessage message) } } - internal async Task ProcessSendQueue(CancellationToken cancellationToken = default) + internal async Task ProcessSendQueue() { if (_isDisposed) { @@ -133,11 +137,11 @@ internal async Task ProcessSendQueue(CancellationToken cancellationToken = defau try { - while (await _sendChannel.Reader.WaitToReadAsync(cancellationToken)) + while (await _sendChannel.Reader.WaitToReadAsync(_cancellationTokenSource.Token)) { while (_sendChannel.Reader.TryRead(out var message)) { - await _clientWebSocket.SendAsync(message.Message, message.MessageType, true, cancellationToken).ConfigureAwait(false); + await _clientWebSocket.SendAsync(message.Message, message.MessageType, true, _cancellationTokenSource.Token).ConfigureAwait(false); } } @@ -148,9 +152,8 @@ internal async Task ProcessSendQueue(CancellationToken cancellationToken = defau } } - internal async Task ProcessReceiveQueue(CancellationToken? cancellationToken = null) + internal async Task ProcessReceiveQueue() { - var cancelToken = cancellationToken ?? _tokenSource.Token; while (_clientWebSocket?.State == WebSocketState.Open) { try @@ -162,7 +165,7 @@ internal async Task ProcessReceiveQueue(CancellationToken? cancellationToken = n { do { - result = await _clientWebSocket.ReceiveAsync(buffer, cancelToken); + result = await _clientWebSocket.ReceiveAsync(buffer, _cancellationTokenSource.Token); if (result.MessageType == WebSocketMessageType.Close) { Log.RequestedSocketClose(logger, result.CloseStatusDescription!); @@ -240,11 +243,10 @@ internal void ProcessDataReceived(WebSocketReceiveResult result, MemoryStream ms public async Task Stop(CancellationToken? cancellationToken = null) { // send the close message and flush transcription messages - var cancelToken = cancellationToken ?? _tokenSource.Token; if (_clientWebSocket!.State != WebSocketState.Open) return; - await _clientWebSocket.SendAsync(new ArraySegment([]), WebSocketMessageType.Binary, true, cancelToken) + await _clientWebSocket.SendAsync(new ArraySegment([]), WebSocketMessageType.Binary, true, _cancellationTokenSource.Token) .ConfigureAwait(false); // attempt to stop the connection @@ -262,12 +264,12 @@ await _clientWebSocket.SendAsync(new ArraySegment([]), WebSocketMessageTyp await _clientWebSocket.CloseOutputAsync( WebSocketCloseStatus.NormalClosure, string.Empty, - cancelToken) + _cancellationTokenSource.Token) .ConfigureAwait(false); } // Always request cancellation to the local token source, if some function has been called without a token - _tokenSource?.Cancel(); + _cancellationTokenSource.Cancel(); } } catch (Exception ex) @@ -286,18 +288,23 @@ await _clientWebSocket.CloseOutputAsync( internal readonly Channel _sendChannel = System.Threading.Channels.Channel .CreateUnbounded(new UnboundedChannelOptions { SingleReader = true, SingleWriter = true, }); - internal static Uri GetUri(LiveSchema queryParameters, DeepgramClientOptions options, Dictionary? addons = null) + internal static Uri GetUri(DeepgramClientOptions options, LiveSchema parameter, Dictionary? addons = null) { var baseUrl = GetBaseUrl(options); - var query = QueryParameterUtil.GetParameters(queryParameters, addons); - return new Uri($"{baseUrl}/{options.APIVersion}/{UriSegments.LISTEN}?{query}"); + var propertyInfoList = parameter.GetType() + .GetProperties() + .Where(v => v.GetValue(parameter) is not null); + + var queryString = QueryParameterUtil.UrlEncode(parameter, propertyInfoList, addons); + + return new Uri($"{baseUrl}/{options.APIVersion}/{UriSegments.LISTEN}?{queryString}"); } internal static string GetBaseUrl(DeepgramClientOptions options) { string baseAddress = Defaults.DEFAULT_URI; - if (options.BaseAddress is not null) + if (options.BaseAddress != null) { baseAddress = options.BaseAddress; } @@ -305,9 +312,11 @@ internal static string GetBaseUrl(DeepgramClientOptions options) //checks for ws:// wss:// ws wss - wss:// is include to ensure it is all stripped out and correctly formatted Regex regex = new Regex(@"\b(ws:\/\/|wss:\/\/|ws|wss)\b", RegexOptions.IgnoreCase); if (!regex.IsMatch(baseAddress)) + { //if no protocol in the address then https:// is added // TODO: log baseAddress = $"wss://{baseAddress}"; + } return baseAddress; } @@ -330,8 +339,11 @@ public void Dispose() return; } - _tokenSource.Cancel(); - _tokenSource.Dispose(); + if (_cancellationTokenSource != null) + { + _cancellationTokenSource.Cancel(); + _cancellationTokenSource.Dispose(); + } _sendChannel?.Writer.Complete(); _clientWebSocket?.Dispose(); diff --git a/Deepgram/Clients/Manage/v1/Client.cs b/Deepgram/Clients/Manage/v1/Client.cs index 1fcf9c0c..82eb75b6 100644 --- a/Deepgram/Clients/Manage/v1/Client.cs +++ b/Deepgram/Clients/Manage/v1/Client.cs @@ -20,16 +20,20 @@ public class Client(string apiKey, DeepgramClientOptions? deepgramClientOptions /// Gets projects associated to ApiKey /// /// - public async Task GetProjects(CancellationToken cancellationToken = default, Dictionary? addons = null) => - await GetAsync(UriSegments.PROJECTS, cancellationToken, addons); + public async Task GetProjects(CancellationTokenSource? cancellationToken = default, + Dictionary? addons = null, Dictionary? headers = null) => + await GetAsync(GetUri(_options, $"{UriSegments.PROJECTS}"), cancellationToken, addons, headers); /// /// Gets project associated with project Id /// /// Id of Project /// - public async Task GetProject(string projectId, CancellationToken cancellationToken = default, Dictionary? addons = null) => - await GetAsync($"{UriSegments.PROJECTS}/{projectId}", cancellationToken, addons); + public async Task GetProject(string projectId, CancellationTokenSource? cancellationToken = default, + Dictionary? addons = null, Dictionary? headers = null) => + await GetAsync( + GetUri(_options, $"{UriSegments.PROJECTS}/{projectId}"), cancellationToken, addons, headers + ); /// /// Update a project associated with the projectID @@ -38,27 +42,33 @@ public async Task GetProject(string projectId, CancellationToke /// for project /// // USES PATCH - public async Task UpdateProject(string projectId, ProjectSchema updateProjectSchema, CancellationToken cancellationToken = default, Dictionary? addons = null) => - await PatchAsync( - $"{UriSegments.PROJECTS}/{projectId}", - RequestContentUtil.CreatePayload(updateProjectSchema), cancellationToken, addons); + public async Task UpdateProject(string projectId, ProjectSchema updateProjectSchema, CancellationTokenSource? cancellationToken = default, + Dictionary? addons = null, Dictionary? headers = null) => + await PatchAsync( + GetUri(_options, $"{UriSegments.PROJECTS}/{projectId}"), updateProjectSchema, cancellationToken, addons, headers + ); /// /// Deletes a project, no response will be returned /// /// Id of project // No response expected - public async Task DeleteProject(string projectId, CancellationToken cancellationToken = default, Dictionary? addons = null) => - await DeleteAsync($"{UriSegments.PROJECTS}/{projectId}", cancellationToken, addons); + public async Task DeleteProject(string projectId, CancellationTokenSource? cancellationToken = default, + Dictionary? addons = null, Dictionary? headers = null) => + await DeleteAsync( + GetUri(_options, $"{UriSegments.PROJECTS}/{projectId}"), cancellationToken, addons, headers + ); /// /// leave project associated with the project Id /// /// Id of project /// - public async Task LeaveProject(string projectId, CancellationToken cancellationToken = default, Dictionary? addons = null) => - await DeleteAsync($"{UriSegments.PROJECTS}/{projectId}/leave", cancellationToken, addons); - + public async Task LeaveProject(string projectId, CancellationTokenSource? cancellationToken = default, + Dictionary? addons = null, Dictionary? headers = null) => + await DeleteAsync( + GetUri(_options, $"{UriSegments.PROJECTS}/{projectId}/leave"), cancellationToken, addons, headers + ); #endregion #region ProjectKeys @@ -68,8 +78,10 @@ public async Task LeaveProject(string projectId, CancellationTo /// /// Id of project /// - public async Task GetKeys(string projectId, CancellationToken cancellationToken = default, Dictionary? addons = null) => - await GetAsync($"{UriSegments.PROJECTS}/{projectId}/{UriSegments.KEYS}", cancellationToken, addons); + public async Task GetKeys(string projectId, CancellationTokenSource? cancellationToken = default, Dictionary? addons = null, Dictionary? headers = null) => + await GetAsync( + GetUri(_options, $"{UriSegments.PROJECTS}/{projectId}/{UriSegments.KEYS}"), cancellationToken, addons, headers + ); /// /// Get details of key associated with the key ID @@ -77,8 +89,10 @@ public async Task GetKeys(string projectId, CancellationToken canc /// Id of project /// Id of key /// - public async Task GetKey(string projectId, string keyId, CancellationToken cancellationToken = default, Dictionary? addons = null) => - await GetAsync($"{UriSegments.PROJECTS}/{projectId}/{UriSegments.KEYS}/{keyId}", cancellationToken, addons); + public async Task GetKey(string projectId, string keyId, CancellationTokenSource? cancellationToken = default, Dictionary? addons = null, Dictionary? headers = null) => + await GetAsync( + GetUri(_options, $"{UriSegments.PROJECTS}/{projectId}/{UriSegments.KEYS}/{keyId}"), cancellationToken, addons, headers + ); /// /// Create a key in the associated project @@ -86,18 +100,19 @@ public async Task GetKey(string projectId, string keyId, Cance /// Id of project /// for the key to be created /// - public async Task CreateKey(string projectId, KeySchema createProjectKeySchema, CancellationToken cancellationToken = default, Dictionary? addons = null) + public async Task CreateKey(string projectId, KeySchema createKeySchema, CancellationTokenSource? cancellationToken = default, + Dictionary? addons = null, Dictionary? headers = null) { // TODO: think about logging here based on coderabbit feedback - if (createProjectKeySchema.ExpirationDate is not null && createProjectKeySchema.TimeToLiveInSeconds is not null) + if (createKeySchema.ExpirationDate is not null && createKeySchema.TimeToLiveInSeconds is not null) { - Log.CreateKeyError(_logger, createProjectKeySchema); + Log.CreateKeyError(_logger, createKeySchema); throw new ArgumentException("Both ExpirationDate and TimeToLiveInSeconds is set. set either one but not both"); } - return await PostAsync( - $"{UriSegments.PROJECTS}/{projectId}/keys", - RequestContentUtil.CreatePayload(createProjectKeySchema), cancellationToken, addons); + return await PostAsync( + GetUri(_options, $"{UriSegments.PROJECTS}/{projectId}/keys"), createKeySchema, cancellationToken, addons, headers + ); } @@ -107,9 +122,9 @@ public async Task CreateKey(string projectId, KeySchema createProje /// Id of project /// Id of key // Nothing being returned - public async Task DeleteKey(string projectId, string keyId, CancellationToken cancellationToken = default, Dictionary? addons = null) => - await DeleteAsync($"{UriSegments.PROJECTS}/{projectId}/keys/{keyId}", cancellationToken, addons); - + public async Task DeleteKey(string projectId, string keyId, CancellationTokenSource? cancellationToken = default, + Dictionary? addons = null, Dictionary? headers = null) => + await DeleteAsync(GetUri(_options, $"{UriSegments.PROJECTS}/{projectId}/keys/{keyId}"), cancellationToken, addons, headers); #endregion #region ProjectInvites @@ -118,8 +133,9 @@ public async Task DeleteKey(string projectId, string keyId, CancellationToken ca /// /// Id of project /// - public async Task GetInvites(string projectId, CancellationToken cancellationToken = default, Dictionary? addons = null) => - await GetAsync($"{UriSegments.PROJECTS}/{projectId}/{UriSegments.INVITES}", cancellationToken, addons); + public async Task GetInvites(string projectId, CancellationTokenSource? cancellationToken = default, + Dictionary? addons = null, Dictionary? headers = null) => + await GetAsync(GetUri(_options, $"{UriSegments.PROJECTS}/{projectId}/{UriSegments.INVITES}"), cancellationToken, addons, headers); /// /// Delete a project invite that has been sent @@ -127,8 +143,10 @@ public async Task GetInvites(string projectId, CancellationToke /// Id of project /// email of the invite to be removed //no response expected - public async Task DeleteInvite(string projectId, string email, CancellationToken cancellationToken = default, Dictionary? addons = null) => - await DeleteAsync($"{UriSegments.PROJECTS}/{projectId}/{UriSegments.INVITES}/{email}", cancellationToken, addons); + public async Task DeleteInvite(string projectId, string email, CancellationTokenSource? cancellationToken = default, + Dictionary? addons = null, Dictionary? headers = null) => + await DeleteAsync(GetUri(_options, $"{UriSegments.PROJECTS}/{projectId}/{UriSegments.INVITES}/{email}"), + cancellationToken, addons, headers); /// /// Send a invite to the associated project @@ -136,10 +154,11 @@ public async Task DeleteInvite(string projectId, string email, CancellationToken /// Id of project /// for a invite to project /// - public async Task SendInvite(string projectId, InviteSchema inviteSchema, CancellationToken cancellationToken = default, Dictionary? addons = null) => - await PostAsync( - $"{UriSegments.PROJECTS}/{projectId}/{UriSegments.INVITES}", - RequestContentUtil.CreatePayload(inviteSchema), cancellationToken, addons); + public async Task SendInvite(string projectId, InviteSchema inviteSchema, CancellationTokenSource? cancellationToken = default, + Dictionary? addons = null, Dictionary? headers = null) => + await PostAsync( + GetUri(_options, $"{UriSegments.PROJECTS}/{projectId}/{UriSegments.INVITES}"), inviteSchema, cancellationToken, addons, headers + ); #endregion #region Members @@ -148,8 +167,9 @@ await PostAsync( /// /// Id of project /// - public async Task GetMembers(string projectId, CancellationToken cancellationToken = default, Dictionary? addons = null) => - await GetAsync($"{UriSegments.PROJECTS}/{projectId}/{UriSegments.MEMBERS}", cancellationToken, addons); + public async Task GetMembers(string projectId, CancellationTokenSource? cancellationToken = default, + Dictionary? addons = null, Dictionary? headers = null) => + await GetAsync(GetUri(_options, $"{UriSegments.PROJECTS}/{projectId}/{UriSegments.MEMBERS}"), cancellationToken, addons, headers); /// /// Get the scopes associated with member @@ -157,8 +177,11 @@ public async Task GetMembers(string projectId, CancellationToke /// Id of project /// Id of member /// - public async Task GetMemberScopes(string projectId, string memberId, CancellationToken cancellationToken = default, Dictionary? addons = null) => - await GetAsync($"{UriSegments.PROJECTS}/{projectId}/{UriSegments.MEMBERS}/{memberId}/{UriSegments.SCOPES}", cancellationToken, addons); + public async Task GetMemberScopes(string projectId, string memberId, CancellationTokenSource? cancellationToken = default, + Dictionary? addons = null, Dictionary? headers = null) => + await GetAsync(GetUri(_options, $"{UriSegments.PROJECTS}/{projectId}/{UriSegments.MEMBERS}/{memberId}/{UriSegments.SCOPES}"), + cancellationToken, addons, headers + ); /// /// Update the scopes fot the member @@ -167,10 +190,12 @@ public async Task GetMemberScopes(string projectId, string /// Id of member /// updates scope options for member /// - public async Task UpdateMemberScope(string projectId, string memberId, MemberScopeSchema memberScopeSchema, CancellationToken cancellationToken = default, Dictionary? addons = null) => - await PutAsync( - $"{UriSegments.PROJECTS}/{projectId}/{UriSegments.MEMBERS}/{memberId}/{UriSegments.SCOPES}", - RequestContentUtil.CreatePayload(memberScopeSchema), cancellationToken, addons); + public async Task UpdateMemberScope(string projectId, string memberId, MemberScopeSchema memberScopeSchema, + CancellationTokenSource? cancellationToken = default, Dictionary? addons = null, Dictionary? headers = null) => + await PutAsync( + GetUri(_options, $"{UriSegments.PROJECTS}/{projectId}/{UriSegments.MEMBERS}/{memberId}/{UriSegments.SCOPES}"), memberScopeSchema, + cancellationToken, addons, headers + ); /// /// Remove member from project, there is no response @@ -178,8 +203,11 @@ await PutAsync( /// Id of project /// Id of member //No response expected - public async Task RemoveMember(string projectId, string memberId, CancellationToken cancellationToken = default, Dictionary? addons = null) => - await DeleteAsync($"{UriSegments.PROJECTS}/{projectId}/{UriSegments.MEMBERS}/{memberId}", cancellationToken, addons); + public async Task RemoveMember(string projectId, string memberId, CancellationTokenSource? cancellationToken = default, + Dictionary? addons = null, Dictionary? headers = null) => + await DeleteAsync(GetUri(_options, $"{UriSegments.PROJECTS}/{projectId}/{UriSegments.MEMBERS}/{memberId}"), + cancellationToken, addons, headers + ); #endregion #region Usage @@ -190,10 +218,12 @@ public async Task RemoveMember(string projectId, string memberId, CancellationTo /// Id of project /// Project usage request options /// - public async Task GetUsageRequests(string projectId, UsageRequestsSchema UsageRequestsSchema, CancellationToken cancellationToken = default, Dictionary? addons = null) + public async Task GetUsageRequests(string projectId, UsageRequestsSchema usageRequestsSchema, + CancellationTokenSource? cancellationToken = default, Dictionary? addons = null, Dictionary? headers = null) { - var stringedOptions = QueryParameterUtil.GetParameters(UsageRequestsSchema); - return await GetAsync($"{UriSegments.PROJECTS}/{projectId}/{UriSegments.REQUESTS}?{stringedOptions}", cancellationToken, addons); + return await GetAsync(GetUri(_options, $"{UriSegments.PROJECTS}/{projectId}/{UriSegments.REQUESTS}"), + usageRequestsSchema, cancellationToken, addons, headers + ); } /// @@ -202,45 +232,49 @@ public async Task GetUsageRequests(string projectId, Usag /// Id of project /// Id of request /// - public async Task GetUsageRequest(string projectId, string requestId, CancellationToken cancellationToken = default, Dictionary? addons = null) => - await GetAsync($"{UriSegments.PROJECTS}/{projectId}/{UriSegments.REQUESTS}/{requestId}", cancellationToken, addons); + public async Task GetUsageRequest(string projectId, string requestId, CancellationTokenSource? cancellationToken = default, + Dictionary? addons = null, Dictionary? headers = null) => + await GetAsync(GetUri(_options, $"{UriSegments.PROJECTS}/{projectId}/{UriSegments.REQUESTS}/{requestId}"), + cancellationToken, addons, headers + ); /// /// Gets a summary of usage /// /// Id of project - /// Usage summary options + /// Usage summary options /// - public async Task GetUsageSummary(string projectId, UsageSummarySchema getProjectUsageSummarySchema, CancellationToken cancellationToken = default, Dictionary? addons = null) + public async Task GetUsageSummary(string projectId, UsageSummarySchema usageSummarySchema, + CancellationTokenSource? cancellationToken = default, Dictionary? addons = null, Dictionary? headers = null) { - var stringedOptions = QueryParameterUtil.GetParameters(getProjectUsageSummarySchema); - return await GetAsync( - $"{UriSegments.PROJECTS}/{projectId}/{UriSegments.USAGE}?{stringedOptions}", cancellationToken, addons); + return await GetAsync( + GetUri(_options, $"{UriSegments.PROJECTS}/{projectId}/{UriSegments.USAGE}"), usageSummarySchema, cancellationToken, addons, headers + ); } /// /// Get usage fields /// /// Id of project - /// Project usage request field options + /// Project usage request field options /// - public async Task GetUsageFields(string projectId, UsageFieldsSchema getProjectUsageFieldsSchema, CancellationToken cancellationToken = default, Dictionary? addons = null) + public async Task GetUsageFields(string projectId, UsageFieldsSchema usageFieldsSchema, + CancellationTokenSource? cancellationToken = default, Dictionary? addons = null, Dictionary? headers = null) { - var stringedOptions = QueryParameterUtil.GetParameters(getProjectUsageFieldsSchema); - return await GetAsync( - $"{UriSegments.PROJECTS}/{projectId}/{UriSegments.USAGE}/fields?{stringedOptions}", cancellationToken, addons); + return await GetAsync( + GetUri(_options, $"{UriSegments.PROJECTS}/{projectId}/{UriSegments.USAGE}/fields"), usageFieldsSchema, cancellationToken, addons, headers); } #endregion #region Balances - /// /// Gets a list of balances /// /// Id of project /// - public async Task GetBalances(string projectId, CancellationToken cancellationToken = default, Dictionary? addons = null) => - await GetAsync($"{UriSegments.PROJECTS}/{projectId}/{UriSegments.BALANCES}", cancellationToken, addons); + public async Task GetBalances(string projectId, CancellationTokenSource? cancellationToken = default, + Dictionary? addons = null, Dictionary? headers = null) => + await GetAsync(GetUri(_options, $"{UriSegments.PROJECTS}/{projectId}/{UriSegments.BALANCES}"), cancellationToken, addons, headers); /// /// Get the balance details associated with the balance id @@ -248,7 +282,8 @@ public async Task GetBalances(string projectId, CancellationTo /// Id of project /// Id of balance /// - public async Task GetBalance(string projectId, string balanceId, CancellationToken cancellationToken = default, Dictionary? addons = null) => - await GetAsync($"{UriSegments.PROJECTS}/{projectId}/{UriSegments.BALANCES}/{balanceId}", cancellationToken, addons); + public async Task GetBalance(string projectId, string balanceId, CancellationTokenSource? cancellationToken = default, + Dictionary? addons = null, Dictionary? headers = null) => + await GetAsync(GetUri(_options, $"{UriSegments.PROJECTS}/{projectId}/{UriSegments.BALANCES}/{balanceId}"), cancellationToken, addons, headers); #endregion } diff --git a/Deepgram/Clients/OnPrem/v1/Client.cs b/Deepgram/Clients/OnPrem/v1/Client.cs index a8cd1997..e012df0b 100644 --- a/Deepgram/Clients/OnPrem/v1/Client.cs +++ b/Deepgram/Clients/OnPrem/v1/Client.cs @@ -20,8 +20,9 @@ public class Client(string apiKey, DeepgramClientOptions? deepgramClientOptions /// /// Id of project /// - public async Task ListCredentials(string projectId, CancellationToken cancellationToken = default) => - await GetAsync($"{UriSegments.PROJECTS}/{projectId}/{UriSegments.ONPREM}", cancellationToken); + public async Task ListCredentials(string projectId, CancellationTokenSource? cancellationToken = default, + Dictionary? addons = null, Dictionary? headers = null) => + await GetAsync(GetUri(_options, $"{UriSegments.PROJECTS}/{projectId}/{UriSegments.ONPREM}"), cancellationToken, addons, headers); /// /// Get credentials for the project that is associated with credential ID @@ -29,8 +30,11 @@ public async Task ListCredentials(string projectId, Cancell /// Id of project /// Id of credentials /// - public async Task GetCredentials(string projectId, string credentialsId, CancellationToken cancellationToken = default) => - await GetAsync($"{UriSegments.PROJECTS}/{projectId}/{UriSegments.ONPREM}/{credentialsId}", cancellationToken); + public async Task GetCredentials(string projectId, string credentialsId, CancellationTokenSource? cancellationToken = default, + Dictionary? addons = null, Dictionary? headers = null) => + await GetAsync(GetUri(_options, $"{UriSegments.PROJECTS}/{projectId}/{UriSegments.ONPREM}/{credentialsId}"), + cancellationToken, addons, headers + ); /// /// Remove credentials in the project associated with the credentials ID @@ -38,8 +42,11 @@ public async Task GetCredentials(string projectId, string cr /// Id of project /// Id of credentials /// - public async Task DeleteCredentials(string projectId, string credentialsId, CancellationToken cancellationToken = default) => - await DeleteAsync($"{UriSegments.PROJECTS}/{projectId}/{UriSegments.ONPREM}/{credentialsId}", cancellationToken); + public async Task DeleteCredentials(string projectId, string credentialsId, CancellationTokenSource? cancellationToken = default, + Dictionary? addons = null, Dictionary? headers = null) => + await DeleteAsync(GetUri(_options, $"{UriSegments.PROJECTS}/{projectId}/{UriSegments.ONPREM}/{credentialsId}"), + cancellationToken, addons, headers + ); /// /// Create credentials for the associated projects @@ -47,9 +54,10 @@ public async Task DeleteCredentials(string projectId, string cr /// Id of project /// for credentials to be created /// - public async Task CreateCredentials(string projectId, CredentialsSchema createOnPremCredentialsSchema, CancellationToken cancellationToken = default) => - await PostAsync( - $"{UriSegments.PROJECTS}/{projectId}/{UriSegments.ONPREM}", - RequestContentUtil.CreatePayload(createOnPremCredentialsSchema), cancellationToken); + public async Task CreateCredentials(string projectId, CredentialsSchema credentialsSchema, + CancellationTokenSource? cancellationToken = default, Dictionary? addons = null, Dictionary? headers = null) => + await PostAsync( + GetUri(_options, $"{UriSegments.PROJECTS}/{projectId}/{UriSegments.ONPREM}"), credentialsSchema, cancellationToken, addons, headers + ); } diff --git a/Deepgram/Clients/PreRecorded/v1/Client.cs b/Deepgram/Clients/PreRecorded/v1/Client.cs index 4850a1a0..533d4146 100644 --- a/Deepgram/Clients/PreRecorded/v1/Client.cs +++ b/Deepgram/Clients/PreRecorded/v1/Client.cs @@ -23,14 +23,14 @@ public class Client(string apiKey = "", DeepgramClientOptions? deepgramClientOpt /// Url to the file that is to be transcribed /// Options for the transcription /// - public async Task TranscribeUrl(UrlSource source, PrerecordedSchema? prerecordedSchema, CancellationToken cancellationToken = default, Dictionary? addons = null) + public async Task TranscribeUrl(UrlSource source, PrerecordedSchema? prerecordedSchema, + CancellationTokenSource? cancellationToken = default, Dictionary? addons = null, Dictionary? headers = null) { VerifyNoCallBack(nameof(TranscribeUrl), prerecordedSchema); - var stringedOptions = QueryParameterUtil.GetParameters(prerecordedSchema, addons); - return await PostAsync( - $"{UriSegments.LISTEN}?{stringedOptions}", - RequestContentUtil.CreatePayload(source), cancellationToken); + return await PostAsync( + GetUri(_options, $"{UriSegments.LISTEN}"), prerecordedSchema, source, cancellationToken, addons, headers + ); } /// /// Transcribes a file using the provided byte array @@ -38,26 +38,26 @@ public async Task TranscribeUrl(UrlSource source, PrerecordedSchem /// file is the form of a byte[] /// Options for the transcription /// - public async Task TranscribeFile(byte[] source, PrerecordedSchema? prerecordedSchema, CancellationToken cancellationToken = default, Dictionary? addons = null) + public async Task TranscribeFile(byte[] source, PrerecordedSchema? prerecordedSchema, + CancellationTokenSource? cancellationToken = default, Dictionary? addons = null, Dictionary? headers = null) { MemoryStream stream = new MemoryStream(source); - return await TranscribeFile(stream, prerecordedSchema, cancellationToken); + return await TranscribeFile(stream, prerecordedSchema, cancellationToken, addons, headers); } /// /// Transcribes a file using the provided stream /// - /// file is the form of a stream + /// file is the form of a streasm /// Options for the transcription /// - public async Task TranscribeFile(Stream source, PrerecordedSchema? prerecordedSchema, CancellationToken cancellationToken = default, Dictionary? addons = null) + public async Task TranscribeFile(Stream source, PrerecordedSchema? prerecordedSchema, CancellationTokenSource? cancellationToken = default, Dictionary? addons = null, Dictionary? headers = null) { VerifyNoCallBack(nameof(TranscribeFile), prerecordedSchema); - var stringedOptions = QueryParameterUtil.GetParameters(prerecordedSchema, addons); - return await PostAsync( - $"{UriSegments.LISTEN}?{stringedOptions}", - RequestContentUtil.CreateStreamPayload(source), cancellationToken); + return await PostAsync( + GetUri(_options, $"{UriSegments.LISTEN}"), prerecordedSchema, source, cancellationToken, addons, headers + ); } #endregion @@ -70,18 +70,10 @@ public async Task TranscribeFile(Stream source, PrerecordedSchema? /// CallBack url /// Options for the transcription /// - public async Task TranscribeFileCallBack(byte[] source, string? callBack, PrerecordedSchema? prerecordedSchema, CancellationToken cancellationToken = default, Dictionary? addons = null) + public async Task TranscribeFileCallBack(byte[] source, string? callBack, PrerecordedSchema? prerecordedSchema, CancellationTokenSource? cancellationToken = default, Dictionary? addons = null, Dictionary? headers = null) { - VerifyOneCallBackSet(nameof(TranscribeFileCallBack), callBack, prerecordedSchema); - if (callBack != null) - prerecordedSchema.CallBack = callBack; - - var stringedOptions = QueryParameterUtil.GetParameters(prerecordedSchema, addons); - var stream = new MemoryStream(); - stream.Write(source, 0, source.Length); - return await PostAsync( - $"{UriSegments.LISTEN}?{stringedOptions}", - RequestContentUtil.CreateStreamPayload(stream), cancellationToken); + MemoryStream stream = new MemoryStream(source); + return await TranscribeFileCallBack(stream, callBack, prerecordedSchema, cancellationToken, addons, headers); } /// @@ -91,16 +83,15 @@ public async Task TranscribeFileCallBack(byte[] source, string? c /// CallBack url /// Options for the transcription /// - public async Task TranscribeFileCallBack(Stream source, string? callBack, PrerecordedSchema? prerecordedSchema, CancellationToken cancellationToken = default, Dictionary? addons = null) + public async Task TranscribeFileCallBack(Stream source, string? callBack, PrerecordedSchema? prerecordedSchema, CancellationTokenSource? cancellationToken = default, Dictionary? addons = null, Dictionary? headers = null) { VerifyOneCallBackSet(nameof(TranscribeFileCallBack), callBack, prerecordedSchema); if (callBack != null) prerecordedSchema.CallBack = callBack; - var stringedOptions = QueryParameterUtil.GetParameters(prerecordedSchema, addons); - return await PostAsync( - $"{UriSegments.LISTEN}?{stringedOptions}", - RequestContentUtil.CreateStreamPayload(source), cancellationToken); + return await PostAsync( + GetUri(_options, $"{UriSegments.LISTEN}"), prerecordedSchema, source, cancellationToken, addons, headers + ); } /// @@ -110,17 +101,16 @@ public async Task TranscribeFileCallBack(Stream source, string? c /// CallBack url /// Options for the transcription /// - public async Task TranscribeUrlCallBack(UrlSource source, string? callBack, PrerecordedSchema? prerecordedSchema, CancellationToken cancellationToken = default, Dictionary? addons = null) + public async Task TranscribeUrlCallBack(UrlSource source, string? callBack, PrerecordedSchema? prerecordedSchema, CancellationTokenSource? cancellationToken = default, Dictionary? addons = null, Dictionary? headers = null) { VerifyOneCallBackSet(nameof(TranscribeUrlCallBack), callBack, prerecordedSchema); if (callBack != null) prerecordedSchema.CallBack = callBack; - var stringedOptions = QueryParameterUtil.GetParameters(prerecordedSchema, addons); - return await PostAsync( - $"{UriSegments.LISTEN}?{stringedOptions}", - RequestContentUtil.CreatePayload(source), cancellationToken); + return await PostAsync( + GetUri(_options, $"{UriSegments.LISTEN}"), prerecordedSchema, source, cancellationToken, addons, headers + ); } #endregion diff --git a/Deepgram/Clients/Speak/v1/Client.cs b/Deepgram/Clients/Speak/v1/Client.cs index fc717006..c00dd1c7 100644 --- a/Deepgram/Clients/Speak/v1/Client.cs +++ b/Deepgram/Clients/Speak/v1/Client.cs @@ -4,8 +4,6 @@ using Deepgram.Models.Speak.v1; using Deepgram.Models.Authenticate.v1; -using System.Net.Mime; -using System; namespace Deepgram.Clients.Speak.v1; @@ -24,11 +22,11 @@ public class Client(string apiKey, DeepgramClientOptions? deepgramClientOptions /// file is the form of a stream /// Options for the transcription /// - public async Task ToStream(TextSource source, SpeakSchema? speakSchema, CancellationToken cancellationToken = default, Dictionary? addons = null) + public async Task ToStream(TextSource source, SpeakSchema? speakSchema, CancellationTokenSource? cancellationToken = default, + Dictionary? addons = null, Dictionary? headers = null) { - VerifyNoCallBack(nameof(Stream), speakSchema); + VerifyNoCallBack(nameof(ToStream), speakSchema); - var stringedOptions = QueryParameterUtil.GetParameters(speakSchema, addons); List keys = new List { Constants.ContentType, Constants.RequestId, @@ -39,14 +37,14 @@ public async Task ToStream(TextSource source, SpeakSchema? speakSc Constants.Date, }; - var (result, stream) = await PostFileAsync<(Dictionary, MemoryStream)>( - $"{UriSegments.SPEAK}?{stringedOptions}", - RequestContentUtil.CreatePayload(source), keys, cancellationToken); + var localFileResult = await PostRetrieveLocalFileAsync( + GetUri(_options, $"{UriSegments.SPEAK}"), speakSchema, source, keys, cancellationToken, addons, headers + ); SyncResponse response = new SyncResponse(); // build up the response object - foreach (var item in result) + foreach (var item in localFileResult.Metadata) { var key = item.Key.ToLower(); @@ -80,14 +78,16 @@ public async Task ToStream(TextSource source, SpeakSchema? speakSc } // add stream to response - response.Stream = stream; + response.Stream = localFileResult.Content; return response; } - public async Task ToFile(TextSource source, string filename, SpeakSchema? speakSchema, CancellationToken cancellationToken = default, Dictionary? addons = null) + public async Task ToFile(TextSource source, string filename, SpeakSchema? speakSchema, CancellationTokenSource? cancellationToken = default, + Dictionary? addons = null, Dictionary? headers = null + ) { - var response = await ToStream(source, speakSchema, cancellationToken, addons); + var response = await ToStream(source, speakSchema, cancellationToken, addons, headers); // save the file response.Filename = filename; @@ -111,16 +111,15 @@ public async Task ToFile(TextSource source, string filename, Speak /// CallBack url /// Options for the transcription /// - public async Task StreamCallBack(TextSource source, string? callBack, SpeakSchema? speakSchema, CancellationToken cancellationToken = default, Dictionary? addons = null) + public async Task StreamCallBack(TextSource source, string? callBack, SpeakSchema? speakSchema, CancellationTokenSource? cancellationToken = default, + Dictionary? addons = null, Dictionary? headers = null) { VerifyOneCallBackSet(nameof(StreamCallBack), callBack, speakSchema); if (callBack != null) speakSchema.CallBack = callBack; - var stringedOptions = QueryParameterUtil.GetParameters(speakSchema, addons); - return await PostAsync( - $"{UriSegments.SPEAK}?{stringedOptions}", - RequestContentUtil.CreatePayload(source), cancellationToken); + return await PostAsync( + GetUri(_options, $"{UriSegments.SPEAK}"), speakSchema, source, cancellationToken, addons, headers); } #endregion diff --git a/Deepgram/Clients/Speak/v1/Constants.cs b/Deepgram/Clients/Speak/v1/Constants.cs index ff54f463..8e4accc8 100644 --- a/Deepgram/Clients/Speak/v1/Constants.cs +++ b/Deepgram/Clients/Speak/v1/Constants.cs @@ -5,7 +5,7 @@ namespace Deepgram.Clients.Speak.v1; /// -/// Expected encoding of the submitted streaming audio. +/// Headers of interest in the return values from the Deepgram Speak API. /// public static class Constants { diff --git a/Deepgram/Deepgram.csproj b/Deepgram/Deepgram.csproj index de6b7e14..9210a53c 100644 --- a/Deepgram/Deepgram.csproj +++ b/Deepgram/Deepgram.csproj @@ -49,6 +49,18 @@ True latest + + 7 + + + 7 + + + 7 + + + 7 + diff --git a/Deepgram/Factory/HttpClientFactory.cs b/Deepgram/Factory/HttpClientFactory.cs index ba13700b..d4fa4bfb 100644 --- a/Deepgram/Factory/HttpClientFactory.cs +++ b/Deepgram/Factory/HttpClientFactory.cs @@ -20,7 +20,10 @@ public static HttpClient Create(string httpId = HTTPCLIENT_NAME) var sp = services.BuildServiceProvider(); var client = sp.GetRequiredService().CreateClient(httpId); - client.Timeout = TimeSpan.FromMinutes(DEFAULT_HTTP_TINEOUT_IN_MINUTES); + + // this is ok because we are using CancellationTokenSource with a default DefaultRESTTimeout timeout + client.Timeout = Timeout.InfiniteTimeSpan; + return client; } @@ -69,9 +72,11 @@ internal static HttpClient ConfigureDeepgram(HttpClient client, string apiKey = //checks for http:// https:// http https - https:// is include to ensure it is all stripped out and correctly formatted Regex regex = new Regex(@"\b(http:\/\/|https:\/\/|http|https)\b", RegexOptions.IgnoreCase); if (!regex.IsMatch(baseAddress)) + { //if no protocol in the address then https:// is added // TODO: log baseAddress = $"https://{baseAddress}"; + } // TODO: log client.BaseAddress = new Uri(baseAddress); diff --git a/Deepgram/Models/Analyze/v1/NoopSchema.cs b/Deepgram/Models/Analyze/v1/NoopSchema.cs new file mode 100644 index 00000000..a4a561fb --- /dev/null +++ b/Deepgram/Models/Analyze/v1/NoopSchema.cs @@ -0,0 +1,10 @@ +// Copyright 2021-2024 Deepgram .NET SDK contributors. All Rights Reserved. +// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// SPDX-License-Identifier: MIT + +namespace Deepgram.Models.Analyze.v1; + +public class NoopSchema +{ +} + diff --git a/Deepgram/Models/Live/v1/NoopSchema.cs b/Deepgram/Models/Live/v1/NoopSchema.cs new file mode 100644 index 00000000..7839c378 --- /dev/null +++ b/Deepgram/Models/Live/v1/NoopSchema.cs @@ -0,0 +1,10 @@ +// Copyright 2021-2024 Deepgram .NET SDK contributors. All Rights Reserved. +// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// SPDX-License-Identifier: MIT + +namespace Deepgram.Models.Live.v1; + +public class NoopSchema +{ +} + diff --git a/Deepgram/Models/Manage/v1/NoopSchema.cs b/Deepgram/Models/Manage/v1/NoopSchema.cs new file mode 100644 index 00000000..c9867f4d --- /dev/null +++ b/Deepgram/Models/Manage/v1/NoopSchema.cs @@ -0,0 +1,10 @@ +// Copyright 2021-2024 Deepgram .NET SDK contributors. All Rights Reserved. +// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// SPDX-License-Identifier: MIT + +namespace Deepgram.Models.Manage.v1; + +public class NoopSchema +{ +} + diff --git a/Deepgram/Models/OnPrem/v1/NoopSchema.cs b/Deepgram/Models/OnPrem/v1/NoopSchema.cs new file mode 100644 index 00000000..0b683a60 --- /dev/null +++ b/Deepgram/Models/OnPrem/v1/NoopSchema.cs @@ -0,0 +1,10 @@ +// Copyright 2021-2024 Deepgram .NET SDK contributors. All Rights Reserved. +// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// SPDX-License-Identifier: MIT + +namespace Deepgram.Models.OnPrem.v1; + +public class NoopSchema +{ +} + diff --git a/Deepgram/Models/PreRecorded/v1/NoopSchema.cs b/Deepgram/Models/PreRecorded/v1/NoopSchema.cs new file mode 100644 index 00000000..8c458fc3 --- /dev/null +++ b/Deepgram/Models/PreRecorded/v1/NoopSchema.cs @@ -0,0 +1,10 @@ +// Copyright 2021-2024 Deepgram .NET SDK contributors. All Rights Reserved. +// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// SPDX-License-Identifier: MIT + +namespace Deepgram.Models.PreRecorded.v1; + +public class NoopSchema +{ +} + diff --git a/Deepgram/Models/Speak/v1/NoopSchema.cs b/Deepgram/Models/Speak/v1/NoopSchema.cs new file mode 100644 index 00000000..6ea7e255 --- /dev/null +++ b/Deepgram/Models/Speak/v1/NoopSchema.cs @@ -0,0 +1,10 @@ +// Copyright 2021-2024 Deepgram .NET SDK contributors. All Rights Reserved. +// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// SPDX-License-Identifier: MIT + +namespace Deepgram.Models.Speak.v1; + +public class NoopSchema +{ +} + diff --git a/Deepgram/Utilities/QueryParameterUtil.cs b/Deepgram/Utilities/QueryParameterUtil.cs index c88caf08..45830833 100644 --- a/Deepgram/Utilities/QueryParameterUtil.cs +++ b/Deepgram/Utilities/QueryParameterUtil.cs @@ -3,88 +3,100 @@ // SPDX-License-Identifier: MIT using System.Collections; -using System.Linq; using Deepgram.Models.PreRecorded.v1; +using Deepgram.Models.Analyze.v1; +using Deepgram.Models.Speak.v1; namespace Deepgram.Utilities; internal static class QueryParameterUtil { - internal static string GetParameters(T parameters, Dictionary? addons = null) + public static string FormatURL(string uriSegment, S? parameter, Dictionary? addons = null) { - if (parameters is null) return string.Empty; - - var propertyInfoList = parameters.GetType() - .GetProperties() - .Where(v => v.GetValue(parameters) is not null); - - - return UrlEncode(parameters, propertyInfoList, addons); - } + //checks for http:// https:// http https - https:// is include to ensure it is all stripped out and correctly formatted + Regex regex = new Regex(@"\b(http:\/\/|https:\/\/|http|https)\b", RegexOptions.IgnoreCase); + if (!regex.IsMatch(uriSegment)) + //if no protocol in the address then https:// is added + // TODO: log + uriSegment = $"https://{uriSegment}"; + + // schema to be used to build the query string + var queryString = ""; + if (parameter != null) + { + var propertyInfoList = parameter.GetType() + .GetProperties() + .Where(v => v.GetValue(parameter) is not null); - internal static string AppendQueryParameters(string uriSegment, Dictionary? parameters = null) - { - if (parameters is null) + queryString = UrlEncode(parameter, propertyInfoList, addons); + } else { - return uriSegment; + queryString = UrlEncode(parameter, null, addons); } // otherwise build the string var uriBuilder = new UriBuilder(uriSegment); - var query = HttpUtility.ParseQueryString(uriBuilder.Query); - - foreach (var param in parameters) - { - query[param.Key] = param.Value; - } - + var query = HttpUtility.ParseQueryString(queryString); uriBuilder.Query = query.ToString(); - return uriBuilder.ToString(); + return uriBuilder.Uri.ToString().TrimEnd('/'); } - private static string UrlEncode(T parameters, IEnumerable propertyInfoList, Dictionary? addons = null) + internal static string UrlEncode(T parameters, IEnumerable? propertyInfoList, Dictionary? addons = null) { var sb = new StringBuilder(); - foreach (var pInfo in propertyInfoList) + if (propertyInfoList != null) { - var name = pInfo.GetCustomAttribute()?.Name; - var pValue = pInfo.GetValue(parameters); - - //need to check for the CallBack property so the value is not changed to lowercase - required by Signed uri - if (typeof(T) == typeof(PrerecordedSchema) && string.Compare(name, nameof(PrerecordedSchema.CallBack).ToLower(), StringComparison.Ordinal) == 0) + foreach (var pInfo in propertyInfoList) { - sb.Append($"{name}={HttpUtility.UrlEncode(pValue.ToString())}&"); - continue; - } + var name = pInfo.GetCustomAttribute()?.Name; + var pValue = pInfo.GetValue(parameters); - switch (pValue) - { - case bool boolean: - sb.Append($"{name}={HttpUtility.UrlEncode(pValue.ToString().ToLower())}&"); - break; - case IList list: - foreach (var value in list) - sb.Append($"{name}={HttpUtility.UrlEncode(value.ToString())}&"); - break; - case DateTime time: - sb.Append($"{name}={HttpUtility.UrlEncode(time.ToString("yyyy-MM-dd"))}&"); - break; - //specific case for the Extra Parameter dictionary to format the querystring correctly - //no case changing of the key or values as theses are unknowns and the casing may have - //significance to the user - case Dictionary dict: - if (name == "extra") - { - foreach (var kvp in dict) + //need to check for the CallBack property so the value is not changed to lowercase - required by Signed uri + if (typeof(T) == typeof(PrerecordedSchema) && string.Compare(name, nameof(PrerecordedSchema.CallBack).ToLower(), StringComparison.Ordinal) == 0) + { + sb.Append($"{name}={HttpUtility.UrlEncode(pValue.ToString())}&"); + continue; + } + if (typeof(T) == typeof(AnalyzeSchema) && string.Compare(name, nameof(AnalyzeSchema.CallBack).ToLower(), StringComparison.Ordinal) == 0) + { + sb.Append($"{name}={HttpUtility.UrlEncode(pValue.ToString())}&"); + continue; + } + if (typeof(T) == typeof(SpeakSchema) && string.Compare(name, nameof(SpeakSchema.CallBack).ToLower(), StringComparison.Ordinal) == 0) + { + sb.Append($"{name}={HttpUtility.UrlEncode(pValue.ToString())}&"); + continue; + } + + switch (pValue) + { + case bool boolean: + sb.Append($"{name}={HttpUtility.UrlEncode(pValue.ToString().ToLower())}&"); + break; + case IList list: + foreach (var value in list) + sb.Append($"{name}={HttpUtility.UrlEncode(value.ToString())}&"); + break; + case DateTime time: + sb.Append($"{name}={HttpUtility.UrlEncode(time.ToString("yyyy-MM-dd"))}&"); + break; + //specific case for the Extra Parameter dictionary to format the querystring correctly + //no case changing of the key or values as theses are unknowns and the casing may have + //significance to the user + case Dictionary dict: + if (name == "extra") { - sb.Append($"{name}={HttpUtility.UrlEncode($"{kvp.Key}:{kvp.Value}")}&"); + foreach (var kvp in dict) + { + sb.Append($"{name}={HttpUtility.UrlEncode($"{kvp.Key}:{kvp.Value}")}&"); + } } - } - break; - default: - sb.Append($"{name}={HttpUtility.UrlEncode(pValue.ToString())}&"); - break; + break; + default: + sb.Append($"{name}={HttpUtility.UrlEncode(pValue.ToString())}&"); + break; + } } } diff --git a/examples/prerecorded/Prerecorded.csproj b/examples/prerecorded/Prerecorded.csproj index 1dc6815d..0dbe2714 100644 --- a/examples/prerecorded/Prerecorded.csproj +++ b/examples/prerecorded/Prerecorded.csproj @@ -2,7 +2,7 @@ Exe - net8.0 + net6.0 enable enable diff --git a/examples/prerecorded/Program.cs b/examples/prerecorded/Program.cs index 473eb9c6..3ca9d98f 100644 --- a/examples/prerecorded/Program.cs +++ b/examples/prerecorded/Program.cs @@ -8,6 +8,7 @@ class Program { static async Task Main(string[] args) { + // Replace "REPLACE-WITH-YOUR-API-KEY" with your actual Deepgram API key var apiKey = "REPLACE-WITH-YOUR-API-KEY"; var deepgramClient = new PreRecordedClient(apiKey); diff --git a/examples/speak/Program.cs b/examples/speak/Program.cs index da76bece..1e6ef572 100644 --- a/examples/speak/Program.cs +++ b/examples/speak/Program.cs @@ -1,6 +1,7 @@ using Deepgram; using Deepgram.Models.Speak.v1; using System.Text.Json; +using System.Text.RegularExpressions; namespace SampleApp { diff --git a/examples/speak/Speak.csproj b/examples/speak/Speak.csproj index 3cfb8ee6..105d5060 100644 --- a/examples/speak/Speak.csproj +++ b/examples/speak/Speak.csproj @@ -2,7 +2,7 @@ Exe - net8.0 + net6.0 enable enable diff --git a/examples/streaming/Program.cs b/examples/streaming/Program.cs index c2af692d..cc105d48 100644 --- a/examples/streaming/Program.cs +++ b/examples/streaming/Program.cs @@ -13,10 +13,9 @@ class Program { static async Task Main(string[] args) { - // Initialize the LiveClient with your API key and options + // Replace "REPLACE-WITH-YOUR-API-KEY" with your actual Deepgram API key var apiKey = "REPLACE-WITH-YOUR-API-KEY"; - var options = new DeepgramClientOptions(); - var liveClient = new LiveClient(apiKey, options); + var liveClient = new LiveClient(apiKey); // Subscribe to the EventResponseReceived event liveClient.EventResponseReceived += (sender, e) =>