Files
itworx-knowledge-hub-Public/tests/backend/ItWorx.KnowledgeHub.IntegrationTests/Knowledge/InternalLinkResolutionTests.cs
T

104 lines
4.9 KiB
C#

using System.Net.Http.Json;
using ItWorx.KnowledgeHub.Contracts.Knowledge;
using ItWorx.KnowledgeHub.IntegrationTests.Infrastructure;
namespace ItWorx.KnowledgeHub.IntegrationTests.Knowledge;
/// <summary>Internal links resolve by stable page identity and survive title, slug and
/// tree changes (docs/27-acceptance-matrix.md, M2-A02).</summary>
[Collection(PostgresTestGroup.Name)]
public sealed class InternalLinkResolutionTests(PostgresContainerFixture postgres) : OwnerSetupTestBase(postgres)
{
[Fact]
public async Task A_resolved_internal_link_keeps_working_after_the_target_is_renamed_and_moved()
{
using var client = Factory.CreateClient();
await SetupHelper.LoginAsync(client, OwnerEmail, OwnerPassword);
var target = await CreatePageAsync(client, null, "PostgreSQL back-up herstellen");
var newParent = await CreatePageAsync(client, null, "Nieuwe categorie");
var sourceResponse = await SetupHelper.PostWithCsrfAsync(
client,
"/api/v1/pages",
new CreatePageRequest(
null,
"Runbook overzicht",
"WikiPage",
"Zie [[PostgreSQL back-up herstellen|het herstelrunbook]] voor details.",
null));
var source = await sourceResponse.Content.ReadFromJsonAsync<PageDetail>();
Assert.NotNull(source);
Assert.Contains($"href=\"/knowledge/{target.Id}/{target.Slug}\"", source.RenderedHtml, StringComparison.Ordinal);
Assert.Contains("het herstelrunbook", source.RenderedHtml, StringComparison.Ordinal);
// Rename AND move the target page.
var renamed = await SetupHelper.PutWithCsrfAsync(
client,
$"/api/v1/pages/{target.Id}",
new UpdatePageRequest("PostgreSQL herstelprocedure (bijgewerkt)", target.Markdown, "Runbook", "Active", null),
target.ETag);
renamed.EnsureSuccessStatusCode();
var renamedTarget = await renamed.Content.ReadFromJsonAsync<PageDetail>();
Assert.NotNull(renamedTarget);
var moveResponse = await SetupHelper.PostWithCsrfAndIfMatchAsync(
client, $"/api/v1/pages/{target.Id}/move", new MovePageRequest(newParent.Id, null), renamedTarget.ETag);
moveResponse.EnsureSuccessStatusCode();
// Re-fetch the SOURCE page: its stored link must still resolve to the same
// page ID even though the source page's own Markdown/authored link text was
// never touched, and the target's title/slug/parent all changed.
var sourceAfter = await client.GetFromJsonAsync<PageDetail>($"/api/v1/pages/{source.Id}");
Assert.NotNull(sourceAfter);
Assert.Contains($"/knowledge/{target.Id}/", sourceAfter.RenderedHtml, StringComparison.Ordinal);
Assert.DoesNotContain("[[PostgreSQL", sourceAfter.RenderedHtml, StringComparison.Ordinal);
}
[Fact]
public async Task An_unresolved_internal_link_target_remains_visible_as_plain_bracket_text()
{
using var client = Factory.CreateClient();
await SetupHelper.LoginAsync(client, OwnerEmail, OwnerPassword);
var response = await SetupHelper.PostWithCsrfAsync(
client,
"/api/v1/pages",
new CreatePageRequest(null, "Verwijzing naar niets", "WikiPage", "Zie [[Pagina die niet bestaat]].", null));
var page = await response.Content.ReadFromJsonAsync<PageDetail>();
Assert.NotNull(page);
Assert.Contains("[[Pagina die niet bestaat]]", page.RenderedHtml, StringComparison.Ordinal);
Assert.DoesNotContain("<a ", page.RenderedHtml, StringComparison.Ordinal);
}
[Fact]
public async Task An_ambiguous_internal_link_target_also_remains_unresolved_rather_than_guessing()
{
using var client = Factory.CreateClient();
await SetupHelper.LoginAsync(client, OwnerEmail, OwnerPassword);
await CreatePageAsync(client, null, "Overzicht");
await CreatePageAsync(client, null, "Overzicht");
var response = await SetupHelper.PostWithCsrfAsync(
client, "/api/v1/pages", new CreatePageRequest(null, "Verwijst dubbelzinnig", "WikiPage", "Zie [[Overzicht]].", null));
var page = await response.Content.ReadFromJsonAsync<PageDetail>();
Assert.NotNull(page);
Assert.Contains("[[Overzicht]]", page.RenderedHtml, StringComparison.Ordinal);
Assert.DoesNotContain("<a ", page.RenderedHtml, StringComparison.Ordinal);
}
private static async Task<PageDetail> CreatePageAsync(HttpClient client, Guid? parentId, string title)
{
var response = await SetupHelper.PostWithCsrfAsync(
client, "/api/v1/pages", new CreatePageRequest(parentId, title, "WikiPage", $"# {title}", null));
response.EnsureSuccessStatusCode();
var page = await response.Content.ReadFromJsonAsync<PageDetail>();
Assert.NotNull(page);
return page;
}
}