@neo4j-cypher/react-codemirror 2.0.0-next.3 → 2.0.0-next.30

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.
Files changed (163) hide show
  1. package/CHANGELOG.md +257 -0
  2. package/README.md +3 -2
  3. package/dist/{types → src}/CypherEditor.d.ts +81 -3
  4. package/dist/src/CypherEditor.js +336 -0
  5. package/dist/src/CypherEditor.js.map +1 -0
  6. package/dist/src/CypherEditor.test.js +154 -0
  7. package/dist/src/CypherEditor.test.js.map +1 -0
  8. package/dist/src/constants.d.ts +1 -0
  9. package/dist/src/constants.js +2 -0
  10. package/dist/src/constants.js.map +1 -0
  11. package/dist/src/e2e_tests/autoCompletion.spec.js +332 -0
  12. package/dist/src/e2e_tests/autoCompletion.spec.js.map +1 -0
  13. package/dist/src/e2e_tests/configuration.spec.js +83 -0
  14. package/dist/src/e2e_tests/configuration.spec.js.map +1 -0
  15. package/dist/src/e2e_tests/debounce.spec.js +66 -0
  16. package/dist/src/e2e_tests/debounce.spec.js.map +1 -0
  17. package/dist/{types/e2e_tests/e2e-utils.d.ts → src/e2e_tests/e2eUtils.d.ts} +2 -0
  18. package/dist/src/e2e_tests/e2eUtils.js +79 -0
  19. package/dist/src/e2e_tests/e2eUtils.js.map +1 -0
  20. package/dist/src/e2e_tests/extraKeybindings.spec.js +43 -0
  21. package/dist/src/e2e_tests/extraKeybindings.spec.js.map +1 -0
  22. package/dist/src/e2e_tests/historyNavigation.spec.js +227 -0
  23. package/dist/src/e2e_tests/historyNavigation.spec.js.map +1 -0
  24. package/dist/src/e2e_tests/performanceTest.spec.d.ts +6 -0
  25. package/dist/src/e2e_tests/performanceTest.spec.js +97 -0
  26. package/dist/src/e2e_tests/performanceTest.spec.js.map +1 -0
  27. package/dist/src/e2e_tests/sanityChecks.spec.js +53 -0
  28. package/dist/src/e2e_tests/sanityChecks.spec.js.map +1 -0
  29. package/dist/src/e2e_tests/signatureHelp.spec.js +228 -0
  30. package/dist/src/e2e_tests/signatureHelp.spec.js.map +1 -0
  31. package/dist/src/e2e_tests/snippets.spec.js +62 -0
  32. package/dist/src/e2e_tests/snippets.spec.js.map +1 -0
  33. package/dist/src/e2e_tests/syntaxHighlighting.spec.d.ts +1 -0
  34. package/dist/src/e2e_tests/syntaxHighlighting.spec.js +90 -0
  35. package/dist/src/e2e_tests/syntaxHighlighting.spec.js.map +1 -0
  36. package/dist/src/e2e_tests/syntaxValidation.spec.d.ts +1 -0
  37. package/dist/src/e2e_tests/syntaxValidation.spec.js +126 -0
  38. package/dist/src/e2e_tests/syntaxValidation.spec.js.map +1 -0
  39. package/dist/src/historyNavigation.js +163 -0
  40. package/dist/src/historyNavigation.js.map +1 -0
  41. package/dist/{types → src}/icons.d.ts +1 -1
  42. package/dist/src/icons.js +62 -0
  43. package/dist/src/icons.js.map +1 -0
  44. package/dist/src/index.d.ts +4 -0
  45. package/dist/src/index.js +5 -0
  46. package/dist/src/index.js.map +1 -0
  47. package/dist/src/lang-cypher/autocomplete.d.ts +6 -0
  48. package/dist/src/lang-cypher/autocomplete.js +113 -0
  49. package/dist/src/lang-cypher/autocomplete.js.map +1 -0
  50. package/dist/{types → src}/lang-cypher/constants.d.ts +11 -0
  51. package/dist/src/lang-cypher/constants.js +69 -0
  52. package/dist/src/lang-cypher/constants.js.map +1 -0
  53. package/dist/src/lang-cypher/contants.test.d.ts +1 -0
  54. package/dist/src/lang-cypher/contants.test.js +103 -0
  55. package/dist/src/lang-cypher/contants.test.js.map +1 -0
  56. package/dist/src/lang-cypher/createCypherTheme.js +183 -0
  57. package/dist/src/lang-cypher/createCypherTheme.js.map +1 -0
  58. package/dist/src/lang-cypher/langCypher.d.ts +13 -0
  59. package/dist/src/lang-cypher/langCypher.js +23 -0
  60. package/dist/src/lang-cypher/langCypher.js.map +1 -0
  61. package/dist/src/lang-cypher/lintWorker.mjs +2022 -0
  62. package/dist/src/lang-cypher/parser-adapter.d.ts +19 -0
  63. package/dist/src/lang-cypher/parser-adapter.js +113 -0
  64. package/dist/src/lang-cypher/parser-adapter.js.map +1 -0
  65. package/dist/src/lang-cypher/signatureHelp.d.ts +4 -0
  66. package/dist/src/lang-cypher/signatureHelp.js +109 -0
  67. package/dist/src/lang-cypher/signatureHelp.js.map +1 -0
  68. package/dist/{types/lang-cypher/syntax-validation.d.ts → src/lang-cypher/syntaxValidation.d.ts} +2 -1
  69. package/dist/src/lang-cypher/syntaxValidation.js +57 -0
  70. package/dist/src/lang-cypher/syntaxValidation.js.map +1 -0
  71. package/dist/src/lang-cypher/themeIcons.js +22 -0
  72. package/dist/src/lang-cypher/themeIcons.js.map +1 -0
  73. package/dist/src/lang-cypher/utils.d.ts +2 -0
  74. package/dist/src/lang-cypher/utils.js +10 -0
  75. package/dist/src/lang-cypher/utils.js.map +1 -0
  76. package/dist/src/ndlTokensCopy.d.ts +570 -0
  77. package/dist/src/ndlTokensCopy.js +571 -0
  78. package/dist/src/ndlTokensCopy.js.map +1 -0
  79. package/dist/src/ndlTokensCopy.test.d.ts +1 -0
  80. package/dist/src/ndlTokensCopy.test.js +12 -0
  81. package/dist/src/ndlTokensCopy.test.js.map +1 -0
  82. package/dist/src/neo4jSetup.d.ts +6 -0
  83. package/dist/src/neo4jSetup.js +120 -0
  84. package/dist/src/neo4jSetup.js.map +1 -0
  85. package/dist/src/richClipboardCopier.d.ts +4 -0
  86. package/dist/src/richClipboardCopier.js +78 -0
  87. package/dist/src/richClipboardCopier.js.map +1 -0
  88. package/dist/src/richClipboardCopier.test.d.ts +1 -0
  89. package/dist/src/richClipboardCopier.test.js +53 -0
  90. package/dist/src/richClipboardCopier.test.js.map +1 -0
  91. package/dist/{types → src}/themes.d.ts +1 -1
  92. package/dist/src/themes.js +93 -0
  93. package/dist/src/themes.js.map +1 -0
  94. package/dist/tsconfig.tsbuildinfo +1 -0
  95. package/package.json +43 -41
  96. package/src/CypherEditor.test.tsx +204 -0
  97. package/src/CypherEditor.tsx +316 -42
  98. package/src/constants.ts +1 -0
  99. package/src/e2e_tests/autoCompletion.spec.tsx +571 -0
  100. package/src/e2e_tests/configuration.spec.tsx +111 -0
  101. package/src/e2e_tests/debounce.spec.tsx +106 -0
  102. package/src/e2e_tests/{e2e-utils.ts → e2eUtils.ts} +41 -3
  103. package/src/e2e_tests/{extra-keybindings.spec.tsx → extraKeybindings.spec.tsx} +1 -3
  104. package/src/e2e_tests/{history-navigation.spec.tsx → historyNavigation.spec.tsx} +137 -18
  105. package/src/e2e_tests/performanceTest.spec.tsx +163 -0
  106. package/src/e2e_tests/{sanity-checks.spec.tsx → sanityChecks.spec.tsx} +7 -22
  107. package/src/e2e_tests/signatureHelp.spec.tsx +444 -0
  108. package/src/e2e_tests/snippets.spec.tsx +92 -0
  109. package/src/e2e_tests/{syntax-highlighting.spec.tsx → syntaxHighlighting.spec.tsx} +26 -24
  110. package/src/e2e_tests/syntaxValidation.spec.tsx +259 -0
  111. package/src/{history-navigation.ts → historyNavigation.ts} +1 -1
  112. package/src/icons.ts +3 -0
  113. package/src/index.ts +2 -2
  114. package/src/lang-cypher/autocomplete.ts +99 -18
  115. package/src/lang-cypher/constants.ts +27 -0
  116. package/src/lang-cypher/contants.test.ts +6 -2
  117. package/src/lang-cypher/{create-cypher-theme.ts → createCypherTheme.ts} +45 -2
  118. package/src/lang-cypher/langCypher.ts +42 -0
  119. package/src/lang-cypher/lintWorker.mjs +2022 -0
  120. package/src/lang-cypher/parser-adapter.ts +145 -0
  121. package/src/lang-cypher/signatureHelp.ts +151 -0
  122. package/src/lang-cypher/syntaxValidation.ts +72 -0
  123. package/src/lang-cypher/utils.ts +9 -0
  124. package/src/{ndl-tokens-copy.test.ts → ndlTokensCopy.test.ts} +2 -1
  125. package/src/ndlTokensCopy.ts +570 -0
  126. package/src/{neo4j-setup.tsx → neo4jSetup.tsx} +78 -17
  127. package/src/richClipboardCopier.test.ts +65 -0
  128. package/src/richClipboardCopier.ts +99 -0
  129. package/src/themes.ts +45 -70
  130. package/src/viteEnv.d.ts +1 -0
  131. package/dist/cjs/index.cjs +0 -1440
  132. package/dist/cjs/index.cjs.map +0 -7
  133. package/dist/esm/index.mjs +0 -1463
  134. package/dist/esm/index.mjs.map +0 -7
  135. package/dist/types/e2e_tests/mock-data.d.ts +0 -3779
  136. package/dist/types/index.d.ts +0 -4
  137. package/dist/types/lang-cypher/ParserAdapter.d.ts +0 -14
  138. package/dist/types/lang-cypher/autocomplete.d.ts +0 -3
  139. package/dist/types/lang-cypher/lang-cypher.d.ts +0 -7
  140. package/dist/types/ndl-tokens-copy.d.ts +0 -379
  141. package/dist/types/neo4j-setup.d.ts +0 -2
  142. package/dist/types/tsconfig.tsbuildinfo +0 -1
  143. package/src/e2e_tests/auto-completion.spec.tsx +0 -232
  144. package/src/e2e_tests/mock-data.ts +0 -4310
  145. package/src/e2e_tests/performance-test.spec.tsx +0 -71
  146. package/src/e2e_tests/syntax-validation.spec.tsx +0 -156
  147. package/src/lang-cypher/ParserAdapter.ts +0 -92
  148. package/src/lang-cypher/lang-cypher.ts +0 -32
  149. package/src/lang-cypher/syntax-validation.ts +0 -24
  150. package/src/ndl-tokens-copy.ts +0 -379
  151. /package/dist/{types/e2e_tests/auto-completion.spec.d.ts → src/CypherEditor.test.d.ts} +0 -0
  152. /package/dist/{types/e2e_tests/extra-keybindings.spec.d.ts → src/e2e_tests/autoCompletion.spec.d.ts} +0 -0
  153. /package/dist/{types/e2e_tests/history-navigation.spec.d.ts → src/e2e_tests/configuration.spec.d.ts} +0 -0
  154. /package/dist/{types/e2e_tests/performance-test.spec.d.ts → src/e2e_tests/debounce.spec.d.ts} +0 -0
  155. /package/dist/{types/e2e_tests/sanity-checks.spec.d.ts → src/e2e_tests/extraKeybindings.spec.d.ts} +0 -0
  156. /package/dist/{types/e2e_tests/syntax-highlighting.spec.d.ts → src/e2e_tests/historyNavigation.spec.d.ts} +0 -0
  157. /package/dist/{types/e2e_tests/syntax-validation.spec.d.ts → src/e2e_tests/sanityChecks.spec.d.ts} +0 -0
  158. /package/dist/{types/lang-cypher/contants.test.d.ts → src/e2e_tests/signatureHelp.spec.d.ts} +0 -0
  159. /package/dist/{types/ndl-tokens-copy.test.d.ts → src/e2e_tests/snippets.spec.d.ts} +0 -0
  160. /package/dist/{types/history-navigation.d.ts → src/historyNavigation.d.ts} +0 -0
  161. /package/dist/{types/lang-cypher/create-cypher-theme.d.ts → src/lang-cypher/createCypherTheme.d.ts} +0 -0
  162. /package/dist/{types/lang-cypher/theme-icons.d.ts → src/lang-cypher/themeIcons.d.ts} +0 -0
  163. /package/src/lang-cypher/{theme-icons.ts → themeIcons.ts} +0 -0
