From 2b309df197aeb9e1ba5dd8d1e2d7cfede3e617a4 Mon Sep 17 00:00:00 2001 From: Craig Spence Date: Tue, 1 Jun 2021 21:25:28 +1200 Subject: [PATCH] =?UTF-8?q?feat(betterer=20=E2=9C=A8):=20add=20global=20fi?= =?UTF-8?q?le=20cache=20(#712)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 3 +- .prettierignore | 3 +- goldens/api/@betterer/betterer.d.ts | 4 + goldens/api/@betterer/cli.d.ts | 9 +- packages/betterer/src/config/config.ts | 11 +- packages/betterer/src/config/types.ts | 4 + packages/betterer/src/context/context.ts | 11 +- packages/betterer/src/context/run.ts | 9 +- packages/betterer/src/index.ts | 12 +- packages/betterer/src/runner/file-manager.ts | 73 +++ .../file-test => runner}/file-resolver.ts | 19 +- packages/betterer/src/runner/index.ts | 4 +- packages/betterer/src/runner/public.ts | 9 +- packages/betterer/src/runner/runner.ts | 7 +- packages/betterer/src/runner/types.ts | 3 + .../src/test/file-test/file-test-result.ts | 3 +- .../betterer/src/test/file-test/file-test.ts | 33 +- packages/betterer/src/test/file-test/file.ts | 2 +- packages/betterer/src/test/file-test/index.ts | 3 - .../betterer/src/test/file-test/public.ts | 3 - packages/betterer/src/test/file-test/types.ts | 3 - packages/betterer/src/test/index.ts | 6 +- packages/betterer/src/test/public.ts | 3 - packages/betterer/src/writer.ts | 6 +- packages/cli/src/index.ts | 1 + packages/cli/src/options.ts | 7 + packages/cli/src/start.ts | 17 +- packages/cli/src/types.ts | 25 +- packages/cli/src/watch.ts | 4 +- .../__snapshots__/betterer-cache.spec.ts.snap | 446 ++++++++++++++++++ .../betterer-config.spec.ts.snap | 60 +++ .../__snapshots__/betterer-worse.spec.ts.snap | 36 +- test/betterer-cache.spec.ts | 63 +++ test/betterer-config.spec.ts | 6 + test/betterer-worse.spec.ts | 2 +- .../__snapshots__/betterer-ci.spec.ts.snap | 36 +- test/cli/betterer-ci.spec.ts | 2 +- 37 files changed, 832 insertions(+), 116 deletions(-) create mode 100644 packages/betterer/src/runner/file-manager.ts rename packages/betterer/src/{test/file-test => runner}/file-resolver.ts (85%) create mode 100644 test/__snapshots__/betterer-cache.spec.ts.snap create mode 100644 test/betterer-cache.spec.ts diff --git a/.gitignore b/.gitignore index f60e65962..cdaaf2f60 100644 --- a/.gitignore +++ b/.gitignore @@ -11,4 +11,5 @@ website/build website/.docusaurus packages/extension/.vscode-test *.patch -betterer.*.log \ No newline at end of file +betterer.*.log +.betterer.cache diff --git a/.prettierignore b/.prettierignore index cb53f5dd2..c00b1e862 100644 --- a/.prettierignore +++ b/.prettierignore @@ -27,6 +27,7 @@ website/.docusaurus *.patch CHANGELOG.md betterer.log +.betterer.cache website/static/.nojekyll website/static/videos/start.mp4 -website/static/videos/watch.mp4 \ No newline at end of file +website/static/videos/watch.mp4 diff --git a/goldens/api/@betterer/betterer.d.ts b/goldens/api/@betterer/betterer.d.ts index 43b10ee69..59d1549a5 100644 --- a/goldens/api/@betterer/betterer.d.ts +++ b/goldens/api/@betterer/betterer.d.ts @@ -5,6 +5,8 @@ export declare namespace betterer { } export declare type BettererConfig = { + cache: boolean; + cachePath: string; configPaths: BettererConfigPaths; cwd: string; filePaths: BettererConfigPaths; @@ -127,6 +129,8 @@ export declare type BettererFileTestResult = { }; export declare type BettererOptionsBase = Partial<{ + cache: boolean; + cachePath: string; configPaths: BettererOptionsPaths; cwd: string; filters: BettererOptionsFilters; diff --git a/goldens/api/@betterer/cli.d.ts b/goldens/api/@betterer/cli.d.ts index 65df4f8bf..8aadff9f3 100644 --- a/goldens/api/@betterer/cli.d.ts +++ b/goldens/api/@betterer/cli.d.ts @@ -9,6 +9,11 @@ export declare type BettererCLIBaseConfig = BettererCLIEnvConfig & { tsconfig: string; }; +export declare type BettererCLICacheConfig = { + cache: boolean; + cachePath: string; +}; + export declare type BettererCLICIConfig = BettererCLIBaseConfig & { exclude: BettererCLIArguments; include: BettererCLIArguments; @@ -23,14 +28,14 @@ export declare type BettererCLIInitConfig = BettererCLIEnvConfig & { config: string; }; -export declare type BettererCLIStartConfig = BettererCLIBaseConfig & { +export declare type BettererCLIStartConfig = BettererCLIBaseConfig & BettererCLICacheConfig & { exclude: BettererCLIArguments; include: BettererCLIArguments; strict: boolean; update: boolean; }; -export declare type BettererCLIWatchConfig = BettererCLIBaseConfig & { +export declare type BettererCLIWatchConfig = BettererCLIBaseConfig & BettererCLICacheConfig & { ignore: BettererCLIArguments; }; diff --git a/packages/betterer/src/config/config.ts b/packages/betterer/src/config/config.ts index b503c1b85..1fb9f92a7 100644 --- a/packages/betterer/src/config/config.ts +++ b/packages/betterer/src/config/config.ts @@ -5,7 +5,7 @@ import * as path from 'path'; import { registerExtensions } from '../register'; import { BettererReporterΩ, DEFAULT_REPORTER, loadReporters } from '../reporters'; -import { BettererFileResolverΩ } from '../test'; +import { BettererFileResolverΩ } from '../runner'; import { isBoolean, isRegExp, isString, isUndefined } from '../utils'; import { BettererConfig, @@ -47,6 +47,8 @@ async function processOptions(options: unknown = {}): Promise { const relativeConfig: BettererConfig = { // Base: + cache: baseOptions.cache || false, + cachePath: baseOptions.cachePath || './.betterer.cache', configPaths: baseOptions.configPaths ? toArray(baseOptions.configPaths) : ['./.betterer'], cwd: baseOptions.cwd || process.cwd(), filters: toRegExps(toArray(baseOptions.filters)), @@ -74,11 +76,12 @@ async function processOptions(options: unknown = {}): Promise { const { includes, excludes } = startOptions; const resolver = new BettererFileResolverΩ(relativeConfig.cwd); - resolver.includeΔ(...toArray(includes)); - resolver.excludeΔ(...toRegExps(toArray(excludes))); + resolver.include(...toArray(includes)); + resolver.exclude(...toRegExps(toArray(excludes))); globalConfig = { ...relativeConfig, + cachePath: path.resolve(relativeConfig.cwd, relativeConfig.cachePath), filePaths: await resolver.files([]), configPaths: relativeConfig.configPaths.map((configPath) => path.resolve(relativeConfig.cwd, configPath)), resultsPath: path.resolve(relativeConfig.cwd, relativeConfig.resultsPath), @@ -99,6 +102,8 @@ export function getConfig(): BettererConfig { function validateConfig(config: BettererConfig): void { // Base: + validateBool('cache', config); + validateString('cachePath', config); validateStringArray('configPaths', config); validateString('cwd', config); validateStringRegExpArray('filters', config); diff --git a/packages/betterer/src/config/types.ts b/packages/betterer/src/config/types.ts index 881ff13fd..ee2d9761f 100644 --- a/packages/betterer/src/config/types.ts +++ b/packages/betterer/src/config/types.ts @@ -8,6 +8,8 @@ export type BettererConfigReporters = ReadonlyArray; export type BettererConfig = { // Base: + cache: boolean; + cachePath: string; configPaths: BettererConfigPaths; cwd: string; filePaths: BettererConfigPaths; @@ -33,6 +35,8 @@ export type BettererOptionsIncludes = Array | string; export type BettererOptionsReporters = Array; export type BettererOptionsBase = Partial<{ + cache: boolean; + cachePath: string; configPaths: BettererOptionsPaths; cwd: string; filters: BettererOptionsFilters; diff --git a/packages/betterer/src/context/context.ts b/packages/betterer/src/context/context.ts index 3ed557583..c21c48d8c 100644 --- a/packages/betterer/src/context/context.ts +++ b/packages/betterer/src/context/context.ts @@ -6,7 +6,7 @@ import { BettererConfig } from '../config'; import { BettererReporterΩ } from '../reporters'; import { requireUncached } from '../require'; import { BettererResultsΩ, BettererResultΩ } from '../results'; -import { BettererFilePaths } from '../runner'; +import { BettererFileManager } from '../runner'; import { defer, Defer } from '../utils'; import { BettererTest, @@ -58,7 +58,7 @@ export class BettererContextΩ implements BettererContext { }; } - public async run(filePaths: BettererFilePaths = []): Promise { + public async run(fileManager: BettererFileManager): Promise { if (this._running) { await this._running; } @@ -71,7 +71,9 @@ export class BettererContextΩ implements BettererContext { let testNames = Object.keys(this._tests); // Only run BettererFileTests when a list of filePaths is given: - if (filePaths.length) { + const { filePaths } = fileManager; + const runFileTests = filePaths.length > 0; + if (runFileTests) { testNames = testNames.filter((name) => isBettererFileTestΔ(this._tests[name])); } @@ -82,7 +84,7 @@ export class BettererContextΩ implements BettererContext { const isObsolete = obsolete.includes(name); const baseline = await this._results.getBaseline(name, config); const expected = await this._results.getExpectedResult(name, config); - return new BettererRunΩ(this._reporter, name, config, expected, baseline, filePaths, isSkipped, isObsolete); + return new BettererRunΩ(this._reporter, name, config, expected, baseline, fileManager, isSkipped, isObsolete); }) ); const runsLifecycle = defer(); @@ -103,6 +105,7 @@ export class BettererContextΩ implements BettererContext { runsLifecycle.resolve(summary); await reportRunsStart; await this._reporter.runsEnd(summary, filePaths); + return summary; } diff --git a/packages/betterer/src/context/run.ts b/packages/betterer/src/context/run.ts index c6b709e29..101784980 100644 --- a/packages/betterer/src/context/run.ts +++ b/packages/betterer/src/context/run.ts @@ -6,6 +6,7 @@ import { BettererResult } from '../results'; import { BettererFilePaths } from '../runner'; import { BettererDiff, BettererTestConfig } from '../test'; import { Defer, defer } from '../utils'; +import { BettererFileManager } from '../runner/file-manager'; import { BettererDelta, BettererRun, BettererRunStarted } from './types'; enum BettererRunStatus { @@ -38,7 +39,7 @@ export class BettererRunΩ implements BettererRun { private readonly _test: BettererTestConfig, private readonly _expected: BettererResult, private readonly _baseline: BettererResult, - private readonly _filePaths: BettererFilePaths, + private readonly _fileManager: BettererFileManager, isSkipped: boolean, isObsolete: boolean ) { @@ -65,7 +66,11 @@ export class BettererRunΩ implements BettererRun { } public get filePaths(): BettererFilePaths { - return this._filePaths; + return this._fileManager.filePaths; + } + + public get fileManager(): BettererFileManager { + return this._fileManager; } public get delta(): BettererDelta | null { diff --git a/packages/betterer/src/index.ts b/packages/betterer/src/index.ts index 67a12fa14..d20190e04 100644 --- a/packages/betterer/src/index.ts +++ b/packages/betterer/src/index.ts @@ -32,14 +32,18 @@ export { } from './context/public'; export { BettererResult } from './results/public'; export { BettererReporter } from './reporters/public'; -export { BettererFilePaths, BettererRunner, BettererRunHandler } from './runner/public'; export { - BettererDeserialise, - BettererDiff, - BettererDiffer, BettererFileGlobs, + BettererFilePaths, BettererFilePatterns, BettererFileResolver, + BettererRunner, + BettererRunHandler +} from './runner/public'; +export { + BettererDeserialise, + BettererDiff, + BettererDiffer, BettererFileTest, BettererFileTestFunction, BettererFile, diff --git a/packages/betterer/src/runner/file-manager.ts b/packages/betterer/src/runner/file-manager.ts new file mode 100644 index 000000000..4254c486e --- /dev/null +++ b/packages/betterer/src/runner/file-manager.ts @@ -0,0 +1,73 @@ +import { BettererConfig } from '../config'; +import { createHash } from '../hasher'; +import { read } from '../reader'; +import { write } from '../writer'; +import { BettererFileResolverΩ } from './file-resolver'; +import { BettererFilePaths } from './types'; + +type BettererCache = Record; + +export class BettererFileManager { + private _cache: boolean; + private _cachePath: string; + private _cacheMap: BettererCache = {}; + + constructor(config: BettererConfig, private readonly _filePaths: BettererFilePaths) { + this._cache = config.cache; + this._cachePath = config.cachePath; + } + + public get filePaths(): BettererFilePaths { + return this._filePaths; + } + + public async readCache(): Promise { + if (!this._cache) { + return; + } + + const cache = await read(this._cachePath); + if (!cache) { + return; + } + + this._cacheMap = JSON.parse(cache) as BettererCache; + } + + public async writeCache(): Promise { + if (!this._cache) { + return; + } + await write(JSON.stringify(this._cacheMap, null, ' '), this._cachePath); + } + + public async getRequested(resolver: BettererFileResolverΩ): Promise { + return await resolver.files(this.filePaths); + } + + public async getActual(resolver: BettererFileResolverΩ): Promise { + const requestedFilePaths = await this.getRequested(resolver); + + if (!this._cache) { + return requestedFilePaths; + } + + const actualFilePaths: Array = []; + await Promise.all( + requestedFilePaths.map(async (filePath) => { + const content = await read(filePath); + if (content == null) { + return; + } + const hash = createHash(content); + const relativePath = filePath.replace(resolver.cwd, ''); + if (!this._cacheMap[relativePath] || this._cacheMap[relativePath] !== hash) { + actualFilePaths.push(filePath); + } + this._cacheMap[relativePath] = hash; + }) + ); + + return actualFilePaths; + } +} diff --git a/packages/betterer/src/test/file-test/file-resolver.ts b/packages/betterer/src/runner/file-resolver.ts similarity index 85% rename from packages/betterer/src/test/file-test/file-resolver.ts rename to packages/betterer/src/runner/file-resolver.ts index b3cf482d5..c588f676e 100644 --- a/packages/betterer/src/test/file-test/file-resolver.ts +++ b/packages/betterer/src/runner/file-resolver.ts @@ -2,15 +2,16 @@ import stack from 'callsite'; import globby from 'globby'; import * as path from 'path'; -import { BettererFilePaths } from '../../runner'; -import { flatten, normalisedPath } from '../../utils'; -import { BettererFileGlobs, BettererFilePatterns } from './types'; +import { flatten, normalisedPath } from '../utils'; +import { BettererFileGlobs, BettererFilePaths, BettererFilePatterns } from './types'; export class BettererFileResolverΩ { private _excluded: Array = []; private _included: Array = []; - constructor(private _cwd: string) {} + constructor(private _cwd: string) { + this._cwd = normalisedPath(this._cwd); + } public get cwd(): string { return this._cwd; @@ -28,14 +29,12 @@ export class BettererFileResolverΩ { return normalisedPath(path.resolve(this._cwd, ...pathSegments)); } - /** @internal Definitely not stable! Please don't use! */ - public includeΔ(...includePatterns: BettererFileGlobs): this { + public include(...includePatterns: BettererFileGlobs): this { this._included = [...this._included, ...flatten(includePatterns).map((pattern) => this.resolve(pattern))]; return this; } - /** @internal Definitely not stable! Please don't use! */ - public excludeΔ(...excludePatterns: BettererFilePatterns): this { + public exclude(...excludePatterns: BettererFilePatterns): this { this._excluded = [...this._excluded, ...flatten(excludePatterns)]; return this; } @@ -104,13 +103,13 @@ export class BettererFileResolver { /** @internal Definitely not stable! Please don't use! */ public includeΔ(...includePatterns: BettererFileGlobs): this { - this._resolver.includeΔ(...includePatterns); + this._resolver.include(...includePatterns); return this; } /** @internal Definitely not stable! Please don't use! */ public excludeΔ(...excludePatterns: BettererFilePatterns): this { - this._resolver.excludeΔ(...excludePatterns); + this._resolver.exclude(...excludePatterns); return this; } diff --git a/packages/betterer/src/runner/index.ts b/packages/betterer/src/runner/index.ts index 2ce3d7216..5998e633c 100644 --- a/packages/betterer/src/runner/index.ts +++ b/packages/betterer/src/runner/index.ts @@ -1,3 +1,5 @@ +export { BettererFileManager } from './file-manager'; +export { BettererFileResolver, BettererFileResolverΩ } from './file-resolver'; export { BettererRunnerΩ } from './runner'; -export { BettererFilePaths, BettererRunner } from './types'; +export { BettererFileGlobs, BettererFilePaths, BettererFilePatterns, BettererRunner } from './types'; export { BettererWatcherΩ } from './watcher'; diff --git a/packages/betterer/src/runner/public.ts b/packages/betterer/src/runner/public.ts index a2c07fddd..58145516b 100644 --- a/packages/betterer/src/runner/public.ts +++ b/packages/betterer/src/runner/public.ts @@ -1 +1,8 @@ -export { BettererFilePaths, BettererRunner, BettererRunHandler } from './types'; +export { BettererFileResolver } from './file-resolver'; +export { + BettererFileGlobs, + BettererFilePaths, + BettererFilePatterns, + BettererRunner, + BettererRunHandler +} from './types'; diff --git a/packages/betterer/src/runner/runner.ts b/packages/betterer/src/runner/runner.ts index f845d3f1a..6e4849fd8 100644 --- a/packages/betterer/src/runner/runner.ts +++ b/packages/betterer/src/runner/runner.ts @@ -4,6 +4,7 @@ import { BettererConfig } from '../config'; import { BettererContextΩ, BettererContextStarted, BettererSummary } from '../context'; import { BettererReporterΩ } from '../reporters'; import { normalisedPath } from '../utils'; +import { BettererFileManager } from './file-manager'; import { BettererFilePaths, BettererRunHandler, BettererRunner, BettererRunnerJobs } from './types'; const DEBOUNCE_TIME = 200; @@ -74,7 +75,11 @@ export class BettererRunnerΩ implements BettererRunner { private async _runTests(filePaths: BettererFilePaths): Promise { try { - return this._context.run(filePaths); + const fileManager = new BettererFileManager(this._context.config, filePaths); + await fileManager.readCache(); + const summary = await this._context.run(fileManager); + await fileManager.writeCache(); + return summary; } catch (error) { await this._started.error(error); throw error; diff --git a/packages/betterer/src/runner/types.ts b/packages/betterer/src/runner/types.ts index 205835298..63ea9d49e 100644 --- a/packages/betterer/src/runner/types.ts +++ b/packages/betterer/src/runner/types.ts @@ -1,6 +1,9 @@ import { BettererSummary } from '../context'; +export type BettererFileGlobs = ReadonlyArray>; export type BettererFilePaths = ReadonlyArray; +export type BettererFilePatterns = ReadonlyArray>; + export type BettererRunHandler = (summary: BettererSummary) => void; export type BettererRunner = { diff --git a/packages/betterer/src/test/file-test/file-test-result.ts b/packages/betterer/src/test/file-test/file-test-result.ts index 47d40594e..a61719919 100644 --- a/packages/betterer/src/test/file-test/file-test-result.ts +++ b/packages/betterer/src/test/file-test/file-test-result.ts @@ -1,9 +1,8 @@ import assert from 'assert'; import { createHash } from '../../hasher'; -import { BettererFilePaths } from '../../runner'; +import { BettererFilePaths, BettererFileResolverΩ } from '../../runner'; import { BettererFileΩ } from './file'; -import { BettererFileResolverΩ } from './file-resolver'; import { BettererFileTestResult, BettererFileIssues, BettererFile, BettererFileBase } from './types'; export class BettererFileTestResultΩ implements BettererFileTestResult { diff --git a/packages/betterer/src/test/file-test/file-test.ts b/packages/betterer/src/test/file-test/file-test.ts index f54d36131..5b88a390e 100644 --- a/packages/betterer/src/test/file-test/file-test.ts +++ b/packages/betterer/src/test/file-test/file-test.ts @@ -1,18 +1,16 @@ -import { BettererRun } from '../../context'; +import { BettererRun, BettererRunΩ } from '../../context'; import { createTestConfig } from '../config'; +import { BettererFileResolver, BettererFileResolverΩ, BettererFileGlobs, BettererFilePatterns } from '../../runner'; import { BettererTestType } from '../type'; import { BettererTestConstraint, BettererTestFunction, BettererTestGoal } from '../types'; import { constraint } from './constraint'; import { differ } from './differ'; -import { BettererFileResolver, BettererFileResolverΩ } from './file-resolver'; import { BettererFileTestResultΩ } from './file-test-result'; import { goal } from './goal'; import { printer } from './printer'; import { progress } from './progress'; import { deserialise, serialise } from './serialiser'; import { - BettererFileGlobs, - BettererFilePatterns, BettererFileTestBase, BettererFileTestConfig, BettererFileTestFunction, @@ -60,7 +58,7 @@ export class BettererFileTest implements BettererFileTestBase { } public exclude(...excludePatterns: BettererFilePatterns): this { - this._resolver.excludeΔ(...excludePatterns); + this._resolver.exclude(...excludePatterns); return this; } @@ -70,7 +68,7 @@ export class BettererFileTest implements BettererFileTestBase { } public include(...includePatterns: BettererFileGlobs): this { - this._resolver.includeΔ(...includePatterns); + this._resolver.include(...includePatterns); return this; } @@ -90,28 +88,35 @@ function createTest( fileTest: BettererFileTestFunction ): BettererTestFunction { return async (run: BettererRun): Promise => { - const { filePaths } = run; + const { fileManager } = run as BettererRunΩ; - const relevantFilePaths = await resolver.files(filePaths); - const files = new BettererFileTestResultΩ(resolver); - await fileTest(relevantFilePaths, files); + // Get the set of files that are relevant for the test run + const requestedFilePaths = await fileManager.getRequested(resolver); + // Get the set of files that actually need to be tested (because of caching etc.) + const actualFilePaths = await fileManager.getActual(resolver); - if (filePaths.length && !run.isNew) { + const isPartialRun = requestedFilePaths.length !== 0; + + const result = new BettererFileTestResultΩ(resolver); + await fileTest(actualFilePaths, result); + + if (isPartialRun && !run.isNew) { const expectedΩ = run.expected.value as BettererFileTestResultΩ; // Get any filePaths that have expected issues but weren't included in this run: const excludedFilesWithIssues = expectedΩ.files .map((file) => file.absolutePath) - .filter((filePath) => !filePaths.includes(filePath)); + .filter((filePath) => !actualFilePaths.includes(filePath)); // Filter them based on the current resolver: const relevantExcludedFilePaths = await resolver.validate(excludedFilesWithIssues); // Add the existing issues to the new result: relevantExcludedFilePaths.forEach((filePath) => { - files.addExpected(expectedΩ.getFile(filePath)); + result.addExpected(expectedΩ.getFile(filePath)); }); } - return files; + + return result; }; } diff --git a/packages/betterer/src/test/file-test/file.ts b/packages/betterer/src/test/file-test/file.ts index 9fdecb343..1fca449f8 100644 --- a/packages/betterer/src/test/file-test/file.ts +++ b/packages/betterer/src/test/file-test/file.ts @@ -3,8 +3,8 @@ import LinesAndColumns from 'lines-and-columns'; import { getConfig } from '../../config'; import { createHash } from '../../hasher'; +import { BettererFileResolverΩ } from '../../runner'; import { getRelativePath, isString } from '../../utils'; -import { BettererFileResolverΩ } from './file-resolver'; import { BettererFileIssue, BettererFileIssues, BettererFile } from './types'; const UNKNOWN_LOCATION = { diff --git a/packages/betterer/src/test/file-test/index.ts b/packages/betterer/src/test/file-test/index.ts index ac14dfb7e..75b4d8e41 100644 --- a/packages/betterer/src/test/file-test/index.ts +++ b/packages/betterer/src/test/file-test/index.ts @@ -1,9 +1,6 @@ export { BettererFileTest } from './file-test'; -export { BettererFileResolver, BettererFileResolverΩ } from './file-resolver'; export { BettererFileTestResult, - BettererFileGlobs, - BettererFilePatterns, BettererFileTestFunction, BettererFileBase, BettererFile, diff --git a/packages/betterer/src/test/file-test/public.ts b/packages/betterer/src/test/file-test/public.ts index f60f428ce..93402f184 100644 --- a/packages/betterer/src/test/file-test/public.ts +++ b/packages/betterer/src/test/file-test/public.ts @@ -1,11 +1,8 @@ export { BettererFileTest } from './file-test'; -export { BettererFileResolver } from './file-resolver'; export { BettererFileBase, BettererFile, BettererFileTestResult, - BettererFileGlobs, - BettererFilePatterns, BettererFileDiff, BettererFilesDiff, BettererFileTestDiff, diff --git a/packages/betterer/src/test/file-test/types.ts b/packages/betterer/src/test/file-test/types.ts index 333315903..9cb25b645 100644 --- a/packages/betterer/src/test/file-test/types.ts +++ b/packages/betterer/src/test/file-test/types.ts @@ -19,9 +19,6 @@ export type BettererFileTestFunction = ( fileTestResult: BettererFileTestResult ) => MaybeAsync; -export type BettererFileGlobs = ReadonlyArray>; -export type BettererFilePatterns = ReadonlyArray>; - export type BettererFileIssue = { readonly line: number; readonly column: number; diff --git a/packages/betterer/src/test/index.ts b/packages/betterer/src/test/index.ts index 000582c81..e30ca5d60 100644 --- a/packages/betterer/src/test/index.ts +++ b/packages/betterer/src/test/index.ts @@ -1,8 +1,6 @@ export { BettererFileTest, BettererFileTestResult, - BettererFileGlobs, - BettererFilePatterns, BettererFileTestFunction, BettererFileBase, BettererFile, @@ -10,9 +8,7 @@ export { BettererFileTestDiff, BettererFileDiff, BettererFileIssue, - BettererFileIssues, - BettererFileResolver, - BettererFileResolverΩ + BettererFileIssues } from './file-test'; export { BettererTest } from './test'; export { BettererTestType, isBettererFileTestΔ, isBettererTest } from './type'; diff --git a/packages/betterer/src/test/public.ts b/packages/betterer/src/test/public.ts index 2f3f98bba..e7e1b9df9 100644 --- a/packages/betterer/src/test/public.ts +++ b/packages/betterer/src/test/public.ts @@ -1,7 +1,4 @@ export { - BettererFileGlobs, - BettererFilePatterns, - BettererFileResolver, BettererFileTest, BettererFileTestFunction, BettererFileBase, diff --git a/packages/betterer/src/writer.ts b/packages/betterer/src/writer.ts index a2a9cd2b1..d615719a2 100644 --- a/packages/betterer/src/writer.ts +++ b/packages/betterer/src/writer.ts @@ -1,10 +1,10 @@ import { BettererError } from '@betterer/errors'; import { promises as fs } from 'fs'; -export async function write(toWrite: string, resultsPath: string): Promise { +export async function write(toWrite: string, filePath: string): Promise { try { - await fs.writeFile(resultsPath, toWrite, 'utf8'); + await fs.writeFile(filePath, toWrite, 'utf8'); } catch { - throw new BettererError(`could not write results to "${resultsPath}". 😔`); + throw new BettererError(`could not write to "${filePath}". 😔`); } } diff --git a/packages/cli/src/index.ts b/packages/cli/src/index.ts index 398cc0d89..a41e7b2d4 100644 --- a/packages/cli/src/index.ts +++ b/packages/cli/src/index.ts @@ -7,6 +7,7 @@ export { BettererCLIEnvConfig, BettererCLIInitConfig, BettererCLIBaseConfig, + BettererCLICacheConfig, BettererCLIStartConfig, BettererCLICIConfig, BettererCLIWatchConfig, diff --git a/packages/cli/src/options.ts b/packages/cli/src/options.ts index cc704ce68..401645b6c 100644 --- a/packages/cli/src/options.ts +++ b/packages/cli/src/options.ts @@ -27,6 +27,7 @@ export function initOptions(argv: BettererCLIArguments): BettererCLIInitConfig { } export function startOptions(argv: BettererCLIArguments): BettererCLIStartConfig { + cacheOption(); configPathsOption(); resultsPathOption(); tsconfigPathOption(); @@ -42,6 +43,7 @@ export function startOptions(argv: BettererCLIArguments): BettererCLIStartConfig } export function watchOptions(argv: BettererCLIArguments): BettererCLIWatchConfig { + cacheOption(); configPathsOption(); resultsPathOption(); tsconfigPathOption(); @@ -68,6 +70,11 @@ function setEnv(argv: BettererCLIArguments): T & return parsed; } +function cacheOption(): void { + commander.option('--cache', 'When present, Betterer will only run on changed files.'); + commander.option('--cachePath [value]', 'Path to Betterer cache file relative to CWD'); +} + function configPathOption(): void { commander.option('-c, --config [value]', 'Path to test definition file relative to CWD'); } diff --git a/packages/cli/src/start.ts b/packages/cli/src/start.ts index 9d1efa891..10efbc782 100644 --- a/packages/cli/src/start.ts +++ b/packages/cli/src/start.ts @@ -5,10 +5,25 @@ import { BettererCLIArguments } from './types'; /** @internal Definitely not stable! Please don't use! */ export function startΔ(cwd: string, argv: BettererCLIArguments): Promise { - const { config, exclude, filter, include, results, reporter, silent, strict, tsconfig, update } = startOptions(argv); + const { + cache, + cachePath, + config, + exclude, + filter, + include, + results, + reporter, + silent, + strict, + tsconfig, + update + } = startOptions(argv); // Mark options as unknown... const options: unknown = { + cache, + cachePath, configPaths: config, cwd, excludes: exclude, diff --git a/packages/cli/src/types.ts b/packages/cli/src/types.ts index ac1ec39b3..91fd24386 100644 --- a/packages/cli/src/types.ts +++ b/packages/cli/src/types.ts @@ -14,6 +14,11 @@ export type BettererCLIBaseConfig = BettererCLIEnvConfig & { tsconfig: string; }; +export type BettererCLICacheConfig = { + cache: boolean; + cachePath: string; +}; + export type BettererCLICIConfig = BettererCLIBaseConfig & { exclude: BettererCLIArguments; include: BettererCLIArguments; @@ -23,16 +28,18 @@ export type BettererCLIInitConfig = BettererCLIEnvConfig & { config: string; }; -export type BettererCLIStartConfig = BettererCLIBaseConfig & { - exclude: BettererCLIArguments; - include: BettererCLIArguments; - strict: boolean; - update: boolean; -}; +export type BettererCLIStartConfig = BettererCLIBaseConfig & + BettererCLICacheConfig & { + exclude: BettererCLIArguments; + include: BettererCLIArguments; + strict: boolean; + update: boolean; + }; -export type BettererCLIWatchConfig = BettererCLIBaseConfig & { - ignore: BettererCLIArguments; -}; +export type BettererCLIWatchConfig = BettererCLIBaseConfig & + BettererCLICacheConfig & { + ignore: BettererCLIArguments; + }; export type BettererPackageJSON = { version: string; diff --git a/packages/cli/src/watch.ts b/packages/cli/src/watch.ts index d0b4feff3..67971b7b0 100644 --- a/packages/cli/src/watch.ts +++ b/packages/cli/src/watch.ts @@ -5,10 +5,12 @@ import { BettererCLIArguments } from './types'; /** @internal Definitely not stable! Please don't use! */ export async function watchΔ(cwd: string, argv: BettererCLIArguments): Promise { - const { config, filter, ignore, reporter, results, silent, tsconfig } = watchOptions(argv); + const { cache, cachePath, config, filter, ignore, reporter, results, silent, tsconfig } = watchOptions(argv); // Mark options as unknown... const options: unknown = { + cache, + cachePath, configPaths: config, cwd, filters: filter, diff --git a/test/__snapshots__/betterer-cache.spec.ts.snap b/test/__snapshots__/betterer-cache.spec.ts.snap new file mode 100644 index 000000000..5d44616d6 --- /dev/null +++ b/test/__snapshots__/betterer-cache.spec.ts.snap @@ -0,0 +1,446 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`betterer should write a cache file 1`] = ` +"{ + \\"/src/index.ts\\": \\"4126639614\\" +}" +`; + +exports[`betterer should write a cache file 2`] = ` +"// BETTERER RESULTS V2. +exports[\`regexp no hack comments\`] = { + value: \`{ + \\"src/index.ts:4126639614\\": [ + [0, 0, 7, \\"RegExp match\\", \\"645651780\\"] + ] + }\` +}; +" +`; + +exports[`betterer should write a cache file 3`] = ` +Array [ + " + / | / _ _ _ + '-.ooo.-' | |__ ___| |_| |_ ___ _ __ ___ _ __ +---ooooo--- | '_ // _ / __| __/ _ / '__/ _ / '__| + .-'ooo'-. | |_)| __/ |_| || __/ | | __/ | + / | / |_.__//___|/__|/__/___|_| /___|_| + +", + " + / | / _ _ _ + '-.ooo.-' | |__ ___| |_| |_ ___ _ __ ___ _ __ +---ooooo--- | '_ // _ / __| __/ _ / '__/ _ / '__| + .-'ooo'-. | |_)| __/ |_| || __/ | | __/ | + / | / |_.__//___|/__|/__/___|_| /___|_| + +🌟 Betterer (0ms): + +", + " + / | / _ _ _ + '-.ooo.-' | |__ ___| |_| |_ ___ _ __ ___ _ __ +---ooooo--- | '_ // _ / __| __/ _ / '__/ _ / '__| + .-'ooo'-. | |_)| __/ |_| || __/ | | __/ | + / | / |_.__//___|/__|/__/___|_| /___|_| + +🌟 Betterer (0ms): 1 test running... +🤔 regexp no hack comments: running \\"regexp no hack comments\\"! + +", + " + / | / _ _ _ + '-.ooo.-' | |__ ___| |_| |_ ___ _ __ ___ _ __ +---ooooo--- | '_ // _ / __| __/ _ / '__/ _ / '__| + .-'ooo'-. | |_)| __/ |_| || __/ | | __/ | + / | / |_.__//___|/__|/__/___|_| /___|_| + +🌟 Betterer (0ms): 1 test running... +✅ regexp no hack comments: \\"regexp no hack comments\\" got checked for the first time! (1 issue) 🎉 + +", + " + / | / _ _ _ + '-.ooo.-' | |__ ___| |_| |_ ___ _ __ ___ _ __ +---ooooo--- | '_ // _ / __| __/ _ / '__/ _ / '__| + .-'ooo'-. | |_)| __/ |_| || __/ | | __/ | + / | / |_.__//___|/__|/__/___|_| /___|_| + +🎉 Betterer (0ms): 1 test done! +✅ regexp no hack comments: \\"regexp no hack comments\\" got checked for the first time! (1 issue) 🎉 + +", + " + / | / _ _ _ + '-.ooo.-' | |__ ___| |_| |_ ___ _ __ ___ _ __ +---ooooo--- | '_ // _ / __| __/ _ / '__/ _ / '__| + .-'ooo'-. | |_)| __/ |_| || __/ | | __/ | + / | / |_.__//___|/__|/__/___|_| /___|_| + +🎉 Betterer (0ms): 1 test done! +✅ regexp no hack comments: \\"regexp no hack comments\\" got checked for the first time! (1 issue) 🎉 + +1 test got checked. 🤔 +1 test got checked for the first time! 🎉 + +", + " + / | / _ _ _ + '-.ooo.-' | |__ ___| |_| |_ ___ _ __ ___ _ __ +---ooooo--- | '_ // _ / __| __/ _ / '__/ _ / '__| + .-'ooo'-. | |_)| __/ |_| || __/ | | __/ | + / | / |_.__//___|/__|/__/___|_| /___|_| + +", + " + / | / _ _ _ + '-.ooo.-' | |__ ___| |_| |_ ___ _ __ ___ _ __ +---ooooo--- | '_ // _ / __| __/ _ / '__/ _ / '__| + .-'ooo'-. | |_)| __/ |_| || __/ | | __/ | + / | / |_.__//___|/__|/__/___|_| /___|_| + +🌟 Betterer (0ms): + +", + " + / | / _ _ _ + '-.ooo.-' | |__ ___| |_| |_ ___ _ __ ___ _ __ +---ooooo--- | '_ // _ / __| __/ _ / '__/ _ / '__| + .-'ooo'-. | |_)| __/ |_| || __/ | | __/ | + / | / |_.__//___|/__|/__/___|_| /___|_| + +🌟 Betterer (0ms): 1 test running... +🤔 regexp no hack comments: running \\"regexp no hack comments\\"! + +", + " + / | / _ _ _ + '-.ooo.-' | |__ ___| |_| |_ ___ _ __ ___ _ __ +---ooooo--- | '_ // _ / __| __/ _ / '__/ _ / '__| + .-'ooo'-. | |_)| __/ |_| || __/ | | __/ | + / | / |_.__//___|/__|/__/___|_| /___|_| + +🌟 Betterer (0ms): 1 test running... +✅ regexp no hack comments: \\"regexp no hack comments\\" stayed the same. (1 issue) 😐 + +", + " + / | / _ _ _ + '-.ooo.-' | |__ ___| |_| |_ ___ _ __ ___ _ __ +---ooooo--- | '_ // _ / __| __/ _ / '__/ _ / '__| + .-'ooo'-. | |_)| __/ |_| || __/ | | __/ | + / | / |_.__//___|/__|/__/___|_| /___|_| + +🎉 Betterer (0ms): 1 test done! +✅ regexp no hack comments: \\"regexp no hack comments\\" stayed the same. (1 issue) 😐 + +", + " + / | / _ _ _ + '-.ooo.-' | |__ ___| |_| |_ ___ _ __ ___ _ __ +---ooooo--- | '_ // _ / __| __/ _ / '__/ _ / '__| + .-'ooo'-. | |_)| __/ |_| || __/ | | __/ | + / | / |_.__//___|/__|/__/___|_| /___|_| + +🎉 Betterer (0ms): 1 test done! +✅ regexp no hack comments: \\"regexp no hack comments\\" stayed the same. (1 issue) 😐 + +1 test got checked. 🤔 +1 test stayed the same. 😐 + +", + " + / | / _ _ _ + '-.ooo.-' | |__ ___| |_| |_ ___ _ __ ___ _ __ +---ooooo--- | '_ // _ / __| __/ _ / '__/ _ / '__| + .-'ooo'-. | |_)| __/ |_| || __/ | | __/ | + / | / |_.__//___|/__|/__/___|_| /___|_| + +", + " + / | / _ _ _ + '-.ooo.-' | |__ ___| |_| |_ ___ _ __ ___ _ __ +---ooooo--- | '_ // _ / __| __/ _ / '__/ _ / '__| + .-'ooo'-. | |_)| __/ |_| || __/ | | __/ | + / | / |_.__//___|/__|/__/___|_| /___|_| + +🌟 Betterer (0ms): + +", + " + / | / _ _ _ + '-.ooo.-' | |__ ___| |_| |_ ___ _ __ ___ _ __ +---ooooo--- | '_ // _ / __| __/ _ / '__/ _ / '__| + .-'ooo'-. | |_)| __/ |_| || __/ | | __/ | + / | / |_.__//___|/__|/__/___|_| /___|_| + +🌟 Betterer (0ms): 1 test running... +🤔 regexp no hack comments: running \\"regexp no hack comments\\"! + +", + " + / | / _ _ _ + '-.ooo.-' | |__ ___| |_| |_ ___ _ __ ___ _ __ +---ooooo--- | '_ // _ / __| __/ _ / '__/ _ / '__| + .-'ooo'-. | |_)| __/ |_| || __/ | | __/ | + / | / |_.__//___|/__|/__/___|_| /___|_| + +🌟 Betterer (0ms): 1 test running... +・ 1 existing issue in \\"/fixtures/test-betterer-cache/src/index.ts\\". +🤔 regexp no hack comments: running \\"regexp no hack comments\\"! + +", + " + / | / _ _ _ + '-.ooo.-' | |__ ___| |_| |_ ___ _ __ ___ _ __ +---ooooo--- | '_ // _ / __| __/ _ / '__/ _ / '__| + .-'ooo'-. | |_)| __/ |_| || __/ | | __/ | + / | / |_.__//___|/__|/__/___|_| /___|_| + +🌟 Betterer (0ms): 1 test running... +・ 1 existing issue in \\"/fixtures/test-betterer-cache/src/index.ts\\". +・ 1 new issue in \\"/fixtures/test-betterer-cache/src/index.ts\\": +🤔 regexp no hack comments: running \\"regexp no hack comments\\"! + +", + " + / | / _ _ _ + '-.ooo.-' | |__ ___| |_| |_ ___ _ __ ___ _ __ +---ooooo--- | '_ // _ / __| __/ _ / '__/ _ / '__| + .-'ooo'-. | |_)| __/ |_| || __/ | | __/ | + / | / |_.__//___|/__|/__/___|_| /___|_| + +🌟 Betterer (0ms): 1 test running... +・ 1 existing issue in \\"/fixtures/test-betterer-cache/src/index.ts\\". +・ 1 new issue in \\"/fixtures/test-betterer-cache/src/index.ts\\": +・ +・ /fixtures/test-betterer-cache/src/index.ts +・ 1 | // HACK: +・ > 2 | // HACK: +・ | ^^^^^^^ RegExp match +・ +🤔 regexp no hack comments: running \\"regexp no hack comments\\"! + +", + " + / | / _ _ _ + '-.ooo.-' | |__ ___| |_| |_ ___ _ __ ___ _ __ +---ooooo--- | '_ // _ / __| __/ _ / '__/ _ / '__| + .-'ooo'-. | |_)| __/ |_| || __/ | | __/ | + / | / |_.__//___|/__|/__/___|_| /___|_| + +🌟 Betterer (0ms): 1 test running... +・ 1 existing issue in \\"/fixtures/test-betterer-cache/src/index.ts\\". +・ 1 new issue in \\"/fixtures/test-betterer-cache/src/index.ts\\": +・ +・ /fixtures/test-betterer-cache/src/index.ts +・ 1 | // HACK: +・ > 2 | // HACK: +・ | ^^^^^^^ RegExp match +・ +🔥 regexp no hack comments: \\"regexp no hack comments\\" got worse. (1 new issue, 2 total) 😔 + +", + " + / | / _ _ _ + '-.ooo.-' | |__ ___| |_| |_ ___ _ __ ___ _ __ +---ooooo--- | '_ // _ / __| __/ _ / '__/ _ / '__| + .-'ooo'-. | |_)| __/ |_| || __/ | | __/ | + / | / |_.__//___|/__|/__/___|_| /___|_| + +🌟 Betterer (0ms): 1 test running... +🔥 regexp no hack comments: \\"regexp no hack comments\\" got worse. (1 new issue, 2 total) 😔 +・ 1 existing issue in \\"/fixtures/test-betterer-cache/src/index.ts\\". +・ 1 new issue in \\"/fixtures/test-betterer-cache/src/index.ts\\": +・ +・ /fixtures/test-betterer-cache/src/index.ts +・ 1 | // HACK: +・ > 2 | // HACK: +・ | ^^^^^^^ RegExp match +・ + +Error: \\"regexp no hack comments\\" got worse. (1 new issue, 2 total) 😔 + +", + " + / | / _ _ _ + '-.ooo.-' | |__ ___| |_| |_ ___ _ __ ___ _ __ +---ooooo--- | '_ // _ / __| __/ _ / '__/ _ / '__| + .-'ooo'-. | |_)| __/ |_| || __/ | | __/ | + / | / |_.__//___|/__|/__/___|_| /___|_| + +💥 Betterer (0ms): 1 test done! 1 test errored! +🔥 regexp no hack comments: \\"regexp no hack comments\\" got worse. (1 new issue, 2 total) 😔 +・ 1 existing issue in \\"/fixtures/test-betterer-cache/src/index.ts\\". +・ 1 new issue in \\"/fixtures/test-betterer-cache/src/index.ts\\": +・ +・ /fixtures/test-betterer-cache/src/index.ts +・ 1 | // HACK: +・ > 2 | // HACK: +・ | ^^^^^^^ RegExp match +・ + +Error: \\"regexp no hack comments\\" got worse. (1 new issue, 2 total) 😔 + +", + " + / | / _ _ _ + '-.ooo.-' | |__ ___| |_| |_ ___ _ __ ___ _ __ +---ooooo--- | '_ // _ / __| __/ _ / '__/ _ / '__| + .-'ooo'-. | |_)| __/ |_| || __/ | | __/ | + / | / |_.__//___|/__|/__/___|_| /___|_| + +💥 Betterer (0ms): 1 test done! 1 test errored! +🔥 regexp no hack comments: \\"regexp no hack comments\\" got worse. (1 new issue, 2 total) 😔 +・ 1 existing issue in \\"/fixtures/test-betterer-cache/src/index.ts\\". +・ 1 new issue in \\"/fixtures/test-betterer-cache/src/index.ts\\": +・ +・ /fixtures/test-betterer-cache/src/index.ts +・ 1 | // HACK: +・ > 2 | // HACK: +・ | ^^^^^^^ RegExp match +・ + +Error: \\"regexp no hack comments\\" got worse. (1 new issue, 2 total) 😔 + +1 test got checked. 🤔 +1 test got worse. 😔 + +You should try to fix the new issues! As a last resort, you can run \`betterer --update\` to force an update of the results file. 🆙 + +", + " + / | / _ _ _ + '-.ooo.-' | |__ ___| |_| |_ ___ _ __ ___ _ __ +---ooooo--- | '_ // _ / __| __/ _ / '__/ _ / '__| + .-'ooo'-. | |_)| __/ |_| || __/ | | __/ | + / | / |_.__//___|/__|/__/___|_| /___|_| + +", + " + / | / _ _ _ + '-.ooo.-' | |__ ___| |_| |_ ___ _ __ ___ _ __ +---ooooo--- | '_ // _ / __| __/ _ / '__/ _ / '__| + .-'ooo'-. | |_)| __/ |_| || __/ | | __/ | + / | / |_.__//___|/__|/__/___|_| /___|_| + +🌟 Betterer (0ms): + +", + " + / | / _ _ _ + '-.ooo.-' | |__ ___| |_| |_ ___ _ __ ___ _ __ +---ooooo--- | '_ // _ / __| __/ _ / '__/ _ / '__| + .-'ooo'-. | |_)| __/ |_| || __/ | | __/ | + / | / |_.__//___|/__|/__/___|_| /___|_| + +🌟 Betterer (0ms): 1 test running... +🤔 regexp no hack comments: running \\"regexp no hack comments\\"! + +", + " + / | / _ _ _ + '-.ooo.-' | |__ ___| |_| |_ ___ _ __ ___ _ __ +---ooooo--- | '_ // _ / __| __/ _ / '__/ _ / '__| + .-'ooo'-. | |_)| __/ |_| || __/ | | __/ | + / | / |_.__//___|/__|/__/___|_| /___|_| + +🌟 Betterer (0ms): 1 test running... +✅ regexp no hack comments: \\"regexp no hack comments\\" met its goal! 🎉 + +", + " + / | / _ _ _ + '-.ooo.-' | |__ ___| |_| |_ ___ _ __ ___ _ __ +---ooooo--- | '_ // _ / __| __/ _ / '__/ _ / '__| + .-'ooo'-. | |_)| __/ |_| || __/ | | __/ | + / | / |_.__//___|/__|/__/___|_| /___|_| + +🎉 Betterer (0ms): 1 test done! +✅ regexp no hack comments: \\"regexp no hack comments\\" met its goal! 🎉 + +", + " + / | / _ _ _ + '-.ooo.-' | |__ ___| |_| |_ ___ _ __ ___ _ __ +---ooooo--- | '_ // _ / __| __/ _ / '__/ _ / '__| + .-'ooo'-. | |_)| __/ |_| || __/ | | __/ | + / | / |_.__//___|/__|/__/___|_| /___|_| + +🎉 Betterer (0ms): 1 test done! +✅ regexp no hack comments: \\"regexp no hack comments\\" met its goal! 🎉 + +1 test got checked. 🤔 +1 test got better! 😍 +\\"regexp no hack comments\\" met its goal! 🎉) + +", + " + / | / _ _ _ + '-.ooo.-' | |__ ___| |_| |_ ___ _ __ ___ _ __ +---ooooo--- | '_ // _ / __| __/ _ / '__/ _ / '__| + .-'ooo'-. | |_)| __/ |_| || __/ | | __/ | + / | / |_.__//___|/__|/__/___|_| /___|_| + +", + " + / | / _ _ _ + '-.ooo.-' | |__ ___| |_| |_ ___ _ __ ___ _ __ +---ooooo--- | '_ // _ / __| __/ _ / '__/ _ / '__| + .-'ooo'-. | |_)| __/ |_| || __/ | | __/ | + / | / |_.__//___|/__|/__/___|_| /___|_| + +🌟 Betterer (0ms): + +", + " + / | / _ _ _ + '-.ooo.-' | |__ ___| |_| |_ ___ _ __ ___ _ __ +---ooooo--- | '_ // _ / __| __/ _ / '__/ _ / '__| + .-'ooo'-. | |_)| __/ |_| || __/ | | __/ | + / | / |_.__//___|/__|/__/___|_| /___|_| + +🌟 Betterer (0ms): 1 test running... +🤔 regexp no hack comments: running \\"regexp no hack comments\\"! + +", + " + / | / _ _ _ + '-.ooo.-' | |__ ___| |_| |_ ___ _ __ ___ _ __ +---ooooo--- | '_ // _ / __| __/ _ / '__/ _ / '__| + .-'ooo'-. | |_)| __/ |_| || __/ | | __/ | + / | / |_.__//___|/__|/__/___|_| /___|_| + +🌟 Betterer (0ms): 1 test running... +✅ regexp no hack comments: \\"regexp no hack comments\\" has already met its goal! ✨ + +", + " + / | / _ _ _ + '-.ooo.-' | |__ ___| |_| |_ ___ _ __ ___ _ __ +---ooooo--- | '_ // _ / __| __/ _ / '__/ _ / '__| + .-'ooo'-. | |_)| __/ |_| || __/ | | __/ | + / | / |_.__//___|/__|/__/___|_| /___|_| + +🎉 Betterer (0ms): 1 test done! +✅ regexp no hack comments: \\"regexp no hack comments\\" has already met its goal! ✨ + +", + " + / | / _ _ _ + '-.ooo.-' | |__ ___| |_| |_ ___ _ __ ___ _ __ +---ooooo--- | '_ // _ / __| __/ _ / '__/ _ / '__| + .-'ooo'-. | |_)| __/ |_| || __/ | | __/ | + / | / |_.__//___|/__|/__/___|_| /___|_| + +🎉 Betterer (0ms): 1 test done! +✅ regexp no hack comments: \\"regexp no hack comments\\" has already met its goal! ✨ + +1 test got checked. 🤔 +1 test got checked for the first time! 🎉 +\\"regexp no hack comments\\" met its goal! 🎉) + +", +] +`; diff --git a/test/__snapshots__/betterer-config.spec.ts.snap b/test/__snapshots__/betterer-config.spec.ts.snap index 229ae462e..95f734f6e 100644 --- a/test/__snapshots__/betterer-config.spec.ts.snap +++ b/test/__snapshots__/betterer-config.spec.ts.snap @@ -10,6 +10,66 @@ Array [ / | / |_.__//___|/__|/__/___|_| /___|_| +Error: \\"cache\\" must be \`true\` or \`false\`. Recieved \`1234\`. +", + " + / | / _ _ _ + '-.ooo.-' | |__ ___| |_| |_ ___ _ __ ___ _ __ +---ooooo--- | '_ // _ / __| __/ _ / '__/ _ / '__| + .-'ooo'-. | |_)| __/ |_| || __/ | | __/ | + / | / |_.__//___|/__|/__/___|_| /___|_| + + +Error: \\"cache\\" must be \`true\` or \`false\`. Recieved \`\\"betterer\\"\`. +", + " + / | / _ _ _ + '-.ooo.-' | |__ ___| |_| |_ ___ _ __ ___ _ __ +---ooooo--- | '_ // _ / __| __/ _ / '__/ _ / '__| + .-'ooo'-. | |_)| __/ |_| || __/ | | __/ | + / | / |_.__//___|/__|/__/___|_| /___|_| + + +Error: \\"cache\\" must be \`true\` or \`false\`. Recieved \`{}\`. +", + " + / | / _ _ _ + '-.ooo.-' | |__ ___| |_| |_ ___ _ __ ___ _ __ +---ooooo--- | '_ // _ / __| __/ _ / '__/ _ / '__| + .-'ooo'-. | |_)| __/ |_| || __/ | | __/ | + / | / |_.__//___|/__|/__/___|_| /___|_| + + +Error: \\"cachePath\\" must be a string. Recieved \`1234\`. +", + " + / | / _ _ _ + '-.ooo.-' | |__ ___| |_| |_ ___ _ __ ___ _ __ +---ooooo--- | '_ // _ / __| __/ _ / '__/ _ / '__| + .-'ooo'-. | |_)| __/ |_| || __/ | | __/ | + / | / |_.__//___|/__|/__/___|_| /___|_| + + +Error: \\"cachePath\\" must be a string. Recieved \`{}\`. +", + " + / | / _ _ _ + '-.ooo.-' | |__ ___| |_| |_ ___ _ __ ___ _ __ +---ooooo--- | '_ // _ / __| __/ _ / '__/ _ / '__| + .-'ooo'-. | |_)| __/ |_| || __/ | | __/ | + / | / |_.__//___|/__|/__/___|_| /___|_| + + +Error: \\"cachePath\\" must be a string. Recieved \`true\`. +", + " + / | / _ _ _ + '-.ooo.-' | |__ ___| |_| |_ ___ _ __ ___ _ __ +---ooooo--- | '_ // _ / __| __/ _ / '__/ _ / '__| + .-'ooo'-. | |_)| __/ |_| || __/ | | __/ | + / | / |_.__//___|/__|/__/___|_| /___|_| + + Error: \\"ci\\" must be \`true\` or \`false\`. Recieved \`1234\`. ", " diff --git a/test/__snapshots__/betterer-worse.spec.ts.snap b/test/__snapshots__/betterer-worse.spec.ts.snap index 15662fc13..0fcca3965 100644 --- a/test/__snapshots__/betterer-worse.spec.ts.snap +++ b/test/__snapshots__/betterer-worse.spec.ts.snap @@ -416,7 +416,7 @@ Array [ / | / |_.__//___|/__|/__/___|_| /___|_| 🌟 Betterer (0ms): 1 test running... -・ 1 existing issue in \\"/fixtures/test-betterer-update/src/index.ts\\". +・ 1 existing issue in \\"/fixtures/test-betterer-no-update/src/index.ts\\". 🤔 tsquery no raw console.log: running \\"tsquery no raw console.log\\"! ", @@ -428,8 +428,8 @@ Array [ / | / |_.__//___|/__|/__/___|_| /___|_| 🌟 Betterer (0ms): 1 test running... -・ 1 existing issue in \\"/fixtures/test-betterer-update/src/index.ts\\". -・ 1 new issue in \\"/fixtures/test-betterer-update/src/index.ts\\": +・ 1 existing issue in \\"/fixtures/test-betterer-no-update/src/index.ts\\". +・ 1 new issue in \\"/fixtures/test-betterer-no-update/src/index.ts\\": 🤔 tsquery no raw console.log: running \\"tsquery no raw console.log\\"! ", @@ -441,10 +441,10 @@ Array [ / | / |_.__//___|/__|/__/___|_| /___|_| 🌟 Betterer (0ms): 1 test running... -・ 1 existing issue in \\"/fixtures/test-betterer-update/src/index.ts\\". -・ 1 new issue in \\"/fixtures/test-betterer-update/src/index.ts\\": +・ 1 existing issue in \\"/fixtures/test-betterer-no-update/src/index.ts\\". +・ 1 new issue in \\"/fixtures/test-betterer-no-update/src/index.ts\\": ・ -・ /fixtures/test-betterer-update/src/index.ts +・ /fixtures/test-betterer-no-update/src/index.ts ・ 1 | console.log('foo'); ・ > 2 | console.log('foo'); ・ | ^^^^^^^^^^^ TSQuery match @@ -460,10 +460,10 @@ Array [ / | / |_.__//___|/__|/__/___|_| /___|_| 🌟 Betterer (0ms): 1 test running... -・ 1 existing issue in \\"/fixtures/test-betterer-update/src/index.ts\\". -・ 1 new issue in \\"/fixtures/test-betterer-update/src/index.ts\\": +・ 1 existing issue in \\"/fixtures/test-betterer-no-update/src/index.ts\\". +・ 1 new issue in \\"/fixtures/test-betterer-no-update/src/index.ts\\": ・ -・ /fixtures/test-betterer-update/src/index.ts +・ /fixtures/test-betterer-no-update/src/index.ts ・ 1 | console.log('foo'); ・ > 2 | console.log('foo'); ・ | ^^^^^^^^^^^ TSQuery match @@ -480,10 +480,10 @@ Array [ 🌟 Betterer (0ms): 1 test running... 🔥 tsquery no raw console.log: \\"tsquery no raw console.log\\" got worse. (1 new issue, 2 total) 😔 -・ 1 existing issue in \\"/fixtures/test-betterer-update/src/index.ts\\". -・ 1 new issue in \\"/fixtures/test-betterer-update/src/index.ts\\": +・ 1 existing issue in \\"/fixtures/test-betterer-no-update/src/index.ts\\". +・ 1 new issue in \\"/fixtures/test-betterer-no-update/src/index.ts\\": ・ -・ /fixtures/test-betterer-update/src/index.ts +・ /fixtures/test-betterer-no-update/src/index.ts ・ 1 | console.log('foo'); ・ > 2 | console.log('foo'); ・ | ^^^^^^^^^^^ TSQuery match @@ -501,10 +501,10 @@ Error: \\"tsquery no raw console.log\\" got worse. (1 new issue, 2 total) 😔 💥 Betterer (0ms): 1 test done! 1 test errored! 🔥 tsquery no raw console.log: \\"tsquery no raw console.log\\" got worse. (1 new issue, 2 total) 😔 -・ 1 existing issue in \\"/fixtures/test-betterer-update/src/index.ts\\". -・ 1 new issue in \\"/fixtures/test-betterer-update/src/index.ts\\": +・ 1 existing issue in \\"/fixtures/test-betterer-no-update/src/index.ts\\". +・ 1 new issue in \\"/fixtures/test-betterer-no-update/src/index.ts\\": ・ -・ /fixtures/test-betterer-update/src/index.ts +・ /fixtures/test-betterer-no-update/src/index.ts ・ 1 | console.log('foo'); ・ > 2 | console.log('foo'); ・ | ^^^^^^^^^^^ TSQuery match @@ -522,10 +522,10 @@ Error: \\"tsquery no raw console.log\\" got worse. (1 new issue, 2 total) 😔 💥 Betterer (0ms): 1 test done! 1 test errored! 🔥 tsquery no raw console.log: \\"tsquery no raw console.log\\" got worse. (1 new issue, 2 total) 😔 -・ 1 existing issue in \\"/fixtures/test-betterer-update/src/index.ts\\". -・ 1 new issue in \\"/fixtures/test-betterer-update/src/index.ts\\": +・ 1 existing issue in \\"/fixtures/test-betterer-no-update/src/index.ts\\". +・ 1 new issue in \\"/fixtures/test-betterer-no-update/src/index.ts\\": ・ -・ /fixtures/test-betterer-update/src/index.ts +・ /fixtures/test-betterer-no-update/src/index.ts ・ 1 | console.log('foo'); ・ > 2 | console.log('foo'); ・ | ^^^^^^^^^^^ TSQuery match diff --git a/test/betterer-cache.spec.ts b/test/betterer-cache.spec.ts new file mode 100644 index 000000000..2ca9ed2e4 --- /dev/null +++ b/test/betterer-cache.spec.ts @@ -0,0 +1,63 @@ +import { betterer } from '@betterer/betterer'; + +import { createFixture } from './fixture'; + +describe('betterer', () => { + it('should write a cache file', async () => { + const { logs, paths, readFile, cleanup, resolve, writeFile, runNames } = await createFixture( + 'test-betterer-cache', + { + '.betterer.js': ` +const { regexp } = require('@betterer/regexp'); + +module.exports = { +'regexp no hack comments': regexp(/(\\/\\/\\s*HACK)/i).include('./src/**/*.ts') +}; + ` + } + ); + + const configPaths = [paths.config]; + const resultsPath = paths.results; + const indexPath = resolve('./src/index.ts'); + const cachePath = resolve('./.betterer.cache'); + + await writeFile(indexPath, `// HACK:`); + + const newTestRun = await betterer({ configPaths, resultsPath, cache: true, cachePath }); + + expect(runNames(newTestRun.new)).toEqual(['regexp no hack comments']); + + const cache = await readFile(cachePath); + + expect(cache).toMatchSnapshot(); + + const sameTestRun = await betterer({ configPaths, resultsPath, cache: true, cachePath }); + + expect(runNames(sameTestRun.same)).toEqual(['regexp no hack comments']); + + await writeFile(indexPath, `// HACK:\n// HACK:`); + + const worseTestRun = await betterer({ configPaths, resultsPath, cache: true, cachePath }); + + expect(runNames(worseTestRun.worse)).toEqual(['regexp no hack comments']); + + const result = await readFile(resultsPath); + + expect(result).toMatchSnapshot(); + + await writeFile(indexPath, ``); + + const betterTestRun = await betterer({ configPaths, resultsPath, cache: true, cachePath }); + + expect(runNames(betterTestRun.better)).toEqual(['regexp no hack comments']); + + const completedTestRun = await betterer({ configPaths, resultsPath, cache: true, cachePath }); + + expect(runNames(completedTestRun.completed)).toEqual(['regexp no hack comments']); + + expect(logs).toMatchSnapshot(); + + await cleanup(); + }); +}); diff --git a/test/betterer-config.spec.ts b/test/betterer-config.spec.ts index ad79708bc..8d53205c6 100644 --- a/test/betterer-config.spec.ts +++ b/test/betterer-config.spec.ts @@ -22,6 +22,12 @@ describe('betterer', () => { const resultsPath = paths.results; const tests = [ + { cache: 1234 }, + { cache: 'betterer' }, + { cache: {} }, + { cachePath: 1234 }, + { cachePath: {} }, + { cachePath: true }, { ci: 1234 }, { ci: 'betterer' }, { ci: {} }, diff --git a/test/betterer-worse.spec.ts b/test/betterer-worse.spec.ts index 3240ffd30..ff4bb0be9 100644 --- a/test/betterer-worse.spec.ts +++ b/test/betterer-worse.spec.ts @@ -105,7 +105,7 @@ export default { it('should stay worse if an update is not allowed', async () => { const { logs, paths, readFile, cleanup, resolve, writeFile, runNames } = await createFixture( - 'test-betterer-update', + 'test-betterer-no-update', { '.betterer.ts': ` import { tsquery } from '@betterer/tsquery'; diff --git a/test/cli/__snapshots__/betterer-ci.spec.ts.snap b/test/cli/__snapshots__/betterer-ci.spec.ts.snap index baac3bafb..7c4ca60f9 100644 --- a/test/cli/__snapshots__/betterer-ci.spec.ts.snap +++ b/test/cli/__snapshots__/betterer-ci.spec.ts.snap @@ -255,7 +255,7 @@ Array [ / | / |_.__//___|/__|/__/___|_| /___|_| 🌟 Betterer (0ms): 1 test running... -・ 1 existing issue in \\"/fixtures/test-betterer-ci-diff/src/index.ts\\". +・ 1 existing issue in \\"/fixtures/test-betterer-ci-worse/src/index.ts\\". 🤔 typescript use strict mode: running \\"typescript use strict mode\\"! ", @@ -267,8 +267,8 @@ Array [ / | / |_.__//___|/__|/__/___|_| /___|_| 🌟 Betterer (0ms): 1 test running... -・ 1 existing issue in \\"/fixtures/test-betterer-ci-diff/src/index.ts\\". -・ 1 new issue in \\"/fixtures/test-betterer-ci-diff/src/index.ts\\": +・ 1 existing issue in \\"/fixtures/test-betterer-ci-worse/src/index.ts\\". +・ 1 new issue in \\"/fixtures/test-betterer-ci-worse/src/index.ts\\": 🤔 typescript use strict mode: running \\"typescript use strict mode\\"! ", @@ -280,10 +280,10 @@ Array [ / | / |_.__//___|/__|/__/___|_| /___|_| 🌟 Betterer (0ms): 1 test running... -・ 1 existing issue in \\"/fixtures/test-betterer-ci-diff/src/index.ts\\". -・ 1 new issue in \\"/fixtures/test-betterer-ci-diff/src/index.ts\\": +・ 1 existing issue in \\"/fixtures/test-betterer-ci-worse/src/index.ts\\". +・ 1 new issue in \\"/fixtures/test-betterer-ci-worse/src/index.ts\\": ・ -・ /fixtures/test-betterer-ci-diff/src/index.ts +・ /fixtures/test-betterer-ci-worse/src/index.ts ・ 2 | const one = 1; ・ 3 | console.log(one * a); ・ > 4 | console.log(a * one); @@ -300,10 +300,10 @@ Array [ / | / |_.__//___|/__|/__/___|_| /___|_| 🌟 Betterer (0ms): 1 test running... -・ 1 existing issue in \\"/fixtures/test-betterer-ci-diff/src/index.ts\\". -・ 1 new issue in \\"/fixtures/test-betterer-ci-diff/src/index.ts\\": +・ 1 existing issue in \\"/fixtures/test-betterer-ci-worse/src/index.ts\\". +・ 1 new issue in \\"/fixtures/test-betterer-ci-worse/src/index.ts\\": ・ -・ /fixtures/test-betterer-ci-diff/src/index.ts +・ /fixtures/test-betterer-ci-worse/src/index.ts ・ 2 | const one = 1; ・ 3 | console.log(one * a); ・ > 4 | console.log(a * one); @@ -321,10 +321,10 @@ Array [ 🌟 Betterer (0ms): 1 test running... 🔥 typescript use strict mode: \\"typescript use strict mode\\" got worse. (1 new issue, 2 total) 😔 -・ 1 existing issue in \\"/fixtures/test-betterer-ci-diff/src/index.ts\\". -・ 1 new issue in \\"/fixtures/test-betterer-ci-diff/src/index.ts\\": +・ 1 existing issue in \\"/fixtures/test-betterer-ci-worse/src/index.ts\\". +・ 1 new issue in \\"/fixtures/test-betterer-ci-worse/src/index.ts\\": ・ -・ /fixtures/test-betterer-ci-diff/src/index.ts +・ /fixtures/test-betterer-ci-worse/src/index.ts ・ 2 | const one = 1; ・ 3 | console.log(one * a); ・ > 4 | console.log(a * one); @@ -343,10 +343,10 @@ Error: \\"typescript use strict mode\\" got worse. (1 new issue, 2 total) 😔 💥 Betterer (0ms): 1 test done! 1 test errored! 🔥 typescript use strict mode: \\"typescript use strict mode\\" got worse. (1 new issue, 2 total) 😔 -・ 1 existing issue in \\"/fixtures/test-betterer-ci-diff/src/index.ts\\". -・ 1 new issue in \\"/fixtures/test-betterer-ci-diff/src/index.ts\\": +・ 1 existing issue in \\"/fixtures/test-betterer-ci-worse/src/index.ts\\". +・ 1 new issue in \\"/fixtures/test-betterer-ci-worse/src/index.ts\\": ・ -・ /fixtures/test-betterer-ci-diff/src/index.ts +・ /fixtures/test-betterer-ci-worse/src/index.ts ・ 2 | const one = 1; ・ 3 | console.log(one * a); ・ > 4 | console.log(a * one); @@ -365,10 +365,10 @@ Error: \\"typescript use strict mode\\" got worse. (1 new issue, 2 total) 😔 💥 Betterer (0ms): 1 test done! 1 test errored! 🔥 typescript use strict mode: \\"typescript use strict mode\\" got worse. (1 new issue, 2 total) 😔 -・ 1 existing issue in \\"/fixtures/test-betterer-ci-diff/src/index.ts\\". -・ 1 new issue in \\"/fixtures/test-betterer-ci-diff/src/index.ts\\": +・ 1 existing issue in \\"/fixtures/test-betterer-ci-worse/src/index.ts\\". +・ 1 new issue in \\"/fixtures/test-betterer-ci-worse/src/index.ts\\": ・ -・ /fixtures/test-betterer-ci-diff/src/index.ts +・ /fixtures/test-betterer-ci-worse/src/index.ts ・ 2 | const one = 1; ・ 3 | console.log(one * a); ・ > 4 | console.log(a * one); diff --git a/test/cli/betterer-ci.spec.ts b/test/cli/betterer-ci.spec.ts index d9a366060..ad2046912 100644 --- a/test/cli/betterer-ci.spec.ts +++ b/test/cli/betterer-ci.spec.ts @@ -55,7 +55,7 @@ export default { }); it('should work when a test gets worse', async () => { - const { paths, logs, cleanup, resolve, writeFile } = await createFixture('test-betterer-ci-diff', { + const { paths, logs, cleanup, resolve, writeFile } = await createFixture('test-betterer-ci-worse', { 'src/index.ts': ` const a = 'a'; const one = 1;