Headless CMS and Content Managment Hub
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

263 lines
8.6 KiB

// ==========================================================================
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex UG (haftungsbeschraenkt)
// All rights reserved. Licensed under the MIT license.
// ==========================================================================
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Squidex.Domain.Apps.Core.Contents;
using Squidex.Infrastructure.Assets;
using Squidex.Infrastructure.Validation;
using Xunit;
namespace Squidex.Domain.Apps.Entities.Contents.Text
{
public class TextIndexerGrainTests : IDisposable
{
private readonly Guid schemaId = Guid.NewGuid();
private readonly List<Guid> ids1 = new List<Guid> { Guid.NewGuid() };
private readonly List<Guid> ids2 = new List<Guid> { Guid.NewGuid() };
private readonly SearchContext context;
private readonly IAssetStore assetStore = new MemoryAssetStore();
private readonly TextIndexerGrain sut;
public TextIndexerGrainTests()
{
context = new SearchContext
{
Languages = new HashSet<string> { "de", "en" }
};
sut = new TextIndexerGrain(assetStore);
sut.ActivateAsync(schemaId).Wait();
}
public void Dispose()
{
sut.OnDeactivateAsync().Wait();
}
[Fact]
public async Task Should_throw_exception_for_invalid_query()
{
await Assert.ThrowsAsync<ValidationException>(() => sut.SearchAsync("~hello", context));
}
[Fact]
public async Task Should_read_index_and_retrieve()
{
await AddInvariantContent("Hello", "World", false);
await sut.DeactivateAsync(true);
var other = new TextIndexerGrain(assetStore);
try
{
await other.ActivateAsync(schemaId);
await TestSearchAsync(ids1, "Hello", grain: other);
await TestSearchAsync(ids2, "World", grain: other);
}
finally
{
await other.OnDeactivateAsync();
}
}
[Fact]
public async Task Should_index_invariant_content_and_retrieve()
{
await AddInvariantContent("Hello", "World", false);
await TestSearchAsync(ids1, "Hello");
await TestSearchAsync(ids2, "World");
}
[Fact]
public async Task Should_index_invariant_content_and_retrieve_with_fuzzy()
{
await AddInvariantContent("Hello", "World", false);
await TestSearchAsync(ids1, "helo~");
await TestSearchAsync(ids2, "wold~");
}
[Fact]
public async Task Should_update_draft_only()
{
await AddInvariantContent("Hello", "World", false);
await AddInvariantContent("Hallo", "Welt", false);
await TestSearchAsync(null, "Hello", Scope.Draft);
await TestSearchAsync(null, "Hello", Scope.Published);
await TestSearchAsync(ids1, "Hallo", Scope.Draft);
await TestSearchAsync(null, "Hallo", Scope.Published);
}
[Fact]
public async Task Should_also_update_published_after_copy()
{
await AddInvariantContent("Hello", "World", false);
await CopyAsync(true);
await AddInvariantContent("Hallo", "Welt", false);
await TestSearchAsync(null, "Hello", Scope.Draft);
await TestSearchAsync(null, "Hello", Scope.Published);
await TestSearchAsync(ids1, "Hallo", Scope.Draft);
await TestSearchAsync(ids1, "Hallo", Scope.Published);
}
[Fact]
public async Task Should_simulate_content_reversion()
{
await AddInvariantContent("Hello", "World", false);
await CopyAsync(true);
await AddInvariantContent("Hallo", "Welt", true);
await TestSearchAsync(null, "Hello", Scope.Draft);
await TestSearchAsync(ids1, "Hello", Scope.Published);
await TestSearchAsync(ids1, "Hallo", Scope.Draft);
await TestSearchAsync(null, "Hallo", Scope.Published);
await CopyAsync(false);
await TestSearchAsync(ids1, "Hello", Scope.Draft);
await TestSearchAsync(ids1, "Hello", Scope.Published);
await TestSearchAsync(null, "Hallo", Scope.Draft);
await TestSearchAsync(null, "Hallo", Scope.Published);
await AddInvariantContent("Guten Morgen", "Welt", true);
await TestSearchAsync(null, "Hello", Scope.Draft);
await TestSearchAsync(ids1, "Hello", Scope.Published);
await TestSearchAsync(ids1, "Guten Morgen", Scope.Draft);
await TestSearchAsync(null, "Guten Morgen", Scope.Published);
}
[Fact]
public async Task Should_also_retrieve_published_content_after_copy()
{
await AddInvariantContent("Hello", "World", false);
await TestSearchAsync(ids1, "Hello", Scope.Draft);
await TestSearchAsync(null, "Hello", Scope.Published);
await CopyAsync(true);
await TestSearchAsync(ids1, "Hello", Scope.Draft);
await TestSearchAsync(ids1, "Hello", Scope.Published);
}
[Fact]
public async Task Should_delete_documents_from_index()
{
await AddInvariantContent("Hello", "World", false);
await TestSearchAsync(ids1, "Hello");
await TestSearchAsync(ids2, "World");
await DeleteAsync(ids1[0]);
await TestSearchAsync(null, "Hello");
await TestSearchAsync(ids2, "World");
}
[Fact]
public async Task Should_search_by_field()
{
await AddLocalizedContent();
await TestSearchAsync(null, "de:city");
await TestSearchAsync(null, "en:Stadt");
}
[Fact]
public async Task Should_index_localized_content_and_retrieve()
{
await AddLocalizedContent();
await TestSearchAsync(ids1, "Stadt");
await TestSearchAsync(ids1, "and");
await TestSearchAsync(ids2, "und");
await TestSearchAsync(ids2, "City");
await TestSearchAsync(ids2, "und");
await TestSearchAsync(ids1, "and");
}
private async Task AddLocalizedContent()
{
var germanData =
new NamedContentData()
.AddField("localized",
new ContentFieldData()
.AddValue("de", "Stadt und Umgebung and whatever"));
var englishData =
new NamedContentData()
.AddField("localized",
new ContentFieldData()
.AddValue("en", "City and Surroundings und sonstiges"));
await sut.IndexAsync(new Update { Id = ids1[0], Data = germanData, OnlyDraft = true });
await sut.IndexAsync(new Update { Id = ids2[0], Data = englishData, OnlyDraft = true });
}
private async Task AddInvariantContent(string text1, string text2, bool onlyDraft = false)
{
var data1 =
new NamedContentData()
.AddField("test",
new ContentFieldData()
.AddValue("iv", text1));
var data2 =
new NamedContentData()
.AddField("test",
new ContentFieldData()
.AddValue("iv", text2));
await sut.IndexAsync(new Update { Id = ids1[0], Data = data1, OnlyDraft = onlyDraft });
await sut.IndexAsync(new Update { Id = ids2[0], Data = data2, OnlyDraft = onlyDraft });
}
private async Task DeleteAsync(Guid id)
{
await sut.DeleteAsync(id);
}
private async Task CopyAsync(bool fromDraft)
{
await sut.CopyAsync(ids1[0], fromDraft);
await sut.CopyAsync(ids2[0], fromDraft);
}
private async Task TestSearchAsync(List<Guid> expected, string text, Scope target = Scope.Draft, TextIndexerGrain grain = null)
{
context.Scope = target;
var result = await (grain ?? sut).SearchAsync(text, context);
if (expected != null)
{
Assert.Equal(expected, result);
}
else
{
Assert.Empty(result);
}
}
}
}