Anton Shchekota e3c59d77e4 fix: external was removed as prefer of input usages
BREAKING CHANGE:
external parameter was removed
Migration plan propose to move all external resources to input usages
Motivation: packages has many inputs which describe in package.json
so that mean need each time to parse all package.json of exsternal resources to understand which etry point need to pick.
But it is base on guesses because entry point may could not contains a documentation and the best way to handle it manualy.
2021-11-11 11:52:31 +03:00

405 lines
10 KiB
JavaScript

/* global jasmine */
import path from 'path';
import os from 'os';
import { exec } from 'child_process';
import tmp from 'tmp';
import fs from 'fs-extra';
import { fileURLToPath } from 'url';
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
function documentation(args, options, parseJSON) {
if (!options) {
options = {};
}
if (!options.cwd) {
options.cwd = __dirname;
}
options.maxBuffer = 1024 * 1024;
args.unshift('node ' + path.join(__dirname, '..', 'bin', 'documentation.js'));
return new Promise((resolve, reject) => {
exec(args.join(' '), options, function (err, stdout, stderr) {
if (err) {
err.stderr = stderr;
return reject(err);
}
if (parseJSON === false) {
resolve(stdout);
} else {
try {
resolve(JSON.parse(stdout));
} catch (e) {
reject(e);
}
}
});
});
}
function normalize(result) {
result.forEach(function (item) {
item.context.file = '[path]';
});
return result;
}
test('documentation binary', async function () {
const data = await documentation(['build fixture/simple.input.js'], {});
expect(data.length).toBe(1);
});
test.skip('defaults to parsing package.json main', async function () {
const data = await documentation(['build'], {
cwd: path.join(__dirname, '..')
});
expect(data.length).toBeTruthy();
});
test('accepts config file', async function () {
const data = await documentation([
'build fixture/sorting/input.js -c fixture/config.json'
]);
expect(normalize(data)).toMatchSnapshot();
});
test('accepts config file - reports failures', async function () {
try {
await documentation(
['build fixture/sorting/input.js -c fixture/config-bad.yml'],
{},
false
);
} catch (stderr) {
expect(stderr).toMatchSnapshot();
}
});
test('accepts config file - reports parse failures', async function () {
try {
await documentation(
['build fixture/sorting/input.js -c fixture/config-malformed.json'],
{},
false
);
} catch (stderr) {
expect(stderr.stderr.match(/SyntaxError/g)).toBeTruthy();
}
});
test('--shallow option', async function () {
const data = await documentation([
'build --shallow fixture/internal.input.js'
]);
expect(data.length).toBe(0);
});
test('when a file is specified both in a glob and explicitly, it is only documented once', async function () {
const data = await documentation([
'build fixture/simple.input.js fixture/simple.input.*'
]);
expect(data.length).toBe(1);
});
test('extension option', async function () {
const data = await documentation([
'build fixture/extension/index.otherextension ' +
'--requireExtension=otherextension --parseExtension=otherextension'
]);
expect(data.length).toBe(1);
});
test('extension option', function () {
return documentation(['build fixture/extension.jsx']);
});
describe('invalid arguments', function () {
test('bad -f option', async function () {
try {
await documentation(
['build -f DOES-NOT-EXIST fixture/internal.input.js'],
{},
false
);
} catch (err) {
expect(err).toBeTruthy();
}
});
test('html with no destination', async function () {
try {
await documentation(['build -f html fixture/internal.input.js']);
} catch (err) {
expect(
err
.toString()
.match(
/The HTML output mode requires a destination directory set with -o/
)
).toBeTruthy();
}
});
test('bad command', async function () {
try {
await documentation(['-f html fixture/internal.input.js'], {}, false);
} catch (err) {
expect(err.code).toBeTruthy();
}
});
});
const semver =
/\bv?(?:0|[1-9]\d*)\.(?:0|[1-9]\d*)\.(?:0|[1-9]\d*)(?:-[\da-z-]+(?:\.[\da-z-]+)*)?(?:\+[\da-z-]+(?:\.[\da-z-]+)*)?\b/gi;
test('--config', async function () {
const dst = path.join(os.tmpdir(), (Date.now() + Math.random()).toString());
fs.mkdirSync(dst);
const outputIndex = path.join(dst, 'index.html');
const data = await documentation(
[
'build -c fixture/html/documentation.yml -f html fixture/html/nested.input.js -o ' +
dst
],
{},
false
);
let output = fs.readFileSync(outputIndex, 'utf8');
const version = (await import('../package.json')).default.version;
output = output.replace(new RegExp(version.replace(/\./g, '\\.'), 'g'), '');
expect(output).toMatchSnapshot();
});
test('--version', async function () {
const output = await documentation(['--version'], {}, false);
expect(output).toBeTruthy();
});
describe('lint command', function () {
test('generates lint output', async function () {
try {
await documentation(['lint fixture/lint/lint.input.js'], {}, false);
} catch (err) {
const data = err.stderr.toString().split('\n').slice(2).join('\n');
expect(data).toMatchSnapshot();
}
});
test('generates no output on a good file', async function () {
const data = await documentation(
['lint fixture/simple.input.js'],
{},
false
);
expect(data).toBe('');
});
test('exposes syntax error on a bad file', async function () {
try {
await documentation(
['lint fixture/bad/syntax.input', '--parseExtension input'],
{},
false
);
} catch (err) {
expect(err.code > 0).toBeTruthy();
}
});
test('lint with no inputs', async function () {
try {
await documentation(
['lint'],
{
cwd: path.join(__dirname, 'fixture/bad')
},
false
);
} catch (err) {
expect(err.code > 0).toBeTruthy();
}
});
test('generates lint output with shallow', async function () {
const data = await documentation(
['lint fixture/lint/lint.input.shallow.js --shallow'],
{},
false
);
expect(data).toBe('');
});
});
test('given no files', async function () {
try {
await documentation(['build']);
} catch (err) {
expect(
err
.toString()
.match(
/documentation was given no files and was not run in a module directory/
)
).toBeTruthy();
}
});
test('with an invalid command', async function () {
try {
await documentation(['invalid'], {}, false);
} catch (err) {
expect(err).toBeTruthy();
}
});
test.skip('--access flag', async function () {
const data = await documentation(
['build --shallow fixture/internal.input.js -a public'],
{},
false
);
expect(data).toBe('[]');
});
test.skip('--infer-private flag', async function () {
const data = await documentation(
['build fixture/infer-private.input.js --infer-private ^_'],
{},
false
);
// This uses JSON.parse with a reviver used as a visitor.
JSON.parse(data, function (n, v) {
// Make sure we do not see any names that match `^_`.
if (n === 'name') {
expect(typeof v).toBe('string');
expect(!/_$/.test.skip(v)).toBeTruthy();
}
return v;
});
});
test.skip('write to file', async function () {
const dst = path.join(os.tmpdir(), (Date.now() + Math.random()).toString());
const data = await documentation(
['build --shallow fixture/internal.input.js -o ' + dst],
{},
false
);
expect(data).toBe('');
expect(fs.existsSync(dst)).toBeTruthy();
});
test.skip('write to html', async function () {
const dstDir = path.join(
os.tmpdir(),
(Date.now() + Math.random()).toString()
);
fs.mkdirSync(dstDir);
const data = await documentation(
['build --shallow fixture/internal.input.js -f html -o ' + dstDir],
{},
false
);
expect(data).toBe('');
expect(fs.existsSync(path.join(dstDir, 'index.html'))).toBeTruthy();
});
test.skip('write to html with custom theme', async function () {
const dstDir = path.join(
os.tmpdir(),
(Date.now() + Math.random()).toString()
);
fs.mkdirSync(dstDir);
const data = await documentation(
[
'build -t fixture/custom_theme --shallow fixture/internal.input.js -f html -o ' +
dstDir
],
{},
false
);
expect(data).toBe('');
expect(fs.readFileSync(path.join(dstDir, 'index.html'), 'utf8')).toBeTruthy();
});
test.skip('write to html, highlightAuto', function () {
const fixture = 'fixture/auto_lang_hljs/multilanguage.input.js';
const config = 'fixture/auto_lang_hljs/config.yml';
const dstDir = path.join(
os.tmpdir(),
(Date.now() + Math.random()).toString()
);
fs.mkdirSync(dstDir);
return documentation(
['build --shallow ' + fixture + ' -c ' + config + ' -f html -o ' + dstDir],
{},
false
).then(() => {
const result = fs.readFileSync(path.join(dstDir, 'index.html'), 'utf8');
expect(
result.indexOf('<span class="hljs-number">42</span>') > 0
).toBeTruthy();
expect(
result.indexOf('<span class="hljs-selector-attr">[data-foo]</span>') > 0
).toBeTruthy();
expect(
result.indexOf('<span class="hljs-attr">data-foo</span>') > 0
).toBeTruthy();
});
});
test.skip('fatal error', async function () {
try {
await documentation(
['build --shallow fixture/bad/syntax.input --parseExtension input'],
{},
false
);
} catch (err) {
expect(err.toString().match(/Unexpected token/)).toBeTruthy();
}
});
test.skip('build --document-exported', async function () {
const data = await documentation(
['build fixture/document-exported.input.js --document-exported -f md'],
{},
false
);
expect(data).toMatchSnapshot();
});
test.skip('build large file without error (no deoptimized styling error)', function () {
const dstFile =
path.join(os.tmpdir(), (Date.now() + Math.random()).toString()) + '.js';
let contents = '';
for (let i = 0; i < 4e4; i++) {
contents += '/* - */\n';
}
fs.writeFileSync(dstFile, contents, 'utf8');
return documentation(['build ' + dstFile], {}, false).then(() => {
fs.unlinkSync(dstFile);
});
});
test.skip('should use browser resolve', async function () {
const data = await documentation(['build fixture/resolve/index.js']);
expect(normalize(data)).toMatchSnapshot();
});
test.skip('should use node resolve', async function () {
const data = await documentation([
'build fixture/resolve/index.js --resolve node'
]);
expect(normalize(data)).toMatchSnapshot();
});