[console] porting console tests to Jest (#19543)

* porting console tests to Jest

* adding missing import
This commit is contained in:
Bill McConaghy 2018-06-04 11:23:59 -04:00 committed by GitHub
parent ff601039b0
commit 55c65a7c62
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
44 changed files with 3686 additions and 5908 deletions

View file

@ -277,6 +277,7 @@
"istanbul-instrumenter-loader": "3.0.0",
"jest": "^22.4.3",
"jest-cli": "^22.4.3",
"jest-raw-loader": "^1.0.1",
"jimp": "0.2.28",
"jsdom": "9.9.1",
"karma": "1.7.0",

View file

@ -19,7 +19,6 @@
import Boom from 'boom';
import { resolveApi } from './api_server/server';
import { existsSync } from 'fs';
import { resolve, join, sep } from 'path';
import { has, isEmpty } from 'lodash';
import setHeaders from '../elasticsearch/lib/set_headers';
@ -36,17 +35,6 @@ export default function (kibana) {
const src = resolve(__dirname, 'public/src/');
const apps = [];
if (existsSync(resolve(__dirname, 'public/tests'))) {
apps.push({
title: 'Console Tests',
id: 'sense-tests',
main: 'plugins/console/tests',
hidden: true
//listed: false // uncomment after https://github.com/elastic/kibana/pull/4755
});
}
return new kibana.Plugin({
id: 'console',
require: [ 'elasticsearch' ],
@ -135,17 +123,6 @@ export default function (kibana) {
return resolveApi(version, apis.split(','), reply);
}
});
const testApp = server.getHiddenUiAppById('sense-tests');
if (testApp) {
server.route({
path: '/app/sense-tests',
method: 'GET',
handler: function (req, reply) {
return reply.renderApp(testApp);
}
});
}
},
uiExports: {

View file

@ -20,7 +20,7 @@
import uiRoutes from 'ui/routes';
import template from './index.html';
require('ace');
require('brace');
require('ui-bootstrap-custom');
require('ui/modules').get('kibana', ['sense.ui.bootstrap']);

View file

@ -16,5 +16,3 @@
* specific language governing permissions and limitations
* under the License.
*/
import './tests';

View file

@ -27,7 +27,7 @@ import utils from './utils';
import { populateContext } from './autocomplete/engine';
import { URL_PATH_END_MARKER } from './autocomplete/url_pattern_matcher';
import _ from 'lodash';
import ace from 'ace';
import ace from 'brace';
import 'brace/ext/language_tools';
const AceRange = ace.acequire('ace/range').Range;
@ -250,7 +250,7 @@ export default function (editor) {
function getAutoCompleteType(pos) {
// return "method", "path" or "body" to determine auto complete type.
let rowMode = editor.parser.getRowParseMode(pos.row);
let rowMode = editor.parser.getRowParseMode();
//noinspection JSBitwiseOperatorUsage
if (rowMode & editor.parser.MODE.IN_REQUEST) {

View file

@ -18,7 +18,7 @@
*/
const $ = require('jquery');
require('ace');
require('brace');
require('brace/ext/searchbox');
const Autocomplete = require('./autocomplete');
const SenseEditor = require('./sense_editor/editor');
@ -33,8 +33,12 @@ export function initializeInput($el, $actionsEl, $copyAsCurlEl, output) {
input = new SenseEditor($el);
// this may not exist if running from tests
const appSense = uiModules.get('app/sense');
appSense.setupResizeCheckerForRootEditors($el, input, output);
if (uiModules) {
const appSense = uiModules.get('app/sense');
if (appSense && appSense.setupResizeCheckerForRootEditors) {
appSense.setupResizeCheckerForRootEditors($el, input, output);
}
}
input.autocomplete = new Autocomplete(input);

View file

@ -18,7 +18,7 @@
*/
import _ from 'lodash';
const ace = require('ace');
const ace = require('brace');
const settings = require('./settings');
const OutputMode = require('./sense_editor/mode/output');
const smartResize = require('./smart_resize');

View file

@ -18,7 +18,7 @@
*/
const _ = require('lodash');
const ace = require('ace');
const ace = require('brace');
const $ = require('jquery');
const curl = require('../curl');
const RowParser = require('./row_parser');

View file

@ -17,7 +17,7 @@
* under the License.
*/
import ace from 'ace';
import ace from 'brace';
const oop = ace.acequire('ace/lib/oop');
const TextMode = ace.acequire('ace/mode/text').Mode;

View file

@ -17,7 +17,7 @@
* under the License.
*/
const ace = require('ace');
const ace = require('brace');
import { addToRules } from './x_json_highlight_rules';
const oop = ace.acequire('ace/lib/oop');

View file

@ -17,7 +17,7 @@
* under the License.
*/
const ace = require('ace');
const ace = require('brace');
require('./output_highlight_rules');

View file

@ -17,7 +17,8 @@
* under the License.
*/
const ace = require('ace');
const ace = require('brace');
import 'brace/mode/json';
import { addToRules } from './x_json_highlight_rules';
const oop = ace.acequire('ace/lib/oop');

View file

@ -17,7 +17,7 @@
* under the License.
*/
import ace from 'ace';
import ace from 'brace';
const oop = ace.acequire('ace/lib/oop');
const TextMode = ace.acequire('ace/mode/text').Mode;

View file

@ -18,7 +18,7 @@
*/
const ace = require('ace');
const ace = require('brace');
const oop = ace.acequire('ace/lib/oop');
const { TextHighlightRules } = ace.acequire('ace/mode/text_highlight_rules');
const painlessKeywords = (

View file

@ -20,7 +20,7 @@
/* eslint import/no-unresolved: 0 */
/* eslint no-multi-str: 0 */
/* eslint max-len: 0 */
const ace = require('ace');
const ace = require('brace');
ace.define('ace/theme/sense-dark', ['require', 'exports', 'module'],
function (require, exports) {

View file

@ -74,6 +74,6 @@ class Storage {
}
}
const instance = new Storage(localStorage, 'sense:');
const instance = new Storage(window.localStorage, 'sense:');
export default instance;

View file

@ -1,36 +0,0 @@
<style type="text/css">
#editor_container {
display: none;
position: absolute;
top: 20px;
bottom: 20px;
left: 20px;
right: 20px;
z-index: 200;
border: 1px solid #333;
}
#output_container {
display: none;
position: absolute;
height: 250px;
width: 350px;
bottom: 20px;
right: 20px;
z-index: 201;
border: 1px solid #333;
}
#editor, #output {
height: 100%;
width: 100%;
position: relative;
}
</style>
<div id="qunit"></div>
<div id="editor_container">
<div id="editor"></div>
</div>
<div id="output_container">
<div id="output"></div>
</div>

View file

@ -19,27 +19,25 @@
import { getContentType } from '../../src/es';
const { test, module, equal } = window.QUnit;
const APPLICATION_JSON = 'application/json';
describe('Content type', () => {
test('body', () => {
const contentType = getContentType([
JSON.stringify({
foo: 'baz'
}),
JSON.stringify({
foo: 'bar'
})
].join('\n'));
module('Content type');
expect(contentType).toEqual(APPLICATION_JSON);
});
test('body', () => {
const contentType = getContentType([
JSON.stringify({
foo: 'baz'
}),
JSON.stringify({
foo: 'bar'
})
].join('\n'));
test('no body', () => {
const contentType = getContentType('');
equal(contentType, APPLICATION_JSON);
expect(contentType).toBeUndefined();
});
});
test('no body', () => {
const contentType = getContentType('');
equal(contentType, undefined);
});

View file

@ -19,37 +19,35 @@
const _ = require('lodash');
const curl = require('../../src/curl');
const curlTests = require('raw-loader!./curl_parsing_tests.txt');
import curlTests from './curl_parsing.txt';
const { test, module, ok, equal } = window.QUnit;
describe('CURL', () => {
const notCURLS = [
'sldhfsljfhs',
's;kdjfsldkfj curl -XDELETE ""',
'{ "hello": 1 }'
];
_.each(notCURLS, function (notCURL, i) {
test('cURL Detection - broken strings ' + i, function () {
expect(curl.detectCURL(notCURL)).toEqual(false);
});
});
module('CURL');
curlTests.split(/^=+$/m).forEach(function (fixture) {
if (fixture.trim() === '') {
return;
}
fixture = fixture.split(/^-+$/m);
const name = fixture[0].trim();
const curlText = fixture[1];
const response = fixture[2].trim();
const notCURLS = [
'sldhfsljfhs',
's;kdjfsldkfj curl -XDELETE ""',
'{ "hello": 1 }'
];
_.each(notCURLS, function (notCURL, i) {
test('cURL Detection - broken strings ' + i, function () {
ok(!curl.detectCURL(notCURL), 'marked as curl while it wasn\'t:' + notCURL);
test('cURL Detection - ' + name, function () {
expect(curl.detectCURL(curlText)).toBe(true);
const r = curl.parseCURL(curlText);
expect(r).toEqual(response);
});
});
});
_.each(curlTests.split(/^=+$/m), function (fixture) {
if (fixture.trim() === '') {
return;
}
fixture = fixture.split(/^-+$/m);
const name = fixture[0].trim();
const curlText = fixture[1];
const response = fixture[2].trim();
test('cURL Detection - ' + name, function () {
ok(curl.detectCURL(curlText), 'marked as not curl while it was:' + curlText);
const r = curl.parseCURL(curlText);
equal(r, response);
});
});

View file

@ -0,0 +1,498 @@
/*
* Licensed to Elasticsearch B.V. under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch B.V. licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import './setup_mocks';
import $ from 'jquery';
import _ from 'lodash';
import ace from 'brace';
import 'brace/mode/json';
import { initializeInput } from '../../src/input';
const editorInput1 = require('./editor_input1.txt');
const utils = require('../../src/utils');
const aceRange = ace.acequire('ace/range');
describe('Editor', () => {
let input;
beforeEach(function () {
// Set up our document body
document.body.innerHTML =
`<div>
<div id="editor" />
<div id="editor_actions" />
<div id="copy_as_curl" />
</div>`;
input = initializeInput(
$('#editor'),
$('#editor_actions'),
$('#copy_as_curl'),
null
);
input.$el.show();
input.autocomplete._test.removeChangeListener();
});
afterEach(function () {
input.$el.hide();
input.autocomplete._test.addChangeListener();
});
let testCount = 0;
function utilsTest(name, prefix, data, testToRun) {
const id = testCount++;
if (typeof data === 'function') {
testToRun = data;
data = null;
}
if (data && typeof data !== 'string') {
data = JSON.stringify(data, null, 3);
}
if (data) {
if (prefix) {
data = prefix + '\n' + data;
}
} else {
data = prefix;
}
test('Utils test ' + id + ' : ' + name, async function (done) {
input.update(data, function () {
testToRun();
done();
});
});
}
function compareRequest(requests, expected) {
if (!Array.isArray(requests)) {
requests = [requests];
expected = [expected];
}
_.each(requests, function (r) {
delete r.range;
});
expect(requests).toEqual(expected);
}
const simpleRequest = {
prefix: 'POST _search',
data: ['{', ' "query": { "match_all": {} }', '}'].join('\n'),
};
const singleLineRequest = {
prefix: 'POST _search',
data: '{ "query": { "match_all": {} } }',
};
const getRequestNoData = {
prefix: 'GET _stats',
};
const multiDocRequest = {
prefix: 'POST _bulk',
data_as_array: [
'{ "index": { "_index": "index", "_type":"type" } }',
'{ "field": 1 }',
],
};
multiDocRequest.data = multiDocRequest.data_as_array.join('\n');
utilsTest(
'simple request range',
simpleRequest.prefix,
simpleRequest.data,
function () {
input.getRequestRange(function (range) {
const expected = new aceRange.Range(0, 0, 3, 1);
compareRequest(range, expected);
});
}
);
utilsTest(
'simple request data',
simpleRequest.prefix,
simpleRequest.data,
function () {
input.getRequest(function (request) {
const expected = {
method: 'POST',
url: '_search',
data: [simpleRequest.data],
};
compareRequest(request, expected);
});
}
);
utilsTest(
'simple request range, prefixed with spaces',
' ' + simpleRequest.prefix,
simpleRequest.data,
function () {
input.getRequestRange(function (range) {
const expected = new aceRange.Range(0, 0, 3, 1);
expect(range).toEqual(expected);
});
}
);
utilsTest(
'simple request data, prefixed with spaces',
' ' + simpleRequest.prefix,
simpleRequest.data,
function () {
input.getRequest(function (request) {
const expected = {
method: 'POST',
url: '_search',
data: [simpleRequest.data],
};
compareRequest(request, expected);
});
}
);
utilsTest(
'simple request range, suffixed with spaces',
simpleRequest.prefix + ' ',
simpleRequest.data + ' ',
function () {
input.getRequestRange(function (range) {
const expected = new aceRange.Range(0, 0, 3, 1);
compareRequest(range, expected);
});
}
);
utilsTest(
'simple request data, suffixed with spaces',
simpleRequest.prefix + ' ',
simpleRequest.data + ' ',
function () {
input.getRequest(function (request) {
const expected = {
method: 'POST',
url: '_search',
data: [simpleRequest.data],
};
compareRequest(request, expected);
});
}
);
utilsTest(
'single line request range',
singleLineRequest.prefix,
singleLineRequest.data,
function () {
input.getRequestRange(function (range) {
const expected = new aceRange.Range(0, 0, 1, 32);
compareRequest(range, expected);
});
}
);
utilsTest(
'full url: single line request data',
'POST https://somehoset/_search',
singleLineRequest.data,
function () {
input.getRequest(function (request) {
const expected = {
method: 'POST',
url: 'https://somehoset/_search',
data: [singleLineRequest.data],
};
compareRequest(request, expected);
});
}
);
utilsTest(
'request with no data followed by a new line',
getRequestNoData.prefix,
'\n',
function () {
input.getRequestRange(function (range) {
const expected = new aceRange.Range(0, 0, 0, 10);
compareRequest(range, expected);
});
}
);
utilsTest(
'request with no data followed by a new line (data)',
getRequestNoData.prefix,
'\n',
function () {
input.getRequest(function (request) {
const expected = {
method: 'GET',
url: '_stats',
data: [],
};
compareRequest(request, expected);
});
}
);
utilsTest(
'request with no data',
getRequestNoData.prefix,
getRequestNoData.data,
function () {
input.getRequestRange(function (range) {
const expected = new aceRange.Range(0, 0, 0, 10);
expect(range).toEqual(expected);
});
}
);
utilsTest(
'request with no data (data)',
getRequestNoData.prefix,
getRequestNoData.data,
function () {
input.getRequest(function (request) {
const expected = {
method: 'GET',
url: '_stats',
data: [],
};
compareRequest(request, expected);
});
}
);
utilsTest(
'multi doc request range',
multiDocRequest.prefix,
multiDocRequest.data,
function () {
input.getRequestRange(function (range) {
const expected = new aceRange.Range(0, 0, 2, 14);
expect(range).toEqual(expected);
});
}
);
utilsTest(
'multi doc request data',
multiDocRequest.prefix,
multiDocRequest.data,
function () {
input.getRequest(function (request) {
const expected = {
method: 'POST',
url: '_bulk',
data: multiDocRequest.data_as_array,
};
compareRequest(request, expected);
});
}
);
const scriptRequest = {
prefix: 'POST _search',
data: [
'{',
' "query": { "script": """',
' some script ',
' """}',
'}',
].join('\n'),
};
utilsTest(
'script request range',
scriptRequest.prefix,
scriptRequest.data,
function () {
input.getRequestRange(function (range) {
const expected = new aceRange.Range(0, 0, 5, 1);
compareRequest(range, expected);
});
}
);
utilsTest(
'simple request data',
simpleRequest.prefix,
simpleRequest.data,
function () {
input.getRequest(function (request) {
const expected = {
method: 'POST',
url: '_search',
data: [utils.collapseLiteralStrings(simpleRequest.data)],
};
compareRequest(request, expected);
});
}
);
function multiReqTest(name, editorInput, range, expected) {
utilsTest('multi request select - ' + name, editorInput, function () {
input.getRequestsInRange(range, function (requests) {
// convert to format returned by request.
_.each(expected, function (req) {
req.data =
req.data == null ? [] : [JSON.stringify(req.data, null, 2)];
});
compareRequest(requests, expected);
});
});
}
multiReqTest(
'mid body to mid body',
editorInput1,
{ start: { row: 12 }, end: { row: 17 } },
[
{
method: 'PUT',
url: 'index_1/type1/1',
data: {
f: 1,
},
},
{
method: 'PUT',
url: 'index_1/type1/2',
data: {
f: 2,
},
},
]
);
multiReqTest(
'single request start to end',
editorInput1,
{ start: { row: 10 }, end: { row: 13 } },
[
{
method: 'PUT',
url: 'index_1/type1/1',
data: {
f: 1,
},
},
]
);
multiReqTest(
'start to end, with comment',
editorInput1,
{ start: { row: 6 }, end: { row: 13 } },
[
{
method: 'GET',
url: '_stats?level=shards',
data: null,
},
{
method: 'PUT',
url: 'index_1/type1/1',
data: {
f: 1,
},
},
]
);
multiReqTest(
'before start to after end, with comments',
editorInput1,
{ start: { row: 4 }, end: { row: 14 } },
[
{
method: 'GET',
url: '_stats?level=shards',
data: null,
},
{
method: 'PUT',
url: 'index_1/type1/1',
data: {
f: 1,
},
},
]
);
multiReqTest(
'between requests',
editorInput1,
{ start: { row: 21 }, end: { row: 22 } },
[]
);
multiReqTest(
'between requests - with comment',
editorInput1,
{ start: { row: 20 }, end: { row: 22 } },
[]
);
multiReqTest(
'between requests - before comment',
editorInput1,
{ start: { row: 19 }, end: { row: 22 } },
[]
);
function multiReqCopyAsCurlTest(name, editorInput, range, expected) {
utilsTest('multi request copy as curl - ' + name, editorInput, function () {
input.getRequestsAsCURL(range, function (curl) {
expect(curl).toEqual(expected);
});
});
}
multiReqCopyAsCurlTest(
'start to end, with comment',
editorInput1,
{ start: { row: 6 }, end: { row: 13 } },
`
curl -XGET "http://localhost:9200/_stats?level=shards"
#in between comment
curl -XPUT "http://localhost:9200/index_1/type1/1" -H 'Content-Type: application/json' -d'
{
"f": 1
}'`.trim()
);
});

View file

@ -1,413 +0,0 @@
/*
* Licensed to Elasticsearch B.V. under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch B.V. licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import $ from 'jquery';
import _ from 'lodash';
const ace = require('ace');
import { initializeInput } from '../../src/input';
const editorInput1 = require('raw-loader!./editor_input1.txt');
const utils = require('../../src/utils');
const aceRange = ace.acequire('ace/range');
const { module, asyncTest, deepEqual, equal, start } = window.QUnit;
let input;
module('Editor', {
setup: function () {
input = initializeInput($('#editor'), $('#editor_actions'), $('#copy_as_curl'), null);
input.$el.show();
input.autocomplete._test.removeChangeListener();
},
teardown: function () {
input.$el.hide();
input.autocomplete._test.addChangeListener();
}
});
let testCount = 0;
function utilsTest(name, prefix, data, test) {
const id = testCount++;
if (typeof data === 'function') {
test = data;
data = null;
}
if (data && typeof data !== 'string') {
data = JSON.stringify(data, null, 3);
}
if (data) {
if (prefix) {
data = prefix + '\n' + data;
}
}
else {
data = prefix;
}
asyncTest('Utils test ' + id + ' : ' + name, function () {
input.update(data, function () {
test();
});
});
}
function compareRequest(requests, expected) {
if (!Array.isArray(requests)) {
requests = [requests];
expected = [expected];
}
_.each(requests, function (r) {
delete r.range;
});
deepEqual(requests, expected);
}
const simpleRequest = {
prefix: 'POST _search',
data: [
'{',
' "query": { "match_all": {} }',
'}'
].join('\n')
};
const singleLineRequest =
{
prefix: 'POST _search',
data: '{ "query": { "match_all": {} } }'
};
const getRequestNoData = {
prefix: 'GET _stats'
};
const multiDocRequest = {
prefix: 'POST _bulk',
data_as_array: [
'{ "index": { "_index": "index", "_type":"type" } }',
'{ "field": 1 }'
]
};
multiDocRequest.data = multiDocRequest.data_as_array.join('\n');
utilsTest('simple request range', simpleRequest.prefix, simpleRequest.data, function () {
input.getRequestRange(function (range) {
const expected = new aceRange.Range(
0, 0,
3, 1
);
compareRequest(range, expected);
start();
});
});
utilsTest('simple request data', simpleRequest.prefix, simpleRequest.data, function () {
input.getRequest(function (request) {
const expected = {
method: 'POST',
url: '_search',
data: [ simpleRequest.data]
};
compareRequest(request, expected);
start();
});
});
utilsTest('simple request range, prefixed with spaces', ' ' + simpleRequest.prefix, simpleRequest.data, function () {
input.getRequestRange(function (range) {
const expected = new aceRange.Range(
0, 0,
3, 1
);
deepEqual(range, expected);
start();
});
});
utilsTest('simple request data, prefixed with spaces', ' ' + simpleRequest.prefix, simpleRequest.data, function () {
input.getRequest(function (request) {
const expected = {
method: 'POST',
url: '_search',
data: [ simpleRequest.data]
};
compareRequest(request, expected);
start();
});
});
utilsTest('simple request range, suffixed with spaces', simpleRequest.prefix + ' ', simpleRequest.data + ' ', function () {
input.getRequestRange(function (range) {
const expected = new aceRange.Range(
0, 0,
3, 1
);
compareRequest(range, expected);
start();
});
});
utilsTest('simple request data, suffixed with spaces', simpleRequest.prefix + ' ', simpleRequest.data + ' ', function () {
input.getRequest(function (request) {
const expected = {
method: 'POST',
url: '_search',
data: [ simpleRequest.data]
};
compareRequest(request, expected);
start();
});
});
utilsTest('single line request range', singleLineRequest.prefix, singleLineRequest.data, function () {
input.getRequestRange(function (range) {
const expected = new aceRange.Range(
0, 0,
1, 32
);
compareRequest(range, expected);
start();
});
});
utilsTest('full url: single line request data', 'POST https://somehoset/_search', singleLineRequest.data, function () {
input.getRequest(function (request) {
const expected = {
method: 'POST',
url: 'https://somehoset/_search',
data: [singleLineRequest.data]
};
compareRequest(request, expected);
start();
});
});
utilsTest('request with no data followed by a new line', getRequestNoData.prefix, '\n', function () {
input.getRequestRange(function (range) {
const expected = new aceRange.Range(
0, 0,
0, 10
);
compareRequest(range, expected);
start();
});
});
utilsTest('request with no data followed by a new line (data)', getRequestNoData.prefix, '\n', function () {
input.getRequest(function (request) {
const expected = {
method: 'GET',
url: '_stats',
data: []
};
compareRequest(request, expected);
start();
});
});
utilsTest('request with no data', getRequestNoData.prefix, getRequestNoData.data, function () {
input.getRequestRange(function (range) {
const expected = new aceRange.Range(
0, 0,
0, 10
);
deepEqual(range, expected);
start();
});
});
utilsTest('request with no data (data)', getRequestNoData.prefix, getRequestNoData.data, function () {
input.getRequest(function (request) {
const expected = {
method: 'GET',
url: '_stats',
data: []
};
compareRequest(request, expected);
start();
});
});
utilsTest('multi doc request range', multiDocRequest.prefix, multiDocRequest.data, function () {
input.getRequestRange(function (range) {
const expected = new aceRange.Range(
0, 0,
2, 14
);
deepEqual(range, expected);
start();
});
});
utilsTest('multi doc request data', multiDocRequest.prefix, multiDocRequest.data, function () {
input.getRequest(function (request) {
const expected = {
method: 'POST',
url: '_bulk',
data: multiDocRequest.data_as_array
};
compareRequest(request, expected);
start();
});
});
const scriptRequest = {
prefix: 'POST _search',
data: [
'{',
' "query": { "script": """',
' some script ',
' """}',
'}'
].join('\n')
};
utilsTest('script request range', scriptRequest.prefix, scriptRequest.data, function () {
input.getRequestRange(function (range) {
const expected = new aceRange.Range(
0, 0,
5, 1
);
compareRequest(range, expected);
start();
});
});
utilsTest('simple request data', simpleRequest.prefix, simpleRequest.data, function () {
input.getRequest(function (request) {
const expected = {
method: 'POST',
url: '_search',
data: [ utils.collapseLiteralStrings(simpleRequest.data) ]
};
compareRequest(request, expected);
start();
});
});
function multiReqTest(name, editorInput, range, expected) {
utilsTest('multi request select - ' + name, editorInput, function () {
input.getRequestsInRange(range, function (requests) {
// convert to format returned by request.
_.each(expected, function (req) {
req.data = req.data == null ? [] : [JSON.stringify(req.data, null, 2)];
});
compareRequest(requests, expected);
start();
});
});
}
multiReqTest('mid body to mid body', editorInput1,
{ start: { row: 12 }, end: { row: 17 } }, [{
method: 'PUT',
url: 'index_1/type1/1',
data: {
'f': 1
}
}, {
method: 'PUT',
url: 'index_1/type1/2',
data: {
'f': 2
}
}]);
multiReqTest('single request start to end', editorInput1,
{ start: { row: 10 }, end: { row: 13 } }, [{
method: 'PUT',
url: 'index_1/type1/1',
data: {
'f': 1
}
}]);
multiReqTest('start to end, with comment', editorInput1,
{ start: { row: 6 }, end: { row: 13 } }, [{
method: 'GET',
url: '_stats?level=shards',
data: null
},
{
method: 'PUT',
url: 'index_1/type1/1',
data: {
'f': 1
}
}]);
multiReqTest('before start to after end, with comments', editorInput1,
{ start: { row: 4 }, end: { row: 14 } }, [{
method: 'GET',
url: '_stats?level=shards',
data: null
},
{
method: 'PUT',
url: 'index_1/type1/1',
data: {
'f': 1
}
}]);
multiReqTest('between requests', editorInput1,
{ start: { row: 21 }, end: { row: 22 } }, []);
multiReqTest('between requests - with comment', editorInput1,
{ start: { row: 20 }, end: { row: 22 } }, []);
multiReqTest('between requests - before comment', editorInput1,
{ start: { row: 19 }, end: { row: 22 } }, []);
function multiReqCopyAsCurlTest(name, editorInput, range, expected) {
utilsTest('multi request copy as curl - ' + name, editorInput, function () {
input.getRequestsAsCURL(range, function (curl) {
equal(curl, expected);
start();
});
});
}
multiReqCopyAsCurlTest('start to end, with comment', editorInput1,
{ start: { row: 6 }, end: { row: 13 } }, `
curl -XGET "http://localhost:9200/_stats?level=shards"
#in between comment
curl -XPUT "http://localhost:9200/index_1/type1/1" -H 'Content-Type: application/json' -d'
{
"f": 1
}'`.trim()
);

View file

@ -0,0 +1,410 @@
/*
* Licensed to Elasticsearch B.V. under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch B.V. licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import './setup_mocks';
import ace from 'brace';
import 'brace/mode/json';
const $ = require('jquery');
import { initializeInput } from '../../src/input';
const tokenIterator = ace.acequire('ace/token_iterator');
describe('Input Tokenization', () => {
let input;
beforeEach(() => {
// Set up our document body
document.body.innerHTML =
`<div>
<div id="editor" />
<div id="editor_actions" />
<div id="copy_as_curl" />
</div>`;
input = initializeInput(
$('#editor'),
$('#editor_actions'),
$('#copy_as_curl'),
null
);
input = initializeInput($('#editor'), $('#editor_actions'), $('#copy_as_curl'), null);
input.$el.show();
input.autocomplete._test.removeChangeListener();
});
afterEach(() => {
input.$el.hide();
input.autocomplete._test.addChangeListener();
});
function tokensAsList() {
const iter = new tokenIterator.TokenIterator(input.getSession(), 0, 0);
const ret = [];
let t = iter.getCurrentToken();
if (input.parser.isEmptyToken(t)) {
t = input.parser.nextNonEmptyToken(iter);
}
while (t) {
ret.push({ value: t.value, type: t.type });
t = input.parser.nextNonEmptyToken(iter);
}
return ret;
}
let testCount = 0;
function tokenTest(tokenList, prefix, data) {
if (data && typeof data !== 'string') {
data = JSON.stringify(data, null, 3);
}
if (data) {
if (prefix) {
data = prefix + '\n' + data;
}
}
else {
data = prefix;
}
test('Token test ' + testCount++ + ' prefix: ' + prefix, async function (done) {
input.update(data, function () {
const tokens = tokensAsList();
const normTokenList = [];
for (let i = 0; i < tokenList.length; i++) {
normTokenList.push({ type: tokenList[i++], value: tokenList[i] });
}
expect(tokens).toEqual(normTokenList);
done();
});
});
}
tokenTest(
['method', 'GET', 'url.part', '_search'],
'GET _search'
);
tokenTest(
['method', 'GET', 'url.slash', '/', 'url.part', '_search'],
'GET /_search'
);
tokenTest(
['method', 'GET', 'url.protocol_host', 'http://somehost', 'url.slash', '/', 'url.part', '_search'],
'GET http://somehost/_search'
);
tokenTest(
['method', 'GET', 'url.protocol_host', 'http://somehost'],
'GET http://somehost'
);
tokenTest(
['method', 'GET', 'url.protocol_host', 'http://somehost', 'url.slash', '/'],
'GET http://somehost/'
);
tokenTest(
['method', 'GET', 'url.protocol_host', 'http://test:user@somehost', 'url.slash', '/'],
'GET http://test:user@somehost/'
);
tokenTest(
['method', 'GET', 'url.part', '_cluster', 'url.slash', '/', 'url.part', 'nodes'],
'GET _cluster/nodes'
);
tokenTest(
['method', 'GET', 'url.slash', '/', 'url.part', '_cluster', 'url.slash', '/', 'url.part', 'nodes'],
'GET /_cluster/nodes'
);
tokenTest(
['method', 'GET', 'url.part', 'index', 'url.slash', '/', 'url.part', '_search'],
'GET index/_search'
);
tokenTest(
['method', 'GET', 'url.part', 'index'],
'GET index'
);
tokenTest(
['method', 'GET', 'url.part', 'index', 'url.slash', '/', 'url.part', 'type'],
'GET index/type'
);
tokenTest(
['method', 'GET', 'url.slash', '/', 'url.part', 'index', 'url.slash', '/', 'url.part', 'type', 'url.slash', '/'],
'GET /index/type/'
);
tokenTest(
['method', 'GET', 'url.part', 'index', 'url.slash', '/', 'url.part', 'type', 'url.slash', '/', 'url.part', '_search'],
'GET index/type/_search'
);
tokenTest(
['method', 'GET', 'url.part', 'index', 'url.slash', '/', 'url.part', 'type', 'url.slash', '/', 'url.part', '_search',
'url.questionmark', '?', 'url.param', 'value', 'url.equal', '=', 'url.value', '1'
],
'GET index/type/_search?value=1'
);
tokenTest(
['method', 'GET', 'url.part', 'index', 'url.slash', '/', 'url.part', 'type', 'url.slash', '/', 'url.part', '1'],
'GET index/type/1'
);
tokenTest(
['method', 'GET', 'url.slash', '/', 'url.part', 'index1', 'url.comma', ',', 'url.part', 'index2', 'url.slash', '/'],
'GET /index1,index2/'
);
tokenTest(
['method', 'GET', 'url.slash', '/', 'url.part', 'index1', 'url.comma', ',', 'url.part', 'index2', 'url.slash', '/',
'url.part', '_search'],
'GET /index1,index2/_search'
);
tokenTest(
['method', 'GET', 'url.part', 'index1', 'url.comma', ',', 'url.part', 'index2', 'url.slash', '/',
'url.part', '_search'],
'GET index1,index2/_search'
);
tokenTest(
['method', 'GET', 'url.slash', '/', 'url.part', 'index1', 'url.comma', ',', 'url.part', 'index2'],
'GET /index1,index2'
);
tokenTest(
['method', 'GET', 'url.part', 'index1', 'url.comma', ',', 'url.part', 'index2'],
'GET index1,index2'
);
tokenTest(
['method', 'GET', 'url.slash', '/', 'url.part', 'index1', 'url.comma', ','],
'GET /index1,'
);
tokenTest(
['method', 'PUT', 'url.slash', '/', 'url.part', 'index', 'url.slash', '/'],
'PUT /index/'
);
tokenTest(
['method', 'GET', 'url.part', 'index', 'url.slash', '/', 'url.part', '_search'],
'GET index/_search '
);
tokenTest(
['method', 'PUT', 'url.slash', '/', 'url.part', 'index'],
'PUT /index'
);
tokenTest(
['method', 'PUT', 'url.slash', '/', 'url.part', 'index1', 'url.comma', ',', 'url.part', 'index2',
'url.slash', '/', 'url.part', 'type1', 'url.comma', ',', 'url.part', 'type2'],
'PUT /index1,index2/type1,type2'
);
tokenTest(
['method', 'PUT', 'url.slash', '/', 'url.part', 'index1',
'url.slash', '/', 'url.part', 'type1', 'url.comma', ',', 'url.part', 'type2', 'url.comma', ','],
'PUT /index1/type1,type2,'
);
tokenTest(
['method', 'PUT', 'url.part', 'index1', 'url.comma', ',', 'url.part', 'index2',
'url.slash', '/', 'url.part', 'type1', 'url.comma', ',', 'url.part', 'type2', 'url.slash', '/',
'url.part', '1234'],
'PUT index1,index2/type1,type2/1234'
);
tokenTest(
['method', 'POST', 'url.part', '_search', 'paren.lparen', '{', 'variable', '"q"', 'punctuation.colon', ':',
'paren.lparen', '{', 'paren.rparen', '}', 'paren.rparen', '}'
],
'POST _search\n' +
'{\n' +
' "q": {}\n' +
' \n' +
'}'
);
tokenTest(
['method', 'POST', 'url.part', '_search', 'paren.lparen', '{', 'variable', '"q"', 'punctuation.colon', ':',
'paren.lparen', '{', 'variable', '"s"', 'punctuation.colon', ':', 'paren.lparen', '{', 'paren.rparen', '}',
'paren.rparen', '}', 'paren.rparen', '}'
],
'POST _search\n' +
'{\n' +
' "q": { "s": {}}\n' +
' \n' +
'}'
);
function statesAsList() {
const ret = [];
const session = input.getSession();
const maxLine = session.getLength();
for (let row = 0; row < maxLine; row++) ret.push(session.getState(row));
return ret;
}
function statesTest(statesList, prefix, data) {
if (data && typeof data !== 'string') {
data = JSON.stringify(data, null, 3);
}
if (data) {
if (prefix) {
data = prefix + '\n' + data;
}
}
else {
data = prefix;
}
test('States test ' + testCount++ + ' prefix: ' + prefix, async function (done) {
input.update(data, function () {
const modes = statesAsList();
expect(modes).toEqual(statesList);
done();
});
});
}
statesTest(
['start', 'json', 'json', 'start'],
'POST _search\n' +
'{\n' +
' "query": { "match_all": {} }\n' +
'}'
);
statesTest(
['start', 'json', ['json', 'json'], ['json', 'json'], 'json', 'start'],
'POST _search\n' +
'{\n' +
' "query": { \n' +
' "match_all": {} \n' +
' }\n' +
'}'
);
statesTest(
['start', 'json', 'json', 'start'],
'POST _search\n' +
'{\n' +
' "script": { "inline": "" }\n' +
'}'
);
statesTest(
['start', 'json', 'json', 'start'],
'POST _search\n' +
'{\n' +
' "script": ""\n' +
'}'
);
statesTest(
['start', 'json', ['json', 'json'], 'json', 'start'],
'POST _search\n' +
'{\n' +
' "script": {\n' +
' }\n' +
'}'
);
statesTest(
['start', 'json', ['script-start', 'json', 'json', 'json'], ['script-start', 'json', 'json', 'json'],
['json', 'json'], 'json', 'start'],
'POST _search\n' +
'{\n' +
' "test": { "script": """\n' +
' test script\n' +
' """\n' +
' }\n' +
'}'
);
statesTest(
['start', 'json', ['script-start', 'json'], ['script-start', 'json'], 'json', 'start'],
'POST _search\n' +
'{\n' +
' "script": """\n' +
' test script\n' +
' """,\n' +
'}'
);
statesTest(
['start', 'json', 'json', 'start'],
'POST _search\n' +
'{\n' +
' "script": """test script""",\n' +
'}'
);
statesTest(
['start', 'json', ['string_literal', 'json'], ['string_literal', 'json'], 'json', 'start'],
'POST _search\n' +
'{\n' +
' "somthing": """\n' +
' test script\n' +
' """,\n' +
'}'
);
statesTest(
['start', 'json', ['string_literal', 'json', 'json', 'json'], ['string_literal', 'json', 'json', 'json'],
['json', 'json'], ['json', 'json'],
'json', 'start'],
'POST _search\n' +
'{\n' +
' "somthing": { "f" : """\n' +
' test script\n' +
' """,\n' +
' "g": 1\n' +
' }\n' +
'}'
);
statesTest(
['start', 'json', 'json', 'start'],
'POST _search\n' +
'{\n' +
' "something": """test script""",\n' +
'}'
);
});

View file

@ -1,395 +0,0 @@
/*
* Licensed to Elasticsearch B.V. under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch B.V. licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
const ace = require('ace');
const $ = require('jquery');
import { initializeInput } from '../../src/input';
let input;
const tokenIterator = ace.acequire('ace/token_iterator');
const { module, asyncTest, deepEqual, start } = window.QUnit;
module('Input Tokenization', {
setup: function () {
input = initializeInput($('#editor'), $('#editor_actions'), $('#copy_as_curl'), null);
input.$el.show();
input.autocomplete._test.removeChangeListener();
},
teardown: function () {
input.$el.hide();
input.autocomplete._test.addChangeListener();
}
});
function tokensAsList() {
const iter = new tokenIterator.TokenIterator(input.getSession(), 0, 0);
const ret = [];
let t = iter.getCurrentToken();
if (input.parser.isEmptyToken(t)) {
t = input.parser.nextNonEmptyToken(iter);
}
while (t) {
ret.push({ value: t.value, type: t.type });
t = input.parser.nextNonEmptyToken(iter);
}
return ret;
}
let testCount = 0;
function tokenTest(tokenList, prefix, data) {
if (data && typeof data !== 'string') {
data = JSON.stringify(data, null, 3);
}
if (data) {
if (prefix) {
data = prefix + '\n' + data;
}
}
else {
data = prefix;
}
asyncTest('Token test ' + testCount++ + ' prefix: ' + prefix, function () {
input.update(data, function () {
const tokens = tokensAsList();
const normTokenList = [];
for (let i = 0; i < tokenList.length; i++) {
normTokenList.push({ type: tokenList[i++], value: tokenList[i] });
}
deepEqual(tokens, normTokenList, 'Doc:\n' + data);
start();
});
});
}
tokenTest(
['method', 'GET', 'url.part', '_search'],
'GET _search'
);
tokenTest(
['method', 'GET', 'url.slash', '/', 'url.part', '_search'],
'GET /_search'
);
tokenTest(
['method', 'GET', 'url.protocol_host', 'http://somehost', 'url.slash', '/', 'url.part', '_search'],
'GET http://somehost/_search'
);
tokenTest(
['method', 'GET', 'url.protocol_host', 'http://somehost'],
'GET http://somehost'
);
tokenTest(
['method', 'GET', 'url.protocol_host', 'http://somehost', 'url.slash', '/'],
'GET http://somehost/'
);
tokenTest(
['method', 'GET', 'url.protocol_host', 'http://test:user@somehost', 'url.slash', '/'],
'GET http://test:user@somehost/'
);
tokenTest(
['method', 'GET', 'url.part', '_cluster', 'url.slash', '/', 'url.part', 'nodes'],
'GET _cluster/nodes'
);
tokenTest(
['method', 'GET', 'url.slash', '/', 'url.part', '_cluster', 'url.slash', '/', 'url.part', 'nodes'],
'GET /_cluster/nodes'
);
tokenTest(
['method', 'GET', 'url.part', 'index', 'url.slash', '/', 'url.part', '_search'],
'GET index/_search'
);
tokenTest(
['method', 'GET', 'url.part', 'index'],
'GET index'
);
tokenTest(
['method', 'GET', 'url.part', 'index', 'url.slash', '/', 'url.part', 'type'],
'GET index/type'
);
tokenTest(
['method', 'GET', 'url.slash', '/', 'url.part', 'index', 'url.slash', '/', 'url.part', 'type', 'url.slash', '/'],
'GET /index/type/'
);
tokenTest(
['method', 'GET', 'url.part', 'index', 'url.slash', '/', 'url.part', 'type', 'url.slash', '/', 'url.part', '_search'],
'GET index/type/_search'
);
tokenTest(
['method', 'GET', 'url.part', 'index', 'url.slash', '/', 'url.part', 'type', 'url.slash', '/', 'url.part', '_search',
'url.questionmark', '?', 'url.param', 'value', 'url.equal', '=', 'url.value', '1'
],
'GET index/type/_search?value=1'
);
tokenTest(
['method', 'GET', 'url.part', 'index', 'url.slash', '/', 'url.part', 'type', 'url.slash', '/', 'url.part', '1'],
'GET index/type/1'
);
tokenTest(
['method', 'GET', 'url.slash', '/', 'url.part', 'index1', 'url.comma', ',', 'url.part', 'index2', 'url.slash', '/'],
'GET /index1,index2/'
);
tokenTest(
['method', 'GET', 'url.slash', '/', 'url.part', 'index1', 'url.comma', ',', 'url.part', 'index2', 'url.slash', '/',
'url.part', '_search'],
'GET /index1,index2/_search'
);
tokenTest(
['method', 'GET', 'url.part', 'index1', 'url.comma', ',', 'url.part', 'index2', 'url.slash', '/',
'url.part', '_search'],
'GET index1,index2/_search'
);
tokenTest(
['method', 'GET', 'url.slash', '/', 'url.part', 'index1', 'url.comma', ',', 'url.part', 'index2'],
'GET /index1,index2'
);
tokenTest(
['method', 'GET', 'url.part', 'index1', 'url.comma', ',', 'url.part', 'index2'],
'GET index1,index2'
);
tokenTest(
['method', 'GET', 'url.slash', '/', 'url.part', 'index1', 'url.comma', ','],
'GET /index1,'
);
tokenTest(
['method', 'PUT', 'url.slash', '/', 'url.part', 'index', 'url.slash', '/'],
'PUT /index/'
);
tokenTest(
['method', 'GET', 'url.part', 'index', 'url.slash', '/', 'url.part', '_search'],
'GET index/_search '
);
tokenTest(
['method', 'PUT', 'url.slash', '/', 'url.part', 'index'],
'PUT /index'
);
tokenTest(
['method', 'PUT', 'url.slash', '/', 'url.part', 'index1', 'url.comma', ',', 'url.part', 'index2',
'url.slash', '/', 'url.part', 'type1', 'url.comma', ',', 'url.part', 'type2'],
'PUT /index1,index2/type1,type2'
);
tokenTest(
['method', 'PUT', 'url.slash', '/', 'url.part', 'index1',
'url.slash', '/', 'url.part', 'type1', 'url.comma', ',', 'url.part', 'type2', 'url.comma', ','],
'PUT /index1/type1,type2,'
);
tokenTest(
['method', 'PUT', 'url.part', 'index1', 'url.comma', ',', 'url.part', 'index2',
'url.slash', '/', 'url.part', 'type1', 'url.comma', ',', 'url.part', 'type2', 'url.slash', '/',
'url.part', '1234'],
'PUT index1,index2/type1,type2/1234'
);
tokenTest(
['method', 'POST', 'url.part', '_search', 'paren.lparen', '{', 'variable', '"q"', 'punctuation.colon', ':',
'paren.lparen', '{', 'paren.rparen', '}', 'paren.rparen', '}'
],
'POST _search\n' +
'{\n' +
' "q": {}\n' +
' \n' +
'}'
);
tokenTest(
['method', 'POST', 'url.part', '_search', 'paren.lparen', '{', 'variable', '"q"', 'punctuation.colon', ':',
'paren.lparen', '{', 'variable', '"s"', 'punctuation.colon', ':', 'paren.lparen', '{', 'paren.rparen', '}',
'paren.rparen', '}', 'paren.rparen', '}'
],
'POST _search\n' +
'{\n' +
' "q": { "s": {}}\n' +
' \n' +
'}'
);
function statesAsList() {
const ret = [];
const session = input.getSession();
const maxLine = session.getLength();
for (let row = 0; row < maxLine; row++) ret.push(session.getState(row));
return ret;
}
function statesTest(statesList, prefix, data) {
if (data && typeof data !== 'string') {
data = JSON.stringify(data, null, 3);
}
if (data) {
if (prefix) {
data = prefix + '\n' + data;
}
}
else {
data = prefix;
}
asyncTest('States test ' + testCount++ + ' prefix: ' + prefix, function () {
input.update(data, function () {
const modes = statesAsList();
deepEqual(modes, statesList, 'Doc:\n' + data);
start();
});
});
}
statesTest(
['start', 'json', 'json', 'start'],
'POST _search\n' +
'{\n' +
' "query": { "match_all": {} }\n' +
'}'
);
statesTest(
['start', 'json', ['json', 'json'], ['json', 'json'], 'json', 'start'],
'POST _search\n' +
'{\n' +
' "query": { \n' +
' "match_all": {} \n' +
' }\n' +
'}'
);
statesTest(
['start', 'json', 'json', 'start'],
'POST _search\n' +
'{\n' +
' "script": { "inline": "" }\n' +
'}'
);
statesTest(
['start', 'json', 'json', 'start'],
'POST _search\n' +
'{\n' +
' "script": ""\n' +
'}'
);
statesTest(
['start', 'json', ['json', 'json'], 'json', 'start'],
'POST _search\n' +
'{\n' +
' "script": {\n' +
' }\n' +
'}'
);
statesTest(
['start', 'json', ['script-start', 'json', 'json', 'json'], ['script-start', 'json', 'json', 'json'],
['json', 'json'], 'json', 'start'],
'POST _search\n' +
'{\n' +
' "test": { "script": """\n' +
' test script\n' +
' """\n' +
' }\n' +
'}'
);
statesTest(
['start', 'json', ['script-start', 'json'], ['script-start', 'json'], 'json', 'start'],
'POST _search\n' +
'{\n' +
' "script": """\n' +
' test script\n' +
' """,\n' +
'}'
);
statesTest(
['start', 'json', 'json', 'start'],
'POST _search\n' +
'{\n' +
' "script": """test script""",\n' +
'}'
);
statesTest(
['start', 'json', ['string_literal', 'json'], ['string_literal', 'json'], 'json', 'start'],
'POST _search\n' +
'{\n' +
' "somthing": """\n' +
' test script\n' +
' """,\n' +
'}'
);
statesTest(
['start', 'json', ['string_literal', 'json', 'json', 'json'], ['string_literal', 'json', 'json', 'json'],
['json', 'json'], ['json', 'json'],
'json', 'start'],
'POST _search\n' +
'{\n' +
' "somthing": { "f" : """\n' +
' test script\n' +
' """,\n' +
' "g": 1\n' +
' }\n' +
'}'
);
statesTest(
['start', 'json', 'json', 'start'],
'POST _search\n' +
'{\n' +
' "something": """test script""",\n' +
'}'
);

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,227 @@
/*
* Licensed to Elasticsearch B.V. under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch B.V. licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import _ from 'lodash';
import { populateContext } from '../../src/autocomplete/engine';
import './setup_mocks';
import 'brace';
import 'brace/mode/javascript';
import 'brace/mode/json';
const kb = require('../../src/kb');
const mappings = require('../../src/mappings');
describe('Knowledge base', () => {
beforeEach(() => {
mappings.clear();
kb.setActiveApi(kb._test.loadApisFromJson({}));
});
afterEach(() => {
mappings.clear();
kb.setActiveApi(kb._test.loadApisFromJson({}));
});
const MAPPING = {
index1: {
'type1.1': {
properties: {
'field1.1.1': { type: 'string' },
'field1.1.2': { type: 'long' },
},
},
'type1.2': {
properties: {},
},
},
index2: {
'type2.1': {
properties: {
'field2.1.1': { type: 'string' },
'field2.1.2': { type: 'string' },
},
},
},
};
function testUrlContext(tokenPath, otherTokenValues, expectedContext) {
if (expectedContext.autoCompleteSet) {
expectedContext.autoCompleteSet = _.map(
expectedContext.autoCompleteSet,
function (t) {
if (_.isString(t)) {
t = { name: t };
}
return t;
}
);
}
const context = { otherTokenValues: otherTokenValues };
populateContext(
tokenPath,
context,
null,
expectedContext.autoCompleteSet,
kb.getTopLevelUrlCompleteComponents()
);
// override context to just check on id
if (context.endpoint) {
context.endpoint = context.endpoint.id;
}
delete context.otherTokenValues;
function norm(t) {
if (_.isString(t)) {
return { name: t };
}
return t;
}
if (context.autoCompleteSet) {
context.autoCompleteSet = _.sortBy(
_.map(context.autoCompleteSet, norm),
'name'
);
}
if (expectedContext.autoCompleteSet) {
expectedContext.autoCompleteSet = _.sortBy(
_.map(expectedContext.autoCompleteSet, norm),
'name'
);
}
expect(context).toEqual(expectedContext);
}
function t(term) {
return { name: term, meta: 'type' };
}
function i(term) {
return { name: term, meta: 'index' };
}
function indexTest(name, tokenPath, otherTokenValues, expectedContext) {
test(name, function () {
// eslint-disable-next-line new-cap
const testApi = new kb._test.loadApisFromJson(
{
indexTest: {
endpoints: {
_multi_indices: {
patterns: ['{indices}/_multi_indices'],
},
_single_index: { patterns: ['{index}/_single_index'] },
_no_index: {
// testing default patters
// patterns: ["_no_index"]
},
},
},
},
kb._test.globalUrlComponentFactories
);
kb.setActiveApi(testApi);
mappings.loadMappings(MAPPING);
testUrlContext(tokenPath, otherTokenValues, expectedContext);
});
}
indexTest('Index integration 1', [], [], {
autoCompleteSet: ['_no_index', i('index1'), i('index2')],
});
indexTest(
'Index integration 2',
[],
['index1'],
// still return _no_index as index1 is not committed to yet.
{ autoCompleteSet: ['_no_index', i('index2')] }
);
indexTest('Index integration 2', ['index1'], [], {
indices: ['index1'],
autoCompleteSet: ['_multi_indices', '_single_index'],
});
indexTest('Index integration 2', [['index1', 'index2']], [], {
indices: ['index1', 'index2'],
autoCompleteSet: ['_multi_indices'],
});
function typeTest(name, tokenPath, otherTokenValues, expectedContext) {
test(name, function () {
const testApi = kb._test.loadApisFromJson(
{
typeTest: {
endpoints: {
_multi_types: { patterns: ['{indices}/{types}/_multi_types'] },
_single_type: { patterns: ['{indices}/{type}/_single_type'] },
_no_types: { patterns: ['{indices}/_no_types'] },
},
},
},
kb._test.globalUrlComponentFactories
);
kb.setActiveApi(testApi);
mappings.loadMappings(MAPPING);
testUrlContext(tokenPath, otherTokenValues, expectedContext);
});
}
typeTest('Type integration 1', ['index1'], [], {
indices: ['index1'],
autoCompleteSet: ['_no_types', t('type1.1'), t('type1.2')],
});
typeTest(
'Type integration 2',
['index1'],
['type1.2'],
// we are not yet comitted to type1.2, so _no_types is returned
{ indices: ['index1'], autoCompleteSet: ['_no_types', t('type1.1')] }
);
typeTest('Type integration 3', ['index2'], [], {
indices: ['index2'],
autoCompleteSet: ['_no_types', t('type2.1')],
});
typeTest('Type integration 4', ['index1', 'type1.2'], [], {
indices: ['index1'],
types: ['type1.2'],
autoCompleteSet: ['_multi_types', '_single_type'],
});
typeTest(
'Type integration 5',
[['index1', 'index2'], ['type1.2', 'type1.1']],
[],
{
indices: ['index1', 'index2'],
types: ['type1.2', 'type1.1'],
autoCompleteSet: ['_multi_types'],
}
);
});

View file

@ -1,193 +0,0 @@
/*
* Licensed to Elasticsearch B.V. under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch B.V. licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import _ from 'lodash';
const kb = require('../../src/kb');
const mappings = require('../../src/mappings');
import { populateContext } from '../../src/autocomplete/engine';
const { test, module, deepEqual } = window.QUnit;
module('Knowledge base', {
setup: function () {
mappings.clear();
kb.setActiveApi(kb._test.loadApisFromJson({}));
},
teardown: function () {
mappings.clear();
kb.setActiveApi(kb._test.loadApisFromJson({}));
}
});
const MAPPING = {
'index1': {
'type1.1': {
'properties': {
'field1.1.1': { 'type': 'string' },
'field1.1.2': { 'type': 'long' }
}
},
'type1.2': {
'properties': {}
}
},
'index2': {
'type2.1': {
'properties': {
'field2.1.1': { 'type': 'string' },
'field2.1.2': { 'type': 'string' }
}
}
}
};
function testUrlContext(tokenPath, otherTokenValues, expectedContext) {
if (expectedContext.autoCompleteSet) {
expectedContext.autoCompleteSet = _.map(expectedContext.autoCompleteSet, function (t) {
if (_.isString(t)) {
t = { name: t };
}
return t;
});
}
const context = { otherTokenValues: otherTokenValues };
populateContext(tokenPath, context, null,
expectedContext.autoCompleteSet, kb.getTopLevelUrlCompleteComponents()
);
// override context to just check on id
if (context.endpoint) {
context.endpoint = context.endpoint.id;
}
delete context.otherTokenValues;
function norm(t) {
if (_.isString(t)) {
return { name: t };
}
return t;
}
if (context.autoCompleteSet) {
context.autoCompleteSet = _.sortBy(_.map(context.autoCompleteSet, norm), 'name');
}
if (expectedContext.autoCompleteSet) {
expectedContext.autoCompleteSet = _.sortBy(_.map(expectedContext.autoCompleteSet, norm), 'name');
}
deepEqual(context, expectedContext);
}
function t(term) {
return { name: term, meta: 'type' };
}
function i(term) {
return { name: term, meta: 'index' };
}
function indexTest(name, tokenPath, otherTokenValues, expectedContext) {
test(name, function () {
// eslint-disable-next-line new-cap
const testApi = new kb._test.loadApisFromJson({
indexTest: {
endpoints: {
_multi_indices: {
patterns: ['{indices}/_multi_indices']
},
_single_index: { patterns: ['{index}/_single_index'] },
_no_index: {
// testing default patters
// patterns: ["_no_index"]
}
}
}
}, kb._test.globalUrlComponentFactories);
kb.setActiveApi(testApi);
mappings.loadMappings(MAPPING);
testUrlContext(tokenPath, otherTokenValues, expectedContext);
});
}
indexTest('Index integration 1', [], [],
{ autoCompleteSet: ['_no_index', i('index1'), i('index2')] }
);
indexTest('Index integration 2', [], ['index1'],
// still return _no_index as index1 is not committed to yet.
{ autoCompleteSet: ['_no_index', i('index2')] }
);
indexTest('Index integration 2', ['index1'], [],
{ indices: ['index1'], autoCompleteSet: ['_multi_indices', '_single_index'] }
);
indexTest('Index integration 2', [
['index1', 'index2']
], [],
{ indices: ['index1', 'index2'], autoCompleteSet: ['_multi_indices'] }
);
function typeTest(name, tokenPath, otherTokenValues, expectedContext) {
test(name, function () {
const testApi = kb._test.loadApisFromJson({
'typeTest': {
endpoints: {
_multi_types: { patterns: ['{indices}/{types}/_multi_types'] },
_single_type: { patterns: ['{indices}/{type}/_single_type'] },
_no_types: { patterns: ['{indices}/_no_types'] }
}
}
}, kb._test.globalUrlComponentFactories);
kb.setActiveApi(testApi);
mappings.loadMappings(MAPPING);
testUrlContext(tokenPath, otherTokenValues, expectedContext);
});
}
typeTest('Type integration 1', ['index1'], [],
{ indices: ['index1'], autoCompleteSet: ['_no_types', t('type1.1'), t('type1.2')] }
);
typeTest('Type integration 2', ['index1'], ['type1.2'],
// we are not yet comitted to type1.2, so _no_types is returned
{ indices: ['index1'], autoCompleteSet: ['_no_types', t('type1.1')] }
);
typeTest('Type integration 3', ['index2'], [],
{ indices: ['index2'], autoCompleteSet: ['_no_types', t('type2.1')] }
);
typeTest('Type integration 4', ['index1', 'type1.2'], [],
{ indices: ['index1'], types: ['type1.2'], autoCompleteSet: ['_multi_types', '_single_type'] }
);
typeTest('Type integration 5', [
['index1', 'index2'],
['type1.2', 'type1.1']
], [],
{ indices: ['index1', 'index2'], types: ['type1.2', 'type1.1'], autoCompleteSet: ['_multi_types'] }
);

View file

@ -0,0 +1,319 @@
/*
* Licensed to Elasticsearch B.V. under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch B.V. licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import './setup_mocks';
import 'brace';
import 'brace/mode/javascript';
import 'brace/mode/json';
const mappings = require('../../src/mappings');
describe('Mappings', () => {
beforeEach(() => {
mappings.clear();
});
afterEach(() => {
mappings.clear();
});
function fc(f1, f2) {
if (f1.name < f2.name) {
return -1;
}
if (f1.name > f2.name) {
return 1;
}
return 0;
}
function f(name, type) {
return { name: name, type: type || 'string' };
}
test('Multi fields', function () {
mappings.loadMappings({
index: {
tweet: {
properties: {
first_name: {
type: 'multi_field',
path: 'just_name',
fields: {
first_name: { type: 'string', index: 'analyzed' },
any_name: { type: 'string', index: 'analyzed' },
},
},
last_name: {
type: 'multi_field',
path: 'just_name',
fields: {
last_name: { type: 'string', index: 'analyzed' },
any_name: { type: 'string', index: 'analyzed' },
},
},
},
},
},
});
expect(mappings.getFields('index').sort(fc)).toEqual([
f('any_name', 'string'),
f('first_name', 'string'),
f('last_name', 'string'),
]);
});
test('Multi fields 1.0 style', function () {
mappings.loadMappings({
index: {
tweet: {
properties: {
first_name: {
type: 'string',
index: 'analyzed',
path: 'just_name',
fields: {
any_name: { type: 'string', index: 'analyzed' },
},
},
last_name: {
type: 'string',
index: 'no',
fields: {
raw: { type: 'string', index: 'analyzed' },
},
},
},
},
},
});
expect(mappings.getFields('index').sort(fc)).toEqual([
f('any_name', 'string'),
f('first_name', 'string'),
f('last_name', 'string'),
f('last_name.raw', 'string'),
]);
});
test('Simple fields', function () {
mappings.loadMappings({
index: {
tweet: {
properties: {
str: {
type: 'string',
},
number: {
type: 'int',
},
},
},
},
});
expect(mappings.getFields('index').sort(fc)).toEqual([
f('number', 'int'),
f('str', 'string'),
]);
});
test('Simple fields - 1.0 style', function () {
mappings.loadMappings({
index: {
mappings: {
tweet: {
properties: {
str: {
type: 'string',
},
number: {
type: 'int',
},
},
},
},
},
});
expect(mappings.getFields('index').sort(fc)).toEqual([
f('number', 'int'),
f('str', 'string'),
]);
});
test('Nested fields', function () {
mappings.loadMappings({
index: {
tweet: {
properties: {
person: {
type: 'object',
properties: {
name: {
properties: {
first_name: { type: 'string' },
last_name: { type: 'string' },
},
},
sid: { type: 'string', index: 'not_analyzed' },
},
},
message: { type: 'string' },
},
},
},
});
expect(mappings.getFields('index', ['tweet']).sort(fc)).toEqual([
f('message'),
f('person.name.first_name'),
f('person.name.last_name'),
f('person.sid'),
]);
});
test('Enabled fields', function () {
mappings.loadMappings({
index: {
tweet: {
properties: {
person: {
type: 'object',
properties: {
name: {
type: 'object',
enabled: false,
},
sid: { type: 'string', index: 'not_analyzed' },
},
},
message: { type: 'string' },
},
},
},
});
expect(mappings.getFields('index', ['tweet']).sort(fc)).toEqual([
f('message'),
f('person.sid'),
]);
});
test('Path tests', function () {
mappings.loadMappings({
index: {
person: {
properties: {
name1: {
type: 'object',
path: 'just_name',
properties: {
first1: { type: 'string' },
last1: { type: 'string', index_name: 'i_last_1' },
},
},
name2: {
type: 'object',
path: 'full',
properties: {
first2: { type: 'string' },
last2: { type: 'string', index_name: 'i_last_2' },
},
},
},
},
},
});
expect(mappings.getFields().sort(fc)).toEqual([
f('first1'),
f('i_last_1'),
f('name2.first2'),
f('name2.i_last_2'),
]);
});
test('Use index_name tests', function () {
mappings.loadMappings({
index: {
person: {
properties: {
last1: { type: 'string', index_name: 'i_last_1' },
},
},
},
});
expect(mappings.getFields().sort(fc)).toEqual([f('i_last_1')]);
});
test('Aliases', function () {
mappings.loadAliases({
test_index1: {
aliases: {
alias1: {},
},
},
test_index2: {
aliases: {
alias2: {
filter: {
term: {
FIELD: 'VALUE',
},
},
},
alias1: {},
},
},
});
mappings.loadMappings({
test_index1: {
type1: {
properties: {
last1: { type: 'string', index_name: 'i_last_1' },
},
},
},
test_index2: {
type2: {
properties: {
last1: { type: 'string', index_name: 'i_last_1' },
},
},
},
});
expect(mappings.getIndices().sort()).toEqual([
'_all',
'alias1',
'alias2',
'test_index1',
'test_index2',
]);
expect(mappings.getIndices(false).sort()).toEqual([
'test_index1',
'test_index2',
]);
expect(mappings.expandAliases(['alias1', 'test_index2']).sort()).toEqual([
'test_index1',
'test_index2',
]);
expect(mappings.expandAliases('alias2')).toEqual('test_index2');
});
});

View file

@ -1,289 +0,0 @@
/*
* Licensed to Elasticsearch B.V. under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch B.V. licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
const mappings = require('../../src/mappings');
const { test, module, deepEqual } = window.QUnit;
module('Mappings', {
setup: function () {
mappings.clear();
},
teardown: function () {
mappings.clear();
}
});
function fc(f1, f2) {
if (f1.name < f2.name) {
return -1;
}
if (f1.name > f2.name) {
return 1;
}
return 0;
}
function f(name, type) {
return { name: name, type: type || 'string' };
}
test('Multi fields', function () {
mappings.loadMappings({
'index': {
'tweet': {
'properties': {
'first_name': {
'type': 'multi_field',
'path': 'just_name',
'fields': {
'first_name': { 'type': 'string', 'index': 'analyzed' },
'any_name': { 'type': 'string', 'index': 'analyzed' }
}
},
'last_name': {
'type': 'multi_field',
'path': 'just_name',
'fields': {
'last_name': { 'type': 'string', 'index': 'analyzed' },
'any_name': { 'type': 'string', 'index': 'analyzed' }
}
}
}
}
}
});
deepEqual(mappings.getFields('index').sort(fc), [
f('any_name', 'string'), f('first_name', 'string'), f('last_name', 'string')]);
});
test('Multi fields 1.0 style', function () {
mappings.loadMappings({
'index': {
'tweet': {
'properties': {
'first_name': {
'type': 'string', 'index': 'analyzed',
'path': 'just_name',
'fields': {
'any_name': { 'type': 'string', 'index': 'analyzed' }
}
},
'last_name': {
'type': 'string', 'index': 'no',
'fields': {
'raw': { 'type': 'string', 'index': 'analyzed' }
}
}
}
}
}
});
deepEqual(mappings.getFields('index').sort(fc), [
f('any_name', 'string'), f('first_name', 'string'), f('last_name', 'string'), f('last_name.raw', 'string')]);
});
test('Simple fields', function () {
mappings.loadMappings({
'index': {
'tweet': {
'properties': {
'str': {
'type': 'string'
},
'number': {
'type': 'int'
}
}
}
}
});
deepEqual(mappings.getFields('index').sort(fc), [f('number', 'int'), f('str', 'string')]);
});
test('Simple fields - 1.0 style', function () {
mappings.loadMappings({
'index': {
'mappings': {
'tweet': {
'properties': {
'str': {
'type': 'string'
},
'number': {
'type': 'int'
}
}
}
}
}
});
deepEqual(mappings.getFields('index').sort(fc), [f('number', 'int'), f('str', 'string')]);
});
test('Nested fields', function () {
mappings.loadMappings({
'index': {
'tweet': {
'properties': {
'person': {
'type': 'object',
'properties': {
'name': {
'properties': {
'first_name': { 'type': 'string' },
'last_name': { 'type': 'string' }
}
},
'sid': { 'type': 'string', 'index': 'not_analyzed' }
}
},
'message': { 'type': 'string' }
}
}
}
});
deepEqual(mappings.getFields('index', ['tweet']).sort(fc),
[f('message'), f('person.name.first_name'), f('person.name.last_name'), f('person.sid')]);
});
test('Enabled fields', function () {
mappings.loadMappings({
'index': {
'tweet': {
'properties': {
'person': {
'type': 'object',
'properties': {
'name': {
'type': 'object',
'enabled': false
},
'sid': { 'type': 'string', 'index': 'not_analyzed' }
}
},
'message': { 'type': 'string' }
}
}
}
});
deepEqual(mappings.getFields('index', ['tweet']).sort(fc),
[f('message'), f('person.sid')]);
});
test('Path tests', function () {
mappings.loadMappings({
'index': {
'person': {
'properties': {
'name1': {
'type': 'object',
'path': 'just_name',
'properties': {
'first1': { 'type': 'string' },
'last1': { 'type': 'string', 'index_name': 'i_last_1' }
}
},
'name2': {
'type': 'object',
'path': 'full',
'properties': {
'first2': { 'type': 'string' },
'last2': { 'type': 'string', 'index_name': 'i_last_2' }
}
}
}
}
}
});
deepEqual(mappings.getFields().sort(fc),
[f('first1'), f('i_last_1'), f('name2.first2'), f('name2.i_last_2')]);
});
test('Use index_name tests', function () {
mappings.loadMappings({
'index': {
'person': {
'properties': {
'last1': { 'type': 'string', 'index_name': 'i_last_1' }
}
}
}
});
deepEqual(mappings.getFields().sort(fc),
[f('i_last_1')]);
});
test('Aliases', function () {
mappings.loadAliases({
'test_index1': {
'aliases': {
'alias1': {}
}
},
'test_index2': {
'aliases': {
'alias2': {
'filter': {
'term': {
'FIELD': 'VALUE'
}
}
},
'alias1': {}
}
}
});
mappings.loadMappings({
'test_index1': {
'type1': {
'properties': {
'last1': { 'type': 'string', 'index_name': 'i_last_1' }
}
}
},
'test_index2': {
'type2': {
'properties': {
'last1': { 'type': 'string', 'index_name': 'i_last_1' }
}
}
}
});
deepEqual(mappings.getIndices().sort(),
['_all', 'alias1', 'alias2', 'test_index1', 'test_index2']
);
deepEqual(mappings.getIndices(false).sort(),
['test_index1', 'test_index2']
);
deepEqual(mappings.expandAliases(['alias1', 'test_index2']).sort(),
['test_index1', 'test_index2']
);
deepEqual(mappings.expandAliases('alias2'), 'test_index2');
});

View file

@ -0,0 +1,113 @@
/*
* Licensed to Elasticsearch B.V. under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch B.V. licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import './setup_mocks';
import ace from 'brace';
import 'brace/mode/javascript';
import 'brace/mode/json';
const $ = require('jquery');
const RowParser = require('../../src/sense_editor/row_parser');
import { initializeOutput } from '../../src/output';
let output;
const tokenIterator = ace.acequire('ace/token_iterator');
describe('Output Tokenization', () => {
beforeEach(() => {
output = initializeOutput($('#output'));
output.$el.show();
});
afterEach(() => {
output.$el.hide();
});
function tokensAsList() {
const iter = new tokenIterator.TokenIterator(output.getSession(), 0, 0);
const ret = [];
let t = iter.getCurrentToken();
const parser = new RowParser(output);
if (parser.isEmptyToken(t)) {
t = parser.nextNonEmptyToken(iter);
}
while (t) {
ret.push({ value: t.value, type: t.type });
t = parser.nextNonEmptyToken(iter);
}
return ret;
}
let testCount = 0;
function tokenTest(tokenList, data) {
if (data && typeof data !== 'string') {
data = JSON.stringify(data, null, 3);
}
test('Token test ' + testCount++, async function (done) {
output.update(data, function () {
const tokens = tokensAsList();
const normTokenList = [];
for (let i = 0; i < tokenList.length; i++) {
normTokenList.push({ type: tokenList[i++], value: tokenList[i] });
}
expect(tokens).toEqual(normTokenList);
done();
});
});
}
tokenTest(
[
'warning',
'#! warning',
'comment',
'# GET url',
'paren.lparen',
'{',
'paren.rparen',
'}',
],
'#! warning\n' + '# GET url\n' + '{}'
);
tokenTest(
[
'comment',
'# GET url',
'paren.lparen',
'{',
'variable',
'"f"',
'punctuation.colon',
':',
'punctuation.start_triple_quote',
'"""',
'multi_string',
'raw',
'punctuation.end_triple_quote',
'"""',
'paren.rparen',
'}',
],
'# GET url\n' + '{ "f": """raw""" }'
);
});

View file

@ -1,98 +0,0 @@
/*
* Licensed to Elasticsearch B.V. under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch B.V. licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
const ace = require('ace');
const $ = require('jquery');
const RowParser = require('../../src/sense_editor/row_parser');
import { initializeOutput } from '../../src/output';
let output;
const tokenIterator = ace.acequire('ace/token_iterator');
const { module, asyncTest, deepEqual, start } = window.QUnit;
module('Output Tokenization', {
setup: function () {
output = initializeOutput($('#output'));
output.$el.show();
},
teardown: function () {
output.$el.hide();
}
});
function tokensAsList() {
const iter = new tokenIterator.TokenIterator(output.getSession(), 0, 0);
const ret = [];
let t = iter.getCurrentToken();
const parser = new RowParser(output);
if (parser.isEmptyToken(t)) {
t = parser.nextNonEmptyToken(iter);
}
while (t) {
ret.push({ value: t.value, type: t.type });
t = parser.nextNonEmptyToken(iter);
}
return ret;
}
let testCount = 0;
function tokenTest(tokenList, data) {
if (data && typeof data !== 'string') {
data = JSON.stringify(data, null, 3);
}
asyncTest('Token test ' + testCount++, function () {
output.update(data, function () {
const tokens = tokensAsList();
const normTokenList = [];
for (let i = 0; i < tokenList.length; i++) {
normTokenList.push({ type: tokenList[i++], value: tokenList[i] });
}
deepEqual(tokens, normTokenList, 'Doc:\n' + data);
start();
});
});
}
tokenTest(
['warning', '#! warning', 'comment', '# GET url', 'paren.lparen', '{', 'paren.rparen', '}'],
'#! warning\n' +
'# GET url\n' +
'{}'
);
tokenTest(
[ 'comment', '# GET url',
'paren.lparen', '{',
'variable', '"f"',
'punctuation.colon', ':',
'punctuation.start_triple_quote', '"""',
'multi_string', 'raw',
'punctuation.end_triple_quote', '"""',
'paren.rparen', '}'
],
'# GET url\n' +
'{ "f": """raw""" }'
);

View file

@ -0,0 +1,26 @@
/*
* Licensed to Elasticsearch B.V. under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch B.V. licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
/* eslint no-undef: 0 */
jest.mock('../../src/sense_editor/mode/worker', () => { return { workerModule: { id: 'sense_editor/mode/worker', src: '' } }; });
window.Worker = function () { this.postMessage = () => {}; this.terminate = () => {}; };
window.URL = {
createObjectURL: () => { return ''; }
};
jest.mock('../../src/storage');
document.queryCommandSupported = () => true;

View file

@ -0,0 +1,481 @@
/*
* Licensed to Elasticsearch B.V. under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch B.V. licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import './setup_mocks';
import 'brace';
import 'brace/mode/javascript';
import 'brace/mode/json';
const _ = require('lodash');
import {
URL_PATH_END_MARKER,
UrlPatternMatcher,
} from '../../src/autocomplete/url_pattern_matcher';
import { populateContext, ListComponent } from '../../src/autocomplete/engine';
describe('Url autocomplete', () => {
function patternsTest(
name,
endpoints,
tokenPath,
expectedContext,
globalUrlComponentFactories
) {
test(name, function () {
const patternMatcher = new UrlPatternMatcher(globalUrlComponentFactories);
_.each(endpoints, function (e, id) {
e.id = id;
_.each(e.patterns, function (p) {
patternMatcher.addEndpoint(p, e);
});
});
if (typeof tokenPath === 'string') {
if (tokenPath[tokenPath.length - 1] === '$') {
tokenPath =
tokenPath.substr(0, tokenPath.length - 1) +
'/' +
URL_PATH_END_MARKER;
}
tokenPath = _.map(tokenPath.split('/'), function (p) {
p = p.split(',');
if (p.length === 1) {
return p[0];
}
return p;
});
}
if (expectedContext.autoCompleteSet) {
expectedContext.autoCompleteSet = _.map(
expectedContext.autoCompleteSet,
function (t) {
if (_.isString(t)) {
t = { name: t };
}
return t;
}
);
expectedContext.autoCompleteSet = _.sortBy(
expectedContext.autoCompleteSet,
'name'
);
}
const context = {};
if (expectedContext.method) {
context.method = expectedContext.method;
}
populateContext(
tokenPath,
context,
null,
expectedContext.autoCompleteSet,
patternMatcher.getTopLevelComponents()
);
// override context to just check on id
if (context.endpoint) {
context.endpoint = context.endpoint.id;
}
if (context.autoCompleteSet) {
context.autoCompleteSet = _.sortBy(context.autoCompleteSet, 'name');
}
expect(context).toEqual(expectedContext);
});
}
function t(name, meta) {
if (meta) {
return { name: name, meta: meta };
}
return name;
}
(function () {
const endpoints = {
'1': {
patterns: ['a/b'],
},
};
patternsTest('simple single path - completion', endpoints, 'a/b$', {
endpoint: '1',
});
patternsTest(
'simple single path - completion, with auto complete',
endpoints,
'a/b',
{ autoCompleteSet: [] }
);
patternsTest(
'simple single path - partial, without auto complete',
endpoints,
'a',
{}
);
patternsTest(
'simple single path - partial, with auto complete',
endpoints,
'a',
{ autoCompleteSet: ['b'] }
);
patternsTest(
'simple single path - partial, with auto complete',
endpoints,
[],
{ autoCompleteSet: ['a/b'] }
);
patternsTest('simple single path - different path', endpoints, 'a/c', {});
}());
(function () {
const endpoints = {
'1': {
patterns: ['a/b', 'a/b/{p}'],
},
'2': {
patterns: ['a/c'],
},
};
patternsTest('shared path - completion 1', endpoints, 'a/b$', {
endpoint: '1',
});
patternsTest('shared path - completion 2', endpoints, 'a/c$', {
endpoint: '2',
});
patternsTest(
'shared path - completion 1 with param',
endpoints,
'a/b/v$',
{ endpoint: '1', p: 'v' }
);
patternsTest('shared path - partial, with auto complete', endpoints, 'a', {
autoCompleteSet: ['b', 'c'],
});
patternsTest(
'shared path - partial, with auto complete of param, no options',
endpoints,
'a/b',
{ autoCompleteSet: [] }
);
patternsTest(
'shared path - partial, without auto complete',
endpoints,
'a',
{}
);
patternsTest(
'shared path - different path - with auto complete',
endpoints,
'a/e',
{ autoCompleteSet: [] }
);
patternsTest(
'shared path - different path - without auto complete',
endpoints,
'a/e',
{}
);
}());
(function () {
const endpoints = {
'1': {
patterns: ['a/{p}'],
url_components: {
p: ['a', 'b'],
},
},
'2': {
patterns: ['a/c'],
},
};
patternsTest('option testing - completion 1', endpoints, 'a/a$', {
endpoint: '1',
p: ['a'],
});
patternsTest('option testing - completion 2', endpoints, 'a/b$', {
endpoint: '1',
p: ['b'],
});
patternsTest('option testing - completion 3', endpoints, 'a/b,a$', {
endpoint: '1',
p: ['b', 'a'],
});
patternsTest('option testing - completion 4', endpoints, 'a/c$', {
endpoint: '2',
});
patternsTest('option testing - completion 5', endpoints, 'a/d$', {});
patternsTest(
'option testing - partial, with auto complete',
endpoints,
'a',
{ autoCompleteSet: [t('a', 'p'), t('b', 'p'), 'c'] }
);
patternsTest(
'option testing - partial, without auto complete',
endpoints,
'a',
{}
);
patternsTest(
'option testing - different path - with auto complete',
endpoints,
'a/e',
{ autoCompleteSet: [] }
);
}());
(function () {
const endpoints = {
'1': {
patterns: ['a/{p}'],
url_components: {
p: ['a', 'b'],
},
},
'2': {
patterns: ['b/{p}'],
},
'3': {
patterns: ['b/{l}/c'],
url_components: {
l: {
type: 'list',
list: ['la', 'lb'],
allow_non_valid: true,
},
},
},
};
const globalFactories = {
p: function (name, parent) {
return new ListComponent(name, ['g1', 'g2'], parent);
},
};
patternsTest(
'global parameters testing - completion 1',
endpoints,
'a/a$',
{ endpoint: '1', p: ['a'] },
globalFactories
);
patternsTest(
'global parameters testing - completion 2',
endpoints,
'b/g1$',
{ endpoint: '2', p: ['g1'] },
globalFactories
);
patternsTest(
'global parameters testing - partial, with auto complete',
endpoints,
'a',
{ autoCompleteSet: [t('a', 'p'), t('b', 'p')] },
globalFactories
);
patternsTest(
'global parameters testing - partial, with auto complete 2',
endpoints,
'b',
{
autoCompleteSet: [
t('g1', 'p'),
t('g2', 'p'),
t('la', 'l'),
t('lb', 'l'),
],
},
globalFactories
);
patternsTest(
'Non valid token acceptance - partial, with auto complete 1',
endpoints,
'b/la',
{ autoCompleteSet: ['c'], l: ['la'] },
globalFactories
);
patternsTest(
'Non valid token acceptance - partial, with auto complete 2',
endpoints,
'b/non_valid',
{ autoCompleteSet: ['c'], l: ['non_valid'] },
globalFactories
);
}());
(function () {
const endpoints = {
'1': {
patterns: ['a/b/{p}/c/e'],
},
};
patternsTest('look ahead - autocomplete before param 1', endpoints, 'a', {
autoCompleteSet: ['b'],
});
patternsTest('look ahead - autocomplete before param 2', endpoints, [], {
autoCompleteSet: ['a/b'],
});
patternsTest(
'look ahead - autocomplete after param 1',
endpoints,
'a/b/v',
{ autoCompleteSet: ['c/e'], p: 'v' }
);
patternsTest(
'look ahead - autocomplete after param 2',
endpoints,
'a/b/v/c',
{ autoCompleteSet: ['e'], p: 'v' }
);
}());
(function () {
const endpoints = {
'1_param': {
patterns: ['a/{p}'],
methods: ['GET'],
},
'2_explicit': {
patterns: ['a/b'],
methods: ['GET'],
},
};
let e = _.cloneDeep(endpoints);
e['1_param'].priority = 1;
patternsTest('Competing endpoints - priority 1', e, 'a/b$', {
method: 'GET',
endpoint: '1_param',
p: 'b',
});
e = _.cloneDeep(endpoints);
e['1_param'].priority = 1;
e['2_explicit'].priority = 0;
patternsTest('Competing endpoints - priority 2', e, 'a/b$', {
method: 'GET',
endpoint: '2_explicit',
});
e = _.cloneDeep(endpoints);
e['2_explicit'].priority = 0;
patternsTest('Competing endpoints - priority 3', e, 'a/b$', {
method: 'GET',
endpoint: '2_explicit',
});
}());
(function () {
const endpoints = {
'1_GET': {
patterns: ['a'],
methods: ['GET'],
},
'1_PUT': {
patterns: ['a'],
methods: ['PUT'],
},
'2_GET': {
patterns: ['a/b'],
methods: ['GET'],
},
'2_DELETE': {
patterns: ['a/b'],
methods: ['DELETE'],
},
};
patternsTest(
'Competing endpoint - sub url of another - auto complete',
endpoints,
'a',
{ method: 'GET', autoCompleteSet: ['b'] }
);
patternsTest(
'Competing endpoint - sub url of another, complete 1',
endpoints,
'a$',
{ method: 'GET', endpoint: '1_GET' }
);
patternsTest(
'Competing endpoint - sub url of another, complete 2',
endpoints,
'a$',
{ method: 'PUT', endpoint: '1_PUT' }
);
patternsTest(
'Competing endpoint - sub url of another, complete 3',
endpoints,
'a$',
{ method: 'DELETE' }
);
patternsTest(
'Competing endpoint - extension of another, complete 1, auto complete',
endpoints,
'a/b$',
{ method: 'PUT', autoCompleteSet: [] }
);
patternsTest(
'Competing endpoint - extension of another, complete 1',
endpoints,
'a/b$',
{ method: 'GET', endpoint: '2_GET' }
);
patternsTest(
'Competing endpoint - extension of another, complete 1',
endpoints,
'a/b$',
{ method: 'DELETE', endpoint: '2_DELETE' }
);
patternsTest(
'Competing endpoint - extension of another, complete 1',
endpoints,
'a/b$',
{ method: 'PUT' }
);
}());
});

View file

@ -1,493 +0,0 @@
/*
* Licensed to Elasticsearch B.V. under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch B.V. licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
const _ = require('lodash');
import { URL_PATH_END_MARKER, UrlPatternMatcher } from '../../src/autocomplete/url_pattern_matcher';
import { populateContext, ListComponent } from '../../src/autocomplete/engine';
const { test, module, deepEqual } = window.QUnit;
module('Url autocomplete');
function patternsTest(name, endpoints, tokenPath, expectedContext, globalUrlComponentFactories) {
test(name, function () {
const patternMatcher = new UrlPatternMatcher(globalUrlComponentFactories);
_.each(endpoints, function (e, id) {
e.id = id;
_.each(e.patterns, function (p) {
patternMatcher.addEndpoint(p, e);
});
});
if (typeof tokenPath === 'string') {
if (tokenPath[tokenPath.length - 1] === '$') {
tokenPath = tokenPath.substr(0, tokenPath.length - 1) + '/' + URL_PATH_END_MARKER;
}
tokenPath = _.map(tokenPath.split('/'), function (p) {
p = p.split(',');
if (p.length === 1) {
return p[0];
}
return p;
});
}
if (expectedContext.autoCompleteSet) {
expectedContext.autoCompleteSet = _.map(expectedContext.autoCompleteSet, function (t) {
if (_.isString(t)) {
t = { name: t };
}
return t;
});
expectedContext.autoCompleteSet = _.sortBy(expectedContext.autoCompleteSet, 'name');
}
const context = {};
if (expectedContext.method) {
context.method = expectedContext.method;
}
populateContext(tokenPath, context, null,
expectedContext.autoCompleteSet, patternMatcher.getTopLevelComponents()
);
// override context to just check on id
if (context.endpoint) {
context.endpoint = context.endpoint.id;
}
if (context.autoCompleteSet) {
context.autoCompleteSet = _.sortBy(context.autoCompleteSet, 'name');
}
deepEqual(context, expectedContext);
});
}
function t(name, meta) {
if (meta) {
return { name: name, meta: meta };
}
return name;
}
(function () {
const endpoints = {
'1': {
patterns: [
'a/b'
]
}
};
patternsTest('simple single path - completion',
endpoints,
'a/b$',
{ endpoint: '1' }
);
patternsTest('simple single path - completion, with auto complete',
endpoints,
'a/b',
{ autoCompleteSet: [] }
);
patternsTest('simple single path - partial, without auto complete',
endpoints,
'a',
{}
);
patternsTest('simple single path - partial, with auto complete',
endpoints,
'a',
{ autoCompleteSet: ['b'] }
);
patternsTest('simple single path - partial, with auto complete',
endpoints,
[],
{ autoCompleteSet: ['a/b'] }
);
patternsTest('simple single path - different path',
endpoints,
'a/c',
{}
);
}());
(function () {
const endpoints = {
'1': {
patterns: [
'a/b',
'a/b/{p}'
]
},
'2': {
patterns: [
'a/c'
]
}
};
patternsTest('shared path - completion 1',
endpoints,
'a/b$',
{ endpoint: '1' }
);
patternsTest('shared path - completion 2',
endpoints,
'a/c$',
{ endpoint: '2' }
);
patternsTest('shared path - completion 1 with param',
endpoints,
'a/b/v$',
{ endpoint: '1', p: 'v' }
);
patternsTest('shared path - partial, with auto complete',
endpoints,
'a',
{ autoCompleteSet: ['b', 'c'] }
);
patternsTest('shared path - partial, with auto complete of param, no options',
endpoints,
'a/b',
{ autoCompleteSet: [] }
);
patternsTest('shared path - partial, without auto complete',
endpoints,
'a',
{}
);
patternsTest('shared path - different path - with auto complete',
endpoints,
'a/e',
{ autoCompleteSet: [] }
);
patternsTest('shared path - different path - without auto complete',
endpoints,
'a/e',
{}
);
}());
(function () {
const endpoints = {
'1': {
patterns: [
'a/{p}',
],
url_components: {
p: ['a', 'b']
}
},
'2': {
patterns: [
'a/c'
]
}
};
patternsTest('option testing - completion 1',
endpoints,
'a/a$',
{ endpoint: '1', p: ['a'] }
);
patternsTest('option testing - completion 2',
endpoints,
'a/b$',
{ endpoint: '1', p: ['b'] }
);
patternsTest('option testing - completion 3',
endpoints,
'a/b,a$',
{ endpoint: '1', p: ['b', 'a'] }
);
patternsTest('option testing - completion 4',
endpoints,
'a/c$',
{ endpoint: '2' }
);
patternsTest('option testing - completion 5',
endpoints,
'a/d$',
{}
);
patternsTest('option testing - partial, with auto complete',
endpoints,
'a',
{ autoCompleteSet: [t('a', 'p'), t('b', 'p'), 'c'] }
);
patternsTest('option testing - partial, without auto complete',
endpoints,
'a',
{}
);
patternsTest('option testing - different path - with auto complete',
endpoints,
'a/e',
{ autoCompleteSet: [] }
);
}());
(function () {
const endpoints = {
'1': {
patterns: [
'a/{p}',
],
url_components: {
p: ['a', 'b']
}
},
'2': {
patterns: [
'b/{p}',
]
},
'3': {
patterns: [
'b/{l}/c',
],
url_components: {
l: {
type: 'list',
list: ['la', 'lb'],
allow_non_valid: true
}
}
}
};
const globalFactories = {
'p': function (name, parent) {
return new ListComponent(name, ['g1', 'g2'], parent);
}
};
patternsTest('global parameters testing - completion 1',
endpoints,
'a/a$',
{ endpoint: '1', p: ['a'] },
globalFactories
);
patternsTest('global parameters testing - completion 2',
endpoints,
'b/g1$',
{ endpoint: '2', p: ['g1'] },
globalFactories
);
patternsTest('global parameters testing - partial, with auto complete',
endpoints,
'a',
{ autoCompleteSet: [t('a', 'p'), t('b', 'p')] },
globalFactories
);
patternsTest('global parameters testing - partial, with auto complete 2',
endpoints,
'b',
{ autoCompleteSet: [t('g1', 'p'), t('g2', 'p'), t('la', 'l'), t('lb', 'l')] },
globalFactories
);
patternsTest('Non valid token acceptance - partial, with auto complete 1',
endpoints,
'b/la',
{ autoCompleteSet: ['c'], 'l': ['la'] },
globalFactories
);
patternsTest('Non valid token acceptance - partial, with auto complete 2',
endpoints,
'b/non_valid',
{ autoCompleteSet: ['c'], 'l': ['non_valid'] },
globalFactories
);
}());
(function () {
const endpoints = {
'1': {
patterns: [
'a/b/{p}/c/e'
]
}
};
patternsTest('look ahead - autocomplete before param 1',
endpoints,
'a',
{ autoCompleteSet: ['b'] }
);
patternsTest('look ahead - autocomplete before param 2',
endpoints,
[],
{ autoCompleteSet: ['a/b'] }
);
patternsTest('look ahead - autocomplete after param 1',
endpoints,
'a/b/v',
{ autoCompleteSet: ['c/e'], 'p': 'v' }
);
patternsTest('look ahead - autocomplete after param 2',
endpoints,
'a/b/v/c',
{ autoCompleteSet: ['e'], 'p': 'v' }
);
}());
(function () {
const endpoints = {
'1_param': {
patterns: [
'a/{p}'
],
methods: ['GET']
},
'2_explicit': {
patterns: [
'a/b'
],
methods: ['GET']
}
};
let e = _.cloneDeep(endpoints);
e['1_param'].priority = 1;
patternsTest('Competing endpoints - priority 1',
e,
'a/b$',
{ method: 'GET', endpoint: '1_param', 'p': 'b' }
);
e = _.cloneDeep(endpoints);
e['1_param'].priority = 1;
e['2_explicit'].priority = 0;
patternsTest('Competing endpoints - priority 2',
e,
'a/b$',
{ method: 'GET', endpoint: '2_explicit' }
);
e = _.cloneDeep(endpoints);
e['2_explicit'].priority = 0;
patternsTest('Competing endpoints - priority 3',
e,
'a/b$',
{ method: 'GET', endpoint: '2_explicit' }
);
}());
(function () {
const endpoints = {
'1_GET': {
patterns: [
'a'
],
methods: ['GET']
},
'1_PUT': {
patterns: [
'a'
],
methods: ['PUT']
},
'2_GET': {
patterns: [
'a/b'
],
methods: ['GET']
},
'2_DELETE': {
patterns: [
'a/b'
],
methods: ['DELETE']
}
};
patternsTest('Competing endpoint - sub url of another - auto complete',
endpoints,
'a',
{ method: 'GET', autoCompleteSet: ['b'] }
);
patternsTest('Competing endpoint - sub url of another, complete 1',
endpoints,
'a$',
{ method: 'GET', endpoint: '1_GET' }
);
patternsTest('Competing endpoint - sub url of another, complete 2',
endpoints,
'a$',
{ method: 'PUT', endpoint: '1_PUT' }
);
patternsTest('Competing endpoint - sub url of another, complete 3',
endpoints,
'a$',
{ method: 'DELETE' }
);
patternsTest('Competing endpoint - extension of another, complete 1, auto complete',
endpoints,
'a/b$',
{ method: 'PUT', autoCompleteSet: [] }
);
patternsTest('Competing endpoint - extension of another, complete 1',
endpoints,
'a/b$',
{ method: 'GET', endpoint: '2_GET' }
);
patternsTest('Competing endpoint - extension of another, complete 1',
endpoints,
'a/b$',
{ method: 'DELETE', endpoint: '2_DELETE' }
);
patternsTest('Competing endpoint - extension of another, complete 1',
endpoints,
'a/b$',
{ method: 'PUT' }
);
}());

View file

@ -0,0 +1,127 @@
/*
* Licensed to Elasticsearch B.V. under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch B.V. licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import './setup_mocks';
import 'brace';
import 'brace/mode/javascript';
import 'brace/mode/json';
const _ = require('lodash');
import { UrlParams } from '../../src/autocomplete/url_params';
import { populateContext } from '../../src/autocomplete/engine';
describe('Url params', () => {
function paramTest(
name,
description,
tokenPath,
expectedContext,
globalParams
) {
test(name, function () {
const urlParams = new UrlParams(description, globalParams || {});
if (typeof tokenPath === 'string') {
tokenPath = _.map(tokenPath.split('/'), function (p) {
p = p.split(',');
if (p.length === 1) {
return p[0];
}
return p;
});
}
if (expectedContext.autoCompleteSet) {
expectedContext.autoCompleteSet = _.map(
expectedContext.autoCompleteSet,
function (t) {
if (_.isString(t)) {
t = { name: t };
}
return t;
}
);
expectedContext.autoCompleteSet = _.sortBy(
expectedContext.autoCompleteSet,
'name'
);
}
const context = {};
populateContext(
tokenPath,
context,
null,
expectedContext.autoCompleteSet,
urlParams.getTopLevelComponents()
);
if (context.autoCompleteSet) {
context.autoCompleteSet = _.sortBy(context.autoCompleteSet, 'name');
}
expect(context).toEqual(expectedContext);
});
}
function t(name, meta, insertValue) {
let r = name;
if (meta) {
r = { name: name, meta: meta };
if (meta === 'param' && !insertValue) {
insertValue = name + '=';
}
}
if (insertValue) {
if (_.isString(r)) {
r = { name: name };
}
r.insertValue = insertValue;
}
return r;
}
(function () {
const params = {
a: ['1', '2'],
b: '__flag__',
};
paramTest('settings params', params, 'a/1', { a: ['1'] });
paramTest('autocomplete top level', params, [], {
autoCompleteSet: [t('a', 'param'), t('b', 'flag')],
});
paramTest(
'autocomplete top level, with defaults',
params,
[],
{ autoCompleteSet: [t('a', 'param'), t('b', 'flag'), t('c', 'param')] },
{
c: [2],
}
);
paramTest('autocomplete values', params, 'a', {
autoCompleteSet: [t('1', 'a'), t('2', 'a')],
});
paramTest('autocomplete values flag', params, 'b', {
autoCompleteSet: [t('true', 'b'), t('false', 'b')],
});
}());
});

View file

@ -1,124 +0,0 @@
/*
* Licensed to Elasticsearch B.V. under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch B.V. licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
const _ = require('lodash');
import { UrlParams } from '../../src/autocomplete/url_params';
import { populateContext } from '../../src/autocomplete/engine';
const { test, module, deepEqual } = window.QUnit;
module('Url params');
function paramTest(name, description, tokenPath, expectedContext, globalParams) {
test(name, function () {
const urlParams = new UrlParams(description, globalParams || {});
if (typeof tokenPath === 'string') {
tokenPath = _.map(tokenPath.split('/'), function (p) {
p = p.split(',');
if (p.length === 1) {
return p[0];
}
return p;
});
}
if (expectedContext.autoCompleteSet) {
expectedContext.autoCompleteSet = _.map(expectedContext.autoCompleteSet, function (t) {
if (_.isString(t)) {
t = { name: t };
}
return t;
});
expectedContext.autoCompleteSet = _.sortBy(expectedContext.autoCompleteSet, 'name');
}
const context = {};
populateContext(tokenPath, context, null,
expectedContext.autoCompleteSet, urlParams.getTopLevelComponents()
);
if (context.autoCompleteSet) {
context.autoCompleteSet = _.sortBy(context.autoCompleteSet, 'name');
}
deepEqual(context, expectedContext);
});
}
function t(name, meta, insertValue) {
let r = name;
if (meta) {
r = { name: name, meta: meta };
if (meta === 'param' && !insertValue) {
insertValue = name + '=';
}
}
if (insertValue) {
if (_.isString(r)) {
r = { name: name };
}
r.insertValue = insertValue;
}
return r;
}
(function () {
const params = {
'a': ['1', '2'],
'b': '__flag__'
};
paramTest('settings params',
params,
'a/1',
{ 'a': ['1'] }
);
paramTest('autocomplete top level',
params,
[],
{ autoCompleteSet: [t('a', 'param'), t('b', 'flag')] }
);
paramTest('autocomplete top level, with defaults',
params,
[],
{ autoCompleteSet: [t('a', 'param'), t('b', 'flag'), t('c', 'param')] },
{
'c': [2]
}
);
paramTest('autocomplete values',
params,
'a',
{ autoCompleteSet: [t('1', 'a'), t('2', 'a')] }
);
paramTest('autocomplete values flag',
params,
'b',
{ autoCompleteSet: [t('true', 'b'), t('false', 'b')] }
);
}());

View file

@ -0,0 +1,87 @@
/*
* Licensed to Elasticsearch B.V. under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch B.V. licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
const _ = require('lodash');
const utils = require('../../src/utils');
const collapsingTests = require('./utils_string_collapsing.txt');
const expandingTests = require('./utils_string_expanding.txt');
describe('Utils class', () => {
_.each(collapsingTests.split(/^=+$/m), function (fixture) {
if (fixture.trim() === '') {
return;
}
fixture = fixture.split(/^-+$/m);
const name = fixture[0].trim();
const expanded = fixture[1].trim();
const collapsed = fixture[2].trim();
test('Literal collapse - ' + name, function () {
expect(utils.collapseLiteralStrings(expanded)).toEqual(collapsed);
});
});
_.each(expandingTests.split(/^=+$/m), function (fixture) {
if (fixture.trim() === '') {
return;
}
fixture = fixture.split(/^-+$/m);
const name = fixture[0].trim();
const collapsed = fixture[1].trim();
const expanded = fixture[2].trim();
test('Literal expand - ' + name, function () {
expect(utils.expandLiteralStrings(collapsed)).toEqual(expanded);
});
test('extract deprecation messages', function () {
expect(utils.extractDeprecationMessages(
'299 Elasticsearch-6.0.0-alpha1-SNAPSHOT-abcdef1 "this is a warning" "Mon, 27 Feb 2017 14:52:14 GMT"')).toEqual(
['#! Deprecation: this is a warning']);
expect(utils.extractDeprecationMessages( //eslint-disable-next-line max-len
'299 Elasticsearch-6.0.0-alpha1-SNAPSHOT-abcdef1 "this is a warning" "Mon, 27 Feb 2017 14:52:14 GMT", 299 Elasticsearch-6.0.0-alpha1-SNAPSHOT-abcdef1 "this is a second warning" "Mon, 27 Feb 2017 14:52:14 GMT"')).toEqual(
['#! Deprecation: this is a warning', '#! Deprecation: this is a second warning']);
expect(utils.extractDeprecationMessages( //eslint-disable-next-line max-len
'299 Elasticsearch-6.0.0-alpha1-SNAPSHOT-abcdef1 "this is a warning, and it includes a comma" "Mon, 27 Feb 2017 14:52:14 GMT"')).toEqual(
['#! Deprecation: this is a warning, and it includes a comma']);
expect(utils.extractDeprecationMessages( //eslint-disable-next-line max-len
'299 Elasticsearch-6.0.0-alpha1-SNAPSHOT-abcdef1 "this is a warning, and it includes an escaped backslash \\\\ and a pair of \\\"escaped quotes\\\"" "Mon, 27 Feb 2017 14:52:14 GMT"')).toEqual(
['#! Deprecation: this is a warning, and it includes an escaped backslash \\ and a pair of "escaped quotes"']);
});
test('unescape', function () {
expect(utils.unescape('escaped backslash \\\\')).toEqual('escaped backslash \\');
expect(utils.unescape('a pair of \\\"escaped quotes\\\"')).toEqual('a pair of "escaped quotes"');
expect(utils.unescape('escaped quotes do not have to come in pairs: \\\"')).toEqual('escaped quotes do not have to come in pairs: "');
});
test('split on unquoted comma followed by space', function () {
expect(utils.splitOnUnquotedCommaSpace('a, b')).toEqual(['a', 'b']);
expect(utils.splitOnUnquotedCommaSpace('a,b, c')).toEqual(['a,b', 'c']);
expect(utils.splitOnUnquotedCommaSpace('"a, b"')).toEqual(['"a, b"']);
expect(utils.splitOnUnquotedCommaSpace('"a, b", c')).toEqual(['"a, b"', 'c']);
expect(utils.splitOnUnquotedCommaSpace('"a, b\\", c"')).toEqual(['"a, b\\", c"']);
expect(utils.splitOnUnquotedCommaSpace(', a, b')).toEqual(['', 'a', 'b']);
expect(utils.splitOnUnquotedCommaSpace('a, b, ')).toEqual(['a', 'b', '']);
expect(utils.splitOnUnquotedCommaSpace('\\"a, b", "c, d\\", e", f"')).toEqual(['\\"a', 'b", "c', 'd\\"', 'e", f"']);
});
});
});

View file

@ -1,87 +0,0 @@
/*
* Licensed to Elasticsearch B.V. under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch B.V. licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
const _ = require('lodash');
const utils = require('../../src/utils');
const collapsingTests = require('raw-loader!./utils_string_collapsing.txt');
const expandingTests = require('raw-loader!./utils_string_expanding.txt');
const { test, module, deepEqual } = window.QUnit;
module('Utils class');
_.each(collapsingTests.split(/^=+$/m), function (fixture) {
if (fixture.trim() === '') {
return;
}
fixture = fixture.split(/^-+$/m);
const name = fixture[0].trim();
const expanded = fixture[1].trim();
const collapsed = fixture[2].trim();
test('Literal collapse - ' + name, function () {
deepEqual(utils.collapseLiteralStrings(expanded), collapsed);
});
});
_.each(expandingTests.split(/^=+$/m), function (fixture) {
if (fixture.trim() === '') {
return;
}
fixture = fixture.split(/^-+$/m);
const name = fixture[0].trim();
const collapsed = fixture[1].trim();
const expanded = fixture[2].trim();
test('Literal expand - ' + name, function () {
deepEqual(utils.expandLiteralStrings(collapsed), expanded);
});
test('extract deprecation messages', function () {
deepEqual(utils.extractDeprecationMessages(
'299 Elasticsearch-6.0.0-alpha1-SNAPSHOT-abcdef1 "this is a warning" "Mon, 27 Feb 2017 14:52:14 GMT"'),
['#! Deprecation: this is a warning']);
deepEqual(utils.extractDeprecationMessages( //eslint-disable-next-line max-len
'299 Elasticsearch-6.0.0-alpha1-SNAPSHOT-abcdef1 "this is a warning" "Mon, 27 Feb 2017 14:52:14 GMT", 299 Elasticsearch-6.0.0-alpha1-SNAPSHOT-abcdef1 "this is a second warning" "Mon, 27 Feb 2017 14:52:14 GMT"'),
['#! Deprecation: this is a warning', '#! Deprecation: this is a second warning']);
deepEqual(utils.extractDeprecationMessages(
'299 Elasticsearch-6.0.0-alpha1-SNAPSHOT-abcdef1 "this is a warning, and it includes a comma" "Mon, 27 Feb 2017 14:52:14 GMT"'),
['#! Deprecation: this is a warning, and it includes a comma']);
deepEqual(utils.extractDeprecationMessages( //eslint-disable-next-line max-len
'299 Elasticsearch-6.0.0-alpha1-SNAPSHOT-abcdef1 "this is a warning, and it includes an escaped backslash \\\\ and a pair of \\\"escaped quotes\\\"" "Mon, 27 Feb 2017 14:52:14 GMT"'),
['#! Deprecation: this is a warning, and it includes an escaped backslash \\ and a pair of "escaped quotes"']);
});
test('unescape', function () {
deepEqual(utils.unescape('escaped backslash \\\\'), 'escaped backslash \\');
deepEqual(utils.unescape('a pair of \\\"escaped quotes\\\"'), 'a pair of "escaped quotes"');
deepEqual(utils.unescape('escaped quotes do not have to come in pairs: \\\"'), 'escaped quotes do not have to come in pairs: "');
});
test('split on unquoted comma followed by space', function () {
deepEqual(utils.splitOnUnquotedCommaSpace('a, b'), ['a', 'b']);
deepEqual(utils.splitOnUnquotedCommaSpace('a,b, c'), ['a,b', 'c']);
deepEqual(utils.splitOnUnquotedCommaSpace('"a, b"'), ['"a, b"']);
deepEqual(utils.splitOnUnquotedCommaSpace('"a, b", c'), ['"a, b"', 'c']);
deepEqual(utils.splitOnUnquotedCommaSpace('"a, b\\", c"'), ['"a, b\\", c"']);
deepEqual(utils.splitOnUnquotedCommaSpace(', a, b'), ['', 'a', 'b']);
deepEqual(utils.splitOnUnquotedCommaSpace('a, b, '), ['a', 'b', '']);
deepEqual(utils.splitOnUnquotedCommaSpace('\\"a, b", "c, d\\", e", f"'), ['\\"a', 'b", "c', 'd\\"', 'e", f"']);
});
});

View file

@ -1,54 +0,0 @@
/*
* Licensed to Elasticsearch B.V. under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch B.V. licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
require('ace');
const module = require('ui/modules').get('app/sense');
// mock the resize checker
module.run(function () {
module.setupResizeCheckerForRootEditors = () => {};
});
require('ui/chrome')
.setRootTemplate(require('./index.html'))
.setRootController(function () {
window.QUnit = require('qunit-1.10.0');
require('qunit-1.10.0.css');
require('ace');
/* global QUnit */
QUnit.config.autostart = false;
QUnit.init();
require('./src/content_type.js');
require('./src/utils_tests.js');
require('./src/url_autocomplete_tests.js');
require('./src/url_params_tests.js');
require('./src/curl_parsing_tests.js');
require('./src/kb_tests.js');
require('./src/mapping_tests.js');
require('./src/editor_tests.js');
require('./src/input_tokenization_tests.js');
require('./src/output_tokenization_tests.js');
require('./src/integration_tests.js');
console.log('all tests loaded');
QUnit.start();
});

View file

@ -1,270 +0,0 @@
/**
* QUnit v1.10.0 - A JavaScript Unit Testing Framework
*
* http://qunitjs.com
*
* Copyright 2012 jQuery Foundation and other contributors
* Released under the MIT license.
* http://jquery.org/license
*/
/** Font Family and Sizes */
#qunit-tests, #qunit-header, #qunit-banner, #qunit-testrunner-toolbar, #qunit-userAgent, #qunit-testresult {
font-family: "Helvetica Neue Light", "HelveticaNeue-Light", "Helvetica Neue", Calibri, Helvetica, Arial, sans-serif;
}
#qunit-testrunner-toolbar, #qunit-userAgent, #qunit-testresult, #qunit-tests li {
font-size: small;
}
#qunit-tests {
font-size: smaller;
}
/** Resets */
#qunit-tests, #qunit-tests ol, #qunit-header, #qunit-banner, #qunit-userAgent, #qunit-testresult, #qunit-modulefilter {
margin: 0;
padding: 0;
}
/** Header */
#qunit-header {
padding: 0.5em 0 0.5em 1em;
color: #8699a4;
background-color: #0d3349;
font-size: 1.5em;
line-height: 1em;
font-weight: normal;
border-radius: 5px 5px 0 0;
-moz-border-radius: 5px 5px 0 0;
-webkit-border-top-right-radius: 5px;
-webkit-border-top-left-radius: 5px;
}
#qunit-header a {
text-decoration: none;
color: #c2ccd1;
}
#qunit-header a:hover,
#qunit-header a:focus {
color: #fff;
}
#qunit-testrunner-toolbar label {
display: inline-block;
padding: 0 .5em 0 .1em;
}
#qunit-banner {
height: 5px;
}
#qunit-testrunner-toolbar {
padding: 0.5em 0 0.5em 2em;
color: #5E740B;
background-color: #eee;
overflow: hidden;
}
#qunit-userAgent {
padding: 0.5em 0 0.5em 2.5em;
background-color: #2b81af;
color: #fff;
text-shadow: rgba(0, 0, 0, 0.5) 2px 2px 1px;
}
#qunit-modulefilter-container {
float: right;
}
/** Tests: Pass/Fail */
#qunit-tests {
list-style-position: inside;
}
#qunit-tests li {
padding: 0.4em 0.5em 0.4em 2.5em;
border-bottom: 1px solid #fff;
list-style-position: inside;
}
#qunit-tests.hidepass li.pass, #qunit-tests.hidepass li.running {
display: none;
}
#qunit-tests li strong {
cursor: pointer;
}
#qunit-tests li a {
padding: 0.5em;
color: #c2ccd1;
text-decoration: none;
}
#qunit-tests li a:hover,
#qunit-tests li a:focus {
color: #000;
}
#qunit-tests ol {
margin-top: 0.5em;
padding: 0.5em;
background-color: #fff;
border-radius: 5px;
-moz-border-radius: 5px;
-webkit-border-radius: 5px;
}
#qunit-tests table {
border-collapse: collapse;
margin-top: .2em;
}
#qunit-tests th {
text-align: right;
vertical-align: top;
padding: 0 .5em 0 0;
}
#qunit-tests td {
vertical-align: top;
}
#qunit-tests pre {
margin: 0;
white-space: pre-wrap;
word-wrap: break-word;
}
#qunit-tests del {
background-color: #e0f2be;
color: #374e0c;
text-decoration: none;
}
#qunit-tests ins {
background-color: #ffcaca;
color: #500;
text-decoration: none;
}
/*** Test Counts */
#qunit-tests b.counts {
color: black;
}
#qunit-tests b.passed {
color: #5E740B;
}
#qunit-tests b.failed {
color: #710909;
}
#qunit-tests li li {
padding: 5px;
background-color: #fff;
border-bottom: none;
list-style-position: inside;
}
/*** Passing Styles */
#qunit-tests li li.pass {
color: #3c510c;
background-color: #fff;
border-left: 10px solid #C6E746;
}
#qunit-tests .pass {
color: #528CE0;
background-color: #D2E0E6;
}
#qunit-tests .pass .test-name {
color: #366097;
}
#qunit-tests .pass .test-actual,
#qunit-tests .pass .test-expected {
color: #999999;
}
#qunit-banner.qunit-pass {
background-color: #C6E746;
}
/*** Failing Styles */
#qunit-tests li li.fail {
color: #710909;
background-color: #fff;
border-left: 10px solid #EE5757;
white-space: pre;
}
#qunit-tests > li:last-child {
border-radius: 0 0 5px 5px;
-moz-border-radius: 0 0 5px 5px;
-webkit-border-bottom-right-radius: 5px;
-webkit-border-bottom-left-radius: 5px;
}
#qunit-tests .fail {
color: #000000;
background-color: #EE5757;
}
#qunit-tests .fail .test-name,
#qunit-tests .fail .module-name {
color: #000000;
}
#qunit-tests .fail .test-actual {
color: #EE5757;
}
#qunit-tests .fail .test-expected {
color: green;
}
#qunit-banner.qunit-fail {
background-color: #EE5757;
}
/** Result */
#qunit-testresult {
padding: 0.5em 0.5em 0.5em 2.5em;
color: #2b81af;
background-color: #D2E0E6;
border-bottom: 1px solid white;
}
#qunit-testresult .module-name {
font-weight: bold;
}
/** Fixture */
#qunit-fixture {
position: absolute;
top: -10000px;
left: -10000px;
width: 1000px;
height: 1000px;
}

View file

@ -80,6 +80,8 @@ export default {
transform: {
'^.+\\.js$': '<rootDir>/src/dev/jest/babel_transform.js',
'^.+\\.tsx?$': '<rootDir>/src/dev/jest/ts_transform.js',
'^.+\\.txt?$': 'jest-raw-loader',
'^.+\\.html?$': 'jest-raw-loader',
},
transformIgnorePatterns: [
'[/\\\\]node_modules[/\\\\].+\\.js$',

View file

@ -7097,6 +7097,10 @@ jest-mock@^22.4.3:
version "22.4.3"
resolved "https://registry.yarnpkg.com/jest-mock/-/jest-mock-22.4.3.tgz#f63ba2f07a1511772cdc7979733397df770aabc7"
jest-raw-loader@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/jest-raw-loader/-/jest-raw-loader-1.0.1.tgz#ce9f56d54650f157c4a7d16d224ba5d613bcd626"
jest-regex-util@^22.4.3:
version "22.4.3"
resolved "https://registry.yarnpkg.com/jest-regex-util/-/jest-regex-util-22.4.3.tgz#a826eb191cdf22502198c5401a1fc04de9cef5af"