@@ -0,0 +1,444 @@
1
+ /* eslint-disable @typescript-eslint/unbound-method */
2
+ import { testData } from '@neo4j-cypher/language-support';
3
+ import { expect, test } from '@playwright/experimental-ct-react';
4
+ import { Locator } from 'playwright/test';
5
+ import { CypherEditor } from '../CypherEditor';
6
+
7
+ test.use({ viewport: { width: 1000, height: 500 } });
8
+
9
+ type TooltipExpectations = {
10
+ includes?: string[];
11
+ excludes?: string[];
12
+ };
13
+
14
+ const importCsvProc =
15
+ testData.mockSchema.procedures['CYPHER 5']['apoc.import.csv'];
16
+
17
+ function testTooltip(tooltip: Locator, expectations: TooltipExpectations) {
18
+ const includes = expectations.includes ?? [];
19
+ const excludes = expectations.excludes ?? [];
20
+
21
+ const included = Promise.all(
22
+ includes.map((text) => {
23
+ return expect(tooltip).toContainText(text, {
24
+ timeout: 10000,
25
+ });
26
+ }),
27
+ );
28
+
29
+ const excluded = Promise.all(
30
+ excludes.map((text) => {
31
+ return expect(tooltip).not.toContainText(text, {
32
+ timeout: 10000,
33
+ });
34
+ }),
35
+ );
36
+
37
+ return Promise.all([included, excluded]);
38
+ }
39
+
40
+ test('Signature help works for functions', async ({ page, mount }) => {
41
+ const query = 'RETURN abs(';
42
+
43
+ await mount(
44
+ <CypherEditor
45
+ value={query}
46
+ schema={testData.mockSchema}
47
+ autofocus={true}
48
+ />,
49
+ );
50
+
51
+ await expect(page.locator('.cm-signature-help-panel')).toBeVisible({
52
+ timeout: 10000,
53
+ });
54
+ });
55
+
56
+ test('Signature help works for procedures', async ({ page, mount }) => {
57
+ const query = 'CALL apoc.import.csv(';
58
+
59
+ await mount(
60
+ <CypherEditor
61
+ value={query}
62
+ schema={testData.mockSchema}
63
+ autofocus={true}
64
+ />,
65
+ );
66
+
67
+ await expect(page.locator('.cm-signature-help-panel')).toBeVisible({
68
+ timeout: 10000,
69
+ });
70
+ });
71
+
72
+ test('Signature help shows the description for the first argument', async ({
73
+ page,
74
+ mount,
75
+ }) => {
76
+ const query = 'CALL apoc.import.csv(';
77
+
78
+ await mount(
79
+ <CypherEditor
80
+ value={query}
81
+ schema={testData.mockSchema}
82
+ autofocus={true}
83
+ />,
84
+ );
85
+
86
+ const tooltip = page.locator('.cm-signature-help-panel');
87
+
88
+ await testTooltip(tooltip, {
89
+ includes: [
90
+ testData.mockSchema.procedures['CYPHER 5']['apoc.import.csv']
91
+ .argumentDescription[0].description,
92
+ testData.mockSchema.procedures['CYPHER 5']['apoc.import.csv'].description,
93
+ ],
94
+ });
95
+ });
96
+
97
+ test('Signature help shows the description for the first argument when the cursor is at that position', async ({
98
+ page,
99
+ mount,
100
+ }) => {
101
+ const query = 'CALL apoc.import.csv()';
102
+
103
+ await mount(
104
+ <CypherEditor value={query} schema={testData.mockSchema} offset={21} />,
105
+ );
106
+
107
+ const tooltip = page.locator('.cm-signature-help-panel');
108
+
109
+ await testTooltip(tooltip, {
110
+ includes: [
111
+ importCsvProc.argumentDescription[0].description,
112
+ importCsvProc.description,
113
+ ],
114
+ });
115
+ });
116
+
117
+ test('Signature help shows the description for the second argument', async ({
118
+ page,
119
+ mount,
120
+ }) => {
121
+ const query = 'CALL apoc.import.csv(nodes,';
122
+
123
+ await mount(
124
+ <CypherEditor
125
+ value={query}
126
+ schema={testData.mockSchema}
127
+ autofocus={true}
128
+ />,
129
+ );
130
+
131
+ const tooltip = page.locator('.cm-signature-help-panel');
132
+
133
+ await testTooltip(tooltip, {
134
+ includes: [
135
+ importCsvProc.argumentDescription[1].description,
136
+ importCsvProc.description,
137
+ ],
138
+ });
139
+ });
140
+
141
+ test('Signature help shows the description for the second argument when the cursor is at that position', async ({
142
+ page,
143
+ mount,
144
+ }) => {
145
+ const query = 'CALL apoc.import.csv(nodes,)';
146
+
147
+ await mount(
148
+ <CypherEditor value={query} schema={testData.mockSchema} offset={27} />,
149
+ );
150
+
151
+ const tooltip = page.locator('.cm-signature-help-panel');
152
+
153
+ await testTooltip(tooltip, {
154
+ includes: [
155
+ importCsvProc.argumentDescription[1].description,
156
+ importCsvProc.description,
157
+ ],
158
+ });
159
+ });
160
+
161
+ test('Signature help shows the description for the second argument when the cursor is at that position, even after whitespaces', async ({
162
+ page,
163
+ mount,
164
+ }) => {
165
+ const query = 'CALL apoc.import.csv(nodes, )';
166
+
167
+ await mount(
168
+ <CypherEditor value={query} schema={testData.mockSchema} offset={28} />,
169
+ );
170
+
171
+ const tooltip = page.locator('.cm-signature-help-panel');
172
+
173
+ await testTooltip(tooltip, {
174
+ includes: [
175
+ 'rels :: LIST<MAP>',
176
+ 'Imports `NODE` and `RELATIONSHIP` values with the given labels and types from the provided CSV file',
177
+ ],
178
+ });
179
+ });
180
+
181
+ test('Signature help shows description for arguments with a space following a separator', async ({
182
+ page,
183
+ mount,
184
+ }) => {
185
+ const query = 'CALL apoc.import.csv(nodes, ';
186
+
187
+ await mount(
188
+ <CypherEditor
189
+ value={query}
190
+ schema={testData.mockSchema}
191
+ autofocus={true}
192
+ />,
193
+ );
194
+
195
+ const tooltip = page.locator('.cm-signature-help-panel');
196
+
197
+ await testTooltip(tooltip, {
198
+ includes: [
199
+ 'rels :: LIST<MAP>',
200
+ 'Imports `NODE` and `RELATIONSHIP` values with the given labels and types from the provided CSV file',
201
+ ],
202
+ });
203
+ });
204
+
205
+ test('Signature help shows the description for the third argument', async ({
206
+ page,
207
+ mount,
208
+ }) => {
209
+ const query = 'CALL apoc.import.csv(nodes, rels,';
210
+
211
+ await mount(
212
+ <CypherEditor
213
+ value={query}
214
+ schema={testData.mockSchema}
215
+ autofocus={true}
216
+ />,
217
+ );
218
+
219
+ const tooltip = page.locator('.cm-signature-help-panel');
220
+
221
+ await testTooltip(tooltip, {
222
+ includes: [
223
+ 'config :: MAP',
224
+ 'Imports `NODE` and `RELATIONSHIP` values with the given labels and types from the provided CSV file',
225
+ ],
226
+ });
227
+ });
228
+
229
+ test('Signature help works on multiline queries', async ({ page, mount }) => {
230
+ const query = `CALL apoc.import.csv(
231
+ nodes,
232
+ rels,
233
+ `;
234
+
235
+ await mount(
236
+ <CypherEditor
237
+ value={query}
238
+ schema={testData.mockSchema}
239
+ autofocus={true}
240
+ />,
241
+ );
242
+
243
+ const tooltip = page.locator('.cm-signature-help-panel');
244
+
245
+ await testTooltip(tooltip, {
246
+ includes: [
247
+ 'config :: MAP',
248
+ 'Imports `NODE` and `RELATIONSHIP` values with the given labels and types from the provided CSV file',
249
+ ],
250
+ });
251
+ });
252
+
253
+ test('Signature help only shows the description past the last argument', async ({
254
+ page,
255
+ mount,
256
+ }) => {
257
+ const query = 'CALL apoc.import.csv(nodes, rels, config,';
258
+
259
+ await mount(
260
+ <CypherEditor
261
+ value={query}
262
+ schema={testData.mockSchema}
263
+ autofocus={true}
264
+ />,
265
+ );
266
+ 1;
267
+
268
+ const tooltip = page.locator('.cm-signature-help-panel');
269
+
270
+ await testTooltip(tooltip, {
271
+ includes: [
272
+ 'apoc.import.csv(nodes :: LIST<MAP>, rels :: LIST<MAP>, config :: MAP)',
273
+ 'Imports `NODE` and `RELATIONSHIP` values with the given labels and types from the provided CSV file.',
274
+ ],
275
+ });
276
+ });
277
+
278
+ test('Signature help does not show any help when method finished', async ({
279
+ page,
280
+ mount,
281
+ }) => {
282
+ const query = 'CALL apoc.import.csv(nodes, rels, config)';
283
+
284
+ await mount(
285
+ <CypherEditor
286
+ value={query}
287
+ schema={testData.mockSchema}
288
+ autofocus={true}
289
+ />,
290
+ );
291
+
292
+ await expect(page.locator('.cm-signature-help-panel')).not.toBeVisible({
293
+ timeout: 10000,
294
+ });
295
+ });
296
+
297
+ test('Signature help does not blow up on empty query', async ({
298
+ page,
299
+ mount,
300
+ }) => {
301
+ const query = '';
302
+
303
+ await mount(
304
+ <CypherEditor
305
+ value={query}
306
+ schema={testData.mockSchema}
307
+ autofocus={true}
308
+ />,
309
+ );
310
+
311
+ await expect(page.locator('.cm-signature-help-panel')).not.toBeVisible({
312
+ timeout: 10000,
313
+ });
314
+ });
315
+
316
+ test('Signature help is shown below the text by default', async ({
317
+ page,
318
+ mount,
319
+ }) => {
320
+ // We need to introduce new lines to make sure there's
321
+ // enough space to show the tooltip above
322
+ const query = '\n\n\n\n\n\n\nRETURN abs(';
323
+
324
+ await mount(
325
+ <CypherEditor
326
+ value={query}
327
+ schema={testData.mockSchema}
328
+ autofocus={true}
329
+ />,
330
+ );
331
+
332
+ await expect(
333
+ page.locator('.cm-signature-help-panel.cm-tooltip-below'),
334
+ ).toBeVisible({
335
+ timeout: 10000,
336
+ });
337
+ });
338
+
339
+ test('Setting showSignatureTooltipBelow to true shows the signature help above the text', async ({
340
+ page,
341
+ mount,
342
+ }) => {
343
+ // We need to introduce new lines to make sure there's
344
+ // enough space to show the tooltip above
345
+ const query = '\n\n\n\n\n\n\nRETURN abs(';
346
+
347
+ await mount(
348
+ <CypherEditor
349
+ value={query}
350
+ schema={testData.mockSchema}
351
+ showSignatureTooltipBelow={true}
352
+ autofocus={true}
353
+ />,
354
+ );
355
+
356
+ await expect(
357
+ page.locator('.cm-signature-help-panel.cm-tooltip-below'),
358
+ ).toBeVisible({
359
+ timeout: 10000,
360
+ });
361
+ });
362
+
363
+ test('Setting showSignatureTooltipBelow to false shows the signature help above the text', async ({
364
+ page,
365
+ mount,
366
+ }) => {
367
+ // We need to introduce new lines to make sure there's
368
+ // enough space to show the tooltip above
369
+ const query = '\n\n\n\n\n\n\nRETURN abs(';
370
+
371
+ await mount(
372
+ <CypherEditor
373
+ value={query}
374
+ schema={testData.mockSchema}
375
+ showSignatureTooltipBelow={false}
376
+ autofocus={true}
377
+ />,
378
+ );
379
+
380
+ await expect(
381
+ page.locator('.cm-signature-help-panel.cm-tooltip-above'),
382
+ ).toBeVisible({
383
+ timeout: 10000,
384
+ });
385
+ });
386
+
387
+ test('Signature help depends on the Cypher version', async ({
388
+ page,
389
+ mount,
390
+ }) => {
391
+ const cypher5ArgDescription = 'The Cypher 5 statement to run.';
392
+ const cypher25ArgDescription = 'The Cypher 25 statement to run.';
393
+
394
+ await mount(
395
+ <CypherEditor
396
+ schema={{
397
+ functions: {
398
+ 'CYPHER 5': {
399
+ cypher5Function: {
400
+ ...testData.emptyFunction,
401
+ argumentDescription: [
402
+ {
403
+ isDeprecated: false,
404
+ description: cypher5ArgDescription,
405
+ name: 'statement',
406
+ type: 'STRING',
407
+ },
408
+ ],
409
+ name: 'cypher5Function',
410
+ },
411
+ },
412
+ 'CYPHER 25': {
413
+ cypher25Function: {
414
+ ...testData.emptyFunction,
415
+ argumentDescription: [
416
+ {
417
+ isDeprecated: false,
418
+ description: cypher25ArgDescription,
419
+ name: 'statement',
420
+ type: 'STRING',
421
+ },
422
+ ],
423
+ name: 'cypher25Function',
424
+ },
425
+ },
426
+ },
427
+ }}
428
+ />,
429
+ );
430
+
431
+ const textField = page.getByRole('textbox');
432
+ await textField.fill('CYPHER 5 RETURN cypher5Function(');
433
+ const tooltip = page.locator('.cm-signature-help-panel');
434
+
435
+ await testTooltip(tooltip, {
436
+ includes: [cypher5ArgDescription],
437
+ });
438
+
439
+ await textField.fill('CYPHER 25 RETURN cypher25Function(');
440
+
441
+ await testTooltip(tooltip, {
442
+ includes: [cypher25ArgDescription],
443
+ });
444
+ });
@@ -0,0 +1,92 @@
1
+ import { expect, test } from '@playwright/experimental-ct-react';
2
+ import { CypherEditor } from '../CypherEditor';
3
+
4
+ test('can complete pattern snippet', async ({ page, mount }) => {
5
+ await mount(<CypherEditor />);
6
+ const textField = page.getByRole('textbox');
7
+
8
+ await textField.fill('MATCH ()-[]->()');
9
+
10
+ await page.locator('.cm-tooltip-autocomplete').getByText('-[]->()').click();
11
+ await expect(page.locator('.cm-tooltip-autocomplete')).not.toBeVisible();
12
+
13
+ await textField.press('Tab');
14
+ await textField.press('Tab');
15
+
16
+ await expect(textField).toHaveText('MATCH ()-[]->()-[ ]->( )');
17
+ });
18
+
19
+ test('can navigate snippet', async ({ page, mount }) => {
20
+ await mount(<CypherEditor />);
21
+ const textField = page.getByRole('textbox');
22
+
23
+ await textField.fill('CREATE INDEX abc FOR ()');
24
+
25
+ await page
26
+ .locator('.cm-tooltip-autocomplete')
27
+ .getByText('-[]-()', { exact: true })
28
+ .click();
29
+ await expect(page.locator('.cm-tooltip-autocomplete')).not.toBeVisible();
30
+ await expect(page.locator('.cm-snippetField')).toHaveCount(2);
31
+
32
+ await textField.press('Tab');
33
+ await textField.press('Shift+Tab');
34
+
35
+ await expect(textField).toHaveText('CREATE INDEX abc FOR ()-[ ]-( )');
36
+
37
+ await textField.press('a');
38
+ await expect(textField).toHaveText('CREATE INDEX abc FOR ()-[a]-( )');
39
+
40
+ await textField.press('Escape');
41
+ await textField.press('Escape');
42
+ await expect(page.locator('.cm-snippetField')).toHaveCount(0);
43
+ await textField.press('Tab');
44
+ await expect(textField).toHaveText('CREATE INDEX abc FOR ()-[a ]-( )');
45
+ });
46
+
47
+ test('can accept completion inside pattern snippet', async ({
48
+ page,
49
+ mount,
50
+ }) => {
51
+ await mount(<CypherEditor schema={{ labels: ['City'] }} />);
52
+ const textField = page.getByRole('textbox');
53
+
54
+ await textField.fill('MATCH ()-[]->()');
55
+
56
+ await page.locator('.cm-tooltip-autocomplete').getByText('-[]->()').click();
57
+ await expect(page.locator('.cm-tooltip-autocomplete')).not.toBeVisible();
58
+
59
+ // move to node
60
+ await textField.press('Tab');
61
+
62
+ // get & accept completion
63
+ await textField.press(':');
64
+ await expect(
65
+ page.locator('.cm-tooltip-autocomplete').getByText('City'),
66
+ ).toBeVisible();
67
+
68
+ await textField.press('Tab', { delay: 300 });
69
+ await expect(page.locator('.cm-tooltip-autocomplete')).not.toBeVisible();
70
+
71
+ // tab out of the snippet
72
+ await textField.press('Tab', { delay: 300 });
73
+
74
+ await expect(textField).toHaveText('MATCH ()-[]->()-[ ]->(:City)');
75
+ });
76
+
77
+ test('does not automatically open completion panel for expressions after snippet trigger char', async ({
78
+ page,
79
+ mount,
80
+ }) => {
81
+ await mount(<CypherEditor />);
82
+ const textField = page.getByRole('textbox');
83
+
84
+ await textField.fill('RETURN (1)');
85
+
86
+ // expect the panel to not show up
87
+ await expect(page.locator('.cm-tooltip-autocomplete')).not.toBeVisible();
88
+
89
+ // unless manually triggered
90
+ await textField.press('Control+ ');
91
+ await expect(page.locator('.cm-tooltip-autocomplete')).toBeVisible();
92
+ });
@@ -1,9 +1,7 @@
1
1
  import { expect, test } from '@playwright/experimental-ct-react';
