documentation-hub 5.7.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.eslintrc.json +43 -0
- package/.github/workflows/build.yml +64 -0
- package/.github/workflows/ci.yml +39 -0
- package/.vscode/extensions.json +3 -0
- package/Current.md +97 -0
- package/DocHub_Image.png +0 -0
- package/README.md +666 -0
- package/USER_GUIDE.md +1173 -0
- package/Updater.md +311 -0
- package/build/256x256.png +0 -0
- package/build/512x512.png +0 -0
- package/build/app-update.yml +4 -0
- package/build/create-icon.js +208 -0
- package/build/icon.ico +0 -0
- package/build/icon.png +0 -0
- package/build/icon_1024x1024.png +0 -0
- package/dist/assets/Analytics-BpsG9895.js +1 -0
- package/dist/assets/Card-IAZin8kp.js +1 -0
- package/dist/assets/CurrentSession-B-rFkHvf.js +12 -0
- package/dist/assets/Dashboard-C_5gMb0q.js +1 -0
- package/dist/assets/Documents-CqZ25axS.js +1 -0
- package/dist/assets/Input-l89xwXBi.js +1 -0
- package/dist/assets/Reporting-DqdHJY_a.js +1 -0
- package/dist/assets/Search-XNbu5z_3.js +1 -0
- package/dist/assets/SessionManager-lH9hZfzH.js +1 -0
- package/dist/assets/Sessions-ClZOPYNc.js +1 -0
- package/dist/assets/Settings-DUEHGURa.js +11 -0
- package/dist/assets/index-8xUe8ptc.js +24 -0
- package/dist/assets/index-RYyJqF7O.css +1 -0
- package/dist/assets/path-BkOl0AGO.js +1 -0
- package/dist/assets/promises-ID_B9S-h.js +1 -0
- package/dist/assets/urlHelpers-TvgahX0r.js +1 -0
- package/dist/assets/useToast-yRSO1dkm.js +1 -0
- package/dist/assets/vendor-charts-RkGK5ROP.js +36 -0
- package/dist/assets/vendor-db-l0sNRNKZ.js +1 -0
- package/dist/assets/vendor-react-BVZ_anCF.js +4 -0
- package/dist/assets/vendor-search-Dw8P0qyA.js +1 -0
- package/dist/assets/vendor-ui-BU7NfluV.js +53 -0
- package/dist/electron/PowerAutomateApiService-LfW09ZGr.js +147 -0
- package/dist/electron/main-CXkNtyv-.js +19789 -0
- package/dist/electron/main.js +5 -0
- package/dist/electron/preload.js +1 -0
- package/dist/icon.png +0 -0
- package/dist/index.html +27 -0
- package/docs/CODEBASE_ANALYSIS_REPORT.md +309 -0
- package/docs/DEBUG_LOGGING_GUIDE.md +244 -0
- package/docs/README.md +115 -0
- package/docs/TOC_WIRING_GUIDE.md +344 -0
- package/docs/analysis/Bullet_Symbol_Bug_Analysis.md +136 -0
- package/docs/analysis/DOCXMLATER_ANALYSIS_SUMMARY.txt +169 -0
- package/docs/analysis/Document_Processing_Issues_Analysis.md +704 -0
- package/docs/analysis/FIELD_PRESERVATION_ANALYSIS.md +1200 -0
- package/docs/analysis/INDENTATION_PRESERVE_ANALYSIS.md +181 -0
- package/docs/analysis/INDENTATION_PRESERVE_IMPLEMENTATION.md +207 -0
- package/docs/analysis/List_Implementation.md +206 -0
- package/docs/analysis/List_Implementation_Accuracy_Report.md +366 -0
- package/docs/analysis/PROCESSING_OPTIONS_UI_UPDATES.md +220 -0
- package/docs/analysis/RefactorStyles.md +852 -0
- package/docs/analysis/STYLE_PARAMETER_ENHANCEMENT.md +143 -0
- package/docs/analysis/docxmlater-comparison-todo-2025-11-13.md +636 -0
- package/docs/analysis/docxmlater-implementation-analysis-2025-11-13.md +340 -0
- package/docs/analysis/docxmlater-template_ui-integration-analysis.md +263 -0
- package/docs/analysis/github-issues-to-create.md +237 -0
- package/docs/api/API_README.md +538 -0
- package/docs/api/API_REFERENCE.md +751 -0
- package/docs/api/TYPE_DEFINITIONS.md +869 -0
- package/docs/architecture/FONT_EMBEDDING_GUIDE.md +318 -0
- package/docs/architecture/docxmlater-functions-and-structure.md +726 -0
- package/docs/docxmlater-readme.md +1341 -0
- package/docs/fixes/EXECUTION_LOG_TEST_BASE.md +573 -0
- package/docs/fixes/HYPERLINK_TEXT_SANITIZATION.md +253 -0
- package/docs/fixes/README.md +37 -0
- package/docs/github-issues/issue-1-body.md +125 -0
- package/docs/github-issues/issue-10-body.md +850 -0
- package/docs/github-issues/issue-2-body.md +200 -0
- package/docs/github-issues/issue-3-body.md +270 -0
- package/docs/github-issues/issue-4-body.md +169 -0
- package/docs/github-issues/issue-5-body.md +173 -0
- package/docs/github-issues/issue-6-body.md +158 -0
- package/docs/github-issues/issue-7-body.md +171 -0
- package/docs/github-issues/issue-8-body.md +407 -0
- package/docs/github-issues/issue-9-body.md +515 -0
- package/docs/github-issues/issue-tracker.md +274 -0
- package/docs/github-issues/predictive-analysis-2025-10-18.md +2131 -0
- package/docs/implementation/List_Framework_Refactor_Plan.md +336 -0
- package/docs/implementation/PRIMARY_TEXT_COLOR_FEATURE.md +217 -0
- package/docs/implementation/RELEASE_PLAN_v2.1.0.md +362 -0
- package/docs/implementation/RefactorStyles.md +588 -0
- package/docs/implementation/implement-plan.md +489 -0
- package/docs/implementation/missing-helpers-implementation.md +391 -0
- package/docs/implementation/refactor-plan.md +520 -0
- package/docs/implementation/session-implementation-complete.md +233 -0
- package/docs/implementation/session-management-plan.md +250 -0
- package/docs/setup-checklist.md +77 -0
- package/docs/versions/changelog.md +345 -0
- package/electron/customUpdater.ts +656 -0
- package/electron/main.ts +2441 -0
- package/electron/memoryConfig.ts +187 -0
- package/electron/preload.ts +394 -0
- package/electron/proxyConfig.ts +340 -0
- package/electron/services/BackupService.ts +452 -0
- package/electron/services/DictionaryService.ts +402 -0
- package/electron/services/LocalDictionaryLookupService.ts +147 -0
- package/electron/services/PowerAutomateApiService.ts +231 -0
- package/electron/services/SharePointSyncService.ts +474 -0
- package/electron/windowsCertStore.ts +427 -0
- package/electron/zscalerConfig.ts +381 -0
- package/eslint.config.js +92 -0
- package/jest.config.js +52 -0
- package/package.json +214 -0
- package/postcss.config.mjs +6 -0
- package/public/icon.png +0 -0
- package/publish-release.ps1 +5 -0
- package/renovate.json +30 -0
- package/src/App.tsx +216 -0
- package/src/__mocks__/p-limit.js +12 -0
- package/src/__mocks__/styleMock.js +1 -0
- package/src/components/common/BugReportButton.tsx +44 -0
- package/src/components/common/BugReportDialog.tsx +193 -0
- package/src/components/common/Button.tsx +153 -0
- package/src/components/common/Card.tsx +86 -0
- package/src/components/common/ColorPickerDialog.tsx +177 -0
- package/src/components/common/ConfirmDialog.tsx +96 -0
- package/src/components/common/DebugConsole.tsx +275 -0
- package/src/components/common/EmptyState.tsx +183 -0
- package/src/components/common/ErrorBoundary.tsx +98 -0
- package/src/components/common/ErrorDetailsDialog.tsx +153 -0
- package/src/components/common/ErrorFallback.tsx +218 -0
- package/src/components/common/Input.tsx +109 -0
- package/src/components/common/Skeleton.tsx +184 -0
- package/src/components/common/SplashScreen.tsx +81 -0
- package/src/components/common/Toast.tsx +155 -0
- package/src/components/common/Tooltip.tsx +79 -0
- package/src/components/common/UpdateNotification.tsx +320 -0
- package/src/components/comparison/ComparisonWindow.tsx +374 -0
- package/src/components/comparison/SideBySideDiff.tsx +486 -0
- package/src/components/comparison/index.ts +8 -0
- package/src/components/document/DocumentUploader.tsx +288 -0
- package/src/components/document/HyperlinkPreview.tsx +430 -0
- package/src/components/document/HyperlinkService.md +1484 -0
- package/src/components/document/Hyperlink_Technical_Documentation.md +496 -0
- package/src/components/document/InlineChangesView.tsx +707 -0
- package/src/components/document/ProcessingProgress.tsx +303 -0
- package/src/components/document/ProcessingResults.tsx +256 -0
- package/src/components/document/TrackedChangesDetail.tsx +530 -0
- package/src/components/document/TrackedChangesPanel.tsx +546 -0
- package/src/components/document/VirtualDocumentList.tsx +240 -0
- package/src/components/editor/DocumentEditor.tsx +723 -0
- package/src/components/editor/DocumentEditorModal.tsx +640 -0
- package/src/components/editor/EditorQuickActions.tsx +502 -0
- package/src/components/editor/EditorToolbar.tsx +312 -0
- package/src/components/editor/TableEditor.tsx +926 -0
- package/src/components/editor/index.ts +18 -0
- package/src/components/layout/Header.tsx +190 -0
- package/src/components/layout/Sidebar.tsx +313 -0
- package/src/components/layout/TitleBar.tsx +190 -0
- package/src/components/navigation/CommandPalette.tsx +233 -0
- package/src/components/navigation/KeyboardShortcutsModal.tsx +173 -0
- package/src/components/sessions/ChangeItem.tsx +408 -0
- package/src/components/sessions/ChangeViewer.tsx +1155 -0
- package/src/components/sessions/DocumentComparisonModal.tsx +314 -0
- package/src/components/sessions/ProcessingOptions.tsx +297 -0
- package/src/components/sessions/ReplacementsTab.tsx +438 -0
- package/src/components/sessions/RevisionHandlingOptions.tsx +87 -0
- package/src/components/sessions/SessionManager.tsx +188 -0
- package/src/components/sessions/StylesEditor.tsx +1335 -0
- package/src/components/sessions/TabContainer.tsx +151 -0
- package/src/components/sessions/VirtualSessionList.tsx +157 -0
- package/src/components/sessions/sessionToProcessorManager.tsx +420 -0
- package/src/components/settings/CertificateManager.tsx +410 -0
- package/src/components/settings/SegmentedControl.tsx +88 -0
- package/src/components/settings/SettingRow.tsx +52 -0
- package/src/contexts/GlobalStatsContext.tsx +396 -0
- package/src/contexts/SessionContext.tsx +2129 -0
- package/src/contexts/ThemeContext.tsx +428 -0
- package/src/contexts/UserSettingsContext.tsx +290 -0
- package/src/contexts/__tests__/GlobalStatsContext.test.tsx +390 -0
- package/src/global.d.ts +273 -0
- package/src/hooks/useDocumentQueue.tsx +210 -0
- package/src/hooks/useToast.tsx +55 -0
- package/src/main.tsx +10 -0
- package/src/pages/Analytics.tsx +386 -0
- package/src/pages/CurrentSession.tsx +1174 -0
- package/src/pages/Dashboard.tsx +319 -0
- package/src/pages/Documents.tsx +317 -0
- package/src/pages/Projects.tsx +250 -0
- package/src/pages/Reporting.tsx +386 -0
- package/src/pages/Search.tsx +349 -0
- package/src/pages/Sessions.tsx +285 -0
- package/src/pages/Settings.tsx +2662 -0
- package/src/services/HyperlinkService.ts +1085 -0
- package/src/services/document/DocXMLaterProcessor.ts +617 -0
- package/src/services/document/DocumentProcessingComparison.ts +856 -0
- package/src/services/document/DocumentSnapshotService.ts +575 -0
- package/src/services/document/WordDocumentProcessor.ts +10509 -0
- package/src/services/document/__tests__/DocXMLaterProcessor.hyperlinks.test.md +311 -0
- package/src/services/document/__tests__/WordDocumentProcessor.integration.test.ts +515 -0
- package/src/services/document/__tests__/WordDocumentProcessor.test.ts +812 -0
- package/src/services/document/blanklines/BlankLineManager.ts +658 -0
- package/src/services/document/blanklines/__tests__/paragraphChecks.test.ts +281 -0
- package/src/services/document/blanklines/helpers/blankLineInsertion.ts +87 -0
- package/src/services/document/blanklines/helpers/blankLineSnapshot.ts +251 -0
- package/src/services/document/blanklines/helpers/clearCustom.ts +121 -0
- package/src/services/document/blanklines/helpers/contextChecks.ts +117 -0
- package/src/services/document/blanklines/helpers/imageChecks.ts +51 -0
- package/src/services/document/blanklines/helpers/paragraphChecks.ts +236 -0
- package/src/services/document/blanklines/helpers/removeBlanksBetweenListItems.ts +91 -0
- package/src/services/document/blanklines/helpers/removeTrailingBlanks.ts +35 -0
- package/src/services/document/blanklines/helpers/tableGuards.ts +21 -0
- package/src/services/document/blanklines/index.ts +67 -0
- package/src/services/document/blanklines/rules/additionRules.ts +337 -0
- package/src/services/document/blanklines/rules/indentationRules.ts +317 -0
- package/src/services/document/blanklines/rules/removalRules.ts +362 -0
- package/src/services/document/blanklines/rules/ruleTypes.ts +92 -0
- package/src/services/document/blanklines/types.ts +29 -0
- package/src/services/document/helpers/ImageBorderCropper.ts +377 -0
- package/src/services/document/helpers/__tests__/whitespace.test.ts +272 -0
- package/src/services/document/helpers/whitespace.ts +117 -0
- package/src/services/document/list/ListNormalizer.ts +947 -0
- package/src/services/document/list/index.ts +45 -0
- package/src/services/document/list/list-detection.ts +275 -0
- package/src/services/document/list/list-types.ts +162 -0
- package/src/services/document/processors/HyperlinkProcessor.ts +370 -0
- package/src/services/document/processors/ListProcessor.ts +257 -0
- package/src/services/document/processors/StructureProcessor.ts +176 -0
- package/src/services/document/processors/StyleProcessor.ts +389 -0
- package/src/services/document/processors/TableProcessor.ts +2238 -0
- package/src/services/document/processors/__tests__/HyperlinkProcessor.test.ts +314 -0
- package/src/services/document/processors/__tests__/ListProcessor.test.ts +291 -0
- package/src/services/document/processors/__tests__/StructureProcessor.test.ts +257 -0
- package/src/services/document/processors/__tests__/TableProcessor.hlp-tips-bullets.test.ts +459 -0
- package/src/services/document/processors/__tests__/TableProcessor.test.ts +1604 -0
- package/src/services/document/processors/index.ts +28 -0
- package/src/services/document/types/docx-processing.ts +310 -0
- package/src/services/editor/EditorActionHandlers.ts +901 -0
- package/src/services/editor/index.ts +13 -0
- package/src/setupTests.ts +47 -0
- package/src/styles/global.css +782 -0
- package/src/types/backup.ts +132 -0
- package/src/types/dictionary.ts +125 -0
- package/src/types/document-processing.ts +331 -0
- package/src/types/docxmlater-augments.d.ts +142 -0
- package/src/types/editor.ts +280 -0
- package/src/types/electron.ts +340 -0
- package/src/types/globalStats.ts +155 -0
- package/src/types/hyperlink.ts +471 -0
- package/src/types/operations.ts +354 -0
- package/src/types/session.ts +427 -0
- package/src/types/settings.ts +112 -0
- package/src/utils/MemoryMonitor.ts +248 -0
- package/src/utils/cn.ts +6 -0
- package/src/utils/colorConvert.ts +306 -0
- package/src/utils/diffUtils.ts +347 -0
- package/src/utils/documentUtils.ts +202 -0
- package/src/utils/electronGuard.ts +62 -0
- package/src/utils/indexedDB.ts +915 -0
- package/src/utils/logger.ts +717 -0
- package/src/utils/pathSecurity.ts +232 -0
- package/src/utils/pathValidator.ts +236 -0
- package/src/utils/processingTimeEstimator.ts +153 -0
- package/src/utils/safeJsonParse.ts +62 -0
- package/src/utils/textSanitizer.ts +162 -0
- package/src/utils/urlHelpers.ts +304 -0
- package/src/utils/urlPatterns.ts +198 -0
- package/src/utils/urlSanitizer.ts +152 -0
- package/src/vite-env.d.ts +11 -0
- package/tsconfig.electron.json +19 -0
- package/tsconfig.json +36 -0
- package/tsconfig.node.json +12 -0
- package/typedoc.json +45 -0
- package/vite.config.ts +152 -0
|
@@ -0,0 +1,314 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Test Suite for HyperlinkProcessor
|
|
3
|
+
*
|
|
4
|
+
* Tests hyperlink manipulation, URL updates, and custom replacements.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { vi, describe, it, expect, beforeEach, type Mocked } from 'vitest';
|
|
8
|
+
import { HyperlinkProcessor } from '../HyperlinkProcessor';
|
|
9
|
+
import { Document, Hyperlink, Paragraph, Revision } from 'docxmlater';
|
|
10
|
+
import { DocXMLaterProcessor } from '../../DocXMLaterProcessor';
|
|
11
|
+
|
|
12
|
+
// Mock dependencies
|
|
13
|
+
vi.mock('docxmlater');
|
|
14
|
+
vi.mock('../../DocXMLaterProcessor');
|
|
15
|
+
|
|
16
|
+
describe('HyperlinkProcessor', () => {
|
|
17
|
+
let processor: HyperlinkProcessor;
|
|
18
|
+
let mockDoc: Mocked<Document>;
|
|
19
|
+
let mockDocXMLater: Mocked<DocXMLaterProcessor>;
|
|
20
|
+
|
|
21
|
+
beforeEach(() => {
|
|
22
|
+
vi.clearAllMocks();
|
|
23
|
+
processor = new HyperlinkProcessor();
|
|
24
|
+
|
|
25
|
+
// Create mock document
|
|
26
|
+
mockDoc = {
|
|
27
|
+
getAllParagraphs: vi.fn().mockReturnValue([]),
|
|
28
|
+
isTrackChangesEnabled: vi.fn().mockReturnValue(false),
|
|
29
|
+
getRevisionManager: vi.fn().mockReturnValue({
|
|
30
|
+
register: vi.fn(),
|
|
31
|
+
}),
|
|
32
|
+
hasBookmark: vi.fn().mockReturnValue(false),
|
|
33
|
+
} as unknown as Mocked<Document>;
|
|
34
|
+
|
|
35
|
+
// Setup DocXMLaterProcessor mock
|
|
36
|
+
mockDocXMLater = new DocXMLaterProcessor() as Mocked<DocXMLaterProcessor>;
|
|
37
|
+
mockDocXMLater.extractHyperlinks = vi.fn().mockResolvedValue([]);
|
|
38
|
+
(processor as any).docXMLater = mockDocXMLater;
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
describe('standardizeFormatting', () => {
|
|
42
|
+
it('should standardize hyperlink formatting to Verdana 12pt blue', async () => {
|
|
43
|
+
const mockHyperlink = createMockHyperlink('https://example.com', 'Test Link');
|
|
44
|
+
mockDocXMLater.extractHyperlinks.mockResolvedValue([
|
|
45
|
+
{
|
|
46
|
+
hyperlink: mockHyperlink,
|
|
47
|
+
paragraph: {} as Paragraph,
|
|
48
|
+
paragraphIndex: 0,
|
|
49
|
+
hyperlinkIndexInParagraph: 0,
|
|
50
|
+
url: 'https://example.com',
|
|
51
|
+
text: 'Test Link',
|
|
52
|
+
},
|
|
53
|
+
]);
|
|
54
|
+
|
|
55
|
+
const count = await processor.standardizeFormatting(mockDoc);
|
|
56
|
+
|
|
57
|
+
expect(count).toBe(1);
|
|
58
|
+
expect(mockHyperlink.setFormatting).toHaveBeenCalledWith({
|
|
59
|
+
font: 'Verdana',
|
|
60
|
+
size: 12,
|
|
61
|
+
color: '0000FF',
|
|
62
|
+
underline: 'single',
|
|
63
|
+
bold: false,
|
|
64
|
+
italic: false,
|
|
65
|
+
});
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
it('should handle empty hyperlink list', async () => {
|
|
69
|
+
mockDocXMLater.extractHyperlinks.mockResolvedValue([]);
|
|
70
|
+
|
|
71
|
+
const count = await processor.standardizeFormatting(mockDoc);
|
|
72
|
+
|
|
73
|
+
expect(count).toBe(0);
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
it('should continue processing if one hyperlink fails', async () => {
|
|
77
|
+
const mockHyperlink1 = createMockHyperlink('https://example1.com', 'Link 1');
|
|
78
|
+
const mockHyperlink2 = createMockHyperlink('https://example2.com', 'Link 2');
|
|
79
|
+
|
|
80
|
+
// Make first hyperlink throw error
|
|
81
|
+
mockHyperlink1.setFormatting = vi.fn().mockImplementation(() => {
|
|
82
|
+
throw new Error('Format error');
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
mockDocXMLater.extractHyperlinks.mockResolvedValue([
|
|
86
|
+
{
|
|
87
|
+
hyperlink: mockHyperlink1,
|
|
88
|
+
paragraph: {} as Paragraph,
|
|
89
|
+
paragraphIndex: 0,
|
|
90
|
+
hyperlinkIndexInParagraph: 0,
|
|
91
|
+
url: 'https://example1.com',
|
|
92
|
+
text: 'Link 1',
|
|
93
|
+
},
|
|
94
|
+
{
|
|
95
|
+
hyperlink: mockHyperlink2,
|
|
96
|
+
paragraph: {} as Paragraph,
|
|
97
|
+
paragraphIndex: 1,
|
|
98
|
+
hyperlinkIndexInParagraph: 0,
|
|
99
|
+
url: 'https://example2.com',
|
|
100
|
+
text: 'Link 2',
|
|
101
|
+
},
|
|
102
|
+
]);
|
|
103
|
+
|
|
104
|
+
const count = await processor.standardizeFormatting(mockDoc);
|
|
105
|
+
|
|
106
|
+
expect(count).toBe(1); // Only second one succeeded
|
|
107
|
+
expect(mockHyperlink2.setFormatting).toHaveBeenCalled();
|
|
108
|
+
});
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
describe('applyUrlUpdates', () => {
|
|
112
|
+
it('should update URLs in hyperlinks', async () => {
|
|
113
|
+
const mockHyperlink = createMockHyperlink('https://old-url.com', 'Link');
|
|
114
|
+
const mockParagraph = {
|
|
115
|
+
getContent: vi.fn().mockReturnValue([mockHyperlink]),
|
|
116
|
+
};
|
|
117
|
+
|
|
118
|
+
mockDoc.getAllParagraphs.mockReturnValue([mockParagraph as unknown as Paragraph]);
|
|
119
|
+
|
|
120
|
+
// Make mockHyperlink an instance of Hyperlink
|
|
121
|
+
Object.setPrototypeOf(mockHyperlink, Hyperlink.prototype);
|
|
122
|
+
|
|
123
|
+
const urlMap = new Map([['https://old-url.com', 'https://new-url.com']]);
|
|
124
|
+
|
|
125
|
+
const result = await processor.applyUrlUpdates(mockDoc, urlMap, 'TestAuthor');
|
|
126
|
+
|
|
127
|
+
expect(result.updated).toBe(1);
|
|
128
|
+
expect(result.failed).toHaveLength(0);
|
|
129
|
+
expect(mockHyperlink.setUrl).toHaveBeenCalledWith('https://new-url.com');
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
it('should skip identical URLs', async () => {
|
|
133
|
+
const mockHyperlink = createMockHyperlink('https://same-url.com', 'Link');
|
|
134
|
+
const mockParagraph = {
|
|
135
|
+
getContent: vi.fn().mockReturnValue([mockHyperlink]),
|
|
136
|
+
};
|
|
137
|
+
|
|
138
|
+
mockDoc.getAllParagraphs.mockReturnValue([mockParagraph as unknown as Paragraph]);
|
|
139
|
+
Object.setPrototypeOf(mockHyperlink, Hyperlink.prototype);
|
|
140
|
+
|
|
141
|
+
const urlMap = new Map([['https://same-url.com', 'https://same-url.com']]);
|
|
142
|
+
|
|
143
|
+
const result = await processor.applyUrlUpdates(mockDoc, urlMap);
|
|
144
|
+
|
|
145
|
+
expect(result.updated).toBe(0);
|
|
146
|
+
expect(mockHyperlink.setUrl).not.toHaveBeenCalled();
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
it('should return empty result for empty map', async () => {
|
|
150
|
+
const result = await processor.applyUrlUpdates(mockDoc, new Map());
|
|
151
|
+
|
|
152
|
+
expect(result.updated).toBe(0);
|
|
153
|
+
expect(result.failed).toHaveLength(0);
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
it('should track failed updates', async () => {
|
|
157
|
+
const mockHyperlink = createMockHyperlink('https://old-url.com', 'Link');
|
|
158
|
+
mockHyperlink.setUrl = vi.fn().mockImplementation(() => {
|
|
159
|
+
throw new Error('Update failed');
|
|
160
|
+
});
|
|
161
|
+
|
|
162
|
+
const mockParagraph = {
|
|
163
|
+
getContent: vi.fn().mockReturnValue([mockHyperlink]),
|
|
164
|
+
};
|
|
165
|
+
|
|
166
|
+
mockDoc.getAllParagraphs.mockReturnValue([mockParagraph as unknown as Paragraph]);
|
|
167
|
+
Object.setPrototypeOf(mockHyperlink, Hyperlink.prototype);
|
|
168
|
+
|
|
169
|
+
const urlMap = new Map([['https://old-url.com', 'https://new-url.com']]);
|
|
170
|
+
|
|
171
|
+
const result = await processor.applyUrlUpdates(mockDoc, urlMap);
|
|
172
|
+
|
|
173
|
+
expect(result.updated).toBe(0);
|
|
174
|
+
expect(result.failed).toHaveLength(1);
|
|
175
|
+
expect(result.failed[0].oldUrl).toBe('https://old-url.com');
|
|
176
|
+
});
|
|
177
|
+
});
|
|
178
|
+
|
|
179
|
+
describe('processCustomReplacements', () => {
|
|
180
|
+
it('should apply URL replacement with contains match', async () => {
|
|
181
|
+
const mockHyperlink = createMockHyperlink('https://old-domain.com/path', 'Link');
|
|
182
|
+
mockDocXMLater.extractHyperlinks.mockResolvedValue([
|
|
183
|
+
{
|
|
184
|
+
hyperlink: mockHyperlink,
|
|
185
|
+
paragraph: {} as Paragraph,
|
|
186
|
+
paragraphIndex: 0,
|
|
187
|
+
hyperlinkIndexInParagraph: 0,
|
|
188
|
+
url: 'https://old-domain.com/path',
|
|
189
|
+
text: 'Link',
|
|
190
|
+
},
|
|
191
|
+
]);
|
|
192
|
+
|
|
193
|
+
const result = await processor.processCustomReplacements(mockDoc, [
|
|
194
|
+
{
|
|
195
|
+
find: 'old-domain',
|
|
196
|
+
replace: 'new-domain',
|
|
197
|
+
matchType: 'contains',
|
|
198
|
+
applyTo: 'url',
|
|
199
|
+
},
|
|
200
|
+
]);
|
|
201
|
+
|
|
202
|
+
expect(result.updatedUrls).toBe(1);
|
|
203
|
+
expect(mockHyperlink.setUrl).toHaveBeenCalledWith('https://new-domain.com/path');
|
|
204
|
+
});
|
|
205
|
+
|
|
206
|
+
it('should apply text replacement with exact match', async () => {
|
|
207
|
+
const mockHyperlink = createMockHyperlink('https://example.com', 'Old Text');
|
|
208
|
+
mockDocXMLater.extractHyperlinks.mockResolvedValue([
|
|
209
|
+
{
|
|
210
|
+
hyperlink: mockHyperlink,
|
|
211
|
+
paragraph: {} as Paragraph,
|
|
212
|
+
paragraphIndex: 0,
|
|
213
|
+
hyperlinkIndexInParagraph: 0,
|
|
214
|
+
url: 'https://example.com',
|
|
215
|
+
text: 'Old Text',
|
|
216
|
+
},
|
|
217
|
+
]);
|
|
218
|
+
|
|
219
|
+
const result = await processor.processCustomReplacements(mockDoc, [
|
|
220
|
+
{
|
|
221
|
+
find: 'Old Text',
|
|
222
|
+
replace: 'New Text',
|
|
223
|
+
matchType: 'exact',
|
|
224
|
+
applyTo: 'text',
|
|
225
|
+
},
|
|
226
|
+
]);
|
|
227
|
+
|
|
228
|
+
expect(result.updatedTexts).toBe(1);
|
|
229
|
+
expect(mockHyperlink.setText).toHaveBeenCalledWith('New Text');
|
|
230
|
+
});
|
|
231
|
+
|
|
232
|
+
it('should apply replacement to both URL and text', async () => {
|
|
233
|
+
const mockHyperlink = createMockHyperlink('https://old.com', 'old link');
|
|
234
|
+
mockDocXMLater.extractHyperlinks.mockResolvedValue([
|
|
235
|
+
{
|
|
236
|
+
hyperlink: mockHyperlink,
|
|
237
|
+
paragraph: {} as Paragraph,
|
|
238
|
+
paragraphIndex: 0,
|
|
239
|
+
hyperlinkIndexInParagraph: 0,
|
|
240
|
+
url: 'https://old.com',
|
|
241
|
+
text: 'old link',
|
|
242
|
+
},
|
|
243
|
+
]);
|
|
244
|
+
|
|
245
|
+
const result = await processor.processCustomReplacements(mockDoc, [
|
|
246
|
+
{
|
|
247
|
+
find: 'old',
|
|
248
|
+
replace: 'new',
|
|
249
|
+
matchType: 'contains',
|
|
250
|
+
applyTo: 'both',
|
|
251
|
+
},
|
|
252
|
+
]);
|
|
253
|
+
|
|
254
|
+
expect(result.updatedUrls).toBe(1);
|
|
255
|
+
expect(result.updatedTexts).toBe(1);
|
|
256
|
+
});
|
|
257
|
+
});
|
|
258
|
+
|
|
259
|
+
describe('findMatchingApiResult', () => {
|
|
260
|
+
it('should match by Content_ID', () => {
|
|
261
|
+
const apiResultsMap = new Map([['TSRC-ABC-123456', { title: 'Found Doc' }]]);
|
|
262
|
+
|
|
263
|
+
const result = processor.findMatchingApiResult(
|
|
264
|
+
'https://thesource.cvshealth.com/doc?Content_ID=TSRC-ABC-123456',
|
|
265
|
+
apiResultsMap
|
|
266
|
+
);
|
|
267
|
+
|
|
268
|
+
expect(result).toEqual({ title: 'Found Doc' });
|
|
269
|
+
});
|
|
270
|
+
|
|
271
|
+
it('should match by Document_ID (UUID)', () => {
|
|
272
|
+
const uuid = '12345678-1234-1234-1234-123456789abc';
|
|
273
|
+
const apiResultsMap = new Map([[uuid, { title: 'UUID Doc' }]]);
|
|
274
|
+
|
|
275
|
+
const result = processor.findMatchingApiResult(
|
|
276
|
+
`https://thesource.cvshealth.com/nuxeo/thesource/#!/view?docid=${uuid}`,
|
|
277
|
+
apiResultsMap
|
|
278
|
+
);
|
|
279
|
+
|
|
280
|
+
expect(result).toEqual({ title: 'UUID Doc' });
|
|
281
|
+
});
|
|
282
|
+
|
|
283
|
+
it('should return null for URLs without IDs', () => {
|
|
284
|
+
const apiResultsMap = new Map([['TSRC-ABC-123456', { title: 'Doc' }]]);
|
|
285
|
+
|
|
286
|
+
const result = processor.findMatchingApiResult('https://example.com/page', apiResultsMap);
|
|
287
|
+
|
|
288
|
+
expect(result).toBeNull();
|
|
289
|
+
});
|
|
290
|
+
|
|
291
|
+
it('should return null for empty map', () => {
|
|
292
|
+
const result = processor.findMatchingApiResult(
|
|
293
|
+
'https://thesource.cvshealth.com/doc?Content_ID=TSRC-ABC-123456',
|
|
294
|
+
new Map()
|
|
295
|
+
);
|
|
296
|
+
|
|
297
|
+
expect(result).toBeNull();
|
|
298
|
+
});
|
|
299
|
+
});
|
|
300
|
+
});
|
|
301
|
+
|
|
302
|
+
// Helper function to create mock hyperlink
|
|
303
|
+
function createMockHyperlink(url: string, text: string): Mocked<Hyperlink> {
|
|
304
|
+
return {
|
|
305
|
+
getUrl: vi.fn().mockReturnValue(url),
|
|
306
|
+
getText: vi.fn().mockReturnValue(text),
|
|
307
|
+
setText: vi.fn(),
|
|
308
|
+
setUrl: vi.fn(),
|
|
309
|
+
setFormatting: vi.fn(),
|
|
310
|
+
getFormatting: vi.fn().mockReturnValue({}),
|
|
311
|
+
getAnchor: vi.fn().mockReturnValue(null),
|
|
312
|
+
clone: vi.fn(),
|
|
313
|
+
} as unknown as Mocked<Hyperlink>;
|
|
314
|
+
}
|
|
@@ -0,0 +1,291 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Test Suite for ListProcessor
|
|
3
|
+
*
|
|
4
|
+
* Tests list bullet settings, indentation, and numbered list formatting.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { vi, describe, it, expect, beforeEach, type Mocked } from 'vitest';
|
|
8
|
+
import { ListProcessor, ListBulletSettings } from '../ListProcessor';
|
|
9
|
+
import { Document, Paragraph } from 'docxmlater';
|
|
10
|
+
|
|
11
|
+
// Mock docxmlater
|
|
12
|
+
vi.mock('docxmlater');
|
|
13
|
+
|
|
14
|
+
describe('ListProcessor', () => {
|
|
15
|
+
let processor: ListProcessor;
|
|
16
|
+
let mockDoc: Mocked<Document>;
|
|
17
|
+
|
|
18
|
+
beforeEach(() => {
|
|
19
|
+
vi.clearAllMocks();
|
|
20
|
+
processor = new ListProcessor();
|
|
21
|
+
|
|
22
|
+
mockDoc = {
|
|
23
|
+
getAllParagraphs: vi.fn().mockReturnValue([]),
|
|
24
|
+
getPart: vi.fn().mockResolvedValue(null),
|
|
25
|
+
setPart: vi.fn().mockResolvedValue(undefined),
|
|
26
|
+
getNumberingManager: vi.fn().mockReturnValue(null),
|
|
27
|
+
} as unknown as Mocked<Document>;
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
describe('applyListIndentation', () => {
|
|
31
|
+
it('should apply indentation to list items', async () => {
|
|
32
|
+
const mockParagraph = createMockListParagraph(0, 1);
|
|
33
|
+
mockDoc.getAllParagraphs.mockReturnValue([mockParagraph]);
|
|
34
|
+
|
|
35
|
+
const settings: ListBulletSettings = {
|
|
36
|
+
enabled: true,
|
|
37
|
+
indentationLevels: [
|
|
38
|
+
{ level: 0, symbolIndent: 0.5, textIndent: 0.75 },
|
|
39
|
+
{ level: 1, symbolIndent: 1.0, textIndent: 1.25 },
|
|
40
|
+
],
|
|
41
|
+
spacingBetweenItems: 6,
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
const result = await processor.applyListIndentation(mockDoc, settings);
|
|
45
|
+
|
|
46
|
+
expect(result.listsUpdated).toBe(1);
|
|
47
|
+
expect(mockParagraph.setLeftIndent).toHaveBeenCalled();
|
|
48
|
+
expect(mockParagraph.setSpaceAfter).toHaveBeenCalledWith(120); // 6 * 20 twips
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
it('should skip non-list paragraphs', async () => {
|
|
52
|
+
const mockParagraph = createMockNormalParagraph();
|
|
53
|
+
mockDoc.getAllParagraphs.mockReturnValue([mockParagraph]);
|
|
54
|
+
|
|
55
|
+
const settings: ListBulletSettings = {
|
|
56
|
+
enabled: true,
|
|
57
|
+
indentationLevels: [{ level: 0, symbolIndent: 0.5, textIndent: 0.75 }],
|
|
58
|
+
spacingBetweenItems: 0,
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
const result = await processor.applyListIndentation(mockDoc, settings);
|
|
62
|
+
|
|
63
|
+
expect(result.listsUpdated).toBe(0);
|
|
64
|
+
expect(mockParagraph.setLeftIndent).not.toHaveBeenCalled();
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
it('should return zero counts when disabled', async () => {
|
|
68
|
+
const settings: ListBulletSettings = {
|
|
69
|
+
enabled: false,
|
|
70
|
+
indentationLevels: [],
|
|
71
|
+
spacingBetweenItems: 0,
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
const result = await processor.applyListIndentation(mockDoc, settings);
|
|
75
|
+
|
|
76
|
+
expect(result.listsUpdated).toBe(0);
|
|
77
|
+
expect(result.levelsProcessed).toBe(0);
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
it('should handle multiple list levels', async () => {
|
|
81
|
+
const level0Para = createMockListParagraph(0, 1);
|
|
82
|
+
const level1Para = createMockListParagraph(1, 1);
|
|
83
|
+
const level2Para = createMockListParagraph(2, 1);
|
|
84
|
+
|
|
85
|
+
mockDoc.getAllParagraphs.mockReturnValue([level0Para, level1Para, level2Para]);
|
|
86
|
+
|
|
87
|
+
const settings: ListBulletSettings = {
|
|
88
|
+
enabled: true,
|
|
89
|
+
indentationLevels: [
|
|
90
|
+
{ level: 0, symbolIndent: 0.5, textIndent: 0.75 },
|
|
91
|
+
{ level: 1, symbolIndent: 1.0, textIndent: 1.25 },
|
|
92
|
+
{ level: 2, symbolIndent: 1.5, textIndent: 1.75 },
|
|
93
|
+
],
|
|
94
|
+
spacingBetweenItems: 0,
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
const result = await processor.applyListIndentation(mockDoc, settings);
|
|
98
|
+
|
|
99
|
+
expect(result.listsUpdated).toBe(3);
|
|
100
|
+
expect(level0Para.setLeftIndent).toHaveBeenCalled();
|
|
101
|
+
expect(level1Para.setLeftIndent).toHaveBeenCalled();
|
|
102
|
+
expect(level2Para.setLeftIndent).toHaveBeenCalled();
|
|
103
|
+
});
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
describe('standardizeListPrefixFormatting', () => {
|
|
107
|
+
it('should standardize list prefix formatting to Verdana', async () => {
|
|
108
|
+
const mockLevel = createMockNumberingLevel('Arial');
|
|
109
|
+
const mockAbstractNum = {
|
|
110
|
+
getLevel: vi.fn((idx: number) => (idx === 0 ? mockLevel : null)),
|
|
111
|
+
};
|
|
112
|
+
const mockNumberingManager = {
|
|
113
|
+
getAllAbstractNumberings: vi.fn().mockReturnValue([mockAbstractNum]),
|
|
114
|
+
};
|
|
115
|
+
mockDoc.getNumberingManager = vi.fn().mockReturnValue(mockNumberingManager);
|
|
116
|
+
|
|
117
|
+
const count = await processor.standardizeListPrefixFormatting(mockDoc);
|
|
118
|
+
|
|
119
|
+
expect(count).toBe(1);
|
|
120
|
+
expect(mockLevel.setFont).toHaveBeenCalledWith('Verdana');
|
|
121
|
+
expect(mockLevel.setColor).toHaveBeenCalledWith('000000');
|
|
122
|
+
expect(mockLevel.setFontSize).toHaveBeenCalledWith(24);
|
|
123
|
+
expect(mockLevel.setBold).toHaveBeenCalledWith(false);
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
it('should handle missing numbering manager', async () => {
|
|
127
|
+
mockDoc.getNumberingManager = vi.fn().mockReturnValue(null);
|
|
128
|
+
|
|
129
|
+
const count = await processor.standardizeListPrefixFormatting(mockDoc);
|
|
130
|
+
|
|
131
|
+
expect(count).toBe(0);
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
it('should preserve special bullet fonts', async () => {
|
|
135
|
+
const mockLevel = createMockNumberingLevel('Symbol');
|
|
136
|
+
const mockAbstractNum = {
|
|
137
|
+
getLevel: vi.fn((idx: number) => (idx === 0 ? mockLevel : null)),
|
|
138
|
+
};
|
|
139
|
+
const mockNumberingManager = {
|
|
140
|
+
getAllAbstractNumberings: vi.fn().mockReturnValue([mockAbstractNum]),
|
|
141
|
+
};
|
|
142
|
+
mockDoc.getNumberingManager = vi.fn().mockReturnValue(mockNumberingManager);
|
|
143
|
+
|
|
144
|
+
await processor.standardizeListPrefixFormatting(mockDoc);
|
|
145
|
+
|
|
146
|
+
// Symbol font should be preserved, not replaced with Verdana
|
|
147
|
+
expect(mockLevel.setFont).toHaveBeenCalledWith('Symbol');
|
|
148
|
+
expect(mockLevel.setBold).toHaveBeenCalledWith(false);
|
|
149
|
+
});
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
describe('isBulletList', () => {
|
|
153
|
+
it('should identify bullet lists', () => {
|
|
154
|
+
const mockAbstractNum = {
|
|
155
|
+
getLevel: vi.fn().mockReturnValue({
|
|
156
|
+
getFormat: vi.fn().mockReturnValue('bullet'),
|
|
157
|
+
}),
|
|
158
|
+
};
|
|
159
|
+
const mockInstance = {
|
|
160
|
+
getAbstractNumId: vi.fn().mockReturnValue(0),
|
|
161
|
+
};
|
|
162
|
+
const mockNumberingManager = {
|
|
163
|
+
getNumberingInstance: vi.fn().mockReturnValue(mockInstance),
|
|
164
|
+
getAbstractNumbering: vi.fn().mockReturnValue(mockAbstractNum),
|
|
165
|
+
};
|
|
166
|
+
mockDoc.getNumberingManager = vi.fn().mockReturnValue(mockNumberingManager);
|
|
167
|
+
|
|
168
|
+
const result = processor.isBulletList(mockDoc, 1);
|
|
169
|
+
|
|
170
|
+
expect(result).toBe(true);
|
|
171
|
+
});
|
|
172
|
+
|
|
173
|
+
it('should return false for numbered lists', () => {
|
|
174
|
+
const mockAbstractNum = {
|
|
175
|
+
getLevel: vi.fn().mockReturnValue({
|
|
176
|
+
getFormat: vi.fn().mockReturnValue('decimal'),
|
|
177
|
+
}),
|
|
178
|
+
};
|
|
179
|
+
const mockInstance = {
|
|
180
|
+
getAbstractNumId: vi.fn().mockReturnValue(0),
|
|
181
|
+
};
|
|
182
|
+
const mockNumberingManager = {
|
|
183
|
+
getNumberingInstance: vi.fn().mockReturnValue(mockInstance),
|
|
184
|
+
getAbstractNumbering: vi.fn().mockReturnValue(mockAbstractNum),
|
|
185
|
+
};
|
|
186
|
+
mockDoc.getNumberingManager = vi.fn().mockReturnValue(mockNumberingManager);
|
|
187
|
+
|
|
188
|
+
const result = processor.isBulletList(mockDoc, 1);
|
|
189
|
+
|
|
190
|
+
expect(result).toBe(false);
|
|
191
|
+
});
|
|
192
|
+
});
|
|
193
|
+
|
|
194
|
+
describe('isNumberedList', () => {
|
|
195
|
+
it('should identify decimal numbered lists', () => {
|
|
196
|
+
const mockAbstractNum = {
|
|
197
|
+
getLevel: vi.fn().mockReturnValue({
|
|
198
|
+
getFormat: vi.fn().mockReturnValue('decimal'),
|
|
199
|
+
}),
|
|
200
|
+
};
|
|
201
|
+
const mockInstance = {
|
|
202
|
+
getAbstractNumId: vi.fn().mockReturnValue(0),
|
|
203
|
+
};
|
|
204
|
+
const mockNumberingManager = {
|
|
205
|
+
getNumberingInstance: vi.fn().mockReturnValue(mockInstance),
|
|
206
|
+
getAbstractNumbering: vi.fn().mockReturnValue(mockAbstractNum),
|
|
207
|
+
};
|
|
208
|
+
mockDoc.getNumberingManager = vi.fn().mockReturnValue(mockNumberingManager);
|
|
209
|
+
|
|
210
|
+
const result = processor.isNumberedList(mockDoc, 1);
|
|
211
|
+
|
|
212
|
+
expect(result).toBe(true);
|
|
213
|
+
});
|
|
214
|
+
|
|
215
|
+
it('should identify letter numbered lists', () => {
|
|
216
|
+
const mockAbstractNum = {
|
|
217
|
+
getLevel: vi.fn().mockReturnValue({
|
|
218
|
+
getFormat: vi.fn().mockReturnValue('lowerLetter'),
|
|
219
|
+
}),
|
|
220
|
+
};
|
|
221
|
+
const mockInstance = {
|
|
222
|
+
getAbstractNumId: vi.fn().mockReturnValue(0),
|
|
223
|
+
};
|
|
224
|
+
const mockNumberingManager = {
|
|
225
|
+
getNumberingInstance: vi.fn().mockReturnValue(mockInstance),
|
|
226
|
+
getAbstractNumbering: vi.fn().mockReturnValue(mockAbstractNum),
|
|
227
|
+
};
|
|
228
|
+
mockDoc.getNumberingManager = vi.fn().mockReturnValue(mockNumberingManager);
|
|
229
|
+
|
|
230
|
+
const result = processor.isNumberedList(mockDoc, 1);
|
|
231
|
+
|
|
232
|
+
expect(result).toBe(true);
|
|
233
|
+
});
|
|
234
|
+
|
|
235
|
+
it('should return false for bullet lists', () => {
|
|
236
|
+
const mockAbstractNum = {
|
|
237
|
+
getLevel: vi.fn().mockReturnValue({
|
|
238
|
+
getFormat: vi.fn().mockReturnValue('bullet'),
|
|
239
|
+
}),
|
|
240
|
+
};
|
|
241
|
+
const mockInstance = {
|
|
242
|
+
getAbstractNumId: vi.fn().mockReturnValue(0),
|
|
243
|
+
};
|
|
244
|
+
const mockNumberingManager = {
|
|
245
|
+
getNumberingInstance: vi.fn().mockReturnValue(mockInstance),
|
|
246
|
+
getAbstractNumbering: vi.fn().mockReturnValue(mockAbstractNum),
|
|
247
|
+
};
|
|
248
|
+
mockDoc.getNumberingManager = vi.fn().mockReturnValue(mockNumberingManager);
|
|
249
|
+
|
|
250
|
+
const result = processor.isNumberedList(mockDoc, 1);
|
|
251
|
+
|
|
252
|
+
expect(result).toBe(false);
|
|
253
|
+
});
|
|
254
|
+
});
|
|
255
|
+
});
|
|
256
|
+
|
|
257
|
+
// Helper functions
|
|
258
|
+
|
|
259
|
+
function createMockListParagraph(level: number, numId: number): Mocked<Paragraph> {
|
|
260
|
+
return {
|
|
261
|
+
getNumbering: vi.fn().mockReturnValue({ level, numId }),
|
|
262
|
+
setLeftIndent: vi.fn().mockReturnThis(),
|
|
263
|
+
setFirstLineIndent: vi.fn().mockReturnThis(),
|
|
264
|
+
setSpaceAfter: vi.fn(),
|
|
265
|
+
getText: vi.fn().mockReturnValue('List item'),
|
|
266
|
+
getStyle: vi.fn().mockReturnValue('ListParagraph'),
|
|
267
|
+
} as unknown as Mocked<Paragraph>;
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
function createMockNumberingLevel(font: string) {
|
|
271
|
+
return {
|
|
272
|
+
getProperties: vi.fn().mockReturnValue({ font }),
|
|
273
|
+
getFormat: vi.fn().mockReturnValue('bullet'),
|
|
274
|
+
setFont: vi.fn().mockReturnThis(),
|
|
275
|
+
setColor: vi.fn().mockReturnThis(),
|
|
276
|
+
setFontSize: vi.fn().mockReturnThis(),
|
|
277
|
+
setBold: vi.fn().mockReturnThis(),
|
|
278
|
+
setText: vi.fn().mockReturnThis(),
|
|
279
|
+
};
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
function createMockNormalParagraph(): Mocked<Paragraph> {
|
|
283
|
+
return {
|
|
284
|
+
getNumbering: vi.fn().mockReturnValue(null),
|
|
285
|
+
setLeftIndent: vi.fn().mockReturnThis(),
|
|
286
|
+
setFirstLineIndent: vi.fn().mockReturnThis(),
|
|
287
|
+
setSpaceAfter: vi.fn(),
|
|
288
|
+
getText: vi.fn().mockReturnValue('Normal paragraph'),
|
|
289
|
+
getStyle: vi.fn().mockReturnValue('Normal'),
|
|
290
|
+
} as unknown as Mocked<Paragraph>;
|
|
291
|
+
}
|