Files

93 lines
4.4 KiB
C#

using System.Net;
using System.Net.Http.Json;
using ItWorx.KnowledgeHub.Contracts.Knowledge;
using ItWorx.KnowledgeHub.IntegrationTests.Infrastructure;
namespace ItWorx.KnowledgeHub.IntegrationTests.Knowledge;
/// <summary>Autosaved drafts survive navigation/restart without overwriting a newer
/// server revision (docs/27-acceptance-matrix.md, M2-A04).</summary>
[Collection(PostgresTestGroup.Name)]
public sealed class DraftAutosaveTests(PostgresContainerFixture postgres) : OwnerSetupTestBase(postgres)
{
[Fact]
public async Task A_saved_draft_can_be_retrieved_later_as_if_after_a_browser_restart()
{
using var writer = Factory.CreateClient();
await SetupHelper.LoginAsync(writer, OwnerEmail, OwnerPassword);
var draftKey = $"new-page-{Guid.NewGuid():N}";
var saveResponse = await SetupHelper.PutWithCsrfAsync(
writer, $"/api/v1/drafts/{draftKey}", new SaveDraftRequest(null, null, "Concepttitel", "Conceptinhoud"));
Assert.Equal(HttpStatusCode.OK, saveResponse.StatusCode);
// A brand new HttpClient with its own (empty) cookie jar, logging in again —
// simulating the browser having fully restarted.
using var afterRestart = Factory.CreateClient();
await SetupHelper.LoginAsync(afterRestart, OwnerEmail, OwnerPassword);
var fetched = await afterRestart.GetFromJsonAsync<DraftResponse>($"/api/v1/drafts/{draftKey}");
Assert.NotNull(fetched);
Assert.Equal("Concepttitel", fetched.Title);
Assert.Equal("Conceptinhoud", fetched.Markdown);
}
[Fact]
public async Task Saving_a_draft_against_an_outdated_base_revision_is_flagged_as_stale_not_silently_accepted()
{
using var client = Factory.CreateClient();
await SetupHelper.LoginAsync(client, OwnerEmail, OwnerPassword);
var createResponse = await SetupHelper.PostWithCsrfAsync(
client, "/api/v1/pages", new CreatePageRequest(null, "Concepttest pagina", "WikiPage", "Origineel", null));
var page = await createResponse.Content.ReadFromJsonAsync<PageDetail>();
Assert.NotNull(page);
// A draft is started against revision 1...
var draftKey = page.Id.ToString();
await SetupHelper.PutWithCsrfAsync(
client, $"/api/v1/drafts/{draftKey}", new SaveDraftRequest(page.Id, page.CurrentRevisionNumber, page.Title, "Conceptwijziging"));
// ...but someone else (or another tab) publishes revision 2 in the meantime.
await SetupHelper.PutWithCsrfAsync(
client,
$"/api/v1/pages/{page.Id}",
new UpdatePageRequest("Gepubliceerde titel", "Gepubliceerde inhoud", "WikiPage", "Active", null),
page.ETag);
// Saving the draft again must surface that its base revision is now stale,
// rather than silently proceeding as if nothing happened.
var staleSave = await SetupHelper.PutWithCsrfAsync(
client, $"/api/v1/drafts/{draftKey}", new SaveDraftRequest(page.Id, page.CurrentRevisionNumber, page.Title, "Nog een conceptwijziging"));
var staleDraft = await staleSave.Content.ReadFromJsonAsync<DraftResponse>();
Assert.NotNull(staleDraft);
Assert.True(staleDraft.BaseRevisionIsStale);
// Crucially, the published page itself was never overwritten by the draft.
var currentPage = await client.GetFromJsonAsync<PageDetail>($"/api/v1/pages/{page.Id}");
Assert.NotNull(currentPage);
Assert.Equal("Gepubliceerde titel", currentPage.Title);
}
[Fact]
public async Task Discarding_a_draft_removes_it()
{
using var client = Factory.CreateClient();
await SetupHelper.LoginAsync(client, OwnerEmail, OwnerPassword);
var draftKey = $"discard-me-{Guid.NewGuid():N}";
await SetupHelper.PutWithCsrfAsync(
client, $"/api/v1/drafts/{draftKey}", new SaveDraftRequest(null, null, "Weg te gooien", "Inhoud"));
var csrf = await SetupHelper.GetCsrfTokenAsync(client);
using var request = new HttpRequestMessage(HttpMethod.Delete, $"/api/v1/drafts/{draftKey}");
request.Headers.Add(csrf.HeaderName, csrf.Value);
using var deleteResponse = await client.SendAsync(request);
Assert.Equal(HttpStatusCode.OK, deleteResponse.StatusCode);
var getResponse = await client.GetAsync($"/api/v1/drafts/{draftKey}");
Assert.Equal(HttpStatusCode.NotFound, getResponse.StatusCode);
}
}