Skip to content

Commit

Permalink
Merge pull request #154 from binarymash/feature/#39-implement-client-…
Browse files Browse the repository at this point in the history
…endpoint

Feature/#39 implement client endpoint
  • Loading branch information
binarymash authored Jan 13, 2019
2 parents 837bb34 + 5b11411 commit f002a49
Show file tree
Hide file tree
Showing 34 changed files with 1,166 additions and 2,125 deletions.
6 changes: 3 additions & 3 deletions src/Evelyn.Client.Rest/EnvironmentStateRestProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,12 @@

public class EnvironmentStateRestProvider : IEnvironmentStateProvider
{
private readonly Client _client;
private readonly EvelynRestClient _client;
private readonly ILogger<EnvironmentStateRestProvider> _logger;

public EnvironmentStateRestProvider(IOptions<EnvironmentStateRestProviderOptions> options, ILogger<EnvironmentStateRestProvider> logger)
{
_client = new Client(options.Value.BaseUrl);
_client = new EvelynRestClient(options.Value.BaseUrl);
_logger = logger;
}

Expand All @@ -24,7 +24,7 @@ public Domain.EnvironmentState Invoke(Guid projectId, string environmentKey)
try
{
var dto = _client
.ApiStatesAsync(projectId, environmentKey)
.GetAsync(projectId, environmentKey)
.GetAwaiter().GetResult();

var toggleStates = new List<Domain.ToggleState>();
Expand Down
4 changes: 0 additions & 4 deletions src/Evelyn.Client.Rest/Evelyn.Client.Rest.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,4 @@
<ProjectReference Include="..\Evelyn.Client\Evelyn.Client.csproj" />
</ItemGroup>

<ItemGroup>
<Folder Include="Generated\" />
</ItemGroup>

</Project>
377 changes: 377 additions & 0 deletions src/Evelyn.Client.Rest/Generated/EvelynRestClient.cs

Large diffs are not rendered by default.

2,093 changes: 0 additions & 2,093 deletions src/Evelyn.Client.Rest/Generated/OpenApiClasses.cs

This file was deleted.

11 changes: 7 additions & 4 deletions src/Evelyn.Client.Rest/Generated/RestApi.nswag
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
"defaultVariables": null,
"swaggerGenerator": {
"fromSwagger": {
"url": "http://localhost:2316/swagger/v0.1/swagger.json",
"json": "{\r\n \"swagger\": \"2.0\",\r\n \"info\": {\r\n \"version\": \"client-api\",\r\n \"title\": \"Evelyn Client API\",\r\n \"description\": \"Client API for Evelyn\"\r\n },\r\n \"paths\": {\r\n \"/client-api/projects/{projectId}/environments/{environmentName}/state\": {\r\n \"get\": {\r\n \"tags\": [\r\n \"ClientEnvironmentStates\"\r\n ],\r\n \"operationId\": \"Get\",\r\n \"consumes\": [],\r\n \"produces\": [\r\n \"text/plain\",\r\n \"application/json\",\r\n \"text/json\"\r\n ],\r\n \"parameters\": [\r\n {\r\n \"name\": \"projectId\",\r\n \"in\": \"path\",\r\n \"required\": true,\r\n \"type\": \"string\",\r\n \"format\": \"uuid\"\r\n },\r\n {\r\n \"name\": \"environmentName\",\r\n \"in\": \"path\",\r\n \"required\": true,\r\n \"type\": \"string\"\r\n }\r\n ],\r\n \"responses\": {\r\n \"500\": {\r\n \"description\": \"Server Error\",\r\n \"schema\": {\r\n \"type\": \"object\",\r\n \"additionalProperties\": {\r\n \"type\": \"string\"\r\n }\r\n }\r\n },\r\n \"200\": {\r\n \"description\": \"Success\",\r\n \"schema\": {\r\n \"$ref\": \"#/definitions/Evelyn.Core.ReadModel.Projections.ClientEnvironmentState.Projection\"\r\n }\r\n },\r\n \"404\": {\r\n \"description\": \"Not Found\",\r\n \"schema\": {\r\n \"type\": \"object\",\r\n \"additionalProperties\": {\r\n \"type\": \"string\"\r\n }\r\n }\r\n }\r\n }\r\n }\r\n },\r\n \"/status/health\": {\r\n \"get\": {\r\n \"tags\": [\r\n \"Status\"\r\n ],\r\n \"operationId\": \"GetHealth\",\r\n \"consumes\": [],\r\n \"produces\": [],\r\n \"parameters\": [],\r\n \"responses\": {\r\n \"200\": {\r\n \"description\": \"Success\"\r\n }\r\n }\r\n }\r\n }\r\n },\r\n \"definitions\": {\r\n \"Evelyn.Core.ReadModel.Projections.ClientEnvironmentState.Projection\": {\r\n \"type\": \"object\",\r\n \"properties\": {\r\n \"environmentState\": {\r\n \"$ref\": \"#/definitions/Evelyn.Core.ReadModel.Projections.ClientEnvironmentState.Model.EnvironmentState\"\r\n },\r\n \"audit\": {\r\n \"$ref\": \"#/definitions/Evelyn.Core.ReadModel.Projections.ProjectionAudit\",\r\n \"readOnly\": true\r\n }\r\n }\r\n },\r\n \"Evelyn.Core.ReadModel.Projections.ClientEnvironmentState.Model.EnvironmentState\": {\r\n \"type\": \"object\",\r\n \"properties\": {\r\n \"toggleStates\": {\r\n \"uniqueItems\": false,\r\n \"type\": \"array\",\r\n \"items\": {\r\n \"$ref\": \"#/definitions/Evelyn.Core.ReadModel.Projections.ClientEnvironmentState.Model.ToggleState\"\r\n },\r\n \"readOnly\": true\r\n }\r\n }\r\n },\r\n \"Evelyn.Core.ReadModel.Projections.ProjectionAudit\": {\r\n \"type\": \"object\",\r\n \"properties\": {\r\n \"generated\": {\r\n \"format\": \"date-time\",\r\n \"type\": \"string\",\r\n \"readOnly\": true\r\n },\r\n \"streamPosition\": {\r\n \"format\": \"int64\",\r\n \"type\": \"integer\",\r\n \"readOnly\": true\r\n }\r\n }\r\n },\r\n \"Evelyn.Core.ReadModel.Projections.ClientEnvironmentState.Model.ToggleState\": {\r\n \"type\": \"object\",\r\n \"properties\": {\r\n \"key\": {\r\n \"type\": \"string\",\r\n \"readOnly\": true\r\n },\r\n \"value\": {\r\n \"type\": \"string\",\r\n \"readOnly\": true\r\n }\r\n }\r\n }\r\n }\r\n}",
"url": "http://localhost:2316/swagger/client-api/swagger.json",
"output": null
}
},
Expand Down Expand Up @@ -36,8 +37,8 @@
"generateUpdateJsonSerializerSettingsMethod": true,
"serializeTypeInformation": false,
"queryNullValue": "",
"className": "{controller}Client",
"operationGenerationMode": "SingleClientFromPathSegments",
"className": "EvelynRestClient",
"operationGenerationMode": "SingleClientFromOperationId",
"additionalNamespaceUsages": [],
"additionalContractNamespaceUsages": [],
"generateOptionalParameters": false,
Expand Down Expand Up @@ -72,13 +73,15 @@
"generateImmutableArrayProperties": false,
"generateImmutableDictionaryProperties": false,
"jsonSerializerSettingsTransformationMethod": null,
"inlineNamedDictionaries": false,
"inlineNamedTuples": true,
"templateDirectory": null,
"typeNameGeneratorType": null,
"propertyNameGeneratorType": null,
"enumNameGeneratorType": null,
"serviceHost": null,
"serviceSchemes": null,
"output": null
"output": "EvelynRestClient.cs"
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
namespace Evelyn.Core.Tests.ReadModel.Projections.ClientEnvironmentState.ProjectEvents
{
using System.Threading.Tasks;
using AutoFixture;
using Evelyn.Core.ReadModel.Projections.ClientEnvironmentState;
using Evelyn.Core.WriteModel.Project.Events;
using FluentAssertions;
using NSubstitute;
using TestStack.BDDfy;
using Xunit;

public class EnvironmentStateAddedSpecs : ProjectionBuilderHarness<EnvironmentStateAdded>
{
[Fact]
public void Nominal()
{
this.Given(_ => GivenThereIsNoProjection())
.When(_ => WhenWeHandleAnEnvironmentStateAddedEvent())
.Then(_ => ThenTheProjectionAuditIsSet())
.And(_ => ThenTheProjectionContainsTheEnvironmentState())
.BDDfy();
}

protected override async Task HandleEventImplementation()
{
await ProjectionBuilder.Handle(StreamPosition, Event, StoppingToken);
}

private async Task WhenWeHandleAnEnvironmentStateAddedEvent()
{
Event = DataFixture.Build<EnvironmentStateAdded>()
.With(ar => ar.Id, ProjectId)
.With(esa => esa.EnvironmentKey, EnvironmentKey)
.Create();

await WhenTheEventIsHandled();
}

private void ThenTheProjectionContainsTheEnvironmentState()
{
ProjectionStore.Received().Create(Projection.StoreKey(ProjectId, EnvironmentKey), UpdatedProjection);

UpdatedProjection.EnvironmentState.ToggleStates.Should().BeEquivalentTo(Event.ToggleStates);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
namespace Evelyn.Core.Tests.ReadModel.Projections.ClientEnvironmentState.ProjectEvents
{
using System.Threading.Tasks;
using AutoFixture;
using Evelyn.Core.ReadModel.Projections.ClientEnvironmentState;
using Evelyn.Core.WriteModel.Project.Events;
using NSubstitute;
using TestStack.BDDfy;
using Xunit;

public class EnvironmentStateDeletedSpecs : ProjectionBuilderHarness<EnvironmentStateDeleted>
{
[Fact]
public void Nominal()
{
this.Given(_ => GivenTheProjectionExists())
.When(_ => WhenWeHandleAnEnvironmentStateDeletedEvent())
.Then(_ => ThenTheProjectionIsDeleted())
.BDDfy();
}

protected override async Task HandleEventImplementation()
{
await ProjectionBuilder.Handle(StreamPosition, Event, StoppingToken);
}

private async Task WhenWeHandleAnEnvironmentStateDeletedEvent()
{
Event = DataFixture.Build<EnvironmentStateDeleted>()
.With(pc => pc.Id, ProjectId)
.With(pc => pc.EnvironmentKey, EnvironmentKey)
.Create();

await WhenTheEventIsHandled();
}

private void ThenTheProjectionIsDeleted()
{
ProjectionStore.Received().Delete(Projection.StoreKey(ProjectId, EnvironmentKey));
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
namespace Evelyn.Core.Tests.ReadModel.Projections.ClientEnvironmentState.ProjectEvents
{
using System.Linq;
using System.Threading.Tasks;
using AutoFixture;
using Evelyn.Core.WriteModel.Project.Events;
using FluentAssertions;
using TestStack.BDDfy;
using Xunit;
using Projections = Evelyn.Core.ReadModel.Projections;

public class ToggleStateAddedSpecs : ProjectionBuilderHarness<ToggleStateAdded>
{
[Fact]
public void ProjectionDoesNotExist()
{
this.Given(_ => GivenThereIsNoProjection())
.When(_ => WhenWeHandleAToggleStateAddedEvent())
.Then(_ => ThenAnExceptionIsThrown())
.BDDfy();
}

[Fact]
public void Nominal()
{
this.Given(_ => GivenTheProjectionExists())
.And(_ => GivenTheProjectAlreadyHasAToggleState())
.When(_ => WhenWeHandleAToggleStateAddedEvent())
.Then(_ => ThenTheNewToggleStateIsAdded())
.And(_ => ThenTheProjectionAuditIsSet())
.BDDfy();
}

protected override async Task HandleEventImplementation()
{
await ProjectionBuilder.Handle(StreamPosition, Event, StoppingToken);
}

private void GivenTheProjectAlreadyHasAToggleState()
{
OriginalProjection.EnvironmentState.AddToggleState(
DataFixture.Create<Projections.EventAudit>(),
DataFixture.Create<string>(),
DataFixture.Create<string>());
}

private async Task WhenWeHandleAToggleStateAddedEvent()
{
Event = DataFixture.Build<ToggleStateAdded>()
.With(pc => pc.Id, ProjectId)
.With(pc => pc.EnvironmentKey, EnvironmentKey)
.Create();

await WhenTheEventIsHandled();
}

private void ThenTheNewToggleStateIsAdded()
{
var toggleStates = UpdatedProjection.EnvironmentState.ToggleStates.ToList();
toggleStates.Count.Should().Be(OriginalProjection.EnvironmentState.ToggleStates.Count() + 1);

foreach (var toggleState in OriginalProjection.EnvironmentState.ToggleStates)
{
toggleStates.Should().Contain(ts =>
ts.Key == toggleState.Key &&
ts.Value == toggleState.Value);
}

toggleStates.Should().Contain(ts =>
ts.Key == Event.ToggleKey &&
ts.Value == Event.Value);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
namespace Evelyn.Core.Tests.ReadModel.Projections.ClientEnvironmentState.ProjectEvents
{
using System.Linq;
using System.Threading.Tasks;
using AutoFixture;
using Evelyn.Core.WriteModel.Project.Events;
using FluentAssertions;
using TestStack.BDDfy;
using Xunit;

public class ToggleStateChangedSpecs : ProjectionBuilderHarness<ToggleStateChanged>
{
[Fact]
public void ProjectionDoesNotExist()
{
this.Given(_ => GivenThereIsNoProjection())
.When(_ => WhenWeHandleAToggleStateChangedEvent())
.Then(_ => ThenAnExceptionIsThrown())
.BDDfy();
}

[Fact]
public void Nominal()
{
this.Given(_ => GivenTheProjectionExists())
.And(_ => GivenOurToggleStateIsOnTheProjection())
.And(_ => GivenTheProjectionHasOtherToggleStates())
.When(_ => WhenWeHandleAToggleStateChangedEvent())
.Then(_ => ThenOurToggleStateIsChanged())
.And(_ => ThenTheProjectionAuditIsSet())
.BDDfy();
}

protected override async Task HandleEventImplementation()
{
await ProjectionBuilder.Handle(StreamPosition, Event, StoppingToken);
}

private async Task WhenWeHandleAToggleStateChangedEvent()
{
Event = DataFixture.Build<ToggleStateChanged>()
.With(pc => pc.Id, ProjectId)
.With(pc => pc.EnvironmentKey, EnvironmentKey)
.With(pc => pc.ToggleKey, ToggleKey)
.Create();

await WhenTheEventIsHandled();
}

private void ThenOurToggleStateIsChanged()
{
var updatedToggleStates = UpdatedProjection.EnvironmentState.ToggleStates.ToList();
updatedToggleStates.Count.Should().Be(OriginalProjection.EnvironmentState.ToggleStates.Count());

foreach (var originalToggleState in OriginalProjection.EnvironmentState.ToggleStates)
{
var expectedToggleStateValue =
(originalToggleState.Key == Event.ToggleKey)
? Event.Value
: originalToggleState.Value;

updatedToggleStates.Should().Contain(ts =>
ts.Key == originalToggleState.Key &&
ts.Value == expectedToggleStateValue);
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
namespace Evelyn.Core.Tests.ReadModel.Projections.ClientEnvironmentState.ProjectEvents
{
using System.Linq;
using System.Threading.Tasks;
using AutoFixture;
using Evelyn.Core.WriteModel.Project.Events;
using FluentAssertions;
using TestStack.BDDfy;
using Xunit;

public class ToggleStateDeletedSpecs : ProjectionBuilderHarness<ToggleStateDeleted>
{
[Fact]
public void Nominal()
{
this.Given(_ => GivenTheProjectionExists())
.And(_ => GivenOurToggleStateIsOnTheProjection())
.When(_ => WhenWeHandleAToggleStateDeletedEvent())
.Then(_ => ThenOurToggleStateIsRemoved())
.And(_ => ThenTheProjectionAuditIsSet())
.BDDfy();
}

[Fact]
public void ProjectionDoesNotExist()
{
this.Given(_ => GivenThereIsNoProjection())
.When(_ => WhenWeHandleAToggleStateDeletedEvent())
.Then(_ => ThenAnExceptionIsThrown())
.BDDfy();
}

protected override async Task HandleEventImplementation()
{
await ProjectionBuilder.Handle(StreamPosition, Event, StoppingToken);
}

private async Task WhenWeHandleAToggleStateDeletedEvent()
{
Event = DataFixture.Build<ToggleStateDeleted>()
.With(pc => pc.Id, ProjectId)
.With(pc => pc.EnvironmentKey, EnvironmentKey)
.With(pc => pc.ToggleKey, ToggleKey)
.Create();

await WhenTheEventIsHandled();
}

private void ThenOurToggleStateIsRemoved()
{
var updatedToggleStates = UpdatedProjection.EnvironmentState.ToggleStates.ToList();
updatedToggleStates.Count.Should().Be(OriginalProjection.EnvironmentState.ToggleStates.Count() - 1);

foreach (var originalToggleState in OriginalProjection.EnvironmentState.ToggleStates)
{
if (originalToggleState.Key != Event.ToggleKey)
{
updatedToggleStates.Should().Contain(ts =>
ts.Key == originalToggleState.Key &&
ts.Value == originalToggleState.Value);
}
}
}
}
}
Loading

0 comments on commit f002a49

Please sign in to comment.