|
1 | 1 | /* eslint-disable */ |
2 | | -/* |
3 | | - * Editor mocks |
| 2 | +/** |
| 3 | + * Editor mocks with Proxy |
4 | 4 | * |
5 | | - * Note: nested object example data are there for reference only -- will need to be deleted or cleaned up before use (consider using a factory) |
6 | | - * For functions: check whether async or not & add params & return value |
| 5 | + * Editor and Note share many of the same properties+methods (CoreNoteFields), so most of them are defined in Note.mock.js and can apply to both. |
7 | 6 | * |
8 | | - * TODO: IMPORTANT NOTE |
9 | | - * - @dwertheimer started adding some of the underlying methods to Note.mock.js, but it's not complete |
10 | | - * - if you need to add a method to Editor that's in Note also, add it to Note.mock.js and then add it here |
| 7 | + * This module uses a JavaScript Proxy to redirect all function calls to the underlying `note` object unless specifically overridden. |
| 8 | + * The `get` trap in the Proxy checks if a property exists on the `Editor` object. If it does, it returns that property. |
| 9 | + * If not, it delegates the call to the `note` object. If the property is not found in either, it throws an error. |
11 | 10 | * |
| 11 | + * To override a function that is not in the underlying `note`, simply define it in the `editorOverrides` object. |
| 12 | + * |
| 13 | + * Note: All `open*` functions are specifically overridden to return `this.note`. |
12 | 14 | */ |
13 | 15 |
|
14 | 16 | import { Note } from './Note.mock' |
15 | | -const blankNote = new Note() // NOTE: try to reference the code in the Note mock wherever possible! |
16 | | -// NOTE: blankNote is spread into Editor below, so any properties that exist in Note will overwrite the ones in Editor |
| 17 | +const noteObject = new Note() // NOTE: try to reference the code in the Note mock wherever possible! |
| 18 | +// NOTE: noteObject is spread into Editor below, so any properties that exist in Note will overwrite the ones in Editor |
17 | 19 |
|
18 | | -export const Editor = { |
| 20 | +const editorOverrides = { |
19 | 21 | ...{ |
20 | | - syncEditorWithNote() { |
21 | | - this.paragraphs = this.note.paragraphs |
22 | | - this.content = this.note.content |
23 | | - // add other fields as needed |
24 | | - }, |
25 | | - note: blankNote, |
26 | | - addBlockID(p) { |
27 | | - return this.note.addBlockID(p) |
28 | | - }, |
29 | | - // async addParagraphBelowHeadingTitle() { return null }, |
30 | | - // async addTheme() { return null }, |
31 | | - // async addTodoBelowHeadingTitle() { return null }, |
32 | | - async appendParagraph(title = 'mock tester', type: 'text') { |
33 | | - return this.note.appendParagraph(title, type) |
34 | | - }, |
35 | | - // async appendParagraphBelowHeadingLineIndex() { return null }, |
36 | | - // async appendTodo() { return null }, |
37 | | - // async appendTodoBelowHeadingLineIndex() { return null }, |
38 | | - /* availableThemes: [{ return default }], */ |
39 | | - // content: VALUE , |
40 | | - // async copySelection() { return null }, |
41 | | - filename: 'thisFileName.txt', |
42 | | - // async highlight() { return null }, |
43 | | - // async highlightByIndex() { return null }, |
44 | | - // async highlightByRange() { return null }, |
45 | | - // async insertCancelledTodo() { return null }, |
46 | | - // async insertCompletedTodo() { return null }, |
47 | | - // async insertHeading() { return null }, |
48 | | - // async insertList() { return null }, |
49 | | - // insertParagraph(name = 'mock tester', lineIndex = 1, type: 'text') { |
50 | | - // return blankNote.insertParagraph(name, lineIndex, type) |
51 | | - // }, |
52 | | - // async insertParagraphAfterParagraph() { return null }, |
53 | | - // async insertParagraphAtCursor() { return null }, |
54 | | - // async insertParagraphBeforeParagraph() { return null }, |
55 | | - // async insertQuote() { return null }, |
56 | | - // async insertScheduledTodo() { return null }, |
57 | | - async insertTextAtCharacterIndex(text = '', length = 0) { |
58 | | - this.note.insertTextAtCharacterIndex(text, length) |
59 | | - this.syncEditorWithNote() |
60 | | - }, |
61 | | - async insertTextAtCursor(text: string) { |
62 | | - this.note.insertTextAtCursor(text) |
63 | | - this.syncEditorWithNote() |
64 | | - }, |
65 | | - // async insertTodo() { return null }, |
66 | | - // async insertTodoAfterParagraph() { return null }, |
67 | | - // async insertTodoBeforeParagraph() { return null }, |
68 | | - async isFolded(para) { |
69 | | - return false |
70 | | - }, |
71 | 22 | async openNoteByDate(date: Date, newWindow?: boolean, highlightStart?: number, highlightEnd?: number, splitView?: boolean, timeframe?: string): Promise<TNote> { |
72 | | - return this.note |
73 | | - }, |
74 | | - // async openNoteByDateString() { return null }, |
75 | | - async openNoteByFilename() { |
76 | | - return this.note |
77 | | - }, |
78 | | - // async openNoteByTitle() { return null }, |
79 | | - // async openNoteByTitleCaseInsensitive() { return null }, |
80 | | - async paragraphRangeAtCharacterIndex() { |
81 | | - return null |
82 | | - }, |
83 | | - /* paragraphs: [{ return { |
84 | | - "type": "title", |
85 | | - "content": "MyNoteTitle", |
86 | | - "rawContent": "# MyNoteTitle", |
87 | | - "prefix": "# ", |
88 | | - "contentRange": {}, |
89 | | - "lineIndex": 0, |
90 | | - "heading": "", |
91 | | - "headingLevel": 1, |
92 | | - "isRecurring": false, |
93 | | - "indents": 0, |
94 | | - "filename": "_TEST/New Note - 15.3950.md", |
95 | | - "noteType": "Notes", |
96 | | - "linkedNoteTitles": [], |
97 | | - "subItems": [], |
98 | | - "referencedBlocks": [], |
99 | | - "note": {} |
100 | | -} }], */ |
101 | | - // async pasteClipboard() { return null }, |
102 | | - // async prependParagraph() { return null }, |
103 | | - // async prependTodo() { return null }, |
104 | | - // async printNote() { return null }, |
105 | | - // async removeBlockID() { return null }, |
106 | | - |
107 | | - async removeParagraph(para) { |
108 | | - this.note.removeParagraph(para) |
109 | | - this.syncEditorWithNote() |
110 | | - return |
| 23 | + return noteObject |
111 | 24 | }, |
112 | | - async removeParagraphs(paras) { |
113 | | - this.note.removeParagraphs(paras) |
114 | | - this.syncEditorWithNote() |
115 | | - return |
| 25 | + async openNoteByDateString() { |
| 26 | + return noteObject |
116 | 27 | }, |
117 | | - |
118 | | - // async removeParagraphAtIndex() { return null }, |
119 | | - // async renderedSelect() { return null }, |
120 | | - /* renderedSelection: { |
121 | | - "start": 36, |
122 | | - "end": 36, |
123 | | - "length": 0 |
124 | | -} , */ |
125 | | - // async replaceSelectionWithText() { return null }, |
126 | | - // async replaceTextInCharacterRange() { return null }, |
127 | | - // async select() { return null }, |
128 | | - // async selectAll() { return null }, |
129 | | - /* selectedLinesText: [{ return * one task in the note }], */ |
130 | | - /* selectedParagraphs: [{ return { |
131 | | - "type": "open", |
132 | | - "content": "one task in the note", |
133 | | - "rawContent": "* one task in the note", |
134 | | - "prefix": "* ", |
135 | | - "contentRange": {}, |
136 | | - "lineIndex": 0, |
137 | | - "heading": "", |
138 | | - "headingLevel": -1, |
139 | | - "isRecurring": false, |
140 | | - "indents": 0, |
141 | | - "filename": "_TEST/New Note - 15.3950.md", |
142 | | - "noteType": "Notes", |
143 | | - "linkedNoteTitles": [], |
144 | | - "subItems": [], |
145 | | - "referencedBlocks": [], |
146 | | - "note": {} |
147 | | -} }], */ |
148 | | - // selectedText: VALUE , |
149 | | - /* selection: { |
150 | | - "start": 36, |
151 | | - "end": 36, |
152 | | - "length": 0 |
153 | | -} , */ |
154 | | - // async setTheme() { return null }, |
155 | | - // title: VALUE , |
156 | | - async toggleFolding() { |
157 | | - return null |
| 28 | + async openNoteByFilename() { |
| 29 | + return noteObject |
158 | 30 | }, |
159 | | - // type: VALUE , |
160 | | - |
161 | | - async updateParagraph(para) { |
162 | | - this.note.updateParagraph(para) |
163 | | - this.syncEditorWithNote() |
| 31 | + async openNoteByTitle() { |
| 32 | + return noteObject |
164 | 33 | }, |
165 | | - async updateParagraphs(paras) { |
166 | | - this.note.updateParagraphs(paras) |
167 | | - this.syncEditorWithNote() |
| 34 | + async openNoteByTitleCaseInsensitive() { |
| 35 | + return noteObject |
168 | 36 | }, |
| 37 | + note: noteObject, |
169 | 38 | }, |
170 | | - ...blankNote, |
| 39 | + ...noteObject, |
171 | 40 | } |
172 | 41 |
|
173 | | -// module.exports = Editor |
| 42 | +export const Editor = new Proxy(editorOverrides, { |
| 43 | + get(target, prop) { |
| 44 | + if (prop in target) { |
| 45 | + return target[prop] |
| 46 | + } |
| 47 | + if (prop in target.note) { |
| 48 | + return target.note[prop] |
| 49 | + } |
| 50 | + // Handle known built-in Symbol properties with sensible defaults |
| 51 | + const symbolProperties = [Symbol.iterator, Symbol.toPrimitive, Symbol.asyncIterator, Symbol.hasInstance, Symbol.toStringTag] |
| 52 | + if (symbolProperties.includes(prop)) { |
| 53 | + if (prop === Symbol.iterator) return undefined |
| 54 | + if (prop === Symbol.toPrimitive) return (hint) => (hint === 'number' ? NaN : String(target.note)) |
| 55 | + if (prop === Symbol.asyncIterator) return undefined |
| 56 | + if (prop === Symbol.hasInstance) return undefined |
| 57 | + if (prop === Symbol.toStringTag) return 'Editor' |
| 58 | + } |
| 59 | + // Handle Jest specific methods that are not defined on Note and which should not cause errors |
| 60 | + if (['asymmetricMatch'].includes(prop)) { |
| 61 | + return undefined |
| 62 | + } |
| 63 | + // Throw detailed error if property is not found |
| 64 | + throw new Error( |
| 65 | + `Editor.mock.js: Property "${String(prop)}" not found. Editor.${String(prop)} or Note.${String(prop)} does not exist.\n` + |
| 66 | + `- Check if this property/method should be implemented in Note.mock.js.\n` + |
| 67 | + `- If it's Editor-specific, consider adding it to Editor.mock.js overrides in editorOverrides.\n` + |
| 68 | + `- If this is a Jest-specific method (such as 'asymmetricMatch') or a built-in Symbol (e.g., Symbol.iterator, Symbol.toPrimitive), ` + |
| 69 | + `return a sensible default instead.\n`, |
| 70 | + ) |
| 71 | + }, |
| 72 | +}) |
0 commit comments