@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.
Files changed (122) hide show
  1. package/CHANGELOG.md +68 -0
  2. package/LICENSE.md +201 -0
  3. package/README.md +27 -4
  4. package/dist/CypherEditor.d.ts +153 -0
  5. package/dist/CypherEditor.js +242 -0
  6. package/dist/CypherEditor.js.map +1 -0
  7. package/dist/e2e_tests/autoCompletion.spec.d.ts +1 -0
  8. package/dist/e2e_tests/autoCompletion.spec.js +133 -0
  9. package/dist/e2e_tests/autoCompletion.spec.js.map +1 -0
  10. package/dist/e2e_tests/configuration.spec.d.ts +1 -0
  11. package/dist/e2e_tests/configuration.spec.js +73 -0
  12. package/dist/e2e_tests/configuration.spec.js.map +1 -0
  13. package/dist/e2e_tests/e2eUtils.d.ts +12 -0
  14. package/dist/e2e_tests/e2eUtils.js +60 -0
  15. package/dist/e2e_tests/e2eUtils.js.map +1 -0
  16. package/dist/e2e_tests/extraKeybindings.spec.d.ts +1 -0
  17. package/dist/e2e_tests/extraKeybindings.spec.js +44 -0
  18. package/dist/e2e_tests/extraKeybindings.spec.js.map +1 -0
  19. package/dist/e2e_tests/historyNavigation.spec.d.ts +1 -0
  20. package/dist/e2e_tests/historyNavigation.spec.js +136 -0
  21. package/dist/e2e_tests/historyNavigation.spec.js.map +1 -0
  22. package/dist/e2e_tests/performanceTest.spec.d.ts +6 -0
  23. package/dist/e2e_tests/performanceTest.spec.js +96 -0
  24. package/dist/e2e_tests/performanceTest.spec.js.map +1 -0
  25. package/dist/e2e_tests/sanityChecks.spec.d.ts +1 -0
  26. package/dist/e2e_tests/sanityChecks.spec.js +56 -0
  27. package/dist/e2e_tests/sanityChecks.spec.js.map +1 -0
  28. package/dist/e2e_tests/signatureHelp.spec.d.ts +1 -0
  29. package/dist/e2e_tests/signatureHelp.spec.js +152 -0
  30. package/dist/e2e_tests/signatureHelp.spec.js.map +1 -0
  31. package/dist/e2e_tests/snippets.spec.d.ts +1 -0
  32. package/dist/e2e_tests/snippets.spec.js +63 -0
  33. package/dist/e2e_tests/snippets.spec.js.map +1 -0
  34. package/dist/e2e_tests/syntaxHighlighting.spec.d.ts +1 -0
  35. package/dist/e2e_tests/syntaxHighlighting.spec.js +91 -0
  36. package/dist/e2e_tests/syntaxHighlighting.spec.js.map +1 -0
  37. package/dist/e2e_tests/syntaxValidation.spec.d.ts +1 -0
  38. package/dist/e2e_tests/syntaxValidation.spec.js +79 -0
  39. package/dist/e2e_tests/syntaxValidation.spec.js.map +1 -0
  40. package/dist/historyNavigation.d.ts +7 -0
  41. package/dist/historyNavigation.js +163 -0
  42. package/dist/historyNavigation.js.map +1 -0
  43. package/dist/icons.d.ts +2 -0
  44. package/dist/icons.js +62 -0
  45. package/dist/icons.js.map +1 -0
  46. package/dist/index.d.ts +4 -0
  47. package/dist/index.js +5 -0
  48. package/dist/index.js.map +1 -0
  49. package/dist/lang-cypher/autocomplete.d.ts +3 -0
  50. package/dist/lang-cypher/autocomplete.js +62 -0
  51. package/dist/lang-cypher/autocomplete.js.map +1 -0
  52. package/dist/lang-cypher/constants.d.ts +40 -0
  53. package/dist/lang-cypher/constants.js +65 -0
  54. package/dist/lang-cypher/constants.js.map +1 -0
  55. package/dist/lang-cypher/contants.test.d.ts +1 -0
  56. package/dist/lang-cypher/contants.test.js +102 -0
  57. package/dist/lang-cypher/contants.test.js.map +1 -0
  58. package/dist/lang-cypher/createCypherTheme.d.ts +26 -0
  59. package/dist/lang-cypher/createCypherTheme.js +172 -0
  60. package/dist/lang-cypher/createCypherTheme.js.map +1 -0
  61. package/dist/lang-cypher/langCypher.d.ts +9 -0
  62. package/dist/lang-cypher/langCypher.js +24 -0
  63. package/dist/lang-cypher/langCypher.js.map +1 -0
  64. package/dist/lang-cypher/lintWorker.d.ts +8 -0
  65. package/dist/lang-cypher/lintWorker.js +4 -0
  66. package/dist/lang-cypher/lintWorker.js.map +1 -0
  67. package/dist/lang-cypher/parser-adapter.d.ts +19 -0
  68. package/dist/lang-cypher/parser-adapter.js +113 -0
  69. package/dist/lang-cypher/parser-adapter.js.map +1 -0
  70. package/dist/lang-cypher/signatureHelp.d.ts +4 -0
  71. package/dist/lang-cypher/signatureHelp.js +93 -0
  72. package/dist/lang-cypher/signatureHelp.js.map +1 -0
  73. package/dist/lang-cypher/syntaxValidation.d.ts +5 -0
  74. package/dist/lang-cypher/syntaxValidation.js +71 -0
  75. package/dist/lang-cypher/syntaxValidation.js.map +1 -0
  76. package/dist/lang-cypher/themeIcons.d.ts +7 -0
  77. package/dist/lang-cypher/themeIcons.js +22 -0
  78. package/dist/lang-cypher/themeIcons.js.map +1 -0
  79. package/dist/ndlTokensCopy.d.ts +379 -0
  80. package/dist/ndlTokensCopy.js +380 -0
  81. package/dist/ndlTokensCopy.js.map +1 -0
  82. package/dist/ndlTokensCopy.test.d.ts +1 -0
  83. package/dist/ndlTokensCopy.test.js +11 -0
  84. package/dist/ndlTokensCopy.test.js.map +1 -0
  85. package/dist/neo4jSetup.d.ts +2 -0
  86. package/dist/neo4jSetup.js +120 -0
  87. package/dist/neo4jSetup.js.map +1 -0
  88. package/dist/themes.d.ts +11 -0
  89. package/dist/themes.js +114 -0
  90. package/dist/themes.js.map +1 -0
  91. package/dist/tsconfig.tsbuildinfo +1 -0
  92. package/package.json +46 -16
  93. package/src/CypherEditor.tsx +461 -0
  94. package/src/e2e_tests/autoCompletion.spec.tsx +236 -0
  95. package/src/e2e_tests/configuration.spec.tsx +97 -0
  96. package/src/e2e_tests/e2eUtils.ts +85 -0
  97. package/src/e2e_tests/extraKeybindings.spec.tsx +57 -0
  98. package/src/e2e_tests/historyNavigation.spec.tsx +196 -0
  99. package/src/e2e_tests/performanceTest.spec.tsx +158 -0
  100. package/src/e2e_tests/sanityChecks.spec.tsx +78 -0
  101. package/src/e2e_tests/signatureHelp.spec.tsx +309 -0
  102. package/src/e2e_tests/snippets.spec.tsx +94 -0
  103. package/src/e2e_tests/syntaxHighlighting.spec.tsx +198 -0
  104. package/src/e2e_tests/syntaxValidation.spec.tsx +156 -0
  105. package/src/historyNavigation.ts +191 -0
  106. package/{esm/index.mjs → src/icons.ts} +37 -1283
  107. package/src/index.ts +4 -0
  108. package/src/lang-cypher/autocomplete.ts +81 -0
  109. package/src/lang-cypher/constants.ts +84 -0
  110. package/src/lang-cypher/contants.test.ts +104 -0
  111. package/src/lang-cypher/createCypherTheme.ts +240 -0
  112. package/src/lang-cypher/langCypher.ts +41 -0
  113. package/src/lang-cypher/lintWorker.ts +14 -0
  114. package/src/lang-cypher/parser-adapter.ts +145 -0
  115. package/src/lang-cypher/signatureHelp.ts +131 -0
  116. package/src/lang-cypher/syntaxValidation.ts +99 -0
  117. package/src/lang-cypher/themeIcons.ts +27 -0
  118. package/src/ndlTokensCopy.test.ts +11 -0
  119. package/src/ndlTokensCopy.ts +379 -0
  120. package/src/neo4jSetup.tsx +179 -0
  121. package/src/themes.ts +132 -0
  122. 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
+ });