2
2
  import { CypherEditor } from '../CypherEditor';
3
3
  import { darkThemeConstants, lightThemeConstants } from '../themes';
4
- import { CypherEditorPage } from './e2e-utils';
5
-
6
- test.use({ viewport: { width: 500, height: 500 } });
4
+ import { CypherEditorPage } from './e2eUtils';
7
5
 
8
6
  test('light theme highlighting', async ({ page, mount }) => {
9
7
  const editorPage = new CypherEditorPage(page);
@@ -23,7 +21,9 @@ RETURN variable;`;
23
21
  ),
24
22
  );
25
23
  keywordcolors.every((kw) =>
26
- expect(kw).toEqual(lightThemeConstants.highlightStyles.keyword),
24
+ expect(kw).toEqual(
25
+ lightThemeConstants.highlightStyles.keyword.toLowerCase(),
26
+ ),
27
27
  );
28
28
 
29
29
  const labelReltype = await Promise.all(
@@ -32,34 +32,34 @@ RETURN variable;`;
32
32
  ),
33
33
  );
34
34
  labelReltype.every((kw) =>
35
- expect(kw).toEqual(lightThemeConstants.highlightStyles.label),
35
+ expect(kw).toEqual(lightThemeConstants.highlightStyles.label.toLowerCase()),
36
36
  );
