Files
redocly-cli/packages/core/__tests__/codeframes.test.ts
2020-11-13 21:13:47 +02:00

510 lines
14 KiB
TypeScript
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { outdent } from 'outdent';
import { getLineColLocation, getCodeframe } from '../src/format/codeframes';
import { LocationObject } from '../src/walk';
import { Source } from '../src/resolve';
describe('Location', () => {
it('should correctly calculate location for key', () => {
const loc = {
reportOnKey: true,
pointer: '#/info/license',
source: new Source(
'foobar.yaml',
outdent`
openapi: 3.0.2
info:
license:
name: MIT
url: https://google.com
`,
),
};
const preciseLocation = getLineColLocation(loc);
expect(preciseLocation.start).toEqual({ line: 3, col: 3 });
expect(preciseLocation.end).toEqual({ line: 3, col: 10 });
});
it('should correctly calculate location for key on top level', () => {
const loc = {
reportOnKey: true,
pointer: '#/info',
source: new Source(
'foobar.yaml',
outdent`
openapi: 3.0.2
info:
license:
name: MIT
url: https://google.com
`,
),
};
const preciseLocation = getLineColLocation(loc);
expect(preciseLocation.start).toEqual({ line: 2, col: 1 });
expect(preciseLocation.end).toEqual({ line: 2, col: 5 });
});
it('should correctly calculate location for value', () => {
const loc = {
reportOnKey: false,
pointer: '#/info/license/name',
source: new Source(
'foobar.yaml',
outdent`
openapi: 3.0.2
info:
license:
name: MIT
url: https://google.com
`,
),
};
const preciseLocation = getLineColLocation(loc);
expect(preciseLocation.start).toEqual({ line: 4, col: 11 });
expect(preciseLocation.end).toEqual({ line: 4, col: 14 });
});
it('should correctly fallback to the closest parent node if pointer is incorrect', () => {
const loc = {
reportOnKey: false,
pointer: '#/info/missing',
source: new Source(
'foobar.yaml',
outdent`
openapi: 3.0.2
info:
license:
name: MIT
url: https://google.com
`,
),
};
const preciseLocation = getLineColLocation(loc);
expect(preciseLocation.start).toEqual({ line: 3, col: 3 });
expect(preciseLocation.end).toEqual({ line: 5, col: 28 });
});
it('should return first line for empty doc', () => {
const loc = {
reportOnKey: false,
pointer: '#/info/missing',
source: new Source('foobar.yaml', ''),
};
const preciseLocation = getLineColLocation(loc);
expect(preciseLocation.start).toEqual({ line: 1, col: 1 });
expect(preciseLocation.end).toEqual({ line: 1, col: 1 });
});
it('should return full range for file with newlines', () => {
const loc = {
reportOnKey: false,
pointer: '#/info/missing',
source: new Source('foobar.yaml', '\n\n\n'),
};
const preciseLocation = getLineColLocation(loc);
expect(preciseLocation.start).toEqual({ line: 1, col: 1 });
expect(preciseLocation.end).toEqual({ line: 1, col: 1 });
});
});
describe('codeframes', () => {
function getColorCodeframe(loc: LocationObject) {
return getCodeframe(getLineColLocation(loc), true)
.replace(/\x1b\[90m(.*?)\x1b\[39m/g, '<g>$1</g>')
.replace(/\x1b\[31m(.*?)\x1b\[39m/g, '<r>$1</r>');
}
function getPlainCodeframe(loc: LocationObject) {
return getCodeframe(getLineColLocation(loc), false);
}
expect.addSnapshotSerializer({
test: (val) => typeof val === 'string',
print: (v) => v as string,
});
it('should correctly generate simple codeframe', () => {
const loc = {
reportOnKey: true,
pointer: '#/info/license',
source: new Source(
'foobar.yaml',
outdent`
openapi: 3.0.2
info:
license:
name: MIT
url: https://google.com
`,
),
};
expect(getPlainCodeframe(loc)).toMatchInlineSnapshot(`
1 | openapi: 3.0.2
2 | info:
3 | license:
| ^^^^^^^
4 | name: MIT
5 | url: https://google.com
`);
expect(getColorCodeframe(loc)).toMatchInlineSnapshot(`
<g>1 |</g> <g>openapi: 3.0.2</g>
<g>2 |</g> <g>info:</g>
<g>3 |</g> <r>license</r>:
<g>4 |</g> <g>name: MIT</g>
<g>5 |</g> <g>url: https://google.com</g>
`);
});
it('correctly generate code-frame for single-line file on key', () => {
const loc = {
reportOnKey: true,
pointer: '#/openapi',
source: new Source('foobar.yaml', `openapi: 3.0.2`),
};
expect(getPlainCodeframe(loc)).toMatchInlineSnapshot(`
1 | openapi: 3.0.2
| ^^^^^^^
`);
expect(getColorCodeframe(loc)).toMatchInlineSnapshot(`<g>1 |</g> <r>openapi</r>: 3.0.2`);
});
it('correctly generate code-frame for single-line file on value', () => {
const loc = {
reportOnKey: false,
pointer: '#/openapi',
source: new Source('foobar.yaml', `openapi: 3.0.2`),
};
expect(getPlainCodeframe(loc)).toMatchInlineSnapshot(`
1 | openapi: 3.0.2
| ^^^^^
`);
expect(getColorCodeframe(loc)).toMatchInlineSnapshot(`<g>1 |</g> openapi: <r>3.0.2</r>`);
});
it('correctly generate code-frame for multiline-value', () => {
const loc = {
reportOnKey: false,
pointer: '#/info/license',
source: new Source(
'foobar.yaml',
outdent`
openapi: 3.0.2
info:
license:
name: MIT
url: https://google.com
`,
),
};
expect(getPlainCodeframe(loc)).toMatchInlineSnapshot(`
2 | info:
3 | license:
4 | name: MIT
| ^^^^^^^^^
5 | url: https://google.com
| ^^^^^^^^^^^^^^^^^^^^^^^
`);
expect(getColorCodeframe(loc)).toMatchInlineSnapshot(`
<g>2 |</g> <g>info:</g>
<g>3 |</g> <g>license:</g>
<g>4 |</g> <r>name: MIT</r>
<g>5 |</g> <r>url: https://google.com</r>
`);
});
it('correctly generate code-frame for multiline-value json-like', () => {
const loc = {
reportOnKey: false,
pointer: '#/info/license',
source: new Source(
'foobar.yaml',
outdent`
openapi: 3.0.2
info:
license: {
name: MIT,
url: https://google.com
}
`,
),
};
expect(getPlainCodeframe(loc)).toMatchInlineSnapshot(`
1 | openapi: 3.0.2
2 | info:
3 | license: {
| ^
4 | name: MIT,
| ^^^^^^^^^^
5 | url: https://google.com
| ^^^^^^^^^^^^^^^^^^^^^^^
6 | }
| ^
`);
expect(getColorCodeframe(loc)).toMatchInlineSnapshot(`
<g>1 |</g> <g>openapi: 3.0.2</g>
<g>2 |</g> <g>info:</g>
<g>3 |</g> license: <r>{</r>
<g>4 |</g> <r>name: MIT,</r>
<g>5 |</g> <r>url: https://google.com</r>
<g>6 |</g> <r>}</r>
`);
});
it('correctly generate code-frame for multiline-value and show only 5 lines', () => {
const loc = {
reportOnKey: false,
pointer: '#/info/license',
source: new Source(
'foobar.yaml',
outdent`
info:
license:
name: MIT
field2: MIT
field3: MIT
field4: MIT
field5: MIT
url: https://google.com
openapi: 3.0.2
`,
),
};
expect(getPlainCodeframe(loc)).toMatchInlineSnapshot(`
1 | info:
2 | license:
3 | name: MIT
| ^^^^^^^^^
4 | field2: MIT
| ^^^^^^^^^^^
… | < 3 more lines >
8 | url: https://google.com
| ^^^^^^^^^^^^^^^^^^^^^^^
9 | openapi: 3.0.2
`);
expect(getColorCodeframe(loc)).toMatchInlineSnapshot(`
<g>1 |</g> <g>info:</g>
<g>2 |</g> <g>license:</g>
<g>3 |</g> <r>name: MIT</r>
<g>4 |</g> <r>field2: MIT</r>
<g>… |</g> <g>< 3 more lines ></g>
<g>8 |</g> <r>url: https://google.com</r>
<g>9 |</g> <g>openapi: 3.0.2</g>
`);
});
it('correctly generate code-frame for multiline-value and show only 5 lines with empty lines', () => {
const loc = {
reportOnKey: false,
pointer: '#/info/license',
source: new Source(
'foobar.yaml',
outdent`
info:
license:
name: MIT
field2: MIT
field3: MIT
field4: MIT
field5: MIT
`,
),
};
expect(getPlainCodeframe(loc)).toMatchInlineSnapshot(`
2 |
3 | license:
4 | name: MIT
| ^^^^^^^^^
5 |
| ^
… | < 3 more lines >
9 | field5: MIT
| ^^^^^^^^^^^
`);
expect(getColorCodeframe(loc)).toMatchInlineSnapshot(`
<g>2 |</g>
<g>3 |</g> <g>license:</g>
<g>4 |</g> <r>name: MIT</r>
<g>5 |</g>
<g>… |</g> <g>< 3 more lines ></g>
<g>9 |</g> <r>field5: MIT</r>
`);
});
it('correctly generate code-frame dedent', () => {
const loc = {
reportOnKey: false,
pointer: '#/paths/~1pet/put/parameters/0/in',
source: new Source(
'foobar.yaml',
outdent`
openapi: 3.0.2
info:
license:
name: MIT
url: https://google.com
paths:
'/pet':
put:
operationId: test
parameters:
- name: a
in: wrong
post:
operationId: test2
`,
),
};
expect(getPlainCodeframe(loc)).toMatchInlineSnapshot(`
10 | parameters:
11 | - name: a
12 | in: wrong
| ^^^^^
13 | post:
14 | operationId: test2
`);
expect(getColorCodeframe(loc)).toMatchInlineSnapshot(`
<g>10 |</g> <g>parameters:</g>
<g>11 |</g> <g>- name: a</g>
<g>12 |</g> in: <r>wrong</r>
<g>13 |</g> <g>post:</g>
<g>14 |</g> <g>operationId: test2</g>
`);
});
it('correctly generate code-frame for too long line', () => {
const loc = {
reportOnKey: false,
pointer: '#/info/description',
source: new Source(
'foobar.yaml',
outdent`
openapi: 3.0.2
info:
description: Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea
license:
name: MIT
url: https://google.com
`,
),
};
expect(getPlainCodeframe(loc)).toMatchInlineSnapshot(`
1 | openapi: 3.0.2
2 | info:
3 | description: Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua...<77 chars>
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^...<77 chars>
4 | license:
5 | name: MIT
`);
expect(getColorCodeframe(loc)).toMatchInlineSnapshot(`
<g>1 |</g> <g>openapi: 3.0.2</g>
<g>2 |</g> <g>info:</g>
<g>3 |</g> description: Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolo<g>...<87 chars></g>
<g>4 |</g> <g>license:</g>
<g>5 |</g> <g>name: MIT</g>
`);
});
it('correctly generate code-frame for empty file', () => {
const loc = {
reportOnKey: false,
pointer: '#/info/description',
source: new Source('foobar.yaml', `\n\n`),
};
expect(getPlainCodeframe(loc)).toMatchInlineSnapshot(`
1 |
| ^
2 |
3 |
`);
expect(getColorCodeframe(loc)).toMatchInlineSnapshot(`
<g>1 |</g>
<g>2 |</g>
<g>3 |</g>
`);
});
it('correctly generate code-frame for whole file and correctly skip newlines', () => {
const loc = {
reportOnKey: false,
pointer: '#/',
source: new Source(
'foobar.yaml',
outdent`
openapi: 3.0.2
info:
description: Lorem ipsum
license:
name: MIT
url: https://google.com
`,
),
};
expect(getPlainCodeframe(loc)).toMatchInlineSnapshot(`
1 | openapi: 3.0.2
| ^^^^^^^^^^^^^^
2 |
| ^
… | < 5 more lines >
8 | url: https://google.com
| ^^^^^^^^^^^^^^^^^^^^^^^
`);
expect(getColorCodeframe(loc)).toMatchInlineSnapshot(`
<g>1 |</g> <r>openapi: 3.0.2</r>
<g>2 |</g>
<g>… |</g> <g>< 5 more lines ></g>
<g>8 |</g> <r>url: https://google.com</r>
`);
});
it('should show line even if there are not so many file in the file', () => {
// (yaml parser sometimes shows error on the next after last line
const loc = {
reportOnKey: false,
pointer: undefined,
start: {
line: 2,
col: 1,
},
source: new Source('foobar.yaml', outdent`openapi: 3.0.2`),
};
expect(getPlainCodeframe(loc)).toMatchInlineSnapshot(`
1 | openapi: 3.0.2
2 |
| ^
`);
expect(getColorCodeframe(loc)).toMatchInlineSnapshot(`
<g>1 |</g> <g>openapi: 3.0.2</g>
<g>2 |</g>
`);
});
});