@neo4j-cypher/language-support
Version:
Cypher language support
382 lines (356 loc) • 14.7 kB
text/typescript
import { CompletionItemKind } from 'vscode-languageserver-types';
import { DbSchema } from '../../dbSchema';
import { testCompletions } from './completionAssertionHelpers';
describe('Can complete database names', () => {
const dbSchema: DbSchema = {
databaseNames: ['db1', 'db2', 'movies'],
aliasNames: ['myMovies', 'scoped.alias', 'a.b.c.d'],
parameters: {
param1: 'something',
param2: 1337,
param3: {
property: 'value',
},
},
};
test('Correctly completes database names and aliases in SHOW DATABASE', () => {
const query = 'SHOW DATABASE ';
testCompletions({
query,
dbSchema,
expected: [
{ label: 'WHERE', kind: CompletionItemKind.Keyword },
{ label: 'YIELD', kind: CompletionItemKind.Keyword },
{ label: 'db1', kind: CompletionItemKind.Value },
{ label: 'db2', kind: CompletionItemKind.Value },
{ label: 'movies', kind: CompletionItemKind.Value },
{ label: 'myMovies', kind: CompletionItemKind.Value },
{ label: 'scoped.alias', kind: CompletionItemKind.Value },
{ label: 'a.b.c.d', kind: CompletionItemKind.Value },
{ label: '$param1', kind: CompletionItemKind.Variable },
],
// do not suggest non-string parameters
excluded: [
{ label: '$param2', kind: CompletionItemKind.Variable },
{ label: '$param3', kind: CompletionItemKind.Variable },
],
});
});
test('Correctly completes database names and aliases in SHOW DATABASE with started db name', () => {
const query = 'SHOW DATABASE m';
testCompletions({
query,
dbSchema,
expected: [
{ label: 'WHERE', kind: CompletionItemKind.Keyword },
{ label: 'YIELD', kind: CompletionItemKind.Keyword },
{ label: 'db1', kind: CompletionItemKind.Value },
{ label: 'db2', kind: CompletionItemKind.Value },
{ label: 'movies', kind: CompletionItemKind.Value },
{ label: 'myMovies', kind: CompletionItemKind.Value },
{ label: 'scoped.alias', kind: CompletionItemKind.Value },
{ label: 'a.b.c.d', kind: CompletionItemKind.Value },
{ label: '$param1', kind: CompletionItemKind.Variable },
],
excluded: [
// validate invalid keyword bug isn't present
{ label: '', kind: CompletionItemKind.Keyword },
// do not suggest non-string parameters
{ label: '$param2', kind: CompletionItemKind.Variable },
{ label: '$param3', kind: CompletionItemKind.Variable },
],
});
});
test("Doesn't suggest existing database names or aliases when createing database", () => {
const query = 'CREATE DATABASE ';
testCompletions({
query,
dbSchema,
excluded: [
{ label: 'db1', kind: CompletionItemKind.Value },
{ label: 'db2', kind: CompletionItemKind.Value },
{ label: 'movies', kind: CompletionItemKind.Value },
{ label: 'myMovies', kind: CompletionItemKind.Value },
{ label: 'scoped.alias', kind: CompletionItemKind.Value },
{ label: 'a.b.c.d', kind: CompletionItemKind.Value },
// do not suggest non-string parameters
{ label: '$param2', kind: CompletionItemKind.Variable },
{ label: '$param3', kind: CompletionItemKind.Variable },
],
// can create new database name using parameter
expected: [{ label: '$param1', kind: CompletionItemKind.Variable }],
});
});
test("Doesn't suggest existing database names or aliases when createing alias", () => {
const query = 'CREATE ALIAS ';
testCompletions({
query,
dbSchema,
excluded: [
{ label: 'db1', kind: CompletionItemKind.Value },
{ label: 'db2', kind: CompletionItemKind.Value },
{ label: 'movies', kind: CompletionItemKind.Value },
{ label: 'myMovies', kind: CompletionItemKind.Value },
{ label: 'scoped.alias', kind: CompletionItemKind.Value },
{ label: 'a.b.c.d', kind: CompletionItemKind.Value },
// do not suggest non-string parameters
{ label: '$param2', kind: CompletionItemKind.Variable },
{ label: '$param3', kind: CompletionItemKind.Variable },
],
// can create new alias name using parameter
expected: [{ label: '$param1', kind: CompletionItemKind.Variable }],
});
});
test('Suggests only aliases when dropping alias', () => {
const query = 'DROP ALIAS ';
testCompletions({
query,
dbSchema,
expected: [
{ label: 'myMovies', kind: CompletionItemKind.Value },
{ label: 'scoped.alias', kind: CompletionItemKind.Value },
{ label: 'a.b.c.d', kind: CompletionItemKind.Value },
{ label: '$param1', kind: CompletionItemKind.Variable },
],
excluded: [
{ label: 'db1', kind: CompletionItemKind.Value },
{ label: 'db2', kind: CompletionItemKind.Value },
{ label: 'movies', kind: CompletionItemKind.Value },
// do not suggest non-string parameters
{ label: '$param2', kind: CompletionItemKind.Variable },
{ label: '$param3', kind: CompletionItemKind.Variable },
],
});
});
test('Suggests only aliases when showing alias', () => {
const query = 'SHOW ALIAS ';
testCompletions({
query,
dbSchema,
expected: [
{ label: 'myMovies', kind: CompletionItemKind.Value },
{ label: '$param1', kind: CompletionItemKind.Variable },
],
excluded: [
{ label: 'db1', kind: CompletionItemKind.Value },
{ label: 'db2', kind: CompletionItemKind.Value },
{ label: 'movies', kind: CompletionItemKind.Value },
// do not suggest non-string parameters
{ label: '$param2', kind: CompletionItemKind.Variable },
{ label: '$param3', kind: CompletionItemKind.Variable },
],
});
});
test('Suggests only aliases when altering alias', () => {
const query = 'ALTER ALIAS a';
testCompletions({
query,
dbSchema,
expected: [
{ label: 'myMovies', kind: CompletionItemKind.Value },
{ label: 'scoped.alias', kind: CompletionItemKind.Value },
{ label: 'a.b.c.d', kind: CompletionItemKind.Value },
{ label: '$param1', kind: CompletionItemKind.Variable },
],
excluded: [
{ label: 'db1', kind: CompletionItemKind.Value },
{ label: 'db2', kind: CompletionItemKind.Value },
{ label: 'movies', kind: CompletionItemKind.Value },
// do not suggest non-string parameters
{ label: '$param2', kind: CompletionItemKind.Variable },
{ label: '$param3', kind: CompletionItemKind.Variable },
],
});
});
test('Can complete when typing scoped alias', () => {
const query = 'ALTER ALIAS a.b.c.';
testCompletions({
query,
dbSchema,
expected: [
{ label: 'myMovies', kind: CompletionItemKind.Value },
{ label: 'scoped.alias', kind: CompletionItemKind.Value },
{ label: 'a.b.c.d', kind: CompletionItemKind.Value },
{ label: '$param1', kind: CompletionItemKind.Variable },
],
excluded: [
{ label: 'db1', kind: CompletionItemKind.Value },
{ label: 'db2', kind: CompletionItemKind.Value },
{ label: 'movies', kind: CompletionItemKind.Value },
// do not suggest non-string parameters
{ label: '$param2', kind: CompletionItemKind.Variable },
{ label: '$param3', kind: CompletionItemKind.Variable },
],
});
});
test('Handles that the parser allows spaces in symbolicAliasName', () => {
// Since the parser allows for spaces in the symbolicAliasName rule but not in created alias (unless quoted)
// I've added a test to verify we don't suggest aliases after the space (false positives)
const query = 'drop alias myMovies ';
testCompletions({
query,
dbSchema,
expected: [
{ label: 'FOR DATABASE', kind: CompletionItemKind.Keyword },
{ label: 'IF EXISTS', kind: CompletionItemKind.Keyword },
],
excluded: [
{ label: 'db1', kind: CompletionItemKind.Value },
{ label: 'db2', kind: CompletionItemKind.Value },
{ label: 'movies', kind: CompletionItemKind.Value },
{ label: 'myMovies', kind: CompletionItemKind.Value },
{ label: 'scoped.alias', kind: CompletionItemKind.Value },
{ label: 'a.b.c.d', kind: CompletionItemKind.Value },
// EOF checks
{ label: '', kind: CompletionItemKind.Value },
{ label: '', kind: CompletionItemKind.Keyword },
],
});
});
test('Correctly completes parameters, database names and alias in DENY PRIVILEGE TO ROLE', () => {
const cases = [
'DENY TRAVERSE ON GRAPH ',
'DENY TRAVERSE ON GRAPH neo4j, ',
'DENY INDEX MANAGEMENT ON DATABASE ',
'DENY INDEX MANAGEMENT ON DATABASE neo4j, ',
];
cases.forEach((query) =>
testCompletions({
query,
dbSchema,
expected: [
{ label: 'db1', kind: CompletionItemKind.Value },
{ label: 'db2', kind: CompletionItemKind.Value },
{ label: 'movies', kind: CompletionItemKind.Value },
{ label: 'myMovies', kind: CompletionItemKind.Value },
{ label: 'scoped.alias', kind: CompletionItemKind.Value },
{ label: 'a.b.c.d', kind: CompletionItemKind.Value },
{ label: '$param1', kind: CompletionItemKind.Variable },
],
excluded: [
// validate invalid keyword bug isn't present
{ label: '', kind: CompletionItemKind.Keyword },
// do not suggest non-string parameters
{ label: '$param2', kind: CompletionItemKind.Variable },
{ label: '$param3', kind: CompletionItemKind.Variable },
],
}),
);
});
test('Correctly completes parameters, database names and alias in GRANT PRIVILEGE TO ROLE', () => {
const cases = [
'GRANT TRAVERSE ON GRAPH ',
'GRANT TRAVERSE ON GRAPH neo4j, ',
'GRANT INDEX MANAGEMENT ON DATABASE ',
'GRANT INDEX MANAGEMENT ON DATABASE neo4j, ',
];
cases.forEach((query) =>
testCompletions({
query,
dbSchema,
expected: [
{ label: 'db1', kind: CompletionItemKind.Value },
{ label: 'db2', kind: CompletionItemKind.Value },
{ label: 'movies', kind: CompletionItemKind.Value },
{ label: 'myMovies', kind: CompletionItemKind.Value },
{ label: 'scoped.alias', kind: CompletionItemKind.Value },
{ label: 'a.b.c.d', kind: CompletionItemKind.Value },
{ label: '$param1', kind: CompletionItemKind.Variable },
],
excluded: [
// validate invalid keyword bug isn't present
{ label: '', kind: CompletionItemKind.Keyword },
// do not suggest non-string parameters
{ label: '$param2', kind: CompletionItemKind.Variable },
{ label: '$param3', kind: CompletionItemKind.Variable },
],
}),
);
});
test('Correctly completes parameters, database names and alias in REVOKE PRIVILEGE FROM ROLE', () => {
const cases = [
'REVOKE GRANT TRAVERSE ON GRAPH ',
'REVOKE GRANT TRAVERSE ON GRAPH neo4j, ',
'REVOKE GRANT INDEX MANAGEMENT ON DATABASE ',
'REVOKE GRANT INDEX MANAGEMENT ON DATABASE neo4j, ',
];
cases.forEach((query) =>
testCompletions({
query,
dbSchema,
expected: [
{ label: 'db1', kind: CompletionItemKind.Value },
{ label: 'db2', kind: CompletionItemKind.Value },
{ label: 'movies', kind: CompletionItemKind.Value },
{ label: 'myMovies', kind: CompletionItemKind.Value },
{ label: 'scoped.alias', kind: CompletionItemKind.Value },
{ label: 'a.b.c.d', kind: CompletionItemKind.Value },
{ label: '$param1', kind: CompletionItemKind.Variable },
],
excluded: [
// validate invalid keyword bug isn't present
{ label: '', kind: CompletionItemKind.Keyword },
// do not suggest non-string parameters
{ label: '$param2', kind: CompletionItemKind.Variable },
{ label: '$param3', kind: CompletionItemKind.Variable },
],
}),
);
});
test('Correctly completes parameters and existing database names in GRANT privilege', () => {
const cases = [
'GRANT SHOW TRANSACTION (user1, user2) ON DATABASE ',
'GRANT SHOW TRANSACTION (user1, user2) ON DATABASE neo4j, ',
];
cases.forEach((query) =>
testCompletions({
query,
dbSchema,
expected: [
{ label: 'db1', kind: CompletionItemKind.Value },
{ label: 'db2', kind: CompletionItemKind.Value },
{ label: 'movies', kind: CompletionItemKind.Value },
{ label: 'myMovies', kind: CompletionItemKind.Value },
{ label: 'scoped.alias', kind: CompletionItemKind.Value },
{ label: 'a.b.c.d', kind: CompletionItemKind.Value },
{ label: '$param1', kind: CompletionItemKind.Variable },
],
excluded: [
// validate invalid keyword bug isn't present
{ label: '', kind: CompletionItemKind.Keyword },
// do not suggest non-string parameters
{ label: '$param2', kind: CompletionItemKind.Variable },
{ label: '$param3', kind: CompletionItemKind.Variable },
],
}),
);
});
test('Correctly completes parameters and existing database names in GRANT database privilege', () => {
const cases = [
'GRANT TERMINATE TRANSACTION (user) ON DATABASE ',
'GRANT TERMINATE TRANSACTION (user) ON DATABASE neo4j, ',
];
cases.forEach((query) =>
testCompletions({
query,
dbSchema,
expected: [
{ label: 'db1', kind: CompletionItemKind.Value },
{ label: 'db2', kind: CompletionItemKind.Value },
{ label: 'movies', kind: CompletionItemKind.Value },
{ label: 'myMovies', kind: CompletionItemKind.Value },
{ label: 'scoped.alias', kind: CompletionItemKind.Value },
{ label: 'a.b.c.d', kind: CompletionItemKind.Value },
{ label: '$param1', kind: CompletionItemKind.Variable },
],
excluded: [
// validate invalid keyword bug isn't present
{ label: '', kind: CompletionItemKind.Keyword },
// do not suggest non-string parameters
{ label: '$param2', kind: CompletionItemKind.Variable },
{ label: '$param3', kind: CompletionItemKind.Variable },
],
}),
);
});
});