1177 строки
51 KiB
TypeScript
1177 строки
51 KiB
TypeScript
/*---------------------------------------------------------------------------------------------
|
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
* Licensed under the MIT License. See License.txt in the project root for license information.
|
|
*--------------------------------------------------------------------------------------------*/
|
|
|
|
import { parseError } from '@microsoft/vscode-azext-utils';
|
|
import assert from 'assert';
|
|
import { Position } from 'vscode';
|
|
import {
|
|
findCommandAtPosition,
|
|
getAllCommandsFromText,
|
|
nonNullProp,
|
|
ObjectId,
|
|
type MongoCommand,
|
|
} from '../extension.bundle';
|
|
|
|
function expectSingleCommand(text: string): MongoCommand {
|
|
const commands = getAllCommandsFromText(text);
|
|
if (commands.length > 1) {
|
|
assert.ok(false, 'Too many commands found');
|
|
}
|
|
|
|
return commands[0];
|
|
}
|
|
|
|
function testParse(
|
|
text: string,
|
|
expectedCommand:
|
|
| { collection: string | undefined; name: string | undefined; args: any[] | undefined; firstErrorText?: string }
|
|
| undefined,
|
|
): void {
|
|
function testCore(coreText: string): void {
|
|
const command = expectSingleCommand(coreText);
|
|
if (expectedCommand) {
|
|
assert.ok(command, 'Expected a command, but found none');
|
|
|
|
assert.equal(
|
|
command.collection || '',
|
|
expectedCommand.collection || '',
|
|
'Parsed collection name is not correct',
|
|
);
|
|
assert.equal(command.name || '', expectedCommand.name || '', 'Parsed command name is not correct');
|
|
|
|
const actualArgs = (command.arguments || []).map((arg) => JSON.parse(arg));
|
|
assert.deepEqual(actualArgs, expectedCommand.args || [], 'Parsed arguments are not correct');
|
|
} else {
|
|
assert.ok(!command, 'Found a command, but expecting to find none');
|
|
return;
|
|
}
|
|
|
|
if (expectedCommand && expectedCommand.firstErrorText) {
|
|
assert.equal((command.errors || []).length > 0, true, 'Expected at least one error');
|
|
assert.equal(
|
|
nonNullProp(command, 'errors')[0].message,
|
|
expectedCommand.firstErrorText,
|
|
'First error text was incorrect',
|
|
);
|
|
} else {
|
|
assert.equal((command.errors || []).length, 0, 'Expected no errors');
|
|
}
|
|
}
|
|
|
|
testCore(text);
|
|
|
|
// Test again with LF changed to CR/LF
|
|
const crlfText = text.replace(/\n/g, '\r\n');
|
|
testCore(crlfText);
|
|
|
|
// Test again with LF changed to multiple CR/LF
|
|
const crlf2Text = text.replace(/\n/g, '\r\n\r\n');
|
|
testCore(crlf2Text);
|
|
|
|
// Test again with LF changed to CR
|
|
const lfText = text.replace(/\n/g, '\r');
|
|
testCore(lfText);
|
|
|
|
// Test again with LF changed to tab
|
|
const tabText = text.replace(/\n/g, '\t');
|
|
testCore(tabText);
|
|
|
|
// Test again with LF changed to space
|
|
const spaceText = text.replace(/\n/g, ' ');
|
|
testCore(spaceText);
|
|
}
|
|
|
|
function wrapInQuotes(word: string, numQuotes: number): string {
|
|
//0 to do nothing, 1 for single quotes, 2 for double quotes
|
|
let result: string;
|
|
if (numQuotes === 1) {
|
|
result = `'${word}'`;
|
|
} else if (numQuotes === 2) {
|
|
result = `"${word}"`;
|
|
} else {
|
|
result = word;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
suite('scrapbook parsing Tests', () => {
|
|
test('find', () => {
|
|
const text = 'db.find()';
|
|
const commands: MongoCommand[] = getAllCommandsFromText(text);
|
|
const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0));
|
|
assert.equal(command.text, text);
|
|
});
|
|
|
|
test('find with semicolon', () => {
|
|
const text = 'db.find();';
|
|
const commands: MongoCommand[] = getAllCommandsFromText(text);
|
|
const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0));
|
|
assert.equal(command.text, text);
|
|
});
|
|
|
|
test('first of two commands, Mac/Linux', () => {
|
|
const line1 = 'db.find()';
|
|
const line2 = "db.insertOne({'a': 'b'})";
|
|
const text = `${line1}\n${line2}`;
|
|
const commands: MongoCommand[] = getAllCommandsFromText(text);
|
|
const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0));
|
|
assert.equal(command.text, line1);
|
|
});
|
|
|
|
test('second of two commands, Mac/Linux', () => {
|
|
const line1 = 'db.find()';
|
|
for (let q = 0; q <= 2; q++) {
|
|
const line2 = `db.insertOne({${wrapInQuotes('a', q)}:'b'})`;
|
|
const text = `${line1}\n${line2}`;
|
|
const commands: MongoCommand[] = getAllCommandsFromText(text);
|
|
const command: MongoCommand = findCommandAtPosition(commands, new Position(2, 0));
|
|
assert.equal(command.text, line2);
|
|
}
|
|
});
|
|
|
|
test('second of two commands, Mac/Linux, semicolon', () => {
|
|
const line1 = 'db.find();';
|
|
for (let q = 0; q <= 2; q++) {
|
|
const line2 = `db.insertOne({${wrapInQuotes('a', q)}:'b'})`;
|
|
const text = `${line1}\n${line2}`;
|
|
const commands: MongoCommand[] = getAllCommandsFromText(text);
|
|
const command: MongoCommand = findCommandAtPosition(commands, new Position(2, 0));
|
|
assert.equal(command.text, line2);
|
|
}
|
|
});
|
|
|
|
test('first of two commands, Windows', () => {
|
|
const line1 = 'db.find()';
|
|
const line2 = "db.insertOne({'a': 'b'})";
|
|
const text = `${line1}\r\n${line2}`;
|
|
const commands: MongoCommand[] = getAllCommandsFromText(text);
|
|
const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0));
|
|
assert.equal(command.text, line1);
|
|
});
|
|
|
|
test('second of two commands, Windows', () => {
|
|
const line1 = 'db.find()';
|
|
const line2 = "db.insertOne({'a':'b'})";
|
|
const text = `${line1}\r\n${line2}`;
|
|
const commands: MongoCommand[] = getAllCommandsFromText(text);
|
|
const command: MongoCommand = findCommandAtPosition(commands, new Position(2, 0));
|
|
assert.equal(command.text, line2);
|
|
});
|
|
|
|
test('second of two commands, lots of blank lines, Windows', () => {
|
|
const line1 = 'db.find()';
|
|
const line2 = "db.insertOne({'a':'b'})";
|
|
const text = `\r\n\r\n\r\n\r\n\r\n\r\n${line1}\r\n\r\n\r\n\r\n\r\n\r\n${line2}\r\n\r\n\r\n\r\n\r\n\r\n`;
|
|
const commands: MongoCommand[] = getAllCommandsFromText(text);
|
|
const command: MongoCommand = findCommandAtPosition(commands, new Position(5, 0));
|
|
assert.equal(command.text, line2);
|
|
});
|
|
|
|
test('first of two commands, Windows, on blank line before second command', () => {
|
|
const line1 = 'db.find()';
|
|
for (let q = 0; q <= 2; q++) {
|
|
const line2 = `db.insertOne({${wrapInQuotes('a', q)}:1})`;
|
|
const text = `${line1}\r\n\r\n\r\n${line2}`;
|
|
const commands: MongoCommand[] = getAllCommandsFromText(text);
|
|
const command: MongoCommand = findCommandAtPosition(commands, new Position(2, 0));
|
|
assert.equal(command.text, line1);
|
|
}
|
|
});
|
|
|
|
test('drop', () => {
|
|
testParse(`db.test.drop()`, { collection: 'test', name: 'drop', args: [] });
|
|
});
|
|
|
|
test('find, with empty object argument', () => {
|
|
testParse(`db.test.find({})`, { collection: 'test', name: 'find', args: [{}] });
|
|
});
|
|
|
|
test('end-of-line comment', () => {
|
|
testParse(`db.test.drop() // Ignore error "ns not found", it means "test" does not exist yet`, {
|
|
collection: 'test',
|
|
name: 'drop',
|
|
args: [],
|
|
});
|
|
});
|
|
|
|
test('multi-line insert from #214', () => {
|
|
for (let q = 0; q <= 2; q++) {
|
|
testParse(
|
|
`db.heroes.insert({\n${wrapInQuotes('id', q)}: 2,\r\n${wrapInQuotes('name', q)}: "Batman",\r\n\r\n${wrapInQuotes('saying', q)}: "I'm Batman"\r})`,
|
|
{
|
|
collection: 'heroes',
|
|
name: 'insert',
|
|
args: [
|
|
{
|
|
id: 2,
|
|
name: 'Batman',
|
|
saying: "I'm Batman",
|
|
},
|
|
],
|
|
},
|
|
);
|
|
}
|
|
});
|
|
|
|
test('find/project from #214', () => {
|
|
testParse(`db.heroes.find({ "id": 2 }, { "saying": 1 })`, {
|
|
collection: 'heroes',
|
|
name: 'find',
|
|
args: [
|
|
{
|
|
id: 2,
|
|
},
|
|
{
|
|
saying: 1,
|
|
},
|
|
],
|
|
});
|
|
});
|
|
|
|
test('extraneous input', () => {
|
|
testParse(
|
|
`db.heros.find();
|
|
hello there`,
|
|
{
|
|
collection: 'heros',
|
|
name: 'find',
|
|
args: [],
|
|
firstErrorText: "mismatched input 'hello' expecting <EOF>",
|
|
},
|
|
);
|
|
});
|
|
|
|
test('empty', () => {
|
|
testParse('// hello there', undefined);
|
|
});
|
|
|
|
test('no command found, errors (will be tacked on to a blank command)', () => {
|
|
testParse('hello there', {
|
|
collection: undefined,
|
|
name: undefined,
|
|
args: undefined,
|
|
firstErrorText: "mismatched input 'hello' expecting <EOF>",
|
|
});
|
|
});
|
|
|
|
test('expect error: missing comma in arguments', () => {
|
|
testParse(`db.heroes.find({ "id": 2 } { "saying": 1 })`, {
|
|
collection: 'heroes',
|
|
name: 'find',
|
|
args: [
|
|
{
|
|
id: 2,
|
|
},
|
|
],
|
|
firstErrorText: "mismatched input '{' expecting {',', ')'}",
|
|
});
|
|
|
|
testParse(`db.c.find({"a":[1,2,3]"b":1});`, {
|
|
collection: 'c',
|
|
name: 'find',
|
|
args: [{ a: [1, 2, 3] }],
|
|
firstErrorText: "mismatched input '\"b\"' expecting {',', '}'}",
|
|
});
|
|
});
|
|
|
|
//https://github.com/Microsoft/vscode-cosmosdb/issues/467
|
|
test('single quoted property names', () => {
|
|
testParse(`db.heroes.find({ 'id': 2 }, { 'saying': 1 })`, {
|
|
collection: 'heroes',
|
|
name: 'find',
|
|
args: [
|
|
{
|
|
id: 2,
|
|
},
|
|
{
|
|
saying: 1,
|
|
},
|
|
],
|
|
});
|
|
});
|
|
test('expect error: missing function name', () => {
|
|
// From https://github.com/Microsoft/vscode-cosmosdb/issues/659
|
|
testParse(`db.c1.`, {
|
|
collection: 'c1',
|
|
name: '',
|
|
args: [],
|
|
firstErrorText: "mismatched input '<EOF>' expecting IDENTIFIER",
|
|
});
|
|
|
|
testParse(`db.c1.;`, {
|
|
collection: 'c1',
|
|
name: '',
|
|
args: [],
|
|
firstErrorText: "mismatched input ';' expecting IDENTIFIER",
|
|
});
|
|
|
|
testParse(`db.c1.(1, "a");`, {
|
|
collection: 'c1',
|
|
name: '<missing IDENTIFIER>',
|
|
args: [1, 'a'],
|
|
firstErrorText: "missing IDENTIFIER at '('",
|
|
});
|
|
|
|
testParse(`..(1, "a");`, {
|
|
collection: undefined,
|
|
name: undefined,
|
|
args: undefined,
|
|
firstErrorText: "mismatched input '.' expecting <EOF>",
|
|
});
|
|
|
|
// Just make sure doesn't throw
|
|
expectSingleCommand(`db..(1, "a");`);
|
|
expectSingleCommand(`..c1(1, "a");`);
|
|
});
|
|
|
|
test('multi-line insert from #214', () => {
|
|
testParse(`db.heroes.insert({\n"id": 2,\r\n"name": "Batman",\r\n\r\n"saying": "I'm Batman"\r})`, {
|
|
collection: 'heroes',
|
|
name: 'insert',
|
|
args: [
|
|
{
|
|
id: 2,
|
|
name: 'Batman',
|
|
saying: "I'm Batman",
|
|
},
|
|
],
|
|
});
|
|
});
|
|
|
|
test('Array followed by } on separate line, from #73', () => {
|
|
testParse(
|
|
`db.createUser({
|
|
"user": "buddhi",
|
|
"pwd": "123",
|
|
"roles": ["readWrite", "dbAdmin"]
|
|
}
|
|
)`,
|
|
{
|
|
collection: undefined,
|
|
name: 'createUser',
|
|
args: [
|
|
{
|
|
user: 'buddhi',
|
|
pwd: '123',
|
|
roles: ['readWrite', 'dbAdmin'],
|
|
},
|
|
],
|
|
},
|
|
);
|
|
});
|
|
|
|
test('Multiple line arrays, from #489', () => {
|
|
testParse(
|
|
`
|
|
db.c2.insertMany([
|
|
{"name": "Stephen", "age": 38, "male": true},
|
|
{"name": "Stephen", "age": 38, "male": true}
|
|
])
|
|
`,
|
|
{
|
|
collection: 'c2',
|
|
name: 'insertMany',
|
|
args: [
|
|
[
|
|
{
|
|
name: 'Stephen',
|
|
age: 38,
|
|
male: true,
|
|
},
|
|
{
|
|
name: 'Stephen',
|
|
age: 38,
|
|
male: true,
|
|
},
|
|
],
|
|
],
|
|
},
|
|
);
|
|
});
|
|
|
|
test('test function call that has 2 arguments', () => {
|
|
const arg0 = `{"Age": 31}`;
|
|
const arg1 = `{"Name": true}`;
|
|
const text = `db.find(${arg0}\r\n,\r\n\r\n${arg1})`;
|
|
const commands: MongoCommand[] = getAllCommandsFromText(text);
|
|
const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0));
|
|
assert.deepEqual(JSON.parse(command.arguments![0]), JSON.parse(arg0));
|
|
assert.deepEqual(JSON.parse(command.arguments![1]), JSON.parse(arg1));
|
|
});
|
|
test('test function call with nested parameters - documents in an array', () => {
|
|
const arg0 = `[{"name": "a"}, {"name": "b"}, {"name": "c"}]`;
|
|
const arg1 = `{"ordered": true}`;
|
|
const text = `db.test1.insertMany(${arg0},\r\n\r\n\r\n${arg1})`;
|
|
const commands: MongoCommand[] = getAllCommandsFromText(text);
|
|
const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0));
|
|
assert.deepEqual(JSON.parse(command.arguments![0]), JSON.parse(arg0));
|
|
assert.deepEqual(JSON.parse(command.arguments![1]), JSON.parse(arg1));
|
|
});
|
|
test('test function call that has a nested parameter', () => {
|
|
const arg0 = `{"name": {"First" : "a", "Last":"b"} }`;
|
|
const text = `db.test1.insertMany(${arg0})`;
|
|
const commands: MongoCommand[] = getAllCommandsFromText(text);
|
|
const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0));
|
|
assert.deepEqual(JSON.parse(command.arguments![0]), JSON.parse(arg0));
|
|
});
|
|
test('test function call with erroneous syntax: missing comma', () => {
|
|
const arg0 = `{"name": {"First" : "a", "Last":"b"} }`;
|
|
const arg1 = `{"ordered": true}`;
|
|
const text = `db.test1.insertMany(${arg0} ${arg1})`;
|
|
const commands: MongoCommand[] = getAllCommandsFromText(text);
|
|
const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0));
|
|
const err = nonNullProp(command, 'errors')[0];
|
|
assert.deepEqual(err.message, "mismatched input '{' expecting {',', ')'}");
|
|
assert.deepEqual(err.range.start.line, 0);
|
|
assert.deepEqual(err.range.start.character, 61);
|
|
});
|
|
test('test function call with erroneous syntax: missing comma, parameters separated with newline', () => {
|
|
const arg0 = `{"name": {"First" : "a", "Last":"b"} }`;
|
|
const arg1 = `{"ordered": \ntrue}`;
|
|
const text = `db.test1.insertMany(${arg0} \n ${arg1})`;
|
|
const commands: MongoCommand[] = getAllCommandsFromText(text);
|
|
const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0));
|
|
const err = nonNullProp(command, 'errors')[0];
|
|
assert.deepEqual(err.message, "mismatched input '{' expecting {',', ')'}");
|
|
assert.deepEqual(err.range.start.line, 1);
|
|
assert.deepEqual(err.range.start.character, 2);
|
|
});
|
|
test('test function call with erroneous syntax: missing double quote', () => {
|
|
const text = `db.test1.insertMany({name": {"First" : "a", "Last":"b"} })`;
|
|
const commands: MongoCommand[] = getAllCommandsFromText(text);
|
|
const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0));
|
|
const err = nonNullProp(command, 'errors')[0];
|
|
assert.deepEqual(err.message, "missing ':' at '\": {\"'");
|
|
assert.deepEqual(err.range.start.line, 0);
|
|
assert.deepEqual(err.range.start.character, 25);
|
|
});
|
|
test('test function call with erroneous syntax: missing opening brace', () => {
|
|
const text = `db.test1.insertMany("name": {"First" : "a", "Last":"b"} })`;
|
|
const commands: MongoCommand[] = getAllCommandsFromText(text);
|
|
const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0));
|
|
const err = nonNullProp(command, 'errors')[0];
|
|
assert.deepEqual(err.message, "mismatched input ':' expecting {',', ')'}");
|
|
assert.deepEqual(err.range.start.line, 0);
|
|
assert.deepEqual(err.range.start.character, 26);
|
|
});
|
|
|
|
test('Chained command: to use pretty()', () => {
|
|
testParse('db.timesheets.find().pretty();', {
|
|
collection: 'timesheets',
|
|
name: 'pretty',
|
|
args: [],
|
|
});
|
|
});
|
|
|
|
test('ISODate with standard date string', () => {
|
|
testParse(
|
|
'db.c1.insertOne({ "_id": ObjectId("5aecf1a63d8af732f07e4275"), "name": "Stephen", "date": ISODate("2018-05-01T00:00:00Z") });',
|
|
{
|
|
collection: 'c1',
|
|
name: 'insertOne',
|
|
args: [
|
|
{
|
|
_id: {
|
|
$oid: '5aecf1a63d8af732f07e4275',
|
|
},
|
|
date: {
|
|
$date: '2018-05-01T00:00:00.000Z',
|
|
},
|
|
name: 'Stephen',
|
|
},
|
|
],
|
|
},
|
|
);
|
|
});
|
|
|
|
test('ISODate without Z in date string', () => {
|
|
testParse(
|
|
'db.c1.insertOne({ "_id": ObjectId("5aecf1a63d8af732f07e4275"), "name": "Stephen", "date": ISODate("2018-05-01T00:00:00") });',
|
|
{
|
|
collection: 'c1',
|
|
name: 'insertOne',
|
|
args: [
|
|
{
|
|
_id: {
|
|
$oid: '5aecf1a63d8af732f07e4275',
|
|
},
|
|
date: {
|
|
$date: '2018-05-01T00:00:00.000Z',
|
|
},
|
|
name: 'Stephen',
|
|
},
|
|
],
|
|
},
|
|
);
|
|
});
|
|
|
|
test('Invalid ISODate', () => {
|
|
testParse(
|
|
'db.c1.insertOne({ "_id": ObjectId("5aecf1a63d8af732f07e4275"), "name": "Stephen", "date": ISODate("2018-05-01T00:00:00z") });',
|
|
{
|
|
collection: 'c1',
|
|
name: 'insertOne',
|
|
args: [],
|
|
firstErrorText: 'Invalid time value',
|
|
},
|
|
);
|
|
});
|
|
|
|
test('Date', () => {
|
|
const date: Date = new Date('2018-05-01T00:00:00');
|
|
testParse(
|
|
`db.c1.insertOne({ "_id": ObjectId("5aecf1a63d8af732f07e4275"), "name": "Stephen", "date": Date("${date.toUTCString()}") });`,
|
|
{
|
|
collection: 'c1',
|
|
name: 'insertOne',
|
|
args: [
|
|
{
|
|
_id: {
|
|
$oid: '5aecf1a63d8af732f07e4275',
|
|
},
|
|
date: {
|
|
$date: date.toString(),
|
|
},
|
|
name: 'Stephen',
|
|
},
|
|
],
|
|
},
|
|
);
|
|
});
|
|
|
|
test('Keys with periods', () => {
|
|
testParse(
|
|
`db.timesheets.update( {
|
|
"year":"2018",
|
|
"month":"06"
|
|
},{
|
|
"$set":{
|
|
"workers.0.days.0.something":"yupy!"
|
|
}
|
|
});
|
|
`,
|
|
{
|
|
collection: 'timesheets',
|
|
name: 'update',
|
|
args: [
|
|
{
|
|
year: 2018,
|
|
month: '06',
|
|
},
|
|
{
|
|
$set: {
|
|
'workers.0.days.0.something': 'yupy!',
|
|
},
|
|
},
|
|
],
|
|
},
|
|
);
|
|
});
|
|
|
|
test('nested objects', () => {
|
|
testParse(
|
|
`db.users.update({},{
|
|
"$pull":{
|
|
"proposals":{
|
|
"$elemMatch":{"_id":"4qsBHLDCb755c3vPH"}
|
|
}
|
|
}
|
|
})`,
|
|
{
|
|
collection: 'users',
|
|
name: 'update',
|
|
args: [
|
|
{},
|
|
{
|
|
$pull: {
|
|
proposals: {
|
|
$elemMatch: {
|
|
_id: '4qsBHLDCb755c3vPH',
|
|
},
|
|
},
|
|
},
|
|
},
|
|
],
|
|
},
|
|
);
|
|
});
|
|
test('test function call with and without quotes', () => {
|
|
for (let q = 0; q <= 2; q++) {
|
|
const text = `db.test1.insertMany({${wrapInQuotes('name', q)}: 'First' })`;
|
|
const commands: MongoCommand[] = getAllCommandsFromText(text);
|
|
const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0));
|
|
assert.deepEqual(command.argumentObjects, [{ name: 'First' }]);
|
|
}
|
|
});
|
|
test('test function call with numbers', () => {
|
|
const text = `db.test1.insertMany({'name': 1010101})`;
|
|
const commands: MongoCommand[] = getAllCommandsFromText(text);
|
|
const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0));
|
|
assert.deepEqual(command.argumentObjects, [{ name: 1010101 }]);
|
|
});
|
|
test('test function call boolean', () => {
|
|
const text = `db.test1.insertMany({'name': false})`;
|
|
const commands: MongoCommand[] = getAllCommandsFromText(text);
|
|
const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0));
|
|
assert.deepEqual(command.argumentObjects, [{ name: false }]);
|
|
});
|
|
test('test function call token inside quotes', () => {
|
|
const text = `db.test1.insertMany({'name': 'false'})`;
|
|
const commands: MongoCommand[] = getAllCommandsFromText(text);
|
|
const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0));
|
|
assert.deepEqual(command.argumentObjects, [{ name: 'false' }]);
|
|
});
|
|
test('test function call with an empty string property value', () => {
|
|
const text = `db.test1.insertMany({'name': ''})`;
|
|
const commands: MongoCommand[] = getAllCommandsFromText(text);
|
|
const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0));
|
|
assert.deepEqual(command.argumentObjects, [{ name: '' }]);
|
|
});
|
|
test('test function call with array and multiple arguments', () => {
|
|
const text = `db.test1.find({'roles': ['readWrite', 'dbAdmin']}, {'resources': ['secondary', 'primary']})`;
|
|
const commands: MongoCommand[] = getAllCommandsFromText(text);
|
|
const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0));
|
|
assert.deepEqual(command.argumentObjects, [
|
|
{ roles: ['readWrite', 'dbAdmin'] },
|
|
{ resources: ['secondary', 'primary'] },
|
|
]);
|
|
});
|
|
test('test function call with nested objects', () => {
|
|
const text = `db.test1.find({'roles': [{'optional': 'yes'}]}, {'resources': ['secondary', 'primary']})`;
|
|
const commands: MongoCommand[] = getAllCommandsFromText(text);
|
|
const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0));
|
|
assert.deepEqual(command.argumentObjects, [
|
|
{ roles: [{ optional: 'yes' }] },
|
|
{ resources: ['secondary', 'primary'] },
|
|
]);
|
|
});
|
|
|
|
test('test incomplete function call - replicate user typing - no function call yet', () => {
|
|
const text = `db.test1.`;
|
|
const commands: MongoCommand[] = getAllCommandsFromText(text);
|
|
const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0));
|
|
assert.deepEqual(command.argumentObjects, []);
|
|
assert.deepEqual(command.collection, 'test1');
|
|
});
|
|
|
|
test('test incomplete function call - replicate user typing - missing propertyValue', () => {
|
|
const text = `db.test1.find({"name": {"First" : } })`;
|
|
const commands: MongoCommand[] = getAllCommandsFromText(text);
|
|
const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0));
|
|
assert.deepEqual(command.argumentObjects, [{ name: { First: {} } }]);
|
|
});
|
|
|
|
test('test incomplete function call - replicate user typing - missing colon & propertyValue', () => {
|
|
const text = `db.test1.find({"name": {"First" } })`;
|
|
const commands: MongoCommand[] = getAllCommandsFromText(text);
|
|
const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0));
|
|
assert.deepEqual(command.argumentObjects, [{ name: { First: {} } }]);
|
|
});
|
|
|
|
test('test incomplete function call - replicate user typing - empty array as argument', () => {
|
|
const text = `db.heroes.aggregate([\n])`;
|
|
const commands: MongoCommand[] = getAllCommandsFromText(text);
|
|
const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0));
|
|
assert.deepEqual(command.argumentObjects, [[]]);
|
|
});
|
|
|
|
test('test quotes inside a string - 1', () => {
|
|
const text = `db.test1.find("That's all")`;
|
|
const commands: MongoCommand[] = getAllCommandsFromText(text);
|
|
const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0));
|
|
assert.deepEqual(command.argumentObjects, ["That's all"]);
|
|
});
|
|
|
|
test('test quotes inside a string - 2', () => {
|
|
const text = `db.test1.find('That"s all')`;
|
|
const commands: MongoCommand[] = getAllCommandsFromText(text);
|
|
const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0));
|
|
assert.deepEqual(command.argumentObjects, ['That"s all']);
|
|
});
|
|
|
|
// Note: when escaping a character, escape it twice.
|
|
test('test quotes inside a string - 3', () => {
|
|
const text = `db.test1.find("Hello \\"there\\"")`;
|
|
const commands: MongoCommand[] = getAllCommandsFromText(text);
|
|
const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0));
|
|
assert.deepEqual(command.argumentObjects, ['Hello \\"there\\"']);
|
|
});
|
|
|
|
test('test quotes inside a string - 4', () => {
|
|
const text = `db.test1.find('Hello \\'there\\'')`;
|
|
const commands: MongoCommand[] = getAllCommandsFromText(text);
|
|
const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0));
|
|
assert.deepEqual(command.argumentObjects, ["Hello \\'there\\'"]);
|
|
});
|
|
|
|
test('test nested property names (has dots in the name)', () => {
|
|
const text = `db.test1.find({"name.FirstName": 1})`;
|
|
const commands: MongoCommand[] = getAllCommandsFromText(text);
|
|
const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0));
|
|
assert.deepEqual(command.argumentObjects, [{ 'name.FirstName': 1 }]);
|
|
});
|
|
|
|
test('test managed namespace collection names (has dots in the name)', () => {
|
|
const text = `db.test1.beep.find({})`;
|
|
const commands: MongoCommand[] = getAllCommandsFromText(text);
|
|
const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0));
|
|
assert.deepEqual(command.collection, 'test1.beep');
|
|
});
|
|
|
|
test('test aggregate query', () => {
|
|
for (let q = 0; q <= 2; q++) {
|
|
const text = `db.orders.aggregate([
|
|
{ ${wrapInQuotes('$match', q)}: { ${wrapInQuotes('status', q)} : "A" } },
|
|
{ ${wrapInQuotes('$group', q)}: { ${wrapInQuotes('_id', q)}: "$cust_id", ${wrapInQuotes('total', q)}: { ${wrapInQuotes('$sum', q)}: "$amount" } } },
|
|
{ ${wrapInQuotes('$sort', q)}: { ${wrapInQuotes('total', q)}: -1 } }
|
|
],
|
|
{
|
|
${wrapInQuotes('cursor', q)}: { ${wrapInQuotes('batchSize', q)}: 0 }
|
|
})`;
|
|
const commands: MongoCommand[] = getAllCommandsFromText(text);
|
|
const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0));
|
|
assert.deepEqual(command.collection, 'orders');
|
|
assert.deepEqual(command.argumentObjects, [
|
|
[
|
|
{ $match: { status: 'A' } },
|
|
{ $group: { _id: '$cust_id', total: { $sum: '$amount' } } },
|
|
{ $sort: { total: -1 } },
|
|
],
|
|
{
|
|
cursor: { batchSize: 0 },
|
|
},
|
|
]);
|
|
}
|
|
});
|
|
|
|
test('test ObjectID - no parameter', () => {
|
|
const text = `db.c1.insert({"name": ObjectId()})`;
|
|
const commands: MongoCommand[] = getAllCommandsFromText(text);
|
|
const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0));
|
|
assert.deepEqual(command.collection, 'c1');
|
|
assert.ok((<any>nonNullProp(command, 'argumentObjects')[0]).name instanceof ObjectId);
|
|
});
|
|
|
|
test('test ObjectID - hex', () => {
|
|
const idParam = 'abcdef123456789012345678';
|
|
const text = `db.c1.insert({"name": ObjectId("${idParam}")})`;
|
|
const commands: MongoCommand[] = getAllCommandsFromText(text);
|
|
const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0));
|
|
assert.deepEqual(command.collection, 'c1');
|
|
const id = new ObjectId(idParam);
|
|
assert.deepEqual(command.argumentObjects, [{ name: id }]);
|
|
});
|
|
|
|
test('test faulty ObjectID - hex - extra characters', () => {
|
|
const idParam = 'abcdef12345678901234567890';
|
|
const text = `db.c1.insert({"name": ObjectId("${idParam}")})`;
|
|
const commands: MongoCommand[] = getAllCommandsFromText(text);
|
|
const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0));
|
|
assert.deepEqual(command.collection, 'c1');
|
|
assert.deepEqual(command.argumentObjects, [{ name: {} }]);
|
|
assert.notStrictEqual(nonNullProp(command, 'errors')[0]?.message, undefined);
|
|
});
|
|
|
|
test('test faulty ObjectID - hex - fewer characters', () => {
|
|
const idParam = 'abcdef123456789012345';
|
|
for (let i = 1; i < 3; i++) {
|
|
const text = `db.c1.insert({"name": ObjectId(${wrapInQuotes(idParam, i)})})`;
|
|
const commands: MongoCommand[] = getAllCommandsFromText(text);
|
|
const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0));
|
|
assert.deepEqual(command.collection, 'c1');
|
|
assert.deepEqual(command.argumentObjects, [{ name: {} }]);
|
|
assert.notStrictEqual(nonNullProp(command, 'errors')[0]?.message, undefined);
|
|
}
|
|
});
|
|
//Examples inspired from https://docs.mongodb.com/manual/reference/operator/query/regex/
|
|
test('test regular expressions - only pattern, no flags', () => {
|
|
const text = `db.test1.beep.find({ sku: /789$/ })`;
|
|
const commands: MongoCommand[] = getAllCommandsFromText(text);
|
|
const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0));
|
|
const generatedRegExp = (<any>nonNullProp(command, 'argumentObjects')[0]).sku;
|
|
assert.deepEqual(generatedRegExp.options, '');
|
|
assert.deepEqual(generatedRegExp.pattern, '789$');
|
|
});
|
|
|
|
test('test regular expressions - pattern and flags', () => {
|
|
const text = `db.test1.beep.find({ sku: /789$/i } )`;
|
|
const commands: MongoCommand[] = getAllCommandsFromText(text);
|
|
const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0));
|
|
const generatedRegExp = (<any>nonNullProp(command, 'argumentObjects')[0]).sku;
|
|
console.log('generatedRegExp', generatedRegExp);
|
|
assert.deepEqual(generatedRegExp.options, 'i');
|
|
assert.deepEqual(generatedRegExp.pattern, '789$');
|
|
});
|
|
|
|
test('test regular expressions - Intellisense - flag contains unsupported option', () => {
|
|
const text = `db.test1.beep.find({ sku: /789$/g })`;
|
|
try {
|
|
const commands: MongoCommand[] = getAllCommandsFromText(text);
|
|
findCommandAtPosition(commands, new Position(0, 0));
|
|
} catch (error) {
|
|
const err = parseError(error);
|
|
assert.deepEqual('Unexpected node encountered', err.message);
|
|
}
|
|
});
|
|
|
|
test('test regular expressions - Intellisense - flag contains invalid option', () => {
|
|
const text = `db.test1.beep.find({ sku: /789$/q })`;
|
|
try {
|
|
const commands: MongoCommand[] = getAllCommandsFromText(text);
|
|
findCommandAtPosition(commands, new Position(0, 0));
|
|
} catch (error) {
|
|
const err = parseError(error);
|
|
assert.deepEqual('Unexpected node encountered', err.message);
|
|
}
|
|
});
|
|
|
|
test('test regular expressions - wrong escape - throw error', () => {
|
|
const text = `db.test1.beep.find({ sku: /789$\\/b\\/q })`;
|
|
try {
|
|
const commands: MongoCommand[] = getAllCommandsFromText(text);
|
|
findCommandAtPosition(commands, new Position(0, 0));
|
|
} catch (error) {
|
|
assert.equal(error.message, 'Invalid regular expression: /789$\\/b\\/: \\ at end of pattern');
|
|
}
|
|
});
|
|
|
|
//Passing the following test should imply the rest of the tests pass too.
|
|
// The regex parsing tests following this test should help zero-in on which case isn't handled properly.
|
|
test('test regular expression parsing - with many special cases', () => {
|
|
const text = `db.test1.beep.find({ sku: /^(hello?= world).*[^0-9]+|(world\\b\\*){0,2}$/ })`;
|
|
console.log(text);
|
|
const commands: MongoCommand[] = getAllCommandsFromText(text);
|
|
console.log('commands', commands);
|
|
const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0));
|
|
console.log('command', command);
|
|
const generatedRegExp = (<any>nonNullProp(command, 'argumentObjects')[0]).sku;
|
|
assert.deepEqual(generatedRegExp.options, '');
|
|
assert.deepEqual(generatedRegExp.pattern, '^(hello?= world).*[^0-9]+|(world\\b\\*){0,2}$');
|
|
});
|
|
|
|
test('test regular expression parsing EJSON syntax - with many special cases', () => {
|
|
const text = `db.test1.beep.find({ sku: {$regex: "^(hello?= world).*[^0-9]+|(world\\\\b\\\\*){0,2}$"} })`;
|
|
const commands: MongoCommand[] = getAllCommandsFromText(text);
|
|
const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0));
|
|
const generatedRegExp = (<any>nonNullProp(command, 'argumentObjects')[0]).sku;
|
|
assert.deepEqual(generatedRegExp.options, '');
|
|
assert.deepEqual(generatedRegExp.pattern, '^(hello?= world).*[^0-9]+|(world\\b\\*){0,2}$');
|
|
});
|
|
|
|
test('test regular expression parsing interoperability', () => {
|
|
const text1 = `db.test1.beep.find({ sku: /^(hello?= world).*[^0-9]+|(world\\b\\*){0,2}$/ })`;
|
|
const commands1: MongoCommand[] = getAllCommandsFromText(text1);
|
|
const command1: MongoCommand = findCommandAtPosition(commands1, new Position(0, 0));
|
|
const generatedRegExp1 = (<any>nonNullProp(command1, 'argumentObjects')[0]).sku;
|
|
const text2 = `db.test1.beep.find({ sku: {$regex: "^(hello?= world).*[^0-9]+|(world\\\\b\\\\*){0,2}$"} })`;
|
|
const commands2: MongoCommand[] = getAllCommandsFromText(text2);
|
|
const command2: MongoCommand = findCommandAtPosition(commands2, new Position(0, 0));
|
|
const generatedRegExp2 = (<any>nonNullProp(command2, 'argumentObjects')[0]).sku;
|
|
assert.deepEqual(
|
|
[generatedRegExp1.options, generatedRegExp1.pattern],
|
|
['', '^(hello?= world).*[^0-9]+|(world\\b\\*){0,2}$'],
|
|
);
|
|
assert.deepEqual(
|
|
[generatedRegExp2.options, generatedRegExp2.pattern],
|
|
['', '^(hello?= world).*[^0-9]+|(world\\b\\*){0,2}$'],
|
|
);
|
|
});
|
|
|
|
test('test regular expression parsing interoperability - word break', () => {
|
|
const text1 = `db.test1.beep.find({ sku: /ker\\b/ })`; // equivalent to user typing out /ker\b/
|
|
const commands1: MongoCommand[] = getAllCommandsFromText(text1);
|
|
const command1: MongoCommand = findCommandAtPosition(commands1, new Position(0, 0));
|
|
const generatedRegExp1 = (<any>nonNullProp(command1, 'argumentObjects')[0]).sku;
|
|
const text2 = `db.test1.beep.find({ sku: {$regex: "ker\\\\b"} })`;
|
|
const commands2: MongoCommand[] = getAllCommandsFromText(text2);
|
|
const command2: MongoCommand = findCommandAtPosition(commands2, new Position(0, 0));
|
|
const generatedRegExp2 = (<any>nonNullProp(command2, 'argumentObjects')[0]).sku;
|
|
assert.deepEqual([generatedRegExp1.options, generatedRegExp1.pattern], ['', 'ker\\b']);
|
|
assert.deepEqual([generatedRegExp2.options, generatedRegExp2.pattern], ['', 'ker\\b']);
|
|
});
|
|
|
|
test('test regular expression parsing interoperability - newline', () => {
|
|
const text1 = `db.test1.beep.find({ sku: /ker\\n/ })`; // equivalent to user typing out /ker\n/
|
|
const commands1: MongoCommand[] = getAllCommandsFromText(text1);
|
|
const command1: MongoCommand = findCommandAtPosition(commands1, new Position(0, 0));
|
|
const generatedRegExp1 = (<any>nonNullProp(command1, 'argumentObjects')[0]).sku;
|
|
const text2 = `db.test1.beep.find({ sku: {$regex: "ker\\\\n"} })`;
|
|
const commands2: MongoCommand[] = getAllCommandsFromText(text2);
|
|
const command2: MongoCommand = findCommandAtPosition(commands2, new Position(0, 0));
|
|
const generatedRegExp2 = (<any>nonNullProp(command2, 'argumentObjects')[0]).sku;
|
|
assert.deepEqual([generatedRegExp2.options, generatedRegExp2.pattern], ['', 'ker\\n']);
|
|
assert.deepEqual([generatedRegExp1.options, generatedRegExp1.pattern], ['', 'ker\\n']);
|
|
});
|
|
test('test regular expression parsing interoperability - carriage return', () => {
|
|
const text1 = `db.test1.beep.find({ sku: /ker\\r/ })`; // equivalent to user typing out /ker\r/
|
|
const commands1: MongoCommand[] = getAllCommandsFromText(text1);
|
|
const command1: MongoCommand = findCommandAtPosition(commands1, new Position(0, 0));
|
|
const generatedRegExp1 = (<any>nonNullProp(command1, 'argumentObjects')[0]).sku;
|
|
const text2 = `db.test1.beep.find({ sku: {$regex: "ker\\\\r"} })`;
|
|
const commands2: MongoCommand[] = getAllCommandsFromText(text2);
|
|
const command2: MongoCommand = findCommandAtPosition(commands2, new Position(0, 0));
|
|
const generatedRegExp2 = (<any>nonNullProp(command2, 'argumentObjects')[0]).sku;
|
|
assert.deepEqual([generatedRegExp1.options, generatedRegExp1.pattern], ['', 'ker\\r']);
|
|
assert.deepEqual([generatedRegExp2.options, generatedRegExp2.pattern], ['', 'ker\\r']);
|
|
});
|
|
|
|
test('test regular expressions - only pattern, no flags', () => {
|
|
const text = `db.test1.beep.find({ sku: { $regex: "789$" } })`;
|
|
const commands: MongoCommand[] = getAllCommandsFromText(text);
|
|
const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0));
|
|
const generatedRegExp = (<any>nonNullProp(command, 'argumentObjects')[0]).sku;
|
|
assert.deepEqual(generatedRegExp.options, '');
|
|
assert.deepEqual(generatedRegExp.pattern, '789$');
|
|
});
|
|
|
|
test('test regular expressions - pattern and flags', () => {
|
|
const text = `db.test1.beep.find({ sku: { $regex: "789$", $options:"i" } })`;
|
|
const commands: MongoCommand[] = getAllCommandsFromText(text);
|
|
const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0));
|
|
const generatedRegExp = (<any>nonNullProp(command, 'argumentObjects')[0]).sku;
|
|
assert.deepEqual(generatedRegExp.options, 'i');
|
|
assert.deepEqual(generatedRegExp.pattern, '789$');
|
|
});
|
|
|
|
test('test regular expressions - Intellisense - flag contains invalid option', () => {
|
|
const text = `db.test1.beep.find({ sku: { $regex: "789$", $options:"q" } })`;
|
|
const commands: MongoCommand[] = getAllCommandsFromText(text);
|
|
const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0));
|
|
assert.notStrictEqual(nonNullProp(command, 'errors')[0]?.message, undefined);
|
|
assert.deepEqual(nonNullProp(command, 'errors')[0].range.start.character, 19);
|
|
});
|
|
|
|
test('test regular expression parsing - with groupings', () => {
|
|
const text = `db.test1.beep.find({ sku: /(?:hello)\\3/ })`;
|
|
const commands: MongoCommand[] = getAllCommandsFromText(text);
|
|
const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0));
|
|
const generatedRegExp = (<any>nonNullProp(command, 'argumentObjects')[0]).sku;
|
|
assert.deepEqual(generatedRegExp.options, '');
|
|
assert.deepEqual(generatedRegExp.pattern, '(?:hello)\\3');
|
|
});
|
|
|
|
test('test regular expression parsing - with special characters', () => {
|
|
const text = `db.test1.beep.find({ sku: /(hello)*(world)?(name)+./ })`;
|
|
const commands: MongoCommand[] = getAllCommandsFromText(text);
|
|
const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0));
|
|
const generatedRegExp = (<any>nonNullProp(command, 'argumentObjects')[0]).sku;
|
|
assert.deepEqual(generatedRegExp.options, '');
|
|
assert.deepEqual(generatedRegExp.pattern, '(hello)*(world)?(name)+.');
|
|
});
|
|
|
|
test('test regular expression parsing - with boundaries', () => {
|
|
const text = `db.test1.beep.find({ sku: /^(hello world)[^0-9]|(world\\b)$/ })`;
|
|
const commands: MongoCommand[] = getAllCommandsFromText(text);
|
|
const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0));
|
|
const generatedRegExp = (<any>nonNullProp(command, 'argumentObjects')[0]).sku;
|
|
assert.deepEqual(generatedRegExp.options, '');
|
|
assert.deepEqual(generatedRegExp.pattern, '^(hello world)[^0-9]|(world\\b)$');
|
|
});
|
|
|
|
test('test regular expression parsing - with quantifiers', () => {
|
|
const text = `db.test1.beep.find({ sku: /(hello)*[^0-9]+|(world){0,2}./ })`;
|
|
const commands: MongoCommand[] = getAllCommandsFromText(text);
|
|
const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0));
|
|
const generatedRegExp = (<any>nonNullProp(command, 'argumentObjects')[0]).sku;
|
|
assert.deepEqual(generatedRegExp.options, '');
|
|
assert.deepEqual(generatedRegExp.pattern, '(hello)*[^0-9]+|(world){0,2}.');
|
|
});
|
|
|
|
test('test regular expression parsing - with conditional', () => {
|
|
const text = `db.test1.beep.find({ sku: /(hello?= world)|(world)/ })`;
|
|
const commands: MongoCommand[] = getAllCommandsFromText(text);
|
|
const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0));
|
|
const generatedRegExp = (<any>nonNullProp(command, 'argumentObjects')[0]).sku;
|
|
assert.deepEqual(generatedRegExp.options, '');
|
|
assert.deepEqual(generatedRegExp.pattern, '(hello?= world)|(world)');
|
|
});
|
|
|
|
test('test regular expression parsing - with escaped special characters', () => {
|
|
const text = `db.test1.beep.find({ sku: /world\\*\\.\\?\\+/ })`;
|
|
const commands: MongoCommand[] = getAllCommandsFromText(text);
|
|
const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0));
|
|
const generatedRegExp = (<any>nonNullProp(command, 'argumentObjects')[0]).sku;
|
|
assert.deepEqual(generatedRegExp.options, '');
|
|
assert.deepEqual(generatedRegExp.pattern, 'world\\*\\.\\?\\+');
|
|
});
|
|
|
|
test('test chained command: argument aggregation', () => {
|
|
testParse('db.timesheets.find({name: "Andy", surname: "Jackson"}).pretty();', {
|
|
collection: 'timesheets',
|
|
name: 'pretty',
|
|
args: [{ name: 'Andy', surname: 'Jackson' }],
|
|
});
|
|
});
|
|
|
|
test('Chained command - order of parsed arguments', () => {
|
|
testParse('db.timesheets.find({name:"Andy"}).sort({age: 1}).skip(40);', {
|
|
collection: 'timesheets',
|
|
name: 'skip',
|
|
args: [{ name: 'Andy' }, { age: 1 }, 40],
|
|
});
|
|
});
|
|
|
|
test('Chained command - missing period', () => {
|
|
testParse('db.timesheets.find({name:"Andy"}).sort({age: 1})skip(40);', {
|
|
collection: 'timesheets',
|
|
name: 'sort',
|
|
args: [{ name: 'Andy' }, { age: 1 }],
|
|
firstErrorText: "mismatched input 'skip' expecting <EOF>",
|
|
});
|
|
});
|
|
|
|
test('Chained command - mid-type - missing bracket', () => {
|
|
testParse('db.timesheets.find({name:"Andy"}).sort', {
|
|
collection: 'timesheets',
|
|
name: 'sort',
|
|
args: [{ name: 'Andy' }],
|
|
firstErrorText: "mismatched input '<EOF>' expecting '('",
|
|
});
|
|
});
|
|
|
|
test('Chained command - mid-type - typed the dot, but not the function call', () => {
|
|
testParse('db.timesheets.find({name:"Andy"}).', {
|
|
collection: 'timesheets',
|
|
name: '',
|
|
args: [{ name: 'Andy' }],
|
|
firstErrorText: "mismatched input '<EOF>' expecting IDENTIFIER",
|
|
});
|
|
});
|
|
|
|
//TODO: Tests to simulate cases where the user hasn't completed typing
|
|
|
|
test('test user issues: https://github.com/Microsoft/vscode-cosmosdb/issues/688', () => {
|
|
for (let q = 0; q <= 2; q++) {
|
|
const text = `db.hdr.aggregate([
|
|
{ ${wrapInQuotes('$match', q)}: { "CURRENCY_ID": "USD" } },
|
|
])`; //Note the trailing comma. There should be 1 argument object returned, an array, that has 2 elements
|
|
//one expected, and another empty object.
|
|
const commands: MongoCommand[] = getAllCommandsFromText(text);
|
|
const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0));
|
|
assert.deepEqual(command.collection, 'hdr');
|
|
assert.deepEqual(command.argumentObjects, [[{ $match: { CURRENCY_ID: 'USD' } }, {}]]);
|
|
}
|
|
});
|
|
|
|
test('Chained command- test user issues: https://github.com/Microsoft/vscode-cosmosdb/issues/785', () => {
|
|
testParse('db.timesheets.find({name:"Andy"}).count();', {
|
|
collection: 'timesheets',
|
|
name: 'count',
|
|
args: [{ name: 'Andy' }],
|
|
});
|
|
});
|
|
|
|
test('Chained command- test user issues: https://github.com/Microsoft/vscode-cosmosdb/issues/795', () => {
|
|
testParse('db.timesheets.find({}).limit(10);', {
|
|
collection: 'timesheets',
|
|
name: 'limit',
|
|
args: [{}, 10],
|
|
});
|
|
});
|
|
|
|
test('Chained command alternative for rs.slaveOk()- test user issues: https://github.com/Microsoft/vscode-cosmosdb/issues/565', () => {
|
|
testParse('db.getMongo().setSlaveOk();', {
|
|
collection: '',
|
|
name: 'setSlaveOk',
|
|
args: [],
|
|
});
|
|
});
|
|
|
|
test('Multiple line command, from #489', () => {
|
|
testParse(
|
|
`
|
|
db.finalists.find({name: "Jefferson"})
|
|
.
|
|
limit
|
|
(10);
|
|
`,
|
|
{
|
|
collection: 'finalists',
|
|
name: 'limit',
|
|
args: [
|
|
{
|
|
name: 'Jefferson',
|
|
},
|
|
10,
|
|
],
|
|
},
|
|
);
|
|
});
|
|
|
|
test('test user issues: https://github.com/Microsoft/vscode-cosmosdb/issues/703', () => {
|
|
for (let q = 0; q <= 2; q++) {
|
|
const text = `db.Users.find({ ${wrapInQuotes('user', q)}: { ${wrapInQuotes('$in', q)}: [ "A80", "HPA" ] } },{ ${wrapInQuotes('_id', q)}: false });`;
|
|
const commands: MongoCommand[] = getAllCommandsFromText(text);
|
|
const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0));
|
|
assert.deepEqual(command.collection, 'Users');
|
|
assert.deepEqual(command.argumentObjects, [{ user: { $in: ['A80', 'HPA'] } }, { _id: false }]);
|
|
}
|
|
});
|
|
|
|
test('test user issues: https://github.com/Microsoft/vscode-cosmosdb/issues/691', () => {
|
|
for (let q = 0; q <= 2; q++) {
|
|
const text = `db.users.aggregate([
|
|
{ ${wrapInQuotes('$match', q)}: {${wrapInQuotes('_id', q)}: {"$oid" :"5b23d2ba92b52cf794bdeb9c")}}},
|
|
{ ${wrapInQuotes('$project', q)}: {
|
|
${wrapInQuotes('scores', q)}: {${wrapInQuotes('$filter', q)}: {
|
|
${wrapInQuotes('input', q)}: '$scores',
|
|
${wrapInQuotes('as', q)}: 'score',
|
|
${wrapInQuotes('cond', q)}: {${wrapInQuotes('$gt', q)}: ['$$score', 3]}
|
|
}}
|
|
}}
|
|
])`;
|
|
const commands: MongoCommand[] = getAllCommandsFromText(text);
|
|
const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0));
|
|
assert.deepEqual(command.collection, 'users');
|
|
assert.deepEqual(nonNullProp(command, 'argumentObjects')[0][0], {
|
|
$match: { _id: new ObjectId('5b23d2ba92b52cf794bdeb9c') },
|
|
});
|
|
assert.deepEqual(nonNullProp(command, 'argumentObjects')[0][1], {
|
|
$project: {
|
|
scores: {
|
|
$filter: {
|
|
input: '$scores',
|
|
as: 'score',
|
|
cond: { $gt: ['$$score', 3] },
|
|
},
|
|
},
|
|
},
|
|
});
|
|
}
|
|
});
|
|
|
|
test('test user issues: https://github.com/Microsoft/vscode-cosmosdb/issues/717', () => {
|
|
for (let q = 0; q <= 2; q++) {
|
|
const text = `db.Users.find({${wrapInQuotes('age', q)} : { ${wrapInQuotes('$in', q)} : [19, 20, 22, 25]}});`;
|
|
const commands: MongoCommand[] = getAllCommandsFromText(text);
|
|
const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0));
|
|
assert.deepEqual(command.collection, 'Users');
|
|
assert.deepEqual(command.argumentObjects, [{ age: { $in: [19, 20, 22, 25] } }]);
|
|
}
|
|
});
|
|
|
|
test('test user issues: https://github.com/Microsoft/vscode-cosmosdb/issues/737', () => {
|
|
const text = `db.c1.insert({},f)`;
|
|
const commands: MongoCommand[] = getAllCommandsFromText(text);
|
|
const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0));
|
|
assert.deepEqual(command.collection, 'c1');
|
|
assert.deepEqual(command.argumentObjects, [{}, {}]);
|
|
assert.deepEqual(
|
|
nonNullProp(command, 'errors')[0].message,
|
|
"mismatched input 'f' expecting {'{', '[', RegexLiteral, StringLiteral, 'null', BooleanLiteral, NumericLiteral}",
|
|
);
|
|
});
|
|
|
|
test('test user issues: https://github.com/Microsoft/vscode-cosmosdb/issues/899 - multi-line comment, not regex', () => {
|
|
for (const escape of ['\n', '\r', '\n\r', '\r\n']) {
|
|
const text = `db.heroes.count()${escape}/*db.c2.insertMany([${escape}{"name": "Stephen", "age": 38, "male": true},${escape}{"name": "Stephen", "age": 38, "male": true}${escape}]);${escape}*/${escape}${escape}db.heroes.find();`;
|
|
const commands = getAllCommandsFromText(text);
|
|
assert.equal(commands.length, 2, `Error in parsing ${text}`);
|
|
assert.equal(commands[0].name, 'count');
|
|
assert.equal(commands[1].name, 'find');
|
|
}
|
|
});
|
|
});
|