@neo4j-cypher/react-codemirror 2.0.0-next.14 → 2.0.0-next.16

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 (38) hide show
  1. package/CHANGELOG.md +19 -0
  2. package/dist/e2e_tests/autoCompletion.spec.js +2 -2
  3. package/dist/e2e_tests/autoCompletion.spec.js.map +1 -1
  4. package/dist/e2e_tests/debounce.spec.js +2 -1
  5. package/dist/e2e_tests/debounce.spec.js.map +1 -1
  6. package/dist/e2e_tests/performanceTest.spec.js +2 -1
  7. package/dist/e2e_tests/performanceTest.spec.js.map +1 -1
  8. package/dist/e2e_tests/syntaxHighlighting.spec.js +21 -21
  9. package/dist/e2e_tests/syntaxHighlighting.spec.js.map +1 -1
  10. package/dist/e2e_tests/syntaxValidation.spec.js +22 -0
  11. package/dist/e2e_tests/syntaxValidation.spec.js.map +1 -1
  12. package/dist/lang-cypher/autocomplete.js +1 -1
  13. package/dist/lang-cypher/autocomplete.js.map +1 -1
  14. package/dist/lang-cypher/constants.d.ts +2 -0
  15. package/dist/lang-cypher/constants.js +4 -0
  16. package/dist/lang-cypher/constants.js.map +1 -1
  17. package/dist/lang-cypher/createCypherTheme.js +1 -1
  18. package/dist/lang-cypher/createCypherTheme.js.map +1 -1
  19. package/dist/lang-cypher/syntaxValidation.js +13 -6
  20. package/dist/lang-cypher/syntaxValidation.js.map +1 -1
  21. package/dist/ndlTokensCopy.d.ts +415 -256
  22. package/dist/ndlTokensCopy.js +458 -299
  23. package/dist/ndlTokensCopy.js.map +1 -1
  24. package/dist/themes.js +25 -42
  25. package/dist/themes.js.map +1 -1
  26. package/dist/tsconfig.tsbuildinfo +1 -1
  27. package/package.json +3 -3
  28. package/src/e2e_tests/autoCompletion.spec.tsx +2 -2
  29. package/src/e2e_tests/debounce.spec.tsx +37 -32
  30. package/src/e2e_tests/performanceTest.spec.tsx +6 -1
  31. package/src/e2e_tests/syntaxHighlighting.spec.tsx +25 -21
  32. package/src/e2e_tests/syntaxValidation.spec.tsx +46 -0
  33. package/src/lang-cypher/autocomplete.ts +1 -1
  34. package/src/lang-cypher/constants.ts +4 -0
  35. package/src/lang-cypher/createCypherTheme.ts +1 -1
  36. package/src/lang-cypher/syntaxValidation.ts +13 -6
  37. package/src/ndlTokensCopy.ts +458 -299
  38. package/src/themes.ts +25 -48
@@ -27,43 +27,48 @@ test.fail(
27
27
  },
28
28
  );
29
29
 
