Skip to content

Commit

Permalink
docs: Add Example Application (#12)
Browse files Browse the repository at this point in the history
  • Loading branch information
hf-kklein authored Feb 2, 2024
1 parent 3c1fdba commit 4f6e89f
Show file tree
Hide file tree
Showing 17 changed files with 241 additions and 21 deletions.
5 changes: 5 additions & 0 deletions .github/workflows/integrationtests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -55,3 +55,8 @@ jobs:
CLIENT_SECRET: ${{ secrets.AUTH0_TEST_CLIENT_SECRET }}
run: |
dotnet test --filter TestCollectionName='authenticated'
- name: Run Integration Tests for Example Application
working-directory: TransformerBeeClient/ExampleAspNetCoreApplication.Test
run: |
dotnet build --no-restore
dotnet test
24 changes: 17 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,38 +15,47 @@ Ask info@hochfrequenz.de or ping @JoschaMetze on GitHub to get one.
You can check if your account is working by logging [into our stage environment](https://transformerstage.utilibee.io/app/).

### Using the client
![Nuget Package](https://badgen.net/nuget/v/TransformerBeeClient)
Install it from nuget [TransformerBeeClient](https://www.nuget.org/packages/TransformerBeeClient):

Install it from nuget [TransformerBeeClient](https://www.nuget.org/packages/TransformerBeeClient) ![Nuget Package](https://badgen.net/nuget/v/TransformerBeeClient):

```bash
dotnet add package TransformerBeeClient
```

### Authentication

You need to provide something that implements `ITransformerBeeAuthenticator` to the `TransformerBeeClient`.

#### No Authentication
If you're hosting transformer.bee in the same network and there is no authentication, you can use the `NoAuthenticator`.

If you're hosting transformer.bee in the same network or your localhost and there is no authentication, you can use the `NoAuthenticator`.

```csharp
using TransformerBeeClient;
var myAuthenticator = new NoAuthenticationProvider();
```

#### OAuth2 Client and Secret
If, which is more likely, Hochfrequenz provided you with a client ID and secret, you can use the `ClientIdClientSecretAuthenticator` class like this:
If, which is more likely, Hochfrequenz provided you with a client Id and secret, you can use the `ClientIdClientSecretAuthenticator` class like this:

```csharp
using TransformerBeeClient;
var myAuthenticator = new ClientIdClientSecretAuthenticationProvider("YOUR_CLIENT_ID", "YOUR_CLIENT_SECRET");
```

...todo
```csharp
### Use with ASP.NET Core
This library is thought to be primarily used in ASP.NET Core applications.
That's why it assumes that you have an `IHttpClientFactory` available in your dependency injection container.
See the [`ExampleAspNetCoreApplication/Program.cs`](TransformerBeeClient/ExampleAspNetCoreApplication/Program.cs) for a minimal working example.

```
### Use without ASP.NET Core
If you're not using ASP.NET Core, you can still use this library but setting up th `IHttpClientFactory` comes with a bit of boilerplate.
See the [`MweWithoutAspNetTest.cs`](TransformerBeeClient/TransformerBeeClient.IntegrationTest/MweWithoutAspNetTest.cs) for a minimal working example.

## Development

### Integration Tests

To run the integration test login to your docker to access the transformer.bee image.

```bash
Expand All @@ -56,6 +65,7 @@ docker login ghcr.io -u YOUR_GITHUB_USERNAME
then paste your PAT similarly to described in the [integration test CI pipeline](.github/workflows/integrationtests.yml)

### Release (CI/CD)

To release a new version of this library, [create a new release](https://github.com/Hochfrequenz/transformer.bee_client.net/releases/new) in GitHub.
Make sure its tag starts with `v` and the version number, e.g. `v1.2.3`.
Tags without a release wont trigger the release workflow; This enforces that you have to write a changelog before releasing.
Expand Down
4 changes: 4 additions & 0 deletions TransformerBeeClient/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,7 @@ TransformerBeeClient.IntegrationTest/obj
TransformerBeeClient.IntegrationTest/bin
TransformerBeeClient.UnitTest/obj
TransformerBeeClient.UnitTest/bin
ExampleAspNetCoreApplication/obj
ExampleAspNetCoreApplication/bin
ExampleAspNetCoreApplication.Test/obj
ExampleAspNetCoreApplication.Test/bin
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
using System.Net;
using System.Text.Json;
using System.Text.Json.Serialization;
using FluentAssertions;
using Microsoft.AspNetCore.Mvc.Testing;
using TransformerBeeClient.Model;

namespace ExampleAspNetCoreApplication.Test;

public class ApplicationTest : IClassFixture<WebApplicationFactory<Program>>
{
protected readonly WebApplicationFactory<Program> Factory;

public ApplicationTest(WebApplicationFactory<Program> factory)
{
Factory = factory;
}

[Fact]
public async Task Test_That_Setup_Works_As_Designed()
{
var client = Factory.CreateDefaultClient();
var response = await client.GetAsync("/talkToTransformerBee");
response.StatusCode.Should().Be(HttpStatusCode.OK);
var content = await response.Content.ReadAsStringAsync();
var bo4e = JsonSerializer.Deserialize<BOneyComb>(content, new JsonSerializerOptions { Converters = { new JsonStringEnumConverter() } });
bo4e.Should().NotBeNull();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>

<IsPackable>false</IsPackable>
<IsTestProject>true</IsTestProject>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="FluentAssertions" Version="6.12.0" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="8.0.1" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.6.0"/>
<PackageReference Include="xunit" Version="2.4.2"/>
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.5">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="coverlet.collector" Version="6.0.0">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\ExampleAspNetCoreApplication\ExampleAspNetCoreApplication.csproj" />
</ItemGroup>

</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
global using Xunit;
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"shadowCopy": false
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<Project Sdk="Microsoft.NET.Sdk.Web">

<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<PreserveCompilationContext>true</PreserveCompilationContext>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\TransformerBeeClient\TransformerBeeClient.csproj"/>
</ItemGroup>
</Project>
29 changes: 29 additions & 0 deletions TransformerBeeClient/ExampleAspNetCoreApplication/Program.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
using EDILibrary;
using TransformerBeeClient;

var builder = WebApplication.CreateBuilder(args);
builder.Services.AddHttpClient();

builder.Services.AddTransient<ITransformerBeeAuthenticator, NoAuthenticator>(); // Or you could use ClientIdClientSecretAuthenticator
builder.Services.AddHttpClient("TransformerBee", client =>
{
client.BaseAddress = new Uri("http://localhost:5021/"); // or https://transformerstage.utilibee.io
});
builder.Services.AddTransient<ICanConvertToBo4e, TransformerBeeRestClient>();
builder.Services.AddTransient<ICanConvertToEdifact, TransformerBeeRestClient>();

var app = builder.Build();

app.MapGet("/", () => "I ❤ BO4E");
app.MapGet("/talkToTransformerBee", async (ICanConvertToBo4e transformerBeeRestClient) =>
{
var bo4e = await transformerBeeRestClient.ConvertToBo4e(
"UNA:+,? 'UNB+UNOC:3+9912345789012:500+9909876543210:500+230703:1059+ASDFHGJ'UNH+11223344556678+UTILMD:D:11A:UN:S1.1'BGM+E01+918273746512345678901'DTM+137:202306300558?+00:303'NAD+MS+9912345789012::293'NAD+MR+9909876543210::293'IDE+24+918273746512345678901'IMD++Z36+Z13'DTM+92:202212312300?+00:303'STS+7++E01'LOC+Z16+78889918283'LOC+Z17+DE0000111122223333444455556667778'RFF+Z13:55001'SEQ+Z01'CCI+Z30++Z07'CCI+Z19++11X0-0000-0116-J'CCI+++Z15'CCI+++Z88'CAV+Z74:::Z09'CAV+Z73:::Z11'SEQ+Z12'QTY+Z16:0:P1'SEQ+Z03'CCI+++E13'CAV+Z30:::788811123'SEQ+Z75'CCI+Z61++ZG1'NAD+Z09+++Schaefer:Ulrike:::Frau:Z01'NAD+Z04+++Schaefer:Ulrike:::Frau:Z01+Flughafenstrasse::64+Vilseck++92247+DE'NAD+DP++++Flughafenstrasse::64+Vilseck++92247+DE'NAD+Z05+++Schaefer:Ulrike:::Frau:Z01+Flughafenstrasse::64+Vilseck++92247+DE'UNT+31+11223344556678'UNZ+1+ASDFHGJ'",
EdifactFormatVersion.FV2310);
return bo4e.Single().Transaktionen.Single();

Check warning on line 23 in TransformerBeeClient/ExampleAspNetCoreApplication/Program.cs

View workflow job for this annotation

GitHub Actions / test (ubuntu-latest, 6.0.201)

Possible null reference argument for parameter 'source' in 'BOneyComb Enumerable.Single<BOneyComb>(IEnumerable<BOneyComb> source)'.

Check warning on line 23 in TransformerBeeClient/ExampleAspNetCoreApplication/Program.cs

View workflow job for this annotation

GitHub Actions / test (ubuntu-latest, 6.0.201)

Possible null reference argument for parameter 'source' in 'BOneyComb Enumerable.Single<BOneyComb>(IEnumerable<BOneyComb> source)'.

Check warning on line 23 in TransformerBeeClient/ExampleAspNetCoreApplication/Program.cs

View workflow job for this annotation

GitHub Actions / test (ubuntu-latest, 7.0.100)

Possible null reference argument for parameter 'source' in 'BOneyComb Enumerable.Single<BOneyComb>(IEnumerable<BOneyComb> source)'.

Check warning on line 23 in TransformerBeeClient/ExampleAspNetCoreApplication/Program.cs

View workflow job for this annotation

GitHub Actions / test (ubuntu-latest, 8.0.100)

Possible null reference argument for parameter 'source' in 'BOneyComb Enumerable.Single<BOneyComb>(IEnumerable<BOneyComb> source)'.
});
app.Run();

public partial class Program
{
} // required for integration testing; If you miss this the test will complain, that it cannot find a 'testhost.deps.json'
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
{
"$schema": "http://json.schemastore.org/launchsettings.json",
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:26369",
"sslPort": 44341
}
},
"profiles": {
"http": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,
"applicationUrl": "http://localhost:5137",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"https": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,
"applicationUrl": "https://localhost:7030;http://localhost:5137",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": true,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
using EDILibrary;
using Xunit;

namespace TransformerBeeClient.IntegrationTest;

/// <summary>
/// A minimal working example on how to use this library without ASP.NET
/// </summary>
public class MweWithoutAspNetTest
{
/// <summary>
/// in asp.net applications, there's a service collection that is used to create the http client factory for you
/// </summary>
internal class MyHttpClientFactory : IHttpClientFactory
{
public HttpClient CreateClient(string name)
{
return new HttpClient
{
BaseAddress = new Uri("http://localhost:5021")
};
}
}

[Fact]
public async Task Test_Transformer_Bee_Communication()
{
IHttpClientFactory myFactory = new MyHttpClientFactory();
ITransformerBeeAuthenticator myAuthenticator = new NoAuthenticator(); // or use ClientIdClientSecretAuthenticator
var client = new TransformerBeeRestClient(myFactory, myAuthenticator);
await client.ConvertToBo4e("UNA:+,? 'UNB+UNOC:3+9912345789012:500+9909876543210:500+230703:1059+ASDFHGJ'UNH+11223344556678+UTILMD:D:11A:UN:S1.1'BGM+E01+918273746512345678901'DTM+137:202306300558?+00:303'NAD+MS+9912345789012::293'NAD+MR+9909876543210::293'IDE+24+918273746512345678901'IMD++Z36+Z13'DTM+92:202212312300?+00:303'STS+7++E01'LOC+Z16+78889918283'LOC+Z17+DE0000111122223333444455556667778'RFF+Z13:55001'SEQ+Z01'CCI+Z30++Z07'CCI+Z19++11X0-0000-0116-J'CCI+++Z15'CCI+++Z88'CAV+Z74:::Z09'CAV+Z73:::Z11'SEQ+Z12'QTY+Z16:0:P1'SEQ+Z03'CCI+++E13'CAV+Z30:::788811123'SEQ+Z75'CCI+Z61++ZG1'NAD+Z09+++Schaefer:Ulrike:::Frau:Z01'NAD+Z04+++Schaefer:Ulrike:::Frau:Z01+Flughafenstrasse::64+Vilseck++92247+DE'NAD+DP++++Flughafenstrasse::64+Vilseck++92247+DE'NAD+Z05+++Schaefer:Ulrike:::Frau:Z01+Flughafenstrasse::64+Vilseck++92247+DE'UNT+31+11223344556678'UNZ+1+ASDFHGJ'", EdifactFormatVersion.FV2310);
}
}
12 changes: 12 additions & 0 deletions TransformerBeeClient/TransformerBeeClient.sln
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TransformerBeeClient.UnitTe
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TransformerBeeClient.IntegrationTest", "TransformerBeeClient.IntegrationTest\TransformerBeeClient.IntegrationTest.csproj", "{77598126-7BB0-4C07-BF06-331033E0DE78}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ExampleAspNetCoreApplication", "ExampleAspNetCoreApplication\ExampleAspNetCoreApplication.csproj", "{E6F6E532-9758-46C0-AC04-42CC054613C7}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ExampleAspNetCoreApplication.Test", "ExampleAspNetCoreApplication.Test\ExampleAspNetCoreApplication.Test.csproj", "{39992205-201D-445B-A58D-BB098F5EFC1D}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand All @@ -24,5 +28,13 @@ Global
{77598126-7BB0-4C07-BF06-331033E0DE78}.Debug|Any CPU.Build.0 = Debug|Any CPU
{77598126-7BB0-4C07-BF06-331033E0DE78}.Release|Any CPU.ActiveCfg = Release|Any CPU
{77598126-7BB0-4C07-BF06-331033E0DE78}.Release|Any CPU.Build.0 = Release|Any CPU
{E6F6E532-9758-46C0-AC04-42CC054613C7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{E6F6E532-9758-46C0-AC04-42CC054613C7}.Debug|Any CPU.Build.0 = Debug|Any CPU
{E6F6E532-9758-46C0-AC04-42CC054613C7}.Release|Any CPU.ActiveCfg = Release|Any CPU
{E6F6E532-9758-46C0-AC04-42CC054613C7}.Release|Any CPU.Build.0 = Release|Any CPU
{39992205-201D-445B-A58D-BB098F5EFC1D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{39992205-201D-445B-A58D-BB098F5EFC1D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{39992205-201D-445B-A58D-BB098F5EFC1D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{39992205-201D-445B-A58D-BB098F5EFC1D}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
EndGlobal
16 changes: 4 additions & 12 deletions TransformerBeeClient/TransformerBeeClient.sln.DotSettings.user
Original file line number Diff line number Diff line change
@@ -1,15 +1,7 @@
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<s:String x:Key="/Default/Environment/UnitTesting/UnitTestSessionStore/Sessions/=1c8bdc71_002Dfc3e_002D44fe_002D9812_002D1b49b4ba3413/@EntryIndexedValue">&lt;SessionState ContinuousTestingMode="0" Name="All tests from Solution" xmlns="urn:schemas-jetbrains-com:jetbrains-ut-session"&gt;&#xD;

<s:String x:Key="/Default/Environment/UnitTesting/UnitTestSessionStore/Sessions/=4fa21289_002Debff_002D4c5a_002D8d89_002D3c311da32c05/@EntryIndexedValue">&lt;SessionState ContinuousTestingMode="0" IsActive="True" Name="All tests from Solution #2" xmlns="urn:schemas-jetbrains-com:jetbrains-ut-session"&gt;&#xD;
&lt;Solution /&gt;&#xD;
&lt;/SessionState&gt;</s:String>
<s:String x:Key="/Default/Environment/UnitTesting/UnitTestSessionStore/Sessions/=4fa21289_002Debff_002D4c5a_002D8d89_002D3c311da32c05/@EntryIndexedValue">&lt;SessionState ContinuousTestingMode="0" Name="All tests from Solution #2" xmlns="urn:schemas-jetbrains-com:jetbrains-ut-session"&gt;&#xD;
&lt;Solution /&gt;&#xD;
&lt;/SessionState&gt;</s:String>
<s:String x:Key="/Default/Environment/UnitTesting/UnitTestSessionStore/Sessions/=591857ee_002D832a_002D4abe_002D964d_002Db61be9cce36e/@EntryIndexedValue">&lt;SessionState ContinuousTestingMode="0" IsActive="True" Name="BOneyComb_Can_Be_Converted_To_Edifact" xmlns="urn:schemas-jetbrains-com:jetbrains-ut-session"&gt;&#xD;
&lt;TestAncestor&gt;&#xD;
&lt;TestId&gt;xUnit::77598126-7BB0-4C07-BF06-331033E0DE78::net8.0::TransformerBeeClient.IntegrationTest.Bo4eToEdifactTests.BOneyComb_Can_Be_Converted_To_Edifact&lt;/TestId&gt;&#xD;
&lt;/TestAncestor&gt;&#xD;
&lt;/SessionState&gt;</s:String>
<s:String x:Key="/Default/Environment/UnitTesting/UnitTestSessionStore/Sessions/=de4efd69_002D9f4a_002D4e00_002D83fa_002Ddaa381865bd8/@EntryIndexedValue">&lt;SessionState ContinuousTestingMode="0" Name="ConnectionTest" xmlns="urn:schemas-jetbrains-com:jetbrains-ut-session"&gt;&#xD;
&lt;Solution /&gt;&#xD;
&lt;/SessionState&gt;</s:String></wpf:ResourceDictionary>

</wpf:ResourceDictionary>
6 changes: 4 additions & 2 deletions TransformerBeeClient/TransformerBeeClient/RestClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -108,12 +108,13 @@ public async Task<List<Marktnachricht>> ConvertToBo4e(string edifact, EdifactFor
var httpResponse = await _httpClient.PostAsync(convertUrl, new StringContent(requestJson, Encoding.UTF8, "application/json"));
if (!httpResponse.IsSuccessStatusCode)
{
var errorContent = await httpResponse.Content.ReadAsStringAsync();
if (httpResponse.StatusCode == HttpStatusCode.Unauthorized && !_authenticator.UseAuthentication())
{
throw new AuthenticationException($"Did you correctly set up the {nameof(ITransformerBeeAuthenticator)}?");
}

throw new HttpRequestException($"Could not convert {edifact} to BO4E. Status code: {httpResponse.StatusCode}");
throw new HttpRequestException($"Could not convert {edifact} to BO4E. Status code: {httpResponse.StatusCode} / {errorContent}");
}

var responseContent = await httpResponse.Content.ReadAsStringAsync();
Expand Down Expand Up @@ -149,12 +150,13 @@ public async Task<string> ConvertToEdifact(BOneyComb boneyComb, EdifactFormatVer
var httpResponse = await _httpClient.PostAsync(convertUrl, new StringContent(requestJson, Encoding.UTF8, "application/json"));
if (!httpResponse.IsSuccessStatusCode)
{
var errorContent = await httpResponse.Content.ReadAsStringAsync();
if (httpResponse.StatusCode == HttpStatusCode.Unauthorized && !_authenticator.UseAuthentication())
{
throw new AuthenticationException($"Did you correctly set up the {nameof(ITransformerBeeAuthenticator)}?");
}

throw new HttpRequestException($"Could not convert to EDIFACT; Status code: {httpResponse.StatusCode}");
throw new HttpRequestException($"Could not convert to EDIFACT; Status code: {httpResponse.StatusCode} / {errorContent}");
}

var responseContent = await httpResponse.Content.ReadAsStringAsync();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<TargetFrameworks>net8.0;net6.0;net7.0</TargetFrameworks>
<RepositoryUrl>https://github.com/Hochfrequenz/transformer.bee_client.net</RepositoryUrl>
<License>MIT</License>
</PropertyGroup>

<PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
Expand Down

0 comments on commit 4f6e89f

Please sign in to comment.