|
|
@@ -0,0 +1,88 @@
|
|
|
+import assert from 'node:assert/strict'
|
|
|
+import { describe, it } from 'node:test'
|
|
|
+import {
|
|
|
+ buildContractDocxFileName,
|
|
|
+ injectSxWatermarkHtml,
|
|
|
+ parseContractSupplierCode,
|
|
|
+ prepareContractHtmlForDocx,
|
|
|
+ stripContractLogoHtml,
|
|
|
+ toAbsoluteAssetUrls
|
|
|
+} from './contract-html-to-docx'
|
|
|
+
|
|
|
+describe('parseContractSupplierCode', () => {
|
|
|
+ it('parses supplier code from contractNo', () => {
|
|
|
+ assert.equal(parseContractSupplierCode('SX/X-JT20250926002'), 'SX')
|
|
|
+ assert.equal(parseContractSupplierCode('YD/X-JT20250926001'), 'YD')
|
|
|
+ })
|
|
|
+
|
|
|
+ it('defaults to SX when missing or unmatched', () => {
|
|
|
+ assert.equal(parseContractSupplierCode(undefined), 'SX')
|
|
|
+ assert.equal(parseContractSupplierCode(''), 'SX')
|
|
|
+ assert.equal(parseContractSupplierCode('NO-MATCH'), 'SX')
|
|
|
+ })
|
|
|
+})
|
|
|
+
|
|
|
+describe('stripContractLogoHtml', () => {
|
|
|
+ it('removes logo img and logo-only wrapper div', () => {
|
|
|
+ const html =
|
|
|
+ '<div><img src="/logo.gif" alt="logo" /></div><p>正文</p><img src="/watermask.jpg" alt="水印" />'
|
|
|
+ const out = stripContractLogoHtml(html)
|
|
|
+ assert.equal(out.includes('logo.gif'), false)
|
|
|
+ assert.equal(out.includes('正文'), true)
|
|
|
+ assert.equal(out.includes('watermask.jpg'), true)
|
|
|
+ })
|
|
|
+})
|
|
|
+
|
|
|
+describe('toAbsoluteAssetUrls', () => {
|
|
|
+ it('prefixes root-relative src with origin', () => {
|
|
|
+ const out = toAbsoluteAssetUrls(
|
|
|
+ '<img src="/seals/a.png" /><img src="https://cdn.example/x.png" />',
|
|
|
+ 'http://localhost:3006'
|
|
|
+ )
|
|
|
+ assert.equal(out.includes('src="http://localhost:3006/seals/a.png"'), true)
|
|
|
+ assert.equal(out.includes('src="https://cdn.example/x.png"'), true)
|
|
|
+ })
|
|
|
+})
|
|
|
+
|
|
|
+describe('injectSxWatermarkHtml', () => {
|
|
|
+ it('prepends watermark image with absolute url', () => {
|
|
|
+ const out = injectSxWatermarkHtml('<p>合同</p>', 'http://localhost:3006/watermask.jpg')
|
|
|
+ assert.equal(out.includes('http://localhost:3006/watermask.jpg'), true)
|
|
|
+ assert.equal(out.includes('alt="水印"'), true)
|
|
|
+ assert.equal(out.includes('<p>合同</p>'), true)
|
|
|
+ })
|
|
|
+})
|
|
|
+
|
|
|
+describe('prepareContractHtmlForDocx', () => {
|
|
|
+ it('adds SX watermark and keeps logo', () => {
|
|
|
+ const out = prepareContractHtmlForDocx({
|
|
|
+ html: '<div><img src="/logo.gif" /></div><p>正文</p>',
|
|
|
+ contractNo: 'SX/X-JT20250926002',
|
|
|
+ origin: 'http://localhost:3006'
|
|
|
+ })
|
|
|
+ assert.equal(out.includes('watermask.jpg'), true)
|
|
|
+ assert.equal(out.includes('logo.gif'), true)
|
|
|
+ assert.equal(out.includes('http://localhost:3006/logo.gif'), true)
|
|
|
+ })
|
|
|
+
|
|
|
+ it('strips logo and skips watermark for non-SX', () => {
|
|
|
+ const out = prepareContractHtmlForDocx({
|
|
|
+ html: '<div><img src="/logo.gif" /></div><p>正文</p>',
|
|
|
+ contractNo: 'YD/X-JT20250926001',
|
|
|
+ origin: 'http://localhost:3006'
|
|
|
+ })
|
|
|
+ assert.equal(out.includes('watermask'), false)
|
|
|
+ assert.equal(out.includes('logo.gif'), false)
|
|
|
+ assert.equal(out.includes('正文'), true)
|
|
|
+ })
|
|
|
+})
|
|
|
+
|
|
|
+describe('buildContractDocxFileName', () => {
|
|
|
+ it('uses contract name and sanitizes illegal chars', () => {
|
|
|
+ assert.equal(buildContractDocxFileName('甲/乙合同', 'SX/X-JT1'), '甲-乙合同合同.docx')
|
|
|
+ })
|
|
|
+
|
|
|
+ it('falls back to contractNo', () => {
|
|
|
+ assert.equal(buildContractDocxFileName('', 'SX/X-JT1'), 'SX-X-JT1合同.docx')
|
|
|
+ })
|
|
|
+})
|