30
- test('onExecute updates should override debounce updates', async ({
31
- mount,
32
- page,
33
- }) => {
34
- const editorPage = new CypherEditorPage(page);
35
- let value = '';
30
+ // TODO Fix this test
31
+ test.fixme(
32
+ 'onExecute updates should override debounce updates',
33
+ async ({ mount, page }) => {
34
+ const editorPage = new CypherEditorPage(page);
35
+ let value = '';
36
36
 
37
- const onExecute = () => {
38
- value = '';
39
- void component.update(
40
- <CypherEditor value={value} onChange={onChange} onExecute={onExecute} />,
41
- );
42
- };
37
+ const onExecute = () => {
38
+ value = '';
39
+ void component.update(
40
+ <CypherEditor
41
+ value={value}
42
+ onChange={onChange}
43
+ onExecute={onExecute}
44
+ />,
45
+ );
46
+ };
43
47
 
44
- const onChange = (val: string) => {
45
- value = val;
46
- void component.update(
47
- <CypherEditor value={val} onChange={onChange} onExecute={onExecute} />,
48
- );
49
- };
48
+ const onChange = (val: string) => {
49
+ value = val;
50
+ void component.update(
51
+ <CypherEditor value={val} onChange={onChange} onExecute={onExecute} />,
52
+ );
53
+ };
50
54
 
51
- const component = await mount(
52
- <CypherEditor value={value} onChange={onChange} onExecute={onExecute} />,
53
- );
55
+ const component = await mount(
56
+ <CypherEditor value={value} onChange={onChange} onExecute={onExecute} />,
57
+ );
54
58
 
55
- await editorPage.getEditor().pressSequentially('RETURN 1');
56
- await editorPage.getEditor().press('Enter');
57
- await page.waitForTimeout(DEBOUNCE_TIME_WITH_MARGIN);
58
- await expect(component).not.toContainText('RETURN 1');
59
+ await editorPage.getEditor().pressSequentially('RETURN 1');
60
+ await editorPage.getEditor().press('Enter');
61
+ await page.waitForTimeout(DEBOUNCE_TIME_WITH_MARGIN);
62
+ await expect(component).not.toContainText('RETURN 1');
59
63
 
60
- await editorPage.getEditor().pressSequentially('RETURN 1');
61
- await editorPage.getEditor().pressSequentially('');
62
- await editorPage.getEditor().pressSequentially('RETURN 1');
63
- await editorPage.getEditor().press('Enter');
64
- await page.waitForTimeout(DEBOUNCE_TIME_WITH_MARGIN);
65
- await expect(component).not.toContainText('RETURN 1');
66
- });
64
+ await editorPage.getEditor().pressSequentially('RETURN 1');
65
+ await editorPage.getEditor().pressSequentially('');
66
+ await editorPage.getEditor().pressSequentially('RETURN 1');
67
+ await editorPage.getEditor().press('Enter');
68
+ await page.waitForTimeout(DEBOUNCE_TIME_WITH_MARGIN);
69
+ await expect(component).not.toContainText('RETURN 1');
70
+ },
71
+ );
67
72
 
68
73
  test('onExecute should fire after debounced updates', async ({
69
74
  mount,
@@ -10,7 +10,12 @@ declare global {
10
10
  }
11
11
  }
12
12
 
13
- test('benchmarking & performance test session', async ({ mount, page }) => {
13
+ test('benchmarking & performance test session', async ({
14
+ browserName,
15
+ mount,
16
+ page,
17
+ }) => {
18
+ test.skip(browserName !== 'chromium');
14
19
  const client = await page.context().newCDPSession(page);
15
20
  if (process.env.BENCHMARKING === 'true') {
16
21
  test.setTimeout(1000000);
@@ -21,7 +21,9 @@ RETURN variable;`;
21
21
  ),
22
22
  );
23
23
  keywordcolors.every((kw) =>
24
- expect(kw).toEqual(lightThemeConstants.highlightStyles.keyword),
24
+ expect(kw).toEqual(
25
+ lightThemeConstants.highlightStyles.keyword.toLowerCase(),
26
+ ),
25
27
  );
26
28
 
27
29
  const labelReltype = await Promise.all(
@@ -30,34 +32,34 @@ RETURN variable;`;
30
32
  ),
31
33
  );
32
34
  labelReltype.every((kw) =>
33
- expect(kw).toEqual(lightThemeConstants.highlightStyles.label),
35
+ expect(kw).toEqual(lightThemeConstants.highlightStyles.label.toLowerCase()),
34
36
  );
35
37
 
36
38
  expect(
37
39
  await editorPage.getHexColorOfLocator(page.getByText('parameter')),
38
- ).toEqual(lightThemeConstants.highlightStyles.paramValue);
40
+ ).toEqual(lightThemeConstants.highlightStyles.paramValue.toLowerCase());
39
41
 
40
42
  expect(
41
43
  await editorPage.getHexColorOfLocator(page.getByText('property')),
42
- ).toEqual(lightThemeConstants.highlightStyles.property);
44
+ ).toEqual(lightThemeConstants.highlightStyles.property.toLowerCase());
43
45
 
44
46
  expect(
45
47
  await editorPage.getHexColorOfLocator(page.getByText('false')),
46
- ).toEqual(lightThemeConstants.highlightStyles.booleanLiteral);
48
+ ).toEqual(lightThemeConstants.highlightStyles.booleanLiteral.toLowerCase());
47
49
 
48
50
  expect(
49
51
  await editorPage.getHexColorOfLocator(page.getByText('String')),
50
- ).toEqual(lightThemeConstants.highlightStyles.stringLiteral);
52
+ ).toEqual(lightThemeConstants.highlightStyles.stringLiteral.toLowerCase());
51
53
 
52
54
  expect(
53
55
  await editorPage.getHexColorOfLocator(page.getByText('comment')),
54
- ).toEqual(lightThemeConstants.highlightStyles.comment);
56
+ ).toEqual(lightThemeConstants.highlightStyles.comment.toLowerCase());
55
57
 
56
58
  expect(
57
59
  await editorPage.getHexColorOfLocator(
58
60
  page.getByText('1234', { exact: true }),
59
61
  ),
60
- ).toEqual(lightThemeConstants.highlightStyles.numberLiteral);
62
+ ).toEqual(lightThemeConstants.highlightStyles.numberLiteral.toLowerCase());
61
63
 
62
64
  expect(await editorPage.editorBackgroundIsUnset()).toEqual(false);
63
65
  });
@@ -80,7 +82,9 @@ RETURN variable;`;
80
82
  ),
81
83
  );
82
84
  keywordcolors.every((kw) =>
83
- expect(kw).toEqual(darkThemeConstants.highlightStyles.keyword),
85
+ expect(kw).toEqual(
86
+ darkThemeConstants.highlightStyles.keyword.toLowerCase(),
87
+ ),
84
88
  );
85
89
 
86
90
  const labelReltype = await Promise.all(
@@ -89,34 +93,34 @@ RETURN variable;`;
89
93
  ),
90
94
  );
91
95
  labelReltype.every((kw) =>
92
- expect(kw).toEqual(darkThemeConstants.highlightStyles.label),
96
+ expect(kw).toEqual(darkThemeConstants.highlightStyles.label.toLowerCase()),
93
97
  );
94
98
 
95
99
  expect(
96
100
  await editorPage.getHexColorOfLocator(page.getByText('parameter')),
97
- ).toEqual(darkThemeConstants.highlightStyles.paramValue);
101
+ ).toEqual(darkThemeConstants.highlightStyles.paramValue.toLowerCase());
98
102
 
99
103
  expect(
100
104
  await editorPage.getHexColorOfLocator(page.getByText('property')),
101
- ).toEqual(darkThemeConstants.highlightStyles.property);
105
+ ).toEqual(darkThemeConstants.highlightStyles.property.toLowerCase());
102
106
 
103
107
  expect(
104
108
  await editorPage.getHexColorOfLocator(page.getByText('false')),
105
- ).toEqual(darkThemeConstants.highlightStyles.booleanLiteral);
109
+ ).toEqual(darkThemeConstants.highlightStyles.booleanLiteral.toLowerCase());
106
110
 
107
111
  expect(
108
112
  await editorPage.getHexColorOfLocator(page.getByText('String')),
109
- ).toEqual(darkThemeConstants.highlightStyles.stringLiteral);
113
+ ).toEqual(darkThemeConstants.highlightStyles.stringLiteral.toLowerCase());
110
114
 
111
115
  expect(
112
116
  await editorPage.getHexColorOfLocator(page.getByText('comment')),
113
- ).toEqual(darkThemeConstants.highlightStyles.comment);
117
+ ).toEqual(darkThemeConstants.highlightStyles.comment.toLowerCase());
114
118
 
115
119
  expect(
116
120
  await editorPage.getHexColorOfLocator(
117
121
  page.getByText('1234', { exact: true }),
118
122
  ),
119
- ).toEqual(darkThemeConstants.highlightStyles.numberLiteral);
123
+ ).toEqual(darkThemeConstants.highlightStyles.numberLiteral.toLowerCase());
120
124
 
121
125
  expect(await editorPage.editorBackgroundIsUnset()).toEqual(false);
122
126
  });
@@ -129,7 +133,7 @@ test('can live switch theme ', async ({ page, mount }) => {
129
133
  await editorPage.getHexColorOfLocator(
130
134
  page.getByText('RETURN', { exact: true }),
131
135
  ),
132
- ).toEqual(lightThemeConstants.highlightStyles.keyword);
136
+ ).toEqual(lightThemeConstants.highlightStyles.keyword.toLowerCase());
133
137
 