37
37
 
38
38
  expect(
39
39
  await editorPage.getHexColorOfLocator(page.getByText('parameter')),
40
- ).toEqual(lightThemeConstants.highlightStyles.paramValue);
40
+ ).toEqual(lightThemeConstants.highlightStyles.paramValue.toLowerCase());
41
41
 
42
42
  expect(
43
43
  await editorPage.getHexColorOfLocator(page.getByText('property')),
44
- ).toEqual(lightThemeConstants.highlightStyles.property);
44
+ ).toEqual(lightThemeConstants.highlightStyles.property.toLowerCase());
45
45
 
46
46
  expect(
47
47
  await editorPage.getHexColorOfLocator(page.getByText('false')),
48
- ).toEqual(lightThemeConstants.highlightStyles.booleanLiteral);
48
+ ).toEqual(lightThemeConstants.highlightStyles.booleanLiteral.toLowerCase());
49
49
 
50
50
  expect(
51
51
  await editorPage.getHexColorOfLocator(page.getByText('String')),
52
- ).toEqual(lightThemeConstants.highlightStyles.stringLiteral);
52
+ ).toEqual(lightThemeConstants.highlightStyles.stringLiteral.toLowerCase());
53
53
 
54
54
  expect(
55
55
  await editorPage.getHexColorOfLocator(page.getByText('comment')),
56
- ).toEqual(lightThemeConstants.highlightStyles.comment);
56
+ ).toEqual(lightThemeConstants.highlightStyles.comment.toLowerCase());
57
57
 
