2017-01-07 04:10:33 +00:00
|
|
|
const assert = require('assert');
|
|
|
|
global.CyTube = {};
|
|
|
|
require('../../www/js/tabcomplete');
|
|
|
|
|
|
|
|
|
|
|
|
describe('CyTube.tabCompletionMethods', () => {
|
2017-01-11 06:26:46 +00:00
|
|
|
describe('"Longest unique match"', () => {
|
2017-01-07 18:55:59 +00:00
|
|
|
const testcases = [
|
|
|
|
{
|
|
|
|
input: 'and his name is j',
|
|
|
|
position: 17,
|
|
|
|
options: ['johncena', 'johnstamos', 'johto'],
|
|
|
|
output: {
|
|
|
|
text: 'and his name is joh',
|
|
|
|
newPosition: 19
|
|
|
|
},
|
|
|
|
description: 'completes the longest unique substring'
|
|
|
|
},
|
|
|
|
{
|
|
|
|
input: 'and his name is johnc',
|
|
|
|
position: 21,
|
|
|
|
options: ['johncena', 'johnstamos', 'johto'],
|
|
|
|
output: {
|
|
|
|
text: 'and his name is johncena ',
|
|
|
|
newPosition: 25
|
|
|
|
},
|
|
|
|
description: 'completes a unique match'
|
|
|
|
},
|
2017-01-11 06:26:46 +00:00
|
|
|
{
|
|
|
|
input: 'johnc',
|
|
|
|
position: 5,
|
|
|
|
options: ['johncena', 'johnstamos', 'johto'],
|
|
|
|
output: {
|
|
|
|
text: 'johncena ',
|
|
|
|
newPosition: 9
|
|
|
|
},
|
|
|
|
description: 'completes a unique match at the beginning of the string'
|
|
|
|
},
|
2017-01-07 18:55:59 +00:00
|
|
|
{
|
|
|
|
input: 'and his name is johnc',
|
|
|
|
position: 21,
|
|
|
|
options: ['asdf'],
|
|
|
|
output: {
|
|
|
|
text: 'and his name is johnc',
|
|
|
|
newPosition: 21
|
|
|
|
},
|
|
|
|
description: 'does not complete when there is no match'
|
|
|
|
},
|
|
|
|
{
|
|
|
|
input: 'and his name is ',
|
|
|
|
position: 16,
|
|
|
|
options: ['asdf'],
|
|
|
|
output: {
|
|
|
|
text: 'and his name is ',
|
|
|
|
newPosition: 16
|
|
|
|
},
|
|
|
|
description: 'does not complete when there is an empty prefix'
|
|
|
|
},
|
|
|
|
{
|
|
|
|
input: 'and his name is johnc',
|
|
|
|
position: 21,
|
|
|
|
options: [],
|
|
|
|
output: {
|
|
|
|
text: 'and his name is johnc',
|
|
|
|
newPosition: 21
|
|
|
|
},
|
|
|
|
description: 'does not complete when there are no options'
|
|
|
|
},
|
|
|
|
{
|
|
|
|
input: '',
|
|
|
|
position: 0,
|
|
|
|
options: ['abc', 'def', 'ghi'],
|
|
|
|
output: {
|
|
|
|
text: '',
|
|
|
|
newPosition: 0
|
|
|
|
},
|
|
|
|
description: 'does not complete when the input is empty'
|
|
|
|
}
|
|
|
|
];
|
2017-01-07 04:10:33 +00:00
|
|
|
testcases.forEach(test => {
|
|
|
|
it(test.description, () => {
|
2017-01-07 18:55:59 +00:00
|
|
|
assert.deepEqual(
|
2017-01-11 06:26:46 +00:00
|
|
|
CyTube.tabCompleteMethods['Longest unique match'](
|
2017-01-07 04:10:33 +00:00
|
|
|
test.input,
|
|
|
|
test.position,
|
|
|
|
test.options,
|
|
|
|
{}
|
2017-01-07 18:55:59 +00:00
|
|
|
),
|
|
|
|
test.output
|
2017-01-07 04:10:33 +00:00
|
|
|
);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
2017-01-07 18:55:59 +00:00
|
|
|
|
|
|
|
describe('"Cycle options"', () => {
|
|
|
|
const testcases = [
|
|
|
|
{
|
|
|
|
input: 'hey c',
|
|
|
|
position: 5,
|
|
|
|
options: ['COBOL', 'Carlos', 'carl', 'john', 'joseph', ''],
|
|
|
|
outputs: [
|
|
|
|
{
|
|
|
|
text: 'hey carl ',
|
|
|
|
newPosition: 9
|
|
|
|
},
|
|
|
|
{
|
|
|
|
text: 'hey Carlos ',
|
|
|
|
newPosition: 11
|
|
|
|
},
|
|
|
|
{
|
|
|
|
text: 'hey COBOL ',
|
|
|
|
newPosition: 10
|
|
|
|
},
|
|
|
|
{
|
|
|
|
text: 'hey carl ',
|
|
|
|
newPosition: 9
|
|
|
|
}
|
|
|
|
],
|
|
|
|
description: 'cycles through options correctly'
|
|
|
|
},
|
2017-01-11 06:26:46 +00:00
|
|
|
{
|
|
|
|
input: 'c',
|
|
|
|
position: 1,
|
|
|
|
options: ['COBOL', 'Carlos', 'carl', 'john', 'joseph', ''],
|
|
|
|
outputs: [
|
|
|
|
{
|
|
|
|
text: 'carl ',
|
|
|
|
newPosition: 5
|
|
|
|
},
|
|
|
|
{
|
|
|
|
text: 'Carlos ',
|
|
|
|
newPosition: 7
|
|
|
|
},
|
|
|
|
{
|
|
|
|
text: 'COBOL ',
|
|
|
|
newPosition: 6
|
|
|
|
},
|
|
|
|
{
|
|
|
|
text: 'carl ',
|
|
|
|
newPosition: 5
|
|
|
|
}
|
|
|
|
],
|
|
|
|
description: 'cycles through options correctly at the beginning of the string'
|
|
|
|
},
|
2017-01-07 18:55:59 +00:00
|
|
|
{
|
|
|
|
input: 'hey ',
|
|
|
|
position: 5,
|
|
|
|
options: ['COBOL', 'Carlos', 'carl', 'john'],
|
|
|
|
outputs: [
|
|
|
|
{
|
|
|
|
text: 'hey ',
|
|
|
|
newPosition: 5
|
|
|
|
}
|
|
|
|
],
|
|
|
|
description: 'does not complete when there is an empty prefix'
|
|
|
|
},
|
|
|
|
{
|
|
|
|
input: 'hey c',
|
|
|
|
position: 6,
|
|
|
|
options: [],
|
|
|
|
outputs: [
|
|
|
|
{
|
|
|
|
text: 'hey c',
|
|
|
|
newPosition: 6
|
|
|
|
}
|
|
|
|
],
|
|
|
|
description: 'does not complete when there are no options'
|
|
|
|
},
|
|
|
|
{
|
|
|
|
input: '',
|
|
|
|
position: 0,
|
|
|
|
options: ['COBOL', 'Carlos', 'carl', 'john'],
|
|
|
|
outputs: [
|
|
|
|
{
|
|
|
|
text: '',
|
|
|
|
newPosition: 0
|
|
|
|
}
|
|
|
|
],
|
|
|
|
description: 'does not complete when the input is empty'
|
|
|
|
}
|
|
|
|
];
|
|
|
|
|
|
|
|
const complete = CyTube.tabCompleteMethods['Cycle options'];
|
|
|
|
testcases.forEach(test => {
|
|
|
|
it(test.description, () => {
|
|
|
|
var context = {};
|
|
|
|
var currentText = test.input;
|
|
|
|
var currentPosition = test.position;
|
|
|
|
for (var i = 0; i < test.outputs.length; i++) {
|
|
|
|
var output = complete(currentText, currentPosition, test.options, context);
|
|
|
|
assert.deepEqual(output, test.outputs[i]);
|
|
|
|
currentText = output.text;
|
|
|
|
currentPosition = output.newPosition;
|
|
|
|
}
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
it('updates the context when the input changes to reduce the # of matches', () => {
|
|
|
|
var test = testcases[0];
|
|
|
|
var context = {};
|
|
|
|
var currentText = test.input;
|
|
|
|
var currentPosition = test.position;
|
|
|
|
|
|
|
|
var output = complete(currentText, currentPosition, test.options, context);
|
|
|
|
assert.deepEqual(context, {
|
|
|
|
start: 4,
|
|
|
|
matches: ['carl', 'Carlos', 'COBOL'],
|
|
|
|
tabIndex: 0
|
|
|
|
});
|
|
|
|
currentText = output.text;
|
|
|
|
currentPosition = output.newPosition;
|
|
|
|
|
|
|
|
output = complete(currentText, currentPosition, test.options, context);
|
|
|
|
assert.deepEqual(context, {
|
|
|
|
start: 4,
|
|
|
|
matches: ['carl', 'Carlos', 'COBOL'],
|
|
|
|
tabIndex: 1
|
|
|
|
});
|
|
|
|
currentText = output.text.replace(context.matches[1], 'jo').trim();
|
|
|
|
currentPosition = 6;
|
|
|
|
|
|
|
|
output = complete(currentText, currentPosition, test.options, context);
|
|
|
|
assert.deepEqual(context, {
|
|
|
|
start: 4,
|
|
|
|
matches: ['john', 'joseph'],
|
|
|
|
tabIndex: 0
|
|
|
|
});
|
|
|
|
assert.deepEqual(output, {
|
|
|
|
text: 'hey john ',
|
|
|
|
newPosition: 9
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
it('clears the context when the input changes to a non-match', () => {
|
|
|
|
var test = testcases[0];
|
|
|
|
var context = {};
|
|
|
|
var currentText = test.input;
|
|
|
|
var currentPosition = test.position;
|
|
|
|
|
|
|
|
var output = complete(currentText, currentPosition, test.options, context);
|
|
|
|
assert.deepEqual(context, {
|
|
|
|
start: 4,
|
|
|
|
matches: ['carl', 'Carlos', 'COBOL'],
|
|
|
|
tabIndex: 0
|
|
|
|
});
|
|
|
|
currentText = output.text;
|
|
|
|
currentPosition = output.newPosition;
|
|
|
|
|
|
|
|
output = complete(currentText, currentPosition, test.options, context);
|
|
|
|
assert.deepEqual(context, {
|
|
|
|
start: 4,
|
|
|
|
matches: ['carl', 'Carlos', 'COBOL'],
|
|
|
|
tabIndex: 1
|
|
|
|
});
|
|
|
|
currentText = output.text.replace(context.matches[1], 'asdf').trim();
|
|
|
|
currentPosition = 8;
|
|
|
|
|
|
|
|
output = complete(currentText, currentPosition, test.options, context);
|
|
|
|
assert.deepEqual(context, {});
|
|
|
|
assert.deepEqual(output, {
|
|
|
|
text: 'hey asdf',
|
|
|
|
newPosition: 8
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
2017-01-07 04:10:33 +00:00
|
|
|
});
|