Skip to content

Commit

Permalink
chore: add marten and (test) databases and test setup
Browse files Browse the repository at this point in the history
  • Loading branch information
AlexZeitler committed Feb 29, 2024
1 parent 3ee5d06 commit c657454
Show file tree
Hide file tree
Showing 24 changed files with 382 additions and 574 deletions.
21 changes: 17 additions & 4 deletions .tmuxinator.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
name: MyRazorPagesApp
name: AspNetMartenHtmxVsa
root: ./
startup_window: 2
startup_pane: 3

# Runs before everything. Use it to start daemons etc.
on_project_start:
Expand All @@ -25,20 +27,31 @@ windows:
- app:
layout: even-vertical
panes:
- database:
- printf '\033]2;%s\033\\' 'database'
- cd database
- docker-compose up
- server:
- printf '\033]2;%s\033\\' 'app'
- cd src/AspNetCoreMvcHtmx
- cd src/AspNetMartenHtmxVsa
- kill -9 $(lsof -t -i tcp:5001)
- kill -9 $(lsof -t -i tcp:5000)
- dotnet watch run
- workspace:
- printf '\033]2;%s\033\\' 'app-workspace'
- cd src/AspNetCoreMvcHtmx
- cd src/AspNetMartenHtmxVsa
- clear
- tests:
layout: even-vertical
panes:
- marten-test:
- printf '\033]2;%s\033\\' 'marten-test'
- cd src/AspNetMartenHtmxVsa.IntegrationTests/test-database
- docker-compose up
- frontend:
layout: even-vertical
panes:
- tailwind:
- printf '\033]2;%s\033\\' 'vite-build'
- cd src/AspNetCoreMvcHtmx
- cd src/AspNetMartenHtmxVsa
- npx tailwindcss -i ./wwwroot/css/input.css -o ./wwwroot/css/site.css --watch
15 changes: 15 additions & 0 deletions database/docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
version: "3"