134
138
  await component.update(<CypherEditor theme="dark" value="RETURN" />);
135
139
 
@@ -137,7 +141,7 @@ test('can live switch theme ', async ({ page, mount }) => {
137
141
  await editorPage.getHexColorOfLocator(
138
142
  page.getByText('RETURN', { exact: true }),
139
143
  ),
140
- ).toEqual(darkThemeConstants.highlightStyles.keyword);
144
+ ).toEqual(darkThemeConstants.highlightStyles.keyword.toLowerCase());
141
145
  });
142
146
 
143
147
  test('respects prop to allow overriding bkg color', async ({ page, mount }) => {
@@ -162,7 +166,7 @@ multilinestring";`;
162
166
 
163
167
  expect(
164
168
  await editorPage.getHexColorOfLocator(page.getByText('multilinestring')),
165
- ).toEqual(lightThemeConstants.highlightStyles.stringLiteral);
169
+ ).toEqual(lightThemeConstants.highlightStyles.stringLiteral.toLowerCase());
166
170
  });
167
171
 
168
172
  test('highlights multiline label correctly', async ({ page, mount }) => {
@@ -177,7 +181,7 @@ Label\`)
177
181
 
178
182
  expect(
179
183
  await editorPage.getHexColorOfLocator(page.getByText('Label')),
180
- ).toEqual(lightThemeConstants.highlightStyles.label);
184
+ ).toEqual(lightThemeConstants.highlightStyles.label.toLowerCase());
181
185
  });
182
186
 
183
187
  test('highlights multiline comment correctly', async ({ page, mount }) => {
@@ -192,5 +196,5 @@ comment
192
196
 
193
197
  expect(
194
198
  await editorPage.getHexColorOfLocator(page.getByText('comment')),
195
- ).toEqual(lightThemeConstants.highlightStyles.comment);
199
+ ).toEqual(lightThemeConstants.highlightStyles.comment.toLowerCase());
196
200
  });
@@ -1,3 +1,4 @@
1
+ import { testData } from '@neo4j-cypher/language-support';
1
2
  import { expect, test } from '@playwright/experimental-ct-react';
2
3
  import { CypherEditor } from '../CypherEditor';
3
4
  import { CypherEditorPage } from './e2eUtils';
@@ -86,6 +87,20 @@ test('Errors for multiline undefined labels are highlighted correctly', async ({
86
87
  await editorPage.checkWarningMessage('Bar`', expectedMsg);
87
88
  });
88
89
 
90
+ test('Semantic errors work in firefox', async ({
91
+ browserName,
92
+ page,
93
+ mount,
94
+ }) => {
95
+ test.skip(browserName !== 'firefox');
96
+ const editorPage = new CypherEditorPage(page);
97
+ const query = 'MATCH (n:OperationalPoint)--(m:OperationalPoint) RETURN s,m,n';
98
+
99
+ await mount(<CypherEditor value={query} schema={testData.mockSchema} />);
100
+
101
+ await editorPage.checkErrorMessage('s,m,n', 'Variable `s` not defined');
102
+ });
103
+
89
104
  test('Semantic errors are surfaced when there are no syntactic errors', async ({
90
105
  page,
91
106
  mount,
@@ -154,3 +169,34 @@ test('Validation errors are correctly overlapped', async ({ page, mount }) => {
154
169
  "Invalid input. '-1' is not a valid value. Must be a positive integer",
155
170
  );
156
171
  });
172
+
173
+ test('Strikethroughs are shown for deprecated functions', async ({ page, mount }) => {
174
+ const editorPage = new CypherEditorPage(page);
175
+ const query = `RETURN id()`;
176
+
177
+ await mount(<CypherEditor value={query} schema={testData.mockSchema} />);
178
+ await expect(editorPage.page.locator('.cm-deprecated-element').last()).toBeVisible(
179
+ { timeout: 3000 },
180
+ );
181
+ await editorPage.checkWarningMessage(
182
+ 'id',
183
+ "Function id is deprecated.",
184
+ );
185
+
186
+ });
187
+
188
+ test('Strikethroughs are shown for deprecated procedures', async ({ page, mount }) => {
189
+ const editorPage = new CypherEditorPage(page);
190
+ const query = `CALL apoc.create.uuids()`;
191
+
192
+ await mount(<CypherEditor value={query} schema={testData.mockSchema} />);
193
+ await expect(editorPage.page.locator('.cm-deprecated-element').last()).toBeVisible(
194
+ { timeout: 3000 },
195
+ );
196
+
197
+ await editorPage.checkWarningMessage(
198
+ 'apoc.create.uuids',
199
+ "Procedure apoc.create.uuids is deprecated.",
200
+ );
201
+
202
+ });
@@ -49,7 +49,7 @@ export const completionStyles: (
49
49
  completion: Completion & { deprecated?: boolean },
50
50
  ) => string = (completion) => {
51
51
  if (completion.deprecated) {
52
- return 'cm-deprecated-completion';
52
+ return 'cm-deprecated-element';
53
53
  } else {
54
54
  return null;
55
55
  }
@@ -40,6 +40,8 @@ export const cypherTokenTypeToNode = (facet: Facet<unknown>) => ({
40
40
  relationship: NodeType.define({ id: 26, name: 'label' }),
41
41
  boolean: NodeType.define({ id: 27, name: 'booleanLiteral' }),
42
42
  number: NodeType.define({ id: 28, name: 'numberLiteral' }),
43
+ setting: NodeType.define({ id: 29, name: 'setting' }),
44
+ settingValue: NodeType.define({ id: 30, name: 'settingValue' }),
43
45
  });
44
46
 
45
47
  export type PrismSpecificTokenType =
@@ -78,6 +80,8 @@ export const tokenTypeToStyleTag: Record<HighlightedCypherTokenTypes, Tag> = {
78
80
  punctuation: tags.punctuation,
79
81
  separator: tags.separator,
80
82
  consoleCommand: tags.macroName,
83
+ setting: tags.attributeName,
84
+ settingValue: tags.attributeValue,
81
85
  };
82
86
 
83
87
  export const parserAdapterNodeSet = (nodes: Record<string, NodeType>) =>
@@ -130,7 +130,7 @@ export const createCypherTheme = ({
130
130
  '.cm-completionInfo-signature': {
131
131
  color: 'darkgrey',
132
132
  },
133
- '.cm-deprecated-completion': {
133
+ '.cm-deprecated-element': {
134
134
  'text-decoration': 'line-through',
135
135
  },
136
136
  '.cm-tooltip-autocomplete': {
@@ -1,7 +1,7 @@
1
1
  import { Diagnostic, linter } from '@codemirror/lint';
2
2
  import { Extension } from '@codemirror/state';
3
3
  import { parserWrapper, validateSyntax } from '@neo4j-cypher/language-support';
4
- import { DiagnosticSeverity } from 'vscode-languageserver-types';
4
+ import { DiagnosticSeverity, DiagnosticTag } from 'vscode-languageserver-types';
5
5
  import workerpool from 'workerpool';
6
6
  import type { CypherConfig } from './langCypher';
7
7
  import type { LinterTask, LintWorker } from './lintWorker';
@@ -74,15 +74,22 @@ export const semanticAnalysisLinter: (config: CypherConfig) => Extension = (
74
74
  );
75
75
  const result = await lastSemanticJob;
76
76
 
77
- return result.map((diag) => {
77
+ const a: Diagnostic[] = result.map((diagnostic) => {
78
78
  return {
79
- from: diag.offsets.start,
80
- to: diag.offsets.end,
79
+ from: diagnostic.offsets.start,
80
+ to: diagnostic.offsets.end,
81
81
  severity:
82
- diag.severity === DiagnosticSeverity.Error ? 'error' : 'warning',
83
- message: diag.message,
82
+ diagnostic.severity === DiagnosticSeverity.Error
83
+ ? 'error'
84
+ : 'warning',
85
+ message: diagnostic.message,
86
+ ...(diagnostic.tags !== undefined &&
87
+ diagnostic.tags.includes(DiagnosticTag.Deprecated)
88
+ ? { markClass: 'cm-deprecated-element' }
89
+ : {}),
84
90
  };
85
91
  });
92
+ return a;
86
93
  } catch (err) {
87
94
  if (!(err instanceof workerpool.Promise.CancellationError)) {
88
95
  console.error(String(err) + ' ' + query);