58
58
  expect(
59
59
  await editorPage.getHexColorOfLocator(
60
60
  page.getByText('1234', { exact: true }),
61
61
  ),
62
- ).toEqual(lightThemeConstants.highlightStyles.numberLiteral);
62
+ ).toEqual(lightThemeConstants.highlightStyles.numberLiteral.toLowerCase());
63
63
 
64
64
  expect(await editorPage.editorBackgroundIsUnset()).toEqual(false);
65
65
  });
@@ -82,7 +82,9 @@ RETURN variable;`;
82
82
  ),
83
83
  );
84
84
  keywordcolors.every((kw) =>
85
- expect(kw).toEqual(darkThemeConstants.highlightStyles.keyword),
85
+ expect(kw).toEqual(
86
+ darkThemeConstants.highlightStyles.keyword.toLowerCase(),
87
+ ),
86
88
  );
87
89
 
88
90
  const labelReltype = await Promise.all(
@@ -91,34 +93,34 @@ RETURN variable;`;
91
93
  ),
92
94
  );
93
95
  labelReltype.every((kw) =>
94
- expect(kw).toEqual(darkThemeConstants.highlightStyles.label),
96
+ expect(kw).toEqual(darkThemeConstants.highlightStyles.label.toLowerCase()),
95
97
  );
