lib/index.js
function snapshotFramework(files, config, emitter, loggerFactory) {
  const logger = loggerFactory.create('framework.snapshot');

  const snapshotConfig = Object.assign({
    update: false,
    prune: false,
    format: "md",
    checkSourceFile: false,
    pathResolver: defaultPathResolver,
    limitUnusedSnapshotsInWarning: -1
  }, config.snapshot);

  if (typeof snapshotConfig.format === "string") {
    switch (snapshotConfig.format) {
      case "indented-md":
        snapshotSerializer = createMarkdownSerializer(true);
        break;
      case "md":
      default:
        snapshotSerializer = createMarkdownSerializer(false);
    }
  } else {
    snapshotSerializer = snapshotConfig.format;
  }

  // it should be in a files list after `adapter.js`
  if (snapshotConfig.update) {
    files.unshift(filePattern(path.join(__dirname, 'snapshot-state-update.js')));
  }

  // inject snapshot adapter
  files.unshift(filePattern(path.join(__dirname, 'adapter.js')));

  emitter.on('browser_complete', (clientInfo, data) => {
    const lastResult = clientInfo.lastResult;

    if (!lastResult.disconnected) {
      if (data && data.snapshot) {
        let rootSuite = data.snapshot;
        let dirty = rootSuite.dirty;

        // prune dead snapshots
        if (!lastResult.error && lastResult.failed === 0 && lastResult.skipped === 0) {
          const prunedSnapshots = prune.pruneSnapshots(rootSuite);
          if (prunedSnapshots.pruned.length > 0) {
            if (snapshotConfig.prune) {
              const prunedList = formatSnapshotList(prunedSnapshots.pruned)
              logger.warn(`Removed ${prunedSnapshots.pruned.length} unused snapshots:\n${prunedList}`);
              rootSuite = prunedSnapshots.suite;
              prune.pruneFiles(snapshotConfig.pathResolver, config.basePath, prunedSnapshots.prunedFiles);
              dirty = true;
            } else {
              logger.warn(formatUnusedSnapshotsWarning(prunedSnapshots.pruned, snapshotConfig.limitUnusedSnapshotsInWarning));
            }
          }
        }

        if (dirty) {
          Object.keys(rootSuite.children).forEach((suiteName) => {
            const suite = rootSuite.children[suiteName];
            if (suite.dirty) {
              if (snapshotConfig.checkSourceFile) {
                const suiteSourceFilePath = path.join(config.basePath, suiteName);
                if (!fs.existsSync(suiteSourceFilePath)) {
                  logger.error(
                    'Failed to save snapshot file. ' +
                    'Source file "' + suiteSourceFilePath + '" does not exist.'
                  );
                  return;
                }
              }

              const snapshotPath = snapshotConfig.pathResolver(config.basePath, suiteName);
              const snapshotDir = path.dirname(snapshotPath);
              if (!fs.existsSync(snapshotDir)) {
                mkdirp.sync(snapshotDir);
              }
              fs.writeFileSync(
                snapshotPath,
                snapshotSerializer.serialize(suiteName, suite)
              );
            }
          });
        }
      }
    } else {
      logger.warn('Snapshot data is unavailable');
    }
  });
}
function snapshotFramework(files, config, emitter, loggerFactory) {
  const logger = loggerFactory.create('framework.snapshot');

  const snapshotConfig = Object.assign({
    update: false,
    prune: false,
    format: "md",
    checkSourceFile: false,
    pathResolver: defaultPathResolver,
    limitUnusedSnapshotsInWarning: -1
  }, config.snapshot);

  if (typeof snapshotConfig.format === "string") {
    switch (snapshotConfig.format) {
      case "indented-md":
        snapshotSerializer = createMarkdownSerializer(true);
        break;
      case "md":
      default:
        snapshotSerializer = createMarkdownSerializer(false);
    }
  } else {
    snapshotSerializer = snapshotConfig.format;
  }

  // it should be in a files list after `adapter.js`
  if (snapshotConfig.update) {
    files.unshift(filePattern(path.join(__dirname, 'snapshot-state-update.js')));
  }

  // inject snapshot adapter
  files.unshift(filePattern(path.join(__dirname, 'adapter.js')));

  emitter.on('browser_complete', (clientInfo, data) => {
    const lastResult = clientInfo.lastResult;

    if (!lastResult.disconnected) {
      if (data && data.snapshot) {
        let rootSuite = data.snapshot;
        let dirty = rootSuite.dirty;

        // prune dead snapshots
        if (!lastResult.error && lastResult.failed === 0 && lastResult.skipped === 0) {
          const prunedSnapshots = prune.pruneSnapshots(rootSuite);
          if (prunedSnapshots.pruned.length > 0) {
            if (snapshotConfig.prune) {
              const prunedList = formatSnapshotList(prunedSnapshots.pruned)
              logger.warn(`Removed ${prunedSnapshots.pruned.length} unused snapshots:\n${prunedList}`);
              rootSuite = prunedSnapshots.suite;
              prune.pruneFiles(snapshotConfig.pathResolver, config.basePath, prunedSnapshots.prunedFiles);
              dirty = true;
            } else {
              logger.warn(formatUnusedSnapshotsWarning(prunedSnapshots.pruned, snapshotConfig.limitUnusedSnapshotsInWarning));
            }
          }
        }

        if (dirty) {
          Object.keys(rootSuite.children).forEach((suiteName) => {
            const suite = rootSuite.children[suiteName];
            if (suite.dirty) {
              if (snapshotConfig.checkSourceFile) {
                const suiteSourceFilePath = path.join(config.basePath, suiteName);
                if (!fs.existsSync(suiteSourceFilePath)) {
                  logger.error(
                    'Failed to save snapshot file. ' +
                    'Source file "' + suiteSourceFilePath + '" does not exist.'
                  );
                  return;
                }
              }

              const snapshotPath = snapshotConfig.pathResolver(config.basePath, suiteName);
              const snapshotDir = path.dirname(snapshotPath);
              if (!fs.existsSync(snapshotDir)) {
                mkdirp.sync(snapshotDir);
              }
              fs.writeFileSync(
                snapshotPath,
                snapshotSerializer.serialize(suiteName, suite)
              );
            }
          });
        }
      }
    } else {
      logger.warn('Snapshot data is unavailable');
    }
  });
}
snapshotFramework

@param {*} files Karma file patterns.
@param {*} config Karma config.
@param {*} emitter Karma emitter.
@param {*} loggerFactory Karma logger factory.