jest-md-dashboard
Advanced tools
Comparing version
# Changelog | ||
## [0.5.0](https://github.com/mshrtsr/jest-md-dashboard/compare/jest-md-dashboard-v0.4.0...jest-md-dashboard-v0.5.0) (2022-07-03) | ||
### ⚠ BREAKING CHANGES | ||
* remove `permalink` option and add `permalinkBaseUrl` (#37) | ||
* output to file by default (#34) | ||
### Features | ||
* output to file by default ([#34](https://github.com/mshrtsr/jest-md-dashboard/issues/34)) ([ed723bf](https://github.com/mshrtsr/jest-md-dashboard/commit/ed723bff813227b43290c2b15f2a6b3160f3054d)) | ||
* remove `permalink` option and add `permalinkBaseUrl` ([#37](https://github.com/mshrtsr/jest-md-dashboard/issues/37)) ([a9fdceb](https://github.com/mshrtsr/jest-md-dashboard/commit/a9fdceb40fd76d12287e9c7181bafa6493f64684)) | ||
### Bug Fixes | ||
* change default dashboard title ([dc5d2cd](https://github.com/mshrtsr/jest-md-dashboard/commit/dc5d2cd47c0d9a4b30baf1cb37d3ae8c0191f066)) | ||
## [0.4.0](https://github.com/mshrtsr/jest-md-dashboard/compare/jest-md-dashboard-v0.3.1...jest-md-dashboard-v0.4.0) (2022-06-29) | ||
@@ -4,0 +22,0 @@ |
import { AggregatedResult } from "@jest/test-result"; | ||
import { Dashboard } from "./types.js"; | ||
export declare type Permalink = { | ||
hostname: string; | ||
repository: string; | ||
commit: string; | ||
pattern: string; | ||
}; | ||
export declare const convertResultsToDashboard: (results: AggregatedResult, options: { | ||
title: string; | ||
rootPath: string; | ||
permalink?: Permalink; | ||
jestRootDir: string; | ||
permalinkBaseUrl?: string; | ||
}) => Dashboard; |
@@ -5,4 +5,4 @@ import path from "path"; | ||
const testFiles = results.testResults.map((resultByFile) => convertTestFile(resultByFile, { | ||
rootPath: options.rootPath, | ||
permalink: options.permalink, | ||
jestRootDir: options.jestRootDir, | ||
permalinkBaseUrl: options.permalinkBaseUrl, | ||
})); | ||
@@ -33,13 +33,6 @@ return { | ||
const convertTestFile = (result, options) => { | ||
const filePath = path.relative(options.rootPath, result.testFilePath); | ||
let permalink; | ||
if (options.permalink) { | ||
permalink = options.permalink.pattern | ||
/* eslint-disable no-template-curly-in-string */ | ||
.replace("${hostname}", options.permalink.hostname) | ||
.replace("${repository}", options.permalink.repository) | ||
.replace("${commit}", options.permalink.commit) | ||
.replace("${filePath}", filePath); | ||
/* eslint-enable no-template-curly-in-string */ | ||
} | ||
const filePath = path.relative(options.jestRootDir, result.testFilePath); | ||
const permalink = options.permalinkBaseUrl | ||
? options.permalinkBaseUrl + filePath | ||
: undefined; | ||
const children = convertChildren(result.testResults); | ||
@@ -46,0 +39,0 @@ return { filePath, children, permalink }; |
export type { Dashboard, Summary, TestFile, Describe, Test } from "./types.js"; | ||
export { convertResultsToDashboard } from "./converter.js"; | ||
export type { Permalink } from "./converter.js"; | ||
export { printDashBoard } from "./printer.js"; |
@@ -7,8 +7,3 @@ import type { Reporter, ReporterContext } from "@jest/reporters"; | ||
outputPath?: string; | ||
permalink?: { | ||
hostname?: string; | ||
repository?: string; | ||
commit?: string; | ||
pattern?: string; | ||
} | boolean; | ||
permalinkBaseUrl?: string; | ||
}; | ||
@@ -19,4 +14,4 @@ export declare class MarkdownDashboardReporter implements Reporter { | ||
private readonly title; | ||
private readonly outputPath?; | ||
private readonly permalink?; | ||
private readonly outputPath; | ||
private readonly permalinkBaseUrl; | ||
constructor(globalConfig: Config.GlobalConfig, reporterOptions: ReporterOptions, reporterContext: ReporterContext); | ||
@@ -23,0 +18,0 @@ onRunStart(): void; |
@@ -13,3 +13,3 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { | ||
import { convertResultsToDashboard, printDashBoard, } from "./dashboard/index.js"; | ||
import { buildTitle, buildPermalink } from "./options.js"; | ||
import { buildTitle, buildPermalinkBaseUrl, buildOutputPath, } from "./options.js"; | ||
export class MarkdownDashboardReporter { | ||
@@ -20,4 +20,7 @@ constructor(globalConfig, reporterOptions, reporterContext) { | ||
this.title = buildTitle(reporterOptions.title); | ||
this.outputPath = reporterOptions.outputPath; | ||
this.permalink = buildPermalink(reporterOptions.permalink); | ||
this.outputPath = buildOutputPath(reporterOptions.outputPath); | ||
this.permalinkBaseUrl = buildPermalinkBaseUrl({ | ||
permalinkBaseUrl: reporterOptions.permalinkBaseUrl, | ||
jestRootDir: this.globalConfig.rootDir, | ||
}); | ||
} | ||
@@ -32,9 +35,13 @@ onRunStart() { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
const permalinkBaseUrl = yield this.permalinkBaseUrl; | ||
const dashboard = convertResultsToDashboard(results, { | ||
title: this.title, | ||
rootPath: this.globalConfig.rootDir, | ||
permalink: this.permalink, | ||
jestRootDir: this.globalConfig.rootDir, | ||
permalinkBaseUrl, | ||
}); | ||
const resultText = printDashBoard(dashboard); | ||
if (this.outputPath !== undefined && this.outputPath.length > 0) { | ||
if (this.outputPath === "-") { | ||
console.log(resultText); | ||
} | ||
else { | ||
const absolutePath = path.resolve(this.outputPath); | ||
@@ -45,5 +52,2 @@ yield fs.mkdir(path.dirname(absolutePath), { recursive: true }); | ||
} | ||
else { | ||
console.log(resultText); | ||
} | ||
}); | ||
@@ -50,0 +54,0 @@ } |
@@ -1,4 +0,7 @@ | ||
import { Permalink } from "./dashboard/index.js"; | ||
import { ReporterOptions } from "./index.js"; | ||
export declare const buildTitle: (title?: string) => string; | ||
export declare const buildPermalink: (permalink?: ReporterOptions["permalink"]) => Permalink | undefined; | ||
export declare const buildOutputPath: (outputPath?: string) => string; | ||
export declare const buildPermalinkBaseUrl: ({ permalinkBaseUrl, jestRootDir, }: { | ||
permalinkBaseUrl?: ReporterOptions["permalinkBaseUrl"]; | ||
jestRootDir: string; | ||
}) => Promise<string | undefined>; |
@@ -0,32 +1,64 @@ | ||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { | ||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } | ||
return new (P || (P = Promise))(function (resolve, reject) { | ||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } | ||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } | ||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } | ||
step((generator = generator.apply(thisArg, _arguments || [])).next()); | ||
}); | ||
}; | ||
import fs from "fs"; | ||
import path from "path"; | ||
import git from "isomorphic-git"; | ||
import { parseRemoteUrl } from "./git.js"; | ||
export const buildTitle = (title) => { | ||
return title !== null && title !== void 0 ? title : "Tests Dashboard"; | ||
return title !== null && title !== void 0 ? title : "Test Dashboard"; | ||
}; | ||
export const buildPermalink = (permalink) => { | ||
var _a; | ||
if (permalink !== undefined && | ||
typeof permalink !== "boolean" && | ||
typeof permalink !== "object") { | ||
throw new Error("`permalink` option must be object or boolean"); | ||
export const buildOutputPath = (outputPath) => { | ||
return outputPath !== null && outputPath !== void 0 ? outputPath : "test-dashboard.md"; | ||
}; | ||
export const buildPermalinkBaseUrl = ({ permalinkBaseUrl, jestRootDir, }) => __awaiter(void 0, void 0, void 0, function* () { | ||
if (permalinkBaseUrl) { | ||
return permalinkBaseUrl; | ||
} | ||
let hostname = "github.com"; | ||
let repository = process.env.GITHUB_REPOSITORY; | ||
let commit = (_a = process.env.GITHUB_SHA) !== null && _a !== void 0 ? _a : "main"; | ||
// eslint-disable-next-line no-template-curly-in-string | ||
let pattern = "https://${hostname}/${repository}/blob/${commit}/${filePath}"; | ||
if (typeof permalink === "boolean" && !permalink) | ||
if (process.env.GITHUB_ACTIONS) { | ||
if (!process.env.GITHUB_SERVER_URL || | ||
!process.env.GITHUB_REPOSITORY || | ||
!process.env.GITHUB_SHA || | ||
!process.env.GITHUB_WORKSPACE) { | ||
throw new Error("The following environment variables are required for the GitHub Actions environment\n- GITHUB_SERVER_URL\n- GITHUB_REPOSITORY\n- GITHUB_SHA\n- GITHUB_WORKSPACE"); | ||
} | ||
const serverUrl = process.env.GITHUB_SERVER_URL; | ||
const repository = process.env.GITHUB_REPOSITORY; | ||
const commit = process.env.GITHUB_SHA; | ||
const rootDir = process.env.GITHUB_WORKSPACE; | ||
const subtree = path.relative(rootDir, jestRootDir); | ||
const trailingSlash = subtree.length > 0 && !subtree.endsWith("/") ? "/" : ""; | ||
return `${serverUrl}/${repository}/blob/${commit}/${subtree}${trailingSlash}`; | ||
} | ||
const rootDir = yield git | ||
.findRoot({ fs, filepath: jestRootDir }) | ||
.then((dir) => dir) | ||
.catch(() => __awaiter(void 0, void 0, void 0, function* () { return undefined; })); | ||
if (rootDir === undefined) { | ||
console.log("permalink disabled because project is not a git repository"); | ||
return undefined; | ||
if (typeof permalink === "object" && permalink !== null) { | ||
if (permalink.hostname) | ||
hostname = permalink.hostname; | ||
if (permalink.repository) | ||
repository = permalink.repository; | ||
if (permalink.commit) | ||
commit = permalink.commit; | ||
if (permalink.pattern) | ||
pattern = permalink.pattern; | ||
} | ||
if (hostname && repository && commit && pattern) { | ||
return { hostname, repository, commit, pattern }; | ||
try { | ||
const remotes = yield git.listRemotes({ fs, dir: rootDir }); | ||
if (remotes.length === 0) { | ||
console.error("no remote URL found."); | ||
return undefined; | ||
} | ||
const remote = remotes[0]; | ||
const { serverUrl, repository } = parseRemoteUrl(remote.url); | ||
const commit = yield git.resolveRef({ fs, dir: rootDir, ref: "HEAD" }); | ||
const subtree = path.relative(rootDir, jestRootDir); | ||
const trailingSlash = subtree.length > 0 && !subtree.endsWith("/") ? "/" : ""; | ||
return `${serverUrl}/${repository}/blob/${commit}/${subtree}${trailingSlash}`; | ||
} | ||
return undefined; | ||
}; | ||
catch (e) { | ||
console.error(e); | ||
return undefined; | ||
} | ||
}); |
{ | ||
"name": "jest-md-dashboard", | ||
"version": "0.4.0", | ||
"version": "0.5.0", | ||
"description": "Generating a pretty Markdown dashboard for Jest", | ||
@@ -30,3 +30,3 @@ "repository": { | ||
"test": "jest", | ||
"test:generate-dashboard": "jest --config=./jest.generate-dashboard.config.cjs", | ||
"test:generate-dashboard": "jest --config=./jest.generate-dashboard.config.js", | ||
"lint": "run-s lint:*", | ||
@@ -40,3 +40,5 @@ "lint:eslint": "eslint --ext .js,.mjs,.cjs,.ts,.mts,.cts ./", | ||
}, | ||
"dependencies": {}, | ||
"dependencies": { | ||
"isomorphic-git": "^1.18.3" | ||
}, | ||
"devDependencies": { | ||
@@ -46,3 +48,4 @@ "@babel/core": "^7.18.6", | ||
"@babel/preset-typescript": "^7.18.6", | ||
"@cybozu/eslint-config": "^17.0.1", | ||
"@cybozu/eslint-config": "^17.0.2", | ||
"@jest/globals": "^28.1.2", | ||
"@jest/reporters": "^28.1.2", | ||
@@ -52,7 +55,7 @@ "@jest/test-result": "^28.1.1", | ||
"@tsconfig/recommended": "^1.0.1", | ||
"@types/jest": "^28.1.3", | ||
"@typescript-eslint/parser": "^5.30.0", | ||
"@types/jest": "^28.1.4", | ||
"@typescript-eslint/parser": "^5.30.4", | ||
"babel-jest": "^28.1.2", | ||
"eslint": "^8.18.0", | ||
"eslint-import-resolver-typescript": "^3.1.1", | ||
"eslint-import-resolver-typescript": "^3.1.5", | ||
"eslint-plugin-import": "^2.26.0", | ||
@@ -63,3 +66,3 @@ "jest": "^28.1.2", | ||
"prettier": "^2.7.1", | ||
"release-please": "^13.18.6", | ||
"release-please": "^13.19.0", | ||
"rimraf": "^3.0.2", | ||
@@ -66,0 +69,0 @@ "typescript": "^4.7.4" |
@@ -43,3 +43,3 @@ # jest-md-dashboard | ||
Run jest and the markdown output is printed to stdout. | ||
Run jest and the markdown dashboard is generated to `test-dashboard.md`. | ||
@@ -86,12 +86,36 @@ ### With options | ||
| Name | Type | Default | Description | | ||
| ---------------------- | ------------------- | --------------------------- | --------------------------------------------------------------------------------------------------------------------------- | | ||
| `title` | `string` | `"Tests Dashboard"` | The title of a dashboard.<br>It will be printed at the top of the markdown output. | | ||
| `outputPath` | `string` | `undefined` | The file path to output dashboard. If this option is specified, dashboard is printed to the file instead of stdout. | | ||
| `permalink` | `object` or `false` | `{(followings)}` | Override permalink generation.<br>Set `false` to disable generation. | | ||
| `permalink.hostname` | `string` | `"github.com"` | The hostname of permalink.<br>Specify if you using services other than github.com.<br>e.g. GitHub Enterprise or GitLab | | ||
| `permalink.repository` | `string` | `${GITHUB_REPOSITORY}` | The repository name of permalink. (`"<owner>/<repo>"`) | | ||
| `permalink.commit` | `string` | `${GITHUB_SHA}` ?? `"main"` | The commit hash of permalink.<br>You can also specify branch or tag. | | ||
| `permalink.pattern` | `string` | see description | The template pattern of permalink.<br>Absence defaults to `"https://${hostname}/${repository}/blob/${commit}/${filePath}"`. | | ||
| Name | Type | Default | Description | | ||
| ------------------ | -------- | ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | ||
| `title` | `string` | `"Test Dashboard"` | The title of a dashboard.<br>It will be printed at the top of the markdown output. | | ||
| `outputPath` | `string` | `test-dashboard.md` | The file path to output dashboard. If you want to output to stdout, specify `-`. | | ||
| `permalinkBaseUrl` | `string` | `undefined` | Override baseUrl of permalink. Specify if generated permalinks are incorrect.<br>URL must have trailing slash.<br>e.g. `https://github.com/mshrtsr/jest-md-dashboard/blob/` <br>See [Permalink generation](#Permalink generation) for more information. | | ||
## Permalink generation | ||
jest-md-dashboard generates permalink to test files on GitHub (or other services) by default. | ||
jest-md-dashboard tries to find git information from the following sources. | ||
1. `permalinkBaseUrl` option | ||
2. (on GitHub Actions) environment variables | ||
3. (in git repository) git config | ||
### `permalinkBaseUrl` option | ||
If `permalinkBaseUrl` is specified on jest config, jest-md-dashboard generates permalink using it. | ||
### on GitHub Actions | ||
If you run jest on GitHub Actions, jest-md-dashboard generates permalink using the following environment variables. | ||
- `$GITHUB_ACTIONS` | ||
- `$GITHUB_SERVER_URL` | ||
- `$GITHUB_REPOSITORY` | ||
- `$GITHUB_SHA` | ||
- `$GITHUB_WORKSPACE` | ||
### in git repository | ||
If jest runs in a git repository, jest-md-dashboard generates permalink using git config of the local repository. | ||
## Contribution | ||
@@ -98,0 +122,0 @@ |
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 5 instances in 1 package
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
Found 1 instance in 1 package
24543
21.4%18
12.5%337
16.61%126
23.53%1
Infinity%22
4.76%11
1000%+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added