96
98
 
97
99
  expect(
98
100
  await editorPage.getHexColorOfLocator(page.getByText('parameter')),
99
- ).toEqual(darkThemeConstants.highlightStyles.paramValue);
101
+ ).toEqual(darkThemeConstants.highlightStyles.paramValue.toLowerCase());
100
102
 
101
103
  expect(
102
104
  await editorPage.getHexColorOfLocator(page.getByText('property')),
103
- ).toEqual(darkThemeConstants.highlightStyles.property);
105
+ ).toEqual(darkThemeConstants.highlightStyles.property.toLowerCase());
104
106
 
105
107
  expect(
106
108
  await editorPage.getHexColorOfLocator(page.getByText('false')),
107
- ).toEqual(darkThemeConstants.highlightStyles.booleanLiteral);
109
+ ).toEqual(darkThemeConstants.highlightStyles.booleanLiteral.toLowerCase());
108
110
 
109
111
  expect(
110
112
  await editorPage.getHexColorOfLocator(page.getByText('String')),
111
- ).toEqual(darkThemeConstants.highlightStyles.stringLiteral);
113
+ ).toEqual(darkThemeConstants.highlightStyles.stringLiteral.toLowerCase());
112
114
 
113
115
  expect(
114
116
  await editorPage.getHexColorOfLocator(page.getByText('comment')),
115
- ).toEqual(darkThemeConstants.highlightStyles.comment);
117
+ ).toEqual(darkThemeConstants.highlightStyles.comment.toLowerCase());
116
118
 
