-
Notifications
You must be signed in to change notification settings - Fork 16
Create text editor test suite #3508
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
📝 WalkthroughWalkthroughThis change set adds a comprehensive ProseMirror testing toolkit: schema builders, editor state/view builders, content generators, command testing utilities, and event simulators, along with corresponding Jest test suites and documentation. Additionally, a table plugin helper (createStyleAttribute) is now exported to support testing. Changes
Sequence Diagram(s)sequenceDiagram
autonumber
actor Tester
participant State as EditorState
participant View as EditorView
participant Cmd as Command
participant PM as ProseMirror
rect rgba(224,240,255,0.5)
note right of Tester: testCommand / getCommandResult
Tester->>PM: Create State (optional content/plugins)
PM-->>State: EditorState
Tester->>Cmd: invoke(state, dispatch[, view])
Cmd-->>Tester: boolean result
alt result is true
Cmd->>Tester: dispatch(tr)
Tester->>State: state.apply(tr)
State-->>Tester: newState
Tester->>Tester: assertions (docContentAfter / size / includes)
else result is false
Tester-->>Tester: assertions on failure
end
end
rect rgba(232,255,232,0.5)
note over Tester,View: testCommandWithView
Tester->>PM: create EditorView(state)
PM-->>View: EditorView
Tester->>Cmd: invoke(state, dispatch, view)
Cmd->>Tester: dispatch(tr)
Tester->>View: view.updateState(state.apply(tr))
Tester-->>Tester: assertions on view.state
end
sequenceDiagram
autonumber
actor Tester
participant ES as EventSimulator
participant View as EditorView
participant DOM as view.dom
rect rgba(255,245,225,0.6)
note over Tester,View: simulateDragAndDrop
Tester->>ES: simulateDragAndDrop(view, start, end, data?)
ES->>DOM: mousedown
ES->>DOM: dragstart (dataTransfer?)
ES->>DOM: dragover
ES->>DOM: drop
ES->>DOM: mouseup
DOM-->>Tester: dispatched events (handled flags)
end
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Suggested reviewers
Pre-merge checks and finishing touches✅ Passed checks (3 passed)
✨ Finishing touches
🧪 Generate unit tests
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
Documentation has been published to https://lundalogik.github.io/lime-elements/versions/PR-3508/ |
0bb61a1 to
fb9a5ab
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
This PR adds a comprehensive test suite for the text editor, enhancing test coverage for editor view utilities, ProseMirror adapter plugins (including table support), event simulation helpers, schema/state builders, content generation utilities, and command testing utilities.
- Introduces tests for editor view creation, dispatch spies, and cleanup routines.
- Adds tests for plugins (e.g. table editing) and supporting helper functions.
- Expands test coverage for state creation, content parsing and command execution.
Reviewed Changes
Copilot reviewed 14 out of 14 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
| src/components/text-editor/test-setup/editor-view-builder.spec.ts | Tests for editor view creation and cleanup utilities |
| src/components/text-editor/prosemirror-adapter/plugins/table-plugin.spec.ts | Tests for table plugin functionality and style attribute helpers |
| src/components/text-editor/test-setup/schema-builder.spec.ts | Schema creation tests including custom configuration |
| src/components/text-editor/test-setup/event-simulator.ts | Event simulation functions for key, paste, click, and drag operations |
| src/components/text-editor/test-setup/command-tester.ts | Command tester utilities for verifying command outcomes |
| src/components/text-editor/test-setup/editor-state-builder.spec.ts | Tests for state creation, selection setting, and document generation |
| src/components/text-editor/test-setup/content-generator.spec.ts | Tests for generating documents from text, HTML, block elements, etc. |
| src/components/text-editor/prosemirror-adapter/plugins/table-plugin.ts | Updates to export the style attribute helper |
Comments suppressed due to low confidence (2)
src/components/text-editor/test-setup/event-simulator.ts:105
- [nitpick] Consider consistently using MockDataTransfer in test environments to avoid discrepancies between environments where DataTransfer might exist partially; this can help ensure uniform behavior in tests.
const dataTransfer = typeof DataTransfer !== 'undefined' ? new DataTransfer() : new MockDataTransfer();
src/components/text-editor/test-setup/content-generator.ts:79
- [nitpick] Enhance the error message to include context (e.g. available mark types) so that debugging missing mark issues becomes easier.
throw new Error(`Mark type "${markSpec.type}" not found in schema`);
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 6
📜 Review details
Configuration used: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
📒 Files selected for processing (14)
src/components/text-editor/prosemirror-adapter/plugins/table-plugin.spec.ts(1 hunks)src/components/text-editor/prosemirror-adapter/plugins/table-plugin.ts(1 hunks)src/components/text-editor/test-setup/command-tester.spec.ts(1 hunks)src/components/text-editor/test-setup/command-tester.ts(1 hunks)src/components/text-editor/test-setup/content-generator.spec.ts(1 hunks)src/components/text-editor/test-setup/content-generator.ts(1 hunks)src/components/text-editor/test-setup/editor-state-builder.spec.ts(1 hunks)src/components/text-editor/test-setup/editor-state-builder.ts(1 hunks)src/components/text-editor/test-setup/editor-view-builder.spec.ts(1 hunks)src/components/text-editor/test-setup/editor-view-builder.ts(1 hunks)src/components/text-editor/test-setup/event-simulator.spec.ts(1 hunks)src/components/text-editor/test-setup/event-simulator.ts(1 hunks)src/components/text-editor/test-setup/schema-builder.spec.ts(1 hunks)src/components/text-editor/test-setup/schema-builder.ts(1 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
`**/*.{ts,tsx}`: Imports from other files in the same module (lime-elements) must use relative paths. Using absolute paths for imports will cause the production build to fail.
**/*.{ts,tsx}: Imports from other files in the same module (lime-elements) must use relative paths. Using absolute paths for imports will cause the production build to fail.
src/components/text-editor/prosemirror-adapter/plugins/table-plugin.tssrc/components/text-editor/test-setup/schema-builder.spec.tssrc/components/text-editor/test-setup/schema-builder.tssrc/components/text-editor/test-setup/editor-state-builder.spec.tssrc/components/text-editor/test-setup/event-simulator.spec.tssrc/components/text-editor/prosemirror-adapter/plugins/table-plugin.spec.tssrc/components/text-editor/test-setup/content-generator.spec.tssrc/components/text-editor/test-setup/command-tester.spec.tssrc/components/text-editor/test-setup/event-simulator.tssrc/components/text-editor/test-setup/command-tester.tssrc/components/text-editor/test-setup/editor-state-builder.tssrc/components/text-editor/test-setup/editor-view-builder.tssrc/components/text-editor/test-setup/content-generator.tssrc/components/text-editor/test-setup/editor-view-builder.spec.ts
🧬 Code Definitions (7)
src/components/text-editor/test-setup/schema-builder.spec.ts (1)
src/components/text-editor/test-setup/schema-builder.ts (2)
createTestSchema(12-33)createCustomTestSchema(42-87)
src/components/text-editor/test-setup/editor-state-builder.spec.ts (1)
src/components/text-editor/test-setup/editor-state-builder.ts (4)
createEditorState(14-29)createEditorStateWithSelection(41-59)setTextSelection(69-77)createDocumentWithText(100-107)
src/components/text-editor/test-setup/event-simulator.spec.ts (1)
src/components/text-editor/test-setup/event-simulator.ts (6)
simulateKeyPress(63-84)KeyModifiers(48-53)PasteData(89-93)simulatePaste(102-139)simulateClick(152-191)simulateDragAndDrop(204-288)
src/components/text-editor/prosemirror-adapter/plugins/table-plugin.spec.ts (1)
src/components/text-editor/prosemirror-adapter/plugins/table-plugin.ts (3)
getTableEditingPlugins(4-10)getTableNodes(22-31)createStyleAttribute(12-20)
src/components/text-editor/test-setup/content-generator.spec.ts (1)
src/components/text-editor/test-setup/content-generator.ts (8)
createDocWithText(13-18)createDocWithHTML(27-31)MarkSpec(36-39)createDocWithFormattedText(49-61)createDocWithBulletList(97-118)createDocWithHeading(128-144)createDocWithBlockquote(153-166)createDocWithCodeBlock(175-187)
src/components/text-editor/test-setup/command-tester.spec.ts (1)
src/components/text-editor/test-setup/command-tester.ts (4)
getCommandResult(29-60)testCommand(74-120)testCommandWithView(130-185)createCommandTester(193-202)
src/components/text-editor/test-setup/editor-view-builder.spec.ts (1)
src/components/text-editor/test-setup/editor-view-builder.ts (4)
cleanupEditorView(84-93)createEditorView(14-46)createDispatchSpy(54-75)mockProseMirrorDOMEnvironment(101-143)
🪛 Biome (1.9.4)
src/components/text-editor/test-setup/content-generator.spec.ts
[error] 119-119: Change to an optional chain.
Unsafe fix: Change to an optional chain.
(lint/complexity/useOptionalChain)
src/components/text-editor/test-setup/editor-state-builder.ts
[error] 101-101: This type annotation is trivially inferred from its initialization.
Safe fix: Remove the type annotation.
(lint/style/noInferrableTypes)
src/components/text-editor/test-setup/editor-view-builder.ts
[error] 90-90: Change to an optional chain.
Unsafe fix: Change to an optional chain.
(lint/complexity/useOptionalChain)
src/components/text-editor/test-setup/content-generator.ts
[error] 130-130: This type annotation is trivially inferred from its initialization.
Safe fix: Remove the type annotation.
(lint/style/noInferrableTypes)
src/components/text-editor/test-setup/editor-view-builder.spec.ts
[error] 210-210: Avoid the delete operator which can impact performance.
Unsafe fix: Use an undefined assignment instead.
(lint/performance/noDelete)
[error] 211-211: Avoid the delete operator which can impact performance.
Unsafe fix: Use an undefined assignment instead.
(lint/performance/noDelete)
🔇 Additional comments (54)
src/components/text-editor/prosemirror-adapter/plugins/table-plugin.ts (1)
12-12: Good job making this function accessible for tests.Making
createStyleAttributefunction exportable is a clean modification that allows it to be used in your test suite while maintaining its existing functionality.src/components/text-editor/test-setup/schema-builder.spec.ts (1)
1-81: Well-structured test suite for schema builders.The tests are comprehensive and cover the important functionality of both
createTestSchemaandcreateCustomTestSchema. Good job verifying the presence of expected nodes and marks, and testing the customization options.src/components/text-editor/test-setup/editor-state-builder.spec.ts (1)
1-115: Thorough test coverage for editor state utilities.The test suite effectively validates all the key functions of the editor state builder, covering various scenarios including content creation, selection handling, and custom schema support. Good job with the detailed assertions that verify both the object types and the expected content.
src/components/text-editor/test-setup/schema-builder.ts (1)
1-87: Well-implemented and documented schema builder utilities.The schema builder functions are well-designed with good flexibility, especially in
createCustomTestSchemawhich offers numerous customization options. The JSDoc comments clearly explain the purpose and usage of each function.src/components/text-editor/prosemirror-adapter/plugins/table-plugin.spec.ts (5)
1-14: Imports look good and follow the correct pattern.All imports correctly use relative paths as required by the coding guidelines, which will ensure the production build works correctly.
16-26: Good test setup with proper cleanup.The test suite correctly implements
afterEachto clean up resources, preventing memory leaks and test interference.
28-70: Comprehensive tests for table editing plugins.The tests thoroughly verify that:
- Plugins are returned when tables are enabled
- An empty array is returned when tables are disabled
- The plugin works correctly with an editor state
This ensures the table editing functionality will behave as expected under different configurations.
72-116: Well-structured tests for table node specifications.These tests thoroughly validate the table node specs, including:
- Verifying the expected node types exist
- Confirming the nodes can be integrated into a schema
- Checking for custom cell attributes used for styling
This ensures table structures will render correctly with proper styling capabilities.
118-169: Thorough testing of the style attribute helper.The tests provide excellent coverage of the
createStyleAttributefunction, verifying:
- Retrieval of style values from DOM elements
- Setting style values on attribute objects
- Appending to existing style attributes
- Proper handling of falsy values
This validates that table cell styling will work correctly in all scenarios.
src/components/text-editor/test-setup/event-simulator.spec.ts (6)
1-11: Imports correctly use relative paths.All imports from the lime-elements module use relative paths as required by the coding guidelines.
13-41: Good test setup with proper cleanup.The test suite correctly:
- Sets up test environment with
beforeEach- Cleans up resources with
afterEach- Initializes an editor view for consistent testing
This approach prevents test interference and memory leaks.
43-84: Well-designed tests for key press simulation.The tests validate:
- Basic key press functionality
- Correct handling of modifier keys (ctrl, shift, alt, meta)
The use of spies to verify event dispatching ensures the implementation works as expected.
86-133: Thorough testing of paste operations.The tests verify:
- Pasting plain text content
- Pasting HTML content
- Proper clipboard data handling
The detailed validation of clipboard data ensures paste operations will work correctly.
135-171: Comprehensive mouse click simulation tests.The tests validate:
- Basic click functionality at specific coordinates
- Support for different mouse buttons
- Support for different click types (single/double)
This ensures the editor will correctly handle various mouse interactions.
173-234: Complete drag and drop operation tests.The tests verify:
- The full sequence of drag-and-drop events
- Correct coordinates for start and end positions
- Proper handling of drag data
The validation of event sequencing is particularly valuable for ensuring smooth drag-and-drop functionality.
src/components/text-editor/test-setup/content-generator.spec.ts (8)
1-12: Imports correctly use relative paths.All imports from within the lime-elements module use relative paths as required by the coding guidelines.
14-41: Good tests for plain text document creation.The tests validate:
- Creation of documents with plain text
- Document structure verification
- Support for custom schemas
This ensures the basic document creation functionality works correctly.
43-72: Thorough HTML content parsing tests.The tests verify:
- Parsing of complex HTML structures
- Correct document structure creation
- Proper handling of empty/invalid HTML
This ensures the editor can properly handle HTML content from various sources.
74-140: Comprehensive formatted text tests.The tests validate:
- Application of multiple marks to text
- Handling of marks with attributes (links)
- Error handling for invalid mark types
The nested assertions provide detailed validation of the document structure.
🧰 Tools
🪛 Biome (1.9.4)
[error] 119-119: Change to an optional chain.
Unsafe fix: Change to an optional chain.
(lint/complexity/useOptionalChain)
142-179: Well-structured bullet list tests.The tests verify:
- Creation of lists with multiple items
- Proper document structure
- Handling of empty lists
The checks on child nodes ensure the list structure is correctly created.
181-208: Good heading creation tests.The tests validate:
- Creation of headings with specific text
- Support for different heading levels
- Default level handling
This ensures headings will be correctly generated in the document.
210-235: Thorough blockquote tests.The test validates:
- Creation of blockquotes with text
- Correct document structure (blockquote containing a paragraph)
This ensures blockquote formatting will work as expected.
237-254: Complete code block tests.The test verifies:
- Creation of code blocks with specific content
- Correct document structure
This ensures code blocks will be properly formatted in the document.
src/components/text-editor/test-setup/command-tester.spec.ts (5)
1-9: Imports correctly use relative paths.All imports from within the lime-elements module use relative paths as required by the coding guidelines.
11-50: Well-designed command result tests.The tests thoroughly validate:
- Handling of commands that cannot be applied
- Processing of commands that generate transactions
- Verification of state changes
This ensures the command execution framework works correctly.
52-114: Comprehensive command testing functionality.The tests verify:
- Command applicability determination
- Document content validation after command execution
- Document size changes tracking
The tests avoid relying on specific content ordering, making them more robust.
116-172: Thorough testing of view-dependent commands.The tests validate:
- Commands that require an editor view context
- State updates through view
- Proper cleanup of resources
The test correctly uses afterEach for cleanup, preventing memory leaks.
174-208: Well-structured tests for command tester factory.The tests verify:
- Creation of reusable command testers
- Application across different document states
- Content validation after command execution
This ensures the command tester factory pattern works correctly.
src/components/text-editor/test-setup/editor-view-builder.ts (4)
1-4: Import usage looks good.The imports correctly use relative paths as required by the coding guidelines for lime-elements.
14-46: Function implementation LGTM.The
createEditorViewfunction is well-implemented, providing all the necessary functionality to create an editor view for testing purposes with good defaults and options.
48-75: Dispatch spy implementation is clean and efficient.The function appropriately creates a Jest mock with auto-update capability and handles view reference tracking correctly.
95-143: Thorough DOM environment mocking.The mock implementation covers all the necessary DOM methods and properties needed for ProseMirror to function in a test environment.
src/components/text-editor/test-setup/editor-state-builder.ts (5)
1-5: Imports look good.The imports correctly use relative paths as required by the coding guidelines.
6-29: Well-implemented state creation function.The
createEditorStatefunction properly handles optional parameters and creates a document from content or an empty one as needed.
31-59: Selection state creation looks good.The function correctly creates an editor state with a text selection at the specified positions.
61-77: Clean implementation of text selection.The function properly creates and applies a text selection to an existing state.
79-91: Document parsing implementation is solid.The helper function correctly converts HTML content to a ProseMirror document node.
src/components/text-editor/test-setup/command-tester.ts (6)
1-4: Imports look good.The imports correctly use relative paths as required by the coding guidelines.
5-20: Well-documented interface.The
CommandResultinterface is clearly defined with thorough documentation explaining all possible states.
22-60: Command result extraction is well implemented.The function correctly handles command execution and captures the relevant transaction and state information.
62-120: Thorough command testing implementation.The function provides comprehensive verification of command execution results, including content checks, size validation, and expected applicability.
122-185: DOM-aware command testing looks good.The implementation correctly handles the view context needed for some commands and properly manages the DOM elements.
187-202: Utility function for command testing is clean.The function creates a reusable tester for a specific command, which helps reduce boilerplate in tests.
src/components/text-editor/test-setup/content-generator.ts (6)
1-5: Imports look good.The imports correctly use relative paths as required by the coding guidelines.
6-31: Document creation utilities look good.The functions for creating documents with plain text and HTML content are well-implemented.
33-61: Formatted text handling is comprehensive.The interface and function for applying marks to text are well-designed and implemented.
63-88: Mark application is implemented correctly.The helper function properly creates text nodes with applied marks and includes good error handling.
90-118: Bullet list creation works well.The function properly maps text items to list nodes and constructs a valid bullet list structure.
146-187: Blockquote and code block implementations are solid.The functions correctly create the appropriate node structures for blockquotes and code blocks.
src/components/text-editor/test-setup/event-simulator.ts (2)
8-43: Well-implemented mock class for DataTransfer.The
MockDataTransferclass is well-designed, properly implementing the core functionality of the DataTransfer interface needed for testing. Good job including the dynamic getter foritems.lengthto reflect the actual files array length.
45-84: Good implementation of key press simulation.The
KeyModifiersinterface andsimulateKeyPressfunction provide a clean and flexible way to simulate keyboard interactions in tests. The double-bang operator ensures proper boolean conversion for the modifiers.src/components/text-editor/test-setup/editor-view-builder.spec.ts (3)
1-9: Properly using relative imports for internal module files.The imports follow the coding guidelines correctly by using relative paths for imports from the same module, which is essential for avoiding production build failures.
11-24: Good test setup with proper cleanup.The test suite has proper setup and teardown to prevent memory leaks. The
afterEachhook ensures that resources are properly cleaned up between tests, which is a good testing practice.
192-247: Well-structured tests for mockProseMirrorDOMEnvironment.The tests properly verify both the creation of mock DOM elements when none exist and preservation of existing DOM elements. Good use of
beforeEachandafterEachhooks to preserve and restore the original window and document objects.🧰 Tools
🪛 Biome (1.9.4)
[error] 210-210: Avoid the delete operator which can impact performance.
Unsafe fix: Use an undefined assignment instead.
(lint/performance/noDelete)
[error] 211-211: Avoid the delete operator which can impact performance.
Unsafe fix: Use an undefined assignment instead.
(lint/performance/noDelete)
src/components/text-editor/test-setup/editor-view-builder.spec.ts
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 5
♻️ Duplicate comments (1)
src/components/text-editor/test-setup/event-simulator.ts (1)
148-163: Simplify redundant conditional check.There's a redundant condition check at line 161. The condition
typeof document.elementFromPoint === 'undefined'is already checked at line 148, making the nested check unnecessary.if (typeof document.elementFromPoint === 'undefined') { // For tests, just pretend the click always hits the editor // This prevents errors when ProseMirror calls elementFromPoint (view.dom as any).getBoundingClientRect = () => ({ left: 0, top: 0, right: 200, bottom: 200, width: 200, height: 200, }); // Mock elementFromPoint to avoid errors - if (typeof document.elementFromPoint === 'undefined') { - (document as any).elementFromPoint = () => view.dom; - } + (document as any).elementFromPoint = () => view.dom; }
📜 Review details
Configuration used: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
📒 Files selected for processing (10)
src/components/text-editor/test-setup/command-tester.spec.ts(1 hunks)src/components/text-editor/test-setup/command-tester.ts(1 hunks)src/components/text-editor/test-setup/content-generator.spec.ts(1 hunks)src/components/text-editor/test-setup/content-generator.ts(1 hunks)src/components/text-editor/test-setup/editor-view-builder.spec.ts(1 hunks)src/components/text-editor/test-setup/editor-view-builder.ts(1 hunks)src/components/text-editor/test-setup/event-simulator.spec.ts(1 hunks)src/components/text-editor/test-setup/event-simulator.ts(1 hunks)src/components/text-editor/test-setup/text-editor-test-suite-guide.md(1 hunks)src/components/text-editor/test-setup/text-editor-test-utils.md(1 hunks)
📓 Path-based instructions (1)
**/*.{ts,tsx}
⚙️ CodeRabbit Configuration File
Imports from other files in the same module (lime-elements) must use relative paths. Using absolute paths for imports will cause the production build to fail.
Files:
src/components/text-editor/test-setup/command-tester.spec.tssrc/components/text-editor/test-setup/editor-view-builder.tssrc/components/text-editor/test-setup/event-simulator.tssrc/components/text-editor/test-setup/command-tester.tssrc/components/text-editor/test-setup/editor-view-builder.spec.tssrc/components/text-editor/test-setup/content-generator.tssrc/components/text-editor/test-setup/content-generator.spec.tssrc/components/text-editor/test-setup/event-simulator.spec.ts
🧠 Learnings (3)
src/components/text-editor/test-setup/event-simulator.ts (1)
Learnt from: adrianschmidt
PR: #3547
File: src/components/text-editor/examples/text-editor-with-inline-images-file-storage.tsx:46-46
Timestamp: 2025-05-02T07:14:19.314Z
Learning: When reviewing TypeScript/JavaScript code, don't suggest converting object literals to constants when the object is mutable and will be modified later in the code. Due to reference semantics, this can cause unintended side effects where the "constant" version is also modified.
src/components/text-editor/test-setup/editor-view-builder.spec.ts (3)
Learnt from: adrianschmidt
PR: #3547
File: src/components/text-editor/examples/text-editor-with-inline-images-file-storage.tsx:46-46
Timestamp: 2025-05-02T07:14:19.314Z
Learning: When reviewing TypeScript/JavaScript code, don't suggest converting object literals to constants when the object is mutable and will be modified later in the code. Due to reference semantics, this can cause unintended side effects where the "constant" version is also modified.
Learnt from: adrianschmidt
PR: #3607
File: docs-index.html:0-0
Timestamp: 2025-07-16T13:28:26.858Z
Learning: Before suggesting any code changes as "safe," thoroughly analyze the entire codebase context, including dependencies, usage patterns, and potential side effects. What appears to be a simple performance optimization might break existing functionality due to execution order or timing dependencies.
Learnt from: adrianschmidt
PR: #3607
File: docs-index.html:0-0
Timestamp: 2025-07-16T13:28:26.858Z
Learning: When suggesting script optimizations like adding defer or async attributes, always analyze the entire HTML file to check for dependencies between external scripts and inline scripts. Scripts loaded with defer execute after DOM parsing but before DOMContentLoaded, which can break synchronous dependencies with inline scripts that expect variables to be immediately available.
src/components/text-editor/test-setup/content-generator.ts (2)
Learnt from: adrianschmidt
PR: #3530
File: src/components/text-editor/examples/text-editor-composite.tsx:4-7
Timestamp: 2025-04-17T09:39:36.254Z
Learning: For lime-elements, example files should import types from the public API using '@limetech/lime-elements' rather than defining duplicate types locally. This includes types like EditorUiType which are part of the component's public API.
Learnt from: adrianschmidt
PR: #3464
File: src/components/text-editor/prosemirror-adapter/plugins/image/inserter.ts:1-11
Timestamp: 2025-03-04T14:27:29.714Z
Learning: In example components (typically found in src/components/*/examples/), imports of lime-elements exports should use @limetech/lime-elements instead of relative paths. This is because example components aren't included in type declarations and are used in documentation to show developers how to properly use lime-elements components.
🧬 Code Graph Analysis (5)
src/components/text-editor/test-setup/command-tester.spec.ts (2)
src/components/text-editor/test-setup/command-tester.ts (4)
getCommandResult(29-58)testCommand(72-118)testCommandWithView(128-179)createCommandTester(187-196)src/components/text-editor/test-setup/editor-view-builder.ts (1)
cleanupEditorView(78-85)
src/components/text-editor/test-setup/editor-view-builder.ts (1)
src/components/text-editor/test-setup/schema-builder.ts (1)
createTestSchema(12-33)
src/components/text-editor/test-setup/command-tester.ts (1)
src/components/text-editor/test-setup/editor-view-builder.ts (1)
createEditorView(14-45)
src/components/text-editor/test-setup/editor-view-builder.spec.ts (1)
src/components/text-editor/test-setup/editor-view-builder.ts (4)
cleanupEditorView(78-85)createEditorView(14-45)createDispatchSpy(53-69)mockProseMirrorDOMEnvironment(93-135)
src/components/text-editor/test-setup/content-generator.ts (1)
src/components/text-editor/test-setup/schema-builder.ts (1)
createTestSchema(12-33)
🪛 LanguageTool
src/components/text-editor/test-setup/text-editor-test-utils.md
[grammar] ~1-~1: Use correct spacing
Context: # Text Editor Testing Utilities This directory contains utility function...
(QB_NEW_EN_OTHER_ERROR_IDS_5)
[grammar] ~3-~3: Use correct spacing
Context: ...e text editor component and its related components. ## Core Testing Utilities 1. **Schema Setu...
(QB_NEW_EN_OTHER_ERROR_IDS_5)
[grammar] ~5-~5: Use correct spacing
Context: ...ts related components. ## Core Testing Utilities 1. Schema Setup - createTestSchema()...
(QB_NEW_EN_OTHER_ERROR_IDS_5)
[grammar] ~7-~7: Use correct spacing
Context: ... ## Core Testing Utilities 1. Schema Setup - createTestSchema() - Creates a ProseMirror schema with all n...
(QB_NEW_EN_OTHER_ERROR_IDS_5)
[grammar] ~8-~8: Use hyphens correctly
Context: ...Mirror schema with all needed marks and nodes - createCustomTestSchema(options) - Creates a custom schema with specified...
(QB_NEW_EN_OTHER_ERROR_IDS_29)
[grammar] ~9-~9: There might be a mistake here.
Context: ... Creates a custom schema with specified extensions 2. Editor State Utilities - `createEdi...
(QB_NEW_EN_OTHER)
[grammar] ~11-~11: Use correct spacing
Context: ...specified extensions 2. Editor State Utilities - createEditorState(content?, schema?) - Creates an editor state with optional c...
(QB_NEW_EN_OTHER_ERROR_IDS_5)
[grammar] ~12-~12: Use hyphens correctly
Context: ...- Creates an editor state with optional content - createEditorStateWithSelection(content, from, to, schema?) - Creates an editor state with a specifi...
(QB_NEW_EN_OTHER_ERROR_IDS_29)
[grammar] ~13-~13: There might be a mistake here.
Context: ...Creates an editor state with a specific selection 3. Editor View Utilities - `createEdit...
(QB_NEW_EN_OTHER)
[grammar] ~15-~15: Use correct spacing
Context: ... a specific selection 3. Editor View Utilities - createEditorView(state, dispatchSpy?) - Creates a ProseMirror editor view with ...
(QB_NEW_EN_OTHER_ERROR_IDS_5)
[grammar] ~16-~16: Use hyphens correctly
Context: ...r editor view with an optional dispatch spy - cleanupEditorView(view) - Properly destroys an editor view to pr...
(QB_NEW_EN_OTHER_ERROR_IDS_29)
[grammar] ~17-~17: There might be a mistake here.
Context: ...stroys an editor view to prevent memory leaks 4. Content Generation - `createDocWith...
(QB_NEW_EN_OTHER)
[grammar] ~19-~19: Use correct spacing
Context: ...w to prevent memory leaks 4. Content Generation - createDocWithText(text, schema?) - Creates a document with plain text -...
(QB_NEW_EN_OTHER_ERROR_IDS_5)
[grammar] ~20-~20: Use hyphens correctly
Context: ...hema?)- Creates a document with plain text -createDocWithHTML(html, schema?)` - Creates a document from HTML string ...
(QB_NEW_EN_OTHER_ERROR_IDS_29)
[grammar] ~21-~21: There might be a problem here.
Context: ...ml, schema?)- Creates a document from HTML string -createDocWithFormattedText(text, marks, schema?)` - Creates a document with marked text 5...
(QB_NEW_EN_MERGED_MATCH)
[grammar] ~22-~22: There might be a mistake here.
Context: ...ema?)- Creates a document with marked text 5. **Command Testing** -testCommand(comm...
(QB_NEW_EN_OTHER)
[grammar] ~24-~24: Use correct spacing
Context: ...document with marked text 5. Command Testing - testCommand(command, state, expected) - Tests a command and verifies the result...
(QB_NEW_EN_OTHER_ERROR_IDS_5)
[grammar] ~25-~25: Use correct spacing
Context: ...ed)- Tests a command and verifies the result -getCommandResult(command, state)` - Gets the result of applying a command ...
(QB_NEW_EN_OTHER_ERROR_IDS_5)
[grammar] ~26-~26: Use correct spacing
Context: ...state)- Gets the result of applying a command -testCommandWithView(command, state, expected)` - Tests a command that requires view cont...
(QB_NEW_EN_OTHER_ERROR_IDS_5)
[grammar] ~27-~27: Use correct spacing
Context: ...)- Tests a command that requires view context -createCommandTester(command)` - Creates a reusable tester for a specifi...
(QB_NEW_EN_OTHER_ERROR_IDS_5)
[grammar] ~28-~28: Use correct spacing
Context: ...reates a reusable tester for a specific command 6. Mocks - createDispatchSpy() - Cre...
(QB_NEW_EN_OTHER_ERROR_IDS_5)
[grammar] ~31-~31: Use hyphens correctly
Context: ...- Creates a Jest spy for the dispatch function -createMockEditorView()- Creates a mocked editor view -mo...
(QB_NEW_EN_OTHER_ERROR_IDS_29)
[grammar] ~32-~32: Use hyphens correctly
Context: ...EditorView()- Creates a mocked editor view -mockProseMirrorDOMEnvironment()` - Sets up the DOM environment for ProseM...
(QB_NEW_EN_OTHER_ERROR_IDS_29)
[grammar] ~33-~33: There might be a mistake here.
Context: ...nt()- Sets up the DOM environment for ProseMirror 7. **Selection Helpers** -setTextSelecti...
(QB_NEW_EN_OTHER)
[grammar] ~35-~35: Use correct spacing
Context: ...ronment for ProseMirror 7. Selection Helpers - setTextSelection(state, from, to) - Creates a text selection - `setNodeS...
(QB_NEW_EN_OTHER_ERROR_IDS_5)
[grammar] ~36-~36: Use correct spacing
Context: ...tion(state, from, to)- Creates a text selection -setNodeSelection(state, pos)` - Creates a node selection 8. **Event Si...
(QB_NEW_EN_OTHER_ERROR_IDS_5)
[grammar] ~37-~37: Use correct spacing
Context: ...Selection(state, pos)- Creates a node selection 8. **Event Simulation** -simulateKeyPres...
(QB_NEW_EN_OTHER_ERROR_IDS_5)
[grammar] ~39-~39: Use correct spacing
Context: ... - Creates a node selection 8. Event Simulation - simulateKeyPress(view, key, modifiers?) - Simulates a key press on the editor ...
(QB_NEW_EN_OTHER_ERROR_IDS_5)
[grammar] ~40-~40: Use correct spacing
Context: ...fiers?)- Simulates a key press on the editor -simulatePaste(view, content)` - Simulates pasting content into the edit...
(QB_NEW_EN_OTHER_ERROR_IDS_5)
[grammar] ~42-~42: Use correct spacing
Context: ...clientY, options?)- Simulates a mouse click -simulateDragAndDrop(view, startX, startY, endX, endY, dragData?)` - Simulates drag and drop ## Usage Examp...
(QB_NEW_EN_OTHER_ERROR_IDS_5)
[grammar] ~43-~43: Use correct spacing
Context: ... endY, dragData?)` - Simulates drag and drop ## Usage Example ```typescript import { ...
(QB_NEW_EN_OTHER_ERROR_IDS_5)
[grammar] ~45-~45: Use correct spacing
Context: ...?)` - Simulates drag and drop ## Usage Example typescript import { createTestSchema, createEditorState, createEditorView, simulateKeyPress, cleanupEditorView } from '../test-setup/test-utils'; describe('Text Editor', () => { let schema, state, view; beforeEach(() => { schema = createTestSchema(); state = createEditorState('<p>Test content</p>', schema); view = createEditorView(state); }); afterEach(() => { cleanupEditorView(view); }); it('should apply bold formatting with keyboard shortcut', () => { // Setup test case // Simulate keypress // Assert results }); }); ## Command Testing Example ```typescript i...
(QB_NEW_EN_OTHER_ERROR_IDS_5)
[grammar] ~77-~77: Use correct spacing
Context: ...sults }); }); ## Command Testing Example typescript import { createEditorState, testCommand, createCommandTester } from '../test-setup/test-utils'; import { toggleMark } from 'prosemirror-commands'; describe('Text Editor Commands', () => { it('should toggle bold mark when applicable', () => { // Create state with selected text const state = createEditorStateWithSelection('
Test content
', 1, 5); // Get the bold mark from schema const boldMark = state.schema.marks.strong; const toggleBold = toggleMark(boldMark); // Test the command testCommand(toggleBold, state, { shouldApply: true, // Additional expectations if needed }); }); it('should test multiple states with the same command', () => { // Create a reusable tester for a command const testToggleBold = createCommandTester(toggleMark(schema.marks.strong)); // Test with different states testToggleBold(state1, { shouldApply: true }); testToggleBold(state2, { shouldApply: false }); }); }); ## Event Simulation Example typescript ...
(QB_NEW_EN_OTHER_ERROR_IDS_5)
[grammar] ~114-~114: Use correct spacing
Context: ... }); }); }); ## Event Simulation Example typescript import { createEditorState, createEditorView, simulateKeyPress, simulatePaste, cleanupEditorView } from '../test-setup/test-utils'; describe('Text Editor Event Handling', () => { let view, container; beforeEach(() => { const state = createEditorState('
Test content
'); const result = createEditorView(state); view = result.view; container = result.container; }); afterEach(() => { cleanupEditorView(view, container); }); it('should handle Ctrl+B keyboard shortcut', () => { // Select some text first // ... // Simulate pressing Ctrl+B for bold simulateKeyPress(view, 'b', { ctrl: true }); // Verify text is now bold // ... }); it('should handle paste events correctly', () => { // Simulate pasting HTML content simulatePaste(view, { text: 'Plain text version', html: 'Formatted HTML content
' }); // Verify pasted content was properly processed // ... }); }); ```(QB_NEW_EN_OTHER_ERROR_IDS_5)
src/components/text-editor/test-setup/text-editor-test-suite-guide.md
[grammar] ~1-~1: Use correct spacing
Context: # Text Editor Testing Suite Guide This document serves as the practical gu...
(QB_NEW_EN_OTHER_ERROR_IDS_5)
[grammar] ~3-~3: Use correct spacing
Context: ...ing tests using the text editor testing utilities. ## Overview Our testing suite provides a c...
(QB_NEW_EN_OTHER_ERROR_IDS_5)
[grammar] ~7-~7: There might be a mistake here.
Context: ...effectively test your ProseMirror-based components: - Schema setup for testing - Editor state...
(QB_NEW_EN_OTHER)
[grammar] ~14-~14: Use correct spacing
Context: ... testing - Event simulation - Mocks and helpers ## Available Utilities ### 1. Schema Setup...
(QB_NEW_EN_OTHER_ERROR_IDS_5)
[grammar] ~16-~16: Use correct spacing
Context: ...ation - Mocks and helpers ## Available Utilities ### 1. Schema Setup - createTestSchema() ...
(QB_NEW_EN_OTHER_ERROR_IDS_5)
[grammar] ~18-~18: Use correct spacing
Context: ... ## Available Utilities ### 1. Schema Setup - createTestSchema() - Creates a standard ProseMirror schema...
(QB_NEW_EN_OTHER_ERROR_IDS_5)
[grammar] ~20-~20: Use hyphens correctly
Context: ...Mirror schema with all needed marks and nodes - createCustomTestSchema(options) - Creates a custom schema with specified...
(QB_NEW_EN_OTHER_ERROR_IDS_29)
[grammar] ~21-~21: There might be a mistake here.
Context: ... Creates a custom schema with specified extensions typescript // Create a standard schema with all marks and nodes const schema = createTestSchema(); // Create a custom schema with only specific features const customSchema = createCustomTestSchema({ addLists: true, // Add ordered and bullet list support addStrikethrough: true, // Add strikethrough mark addUnderline: false // Skip underline mark }); ### 2. Editor State Utilities - `createEdit...
(QB_NEW_EN_OTHER)
[grammar] ~35-~35: Use correct spacing
Context: ...rline mark }); ``` ### 2. Editor State Utilities - createEditorState(content?, schema?, plugins?) - Creates an editor state with optional...
(QB_NEW_EN_OTHER_ERROR_IDS_5)
[grammar] ~37-~37: Use correct spacing
Context: ...- Creates an editor state with optional content - createEditorStateWithSelection(content, from, to, schema?, plugins?) - Creates an editor state with a specific...
(QB_NEW_EN_OTHER_ERROR_IDS_5)
[grammar] ~38-~38: Use correct spacing
Context: ...Creates an editor state with a specific selection - setTextSelection(state, from, to?) - Sets a text selection on an existing st...
(QB_NEW_EN_OTHER_ERROR_IDS_5)
[grammar] ~39-~39: Use correct spacing
Context: ... - Sets a text selection on an existing state - createDocumentWithText(text?, schema?) - Creates a simple document with text ``...
(QB_NEW_EN_OTHER_ERROR_IDS_5)
[grammar] ~40-~40: Use correct spacing
Context: ...ema?)- Creates a simple document with text ```typescript // Create an empty editor state const emptyState = createEditorState(); // Create state with HTML content const state = createEditorState('<p>This is <strong>bold</strong> text.</p>'); // Create state with selection (from position 5 to 10) const stateWithSelection = createEditorStateWithSelection( '<p>Select this text</p>', 5, 10 ); // Add a text selection to an existing state const newState = setTextSelection(state, 1, 5); ``` ### 3. Editor View Utilities -createEdito...
(QB_NEW_EN_OTHER_ERROR_IDS_5)
[grammar] ~60-~60: Use correct spacing
Context: ...n(state, 1, 5); ``` ### 3. Editor View Utilities - createEditorView(state?, dispatchSpy?, parentElement?) - Creates a ProseMirror editor view wit...
(QB_NEW_EN_OTHER_ERROR_IDS_5)
[grammar] ~62-~62: Use correct spacing
Context: ...rror editor view with optional dispatch spy - createDispatchSpy(autoUpdate?) - Creates a Jest spy function for trackin...
(QB_NEW_EN_OTHER_ERROR_IDS_5)
[grammar] ~63-~63: Use correct spacing
Context: ...Jest spy function for tracking dispatch calls - cleanupEditorView(view, container?) - Properly destroys an editor view to pre...
(QB_NEW_EN_OTHER_ERROR_IDS_5)
[grammar] ~64-~64: Use correct spacing
Context: ...stroys an editor view to prevent memory leaks - mockProseMirrorDOMEnvironment() - Sets up the DOM environment for ProseMi...
(QB_NEW_EN_OTHER_ERROR_IDS_5)
[grammar] ~65-~65: Use correct spacing
Context: ... the DOM environment for ProseMirror in Node.js typescript // Create a view with state const { view, container } = createEditorView(state); // Create a view with dispatch tracking const dispatchSpy = createDispatchSpy(true); // autoUpdate=true const { view: viewWithSpy } = createEditorView(state, dispatchSpy); // Create a view with custom parent element const parent = document.createElement('div'); const { view: viewWithParent } = createEditorView(state, null, parent); // Clean up after testing cleanupEditorView(view, container); // Mock DOM environment for Node.js tests const cleanup = mockProseMirrorDOMEnvironment(); // ... test code ... cleanup(); // Restore original environment ### 4. Content Generation - `createDocWithT...
(QB_NEW_EN_OTHER_ERROR_IDS_5)
[grammar] ~88-~88: Use correct spacing
Context: ...riginal environment ``` ### 4. Content Generation - createDocWithText(text, schema?) - Creates a document with plain text - ...
(QB_NEW_EN_OTHER_ERROR_IDS_5)
[grammar] ~90-~90: Use correct spacing
Context: ...hema?)- Creates a document with plain text -createDocWithHTML(html, schema?)- Creates a document from HTML string -...
(QB_NEW_EN_OTHER_ERROR_IDS_5)
[grammar] ~91-~91: There might be a problem here.
Context: ...ml, schema?)- Creates a document from HTML string -createDocWithFormattedText(text, marks, schema?)- Creates a document with marked text -...
(QB_NEW_EN_MERGED_MATCH)
[grammar] ~92-~92: Use correct spacing
Context: ...ema?)- Creates a document with marked text -createDocWithBulletList(items, schema?)` - Creates a document with a bullet list -...
(QB_NEW_EN_OTHER_ERROR_IDS_5)
[grammar] ~93-~93: Use correct spacing
Context: ...a?)- Creates a document with a bullet list -createDocWithHeading(text, level?, schema?)- Creates a document with a heading -cr...
(QB_NEW_EN_OTHER_ERROR_IDS_5)
[grammar] ~94-~94: Use correct spacing
Context: ..., schema?)- Creates a document with a heading -createDocWithBlockquote(text, schema?)` - Creates a document with a blockquote - ...
(QB_NEW_EN_OTHER_ERROR_IDS_5)
[grammar] ~95-~95: Use correct spacing
Context: ..., schema?)- Creates a document with a blockquote -createDocWithCodeBlock(code, schema?)- Creates a document with a code block ...
(QB_NEW_EN_OTHER_ERROR_IDS_5)
[grammar] ~96-~96: Use correct spacing
Context: ...ema?)- Creates a document with a code block ```typescript // Create documents with different content types const textDoc = createDocWithText('Simple text'); const htmlDoc = createDocWithHTML('<p>HTML <em>content</em></p>'); // Create a document with formatted text const formattedDoc = createDocWithFormattedText('Bold and italic text', [ { type: 'strong', attrs: {} }, // Apply to all text { type: 'em', attrs: {}, from: 0, to: 4 } // Only apply to "Bold" ]); // Create various structured documents const listDoc = createDocWithBulletList(['Item 1', 'Item 2', 'Item 3']); const headingDoc = createDocWithHeading('Section Title', 2); // h2 const quoteDoc = createDocWithBlockquote('Famous quote here'); const codeDoc = createDocWithCodeBlock('function test() { return true; }'); ``` ### 5. Command Testing -testCommand(comma...
(QB_NEW_EN_OTHER_ERROR_IDS_5)
[grammar] ~116-~116: Use correct spacing
Context: ...{ return true; }'); ``` ### 5. Command Testing - testCommand(command, state, expected) - Tests a command and verifies the resu...
(QB_NEW_EN_OTHER_ERROR_IDS_5)
[grammar] ~118-~118: Use correct spacing
Context: ...ed)- Tests a command and verifies the result -getCommandResult(command, state)` - Gets the result of applying a command -...
(QB_NEW_EN_OTHER_ERROR_IDS_5)
[grammar] ~119-~119: Use correct spacing
Context: ...state)- Gets the result of applying a command -testCommandWithView(command, state, expected)` - Tests a command that requires view cont...
(QB_NEW_EN_OTHER_ERROR_IDS_5)
[grammar] ~120-~120: Use correct spacing
Context: ...)- Tests a command that requires view context -createCommandTester(command)` - Creates a reusable tester for a specifi...
(QB_NEW_EN_OTHER_ERROR_IDS_5)
[grammar] ~121-~121: Use correct spacing
Context: ...reates a reusable tester for a specific command typescript // Test if a command can be applied const result = getCommandResult(toggleMark(schema.marks.strong), state); expect(result.canApply).toBe(true); // Test a command with expectations testCommand(toggleMark(schema.marks.strong), state, { shouldApply: true, // Command should apply docChanged: true, // Document should change selectionChanged: false, // Selection should not change storedMarksChanged: false // Stored marks should not change }); // Create a reusable command tester const testBold = createCommandTester(toggleMark(schema.marks.strong)); testBold(state1, { shouldApply: true }); testBold(state2, { shouldApply: false }); // Test a command that requires view context testCommandWithView(someViewCommand, state, { shouldApply: true, // other expectations... }); ### 6. Mocks - createDispatchSpy() - Crea...
(QB_NEW_EN_OTHER_ERROR_IDS_5)
[grammar] ~148-~148: Use correct spacing
Context: .../ other expectations... }); ``` ### 6. Mocks - createDispatchSpy() - Creates a Jest spy for the dispatch f...
(QB_NEW_EN_OTHER_ERROR_IDS_5)
[grammar] ~150-~150: Use hyphens correctly
Context: ...- Creates a Jest spy for the dispatch function -mockProseMirrorDOMEnvironment()` - Sets up the DOM environment for ProseM...
(QB_NEW_EN_OTHER_ERROR_IDS_29)
[grammar] ~151-~151: There might be a mistake here.
Context: ...nt()- Sets up the DOM environment for ProseMirror ```typescript // Create a dispatch spy with auto-updating state const dispatchSpy = createDispatchSpy(true); const { view } = createEditorView(state, dispatchSpy); // Execute a command that should dispatch someCommand(view.state, view.dispatch, view); // Verify dispatch was called expect(dispatchSpy).toHaveBeenCalled(); // Get the latest state after updates const updatedState = dispatchSpy.state; ``` ### 7. Selection Helpers -setTextSelectio...
(QB_NEW_EN_OTHER)
[grammar] ~168-~168: Use correct spacing
Context: ...ispatchSpy.state; ``` ### 7. Selection Helpers - setTextSelection(state, from, to) - Creates a text selection - `setNodeSe...
(QB_NEW_EN_OTHER_ERROR_IDS_5)
[grammar] ~170-~170: Use correct spacing
Context: ...tion(state, from, to)- Creates a text selection -setNodeSelection(state, pos)` - Creates a node selection (planned) ```...
(QB_NEW_EN_OTHER_ERROR_IDS_5)
[grammar] ~171-~171: Use correct spacing
Context: ...state, pos)- Creates a node selection (planned) ```typescript // Create a state with a selection let state = createEditorState('<p>Select this text</p>'); // Apply a text selection from position 3 to 9 state = setTextSelection(state, 3, 9); expect(state.selection.from).toBe(3); expect(state.selection.to).toBe(9); ``` ### 8. Event Simulation -simulateKeyPress...
(QB_NEW_EN_OTHER_ERROR_IDS_5)
[grammar] ~183-~183: Use correct spacing
Context: ...election.to).toBe(9); ``` ### 8. Event Simulation - simulateKeyPress(view, key, modifiers?) - Simulates a key press on the editor -...
(QB_NEW_EN_OTHER_ERROR_IDS_5)
[grammar] ~185-~185: Use correct spacing
Context: ...fiers?)- Simulates a key press on the editor -simulatePaste(view, content)` - Simulates pasting content into the edit...
(QB_NEW_EN_OTHER_ERROR_IDS_5)
[grammar] ~187-~187: Use correct spacing
Context: ...clientY, options?)- Simulates a mouse click -simulateDragAndDrop(view, startX, startY, endX, endY, dragData?)` - Simulates drag and drop ```typescript ...
(QB_NEW_EN_OTHER_ERROR_IDS_5)
[grammar] ~188-~188: Use correct spacing
Context: ... endY, dragData?)` - Simulates drag and drop typescript // Simulate keyboard shortcuts simulateKeyPress(view, 'b', { ctrl: true }); // Ctrl+B for bold simulateKeyPress(view, 'z', { ctrl: true }); // Ctrl+Z for undo simulateKeyPress(view, 'Tab'); // Tab key // Simulate paste with both text and HTML simulatePaste(view, { text: 'Plain text', html: '<p><strong>Formatted</strong> HTML</p>' }); // Simulate mouse interactions simulateClick(view, 100, 150); // Click at x=100, y=150 simulateDragAndDrop(view, 50, 50, 200, 50); // Drag from x=50 to x=200 ## Common Testing Patterns ### Basic Test ...
(QB_NEW_EN_OTHER_ERROR_IDS_5)
[grammar] ~207-~207: Use correct spacing
Context: ...om x=50 to x=200 ## Common Testing Patterns ### Basic Test Setup typescript import {...
(QB_NEW_EN_OTHER_ERROR_IDS_5)
[grammar] ~209-~209: Use correct spacing
Context: ...Common Testing Patterns ### Basic Test Setup typescript import { createTestSchema, createEditorState, createEditorView, cleanupEditorView } from '../test-setup/test-utils'; describe('Text Editor', () => { let schema, state, view, container; beforeEach(() => { schema = createTestSchema(); state = createEditorState('<p>Test content</p>', schema); const result = createEditorView(state); view = result.view; container = result.container; }); afterEach(() => { cleanupEditorView(view, container); }); it('should render content correctly', () => { expect(view.dom.textContent).toContain('Test content'); }); }); ### Testing Commands ```typescript import {...
(QB_NEW_EN_OTHER_ERROR_IDS_5)
[grammar] ~240-~240: Use correct spacing
Context: ...t content'); }); }); ### Testing Commands typescript import { createTestSchema, createEditorStateWithSelection, testCommand } from '../test-setup/test-utils'; import { toggleMark } from 'prosemirror-commands'; describe('Bold Command', () => { let schema; beforeEach(() => { schema = createTestSchema(); }); it('should apply bold to selected text', () => { // Create state with text selection const state = createEditorStateWithSelection('
Test content
', 1, 5); // Test the bold command const boldMark = schema.marks.strong; testCommand(toggleMark(boldMark), state, { shouldApply: true, docChanged: true }); }); it('should toggle off bold when already applied', () => { // Create state with bold text and selection const state = createEditorStateWithSelection( 'Test content
', 1, 5 ); // Test the bold command (should toggle off) const boldMark = schema.marks.strong; testCommand(toggleMark(boldMark), state, { shouldApply: true, docChanged: true }); // Verify bold was removed (use the resulting state from testCommand) // ... }); }); ### Testing Keyboard Shortcuts typescrip...
(QB_NEW_EN_OTHER_ERROR_IDS_5)
[grammar] ~289-~289: Use correct spacing
Context: ...... }); }); ### Testing Keyboard Shortcuts typescript import { createTestSchema, createEditorState, createEditorView, setTextSelection, simulateKeyPress, cleanupEditorView } from '../test-setup/test-utils'; describe('Keyboard Shortcuts', () => { let schema, view, container; beforeEach(() => { schema = createTestSchema(); const state = createEditorState('
Test content
', schema); const result = createEditorView(state); view = result.view; container = result.container; }); afterEach(() => { cleanupEditorView(view, container); }); it('should apply bold with Ctrl+B', () => { // Set selection const newState = setTextSelection(view.state, 1, 5); view.dispatch(newState.tr); // Simulate Ctrl+B simulateKeyPress(view, 'b', { ctrl: true }); // Verify result const textNode = view.state.doc.nodeAt(1); const hasBold = textNode.marks.some(mark => mark.type.name === 'strong'); expect(hasBold).toBe(true); }); it('should create a list when pressing Tab in a list item', () => { // Set up a list state const listState = createEditorState( 'First item
Second item
### Testing Paste Handling typescript im...
(QB_NEW_EN_OTHER_ERROR_IDS_5)
[grammar] ~363-~363: Use correct spacing
Context: ... return depth; } ### Testing Paste Handling typescript import { createEditorState, createEditorView, simulatePaste, cleanupEditorView } from '../test-setup/test-utils'; describe('Paste Handling', () => { let view, container; beforeEach(() => { const state = createEditorState('
Existing content
'); const result = createEditorView(state); view = result.view; container = result.container; // Position cursor at end of paragraph const endPos = 17; view.dispatch(view.state.tr.setSelection( TextSelection.create(view.state.doc, endPos) )); }); afterEach(() => { cleanupEditorView(view, container); }); it('should handle plain text paste', () => { simulatePaste(view, { text: 'Pasted text' }); expect(view.state.doc.textContent).toBe('Existing contentPasted text'); }); it('should handle HTML paste', () => { simulatePaste(view, { text: 'Pasted text with bold', html: 'Pasted text with bold' }); expect(view.state.doc.textContent).toBe('Existing contentPasted text with bold'); // Check if "bold" has the strong mark const textPos = view.state.doc.textContent.indexOf('bold'); const nodeWithMark = view.state.doc.nodeAt(textPos); const hasBold = nodeWithMark.marks.some(mark => mark.type.name === 'strong'); expect(hasBold).toBe(true); }); }); ### Testing Lists typescript import { ...
(QB_NEW_EN_OTHER_ERROR_IDS_5)
[grammar] ~416-~416: Use correct spacing
Context: ....toBe(true); }); }); ### Testing Lists typescript import { createTestSchema, createDocWithBulletList, createEditorState, createEditorView, simulateKeyPress, cleanupEditorView } from '../test-setup/test-utils'; import { wrapInList } from 'prosemirror-schema-list'; describe('List Functionality', () => { let schema, view, container; beforeEach(() => { schema = createTestSchema(); const listItems = ['First item', 'Second item', 'Third item']; const doc = createDocWithBulletList(listItems, schema); const state = createEditorState(doc); const result = createEditorView(state); view = result.view; container = result.container; }); afterEach(() => { cleanupEditorView(view, container); }); it('should indent list item on Tab', () => { // Position cursor in second list item const secondItemPos = findPositionInListItem(view.state, 1); view.dispatch(view.state.tr.setSelection( TextSelection.create(view.state.doc, secondItemPos) )); // Simulate Tab simulateKeyPress(view, 'Tab'); // Verify second item is now a sublist of first item const listStructure = getListStructure(view.state); expect(listStructure).toEqual({ items: [ { text: 'First item', children: [ { text: 'Second item', children: [] } ]}, { text: 'Third item', children: [] } ] }); }); it('should outdent list item on Shift+Tab', () => { // First, indent second item const secondItemPos = findPositionInListItem(view.state, 1); view.dispatch(view.state.tr.setSelection( TextSelection.create(view.state.doc, secondItemPos) )); simulateKeyPress(view, 'Tab'); // Then outdent it with Shift+Tab simulateKeyPress(view, 'Tab', { shift: true }); // Verify structure is back to flat list const listStructure = getListStructure(view.state); expect(listStructure).toEqual({ items: [ { text: 'First item', children: [] }, { text: 'Second item', children: [] }, { text: 'Third item', children: [] } ] }); }); // Helper functions function findPositionInListItem(state, itemIndex) { // Implementation to find cursor position in specific list item return 0; // Placeholder } function getListStructure(state) { // Implementation to extract list structure return { items: [] }; // Placeholder } }); ``` ## Implementation Status | Category | Util...
(QB_NEW_EN_OTHER_ERROR_IDS_5)
[grammar] ~503-~503: Use correct spacing
Context: ...ceholder } }); ``` ## Implementation Status | Category | Utility | Status | |-------...
(QB_NEW_EN_OTHER_ERROR_IDS_5)
[grammar] ~538-~538: Use correct spacing
Context: ...agAndDrop()` | ✅ Implemented | ## Best Practices 1. Setup and Cleanup - Always clean up...
(QB_NEW_EN_OTHER_ERROR_IDS_5)
[grammar] ~541-~541: There might be a mistake here.
Context: ...tor views after tests to prevent memory leaks - Create schema once per test suite when p...
(QB_NEW_EN_OTHER)
[grammar] ~542-~542: There might be a mistake here.
Context: ... Create schema once per test suite when possible - Use beforeEach and afterEach for con...
(QB_NEW_EN_OTHER)
[grammar] ~543-~543: There might be a mistake here.
Context: ...nd afterEach for consistent setup and cleanup 2. Content Creation - Use the appropri...
(QB_NEW_EN_OTHER)
[grammar] ~546-~546: There might be a mistake here.
Context: ...ontent generation utility for your test case - Create realistic content for more robust...
(QB_NEW_EN_OTHER)
[grammar] ~547-~547: There might be a mistake here.
Context: ...reate realistic content for more robust tests - Use HTML strings for complex document st...
(QB_NEW_EN_OTHER)
[grammar] ~548-~548: There might be a mistake here.
Context: ...- Use HTML strings for complex document structures 3. Command Testing - Test commands in ...
(QB_NEW_EN_OTHER)
[grammar] ~551-~551: There might be a mistake here.
Context: ...ds in isolation with testCommand when possible - Test both positive and negative cases (w...
(QB_NEW_EN_OTHER)
[grammar] ~552-~552: Use articles correctly
Context: ... both positive and negative cases (when command should and shouldn't apply) - Verify...
(QB_NEW_EN_OTHER_ERROR_IDS_11)
[grammar] ~552-~552: There might be a mistake here.
Context: ...ases (when command should and shouldn't apply) - Verify document structure after command ...
(QB_NEW_EN_OTHER)
[grammar] ~553-~553: There might be a mistake here.
Context: ...Verify document structure after command application 4. Event Handling - For keyboard short...
(QB_NEW_EN_OTHER)
[grammar] ~556-~556: There might be a mistake here.
Context: ...n is set up correctly before simulating keys - When testing paste events, include both ...
(QB_NEW_EN_OTHER)
[grammar] ~557-~557: There might be a mistake here.
Context: ...aste events, include both text and HTML variants - For mouse events, calculate positions re...
(QB_NEW_EN_OTHER)
[grammar] ~558-~558: There might be a mistake here.
Context: ...late positions relative to the document structure 5. State Management - Remember that ed...
(QB_NEW_EN_OTHER)
[typographical] ~561-~561: To join two clauses or set off examples, consider using an em dash.
Context: ...nt** - Remember that editor state is immutable - always use transactions - Use `view.d...
(QB_NEW_EN_DASH_RULE_EM)
[grammar] ~561-~561: There might be a mistake here.
Context: ... editor state is immutable - always use transactions - Use view.dispatch(tr) to update the vi...
(QB_NEW_EN_OTHER)
[grammar] ~562-~562: There might be a mistake here.
Context: ...view.dispatch(tr)to update the view's state - UsedispatchSpywithautoUpdate=true`...
(QB_NEW_EN_OTHER)
[grammar] ~563-~563: There might be a mistake here.
Context: ...withautoUpdate=true` to track state changes 6. Test Organization - Group related t...
(QB_NEW_EN_OTHER)
[grammar] ~566-~566: There might be a mistake here.
Context: ...Organization** - Group related tests logically - Test edge cases (empty documents, select...
(QB_NEW_EN_OTHER)
[grammar] ~567-~567: There might be a mistake here.
Context: ...e cases (empty documents, selections at boundaries) - Test interactions between features (e.g....
(QB_NEW_EN_OTHER)
[grammar] ~568-~568: There might be a mistake here.
Context: ...g., how lists interact with other block types) 7. Debugging Tips - Use `console.log(J...
(QB_NEW_EN_OTHER)
[grammar] ~571-~571: There might be a mistake here.
Context: ....state.doc.toJSON()))to view document structure - Check selection ranges withconsole.log...
(QB_NEW_EN_OTHER)
[grammar] ~573-~573: Use correct spacing
Context: ... - Add debug elements to show editor content: container.appendChild(view.dom)
(QB_NEW_EN_OTHER_ERROR_IDS_5)
🪛 GitHub Check: Lint
src/components/text-editor/test-setup/command-tester.spec.ts
[failure] 145-145:
Delete ,
[failure] 117-117:
Delete ,
[failure] 81-81:
Delete ,
[failure] 44-44:
Delete ,
src/components/text-editor/test-setup/command-tester.ts
[warning] 120-120:
Missing JSDoc @param "expected.docContentAfter" declaration
[warning] 120-120:
Missing JSDoc @param "expected.shouldApply" declaration
[failure] 91-91:
Delete ,
[failure] 80-80:
Delete ,
[warning] 64-64:
Missing @param "expected.includesContent"
[warning] 64-64:
Missing @param "expected.docSizeAfter"
[warning] 64-64:
Missing @param "expected.docContentAfter"
[warning] 64-64:
Missing @param "expected.shouldApply"
[warning] 60-60:
Missing JSDoc @param "expected.includesContent" declaration
[warning] 60-60:
Missing JSDoc @param "expected.docSizeAfter" declaration
[warning] 60-60:
Missing JSDoc @param "expected.docContentAfter" declaration
[warning] 60-60:
Missing JSDoc @param "expected.shouldApply" declaration
[failure] 41-41:
Delete ,
[failure] 31-31:
Delete ,
🪛 Biome (1.9.4)
src/components/text-editor/test-setup/content-generator.ts
[error] 122-122: This type annotation is trivially inferred from its initialization.
Safe fix: Remove the type annotation.
(lint/style/noInferrableTypes)
src/components/text-editor/test-setup/content-generator.spec.ts
[error] 115-115: Change to an optional chain.
Unsafe fix: Change to an optional chain.
(lint/complexity/useOptionalChain)
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{ts,tsx}
⚙️ CodeRabbit Configuration File
Imports from other files in the same module (lime-elements) must use relative paths. Using absolute paths for imports will cause the production build to fail.
Files:
src/components/text-editor/test-setup/command-tester.spec.tssrc/components/text-editor/test-setup/editor-view-builder.tssrc/components/text-editor/test-setup/event-simulator.tssrc/components/text-editor/test-setup/command-tester.tssrc/components/text-editor/test-setup/editor-view-builder.spec.tssrc/components/text-editor/test-setup/content-generator.tssrc/components/text-editor/test-setup/content-generator.spec.tssrc/components/text-editor/test-setup/event-simulator.spec.ts
🧠 Learnings (3)
src/components/text-editor/test-setup/event-simulator.ts (1)
Learnt from: adrianschmidt
PR: #3547
File: src/components/text-editor/examples/text-editor-with-inline-images-file-storage.tsx:46-46
Timestamp: 2025-05-02T07:14:19.314Z
Learning: When reviewing TypeScript/JavaScript code, don't suggest converting object literals to constants when the object is mutable and will be modified later in the code. Due to reference semantics, this can cause unintended side effects where the "constant" version is also modified.
src/components/text-editor/test-setup/editor-view-builder.spec.ts (3)
Learnt from: adrianschmidt
PR: #3547
File: src/components/text-editor/examples/text-editor-with-inline-images-file-storage.tsx:46-46
Timestamp: 2025-05-02T07:14:19.314Z
Learning: When reviewing TypeScript/JavaScript code, don't suggest converting object literals to constants when the object is mutable and will be modified later in the code. Due to reference semantics, this can cause unintended side effects where the "constant" version is also modified.
Learnt from: adrianschmidt
PR: #3607
File: docs-index.html:0-0
Timestamp: 2025-07-16T13:28:26.858Z
Learning: Before suggesting any code changes as "safe," thoroughly analyze the entire codebase context, including dependencies, usage patterns, and potential side effects. What appears to be a simple performance optimization might break existing functionality due to execution order or timing dependencies.
Learnt from: adrianschmidt
PR: #3607
File: docs-index.html:0-0
Timestamp: 2025-07-16T13:28:26.858Z
Learning: When suggesting script optimizations like adding defer or async attributes, always analyze the entire HTML file to check for dependencies between external scripts and inline scripts. Scripts loaded with defer execute after DOM parsing but before DOMContentLoaded, which can break synchronous dependencies with inline scripts that expect variables to be immediately available.
src/components/text-editor/test-setup/content-generator.ts (2)
Learnt from: adrianschmidt
PR: #3530
File: src/components/text-editor/examples/text-editor-composite.tsx:4-7
Timestamp: 2025-04-17T09:39:36.254Z
Learning: For lime-elements, example files should import types from the public API using '@limetech/lime-elements' rather than defining duplicate types locally. This includes types like EditorUiType which are part of the component's public API.
Learnt from: adrianschmidt
PR: #3464
File: src/components/text-editor/prosemirror-adapter/plugins/image/inserter.ts:1-11
Timestamp: 2025-03-04T14:27:29.714Z
Learning: In example components (typically found in src/components/*/examples/), imports of lime-elements exports should use @limetech/lime-elements instead of relative paths. This is because example components aren't included in type declarations and are used in documentation to show developers how to properly use lime-elements components.
🧬 Code Graph Analysis (5)
src/components/text-editor/test-setup/command-tester.spec.ts (2)
src/components/text-editor/test-setup/command-tester.ts (4)
getCommandResult(29-58)testCommand(72-118)testCommandWithView(128-179)createCommandTester(187-196)src/components/text-editor/test-setup/editor-view-builder.ts (1)
cleanupEditorView(78-85)
src/components/text-editor/test-setup/editor-view-builder.ts (1)
src/components/text-editor/test-setup/schema-builder.ts (1)
createTestSchema(12-33)
src/components/text-editor/test-setup/command-tester.ts (1)
src/components/text-editor/test-setup/editor-view-builder.ts (1)
createEditorView(14-45)
src/components/text-editor/test-setup/editor-view-builder.spec.ts (1)
src/components/text-editor/test-setup/editor-view-builder.ts (4)
cleanupEditorView(78-85)createEditorView(14-45)createDispatchSpy(53-69)mockProseMirrorDOMEnvironment(93-135)
src/components/text-editor/test-setup/content-generator.ts (1)
src/components/text-editor/test-setup/schema-builder.ts (1)
createTestSchema(12-33)
🪛 LanguageTool
src/components/text-editor/test-setup/text-editor-test-utils.md
[grammar] ~1-~1: Use correct spacing
Context: # Text Editor Testing Utilities This directory contains utility function...
(QB_NEW_EN_OTHER_ERROR_IDS_5)
[grammar] ~3-~3: Use correct spacing
Context: ...e text editor component and its related components. ## Core Testing Utilities 1. **Schema Setu...
(QB_NEW_EN_OTHER_ERROR_IDS_5)
[grammar] ~5-~5: Use correct spacing
Context: ...ts related components. ## Core Testing Utilities 1. Schema Setup - createTestSchema()...
(QB_NEW_EN_OTHER_ERROR_IDS_5)
[grammar] ~7-~7: Use correct spacing
Context: ... ## Core Testing Utilities 1. Schema Setup - createTestSchema() - Creates a ProseMirror schema with all n...
(QB_NEW_EN_OTHER_ERROR_IDS_5)
[grammar] ~8-~8: Use hyphens correctly
Context: ...Mirror schema with all needed marks and nodes - createCustomTestSchema(options) - Creates a custom schema with specified...
(QB_NEW_EN_OTHER_ERROR_IDS_29)
[grammar] ~9-~9: There might be a mistake here.
Context: ... Creates a custom schema with specified extensions 2. Editor State Utilities - `createEdi...
(QB_NEW_EN_OTHER)
[grammar] ~11-~11: Use correct spacing
Context: ...specified extensions 2. Editor State Utilities - createEditorState(content?, schema?) - Creates an editor state with optional c...
(QB_NEW_EN_OTHER_ERROR_IDS_5)
[grammar] ~12-~12: Use hyphens correctly
Context: ...- Creates an editor state with optional content - createEditorStateWithSelection(content, from, to, schema?) - Creates an editor state with a specifi...
(QB_NEW_EN_OTHER_ERROR_IDS_29)
[grammar] ~13-~13: There might be a mistake here.
Context: ...Creates an editor state with a specific selection 3. Editor View Utilities - `createEdit...
(QB_NEW_EN_OTHER)
[grammar] ~15-~15: Use correct spacing
Context: ... a specific selection 3. Editor View Utilities - createEditorView(state, dispatchSpy?) - Creates a ProseMirror editor view with ...
(QB_NEW_EN_OTHER_ERROR_IDS_5)
[grammar] ~16-~16: Use hyphens correctly
Context: ...r editor view with an optional dispatch spy - cleanupEditorView(view) - Properly destroys an editor view to pr...
(QB_NEW_EN_OTHER_ERROR_IDS_29)
[grammar] ~17-~17: There might be a mistake here.
Context: ...stroys an editor view to prevent memory leaks 4. Content Generation - `createDocWith...
(QB_NEW_EN_OTHER)
[grammar] ~19-~19: Use correct spacing
Context: ...w to prevent memory leaks 4. Content Generation - createDocWithText(text, schema?) - Creates a document with plain text -...
(QB_NEW_EN_OTHER_ERROR_IDS_5)
[grammar] ~20-~20: Use hyphens correctly
Context: ...hema?)- Creates a document with plain text -createDocWithHTML(html, schema?)` - Creates a document from HTML string ...
(QB_NEW_EN_OTHER_ERROR_IDS_29)
[grammar] ~21-~21: There might be a problem here.
Context: ...ml, schema?)- Creates a document from HTML string -createDocWithFormattedText(text, marks, schema?)` - Creates a document with marked text 5...
(QB_NEW_EN_MERGED_MATCH)
[grammar] ~22-~22: There might be a mistake here.
Context: ...ema?)- Creates a document with marked text 5. **Command Testing** -testCommand(comm...
(QB_NEW_EN_OTHER)
[grammar] ~24-~24: Use correct spacing
Context: ...document with marked text 5. Command Testing - testCommand(command, state, expected) - Tests a command and verifies the result...
(QB_NEW_EN_OTHER_ERROR_IDS_5)
[grammar] ~25-~25: Use correct spacing
Context: ...ed)- Tests a command and verifies the result -getCommandResult(command, state)` - Gets the result of applying a command ...
(QB_NEW_EN_OTHER_ERROR_IDS_5)
[grammar] ~26-~26: Use correct spacing
Context: ...state)- Gets the result of applying a command -testCommandWithView(command, state, expected)` - Tests a command that requires view cont...
(QB_NEW_EN_OTHER_ERROR_IDS_5)
[grammar] ~27-~27: Use correct spacing
Context: ...)- Tests a command that requires view context -createCommandTester(command)` - Creates a reusable tester for a specifi...
(QB_NEW_EN_OTHER_ERROR_IDS_5)
[grammar] ~28-~28: Use correct spacing
Context: ...reates a reusable tester for a specific command 6. Mocks - createDispatchSpy() - Cre...
(QB_NEW_EN_OTHER_ERROR_IDS_5)
[grammar] ~31-~31: Use hyphens correctly
Context: ...- Creates a Jest spy for the dispatch function -createMockEditorView()- Creates a mocked editor view -mo...
(QB_NEW_EN_OTHER_ERROR_IDS_29)
[grammar] ~32-~32: Use hyphens correctly
Context: ...EditorView()- Creates a mocked editor view -mockProseMirrorDOMEnvironment()` - Sets up the DOM environment for ProseM...
(QB_NEW_EN_OTHER_ERROR_IDS_29)
[grammar] ~33-~33: There might be a mistake here.
Context: ...nt()- Sets up the DOM environment for ProseMirror 7. **Selection Helpers** -setTextSelecti...
(QB_NEW_EN_OTHER)
[grammar] ~35-~35: Use correct spacing
Context: ...ronment for ProseMirror 7. Selection Helpers - setTextSelection(state, from, to) - Creates a text selection - `setNodeS...
(QB_NEW_EN_OTHER_ERROR_IDS_5)
[grammar] ~36-~36: Use correct spacing
Context: ...tion(state, from, to)- Creates a text selection -setNodeSelection(state, pos)` - Creates a node selection 8. **Event Si...
(QB_NEW_EN_OTHER_ERROR_IDS_5)
[grammar] ~37-~37: Use correct spacing
Context: ...Selection(state, pos)- Creates a node selection 8. **Event Simulation** -simulateKeyPres...
(QB_NEW_EN_OTHER_ERROR_IDS_5)
[grammar] ~39-~39: Use correct spacing
Context: ... - Creates a node selection 8. Event Simulation - simulateKeyPress(view, key, modifiers?) - Simulates a key press on the editor ...
(QB_NEW_EN_OTHER_ERROR_IDS_5)
[grammar] ~40-~40: Use correct spacing
Context: ...fiers?)- Simulates a key press on the editor -simulatePaste(view, content)` - Simulates pasting content into the edit...
(QB_NEW_EN_OTHER_ERROR_IDS_5)
[grammar] ~42-~42: Use correct spacing
Context: ...clientY, options?)- Simulates a mouse click -simulateDragAndDrop(view, startX, startY, endX, endY, dragData?)` - Simulates drag and drop ## Usage Examp...
(QB_NEW_EN_OTHER_ERROR_IDS_5)
[grammar] ~43-~43: Use correct spacing
Context: ... endY, dragData?)` - Simulates drag and drop ## Usage Example ```typescript import { ...
(QB_NEW_EN_OTHER_ERROR_IDS_5)
[grammar] ~45-~45: Use correct spacing
Context: ...?)` - Simulates drag and drop ## Usage Example typescript import { createTestSchema, createEditorState, createEditorView, simulateKeyPress, cleanupEditorView } from '../test-setup/test-utils'; describe('Text Editor', () => { let schema, state, view; beforeEach(() => { schema = createTestSchema(); state = createEditorState('<p>Test content</p>', schema); view = createEditorView(state); }); afterEach(() => { cleanupEditorView(view); }); it('should apply bold formatting with keyboard shortcut', () => { // Setup test case // Simulate keypress // Assert results }); }); ## Command Testing Example ```typescript i...
(QB_NEW_EN_OTHER_ERROR_IDS_5)
[grammar] ~77-~77: Use correct spacing
Context: ...sults }); }); ## Command Testing Example typescript import { createEditorState, testCommand, createCommandTester } from '../test-setup/test-utils'; import { toggleMark } from 'prosemirror-commands'; describe('Text Editor Commands', () => { it('should toggle bold mark when applicable', () => { // Create state with selected text const state = createEditorStateWithSelection('
Test content
', 1, 5); // Get the bold mark from schema const boldMark = state.schema.marks.strong; const toggleBold = toggleMark(boldMark); // Test the command testCommand(toggleBold, state, { shouldApply: true, // Additional expectations if needed }); }); it('should test multiple states with the same command', () => { // Create a reusable tester for a command const testToggleBold = createCommandTester(toggleMark(schema.marks.strong)); // Test with different states testToggleBold(state1, { shouldApply: true }); testToggleBold(state2, { shouldApply: false }); }); }); ## Event Simulation Example typescript ...
(QB_NEW_EN_OTHER_ERROR_IDS_5)
[grammar] ~114-~114: Use correct spacing
Context: ... }); }); }); ## Event Simulation Example typescript import { createEditorState, createEditorView, simulateKeyPress, simulatePaste, cleanupEditorView } from '../test-setup/test-utils'; describe('Text Editor Event Handling', () => { let view, container; beforeEach(() => { const state = createEditorState('
Test content
'); const result = createEditorView(state); view = result.view; container = result.container; }); afterEach(() => { cleanupEditorView(view, container); }); it('should handle Ctrl+B keyboard shortcut', () => { // Select some text first // ... // Simulate pressing Ctrl+B for bold simulateKeyPress(view, 'b', { ctrl: true }); // Verify text is now bold // ... }); it('should handle paste events correctly', () => { // Simulate pasting HTML content simulatePaste(view, { text: 'Plain text version', html: 'Formatted HTML content
' }); // Verify pasted content was properly processed // ... }); }); ```(QB_NEW_EN_OTHER_ERROR_IDS_5)
src/components/text-editor/test-setup/text-editor-test-suite-guide.md
[grammar] ~1-~1: Use correct spacing
Context: # Text Editor Testing Suite Guide This document serves as the practical gu...
(QB_NEW_EN_OTHER_ERROR_IDS_5)
[grammar] ~3-~3: Use correct spacing
Context: ...ing tests using the text editor testing utilities. ## Overview Our testing suite provides a c...
(QB_NEW_EN_OTHER_ERROR_IDS_5)
[grammar] ~7-~7: There might be a mistake here.
Context: ...effectively test your ProseMirror-based components: - Schema setup for testing - Editor state...
(QB_NEW_EN_OTHER)
[grammar] ~14-~14: Use correct spacing
Context: ... testing - Event simulation - Mocks and helpers ## Available Utilities ### 1. Schema Setup...
(QB_NEW_EN_OTHER_ERROR_IDS_5)
[grammar] ~16-~16: Use correct spacing
Context: ...ation - Mocks and helpers ## Available Utilities ### 1. Schema Setup - createTestSchema() ...
(QB_NEW_EN_OTHER_ERROR_IDS_5)
[grammar] ~18-~18: Use correct spacing
Context: ... ## Available Utilities ### 1. Schema Setup - createTestSchema() - Creates a standard ProseMirror schema...
(QB_NEW_EN_OTHER_ERROR_IDS_5)
[grammar] ~20-~20: Use hyphens correctly
Context: ...Mirror schema with all needed marks and nodes - createCustomTestSchema(options) - Creates a custom schema with specified...
(QB_NEW_EN_OTHER_ERROR_IDS_29)
[grammar] ~21-~21: There might be a mistake here.
Context: ... Creates a custom schema with specified extensions typescript // Create a standard schema with all marks and nodes const schema = createTestSchema(); // Create a custom schema with only specific features const customSchema = createCustomTestSchema({ addLists: true, // Add ordered and bullet list support addStrikethrough: true, // Add strikethrough mark addUnderline: false // Skip underline mark }); ### 2. Editor State Utilities - `createEdit...
(QB_NEW_EN_OTHER)
[grammar] ~35-~35: Use correct spacing
Context: ...rline mark }); ``` ### 2. Editor State Utilities - createEditorState(content?, schema?, plugins?) - Creates an editor state with optional...
(QB_NEW_EN_OTHER_ERROR_IDS_5)
[grammar] ~37-~37: Use correct spacing
Context: ...- Creates an editor state with optional content - createEditorStateWithSelection(content, from, to, schema?, plugins?) - Creates an editor state with a specific...
(QB_NEW_EN_OTHER_ERROR_IDS_5)
[grammar] ~38-~38: Use correct spacing
Context: ...Creates an editor state with a specific selection - setTextSelection(state, from, to?) - Sets a text selection on an existing st...
(QB_NEW_EN_OTHER_ERROR_IDS_5)
[grammar] ~39-~39: Use correct spacing
Context: ... - Sets a text selection on an existing state - createDocumentWithText(text?, schema?) - Creates a simple document with text ``...
(QB_NEW_EN_OTHER_ERROR_IDS_5)
[grammar] ~40-~40: Use correct spacing
Context: ...ema?)- Creates a simple document with text ```typescript // Create an empty editor state const emptyState = createEditorState(); // Create state with HTML content const state = createEditorState('<p>This is <strong>bold</strong> text.</p>'); // Create state with selection (from position 5 to 10) const stateWithSelection = createEditorStateWithSelection( '<p>Select this text</p>', 5, 10 ); // Add a text selection to an existing state const newState = setTextSelection(state, 1, 5); ``` ### 3. Editor View Utilities -createEdito...
(QB_NEW_EN_OTHER_ERROR_IDS_5)
[grammar] ~60-~60: Use correct spacing
Context: ...n(state, 1, 5); ``` ### 3. Editor View Utilities - createEditorView(state?, dispatchSpy?, parentElement?) - Creates a ProseMirror editor view wit...
(QB_NEW_EN_OTHER_ERROR_IDS_5)
[grammar] ~62-~62: Use correct spacing
Context: ...rror editor view with optional dispatch spy - createDispatchSpy(autoUpdate?) - Creates a Jest spy function for trackin...
(QB_NEW_EN_OTHER_ERROR_IDS_5)
[grammar] ~63-~63: Use correct spacing
Context: ...Jest spy function for tracking dispatch calls - cleanupEditorView(view, container?) - Properly destroys an editor view to pre...
(QB_NEW_EN_OTHER_ERROR_IDS_5)
[grammar] ~64-~64: Use correct spacing
Context: ...stroys an editor view to prevent memory leaks - mockProseMirrorDOMEnvironment() - Sets up the DOM environment for ProseMi...
(QB_NEW_EN_OTHER_ERROR_IDS_5)
[grammar] ~65-~65: Use correct spacing
Context: ... the DOM environment for ProseMirror in Node.js typescript // Create a view with state const { view, container } = createEditorView(state); // Create a view with dispatch tracking const dispatchSpy = createDispatchSpy(true); // autoUpdate=true const { view: viewWithSpy } = createEditorView(state, dispatchSpy); // Create a view with custom parent element const parent = document.createElement('div'); const { view: viewWithParent } = createEditorView(state, null, parent); // Clean up after testing cleanupEditorView(view, container); // Mock DOM environment for Node.js tests const cleanup = mockProseMirrorDOMEnvironment(); // ... test code ... cleanup(); // Restore original environment ### 4. Content Generation - `createDocWithT...
(QB_NEW_EN_OTHER_ERROR_IDS_5)
[grammar] ~88-~88: Use correct spacing
Context: ...riginal environment ``` ### 4. Content Generation - createDocWithText(text, schema?) - Creates a document with plain text - ...
(QB_NEW_EN_OTHER_ERROR_IDS_5)
[grammar] ~90-~90: Use correct spacing
Context: ...hema?)- Creates a document with plain text -createDocWithHTML(html, schema?)- Creates a document from HTML string -...
(QB_NEW_EN_OTHER_ERROR_IDS_5)
[grammar] ~91-~91: There might be a problem here.
Context: ...ml, schema?)- Creates a document from HTML string -createDocWithFormattedText(text, marks, schema?)- Creates a document with marked text -...
(QB_NEW_EN_MERGED_MATCH)
[grammar] ~92-~92: Use correct spacing
Context: ...ema?)- Creates a document with marked text -createDocWithBulletList(items, schema?)` - Creates a document with a bullet list -...
(QB_NEW_EN_OTHER_ERROR_IDS_5)
[grammar] ~93-~93: Use correct spacing
Context: ...a?)- Creates a document with a bullet list -createDocWithHeading(text, level?, schema?)- Creates a document with a heading -cr...
(QB_NEW_EN_OTHER_ERROR_IDS_5)
[grammar] ~94-~94: Use correct spacing
Context: ..., schema?)- Creates a document with a heading -createDocWithBlockquote(text, schema?)` - Creates a document with a blockquote - ...
(QB_NEW_EN_OTHER_ERROR_IDS_5)
[grammar] ~95-~95: Use correct spacing
Context: ..., schema?)- Creates a document with a blockquote -createDocWithCodeBlock(code, schema?)- Creates a document with a code block ...
(QB_NEW_EN_OTHER_ERROR_IDS_5)
[grammar] ~96-~96: Use correct spacing
Context: ...ema?)- Creates a document with a code block ```typescript // Create documents with different content types const textDoc = createDocWithText('Simple text'); const htmlDoc = createDocWithHTML('<p>HTML <em>content</em></p>'); // Create a document with formatted text const formattedDoc = createDocWithFormattedText('Bold and italic text', [ { type: 'strong', attrs: {} }, // Apply to all text { type: 'em', attrs: {}, from: 0, to: 4 } // Only apply to "Bold" ]); // Create various structured documents const listDoc = createDocWithBulletList(['Item 1', 'Item 2', 'Item 3']); const headingDoc = createDocWithHeading('Section Title', 2); // h2 const quoteDoc = createDocWithBlockquote('Famous quote here'); const codeDoc = createDocWithCodeBlock('function test() { return true; }'); ``` ### 5. Command Testing -testCommand(comma...
(QB_NEW_EN_OTHER_ERROR_IDS_5)
[grammar] ~116-~116: Use correct spacing
Context: ...{ return true; }'); ``` ### 5. Command Testing - testCommand(command, state, expected) - Tests a command and verifies the resu...
(QB_NEW_EN_OTHER_ERROR_IDS_5)
[grammar] ~118-~118: Use correct spacing
Context: ...ed)- Tests a command and verifies the result -getCommandResult(command, state)` - Gets the result of applying a command -...
(QB_NEW_EN_OTHER_ERROR_IDS_5)
[grammar] ~119-~119: Use correct spacing
Context: ...state)- Gets the result of applying a command -testCommandWithView(command, state, expected)` - Tests a command that requires view cont...
(QB_NEW_EN_OTHER_ERROR_IDS_5)
[grammar] ~120-~120: Use correct spacing
Context: ...)- Tests a command that requires view context -createCommandTester(command)` - Creates a reusable tester for a specifi...
(QB_NEW_EN_OTHER_ERROR_IDS_5)
[grammar] ~121-~121: Use correct spacing
Context: ...reates a reusable tester for a specific command typescript // Test if a command can be applied const result = getCommandResult(toggleMark(schema.marks.strong), state); expect(result.canApply).toBe(true); // Test a command with expectations testCommand(toggleMark(schema.marks.strong), state, { shouldApply: true, // Command should apply docChanged: true, // Document should change selectionChanged: false, // Selection should not change storedMarksChanged: false // Stored marks should not change }); // Create a reusable command tester const testBold = createCommandTester(toggleMark(schema.marks.strong)); testBold(state1, { shouldApply: true }); testBold(state2, { shouldApply: false }); // Test a command that requires view context testCommandWithView(someViewCommand, state, { shouldApply: true, // other expectations... }); ### 6. Mocks - createDispatchSpy() - Crea...
(QB_NEW_EN_OTHER_ERROR_IDS_5)
[grammar] ~148-~148: Use correct spacing
Context: .../ other expectations... }); ``` ### 6. Mocks - createDispatchSpy() - Creates a Jest spy for the dispatch f...
(QB_NEW_EN_OTHER_ERROR_IDS_5)
[grammar] ~150-~150: Use hyphens correctly
Context: ...- Creates a Jest spy for the dispatch function -mockProseMirrorDOMEnvironment()` - Sets up the DOM environment for ProseM...
(QB_NEW_EN_OTHER_ERROR_IDS_29)
[grammar] ~151-~151: There might be a mistake here.
Context: ...nt()- Sets up the DOM environment for ProseMirror ```typescript // Create a dispatch spy with auto-updating state const dispatchSpy = createDispatchSpy(true); const { view } = createEditorView(state, dispatchSpy); // Execute a command that should dispatch someCommand(view.state, view.dispatch, view); // Verify dispatch was called expect(dispatchSpy).toHaveBeenCalled(); // Get the latest state after updates const updatedState = dispatchSpy.state; ``` ### 7. Selection Helpers -setTextSelectio...
(QB_NEW_EN_OTHER)
[grammar] ~168-~168: Use correct spacing
Context: ...ispatchSpy.state; ``` ### 7. Selection Helpers - setTextSelection(state, from, to) - Creates a text selection - `setNodeSe...
(QB_NEW_EN_OTHER_ERROR_IDS_5)
[grammar] ~170-~170: Use correct spacing
Context: ...tion(state, from, to)- Creates a text selection -setNodeSelection(state, pos)` - Creates a node selection (planned) ```...
(QB_NEW_EN_OTHER_ERROR_IDS_5)
[grammar] ~171-~171: Use correct spacing
Context: ...state, pos)- Creates a node selection (planned) ```typescript // Create a state with a selection let state = createEditorState('<p>Select this text</p>'); // Apply a text selection from position 3 to 9 state = setTextSelection(state, 3, 9); expect(state.selection.from).toBe(3); expect(state.selection.to).toBe(9); ``` ### 8. Event Simulation -simulateKeyPress...
(QB_NEW_EN_OTHER_ERROR_IDS_5)
[grammar] ~183-~183: Use correct spacing
Context: ...election.to).toBe(9); ``` ### 8. Event Simulation - simulateKeyPress(view, key, modifiers?) - Simulates a key press on the editor -...
(QB_NEW_EN_OTHER_ERROR_IDS_5)
[grammar] ~185-~185: Use correct spacing
Context: ...fiers?)- Simulates a key press on the editor -simulatePaste(view, content)` - Simulates pasting content into the edit...
(QB_NEW_EN_OTHER_ERROR_IDS_5)
[grammar] ~187-~187: Use correct spacing
Context: ...clientY, options?)- Simulates a mouse click -simulateDragAndDrop(view, startX, startY, endX, endY, dragData?)` - Simulates drag and drop ```typescript ...
(QB_NEW_EN_OTHER_ERROR_IDS_5)
[grammar] ~188-~188: Use correct spacing
Context: ... endY, dragData?)` - Simulates drag and drop typescript // Simulate keyboard shortcuts simulateKeyPress(view, 'b', { ctrl: true }); // Ctrl+B for bold simulateKeyPress(view, 'z', { ctrl: true }); // Ctrl+Z for undo simulateKeyPress(view, 'Tab'); // Tab key // Simulate paste with both text and HTML simulatePaste(view, { text: 'Plain text', html: '<p><strong>Formatted</strong> HTML</p>' }); // Simulate mouse interactions simulateClick(view, 100, 150); // Click at x=100, y=150 simulateDragAndDrop(view, 50, 50, 200, 50); // Drag from x=50 to x=200 ## Common Testing Patterns ### Basic Test ...
(QB_NEW_EN_OTHER_ERROR_IDS_5)
[grammar] ~207-~207: Use correct spacing
Context: ...om x=50 to x=200 ## Common Testing Patterns ### Basic Test Setup typescript import {...
(QB_NEW_EN_OTHER_ERROR_IDS_5)
[grammar] ~209-~209: Use correct spacing
Context: ...Common Testing Patterns ### Basic Test Setup typescript import { createTestSchema, createEditorState, createEditorView, cleanupEditorView } from '../test-setup/test-utils'; describe('Text Editor', () => { let schema, state, view, container; beforeEach(() => { schema = createTestSchema(); state = createEditorState('<p>Test content</p>', schema); const result = createEditorView(state); view = result.view; container = result.container; }); afterEach(() => { cleanupEditorView(view, container); }); it('should render content correctly', () => { expect(view.dom.textContent).toContain('Test content'); }); }); ### Testing Commands ```typescript import {...
(QB_NEW_EN_OTHER_ERROR_IDS_5)
[grammar] ~240-~240: Use correct spacing
Context: ...t content'); }); }); ### Testing Commands typescript import { createTestSchema, createEditorStateWithSelection, testCommand } from '../test-setup/test-utils'; import { toggleMark } from 'prosemirror-commands'; describe('Bold Command', () => { let schema; beforeEach(() => { schema = createTestSchema(); }); it('should apply bold to selected text', () => { // Create state with text selection const state = createEditorStateWithSelection('
Test content
', 1, 5); // Test the bold command const boldMark = schema.marks.strong; testCommand(toggleMark(boldMark), state, { shouldApply: true, docChanged: true }); }); it('should toggle off bold when already applied', () => { // Create state with bold text and selection const state = createEditorStateWithSelection( 'Test content
', 1, 5 ); // Test the bold command (should toggle off) const boldMark = schema.marks.strong; testCommand(toggleMark(boldMark), state, { shouldApply: true, docChanged: true }); // Verify bold was removed (use the resulting state from testCommand) // ... }); }); ### Testing Keyboard Shortcuts typescrip...
(QB_NEW_EN_OTHER_ERROR_IDS_5)
[grammar] ~289-~289: Use correct spacing
Context: ...... }); }); ### Testing Keyboard Shortcuts typescript import { createTestSchema, createEditorState, createEditorView, setTextSelection, simulateKeyPress, cleanupEditorView } from '../test-setup/test-utils'; describe('Keyboard Shortcuts', () => { let schema, view, container; beforeEach(() => { schema = createTestSchema(); const state = createEditorState('
Test content
', schema); const result = createEditorView(state); view = result.view; container = result.container; }); afterEach(() => { cleanupEditorView(view, container); }); it('should apply bold with Ctrl+B', () => { // Set selection const newState = setTextSelection(view.state, 1, 5); view.dispatch(newState.tr); // Simulate Ctrl+B simulateKeyPress(view, 'b', { ctrl: true }); // Verify result const textNode = view.state.doc.nodeAt(1); const hasBold = textNode.marks.some(mark => mark.type.name === 'strong'); expect(hasBold).toBe(true); }); it('should create a list when pressing Tab in a list item', () => { // Set up a list state const listState = createEditorState( 'First item
Second item
### Testing Paste Handling typescript im...
(QB_NEW_EN_OTHER_ERROR_IDS_5)
[grammar] ~363-~363: Use correct spacing
Context: ... return depth; } ### Testing Paste Handling typescript import { createEditorState, createEditorView, simulatePaste, cleanupEditorView } from '../test-setup/test-utils'; describe('Paste Handling', () => { let view, container; beforeEach(() => { const state = createEditorState('
Existing content
'); const result = createEditorView(state); view = result.view; container = result.container; // Position cursor at end of paragraph const endPos = 17; view.dispatch(view.state.tr.setSelection( TextSelection.create(view.state.doc, endPos) )); }); afterEach(() => { cleanupEditorView(view, container); }); it('should handle plain text paste', () => { simulatePaste(view, { text: 'Pasted text' }); expect(view.state.doc.textContent).toBe('Existing contentPasted text'); }); it('should handle HTML paste', () => { simulatePaste(view, { text: 'Pasted text with bold', html: 'Pasted text with bold' }); expect(view.state.doc.textContent).toBe('Existing contentPasted text with bold'); // Check if "bold" has the strong mark const textPos = view.state.doc.textContent.indexOf('bold'); const nodeWithMark = view.state.doc.nodeAt(textPos); const hasBold = nodeWithMark.marks.some(mark => mark.type.name === 'strong'); expect(hasBold).toBe(true); }); }); ### Testing Lists typescript import { ...
(QB_NEW_EN_OTHER_ERROR_IDS_5)
[grammar] ~416-~416: Use correct spacing
Context: ....toBe(true); }); }); ### Testing Lists typescript import { createTestSchema, createDocWithBulletList, createEditorState, createEditorView, simulateKeyPress, cleanupEditorView } from '../test-setup/test-utils'; import { wrapInList } from 'prosemirror-schema-list'; describe('List Functionality', () => { let schema, view, container; beforeEach(() => { schema = createTestSchema(); const listItems = ['First item', 'Second item', 'Third item']; const doc = createDocWithBulletList(listItems, schema); const state = createEditorState(doc); const result = createEditorView(state); view = result.view; container = result.container; }); afterEach(() => { cleanupEditorView(view, container); }); it('should indent list item on Tab', () => { // Position cursor in second list item const secondItemPos = findPositionInListItem(view.state, 1); view.dispatch(view.state.tr.setSelection( TextSelection.create(view.state.doc, secondItemPos) )); // Simulate Tab simulateKeyPress(view, 'Tab'); // Verify second item is now a sublist of first item const listStructure = getListStructure(view.state); expect(listStructure).toEqual({ items: [ { text: 'First item', children: [ { text: 'Second item', children: [] } ]}, { text: 'Third item', children: [] } ] }); }); it('should outdent list item on Shift+Tab', () => { // First, indent second item const secondItemPos = findPositionInListItem(view.state, 1); view.dispatch(view.state.tr.setSelection( TextSelection.create(view.state.doc, secondItemPos) )); simulateKeyPress(view, 'Tab'); // Then outdent it with Shift+Tab simulateKeyPress(view, 'Tab', { shift: true }); // Verify structure is back to flat list const listStructure = getListStructure(view.state); expect(listStructure).toEqual({ items: [ { text: 'First item', children: [] }, { text: 'Second item', children: [] }, { text: 'Third item', children: [] } ] }); }); // Helper functions function findPositionInListItem(state, itemIndex) { // Implementation to find cursor position in specific list item return 0; // Placeholder } function getListStructure(state) { // Implementation to extract list structure return { items: [] }; // Placeholder } }); ``` ## Implementation Status | Category | Util...
(QB_NEW_EN_OTHER_ERROR_IDS_5)
[grammar] ~503-~503: Use correct spacing
Context: ...ceholder } }); ``` ## Implementation Status | Category | Utility | Status | |-------...
(QB_NEW_EN_OTHER_ERROR_IDS_5)
[grammar] ~538-~538: Use correct spacing
Context: ...agAndDrop()` | ✅ Implemented | ## Best Practices 1. Setup and Cleanup - Always clean up...
(QB_NEW_EN_OTHER_ERROR_IDS_5)
[grammar] ~541-~541: There might be a mistake here.
Context: ...tor views after tests to prevent memory leaks - Create schema once per test suite when p...
(QB_NEW_EN_OTHER)
[grammar] ~542-~542: There might be a mistake here.
Context: ... Create schema once per test suite when possible - Use beforeEach and afterEach for con...
(QB_NEW_EN_OTHER)
[grammar] ~543-~543: There might be a mistake here.
Context: ...nd afterEach for consistent setup and cleanup 2. Content Creation - Use the appropri...
(QB_NEW_EN_OTHER)
[grammar] ~546-~546: There might be a mistake here.
Context: ...ontent generation utility for your test case - Create realistic content for more robust...
(QB_NEW_EN_OTHER)
[grammar] ~547-~547: There might be a mistake here.
Context: ...reate realistic content for more robust tests - Use HTML strings for complex document st...
(QB_NEW_EN_OTHER)
[grammar] ~548-~548: There might be a mistake here.
Context: ...- Use HTML strings for complex document structures 3. Command Testing - Test commands in ...
(QB_NEW_EN_OTHER)
[grammar] ~551-~551: There might be a mistake here.
Context: ...ds in isolation with testCommand when possible - Test both positive and negative cases (w...
(QB_NEW_EN_OTHER)
[grammar] ~552-~552: Use articles correctly
Context: ... both positive and negative cases (when command should and shouldn't apply) - Verify...
(QB_NEW_EN_OTHER_ERROR_IDS_11)
[grammar] ~552-~552: There might be a mistake here.
Context: ...ases (when command should and shouldn't apply) - Verify document structure after command ...
(QB_NEW_EN_OTHER)
[grammar] ~553-~553: There might be a mistake here.
Context: ...Verify document structure after command application 4. Event Handling - For keyboard short...
(QB_NEW_EN_OTHER)
[grammar] ~556-~556: There might be a mistake here.
Context: ...n is set up correctly before simulating keys - When testing paste events, include both ...
(QB_NEW_EN_OTHER)
[grammar] ~557-~557: There might be a mistake here.
Context: ...aste events, include both text and HTML variants - For mouse events, calculate positions re...
(QB_NEW_EN_OTHER)
[grammar] ~558-~558: There might be a mistake here.
Context: ...late positions relative to the document structure 5. State Management - Remember that ed...
(QB_NEW_EN_OTHER)
[typographical] ~561-~561: To join two clauses or set off examples, consider using an em dash.
Context: ...nt** - Remember that editor state is immutable - always use transactions - Use `view.d...
(QB_NEW_EN_DASH_RULE_EM)
[grammar] ~561-~561: There might be a mistake here.
Context: ... editor state is immutable - always use transactions - Use view.dispatch(tr) to update the vi...
(QB_NEW_EN_OTHER)
[grammar] ~562-~562: There might be a mistake here.
Context: ...view.dispatch(tr)to update the view's state - UsedispatchSpywithautoUpdate=true`...
(QB_NEW_EN_OTHER)
[grammar] ~563-~563: There might be a mistake here.
Context: ...withautoUpdate=true` to track state changes 6. Test Organization - Group related t...
(QB_NEW_EN_OTHER)
[grammar] ~566-~566: There might be a mistake here.
Context: ...Organization** - Group related tests logically - Test edge cases (empty documents, select...
(QB_NEW_EN_OTHER)
[grammar] ~567-~567: There might be a mistake here.
Context: ...e cases (empty documents, selections at boundaries) - Test interactions between features (e.g....
(QB_NEW_EN_OTHER)
[grammar] ~568-~568: There might be a mistake here.
Context: ...g., how lists interact with other block types) 7. Debugging Tips - Use `console.log(J...
(QB_NEW_EN_OTHER)
[grammar] ~571-~571: There might be a mistake here.
Context: ....state.doc.toJSON()))to view document structure - Check selection ranges withconsole.log...
(QB_NEW_EN_OTHER)
[grammar] ~573-~573: Use correct spacing
Context: ... - Add debug elements to show editor content: container.appendChild(view.dom)
(QB_NEW_EN_OTHER_ERROR_IDS_5)
🪛 GitHub Check: Lint
src/components/text-editor/test-setup/command-tester.spec.ts
[failure] 145-145:
Delete ,
[failure] 117-117:
Delete ,
[failure] 81-81:
Delete ,
[failure] 44-44:
Delete ,
src/components/text-editor/test-setup/command-tester.ts
[warning] 120-120:
Missing JSDoc @param "expected.docContentAfter" declaration
[warning] 120-120:
Missing JSDoc @param "expected.shouldApply" declaration
[failure] 91-91:
Delete ,
[failure] 80-80:
Delete ,
[warning] 64-64:
Missing @param "expected.includesContent"
[warning] 64-64:
Missing @param "expected.docSizeAfter"
[warning] 64-64:
Missing @param "expected.docContentAfter"
[warning] 64-64:
Missing @param "expected.shouldApply"
[warning] 60-60:
Missing JSDoc @param "expected.includesContent" declaration
[warning] 60-60:
Missing JSDoc @param "expected.docSizeAfter" declaration
[warning] 60-60:
Missing JSDoc @param "expected.docContentAfter" declaration
[warning] 60-60:
Missing JSDoc @param "expected.shouldApply" declaration
[failure] 41-41:
Delete ,
[failure] 31-31:
Delete ,
🪛 Biome (1.9.4)
src/components/text-editor/test-setup/content-generator.ts
[error] 122-122: This type annotation is trivially inferred from its initialization.
Safe fix: Remove the type annotation.
(lint/style/noInferrableTypes)
src/components/text-editor/test-setup/content-generator.spec.ts
[error] 115-115: Change to an optional chain.
Unsafe fix: Change to an optional chain.
(lint/complexity/useOptionalChain)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
- GitHub Check: Docs / Publish Docs
- GitHub Check: Build
- GitHub Check: Test
🔇 Additional comments (30)
src/components/text-editor/test-setup/text-editor-test-utils.md (1)
1-574: Excellent comprehensive documentation for the testing utilities.This documentation provides thorough coverage of the testing utilities with clear examples and usage patterns. The structured approach with categories, examples, and best practices makes it very developer-friendly. The implementation status table and common testing patterns are particularly valuable additions.
src/components/text-editor/test-setup/text-editor-test-suite-guide.md (1)
1-574: Well-structured and practical testing guide.This guide provides excellent practical examples and testing patterns that complement the utility documentation. The progressive complexity from basic setup to advanced list testing scenarios is well-designed. The best practices section and implementation status table are particularly useful for developers.
src/components/text-editor/test-setup/content-generator.spec.ts (1)
1-246: Comprehensive test coverage for content generation utilities.This test suite provides excellent coverage of all content generation functions with proper edge case testing, error handling validation, and structure verification. The tests are well-organized and follow good testing practices.
src/components/text-editor/test-setup/event-simulator.spec.ts (1)
1-194: Well-structured event simulation tests with comprehensive coverage.This test suite effectively validates all event simulation utilities with proper verification of event properties, modifiers, and data transfer. The setup and cleanup logic is correctly implemented, and the tests cover various event scenarios including keyboard shortcuts, paste operations, and drag-and-drop sequences.
src/components/text-editor/test-setup/command-tester.spec.ts (1)
1-189: Comprehensive command testing utilities with good coverage.This test suite effectively validates all command testing functions including both view-dependent and view-independent commands. The proper cleanup logic for view-based tests prevents memory leaks, and the testing of command applicability, state changes, and document modifications is thorough.
src/components/text-editor/test-setup/event-simulator.ts (5)
8-42: MockDataTransfer implementation looks good.The mock class provides a comprehensive implementation of the DataTransfer API for testing environments, including proper handling of data formats, files, and dynamic length tracking.
62-83: Keyboard event simulation implementation is solid.The function properly constructs KeyboardEvent objects with appropriate modifiers and dispatches them correctly on the editor's DOM node.
101-118: Paste event simulation correctly implemented.The function properly uses the extracted
createDataTransferhelper and correctly sets up the paste event with clipboardData.
183-247: Drag and drop simulation is well-implemented.The function properly sequences drag events and uses the extracted
createDataTransferhelper. The custom event creation approach handles environments where DragEvent constructor isn't available.
256-277: DataTransfer creation helper correctly extracts common logic.This helper function successfully addresses the previous code duplication by centralizing DataTransfer object creation and population logic.
src/components/text-editor/test-setup/editor-view-builder.ts (4)
14-45: Editor view creation utility is well-implemented.The function properly handles optional parameters, creates necessary DOM elements, and sets up the editor view with appropriate dispatch handling.
53-69: Dispatch spy utility provides flexible transaction tracking.The function cleverly uses closures to maintain view references and provides configurable auto-update behavior for testing scenarios.
78-85: Cleanup function correctly implemented with optional chaining.The function properly destroys the editor view and uses optional chaining for safe container removal, addressing the previous review suggestion.
93-135: DOM environment mocking is comprehensive and well-structured.The function provides thorough mock implementations of DOM APIs needed by ProseMirror, with proper state preservation and cleanup handling.
src/components/text-editor/test-setup/content-generator.ts (9)
1-1: MarkSpec import is correctly sourced from prosemirror-model.The import addresses the previous review comment by importing
MarkSpecfrom the appropriate ProseMirror library.
13-18: Text document creation is straightforward and correct.The function properly handles text wrapping and schema defaults for creating test content.
27-31: HTML document creation is appropriately implemented.The function provides a clean wrapper for HTML-based document creation with proper schema handling.
41-53: Formatted text creation properly delegates to helper function.The function correctly uses the helper for mark application and properly creates the document structure.
63-80: Mark application helper is robust with proper validation.The function correctly validates mark types against the schema and provides clear error messages for invalid marks.
89-110: Bullet list creation correctly structures list nodes.The function properly creates the nested structure of bullet lists with list items containing paragraphs.
120-136: Heading creation correctly implements level-based headings.The function properly creates heading nodes with the specified level attribute. The type annotation is maintained per user preference.
145-158: Blockquote creation follows proper document structure.The function correctly nests paragraph content within blockquote nodes as expected by ProseMirror.
167-179: Code block creation correctly omits paragraph wrapper.The function appropriately creates text nodes directly within code blocks, which is the correct structure for this node type.
src/components/text-editor/test-setup/command-tester.ts (2)
16-20: CommandResult interface is well-designed with clear semantics.The interface properly captures the different outcomes of command execution with appropriate optional fields.
187-196: Command tester factory provides clean reusability.The higher-order function elegantly creates reusable testing functions for specific commands.
src/components/text-editor/test-setup/editor-view-builder.spec.ts (5)
11-22: Test structure is well-organized with proper resource management.The test suite correctly handles setup and teardown of editor views to prevent memory leaks.
23-70: Comprehensive test coverage for editor view creation.The tests thoroughly cover all parameter combinations and verify proper integration with dispatch spies and custom containers.
72-118: Dispatch spy tests thoroughly verify tracking and update behavior.The tests properly validate both the transaction tracking and the conditional state update functionality.
120-159: Cleanup function tests properly verify resource disposal.The tests correctly validate both editor view destruction and DOM element removal using appropriate Jest spies.
161-204: DOM environment mocking tests handle global state correctly.The tests properly verify mock creation for missing DOM environments and preservation of existing environments, with appropriate state management.
src/components/text-editor/test-setup/content-generator.spec.ts
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 12
♻️ Duplicate comments (6)
src/components/text-editor/test-setup/command-tester.spec.ts (1)
115-118: Fix trailing comma formatting.Remove the trailing comma after the last parameter to comply with the project's formatting rules.
if (viewAndContainer) { cleanupEditorView( viewAndContainer.view, - viewAndContainer.container, + viewAndContainer.container );src/components/text-editor/test-setup/editor-state-builder.ts (1)
100-107: User preference respected regarding type annotations.Based on past review comments, the user prefers to keep explicit type annotations even when they can be inferred. The function logic is correct for creating simple text documents.
src/components/text-editor/test-setup/event-simulator.ts (1)
160-162: Remove redundant condition check.There's a nested check for
document.elementFromPoint === undefinedinside a block that already checks the same condition at line 147.- // Mock elementFromPoint to avoid errors - if (document.elementFromPoint === undefined) { - (document as any).elementFromPoint = () => view.dom; - } + // Mock elementFromPoint to avoid errors + (document as any).elementFromPoint = () => view.dom;src/components/text-editor/test-setup/content-generator.ts (1)
120-136: User preference respected regarding type annotations.Based on past review comments, the user prefers to keep explicit type annotations. The heading creation logic is correct with proper level attribute handling.
src/components/text-editor/test-setup/command-tester.ts (2)
29-58: Fix remaining trailing comma formatting issues.The function logic is correct, but there are still trailing comma issues that need to be addressed.
Apply this diff to fix the trailing commas:
export function getCommandResult( command: Command, - state: EditorState, + state: EditorState ): CommandResult { let transaction: Transaction | undefined; // Command signature is (state, dispatch, view?) => boolean const commandResult = command( state, (tr) => { transaction = tr; }, - null, + null );
72-116: Address formatting and complexity issues.The function provides excellent testing capabilities but has formatting and complexity issues that need attention.
Fix the trailing comma issues:
expected: { shouldApply: boolean; docContentAfter?: string; docSizeAfter?: number; - includesContent?: string | string[]; + includesContent?: string | string[] - }, + } ): CommandResult {Consider extracting assertion logic to reduce cognitive complexity (currently 16, limit is 15):
+function assertDocumentContent( + newState: EditorState, + expected: { + docContentAfter?: string; + docSizeAfter?: number; + includesContent?: string | string[]; + } +): void { + if (expected.docContentAfter !== undefined) { + expect(newState.doc.textContent).toBe(expected.docContentAfter); + } + + if (expected.includesContent) { + if (Array.isArray(expected.includesContent)) { + for (const content of expected.includesContent) { + expect(newState.doc.textContent).toContain(content); + } + } else { + expect(newState.doc.textContent).toContain(expected.includesContent); + } + } + + if (expected.docSizeAfter !== undefined) { + expect(newState.doc.nodeSize).toBe(expected.docSizeAfter); + } +} export function testCommand( // ... parameters ): CommandResult { const commandResult = getCommandResult(command, state); expect(commandResult.result).toBe(expected.shouldApply); if (expected.shouldApply && commandResult.newState) { - // Replace the existing assertion logic with: + assertDocumentContent(commandResult.newState, expected); } return commandResult; }
📜 Review details
Configuration used: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
📒 Files selected for processing (12)
src/components/text-editor/prosemirror-adapter/plugins/table-plugin.spec.ts(1 hunks)src/components/text-editor/test-setup/command-tester.spec.ts(1 hunks)src/components/text-editor/test-setup/command-tester.ts(1 hunks)src/components/text-editor/test-setup/content-generator.spec.ts(1 hunks)src/components/text-editor/test-setup/content-generator.ts(1 hunks)src/components/text-editor/test-setup/editor-state-builder.spec.ts(1 hunks)src/components/text-editor/test-setup/editor-state-builder.ts(1 hunks)src/components/text-editor/test-setup/editor-view-builder.spec.ts(1 hunks)src/components/text-editor/test-setup/editor-view-builder.ts(1 hunks)src/components/text-editor/test-setup/event-simulator.spec.ts(1 hunks)src/components/text-editor/test-setup/event-simulator.ts(1 hunks)src/components/text-editor/test-setup/schema-builder.ts(1 hunks)
📓 Path-based instructions (1)
**/*.{ts,tsx}
⚙️ CodeRabbit Configuration File
Imports from other files in the same module (lime-elements) must use relative paths. Using absolute paths for imports will cause the production build to fail.
Files:
src/components/text-editor/test-setup/command-tester.spec.tssrc/components/text-editor/prosemirror-adapter/plugins/table-plugin.spec.tssrc/components/text-editor/test-setup/schema-builder.tssrc/components/text-editor/test-setup/content-generator.spec.tssrc/components/text-editor/test-setup/event-simulator.tssrc/components/text-editor/test-setup/editor-state-builder.spec.tssrc/components/text-editor/test-setup/editor-view-builder.tssrc/components/text-editor/test-setup/content-generator.tssrc/components/text-editor/test-setup/event-simulator.spec.tssrc/components/text-editor/test-setup/command-tester.tssrc/components/text-editor/test-setup/editor-state-builder.tssrc/components/text-editor/test-setup/editor-view-builder.spec.ts
🧠 Learnings (4)
src/components/text-editor/prosemirror-adapter/plugins/table-plugin.spec.ts (1)
Learnt from: FredrikWallstrom
PR: #3464
File: src/components/text-editor/prosemirror-adapter/plugins/image/inserter.ts:58-67
Timestamp: 2025-03-04T14:44:40.706Z
Learning: In the image inserter plugin for the text editor's ProseMirror adapter, only standard image nodes (where node.type.name === 'image') are intentionally handled, as custom image-like nodes are not within the current scope.
src/components/text-editor/test-setup/content-generator.spec.ts (1)
Learnt from: adrianschmidt
PR: #3607
File: docs-index.html:0-0
Timestamp: 2025-07-16T13:28:26.858Z
Learning: Before suggesting any code changes as "safe," thoroughly analyze the entire codebase context, including dependencies, usage patterns, and potential side effects. What appears to be a simple performance optimization might break existing functionality due to execution order or timing dependencies.
src/components/text-editor/test-setup/content-generator.ts (2)
Learnt from: adrianschmidt
PR: #3530
File: src/components/text-editor/examples/text-editor-composite.tsx:4-7
Timestamp: 2025-04-17T09:39:36.254Z
Learning: For lime-elements, example files should import types from the public API using '@limetech/lime-elements' rather than defining duplicate types locally. This includes types like EditorUiType which are part of the component's public API.
Learnt from: adrianschmidt
PR: #3464
File: src/components/text-editor/prosemirror-adapter/plugins/image/inserter.ts:1-11
Timestamp: 2025-03-04T14:27:29.714Z
Learning: In example components (typically found in src/components/*/examples/), imports of lime-elements exports should use @limetech/lime-elements instead of relative paths. This is because example components aren't included in type declarations and are used in documentation to show developers how to properly use lime-elements components.
src/components/text-editor/test-setup/editor-view-builder.spec.ts (3)
Learnt from: adrianschmidt
PR: #3607
File: docs-index.html:0-0
Timestamp: 2025-07-16T13:28:26.858Z
Learning: Before suggesting any code changes as "safe," thoroughly analyze the entire codebase context, including dependencies, usage patterns, and potential side effects. What appears to be a simple performance optimization might break existing functionality due to execution order or timing dependencies.
Learnt from: adrianschmidt
PR: #3547
File: src/components/text-editor/examples/text-editor-with-inline-images-file-storage.tsx:46-46
Timestamp: 2025-05-02T07:14:19.314Z
Learning: When reviewing TypeScript/JavaScript code, don't suggest converting object literals to constants when the object is mutable and will be modified later in the code. Due to reference semantics, this can cause unintended side effects where the "constant" version is also modified.
Learnt from: adrianschmidt
PR: #3607
File: docs-index.html:0-0
Timestamp: 2025-07-16T13:28:26.858Z
Learning: When suggesting script optimizations like adding defer or async attributes, always analyze the entire HTML file to check for dependencies between external scripts and inline scripts. Scripts loaded with defer execute after DOM parsing but before DOMContentLoaded, which can break synchronous dependencies with inline scripts that expect variables to be immediately available.
🧬 Code Graph Analysis (8)
src/components/text-editor/test-setup/command-tester.spec.ts (2)
src/components/text-editor/test-setup/command-tester.ts (4)
getCommandResult(29-58)testCommand(72-116)testCommandWithView(129-180)createCommandTester(188-197)src/components/text-editor/test-setup/editor-view-builder.ts (1)
cleanupEditorView(78-85)
src/components/text-editor/prosemirror-adapter/plugins/table-plugin.spec.ts (3)
src/components/text-editor/test-setup/editor-view-builder.ts (3)
cleanupEditorView(78-85)createDispatchSpy(53-69)createEditorView(14-45)src/components/text-editor/prosemirror-adapter/plugins/table-plugin.ts (3)
getTableEditingPlugins(4-10)getTableNodes(22-31)createStyleAttribute(12-20)src/components/text-editor/test-setup/schema-builder.ts (1)
createCustomTestSchema(47-92)
src/components/text-editor/test-setup/content-generator.spec.ts (2)
src/components/text-editor/test-setup/content-generator.ts (7)
createDocWithText(13-18)createDocWithHTML(27-31)createDocWithFormattedText(41-53)createDocWithBulletList(89-110)createDocWithHeading(120-136)createDocWithBlockquote(145-158)createDocWithCodeBlock(167-179)src/components/text-editor/test-setup/schema-builder.ts (1)
createCustomTestSchema(47-92)
src/components/text-editor/test-setup/editor-state-builder.spec.ts (2)
src/components/text-editor/test-setup/editor-state-builder.ts (4)
createEditorState(14-29)createEditorStateWithSelection(41-59)setTextSelection(69-77)createDocumentWithText(100-107)src/components/text-editor/test-setup/schema-builder.ts (1)
createCustomTestSchema(47-92)
src/components/text-editor/test-setup/editor-view-builder.ts (1)
src/components/text-editor/test-setup/schema-builder.ts (1)
createTestSchema(12-33)
src/components/text-editor/test-setup/content-generator.ts (1)
src/components/text-editor/test-setup/schema-builder.ts (1)
createTestSchema(12-33)
src/components/text-editor/test-setup/command-tester.ts (1)
src/components/text-editor/test-setup/editor-view-builder.ts (1)
createEditorView(14-45)
src/components/text-editor/test-setup/editor-view-builder.spec.ts (1)
src/components/text-editor/test-setup/editor-view-builder.ts (4)
cleanupEditorView(78-85)createEditorView(14-45)createDispatchSpy(53-69)mockProseMirrorDOMEnvironment(93-135)
🪛 GitHub Check: Lint
src/components/text-editor/test-setup/command-tester.spec.ts
[failure] 181-181:
Insert ,
[failure] 176-176:
Insert ,
[failure] 145-145:
Delete ,
[failure] 144-144:
Insert ,
[failure] 117-117:
Delete ,
src/components/text-editor/test-setup/event-simulator.ts
[warning] 256-256:
Missing JSDoc @Property "files" description
[warning] 255-255:
Missing JSDoc @Property "html" description
[warning] 254-254:
Missing JSDoc @Property "text" description
[warning] 253-253:
Invalid JSDoc @typedef "PasteData" type "Object"; prefer: "object"
[warning] 126-126:
Missing @param "options.detail"
[warning] 126-126:
Missing @param "options.button"
[warning] 119-119:
Missing JSDoc @param "options.detail" declaration
[warning] 119-119:
Missing JSDoc @param "options.button" declaration
src/components/text-editor/test-setup/command-tester.ts
[failure] 91-91:
Delete ,
[failure] 80-80:
Delete ,
[failure] 72-72:
Refactor this function to reduce its Cognitive Complexity from 16 to the 15 allowed
[failure] 41-41:
Delete ,
[failure] 31-31:
Delete ,
🪛 GitHub Actions: Pull Request Checks
src/components/text-editor/test-setup/command-tester.spec.ts
[error] 117-117: Prettier formatting error: Delete , (prettier/prettier)
🪛 Biome (1.9.4)
src/components/text-editor/test-setup/content-generator.ts
[error] 122-122: This type annotation is trivially inferred from its initialization.
Safe fix: Remove the type annotation.
(lint/style/noInferrableTypes)
src/components/text-editor/test-setup/editor-state-builder.ts
[error] 101-101: This type annotation is trivially inferred from its initialization.
Safe fix: Remove the type annotation.
(lint/style/noInferrableTypes)
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{ts,tsx}
⚙️ CodeRabbit Configuration File
Imports from other files in the same module (lime-elements) must use relative paths. Using absolute paths for imports will cause the production build to fail.
Files:
src/components/text-editor/test-setup/command-tester.spec.tssrc/components/text-editor/prosemirror-adapter/plugins/table-plugin.spec.tssrc/components/text-editor/test-setup/schema-builder.tssrc/components/text-editor/test-setup/content-generator.spec.tssrc/components/text-editor/test-setup/event-simulator.tssrc/components/text-editor/test-setup/editor-state-builder.spec.tssrc/components/text-editor/test-setup/editor-view-builder.tssrc/components/text-editor/test-setup/content-generator.tssrc/components/text-editor/test-setup/event-simulator.spec.tssrc/components/text-editor/test-setup/command-tester.tssrc/components/text-editor/test-setup/editor-state-builder.tssrc/components/text-editor/test-setup/editor-view-builder.spec.ts
🧠 Learnings (4)
src/components/text-editor/prosemirror-adapter/plugins/table-plugin.spec.ts (1)
Learnt from: FredrikWallstrom
PR: #3464
File: src/components/text-editor/prosemirror-adapter/plugins/image/inserter.ts:58-67
Timestamp: 2025-03-04T14:44:40.706Z
Learning: In the image inserter plugin for the text editor's ProseMirror adapter, only standard image nodes (where node.type.name === 'image') are intentionally handled, as custom image-like nodes are not within the current scope.
src/components/text-editor/test-setup/content-generator.spec.ts (1)
Learnt from: adrianschmidt
PR: #3607
File: docs-index.html:0-0
Timestamp: 2025-07-16T13:28:26.858Z
Learning: Before suggesting any code changes as "safe," thoroughly analyze the entire codebase context, including dependencies, usage patterns, and potential side effects. What appears to be a simple performance optimization might break existing functionality due to execution order or timing dependencies.
src/components/text-editor/test-setup/content-generator.ts (2)
Learnt from: adrianschmidt
PR: #3530
File: src/components/text-editor/examples/text-editor-composite.tsx:4-7
Timestamp: 2025-04-17T09:39:36.254Z
Learning: For lime-elements, example files should import types from the public API using '@limetech/lime-elements' rather than defining duplicate types locally. This includes types like EditorUiType which are part of the component's public API.
Learnt from: adrianschmidt
PR: #3464
File: src/components/text-editor/prosemirror-adapter/plugins/image/inserter.ts:1-11
Timestamp: 2025-03-04T14:27:29.714Z
Learning: In example components (typically found in src/components/*/examples/), imports of lime-elements exports should use @limetech/lime-elements instead of relative paths. This is because example components aren't included in type declarations and are used in documentation to show developers how to properly use lime-elements components.
src/components/text-editor/test-setup/editor-view-builder.spec.ts (3)
Learnt from: adrianschmidt
PR: #3607
File: docs-index.html:0-0
Timestamp: 2025-07-16T13:28:26.858Z
Learning: Before suggesting any code changes as "safe," thoroughly analyze the entire codebase context, including dependencies, usage patterns, and potential side effects. What appears to be a simple performance optimization might break existing functionality due to execution order or timing dependencies.
Learnt from: adrianschmidt
PR: #3547
File: src/components/text-editor/examples/text-editor-with-inline-images-file-storage.tsx:46-46
Timestamp: 2025-05-02T07:14:19.314Z
Learning: When reviewing TypeScript/JavaScript code, don't suggest converting object literals to constants when the object is mutable and will be modified later in the code. Due to reference semantics, this can cause unintended side effects where the "constant" version is also modified.
Learnt from: adrianschmidt
PR: #3607
File: docs-index.html:0-0
Timestamp: 2025-07-16T13:28:26.858Z
Learning: When suggesting script optimizations like adding defer or async attributes, always analyze the entire HTML file to check for dependencies between external scripts and inline scripts. Scripts loaded with defer execute after DOM parsing but before DOMContentLoaded, which can break synchronous dependencies with inline scripts that expect variables to be immediately available.
🧬 Code Graph Analysis (8)
src/components/text-editor/test-setup/command-tester.spec.ts (2)
src/components/text-editor/test-setup/command-tester.ts (4)
getCommandResult(29-58)testCommand(72-116)testCommandWithView(129-180)createCommandTester(188-197)src/components/text-editor/test-setup/editor-view-builder.ts (1)
cleanupEditorView(78-85)
src/components/text-editor/prosemirror-adapter/plugins/table-plugin.spec.ts (3)
src/components/text-editor/test-setup/editor-view-builder.ts (3)
cleanupEditorView(78-85)createDispatchSpy(53-69)createEditorView(14-45)src/components/text-editor/prosemirror-adapter/plugins/table-plugin.ts (3)
getTableEditingPlugins(4-10)getTableNodes(22-31)createStyleAttribute(12-20)src/components/text-editor/test-setup/schema-builder.ts (1)
createCustomTestSchema(47-92)
src/components/text-editor/test-setup/content-generator.spec.ts (2)
src/components/text-editor/test-setup/content-generator.ts (7)
createDocWithText(13-18)createDocWithHTML(27-31)createDocWithFormattedText(41-53)createDocWithBulletList(89-110)createDocWithHeading(120-136)createDocWithBlockquote(145-158)createDocWithCodeBlock(167-179)src/components/text-editor/test-setup/schema-builder.ts (1)
createCustomTestSchema(47-92)
src/components/text-editor/test-setup/editor-state-builder.spec.ts (2)
src/components/text-editor/test-setup/editor-state-builder.ts (4)
createEditorState(14-29)createEditorStateWithSelection(41-59)setTextSelection(69-77)createDocumentWithText(100-107)src/components/text-editor/test-setup/schema-builder.ts (1)
createCustomTestSchema(47-92)
src/components/text-editor/test-setup/editor-view-builder.ts (1)
src/components/text-editor/test-setup/schema-builder.ts (1)
createTestSchema(12-33)
src/components/text-editor/test-setup/content-generator.ts (1)
src/components/text-editor/test-setup/schema-builder.ts (1)
createTestSchema(12-33)
src/components/text-editor/test-setup/command-tester.ts (1)
src/components/text-editor/test-setup/editor-view-builder.ts (1)
createEditorView(14-45)
src/components/text-editor/test-setup/editor-view-builder.spec.ts (1)
src/components/text-editor/test-setup/editor-view-builder.ts (4)
cleanupEditorView(78-85)createEditorView(14-45)createDispatchSpy(53-69)mockProseMirrorDOMEnvironment(93-135)
🪛 GitHub Check: Lint
src/components/text-editor/test-setup/command-tester.spec.ts
[failure] 181-181:
Insert ,
[failure] 176-176:
Insert ,
[failure] 145-145:
Delete ,
[failure] 144-144:
Insert ,
[failure] 117-117:
Delete ,
src/components/text-editor/test-setup/event-simulator.ts
[warning] 256-256:
Missing JSDoc @Property "files" description
[warning] 255-255:
Missing JSDoc @Property "html" description
[warning] 254-254:
Missing JSDoc @Property "text" description
[warning] 253-253:
Invalid JSDoc @typedef "PasteData" type "Object"; prefer: "object"
[warning] 126-126:
Missing @param "options.detail"
[warning] 126-126:
Missing @param "options.button"
[warning] 119-119:
Missing JSDoc @param "options.detail" declaration
[warning] 119-119:
Missing JSDoc @param "options.button" declaration
src/components/text-editor/test-setup/command-tester.ts
[failure] 91-91:
Delete ,
[failure] 80-80:
Delete ,
[failure] 72-72:
Refactor this function to reduce its Cognitive Complexity from 16 to the 15 allowed
[failure] 41-41:
Delete ,
[failure] 31-31:
Delete ,
🪛 GitHub Actions: Pull Request Checks
src/components/text-editor/test-setup/command-tester.spec.ts
[error] 117-117: Prettier formatting error: Delete , (prettier/prettier)
🪛 Biome (1.9.4)
src/components/text-editor/test-setup/content-generator.ts
[error] 122-122: This type annotation is trivially inferred from its initialization.
Safe fix: Remove the type annotation.
(lint/style/noInferrableTypes)
src/components/text-editor/test-setup/editor-state-builder.ts
[error] 101-101: This type annotation is trivially inferred from its initialization.
Safe fix: Remove the type annotation.
(lint/style/noInferrableTypes)
🔇 Additional comments (49)
src/components/text-editor/prosemirror-adapter/plugins/table-plugin.spec.ts (3)
1-14: LGTM! Imports follow coding guidelines correctly.All imports use relative paths as required for intra-module imports, ensuring the production build will not fail.
28-70: Excellent comprehensive test coverage for getTableEditingPlugins.The tests effectively cover all scenarios:
- Enabled state returning the correct plugin
- Disabled state returning empty array
- Integration test ensuring the plugin works in a real editor context
The integration test is particularly valuable as it validates the plugin's actual functionality beyond just API contracts.
72-116: Well-structured tests with good ProseMirror integration validation.The tests effectively validate:
- Correct node specifications are returned
- Nodes integrate properly with ProseMirror Schema
- Custom styling attributes are configured correctly with null defaults
The integration with
NodeTypeinstances in the schema validation is particularly thorough.src/components/text-editor/test-setup/schema-builder.ts (2)
12-33: Well-structured schema creation utility.The function provides a clean interface for creating standardized test schemas with proper documentation and logical organization.
47-92: Flexible schema customization with good API design.The options-based approach allows for fine-grained control over schema composition, making it suitable for testing various scenarios.
src/components/text-editor/test-setup/editor-state-builder.spec.ts (3)
10-55: Comprehensive test coverage for editor state creation.The tests thoroughly cover different scenarios including empty states, content parsing, custom schemas, and mark verification. The nested describe blocks provide clear test organization.
57-84: Proper testing of selection functionality.The tests verify both selection creation and state immutability, which are crucial for editor functionality.
86-114: Good edge case coverage for document creation.Testing both with text content and empty scenarios ensures robustness of the utility functions.
src/components/text-editor/test-setup/content-generator.spec.ts (6)
14-41: Excellent test coverage for basic document creation.The tests verify both content creation and schema customization, ensuring the utilities work correctly in various scenarios.
43-70: Good HTML parsing test coverage.Testing both valid HTML content and edge cases (empty/invalid HTML) ensures robust behavior.
72-140: Thorough testing of formatted text with marks.The tests cover both simple mark application and complex scenarios with attributes, plus proper error handling for invalid marks.
115-115: Optional chaining properly implemented.The past review suggestion to use optional chaining has been correctly implemented.
142-177: Complete list functionality testing.Testing both populated and empty lists ensures the utility handles all scenarios correctly.
179-249: Comprehensive block element testing.The tests cover headings, blockquotes, and code blocks with proper attribute and structure verification.
src/components/text-editor/test-setup/event-simulator.spec.ts (5)
13-37: Proper test setup and cleanup.The beforeEach/afterEach pattern with DOM manipulation and cleanup ensures tests are isolated and don't affect each other.
39-71: Comprehensive keyboard event testing.The tests verify both basic key presses and modifier key combinations, ensuring the simulator works correctly for different input scenarios.
73-109: Thorough paste event simulation testing.Testing both plain text and HTML paste scenarios ensures compatibility with different clipboard content types.
111-140: Complete mouse interaction testing.The tests cover different mouse buttons and click types, providing comprehensive coverage for mouse event simulation.
142-193: Excellent drag and drop testing.The tests verify the complete drag and drop sequence with proper event ordering and data handling.
src/components/text-editor/test-setup/command-tester.spec.ts (4)
11-47: Excellent command result testing.The tests thoroughly verify both successful and failed command execution, including proper transaction and state handling.
49-104: Comprehensive command testing utilities.The tests cover various aspects of command testing including applicability, content changes, and document size verification.
107-156: Good view-based command testing.The tests properly handle commands that require an editor view context with appropriate cleanup patterns.
158-188: Well-designed reusable command tester.The
createCommandTesterutility and its tests demonstrate good functional programming patterns for creating reusable test utilities.src/components/text-editor/test-setup/editor-state-builder.ts (4)
14-29: LGTM! Well-structured editor state creation function.The function correctly handles optional parameters, creates a fallback schema, and properly initializes the EditorState. The ternary operator formatting follows the ESLint disable comment appropriately.
41-59: LGTM! Editor state with selection creation works correctly.The function properly creates a text selection between specified positions and initializes the EditorState with all provided parameters.
69-77: LGTM! Text selection utility function is well-implemented.The function correctly creates a new EditorState with the specified text selection using ProseMirror's transaction system.
86-91: LGTM! HTML content parsing helper function is correctly implemented.The function safely creates a DOM element, sets innerHTML, and uses ProseMirror's DOMParser to convert to a document node.
src/components/text-editor/test-setup/event-simulator.ts (5)
7-41: LGTM! MockDataTransfer implementation is comprehensive.The MockDataTransfer class correctly implements the necessary methods and properties for testing environments, with proper length property handling through a getter.
61-82: LGTM! Key press simulation is well-implemented.The function correctly handles keyboard event creation with proper modifier key support and bubbling behavior.
100-117: LGTM! Paste simulation function works correctly.The function properly creates paste events with clipboard data using the extracted createDataTransfer helper function.
130-169: LGTM! Click simulation handles test environment limitations well.The function appropriately handles the absence of DOM methods like
elementFromPointin test environments by providing mock implementations.
182-246: LGTM! Drag and drop simulation is comprehensive.The function correctly handles the sequence of drag events and accommodates test environments lacking DragEvent constructors by using CustomEvent with manually defined properties.
src/components/text-editor/test-setup/editor-view-builder.spec.ts (5)
11-21: LGTM! Proper test cleanup setup.The afterEach hook correctly cleans up editor views and containers, preventing memory leaks between tests.
23-70: LGTM! Comprehensive createEditorView tests.The test suite covers all main scenarios: default state creation, custom state usage, dispatch spy integration, and custom parent elements. Assertions are appropriate and thorough.
72-118: LGTM! Thorough dispatch spy testing.Tests verify both auto-update enabled and disabled scenarios, ensuring the spy correctly tracks transactions and updates view state when configured to do so.
120-159: LGTM! Comprehensive cleanup testing.Tests verify that the cleanup function properly destroys views and removes containers from the DOM, with appropriate spy verification.
161-223: LGTM! Mock DOM environment tests are thorough.Tests cover both scenarios: creating a mock DOM when none exists and preserving existing DOM environments. The cleanup and restoration logic is properly tested.
src/components/text-editor/test-setup/editor-view-builder.ts (4)
14-45: LGTM! Well-structured editor view creation function.The function correctly handles optional parameters, creates appropriate containers, sets up the editor view with proper configuration, and establishes the spy-view relationship when needed.
53-69: LGTM! Dispatch spy implementation is robust.The spy function correctly tracks transactions and optionally updates the view state. The setView mechanism allows proper integration with the editor view.
78-85: LGTM! Clean and effective cleanup function.The function properly destroys the editor view and removes the container using optional chaining, as suggested in previous reviews.
93-135: LGTM! Comprehensive DOM environment mocking.The mock DOM implementation provides all necessary methods and properties for ProseMirror to function in test environments. The cleanup function properly restores the original environment.
src/components/text-editor/test-setup/content-generator.ts (7)
13-18: LGTM! Simple text document creation works correctly.The function properly handles empty text and creates appropriate paragraph content for the editor state.
27-31: LGTM! HTML document creation is straightforward and correct.The function delegates to createEditorState with the provided HTML content, maintaining simplicity and reusability.
41-53: LGTM! Formatted text creation is well-implemented.The function correctly uses the helper function to apply marks and creates a proper document structure.
63-80: LGTM! Mark application helper function is robust.The function correctly maps MarkSpecs to actual marks, includes proper error handling for missing mark types, and creates appropriate paragraph nodes with marked text.
89-110: LGTM! Bullet list creation is correctly implemented.The function properly creates list items with paragraphs and assembles them into a bullet list using ProseMirror's Fragment system.
145-158: LGTM! Blockquote creation follows proper structure.The function correctly creates a blockquote containing a paragraph with the specified text content.
167-179: LGTM! Code block creation is properly implemented.The function correctly creates a code block node with the specified code content.
src/components/text-editor/test-setup/command-tester.ts (1)
1-20: Well-structured interface and imports.The imports correctly use relative paths as required by the coding guidelines, and the
CommandResultinterface is well-documented with clear field semantics.
src/components/text-editor/prosemirror-adapter/plugins/table-plugin.spec.ts
Outdated
Show resolved
Hide resolved
src/components/text-editor/prosemirror-adapter/plugins/table-plugin.spec.ts
Show resolved
Hide resolved
src/components/text-editor/prosemirror-adapter/plugins/table-plugin.spec.ts
Show resolved
Hide resolved
src/components/text-editor/prosemirror-adapter/plugins/table-plugin.spec.ts
Show resolved
Hide resolved
70a5495 to
ed9d56a
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 24
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
src/components/text-editor/prosemirror-adapter/plugins/table-plugin.ts (1)
12-20: Use getPropertyValue and safe concatenation for hyphenated CSS props and existing inline styles
- dom.style[cssProperty] is not type‑safe and won’t work for hyphenated props like background-color. Use getPropertyValue.
- When appending to attrs.style, ensure a separating semicolon if one is missing.
Apply this diff:
export const createStyleAttribute = (cssProperty: string) => ({ default: null, - getFromDOM: (dom: HTMLElement) => dom.style[cssProperty] || null, + getFromDOM: (dom: HTMLElement) => + dom.style.getPropertyValue(cssProperty) || null, setDOMAttr: (value: string, attrs: Record<string, any>) => { if (value) { - attrs.style = (attrs.style || '') + `${cssProperty}: ${value};`; + const prev = attrs.style + ? (attrs.style.endsWith(';') ? attrs.style : attrs.style + ';') + : ''; + attrs.style = `${prev}${cssProperty}: ${value};`; } }, });
♻️ Duplicate comments (11)
src/components/text-editor/prosemirror-adapter/plugins/table-plugin.spec.ts (2)
123-129: Align CSS property names to kebab-case to match plugin API.Tests should use 'background-color' to be consistent with getTableNodes/createStyleAttribute usage. Also adjust expected style strings.
- const backgroundAttr = createStyleAttribute('backgroundColor'); + const backgroundAttr = createStyleAttribute('background-color'); @@ - expect(backgroundAttr.getFromDOM(element)).toBe('red'); + expect(backgroundAttr.getFromDOM(element)).toBe('red');- const backgroundAttr = createStyleAttribute('backgroundColor'); + const backgroundAttr = createStyleAttribute('background-color'); @@ - expect(attrs.style).toBe('backgroundColor: blue;'); + expect(attrs.style).toBe('background-color: blue;');- const backgroundAttr = createStyleAttribute('backgroundColor'); + const backgroundAttr = createStyleAttribute('background-color'); const colorAttr = createStyleAttribute('color'); @@ - expect(attrs.style).toBe('backgroundColor: blue;color: white;'); + expect(attrs.style).toBe('background-color: blue;color: white;');- const backgroundAttr = createStyleAttribute('backgroundColor'); + const backgroundAttr = createStyleAttribute('background-color');Note: createStyleAttribute.getFromDOM currently uses dom.style[cssProperty]; for kebab-case, prefer dom.style.getPropertyValue(cssProperty). Consider updating the implementation accordingly.
Also applies to: 131-139, 140-149, 151-171
19-21: Add missing type annotations (and import) for view/container.Prevents implicit any and clarifies lifecycle in afterEach.
+import { EditorView } from 'prosemirror-view'; @@ - let view; - let container; + let view: EditorView | null; + let container: HTMLElement | null;src/components/text-editor/test-setup/command-tester.spec.ts (3)
140-146: Fix comma formatting in object literal and call.Add missing comma after property; remove trailing comma after the call.
const { result, view, container } = testCommandWithView( viewCommand, state, { - shouldApply: true - }, + shouldApply: true, + } );
174-177: Add trailing commas in multi-line object literals (lint).Aligns with project formatting rules.
const result1 = testHelloCommand(state1, { shouldApply: true, - docContentAfter: 'Hello World' + docContentAfter: 'Hello World', });const result2 = testHelloCommand(state2, { shouldApply: true, - docContentAfter: 'Hello Universe' + docContentAfter: 'Hello Universe', });Also applies to: 179-182
115-119: Remove trailing comma in function call.Fixes lint error.
cleanupEditorView( viewAndContainer.view, - viewAndContainer.container, + viewAndContainer.container );src/components/text-editor/test-setup/event-simulator.ts (2)
159-163: Remove redundant nested elementFromPoint check.Already inside the undefined-guard; simplify.
- // Mock elementFromPoint to avoid errors - if (document.elementFromPoint === undefined) { - (document as any).elementFromPoint = () => view.dom; - } + // Mock elementFromPoint to avoid errors + (document as any).elementFromPoint = () => view.dom;
249-258: Fix JSDoc typedef and add property descriptions.Use lowercase "object" and document fields.
- * @typedef {Object} PasteData - * @property {string} [text] - * @property {string} [html] - * @property {File[]} [files] + * @typedef {object} PasteData + * @property {string} [text] - Plain text content + * @property {string} [html] - HTML content + * @property {File[]} [files] - Files to include in the transfersrc/components/text-editor/test-setup/command-tester.ts (3)
29-33: Remove trailing commas (lint).Conform to style rules in signature and command invocation.
export function getCommandResult( command: Command, - state: EditorState, + state: EditorState ): CommandResult { @@ const commandResult = command( state, (tr) => { transaction = tr; }, - null, + null );Also applies to: 35-42
129-137: Add includesContent support to view-based tester; keep formatting consistent.Parities with testCommand and fixes trailing commas.
export function testCommandWithView( command: Command, state: EditorState, - expected: { + expected: { shouldApply: boolean; docContentAfter?: string; - docSizeAfter?: number; - }, + docSizeAfter?: number; + includesContent?: string | string[]; + } ): { result: CommandResult; view: EditorView; container: HTMLElement } { @@ if (expected.shouldApply && commandResultObj.newState) { if (expected.docContentAfter !== undefined) { expect(commandResultObj.newState.doc.textContent).toBe( expected.docContentAfter, ); } if (expected.docSizeAfter !== undefined) { expect(commandResultObj.newState.doc.nodeSize).toBe( expected.docSizeAfter, ); } + + const includes = expected.includesContent === undefined + ? [] + : Array.isArray(expected.includesContent) + ? expected.includesContent + : [expected.includesContent]; + for (const content of includes) { + expect(commandResultObj.newState.doc.textContent).toContain(content); + } } @@ - return { result: commandResultObj, view: view, container: container }; + return { result: commandResultObj, view: view, container: container };Also applies to: 162-176, 178-180
188-197: Expose includesContent in createCommandTester signature.Keeps the factory consistent with testCommand.
export function createCommandTester(command: Command) { return ( state: EditorState, expected: { shouldApply: boolean; docContentAfter?: string; docSizeAfter?: number; + includesContent?: string | string[]; }, ) => testCommand(command, state, expected); }src/components/text-editor/test-setup/content-generator.ts (1)
119-135: Type annotation preference acknowledged.Based on the past review comment, the user prefers to keep explicit type annotations. The function correctly creates headings with proper level attributes.
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
📒 Files selected for processing (17)
src/components/text-editor/prosemirror-adapter/plugins/table-plugin.spec.ts(1 hunks)src/components/text-editor/prosemirror-adapter/plugins/table-plugin.ts(1 hunks)src/components/text-editor/test-setup/command-tester.spec.ts(1 hunks)src/components/text-editor/test-setup/command-tester.ts(1 hunks)src/components/text-editor/test-setup/content-generator.spec.ts(1 hunks)src/components/text-editor/test-setup/content-generator.ts(1 hunks)src/components/text-editor/test-setup/editor-state-builder.spec.ts(1 hunks)src/components/text-editor/test-setup/editor-state-builder.ts(1 hunks)src/components/text-editor/test-setup/editor-test-utils.ts(1 hunks)src/components/text-editor/test-setup/editor-view-builder.spec.ts(1 hunks)src/components/text-editor/test-setup/editor-view-builder.ts(1 hunks)src/components/text-editor/test-setup/event-simulator.spec.ts(1 hunks)src/components/text-editor/test-setup/event-simulator.ts(1 hunks)src/components/text-editor/test-setup/schema-builder.spec.ts(1 hunks)src/components/text-editor/test-setup/schema-builder.ts(1 hunks)src/components/text-editor/test-setup/text-editor-test-suite-guide.md(1 hunks)src/components/text-editor/test-setup/text-editor-test-utils.md(1 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{ts,tsx}
⚙️ CodeRabbit configuration file
Imports from other files in the same module (lime-elements) must use relative paths. Using absolute paths for imports will cause the production build to fail.
Files:
src/components/text-editor/test-setup/schema-builder.spec.tssrc/components/text-editor/test-setup/editor-test-utils.tssrc/components/text-editor/prosemirror-adapter/plugins/table-plugin.spec.tssrc/components/text-editor/prosemirror-adapter/plugins/table-plugin.tssrc/components/text-editor/test-setup/editor-view-builder.tssrc/components/text-editor/test-setup/command-tester.spec.tssrc/components/text-editor/test-setup/event-simulator.spec.tssrc/components/text-editor/test-setup/content-generator.spec.tssrc/components/text-editor/test-setup/event-simulator.tssrc/components/text-editor/test-setup/command-tester.tssrc/components/text-editor/test-setup/schema-builder.tssrc/components/text-editor/test-setup/editor-view-builder.spec.tssrc/components/text-editor/test-setup/editor-state-builder.spec.tssrc/components/text-editor/test-setup/content-generator.tssrc/components/text-editor/test-setup/editor-state-builder.ts
🧬 Code graph analysis (12)
src/components/text-editor/test-setup/schema-builder.spec.ts (1)
src/components/text-editor/test-setup/schema-builder.ts (2)
createTestSchema(12-33)createCustomTestSchema(47-92)
src/components/text-editor/prosemirror-adapter/plugins/table-plugin.spec.ts (3)
src/components/text-editor/test-setup/editor-view-builder.ts (3)
cleanupEditorView(78-85)createDispatchSpy(53-69)createEditorView(14-45)src/components/text-editor/prosemirror-adapter/plugins/table-plugin.ts (3)
getTableEditingPlugins(4-10)getTableNodes(22-31)createStyleAttribute(12-20)src/components/text-editor/test-setup/schema-builder.ts (1)
createCustomTestSchema(47-92)
src/components/text-editor/test-setup/editor-view-builder.ts (1)
src/components/text-editor/test-setup/schema-builder.ts (1)
createTestSchema(12-33)
src/components/text-editor/test-setup/command-tester.spec.ts (2)
src/components/text-editor/test-setup/command-tester.ts (4)
getCommandResult(29-58)testCommand(72-116)testCommandWithView(129-180)createCommandTester(188-197)src/components/text-editor/test-setup/editor-view-builder.ts (1)
cleanupEditorView(78-85)
src/components/text-editor/test-setup/event-simulator.spec.ts (2)
src/components/text-editor/test-setup/editor-view-builder.ts (2)
createEditorView(14-45)cleanupEditorView(78-85)src/components/text-editor/test-setup/event-simulator.ts (6)
simulateKeyPress(61-82)KeyModifiers(46-51)PasteData(87-91)simulatePaste(100-117)simulateClick(130-169)simulateDragAndDrop(182-246)
src/components/text-editor/test-setup/content-generator.spec.ts (2)
src/components/text-editor/test-setup/content-generator.ts (7)
createDocWithText(13-17)createDocWithHTML(26-30)createDocWithFormattedText(40-52)createDocWithBulletList(88-109)createDocWithHeading(119-135)createDocWithBlockquote(144-157)createDocWithCodeBlock(166-178)src/components/text-editor/test-setup/schema-builder.ts (1)
createCustomTestSchema(47-92)
src/components/text-editor/test-setup/command-tester.ts (1)
src/components/text-editor/test-setup/editor-view-builder.ts (1)
createEditorView(14-45)
src/components/text-editor/test-setup/schema-builder.ts (1)
src/components/text-editor/prosemirror-adapter/menu/menu-schema-extender.ts (1)
strikethrough(3-13)
src/components/text-editor/test-setup/editor-view-builder.spec.ts (1)
src/components/text-editor/test-setup/editor-view-builder.ts (4)
cleanupEditorView(78-85)createEditorView(14-45)createDispatchSpy(53-69)mockProseMirrorDOMEnvironment(93-135)
src/components/text-editor/test-setup/editor-state-builder.spec.ts (2)
src/components/text-editor/test-setup/editor-state-builder.ts (3)
createEditorState(14-29)createEditorStateWithSelection(41-59)setTextSelection(69-77)src/components/text-editor/test-setup/schema-builder.ts (1)
createCustomTestSchema(47-92)
src/components/text-editor/test-setup/content-generator.ts (1)
src/components/text-editor/test-setup/schema-builder.ts (1)
createTestSchema(12-33)
src/components/text-editor/test-setup/editor-state-builder.ts (1)
src/components/text-editor/test-setup/schema-builder.ts (1)
createTestSchema(12-33)
🪛 GitHub Check: Lint
src/components/text-editor/prosemirror-adapter/plugins/table-plugin.spec.ts
[failure] 17-17:
Delete ⏎
src/components/text-editor/test-setup/command-tester.spec.ts
[failure] 181-181:
Insert ,
[failure] 176-176:
Insert ,
[failure] 145-145:
Delete ,
[failure] 144-144:
Insert ,
[failure] 117-117:
Delete ,
src/components/text-editor/test-setup/event-simulator.ts
[warning] 256-256:
Missing JSDoc @Property "files" description
[warning] 255-255:
Missing JSDoc @Property "html" description
[warning] 254-254:
Missing JSDoc @Property "text" description
[warning] 253-253:
Invalid JSDoc @typedef "PasteData" type "Object"; prefer: "object"
[warning] 126-126:
Missing @param "options.detail"
[warning] 126-126:
Missing @param "options.button"
[warning] 119-119:
Missing JSDoc @param "options.detail" declaration
[warning] 119-119:
Missing JSDoc @param "options.button" declaration
src/components/text-editor/test-setup/command-tester.ts
[failure] 80-80:
Delete ,
[failure] 72-72:
Refactor this function to reduce its Cognitive Complexity from 16 to the 15 allowed
[failure] 41-41:
Delete ,
[failure] 31-31:
Delete ,
🪛 markdownlint-cli2 (0.17.2)
src/components/text-editor/test-setup/text-editor-test-utils.md
32-32: Trailing spaces
Expected: 0 or 2; Actual: 1
(MD009, no-trailing-spaces)
src/components/text-editor/test-setup/text-editor-test-suite-guide.md
572-572: Trailing spaces
Expected: 0 or 2; Actual: 1
(MD009, no-trailing-spaces)
🪛 ast-grep (0.38.6)
src/components/text-editor/test-setup/editor-state-builder.ts
[warning] 87-87: Direct HTML content assignment detected. Modifying innerHTML, outerHTML, or using document.write with unsanitized content can lead to XSS vulnerabilities. Use secure alternatives like textContent or sanitize HTML with libraries like DOMPurify.
Context: domNode.innerHTML = content
Note: [CWE-79] Improper Neutralization of Input During Web Page Generation [REFERENCES]
- https://www.dhairyashah.dev/posts/why-innerhtml-is-a-bad-idea-and-how-to-avoid-it/
- https://cwe.mitre.org/data/definitions/79.html
(unsafe-html-content-assignment)
[warning] 87-87: Direct modification of innerHTML or outerHTML properties detected. Modifying these properties with unsanitized user input can lead to XSS vulnerabilities. Use safe alternatives or sanitize content first.
Context: domNode.innerHTML = content
Note: [CWE-79] Improper Neutralization of Input During Web Page Generation [REFERENCES]
- https://owasp.org/www-community/xss-filter-evasion-cheatsheet
- https://cwe.mitre.org/data/definitions/79.html
(dom-content-modification)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
- GitHub Check: Docs / Publish Docs
- GitHub Check: Build
- GitHub Check: Test
🔇 Additional comments (15)
src/components/text-editor/test-setup/schema-builder.spec.ts (2)
6-29: LGTM: good coverage of baseline nodes/marksThe assertions validate both nodes and common marks, including extensions. Looks solid.
33-48: LGTM: options flow validatedNice checks for toggling lists/underline/strikethrough via options.
src/components/text-editor/test-setup/editor-test-utils.ts (1)
1-6: LGTM: central re‑exports with relative pathsClean aggregator; complies with relative‑import guideline.
src/components/text-editor/test-setup/editor-state-builder.spec.ts (1)
45-53: LGTM: custom schema toggle validatedGood check for removing strikethrough via options.
src/components/text-editor/test-setup/schema-builder.ts (1)
21-28: Correct parseDOM matcher syntax — keep '=' formProseMirror accepts style matchers as either "property" or "property=value"; "text-decoration=underline" is correct and should remain unchanged.
src/components/text-editor/test-setup/content-generator.spec.ts (1)
36-55: Solid HTML parsing tests.Covers structure and content well; assertions are clear.
src/components/text-editor/test-setup/editor-view-builder.ts (1)
78-85: Cleanup uses element.remove() and optional chaining correctly.Simple and idiomatic; matches tests after fix.
src/components/text-editor/test-setup/content-generator.ts (8)
1-4: LGTM! Clean imports with proper structure.The imports are well-organized, using relative paths for internal modules as required by the coding guidelines, and appropriately importing from ProseMirror libraries.
13-17: LGTM! Simple and effective text document creation.The function correctly handles empty text cases and provides a clean API for creating basic text documents.
26-30: LGTM! HTML parsing functionality is well-implemented.The function provides a straightforward way to create documents from HTML content, leveraging the existing editor state builder.
40-52: LGTM! Formatted text creation with proper error handling.The function correctly delegates to the helper function and uses the appropriate ProseMirror API for document creation.
62-79: LGTM! Robust mark application with validation.The helper function includes proper error handling for missing mark types and correctly applies marks to text nodes. The validation ensures schema compatibility.
88-109: LGTM! Comprehensive bullet list creation.The function correctly constructs list items and assembles them into a bullet list using ProseMirror's Fragment API.
144-157: LGTM! Proper blockquote structure.The function correctly nests a paragraph within a blockquote node, following ProseMirror's hierarchical structure requirements.
166-178: LGTM! Code block creation is straightforward and correct.The function properly creates code block nodes with text content using the appropriate ProseMirror APIs.
src/components/text-editor/prosemirror-adapter/plugins/table-plugin.spec.ts
Show resolved
Hide resolved
| 6. **Mocks** | ||
| - `createDispatchSpy()` - Creates a Jest spy for the dispatch function | ||
| - `createMockEditorView()` - Creates a mocked editor view | ||
| - `mockProseMirrorDOMEnvironment()` - Sets up the DOM environment for ProseMirror | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧹 Nitpick
Keep docs consistent with actual availability
createMockEditorView is not implemented in this PR; mark as planned or remove to avoid confusion.
- - `createMockEditorView()` - Creates a mocked editor view
+ - `createMockEditorView()` - ⏳ Planned📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| 6. **Mocks** | |
| - `createDispatchSpy()` - Creates a Jest spy for the dispatch function | |
| - `createMockEditorView()` - Creates a mocked editor view | |
| - `mockProseMirrorDOMEnvironment()` - Sets up the DOM environment for ProseMirror | |
| 6. **Mocks** | |
| - `createDispatchSpy()` - Creates a Jest spy for the dispatch function | |
| - `createMockEditorView()` - ⏳ Planned | |
| - `mockProseMirrorDOMEnvironment()` - Sets up the DOM environment for ProseMirror |
🧰 Tools
🪛 markdownlint-cli2 (0.17.2)
32-32: Trailing spaces
Expected: 0 or 2; Actual: 1
(MD009, no-trailing-spaces)
🤖 Prompt for AI Agents
In src/components/text-editor/test-setup/text-editor-test-utils.md around lines
30 to 34, the docs list createMockEditorView as available while the
implementation is missing in this PR; update the documentation to either remove
the createMockEditorView entry or mark it as "planned / TODO" with a note that
it isn't implemented yet, so consumers aren't misled. Keep the other mock
entries intact and ensure the change clearly indicates the current status
(removed or planned) and, if marking planned, include an issue or PR reference
for follow-up.
|
|
||
| 6. **Mocks** | ||
| - `createDispatchSpy()` - Creates a Jest spy for the dispatch function | ||
| - `createMockEditorView()` - Creates a mocked editor view |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧹 Nitpick
markdownlint: remove trailing space
Fix MD009 on this line.
🧰 Tools
🪛 markdownlint-cli2 (0.17.2)
32-32: Trailing spaces
Expected: 0 or 2; Actual: 1
(MD009, no-trailing-spaces)
🤖 Prompt for AI Agents
In src/components/text-editor/test-setup/text-editor-test-utils.md around line
32, there's a trailing space at the end of the line "`createMockEditorView()` -
Creates a mocked editor view "; remove the trailing whitespace so the line ends
immediately after "view" to satisfy markdownlint MD009.
| 7. **Selection Helpers** | ||
| - `setTextSelection(state, from, to)` - Creates a text selection | ||
| - `setNodeSelection(state, pos)` - Creates a node selection | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧹 Nitpick
Align Selection Helpers with implementation status
If setNodeSelection isn’t implemented, label it planned here too.
- - `setNodeSelection(state, pos)` - Creates a node selection
+ - `setNodeSelection(state, pos)` - ⏳ Planned📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| 7. **Selection Helpers** | |
| - `setTextSelection(state, from, to)` - Creates a text selection | |
| - `setNodeSelection(state, pos)` - Creates a node selection | |
| 7. **Selection Helpers** | |
| - `setTextSelection(state, from, to)` - Creates a text selection | |
| - `setNodeSelection(state, pos)` - ⏳ Planned |
🤖 Prompt for AI Agents
In src/components/text-editor/test-setup/text-editor-test-utils.md around lines
35 to 38, the docs list setNodeSelection as a helper but the implementation does
not exist; update the documentation to reflect current implementation status by
marking setNodeSelection as "planned" (or "not yet implemented") next to its
listing, or remove it until implemented; optionally add a short TODO note
indicating expected signature (setNodeSelection(state, pos)) and where to find
or add the implementation.
| ```typescript | ||
| import { | ||
| createTestSchema, | ||
| createEditorState, | ||
| createEditorView, | ||
| simulateKeyPress, | ||
| cleanupEditorView | ||
| } from '../test-setup/test-utils'; | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧹 Nitpick
Fix import path to aggregator
-} from '../test-setup/test-utils';
+} from './editor-test-utils';📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| ```typescript | |
| import { | |
| createTestSchema, | |
| createEditorState, | |
| createEditorView, | |
| simulateKeyPress, | |
| cleanupEditorView | |
| } from '../test-setup/test-utils'; | |
| import { | |
| createTestSchema, | |
| createEditorState, | |
| createEditorView, | |
| simulateKeyPress, | |
| cleanupEditorView | |
| } from './editor-test-utils'; |
🤖 Prompt for AI Agents
In src/components/text-editor/test-setup/text-editor-test-utils.md around lines
47 to 55, the import currently points to '../test-setup/test-utils' but should
reference the aggregator module; update the import source to the correct
aggregator path (e.g., '../test-setup/aggregator' or
'../test-setup/test-utils/aggregator' depending on where aggregator.ts is
located) and ensure the exported names (createTestSchema, createEditorState,
createEditorView, simulateKeyPress, cleanupEditorView) are exported from that
aggregator entry point.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 10
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
src/components/text-editor/prosemirror-adapter/menu/menu-commands.ts (1)
143-155: Fix getAttributes typing and null-safety — src/components/text-editor/prosemirror-adapter/menu/menu-commands.ts (lines 143–155)createToggleMarkCommand passes link?: EditorTextLink but getAttributes requires a non-optional EditorTextLink; this will cause TS errors or runtime crashes. Change getAttributes to accept an optional link and guard href.
-const getAttributes = ( - markName: string, - link: EditorTextLink, -): Attrs | undefined => { - if (markName === EditorMenuTypes.Link && link.href) { +const getAttributes = ( + markName: string, + link?: EditorTextLink, +): Attrs | undefined => { + if (markName === EditorMenuTypes.Link && link && link.href) { return { href: link.href, target: isExternalLink(link.href) ? '_blank' : null, }; } return undefined; };
- Also verify createInsertLinkCommand (same file) — it accepts link?: EditorTextLink but uses link.href without guards; ensure callers always pass link or add similar guards.
♻️ Duplicate comments (17)
src/components/text-editor/test-setup/event-simulator.ts (2)
159-163: Remove redundant nested check for elementFromPoint.The inner condition repeats the outer guard. Simplify to one assignment.
- // Mock elementFromPoint to avoid errors - if (document.elementFromPoint === undefined) { - (document as any).elementFromPoint = () => view.dom; - } + // Mock elementFromPoint to avoid errors + (document as any).elementFromPoint = () => view.dom;
124-129: Complete JSDoc for click options.Document nested properties to satisfy lint and improve clarity.
* @param options - Additional mouse event options + * @param options.button - Mouse button (0=left, 1=middle, 2=right). Default: 0. + * @param options.detail - Click count (1=single, 2=double). Default: 1. * @returns Whether the click event was handled by the editorsrc/components/text-editor/test-setup/command-tester.spec.ts (3)
43-46: Remove trailing comma in toContain call.Fixes lint formatting.
- expect(result.newState.doc.textContent).toContain( - 'additional text', - ); + expect(result.newState.doc.textContent).toContain( + 'additional text' + );
79-83: Remove trailing comma in toContain call.- expect(commandResult.newState.doc.textContent).toContain( - 'Modified', - ); + expect(commandResult.newState.doc.textContent).toContain( + 'Modified' + );
140-146: Remove trailing comma after closing brace in argument.- { - shouldApply: true, - }, + { + shouldApply: true, + }src/components/text-editor/test-setup/editor-state-builder.spec.ts (1)
32-43: Avoid brittle nodeAt() for inline mark checks. Use resolved position marks().More robust across text node boundaries.
- const $pos = state.doc.resolve(wordPos); - const node = state.doc.nodeAt(wordPos); - expect($pos).toBeDefined(); - expect(node).toBeDefined(); - - if (node) { - const hasStrongMark = node.marks.some( - (m) => m.type.name === 'strong', - ); - expect(hasStrongMark).toBe(true); - } + const $pos = state.doc.resolve(wordPos); + const hasStrongMark = $pos.marks().some( + (m) => m.type.name === 'strong', + ); + expect(hasStrongMark).toBe(true);src/components/text-editor/test-setup/event-simulator.spec.ts (3)
14-37: Fix TS nullability and avoid double-append of container.Make vars nullable, remove redundant append, and pass optional container safely to cleanup.
- let view: EditorView; - let container: HTMLElement; - let dispatchSpy: jest.Mock; + let view: EditorView | null = null; + let container: HTMLElement | null = null; @@ - dispatchSpy = jest.fn(); - const state = createEditorState('<p>Test content</p>'); - const result = createEditorView(state, dispatchSpy); + const result = createEditorView(state); view = result.view; container = result.container; - - document.body.append(container); @@ - if (view) { - cleanupEditorView(view, container); + if (view) { + cleanupEditorView(view, container || undefined); view = null; container = null; } - - dispatchSpy = null;
165-169: Don’t cast to DragEvent in JSDOM tests.DragEvent may be undefined; use any/Event.
- const drop = dispatchEventSpy.mock.calls[3][0] as DragEvent; + const drop = dispatchEventSpy.mock.calls[3][0] as any; @@ - const dragstart = dispatchEventSpy.mock.calls[1][0] as DragEvent; + const dragstart = dispatchEventSpy.mock.calls[1][0] as any;Also applies to: 182-189
18-23: Optional: remove unused dispatch spy wiring.You aren’t asserting on dispatchTransaction; keep tests lean by omitting it.
- let dispatchSpy: jest.Mock; @@ - dispatchSpy = jest.fn(); - const state = createEditorState('<p>Test content</p>'); - const result = createEditorView(state, dispatchSpy); + const result = createEditorView(state); @@ - dispatchSpy = null;src/components/text-editor/test-setup/schema-builder.ts (2)
21-28: DRY the underline MarkSpec and reuse it in both builders.Avoid duplicating the underline spec; define it once and reference it in both
createTestSchemaandcreateCustomTestSchema.Apply:
@@ import { strikethrough } from '../prosemirror-adapter/menu/menu-schema-extender'; +const underlineMarkSpec = { + parseDOM: [ + { tag: 'u' }, + { style: 'text-decoration:underline' }, + { style: 'text-decoration-line:underline' }, + ], + toDOM: () => ['u', 0], +}; + export function createTestSchema(): Schema { @@ - marks: basicSchema.spec.marks.append({ - strikethrough: strikethrough, - underline: { - parseDOM: [ - { tag: 'u' }, - { style: 'text-decoration:underline' }, - { style: 'text-decoration-line:underline' }, - ], - toDOM: () => ['u', 0], - }, - }), + marks: basicSchema.spec.marks.append({ + strikethrough: strikethrough, + underline: underlineMarkSpec, + }), @@ - if (options.addUnderline !== false) { - marks = marks.append({ - underline: { - parseDOM: [ - { tag: 'u' }, - { style: 'text-decoration:underline' }, - { style: 'text-decoration-line:underline' }, - ], - toDOM: () => ['u', 0], - }, - }); - } + if (options.addUnderline !== false) { + marks = marks.append({ + underline: underlineMarkSpec, + }); + }Also applies to: 68-79
47-53: Default the options parameter to prevent runtime crashes.Calling
createCustomTestSchema()without args will read properties onundefined.Apply:
-export function createCustomTestSchema(options: { +export function createCustomTestSchema(options: { addLists?: boolean; addStrikethrough?: boolean; addUnderline?: boolean; customMarks?: Record<string, any>; customNodes?: Record<string, any>; -}): Schema { +} = {}): Schema {src/components/text-editor/test-setup/editor-state-builder.ts (2)
79-91: Document trusted-HTML assumption for innerHTML (test-only).Add a brief security note to the JSDoc.
Apply:
* @param schema - Schema to use for parsing * @returns A ProseMirror document node + * + * Security: Test-only helper. Assumes trusted HTML. Do not pass untrusted + * HTML without sanitizing first. */ function parseContentToDoc(content: string, schema: Schema) {
41-59: Clamp selection bounds to avoid RangeError on invalid positions.Unvalidated
from/tocan exceed doc bounds and throw.Apply:
export function createEditorStateWithSelection( @@ - const selection = TextSelection.create(doc, from, to); + const maxPos = doc.content.size; + const fromPos = Math.max(0, Math.min(from, maxPos)); + const toPos = Math.max(0, Math.min(to, maxPos)); + const a = Math.min(fromPos, toPos); + const b = Math.max(fromPos, toPos); + const selection = TextSelection.create(doc, a, b);src/components/text-editor/test-setup/editor-view-builder.spec.ts (1)
136-158: Fix assertion to match implementation (container.remove is used).
cleanupEditorViewcallselement.remove(), notdocument.body.removeChild(...).Apply:
- const removeChildSpy = jest.spyOn(document.body, 'removeChild'); + const removeSpy = jest.spyOn(customContainer, 'remove'); @@ - expect(removeChildSpy).toHaveBeenCalledWith(customContainer); + expect(removeSpy).toHaveBeenCalled(); @@ - removeChildSpy.mockRestore(); + removeSpy.mockRestore();src/components/text-editor/test-setup/content-generator.ts (1)
123-139: Validate heading level (1–6) early.Prevents accidental creation of invalid headings in tests.
Apply:
export function createDocWithHeading( text: string, level: number = 1, schema?: Schema, ): EditorState { + if (!Number.isInteger(level) || level < 1 || level > 6) { + throw new RangeError(`Heading level must be between 1 and 6, got ${level}`); + } const editorSchema = schema || createTestSchema();src/components/text-editor/test-setup/command-tester.ts (2)
73-85: Reduce complexity by normalizing includesContent to an array.Keeps assertions linear and consistent.
Apply:
-function verifyDocumentIncludes( - doc: { textContent: string }, - expectedContent: string | string[], -): void { - if (Array.isArray(expectedContent)) { - // Check that all strings in the array are contained in the doc content - for (const content of expectedContent) { - expect(doc.textContent).toContain(content); - } - } else { - expect(doc.textContent).toContain(expectedContent); - } -} +function verifyDocumentIncludes( + doc: { textContent: string }, + expectedContent: string | string[], +): void { + const parts = Array.isArray(expectedContent) + ? expectedContent + : [expectedContent]; + for (const content of parts) { + expect(doc.textContent).toContain(content); + } +}
206-218: Add includesContent verification (and reuse the shared verifier).
testCommandWithViewdefinesincludesContentin the type but does not assert it. ReuseverifyDocumentContentfor consistency.Apply:
- if (expected.shouldApply && commandResultObj.newState) { - if (expected.docContentAfter !== undefined) { - expect(commandResultObj.newState.doc.textContent).toBe( - expected.docContentAfter, - ); - } - - if (expected.docSizeAfter !== undefined) { - expect(commandResultObj.newState.doc.nodeSize).toBe( - expected.docSizeAfter, - ); - } - } + if (expected.shouldApply && commandResultObj.newState) { + verifyDocumentContent(commandResultObj.newState, expected); + }
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
📒 Files selected for processing (12)
src/components/text-editor/prosemirror-adapter/menu/menu-commands.ts(4 hunks)src/components/text-editor/prosemirror-adapter/plugins/table-plugin.spec.ts(1 hunks)src/components/text-editor/test-setup/command-tester.spec.ts(1 hunks)src/components/text-editor/test-setup/command-tester.ts(1 hunks)src/components/text-editor/test-setup/content-generator.ts(1 hunks)src/components/text-editor/test-setup/editor-state-builder.spec.ts(1 hunks)src/components/text-editor/test-setup/editor-state-builder.ts(1 hunks)src/components/text-editor/test-setup/editor-view-builder.spec.ts(1 hunks)src/components/text-editor/test-setup/editor-view-builder.ts(1 hunks)src/components/text-editor/test-setup/event-simulator.spec.ts(1 hunks)src/components/text-editor/test-setup/event-simulator.ts(1 hunks)src/components/text-editor/test-setup/schema-builder.ts(1 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{ts,tsx}
⚙️ CodeRabbit configuration file
Imports from other files in the same module (lime-elements) must use relative paths. Using absolute paths for imports will cause the production build to fail.
Files:
src/components/text-editor/test-setup/event-simulator.spec.tssrc/components/text-editor/prosemirror-adapter/plugins/table-plugin.spec.tssrc/components/text-editor/test-setup/editor-view-builder.spec.tssrc/components/text-editor/test-setup/editor-state-builder.spec.tssrc/components/text-editor/prosemirror-adapter/menu/menu-commands.tssrc/components/text-editor/test-setup/editor-view-builder.tssrc/components/text-editor/test-setup/command-tester.spec.tssrc/components/text-editor/test-setup/command-tester.tssrc/components/text-editor/test-setup/schema-builder.tssrc/components/text-editor/test-setup/event-simulator.tssrc/components/text-editor/test-setup/content-generator.tssrc/components/text-editor/test-setup/editor-state-builder.ts
🧬 Code graph analysis (10)
src/components/text-editor/test-setup/event-simulator.spec.ts (3)
src/components/text-editor/test-setup/editor-state-builder.ts (1)
createEditorState(14-29)src/components/text-editor/test-setup/editor-view-builder.ts (2)
createEditorView(14-45)cleanupEditorView(78-85)src/components/text-editor/test-setup/event-simulator.ts (6)
simulateKeyPress(70-91)KeyModifiers(55-60)PasteData(46-50)simulatePaste(100-117)simulateClick(130-169)simulateDragAndDrop(182-247)
src/components/text-editor/prosemirror-adapter/plugins/table-plugin.spec.ts (3)
src/components/text-editor/test-setup/editor-view-builder.ts (3)
cleanupEditorView(78-85)createDispatchSpy(53-69)createEditorView(14-45)src/components/text-editor/prosemirror-adapter/plugins/table-plugin.ts (3)
getTableEditingPlugins(4-10)getTableNodes(22-31)createStyleAttribute(12-20)src/components/text-editor/test-setup/schema-builder.ts (1)
createCustomTestSchema(47-92)
src/components/text-editor/test-setup/editor-view-builder.spec.ts (2)
src/components/text-editor/test-setup/editor-view-builder.ts (4)
cleanupEditorView(78-85)createEditorView(14-45)createDispatchSpy(53-69)mockProseMirrorDOMEnvironment(93-135)src/components/text-editor/test-setup/editor-state-builder.ts (1)
createEditorState(14-29)
src/components/text-editor/test-setup/editor-state-builder.spec.ts (2)
src/components/text-editor/test-setup/editor-state-builder.ts (3)
createEditorState(14-29)createEditorStateWithSelection(41-59)setTextSelection(69-77)src/components/text-editor/test-setup/schema-builder.ts (1)
createCustomTestSchema(47-92)
src/components/text-editor/test-setup/editor-view-builder.ts (2)
src/components/text-editor/test-setup/editor-state-builder.ts (1)
createEditorState(14-29)src/components/text-editor/test-setup/schema-builder.ts (1)
createTestSchema(12-33)
src/components/text-editor/test-setup/command-tester.spec.ts (2)
src/components/text-editor/test-setup/command-tester.ts (4)
getCommandResult(29-58)testCommand(136-157)testCommandWithView(170-222)createCommandTester(230-240)src/components/text-editor/test-setup/editor-view-builder.ts (1)
cleanupEditorView(78-85)
src/components/text-editor/test-setup/command-tester.ts (1)
src/components/text-editor/test-setup/editor-view-builder.ts (1)
createEditorView(14-45)
src/components/text-editor/test-setup/schema-builder.ts (1)
src/components/text-editor/prosemirror-adapter/menu/menu-schema-extender.ts (1)
strikethrough(3-13)
src/components/text-editor/test-setup/content-generator.ts (2)
src/components/text-editor/test-setup/schema-builder.ts (1)
createTestSchema(12-33)src/components/text-editor/test-setup/editor-state-builder.ts (1)
createEditorState(14-29)
src/components/text-editor/test-setup/editor-state-builder.ts (1)
src/components/text-editor/test-setup/schema-builder.ts (1)
createTestSchema(12-33)
🪛 ast-grep (0.38.6)
src/components/text-editor/test-setup/editor-state-builder.ts
[warning] 87-87: Direct HTML content assignment detected. Modifying innerHTML, outerHTML, or using document.write with unsanitized content can lead to XSS vulnerabilities. Use secure alternatives like textContent or sanitize HTML with libraries like DOMPurify.
Context: domNode.innerHTML = content
Note: [CWE-79] Improper Neutralization of Input During Web Page Generation [REFERENCES]
- https://www.dhairyashah.dev/posts/why-innerhtml-is-a-bad-idea-and-how-to-avoid-it/
- https://cwe.mitre.org/data/definitions/79.html
(unsafe-html-content-assignment)
[warning] 87-87: Direct modification of innerHTML or outerHTML properties detected. Modifying these properties with unsanitized user input can lead to XSS vulnerabilities. Use safe alternatives or sanitize content first.
Context: domNode.innerHTML = content
Note: [CWE-79] Improper Neutralization of Input During Web Page Generation [REFERENCES]
- https://owasp.org/www-community/xss-filter-evasion-cheatsheet
- https://cwe.mitre.org/data/definitions/79.html
(dom-content-modification)
🔇 Additional comments (4)
src/components/text-editor/prosemirror-adapter/plugins/table-plugin.spec.ts (2)
151-171: LGTM: solid falsy handling and style preservation tests.Coverage is good and matches expected behavior.
19-21: LGTM: view/container nullable typing.Prevents strictNullChecks issues during teardown.
src/components/text-editor/test-setup/editor-view-builder.ts (1)
78-85: Cleanup looks correct and safe.
view.destroy()followed by optionalcontainer.remove()is appropriate.src/components/text-editor/prosemirror-adapter/menu/menu-commands.ts (1)
191-221: Potential for unintended nested wraps when toggling (e.g., blockquote)Because
hasActiveWrappreviously only matched the immediate parent, toggling could wrap again instead of lifting. After fixingcheckForActiveWrap, verify toggling inside an existing wrapper lifts rather than nests.Suggested test scenario:
- Place cursor inside paragraph within a blockquote.
- Toggle blockquote: expect lift (no nested blockquote).
- Toggle again: expect wrap.
If desired, I can add a PM test to cover this.
| import { | ||
| Schema, | ||
| MarkType, | ||
| NodeType, | ||
| Attrs, | ||
| ResolvedPos, | ||
| } from 'prosemirror-model'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧹 Nitpick
Use type-only imports to avoid pulling runtime code from prosemirror-model
These are used purely as types; switch to import type to keep bundles lean and avoid side effects.
-import {
- Schema,
- MarkType,
- NodeType,
- Attrs,
- ResolvedPos,
-} from 'prosemirror-model';
+import type { Schema, MarkType, NodeType, Attrs, ResolvedPos } from 'prosemirror-model';📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| import { | |
| Schema, | |
| MarkType, | |
| NodeType, | |
| Attrs, | |
| ResolvedPos, | |
| } from 'prosemirror-model'; | |
| import type { Schema, MarkType, NodeType, Attrs, ResolvedPos } from 'prosemirror-model'; |
🤖 Prompt for AI Agents
In src/components/text-editor/prosemirror-adapter/menu/menu-commands.ts around
lines 2 to 8, the imports from 'prosemirror-model' are only used as types and
should be switched to type-only imports to avoid pulling runtime code into
bundles; change the statement to use TypeScript's `import type { Schema,
MarkType, NodeType, Attrs, ResolvedPos } from 'prosemirror-model'` so the
compiler emits no runtime require/require side-effects and ensure your
tsconfig/compiler options (like isolatedModules or preserveValueImports) remain
compatible.
| const checkForActiveWrap = ( | ||
| $from: ResolvedPos, | ||
| nodeType: NodeType, | ||
| ): boolean => { | ||
| return $from.depth > 0 && $from.node($from.depth - 1).type === nodeType; | ||
| }; | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wrap detection only checks direct parent; fails for common cases (e.g., paragraph inside blockquote)
This returns false when the selection is inside a paragraph that is inside the target wrapper (e.g., blockquote), causing nested wraps instead of lifting.
-const checkForActiveWrap = (
- $from: ResolvedPos,
- nodeType: NodeType,
-): boolean => {
- return $from.depth > 0 && $from.node($from.depth - 1).type === nodeType;
-};
+const checkForActiveWrap = (
+ $from: ResolvedPos,
+ nodeType: NodeType,
+): boolean => {
+ for (let d = $from.depth; d > 0; d--) {
+ if ($from.node(d).type === nodeType) {
+ return true;
+ }
+ }
+ return false;
+};📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| const checkForActiveWrap = ( | |
| $from: ResolvedPos, | |
| nodeType: NodeType, | |
| ): boolean => { | |
| return $from.depth > 0 && $from.node($from.depth - 1).type === nodeType; | |
| }; | |
| const checkForActiveWrap = ( | |
| $from: ResolvedPos, | |
| nodeType: NodeType, | |
| ): boolean => { | |
| for (let d = $from.depth; d > 0; d--) { | |
| if ($from.node(d).type === nodeType) { | |
| return true; | |
| } | |
| } | |
| return false; | |
| }; |
🤖 Prompt for AI Agents
In src/components/text-editor/prosemirror-adapter/menu/menu-commands.ts around
lines 161 to 167, the current check only compares the immediate parent node type
and misses cases where the target wrapper is an ancestor (e.g., paragraph inside
blockquote); replace the simple $from.node($from.depth - 1).type === nodeType
check with logic that walks up ancestors (from $from.depth - 1 down to 0) and
returns true if any ancestor's type matches nodeType, otherwise false, ensuring
the function detects wrapping at any ancestor level so nested wraps are properly
lifted.
| describe('Style attribute helper', () => { | ||
| it('should get style values from DOM elements', () => { | ||
| const backgroundAttr = createStyleAttribute('background-color'); | ||
|
|
||
| const element = document.createElement('td'); | ||
| element.style.backgroundColor = 'red'; | ||
|
|
||
| expect(backgroundAttr.getFromDOM(element)).toBe('red'); | ||
| }); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fix getFromDOM to read kebab-case CSS props. Tests expect kebab-case; implementation uses style[cssProperty].
CSSStyleDeclaration doesn’t support bracket access with kebab-case. Use getPropertyValue.
Suggested change in src/components/text-editor/prosemirror-adapter/plugins/table-plugin.ts:
export const createStyleAttribute = (cssProperty: string) => ({
default: null,
getFromDOM: (dom: HTMLElement) => {
const v = dom.style.getPropertyValue(cssProperty);
return v || null;
},
setDOMAttr: (value: string, attrs: Record<string, any>) => {
if (value) {
attrs.style = (attrs.style || '') + `${cssProperty}: ${value};`;
}
},
});🤖 Prompt for AI Agents
In src/components/text-editor/prosemirror-adapter/plugins/table-plugin.ts around
lines 121 to 129, getFromDOM currently attempts to read kebab-case CSS
properties via bracket access on element.style which fails; change it to use
dom.style.getPropertyValue(cssProperty) and return null when empty so kebab-case
names like "background-color" are read correctly; also ensure setDOMAttr builds
the style string with the kebab-case property (e.g., `${cssProperty}:
${value};`) rather than using camelCase keys.
| if (expected.docContentAfter !== undefined) { | ||
| verifyExactDocumentContent(state.doc, expected.docContentAfter); | ||
| } | ||
|
|
||
| if ('includesContent' in expected) { | ||
| verifyDocumentIncludes(state.doc, expected.includesContent); | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Guard against undefined includesContent.
Use an explicit undefined check rather than 'in' to avoid accidental calls with undefined.
Apply:
- if ('includesContent' in expected) {
- verifyDocumentIncludes(state.doc, expected.includesContent);
- }
+ if (expected.includesContent !== undefined) {
+ verifyDocumentIncludes(state.doc, expected.includesContent);
+ }📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| if (expected.docContentAfter !== undefined) { | |
| verifyExactDocumentContent(state.doc, expected.docContentAfter); | |
| } | |
| if ('includesContent' in expected) { | |
| verifyDocumentIncludes(state.doc, expected.includesContent); | |
| } | |
| if (expected.docContentAfter !== undefined) { | |
| verifyExactDocumentContent(state.doc, expected.docContentAfter); | |
| } | |
| if (expected.includesContent !== undefined) { | |
| verifyDocumentIncludes(state.doc, expected.includesContent); | |
| } |
🤖 Prompt for AI Agents
In src/components/text-editor/test-setup/command-tester.ts around lines 111 to
117, the code uses the `'in'` operator to detect includesContent which can still
be present but undefined; replace that check with an explicit undefined check
(e.g., if (expected.includesContent !== undefined) ) before calling
verifyDocumentIncludes so the function is only invoked when includesContent has
a defined value; ensure the check handles null if needed per types and keep the
call otherwise unchanged.
| * = `includesContent?`: content that should exist in the document | ||
| * @returns The result of applying the command for further assertions if needed |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧹 Nitpick
JSDoc typo: fix bullet for includesContent.
Apply:
- * = `includesContent?`: content that should exist in the document
+ * - `includesContent?`: content that should exist in the document📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| * = `includesContent?`: content that should exist in the document | |
| * @returns The result of applying the command for further assertions if needed | |
| * - `includesContent?`: content that should exist in the document | |
| * @returns The result of applying the command for further assertions if needed |
🤖 Prompt for AI Agents
In src/components/text-editor/test-setup/command-tester.ts around lines 133-134,
the JSDoc bullet for includesContent is malformed; replace the current bullet
with a proper JSDoc @param declaration such as: @param includesContent? content
that should exist in the document (or use backticks around the optional name if
your style requires `includesContent?`), ensuring the line starts with "@param"
and follows the repository's JSDoc style.
| export function createDocWithFormattedText( | ||
| text: string, | ||
| marks: MarkSpec[], | ||
| schema?: Schema, | ||
| ): EditorState { | ||
| const editorSchema = schema || createTestSchema(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Align parameter typing with the new mark input type.
Apply:
export function createDocWithFormattedText(
text: string,
- marks: MarkSpec[],
+ marks: MarkInput[],
schema?: Schema,
): EditorState {📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| export function createDocWithFormattedText( | |
| text: string, | |
| marks: MarkSpec[], | |
| schema?: Schema, | |
| ): EditorState { | |
| const editorSchema = schema || createTestSchema(); | |
| export function createDocWithFormattedText( | |
| text: string, | |
| marks: MarkInput[], | |
| schema?: Schema, | |
| ): EditorState { | |
| const editorSchema = schema || createTestSchema(); |
🤖 Prompt for AI Agents
In src/components/text-editor/test-setup/content-generator.ts around lines 44 to
49, the createDocWithFormattedText function still types the marks parameter as
MarkSpec[]; update the parameter type to the new MarkInput[] (and import the
MarkInput type) so the signature matches current mark input usage, then adjust
any downstream usage in this file to satisfy the new type (e.g., pass MarkInput
objects into mark-creation helpers or convert them where needed).
| function createTextNodeWithMarks( | ||
| text: string, | ||
| marks: MarkSpec[], | ||
| schema: Schema, | ||
| ): Node { | ||
| const appliedMarks: Mark[] = marks.map((markSpec) => { | ||
| const markType = schema.marks[markSpec.type]; | ||
| if (!markType) { | ||
| throw new Error(`Mark type "${markSpec.type}" not found in schema`); | ||
| } | ||
|
|
||
| return markType.create(markSpec.attrs || {}); | ||
| }); | ||
|
|
||
| const textNode = schema.text(text, appliedMarks); | ||
|
|
||
| return schema.nodes.paragraph.create(null, textNode); | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Update helper to use the new mark input type and keep fast failure on unknown marks.
Apply:
function createTextNodeWithMarks(
text: string,
- marks: MarkSpec[],
+ marks: MarkInput[],
schema: Schema,
): Node {
- const appliedMarks: Mark[] = marks.map((markSpec) => {
- const markType = schema.marks[markSpec.type];
+ const appliedMarks: Mark[] = marks.map((markDef) => {
+ const markType = schema.marks[markDef.type];
if (!markType) {
- throw new Error(`Mark type "${markSpec.type}" not found in schema`);
+ throw new Error(`Mark type "${markDef.type}" not found in schema`);
}
- return markType.create(markSpec.attrs || {});
+ return markType.create(markDef.attrs || {});
});📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| function createTextNodeWithMarks( | |
| text: string, | |
| marks: MarkSpec[], | |
| schema: Schema, | |
| ): Node { | |
| const appliedMarks: Mark[] = marks.map((markSpec) => { | |
| const markType = schema.marks[markSpec.type]; | |
| if (!markType) { | |
| throw new Error(`Mark type "${markSpec.type}" not found in schema`); | |
| } | |
| return markType.create(markSpec.attrs || {}); | |
| }); | |
| const textNode = schema.text(text, appliedMarks); | |
| return schema.nodes.paragraph.create(null, textNode); | |
| } | |
| function createTextNodeWithMarks( | |
| text: string, | |
| marks: MarkInput[], | |
| schema: Schema, | |
| ): Node { | |
| const appliedMarks: Mark[] = marks.map((markDef) => { | |
| const markType = schema.marks[markDef.type]; | |
| if (!markType) { | |
| throw new Error(`Mark type "${markDef.type}" not found in schema`); | |
| } | |
| return markType.create(markDef.attrs || {}); | |
| }); | |
| const textNode = schema.text(text, appliedMarks); | |
| return schema.nodes.paragraph.create(null, textNode); | |
| } |
| let dataTransfer; | ||
| if (typeof DataTransfer !== 'undefined') { | ||
| dataTransfer = new DataTransfer(); | ||
| } else { | ||
| dataTransfer = new MockDataTransfer(); | ||
| } | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧹 Nitpick
Type the local dataTransfer variable.
Avoid implicit any under strict settings.
- let dataTransfer;
+ let dataTransfer: DataTransfer | MockDataTransfer;📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| let dataTransfer; | |
| if (typeof DataTransfer !== 'undefined') { | |
| dataTransfer = new DataTransfer(); | |
| } else { | |
| dataTransfer = new MockDataTransfer(); | |
| } | |
| let dataTransfer: DataTransfer | MockDataTransfer; | |
| if (typeof DataTransfer !== 'undefined') { | |
| dataTransfer = new DataTransfer(); | |
| } else { | |
| dataTransfer = new MockDataTransfer(); | |
| } |
🤖 Prompt for AI Agents
In src/components/text-editor/test-setup/event-simulator.ts around lines 261 to
267, the local variable dataTransfer is declared without a type which causes
implicit any under strict TS settings; annotate it with an explicit union type
(e.g. DataTransfer | MockDataTransfer) so TypeScript knows it will be either the
DOM DataTransfer or your mock, and ensure MockDataTransfer's type is imported or
declared in this file (or export its type from the mock module) so the union
type resolves correctly.
| import { Schema } from 'prosemirror-model'; | ||
| import { schema as basicSchema } from 'prosemirror-schema-basic'; | ||
| import { addListNodes } from 'prosemirror-schema-list'; | ||
| import { strikethrough } from '../prosemirror-adapter/menu/menu-schema-extender'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
Verify strikethrough parseDOM style syntax in the imported spec.
Upstream menu-schema-extender.ts uses text-decoration=line-through; ProseMirror expects CSS style match in parseDOM as text-decoration:line-through. Please align for consistency with underline here.
Run to confirm:
🏁 Script executed:
#!/bin/bash
rg -nP "text-decoration\s*=\s*line-through|text-decoration-line\s*=" -C2 src/components/text-editorLength of output: 518
Fix parseDOM style for strikethrough (use colon, not "=").
Replace { style: 'text-decoration=line-through' } with { style: 'text-decoration:line-through' } in src/components/text-editor/prosemirror-adapter/menu/menu-schema-extender.ts:8 — ProseMirror parseDOM expects CSS property:value syntax.
🤖 Prompt for AI Agents
In src/components/text-editor/test-setup/schema-builder.ts around line 4, update
the referenced ProseMirror schema extender so its parseDOM style uses CSS
property:value syntax: open
src/components/text-editor/prosemirror-adapter/menu/menu-schema-extender.ts
(around line 8) and replace the incorrect `{ style:
'text-decoration=line-through' }` with `{ style: 'text-decoration:line-through'
}`, ensuring parseDOM entries use colon-separated CSS to be recognized by
ProseMirror.
98c661a to
209f90c
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 10
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
src/components/text-editor/prosemirror-adapter/plugins/table-plugin.ts (1)
12-20: Fix style extraction and safe concatenation in createStyleAttributegetFromDOM won’t read hyphenated CSS props via dom.style[cssProperty]; use getPropertyValue. Also guard semicolon spacing when appending to attrs.style.
-export const createStyleAttribute = (cssProperty: string) => ({ +export const createStyleAttribute = (cssProperty: string) => ({ default: null, - getFromDOM: (dom: HTMLElement) => dom.style[cssProperty] || null, + getFromDOM: (dom: HTMLElement) => + (dom.style && typeof dom.style.getPropertyValue === 'function' + ? dom.style.getPropertyValue(cssProperty) + : null) || null, setDOMAttr: (value: string, attrs: Record<string, any>) => { if (value) { - attrs.style = (attrs.style || '') + `${cssProperty}: ${value};`; + const prefix = + attrs.style && !String(attrs.style).trim().endsWith(';') + ? `${attrs.style}; ` + : attrs.style || ''; + attrs.style = `${prefix}${cssProperty}: ${value};`; } }, });src/components/text-editor/test-setup/content-generator.ts (1)
1-183: Replace runtime use of MarkSpec with a dedicated runtime mark descriptor
- Found MarkSpec[] used as a runtime input in test helpers: src/components/text-editor/test-setup/content-generator.ts — createDocWithFormattedText (line 46) and createTextNodeWithMarks (line 68). MarkSpec is a schema-definition type; replace it with a small runtime type (e.g. { type: string; attrs?: Record<string, unknown> } or keyof Schema['marks']) and update mark-creation typing/logic.
- Update tests that pass MarkSpec[] accordingly: src/components/text-editor/test-setup/content-generator.spec.ts (lines 68, 95, 127).
- Keep schema definitions that legitimately use MarkSpec (e.g. src/components/text-editor/prosemirror-adapter/menu/menu-schema-extender.ts) unchanged.
♻️ Duplicate comments (27)
src/components/text-editor/test-setup/text-editor-test-utils.md (5)
15-18: Correct createEditorView/cleanupEditorView API in docsReturn shape is { view, container } and cleanup accepts optional container. Update bullets.
-3. **Editor View Utilities** - - `createEditorView(state, dispatchSpy?)` - Creates a ProseMirror editor view with an optional dispatch spy - - `cleanupEditorView(view)` - Properly destroys an editor view to prevent memory leaks +3. **Editor View Utilities** + - `createEditorView(state, dispatchSpy?, parentElement?) => { view, container }` + - `cleanupEditorView(view, container?)` - Properly destroys an editor view to prevent memory leaks
30-34: Keep docs consistent: mark createMockEditorView as planned and remove trailing space- - `createMockEditorView()` - Creates a mocked editor view␠ + - `createMockEditorView()` - ⏳ Planned
35-38: Align Selection Helpers with implementation statusMark setNodeSelection as planned to match current exports.
- - `setNodeSelection(state, pos)` - Creates a node selection + - `setNodeSelection(state, pos)` - ⏳ Planned
47-55: Fix import path to aggregatorUse the aggregator in the same directory.
-} from '../test-setup/test-utils'; +} from './editor-test-utils';
56-67: Update usage to match return shapeDestructure result and pass container to cleanup.
- let schema, state, view; + let schema, state, view, container; beforeEach(() => { schema = createTestSchema(); state = createEditorState('<p>Test content</p>', schema); - view = createEditorView(state); + const result = createEditorView(state); + view = result.view; + container = result.container; }); afterEach(() => { - cleanupEditorView(view); + cleanupEditorView(view, container); });src/components/text-editor/test-setup/text-editor-test-suite-guide.md (3)
211-217: Fix example imports to use local aggregator (editor-test-utils)Replace '../test-setup/test-utils' with './editor-test-utils' in all example blocks listed.
-} from '../test-setup/test-utils'; +} from './editor-test-utils';Also applies to: 242-247, 291-299, 365-371, 418-427
515-519: Remove duplicate createDocWithText row in Implementation StatusAvoid duplicate entries.
| **Content Generation** | `createDocWithText()` | ✅ Implemented | | | `createDocWithHTML()` | ✅ Implemented | -| | `createDocWithText()` | ✅ Implemented | | | `createDocWithFormattedText()` | ✅ Implemented |
572-572: markdownlint: remove trailing spaceTrim the trailing space at the end of this line.
- - Add debug elements to show editor content: `container.appendChild(view.dom)`␠ + - Add debug elements to show editor content: `container.appendChild(view.dom)`src/components/text-editor/test-setup/schema-builder.spec.ts (2)
50-62: Optional: add parseDOM/toDOM round‑trip for custom markStrengthen test by verifying serialization/parsing consistency of 'highlight'.
64-78: Optional: add round‑trip for custom nodeParse a matching DOM element, then serialize and compare expected attrs.
src/components/text-editor/test-setup/event-simulator.ts (2)
147-163: Remove redundant elementFromPoint checkInner check repeats the outer condition; simplify.
- // Add a noop implementation for coordinate methods that might be missing - if (document.elementFromPoint === undefined) { + // Add a noop implementation for coordinate methods that might be missing + if (document.elementFromPoint === undefined) { // For tests, just pretend the click always hits the editor // This prevents errors when ProseMirror calls elementFromPoint (view.dom as any).getBoundingClientRect = () => ({ ... }); - - // Mock elementFromPoint to avoid errors - if (document.elementFromPoint === undefined) { - (document as any).elementFromPoint = () => view.dom; - } + // Mock elementFromPoint to avoid errors + (document as any).elementFromPoint = () => view.dom; }
258-267: Type dataTransfer to avoid implicit any under strict TS-function createDataTransfer( - content: PasteData, -): DataTransfer | MockDataTransfer { - let dataTransfer; +function createDataTransfer( + content: PasteData, +): DataTransfer | MockDataTransfer { + let dataTransfer: DataTransfer | MockDataTransfer;src/components/text-editor/test-setup/schema-builder.ts (1)
47-53: Prevent crash when options is omitted; provide default parameterCalling createCustomTestSchema() with no arg currently throws on options.* access.
-export function createCustomTestSchema(options: { +export function createCustomTestSchema(options: { addLists?: boolean; addStrikethrough?: boolean; addUnderline?: boolean; customMarks?: Record<string, any>; customNodes?: Record<string, any>; -}): Schema { +} = {}): Schema {src/components/text-editor/test-setup/command-tester.ts (3)
31-41: Remove trailing commas flagged by lint.Clean up trailing commas in params/calls/return to satisfy Prettier/Biome.
export function getCommandResult( command: Command, - state: EditorState, + state: EditorState ): CommandResult { @@ const commandResult = command( state, (tr) => { transaction = tr; }, - undefined, + undefined ); @@ return { result: true, transaction: transaction, - newState: newState, + newState: newState }; } @@ function verifyExactDocumentContent( doc: { textContent: string }, - expectedContent: string, + expectedContent: string ): void { @@ function verifyDocumentIncludes( doc: { textContent: string }, - expectedContent: string | string[], + expectedContent: string | string[] ): void { @@ function verifyDocumentSize( doc: { nodeSize: number }, - expectedSize: number, + expectedSize: number ): void { @@ function verifyDocumentContent( state: EditorState, expected: { docContentAfter?: string; docSizeAfter?: number; includesContent?: string | string[]; - }, + } ): void {Also applies to: 53-58, 63-68, 73-85, 90-95, 103-110
115-117: Guard includesContent with explicit undefined check.Avoid
'in'with possibly undefined values.- if ('includesContent' in expected) { - verifyDocumentIncludes(state.doc, expected.includesContent); - } + if (expected.includesContent !== undefined) { + verifyDocumentIncludes(state.doc, expected.includesContent); + }
206-218: Unify post-checks and add includesContent for view tests.Delegate to verifyDocumentContent for consistency (adds includesContent support).
- if (expected.shouldApply && commandResultObj.newState) { - if (expected.docContentAfter !== undefined) { - expect(commandResultObj.newState.doc.textContent).toBe( - expected.docContentAfter, - ); - } - - if (expected.docSizeAfter !== undefined) { - expect(commandResultObj.newState.doc.nodeSize).toBe( - expected.docSizeAfter, - ); - } - } + if (expected.shouldApply && commandResultObj.newState) { + verifyDocumentContent(commandResultObj.newState, expected); + }src/components/text-editor/test-setup/command-tester.spec.ts (1)
41-46: Fix trailing commas to satisfy Prettier.Remove trailing commas in expect calls and function args.
- expect(result.newState.doc.textContent).toContain( - 'additional text', - ); + expect(result.newState.doc.textContent).toContain( + 'additional text' + ); @@ - expect(commandResult.newState.doc.textContent).toContain( - 'Modified', - ); + expect(commandResult.newState.doc.textContent).toContain( + 'Modified' + ); @@ - const { result, view, container } = testCommandWithView( + const { result, view, container } = testCommandWithView( viewCommand, state, { shouldApply: true, - }, - ); + } + );Also applies to: 78-83, 140-146
src/components/text-editor/test-setup/editor-state-builder.spec.ts (1)
30-43: Prefer resolved marks over nodeAt for inline mark assertions.nodeAt on text offsets can be brittle; inspecting
$pos.marks()is sturdier.- const $pos = state.doc.resolve(wordPos); - const node = state.doc.nodeAt(wordPos); - expect($pos).toBeDefined(); - expect(node).toBeDefined(); - - if (node) { - const hasStrongMark = node.marks.some( - (m) => m.type.name === 'strong', - ); - expect(hasStrongMark).toBe(true); - } + const $pos = state.doc.resolve(wordPos); + const hasStrong = $pos.marks().some((m) => m.type.name === 'strong'); + expect(hasStrong).toBe(true);src/components/text-editor/test-setup/event-simulator.spec.ts (2)
14-21: Fix TS nullability and avoid double-append.Allow null resets and don’t append container twice.
- let view: EditorView; - let container: HTMLElement; - let dispatchSpy: jest.Mock; + let view: EditorView | null; + let container: HTMLElement | null; + let dispatchSpy: jest.Mock | null; @@ - document.body.append(container); + // createEditorView already appends the container when no parent is provided @@ - if (view) { - cleanupEditorView(view, container); + if (view) { + cleanupEditorView(view, container || undefined); view = null; container = null; } @@ - dispatchSpy = null; + dispatchSpy = null;Also applies to: 26-27, 29-37
161-168: Don’t rely on DragEvent in JSDOM.Cast to any/Event; CustomEvent is used under the hood.
- const drop = dispatchEventSpy.mock.calls[3][0] as DragEvent; + const drop = dispatchEventSpy.mock.calls[3][0] as any; @@ - const dragstart = dispatchEventSpy.mock.calls[1][0] as DragEvent; + const dragstart = dispatchEventSpy.mock.calls[1][0] as any;Also applies to: 180-189
src/components/text-editor/test-setup/editor-state-builder.ts (3)
52-58: Clamp selection bounds to prevent RangeError.from/to outside doc bounds will throw. Clamp to [0..doc.content.size].
- const selection = TextSelection.create(doc, from, to); + const maxPos = doc.content.size; + const fromPos = Math.max(0, Math.min(from, maxPos)); + const toPos = Math.max(0, Math.min(to, maxPos)); + const selection = TextSelection.create(doc, fromPos, toPos);
79-91: Document trusted-HTML assumption for parseContentToDoc.Add a security note to appease static analysis and clarify scope.
/** * Parses content string into a ProseMirror document. * * @param content - Content string (HTML) * @param schema - Schema to use for parsing * @returns A ProseMirror document node + * + * Security: Test-only helper. Assumes trusted HTML. Do not use with + * untrusted input without sanitizing (e.g., DOMPurify) before parsing. */ function parseContentToDoc(content: string, schema: Schema) {
69-77: Same bound-clamp for setTextSelection.- const selection = TextSelection.create(state.doc, from, to); + const maxPos = state.doc.content.size; + const fromPos = Math.max(0, Math.min(from, maxPos)); + const toPos = Math.max(0, Math.min(to, maxPos)); + const selection = TextSelection.create(state.doc, fromPos, toPos);src/components/text-editor/prosemirror-adapter/plugins/table-plugin.spec.ts (1)
121-129: Fix createStyleAttribute(getFromDOM) to read kebab-case CSS.As tests now pass 'background-color', current implementation using
dom.style[cssProperty]returns empty. UsegetPropertyValue.-// src/components/text-editor/prosemirror-adapter/plugins/table-plugin.ts -export const createStyleAttribute = (cssProperty: string) => ({ - default: null, - getFromDOM: (dom: HTMLElement) => dom.style[cssProperty] || null, - setDOMAttr: (value: string, attrs: Record<string, any>) => { - if (value) { - attrs.style = (attrs.style || '') + `${cssProperty}: ${value};`; - } - }, -}); +export const createStyleAttribute = (cssProperty: string) => ({ + default: null, + getFromDOM: (dom: HTMLElement) => { + const v = dom.style.getPropertyValue(cssProperty); + return v || null; + }, + setDOMAttr: (value: string, attrs: Record<string, any>) => { + if (value) { + attrs.style = (attrs.style || '') + `${cssProperty}: ${value};`; + } + }, +});src/components/text-editor/test-setup/editor-view-builder.spec.ts (1)
148-158: Fix assertion: cleanup uses container.remove(), not document.body.removeChild.Update the spy to target the container.
Apply:
- const removeChildSpy = jest.spyOn(document.body, 'removeChild'); + const removeSpy = jest.spyOn(customContainer, 'remove'); @@ - expect(removeChildSpy).toHaveBeenCalledWith(customContainer); + expect(removeSpy).toHaveBeenCalled(); @@ - removeChildSpy.mockRestore(); + removeSpy.mockRestore();src/components/text-editor/test-setup/content-generator.ts (2)
123-139: Fix lint error: remove inferrable type annotation on defaulted param.Biome flags this as an error; drop “: number”.
Apply:
export function createDocWithHeading( text: string, - level: number = 1, + level = 1, schema?: Schema, ): EditorState {
127-134: Validate heading level (1–6) early.Prevents invalid states in tests.
Apply:
export function createDocWithHeading( text: string, level = 1, schema?: Schema, ): EditorState { const editorSchema = schema || createTestSchema(); + if (!Number.isInteger(level) || level < 1 || level > 6) { + throw new RangeError(`Heading level must be an integer between 1 and 6. Got: ${level}`); + }
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
📒 Files selected for processing (17)
src/components/text-editor/prosemirror-adapter/plugins/table-plugin.spec.ts(1 hunks)src/components/text-editor/prosemirror-adapter/plugins/table-plugin.ts(1 hunks)src/components/text-editor/test-setup/command-tester.spec.ts(1 hunks)src/components/text-editor/test-setup/command-tester.ts(1 hunks)src/components/text-editor/test-setup/content-generator.spec.ts(1 hunks)src/components/text-editor/test-setup/content-generator.ts(1 hunks)src/components/text-editor/test-setup/editor-state-builder.spec.ts(1 hunks)src/components/text-editor/test-setup/editor-state-builder.ts(1 hunks)src/components/text-editor/test-setup/editor-test-utils.ts(1 hunks)src/components/text-editor/test-setup/editor-view-builder.spec.ts(1 hunks)src/components/text-editor/test-setup/editor-view-builder.ts(1 hunks)src/components/text-editor/test-setup/event-simulator.spec.ts(1 hunks)src/components/text-editor/test-setup/event-simulator.ts(1 hunks)src/components/text-editor/test-setup/schema-builder.spec.ts(1 hunks)src/components/text-editor/test-setup/schema-builder.ts(1 hunks)src/components/text-editor/test-setup/text-editor-test-suite-guide.md(1 hunks)src/components/text-editor/test-setup/text-editor-test-utils.md(1 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{ts,tsx}
⚙️ CodeRabbit configuration file
Imports from other files in the same module (lime-elements) must use relative paths. Using absolute paths for imports will cause the production build to fail.
Files:
src/components/text-editor/test-setup/schema-builder.spec.tssrc/components/text-editor/prosemirror-adapter/plugins/table-plugin.tssrc/components/text-editor/test-setup/editor-state-builder.tssrc/components/text-editor/test-setup/command-tester.spec.tssrc/components/text-editor/test-setup/editor-view-builder.tssrc/components/text-editor/test-setup/schema-builder.tssrc/components/text-editor/test-setup/editor-test-utils.tssrc/components/text-editor/test-setup/editor-state-builder.spec.tssrc/components/text-editor/test-setup/event-simulator.tssrc/components/text-editor/test-setup/event-simulator.spec.tssrc/components/text-editor/test-setup/command-tester.tssrc/components/text-editor/test-setup/content-generator.tssrc/components/text-editor/test-setup/content-generator.spec.tssrc/components/text-editor/test-setup/editor-view-builder.spec.tssrc/components/text-editor/prosemirror-adapter/plugins/table-plugin.spec.ts
🧬 Code graph analysis (12)
src/components/text-editor/test-setup/schema-builder.spec.ts (1)
src/components/text-editor/test-setup/schema-builder.ts (2)
createTestSchema(12-33)createCustomTestSchema(47-92)
src/components/text-editor/test-setup/editor-state-builder.ts (1)
src/components/text-editor/test-setup/schema-builder.ts (1)
createTestSchema(12-33)
src/components/text-editor/test-setup/command-tester.spec.ts (2)
src/components/text-editor/test-setup/command-tester.ts (4)
getCommandResult(29-58)testCommand(136-157)testCommandWithView(170-222)createCommandTester(230-240)src/components/text-editor/test-setup/editor-view-builder.ts (1)
cleanupEditorView(78-85)
src/components/text-editor/test-setup/editor-view-builder.ts (1)
src/components/text-editor/test-setup/schema-builder.ts (1)
createTestSchema(12-33)
src/components/text-editor/test-setup/schema-builder.ts (1)
src/components/text-editor/prosemirror-adapter/menu/menu-schema-extender.ts (1)
strikethrough(3-13)
src/components/text-editor/test-setup/editor-state-builder.spec.ts (2)
src/components/text-editor/test-setup/editor-state-builder.ts (3)
createEditorState(14-29)createEditorStateWithSelection(41-59)setTextSelection(69-77)src/components/text-editor/test-setup/schema-builder.ts (1)
createCustomTestSchema(47-92)
src/components/text-editor/test-setup/event-simulator.spec.ts (2)
src/components/text-editor/test-setup/editor-view-builder.ts (2)
createEditorView(14-45)cleanupEditorView(78-85)src/components/text-editor/test-setup/event-simulator.ts (6)
simulateKeyPress(70-91)KeyModifiers(55-60)PasteData(46-50)simulatePaste(100-117)simulateClick(130-169)simulateDragAndDrop(182-247)
src/components/text-editor/test-setup/command-tester.ts (1)
src/components/text-editor/test-setup/editor-view-builder.ts (1)
createEditorView(14-45)
src/components/text-editor/test-setup/content-generator.ts (1)
src/components/text-editor/test-setup/schema-builder.ts (1)
createTestSchema(12-33)
src/components/text-editor/test-setup/content-generator.spec.ts (2)
src/components/text-editor/test-setup/content-generator.ts (7)
createDocWithText(13-21)createDocWithHTML(30-34)createDocWithFormattedText(44-56)createDocWithBulletList(92-113)createDocWithHeading(123-139)createDocWithBlockquote(148-161)createDocWithCodeBlock(170-182)src/components/text-editor/test-setup/schema-builder.ts (1)
createCustomTestSchema(47-92)
src/components/text-editor/test-setup/editor-view-builder.spec.ts (1)
src/components/text-editor/test-setup/editor-view-builder.ts (4)
cleanupEditorView(78-85)createEditorView(14-45)createDispatchSpy(53-69)mockProseMirrorDOMEnvironment(93-135)
src/components/text-editor/prosemirror-adapter/plugins/table-plugin.spec.ts (3)
src/components/text-editor/test-setup/editor-view-builder.ts (3)
cleanupEditorView(78-85)createDispatchSpy(53-69)createEditorView(14-45)src/components/text-editor/prosemirror-adapter/plugins/table-plugin.ts (3)
getTableEditingPlugins(4-10)getTableNodes(22-31)createStyleAttribute(12-20)src/components/text-editor/test-setup/schema-builder.ts (1)
createCustomTestSchema(47-92)
🪛 ast-grep (0.38.6)
src/components/text-editor/test-setup/editor-state-builder.ts
[warning] 87-87: Direct modification of innerHTML or outerHTML properties detected. Modifying these properties with unsanitized user input can lead to XSS vulnerabilities. Use safe alternatives or sanitize content first.
Context: domNode.innerHTML = content
Note: [CWE-79] Improper Neutralization of Input During Web Page Generation [REFERENCES]
- https://owasp.org/www-community/xss-filter-evasion-cheatsheet
- https://cwe.mitre.org/data/definitions/79.html
(dom-content-modification)
[warning] 87-87: Direct HTML content assignment detected. Modifying innerHTML, outerHTML, or using document.write with unsanitized content can lead to XSS vulnerabilities. Use secure alternatives like textContent or sanitize HTML with libraries like DOMPurify.
Context: domNode.innerHTML = content
Note: [CWE-79] Improper Neutralization of Input During Web Page Generation [REFERENCES]
- https://www.dhairyashah.dev/posts/why-innerhtml-is-a-bad-idea-and-how-to-avoid-it/
- https://cwe.mitre.org/data/definitions/79.html
(unsafe-html-content-assignment)
🪛 GitHub Check: Lint
src/components/text-editor/test-setup/command-tester.spec.ts
[failure] 145-145:
Delete ,
[failure] 117-117:
Delete ,
[failure] 81-81:
Delete ,
[failure] 44-44:
Delete ,
src/components/text-editor/test-setup/command-tester.ts
[failure] 109-109:
Delete ,
[warning] 97-97:
Missing JSDoc @param "expected.docContentAfter" declaration
[failure] 92-92:
Delete ,
[warning] 87-87:
Missing JSDoc @param "expectedSize" declaration
[warning] 87-87:
Missing JSDoc @param "doc.nodeSize" declaration
[warning] 87-87:
Missing JSDoc @param "doc" declaration
[failure] 75-75:
Delete ,
[warning] 70-70:
Missing JSDoc @param "expectedContent" declaration
[warning] 70-70:
Missing JSDoc @param "doc.textContent" declaration
[warning] 70-70:
Missing JSDoc @param "doc" declaration
[failure] 65-65:
Delete ,
[warning] 60-60:
Missing JSDoc @param "expectedContent" declaration
[warning] 60-60:
Missing JSDoc @param "doc.textContent" declaration
[warning] 60-60:
Missing JSDoc @param "doc" declaration
[failure] 41-41:
Delete ,
[failure] 31-31:
Delete ,
🪛 GitHub Actions: Pull Request Checks
src/components/text-editor/test-setup/command-tester.spec.ts
[error] 44-44: Step: npm run lint. Prettier formatting error (prettier/prettier): Delete , at line 44:34.
🔇 Additional comments (4)
src/components/text-editor/test-setup/editor-test-utils.ts (1)
1-6: LGTM: clean aggregator of test utilities.Re-exports are relative and align with build rules.
src/components/text-editor/test-setup/content-generator.spec.ts (1)
1-243: LGTM: thorough coverage of content helpers.Tests are clear and schema-aware. Optional chaining already applied.
src/components/text-editor/test-setup/editor-view-builder.ts (1)
78-85: Cleanup logic looks good (destroy + container?.remove).Matches intended lifecycle and prevents leaks.
src/components/text-editor/test-setup/editor-view-builder.spec.ts (1)
23-35: Tests are clear and exercise the main paths.Good coverage for defaults, provided state/dispatch, cleanup destroy, and DOM mock creation/restoration.
Also applies to: 72-86, 120-135, 161-194
| /** | ||
| * Verifies if the document's exact text content matches the expected content | ||
| */ | ||
| function verifyExactDocumentContent( | ||
| doc: { textContent: string }, | ||
| expectedContent: string, | ||
| ): void { | ||
| expect(doc.textContent).toBe(expectedContent); | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧹 Nitpick
Add missing JSDoc @param entries for helpers.
Satisfy lint and clarify expectations.
/**
* Verifies if the document's exact text content matches the expected content
+ *
+ * @param doc - Object with textContent to assert on
+ * @param expectedContent - Exact expected textContent
*/
function verifyExactDocumentContent(
@@
/**
* Verifies if the document contains all the expected text snippets
+ *
+ * @param doc - Object with textContent to check
+ * @param expectedContent - Substring(s) expected to be present
*/
function verifyDocumentIncludes(
@@
/**
* Verifies if the document's node size matches the expected size
+ *
+ * @param doc - Object with nodeSize to assert on
+ * @param expectedSize - Expected node size
*/
function verifyDocumentSize(
@@
/**
* Verifies the content of the document against expected values
*
* @param state - The editor state containing the document to verify
* @param expected - The expected values to verify against
+ * @param expected.docContentAfter - Expected full textContent after command
+ * @param expected.includesContent - Substrings expected to be present
+ * @param expected.docSizeAfter - Expected node size after command
*/
function verifyDocumentContent(Also applies to: 70-85, 87-95, 97-122, 124-135
🧰 Tools
🤖 Prompt for AI Agents
In src/components/text-editor/test-setup/command-tester.ts around lines 60 to 68
(and similarly for ranges 70-85, 87-95, 97-122, 124-135), the helper functions
are missing JSDoc @param entries; add JSDoc @param annotations for each
parameter (including types and brief descriptions) and update the function JSDoc
blocks to include @returns where applicable so the lint rules are satisfied and
callers understand expectations.
| @@ -0,0 +1,182 @@ | |||
| import { Schema, Mark, Fragment, Node, MarkSpec } from 'prosemirror-model'; | |||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Incorrect use of MarkSpec (schema definition) for runtime marks.
MarkSpec doesn’t have .type/.attrs; this won’t type-check and is conceptually wrong. Define a MarkInput and update usages.
Apply:
-import { Schema, Mark, Fragment, Node, MarkSpec } from 'prosemirror-model';
+import { Schema, Mark, Fragment, Node } from 'prosemirror-model';
+
+type MarkInput = {
+ type: string;
+ attrs?: Record<string, any>;
+};
@@
-export function createDocWithFormattedText(
+export function createDocWithFormattedText(
text: string,
- marks: MarkSpec[],
+ marks: MarkInput[],
schema?: Schema,
): EditorState {
@@
-function createTextNodeWithMarks(
+function createTextNodeWithMarks(
text: string,
- marks: MarkSpec[],
+ marks: MarkInput[],
schema: Schema,
): Node {
- const appliedMarks: Mark[] = marks.map((markSpec) => {
- const markType = schema.marks[markSpec.type];
+ const appliedMarks: Mark[] = marks.map((markDef) => {
+ const markType = schema.marks[markDef.type];
if (!markType) {
- throw new Error(`Mark type "${markSpec.type}" not found in schema`);
+ throw new Error(`Mark type "${markDef.type}" not found in schema`);
}
- return markType.create(markSpec.attrs || {});
+ return markType.create(markDef.attrs || {});
});Also applies to: 44-56, 66-83
| return EditorState.create({ doc: doc }); | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧹 Nitpick
Tiny cleanup: use object shorthand in EditorState.create.
Non-functional simplification.
Apply:
- return EditorState.create({ doc: doc });
+ return EditorState.create({ doc });Also applies to: 112-113, 138-139, 160-161, 181-182
🤖 Prompt for AI Agents
In src/components/text-editor/test-setup/content-generator.ts around lines 55-56
(and similarly at 112-113, 138-139, 160-161, 181-182), the EditorState.create
calls use the verbose object form { doc: doc }; replace each occurrence with the
ES6 object shorthand { doc } to simplify the code (update all listed line ranges
to use { doc } instead of { doc: doc }).
| describe('mockProseMirrorDOMEnvironment', () => { | ||
| let originalWindow; | ||
| let originalDocument; | ||
|
|
||
| beforeEach(() => { | ||
| originalWindow = global.window; | ||
| originalDocument = global.document; | ||
| }); | ||
|
|
||
| afterEach(() => { | ||
| global.window = originalWindow; | ||
| global.document = originalDocument; | ||
| }); | ||
|
|
||
| it('should create mock DOM if none exists', () => { | ||
| try { | ||
| global.window = undefined; | ||
| global.document = undefined; | ||
|
|
||
| const cleanup = mockProseMirrorDOMEnvironment(); | ||
|
|
||
| expect(global.window).toBeDefined(); | ||
| expect(global.document).toBeDefined(); | ||
| expect(global.document.createElement).toBeDefined(); | ||
|
|
||
| cleanup(); | ||
|
|
||
| expect(global.window).toBeUndefined(); | ||
| expect(global.document).toBeUndefined(); | ||
| } finally { | ||
| global.window = originalWindow; | ||
| global.document = originalDocument; | ||
| } | ||
| }); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧹 Nitpick
Add an integration test: createEditorView under mocked DOM.
Prevents regressions like missing body.append/element.remove in mocks.
Apply after the existing “should create mock DOM if none exists”:
+ it('integrates with createEditorView under mocked DOM', () => {
+ const restore = mockProseMirrorDOMEnvironment();
+ try {
+ const { view, container } = createEditorView();
+ expect(view).toBeInstanceOf(EditorView);
+ cleanupEditorView(view, container);
+ } finally {
+ restore();
+ }
+ });📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| describe('mockProseMirrorDOMEnvironment', () => { | |
| let originalWindow; | |
| let originalDocument; | |
| beforeEach(() => { | |
| originalWindow = global.window; | |
| originalDocument = global.document; | |
| }); | |
| afterEach(() => { | |
| global.window = originalWindow; | |
| global.document = originalDocument; | |
| }); | |
| it('should create mock DOM if none exists', () => { | |
| try { | |
| global.window = undefined; | |
| global.document = undefined; | |
| const cleanup = mockProseMirrorDOMEnvironment(); | |
| expect(global.window).toBeDefined(); | |
| expect(global.document).toBeDefined(); | |
| expect(global.document.createElement).toBeDefined(); | |
| cleanup(); | |
| expect(global.window).toBeUndefined(); | |
| expect(global.document).toBeUndefined(); | |
| } finally { | |
| global.window = originalWindow; | |
| global.document = originalDocument; | |
| } | |
| }); | |
| describe('mockProseMirrorDOMEnvironment', () => { | |
| let originalWindow; | |
| let originalDocument; | |
| beforeEach(() => { | |
| originalWindow = global.window; | |
| originalDocument = global.document; | |
| }); | |
| afterEach(() => { | |
| global.window = originalWindow; | |
| global.document = originalDocument; | |
| }); | |
| it('should create mock DOM if none exists', () => { | |
| try { | |
| global.window = undefined; | |
| global.document = undefined; | |
| const cleanup = mockProseMirrorDOMEnvironment(); | |
| expect(global.window).toBeDefined(); | |
| expect(global.document).toBeDefined(); | |
| expect(global.document.createElement).toBeDefined(); | |
| cleanup(); | |
| expect(global.window).toBeUndefined(); | |
| expect(global.document).toBeUndefined(); | |
| } finally { | |
| global.window = originalWindow; | |
| global.document = originalDocument; | |
| } | |
| }); | |
| it('integrates with createEditorView under mocked DOM', () => { | |
| const restore = mockProseMirrorDOMEnvironment(); | |
| try { | |
| const { view, container } = createEditorView(); | |
| expect(view).toBeInstanceOf(EditorView); | |
| cleanupEditorView(view, container); | |
| } finally { | |
| restore(); | |
| } | |
| }); |
🤖 Prompt for AI Agents
In src/components/text-editor/test-setup/editor-view-builder.spec.ts around
lines 161 to 194, add an integration test immediately after the existing "should
create mock DOM if none exists" that verifies createEditorView works under the
mocked DOM and that the mock implements body.appendChild and element.remove so
they are called during view creation and destruction; use the
mockProseMirrorDOMEnvironment to set up the fake window/document, call
createEditorView, assert the editor element was appended to document.body
(spy/check appendChild usage) and that cleanup/destroy removes the element
(spy/check remove usage), then call cleanup and restore globals.
| export function createEditorView( | ||
| state?: EditorState, | ||
| dispatchSpy?: jest.Mock, | ||
| parentElement?: HTMLElement, | ||
| ): { view: EditorView; container: HTMLElement } { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Tighten types: use DirectEditorProps/Transaction and a typed spy.
Use accurate types for dispatch and props to catch errors at compile time.
Apply:
-import { EditorState } from 'prosemirror-state';
-import { EditorView } from 'prosemirror-view';
+import { EditorState, Transaction } from 'prosemirror-state';
+import { EditorView } from 'prosemirror-view';
+import type { DirectEditorProps } from 'prosemirror-view';
@@
-export function createEditorView(
- state?: EditorState,
- dispatchSpy?: jest.Mock,
+export function createEditorView(
+ state?: EditorState,
+ dispatchSpy?: jest.MockedFunction<(tr: Transaction) => void>,
parentElement?: HTMLElement,
): { view: EditorView; container: HTMLElement } {
@@
- const viewProps: {
- state: EditorState;
- dispatchTransaction?: (tr: any) => void;
- } = {
- state: editorState,
- };
+ const viewProps: DirectEditorProps = { state: editorState };
@@
- if (dispatchSpy) {
- viewProps.dispatchTransaction = dispatchSpy;
- }
+ if (dispatchSpy) viewProps.dispatchTransaction = dispatchSpy;Also applies to: 27-36, 38-45
| export function createDispatchSpy(autoUpdate = true): jest.Mock { | ||
| let viewRef: EditorView; | ||
|
|
||
| const spy = jest.fn((transaction) => { | ||
| if (autoUpdate && viewRef) { | ||
| viewRef.updateState(viewRef.state.apply(transaction)); | ||
| } | ||
|
|
||
| return transaction; | ||
| }); | ||
|
|
||
| (spy as any).setView = (view: EditorView) => { | ||
| viewRef = view; | ||
| }; | ||
|
|
||
| return spy; | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧹 Nitpick
Make spy’s signature explicit and return void.
Aligns with dispatchTransaction type and avoids implying a return value.
Apply:
-export function createDispatchSpy(autoUpdate = true): jest.Mock {
+export function createDispatchSpy(
+ autoUpdate = true,
+): jest.MockedFunction<(tr: Transaction) => void> {
let viewRef: EditorView;
- const spy = jest.fn((transaction) => {
+ const spy: jest.MockedFunction<(tr: Transaction) => void> = jest.fn(
+ (transaction: Transaction) => {
if (autoUpdate && viewRef) {
viewRef.updateState(viewRef.state.apply(transaction));
}
-
- return transaction;
- });
+ });📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| export function createDispatchSpy(autoUpdate = true): jest.Mock { | |
| let viewRef: EditorView; | |
| const spy = jest.fn((transaction) => { | |
| if (autoUpdate && viewRef) { | |
| viewRef.updateState(viewRef.state.apply(transaction)); | |
| } | |
| return transaction; | |
| }); | |
| (spy as any).setView = (view: EditorView) => { | |
| viewRef = view; | |
| }; | |
| return spy; | |
| } | |
| export function createDispatchSpy( | |
| autoUpdate = true, | |
| ): jest.MockedFunction<(tr: Transaction) => void> { | |
| let viewRef: EditorView; | |
| const spy: jest.MockedFunction<(tr: Transaction) => void> = jest.fn( | |
| (transaction: Transaction) => { | |
| if (autoUpdate && viewRef) { | |
| viewRef.updateState(viewRef.state.apply(transaction)); | |
| } | |
| }, | |
| ); | |
| (spy as any).setView = (view: EditorView) => { | |
| viewRef = view; | |
| }; | |
| return spy; | |
| } |
🤖 Prompt for AI Agents
In src/components/text-editor/test-setup/editor-view-builder.ts around lines 53
to 69, the created jest spy currently implies it returns a transaction and has
no explicit function signature; change its type to an explicit void-returning
mock (e.g. jest.Mock<void, [Transaction]> or equivalent) so it matches
dispatchTransaction, update the implementation to not return the transaction
(just perform the update), type viewRef as EditorView | undefined, and annotate
the spy with a setView method type (e.g. (view: EditorView) => void) so
TypeScript understands the added method.
| if (!global.window || !global.document) { | ||
| const mockDocument = { | ||
| createElement: () => ({ | ||
| appendChild: () => {}, | ||
| style: {}, | ||
| classList: { | ||
| add: () => {}, | ||
| remove: () => {}, | ||
| contains: () => false, | ||
| }, | ||
| }), | ||
| createTextNode: () => ({}), | ||
| body: { | ||
| appendChild: () => {}, | ||
| removeChild: () => {}, | ||
| }, | ||
| defaultView: {}, | ||
| addEventListener: () => {}, | ||
| removeEventListener: () => {}, | ||
| }; | ||
|
|
||
| const mockWindow = { | ||
| document: mockDocument, | ||
| getComputedStyle: () => ({ | ||
| getPropertyValue: () => '', | ||
| }), | ||
| addEventListener: () => {}, | ||
| removeEventListener: () => {}, | ||
| }; | ||
|
|
||
| global.window = mockWindow as any; | ||
| global.document = mockDocument as any; | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fix mock DOM to match actual usage (missing body.append and element.remove).
createEditorView uses document.body.append(...) and cleanupEditorView calls element.remove(); the mock provides neither, which will throw when used under the mocked environment. Add body.append and element.remove.
Apply:
- const mockDocument = {
- createElement: () => ({
- appendChild: () => {},
- style: {},
+ const mockDocument = {
+ createElement: () => ({
+ appendChild: () => {},
+ remove: () => {},
+ style: {},
classList: {
add: () => {},
remove: () => {},
contains: () => false,
},
}),
createTextNode: () => ({}),
- body: {
- appendChild: () => {},
- removeChild: () => {},
- },
+ body: {
+ append: () => {},
+ appendChild: () => {},
+ removeChild: () => {},
+ },
defaultView: {},
addEventListener: () => {},
removeEventListener: () => {},
};📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| if (!global.window || !global.document) { | |
| const mockDocument = { | |
| createElement: () => ({ | |
| appendChild: () => {}, | |
| style: {}, | |
| classList: { | |
| add: () => {}, | |
| remove: () => {}, | |
| contains: () => false, | |
| }, | |
| }), | |
| createTextNode: () => ({}), | |
| body: { | |
| appendChild: () => {}, | |
| removeChild: () => {}, | |
| }, | |
| defaultView: {}, | |
| addEventListener: () => {}, | |
| removeEventListener: () => {}, | |
| }; | |
| const mockWindow = { | |
| document: mockDocument, | |
| getComputedStyle: () => ({ | |
| getPropertyValue: () => '', | |
| }), | |
| addEventListener: () => {}, | |
| removeEventListener: () => {}, | |
| }; | |
| global.window = mockWindow as any; | |
| global.document = mockDocument as any; | |
| } | |
| if (!global.window || !global.document) { | |
| const mockDocument = { | |
| createElement: () => ({ | |
| appendChild: () => {}, | |
| remove: () => {}, | |
| style: {}, | |
| classList: { | |
| add: () => {}, | |
| remove: () => {}, | |
| contains: () => false, | |
| }, | |
| }), | |
| createTextNode: () => ({}), | |
| body: { | |
| append: () => {}, | |
| appendChild: () => {}, | |
| removeChild: () => {}, | |
| }, | |
| defaultView: {}, | |
| addEventListener: () => {}, | |
| removeEventListener: () => {}, | |
| }; | |
| const mockWindow = { | |
| document: mockDocument, | |
| getComputedStyle: () => ({ | |
| getPropertyValue: () => '', | |
| }), | |
| addEventListener: () => {}, | |
| removeEventListener: () => {}, | |
| }; | |
| global.window = mockWindow as any; | |
| global.document = mockDocument as any; | |
| } |
🤖 Prompt for AI Agents
In src/components/text-editor/test-setup/editor-view-builder.ts around lines 97
to 129, the mock DOM lacks document.body.append and returned elements lack
remove(), while createEditorView calls document.body.append(...) and
cleanupEditorView calls element.remove(); update the mock so document.body
includes an append method in addition to appendChild/removeChild, and ensure
createElement returns an element object that implements remove() (and optionally
append) alongside appendChild, style, and classList methods so tests using
append(...) and element.remove() do not throw.
| const state = createEditorState('<p>Test content</p>'); | ||
| const result = createEditorView(state, dispatchSpy); | ||
| view = result.view; | ||
| container = result.container; | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧹 Nitpick
Optional: remove unused dispatchSpy or assert on it.
Either drop passing the spy or add expectations.
🤖 Prompt for AI Agents
In src/components/text-editor/test-setup/event-simulator.spec.ts around lines 21
to 25, the test creates a dispatchSpy and passes it into createEditorView but
never uses or asserts against it; either remove the dispatchSpy variable and
stop passing it into createEditorView, or keep the spy and add explicit
expectations (e.g., expect(dispatchSpy).toHaveBeenCalledWith(...) or
expect(dispatchSpy).not.toHaveBeenCalled()) that match the test's intended
behavior; update any imports/mocking setup accordingly and run the test to
ensure behavior remains correct.
| import { Schema } from 'prosemirror-model'; | ||
| import { schema as basicSchema } from 'prosemirror-schema-basic'; | ||
| import { addListNodes } from 'prosemirror-schema-list'; | ||
| import { strikethrough } from '../prosemirror-adapter/menu/menu-schema-extender'; | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
Verify strikethrough parseDOM style in upstream extender
Upstream strikethrough uses 'text-decoration=line-through'; ProseMirror expects 'text-decoration:line-through'. Fix there to ensure parseDOM works.
🏁 Script executed:
#!/bin/bash
# Find incorrect CSS parseDOM entries using '=' instead of ':'
rg -nP "text-decoration\s*=\s*line-through" -C2 src | sed -n '1,120p'
# Expected: no matches after fix.Length of output: 1380
Fix strikethrough parseDOM style to use ':' (text-decoration:line-through)
Replace "text-decoration=line-through" with "text-decoration:line-through" so ProseMirror's parseDOM matches, in:
- src/components/text-editor/prosemirror-adapter/menu/menu-schema-extender.ts
- src/design-guidelines/text-editor/node-vs-mark-types.md
- src/design-guidelines/text-editor/editor-development.md
🤖 Prompt for AI Agents
In src/components/text-editor/test-setup/schema-builder.ts around lines 1-5 and
in src/components/text-editor/prosemirror-adapter/menu/menu-schema-extender.ts
and the two docs src/design-guidelines/text-editor/node-vs-mark-types.md and
src/design-guidelines/text-editor/editor-development.md, update the parseDOM
style string used for the strikethrough mark: replace any occurrence of
"text-decoration=line-through" with "text-decoration:line-through" (i.e., use a
colon after "text-decoration") so ProseMirror's parseDOM will match correctly.
| strikethrough: strikethrough, | ||
| underline: { | ||
| parseDOM: [ | ||
| { tag: 'u' }, | ||
| { style: 'text-decoration:underline' }, | ||
| { style: 'text-decoration-line:underline' }, | ||
| ], | ||
| toDOM: () => ['u', 0], | ||
| }, | ||
| }), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧹 Nitpick
DRY: extract shared underline MarkSpec
Same underline spec appears in two places. Extract once and reuse.
+const underlineMarkSpec = {
+ parseDOM: [
+ { tag: 'u' },
+ { style: 'text-decoration:underline' },
+ { style: 'text-decoration-line:underline' },
+ ],
+ toDOM: () => ['u', 0],
+};
...
- marks: basicSchema.spec.marks.append({
- strikethrough: strikethrough,
- underline: {
- parseDOM: [
- { tag: 'u' },
- { style: 'text-decoration:underline' },
- { style: 'text-decoration-line:underline' },
- ],
- toDOM: () => ['u', 0],
- },
- }),
+ marks: basicSchema.spec.marks.append({
+ strikethrough,
+ underline: underlineMarkSpec,
+ }),
...
- if (options.addUnderline !== false) {
+ if (options.addUnderline !== false) {
marks = marks.append({
- underline: {
- parseDOM: [
- { tag: 'u' },
- { style: 'text-decoration:underline' },
- { style: 'text-decoration-line:underline' },
- ],
- toDOM: () => ['u', 0],
- },
+ underline: underlineMarkSpec,
});
}Also applies to: 68-79
🤖 Prompt for AI Agents
In src/components/text-editor/test-setup/schema-builder.ts around lines 20 to 29
(and similarly lines 68 to 79), the underline MarkSpec is duplicated; extract
the shared underline spec into a single constant (e.g., const
UNDERLINE_MARK_SPEC = { parseDOM: [...], toDOM: ... }) defined near the top of
the module and replace both inline specs with a reference to that constant so
both spots reuse the same MarkSpec.
Adds a test suite that can be used to setup test environments for the text-editor.
Summary by CodeRabbit