@neo4j-cypher/react-codemirror 2.0.0-alpha.0 → 2.0.0-canary-e8a1279
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +68 -0
- package/LICENSE.md +201 -0
- package/README.md +27 -4
- package/dist/CypherEditor.d.ts +153 -0
- package/dist/CypherEditor.js +242 -0
- package/dist/CypherEditor.js.map +1 -0
- package/dist/e2e_tests/autoCompletion.spec.d.ts +1 -0
- package/dist/e2e_tests/autoCompletion.spec.js +133 -0
- package/dist/e2e_tests/autoCompletion.spec.js.map +1 -0
- package/dist/e2e_tests/configuration.spec.d.ts +1 -0
- package/dist/e2e_tests/configuration.spec.js +73 -0
- package/dist/e2e_tests/configuration.spec.js.map +1 -0
- package/dist/e2e_tests/e2eUtils.d.ts +12 -0
- package/dist/e2e_tests/e2eUtils.js +60 -0
- package/dist/e2e_tests/e2eUtils.js.map +1 -0
- package/dist/e2e_tests/extraKeybindings.spec.d.ts +1 -0
- package/dist/e2e_tests/extraKeybindings.spec.js +44 -0
- package/dist/e2e_tests/extraKeybindings.spec.js.map +1 -0
- package/dist/e2e_tests/historyNavigation.spec.d.ts +1 -0
- package/dist/e2e_tests/historyNavigation.spec.js +136 -0
- package/dist/e2e_tests/historyNavigation.spec.js.map +1 -0
- package/dist/e2e_tests/performanceTest.spec.d.ts +6 -0
- package/dist/e2e_tests/performanceTest.spec.js +96 -0
- package/dist/e2e_tests/performanceTest.spec.js.map +1 -0
- package/dist/e2e_tests/sanityChecks.spec.d.ts +1 -0
- package/dist/e2e_tests/sanityChecks.spec.js +56 -0
- package/dist/e2e_tests/sanityChecks.spec.js.map +1 -0
- package/dist/e2e_tests/signatureHelp.spec.d.ts +1 -0
- package/dist/e2e_tests/signatureHelp.spec.js +152 -0
- package/dist/e2e_tests/signatureHelp.spec.js.map +1 -0
- package/dist/e2e_tests/snippets.spec.d.ts +1 -0
- package/dist/e2e_tests/snippets.spec.js +63 -0
- package/dist/e2e_tests/snippets.spec.js.map +1 -0
- package/dist/e2e_tests/syntaxHighlighting.spec.d.ts +1 -0
- package/dist/e2e_tests/syntaxHighlighting.spec.js +91 -0
- package/dist/e2e_tests/syntaxHighlighting.spec.js.map +1 -0
- package/dist/e2e_tests/syntaxValidation.spec.d.ts +1 -0
- package/dist/e2e_tests/syntaxValidation.spec.js +79 -0
- package/dist/e2e_tests/syntaxValidation.spec.js.map +1 -0
- package/dist/historyNavigation.d.ts +7 -0
- package/dist/historyNavigation.js +163 -0
- package/dist/historyNavigation.js.map +1 -0
- package/dist/icons.d.ts +2 -0
- package/dist/icons.js +62 -0
- package/dist/icons.js.map +1 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +5 -0
- package/dist/index.js.map +1 -0
- package/dist/lang-cypher/autocomplete.d.ts +3 -0
- package/dist/lang-cypher/autocomplete.js +62 -0
- package/dist/lang-cypher/autocomplete.js.map +1 -0
- package/dist/lang-cypher/constants.d.ts +40 -0
- package/dist/lang-cypher/constants.js +65 -0
- package/dist/lang-cypher/constants.js.map +1 -0
- package/dist/lang-cypher/contants.test.d.ts +1 -0
- package/dist/lang-cypher/contants.test.js +102 -0
- package/dist/lang-cypher/contants.test.js.map +1 -0
- package/dist/lang-cypher/createCypherTheme.d.ts +26 -0
- package/dist/lang-cypher/createCypherTheme.js +172 -0
- package/dist/lang-cypher/createCypherTheme.js.map +1 -0
- package/dist/lang-cypher/langCypher.d.ts +9 -0
- package/dist/lang-cypher/langCypher.js +24 -0
- package/dist/lang-cypher/langCypher.js.map +1 -0
- package/dist/lang-cypher/lintWorker.d.ts +8 -0
- package/dist/lang-cypher/lintWorker.js +4 -0
- package/dist/lang-cypher/lintWorker.js.map +1 -0
- package/dist/lang-cypher/parser-adapter.d.ts +19 -0
- package/dist/lang-cypher/parser-adapter.js +113 -0
- package/dist/lang-cypher/parser-adapter.js.map +1 -0
- package/dist/lang-cypher/signatureHelp.d.ts +4 -0
- package/dist/lang-cypher/signatureHelp.js +93 -0
- package/dist/lang-cypher/signatureHelp.js.map +1 -0
- package/dist/lang-cypher/syntaxValidation.d.ts +5 -0
- package/dist/lang-cypher/syntaxValidation.js +71 -0
- package/dist/lang-cypher/syntaxValidation.js.map +1 -0
- package/dist/lang-cypher/themeIcons.d.ts +7 -0
- package/dist/lang-cypher/themeIcons.js +22 -0
- package/dist/lang-cypher/themeIcons.js.map +1 -0
- package/dist/ndlTokensCopy.d.ts +379 -0
- package/dist/ndlTokensCopy.js +380 -0
- package/dist/ndlTokensCopy.js.map +1 -0
- package/dist/ndlTokensCopy.test.d.ts +1 -0
- package/dist/ndlTokensCopy.test.js +11 -0
- package/dist/ndlTokensCopy.test.js.map +1 -0
- package/dist/neo4jSetup.d.ts +2 -0
- package/dist/neo4jSetup.js +120 -0
- package/dist/neo4jSetup.js.map +1 -0
- package/dist/themes.d.ts +11 -0
- package/dist/themes.js +114 -0
- package/dist/themes.js.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/package.json +46 -16
- package/src/CypherEditor.tsx +461 -0
- package/src/e2e_tests/autoCompletion.spec.tsx +236 -0
- package/src/e2e_tests/configuration.spec.tsx +97 -0
- package/src/e2e_tests/e2eUtils.ts +85 -0
- package/src/e2e_tests/extraKeybindings.spec.tsx +57 -0
- package/src/e2e_tests/historyNavigation.spec.tsx +196 -0
- package/src/e2e_tests/performanceTest.spec.tsx +158 -0
- package/src/e2e_tests/sanityChecks.spec.tsx +78 -0
- package/src/e2e_tests/signatureHelp.spec.tsx +309 -0
- package/src/e2e_tests/snippets.spec.tsx +94 -0
- package/src/e2e_tests/syntaxHighlighting.spec.tsx +198 -0
- package/src/e2e_tests/syntaxValidation.spec.tsx +156 -0
- package/src/historyNavigation.ts +191 -0
- package/{esm/index.mjs → src/icons.ts} +37 -1283
- package/src/index.ts +4 -0
- package/src/lang-cypher/autocomplete.ts +81 -0
- package/src/lang-cypher/constants.ts +84 -0
- package/src/lang-cypher/contants.test.ts +104 -0
- package/src/lang-cypher/createCypherTheme.ts +240 -0
- package/src/lang-cypher/langCypher.ts +41 -0
- package/src/lang-cypher/lintWorker.ts +14 -0
- package/src/lang-cypher/parser-adapter.ts +145 -0
- package/src/lang-cypher/signatureHelp.ts +131 -0
- package/src/lang-cypher/syntaxValidation.ts +99 -0
- package/src/lang-cypher/themeIcons.ts +27 -0
- package/src/ndlTokensCopy.test.ts +11 -0
- package/src/ndlTokensCopy.ts +379 -0
- package/src/neo4jSetup.tsx +179 -0
- package/src/themes.ts +132 -0
- package/dist/index.cjs +0 -1330
|
@@ -0,0 +1,309 @@
|
|
|
1
|
+
import { testData } from '@neo4j-cypher/language-support';
|
|
2
|
+
import { expect, test } from '@playwright/experimental-ct-react';
|
|
3
|
+
import { Locator } from 'playwright/test';
|
|
4
|
+
import { CypherEditor } from '../CypherEditor';
|
|
5
|
+
|
|
6
|
+
test.use({ viewport: { width: 1000, height: 500 } });
|
|
7
|
+
|
|
8
|
+
type TooltipExpectations = {
|
|
9
|
+
includes?: string[];
|
|
10
|
+
excludes?: string[];
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
function testTooltip(tooltip: Locator, expectations: TooltipExpectations) {
|
|
14
|
+
const includes = expectations.includes ?? [];
|
|
15
|
+
const excludes = expectations.excludes ?? [];
|
|
16
|
+
|
|
17
|
+
const included = Promise.all(
|
|
18
|
+
includes.map((text) => {
|
|
19
|
+
return expect(tooltip).toContainText(text, {
|
|
20
|
+
timeout: 2000,
|
|
21
|
+
});
|
|
22
|
+
}),
|
|
23
|
+
);
|
|
24
|
+
|
|
25
|
+
const excluded = Promise.all(
|
|
26
|
+
excludes.map((text) => {
|
|
27
|
+
return expect(tooltip).not.toContainText(text, {
|
|
28
|
+
timeout: 2000,
|
|
29
|
+
});
|
|
30
|
+
}),
|
|
31
|
+
);
|
|
32
|
+
|
|
33
|
+
return Promise.all([included, excluded]);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
test('Signature help works for functions', async ({ page, mount }) => {
|
|
37
|
+
const query = 'RETURN abs(';
|
|
38
|
+
|
|
39
|
+
await mount(
|
|
40
|
+
<CypherEditor
|
|
41
|
+
value={query}
|
|
42
|
+
schema={testData.mockSchema}
|
|
43
|
+
autofocus={true}
|
|
44
|
+
/>,
|
|
45
|
+
);
|
|
46
|
+
|
|
47
|
+
await expect(page.locator('.cm-signature-help-panel')).toBeVisible({
|
|
48
|
+
timeout: 2000,
|
|
49
|
+
});
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
test('Signature help works for procedures', async ({ page, mount }) => {
|
|
53
|
+
const query = 'CALL apoc.import.csv(';
|
|
54
|
+
|
|
55
|
+
await mount(
|
|
56
|
+
<CypherEditor
|
|
57
|
+
value={query}
|
|
58
|
+
schema={testData.mockSchema}
|
|
59
|
+
autofocus={true}
|
|
60
|
+
/>,
|
|
61
|
+
);
|
|
62
|
+
|
|
63
|
+
await expect(page.locator('.cm-signature-help-panel')).toBeVisible({
|
|
64
|
+
timeout: 2000,
|
|
65
|
+
});
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
test('Signature help shows the description for the first argument', async ({
|
|
69
|
+
page,
|
|
70
|
+
mount,
|
|
71
|
+
}) => {
|
|
72
|
+
const query = 'CALL apoc.import.csv(';
|
|
73
|
+
|
|
74
|
+
await mount(
|
|
75
|
+
<CypherEditor
|
|
76
|
+
value={query}
|
|
77
|
+
schema={testData.mockSchema}
|
|
78
|
+
autofocus={true}
|
|
79
|
+
/>,
|
|
80
|
+
);
|
|
81
|
+
|
|
82
|
+
const tooltip = page.locator('.cm-signature-help-panel');
|
|
83
|
+
|
|
84
|
+
await testTooltip(tooltip, {
|
|
85
|
+
includes: [
|
|
86
|
+
'nodes :: LIST<MAP>',
|
|
87
|
+
'Imports `NODE` and `RELATIONSHIP` values with the given labels and types from the provided CSV file',
|
|
88
|
+
],
|
|
89
|
+
});
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
test('Signature help shows the description for the first argument when the cursor is at that position', async ({
|
|
93
|
+
page,
|
|
94
|
+
mount,
|
|
95
|
+
}) => {
|
|
96
|
+
const query = 'CALL apoc.import.csv()';
|
|
97
|
+
|
|
98
|
+
await mount(
|
|
99
|
+
<CypherEditor value={query} schema={testData.mockSchema} offset={21} />,
|
|
100
|
+
);
|
|
101
|
+
|
|
102
|
+
const tooltip = page.locator('.cm-signature-help-panel');
|
|
103
|
+
|
|
104
|
+
await testTooltip(tooltip, {
|
|
105
|
+
includes: [
|
|
106
|
+
'nodes :: LIST<MAP>',
|
|
107
|
+
'Imports `NODE` and `RELATIONSHIP` values with the given labels and types from the provided CSV file',
|
|
108
|
+
],
|
|
109
|
+
});
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
test('Signature help shows the description for the second argument', async ({
|
|
113
|
+
page,
|
|
114
|
+
mount,
|
|
115
|
+
}) => {
|
|
116
|
+
const query = 'CALL apoc.import.csv(nodes,';
|
|
117
|
+
|
|
118
|
+
await mount(
|
|
119
|
+
<CypherEditor
|
|
120
|
+
value={query}
|
|
121
|
+
schema={testData.mockSchema}
|
|
122
|
+
autofocus={true}
|
|
123
|
+
/>,
|
|
124
|
+
);
|
|
125
|
+
|
|
126
|
+
const tooltip = page.locator('.cm-signature-help-panel');
|
|
127
|
+
|
|
128
|
+
await testTooltip(tooltip, {
|
|
129
|
+
includes: [
|
|
130
|
+
'rels :: LIST<MAP>',
|
|
131
|
+
'Imports `NODE` and `RELATIONSHIP` values with the given labels and types from the provided CSV file',
|
|
132
|
+
],
|
|
133
|
+
});
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
test('Signature help shows the description for the second argument when the cursor is at that position', async ({
|
|
137
|
+
page,
|
|
138
|
+
mount,
|
|
139
|
+
}) => {
|
|
140
|
+
const query = 'CALL apoc.import.csv(nodes,)';
|
|
141
|
+
|
|
142
|
+
await mount(
|
|
143
|
+
<CypherEditor value={query} schema={testData.mockSchema} offset={27} />,
|
|
144
|
+
);
|
|
145
|
+
|
|
146
|
+
const tooltip = page.locator('.cm-signature-help-panel');
|
|
147
|
+
|
|
148
|
+
await testTooltip(tooltip, {
|
|
149
|
+
includes: [
|
|
150
|
+
'rels :: LIST<MAP>',
|
|
151
|
+
'Imports `NODE` and `RELATIONSHIP` values with the given labels and types from the provided CSV file',
|
|
152
|
+
],
|
|
153
|
+
});
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
test('Signature help shows the description for the second argument when the cursor is at that position, even after whitespaces', async ({
|
|
157
|
+
page,
|
|
158
|
+
mount,
|
|
159
|
+
}) => {
|
|
160
|
+
const query = 'CALL apoc.import.csv(nodes, )';
|
|
161
|
+
|
|
162
|
+
await mount(
|
|
163
|
+
<CypherEditor value={query} schema={testData.mockSchema} offset={28} />,
|
|
164
|
+
);
|
|
165
|
+
|
|
166
|
+
const tooltip = page.locator('.cm-signature-help-panel');
|
|
167
|
+
|
|
168
|
+
await testTooltip(tooltip, {
|
|
169
|
+
includes: [
|
|
170
|
+
'rels :: LIST<MAP>',
|
|
171
|
+
'Imports `NODE` and `RELATIONSHIP` values with the given labels and types from the provided CSV file',
|
|
172
|
+
],
|
|
173
|
+
});
|
|
174
|
+
});
|
|
175
|
+
|
|
176
|
+
test('Signature help shows description for arguments with a space following a separator', async ({
|
|
177
|
+
page,
|
|
178
|
+
mount,
|
|
179
|
+
}) => {
|
|
180
|
+
const query = 'CALL apoc.import.csv(nodes, ';
|
|
181
|
+
|
|
182
|
+
await mount(
|
|
183
|
+
<CypherEditor
|
|
184
|
+
value={query}
|
|
185
|
+
schema={testData.mockSchema}
|
|
186
|
+
autofocus={true}
|
|
187
|
+
/>,
|
|
188
|
+
);
|
|
189
|
+
|
|
190
|
+
const tooltip = page.locator('.cm-signature-help-panel');
|
|
191
|
+
|
|
192
|
+
await testTooltip(tooltip, {
|
|
193
|
+
includes: [
|
|
194
|
+
'rels :: LIST<MAP>',
|
|
195
|
+
'Imports `NODE` and `RELATIONSHIP` values with the given labels and types from the provided CSV file',
|
|
196
|
+
],
|
|
197
|
+
});
|
|
198
|
+
});
|
|
199
|
+
|
|
200
|
+
test('Signature help shows the description for the third argument', async ({
|
|
201
|
+
page,
|
|
202
|
+
mount,
|
|
203
|
+
}) => {
|
|
204
|
+
const query = 'CALL apoc.import.csv(nodes, rels,';
|
|
205
|
+
|
|
206
|
+
await mount(
|
|
207
|
+
<CypherEditor
|
|
208
|
+
value={query}
|
|
209
|
+
schema={testData.mockSchema}
|
|
210
|
+
autofocus={true}
|
|
211
|
+
/>,
|
|
212
|
+
);
|
|
213
|
+
|
|
214
|
+
const tooltip = page.locator('.cm-signature-help-panel');
|
|
215
|
+
|
|
216
|
+
await testTooltip(tooltip, {
|
|
217
|
+
includes: [
|
|
218
|
+
'config :: MAP',
|
|
219
|
+
'Imports `NODE` and `RELATIONSHIP` values with the given labels and types from the provided CSV file',
|
|
220
|
+
],
|
|
221
|
+
});
|
|
222
|
+
});
|
|
223
|
+
|
|
224
|
+
test('Signature help works on multiline queries', async ({ page, mount }) => {
|
|
225
|
+
const query = `CALL apoc.import.csv(
|
|
226
|
+
nodes,
|
|
227
|
+
rels,
|
|
228
|
+
`;
|
|
229
|
+
|
|
230
|
+
await mount(
|
|
231
|
+
<CypherEditor
|
|
232
|
+
value={query}
|
|
233
|
+
schema={testData.mockSchema}
|
|
234
|
+
autofocus={true}
|
|
235
|
+
/>,
|
|
236
|
+
);
|
|
237
|
+
|
|
238
|
+
const tooltip = page.locator('.cm-signature-help-panel');
|
|
239
|
+
|
|
240
|
+
await testTooltip(tooltip, {
|
|
241
|
+
includes: [
|
|
242
|
+
'config :: MAP',
|
|
243
|
+
'Imports `NODE` and `RELATIONSHIP` values with the given labels and types from the provided CSV file',
|
|
244
|
+
],
|
|
245
|
+
});
|
|
246
|
+
});
|
|
247
|
+
|
|
248
|
+
test('Signature help only shows the description past the last argument', async ({
|
|
249
|
+
page,
|
|
250
|
+
mount,
|
|
251
|
+
}) => {
|
|
252
|
+
const query = 'CALL apoc.import.csv(nodes, rels, config,';
|
|
253
|
+
|
|
254
|
+
await mount(
|
|
255
|
+
<CypherEditor
|
|
256
|
+
value={query}
|
|
257
|
+
schema={testData.mockSchema}
|
|
258
|
+
autofocus={true}
|
|
259
|
+
/>,
|
|
260
|
+
);
|
|
261
|
+
1;
|
|
262
|
+
|
|
263
|
+
const tooltip = page.locator('.cm-signature-help-panel');
|
|
264
|
+
|
|
265
|
+
await testTooltip(tooltip, {
|
|
266
|
+
includes: [
|
|
267
|
+
'apoc.import.csv(nodes :: LIST<MAP>, rels :: LIST<MAP>, config :: MAP)',
|
|
268
|
+
'Imports `NODE` and `RELATIONSHIP` values with the given labels and types from the provided CSV file.',
|
|
269
|
+
],
|
|
270
|
+
});
|
|
271
|
+
});
|
|
272
|
+
|
|
273
|
+
test('Signature help does not show any help when method finished', async ({
|
|
274
|
+
page,
|
|
275
|
+
mount,
|
|
276
|
+
}) => {
|
|
277
|
+
const query = 'CALL apoc.import.csv(nodes, rels, config)';
|
|
278
|
+
|
|
279
|
+
await mount(
|
|
280
|
+
<CypherEditor
|
|
281
|
+
value={query}
|
|
282
|
+
schema={testData.mockSchema}
|
|
283
|
+
autofocus={true}
|
|
284
|
+
/>,
|
|
285
|
+
);
|
|
286
|
+
|
|
287
|
+
await expect(page.locator('.cm-signature-help-panel')).not.toBeVisible({
|
|
288
|
+
timeout: 2000,
|
|
289
|
+
});
|
|
290
|
+
});
|
|
291
|
+
|
|
292
|
+
test('Signature help does not blow up on empty query', async ({
|
|
293
|
+
page,
|
|
294
|
+
mount,
|
|
295
|
+
}) => {
|
|
296
|
+
const query = '';
|
|
297
|
+
|
|
298
|
+
await mount(
|
|
299
|
+
<CypherEditor
|
|
300
|
+
value={query}
|
|
301
|
+
schema={testData.mockSchema}
|
|
302
|
+
autofocus={true}
|
|
303
|
+
/>,
|
|
304
|
+
);
|
|
305
|
+
|
|
306
|
+
await expect(page.locator('.cm-signature-help-panel')).not.toBeVisible({
|
|
307
|
+
timeout: 2000,
|
|
308
|
+
});
|
|
309
|
+
});
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import { expect, test } from '@playwright/experimental-ct-react';
|
|
2
|
+
import { CypherEditor } from '../CypherEditor';
|
|
3
|
+
|
|
4
|
+
test.use({ viewport: { width: 500, height: 500 } });
|
|
5
|
+
|
|
6
|
+
test('can complete pattern snippet', async ({ page, mount }) => {
|
|
7
|
+
await mount(<CypherEditor />);
|
|
8
|
+
const textField = page.getByRole('textbox');
|
|
9
|
+
|
|
10
|
+
await textField.fill('MATCH ()-[]->()');
|
|
11
|
+
|
|
12
|
+
await page.locator('.cm-tooltip-autocomplete').getByText('-[]->()').click();
|
|
13
|
+
await expect(page.locator('.cm-tooltip-autocomplete')).not.toBeVisible();
|
|
14
|
+
|
|
15
|
+
await textField.press('Tab');
|
|
16
|
+
await textField.press('Tab');
|
|
17
|
+
|
|
18
|
+
await expect(textField).toHaveText('MATCH ()-[]->()-[ ]->( )');
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
test('can navigate snippet', async ({ page, mount }) => {
|
|
22
|
+
await mount(<CypherEditor />);
|
|
23
|
+
const textField = page.getByRole('textbox');
|
|
24
|
+
|
|
25
|
+
await textField.fill('CREATE INDEX abc FOR ()');
|
|
26
|
+
|
|
27
|
+
await page
|
|
28
|
+
.locator('.cm-tooltip-autocomplete')
|
|
29
|
+
.getByText('-[]-()', { exact: true })
|
|
30
|
+
.click();
|
|
31
|
+
await expect(page.locator('.cm-tooltip-autocomplete')).not.toBeVisible();
|
|
32
|
+
await expect(page.locator('.cm-snippetField')).toHaveCount(2);
|
|
33
|
+
|
|
34
|
+
await textField.press('Tab');
|
|
35
|
+
await textField.press('Shift+Tab');
|
|
36
|
+
|
|
37
|
+
await expect(textField).toHaveText('CREATE INDEX abc FOR ()-[ ]-( )');
|
|
38
|
+
|
|
39
|
+
await textField.press('a');
|
|
40
|
+
await expect(textField).toHaveText('CREATE INDEX abc FOR ()-[a]-( )');
|
|
41
|
+
|
|
42
|
+
await textField.press('Escape');
|
|
43
|
+
await textField.press('Escape');
|
|
44
|
+
await expect(page.locator('.cm-snippetField')).toHaveCount(0);
|
|
45
|
+
await textField.press('Tab');
|
|
46
|
+
await expect(textField).toHaveText('CREATE INDEX abc FOR ()-[a ]-( )');
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
test('can accept completion inside pattern snippet', async ({
|
|
50
|
+
page,
|
|
51
|
+
mount,
|
|
52
|
+
}) => {
|
|
53
|
+
await mount(<CypherEditor schema={{ labels: ['City'] }} />);
|
|
54
|
+
const textField = page.getByRole('textbox');
|
|
55
|
+
|
|
56
|
+
await textField.fill('MATCH ()-[]->()');
|
|
57
|
+
|
|
58
|
+
await page.locator('.cm-tooltip-autocomplete').getByText('-[]->()').click();
|
|
59
|
+
await expect(page.locator('.cm-tooltip-autocomplete')).not.toBeVisible();
|
|
60
|
+
|
|
61
|
+
// move to node
|
|
62
|
+
await textField.press('Tab');
|
|
63
|
+
|
|
64
|
+
// get & accept completion
|
|
65
|
+
await textField.press(':');
|
|
66
|
+
await expect(
|
|
67
|
+
page.locator('.cm-tooltip-autocomplete').getByText('City'),
|
|
68
|
+
).toBeVisible();
|
|
69
|
+
|
|
70
|
+
await textField.press('Tab');
|
|
71
|
+
await expect(page.locator('.cm-tooltip-autocomplete')).not.toBeVisible();
|
|
72
|
+
|
|
73
|
+
// tab out of the snippet
|
|
74
|
+
await textField.press('Tab');
|
|
75
|
+
|
|
76
|
+
await expect(textField).toHaveText('MATCH ()-[]->()-[ ]->(:City)');
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
test('does not automatically open completion panel for expressions after snippet trigger char', async ({
|
|
80
|
+
page,
|
|
81
|
+
mount,
|
|
82
|
+
}) => {
|
|
83
|
+
await mount(<CypherEditor />);
|
|
84
|
+
const textField = page.getByRole('textbox');
|
|
85
|
+
|
|
86
|
+
await textField.fill('RETURN (1)');
|
|
87
|
+
|
|
88
|
+
// expect the panel to not show up
|
|
89
|
+
await expect(page.locator('.cm-tooltip-autocomplete')).not.toBeVisible();
|
|
90
|
+
|
|
91
|
+
// unless manually triggered
|
|
92
|
+
await textField.press('Control+ ');
|
|
93
|
+
await expect(page.locator('.cm-tooltip-autocomplete')).toBeVisible();
|
|
94
|
+
});
|
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
import { expect, test } from '@playwright/experimental-ct-react';
|
|
2
|
+
import { CypherEditor } from '../CypherEditor';
|
|
3
|
+
import { darkThemeConstants, lightThemeConstants } from '../themes';
|
|
4
|
+
import { CypherEditorPage } from './e2eUtils';
|
|
5
|
+
|
|
6
|
+
test.use({ viewport: { width: 500, height: 500 } });
|
|
7
|
+
|
|
8
|
+
test('light theme highlighting', async ({ page, mount }) => {
|
|
9
|
+
const editorPage = new CypherEditorPage(page);
|
|
10
|
+
const query = `
|
|
11
|
+
MATCH (variable :Label)-[:REL_TYPE]->()
|
|
12
|
+
WHERE variable.property = "String"
|
|
13
|
+
OR namespaced.function() = false
|
|
14
|
+
// comment
|
|
15
|
+
OR $parameter > 1234
|
|
16
|
+
RETURN variable;`;
|
|
17
|
+
|
|
18
|
+
await mount(<CypherEditor value={query} theme="light" />);
|
|
19
|
+
|
|
20
|
+
const keywordcolors = await Promise.all(
|
|
21
|
+
['MATCH', 'WHERE', 'RETURN'].map((kw) =>
|
|
22
|
+
editorPage.getHexColorOfLocator(page.getByText(kw)),
|
|
23
|
+
),
|
|
24
|
+
);
|
|
25
|
+
keywordcolors.every((kw) =>
|
|
26
|
+
expect(kw).toEqual(lightThemeConstants.highlightStyles.keyword),
|
|
27
|
+
);
|
|
28
|
+
|
|
29
|
+
const labelReltype = await Promise.all(
|
|
30
|
+
['Label', 'REL_TYPE'].map((kw) =>
|
|
31
|
+
editorPage.getHexColorOfLocator(page.getByText(kw)),
|
|
32
|
+
),
|
|
33
|
+
);
|
|
34
|
+
labelReltype.every((kw) =>
|
|
35
|
+
expect(kw).toEqual(lightThemeConstants.highlightStyles.label),
|
|
36
|
+
);
|
|
37
|
+
|
|
38
|
+
expect(
|
|
39
|
+
await editorPage.getHexColorOfLocator(page.getByText('parameter')),
|
|
40
|
+
).toEqual(lightThemeConstants.highlightStyles.paramValue);
|
|
41
|
+
|
|
42
|
+
expect(
|
|
43
|
+
await editorPage.getHexColorOfLocator(page.getByText('property')),
|
|
44
|
+
).toEqual(lightThemeConstants.highlightStyles.property);
|
|
45
|
+
|
|
46
|
+
expect(
|
|
47
|
+
await editorPage.getHexColorOfLocator(page.getByText('false')),
|
|
48
|
+
).toEqual(lightThemeConstants.highlightStyles.booleanLiteral);
|
|
49
|
+
|
|
50
|
+
expect(
|
|
51
|
+
await editorPage.getHexColorOfLocator(page.getByText('String')),
|
|
52
|
+
).toEqual(lightThemeConstants.highlightStyles.stringLiteral);
|
|
53
|
+
|
|
54
|
+
expect(
|
|
55
|
+
await editorPage.getHexColorOfLocator(page.getByText('comment')),
|
|
56
|
+
).toEqual(lightThemeConstants.highlightStyles.comment);
|
|
57
|
+
|
|
58
|
+
expect(
|
|
59
|
+
await editorPage.getHexColorOfLocator(
|
|
60
|
+
page.getByText('1234', { exact: true }),
|
|
61
|
+
),
|
|
62
|
+
).toEqual(lightThemeConstants.highlightStyles.numberLiteral);
|
|
63
|
+
|
|
64
|
+
expect(await editorPage.editorBackgroundIsUnset()).toEqual(false);
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
test('dark theme highlighting', async ({ page, mount }) => {
|
|
68
|
+
const editorPage = new CypherEditorPage(page);
|
|
69
|
+
const query = `
|
|
70
|
+
MATCH (variable :Label)-[:REL_TYPE]->()
|
|
71
|
+
WHERE variable.property = "String"
|
|
72
|
+
OR namespaced.function() = false
|
|
73
|
+
// comment
|
|
74
|
+
OR $parameter > 1234
|
|
75
|
+
RETURN variable;`;
|
|
76
|
+
|
|
77
|
+
await mount(<CypherEditor value={query} theme="dark" />);
|
|
78
|
+
|
|
79
|
+
const keywordcolors = await Promise.all(
|
|
80
|
+
['MATCH', 'WHERE', 'RETURN'].map((kw) =>
|
|
81
|
+
editorPage.getHexColorOfLocator(page.getByText(kw)),
|
|
82
|
+
),
|
|
83
|
+
);
|
|
84
|
+
keywordcolors.every((kw) =>
|
|
85
|
+
expect(kw).toEqual(darkThemeConstants.highlightStyles.keyword),
|
|
86
|
+
);
|
|
87
|
+
|
|
88
|
+
const labelReltype = await Promise.all(
|
|
89
|
+
['Label', 'REL_TYPE'].map((kw) =>
|
|
90
|
+
editorPage.getHexColorOfLocator(page.getByText(kw)),
|
|
91
|
+
),
|
|
92
|
+
);
|
|
93
|
+
labelReltype.every((kw) =>
|
|
94
|
+
expect(kw).toEqual(darkThemeConstants.highlightStyles.label),
|
|
95
|
+
);
|
|
96
|
+
|
|
97
|
+
expect(
|
|
98
|
+
await editorPage.getHexColorOfLocator(page.getByText('parameter')),
|
|
99
|
+
).toEqual(darkThemeConstants.highlightStyles.paramValue);
|
|
100
|
+
|
|
101
|
+
expect(
|
|
102
|
+
await editorPage.getHexColorOfLocator(page.getByText('property')),
|
|
103
|
+
).toEqual(darkThemeConstants.highlightStyles.property);
|
|
104
|
+
|
|
105
|
+
expect(
|
|
106
|
+
await editorPage.getHexColorOfLocator(page.getByText('false')),
|
|
107
|
+
).toEqual(darkThemeConstants.highlightStyles.booleanLiteral);
|
|
108
|
+
|
|
109
|
+
expect(
|
|
110
|
+
await editorPage.getHexColorOfLocator(page.getByText('String')),
|
|
111
|
+
).toEqual(darkThemeConstants.highlightStyles.stringLiteral);
|
|
112
|
+
|
|
113
|
+
expect(
|
|
114
|
+
await editorPage.getHexColorOfLocator(page.getByText('comment')),
|
|
115
|
+
).toEqual(darkThemeConstants.highlightStyles.comment);
|
|
116
|
+
|
|
117
|
+
expect(
|
|
118
|
+
await editorPage.getHexColorOfLocator(
|
|
119
|
+
page.getByText('1234', { exact: true }),
|
|
120
|
+
),
|
|
121
|
+
).toEqual(darkThemeConstants.highlightStyles.numberLiteral);
|
|
122
|
+
|
|
123
|
+
expect(await editorPage.editorBackgroundIsUnset()).toEqual(false);
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
test('can live switch theme ', async ({ page, mount }) => {
|
|
127
|
+
const editorPage = new CypherEditorPage(page);
|
|
128
|
+
const component = await mount(<CypherEditor theme="light" value="RETURN" />);
|
|
129
|
+
|
|
130
|
+
expect(
|
|
131
|
+
await editorPage.getHexColorOfLocator(
|
|
132
|
+
page.getByText('RETURN', { exact: true }),
|
|
133
|
+
),
|
|
134
|
+
).toEqual(lightThemeConstants.highlightStyles.keyword);
|
|
135
|
+
|
|
136
|
+
await component.update(<CypherEditor theme="dark" value="RETURN" />);
|
|
137
|
+
|
|
138
|
+
expect(
|
|
139
|
+
await editorPage.getHexColorOfLocator(
|
|
140
|
+
page.getByText('RETURN', { exact: true }),
|
|
141
|
+
),
|
|
142
|
+
).toEqual(darkThemeConstants.highlightStyles.keyword);
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
test('respects prop to allow overriding bkg color', async ({ page, mount }) => {
|
|
146
|
+
const editorPage = new CypherEditorPage(page);
|
|
147
|
+
await mount(
|
|
148
|
+
<CypherEditor theme="light" value="text" overrideThemeBackgroundColor />,
|
|
149
|
+
);
|
|
150
|
+
|
|
151
|
+
expect(await editorPage.editorBackgroundIsUnset()).toEqual(true);
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
test('highlights multiline string literal correctly', async ({
|
|
155
|
+
page,
|
|
156
|
+
mount,
|
|
157
|
+
}) => {
|
|
158
|
+
const editorPage = new CypherEditorPage(page);
|
|
159
|
+
const query = `
|
|
160
|
+
RETURN "
|
|
161
|
+
multilinestring";`;
|
|
162
|
+
|
|
163
|
+
await mount(<CypherEditor theme="light" value={query} />);
|
|
164
|
+
|
|
165
|
+
expect(
|
|
166
|
+
await editorPage.getHexColorOfLocator(page.getByText('multilinestring')),
|
|
167
|
+
).toEqual(lightThemeConstants.highlightStyles.stringLiteral);
|
|
168
|
+
});
|
|
169
|
+
|
|
170
|
+
test('highlights multiline label correctly', async ({ page, mount }) => {
|
|
171
|
+
const editorPage = new CypherEditorPage(page);
|
|
172
|
+
const query = `
|
|
173
|
+
MATCH (v:\`
|
|
174
|
+
|
|
175
|
+
Label\`)
|
|
176
|
+
`;
|
|
177
|
+
|
|
178
|
+
await mount(<CypherEditor theme="light" value={query} />);
|
|
179
|
+
|
|
180
|
+
expect(
|
|
181
|
+
await editorPage.getHexColorOfLocator(page.getByText('Label')),
|
|
182
|
+
).toEqual(lightThemeConstants.highlightStyles.label);
|
|
183
|
+
});
|
|
184
|
+
|
|
185
|
+
test('highlights multiline comment correctly', async ({ page, mount }) => {
|
|
186
|
+
const editorPage = new CypherEditorPage(page);
|
|
187
|
+
const query = `
|
|
188
|
+
/*
|
|
189
|
+
|
|
190
|
+
comment
|
|
191
|
+
*/";`;
|
|
192
|
+
|
|
193
|
+
await mount(<CypherEditor theme="light" value={query} />);
|
|
194
|
+
|
|
195
|
+
expect(
|
|
196
|
+
await editorPage.getHexColorOfLocator(page.getByText('comment')),
|
|
197
|
+
).toEqual(lightThemeConstants.highlightStyles.comment);
|
|
198
|
+
});
|