117
119
  expect(
118
120
  await editorPage.getHexColorOfLocator(
119
121
  page.getByText('1234', { exact: true }),
120
122
  ),
121
- ).toEqual(darkThemeConstants.highlightStyles.numberLiteral);
123
+ ).toEqual(darkThemeConstants.highlightStyles.numberLiteral.toLowerCase());
122
124
 
123
125
  expect(await editorPage.editorBackgroundIsUnset()).toEqual(false);
124
126
  });
@@ -131,7 +133,7 @@ test('can live switch theme ', async ({ page, mount }) => {
131
133
  await editorPage.getHexColorOfLocator(
132
134
  page.getByText('RETURN', { exact: true }),
133
135
  ),
134
- ).toEqual(lightThemeConstants.highlightStyles.keyword);
136
+ ).toEqual(lightThemeConstants.highlightStyles.keyword.toLowerCase());
135
137
 
136
138
  await component.update(<CypherEditor theme="dark" value="RETURN" />);
137
139
 
@@ -139,7 +141,7 @@ test('can live switch theme ', async ({ page, mount }) => {
139
141
  await editorPage.getHexColorOfLocator(
140
142
  page.getByText('RETURN', { exact: true }),
141
143
  ),
142
- ).toEqual(darkThemeConstants.highlightStyles.keyword);
144
+ ).toEqual(darkThemeConstants.highlightStyles.keyword.toLowerCase());
143
145
  });
