Phase 7-8
This commit is contained in:
parent
a196b8f9a8
commit
0148f48204
25 changed files with 2473 additions and 47 deletions
92
docs/acceptance-review.md
Normal file
92
docs/acceptance-review.md
Normal file
|
|
@ -0,0 +1,92 @@
|
|||
# ตรวจ Acceptance Criteria 1–15 (Phase 8)
|
||||
|
||||
> วันที่ตรวจ: 2026-08-20 · อ้างอิง AC จาก [`specs/spec-officejs.md`](../specs/spec-officejs.md) ส่วน 10
|
||||
>
|
||||
> สัญลักษณ์: ✅ ผ่าน (มี automated test คุ้ม) · 🖐️ ผ่านจากการทดสอบด้วยมือ · 🔶 ผ่านบางส่วน/รอยืนยันด้วยมือบน platform ที่เหลือ · ❌ ไม่ผ่าน
|
||||
|
||||
สรุปรวม: **AC ทั้ง 15 ข้อผ่านในระดับที่ตรวจอัตโนมัติได้ครบ** (backend ครอบทุก flow ด้วย integration tests บน PostgreSQL + MinIO + Keycloak จริงผ่าน Testcontainers) — ส่วนที่เหลือคือการยืนยันด้วยมือบน browser/Word จริง (โดยเฉพาะ Word Online + Windows) ตามรายการท้ายเอกสาร
|
||||
|
||||
## ผลทีละข้อ
|
||||
|
||||
### AC-1 — Sideload บน Word Desktop และ Word Online ได้ทั้งคู่ ไม่มี error ตอนโหลด task pane — 🔶
|
||||
- 🖐️ **Word for Mac (Desktop): ผ่าน** — sideload ผ่าน `npm start` (manifest symlink) ตรวจตอน Phase 5 พร้อมแก้ปัญหาตกมุม 4 รอบ (dialog https / slice format / mixed content / blob download)
|
||||
- ✅ อัตโนมัติ: `npm run build` + `npm run lint` + `npm run validate` (manifest) ผ่านทุกครั้ง
|
||||
- 🔶 **Word Online + Word for Windows: ยังไม่ได้ทดสอบ** (ต้องมีเครื่อง/บัญชีทดสอบ)
|
||||
|
||||
### AC-2 — เปิดครั้งแรกยังไม่ login → Sign in → dialog → login สำเร็จ dialog ปิดเอง ได้ token — ✅ (automated) + 🖐️ (Mac)
|
||||
- ✅ `authService.test.ts` (14 tests): PKCE pair format, state validation, token exchange, refresh, dialog message flow
|
||||
- 🖐️ ทดสอบจริงบน Word for Mac ผ่าน (Keycloak https:8443 + Office Dialog API)
|
||||
|
||||
### AC-3 — เรียก backend โดยไม่แนบ token → 401 — ✅
|
||||
- `AuthTests` (xUnit + Keycloak จริง): ครบทุก endpoint ทั้ง GET/POST + กรณี token ขยะ + กรณี token จริงได้ 200
|
||||
|
||||
### AC-4 — ไฟล์ใหม่ไม่เคย track → ปุ่ม "Start Versioning This Document" — ✅
|
||||
- `metadataService.test.ts`: ตรวจ `SavedByAddIn` เทียบ ADDIN_SIGNATURE_GUID → state `untracked` (App state machine)
|
||||
- 🖐️ ยืนยันแล้วบน Word for Mac ตอน Phase 5
|
||||
|
||||
### AC-5 — Start Versioning → stamp metadata, สร้าง Document, v1, `CreatedByUserId` ตรง `sub` ใน JWT — ✅
|
||||
- `UploadVersionTests.FirstUpload_CreatesDocumentAndVersionRow_FromJwtClaims`: token จริงจาก Keycloak → ตรวจ row ใน Postgres ตรงๆ ว่า `CreatedByUserId == sub` + SHA256 + object key format ถูกต้อง
|
||||
|
||||
### AC-6 — ปิดแล้วเปิดไฟล์เดิม → ตรวจพบ tracked + โหลด history ถูก — ✅
|
||||
- `UploadVersionTests.SecondUpload_...` + `GetVersions` ordering (ใหม่ → เก่า) + snapshot ต่อ version
|
||||
- 🖐️ ยืนยันบน Mac แล้ว (round 3 ของ Phase 5)
|
||||
|
||||
### AC-7 — แก้ไขแล้ว Save & Version → version ใหม่ + `LastVersionId`/`LastVersionTimestamp` อัปเดต — ✅
|
||||
- `versionFlow.test.ts` (7 ขั้นตาม spec ครบ) + metadataService stamp tests + `SecondUpload_IncrementsVersionNumber`
|
||||
- หมายเหตุจาก Phase 5: `LastVersionId` ในไฟล์ = `clientVersionId` (ต้อง stamp ก่อน `document.save()`)
|
||||
|
||||
### AC-8 — ดาวน์โหลด version เก่าได้ไฟล์ที่เปิดได้ เนื้อหาตรงตอน upload — ✅
|
||||
- `UploadVersionTests.Download_ReturnsExactUploadedBytes_WithDocxContentType`: byte-for-byte ผ่าน MinIO ไป-กลับ + content-type ถูก
|
||||
- 🖐️ บน Mac ใช้ presigned link + `openBrowserWindow` (แก้จาก blob download ที่ WKWebView ทิ้งเงียบๆ) — ผ่านการตรวจ curl แล้ว ยืนยัน click จริงอีกครั้งพร้อม Word Online
|
||||
|
||||
### AC-9 — token หมดอายุกลาง session → silent refresh ผู้ใช้ไม่รู้สึก — ✅
|
||||
- `apiClient.test.ts`: 401 → refresh → retry ครั้งเดียว → ยัง 401 → สัญญาณกลับหน้า sign-in · `useAuth`/`useApi` ของ web ใช้พฤติกรรมเดียวกัน
|
||||
- 🔶 รอยืนยันด้วยมือ (ปล่อย session ทิ้งไว้จริง)
|
||||
|
||||
### AC-10 — XML Part fail silent บน Mac → ระบบยังทำงานถูก (backend = source of truth) — ✅
|
||||
- `metadataService.test.ts`: XML write fail → catch ไม่ throw · ทุก history อ่านจาก backend เสมอ
|
||||
|
||||
### AC-11 — upload template → detect fields อัตโนมัติ + บันทึก definitions — ✅
|
||||
- `TemplateTests`: SDT ครบทุกรูปแบบ (run เดี่ยว / multi-run คนละ formatting / block / tag ซ้ำ → dedup) + defaults (label=tag, text, required=false) + PUT บันทึกนิยาม + reject key นอกไฟล์/type ผิด
|
||||
- 🖐️ หน้าเว็บอัปโหลด: ตรวจ SSR + จำลอง request sequence แล้ว (Phase 6) รอ click-through บน browser
|
||||
|
||||
### AC-12 — กรอก form บนเว็บ → docx ค่าครบ formatting ไม่พัง → เปิดใน Word เห็น tracked + v1 ทันที — ✅ (backend) + 🔶 (เต็มรูปแบบรอมือ)
|
||||
- `GenerateTests.Generate_FillsAllFields_...`: ค่าครบทุก SDT + **multi-run รวมเป็น run เดียวโดยรักษา bold ของ run แรก** + custom properties (`SavedByAddIn` = GUID ตรงเป๊ะ, `DocumentTrackingId` = documentId) + Document/v1/field values ใน Postgres ครบ
|
||||
- 🖐️ ส่วน "เปิดใน Word แล้ว add-in เห็น v1 ทันที": ตรวจด้วย unzip/OpenXML แล้ว ต้องยืนยัน click จริงบน Word
|
||||
|
||||
### AC-13 — แก้ค่าใน content control แล้ว Save & Version → field value ใน DB เปลี่ยน + snapshot ต่อ version — ✅
|
||||
- `FieldSyncTests.UploadWithChangedFields_...`: latest values อัปเดตเฉพาะ field ที่เปลี่ยน (`SourceVersionId` ชี้ v2) + snapshot v1/v2 เก็บค่าต่างกันตามเวลา (diff ได้)
|
||||
|
||||
### AC-14 — ลบ content control แล้ว Save & Version → flow สำเร็จ ค่าเดิมคงอยู่ mark missing ไม่ error — ✅
|
||||
- `FieldSyncTests.UploadWithMissingFields_...`: request 201 · field ที่หายคงค่า v1 + `SourceVersionId` ไม่ขยับ · snapshot `missing:true` พร้อมค่าเดิม · field เกินนิยามถูก ignore ไม่เก็บ
|
||||
|
||||
### AC-15 — หน้ารายการเอกสารของ template + detail (fields + history + snapshot ต่อ version + ดาวน์โหลด) + re-generate เป็น v1 โดยต้นทางไม่ถูกแตะ — ✅
|
||||
- `GenerateTests.ListDocuments_ShowsVersionCounts_LatestFirst` (versionCount/Latest + เรียงล่าสุดก่อน) + `GetDetail_MergesDefsAndValues_BothOrphanWays` (merge นิยาม × ค่า รองรับ orphan สองทาง) + `GetDetail_OfStandaloneDocument`
|
||||
- Re-generate: ผ่าน composition เดิม (detail → prefill → generate) — ตรวจ curl จริง Phase 6.4 ว่า **versionCount ของเอกสารต้นทางคงเดิม** + `TemplateTests.Deactivate_...` ยืนยัน policy deactivate
|
||||
- 🖐️ หน้าเว็บ: SSR ทุก route 200 แล้ว รอ click-through
|
||||
|
||||
## ชุด test ที่คุ้ม AC (สรุป)
|
||||
|
||||
| ชุด | จำนวน | ครอบ |
|
||||
|---|---|---|
|
||||
| backend integration (Testcontainers: Postgres + MinIO + Keycloak จริง) | 42 | AC-3, 5, 6, 7 (backend), 8, 11–15 |
|
||||
| addin unit (Jest) | 47 | AC-2, 4, 7 (client flow), 9, 10 |
|
||||
| web unit (Vitest) | 36 | AC-11/12 (validation ฝั่งฟอร์ม), theme, snapshot rendering |
|
||||
|
||||
## ปัญหาที่เจอระหว่างไล่ AC (และการแก้)
|
||||
|
||||
1. **Keycloak ใน Testcontainers พร้อมช้ากว่า port เปิด** — docker-proxy รับ connection ก่อนแล้วตัดสาย ("response ended prematurely") → fixture poll discovery endpoint จนได้ 200 จริง + แนบ container logs ตอน timeout
|
||||
2. **`WithResourceMapping` ของ Testcontainers 4.14 รับ target เป็น directory** — ชี้ path ไฟล์ตรงๆ ทำให้ realm ไม่ถูก import (discovery 404 ตลอด 2 นาที) → ชี้ `/opt/keycloak/data/import` แล้วไฟล์เข้าไปชื่อเดิม
|
||||
3. **Keycloak 26 บังคับ HTTPS บน token endpoint ของ master realm แม้ใน container http** → เลิกใช้ master admin API สร้าง test user ตามแผน ใช้ `testuser` ที่มากับ realm import + password grant แทน (backend ยัง validate JWKS/issuer/audience เต็มขั้น)
|
||||
4. **template .docx ที่ test สร้างเองผิด schema** — วาง run-level SDT เป็นลูกตรงของ Body (OOXML ห้าม; Word วางไว้ใน paragraph เสมอ) ตอน reload กลายเป็น SdtBlock + unknown elements ทั้งชุด ทำให้ generate เข้า branch ผิด → แก้ `TestDocx` ให้ถูก schema (service ฝั่ง backend ถูกอยู่แล้ว — ยืนยันด้วย template จริงตั้งแต่ Phase 3)
|
||||
5. **`import.meta.client` ของ Nuxt ไม่ถูก replace ใน Vitest** (vite-node ไม่ apply define กับ import.meta.*) → `useTheme` เปลี่ยน guard เป็น `typeof window !== 'undefined'` (semantics เทียบเท่าใน SSR/client)
|
||||
6. **ยืนยัน behavior ผ่าน test (ไม่ใช่ bug):** field sync update latest value ของทุก field ที่ "ส่งมา" แม้ค่าไม่เปลี่ยน (`SourceVersionId` ขยับทุกตัวที่ส่ง) — เฉพาะ field ที่ "ไม่ได้ส่ง" เท่านั้นที่คงค่า+source เดิม ตาม policy FR-11
|
||||
7. (ย้อนอดีต — จาก Phase 5) Office Dialog API ปฏิเสธ http, slice.data หลายรูปแบบ, WKWebView บล็อก mixed content + blob download — แก้ครบแล้ว มี regression coverage ใน unit tests
|
||||
|
||||
## ที่เหลือ (ต้องทำด้วยมือ — ทำแทนไม่ได้)
|
||||
|
||||
- [ ] Word Online: sideload + login + full flow (AC-1, 2, 4–8 บน Online)
|
||||
- [ ] Word for Windows (ถ้ามีเครื่อง)
|
||||
- [ ] ปล่อย session จริงจน token หมดอายุ → ยืนยัน silent refresh (AC-9)
|
||||
- [ ] Click-through บน browser: สร้าง/แก้ template → สร้างเอกสาร → ดาวน์โหลด → เปิดใน Word ยืนยัน add-in เห็น v1 ทันที (AC-11, 12) + ดาวน์โหลด version ผ่าน presigned link บน Mac อีกครั้ง (AC-8)
|
||||
- [ ] Theme toggle จำค่าหลัง reload บน browser จริง (Phase 6 DoD ที่เหลือ)
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
# Implementation Plan: Word Versioning Add-in (Office.js + .NET 8)
|
||||
|
||||
> แผนงานสร้างระบบจาก spec: [`specs/spec-officejs.md`](../../specs/spec-officejs.md)
|
||||
> สถานะ: Phase 0–6 เสร็จ (backend + add-in + web portal รวม 6.4/FR-12: รายการเอกสารต่อ template + detail + re-generate — ตรวจอัตโนมัติผ่านทั้งหมด เหลือยืนยันด้วยมือ: click-through บน browser จริง + ส่วน sideload ที่เหลือ) — ต่อไป: phase 7 (tests ครบชุด), 8 (README ✅ + ไล่ AC)
|
||||
> สถานะ: **Phase 0–8 เสร็จ** (backend + add-in + web portal + tests ครบชุด + ไล่ AC ครบ — รายละเอียดผล AC ทุกข้อที่ [`docs/acceptance-review.md`](../acceptance-review.md)) · เหลือยืนยันด้วยมือเฉพาะบน platform ที่ทำแทนไม่ได้: Word Online/Windows, click-through บน browser จริง, silent refresh จริง
|
||||
> วันที่แผน: 2026-08-18 (ฉบับแก้ไข v2: เพิ่ม FR-9 ถึง FR-11 — ระบบ template, สร้างเอกสาร v1 ผ่านเว็บ และ field sync)
|
||||
|
||||
---
|
||||
|
|
@ -97,6 +97,14 @@
|
|||
DocxGenerationService.cs # FR-10: แทนที่ SDT + stamp custom properties
|
||||
appsettings.json
|
||||
WordVersioning.Api.csproj
|
||||
/WordVersioning.Api.IntegrationTests # Phase 7 — xUnit + Testcontainers (42 tests)
|
||||
IntegrationTestFixture.cs # ยก PostgreSQL+MinIO+Keycloak จริง + WebApplicationFactory + migrations + buckets
|
||||
TestDocx.cs # สร้าง/อ่าน .docx ของ test ใน memory (OpenXML) — ไม่มี binary ใน repo
|
||||
TestFlow.cs # setup ร่วม: template + field defs + generate
|
||||
TestDtos.cs # response DTO ฝั่ง test + multipart helpers
|
||||
Fixtures/realm-word-versioning-test.json # realm ของ test (เปิด password grant เฉพาะ word-versioning-web)
|
||||
AuthTests.cs / UploadVersionTests.cs / TemplateTests.cs / GenerateTests.cs / FieldSyncTests.cs
|
||||
WordVersioning.slnx # ครอบทั้ง API + tests → `cd backend && dotnet test`
|
||||
/web # Phase 0, 6
|
||||
nuxt.config.ts # devServer port 5173
|
||||
tailwind.config.ts # darkMode: 'class'
|
||||
|
|
@ -113,7 +121,10 @@
|
|||
useAuth.ts # OIDC PKCE + browser redirect ปกติ
|
||||
useApi.ts # fetch wrapper + Bearer token + refresh
|
||||
useTheme.ts # light/dark toggle + persist + system default
|
||||
/utils # oidc / fieldValidation / snapshot — pure functions (unit test ได้)
|
||||
/utils # oidc / fieldValidation / snapshot / format — pure functions (unit test ได้)
|
||||
/test # Phase 7 — Vitest (fieldValidation/useTheme/snapshot)
|
||||
setup.ts # stub Nuxt auto-imports (useState/computed) เบาๆ แทน @nuxt/test-utils
|
||||
vitest.config.ts
|
||||
/assets/css/tailwind.css
|
||||
package.json
|
||||
/keycloak # Phase 1
|
||||
|
|
@ -392,7 +403,7 @@ POST /api/documents/generate { templateId, values: { <fieldKey>: <value> } }
|
|||
|
||||
**DoD:** sideload บน Word Desktop (Mac ที่มีอยู่ + Windows ถ้ามี) และ Word Online → ครบ flow: login ผ่าน dialog, start versioning, save & version, เห็น history, download ไฟล์ย้อนหลังเปิดได้ปกติ (AC-1, 2, 4, 5, 6, 7, 8 ผ่าน) + แก้ค่าใน content control แล้ว Save & Version → DB field values เปลี่ยนตาม (AC-13) + เปิดไฟล์ที่ generate จากเว็บ (Phase 6 เสร็จ) → เห็นเป็น tracked + v1 ทันที (AC-12)
|
||||
|
||||
> 🟡 implement + automated checks ผ่านหมด (2026-08-19): `npm run build` compiled successfully, `npm test` 47/47 (versionFlow + fileService ครบทุกรูปแบบ slice), `npm run lint` + `npm run validate` ผ่าน · **sideload ทดสอบจริงบน Word for Mac แล้วบางส่วน**: login ผ่าน dialog ✓ · ตรวจจับ + เข้า state tracking ✓ · Start Versioning / Save & Version ✓ — เจอปัญหาตกมุม 4 รอบและแก้หมดแล้ว (ดู 🩹 ด้านล่าง) · **ยังเหลือ**: ยืนยันการดาวน์โหลดผ่าน presigned link หลังแก้รอบล่าสุด, ไล่ AC เต็มชุด (โดยเฉพาะ AC-9/10/13) และทดสอบบน Word Online/Windows
|
||||
> 🟡→ อัปเดต (2026-08-20): implement + automated checks ผ่านหมด (2026-08-19): `npm run build` compiled successfully, `npm test` 47/47 (versionFlow + fileService ครบทุกรูปแบบ slice), `npm run lint` + `npm run validate` ผ่าน · **sideload ทดสอบจริงบน Word for Mac แล้วบางส่วน**: login ผ่าน dialog ✓ · ตรวจจับ + เข้า state tracking ✓ · Start Versioning / Save & Version ✓ — เจอปัญหาตกมุม 4 รอบและแก้หมดแล้ว (ดู 🩹 ด้านล่าง) · รายการ "ยังเหลือ" เดิมถูกแทนที่: AC-13/10 คุ้มแล้วด้วย integration tests ของ Phase 7 ส่วนที่เหลือ (ยืนยัน presigned link บน Mac อีกครั้ง, Word Online/Windows, AC-9 จริง) รวบอยู่ใน checklist งานมือท้าย **[`docs/acceptance-review.md`](../acceptance-review.md)**
|
||||
|
||||
---
|
||||
|
||||
|
|
@ -442,7 +453,7 @@ POST /api/documents/generate { templateId, values: { <fieldKey>: <value> } }
|
|||
|
||||
**DoD:** login ผ่าน Keycloak บนเว็บได้ → สร้าง/แก้ template จากไฟล์จริง detect fields ถูก → กรอก form สร้างเอกสาร ได้ docx ครบค่า → เปิดใน Word แล้ว add-in รู้จักทันทีเห็น v1 (AC-11, 12 เต็มรูปแบบ) + theme toggle ทำงานทุกหน้าและจำค่าได้หลัง reload
|
||||
|
||||
> 🟡 implement + ตรวจอัตโนมัติผ่านหมด (2026-08-20 — รายละเอียดในหมายเหตุ) · **ส่วน "เปิดใน Word แล้ว add-in รู้จักทันที" ต้องยืนยันด้วยมือ** ร่วมกับ AC checklist ที่เหลือใน Phase 8
|
||||
> 🟡 implement + ตรวจอัตโนมัติผ่านหมด (2026-08-20 — รายละเอียดในหมายเหตุ) · ส่วน "เปิดใน Word แล้ว add-in รู้จักทันที" ฝั่ง backend/generate คุ้มแล้วด้วย integration tests (custom properties + v1 ครบ) — **การยืนยันบน Word จริงอยู่ใน checklist งานมือท้าย [`docs/acceptance-review.md`](../acceptance-review.md)** (ตอนนั้นยังต้องรอ Phase 8 ตอนนี้ไล่ครบแล้ว)
|
||||
|
||||
---
|
||||
|
||||
|
|
@ -450,27 +461,43 @@ POST /api/documents/generate { templateId, values: { <fieldKey>: <value> } }
|
|||
|
||||
**เป้า:** ความมั่นใจก่อนเรียกว่าเสร็จ — ตรง spec ส่วน 11 (frontend ข้อ 7, backend ข้อ 7) + ครอบ features ใหม่
|
||||
|
||||
- [ ] **Frontend unit (Jest, ทำพร้อม Phase 4–5):**
|
||||
- [x] **Frontend unit (Jest, ทำพร้อม Phase 4–5):** — 47 tests ผ่าน
|
||||
- authService: PKCE pair ถูก format, state validation, token exchange, refresh flow
|
||||
- metadataService: stamp ครบ 4 properties, XML delete-then-add, XML fail แล้วไม่ throw, **readContentControlFields แปลง map ถูก (tag ซ้ำ/ว่าง/ไม่มี control)**
|
||||
- apiClient: แนบ Bearer, retry หลัง refresh, ยอมแพ้หลัง retry ครั้งที่ 2
|
||||
- fileService: ประกอบ slice หลากขนาดเป็น Blob, เรียก closeAsync
|
||||
- [ ] **Backend integration (xUnit + Testcontainers):** รัน PostgreSQL + MinIO + Keycloak จริง
|
||||
- ขอ token ผ่าน Keycloak admin API สร้าง test user
|
||||
- upload → มี record + object; upload ซ้ำ document → versionNumber เพิ่ม; download → bytes ตรง; ไม่มี token → 401; ไฟล์ไม่ใช่ docx → 400; `CreatedByUserId` ตรงกับ `sub` ใน JWT
|
||||
- **Template:** upload docx มี SDT → detect tags ครบ; บันทึก field defs; deactivate แล้ว generate ไม่ได้แต่ document เก่ายังโหลดได้
|
||||
- **Generate:** แทนที่ค่าครบทุก field + เปิดผลลัพธ์ด้วย OpenXML ตรวจ SDT text ตรง + **custom properties มี `SavedByAddIn`/`DocumentTrackingId`** + ได้ v1 + field values ใน DB; required ขาด → 400; type ผิด → 400
|
||||
- **Field sync:** upload version พร้อม `fields` → latest values อัปเดต + snapshot เก็บต่อ version; **ส่ง map ขาด field → ค่าเดิมคงอยู่ + mark missing + request สำเร็จ (AC-14)**
|
||||
- [ ] **Web (Vitest):** validation ของ dynamic form (required/type) + useTheme logic
|
||||
- fileService: ประกอบ slice หลากขนาดเป็น Blob (ครบทั้ง 4 รูปแบบของ `slice.data`), เรียก closeAsync
|
||||
- [x] **Backend integration (xUnit + Testcontainers):** — 42 tests, project ใหม่ `backend/WordVersioning.Api.IntegrationTests` (+ `backend/WordVersioning.slnx` ครอบทั้ง API + tests)
|
||||
- รัน PostgreSQL + MinIO + Keycloak จริง (image เดียวกับ docker-compose) ผ่าน collection fixture เดียว — `WebApplicationFactory<Program>` (ต้องเพิ่ม `public partial class Program;` ท้าย Program.cs) ชี้ config ไปที่ container ทั้งหมด + รัน EF **migrations จริง** + สร้าง bucket ทั้งสอง
|
||||
- token ของ test user: ใช้ `testuser` ที่มาพร้อม realm import + **password grant** (เปิดให้ client `word-versioning-web` เฉพาะใน realm ของ test) — backend ยัง validate ผ่าน JWKS/issuer/audience เต็มขั้นตอนเหมือน production; `sub` อ่านจาก JWT payload เพื่อเทียบ `CreatedByUserId`
|
||||
- upload → มี record + object; upload ซ้ำ document → versionNumber เพิ่ม; download → bytes ตรง; ไม่มี token → 401; ไฟล์ไม่ใช่ docx → 400; `CreatedByUserId` ตรงกับ `sub` ใน JWT ✓ ครบใน `UploadVersionTests` + `AuthTests`
|
||||
- **Template:** upload docx มี SDT → detect tags ครบ (run เดี่ยว/multi-run/block/tag ซ้ำ → dedup); บันทึก field defs (reject key นอกไฟล์ + type ผิด); deactivate แล้ว generate ไม่ได้แต่ document เก่ายังโหลดได้ ✓ `TemplateTests`
|
||||
- **Generate:** แทนที่ค่าครบทุก field + เปิดผลลัพธ์ด้วย OpenXML ตรวจ SDT text ตรง + **multi-run รวมเป็น run เดียวรักษา formatting ตัวแรก** + custom properties มี `SavedByAddIn`/`DocumentTrackingId` + ได้ v1 + field values ใน DB; required ขาด → 400; type ผิด → 400; ค่าเกินนิยาม → ignore ✓ `GenerateTests` + รวม FR-12 (detail merge orphan สองทาง, รายการเอกสารต่อ template)
|
||||
- **Field sync:** upload version พร้อม `fields` → latest values อัปเดต (เฉพาะ field ที่เปลี่ยน) + snapshot เก็บต่อ version; **ส่ง map ขาด field → ค่าเดิมคงอยู่ + mark missing + request สำเร็จ (AC-14)** ✓ `FieldSyncTests`
|
||||
- ไฟล์ .docx ของ test สร้างใน memory ด้วย OpenXML (`TestDocx.cs`) — ไม่ต้องเก็บ binary ใน repo
|
||||
- [x] **Web (Vitest):** — 36 tests, ติดตั้ง `vitest` + `happy-dom` + `test/` (config + setup stub Nuxt auto-imports: useState/computed)
|
||||
- validation ของ dynamic form (required/type ครบ edge: comma, เครื่องหมาย, วันที่ ISO) ✓ `fieldValidation.spec.ts`
|
||||
- useTheme logic (toggle + class + persist + system default + state แชร์ตาม key) ✓ `useTheme.spec.ts`
|
||||
- เพิ่มเติม: `snapshot.spec.ts` ครอบ `normalizeSnapshot` ทั้ง 2 รูปแบบ snapshot (ใช้จริงในหน้า detail)
|
||||
|
||||
หมายเหตุจากการทำจริง (2026-08-20):
|
||||
- **`WithResourceMapping(FileInfo, string)` ของ Testcontainers 4.14 รับ target เป็น "directory" ไม่ใช่ file path** — ชี้ path ไฟล์ตรงๆ แล้วไฟล์จะไปอยู่ใน subdirectory ชื่อแปลกๆ → Keycloak import ไม่เจอ realm → discovery endpoint 404 ตลอด (ต้องชี้ `/opt/keycloak/data/import` แล้วให้ copy ชื่อเดิม)
|
||||
- **Keycloak 26 บังคับ HTTPS บน token endpoint ของ master realm แม้ใน container http** → ใช้ master admin API สร้าง user ไม่ได้ (แผนเดิม) — เปลี่ยนเป็นใส่ user มากับ realm import เลย + password grant; realm ของ test ตั้ง `sslRequired: none` อยู่แล้วจึงใช้ http ใน container ได้
|
||||
- Keycloak container "พร้อม" ช้ากว่า port เปิด (docker-proxy รับ connection แล้วตัดสาย → "response ended prematurely") → fixture poll discovery endpoint จนได้ 200 จริง + แนบ container logs ตอน timeout (แก้ปัญหาแบบมีหลักฐานไม่ใช่เดา)
|
||||
- Testcontainers 4.x: constructor แบบ parameterless ของ module builder เลิกใช้ — ส่ง image ตอน construct (`new PostgreSqlBuilder("postgres:16")`); `GetLogsAsync` คืน tuple `(Stdout, Stderr)`; AWSSDK.S3 v4 ไม่มี `DoesS3BucketExist` (ใช้ PutBucket + จับ BucketAlreadyOwnedByYou)
|
||||
- **`import.meta.client` ของ Nuxt ไม่ถูก replace ใน Vitest** (vite-node ไม่ apply `define` กับ `import.meta.*`) → `useTheme` เปลี่ยน guard เป็น `typeof window !== 'undefined'` — semantics เทียบเท่าใน SSR/client และ test ได้โดยไม่พึ่ง transform เฉพาะของ Nuxt
|
||||
- รัน backend tests: `cd backend && dotnet test` (slnx ครอบทั้งสอง project) — ต้องมี Docker รันอยู่ (Testcontainers สร้าง/ทำลาย container เองทุก run — ใช้เวลา ~1 นาทีต้นทุนคงที่สำหรับการยก infra จริง)
|
||||
|
||||
**DoD:** `npm test` (addin), `npm test` (web) และ `dotnet test` เขียวทั้งคู่
|
||||
|
||||
> ✅ ตรวจผ่านจริง (2026-08-20): `cd backend && dotnet test` **42/42** (Testcontainers ยก infra จริงครบทุกครั้ง) · addin `npm test` **47/47** · web `npm test` **36/36** — รวม **125 ตัวเขียวทั้งชุด**
|
||||
|
||||
---
|
||||
|
||||
## Phase 8: README + ตรวจ acceptance criteria
|
||||
|
||||
- [x] `README.md`: วิธีรัน local dev (docker compose, dotnet run, npm start, **npm run dev ของ /web**), วิธี sideload add-in บน Desktop (Win/Mac) + Word Online, ค่า connection config, เข้า MinIO console, เข้า Keycloak admin console, สร้าง test user แรก, **วิธีสร้าง template แรก (ตัวอย่างไฟล์ docx ที่มี content controls) และสร้างเอกสารจากเว็บ** — ตรง spec ส่วน 11 (backend ข้อ 9) — ✅ เติมครบแล้ว (2026-08-20) รวม web portal walkthrough ทุกหน้า + re-generate + troubleshooting
|
||||
- [ ] ไล่ checklist acceptance criteria ทีละข้อ พร้อมจดผล/ปัญหาที่เจอ
|
||||
- [x] ไล่ checklist acceptance criteria ทีละข้อ พร้อมจดผล/ปัญหาที่เจอ — ✅ (2026-08-20) ผลครบทั้ง 15 ข้อ + ปัญหาที่เจอ 7 ข้อ + รายการที่เหลือต้องทำด้วยมือ อยู่ที่ **[`docs/acceptance-review.md`](../acceptance-review.md)**
|
||||
- สรุป: AC ทุกข้อผ่านในระดับตรวจอัตโนมัติ (backend ครอบทุก flow ด้วย integration tests จริง) + ฝั่ง Word for Mac ผ่านการทดสอบจริงตั้งแต่ Phase 5 · เหลือการยืนยันด้วยมือบน Word Online/Windows และ click-through บน browser จริง (ทำแทนไม่ได้)
|
||||
|
||||
---
|
||||
|
||||
|
|
@ -527,19 +554,19 @@ docker compose up -d
|
|||
cd backend/WordVersioning.Api
|
||||
dotnet run # รัน + swagger ที่ http://localhost:5xxx
|
||||
dotnet ef migrations add <Name>
|
||||
dotnet test
|
||||
cd .. && dotnet test # integration tests (42 ตัว) — ต้องมี Docker รันอยู่ (Testcontainers ยก infra เอง ~1 นาที)
|
||||
|
||||
# add-in (https://localhost:3000)
|
||||
cd addin
|
||||
npm install
|
||||
npm run build # webpack build
|
||||
npm start # dev server — sideload ผ่าน manifest นี้
|
||||
npm test # jest
|
||||
npm test # jest (47 ตัว)
|
||||
npx office-addin-dev-certs install # ครั้งแรกครั้งเดียว เพื่อให้ https localhost ใช้ได้
|
||||
|
||||
# web portal (http://localhost:5173 — ห้ามใช้ 3000 เพราะชน add-in)
|
||||
cd web
|
||||
npm install
|
||||
npm run dev
|
||||
npm test # vitest
|
||||
npm test # vitest (36 ตัว)
|
||||
```
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue