import { writeFileSync } from "fs"; import { numberOrDefault } from "../../../../commons/coolKids"; import { stringHasLength } from "../../../../commons/validators"; import { iCoverageTableFormat } from "../../../../contracts/coverage/helpers/iCoverageTableFormat"; import { iCoverageResponseData } from "../../../../contracts/coverage/model/iCoverageResponseData"; import { iCoverageOptions } from "../../../../contracts/coverage/request/iCoverageOptions"; import { iDispatchRequestCoverage } from "../../../../contracts/coverage/request/iDispatchRequestCoverage"; import { translateResponse } from "../../../../translation/translate"; import { MarkdownEnvironment } from "../../../configuration/markdownEnvironment"; import { filterLines } from "../../../processor/filters"; import { callEntry } from "../../../processor/processor"; import { Kernel } from "../../kernel"; import * as theme from "./markdownTheme"; export class MarkdownCoverage { public entries: string[] = []; public coverageOptions: iCoverageOptions; public constructor( private kernel: Kernel, private markdownEnvironment: MarkdownEnvironment ) { } public controller() { this.getEntries(); this.getCoverageOptions(); this.update(); } public getEntries() { this.entries = this.kernel.modules .repoManager.getEntries(this.markdownEnvironment.repo) } public getCoverageOptions() { this.coverageOptions = this.kernel.modules .repoManager.getCoverageOptions(this.markdownEnvironment.repo); } public createRequest(entry: string): iDispatchRequestCoverage { const headers = this.kernel.modules.requests.getBaseHeadersForEntry(entry) return { url: "/coverage", userAgent: "@markdown", body: this.coverageOptions, headers } } public update() { const pages: string[][] = []; const promises = this.entries.map(entry => { const messages = []; return callEntry(entry, this.createRequest(entry), messages) .then(response => translateResponse(response)) .then(response => { response.whenCoverage(coverage => { const files = this.kernel.modules.coverage.coverageToTable(coverage.body.data); const data = this.writeToLines(files); const headerLines: string[] = []; this.writeHeader(headerLines, entry, data.shouldThrow) this.writeChart(headerLines, coverage.body.data) const finalLines = filterLines(headerLines.concat(data.lines)); pages.push(finalLines); }); response.whenError(error => { this.kernel.modules.messages.error(this.markdownEnvironment, error.body); }) }) }) Promise.all(promises).then(() => { const lines = []; pages.forEach(page => page.forEach(line => lines.push(line))); if (stringHasLength(this.markdownEnvironment.coverageOptions.path)) { writeFileSync(this.markdownEnvironment.coverageOptions.path, lines.join("\n")) } }) } public writeHeader(lines: string[], entry: string, shouldThrow: boolean) { theme.h2(lines, entry) lines.push(theme.oneSpace()) shouldThrow ? lines.push(``) : lines.push(``) lines.push(theme.oneSpace()) } public writeChart(lines: string[], data: iCoverageResponseData) { const report = this.kernel.modules.coverage.calcTotalFromFiles(data); theme.h3(lines, "Totals"); lines.push("") lines.push(`| Total Functions | Total Branches | Total Statements |`) lines.push("|---:|---:|---:|") lines.push(`| ${report.functionsAverageString} | ${report.branchesAverageString} | ${report.statementAverageString} |`); lines.push(theme.oneSpace()) theme.h3(lines, "Files") } public writeToLines(files: iCoverageTableFormat[]) { const lines: string[] = []; let threshold: number = numberOrDefault(this.coverageOptions.threshold, 0); let lessThanThreshold: boolean = false; files.forEach(file => { lines.push(theme.highlight(file.path) + "
") const segments = [ `**Functions:** ${file.functionPercentage}%`, `**Branches:** ${file.branchPercentage}%`, `**Statements:** ${file.statementPercentage}%` ] const line = segments.join(theme.oneSpace()) lines.push(line); lines.push(theme.oneSpace()) if (file.statementCount < threshold) { lessThanThreshold = true; } }) return { lines, shouldThrow: this.markdownEnvironment.console.throwWhenErrorsPresent && lessThanThreshold } } }