Skip to content

Commit ed9d56a

Browse files
committed
feat(text-editor): add tests for the table plugin
1 parent 070e799 commit ed9d56a

2 files changed

Lines changed: 174 additions & 1 deletion

File tree

Lines changed: 173 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,173 @@
1+
import { Schema, NodeType } from 'prosemirror-model';
2+
import { Plugin } from 'prosemirror-state';
3+
import {
4+
cleanupEditorView,
5+
createCustomTestSchema,
6+
createDispatchSpy,
7+
createEditorState,
8+
createEditorView,
9+
} from '../../test-setup/editor-test-utils';
10+
11+
import {
12+
getTableEditingPlugins,
13+
getTableNodes,
14+
createStyleAttribute,
15+
} from './table-plugin';
16+
17+
18+
describe('Table Plugin', () => {
19+
let view;
20+
let container;
21+
22+
afterEach(() => {
23+
if (view) {
24+
cleanupEditorView(view, container);
25+
view = null;
26+
container = null;
27+
}
28+
});
29+
30+
describe('getTableEditingPlugins', () => {
31+
it('should return an array with table editing plugin when tables are enabled', () => {
32+
const plugins = getTableEditingPlugins(true);
33+
34+
expect(plugins).toBeInstanceOf(Array);
35+
expect(plugins.length).toBe(1);
36+
expect(plugins[0]).toBeInstanceOf(Plugin);
37+
});
38+
39+
it('should return an empty array when tables are disabled', () => {
40+
const plugins = getTableEditingPlugins(false);
41+
42+
expect(plugins).toBeInstanceOf(Array);
43+
expect(plugins.length).toBe(0);
44+
});
45+
46+
it('should create a working plugin that can be added to an editor state', () => {
47+
const baseSchema = createCustomTestSchema({});
48+
const tableNodes = getTableNodes();
49+
let nodes = baseSchema.spec.nodes;
50+
51+
for (const [name, spec] of Object.entries(tableNodes)) {
52+
nodes = nodes.addToEnd(name, spec);
53+
}
54+
55+
const schema = new Schema({
56+
nodes: nodes,
57+
marks: baseSchema.spec.marks,
58+
});
59+
60+
const content = '<p>Text with table support</p>';
61+
const plugins = getTableEditingPlugins(true);
62+
const state = createEditorState(content, schema, plugins);
63+
64+
const dispatchSpy = createDispatchSpy();
65+
const result = createEditorView(state, dispatchSpy);
66+
view = result.view;
67+
container = result.container;
68+
69+
expect(plugins.length).toBe(1);
70+
expect(view.state.plugins).toContain(plugins[0]);
71+
});
72+
});
73+
74+
describe('getTableNodes', () => {
75+
it('should return an object with table node specs', () => {
76+
const tableNodes = getTableNodes();
77+
78+
expect(tableNodes).toBeDefined();
79+
expect(typeof tableNodes).toBe('object');
80+
81+
expect(tableNodes.table).toBeDefined();
82+
expect(tableNodes.table_row).toBeDefined();
83+
expect(tableNodes.table_cell).toBeDefined();
84+
expect(tableNodes.table_header).toBeDefined();
85+
});
86+
87+
it('should create node specs that can be added to a schema', () => {
88+
const baseSchema = createCustomTestSchema({});
89+
const tableNodes = getTableNodes();
90+
let nodes = baseSchema.spec.nodes;
91+
92+
for (const [name, spec] of Object.entries(tableNodes)) {
93+
nodes = nodes.addToEnd(name, spec);
94+
}
95+
96+
const schema = new Schema({
97+
nodes: nodes,
98+
marks: baseSchema.spec.marks,
99+
});
100+
101+
expect(schema.nodes.table instanceof NodeType).toBe(true);
102+
expect(schema.nodes.table_row instanceof NodeType).toBe(true);
103+
expect(schema.nodes.table_cell instanceof NodeType).toBe(true);
104+
expect(schema.nodes.table_header instanceof NodeType).toBe(true);
105+
});
106+
107+
it('should include custom cell attributes for styling', () => {
108+
const tableNodes = getTableNodes();
109+
const cellSpec = tableNodes.table_cell;
110+
111+
expect(tableNodes.table_cell).toBeDefined();
112+
expect(tableNodes.table_cell.attrs).toBeDefined();
113+
expect(tableNodes.table_cell.attrs.background).toBeDefined();
114+
expect(tableNodes.table_cell.attrs.color).toBeDefined();
115+
116+
expect(cellSpec.attrs).toHaveProperty('background');
117+
expect(cellSpec.attrs).toHaveProperty('color');
118+
});
119+
});
120+
121+
describe('Style attribute helper', () => {
122+
it('should get style values from DOM elements', () => {
123+
const backgroundAttr = createStyleAttribute('backgroundColor');
124+
125+
const element = document.createElement('td');
126+
element.style.backgroundColor = 'red';
127+
128+
expect(backgroundAttr.getFromDOM(element)).toBe('red');
129+
});
130+
131+
it('should set style values on attributes object', () => {
132+
const backgroundAttr = createStyleAttribute('backgroundColor');
133+
const attrs: Record<string, any> = {};
134+
135+
backgroundAttr.setDOMAttr('blue', attrs);
136+
137+
expect(attrs.style).toBe('backgroundColor: blue;');
138+
});
139+
140+
it('should append to existing style attribute when setting multiple styles', () => {
141+
const backgroundAttr = createStyleAttribute('backgroundColor');
142+
const colorAttr = createStyleAttribute('color');
143+
const attrs: Record<string, any> = {};
144+
145+
backgroundAttr.setDOMAttr('blue', attrs);
146+
colorAttr.setDOMAttr('white', attrs);
147+
148+
expect(attrs.style).toBe('backgroundColor: blue;color: white;');
149+
});
150+
151+
it('should not modify the style attribute when value is falsy', () => {
152+
const backgroundAttr = createStyleAttribute('backgroundColor');
153+
const attrs: Record<string, any> = {};
154+
155+
// Test with empty string
156+
backgroundAttr.setDOMAttr('', attrs);
157+
expect(attrs.style).toBeUndefined();
158+
159+
// Test with null
160+
backgroundAttr.setDOMAttr(null, attrs);
161+
expect(attrs.style).toBeUndefined();
162+
163+
// Test with undefined
164+
backgroundAttr.setDOMAttr(undefined, attrs);
165+
expect(attrs.style).toBeUndefined();
166+
167+
// Test that existing style is preserved when falsy value is passed
168+
attrs.style = 'color: red;';
169+
backgroundAttr.setDOMAttr('', attrs);
170+
expect(attrs.style).toBe('color: red;');
171+
});
172+
});
173+
});

src/components/text-editor/prosemirror-adapter/plugins/table-plugin.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ export const getTableEditingPlugins = (tablesEnabled: boolean): Plugin[] => {
99
return [];
1010
};
1111

12-
const createStyleAttribute = (cssProperty: string) => ({
12+
export const createStyleAttribute = (cssProperty: string) => ({
1313
default: null,
1414
getFromDOM: (dom: HTMLElement) => dom.style[cssProperty] || null,
1515
setDOMAttr: (value: string, attrs: Record<string, any>) => {

0 commit comments

Comments
 (0)