* `@0x/sol-doc`: New doc generator. * `@0x/sol-compiler`: Be more tolerant of AST-only compilation targets. * `@0x/contracts-exchange`: Add more devdoc comments. `@0x/contracts-exchange-libs`: Add more devdoc comments. * `@0x/sol-doc`: Update package script. * `@0x/sol-doc`: Remove unused files and update package scripts to be easier to configure. * Add more devdocs to contracts. * `@0x/sol-doc`: Remove doc artifacts. * `@0x/sol-doc`: Add `.gitignore` and `.npmignore`. * `@0x/contracts-exchange`: Fix compilation errors. * Fix more broken contracts. * `@0x/contracts-erc20-bridge-sampler`: Fix failing tests. * `@0x/contracts-asset-proxy`: Remove accidentally introduced hackathion file (lol). * `@0x/sol-doc`: Prevent some inherited contracts from being included in docs unintentionally. * `@0x/sol-doc`: Rename test file. * `@0x/contracts-exchange`: Update `orderEpoch` devdoc. * `@0x/sol-doc`: Tweak event and function docs. * Update CODEOWNERS. * `@0x/sol-doc` Tweak function md generation. * `@0x/sol-doc`: add `transformDocs()` tests. * `@0x/sol-doc`: add `extract_docs` tests. * `@0x/sol-doc` Fix linter errors. * `@0x/contracts-erc20-bridge-sampler`: Fix broken `ERC20BridgeSampler.sol` compile. * `@0x/sol-doc` Fix mismatched `dev-utils` dep version. * `@0x/sol-doc`: Add `gen_md` tests. * `@0x/sol-doc`: Remove `fs.promises` calls. * `@0x/sol-doc`: Fix linter errors. * `@0x/sol-doc`: Export all relevant types and functions. Co-authored-by: Lawrence Forman <me@merklejerk.com>
		
			
				
	
	
		
			115 lines
		
	
	
		
			3.8 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
			
		
		
	
	
			115 lines
		
	
	
		
			3.8 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
import { chaiSetup } from '@0x/dev-utils';
 | 
						|
import { expect } from 'chai';
 | 
						|
import * as _ from 'lodash';
 | 
						|
 | 
						|
import { FunctionKind, SolidityDocs } from '../src/extract_docs';
 | 
						|
import { generateMarkdownFromDocs } from '../src/gen_md';
 | 
						|
 | 
						|
import { randomContract, randomWord } from './utils/random_docs';
 | 
						|
 | 
						|
chaiSetup.configure();
 | 
						|
 | 
						|
// tslint:disable: custom-no-magic-numbers
 | 
						|
describe('generateMarkdownFromDocs()', () => {
 | 
						|
    const URL_PREFIX = randomWord();
 | 
						|
    const DOCS: SolidityDocs = {
 | 
						|
        contracts: {
 | 
						|
            ..._.mapValues(
 | 
						|
                _.groupBy(
 | 
						|
                    _.times(_.random(2, 8), () =>
 | 
						|
                        ((name: string) => ({ name, ...randomContract(name) }))(`${randomWord()}Contract`),
 | 
						|
                    ),
 | 
						|
                    'name',
 | 
						|
                ),
 | 
						|
                g => g[0],
 | 
						|
            ),
 | 
						|
        },
 | 
						|
    };
 | 
						|
 | 
						|
    let md: string;
 | 
						|
    let mdLines: string[];
 | 
						|
 | 
						|
    function getMarkdownHeaders(level: number): string[] {
 | 
						|
        const lines = mdLines.filter(line => new RegExp(`^\\s*#{${level}}[^#]`).test(line));
 | 
						|
        // tslint:disable-next-line: no-non-null-assertion
 | 
						|
        return lines.map(line => /^\s*#+\s*(.+?)\s*$/.exec(line)![1]);
 | 
						|
    }
 | 
						|
 | 
						|
    function getMarkdownLinks(): string[] {
 | 
						|
        const links: string[] = [];
 | 
						|
        for (const line of mdLines) {
 | 
						|
            const re = /\[[^\]]+\]\(([^)]+)\)/g;
 | 
						|
            let m: string[] | undefined | null;
 | 
						|
            do {
 | 
						|
                m = re.exec(line);
 | 
						|
                if (m) {
 | 
						|
                    links.push(m[1]);
 | 
						|
                }
 | 
						|
            } while (m);
 | 
						|
        }
 | 
						|
        return links;
 | 
						|
    }
 | 
						|
 | 
						|
    before(() => {
 | 
						|
        md = generateMarkdownFromDocs(DOCS, { urlPrefix: URL_PREFIX });
 | 
						|
        mdLines = md.split('\n');
 | 
						|
    });
 | 
						|
 | 
						|
    it('generates entries for all contracts', () => {
 | 
						|
        const headers = getMarkdownHeaders(1);
 | 
						|
        for (const [contractName, contract] of Object.entries(DOCS.contracts)) {
 | 
						|
            expect(headers).to.include(`${contract.kind} \`${contractName}\``);
 | 
						|
        }
 | 
						|
    });
 | 
						|
 | 
						|
    it('generates entries for all enums', () => {
 | 
						|
        const headers = getMarkdownHeaders(3);
 | 
						|
        for (const contract of Object.values(DOCS.contracts)) {
 | 
						|
            for (const enumName of Object.keys(contract.enums)) {
 | 
						|
                expect(headers).to.include(`\`${enumName}\``);
 | 
						|
            }
 | 
						|
        }
 | 
						|
    });
 | 
						|
 | 
						|
    it('generates entries for all structs', () => {
 | 
						|
        const headers = getMarkdownHeaders(3);
 | 
						|
        for (const contract of Object.values(DOCS.contracts)) {
 | 
						|
            for (const structName of Object.keys(contract.structs)) {
 | 
						|
                expect(headers).to.include(`\`${structName}\``);
 | 
						|
            }
 | 
						|
        }
 | 
						|
    });
 | 
						|
 | 
						|
    it('generates entries for all events', () => {
 | 
						|
        const headers = getMarkdownHeaders(3);
 | 
						|
        for (const contract of Object.values(DOCS.contracts)) {
 | 
						|
            for (const event of contract.events) {
 | 
						|
                expect(headers).to.include(`\`${event.name}\``);
 | 
						|
            }
 | 
						|
        }
 | 
						|
    });
 | 
						|
 | 
						|
    it('generates entries for all methods', () => {
 | 
						|
        const headers = getMarkdownHeaders(3);
 | 
						|
        for (const contract of Object.values(DOCS.contracts)) {
 | 
						|
            for (const method of contract.methods) {
 | 
						|
                if (method.kind === FunctionKind.Fallback) {
 | 
						|
                    expect(headers).to.include(`\`<fallback>\``);
 | 
						|
                } else if (method.kind === FunctionKind.Constructor) {
 | 
						|
                    expect(headers).to.include(`\`constructor\``);
 | 
						|
                } else {
 | 
						|
                    expect(headers).to.include(`\`${method.name}\``);
 | 
						|
                }
 | 
						|
            }
 | 
						|
        }
 | 
						|
    });
 | 
						|
 | 
						|
    it('prefixes all URLs with the prefix', () => {
 | 
						|
        const urls = getMarkdownLinks();
 | 
						|
        for (const url of urls) {
 | 
						|
            expect(url.startsWith(URL_PREFIX)).to.be.true();
 | 
						|
        }
 | 
						|
    });
 | 
						|
});
 | 
						|
// tslint:disable: max-file-line-count
 |