mirror of https://github.com/Squidex/squidex.git
committed by
GitHub
40 changed files with 641 additions and 297 deletions
@ -0,0 +1,42 @@ |
|||
// ==========================================================================
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex UG (haftungsbeschränkt)
|
|||
// All rights reserved. Licensed under the MIT license.
|
|||
// ==========================================================================
|
|||
|
|||
using Newtonsoft.Json; |
|||
using Squidex.Infrastructure.Json.Newtonsoft; |
|||
using System; |
|||
using System.Collections.Generic; |
|||
|
|||
namespace Squidex.Domain.Apps.Core.Contents.Json |
|||
{ |
|||
public sealed class StatusConverter : JsonConverter, ISupportedTypes |
|||
{ |
|||
public IEnumerable<Type> SupportedTypes |
|||
{ |
|||
get { yield return typeof(Status); } |
|||
} |
|||
|
|||
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) |
|||
{ |
|||
writer.WriteValue(value.ToString()); |
|||
} |
|||
|
|||
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) |
|||
{ |
|||
if (reader.TokenType != JsonToken.String) |
|||
{ |
|||
throw new JsonException($"Expected String, but got {reader.TokenType}."); |
|||
} |
|||
|
|||
return new Status(reader.Value.ToString()); |
|||
} |
|||
|
|||
public override bool CanConvert(Type objectType) |
|||
{ |
|||
return objectType == typeof(Status); |
|||
} |
|||
} |
|||
} |
|||
@ -1,46 +0,0 @@ |
|||
// ==========================================================================
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex UG (haftungsbeschränkt)
|
|||
// All rights reserved. Licensed under the MIT license.
|
|||
// ==========================================================================
|
|||
|
|||
using Squidex.Infrastructure; |
|||
using System; |
|||
|
|||
namespace Squidex.Domain.Apps.Core.Contents |
|||
{ |
|||
public struct Status2 : IEquatable<Status2> |
|||
{ |
|||
public static readonly Status2 Published = new Status2("Published"); |
|||
|
|||
public string Name { get; } |
|||
|
|||
public Status2(string name) |
|||
{ |
|||
Guard.NotNullOrEmpty(name, nameof(name)); |
|||
|
|||
Name = name; |
|||
} |
|||
|
|||
public override bool Equals(object obj) |
|||
{ |
|||
return obj is Status2 status && Equals(status); |
|||
} |
|||
|
|||
public bool Equals(Status2 other) |
|||
{ |
|||
return Name.Equals(other.Name); |
|||
} |
|||
|
|||
public override int GetHashCode() |
|||
{ |
|||
return base.GetHashCode(); |
|||
} |
|||
|
|||
public override string ToString() |
|||
{ |
|||
return Name; |
|||
} |
|||
} |
|||
} |
|||
@ -1,37 +0,0 @@ |
|||
// ==========================================================================
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex UG (haftungsbeschränkt)
|
|||
// All rights reserved. Licensed under the MIT license.
|
|||
// ==========================================================================
|
|||
|
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
|
|||
namespace Squidex.Domain.Apps.Core.Contents |
|||
{ |
|||
public static class StatusFlow |
|||
{ |
|||
private static readonly Dictionary<Status, Status[]> Flow = new Dictionary<Status, Status[]> |
|||
{ |
|||
[Status.Draft] = new[] { Status.Published, Status.Archived }, |
|||
[Status.Archived] = new[] { Status.Draft }, |
|||
[Status.Published] = new[] { Status.Draft, Status.Archived } |
|||
}; |
|||
|
|||
public static bool Exists(Status status) |
|||
{ |
|||
return Flow.ContainsKey(status); |
|||
} |
|||
|
|||
public static bool CanChange(Status status, Status toStatus) |
|||
{ |
|||
return Flow.TryGetValue(status, out var state) && state.Contains(toStatus); |
|||
} |
|||
|
|||
public static IEnumerable<Status> Next(Status status) |
|||
{ |
|||
return Flow.TryGetValue(status, out var result) ? result : Enumerable.Empty<Status>(); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,54 @@ |
|||
// ==========================================================================
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex UG (haftungsbeschränkt)
|
|||
// All rights reserved. Licensed under the MIT license.
|
|||
// ==========================================================================
|
|||
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using System.Threading.Tasks; |
|||
using Squidex.Domain.Apps.Core.Contents; |
|||
using Squidex.Domain.Apps.Entities.Schemas; |
|||
using Squidex.Infrastructure.Tasks; |
|||
|
|||
namespace Squidex.Domain.Apps.Entities.Contents |
|||
{ |
|||
public sealed class DefaultContentWorkflow : IContentWorkflow |
|||
{ |
|||
private static readonly Status[] All = { Status.Archived, Status.Draft, Status.Published }; |
|||
|
|||
private static readonly Dictionary<Status, Status[]> Flow = new Dictionary<Status, Status[]> |
|||
{ |
|||
[Status.Draft] = new[] { Status.Archived, Status.Published }, |
|||
[Status.Archived] = new[] { Status.Draft }, |
|||
[Status.Published] = new[] { Status.Draft, Status.Archived } |
|||
}; |
|||
|
|||
public Task<Status> GetInitialStatusAsync(ISchemaEntity schema) |
|||
{ |
|||
return Task.FromResult(Status.Draft); |
|||
} |
|||
|
|||
public Task<bool> CanMoveToAsync(IContentEntity content, Status next) |
|||
{ |
|||
return Task.FromResult(Flow.TryGetValue(content.Status, out var state) && state.Contains(next)); |
|||
} |
|||
|
|||
public Task<bool> CanUpdateAsync(IContentEntity content) |
|||
{ |
|||
return Task.FromResult(content.Status != Status.Archived); |
|||
} |
|||
|
|||
public Task<Status[]> GetNextsAsync(IContentEntity content) |
|||
{ |
|||
return Task.FromResult(Flow.TryGetValue(content.Status, out var result) ? result : Array.Empty<Status>()); |
|||
} |
|||
|
|||
public Task<Status[]> GetAllAsync(ISchemaEntity schema) |
|||
{ |
|||
return Task.FromResult(All); |
|||
} |
|||
} |
|||
} |
|||
@ -1,34 +0,0 @@ |
|||
// ==========================================================================
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex UG (haftungsbeschränkt)
|
|||
// All rights reserved. Licensed under the MIT license.
|
|||
// ==========================================================================
|
|||
|
|||
using Squidex.Domain.Apps.Core.Contents; |
|||
using Xunit; |
|||
|
|||
namespace Squidex.Domain.Apps.Core.Model.Contents |
|||
{ |
|||
public class StatusFlowTests |
|||
{ |
|||
[Fact] |
|||
public void Should_make_tests() |
|||
{ |
|||
Assert.True(StatusFlow.Exists(Status.Draft)); |
|||
Assert.True(StatusFlow.Exists(Status.Archived)); |
|||
Assert.True(StatusFlow.Exists(Status.Published)); |
|||
|
|||
Assert.True(StatusFlow.CanChange(Status.Draft, Status.Archived)); |
|||
Assert.True(StatusFlow.CanChange(Status.Draft, Status.Published)); |
|||
|
|||
Assert.True(StatusFlow.CanChange(Status.Published, Status.Draft)); |
|||
Assert.True(StatusFlow.CanChange(Status.Published, Status.Archived)); |
|||
|
|||
Assert.True(StatusFlow.CanChange(Status.Archived, Status.Draft)); |
|||
|
|||
Assert.False(StatusFlow.Exists((Status)int.MaxValue)); |
|||
Assert.False(StatusFlow.CanChange(Status.Archived, Status.Published)); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,84 @@ |
|||
// ==========================================================================
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex UG (haftungsbeschraenkt)
|
|||
// All rights reserved. Licensed under the MIT license.
|
|||
// ==========================================================================
|
|||
|
|||
using Squidex.Domain.Apps.Core.Contents; |
|||
using Xunit; |
|||
|
|||
namespace Squidex.Domain.Apps.Core.Model.Contents |
|||
{ |
|||
public class StatusTests |
|||
{ |
|||
[Fact] |
|||
public void Should_initialize_status_from_string() |
|||
{ |
|||
var result = new Status("Custom"); |
|||
|
|||
Assert.Equal("Custom", result.Name); |
|||
Assert.Equal("Custom", result.ToString()); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_provide_draft_status() |
|||
{ |
|||
var result = Status.Draft; |
|||
|
|||
Assert.Equal("Draft", result.Name); |
|||
Assert.Equal("Draft", result.ToString()); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_provide_archived_status() |
|||
{ |
|||
var result = Status.Archived; |
|||
|
|||
Assert.Equal("Archived", result.Name); |
|||
Assert.Equal("Archived", result.ToString()); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_provide_published_status() |
|||
{ |
|||
var result = Status.Published; |
|||
|
|||
Assert.Equal("Published", result.Name); |
|||
Assert.Equal("Published", result.ToString()); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_make_correct_equal_comparisons() |
|||
{ |
|||
var status_1_a = Status.Draft; |
|||
var status_1_b = Status.Draft; |
|||
|
|||
var status2_a = Status.Published; |
|||
|
|||
Assert.Equal(status_1_a, status_1_b); |
|||
Assert.Equal(status_1_a.GetHashCode(), status_1_b.GetHashCode()); |
|||
Assert.True(status_1_a.Equals((object)status_1_b)); |
|||
|
|||
Assert.NotEqual(status_1_a, status2_a); |
|||
Assert.NotEqual(status_1_a.GetHashCode(), status2_a.GetHashCode()); |
|||
Assert.False(status_1_a.Equals((object)status2_a)); |
|||
|
|||
Assert.True(status_1_a == status_1_b); |
|||
Assert.True(status_1_a != status2_a); |
|||
|
|||
Assert.False(status_1_a != status_1_b); |
|||
Assert.False(status_1_a == status2_a); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_serialize_and_deserialize() |
|||
{ |
|||
var status = Status.Draft; |
|||
|
|||
var serialized = status.SerializeAndDeserialize(); |
|||
|
|||
Assert.Equal(status, serialized); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,122 @@ |
|||
// ==========================================================================
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex UG (haftungsbeschränkt)
|
|||
// All rights reserved. Licensed under the MIT license.
|
|||
// ==========================================================================
|
|||
|
|||
using System.Threading.Tasks; |
|||
using FakeItEasy; |
|||
using Squidex.Domain.Apps.Core.Contents; |
|||
using Xunit; |
|||
|
|||
namespace Squidex.Domain.Apps.Entities.Contents |
|||
{ |
|||
public class DefaultContentWorkflowTests |
|||
{ |
|||
private readonly DefaultContentWorkflow sut = new DefaultContentWorkflow(); |
|||
|
|||
[Fact] |
|||
public async Task Should_draft_as_initial_status() |
|||
{ |
|||
var result = await sut.GetInitialStatusAsync(null); |
|||
|
|||
Assert.Equal(Status.Draft, result); |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task Should_check_is_valid_next() |
|||
{ |
|||
var entity = CreateContent(Status.Published); |
|||
|
|||
var result = await sut.CanMoveToAsync(entity, Status.Draft); |
|||
|
|||
Assert.True(result); |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task Should_be_able_to_update_published() |
|||
{ |
|||
var entity = CreateContent(Status.Published); |
|||
|
|||
var result = await sut.CanUpdateAsync(entity); |
|||
|
|||
Assert.True(result); |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task Should_be_able_to_update_draft() |
|||
{ |
|||
var entity = CreateContent(Status.Published); |
|||
|
|||
var result = await sut.CanUpdateAsync(entity); |
|||
|
|||
Assert.True(result); |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task Should_not_be_able_to_update_archived() |
|||
{ |
|||
var entity = CreateContent(Status.Archived); |
|||
|
|||
var result = await sut.CanUpdateAsync(entity); |
|||
|
|||
Assert.False(result); |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task Should_get_next_statuses_for_draft() |
|||
{ |
|||
var content = CreateContent(Status.Draft); |
|||
|
|||
var expected = new[] { Status.Archived, Status.Published }; |
|||
|
|||
var result = await sut.GetNextsAsync(content); |
|||
|
|||
Assert.Equal(expected, result); |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task Should_get_next_statuses_for_archived() |
|||
{ |
|||
var content = CreateContent(Status.Archived); |
|||
|
|||
var expected = new[] { Status.Draft }; |
|||
|
|||
var result = await sut.GetNextsAsync(content); |
|||
|
|||
Assert.Equal(expected, result); |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task Should_get_next_statuses_for_published() |
|||
{ |
|||
var content = CreateContent(Status.Published); |
|||
|
|||
var expected = new[] { Status.Draft, Status.Archived }; |
|||
|
|||
var result = await sut.GetNextsAsync(content); |
|||
|
|||
Assert.Equal(expected, result); |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task Should_return_all_statuses() |
|||
{ |
|||
var expected = new[] { Status.Archived, Status.Draft, Status.Published }; |
|||
|
|||
var result = await sut.GetAllAsync(null); |
|||
|
|||
Assert.Equal(expected, result); |
|||
} |
|||
|
|||
private IContentEntity CreateContent(Status status) |
|||
{ |
|||
var content = A.Fake<IContentEntity>(); |
|||
|
|||
A.CallTo(() => content.Status).Returns(status); |
|||
|
|||
return content; |
|||
} |
|||
} |
|||
} |
|||
Loading…
Reference in new issue