fix(test): cover new reporters
This commit is contained in:
parent
b2122d5780
commit
09f83ee5ab
|
@ -3,16 +3,20 @@ import { setOrPush } from '@apextoaster/js-utils';
|
||||||
import { Rule, RuleError, RuleResult } from '../rule/index.js';
|
import { Rule, RuleError, RuleResult } from '../rule/index.js';
|
||||||
import { Reporter } from './index.js';
|
import { Reporter } from './index.js';
|
||||||
|
|
||||||
|
export const ERROR_EMPTY_RESULT = 'no errors to report';
|
||||||
|
|
||||||
export class SummaryReporter implements Reporter {
|
export class SummaryReporter implements Reporter {
|
||||||
public async report(results: Array<RuleResult>): Promise<string> {
|
public async report(results: Array<RuleResult>): Promise<string> {
|
||||||
const ruleErrors = new Map<Rule, Array<RuleError>>();
|
const ruleErrors = new Map<Rule, Array<RuleError>>();
|
||||||
|
|
||||||
for (const err of results.flatMap((r) => r.errors)) {
|
for (const result of results) {
|
||||||
setOrPush(ruleErrors, err.rule, err);
|
for (const err of result.errors) {
|
||||||
|
setOrPush(ruleErrors, err.rule, err);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ruleErrors.size === 0) {
|
if (ruleErrors.size === 0) {
|
||||||
return 'no errors to report';
|
return ERROR_EMPTY_RESULT;
|
||||||
}
|
}
|
||||||
|
|
||||||
const summary = ['rule errors'];
|
const summary = ['rule errors'];
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { getOrDefault, leftPad, mustExist, mustGet, setOrPush } from '@apextoaster/js-utils';
|
import { getOrDefault, leftPad, mustGet, setOrPush } from '@apextoaster/js-utils';
|
||||||
|
|
||||||
import { Rule, RuleResult } from '../rule/index.js';
|
import { Rule, RuleResult } from '../rule/index.js';
|
||||||
import { Reporter } from './index.js';
|
import { Reporter } from './index.js';
|
||||||
|
@ -15,6 +15,8 @@ interface RuleCounts {
|
||||||
rule: string;
|
rule: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const ERROR_EMPTY_RESULT = 'no results to format';
|
||||||
|
|
||||||
export class TableReporter implements Reporter {
|
export class TableReporter implements Reporter {
|
||||||
public async report(results: ReadonlyArray<RuleResult>): Promise<string> {
|
public async report(results: ReadonlyArray<RuleResult>): Promise<string> {
|
||||||
const rules = new Map<Rule, RuleCounts>();
|
const rules = new Map<Rule, RuleCounts>();
|
||||||
|
@ -30,6 +32,11 @@ export class TableReporter implements Reporter {
|
||||||
}
|
}
|
||||||
|
|
||||||
const rows = Array.from(rules.values());
|
const rows = Array.from(rules.values());
|
||||||
|
|
||||||
|
if (rows.length === 0) {
|
||||||
|
return ERROR_EMPTY_RESULT;
|
||||||
|
}
|
||||||
|
|
||||||
return printTable(rows, ['rule', 'errors', 'changes'], {
|
return printTable(rows, ['rule', 'errors', 'changes'], {
|
||||||
delimiter: {
|
delimiter: {
|
||||||
column: COL_DELIMITER,
|
column: COL_DELIMITER,
|
||||||
|
|
|
@ -7,7 +7,7 @@ export class YamlReporter implements Reporter {
|
||||||
const parser = new YamlParser();
|
const parser = new YamlParser();
|
||||||
const data = {
|
const data = {
|
||||||
changes: results.flatMap((r) => r.changes).map((c) => c.rule.name),
|
changes: results.flatMap((r) => r.changes).map((c) => c.rule.name),
|
||||||
errors: results.flatMap((r) => r.errors).map((c) => c.rule.name),
|
errors: results.flatMap((r) => r.errors).map((e) => e.rule.name),
|
||||||
};
|
};
|
||||||
return parser.dump({
|
return parser.dump({
|
||||||
data,
|
data,
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import { LogLevel, NullLogger } from 'noicejs';
|
import { LogLevel, NullLogger } from 'noicejs';
|
||||||
|
|
||||||
|
import { RuleChange, RuleError } from '../src/rule/index.js';
|
||||||
import { SchemaRule } from '../src/rule/SchemaRule.js';
|
import { SchemaRule } from '../src/rule/SchemaRule.js';
|
||||||
import { Document, Element } from '../src/source.js';
|
import { Document, Element } from '../src/source.js';
|
||||||
import { VisitorContext } from '../src/visitor/VisitorContext.js';
|
import { VisitorContext } from '../src/visitor/VisitorContext.js';
|
||||||
|
@ -36,3 +37,22 @@ export function makeElement(data: unknown): Element {
|
||||||
index: 0,
|
index: 0,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function makeResults(names: Array<string>, changes: Array<RuleChange> = [], errors: Array<RuleError> = []) {
|
||||||
|
const rules = names.map((name) => new SchemaRule({
|
||||||
|
check: {},
|
||||||
|
desc: name,
|
||||||
|
level: LogLevel.Info,
|
||||||
|
name,
|
||||||
|
select: '',
|
||||||
|
tags: [],
|
||||||
|
}));
|
||||||
|
|
||||||
|
const results = rules.map((rule) => ({
|
||||||
|
changes,
|
||||||
|
errors,
|
||||||
|
rule,
|
||||||
|
}));
|
||||||
|
|
||||||
|
return { rules, results };
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,38 @@
|
||||||
|
import { expect } from 'chai';
|
||||||
|
import { LogLevel } from 'noicejs';
|
||||||
|
|
||||||
|
import { ERROR_EMPTY_RESULT, SummaryReporter } from '../../src/reporter/SummaryReporter.js';
|
||||||
|
import { RuleResult } from '../../src/rule/index.js';
|
||||||
|
import { makeElement, makeResults } from '../helpers.js';
|
||||||
|
|
||||||
|
describe('summary reporter', () => {
|
||||||
|
it('should handle empty results', async () => {
|
||||||
|
const reporter = new SummaryReporter();
|
||||||
|
const report = await reporter.report([]);
|
||||||
|
expect(report).to.equal(ERROR_EMPTY_RESULT);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should count results by type', async () => {
|
||||||
|
const ruleNames = ['test', 'foo', 'bar'];
|
||||||
|
const { rules } = makeResults(ruleNames);
|
||||||
|
const results: Array<RuleResult> = rules.map((rule) => ({
|
||||||
|
changes: [],
|
||||||
|
errors: [{
|
||||||
|
data: makeElement({}),
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
|
err: {} as any,
|
||||||
|
level: LogLevel.Debug,
|
||||||
|
msg: '',
|
||||||
|
rule,
|
||||||
|
}],
|
||||||
|
rule,
|
||||||
|
}));
|
||||||
|
|
||||||
|
const reporter = new SummaryReporter();
|
||||||
|
const report = await reporter.report(results);
|
||||||
|
|
||||||
|
for (const name of ruleNames) {
|
||||||
|
expect(report).to.include(`${name}: 1`); // wrap with margin to avoid partial words
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
|
@ -0,0 +1,43 @@
|
||||||
|
import { expect } from 'chai';
|
||||||
|
|
||||||
|
import { ERROR_EMPTY_RESULT, TableReporter } from '../../src/reporter/TableReporter.js';
|
||||||
|
import { makeResults } from '../helpers.js';
|
||||||
|
|
||||||
|
describe('table reporter', () => {
|
||||||
|
it('should handle empty results', async () => {
|
||||||
|
const reporter = new TableReporter();
|
||||||
|
const report = await reporter.report([]);
|
||||||
|
expect(report).to.equal(ERROR_EMPTY_RESULT);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should group results by rule', async () => {
|
||||||
|
const ruleNames = ['test', 'foo', 'bar'];
|
||||||
|
const { results } = makeResults(ruleNames);
|
||||||
|
|
||||||
|
const reporter = new TableReporter();
|
||||||
|
const report = await reporter.report(results);
|
||||||
|
|
||||||
|
for (const name of ruleNames) {
|
||||||
|
expect(report).to.include(` ${name} `); // wrap with margin to avoid partial words
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should print results in a table', async () => {
|
||||||
|
const ruleNames = ['test', 'foo', 'bar'];
|
||||||
|
const { results } = makeResults(ruleNames);
|
||||||
|
|
||||||
|
const reporter = new TableReporter();
|
||||||
|
const report = await reporter.report(results);
|
||||||
|
|
||||||
|
for (const line of report.split('\n')) {
|
||||||
|
expect(line).to.match(/^|/);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('print table helper', () => {
|
||||||
|
it('should include column names in the first row');
|
||||||
|
it('should have a second row with delimiters');
|
||||||
|
it('should show data starting from the third row');
|
||||||
|
it('should pad and right-align short fields');
|
||||||
|
});
|
|
@ -0,0 +1,46 @@
|
||||||
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||||
|
import { expect } from 'chai';
|
||||||
|
import { LogLevel } from 'noicejs';
|
||||||
|
|
||||||
|
import { YamlReporter } from '../../src/reporter/YamlReporter.js';
|
||||||
|
import { RuleResult } from '../../src/rule/index.js';
|
||||||
|
import { makeElement, makeResults } from '../helpers.js';
|
||||||
|
|
||||||
|
describe('yaml reporter', () => {
|
||||||
|
it('should handle empty results', async () => {
|
||||||
|
const reporter = new YamlReporter();
|
||||||
|
const report = await reporter.report([]);
|
||||||
|
expect(report).to.equal('changes: []\nerrors: []\n');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should collect results by type', async () => {
|
||||||
|
const ruleNames = ['test', 'foo', 'bar'];
|
||||||
|
const { rules } = makeResults(ruleNames, [], [{
|
||||||
|
data: makeElement({}),
|
||||||
|
err: {} as any,
|
||||||
|
level: LogLevel.Debug,
|
||||||
|
msg: '',
|
||||||
|
rule: {
|
||||||
|
name: 'test',
|
||||||
|
} as any,
|
||||||
|
}]);
|
||||||
|
const results: Array<RuleResult> = rules.map((rule) => ({
|
||||||
|
changes: [],
|
||||||
|
errors: [{
|
||||||
|
data: makeElement({}),
|
||||||
|
err: {} as any,
|
||||||
|
level: LogLevel.Debug,
|
||||||
|
msg: '',
|
||||||
|
rule,
|
||||||
|
}],
|
||||||
|
rule,
|
||||||
|
}));
|
||||||
|
|
||||||
|
const reporter = new YamlReporter();
|
||||||
|
const report = await reporter.report(results);
|
||||||
|
|
||||||
|
for (const name of ruleNames) {
|
||||||
|
expect(report).to.include(`- ${name}\n`); // wrap with margin to avoid partial words
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
Loading…
Reference in New Issue