This commit is contained in:
Tutur33
2023-11-24 22:35:41 +01:00
parent 3c0b507a93
commit 7644b2a0f7
45165 changed files with 4803356 additions and 3 deletions
+9
View File
@@ -0,0 +1,9 @@
# The MIT License
Copyright 2022 Harminder Virk, contributors
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the 'Software'), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+145
View File
@@ -0,0 +1,145 @@
# @japa/errors-printer
> Print errors produced by the Japa tests runner
[![github-actions-image]][github-actions-url] [![npm-image]][npm-url] [![license-image]][license-url] [![typescript-image]][typescript-url]
## Installation
Install the package from the npm registry as follows:
```sh
npm i @japa/errors-printer
# yarn
yarn add @japa/errors-printer
```
## Usage
You can print errors produced by japa test runner as follows.
```ts
import { ErrorsPrinter } from '@japa/errors-printer'
const printer = new ErrorsPrinter()
const error = new Error('boom')
await printer.printError(error)
```
Most of the times, you will find yourself printing errors using the Japa test summary. Here is how you can go about doing it.
```ts
import { ErrorsPrinter } from '@japa/errors-printer'
const printer = new ErrorsPrinter()
// assuming you have the runner instance
const summary = runner.getSummary()
/**
* Printing all the errors inside the failure tree
*/
for (let suite in summary.failureTree) {
await printer.printErrors(suite.name, suite.errors)
for (let groupOrTest in suite.children) {
if (groupOrTest.type === 'test') {
await printer.printErrors(groupOrTest.title, groupOrTest.errors)
} else {
await printer.printErrors(groupOrTest.title, groupOrTest.errors)
for (let group in groupOrTest.children) {
await printer.printErrors(group.title, group.errors)
}
}
}
}
```
## API
Following are the available methods.
### printError()
Accepts error as the only argument. If the error is an assertion error, then the diff will be displayed. Otherwise, the error stack is printed.
**Assertion diff**
```ts
import { Assert } from '@japa/assert'
import { ErrorsPrinter } from '@japa/errors-printer'
const printer = new ErrorsPrinter()
try {
new Assert().deepEqual({ id: 1 }, { id: 2 })
} catch (error) {
await printer.printError(error)
}
```
![](assets/assertion-error.png)
**Jest error**
```ts
import expect from 'expect'
import { ErrorsPrinter } from '@japa/errors-printer'
const printer = new ErrorsPrinter()
try {
expect({ bar: 'baz' }).toEqual(expect.not.objectContaining({ bar: 'baz' }))
} catch (error) {
await printer.printError(error)
}
```
![](assets/jest-error.png)
**Error stack**
```ts
import { ErrorsPrinter } from '@japa/errors-printer'
const printer = new ErrorsPrinter()
await printer.printError(new Error('boom'))
```
![](assets/error-stack.png)
### printErrors
Print an array of errors produced by the Japa test runner summary. The method accepts the following arguments.
- `label`: The error label to print. Usually, it will be test title or the group title.
- `errors`: An array of errors in the following format.
```ts
{
phase: string,
error: Error
}
```
```ts
await printer.printErrors('test 1', [
{
phase: 'test',
error: new Error('test failed')
},
{
phase: 'teardown',
error: new Error('teardown failed')
}
])
```
[github-actions-image]: https://img.shields.io/github/actions/workflow/status/japa/errors-printer/test.yml?style=for-the-badge
[github-actions-url]: https://github.com/japa/errors-printer/actions/workflows/test.yml "github-actions"
[npm-image]: https://img.shields.io/npm/v/@japa/errors-printer.svg?style=for-the-badge&logo=npm
[npm-url]: https://npmjs.org/package/@japa/errors-printer "npm"
[license-image]: https://img.shields.io/npm/l/@japa/errors-printer?color=blueviolet&style=for-the-badge
[license-url]: LICENSE.md "license"
[typescript-image]: https://img.shields.io/badge/Typescript-294E80.svg?style=for-the-badge&logo=typescript
[typescript-url]: "typescript"
+1
View File
@@ -0,0 +1 @@
export { ErrorsPrinter } from './src/printer';
+13
View File
@@ -0,0 +1,13 @@
"use strict";
/*
* @japa/errors-printer
*
* (c) Harminder Virk <virk@adonisjs.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.ErrorsPrinter = void 0;
var printer_1 = require("./src/printer");
Object.defineProperty(exports, "ErrorsPrinter", { enumerable: true, get: function () { return printer_1.ErrorsPrinter; } });
+42
View File
@@ -0,0 +1,42 @@
/**
* Print test runner errors
*/
export declare class ErrorsPrinter {
private stackLinesCount;
private framesMaxLimit;
constructor(options?: {
stackLinesCount?: number;
framesMaxLimit?: number;
});
/**
* Get Youch's JSON report of the given error
*/
private getYouchJson;
/**
* Returns human readable message for error phase
*/
private getPhaseTitle;
/**
* Displays the error stack for a given error
*/
private displayErrorStack;
/**
* Display chai assertion error
*/
private displayAssertionError;
/**
* Display jest assertion error
*/
private displayJestError;
/**
* Pretty print the error to the console
*/
printError(error: any): Promise<void>;
/**
* Print summary errors
*/
printErrors(label: string, errors: {
phase: string;
error: any;
}[]): Promise<void>;
}
+152
View File
@@ -0,0 +1,152 @@
"use strict";
/*
* @japa/errors-printer
*
* (c) Japa.dev
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.ErrorsPrinter = void 0;
const os_1 = require("os");
const youch_1 = __importDefault(require("youch"));
const youch_terminal_1 = __importDefault(require("youch-terminal"));
const jest_diff_1 = require("jest-diff");
const cliui_1 = require("@poppinss/cliui");
/**
* Print test runner errors
*/
class ErrorsPrinter {
constructor(options) {
this.stackLinesCount = options?.stackLinesCount || 5;
this.framesMaxLimit = options?.framesMaxLimit || 3;
}
/**
* Get Youch's JSON report of the given error
*/
async getYouchJson(error) {
const youch = new youch_1.default(error, {}, {
postLines: this.stackLinesCount,
preLines: this.stackLinesCount,
});
return youch.toJSON();
}
/**
* Returns human readable message for error phase
*/
getPhaseTitle(phase) {
switch (phase) {
case 'setup':
return 'Setup hook';
case 'setup:cleanup':
return 'Setup hook cleanup function';
case 'teardown':
return 'Teardown hook';
case 'teardown:cleanup':
return 'Teardown hook cleanup function';
}
}
/**
* Displays the error stack for a given error
*/
async displayErrorStack(error) {
const jsonResponse = await this.getYouchJson(error);
console.log((0, youch_terminal_1.default)(jsonResponse, {
displayShortPath: true,
framesMaxLimit: this.framesMaxLimit,
displayMainFrameOnly: false,
}));
}
/**
* Display chai assertion error
*/
async displayAssertionError(error) {
/**
* Display diff
*/
console.log();
console.log(` Assertion Error: ${error.message}`);
console.log();
if (error.showDiff) {
const { actual, expected } = error;
const diff = (0, jest_diff_1.diff)(expected, actual, {
expand: true,
includeChangeCounts: true,
});
console.log(diff);
}
/**
* Display error stack with the main frame only
*/
const jsonResponse = await this.getYouchJson(error);
console.log((0, youch_terminal_1.default)(jsonResponse, {
hideErrorTitle: true,
hideMessage: true,
displayShortPath: true,
displayMainFrameOnly: true,
}));
}
/**
* Display jest assertion error
*/
async displayJestError(error) {
/**
* Display diff
*/
console.log();
console.log(` Assertion Error:${error.message
.split(os_1.EOL)
.map((line) => ` ${line}`)
.join(os_1.EOL)}`);
console.log();
/**
* Display error stack with the main frame only
*/
const jsonResponse = await this.getYouchJson(error);
console.log((0, youch_terminal_1.default)(jsonResponse, {
hideErrorTitle: true,
hideMessage: true,
displayShortPath: true,
displayMainFrameOnly: true,
}));
}
/**
* Pretty print the error to the console
*/
async printError(error) {
/**
* Values are not object objects are printed as it is.
*/
if (error === null || Array.isArray(error) || typeof error !== 'object') {
console.log(`Error: ${error}`);
return;
}
if ('actual' in error && 'expected' in error) {
await this.displayAssertionError(error);
return;
}
if ('matcherResult' in error) {
await this.displayJestError(error);
return;
}
await this.displayErrorStack(error);
}
/**
* Print summary errors
*/
async printErrors(label, errors) {
for (let { phase, error } of errors) {
console.log(cliui_1.logger.colors.red(`${cliui_1.icons.cross} ${label}`));
if (phase !== 'test') {
console.log(` ${cliui_1.logger.colors.red(`(${this.getPhaseTitle(phase)})`)}`);
}
await this.printError(error);
console.log();
}
}
}
exports.ErrorsPrinter = ErrorsPrinter;
+128
View File
@@ -0,0 +1,128 @@
{
"name": "@japa/errors-printer",
"version": "2.1.0",
"description": "Reusable package to pretty print test runner summary errors",
"main": "build/index.js",
"files": [
"build/src",
"build/index.d.ts",
"build/index.js"
],
"exports": {
".": "./build/index.js"
},
"scripts": {
"mrm": "mrm --preset=@adonisjs/mrm-preset",
"pretest": "npm run lint",
"test": "node .bin/test.js",
"clean": "del-cli build",
"compile": "npm run lint && npm run clean && tsc",
"build": "npm run compile",
"prepublishOnly": "npm run build",
"lint": "eslint . --ext=.ts",
"format": "prettier --write .",
"commit": "git-cz",
"release": "np --message=\"chore(release): %s\"",
"version": "npm run build",
"sync-labels": "github-label-sync --labels ./node_modules/@adonisjs/mrm-preset/gh-labels.json japa/errors-printer"
},
"keywords": [
"japa",
"test",
"printer"
],
"author": "virk,japa",
"license": "MIT",
"devDependencies": {
"@adonisjs/mrm-preset": "^5.0.3",
"@adonisjs/require-ts": "^2.0.13",
"@japa/assert": "^1.3.6",
"@types/node": "^18.11.19",
"commitizen": "^4.3.0",
"cz-conventional-changelog": "^3.3.0",
"del-cli": "^5.0.0",
"eslint": "^8.33.0",
"eslint-config-prettier": "^8.6.0",
"eslint-plugin-adonis": "^3.0.3",
"eslint-plugin-prettier": "^4.2.1",
"expect": "^29.4.1",
"github-label-sync": "^2.2.0",
"husky": "^8.0.3",
"japa": "^4.0.0",
"mrm": "^4.1.13",
"np": "^7.6.3",
"prettier": "^2.8.3",
"typescript": "^4.9.5"
},
"mrmConfig": {
"core": false,
"license": "MIT",
"services": [
"github-actions"
],
"minNodeVersion": "16.13.1",
"probotApps": [
"stale",
"lock"
],
"runGhActionsOnWindows": false
},
"eslintConfig": {
"extends": [
"plugin:adonis/typescriptPackage",
"prettier"
],
"plugins": [
"prettier"
],
"rules": {
"unicorn/prefer-node-protocol": "off",
"prettier/prettier": [
"error",
{
"endOfLine": "auto"
}
]
}
},
"eslintIgnore": [
"build"
],
"prettier": {
"trailingComma": "es5",
"semi": false,
"singleQuote": true,
"useTabs": false,
"quoteProps": "consistent",
"bracketSpacing": true,
"arrowParens": "always",
"printWidth": 100
},
"config": {
"commitizen": {
"path": "cz-conventional-changelog"
}
},
"np": {
"contents": ".",
"anyBranch": false
},
"repository": {
"type": "git",
"url": "git+https://github.com/japa/errors-printer.git"
},
"bugs": {
"url": "https://github.com/japa/errors-printer/issues"
},
"homepage": "https://github.com/japa/errors-printer#readme",
"dependencies": {
"@poppinss/cliui": "^3.0.5",
"jest-diff": "^29.4.1",
"youch": "^3.2.3",
"youch-terminal": "^2.2.0"
},
"publishConfig": {
"access": "public",
"tag": "latest"
}
}