@jupyter-lsp/jupyterlab-lsp
Version:
Language Server Protocol integration for JupyterLab
224 lines (211 loc) • 6.44 kB
text/typescript
import { python } from '@codemirror/lang-python';
import { Language } from '@codemirror/language';
import { jupyterHighlightStyle } from '@jupyterlab/codemirror';
import { tags } from '@lezer/highlight';
import * as lsProtocol from 'vscode-languageserver-protocol';
import { BrowserConsole } from '../virtual/console';
import { extractLead, signatureToMarkdown, highlightCode } from './signature';
describe('Signature', () => {
describe('extractLead()', () => {
it('Extracts standalone one-line paragraph', () => {
const split = extractLead(
['This function does foo', '', 'But there are more details'],
1
)!;
expect(split.lead).toBe('This function does foo');
expect(split.remainder).toBe('But there are more details');
});
it('Does not extracts when it would break markdown', () => {
let split = extractLead(
['This is **not the end', '', 'of this spread sentence**'],
1
);
expect(split).toBe(null);
split = extractLead(
['This is <b>not the end', '', 'of this spread sentence</b>'],
1
);
expect(split).toBe(null);
});
it('Extracts standalone two-line paragraph', () => {
const split = extractLead(
[
'This function does foo,',
'and it does bar',
'',
'But there are more details'
],
2
)!;
expect(split.lead).toBe('This function does foo,\nand it does bar');
expect(split.remainder).toBe('But there are more details');
});
it('Does not extract too long paragraph', () => {
const split = extractLead(
[
'This function does foo,',
'and it does bar',
'',
'But there are more details'
],
1
);
expect(split).toBe(null);
});
});
describe('highlightCode()', () => {
const pythonLanguage = python().language;
const arithmeticClass = jupyterHighlightStyle.style([
tags.arithmeticOperator
]);
const numberClass = jupyterHighlightStyle.style([tags.number]);
it('marks first parameter', () => {
const result = highlightCode(
'(x: int = 1, y: int = 2) -> None',
{ label: 'x: int = 1' },
pythonLanguage
);
expect(
result.includes(
`<mark>x: int </mark><mark class="${arithmeticClass}">=</mark><mark> </mark><mark class="${numberClass}">1</mark>`
)
).toBe(true);
});
it('marks second parameter', () => {
const result = highlightCode(
'(x: int = 1, y: int = 2) -> None',
{ label: 'y: int = 2' },
pythonLanguage
);
expect(
result.includes(
`<mark>y: int </mark><mark class="${arithmeticClass}">=</mark><mark> </mark><mark class="${numberClass}">2</mark>`
)
).toBe(true);
});
});
describe('signatureToMarkdown()', () => {
const MockHighlighter = (
code: string,
fragment: lsProtocol.ParameterInformation,
_language: Language | undefined
) => {
const label = typeof fragment.label === 'string' ? fragment.label : '';
return code.replace(label, `<u>${label}</u>`);
};
it('renders plaintext signature', async () => {
let text = signatureToMarkdown(
{
label: 'str(text)',
documentation: 'Create a new *string* object from the given object.',
parameters: [
{
label: 'text',
documentation: undefined
}
],
activeParameter: 0
},
python().language,
MockHighlighter,
new BrowserConsole()
);
expect(text).toBe(
'str(<u>text</u>)\n\nCreate a new \\*string\\* object from the given object.\n'
);
});
it('renders plaintext signature with MarkupContent documentation', async () => {
let text = signatureToMarkdown(
{
label: 'str(text)',
documentation: {
value: 'Create a new *string* object from the given object.',
kind: 'plaintext'
},
parameters: [
{
label: 'text',
documentation: undefined
}
],
activeParameter: 0
},
python().language,
MockHighlighter,
new BrowserConsole()
);
expect(text).toBe(
'str(<u>text</u>)\n\nCreate a new \\*string\\* object from the given object.\n'
);
});
it('renders Markdown signature', async () => {
let text = signatureToMarkdown(
{
label: 'str(text)',
documentation: {
value: 'Create a new *string* object from the given object.',
kind: 'markdown'
},
parameters: [
{
label: 'text',
documentation: undefined
}
],
activeParameter: 0
},
python().language,
MockHighlighter,
new BrowserConsole()
);
expect(text).toBe(
'str(<u>text</u>)\n\nCreate a new *string* object from the given object.'
);
});
it('renders plaintext with details and paramaters', async () => {
let text = signatureToMarkdown(
{
label: 'str(text)',
documentation: {
value: 'line 1\n\nline 2\nline 3\nline 4\nline 5',
kind: 'plaintext'
},
parameters: [
{
label: 'text',
documentation: undefined
}
],
activeParameter: 0
},
python().language,
MockHighlighter,
new BrowserConsole(),
undefined,
4
);
expect(text).toBe(
'str(<u>text</u>)\n\nline 1\n<details>\nline 2\nline 3\nline 4\nline 5\n</details>'
);
});
it('renders plaintext with details and no parameters', async () => {
let text = signatureToMarkdown(
{
label: 'str()',
documentation: {
value: 'line 1\n\nline 2\nline 3\nline 4\nline 5',
kind: 'plaintext'
}
},
python().language,
MockHighlighter,
new BrowserConsole(),
undefined,
4
);
expect(text).toBe(
'```python\nstr()\n```\n\nline 1\n<details>\nline 2\nline 3\nline 4\nline 5\n</details>'
);
});
});
});