using EphemeralMongo;
using Microsoft.Extensions.Logging.Abstractions;
using MongoDB.Driver;
using Notesnook.API.Accessors;
using Notesnook.API.Models;
using Notesnook.API.Services;
using Streetwriters.Data;
using Streetwriters.Data.DbContexts;
using Streetwriters.Data.Repositories;
namespace Notesnook.API.Tests;
///
/// A throwaway database on an ephemeral single-node MongoDB replica set
/// (transactions don't work on a standalone server).
///
public sealed class TestDatabase : IAsyncLifetime
{
// one mongod for the whole test run, stopped when the test process exits
private static readonly Lazy Runner = new(() =>
{
var runner = MongoRunner.Run(new MongoRunnerOptions
{
UseSingleNodeReplicaSet = true,
Version = MongoVersion.V8
});
AppDomain.CurrentDomain.ProcessExit += (_, _) => runner.Dispose();
return runner;
});
public IMongoClient Client { get; }
public string Name { get; } = "notesnook_test_" + Guid.NewGuid().ToString("N");
public TestDatabase()
{
Client = MongoDbContext.CreateMongoDbClient(new TestDbSettings { ConnectionString = Runner.Value.ConnectionString });
}
public IMongoCollection Collection(string name) => MongoDbContext.GetMongoCollection(Client, Name, name);
///
/// The services of a single request scope, wired the same way as in Startup.
///
public Scope CreateScope() => new(this);
public async Task InitializeAsync()
{
// collections can't be created implicitly inside a transaction on older servers
foreach (var name in new[] { Collections.NotesKey, Collections.SyncDevicesKey, Collections.DeviceIdsChunksKey })
await Client.GetDatabase(Name).CreateCollectionAsync(name);
}
public Task DisposeAsync() => Client.DropDatabaseAsync(Name);
public sealed class Scope
{
public MongoDbContext DbContext { get; }
public UnitOfWork Unit { get; }
public SyncItemsRepositoryAccessor Repositories { get; }
public SyncDeviceService Devices { get; }
public Scope(TestDatabase db)
{
DbContext = new MongoDbContext(db.Client);
Unit = new UnitOfWork(DbContext);
IMongoCollection items(string name) => db.Collection(name);
Repositories = new SyncItemsRepositoryAccessor(DbContext,
items(Collections.NotebooksKey), items(Collections.NotesKey), items(Collections.ContentKey),
items(Collections.SettingsKey), items(Collections.LegacySettingsKey), items(Collections.AttachmentsKey),
items(Collections.ShortcutsKey), items(Collections.RemindersKey), items(Collections.RelationsKey),
items(Collections.ColorsKey), items(Collections.VaultsKey), items(Collections.TagsKey),
items(Collections.InboxItemsHistoryKey),
new Repository(DbContext, db.Collection("user_settings")),
new Repository(DbContext, db.Collection("monographs")),
new Repository(DbContext, db.Collection(Collections.InboxApiKeysKey)),
new Repository(DbContext, db.Collection(Collections.InboxItemsKey)),
new Repository(DbContext, db.Collection(Collections.SyncDevicesKey)),
new Repository(DbContext, db.Collection(Collections.DeviceIdsChunksKey)),
NullLogger.Instance);
Devices = new SyncDeviceService(Repositories, DbContext, NullLogger.Instance);
}
}
private sealed class TestDbSettings : Streetwriters.Data.Interfaces.IDbSettings
{
public string DatabaseName { get; set; } = "";
public string ConnectionString { get; set; } = "";
}
}