@actualwave/traceability-matrices
Advanced tools
Comparing version 0.0.10 to 0.0.11
72
cli.js
@@ -68,2 +68,8 @@ #!/usr/bin/env node | ||
let projectTableType = "default"; | ||
if (String(args.compact) === "true") { | ||
projectTableType = "compact"; | ||
} | ||
switch (command) { | ||
@@ -73,3 +79,3 @@ case "serve": | ||
/** | ||
* serve --target-dir= --port= --https=true | ||
* serve --target-dir= --port= --https=true --compact=true | ||
*/ | ||
@@ -85,3 +91,3 @@ const port = args.port ? parseInt(String(args.port), 10) : DEFAULT_PORT; | ||
serve(targetDirs, port, useHttps).then(() => { | ||
serve(targetDirs, port, useHttps, projectTableType).then(() => { | ||
import("open").then(({ default: open }) => | ||
@@ -98,3 +104,3 @@ open( | ||
/** | ||
* generate --target-dir= --output-dir= | ||
* generate --target-dir= --output-dir= --compact=true | ||
*/ | ||
@@ -117,35 +123,35 @@ const outputDir = path.resolve(process.cwd(), String(args["output-dir"])); | ||
generateStatic(targetDirs, outputDir); | ||
generateStatic(targetDirs, outputDir, projectTableType); | ||
} | ||
break; | ||
case "threshold": | ||
{ | ||
// threshold --target-dir= --total=80 --per-project=40 | ||
const total = | ||
args["total"] === undefined ? 100 : parseInt(args["total"], 10); | ||
const perProject = | ||
args["per-project"] === undefined | ||
? 100 | ||
: parseInt(args["per-project"], 10); | ||
if (isNaN(total) || isNaN(perProject)) { | ||
exitWithError( | ||
"Coverage thresholds should be positive integer values between 0 and 100." | ||
); | ||
} | ||
const { threshold } = require("./commands/threshold.js"); | ||
threshold(targetDirs, total, perProject); | ||
case "threshold": | ||
{ | ||
// threshold --target-dir= --total=80 --per-project=40 | ||
const total = | ||
args["total"] === undefined ? 100 : parseInt(args["total"], 10); | ||
const perProject = | ||
args["per-project"] === undefined | ||
? 100 | ||
: parseInt(args["per-project"], 10); | ||
if (isNaN(total) || isNaN(perProject)) { | ||
exitWithError( | ||
"Coverage thresholds should be positive integer values between 0 and 100." | ||
); | ||
} | ||
break; | ||
case "stats": | ||
{ | ||
// stats --target-dir= | ||
const { stats } = require("./commands/stats.js"); | ||
stats(targetDirs); | ||
} | ||
break; | ||
const { threshold } = require("./commands/threshold.js"); | ||
threshold(targetDirs, total, perProject); | ||
} | ||
break; | ||
case "stats": | ||
{ | ||
// stats --target-dir= | ||
const { stats } = require("./commands/stats.js"); | ||
stats(targetDirs); | ||
} | ||
break; | ||
case "help": | ||
@@ -152,0 +158,0 @@ // TODO |
@@ -40,3 +40,3 @@ const { writeFile } = require("fs/promises"); | ||
const generateStatic = async (targetDirs, outputDir) => { | ||
const generateStatic = async (targetDirs, outputDir, projectTableType) => { | ||
const state = await readCoverage(targetDirs); | ||
@@ -59,3 +59,3 @@ const totals = calculateTotals(state); | ||
filePath, | ||
(state, links) => renderFile(file, state, links) | ||
(state, links) => renderFile(file, state, links, projectTableType) | ||
) | ||
@@ -80,3 +80,3 @@ ) | ||
projectTitle, | ||
(state, links) => renderProject(project, state, links) | ||
(state, links) => renderProject(project, state, links, projectTableType) | ||
) | ||
@@ -83,0 +83,0 @@ ) |
@@ -24,3 +24,3 @@ const Koa = require("koa"); | ||
const serve = async (targetDirs, port, useHttps = true) => { | ||
const serve = async (targetDirs, port, useHttps = true, projectTableType = 'default') => { | ||
let state = await readCoverage(targetDirs); | ||
@@ -59,3 +59,3 @@ let totals = calculateTotals(state); | ||
const content = renderFile(file, state, links); | ||
const content = renderFile(file, state, links, projectTableType); | ||
@@ -93,3 +93,3 @@ ctx.response.body = pageTemplate({ | ||
const content = renderProject(project, state, links); | ||
const content = renderProject(project, state, links, projectTableType); | ||
@@ -96,0 +96,0 @@ ctx.response.body = pageTemplate({ |
{ | ||
"name": "@actualwave/traceability-matrices", | ||
"version": "0.0.10", | ||
"version": "0.0.11", | ||
"types": "cypress.d.ts", | ||
@@ -5,0 +5,0 @@ "bin": { |
# @actualwave/traceability-matrices | ||
Integrate requirements into e2e/integration test code and generate traceability matrices for your project. Currently this project has an adapter to work with [Cypress](https://www.cypress.io/) tests. | ||
@@ -64,2 +65,3 @@ | ||
``` | ||
calling `npm run tm:serve` will start local HTTP server with coveragereports and `npm run tm:generate` will generate HTML reports into `xcoverage-static` folder. | ||
@@ -79,2 +81,3 @@ | ||
- `--https` - set to "true"(`--https=true`) to start HTTPS server, by default starts HTTP server | ||
- `--compact` - optional, uses compact variant of HTML table, categories displayed as rows instead of columns. Default value is false. Might be preferable way of rendering projects with deep structures. | ||
@@ -84,3 +87,3 @@ Example: | ||
``` | ||
traceability-matrices serve --target-dir=cypress/coverage --https=true | ||
traceability-matrices serve --target-dir=cypress/coverage --https=true --compact=true | ||
``` | ||
@@ -95,2 +98,3 @@ | ||
- `--output-dir` - required, path to folder where generated HTML files should be stored | ||
- `--compact` - optional, uses compact variant of HTML table, categories displayed as rows instead of columns. Default value is false. Might be preferable way of rendering projects with deep structures. | ||
@@ -119,2 +123,3 @@ Example: | ||
### traceability-matrices stats | ||
Outputs coverage information per project with requirements. | ||
@@ -151,9 +156,14 @@ | ||
``` | ||
`createProject(projectTitle: string, projectDescription?: string)` accepts project title and optionally description. Project titles must be unique strings. Project description could be an HTML string, it will display on top of project coverage table and is suitable for placing various project links and other useful information. | ||
```ts | ||
import { createProject } from "@actualwave/traceability-matrices/cypress"; | ||
const project = createProject("My Project", ` | ||
const project = createProject( | ||
"My Project", | ||
` | ||
<h1>Useful information</1> | ||
<a href="https://react.dev/">Learn React</a>`); | ||
<a href="https://react.dev/">Learn React</a>` | ||
); | ||
``` | ||
@@ -176,2 +186,3 @@ | ||
``` | ||
> Note: To properly match requirement string with project structure requirement must be a unique string within its project. | ||
@@ -263,2 +274,4 @@ | ||
Without structure containing all project requirements it will have 100% coverage because there will be only requirements added from traces placed in specs(which are already marked as covered). Having structure with all project requirements allows proper coverage calculation. For coverage calculation it does not matter(purely visual benefit) if structure is flat or organised into categories. | ||
> Note: Categories(branches, not leaf nodes) in such structure could contain HTML markup. Using HTML markup in requirement string is also possible, it will be properly rendered but might be uncomfortable to use in test specs. | ||
@@ -305,16 +318,20 @@ | ||
``` | ||
With structure tree optionally list of table headers could be provided, they will be used to render HTML table in the report | ||
```js | ||
project.structure({ | ||
High: { | ||
General: { | ||
"PRD I": { | ||
"requirement #1": {}, | ||
"requirement #2": {}, | ||
"requirement #3": {}, | ||
project.structure( | ||
{ | ||
High: { | ||
General: { | ||
"PRD I": { | ||
"requirement #1": {}, | ||
"requirement #2": {}, | ||
"requirement #3": {}, | ||
}, | ||
}, | ||
}, | ||
}, | ||
}, ['Priority', 'Category', 'Requirement']); | ||
["Priority", "Category", "Requirement"] | ||
); | ||
``` | ||
@@ -335,3 +352,3 @@ | ||
Allows to specify list of HTML table headers | ||
Allows to specify list of HTML table headers. In compact mode only last header is used. | ||
@@ -344,2 +361,2 @@ ### project.clone() | ||
Returns internal state of the project | ||
Returns internal state of the project |
@@ -7,5 +7,5 @@ const { renderProject } = require("./project"); | ||
*/ | ||
const renderFile = (file, state, links) => { | ||
const renderFile = (file, state, links, projectTableType) => { | ||
const list = Object.values(file.projects).map((source) => { | ||
return renderProject(source, state, links); | ||
return renderProject(source, state, links, projectTableType); | ||
}); | ||
@@ -12,0 +12,0 @@ |
@@ -47,2 +47,48 @@ const { basename } = require("path"); | ||
const projectCompactTemplate = compile( | ||
` | ||
table.project.compact | ||
if self.projectDescription | ||
tr | ||
td.project-description(colspan=self.totalSpecCount + 2) !{self.projectDescription} | ||
//- Header Rows | ||
tr.file-headers | ||
th.project-title(colspan=1, rowspan=self.projectHeaders.length ? 1 : 2) #{self.projectTitle} (#{self.coveredRequirements} / #{self.totalRequirements}) | ||
th.spec-count(rowspan='2') Spec count | ||
each file in self.fileHeaders | ||
th.file-name(colspan=file.colspan, title=file.title) #{file.name} | ||
tr.specs-headers | ||
if self.projectHeaders.length | ||
- var header = self.projectHeaders[self.projectHeaders.length - 1]; | ||
th.header(title=header) #{header} | ||
each spec in self.specHeaders | ||
th.spec-name(title=spec.title) | ||
span.spec-name-text #{spec.name} | ||
//- Data Rows | ||
each row, index in self.dataRows | ||
- var dataHeaderCols = self.dataHeaderRows[index]; | ||
each dataHeader, headerIndex in dataHeaderCols | ||
if headerIndex < dataHeaderCols.length - 1 | ||
tr.category-row | ||
th(colspan=self.totalSpecCount + 2, class=\`category category-level-\${dataHeader.depth} \${dataHeader.class || ''}\`, title=dataHeader.title) | ||
span.category-text !{dataHeader.name} | ||
else | ||
tr(class=\`result \${row.class}\`) | ||
th(colspan=1, rowspan=1, class=\`requirement requirement-compact requirement-level-\${dataHeader.depth} \${dataHeader.class || ''}\`, title=dataHeader.title) | ||
span.requirement-text !{dataHeader.name} | ||
each data in row.cells | ||
td(title=data.title, class=\`cell \${data.class || ''}\`) | ||
span.cell-text #{data.name} | ||
//- Totals | ||
tr.totals | ||
td Project Coverage | ||
td(colspan=self.totalSpecCount + 1) #{self.coveredRequirements} / #{self.totalRequirements} | ||
`, | ||
{ self: true } | ||
); | ||
/** | ||
@@ -133,2 +179,3 @@ * | ||
name: requirement.title, | ||
depth, | ||
@@ -224,3 +271,3 @@ // if title contains HTML -- strip tags | ||
*/ | ||
const renderProject = (project, state, links) => { | ||
const renderProject = (project, state, links, type) => { | ||
/* | ||
@@ -244,3 +291,5 @@ * build headers | ||
const tableHtml = projectTableTemplate({ | ||
const renderer = type === 'compact' ? projectCompactTemplate : projectTableTemplate; | ||
const tableHtml = renderer({ | ||
// +1 for spec counts column | ||
@@ -247,0 +296,0 @@ requirementsDepth: project.depth, |
Sorry, the diff of this file is not supported yet
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
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
66420
1644
352