services:
database:
image: library/postgres:14
container_name: eventstoredb
environment:
POSTGRES_USER: 'marten'
POSTGRES_PASSWORD: '123456'
POSTGRES_DB: 'marten'
ports:
- "5400:5432"
user: "1000:1000"
volumes:
- ./data:/var/lib/postgresql/data
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
"scripts": {
"prepare": "husky install",
"start": "tmuxinator",
"stop": "tmux kill-session"
"stop": "docker stop $(docker ps -aq); docker rm $(docker ps -aq);tmux kill-session"
},
"repository": {
"type": "git",
Expand Down
8 changes: 8 additions & 0 deletions setup.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#!/bin/bash

yarn
cd src/AspNetMartenHtmxVsa
yarn
libman restore
cd ../../
mkdir -p database/data
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,14 @@
<IsPackable>false</IsPackable>

<LangVersion>12</LangVersion>

<RootNamespace>AspNetMartenHtmxVsa.Tests</RootNamespace>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Alba" Version="7.4.1" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.8.0" />
<PackageReference Include="Npgsql" Version="8.0.2" />
<PackageReference Include="xunit" Version="2.6.4" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.5.6">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
Expand All @@ -23,4 +27,8 @@
</PackageReference>
</ItemGroup>

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

</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
using Alba;
using AspNetMartenHtmxVsa.Tests.TestSetup;
using Microsoft.Extensions.Configuration;
using Xunit.Abstractions;

namespace AspNetMartenHtmxVsa.Tests.IntegrationTestHost;

public class TestConfiguration : Dictionary<string, string?>
{
public IConfigurationRoot AsConfigurationRoot()
{
return new ConfigurationBuilder()
.AddInMemoryCollection(this)
.Build();
}
}

public class IntegrationTestHost : IDisposable
{
private IAlbaHost Host { get; init; }
private TestEventStore EventStore { get; init; }

private IntegrationTestHost(IAlbaHost host, TestEventStore eventStore)
{
Host = host;
EventStore = eventStore;
}

public static async Task<IAlbaHost> InitializeAsync(
ITestOutputHelper? testOutputHelper = null
)
{
var testEventStore = await TestEventStore.InitializeAsync();
var configuration = new TestConfiguration
{
["ConnectionStrings:EventStore"] = testEventStore.MasterDbConnectionString
}.AsConfigurationRoot();

var builder = ConfigureHost.GetHostBuilder(configuration, services => {});

return await builder.StartAlbaAsync();
}

public async Task DisposeAsync()
{
await Host.DisposeAsync();
await EventStore.DisposeAsync();
}

public void Dispose()
{
DisposeAsync().GetAwaiter().GetResult();
}
}
168 changes: 168 additions & 0 deletions src/AspNetMartenHtmxVsa.IntegrationTests/TestSetup/TestEventStore.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
using AspNetMartenHtmxVsa.EventSourcing;
using Marten;
using Npgsql;

namespace AspNetMartenHtmxVsa.Tests.TestSetup;

public class PostgresAdministration
{
private readonly string _connectionString;

public PostgresAdministration(
string connectionString
)
{
_connectionString = connectionString;
}

public async Task CreateDatabaseAsync(
string? databaseName
)
{
await using var connection = new NpgsqlConnection();
connection.ConnectionString = _connectionString;
await connection.OpenAsync();
var command = new NpgsqlCommand(
$"CREATE DATABASE {databaseName}",
connection
);
await command.ExecuteNonQueryAsync();
await connection.CloseAsync();
}

public async Task DropDatabase(
string? databaseName
)
{
await using var connection = new NpgsqlConnection();
connection.ConnectionString = _connectionString;
await connection.OpenAsync();
var command = new NpgsqlCommand(
$"DROP DATABASE IF EXISTS {databaseName} WITH (FORCE);",
connection
);
await command.ExecuteNonQueryAsync();
await connection.CloseAsync();
}

public async Task<bool> EnsureDatabaseExists(
string databaseName
)
{
await using var connection = new NpgsqlConnection();
connection.ConnectionString = _connectionString;

await connection.OpenAsync();
var command = new NpgsqlCommand(
$"SELECT 1 FROM pg_database WHERE datname LIKE '{databaseName}'",
connection
);

var result = await command.ExecuteScalarAsync();
await connection.CloseAsync();

return result != null;
}
}

public class TestDatabase
{
private readonly PostgresAdministration _postgresAdministration;
private string? _testDbName;
public string MasterDbConnectionString { get; }

public TestDatabase(
string masterDbConnectionString
)
{
MasterDbConnectionString = masterDbConnectionString;
_postgresAdministration = new PostgresAdministration(
masterDbConnectionString
);
}

public async Task<string> InitializeAsync(
string masterDbConnection
)
{
Task
.Delay(new Random().Next(50, 100))
.Wait();

var dbId = DateTime.UtcNow.ToString("yyyy_MM_dd_HH_mm_ss_fff");
_testDbName = $"marten_test_{dbId}_{Guid.NewGuid().ToString()[..4]}";
await _postgresAdministration.CreateDatabaseAsync(
_testDbName
);

var connectionString = new NpgsqlConnectionStringBuilder
{
Pooling = false,
Port = 5435,
Host = "localhost",
CommandTimeout = 20,
Database = _testDbName,
Password = "123456",
Username = "postgres"
}.ToString();

return connectionString;
}

public async Task DropAsync() => await _postgresAdministration.DropDatabase(_testDbName);
}

public class TestEventStore
{
public string MasterDbConnectionString { get; }
public IDocumentStore Store { get; }
private TestDatabase TestDatabase { get; }

private TestEventStore(
IDocumentStore store,
TestDatabase testDatabase,
string masterDbConnectionString
)
{
Store = store;
TestDatabase = testDatabase;
MasterDbConnectionString = masterDbConnectionString;
}

public static async Task<TestEventStore> InitializeAsync(
Action<StoreOptions>? configureStoreOptions = null
)
{
var masterDbConnection = new NpgsqlConnectionStringBuilder
{
Pooling = false,
Port = 5435,
Host = "localhost",
CommandTimeout = 20,
Database = "postgres",
Password = "123456",
Username = "postgres"
}.ToString();
var testDatabase = new TestDatabase(masterDbConnection);

var connectionString = await testDatabase.InitializeAsync(masterDbConnection);


var store = DocumentStore.For(
options =>
{
options.Connection(connectionString);
StoreConfiguration.Configure(options);
configureStoreOptions?.Invoke(options);
}
);

return new TestEventStore(store, testDatabase, connectionString);
}

public async Task DisposeAsync()
{
await TestDatabase.DropAsync();
Store.Dispose();
}
}
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
postgres_data
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
version: "3"

services:
database:
image: library/postgres:14
container_name: eventstoretestdb
environment:
POSTGRES_USER: 'postgres'
POSTGRES_PASSWORD: '123456'
POSTGRES_DB: 'postgres'
ports:
- "5435:5432"
2 changes: 1 addition & 1 deletion src/AspNetMartenHtmxVsa.sln
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ VisualStudioVersion = 16.0.30114.105
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AspNetMartenHtmxVsa", "AspNetMartenHtmxVsa\AspNetMartenHtmxVsa.csproj", "{46101C3D-4CC3-4C6D-A868-E8AFD9DF3403}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AspNetMartenHtmxVsa.Tests", "AspNetMartenHtmxVsa.Tests\AspNetMartenHtmxVsa.Tests.csproj", "{E6BB0A13-D231-47E0-9CB7-8AA395B47528}"
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AspNetMartenHtmxVsa.IntegrationTests", "AspNetMartenHtmxVsa.IntegrationTests\AspNetMartenHtmxVsa.IntegrationTests.csproj", "{E6BB0A13-D231-47E0-9CB7-8AA395B47528}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Expand Down
7 changes: 7 additions & 0 deletions src/AspNetMartenHtmxVsa/AspNetMartenHtmxVsa.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
<PackageReference Include="Htmx" Version="1.6.3" />
<PackageReference Include="Htmx.TagHelpers" Version="1.6.3" />
<PackageReference Include="JetBrains.Annotations" Version="2023.3.0" />
<PackageReference Include="Marten" Version="6.4.1" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation" Version="8.0.0" />
<PackageReference Include="Serilog" Version="3.1.1" />
<PackageReference Include="Serilog.AspNetCore" Version="8.0.0" />
Expand Down Expand Up @@ -42,6 +43,12 @@
<_ContentIncludedByDefault Remove="Views\Shared\_ValidationScriptsPartial.cshtml" />
<_ContentIncludedByDefault Remove="Views\_ViewImports.cshtml" />
<_ContentIncludedByDefault Remove="Views\_ViewStart.cshtml" />
<_ContentIncludedByDefault Remove="wwwroot\lib\bootstrap\LICENSE" />
<_ContentIncludedByDefault Remove="wwwroot\lib\jquery-validation-unobtrusive\jquery.validate.unobtrusive.js" />
<_ContentIncludedByDefault Remove="wwwroot\lib\jquery-validation-unobtrusive\jquery.validate.unobtrusive.min.js" />
<_ContentIncludedByDefault Remove="wwwroot\lib\jquery-validation-unobtrusive\LICENSE.txt" />
<_ContentIncludedByDefault Remove="wwwroot\lib\jquery-validation\LICENSE.md" />
<_ContentIncludedByDefault Remove="wwwroot\lib\jquery\LICENSE.txt" />
</ItemGroup>

</Project>
Loading

0 comments on commit c657454

Please sign in to comment.