182 lines
7.8 KiB
C#
182 lines
7.8 KiB
C#
|
|
using System.Net;
|
||
|
|
using System.Net.Http.Json;
|
||
|
|
using Microsoft.EntityFrameworkCore;
|
||
|
|
|
||
|
|
namespace WordVersioning.Api.IntegrationTests;
|
||
|
|
|
||
|
|
/// <summary>FR-14 — editor ต่อ field: เลือกได้ตาม type, ไม่ส่ง = default ของ type,
|
||
|
|
/// ค่าเท่ากับ default normalize เป็น null ใน DB, ค่าไม่รู้จัก/ไม่เข้ากับ type → 400 (AC-17)</summary>
|
||
|
|
[Collection(IntegrationTestCollection.Name)]
|
||
|
|
public sealed class FieldEditorTests(IntegrationTestFixture fixture)
|
||
|
|
{
|
||
|
|
private async Task<(Guid TemplateId, List<TemplateFieldItem> Fields)> CreateTemplateAsync(HttpClient client) =>
|
||
|
|
await TemplateTests.CreateDefaultTemplateAsync(client, $"editor {Guid.NewGuid():N}");
|
||
|
|
|
||
|
|
[Fact]
|
||
|
|
public async Task Update_TextFieldEditorTextarea_PersistsAndEchoed()
|
||
|
|
{
|
||
|
|
using var client = fixture.CreateClient();
|
||
|
|
var (templateId, fields) = await CreateTemplateAsync(client);
|
||
|
|
|
||
|
|
var updated = new
|
||
|
|
{
|
||
|
|
fields = fields.Select(f => new
|
||
|
|
{
|
||
|
|
key = f.Key,
|
||
|
|
label = f.Key,
|
||
|
|
type = "text",
|
||
|
|
editor = f.Key == "employee_name" ? "textarea" : null as string,
|
||
|
|
isRequired = false,
|
||
|
|
sortOrder = f.SortOrder,
|
||
|
|
}),
|
||
|
|
};
|
||
|
|
|
||
|
|
using var put = await client.PutAsJsonAsync($"api/templates/{templateId}", updated, IntegrationTestFixture.Json);
|
||
|
|
Assert.Equal(HttpStatusCode.OK, put.StatusCode);
|
||
|
|
var body = await put.Content.ReadFromJsonAsync<TemplateDetailResult>(IntegrationTestFixture.Json);
|
||
|
|
Assert.Equal("textarea", body!.Fields.Single(f => f.Key == "employee_name").Editor);
|
||
|
|
|
||
|
|
await using var db = fixture.CreateDb();
|
||
|
|
var row = await db.TemplateFields.AsNoTracking().SingleAsync(f => f.TemplateId == templateId && f.Key == "employee_name");
|
||
|
|
Assert.Equal("textarea", row.Editor);
|
||
|
|
}
|
||
|
|
|
||
|
|
/// <summary>ไม่ส่ง editor → response ได้ default ของ type แต่ DB เก็บ null ทั้งหมด (null = default)</summary>
|
||
|
|
[Fact]
|
||
|
|
public async Task Update_OmittedEditor_ResolvesDefaultPerType_StoresNull()
|
||
|
|
{
|
||
|
|
using var client = fixture.CreateClient();
|
||
|
|
var (templateId, fields) = await CreateTemplateAsync(client);
|
||
|
|
|
||
|
|
var updated = new
|
||
|
|
{
|
||
|
|
fields = fields.Select(f => new
|
||
|
|
{
|
||
|
|
key = f.Key,
|
||
|
|
label = f.Key,
|
||
|
|
type = f.Key == "salary" ? "number" : f.Key == "start_date" ? "date" : "text",
|
||
|
|
isRequired = false,
|
||
|
|
sortOrder = f.SortOrder,
|
||
|
|
}),
|
||
|
|
};
|
||
|
|
|
||
|
|
using var put = await client.PutAsJsonAsync($"api/templates/{templateId}", updated, IntegrationTestFixture.Json);
|
||
|
|
Assert.Equal(HttpStatusCode.OK, put.StatusCode);
|
||
|
|
var body = await put.Content.ReadFromJsonAsync<TemplateDetailResult>(IntegrationTestFixture.Json);
|
||
|
|
Assert.Equal("textbox", body!.Fields.Single(f => f.Key == "employee_name").Editor);
|
||
|
|
Assert.Equal("number", body.Fields.Single(f => f.Key == "salary").Editor);
|
||
|
|
Assert.Equal("date", body.Fields.Single(f => f.Key == "start_date").Editor);
|
||
|
|
|
||
|
|
await using var db = fixture.CreateDb();
|
||
|
|
var rows = await db.TemplateFields.AsNoTracking().Where(f => f.TemplateId == templateId).ToListAsync();
|
||
|
|
Assert.All(rows, r => Assert.Null(r.Editor)); // DB ไม่เก็บค่า default ซ้ำซ้อน
|
||
|
|
}
|
||
|
|
|
||
|
|
/// <summary>ส่ง editor ตรงกับ default ("textbox" ของ text) → response echo ค่าเดิมแต่ DB normalize เป็น null</summary>
|
||
|
|
[Fact]
|
||
|
|
public async Task Update_EditorEqualToDefault_NormalizedToNull()
|
||
|
|
{
|
||
|
|
using var client = fixture.CreateClient();
|
||
|
|
var (templateId, fields) = await CreateTemplateAsync(client);
|
||
|
|
|
||
|
|
var updated = new
|
||
|
|
{
|
||
|
|
fields = fields.Select(f => new
|
||
|
|
{
|
||
|
|
key = f.Key,
|
||
|
|
label = f.Key,
|
||
|
|
type = "text",
|
||
|
|
editor = "textbox",
|
||
|
|
isRequired = false,
|
||
|
|
sortOrder = f.SortOrder,
|
||
|
|
}),
|
||
|
|
};
|
||
|
|
|
||
|
|
using var put = await client.PutAsJsonAsync($"api/templates/{templateId}", updated, IntegrationTestFixture.Json);
|
||
|
|
Assert.Equal(HttpStatusCode.OK, put.StatusCode);
|
||
|
|
var body = await put.Content.ReadFromJsonAsync<TemplateDetailResult>(IntegrationTestFixture.Json);
|
||
|
|
Assert.All(body!.Fields, f => Assert.Equal("textbox", f.Editor));
|
||
|
|
|
||
|
|
await using var db = fixture.CreateDb();
|
||
|
|
var rows = await db.TemplateFields.AsNoTracking().Where(f => f.TemplateId == templateId).ToListAsync();
|
||
|
|
Assert.All(rows, r => Assert.Null(r.Editor));
|
||
|
|
}
|
||
|
|
|
||
|
|
[Fact]
|
||
|
|
public async Task Update_UnknownEditor_Returns400()
|
||
|
|
{
|
||
|
|
using var client = fixture.CreateClient();
|
||
|
|
var (templateId, fields) = await CreateTemplateAsync(client);
|
||
|
|
|
||
|
|
var updated = new
|
||
|
|
{
|
||
|
|
fields = fields.Select(f => new
|
||
|
|
{
|
||
|
|
key = f.Key,
|
||
|
|
label = f.Key,
|
||
|
|
type = "text",
|
||
|
|
editor = f.Key == "employee_name" ? "dropdown" : null as string,
|
||
|
|
isRequired = false,
|
||
|
|
sortOrder = f.SortOrder,
|
||
|
|
}),
|
||
|
|
};
|
||
|
|
|
||
|
|
using var put = await client.PutAsJsonAsync($"api/templates/{templateId}", updated, IntegrationTestFixture.Json);
|
||
|
|
Assert.Equal(HttpStatusCode.BadRequest, put.StatusCode);
|
||
|
|
}
|
||
|
|
|
||
|
|
/// <summary>editor ถูก allow-list ทั่วไปแต่ไม่เข้ากับ type ของ field นั้น → 400</summary>
|
||
|
|
[Theory]
|
||
|
|
[InlineData("number", "textarea")]
|
||
|
|
[InlineData("text", "date")]
|
||
|
|
[InlineData("date", "textbox")]
|
||
|
|
public async Task Update_EditorIncompatibleWithType_Returns400(string type, string editor)
|
||
|
|
{
|
||
|
|
using var client = fixture.CreateClient();
|
||
|
|
var (templateId, fields) = await CreateTemplateAsync(client);
|
||
|
|
|
||
|
|
var updated = new
|
||
|
|
{
|
||
|
|
fields = fields.Select(f => new
|
||
|
|
{
|
||
|
|
key = f.Key,
|
||
|
|
label = f.Key,
|
||
|
|
type = f.Key == "employee_name" ? type : "text",
|
||
|
|
editor = f.Key == "employee_name" ? editor : null as string,
|
||
|
|
isRequired = false,
|
||
|
|
sortOrder = f.SortOrder,
|
||
|
|
}),
|
||
|
|
};
|
||
|
|
|
||
|
|
using var put = await client.PutAsJsonAsync($"api/templates/{templateId}", updated, IntegrationTestFixture.Json);
|
||
|
|
Assert.Equal(HttpStatusCode.BadRequest, put.StatusCode);
|
||
|
|
}
|
||
|
|
|
||
|
|
/// <summary>tag ที่เพิ่มจากการ replace ไฟล์ได้ editor default (textbox) โดย DB เก็บ null</summary>
|
||
|
|
[Fact]
|
||
|
|
public async Task ReplaceFile_AddedTagGetsDefaultEditor()
|
||
|
|
{
|
||
|
|
using var client = fixture.CreateClient();
|
||
|
|
var (templateId, _) = await CreateTemplateAsync(client);
|
||
|
|
|
||
|
|
using var put = await client.PutAsync(
|
||
|
|
$"api/templates/{templateId}/file",
|
||
|
|
new MultipartFormDataContent
|
||
|
|
{
|
||
|
|
{ new ByteArrayContent(TestDocx.BuildReplacementTemplateDocx())
|
||
|
|
{ Headers = { ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue(TestDocx.DocxContentType) } },
|
||
|
|
"file", "replaced.docx" },
|
||
|
|
});
|
||
|
|
Assert.Equal(HttpStatusCode.OK, put.StatusCode);
|
||
|
|
var body = await put.Content.ReadFromJsonAsync<ReplaceFileResult>(IntegrationTestFixture.Json);
|
||
|
|
|
||
|
|
var note = body!.Fields.Single(f => f.Key == "note");
|
||
|
|
Assert.Equal("note", note.Key); // added tag
|
||
|
|
Assert.Equal("textbox", note.Editor);
|
||
|
|
|
||
|
|
await using var db = fixture.CreateDb();
|
||
|
|
var row = await db.TemplateFields.AsNoTracking().SingleAsync(f => f.TemplateId == templateId && f.Key == "note");
|
||
|
|
Assert.Null(row.Editor);
|
||
|
|
}
|
||
|
|
}
|