@code-to-json/core
Version:
Core analysis tools for code-to-json
242 lines (218 loc) • 6.77 kB
text/typescript
import { expect } from 'chai';
import { describe, it } from 'mocha';
import SingleFileAcceptanceTestCase from './helpers/test-case';
describe('Comment serialization tests', () => {
it('basic comments', async () => {
const code = `interface Foo { num: number; }
/**
* A thing
*/
export const x: Foo = { num: 4 };`;
const t = new SingleFileAcceptanceTestCase(code);
await t.run();
const file = t.sourceFile();
const fileSymbol = t.resolveReference(file.symbol);
const variableSymbol = t.resolveReference(fileSymbol.exports!.x);
expect(variableSymbol.text).to.eql('x');
expect(variableSymbol.flags).to.eql(['BlockScopedVariable'], 'Regarded as a variable');
expect(variableSymbol.documentation).to.deep.eq({
summary: ['A thing'],
});
const variableType = t.resolveReference(variableSymbol.valueDeclarationType);
expect(variableType.text).to.eql('Foo', 'has correct type');
t.cleanup();
});
it('with @see block tag', async () => {
const code = `interface Foo { num: number; }
/**
* A thing
* @see Mike
*/
export const x: Foo = { num: 4 };`;
const t = new SingleFileAcceptanceTestCase(code);
await t.run();
const file = t.sourceFile();
const fileSymbol = t.resolveReference(file.symbol);
const variableSymbol = t.resolveReference(fileSymbol.exports!.x);
expect(variableSymbol.text).to.eql('x');
expect(variableSymbol.flags).to.eql(['BlockScopedVariable'], 'Regarded as a variable');
expect(variableSymbol.documentation).to.deep.eq({
summary: ['A thing'],
customTags: [
{
content: ['Mike'],
kind: 'blockTag',
tagName: 'see',
},
],
});
const variableType = t.resolveReference(variableSymbol.valueDeclarationType);
expect(variableType.text).to.eql('Foo', 'has correct type');
t.cleanup();
});
it('with @param tags', async () => {
const code = `interface Foo { num: number; }
/**
* Add two numbers
* @param a first number
* @param b second number
*/
export function add(a: number, b: number) { return a + b; }`;
const t = new SingleFileAcceptanceTestCase(code);
await t.run();
const file = t.sourceFile();
const fileSymbol = t.resolveReference(file.symbol);
const functionSymbol = t.resolveReference(fileSymbol.exports!.add);
expect(functionSymbol.text).to.eql('add');
expect(functionSymbol.flags).to.eql(['Function'], 'Regarded as a function');
expect(functionSymbol.documentation).to.deep.eq({
summary: ['Add two numbers'],
params: [
{
content: ['first number'],
kind: 'param',
name: 'a',
tagName: 'param',
},
{
content: ['second number'],
kind: 'param',
name: 'b',
tagName: 'param',
},
],
});
const functionType = t.resolveReference(functionSymbol.valueDeclarationType);
expect(functionType.text).to.eql('(a: number, b: number) => number');
const [callSig1] = functionType.callSignatures!;
expect(callSig1.parameters!.length).to.eql(2);
const [sig1Param1, sig1Param2] = callSig1.parameters!.map(p => t.resolveReference(p));
expect(sig1Param1.jsDocTags![0].name).to.eq('param');
expect(sig1Param2.jsDocTags![0].name).to.eq('param');
expect(sig1Param1.jsDocTags![0].text).contains('first number');
expect(sig1Param2.jsDocTags![0].text).contains('second number');
t.cleanup();
});
it('with an @example tag and fenced code example', async () => {
const code = `interface Foo { num: number; }
/**
* Add two numbers
*
* @example
* \`\`\`ts
* const x = add(4, 6); // 10
* \`\`\`
*/
export function add(a: number, b: number) { return a + b; }`;
const t = new SingleFileAcceptanceTestCase(code);
await t.run();
const file = t.sourceFile();
const fileSymbol = t.resolveReference(file.symbol);
const functionSymbol = t.resolveReference(fileSymbol.exports!.add);
expect(functionSymbol.documentation).to.deep.eq({
summary: ['Add two numbers'],
customTags: [
{
content: [
{
code: 'const x = add(4, 6); // 10\n',
kind: 'fencedCode',
language: 'ts',
},
],
kind: 'blockTag',
tagName: 'example',
},
],
});
t.cleanup();
});
it('with inline code', async () => {
const code = `interface Foo { num: number; }
/**
* Add two numbers
*
* \`const x = add(4, 6); // 10\`
*/
export function add(a: number, b: number) { return a + b; }`;
const t = new SingleFileAcceptanceTestCase(code);
await t.run();
const file = t.sourceFile();
const fileSymbol = t.resolveReference(file.symbol);
const functionSymbol = t.resolveReference(fileSymbol.exports!.add);
expect(functionSymbol.documentation).to.deep.eq({
summary: [
'Add two numbers',
'\n',
'\n',
{
code: 'const x = add(4, 6); // 10',
kind: 'inlineCode',
},
],
});
t.cleanup();
});
it('with HTML tags', async () => {
const code = `interface Foo { num: number; }
/**
* Add two numbers
*
* <a data-name="foo" href="https://example.com">Example.com</a>
*
* And a picture
*
* <img src="https://example.com/foo.gif" />
*/
export function add(a: number, b: number) { return a + b; }`;
const t = new SingleFileAcceptanceTestCase(code);
await t.run();
const file = t.sourceFile();
const fileSymbol = t.resolveReference(file.symbol);
const functionSymbol = t.resolveReference(fileSymbol.exports!.add);
expect(functionSymbol.documentation).to.deep.eq({
summary: [
'Add two numbers',
'\n',
'\n',
{
attributes: [
{
name: 'data-name',
value: '"foo"',
},
{
name: 'href',
value: '"https://example.com"',
},
],
isSelfClosingTag: false,
kind: 'htmlStartTag',
name: 'a',
},
'Example.com',
{
kind: 'htmlEndTag',
name: 'a',
},
'\n',
'\n',
'And a picture',
'\n',
'\n',
{
attributes: [
{
name: 'src',
value: '"https://example.com/foo.gif"',
},
],
isSelfClosingTag: true,
kind: 'htmlStartTag',
name: 'img',
},
],
});
t.cleanup();
});
});