216 lines
9.6 KiB
TypeScript
216 lines
9.6 KiB
TypeScript
import * as _ from 'lodash';
|
|
|
|
import * as chai from 'chai';
|
|
import 'mocha';
|
|
|
|
import { DocAgnosticFormat, Event, SolidityMethod } from '@0xproject/types';
|
|
|
|
import { generateSolDocAsync } from '../src/solidity_doc_generator';
|
|
|
|
import { chaiSetup } from './util/chai_setup';
|
|
|
|
chaiSetup.configure();
|
|
const expect = chai.expect;
|
|
|
|
describe('#SolidityDocGenerator', () => {
|
|
it('should generate a doc object that matches the devdoc-free fixture', async () => {
|
|
const doc = await generateSolDocAsync(`${__dirname}/../../test/fixtures/contracts`, [
|
|
'TokenTransferProxyNoDevdoc',
|
|
]);
|
|
expect(doc).to.not.be.undefined();
|
|
|
|
verifyTokenTransferProxyABIIsDocumented(doc, 'TokenTransferProxyNoDevdoc');
|
|
});
|
|
const docPromises: Array<Promise<DocAgnosticFormat>> = [
|
|
generateSolDocAsync(`${__dirname}/../../test/fixtures/contracts`),
|
|
generateSolDocAsync(`${__dirname}/../../test/fixtures/contracts`, []),
|
|
generateSolDocAsync(`${__dirname}/../../test/fixtures/contracts`, ['TokenTransferProxy']),
|
|
];
|
|
docPromises.forEach(docPromise => {
|
|
it('should generate a doc object that matches the fixture', async () => {
|
|
const doc = await docPromise;
|
|
expect(doc).to.not.be.undefined();
|
|
|
|
verifyTokenTransferProxyABIIsDocumented(doc, 'TokenTransferProxy');
|
|
|
|
let addAuthorizedAddressMethod: SolidityMethod | undefined;
|
|
for (const method of doc.TokenTransferProxy.methods) {
|
|
if (method.name === 'addAuthorizedAddress') {
|
|
addAuthorizedAddressMethod = method;
|
|
}
|
|
}
|
|
const tokenTransferProxyAddAuthorizedAddressComment = 'Authorizes an address.';
|
|
expect((addAuthorizedAddressMethod as SolidityMethod).comment).to.equal(
|
|
tokenTransferProxyAddAuthorizedAddressComment,
|
|
);
|
|
|
|
const expectedParamComment = 'Address to authorize.';
|
|
expect((addAuthorizedAddressMethod as SolidityMethod).parameters[0].comment).to.equal(expectedParamComment);
|
|
});
|
|
});
|
|
describe('when processing all the permutations of devdoc stuff that we use in our contracts', () => {
|
|
let doc: DocAgnosticFormat;
|
|
before(async () => {
|
|
doc = await generateSolDocAsync(`${__dirname}/../../test/fixtures/contracts`, ['NatspecEverything']);
|
|
expect(doc).to.not.be.undefined();
|
|
expect(doc.NatspecEverything).to.not.be.undefined();
|
|
});
|
|
it('should emit the contract @title as its comment', () => {
|
|
expect(doc.NatspecEverything.comment).to.equal('Contract Title');
|
|
});
|
|
describe('should emit public method documentation for', () => {
|
|
let methodDoc: SolidityMethod;
|
|
before(() => {
|
|
// tslint:disable-next-line:no-unnecessary-type-assertion
|
|
methodDoc = doc.NatspecEverything.methods.find(method => {
|
|
return method.name === 'publicMethod';
|
|
}) as SolidityMethod;
|
|
if (_.isUndefined(methodDoc)) {
|
|
throw new Error('publicMethod not found');
|
|
}
|
|
});
|
|
it('method name', () => {
|
|
expect(methodDoc.name).to.equal('publicMethod');
|
|
});
|
|
it('method comment', () => {
|
|
expect(methodDoc.comment).to.equal('publicMethod @dev');
|
|
});
|
|
it('parameter name', () => {
|
|
expect(methodDoc.parameters[0].name).to.equal('p');
|
|
});
|
|
it('parameter comment', () => {
|
|
expect(methodDoc.parameters[0].comment).to.equal('publicMethod @param');
|
|
});
|
|
it('return type name', () => {
|
|
expect(methodDoc.returnType.name).to.equal('r');
|
|
});
|
|
});
|
|
describe('should emit external method documentation for', () => {
|
|
let methodDoc: SolidityMethod;
|
|
before(() => {
|
|
// tslint:disable-next-line:no-unnecessary-type-assertion
|
|
methodDoc = doc.NatspecEverything.methods.find(method => {
|
|
return method.name === 'externalMethod';
|
|
}) as SolidityMethod;
|
|
if (_.isUndefined(methodDoc)) {
|
|
throw new Error('externalMethod not found');
|
|
}
|
|
});
|
|
it('method name', () => {
|
|
expect(methodDoc.name).to.equal('externalMethod');
|
|
});
|
|
it('method comment', () => {
|
|
expect(methodDoc.comment).to.equal('externalMethod @dev');
|
|
});
|
|
it('parameter name', () => {
|
|
expect(methodDoc.parameters[0].name).to.equal('p');
|
|
});
|
|
it('parameter comment', () => {
|
|
expect(methodDoc.parameters[0].comment).to.equal('externalMethod @param');
|
|
});
|
|
it('return type name', () => {
|
|
expect(methodDoc.returnType.name).to.equal('r');
|
|
});
|
|
});
|
|
it('should not truncate a multi-line devdoc comment', () => {
|
|
// tslint:disable-next-line:no-unnecessary-type-assertion
|
|
const methodDoc: SolidityMethod = doc.NatspecEverything.methods.find(method => {
|
|
return method.name === 'methodWithLongDevdoc';
|
|
}) as SolidityMethod;
|
|
if (_.isUndefined(methodDoc)) {
|
|
throw new Error('methodWithLongDevdoc not found');
|
|
}
|
|
expect(methodDoc.comment).to.equal(
|
|
'Here is a really long developer documentation comment, which spans multiple lines, for the purposes of making sure that broken lines are consolidated into one devdoc comment.',
|
|
);
|
|
});
|
|
describe('should emit event documentation for', () => {
|
|
let eventDoc: Event;
|
|
before(() => {
|
|
eventDoc = (doc.NatspecEverything.events as Event[])[0];
|
|
});
|
|
it('event name', () => {
|
|
expect(eventDoc.name).to.equal('AnEvent');
|
|
});
|
|
it('parameter name', () => {
|
|
expect(eventDoc.eventArgs[0].name).to.equal('p');
|
|
});
|
|
});
|
|
it('should not let solhint directives obscure natspec content', () => {
|
|
// tslint:disable-next-line:no-unnecessary-type-assertion
|
|
const methodDoc: SolidityMethod = doc.NatspecEverything.methods.find(method => {
|
|
return method.name === 'methodWithSolhintDirective';
|
|
}) as SolidityMethod;
|
|
if (_.isUndefined(methodDoc)) {
|
|
throw new Error('methodWithSolhintDirective not found');
|
|
}
|
|
expect(methodDoc.comment).to.equal('methodWithSolhintDirective @dev');
|
|
});
|
|
});
|
|
});
|
|
|
|
function verifyTokenTransferProxyABIIsDocumented(doc: DocAgnosticFormat, contractName: string): void {
|
|
expect(doc[contractName]).to.not.be.undefined();
|
|
expect(doc[contractName].constructors).to.not.be.undefined();
|
|
const tokenTransferProxyConstructorCount = 0;
|
|
const tokenTransferProxyMethodCount = 8;
|
|
const tokenTransferProxyEventCount = 3;
|
|
expect(doc[contractName].constructors.length).to.equal(tokenTransferProxyConstructorCount);
|
|
expect(doc[contractName].methods.length).to.equal(tokenTransferProxyMethodCount);
|
|
const events = doc[contractName].events;
|
|
if (_.isUndefined(events)) {
|
|
throw new Error('events should never be undefined');
|
|
}
|
|
expect(events.length).to.equal(tokenTransferProxyEventCount);
|
|
|
|
expect(doc.Ownable).to.not.be.undefined();
|
|
expect(doc.Ownable.constructors).to.not.be.undefined();
|
|
expect(doc.Ownable.methods).to.not.be.undefined();
|
|
const ownableConstructorCount = 1;
|
|
const ownableMethodCount = 2;
|
|
const ownableEventCount = 1;
|
|
expect(doc.Ownable.constructors.length).to.equal(ownableConstructorCount);
|
|
expect(doc.Ownable.methods.length).to.equal(ownableMethodCount);
|
|
if (_.isUndefined(doc.Ownable.events)) {
|
|
throw new Error('events should never be undefined');
|
|
}
|
|
expect(doc.Ownable.events.length).to.equal(ownableEventCount);
|
|
|
|
expect(doc.ERC20).to.not.be.undefined();
|
|
expect(doc.ERC20.constructors).to.not.be.undefined();
|
|
expect(doc.ERC20.methods).to.not.be.undefined();
|
|
const erc20ConstructorCount = 0;
|
|
const erc20MethodCount = 6;
|
|
const erc20EventCount = 2;
|
|
expect(doc.ERC20.constructors.length).to.equal(erc20ConstructorCount);
|
|
expect(doc.ERC20.methods.length).to.equal(erc20MethodCount);
|
|
if (_.isUndefined(doc.ERC20.events)) {
|
|
throw new Error('events should never be undefined');
|
|
}
|
|
expect(doc.ERC20.events.length).to.equal(erc20EventCount);
|
|
|
|
expect(doc.ERC20Basic).to.not.be.undefined();
|
|
expect(doc.ERC20Basic.constructors).to.not.be.undefined();
|
|
expect(doc.ERC20Basic.methods).to.not.be.undefined();
|
|
const erc20BasicConstructorCount = 0;
|
|
const erc20BasicMethodCount = 3;
|
|
const erc20BasicEventCount = 1;
|
|
expect(doc.ERC20Basic.constructors.length).to.equal(erc20BasicConstructorCount);
|
|
expect(doc.ERC20Basic.methods.length).to.equal(erc20BasicMethodCount);
|
|
if (_.isUndefined(doc.ERC20Basic.events)) {
|
|
throw new Error('events should never be undefined');
|
|
}
|
|
expect(doc.ERC20Basic.events.length).to.equal(erc20BasicEventCount);
|
|
|
|
let addAuthorizedAddressMethod: SolidityMethod | undefined;
|
|
for (const method of doc[contractName].methods) {
|
|
if (method.name === 'addAuthorizedAddress') {
|
|
addAuthorizedAddressMethod = method;
|
|
}
|
|
}
|
|
expect(
|
|
addAuthorizedAddressMethod,
|
|
`method addAuthorizedAddress not found in ${JSON.stringify(doc[contractName].methods)}`,
|
|
).to.not.be.undefined();
|
|
}
|