mirror of https://github.com/Squidex/squidex.git
48 changed files with 568 additions and 97 deletions
@ -0,0 +1,21 @@ |
|||
// ==========================================================================
|
|||
// MongoAppEntity.cs
|
|||
// PinkParrot Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) PinkParrot Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
using MongoDB.Bson.Serialization.Attributes; |
|||
using PinkParrot.Read.Apps; |
|||
using PinkParrot.Store.MongoDb.Utils; |
|||
|
|||
namespace PinkParrot.Store.MongoDb.Apps |
|||
{ |
|||
public sealed class MongoAppEntity : MongoEntity, IAppEntity |
|||
{ |
|||
[BsonRequired] |
|||
[BsonElement] |
|||
public string Name { get; set; } |
|||
} |
|||
} |
|||
@ -0,0 +1,57 @@ |
|||
// ==========================================================================
|
|||
// MongoAppRepository.cs
|
|||
// PinkParrot Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) PinkParrot Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
using System.Collections.Generic; |
|||
using System.Threading.Tasks; |
|||
using MongoDB.Bson; |
|||
using MongoDB.Driver; |
|||
using PinkParrot.Events.Apps; |
|||
using PinkParrot.Infrastructure.CQRS; |
|||
using PinkParrot.Infrastructure.CQRS.Events; |
|||
using PinkParrot.Infrastructure.Dispatching; |
|||
using PinkParrot.Infrastructure.Reflection; |
|||
using PinkParrot.Read.Apps; |
|||
using PinkParrot.Read.Apps.Repositories; |
|||
using PinkParrot.Store.MongoDb.Utils; |
|||
|
|||
namespace PinkParrot.Store.MongoDb.Apps |
|||
{ |
|||
public sealed class MongoAppRepository : MongoRepositoryBase<MongoAppEntity>, IAppRepository, ICatchEventConsumer |
|||
{ |
|||
public MongoAppRepository(IMongoDatabase database) |
|||
: base(database) |
|||
{ |
|||
} |
|||
|
|||
public async Task<IReadOnlyList<IAppEntity>> QueryAllAsync() |
|||
{ |
|||
var entities = |
|||
await Collection.Find(new BsonDocument()).ToListAsync(); |
|||
|
|||
return entities; |
|||
} |
|||
|
|||
public async Task<IAppEntity> FindAppByNameAsync(string name) |
|||
{ |
|||
var entity = |
|||
await Collection.Find(s => s.Name == name).FirstOrDefaultAsync(); |
|||
|
|||
return entity; |
|||
} |
|||
|
|||
public Task On(AppCreated @event, EnvelopeHeaders headers) |
|||
{ |
|||
return Collection.CreateAsync(headers, a => SimpleMapper.Map(a, @event)); |
|||
} |
|||
|
|||
public Task On(Envelope<IEvent> @event) |
|||
{ |
|||
return this.DispatchActionAsync(@event.Payload, @event.Headers); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,31 @@ |
|||
// ==========================================================================
|
|||
// MongoEntity.cs
|
|||
// PinkParrot Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) PinkParrot Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
using System; |
|||
using MongoDB.Bson; |
|||
using MongoDB.Bson.Serialization.Attributes; |
|||
using PinkParrot.Read; |
|||
|
|||
namespace PinkParrot.Store.MongoDb.Utils |
|||
{ |
|||
public abstract class MongoEntity : IEntity |
|||
{ |
|||
[BsonId] |
|||
[BsonElement] |
|||
[BsonRepresentation(BsonType.String)] |
|||
public Guid Id { get; set; } |
|||
|
|||
[BsonRequired] |
|||
[BsonElement] |
|||
public DateTime Created { get; set; } |
|||
|
|||
[BsonRequired] |
|||
[BsonElement] |
|||
public DateTime LastModified { get; set; } |
|||
} |
|||
} |
|||
@ -0,0 +1,35 @@ |
|||
// ==========================================================================
|
|||
// AppCommandHandler.cs
|
|||
// PinkParrot Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) PinkParrot Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
using System.Threading.Tasks; |
|||
using PinkParrot.Infrastructure.CQRS.Commands; |
|||
using PinkParrot.Infrastructure.Dispatching; |
|||
using PinkParrot.Write.Apps.Commands; |
|||
|
|||
namespace PinkParrot.Write.Apps |
|||
{ |
|||
public class AppCommandHandler : CommandHandler<AppDomainObject> |
|||
{ |
|||
public AppCommandHandler( |
|||
IDomainObjectFactory domainObjectFactory, |
|||
IDomainObjectRepository domainObjectRepository) |
|||
: base(domainObjectFactory, domainObjectRepository) |
|||
{ |
|||
} |
|||
|
|||
public Task On(CreateApp command) |
|||
{ |
|||
return CreateAsync(command, x => x.Create(command)); |
|||
} |
|||
|
|||
public override Task<bool> HandleAsync(CommandContext context) |
|||
{ |
|||
return context.IsHandled ? Task.FromResult(false) : this.DispatchActionAsync(context.Command); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,31 @@ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using System.Threading.Tasks; |
|||
using Microsoft.AspNetCore.Mvc; |
|||
using PinkParrot.Infrastructure.Reflection; |
|||
using PinkParrot.Modules.Api.Apps.Models; |
|||
using PinkParrot.Modules.Api.Schemas.Models; |
|||
using PinkParrot.Read.Apps.Repositories; |
|||
|
|||
namespace PinkParrot.Modules.Api.Apps |
|||
{ |
|||
public class AppController |
|||
{ |
|||
private readonly IAppRepository appRepository; |
|||
|
|||
public AppController(IAppRepository appRepository) |
|||
{ |
|||
this.appRepository = appRepository; |
|||
} |
|||
|
|||
[HttpGet] |
|||
[Route("api/schemas/")] |
|||
public async Task<List<ListAppDto>> Query() |
|||
{ |
|||
var schemas = await appRepository.QueryAllAsync(); |
|||
|
|||
return schemas.Select(s => SimpleMapper.Map(s, new ListAppDto())).ToList(); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,23 @@ |
|||
// ==========================================================================
|
|||
// ListAppDto.cs
|
|||
// PinkParrot Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) PinkParrot Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
using System; |
|||
|
|||
namespace PinkParrot.Modules.Api.Apps.Models |
|||
{ |
|||
public sealed class ListAppDto |
|||
{ |
|||
public Guid Id { get; set; } |
|||
|
|||
public string Name { get; set; } |
|||
|
|||
public DateTime Created { get; set; } |
|||
|
|||
public DateTime LastModified { get; set; } |
|||
} |
|||
} |
|||
@ -0,0 +1,42 @@ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using System.Threading.Tasks; |
|||
using Autofac; |
|||
using PinkParrot.Infrastructure.CQRS.Events; |
|||
using Xunit; |
|||
|
|||
namespace PinkParrot.Infrastructure.CQRS.Autofac |
|||
{ |
|||
public class AutofacDomainObjectFactoryTests |
|||
{ |
|||
private sealed class DO : DomainObject |
|||
{ |
|||
public DO(Guid id, int version) : base(id, version) |
|||
{ |
|||
} |
|||
|
|||
protected override void DispatchEvent(Envelope<IEvent> @event) |
|||
{ |
|||
} |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_create_domain_object_with_autofac() |
|||
{ |
|||
var containerBuilder = new ContainerBuilder(); |
|||
|
|||
containerBuilder.RegisterType<DO>() |
|||
.AsSelf(); |
|||
|
|||
var factory = new AutofacDomainObjectFactory(containerBuilder.Build()); |
|||
|
|||
var id = Guid.NewGuid(); |
|||
|
|||
var domainObject = factory.CreateNew(typeof(DO), id); |
|||
|
|||
Assert.Equal(id, domainObject.Id); |
|||
Assert.Equal(0, domainObject.Version); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,106 @@ |
|||
// ==========================================================================
|
|||
// SchemaDomainObjectTest.cs
|
|||
// PinkParrot Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) PinkParrot Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
using System; |
|||
using System.Linq; |
|||
using FluentAssertions; |
|||
using PinkParrot.Core.Schemas; |
|||
using PinkParrot.Events.Schemas; |
|||
using PinkParrot.Infrastructure; |
|||
using PinkParrot.Write.Schemas; |
|||
using PinkParrot.Write.Schemas.Commands; |
|||
using Xunit; |
|||
|
|||
namespace PinkParrot.Write.Tests.Schemas |
|||
{ |
|||
[Collection("Schema")] |
|||
public class SchemaDomainObjectTest |
|||
{ |
|||
private const string TestName = "schema"; |
|||
private readonly Guid appId = Guid.NewGuid(); |
|||
private readonly FieldRegistry registry = new FieldRegistry(); |
|||
private readonly SchemaDomainObject sut; |
|||
|
|||
public SchemaDomainObjectTest() |
|||
{ |
|||
sut = new SchemaDomainObject(Guid.NewGuid(), 0, registry); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Create_should_throw_if_created() |
|||
{ |
|||
sut.Create(new CreateSchema { Name = TestName }); |
|||
|
|||
Assert.Throws<DomainException>(() => sut.Create(new CreateSchema { Name = TestName })); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Create_should_throw_if_command_is_invalid() |
|||
{ |
|||
Assert.Throws<ValidationException>(() => sut.Create(new CreateSchema())); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Create_should_create_schema() |
|||
{ |
|||
var props = new SchemaProperties(null, null); |
|||
|
|||
sut.Create(new CreateSchema { Name = TestName, AppId = appId, Properties = props }); |
|||
|
|||
Assert.Equal("schema", sut.Schema.Name); |
|||
Assert.Equal(props, sut.Schema.Properties); |
|||
Assert.Equal(appId, sut.AppId); |
|||
|
|||
sut.GetUncomittedEvents() |
|||
.Select(x => x.Payload as SchemaCreated) |
|||
.Single() |
|||
.ShouldBeEquivalentTo( |
|||
new SchemaCreated { Name = TestName, AppId = appId, Properties = props }); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Update_should_throw_if_not_created() |
|||
{ |
|||
Assert.Throws<DomainException>(() => sut.Update(new UpdateSchema { Properties = new SchemaProperties(null, null) })); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Update_should_throw_if_command_is_deleted() |
|||
{ |
|||
sut.Create(new CreateSchema { Name = TestName }); |
|||
sut.Delete(); |
|||
|
|||
Assert.Throws<ValidationException>(() => sut.Update(new UpdateSchema())); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Update_should_throw_if_command_is_invalid() |
|||
{ |
|||
sut.Create(new CreateSchema { Name = TestName }); |
|||
|
|||
Assert.Throws<ValidationException>(() => sut.Update(new UpdateSchema())); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Update_should_refresh_properties() |
|||
{ |
|||
var props = new SchemaProperties(null, null); |
|||
|
|||
sut.Create(new CreateSchema { Name = TestName, AppId = appId }); |
|||
sut.Update(new UpdateSchema { Properties = props }); |
|||
|
|||
Assert.Equal(props, sut.Schema.Properties); |
|||
|
|||
sut.GetUncomittedEvents() |
|||
.Select(x => x.Payload as SchemaUpdated) |
|||
.Last() |
|||
.ShouldBeEquivalentTo( |
|||
new SchemaUpdated { Properties = props }); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,28 @@ |
|||
// ==========================================================================
|
|||
// SchemaFixture.cs
|
|||
// PinkParrot Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) PinkParrot Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
using PinkParrot.Core.Schemas; |
|||
using PinkParrot.Infrastructure; |
|||
using System.Reflection; |
|||
using Xunit; |
|||
|
|||
namespace PinkParrot.Write.Tests.Utils |
|||
{ |
|||
public class SchemaFixture |
|||
{ |
|||
public SchemaFixture() |
|||
{ |
|||
TypeNameRegistry.Map(typeof(Schema).GetTypeInfo().Assembly); |
|||
} |
|||
} |
|||
|
|||
[CollectionDefinition("Schema")] |
|||
public class DatabaseCollection : ICollectionFixture<SchemaFixture> |
|||
{ |
|||
} |
|||
} |
|||
Loading…
Reference in new issue