text: ﻿// ==========================================================================
  //  Squidex Headless CMS
  // ==========================================================================
  //  Copyright (c) Squidex UG (haftungsbeschraenkt)
  //  All rights reserved. Licensed under the MIT license.
  // ==========================================================================
  
  using System.Collections.Generic;
  using System.Linq;
  using System.Threading.Tasks;
  using FakeItEasy;
  using Squidex.Domain.Apps.Core;
  using Squidex.Domain.Apps.Core.Contents;
  using Squidex.Domain.Apps.Core.Schemas;
  using Squidex.Domain.Apps.Entities.Assets.Repositories;
  using Squidex.Domain.Apps.Entities.Contents.Queries.Steps;
  using Squidex.Domain.Apps.Entities.Contents.Repositories;
  using Squidex.Domain.Apps.Entities.Schemas;
  using Squidex.Domain.Apps.Entities.TestHelpers;
  using Squidex.Infrastructure;
  using Squidex.Infrastructure.Json.Objects;
  using Xunit;
  
  namespace Squidex.Domain.Apps.Entities.Contents.Queries
  {
      public class ConvertDataTests
      {
          private readonly ISchemaEntity schema;
          private readonly IUrlGenerator urlGenerator = A.Fake<IUrlGenerator>();
          private readonly IAssetRepository assetRepository = A.Fake<IAssetRepository>();
          private readonly IContentRepository contentRepository = A.Fake<IContentRepository>();
          private readonly NamedId<DomainId> appId = NamedId.Of(DomainId.NewGuid(), "my-app");
          private readonly NamedId<DomainId> schemaId = NamedId.Of(DomainId.NewGuid(), "my-schema");
          private readonly ProvideSchema schemaProvider;
          private readonly ConvertData sut;
  
          public ConvertDataTests()
          {
              var schemaDef =
                  new Schema("my-schema")
                      .AddReferences(1, "references", Partitioning.Invariant)
                      .AddAssets(2, "assets", Partitioning.Invariant)
                      .AddArray(3, "array", Partitioning.Invariant, a => a
                          .AddAssets(31, "nested"));
  
              schema = Mocks.Schema(appId, schemaId, schemaDef);
              schemaProvider = x => Task.FromResult(schema);
  
              sut = new ConvertData(urlGenerator, assetRepository, contentRepository);
          }
  
          [Fact]
          public async Task Should_convert_data_and_data_draft_when_frontend_user()
          {
              var content = CreateContent(new NamedContentData());
  
              var ctx = new Context(Mocks.FrontendUser(), Mocks.App(appId));
  
              await sut.EnrichAsync(ctx, Enumerable.Repeat(content, 1), schemaProvider);
  
              Assert.NotNull(content.Data);
          }
  
          [Fact]
          public async Task Should_cleanup_references()
          {
              var id1 = DomainId.NewGuid();
              var id2 = DomainId.NewGuid();
  
              var source = BuildTestData(id1, id2);
  
              var content = CreateContent(source);
  
              var expected =
                  new NamedContentData()
                      .AddField("references",
                          new ContentFieldData()
                              .AddJsonValue(JsonValue.Array(id2)))
                      .AddField("assets",
                          new ContentFieldData()
                              .AddJsonValue(JsonValue.Array()))
                      .AddField("array",
                          new ContentFieldData()
                              .AddJsonValue(
                                  JsonValue.Array(
                                      JsonValue.Object()
                                          .Add("nested", JsonValue.Array(id2)))));
  
              A.CallTo(() => assetRepository.QueryIdsAsync(appId.Id, A<HashSet<DomainId>>.That.Is(id1, id2)))
                  .Returns(new List<DomainId> { id2 });
  
              A.CallTo(() => contentRepository.QueryIdsAsync(appId.Id, A<HashSet<DomainId>>.That.Is(id1, id2), SearchScope.All))
                  .Returns(new List<(DomainId, DomainId)> { (id2, id2) });
  
              var ctx = new Context(Mocks.FrontendUser(), Mocks.App(appId));
  
              await sut.EnrichAsync(ctx, Enumerable.Repeat(content, 1), schemaProvider);
  
              Assert.Equal(expected, content.Data);
          }
  
          [Fact]
          public async Task Should_cleanup_references_when_everything_deleted()
          {
              var id1 = DomainId.NewGuid();
              var id2 = DomainId.NewGuid();
  
              var source = BuildTestData(id1, id2);
  
              var content = CreateContent(source);
  
              var expected =
                  new NamedContentData()
                      .AddField("references",
                          new ContentFieldData()
                              .AddJsonValue(JsonValue.Array()))
                      .AddField("assets",
                          new ContentFieldData()
                              .AddJsonValue(JsonValue.Array()))
                      .AddField("array",
                          new ContentFieldData()
                              .AddJsonValue(
                                  JsonValue.Array(
                                      JsonValue.Object()
                                          .Add("nested", JsonValue.Array()))));
  
              A.CallTo(() => assetRepository.QueryIdsAsync(appId.Id, A<HashSet<DomainId>>.That.Is(id1, id2)))
                  .Returns(new List<DomainId>());
  
              A.CallTo(() => contentRepository.QueryIdsAsync(appId.Id, A<HashSet<DomainId>>.That.Is(id1, id2), SearchScope.All))
                  .Returns(new List<(DomainId, DomainId)>());
  
              var ctx = new Context(Mocks.FrontendUser(), Mocks.App(appId));
  
              await sut.EnrichAsync(ctx, Enumerable.Repeat(content, 1), schemaProvider);
  
              Assert.Equal(expected, content.Data);
          }
  
          private static NamedContentData BuildTestData(DomainId id1, DomainId id2)
          {
              return new NamedContentData()
                  .AddField("references",
                      new ContentFieldData()
                          .AddJsonValue(JsonValue.Array(id1, id2)))
                  .AddField("assets",
                      new ContentFieldData()
                          .AddJsonValue(JsonValue.Array(id1)))
                  .AddField("array",
                      new ContentFieldData()
                          .AddJsonValue(
                              JsonValue.Array(
                                  JsonValue.Object()
                                      .Add("nested", JsonValue.Array(id1, id2)))));
          }
  
          private ContentEntity CreateContent(NamedContentData data)
          {
              return new ContentEntity
              {
                  Data = data,
                  SchemaId = schemaId,
                  Status = Status.Published
              };
          }
      }
  }
  