144
146
 
145
147
  test('respects prop to allow overriding bkg color', async ({ page, mount }) => {
@@ -164,7 +166,7 @@ multilinestring";`;
164
166
 
165
167
  expect(
166
168
  await editorPage.getHexColorOfLocator(page.getByText('multilinestring')),
167
- ).toEqual(lightThemeConstants.highlightStyles.stringLiteral);
169
+ ).toEqual(lightThemeConstants.highlightStyles.stringLiteral.toLowerCase());
168
170
  });
169
171
 
170
172
  test('highlights multiline label correctly', async ({ page, mount }) => {
@@ -179,7 +181,7 @@ Label\`)
179
181
 
180
182
  expect(
181
183
  await editorPage.getHexColorOfLocator(page.getByText('Label')),
182
- ).toEqual(lightThemeConstants.highlightStyles.label);
184
+ ).toEqual(lightThemeConstants.highlightStyles.label.toLowerCase());
183
185
  });
184
186
 
185
187
  test('highlights multiline comment correctly', async ({ page, mount }) => {
@@ -194,5 +196,5 @@ comment
194
196
 
195
197
  expect(
196
198
  await editorPage.getHexColorOfLocator(page.getByText('comment')),
197
- ).toEqual(lightThemeConstants.highlightStyles.comment);
199
+ ).toEqual(lightThemeConstants.highlightStyles.comment.toLowerCase());
198
200
  });