@actualwave/traceability-matrices
Advanced tools
Comparing version 1.0.2 to 1.0.3
82
cli.js
@@ -38,29 +38,34 @@ #!/usr/bin/env node | ||
let targetDirs = args["target-dir"] || []; | ||
// validate target first, must be at least one, all must be dirs | ||
const exitWithError = (message) => { | ||
console.error(message); | ||
process.exit(1); | ||
}; | ||
const getFullDirPaths = (dirs) => | ||
dirs.map((target) => { | ||
const fullPath = path.resolve(process.cwd(), String(target)); | ||
if (!targetDirs.length) { | ||
exitWithError( | ||
"No target directories were provided, please use --target-dir argument to specify at least one target directory." | ||
); | ||
} | ||
if (!fullPath) { | ||
exitWithError(`Path "${target}" could not be resolved.`); | ||
} | ||
targetDirs = targetDirs.map((target) => { | ||
const fullPath = path.resolve(process.cwd(), String(target)); | ||
if (!fs.existsSync(fullPath)) { | ||
exitWithError(`Directory "${fullPath}" does not exist.`); | ||
} | ||
if (!fullPath) { | ||
exitWithError(`Path "${target}" could not be resolved.`); | ||
} | ||
return fullPath; | ||
}); | ||
if (!fs.existsSync(fullPath)) { | ||
exitWithError(`Target directory "${fullPath}" does not exist.`); | ||
// validate targets, must be at least one, all must be dirs | ||
const validateTargetDirs = () => { | ||
if (!targetDirs.length) { | ||
exitWithError( | ||
"No target directories were provided, please use --target-dir argument to specify at least one target directory." | ||
); | ||
} | ||
}; | ||
return fullPath; | ||
}); | ||
const exitWithError = (message) => { | ||
console.error(message); | ||
process.exit(1); | ||
}; | ||
let targetDirs = args["target-dir"] || []; | ||
targetDirs = getFullDirPaths(targetDirs); | ||
// TM char codes 84 and 77 | ||
@@ -81,2 +86,3 @@ const DEFAULT_PORT = 8477; | ||
*/ | ||
validateTargetDirs(); | ||
const port = args.port ? parseInt(String(args.port), 10) : DEFAULT_PORT; | ||
@@ -145,2 +151,3 @@ let keyFilePath = (args.key || [])[0]; | ||
*/ | ||
validateTargetDirs(); | ||
const outputDir = path.resolve(process.cwd(), String(args["output-dir"])); | ||
@@ -170,2 +177,3 @@ | ||
*/ | ||
validateTargetDirs(); | ||
const outputDir = path.resolve(process.cwd(), String(args["output-dir"])); | ||
@@ -196,3 +204,6 @@ | ||
{ | ||
// threshold --target-dir= --total=80 --per-feature=40 | ||
/** | ||
* threshold --target-dir= --total=80 --per-feature=40 | ||
*/ | ||
validateTargetDirs(); | ||
const total = | ||
@@ -218,4 +229,6 @@ args["total"] === undefined ? 100 : parseInt(args["total"], 10); | ||
{ | ||
// stats --target-dir= --feature= | ||
/** | ||
* stats --target-dir= --feature= | ||
*/ | ||
validateTargetDirs(); | ||
const features = args["feature"] || []; | ||
@@ -228,5 +241,26 @@ | ||
break; | ||
case "scan": | ||
{ | ||
/** | ||
* Scan features dirs for any feature descriptions and store in target dir where all coverage reports. | ||
* scan --features-dir= --target-dir= | ||
*/ | ||
validateTargetDirs(); | ||
const featureDirs = getFullDirPaths(args["features-dir"] || []); | ||
const { scanFeatures } = require("./commands/scan_features.js"); | ||
scanFeatures(featureDirs, targetDirs[0]); | ||
} | ||
break; | ||
case "help": | ||
// TODO | ||
/** | ||
* help --command= | ||
*/ | ||
const command = args["command"]?.[0] || ""; | ||
const { help } = require("./commands/help.js"); | ||
help(command); | ||
break; | ||
} |
@@ -6,4 +6,4 @@ 'use strict'; | ||
var node_fs = require('node:fs'); | ||
var reader = require('./reader-7e5e7d4d.js'); | ||
var page = require('./page-d820c606.js'); | ||
var reader = require('./reader-80380299.js'); | ||
var page = require('./page-23c65ba5.js'); | ||
var feature = require('./feature-22b67915.js'); | ||
@@ -10,0 +10,0 @@ var totals = require('./totals-a51b16ec.js'); |
@@ -6,3 +6,3 @@ 'use strict'; | ||
var fs = require('node:fs/promises'); | ||
var reader = require('./reader-7e5e7d4d.js'); | ||
var reader = require('./reader-80380299.js'); | ||
var feature = require('./feature-22b67915.js'); | ||
@@ -12,2 +12,19 @@ require('pug'); | ||
const stripTags = (text) => text.replace(/[,\r\n\s]+/gi, " ").replace(/<\/?a-z[^>]+>/gi, ""); | ||
/* | ||
TN:<test name> usually empty | ||
SF:<absolute path to the source file> | ||
FN:<line number of function start>,<function name> | ||
FNDA:<execution count>,<function name> | ||
FNF:<number of functions found> | ||
FNH:<number of function hit> | ||
BRDA:<line number>,<block number>,<branch number>,<taken> | ||
BRF:<number of branches found> | ||
BRH:<number of branches hit> | ||
DA:<line number>,<execution count> | ||
LH:<number of lines with a non-zero execution count> | ||
LF:<number of instrumented lines> | ||
end_of_record | ||
Reference https://xujihui1985.github.io/test/2015/10/06/lcovinfo | ||
*/ | ||
const generateFeatureLcovContent = (feature$1, relativeDir, info = feature.buildVerticalHeaders(feature$1)) => { | ||
@@ -34,3 +51,3 @@ let lineNumber = 2; | ||
// lines -- only requirements | ||
const da = []; // [`DA:${info.requirementsCovered},${lineNumber}`]; -- cover feature title | ||
const da = []; // [`DA:${lineNumber},${info.requirementsCovered}`]; -- cover feature title | ||
let lh = info.requirementsCovered ? 1 : 0; | ||
@@ -54,3 +71,3 @@ info.rows.forEach((row) => { | ||
// line | ||
da.push(`DA:${cell.requirementsCovered},${lineNumber}`); | ||
da.push(`DA:${lineNumber},${cell.requirementsCovered}`); | ||
lh += cell.requirementsCovered ? 1 : 0; | ||
@@ -57,0 +74,0 @@ }); |
@@ -8,4 +8,4 @@ 'use strict'; | ||
require('node:fs/promises'); | ||
var reader = require('./reader-7e5e7d4d.js'); | ||
var page = require('./page-d820c606.js'); | ||
var reader = require('./reader-80380299.js'); | ||
var page = require('./page-23c65ba5.js'); | ||
var feature = require('./feature-22b67915.js'); | ||
@@ -12,0 +12,0 @@ var totals = require('./totals-a51b16ec.js'); |
'use strict'; | ||
require('node:fs/promises'); | ||
var reader = require('./reader-7e5e7d4d.js'); | ||
var reader = require('./reader-80380299.js'); | ||
var feature = require('./feature-22b67915.js'); | ||
@@ -6,0 +6,0 @@ require('node:path'); |
'use strict'; | ||
require('node:fs/promises'); | ||
var reader = require('./reader-7e5e7d4d.js'); | ||
var reader = require('./reader-80380299.js'); | ||
var totals = require('./totals-a51b16ec.js'); | ||
@@ -6,0 +6,0 @@ require('node:path'); |
@@ -0,1 +1,3 @@ | ||
import { createCategoryApi, createRequirementApi, createTraceFn } from "./records"; | ||
import { createHeadersApi, createStructureApi } from "./structure"; | ||
import { Feature, MatcherFn } from "./types"; | ||
@@ -18,99 +20,20 @@ export type CreateFeatureParams = { | ||
export declare const createEmptyFeatureState: ({ title, group, description, }: CreateFeatureParams) => Feature; | ||
export declare const wrapFeatureState: (feature: Feature) => { | ||
clone: (params: CreateFeatureParams) => any; | ||
branch: (params: CreateFeatureParams & { | ||
path: string[]; | ||
}) => any; | ||
narrow: (params: CreateFeatureParams & { | ||
path: string[]; | ||
}) => any; | ||
export type FeatureApi = { | ||
valueOf: () => Feature; | ||
structure: (data?: object, columnHeaders?: string[]) => { | ||
add: (...path: string[]) => object; | ||
get: (...path: string[]) => object; | ||
merge: (struct: object) => void; | ||
clone: () => object; | ||
branch: (path: string[]) => object; | ||
narrow: (path: string[]) => {}; | ||
}; | ||
headers: (columnHeaders?: string[]) => { | ||
clone: () => string[]; | ||
get: (index: number) => string; | ||
set: (index: number, header: string) => void; | ||
}; | ||
category: (nameOrFn: string | import("./records").CategoryPathFn, ...path: string[]) => { | ||
category: any; | ||
requirement: (...namePath: string[] | [import("./records").RequirementPathFn]) => { | ||
describe: (...args: [string, () => void] | [string, object, () => void]) => void; | ||
context: (...args: [string, () => void] | [string, object, () => void]) => void; | ||
suite: (...args: [string, () => void] | [string, object, () => void]) => void; | ||
it: (name: string, callback: () => void) => void; | ||
specify: (name: string, callback: () => void) => void; | ||
test: (name: string, callback: () => void) => void; | ||
trace: (chainFn?: () => void) => void; | ||
}; | ||
trace: (namePath: string | string[] | import("./records").RequirementPathFn, chainFn?: () => void) => void; | ||
setTraceToRequirementMatcher: (matcher: MatcherFn) => void; | ||
}; | ||
requirement: (...namePath: string[] | [import("./records").RequirementPathFn]) => { | ||
describe: (...args: [string, () => void] | [string, object, () => void]) => void; | ||
context: (...args: [string, () => void] | [string, object, () => void]) => void; | ||
suite: (...args: [string, () => void] | [string, object, () => void]) => void; | ||
it: (name: string, callback: () => void) => void; | ||
specify: (name: string, callback: () => void) => void; | ||
test: (name: string, callback: () => void) => void; | ||
trace: (chainFn?: () => void) => void; | ||
}; | ||
trace: (namePath: string | string[] | import("./records").RequirementPathFn, chainFn?: () => void) => void; | ||
structure: ReturnType<typeof createStructureApi>; | ||
headers: ReturnType<typeof createHeadersApi>; | ||
category: ReturnType<typeof createCategoryApi>; | ||
requirement: ReturnType<typeof createRequirementApi>; | ||
trace: ReturnType<typeof createTraceFn>; | ||
setTraceToRequirementMatcher: (matcher: MatcherFn) => void; | ||
}; | ||
export type FeatureApi = ReturnType<typeof wrapFeatureState>; | ||
export declare const registerFeature: (feature: Feature | FeatureApi) => number; | ||
export declare const createFeature: (params: CreateFeatureParams) => { | ||
clone: (params: CreateFeatureParams) => any; | ||
clone: (params: CreateFeatureParams) => FeatureApi; | ||
branch: (params: CreateFeatureParams & { | ||
path: string[]; | ||
}) => any; | ||
}) => FeatureApi; | ||
narrow: (params: CreateFeatureParams & { | ||
path: string[]; | ||
}) => any; | ||
valueOf: () => Feature; | ||
structure: (data?: object, columnHeaders?: string[]) => { | ||
add: (...path: string[]) => object; | ||
get: (...path: string[]) => object; | ||
merge: (struct: object) => void; | ||
clone: () => object; | ||
branch: (path: string[]) => object; | ||
narrow: (path: string[]) => {}; | ||
}; | ||
headers: (columnHeaders?: string[]) => { | ||
clone: () => string[]; | ||
get: (index: number) => string; | ||
set: (index: number, header: string) => void; | ||
}; | ||
category: (nameOrFn: string | import("./records").CategoryPathFn, ...path: string[]) => { | ||
category: any; | ||
requirement: (...namePath: string[] | [import("./records").RequirementPathFn]) => { | ||
describe: (...args: [string, () => void] | [string, object, () => void]) => void; | ||
context: (...args: [string, () => void] | [string, object, () => void]) => void; | ||
suite: (...args: [string, () => void] | [string, object, () => void]) => void; | ||
it: (name: string, callback: () => void) => void; | ||
specify: (name: string, callback: () => void) => void; | ||
test: (name: string, callback: () => void) => void; | ||
trace: (chainFn?: () => void) => void; | ||
}; | ||
trace: (namePath: string | string[] | import("./records").RequirementPathFn, chainFn?: () => void) => void; | ||
setTraceToRequirementMatcher: (matcher: MatcherFn) => void; | ||
}; | ||
requirement: (...namePath: string[] | [import("./records").RequirementPathFn]) => { | ||
describe: (...args: [string, () => void] | [string, object, () => void]) => void; | ||
context: (...args: [string, () => void] | [string, object, () => void]) => void; | ||
suite: (...args: [string, () => void] | [string, object, () => void]) => void; | ||
it: (name: string, callback: () => void) => void; | ||
specify: (name: string, callback: () => void) => void; | ||
test: (name: string, callback: () => void) => void; | ||
trace: (chainFn?: () => void) => void; | ||
}; | ||
trace: (namePath: string | string[] | import("./records").RequirementPathFn, chainFn?: () => void) => void; | ||
setTraceToRequirementMatcher: (matcher: MatcherFn) => void; | ||
}) => FeatureApi; | ||
}; | ||
export declare const wrapFeatureState: (feature: Feature) => FeatureApi; | ||
export declare const registerFeature: (feature: Feature | FeatureApi) => number; | ||
export declare const createFeature: (params: CreateFeatureParams) => FeatureApi; |
@@ -1,2 +0,2 @@ | ||
import { createEmptyFeatureState, registerFeature, wrapFeatureState, createFeature } from '@actualwave/traceability-matrices/cypress'; | ||
import { createEmptyFeatureState, registerFeature, wrapFeatureState, createFeature } from './cypress'; | ||
@@ -3,0 +3,0 @@ // somehow "node instanceof Array" may give FALSE for parsed arrays |
{ | ||
"name": "@actualwave/traceability-matrices", | ||
"version": "1.0.2", | ||
"version": "1.0.3", | ||
"types": "cypress.d.ts", | ||
@@ -5,0 +5,0 @@ "bin": { |
@@ -89,6 +89,6 @@ # @actualwave/traceability-matrices | ||
- `--target-dir` - required, path to directory with coverage reports | ||
- `--port` - port for HTTP/S server, 8477 by default | ||
- `--key` and `--cert` - should point at private key and signed certificate files to start HTTPS server, by default starts HTTP server | ||
- `--compact` - optional, uses [compact variant of HTML table](https://burdiuz.github.io/traceability-matrices/generated_coverage_compact/features/Records-_-Category.html), categories displayed as rows instead of columns. Default value is false. Might be preferable way of rendering features with deep structures. | ||
- `--target-dir` - Required, path to directory with coverage reports | ||
- `--port` - Port for HTTP/S server, 8477 by default | ||
- `--key` and `--cert` - Should point at private key and signed certificate files to start HTTPS server, by default starts HTTP server | ||
- `--compact` - Optional, uses [compact variant of HTML table](https://burdiuz.github.io/traceability-matrices/generated_coverage_compact/features/Records-_-Category.html), categories displayed as rows instead of columns. Default value is false. Might be preferable way of rendering features with deep structures. | ||
@@ -114,6 +114,6 @@ Example: | ||
- `--target-dir` - required, path to directory with coverage reports. | ||
- `--output-dir` - required, path to folder where generated HTML files should be stored | ||
- `--compact=true` - optional, uses [compact variant of HTML table](https://burdiuz.github.io/traceability-matrices/generated_coverage_compact/features/Records-_-Category.html), categories displayed as rows instead of columns. Default value is false. Might be preferable way of rendering features with deep structures. | ||
- `--force-cleanup=true` - will remove all contents of output folder before generating new content. | ||
- `--target-dir` - Required, path to directory with coverage reports. | ||
- `--output-dir` - Required, path to folder where generated HTML files should be stored | ||
- `--compact=true` - Optional, uses [compact variant of HTML table](https://burdiuz.github.io/traceability-matrices/generated_coverage_compact/features/Records-_-Category.html), categories displayed as rows instead of columns. Default value is false. Might be preferable way of rendering features with deep structures. | ||
- `--force-cleanup=true` - Will remove all contents of output folder before generating new content. | ||
@@ -131,5 +131,5 @@ Example: | ||
- `--target-dir` - required, path to directory with coverage reports. | ||
- `--total` - optional, defines global coverage threshold, value can be between 0 and 100. Fails command if combined coverage of all features does not meet threshold. | ||
- `--per-feature` - optional, defines coverage threshold applied to each feature, value can be between 0 and 100. Fails command if at least one feature does not meet threshold. | ||
- `--target-dir` - Required, path to directory with coverage reports. | ||
- `--total` - Optional, defines global coverage threshold, value can be between 0 and 100. Fails command if combined coverage of all features does not meet threshold. | ||
- `--per-feature` - Optional, defines coverage threshold applied to each feature, value can be between 0 and 100. Fails command if at least one feature does not meet threshold. | ||
@@ -150,3 +150,3 @@ Example: | ||
- `--target-dir` - required, path to directory with coverage reports. | ||
- `--target-dir` - Required, path to directory with coverage reports. | ||
@@ -167,6 +167,6 @@ Example: | ||
- `--target-dir` | ||
- `--target-dir` - Required, path to directory with coverage reports. | ||
- `--output-dir` - Folder where to store LCOV coverage information and generated "source" files which can be used as a reference coverage reading tools. | ||
- `--relative-dir` - used to prepend file paths in coverage reports. By default recorded path to genrated sources will be `lcov/*`. | ||
- `--force-cleanup=true` - will remove all contents of output folder before generating new content. | ||
- `--relative-dir` - Used to prepend file paths in coverage reports. By default recorded path to genrated sources will be `lcov/*`. | ||
- `--force-cleanup=true` - Will remove all contents of output folder before generating new content. | ||
@@ -190,2 +190,18 @@ Example: | ||
### traceability-matrices scan | ||
Searches provided directories for supported feature files and creates report in target dir. Created report is a hidden coverage report with no coverage, this way all found features will be added to report even if they weren't used in tests. | ||
Parameters: | ||
- `--features-dir` - Required, path to a directory with feature files, can be added multiple times if features stored in different folders. Sub-directories will also be scanned recursively. | ||
- `--target-dir` - Required, path to a directory with coverage reports. | ||
Example: | ||
``` | ||
traceability-matrices scan --features-dir=./cypress/features --target-dir=coverage | ||
``` | ||
## Cypress integration | ||
@@ -192,0 +208,0 @@ |
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Obfuscated code
Supply chain riskObfuscated files are intentionally packed to hide their behavior. This could be a sign of malware.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
4769400
107
81834
960
2
10
32