Skip to content

Commit

Permalink
Merge c9039ed into ac48c18
Browse files Browse the repository at this point in the history
  • Loading branch information
dlidstrom authored Nov 23, 2021
2 parents ac48c18 + c9039ed commit 371a046
Show file tree
Hide file tree
Showing 58 changed files with 801 additions and 65 deletions.
29 changes: 27 additions & 2 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ jobs:
- uses: actions/cache@v2
id: cache
with:
path: ~/.nuget/packages
path: C:\Users\runneradmin\.nuget\packages
key: ${{ runner.os }}-nuget-${{ hashFiles('**/packages.lock.json') }}
restore-keys: |
${{ runner.os }}-nuget-
Expand All @@ -43,18 +43,43 @@ jobs:
#if: steps.cache.outputs.cache-hit != 'true'
run: |
nuget restore Snittlistan.sln
Get-ChildItem -Recurse C:\Users\runneradmin\.nuget
- name: Build
run: msbuild build.build -t:All -p:Version=$env:BUILD_VERSION -p:WIX_PATH=$env:wix -p:NUnitConsoleRunnerPath=C:\Users\runneradmin\.nuget\packages\nunit.consolerunner\3.12.0\

- name: Upload a Build Artifact
uses: actions/upload-artifact@v2
with:
name: 'Test Result'
path: Build\_build\TestResult.html

- name: Push tag
id: tag
uses: laputansoft/[email protected]
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
tag: ${{ env.BUILD_VERSION }}

#- name: Comment pull request
# uses: machine-learning-apps/pr-comment@master
# if: ${{ github.event_name == 'pull_request' }}
# env:
# GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
# with:
# path: Build\_build\TestResult.html

- name: Comment pull request
uses: actions/[email protected]
if: github.event_name == 'pull_request'
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
const fs = require('fs');
const filename = "Build/_build/TestResult.html";
const contents = fs.readFileSync(filename, "utf8");
const { issue: { number: issue_number }, repo: { owner, repo } } = context;
github.issues.createComment({ issue_number, owner, repo, body: contents });
- name: Create release
id: create_release
uses: actions/create-release@v1
Expand Down
1 change: 0 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ obj/
_ReSharper*/
[Tt]est[Rr]esult*
packages
Snittlistan.Web/Web.Release.config
Snittlistan.Web/Snittlistan.Publish.xml
Snittlistan.Web/App_Data/Database
Tools/
Expand Down
14 changes: 14 additions & 0 deletions Snittlistan.Test/ApiControllers/Infrastructure/IdGenerator.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#nullable enable

namespace Snittlistan.Test.ApiControllers.Infrastructure
{
public class IdGenerator
{
private int _currentId;

public int GetNext()
{
return ++_currentId;
}
}
}
141 changes: 141 additions & 0 deletions Snittlistan.Test/ApiControllers/Infrastructure/InMemoryContext.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
#nullable enable

namespace Snittlistan.Test.ApiControllers.Infrastructure
{
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Data.Entity;
using System.Data.Entity.Infrastructure;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Threading.Tasks;
using Snittlistan.Web.Infrastructure.Database;

public sealed class InMemoryDbSet<T> : IDbSet<T>, IDbAsyncEnumerable<T> where T : class
{
private readonly IdGenerator _generator;
private readonly HashSet<T> _data;
private readonly IQueryable<T> _query;

public InMemoryDbSet(IdGenerator generator)
{
_generator = generator;
_data = new HashSet<T>();
_query = _data.AsQueryable();
}

public ObservableCollection<T> Local => new(_data);

public Type ElementType => _query.ElementType;

public Expression Expression => _query.Expression;

public IQueryProvider Provider => new InMemoryDbAsyncQueryProvider<T>(_query.Provider);

public IQueryable<T> AsQueryable()
{
return _query;
}

public T Add(T entity)
{
_ = _data.Add(entity);
Type type = typeof(T);
string idPropertyName = $"{type.Name}Id";
PropertyInfo propertyInfo = type.GetProperty(idPropertyName);
if (propertyInfo == null)
{
throw new Exception($"No {idPropertyName} property found on {type.Name} class");
}

propertyInfo.SetValue(entity, _generator.GetNext());

return entity;
}

public T Attach(T entity)
{
_ = _data.Add(entity);
return entity;
}

public TDerivedEntity Create<TDerivedEntity>() where TDerivedEntity : class, T
{
throw new NotImplementedException();
}

public T Create()
{
return Activator.CreateInstance<T>();
}

public T Find(params object[] keyValues)
{
throw new NotImplementedException("Derive from FakeDbSet and override Find");
}

public T Remove(T entity)
{
_ = _data.Remove(entity);
return entity;
}

public IEnumerator<T> GetEnumerator()
{
return _data.GetEnumerator();
}

IEnumerator IEnumerable.GetEnumerator()
{
return _data.GetEnumerator();
}

public IDbAsyncEnumerator<T> GetAsyncEnumerator()
{
return new InMemoryDbAsyncEnumerator<T>(GetEnumerator());
}

IDbAsyncEnumerator IDbAsyncEnumerable.GetAsyncEnumerator()
{
return GetAsyncEnumerator();
}
}

public class InMemoryContext : ISnittlistanContext, IBitsContext
{
public InMemoryContext()
{
IdGenerator generator = new();
DelayedTasks = new InMemoryDbSet<DelayedTask>(generator);
PublishedTasks = new InMemoryDbSet<PublishedTask>(generator);
Tenants = new InMemoryDbSet<Tenant>(generator);
Teams = new InMemoryDbSet<Bits_Team>(generator);
Hallar = new InMemoryDbSet<Bits_Hall>(generator);
}

public IDbSet<DelayedTask> DelayedTasks { get; }

public IDbSet<PublishedTask> PublishedTasks { get; }

public IDbSet<Bits_Team> Teams { get; }

public IDbSet<Bits_Hall> Hallar { get; }

public IDbSet<Tenant> Tenants { get; }

public DbChangeTracker ChangeTracker => throw new NotImplementedException();

public int SaveChanges()
{
throw new NotImplementedException();
}

public Task<int> SaveChangesAsync()
{
throw new NotImplementedException();
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
#nullable enable

namespace Snittlistan.Test.ApiControllers.Infrastructure
{
using System.Collections.Generic;
using System.Data.Entity.Infrastructure;
using System.Linq;
using System.Linq.Expressions;

public class InMemoryDbAsyncEnumerable<T> : EnumerableQuery<T>, IDbAsyncEnumerable<T>, IQueryable<T>
{
public InMemoryDbAsyncEnumerable(IEnumerable<T> enumerable)
: base(enumerable)
{ }

public InMemoryDbAsyncEnumerable(Expression expression)
: base(expression)
{ }

public IQueryProvider Provider => new InMemoryDbAsyncQueryProvider<T>(this);

public IDbAsyncEnumerator<T> GetAsyncEnumerator()
{
return new InMemoryDbAsyncEnumerator<T>(this.AsEnumerable().GetEnumerator());
}

IDbAsyncEnumerator IDbAsyncEnumerable.GetAsyncEnumerator()
{
return GetAsyncEnumerator();
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
#nullable enable

namespace Snittlistan.Test.ApiControllers.Infrastructure
{
using System.Collections.Generic;
using System.Data.Entity.Infrastructure;
using System.Threading;
using System.Threading.Tasks;

public class InMemoryDbAsyncEnumerator<T> : IDbAsyncEnumerator<T>
{
private readonly IEnumerator<T> _inner;

public InMemoryDbAsyncEnumerator(IEnumerator<T> inner)
{
_inner = inner;
}

public T Current => _inner.Current;

object? IDbAsyncEnumerator.Current => Current;

public void Dispose()
{
_inner.Dispose();
}

public Task<bool> MoveNextAsync(CancellationToken cancellationToken)
{
return Task.FromResult(_inner.MoveNext());
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
#nullable enable

namespace Snittlistan.Test.ApiControllers.Infrastructure
{
using System.Data.Entity.Infrastructure;
using System.Linq;
using System.Linq.Expressions;
using System.Threading;
using System.Threading.Tasks;

public class InMemoryDbAsyncQueryProvider<TEntity> : IDbAsyncQueryProvider
{
private readonly IQueryProvider _inner;

public InMemoryDbAsyncQueryProvider(IQueryProvider inner)
{
_inner = inner;
}

public IQueryable CreateQuery(Expression expression)
{
return new InMemoryDbAsyncEnumerable<TEntity>(expression);
}

public IQueryable<TElement> CreateQuery<TElement>(Expression expression)
{
return new InMemoryDbAsyncEnumerable<TElement>(expression);
}

public object Execute(Expression expression)
{
return _inner.Execute(expression);
}

public TResult Execute<TResult>(Expression expression)
{
return _inner.Execute<TResult>(expression);
}

public Task<object> ExecuteAsync(Expression expression, CancellationToken cancellationToken)
{
return Task.FromResult(Execute(expression));
}

public Task<TResult> ExecuteAsync<TResult>(Expression expression, CancellationToken cancellationToken)
{
return Task.FromResult(Execute<TResult>(expression));
}
}
}
13 changes: 10 additions & 3 deletions Snittlistan.Test/ApiControllers/WebApiIntegrationTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,33 +15,40 @@ namespace Snittlistan.Test.ApiControllers
using NUnit.Framework;
using Raven.Client;
using Snittlistan.Queue;
using Snittlistan.Test.ApiControllers.Infrastructure;
using Snittlistan.Web;
using Snittlistan.Web.Infrastructure.Attributes;
using Snittlistan.Web.Infrastructure.Database;
using Snittlistan.Web.Infrastructure.Installers;
using Snittlistan.Web.Infrastructure.IoC;

public abstract class WebApiIntegrationTest
{
protected HttpClient Client { get; private set; } = null!;

protected Databases Databases { get; private set; } = null!;

private IWindsorContainer Container { get; set; } = null!;

[SetUp]
public void SetUp()
public async Task SetUp()
{
HttpConfiguration configuration = new();
Container = new WindsorContainer();
InMemoryContext inMemoryContext = new();
_ = Container.Install(
new ControllerInstaller(),
new ApiControllerInstaller(),
new ControllerFactoryInstaller(),
new RavenInstaller(DocumentStoreMode.InMemory),
new TaskHandlerInstaller(),
new DatabaseContextInstaller(() => new(inMemoryContext, inMemoryContext)),
EventStoreInstaller.FromAssembly(typeof(MvcApplication).Assembly, DocumentStoreMode.InMemory),
new EventStoreSessionInstaller(LifestyleType.Scoped));
_ = Container.Register(Component.For<IMsmqTransaction>().Instance(Mock.Of<IMsmqTransaction>()));
Task.Run(async () => await OnSetUp(Container)).Wait();
await OnSetUp(Container);

MvcApplication.Bootstrap(Container, configuration);
MvcApplication.Bootstrap(Container, configuration, () => new(inMemoryContext, inMemoryContext));
Client = new HttpClient(new HttpServer(configuration));
OnlyLocalAllowedAttribute.SkipValidation = true;

Expand Down
5 changes: 5 additions & 0 deletions Snittlistan.Test/Snittlistan.Test.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,12 @@
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="ApiControllers\Infrastructure\IdGenerator.cs" />
<Compile Include="ApiControllers\Infrastructure\InMemoryContext.cs" />
<Compile Include="ApiControllers\Task_Post_RegisterMatch.cs" />
<Compile Include="ApiControllers\Infrastructure\InMemoryDbAsyncEnumerable.cs" />
<Compile Include="ApiControllers\Infrastructure\InMemoryDbAsyncEnumerator.cs" />
<Compile Include="ApiControllers\Infrastructure\InMemoryDbAsyncQueryProvider.cs" />
<Compile Include="ApiControllers\WebApiIntegrationTest.cs" />
<Compile Include="BitsClientTest.cs" />
<Compile Include="BitsGateway.cs" />
Expand Down
Loading

0 comments on commit 371a046

Please sign in to comment.