WEB-3: lokale Webseiten-Vorschau - GET /api/preview/{**path} (rendert live, korrekte Content-Types, nur Veroeffentlichte) + /webseite/vorschau (iframe, Seiten-Wechsler, Smartphone/Desktop-Umschalter, Neu laden) + Einstiege auf der Uebersicht + Fix: pages.ts rief /pages statt /api/pages (live-404, vom Mock kaschiert) + 1 Backend-Roundtrip + 4 e2e-Specs
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
69
GerbilManager.Tests/CmsPreviewTests.cs
Normal file
69
GerbilManager.Tests/CmsPreviewTests.cs
Normal file
@@ -0,0 +1,69 @@
|
||||
using System.Net;
|
||||
using System.Net.Http.Json;
|
||||
|
||||
namespace GerbilManager.Tests;
|
||||
|
||||
/// <summary>
|
||||
/// WEB-3: Round-Trips für die lokale Webseiten-Vorschau (GET /api/preview/…):
|
||||
/// veröffentlichte Seiten werden als HTML ausgeliefert, Entwürfe nicht,
|
||||
/// styles.css kommt mit CSS-Content-Type.
|
||||
/// </summary>
|
||||
public class CmsPreviewTests : IClassFixture<ApiFactory>
|
||||
{
|
||||
private readonly ApiFactory _factory;
|
||||
|
||||
public CmsPreviewTests(ApiFactory factory) => _factory = factory;
|
||||
|
||||
private static object PageInput(string slug, string title, string status) =>
|
||||
new { slug, title, seoDescription = (string?)null, status };
|
||||
|
||||
private sealed record PageRow(Guid Id, string Slug);
|
||||
|
||||
/// <summary>Seite anlegen oder (falls von WEB-0b geseedet) auf den Zielzustand setzen.</summary>
|
||||
private static async Task UpsertPageAsync(HttpClient client, string slug, string title, string status)
|
||||
{
|
||||
var existing = (await client.GetFromJsonAsync<List<PageRow>>("/api/pages"))!
|
||||
.FirstOrDefault(p => p.Slug == slug);
|
||||
if (existing is null)
|
||||
{
|
||||
var created = await client.PostAsJsonAsync("/api/pages", PageInput(slug, title, status));
|
||||
Assert.Equal(HttpStatusCode.Created, created.StatusCode);
|
||||
}
|
||||
else
|
||||
{
|
||||
var updated = await client.PutAsJsonAsync($"/api/pages/{existing.Id}", PageInput(slug, title, status));
|
||||
Assert.Equal(HttpStatusCode.NoContent, updated.StatusCode);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Vorschau_LiefertVeroeffentlichteSeiteAlsHtml_UndKeineEntwuerfe()
|
||||
{
|
||||
var client = _factory.CreateClient();
|
||||
|
||||
await UpsertPageAsync(client, "start", "Willkommen bei der Zucht", "Published");
|
||||
await UpsertPageAsync(client, "e2e-entwurf", "Unsere Zucht", "Draft");
|
||||
|
||||
// Startseite: /api/preview/ → index.html (text/html, enthält den Titel)
|
||||
var index = await client.GetAsync("/api/preview/");
|
||||
Assert.Equal(HttpStatusCode.OK, index.StatusCode);
|
||||
Assert.StartsWith("text/html", index.Content.Headers.ContentType!.ToString());
|
||||
Assert.Contains("Willkommen bei der Zucht", await index.Content.ReadAsStringAsync());
|
||||
|
||||
// Expliziter Pfad funktioniert ebenso
|
||||
var explicitIndex = await client.GetAsync("/api/preview/index.html");
|
||||
Assert.Equal(HttpStatusCode.OK, explicitIndex.StatusCode);
|
||||
|
||||
// CSS mit korrektem Content-Type (Renderer: SiteRenderer.CssPath)
|
||||
var css = await client.GetAsync("/api/preview/assets/site.css");
|
||||
Assert.Equal(HttpStatusCode.OK, css.StatusCode);
|
||||
Assert.StartsWith("text/css", css.Content.Headers.ContentType!.ToString());
|
||||
|
||||
// Entwurf wird NICHT gerendert (Vorschau zeigt nur Veröffentlichtes)
|
||||
Assert.Equal(HttpStatusCode.NotFound, (await client.GetAsync("/api/preview/e2e-entwurf/index.html")).StatusCode);
|
||||
Assert.Equal(HttpStatusCode.NotFound, (await client.GetAsync("/api/preview/e2e-entwurf/")).StatusCode);
|
||||
|
||||
// Unsinnige Pfade → 404
|
||||
Assert.Equal(HttpStatusCode.NotFound, (await client.GetAsync("/api/preview/gibt-es-nicht.html")).StatusCode);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user