Merge pull request #845 from ing-bank/chore/providenceCliTests
feat(providence-analytics): allow target dependencies via cli
This commit is contained in:
commit
8a7b550f68
11 changed files with 582 additions and 191 deletions
5
.changeset/sharp-rules-tell.md
Normal file
5
.changeset/sharp-rules-tell.md
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
---
|
||||||
|
'providence-analytics': patch
|
||||||
|
---
|
||||||
|
|
||||||
|
feat: allow target dependencies via cli
|
||||||
|
|
@ -60,7 +60,7 @@ function pathsArrayFromCs(t, cwd = process.cwd()) {
|
||||||
* @param {object} eCfg external configuration. Usually providence.conf.js
|
* @param {object} eCfg external configuration. Usually providence.conf.js
|
||||||
* @returns {string[]}
|
* @returns {string[]}
|
||||||
*/
|
*/
|
||||||
function pathsArrayFromCollectionName(name, colType = 'search-target', eCfg) {
|
function pathsArrayFromCollectionName(name, colType = 'search-target', eCfg, cwd) {
|
||||||
let collection;
|
let collection;
|
||||||
if (colType === 'search-target') {
|
if (colType === 'search-target') {
|
||||||
collection = eCfg.searchTargetCollections;
|
collection = eCfg.searchTargetCollections;
|
||||||
|
|
@ -68,7 +68,7 @@ function pathsArrayFromCollectionName(name, colType = 'search-target', eCfg) {
|
||||||
collection = eCfg.referenceCollections;
|
collection = eCfg.referenceCollections;
|
||||||
}
|
}
|
||||||
if (collection && collection[name]) {
|
if (collection && collection[name]) {
|
||||||
return pathsArrayFromCs(collection[name].join(','));
|
return pathsArrayFromCs(collection[name].join(','), cwd);
|
||||||
}
|
}
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
@ -107,10 +107,20 @@ function targetDefault() {
|
||||||
/**
|
/**
|
||||||
* @desc Returns all sub projects matching condition supplied in matchFn
|
* @desc Returns all sub projects matching condition supplied in matchFn
|
||||||
* @param {string[]} searchTargetPaths all search-target project paths
|
* @param {string[]} searchTargetPaths all search-target project paths
|
||||||
* @param {function} matchFn filters out packages we're interested in
|
* @param {string} matchPattern base for RegExp
|
||||||
* @param {string[]} modes
|
* @param {string[]} modes
|
||||||
*/
|
*/
|
||||||
async function appendProjectDependencyPaths(rootPaths, matchFn, modes = ['npm', 'bower']) {
|
async function appendProjectDependencyPaths(rootPaths, matchPattern, modes = ['npm', 'bower']) {
|
||||||
|
let matchFn;
|
||||||
|
if (matchPattern) {
|
||||||
|
if (matchPattern.startsWith('/') && matchPattern.endsWith('/')) {
|
||||||
|
matchFn = (_, d) => new RegExp(matchPattern.slice(1, -1)).test(d);
|
||||||
|
} else {
|
||||||
|
LogService.error(
|
||||||
|
`[appendProjectDependencyPaths] Please provide a matchPattern enclosed by '/'. Found: ${matchPattern}`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
const depProjectPaths = [];
|
const depProjectPaths = [];
|
||||||
await aForEach(rootPaths, async targetPath => {
|
await aForEach(rootPaths, async targetPath => {
|
||||||
await aForEach(modes, async mode => {
|
await aForEach(modes, async mode => {
|
||||||
|
|
|
||||||
|
|
@ -8,22 +8,18 @@ const providenceModule = require('../program/providence.js');
|
||||||
const { LogService } = require('../program/services/LogService.js');
|
const { LogService } = require('../program/services/LogService.js');
|
||||||
const { QueryService } = require('../program/services/QueryService.js');
|
const { QueryService } = require('../program/services/QueryService.js');
|
||||||
const { InputDataService } = require('../program/services/InputDataService.js');
|
const { InputDataService } = require('../program/services/InputDataService.js');
|
||||||
const { promptAnalyzerMenu, promptAnalyzerConfigMenu } = require('./prompt-analyzer-menu.js');
|
const promptModule = require('./prompt-analyzer-menu.js');
|
||||||
const {
|
const cliHelpers = require('./cli-helpers.js');
|
||||||
extensionsFromCs,
|
|
||||||
setQueryMethod,
|
|
||||||
targetDefault,
|
|
||||||
appendProjectDependencyPaths,
|
|
||||||
installDeps,
|
|
||||||
pathsArrayFromCollectionName,
|
|
||||||
pathsArrayFromCs,
|
|
||||||
} = require('./cli-helpers.js');
|
|
||||||
const extendDocsModule = require('./generate-extend-docs-data.js');
|
const extendDocsModule = require('./generate-extend-docs-data.js');
|
||||||
|
|
||||||
|
const { extensionsFromCs, setQueryMethod, targetDefault, installDeps } = cliHelpers;
|
||||||
|
|
||||||
const { version } = require('../../package.json');
|
const { version } = require('../../package.json');
|
||||||
|
|
||||||
async function cli({ cwd, addProjectDependencyPaths } = {}) {
|
async function cli({ cwd } = {}) {
|
||||||
let resolveCli;
|
let resolveCli;
|
||||||
let rejectCli;
|
let rejectCli;
|
||||||
|
|
||||||
const cliPromise = new Promise((resolve, reject) => {
|
const cliPromise = new Promise((resolve, reject) => {
|
||||||
resolveCli = resolve;
|
resolveCli = resolve;
|
||||||
rejectCli = reject;
|
rejectCli = reject;
|
||||||
|
|
@ -39,7 +35,6 @@ async function cli({ cwd, addProjectDependencyPaths } = {}) {
|
||||||
let regexSearchOptions;
|
let regexSearchOptions;
|
||||||
|
|
||||||
const externalConfig = InputDataService.getExternalConfig();
|
const externalConfig = InputDataService.getExternalConfig();
|
||||||
console.log('externalConfig', externalConfig);
|
|
||||||
|
|
||||||
async function getQueryInputData(
|
async function getQueryInputData(
|
||||||
/* eslint-disable no-shadow */
|
/* eslint-disable no-shadow */
|
||||||
|
|
@ -48,7 +43,6 @@ async function cli({ cwd, addProjectDependencyPaths } = {}) {
|
||||||
featureOptions,
|
featureOptions,
|
||||||
analyzerOptions,
|
analyzerOptions,
|
||||||
/* eslint-enable no-shadow */
|
/* eslint-enable no-shadow */
|
||||||
showAnalyzerConfigMenu,
|
|
||||||
) {
|
) {
|
||||||
let queryConfig = null;
|
let queryConfig = null;
|
||||||
let queryMethod = null;
|
let queryMethod = null;
|
||||||
|
|
@ -64,11 +58,14 @@ async function cli({ cwd, addProjectDependencyPaths } = {}) {
|
||||||
} else if (searchMode === 'analyzer-query') {
|
} else if (searchMode === 'analyzer-query') {
|
||||||
let { name, config } = analyzerOptions;
|
let { name, config } = analyzerOptions;
|
||||||
if (!name) {
|
if (!name) {
|
||||||
const answers = await promptAnalyzerMenu();
|
const answers = await promptModule.promptAnalyzerMenu();
|
||||||
name = answers.analyzerName;
|
name = answers.analyzerName;
|
||||||
}
|
}
|
||||||
if (showAnalyzerConfigMenu && !config) {
|
if (!config) {
|
||||||
const answers = await promptAnalyzerConfigMenu(name, analyzerOptions.promptOptionalConfig);
|
const answers = await promptModule.promptAnalyzerConfigMenu(
|
||||||
|
name,
|
||||||
|
analyzerOptions.promptOptionalConfig,
|
||||||
|
);
|
||||||
config = answers.analyzerConfig;
|
config = answers.analyzerConfig;
|
||||||
}
|
}
|
||||||
// Will get metaConfig from ./providence.conf.js
|
// Will get metaConfig from ./providence.conf.js
|
||||||
|
|
@ -97,11 +94,18 @@ async function cli({ cwd, addProjectDependencyPaths } = {}) {
|
||||||
referencePaths = commander.referenceCollection || commander.referencePaths;
|
referencePaths = commander.referenceCollection || commander.referencePaths;
|
||||||
}
|
}
|
||||||
|
|
||||||
let extendedSearchTargets;
|
/**
|
||||||
if (addProjectDependencyPaths) {
|
* May or may not include dependencies of search target
|
||||||
extendedSearchTargets = await appendProjectDependencyPaths(searchTargetPaths);
|
* @type {string[]}
|
||||||
|
*/
|
||||||
|
let totalSearchTargets;
|
||||||
|
if (commander.targetDependencies !== undefined) {
|
||||||
|
totalSearchTargets = await cliHelpers.appendProjectDependencyPaths(
|
||||||
|
searchTargetPaths,
|
||||||
|
commander.targetDependencies,
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
extendedSearchTargets = searchTargetPaths;
|
totalSearchTargets = searchTargetPaths;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: filter out:
|
// TODO: filter out:
|
||||||
|
|
@ -120,7 +124,7 @@ async function cli({ cwd, addProjectDependencyPaths } = {}) {
|
||||||
},
|
},
|
||||||
debugEnabled: commander.debug,
|
debugEnabled: commander.debug,
|
||||||
queryMethod,
|
queryMethod,
|
||||||
targetProjectPaths: extendedSearchTargets,
|
targetProjectPaths: totalSearchTargets,
|
||||||
referenceProjectPaths: referencePaths,
|
referenceProjectPaths: referencePaths,
|
||||||
targetProjectRootPaths: searchTargetPaths,
|
targetProjectRootPaths: searchTargetPaths,
|
||||||
writeLogFile: commander.writeLogFile,
|
writeLogFile: commander.writeLogFile,
|
||||||
|
|
@ -157,7 +161,7 @@ async function cli({ cwd, addProjectDependencyPaths } = {}) {
|
||||||
'-t, --search-target-paths [targets]',
|
'-t, --search-target-paths [targets]',
|
||||||
`path(s) to project(s) on which analysis/querying should take place. Requires
|
`path(s) to project(s) on which analysis/querying should take place. Requires
|
||||||
a list of comma seperated values relative to project root`,
|
a list of comma seperated values relative to project root`,
|
||||||
v => pathsArrayFromCs(v, cwd),
|
v => cliHelpers.pathsArrayFromCs(v, cwd),
|
||||||
targetDefault(),
|
targetDefault(),
|
||||||
)
|
)
|
||||||
.option(
|
.option(
|
||||||
|
|
@ -165,31 +169,39 @@ async function cli({ cwd, addProjectDependencyPaths } = {}) {
|
||||||
`path(s) to project(s) which serve as a reference (applicable for certain analyzers like
|
`path(s) to project(s) which serve as a reference (applicable for certain analyzers like
|
||||||
'match-imports'). Requires a list of comma seperated values relative to
|
'match-imports'). Requires a list of comma seperated values relative to
|
||||||
project root (like 'node_modules/lion-based-ui, node_modules/lion-based-ui-labs').`,
|
project root (like 'node_modules/lion-based-ui, node_modules/lion-based-ui-labs').`,
|
||||||
v => pathsArrayFromCs(v, cwd),
|
v => cliHelpers.pathsArrayFromCs(v, cwd),
|
||||||
InputDataService.referenceProjectPaths,
|
InputDataService.referenceProjectPaths,
|
||||||
)
|
)
|
||||||
.option('-w, --whitelist [whitelist]', `whitelisted paths, like './src, ./packages/*'`, v =>
|
.option('-w, --whitelist [whitelist]', `whitelisted paths, like './src, ./packages/*'`, v =>
|
||||||
pathsArrayFromCs(v, cwd),
|
cliHelpers.pathsArrayFromCs(v, cwd),
|
||||||
)
|
)
|
||||||
.option(
|
.option(
|
||||||
'--whitelist-reference [whitelist-reference]',
|
'--whitelist-reference [whitelist-reference]',
|
||||||
`whitelisted paths for reference, like './src, ./packages/*'`,
|
`whitelisted paths for reference, like './src, ./packages/*'`,
|
||||||
v => pathsArrayFromCs(v, cwd),
|
v => cliHelpers.pathsArrayFromCs(v, cwd),
|
||||||
)
|
)
|
||||||
.option(
|
.option(
|
||||||
'--search-target-collection [collection-name]',
|
'--search-target-collection [collection-name]',
|
||||||
`path(s) to project(s) which serve as a reference (applicable for certain analyzers like
|
`path(s) to project(s) which serve as a reference (applicable for certain analyzers like
|
||||||
'match-imports'). Should be a collection defined in providence.conf.js as paths relative to
|
'match-imports'). Should be a collection defined in providence.conf.js as paths relative to
|
||||||
project root.`,
|
project root.`,
|
||||||
v => pathsArrayFromCollectionName(v, 'search-target', externalConfig),
|
v => cliHelpers.pathsArrayFromCollectionName(v, 'search-target', externalConfig),
|
||||||
)
|
)
|
||||||
.option(
|
.option(
|
||||||
'--reference-collection [collection-name]',
|
'--reference-collection [collection-name]',
|
||||||
`path(s) to project(s) on which analysis/querying should take place. Should be a collection
|
`path(s) to project(s) on which analysis/querying should take place. Should be a collection
|
||||||
defined in providence.conf.js as paths relative to project root.`,
|
defined in providence.conf.js as paths relative to project root.`,
|
||||||
v => pathsArrayFromCollectionName(v, 'reference', externalConfig),
|
v => cliHelpers.pathsArrayFromCollectionName(v, 'reference', externalConfig),
|
||||||
)
|
)
|
||||||
.option('--write-log-file', `Writes all logs to 'providence.log' file`);
|
.option('--write-log-file', `Writes all logs to 'providence.log' file`)
|
||||||
|
.option(
|
||||||
|
'--target-dependencies [target-dependencies]',
|
||||||
|
`For all search targets, will include all its dependencies
|
||||||
|
(node_modules and bower_components). When --target-dependencies is applied
|
||||||
|
without argument, it will act as boolean and include all dependencies.
|
||||||
|
When a regex is supplied like --target-dependencies /^my-brand-/, it will filter
|
||||||
|
all packages that comply with the regex`,
|
||||||
|
);
|
||||||
|
|
||||||
commander
|
commander
|
||||||
.command('search <regex>')
|
.command('search <regex>')
|
||||||
|
|
|
||||||
|
|
@ -9,26 +9,6 @@ const { InputDataService } = require('../../services/InputDataService.js');
|
||||||
const { aForEach } = require('../../utils/async-array-utils.js');
|
const { aForEach } = require('../../utils/async-array-utils.js');
|
||||||
const { getFilePathRelativeFromRoot } = require('../../utils/get-file-path-relative-from-root.js');
|
const { getFilePathRelativeFromRoot } = require('../../utils/get-file-path-relative-from-root.js');
|
||||||
|
|
||||||
/**
|
|
||||||
* @desc Gets a cached result from ReportService. Since ReportService slightly modifies analyzer
|
|
||||||
* output, we 'unwind' before we return...
|
|
||||||
* @param {object} config
|
|
||||||
* @param {string} config.analyzerName
|
|
||||||
* @param {string} config.identifier
|
|
||||||
*/
|
|
||||||
function getCachedAnalyzerResult({ analyzerName, identifier }) {
|
|
||||||
const cachedResult = ReportService.getCachedResult({ analyzerName, identifier });
|
|
||||||
if (!cachedResult) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
LogService.success(`cached version found for ${identifier}`);
|
|
||||||
|
|
||||||
const { queryOutput } = cachedResult;
|
|
||||||
const { analyzerMeta } = cachedResult.meta;
|
|
||||||
analyzerMeta.__fromCache = true;
|
|
||||||
return { analyzerMeta, queryOutput }; // eslint-disable-line consistent-return
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @desc analyzes one entry: the callback can traverse a given ast for each entry
|
* @desc analyzes one entry: the callback can traverse a given ast for each entry
|
||||||
* @param {AstDataProject[]} astDataProjects
|
* @param {AstDataProject[]} astDataProjects
|
||||||
|
|
@ -48,7 +28,7 @@ async function analyzePerAstEntry(projectData, astAnalysis) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @desc This method ensures that the result returned by an analyzer always has a consitent format,
|
* @desc This method ensures that the result returned by an analyzer always has a consistent format.
|
||||||
* By returning the configuration for the queryOutput, it will be possible to run later queries
|
* By returning the configuration for the queryOutput, it will be possible to run later queries
|
||||||
* under the same circumstances
|
* under the same circumstances
|
||||||
* @param {array} queryOutput
|
* @param {array} queryOutput
|
||||||
|
|
@ -86,6 +66,14 @@ function ensureAnalyzerResultFormat(queryOutput, configuration, analyzer) {
|
||||||
delete aResult.analyzerMeta.configuration.referenceProjectPath;
|
delete aResult.analyzerMeta.configuration.referenceProjectPath;
|
||||||
delete aResult.analyzerMeta.configuration.targetProjectPath;
|
delete aResult.analyzerMeta.configuration.targetProjectPath;
|
||||||
|
|
||||||
|
const { referenceProjectResult, targetProjectResult } = aResult.analyzerMeta.configuration;
|
||||||
|
|
||||||
|
if (referenceProjectResult) {
|
||||||
|
delete aResult.analyzerMeta.configuration.referenceProjectResult;
|
||||||
|
} else if (targetProjectResult) {
|
||||||
|
delete aResult.analyzerMeta.configuration.targetProjectResult;
|
||||||
|
}
|
||||||
|
|
||||||
if (Array.isArray(aResult.queryOutput)) {
|
if (Array.isArray(aResult.queryOutput)) {
|
||||||
aResult.queryOutput.forEach(projectOutput => {
|
aResult.queryOutput.forEach(projectOutput => {
|
||||||
if (projectOutput.project) {
|
if (projectOutput.project) {
|
||||||
|
|
@ -123,6 +111,16 @@ function checkForMatchCompatibility(referencePath, targetPath) {
|
||||||
return { compatible: true };
|
return { compatible: true };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If in json format, 'unwind' to be compatible for analysis...
|
||||||
|
* @param {AnalyzerResult} targetOrReferenceProjectResult
|
||||||
|
*/
|
||||||
|
function unwindJsonResult(targetOrReferenceProjectResult) {
|
||||||
|
const { queryOutput } = targetOrReferenceProjectResult;
|
||||||
|
const { analyzerMeta } = targetOrReferenceProjectResult.meta;
|
||||||
|
return { queryOutput, analyzerMeta };
|
||||||
|
}
|
||||||
|
|
||||||
class Analyzer {
|
class Analyzer {
|
||||||
constructor() {
|
constructor() {
|
||||||
this.requiredAst = 'babel';
|
this.requiredAst = 'babel';
|
||||||
|
|
@ -132,15 +130,39 @@ class Analyzer {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* In a MatchAnalyzer, two Analyzers (a reference and targer) are run.
|
||||||
|
* For instance, in a MatchImportsAnalyzer, a FindExportsAnalyzer and FinImportsAnalyzer are run.
|
||||||
|
* Their results can be provided as config params.
|
||||||
|
* If they are stored in json format, 'unwind' them to be compatible for analysis...
|
||||||
|
* @param {MatchAnalyzerConfig} cfg
|
||||||
|
*/
|
||||||
|
static __unwindProvidedResults(cfg) {
|
||||||
|
if (cfg.targetProjectResult && !cfg.targetProjectResult.analyzerMeta) {
|
||||||
|
cfg.targetProjectResult = unwindJsonResult(cfg.targetProjectResult);
|
||||||
|
}
|
||||||
|
if (cfg.referenceProjectResult && !cfg.referenceProjectResult.analyzerMeta) {
|
||||||
|
cfg.referenceProjectResult = unwindJsonResult(cfg.referenceProjectResult);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {AnalyzerConfig} cfg
|
* @param {AnalyzerConfig} cfg
|
||||||
* @returns {CachedAnalyzerResult|undefined}
|
* @returns {CachedAnalyzerResult|undefined}
|
||||||
*/
|
*/
|
||||||
_prepare(cfg) {
|
_prepare(cfg) {
|
||||||
this.targetProjectMeta = InputDataService.getProjectMeta(cfg.targetProjectPath, true);
|
this.constructor.__unwindProvidedResults(cfg);
|
||||||
|
|
||||||
if (cfg.referenceProjectPath) {
|
if (!cfg.targetProjectResult) {
|
||||||
|
this.targetProjectMeta = InputDataService.getProjectMeta(cfg.targetProjectPath, true);
|
||||||
|
} else {
|
||||||
|
this.targetProjectMeta = cfg.targetProjectResult.analyzerMeta.targetProject;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cfg.referenceProjectPath && !cfg.referenceProjectResult) {
|
||||||
this.referenceProjectMeta = InputDataService.getProjectMeta(cfg.referenceProjectPath, true);
|
this.referenceProjectMeta = InputDataService.getProjectMeta(cfg.referenceProjectPath, true);
|
||||||
|
} else if (cfg.referenceProjectResult) {
|
||||||
|
this.referenceProjectMeta = cfg.referenceProjectResult.analyzerMeta.targetProject;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -152,9 +174,9 @@ class Analyzer {
|
||||||
analyzerConfig: cfg,
|
analyzerConfig: cfg,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// If we have a provided result cfg.referenceProjectResult, we assume the providing
|
||||||
|
// party provides compatible results for now...
|
||||||
if (cfg.referenceProjectPath) {
|
if (cfg.referenceProjectPath) {
|
||||||
this.referenceProjectMeta = InputDataService.getProjectMeta(cfg.referenceProjectPath, true);
|
|
||||||
|
|
||||||
const { compatible, reason } = checkForMatchCompatibility(
|
const { compatible, reason } = checkForMatchCompatibility(
|
||||||
cfg.referenceProjectPath,
|
cfg.referenceProjectPath,
|
||||||
cfg.targetProjectPath,
|
cfg.targetProjectPath,
|
||||||
|
|
@ -176,7 +198,7 @@ class Analyzer {
|
||||||
/**
|
/**
|
||||||
* See if we maybe already have our result in cache in the file-system.
|
* See if we maybe already have our result in cache in the file-system.
|
||||||
*/
|
*/
|
||||||
const cachedResult = getCachedAnalyzerResult({
|
const cachedResult = Analyzer._getCachedAnalyzerResult({
|
||||||
analyzerName: this.name,
|
analyzerName: this.name,
|
||||||
identifier: this.identifier,
|
identifier: this.identifier,
|
||||||
});
|
});
|
||||||
|
|
@ -186,13 +208,16 @@ class Analyzer {
|
||||||
}
|
}
|
||||||
|
|
||||||
LogService.info(`starting ${LogService.pad(this.name, 16)} for ${this.identifier}`);
|
LogService.info(`starting ${LogService.pad(this.name, 16)} for ${this.identifier}`);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get reference and search-target data
|
* Get reference and search-target data
|
||||||
*/
|
*/
|
||||||
this.targetData = InputDataService.createDataObject(
|
if (!cfg.targetProjectResult) {
|
||||||
[cfg.targetProjectPath],
|
this.targetData = InputDataService.createDataObject(
|
||||||
cfg.gatherFilesConfig,
|
[cfg.targetProjectPath],
|
||||||
);
|
cfg.gatherFilesConfig,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
if (cfg.referenceProjectPath) {
|
if (cfg.referenceProjectPath) {
|
||||||
this.referenceData = InputDataService.createDataObject(
|
this.referenceData = InputDataService.createDataObject(
|
||||||
|
|
@ -251,6 +276,27 @@ class Analyzer {
|
||||||
*/
|
*/
|
||||||
return this._finalize(queryOutput, cfg);
|
return this._finalize(queryOutput, cfg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @desc Gets a cached result from ReportService. Since ReportService slightly modifies analyzer
|
||||||
|
* output, we 'unwind' before we return...
|
||||||
|
* @param {object} config
|
||||||
|
* @param {string} config.analyzerName
|
||||||
|
* @param {string} config.identifier
|
||||||
|
* @returns {AnalyzerResult|undefined}
|
||||||
|
*/
|
||||||
|
static _getCachedAnalyzerResult({ analyzerName, identifier }) {
|
||||||
|
const cachedResult = ReportService.getCachedResult({ analyzerName, identifier });
|
||||||
|
if (!cachedResult) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
LogService.success(`cached version found for ${identifier}`);
|
||||||
|
|
||||||
|
/** @type {AnalyzerResult} */
|
||||||
|
const result = unwindJsonResult(cachedResult);
|
||||||
|
result.analyzerMeta.__fromCache = true;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = { Analyzer };
|
module.exports = { Analyzer };
|
||||||
|
|
|
||||||
|
|
@ -49,17 +49,21 @@ function fromImportToExportPerspective({
|
||||||
// we still need to check if we're not dealing with a folder.
|
// we still need to check if we're not dealing with a folder.
|
||||||
// - '@open-wc/x/y.js' -> '@open-wc/x/y.js' or... '@open-wc/x/y.js/index.js' ?
|
// - '@open-wc/x/y.js' -> '@open-wc/x/y.js' or... '@open-wc/x/y.js/index.js' ?
|
||||||
// - or 'lion-based-ui/test' -> 'lion-based-ui/test/index.js' or 'lion-based-ui/test' ?
|
// - or 'lion-based-ui/test' -> 'lion-based-ui/test/index.js' or 'lion-based-ui/test' ?
|
||||||
const pathToCheck = pathLib.resolve(externalRootPath, `./${localPath}`);
|
if (externalRootPath) {
|
||||||
|
const pathToCheck = pathLib.resolve(externalRootPath, `./${localPath}`);
|
||||||
|
|
||||||
if (fs.existsSync(pathToCheck)) {
|
if (fs.existsSync(pathToCheck)) {
|
||||||
const stat = fs.statSync(pathToCheck);
|
const stat = fs.statSync(pathToCheck);
|
||||||
if (stat && stat.isFile()) {
|
if (stat && stat.isFile()) {
|
||||||
return `./${localPath}`; // '/path/to/lion-based-ui/fol.der' is a file
|
return `./${localPath}`; // '/path/to/lion-based-ui/fol.der' is a file
|
||||||
|
}
|
||||||
|
return `./${localPath}/index.js`; // '/path/to/lion-based-ui/fol.der' is a folder
|
||||||
|
// eslint-disable-next-line no-else-return
|
||||||
|
} else if (fs.existsSync(`${pathToCheck}.js`)) {
|
||||||
|
return `./${localPath}.js`; // '/path/to/lion-based-ui/fol.der' is file '/path/to/lion-based-ui/fol.der.js'
|
||||||
}
|
}
|
||||||
return `./${localPath}/index.js`; // '/path/to/lion-based-ui/fol.der' is a folder
|
} else {
|
||||||
// eslint-disable-next-line no-else-return
|
return `./${localPath}`;
|
||||||
} else if (fs.existsSync(`${pathToCheck}.js`)) {
|
|
||||||
return `./${localPath}.js`; // '/path/to/lion-based-ui/fol.der' is file '/path/to/lion-based-ui/fol.der.js'
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// like '@lion/core'
|
// like '@lion/core'
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,20 @@ function storeResult(resultsObj, exportId, filteredList, meta) {
|
||||||
resultsObj[exportId].files = [...(resultsObj[exportId].files || []), ...Array.from(filteredList)];
|
resultsObj[exportId].files = [...(resultsObj[exportId].files || []), ...Array.from(filteredList)];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Needed in case fromImportToExportPerspective does not have a
|
||||||
|
* externalRootPath supplied.
|
||||||
|
* @param {string} exportPath exportEntry.file
|
||||||
|
* @param {string} translatedImportPath result of fromImportToExportPerspective
|
||||||
|
*/
|
||||||
|
function compareImportAndExportPaths(exportPath, translatedImportPath) {
|
||||||
|
return (
|
||||||
|
exportPath === translatedImportPath ||
|
||||||
|
exportPath === `${translatedImportPath}.js` ||
|
||||||
|
exportPath === `${translatedImportPath}/index.js`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {FindExportsAnalyzerResult} exportsAnalyzerResult
|
* @param {FindExportsAnalyzerResult} exportsAnalyzerResult
|
||||||
* @param {FindImportsAnalyzerResult} importsAnalyzerResult
|
* @param {FindImportsAnalyzerResult} importsAnalyzerResult
|
||||||
|
|
@ -83,6 +97,10 @@ function matchImportsPostprocess(exportsAnalyzerResult, importsAnalyzerResult, c
|
||||||
importEntryResult.importSpecifiers.includes(exportSpecifier) ||
|
importEntryResult.importSpecifiers.includes(exportSpecifier) ||
|
||||||
importEntryResult.importSpecifiers.includes('[*]');
|
importEntryResult.importSpecifiers.includes('[*]');
|
||||||
|
|
||||||
|
if (!hasExportSpecifierImported) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @example
|
* @example
|
||||||
* exportFile './foo.js'
|
* exportFile './foo.js'
|
||||||
|
|
@ -90,22 +108,23 @@ function matchImportsPostprocess(exportsAnalyzerResult, importsAnalyzerResult, c
|
||||||
* importFile 'importing-target-project/file.js'
|
* importFile 'importing-target-project/file.js'
|
||||||
* => import { z } from '@reference/foo.js'
|
* => import { z } from '@reference/foo.js'
|
||||||
*/
|
*/
|
||||||
const isFromSameSource =
|
const fromImportToExport = fromImportToExportPerspective({
|
||||||
exportEntry.file ===
|
requestedExternalSource: importEntryResult.normalizedSource,
|
||||||
fromImportToExportPerspective({
|
externalProjectMeta: exportsProjectObj,
|
||||||
requestedExternalSource: importEntryResult.normalizedSource,
|
externalRootPath: cfg.referenceProjectResult ? null : cfg.referenceProjectPath,
|
||||||
externalProjectMeta: exportsProjectObj,
|
});
|
||||||
externalRootPath: cfg.referenceProjectPath,
|
const isFromSameSource = compareImportAndExportPaths(
|
||||||
});
|
exportEntry.file,
|
||||||
|
fromImportToExport,
|
||||||
|
);
|
||||||
|
|
||||||
// TODO: transitive deps recognition. Could also be distinct post processor
|
if (!isFromSameSource) {
|
||||||
// // export { z } from '../foo.js'
|
return;
|
||||||
// // import { z } from '@reference/foo.js'
|
|
||||||
// (exportEntryResult.normalizedSource === importEntryResult.normalizedSource)
|
|
||||||
|
|
||||||
if (hasExportSpecifierImported && isFromSameSource) {
|
|
||||||
filteredImportsList.add(`${importProject}::${file}`);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: transitive deps recognition? Could also be distinct post processor
|
||||||
|
|
||||||
|
filteredImportsList.add(`${importProject}::${file}`);
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
storeResult(resultsObj, exportId, filteredImportsList, exportEntry.meta);
|
storeResult(resultsObj, exportId, filteredImportsList, exportEntry.meta);
|
||||||
|
|
@ -201,15 +220,15 @@ class MatchImportsAnalyzer extends Analyzer {
|
||||||
* @property {GatherFilesConfig} [gatherFilesConfig]
|
* @property {GatherFilesConfig} [gatherFilesConfig]
|
||||||
* @property {array} [referenceProjectPath] reference paths
|
* @property {array} [referenceProjectPath] reference paths
|
||||||
* @property {array} [targetProjectPath] search target paths
|
* @property {array} [targetProjectPath] search target paths
|
||||||
* @property {FindExportsAnalyzerResult} [exportsAnalyzerResult]
|
* @property {FindImportsAnalyzerResult} [targetProjectResult]
|
||||||
* @property {FindImportsAnalyzerResult} [importsAnalyzerResult]
|
* @property {FindExportsAnalyzerResult} [referenceProjectResult]
|
||||||
*/
|
*/
|
||||||
const cfg = {
|
const cfg = {
|
||||||
gatherFilesConfig: {},
|
gatherFilesConfig: {},
|
||||||
referenceProjectPath: null,
|
referenceProjectPath: null,
|
||||||
targetProjectPath: null,
|
targetProjectPath: null,
|
||||||
exportsAnalyzerResult: null,
|
targetProjectResult: null,
|
||||||
importsAnalyzerResult: null,
|
referenceProjectResult: null,
|
||||||
...customConfig,
|
...customConfig,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -224,25 +243,25 @@ class MatchImportsAnalyzer extends Analyzer {
|
||||||
/**
|
/**
|
||||||
* Traverse
|
* Traverse
|
||||||
*/
|
*/
|
||||||
let { exportsAnalyzerResult } = cfg;
|
let { referenceProjectResult } = cfg;
|
||||||
if (!exportsAnalyzerResult) {
|
if (!referenceProjectResult) {
|
||||||
const findExportsAnalyzer = new FindExportsAnalyzer();
|
const findExportsAnalyzer = new FindExportsAnalyzer();
|
||||||
exportsAnalyzerResult = await findExportsAnalyzer.execute({
|
referenceProjectResult = await findExportsAnalyzer.execute({
|
||||||
metaConfig: cfg.metaConfig,
|
metaConfig: cfg.metaConfig,
|
||||||
targetProjectPath: cfg.referenceProjectPath,
|
targetProjectPath: cfg.referenceProjectPath,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
let { importsAnalyzerResult } = cfg;
|
let { targetProjectResult } = cfg;
|
||||||
if (!importsAnalyzerResult) {
|
if (!targetProjectResult) {
|
||||||
const findImportsAnalyzer = new FindImportsAnalyzer();
|
const findImportsAnalyzer = new FindImportsAnalyzer();
|
||||||
importsAnalyzerResult = await findImportsAnalyzer.execute({
|
targetProjectResult = await findImportsAnalyzer.execute({
|
||||||
metaConfig: cfg.metaConfig,
|
metaConfig: cfg.metaConfig,
|
||||||
targetProjectPath: cfg.targetProjectPath,
|
targetProjectPath: cfg.targetProjectPath,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const queryOutput = matchImportsPostprocess(exportsAnalyzerResult, importsAnalyzerResult, cfg);
|
const queryOutput = matchImportsPostprocess(referenceProjectResult, targetProjectResult, cfg);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Finalize
|
* Finalize
|
||||||
|
|
|
||||||
|
|
@ -329,7 +329,7 @@ function matchPathsPostprocess(
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Designed to work in conjunction with npm package `extend-docs`.
|
* Designed to work in conjunction with npm package `babel-plugin-extend-docs`.
|
||||||
* It will lookup all class exports from reference project A (and store their available paths) and
|
* It will lookup all class exports from reference project A (and store their available paths) and
|
||||||
* matches them against all imports of project B that extend exported class (and store their
|
* matches them against all imports of project B that extend exported class (and store their
|
||||||
* available paths).
|
* available paths).
|
||||||
|
|
@ -426,7 +426,8 @@ class MatchPathsAnalyzer extends Analyzer {
|
||||||
const targetMatchSubclassesResult = await targetMatchSubclassesAnalyzer.execute({
|
const targetMatchSubclassesResult = await targetMatchSubclassesAnalyzer.execute({
|
||||||
targetProjectPath: cfg.targetProjectPath,
|
targetProjectPath: cfg.targetProjectPath,
|
||||||
referenceProjectPath: cfg.referenceProjectPath,
|
referenceProjectPath: cfg.referenceProjectPath,
|
||||||
gatherFilesConfig: cfg.gatherFilesConfigReference,
|
gatherFilesConfig: cfg.gatherFilesConfig,
|
||||||
|
gatherFilesConfigReference: cfg.gatherFilesConfigReference,
|
||||||
});
|
});
|
||||||
|
|
||||||
// [A2]
|
// [A2]
|
||||||
|
|
@ -434,6 +435,7 @@ class MatchPathsAnalyzer extends Analyzer {
|
||||||
/** @type {FindExportsAnalyzerResult} */
|
/** @type {FindExportsAnalyzerResult} */
|
||||||
const targetExportsResult = await targetFindExportsAnalyzer.execute({
|
const targetExportsResult = await targetFindExportsAnalyzer.execute({
|
||||||
targetProjectPath: cfg.targetProjectPath,
|
targetProjectPath: cfg.targetProjectPath,
|
||||||
|
gatherFilesConfig: cfg.gatherFilesConfig,
|
||||||
});
|
});
|
||||||
|
|
||||||
// [A3]
|
// [A3]
|
||||||
|
|
@ -441,6 +443,7 @@ class MatchPathsAnalyzer extends Analyzer {
|
||||||
/** @type {FindExportsAnalyzerResult} */
|
/** @type {FindExportsAnalyzerResult} */
|
||||||
const refFindExportsResult = await refFindExportsAnalyzer.execute({
|
const refFindExportsResult = await refFindExportsAnalyzer.execute({
|
||||||
targetProjectPath: cfg.referenceProjectPath,
|
targetProjectPath: cfg.referenceProjectPath,
|
||||||
|
gatherFilesConfig: cfg.gatherFilesConfigReference,
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -448,14 +451,14 @@ class MatchPathsAnalyzer extends Analyzer {
|
||||||
* Automatically generate a mapping from lion docs import paths to extension layer
|
* Automatically generate a mapping from lion docs import paths to extension layer
|
||||||
* import paths. To be served to extend-docs
|
* import paths. To be served to extend-docs
|
||||||
*
|
*
|
||||||
* [1] Find path variable.to 'WolfCheckbox'
|
* [B1] Find path variable.to 'WolfCheckbox'
|
||||||
* Run 'match-subclasses' for target project: we find the 'rootFilePath' of class definition,
|
* Run 'match-subclasses' for target project: we find the 'rootFilePath' of class definition,
|
||||||
* Result: './packages/wolf-checkbox/WolfCheckbox.js'
|
* Result: './packages/wolf-checkbox/WolfCheckbox.js'
|
||||||
* [B1] Find export path of 'wolf-checkbox'
|
* [B2] Find export path of 'wolf-checkbox'
|
||||||
* Run 'find-customelements' on target project and match rootFile of [A1] with rootFile of
|
* Run 'find-customelements' on target project and match rootFile of [B1] with rootFile of
|
||||||
* constructor.
|
* constructor.
|
||||||
* Result: './wolf-checkbox.js'
|
* Result: './wolf-checkbox.js'
|
||||||
* [B2] Find export path of 'lion-checkbox'
|
* [B3] Find export path of 'lion-checkbox'
|
||||||
* Run 'find-customelements' and find-exports (for rootpath) on reference project and match
|
* Run 'find-customelements' and find-exports (for rootpath) on reference project and match
|
||||||
* rootFile of constructor with rootFiles of where LionCheckbox is defined.
|
* rootFile of constructor with rootFiles of where LionCheckbox is defined.
|
||||||
* Result: './packages/checkbox/lion-checkbox.js',
|
* Result: './packages/checkbox/lion-checkbox.js',
|
||||||
|
|
@ -467,6 +470,7 @@ class MatchPathsAnalyzer extends Analyzer {
|
||||||
/** @type {FindCustomelementsAnalyzerResult} */
|
/** @type {FindCustomelementsAnalyzerResult} */
|
||||||
const targetFindCustomelementsResult = await targetFindCustomelementsAnalyzer.execute({
|
const targetFindCustomelementsResult = await targetFindCustomelementsAnalyzer.execute({
|
||||||
targetProjectPath: cfg.targetProjectPath,
|
targetProjectPath: cfg.targetProjectPath,
|
||||||
|
gatherFilesConfig: cfg.gatherFilesConfig,
|
||||||
});
|
});
|
||||||
|
|
||||||
// [B2]
|
// [B2]
|
||||||
|
|
@ -474,6 +478,7 @@ class MatchPathsAnalyzer extends Analyzer {
|
||||||
/** @type {FindCustomelementsAnalyzerResult} */
|
/** @type {FindCustomelementsAnalyzerResult} */
|
||||||
const refFindCustomelementsResult = await refFindCustomelementsAnalyzer.execute({
|
const refFindCustomelementsResult = await refFindCustomelementsAnalyzer.execute({
|
||||||
targetProjectPath: cfg.referenceProjectPath,
|
targetProjectPath: cfg.referenceProjectPath,
|
||||||
|
gatherFilesConfig: cfg.gatherFilesConfigReference,
|
||||||
});
|
});
|
||||||
// refFindExportsAnalyzer was already created in A3
|
// refFindExportsAnalyzer was already created in A3
|
||||||
|
|
||||||
|
|
@ -483,7 +488,6 @@ class MatchPathsAnalyzer extends Analyzer {
|
||||||
let queryOutput = matchPathsPostprocess(
|
let queryOutput = matchPathsPostprocess(
|
||||||
targetMatchSubclassesResult,
|
targetMatchSubclassesResult,
|
||||||
targetExportsResult,
|
targetExportsResult,
|
||||||
// refImportsResult,
|
|
||||||
targetFindCustomelementsResult,
|
targetFindCustomelementsResult,
|
||||||
refFindCustomelementsResult,
|
refFindCustomelementsResult,
|
||||||
refFindExportsResult,
|
refFindExportsResult,
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
/**
|
/**
|
||||||
* @desc Readable way to do an async forEach
|
* @desc Readable way to do an async forEach
|
||||||
* Since predictability mathers, all array items will be handled in a queue;
|
* Since predictability matters, all array items will be handled in a queue,
|
||||||
* one after anotoher
|
* one after another
|
||||||
* @param {array} array
|
* @param {array} array
|
||||||
* @param {function} callback
|
* @param {function} callback
|
||||||
*/
|
*/
|
||||||
|
|
@ -13,8 +13,8 @@ async function aForEach(array, callback) {
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* @desc Readable way to do an async forEach
|
* @desc Readable way to do an async forEach
|
||||||
* Since predictability mathers, all array items will be handled in a queue;
|
* If predictability does not matter, this method will traverse array items concurrently,
|
||||||
* one after anotoher
|
* leading to a better performance
|
||||||
* @param {array} array
|
* @param {array} array
|
||||||
* @param {function} callback
|
* @param {function} callback
|
||||||
*/
|
*/
|
||||||
|
|
@ -23,7 +23,7 @@ async function aForEachNonSequential(array, callback) {
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* @desc Readable way to do an async map
|
* @desc Readable way to do an async map
|
||||||
* Since predictability is crucial for a map, all array items will be handled in a queue;
|
* Since predictability is crucial for a map, all array items will be handled in a queue,
|
||||||
* one after anotoher
|
* one after anotoher
|
||||||
* @param {array} array
|
* @param {array} array
|
||||||
* @param {function} callback
|
* @param {function} callback
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
const sinon = require('sinon');
|
const sinon = require('sinon');
|
||||||
const pathLib = require('path');
|
const pathLib = require('path');
|
||||||
const { expect } = require('chai');
|
const { expect } = require('chai');
|
||||||
|
const commander = require('commander');
|
||||||
const {
|
const {
|
||||||
mockProject,
|
mockProject,
|
||||||
restoreMockedProjects,
|
restoreMockedProjects,
|
||||||
|
|
@ -13,147 +14,339 @@ const {
|
||||||
suppressNonCriticalLogs,
|
suppressNonCriticalLogs,
|
||||||
restoreSuppressNonCriticalLogs,
|
restoreSuppressNonCriticalLogs,
|
||||||
} = require('../../test-helpers/mock-log-service-helpers.js');
|
} = require('../../test-helpers/mock-log-service-helpers.js');
|
||||||
|
const { InputDataService } = require('../../src/program/services/InputDataService.js');
|
||||||
const { QueryService } = require('../../src/program/services/QueryService.js');
|
const { QueryService } = require('../../src/program/services/QueryService.js');
|
||||||
|
|
||||||
const providenceModule = require('../../src/program/providence.js');
|
const providenceModule = require('../../src/program/providence.js');
|
||||||
const extendDocsModule = require('../../src/cli/generate-extend-docs-data.js');
|
const extendDocsModule = require('../../src/cli/generate-extend-docs-data.js');
|
||||||
|
const cliHelpersModule = require('../../src/cli/cli-helpers.js');
|
||||||
const dummyAnalyzer = require('../../test-helpers/templates/analyzer-template.js');
|
|
||||||
const { cli } = require('../../src/cli/cli.js');
|
const { cli } = require('../../src/cli/cli.js');
|
||||||
const { pathsArrayFromCs } = require('../../src/cli/cli-helpers.js');
|
const promptAnalyzerModule = require('../../src/cli/prompt-analyzer-menu.js');
|
||||||
|
|
||||||
|
const {
|
||||||
|
pathsArrayFromCs,
|
||||||
|
pathsArrayFromCollectionName,
|
||||||
|
appendProjectDependencyPaths,
|
||||||
|
} = cliHelpersModule;
|
||||||
|
|
||||||
const queryResults = [];
|
const queryResults = [];
|
||||||
const rootDir = pathLib.resolve(__dirname, '../../');
|
const rootDir = pathLib.resolve(__dirname, '../../');
|
||||||
|
|
||||||
|
const externalCfgMock = {
|
||||||
|
searchTargetCollections: {
|
||||||
|
'lion-collection': [
|
||||||
|
'./providence-input-data/search-targets/example-project-a',
|
||||||
|
'./providence-input-data/search-targets/example-project-b',
|
||||||
|
// ...etc
|
||||||
|
],
|
||||||
|
},
|
||||||
|
referenceCollections: {
|
||||||
|
'lion-based-ui-collection': [
|
||||||
|
'./providence-input-data/references/lion-based-ui',
|
||||||
|
'./providence-input-data/references/lion-based-ui-labs',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
async function runCli(args, cwd) {
|
||||||
|
process.argv = [...process.argv.slice(0, 2), ...args.split(' ')];
|
||||||
|
await cli({ cwd });
|
||||||
|
}
|
||||||
|
|
||||||
describe('Providence CLI', () => {
|
describe('Providence CLI', () => {
|
||||||
|
let providenceStub;
|
||||||
|
let promptCfgStub;
|
||||||
|
let iExtConfStub;
|
||||||
|
let promptStub;
|
||||||
|
let qConfStub;
|
||||||
|
|
||||||
before(() => {
|
before(() => {
|
||||||
suppressNonCriticalLogs();
|
// Prevent MaxListenersExceededWarning
|
||||||
|
commander.setMaxListeners(100);
|
||||||
|
|
||||||
mockWriteToJson(queryResults);
|
mockWriteToJson(queryResults);
|
||||||
|
suppressNonCriticalLogs();
|
||||||
|
|
||||||
mockProject(
|
mockProject(
|
||||||
{
|
{
|
||||||
'./src/OriginalComp.js': `export class OriginalComp {}`,
|
'./src/OriginalComp.js': `export class OriginalComp {}`,
|
||||||
'./src/inbetween.js': `export { OriginalComp as InBetweenComp } from './OriginalComp.js'`,
|
'./src/inbetween.js': `export { OriginalComp as InBetweenComp } from './OriginalComp.js'`,
|
||||||
'./index.js': `export { InBetweenComp as MyComp } from './src/inbetween.js'`,
|
'./index.js': `export { InBetweenComp as MyComp } from './src/inbetween.js'`,
|
||||||
|
'./node_modules/dependency-a/index.js': '',
|
||||||
|
'./bower_components/dependency-b/index.js': '',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
projectName: 'example-project',
|
projectName: 'example-project',
|
||||||
projectPath: '/mocked/path/example-project',
|
projectPath: '/mocked/path/example-project',
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
providenceStub = sinon.stub(providenceModule, 'providence').returns(
|
||||||
|
new Promise(resolve => {
|
||||||
|
resolve();
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
promptCfgStub = sinon
|
||||||
|
.stub(promptAnalyzerModule, 'promptAnalyzerConfigMenu')
|
||||||
|
.returns({ analyzerConfig: { con: 'fig' } });
|
||||||
|
|
||||||
|
iExtConfStub = sinon.stub(InputDataService, 'getExternalConfig').returns(externalCfgMock);
|
||||||
|
|
||||||
|
promptStub = sinon
|
||||||
|
.stub(promptAnalyzerModule, 'promptAnalyzerMenu')
|
||||||
|
.returns({ analyzerName: 'mock-analyzer' });
|
||||||
|
|
||||||
|
qConfStub = sinon.stub(QueryService, 'getQueryConfigFromAnalyzer').returns({
|
||||||
|
analyzer: {
|
||||||
|
name: 'mock-analyzer',
|
||||||
|
requiresReference: true,
|
||||||
|
},
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
after(() => {
|
after(() => {
|
||||||
|
commander.setMaxListeners(10);
|
||||||
|
|
||||||
restoreSuppressNonCriticalLogs();
|
restoreSuppressNonCriticalLogs();
|
||||||
restoreWriteToJson();
|
|
||||||
restoreMockedProjects();
|
restoreMockedProjects();
|
||||||
});
|
restoreWriteToJson();
|
||||||
|
|
||||||
let providenceStub;
|
|
||||||
let qConfStub;
|
|
||||||
beforeEach(() => {
|
|
||||||
qConfStub = sinon.stub(QueryService, 'getQueryConfigFromAnalyzer').returns({ analyzer: {} });
|
|
||||||
providenceStub = sinon.stub(providenceModule, 'providence').returns(Promise.resolve());
|
|
||||||
});
|
|
||||||
|
|
||||||
afterEach(() => {
|
|
||||||
providenceStub.restore();
|
providenceStub.restore();
|
||||||
|
promptCfgStub.restore();
|
||||||
|
iExtConfStub.restore();
|
||||||
|
promptStub.restore();
|
||||||
qConfStub.restore();
|
qConfStub.restore();
|
||||||
});
|
});
|
||||||
|
|
||||||
async function runCli(args, cwd) {
|
afterEach(() => {
|
||||||
process.argv = [...process.argv.slice(0, 2), ...args.split(' ')];
|
providenceStub.resetHistory();
|
||||||
await cli({ cwd, addProjectDependencyPaths: false });
|
promptCfgStub.resetHistory();
|
||||||
}
|
iExtConfStub.resetHistory();
|
||||||
|
promptStub.resetHistory();
|
||||||
const analyzCmd = 'analyze find-exports';
|
qConfStub.resetHistory();
|
||||||
|
|
||||||
it('creates a QueryConfig', async () => {
|
|
||||||
await runCli('analyze find-exports -t /mocked/path/example-project');
|
|
||||||
expect(qConfStub.called).to.be.true;
|
|
||||||
expect(qConfStub.args[0][0]).to.equal('find-exports');
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const analyzeCmd = 'analyze mock-analyzer';
|
||||||
|
|
||||||
it('calls providence', async () => {
|
it('calls providence', async () => {
|
||||||
await runCli(`${analyzCmd} -t /mocked/path/example-project`);
|
await runCli(`${analyzeCmd} -t /mocked/path/example-project`);
|
||||||
expect(providenceStub.called).to.be.true;
|
expect(providenceStub.called).to.be.true;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('creates a QueryConfig', async () => {
|
||||||
|
await runCli(`${analyzeCmd} -t /mocked/path/example-project`);
|
||||||
|
expect(qConfStub.called).to.be.true;
|
||||||
|
expect(qConfStub.args[0][0]).to.equal('mock-analyzer');
|
||||||
|
});
|
||||||
|
|
||||||
describe('Global options', () => {
|
describe('Global options', () => {
|
||||||
|
let pathsArrayFromCollectionStub;
|
||||||
|
let pathsArrayFromCsStub;
|
||||||
|
let appendProjectDependencyPathsStub;
|
||||||
|
|
||||||
|
before(() => {
|
||||||
|
pathsArrayFromCsStub = sinon
|
||||||
|
.stub(cliHelpersModule, 'pathsArrayFromCs')
|
||||||
|
.returns(['/mocked/path/example-project']);
|
||||||
|
pathsArrayFromCollectionStub = sinon
|
||||||
|
.stub(cliHelpersModule, 'pathsArrayFromCollectionName')
|
||||||
|
.returns(['/mocked/path/example-project']);
|
||||||
|
appendProjectDependencyPathsStub = sinon
|
||||||
|
.stub(cliHelpersModule, 'appendProjectDependencyPaths')
|
||||||
|
.returns([
|
||||||
|
'/mocked/path/example-project',
|
||||||
|
'/mocked/path/example-project/node_modules/mock-dep-a',
|
||||||
|
'/mocked/path/example-project/bower_components/mock-dep-b',
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
after(() => {
|
||||||
|
pathsArrayFromCsStub.restore();
|
||||||
|
pathsArrayFromCollectionStub.restore();
|
||||||
|
appendProjectDependencyPathsStub.restore();
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
pathsArrayFromCsStub.resetHistory();
|
||||||
|
pathsArrayFromCollectionStub.resetHistory();
|
||||||
|
appendProjectDependencyPathsStub.resetHistory();
|
||||||
|
});
|
||||||
|
|
||||||
it('"-e --extensions"', async () => {
|
it('"-e --extensions"', async () => {
|
||||||
await runCli(`${analyzCmd} --extensions bla,blu`);
|
await runCli(`${analyzeCmd} -e bla,blu`);
|
||||||
|
expect(providenceStub.args[0][1].gatherFilesConfig.extensions).to.eql(['.bla', '.blu']);
|
||||||
|
|
||||||
|
providenceStub.resetHistory();
|
||||||
|
|
||||||
|
await runCli(`${analyzeCmd} --extensions bla,blu`);
|
||||||
expect(providenceStub.args[0][1].gatherFilesConfig.extensions).to.eql(['.bla', '.blu']);
|
expect(providenceStub.args[0][1].gatherFilesConfig.extensions).to.eql(['.bla', '.blu']);
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('"-t", "--search-target-paths"', async () => {
|
it('"-t --search-target-paths"', async () => {
|
||||||
it('allows absolute paths', async () => {
|
await runCli(`${analyzeCmd} -t /mocked/path/example-project`, rootDir);
|
||||||
await runCli(`${analyzCmd} -t /mocked/path/example-project`, rootDir);
|
expect(pathsArrayFromCsStub.args[0][0]).to.equal('/mocked/path/example-project');
|
||||||
expect(providenceStub.args[0][1].targetProjectPaths).to.eql([
|
expect(providenceStub.args[0][1].targetProjectPaths).to.eql(['/mocked/path/example-project']);
|
||||||
'/mocked/path/example-project',
|
|
||||||
]);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('allows relative paths', async () => {
|
pathsArrayFromCsStub.resetHistory();
|
||||||
await runCli(
|
providenceStub.resetHistory();
|
||||||
`${analyzCmd} -t ./test-helpers/project-mocks/importing-target-project`,
|
|
||||||
rootDir,
|
|
||||||
);
|
|
||||||
expect(providenceStub.args[0][1].targetProjectPaths).to.eql([
|
|
||||||
`${rootDir}/test-helpers/project-mocks/importing-target-project`,
|
|
||||||
]);
|
|
||||||
|
|
||||||
await runCli(
|
await runCli(`${analyzeCmd} --search-target-paths /mocked/path/example-project`, rootDir);
|
||||||
`${analyzCmd} -t test-helpers/project-mocks/importing-target-project`,
|
expect(pathsArrayFromCsStub.args[0][0]).to.equal('/mocked/path/example-project');
|
||||||
rootDir,
|
expect(providenceStub.args[0][1].targetProjectPaths).to.eql(['/mocked/path/example-project']);
|
||||||
);
|
|
||||||
expect(providenceStub.args[0][1].targetProjectPaths).to.eql([
|
|
||||||
`${rootDir}/test-helpers/project-mocks/importing-target-project`,
|
|
||||||
]);
|
|
||||||
});
|
|
||||||
|
|
||||||
// TODO: globbing via cli-helpers doesn't work for some reason when run in this test
|
|
||||||
it.skip('allows globs', async () => {
|
|
||||||
await runCli(`${analyzCmd} -t test-helpers/*`, rootDir);
|
|
||||||
expect(providenceStub.args[0][1].targetProjectPaths).to.eql([
|
|
||||||
`${process.cwd()}/needed-for-test/pass-glob`,
|
|
||||||
]);
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('"-r", "--reference-paths"', async () => {});
|
it('"-r --reference-paths"', async () => {
|
||||||
it('"--search-target-collection"', async () => {});
|
await runCli(`${analyzeCmd} -r /mocked/path/example-project`, rootDir);
|
||||||
it('"--reference-collection"', async () => {});
|
expect(pathsArrayFromCsStub.args[0][0]).to.equal('/mocked/path/example-project');
|
||||||
|
expect(providenceStub.args[0][1].referenceProjectPaths).to.eql([
|
||||||
|
'/mocked/path/example-project',
|
||||||
|
]);
|
||||||
|
|
||||||
it.skip('"-R --verbose-report"', async () => {});
|
pathsArrayFromCsStub.resetHistory();
|
||||||
it.skip('"-D", "--debug"', async () => {});
|
providenceStub.resetHistory();
|
||||||
|
|
||||||
|
await runCli(`${analyzeCmd} --reference-paths /mocked/path/example-project`, rootDir);
|
||||||
|
expect(pathsArrayFromCsStub.args[0][0]).to.equal('/mocked/path/example-project');
|
||||||
|
expect(providenceStub.args[0][1].referenceProjectPaths).to.eql([
|
||||||
|
'/mocked/path/example-project',
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('"--search-target-collection"', async () => {
|
||||||
|
await runCli(`${analyzeCmd} --search-target-collection lion-collection`, rootDir);
|
||||||
|
expect(pathsArrayFromCollectionStub.args[0][0]).to.equal('lion-collection');
|
||||||
|
expect(providenceStub.args[0][1].targetProjectPaths).to.eql(['/mocked/path/example-project']);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('"--reference-collection"', async () => {
|
||||||
|
await runCli(`${analyzeCmd} --reference-collection lion-based-ui-collection`, rootDir);
|
||||||
|
expect(pathsArrayFromCollectionStub.args[0][0]).to.equal('lion-based-ui-collection');
|
||||||
|
expect(providenceStub.args[0][1].referenceProjectPaths).to.eql([
|
||||||
|
'/mocked/path/example-project',
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('"-w --whitelist"', async () => {
|
||||||
|
await runCli(`${analyzeCmd} -w /mocked/path/example-project`, rootDir);
|
||||||
|
expect(pathsArrayFromCsStub.args[0][0]).to.equal('/mocked/path/example-project');
|
||||||
|
expect(providenceStub.args[0][1].gatherFilesConfig.filter).to.eql([
|
||||||
|
'/mocked/path/example-project',
|
||||||
|
]);
|
||||||
|
|
||||||
|
pathsArrayFromCsStub.resetHistory();
|
||||||
|
providenceStub.resetHistory();
|
||||||
|
|
||||||
|
await runCli(`${analyzeCmd} --whitelist /mocked/path/example-project`, rootDir);
|
||||||
|
expect(pathsArrayFromCsStub.args[0][0]).to.equal('/mocked/path/example-project');
|
||||||
|
expect(providenceStub.args[0][1].gatherFilesConfig.filter).to.eql([
|
||||||
|
'/mocked/path/example-project',
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('"--whitelist-reference"', async () => {
|
||||||
|
await runCli(`${analyzeCmd} --whitelist-reference /mocked/path/example-project`, rootDir);
|
||||||
|
expect(pathsArrayFromCsStub.args[0][0]).to.equal('/mocked/path/example-project');
|
||||||
|
expect(providenceStub.args[0][1].gatherFilesConfigReference.filter).to.eql([
|
||||||
|
'/mocked/path/example-project',
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('"-D --debug"', async () => {
|
||||||
|
await runCli(`${analyzeCmd} -D`, rootDir);
|
||||||
|
expect(providenceStub.args[0][1].debugEnabled).to.equal(true);
|
||||||
|
|
||||||
|
providenceStub.resetHistory();
|
||||||
|
|
||||||
|
await runCli(`${analyzeCmd} --debug`, rootDir);
|
||||||
|
expect(providenceStub.args[0][1].debugEnabled).to.equal(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('--write-log-file"', async () => {
|
||||||
|
await runCli(`${analyzeCmd} --write-log-file`, rootDir);
|
||||||
|
expect(providenceStub.args[0][1].writeLogFile).to.equal(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('--target-dependencies"', async () => {
|
||||||
|
await runCli(`${analyzeCmd}`, rootDir);
|
||||||
|
expect(appendProjectDependencyPathsStub.called).to.be.false;
|
||||||
|
|
||||||
|
appendProjectDependencyPathsStub.resetHistory();
|
||||||
|
providenceStub.resetHistory();
|
||||||
|
|
||||||
|
await runCli(`${analyzeCmd} --target-dependencies`, rootDir);
|
||||||
|
expect(appendProjectDependencyPathsStub.called).to.be.true;
|
||||||
|
expect(providenceStub.args[0][1].targetProjectPaths).to.eql([
|
||||||
|
'/mocked/path/example-project',
|
||||||
|
'/mocked/path/example-project/node_modules/mock-dep-a',
|
||||||
|
'/mocked/path/example-project/bower_components/mock-dep-b',
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('--target-dependencies /^with-regex/"', async () => {
|
||||||
|
await runCli(`${analyzeCmd} --target-dependencies /^mock-/`, rootDir);
|
||||||
|
expect(appendProjectDependencyPathsStub.args[0][1]).to.equal('/^mock-/');
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('Commands', () => {
|
describe('Commands', () => {
|
||||||
describe('Analyze', () => {
|
describe('Analyze', () => {
|
||||||
it('calls providence', async () => {
|
it('calls providence', async () => {
|
||||||
expect(typeof dummyAnalyzer.name).to.equal('string');
|
await runCli(`${analyzeCmd}`, rootDir);
|
||||||
|
expect(providenceStub.called).to.be.true;
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('Options', () => {
|
describe('Options', () => {
|
||||||
it('"-o", "--prompt-optional-config"', async () => {});
|
it('"-o --prompt-optional-config"', async () => {
|
||||||
it('"-c", "--config"', async () => {});
|
await runCli(`analyze -o`, rootDir);
|
||||||
|
expect(promptStub.called).to.be.true;
|
||||||
|
|
||||||
|
promptStub.resetHistory();
|
||||||
|
|
||||||
|
await runCli(`analyze --prompt-optional-config`, rootDir);
|
||||||
|
expect(promptStub.called).to.be.true;
|
||||||
|
});
|
||||||
|
|
||||||
|
it('"-c --config"', async () => {
|
||||||
|
await runCli(`analyze mock-analyzer -c {"a":"2"}`, rootDir);
|
||||||
|
expect(qConfStub.args[0][0]).to.equal('mock-analyzer');
|
||||||
|
expect(qConfStub.args[0][1]).to.eql({ a: '2', metaConfig: undefined });
|
||||||
|
|
||||||
|
qConfStub.resetHistory();
|
||||||
|
|
||||||
|
await runCli(`analyze mock-analyzer --config {"a":"2"}`, rootDir);
|
||||||
|
expect(qConfStub.args[0][0]).to.equal('mock-analyzer');
|
||||||
|
expect(qConfStub.args[0][1]).to.eql({ a: '2', metaConfig: undefined });
|
||||||
|
});
|
||||||
|
|
||||||
|
it('calls "promptAnalyzerConfigMenu" without config given', async () => {
|
||||||
|
await runCli(`analyze mock-analyzer`, rootDir);
|
||||||
|
expect(promptCfgStub.called).to.be.true;
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
describe('Query', () => {});
|
|
||||||
describe('Search', () => {});
|
describe.skip('Query', () => {});
|
||||||
|
describe.skip('Search', () => {});
|
||||||
|
|
||||||
describe('Manage', () => {});
|
describe('Manage', () => {});
|
||||||
|
|
||||||
describe('Extend docs', () => {
|
describe('Extend docs', () => {
|
||||||
let extendDocsStub;
|
let extendDocsStub;
|
||||||
beforeEach(() => {
|
|
||||||
|
before(() => {
|
||||||
extendDocsStub = sinon
|
extendDocsStub = sinon
|
||||||
.stub(extendDocsModule, 'launchProvidenceWithExtendDocs')
|
.stub(extendDocsModule, 'launchProvidenceWithExtendDocs')
|
||||||
.returns(Promise.resolve());
|
.returns(Promise.resolve());
|
||||||
});
|
});
|
||||||
|
|
||||||
afterEach(() => {
|
after(() => {
|
||||||
extendDocsStub.restore();
|
extendDocsStub.restore();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
extendDocsStub.resetHistory();
|
||||||
|
});
|
||||||
|
|
||||||
it('allows configuration', async () => {
|
it('allows configuration', async () => {
|
||||||
await runCli(
|
await runCli(
|
||||||
[
|
[
|
||||||
|
|
@ -176,8 +369,8 @@ describe('Providence CLI', () => {
|
||||||
},
|
},
|
||||||
outputFolder: '/outp',
|
outputFolder: '/outp',
|
||||||
extensions: ['.bla'],
|
extensions: ['.bla'],
|
||||||
whitelist: [`${process.cwd()}/wl`],
|
whitelist: [`${rootDir}/wl`],
|
||||||
whitelistReference: [`${process.cwd()}/wlr`],
|
whitelistReference: [`${rootDir}/wlr`],
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
@ -203,8 +396,102 @@ describe('CLI helpers', () => {
|
||||||
|
|
||||||
it('allows globs', async () => {
|
it('allows globs', async () => {
|
||||||
expect(pathsArrayFromCs('test-helpers/project-mocks*', rootDir)).to.eql([
|
expect(pathsArrayFromCs('test-helpers/project-mocks*', rootDir)).to.eql([
|
||||||
`${process.cwd()}/test-helpers/project-mocks`,
|
`${rootDir}/test-helpers/project-mocks`,
|
||||||
`${process.cwd()}/test-helpers/project-mocks-analyzer-outputs`,
|
`${rootDir}/test-helpers/project-mocks-analyzer-outputs`,
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('allows multiple comma separated paths', async () => {
|
||||||
|
const paths =
|
||||||
|
'test-helpers/project-mocks*, ./test-helpers/project-mocks/importing-target-project,/mocked/path/example-project';
|
||||||
|
expect(pathsArrayFromCs(paths, rootDir)).to.eql([
|
||||||
|
`${rootDir}/test-helpers/project-mocks`,
|
||||||
|
`${rootDir}/test-helpers/project-mocks-analyzer-outputs`,
|
||||||
|
`${rootDir}/test-helpers/project-mocks/importing-target-project`,
|
||||||
|
'/mocked/path/example-project',
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('pathsArrayFromCollectionName', () => {
|
||||||
|
it('gets collections from external target config', async () => {
|
||||||
|
expect(
|
||||||
|
pathsArrayFromCollectionName('lion-collection', 'search-target', externalCfgMock, rootDir),
|
||||||
|
).to.eql(
|
||||||
|
externalCfgMock.searchTargetCollections['lion-collection'].map(p =>
|
||||||
|
pathLib.join(rootDir, p),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('gets collections from external reference config', async () => {
|
||||||
|
expect(
|
||||||
|
pathsArrayFromCollectionName(
|
||||||
|
'lion-based-ui-collection',
|
||||||
|
'reference',
|
||||||
|
externalCfgMock,
|
||||||
|
rootDir,
|
||||||
|
),
|
||||||
|
).to.eql(
|
||||||
|
externalCfgMock.referenceCollections['lion-based-ui-collection'].map(p =>
|
||||||
|
pathLib.join(rootDir, p),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('appendProjectDependencyPaths', () => {
|
||||||
|
before(() => {
|
||||||
|
mockWriteToJson(queryResults);
|
||||||
|
suppressNonCriticalLogs();
|
||||||
|
|
||||||
|
mockProject(
|
||||||
|
{
|
||||||
|
'./src/OriginalComp.js': `export class OriginalComp {}`,
|
||||||
|
'./src/inbetween.js': `export { OriginalComp as InBetweenComp } from './OriginalComp.js'`,
|
||||||
|
'./index.js': `export { InBetweenComp as MyComp } from './src/inbetween.js'`,
|
||||||
|
'./node_modules/dependency-a/index.js': '',
|
||||||
|
'./bower_components/dependency-b/index.js': '',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
projectName: 'example-project',
|
||||||
|
projectPath: '/mocked/path/example-project',
|
||||||
|
},
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('adds bower and node dependencies', async () => {
|
||||||
|
const result = await appendProjectDependencyPaths(['/mocked/path/example-project']);
|
||||||
|
expect(result).to.eql([
|
||||||
|
'/mocked/path/example-project/node_modules/dependency-a',
|
||||||
|
'/mocked/path/example-project/bower_components/dependency-b',
|
||||||
|
'/mocked/path/example-project',
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('allows a regex filter', async () => {
|
||||||
|
const result = await appendProjectDependencyPaths(['/mocked/path/example-project'], '/b$/');
|
||||||
|
expect(result).to.eql([
|
||||||
|
'/mocked/path/example-project/bower_components/dependency-b',
|
||||||
|
'/mocked/path/example-project',
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('allows to filter out only npm or bower deps', async () => {
|
||||||
|
const result = await appendProjectDependencyPaths(['/mocked/path/example-project'], null, [
|
||||||
|
'npm',
|
||||||
|
]);
|
||||||
|
expect(result).to.eql([
|
||||||
|
'/mocked/path/example-project/node_modules/dependency-a',
|
||||||
|
'/mocked/path/example-project',
|
||||||
|
]);
|
||||||
|
|
||||||
|
const result2 = await appendProjectDependencyPaths(['/mocked/path/example-project'], null, [
|
||||||
|
'bower',
|
||||||
|
]);
|
||||||
|
expect(result2).to.eql([
|
||||||
|
'/mocked/path/example-project/bower_components/dependency-b',
|
||||||
|
'/mocked/path/example-project',
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -312,17 +312,18 @@ describe('Analyzer "match-imports"', () => {
|
||||||
describe('Configuration', () => {
|
describe('Configuration', () => {
|
||||||
it(`allows to provide results of FindExportsAnalyzer and FindImportsAnalyzer`, async () => {
|
it(`allows to provide results of FindExportsAnalyzer and FindImportsAnalyzer`, async () => {
|
||||||
mockTargetAndReferenceProject(searchTargetProject, referenceProject);
|
mockTargetAndReferenceProject(searchTargetProject, referenceProject);
|
||||||
const importsAnalyzerResult = await new FindImportsAnalyzer().execute({
|
const findImportsResult = await new FindImportsAnalyzer().execute({
|
||||||
targetProjectPath: searchTargetProject.path,
|
targetProjectPath: searchTargetProject.path,
|
||||||
});
|
});
|
||||||
const exportsAnalyzerResult = await new FindExportsAnalyzer().execute({
|
const findExportsResult = await new FindExportsAnalyzer().execute({
|
||||||
targetProjectPath: referenceProject.path,
|
targetProjectPath: referenceProject.path,
|
||||||
});
|
});
|
||||||
await providence(matchImportsQueryConfig, {
|
|
||||||
..._providenceCfg,
|
const matchImportsQueryConfigExt = QueryService.getQueryConfigFromAnalyzer('match-imports', {
|
||||||
importsAnalyzerResult,
|
targetProjectResult: findImportsResult,
|
||||||
exportsAnalyzerResult,
|
referenceProjectResult: findExportsResult,
|
||||||
});
|
});
|
||||||
|
await providence(matchImportsQueryConfigExt, _providenceCfg);
|
||||||
const queryResult = queryResults[0];
|
const queryResult = queryResults[0];
|
||||||
|
|
||||||
expectedExportIdsDirect.forEach(targetId => {
|
expectedExportIdsDirect.forEach(targetId => {
|
||||||
|
|
@ -333,5 +334,8 @@ describe('Analyzer "match-imports"', () => {
|
||||||
testMatchedEntry(targetId, queryResult, ['./target-src/indirect-imports.js']);
|
testMatchedEntry(targetId, queryResult, ['./target-src/indirect-imports.js']);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// TODO: Test this unwind functionality in a generic MatchAnalyzer test
|
||||||
|
it.skip(`allows to provide results of FindExportsAnalyzer and FindImportsAnalyzer from external jsons`, async () => {});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -118,7 +118,7 @@ describe('InputDataService', () => {
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('allows passing excludeFolders', async () => {
|
it('allows passing excluded folders', async () => {
|
||||||
const globOutput = InputDataService.gatherFilesFromDir('/fictional/project', {
|
const globOutput = InputDataService.gatherFilesFromDir('/fictional/project', {
|
||||||
extensions: ['.html', '.js'],
|
extensions: ['.html', '.js'],
|
||||||
filter: ['!nested/**'],
|
filter: ['!nested/**'],
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue