Phase 10: field editor (FR-14)
เพิ่ม editor ต่อ template field — ผู้ดูแลเลือกรูปแบบช่องกรอกในฟอร์มสร้างเอกสารได้: text → textbox/textarea, number/date → control ตาม type (presentation metadata ล้วน — validation ยังยึด Type, ค่า field เป็น string ทั้ง flow, ไม่แตะ generate/sync/add-in) - Backend: TemplateField.Editor (nullable, null = default ของ type) + migration AddTemplateFieldEditor + validate ตาม type ใน PUT templates (ค่าไม่รู้จัก/ไม่เข้ากับ type → 400, normalize-on-write, API คืน resolved เสมอ) - Web: util fieldEditor.ts + editor select หน้าแก้ template (desktop+mobile, ซ่อนเมื่อ type มีทางเดียว) + ฟอร์มสร้างเอกสาร render ตาม editor + แก้ prefill re-generate ของ field date จาก ISO timestamp เต็ม (input[type=date] รับเฉพาะ yyyy-MM-dd เดิมแสดงว่าง) - Docs: spec v6 (FR-14/AC-17) + plan Phase 10 + sub-plan field-editor.md + acceptance-review AC-17 + README/CLAUDE.md - Tests: backend 60/60 (FieldEditorTests ใหม่ 8 กรณี) · web 46/46 + build ผ่าน Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
7b20f12ede
commit
9bb4a48c00
23 changed files with 865 additions and 45 deletions
62
web/test/fieldEditor.spec.ts
Normal file
62
web/test/fieldEditor.spec.ts
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
import { describe, expect, it } from 'vitest'
|
||||
import { dateInputValue, defaultEditor, editorOptions, resolveEditor } from '../app/utils/fieldEditor'
|
||||
|
||||
describe('fieldEditor — editor ต่อ field (FR-14)', () => {
|
||||
describe('defaultEditor', () => {
|
||||
it('ทุก type มี default ตาม allow-list ของ backend', () => {
|
||||
expect(defaultEditor('text')).toBe('textbox')
|
||||
expect(defaultEditor('number')).toBe('number')
|
||||
expect(defaultEditor('date')).toBe('date')
|
||||
})
|
||||
|
||||
it('type ที่ไม่รู้จัก → textbox (degrade อ่อนโยน)', () => {
|
||||
expect(defaultEditor('unknown')).toBe('textbox')
|
||||
})
|
||||
})
|
||||
|
||||
describe('editorOptions', () => {
|
||||
it('text เลือกได้ 2 แบบ — number/date มีทางเดียว (ซ่อน select)', () => {
|
||||
expect(editorOptions('text')).toEqual(['textbox', 'textarea'])
|
||||
expect(editorOptions('number')).toEqual(['number'])
|
||||
expect(editorOptions('date')).toEqual(['date'])
|
||||
})
|
||||
})
|
||||
|
||||
describe('resolveEditor — ใช้ตอน render ฟอร์มสร้างเอกสาร', () => {
|
||||
it('editor ที่เข้ากับ type → ใช้ค่านั้น (text + textarea = ข้อความยาว)', () => {
|
||||
expect(resolveEditor({ type: 'text', editor: 'textarea' })).toBe('textarea')
|
||||
expect(resolveEditor({ type: 'text', editor: 'textbox' })).toBe('textbox')
|
||||
})
|
||||
|
||||
it('ไม่มี editor / null → default ของ type (backend เก่าหรือค่า default ที่เก็บ null)', () => {
|
||||
expect(resolveEditor({ type: 'text' })).toBe('textbox')
|
||||
expect(resolveEditor({ type: 'text', editor: null })).toBe('textbox')
|
||||
expect(resolveEditor({ type: 'date', editor: undefined })).toBe('date')
|
||||
})
|
||||
|
||||
it('editor ไม่เข้ากับ type → default ของ type ไม่ throw (กันค่าหลุดจาก API)', () => {
|
||||
expect(resolveEditor({ type: 'number', editor: 'textarea' })).toBe('number')
|
||||
expect(resolveEditor({ type: 'text', editor: 'date' })).toBe('textbox')
|
||||
})
|
||||
|
||||
it('type ที่ไม่รู้จัก → textbox', () => {
|
||||
expect(resolveEditor({ type: 'other', editor: 'whatever' })).toBe('textbox')
|
||||
})
|
||||
})
|
||||
|
||||
describe('dateInputValue — prefill re-generate ของ field วันที่', () => {
|
||||
it('ISO timestamp เต็ม (ค่าจาก field sync ของ Word) → เหลือ yyyy-MM-dd ให้ input[type=date] แสดงได้', () => {
|
||||
expect(dateInputValue('2026-08-20T09:00:00Z')).toBe('2026-08-20')
|
||||
expect(dateInputValue('2026-08-20T09:00:00+07:00')).toBe('2026-08-20')
|
||||
})
|
||||
|
||||
it('yyyy-MM-dd อยู่แล้ว → คงเดิม', () => {
|
||||
expect(dateInputValue('2026-08-20')).toBe('2026-08-20')
|
||||
})
|
||||
|
||||
it('ค่าอื่น → คงเดิมให้ validation ของฟอร์มจัดการ', () => {
|
||||
expect(dateInputValue('20 ส.ค. 2569')).toBe('20 ส.ค. 2569')
|
||||
expect(dateInputValue('')).toBe('')
|
||||
})
|
||||
})
|
||||
})
|
||||
Loading…
Add table
Add a link
Reference in a new issue