kopach/karma-sabarivka-reporter

View on GitHub
src/instrumenter.ts

Summary

Maintainability
A
0 mins
Test Coverage
import * as fs from 'fs';
import { sync } from 'globby';
import { createInstrumenter, Instrumenter } from 'istanbul-lib-instrument';
import * as path from 'path';
import { ModuleKind, transpileModule, TranspileOutput } from 'typescript';
import { CoverageData, InstrumenterFnArgs, PublicAPI } from './model';

export function getFileInstrumenterFn(
  coverageReporterConfig: PublicAPI
): (...args: InstrumenterFnArgs) => void {
  return (...[, { coverage }]: InstrumenterFnArgs): void => {
    const filesToCover: string[] = getListOfFilesToCover(
      coverageReporterConfig
    );

    addFileListToCoverageData(filesToCover, coverage);
  };
}

function getListOfFilesToCover(coverageReporterConfig: PublicAPI): string[] {
  const globPatternList: string[] = flatten([
    coverageReporterConfig.coverageReporter.include || [],
  ]);

  return sync(globPatternList);
}

function addFileListToCoverageData(
  filesToCover: string[],
  coverage?: CoverageData
): void {
  filesToCover.forEach((filePath: string): void => {
    if (!coverage) return;

    const fullFilePath: string = path.resolve(process.cwd(), filePath);

    if (!coverage[fullFilePath]) {
      const fileContentJS: TranspileOutput =
        getFileTranspiledToJs(fullFilePath);

      coverage[fullFilePath] = getFileCoverageData(fileContentJS, fullFilePath);
    }
  });
}

function getFileTranspiledToJs(fullFilePath: string): TranspileOutput {
  const rawFile: string = fs.readFileSync(fullFilePath, 'utf-8');
  const jsResult: TranspileOutput = transpileModule(rawFile, {
    compilerOptions: {
      allowJs: true,
      module: ModuleKind.ES2015,
    },
  });

  return jsResult;
}

function getFileCoverageData(
  fileContentJS: TranspileOutput,
  fullFilePath: string
): ReturnType<Instrumenter['lastFileCoverage']> {
  const instrumenter: Instrumenter = createInstrumenter({
    esModules: true,
  });

  instrumenter.instrumentSync(fileContentJS.outputText, fullFilePath);

  return instrumenter.lastFileCoverage();
}

function flatten(arr: ReadonlyArray<string | string[]>): string[] {
  return ([] as string[]).concat(...arr);
}