From fb9e9fcde2dc57c56f38ac324bfbd4bb446299b5 Mon Sep 17 00:00:00 2001 From: connectdotz Date: Mon, 25 May 2020 22:07:15 -0400 Subject: [PATCH 1/6] upgrade istanbul dependencies --- package.json | 6 +- src/Coverage/CoverageCodeLensProvider.ts | 14 ++- src/Coverage/CoverageMapProvider.ts | 32 +++++-- .../Formatters/GutterFormatter/index.ts | 6 +- src/Coverage/Formatters/helpers.ts | 6 +- src/JestExt.ts | 71 ++++++++------ src/extension.ts | 10 +- src/extensionManager.ts | 38 ++++---- .../Coverage/CoverageCodeLensProvider.test.ts | 46 +++++++--- tests/Coverage/CoverageMapProvider.test.ts | 92 ++++++++++++------- .../Formatters/GutterFormatter.test.ts | 2 +- tests/JestExt.test.ts | 44 ++++++++- typings/istanbul-lib-coverage.d.ts | 57 ------------ yarn.lock | 33 +++---- 14 files changed, 264 insertions(+), 193 deletions(-) delete mode 100644 typings/istanbul-lib-coverage.d.ts diff --git a/package.json b/package.json index 62e04fe65..231bbee88 100644 --- a/package.json +++ b/package.json @@ -277,12 +277,14 @@ "watch-test": "yarn test -- --watch" }, "dependencies": { - "istanbul-lib-coverage": "^1.1.1", - "istanbul-lib-source-maps": "^1.1.0", + "istanbul-lib-coverage": "^3.0.0", + "istanbul-lib-source-maps": "^4.0.0", "jest-editor-support": "^27.2.0", "jest-snapshot": "^25.5.0" }, "devDependencies": { + "@types/istanbul-lib-coverage": "^2.0.2", + "@types/istanbul-lib-source-maps": "^4.0.1", "@types/jest": "^25.2.1", "@types/node": "^8.0.31", "@types/vscode": "^1.23.0", diff --git a/src/Coverage/CoverageCodeLensProvider.ts b/src/Coverage/CoverageCodeLensProvider.ts index d865ee76a..9dd71f0e2 100644 --- a/src/Coverage/CoverageCodeLensProvider.ts +++ b/src/Coverage/CoverageCodeLensProvider.ts @@ -4,14 +4,21 @@ import { GetJestExtByURI } from '../extensionManager'; export class CoverageCodeLensProvider implements vscode.CodeLensProvider { private getJestExt: GetJestExtByURI; + private onDidChange: vscode.EventEmitter; + onDidChangeCodeLenses: vscode.Event; constructor(getJestExt: GetJestExtByURI) { this.getJestExt = getJestExt; + this.onDidChange = new vscode.EventEmitter(); + this.onDidChangeCodeLenses = this.onDidChange.event; } - public provideCodeLenses(document: vscode.TextDocument, _token: vscode.CancellationToken) { + public provideCodeLenses(document: vscode.TextDocument): vscode.CodeLens[] { const ext = this.getJestExt(document.uri); - const coverage = ext && ext.coverageMapProvider.getFileCoverage(document.fileName); + const coverage = + ext && + ext.coverageOverlay.enabled && + ext.coverageMapProvider.getFileCoverage(document.fileName); if (!coverage) { return; } @@ -30,4 +37,7 @@ export class CoverageCodeLensProvider implements vscode.CodeLensProvider { return [new vscode.CodeLens(range, command)]; } + public coverageChanged(): void { + this.onDidChange.fire(); + } } diff --git a/src/Coverage/CoverageMapProvider.ts b/src/Coverage/CoverageMapProvider.ts index 72e82b289..368612fa7 100644 --- a/src/Coverage/CoverageMapProvider.ts +++ b/src/Coverage/CoverageMapProvider.ts @@ -1,5 +1,10 @@ import { createSourceMapStore, MapStore } from 'istanbul-lib-source-maps'; -import { createCoverageMap, CoverageMap } from 'istanbul-lib-coverage'; +import { + createCoverageMap, + CoverageMap, + CoverageMapData, + FileCoverage, +} from 'istanbul-lib-coverage'; export class CoverageMapProvider { private mapStore: MapStore; @@ -10,25 +15,38 @@ export class CoverageMapProvider { private _map: CoverageMap; constructor() { + this.init(); + } + + init(): void { this._map = createCoverageMap(); this.mapStore = createSourceMapStore(); } - get map(): CoverageMap { return this._map; } - update(obj: CoverageMap | object) { + async update(obj?: CoverageMap | CoverageMapData): Promise { const map = createCoverageMap(obj); - const transformed = this.mapStore.transformCoverage(map); + const transformed = await this.mapStore.transformCoverage(map); if (this._map) { - this._map.merge(transformed.map); + transformed.files().forEach((fileName) => { + this.setFileCoverage(fileName, transformed); + }); } else { - this._map = transformed.map; + this._map = transformed; } } - public getFileCoverage(filePath: string) { + setFileCoverage(filePath: string, map: CoverageMap): void { + this._map.data[filePath] = map.fileCoverageFor(filePath); + } + public getFileCoverage(filePath: string): FileCoverage { return this._map.data[filePath]; } + public onVisibilityChanged(visible: boolean): void { + if (!visible) { + this.init(); + } + } } diff --git a/src/Coverage/Formatters/GutterFormatter/index.ts b/src/Coverage/Formatters/GutterFormatter/index.ts index b6fc2b055..079c311ab 100644 --- a/src/Coverage/Formatters/GutterFormatter/index.ts +++ b/src/Coverage/Formatters/GutterFormatter/index.ts @@ -48,7 +48,7 @@ export class GutterFormatter extends AbstractFormatter { }); } - format(editor: vscode.TextEditor) { + format(editor: vscode.TextEditor): void { const fileCoverage = this.coverageMapProvider.getFileCoverage(editor.document.fileName); if (!fileCoverage) { return; @@ -72,7 +72,7 @@ export class GutterFormatter extends AbstractFormatter { for (let line = 1; line <= editor.document.lineCount; line++) { const zeroBasedLineNumber = line - 1; - if (uncoveredLines.indexOf(line.toString()) >= 0) { + if (uncoveredLines.indexOf(line) >= 0) { coverageFormatting.uncovered.push( new vscode.Range(zeroBasedLineNumber, 0, zeroBasedLineNumber, 0) ); @@ -121,7 +121,7 @@ export class GutterFormatter extends AbstractFormatter { return coverageFormatting; } - clear(editor: vscode.TextEditor) { + clear(editor: vscode.TextEditor): void { editor.setDecorations(this.coveredLine, []); editor.setDecorations(this.partiallyCoveredLine, []); editor.setDecorations(this.uncoveredLine, []); diff --git a/src/Coverage/Formatters/helpers.ts b/src/Coverage/Formatters/helpers.ts index e062ec56e..8ab5dea74 100644 --- a/src/Coverage/Formatters/helpers.ts +++ b/src/Coverage/Formatters/helpers.ts @@ -1,9 +1,9 @@ -import { Location, Position } from 'istanbul-lib-coverage'; +import { Range, Location } from 'istanbul-lib-coverage'; -export function isValidPosition(p: Position) { +export function isValidPosition(p: Location): boolean { return (p || false) && p.line !== null && p.line >= 0; } -export function isValidLocation(l: Location) { +export function isValidLocation(l: Range): boolean { return isValidPosition(l.start) && isValidPosition(l.end); } diff --git a/src/JestExt.ts b/src/JestExt.ts index 5605d0c8d..7b0a86c68 100644 --- a/src/JestExt.ts +++ b/src/JestExt.ts @@ -12,7 +12,7 @@ import { SortedTestResults, } from './TestResults'; import { pathToJest, pathToConfig, cleanAnsi } from './helpers'; -import { CoverageMapProvider } from './Coverage'; +import { CoverageMapProvider, CoverageCodeLensProvider } from './Coverage'; import { updateDiagnostics, updateCurrentDiagnostics, @@ -28,6 +28,7 @@ import { JestProcess, JestProcessManager } from './JestProcessManagement'; import { isWatchNotSupported, WatchMode } from './Jest'; import * as messaging from './messaging'; import { resultsWithoutAnsiEscapeSequence } from './TestResults/TestResult'; +import { CoverageMap, CoverageMapData } from 'istanbul-lib-coverage'; interface InstanceSettings { multirootEnv: boolean; @@ -40,6 +41,7 @@ export class JestExt { testResultProvider: TestResultProvider; debugCodeLensProvider: DebugCodeLensProvider; debugConfigurationProvider: DebugConfigurationProvider; + coverageCodeLensProvider: CoverageCodeLensProvider; // So you can read what's going on channel: vscode.OutputChannel; @@ -77,7 +79,8 @@ export class JestExt { debugCodeLensProvider: DebugCodeLensProvider, debugConfigurationProvider: DebugConfigurationProvider, failDiagnostics: vscode.DiagnosticCollection, - instanceSettings: InstanceSettings + instanceSettings: InstanceSettings, + coverageCodeLensProvider: CoverageCodeLensProvider ) { this.workspaceFolder = workspaceFolder; this.jestWorkspace = jestWorkspace; @@ -87,6 +90,7 @@ export class JestExt { this.pluginSettings = pluginSettings; this.debugCodeLensProvider = debugCodeLensProvider; this.instanceSettings = instanceSettings; + this.coverageCodeLensProvider = coverageCodeLensProvider; this.coverageMapProvider = new CoverageMapProvider(); this.coverageOverlay = new CoverageOverlay( @@ -123,7 +127,7 @@ export class JestExt { } } - public startProcess() { + public startProcess(): void { if (this.jestProcessManager.numberOfProcesses > 0) { // tslint:disable-next-line no-console console.warn(`process is already running, will not start a new process.`); @@ -162,20 +166,20 @@ export class JestExt { this.assignHandlers(this.jestProcess); } - public stopProcess() { + public stopProcess(): Promise { this.channel.appendLine('Closing Jest'); return this.jestProcessManager.stopAll().then(() => { this.updateStatusBar('stopped'); }); } - public restartProcess() { + public restartProcess(): Promise { return this.stopProcess().then(() => { this.startProcess(); }); } - public triggerUpdateActiveEditor(editor: vscode.TextEditor) { + public triggerUpdateActiveEditor(editor: vscode.TextEditor): void { this.coverageOverlay.updateVisibleEditors(); if (!this.canUpdateActiveEditor(editor)) { @@ -196,7 +200,7 @@ export class JestExt { this.parsingTestFile = false; } - public triggerUpdateSettings(updatedSettings: PluginResourceSettings) { + public triggerUpdateSettings(updatedSettings: PluginResourceSettings): void { this.pluginSettings = updatedSettings; this.jestWorkspace.rootPath = updatedSettings.rootPath; @@ -218,7 +222,7 @@ export class JestExt { this.restartProcess(); } - updateDecorators(testResults: SortedTestResults, editor: vscode.TextEditor) { + updateDecorators(testResults: SortedTestResults, editor: vscode.TextEditor): void { // Dots const styleMap = [ { @@ -262,7 +266,7 @@ export class JestExt { } } - canUpdateActiveEditor(editor: vscode.TextEditor) { + canUpdateActiveEditor(editor: vscode.TextEditor): boolean { const inSettings = !editor.document; if (inSettings) { return false; @@ -277,7 +281,7 @@ export class JestExt { return codeRegex.test(editor.document.uri.fsPath); } - public deactivate() { + public deactivate(): void { this.jestProcessManager.stopAll(); } @@ -285,13 +289,13 @@ export class JestExt { workspaceFolder: vscode.WorkspaceFolder, fileName: string, identifier: string - ) => { + ): Promise => { const restart = this.jestProcessManager.numberOfProcesses > 0; this.jestProcessManager.stopAll(); this.debugConfigurationProvider.prepareTestRun(fileName, identifier); - const handle = vscode.debug.onDidTerminateDebugSession((_) => { + const handle = vscode.debug.onDidTerminateDebugSession(() => { handle.dispose(); if (restart) { this.startProcess(); @@ -311,12 +315,12 @@ export class JestExt { } }; - onDidCloseTextDocument(document: vscode.TextDocument) { + onDidCloseTextDocument(document: vscode.TextDocument): void { this.removeCachedTestResults(document); this.removeCachedDecorationTypes(document); } - removeCachedTestResults(document: vscode.TextDocument) { + removeCachedTestResults(document: vscode.TextDocument): void { if (!document || document.isUntitled) { return; } @@ -325,7 +329,7 @@ export class JestExt { this.testResultProvider.removeCachedResults(filePath); } - removeCachedDecorationTypes(document: vscode.TextDocument) { + removeCachedDecorationTypes(document: vscode.TextDocument): void { if (!document || !document.fileName) { return; } @@ -333,7 +337,7 @@ export class JestExt { delete this.failingAssertionDecorators[document.fileName]; } - onDidChangeActiveTextEditor(editor: vscode.TextEditor) { + onDidChangeActiveTextEditor(editor: vscode.TextEditor): void { this.triggerUpdateActiveEditor(editor); } @@ -342,7 +346,7 @@ export class JestExt { * - before the onDidSaveTextDocument event * - the document was changed by an external editor */ - onDidChangeTextDocument(event: vscode.TextDocumentChangeEvent) { + onDidChangeTextDocument(event: vscode.TextDocumentChangeEvent): void { if (event.document.isDirty) { return; } @@ -364,14 +368,14 @@ export class JestExt { } } - toggleCoverageOverlay() { + toggleCoverageOverlay(): void { this.coverageOverlay.toggleVisibility(); // restart jest since coverage condition has changed this.triggerUpdateSettings(this.pluginSettings); } - private detectedSnapshotErrors() { + private detectedSnapshotErrors(): void { if (!this.pluginSettings.enableSnapshotUpdateMessages) { return; } @@ -396,7 +400,7 @@ export class JestExt { }); } - private resetInlineErrorDecorators(editor: vscode.TextEditor) { + private resetInlineErrorDecorators(editor: vscode.TextEditor): void { if (!this.failingAssertionDecorators[editor.document.fileName]) { this.failingAssertionDecorators[editor.document.fileName] = []; return; @@ -412,7 +416,10 @@ export class JestExt { this.failingAssertionDecorators[editor.document.fileName] = []; } - private generateInlineErrorDecorator(fileName: string, test: TestResult) { + private generateInlineErrorDecorator( + fileName: string, + test: TestResult + ): { style: vscode.TextEditorDecorationType; decorator: vscode.DecorationOptions } { const errorMessage = test.terseMessage || test.shortMessage; const decorator = { range: new vscode.Range(test.lineNumberOfError, 0, test.lineNumberOfError, 0), @@ -426,7 +433,7 @@ export class JestExt { return { style, decorator }; } - private handleStdErr(error: Buffer) { + private handleStdErr(error: Buffer): void { const message = error.toString(); if (this.shouldIgnoreOutput(message)) { return; @@ -444,7 +451,7 @@ export class JestExt { this.channel.appendLine(noANSI); } - private handleJestEditorSupportEvent(output: string) { + private handleJestEditorSupportEvent(output: string): void { if (output.includes('onRunStart')) { this.channel.clear(); this.updateStatusBar('running', 'Running tests', false); @@ -459,7 +466,7 @@ export class JestExt { } } - private assignHandlers(jestProcess: JestProcess) { + private assignHandlers(jestProcess: JestProcess): void { jestProcess .onJestEditorSupportEvent('executableJSON', (data: JestTotalResults) => { this.updateWithData(data); @@ -480,11 +487,11 @@ export class JestExt { }); } - private setupStatusBar() { + private setupStatusBar(): void { this.updateStatusBar('initial', undefined, false); } - private updateStatusBar(status: Status, details?: string, watchMode = true) { + private updateStatusBar(status: Status, details?: string, watchMode = true): void { const modes: Mode[] = []; if (this.coverageOverlay.enabled) { modes.push('coverage'); @@ -495,7 +502,7 @@ export class JestExt { this.status.update(status, details, modes); } - private setupDecorators() { + private setupDecorators(): void { this.passingItStyle = decorations.passingItName(); this.failingItStyle = decorations.failingItName(); this.skipItStyle = decorations.skipItName(); @@ -509,10 +516,16 @@ export class JestExt { ); } - private updateWithData(data: JestTotalResults) { + _updateCoverageMap(coverageMap: CoverageMap | CoverageMapData): Promise { + return this.coverageMapProvider.update(coverageMap).then(() => { + this.coverageCodeLensProvider.coverageChanged(); + this.coverageOverlay.updateVisibleEditors(); + }); + } + private updateWithData(data: JestTotalResults): void { const noAnsiData = resultsWithoutAnsiEscapeSequence(data); const normalizedData = resultsWithLowerCaseWindowsDriveLetters(noAnsiData); - this.coverageMapProvider.update(normalizedData.coverageMap); + this._updateCoverageMap(normalizedData.coverageMap); const statusList = this.testResultProvider.updateTestResults(normalizedData); updateDiagnostics(statusList, this.failDiagnostics); diff --git a/src/extension.ts b/src/extension.ts index a1d8de62e..4635c0317 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -2,13 +2,12 @@ import * as vscode from 'vscode'; import { extensionName } from './appGlobals'; import { statusBar } from './StatusBar'; -import { CoverageCodeLensProvider } from './Coverage'; import { ExtensionManager, getExtensionWindowSettings } from './extensionManager'; import { registerSnapshotCodeLens, registerSnapshotPreview } from './SnapshotCodeLens'; let extensionManager: ExtensionManager; -export function activate(context: vscode.ExtensionContext) { +export function activate(context: vscode.ExtensionContext): void { extensionManager = new ExtensionManager(context); const languages = [ @@ -47,10 +46,7 @@ export function activate(context: vscode.ExtensionContext) { ), ...registerSnapshotCodeLens(getExtensionWindowSettings().enableSnapshotPreviews), ...registerSnapshotPreview(), - vscode.languages.registerCodeLensProvider( - { pattern: '**/*.{ts,tsx,js,jsx}' }, - new CoverageCodeLensProvider((uri) => extensionManager.getByDocUri(uri)) - ), + vscode.languages.registerCodeLensProvider(languages, extensionManager.coverageCodeLensProvider), vscode.languages.registerCodeLensProvider(languages, extensionManager.debugCodeLensProvider), // this provides the opportunity to inject test names into the DebugConfiguration vscode.debug.registerDebugConfigurationProvider( @@ -88,6 +84,6 @@ export function activate(context: vscode.ExtensionContext) { ); } -export function deactivate() { +export function deactivate(): void { extensionManager.unregisterAll(); } diff --git a/src/extensionManager.ts b/src/extensionManager.ts index 747549eab..a0c1d183d 100644 --- a/src/extensionManager.ts +++ b/src/extensionManager.ts @@ -7,6 +7,7 @@ import { DebugCodeLensProvider, TestState } from './DebugCodeLens'; import { DebugConfigurationProvider } from './DebugConfigurationProvider'; import { PluginResourceSettings, PluginWindowSettings } from './Settings'; import { statusBar } from './StatusBar'; +import { CoverageCodeLensProvider } from './Coverage'; export type GetJestExtByURI = (uri: vscode.Uri) => JestExt | undefined; @@ -42,6 +43,7 @@ export function getExtensionResourceSettings(uri: vscode.Uri): PluginResourceSet export class ExtensionManager { debugCodeLensProvider: DebugCodeLensProvider; debugConfigurationProvider: DebugConfigurationProvider; + coverageCodeLensProvider: CoverageCodeLensProvider; private extByWorkspace: Map = new Map(); private context: vscode.ExtensionContext; @@ -54,10 +56,11 @@ export class ExtensionManager { this.debugConfigurationProvider = new DebugConfigurationProvider(); this.debugCodeLensProvider = new DebugCodeLensProvider((uri) => this.getByDocUri(uri)); + this.coverageCodeLensProvider = new CoverageCodeLensProvider((uri) => this.getByDocUri(uri)); this.applySettings(getExtensionWindowSettings()); this.registerAll(); } - applySettings(settings: PluginWindowSettings) { + applySettings(settings: PluginWindowSettings): void { this.commonPluginSettings = settings; const { debugCodeLens } = settings; this.debugCodeLensProvider.showWhenTestStateIn = debugCodeLens.enabled @@ -65,7 +68,7 @@ export class ExtensionManager { : []; settings.disabledWorkspaceFolders.forEach(this.unregisterByName, this); } - register(workspaceFolder: vscode.WorkspaceFolder) { + register(workspaceFolder: vscode.WorkspaceFolder): void { if (!this.shouldStart(workspaceFolder.name)) { return; } @@ -105,24 +108,25 @@ export class ExtensionManager { this.debugCodeLensProvider, this.debugConfigurationProvider, failDiagnostics, - instanceSettings + instanceSettings, + this.coverageCodeLensProvider ) ); } - registerAll() { + registerAll(): void { vscode.workspace.workspaceFolders.forEach(this.register, this); } - unregister(workspaceFolder: vscode.WorkspaceFolder) { + unregister(workspaceFolder: vscode.WorkspaceFolder): void { this.unregisterByName(workspaceFolder.name); } - unregisterByName(name: string) { + unregisterByName(name: string): void { const extension = this.extByWorkspace.get(name); if (extension) { extension.deactivate(); this.extByWorkspace.delete(name); } } - unregisterAll() { + unregisterAll(): void { const keys = this.extByWorkspace.keys(); for (const key of keys) { this.unregisterByName(key); @@ -140,7 +144,7 @@ export class ExtensionManager { } return true; } - getByName(workspaceFolderName: string) { + getByName(workspaceFolderName: string): JestExt | undefined { return this.extByWorkspace.get(workspaceFolderName); } public getByDocUri: GetJestExtByURI = (uri: vscode.Uri) => { @@ -149,7 +153,7 @@ export class ExtensionManager { return this.getByName(workspace.name); } }; - async get() { + async get(): Promise { const workspace = vscode.workspace.workspaceFolders.length <= 1 ? vscode.workspace.workspaceFolders[0] @@ -164,9 +168,9 @@ export class ExtensionManager { } registerCommand( command: string, - callback: (extension: JestExt, ...args: any[]) => any, - thisArg?: any - ) { + callback: (extension: JestExt, ...args: unknown[]) => unknown, + thisArg?: unknown + ): vscode.Disposable { return vscode.commands.registerCommand(command, async (...args) => { const extension = await this.get(); if (extension) { @@ -174,7 +178,7 @@ export class ExtensionManager { } }); } - onDidChangeConfiguration(e: vscode.ConfigurationChangeEvent) { + onDidChangeConfiguration(e: vscode.ConfigurationChangeEvent): void { if (e.affectsConfiguration('jest')) { this.applySettings(getExtensionWindowSettings()); this.registerAll(); @@ -187,17 +191,17 @@ export class ExtensionManager { } }); } - onDidChangeWorkspaceFolders(e: vscode.WorkspaceFoldersChangeEvent) { + onDidChangeWorkspaceFolders(e: vscode.WorkspaceFoldersChangeEvent): void { e.added.forEach(this.register, this); e.removed.forEach(this.unregister, this); } - onDidCloseTextDocument(document: vscode.TextDocument) { + onDidCloseTextDocument(document: vscode.TextDocument): void { const ext = this.getByDocUri(document.uri); if (ext) { ext.onDidCloseTextDocument(document); } } - onDidChangeActiveTextEditor(editor: vscode.TextEditor) { + onDidChangeActiveTextEditor(editor: vscode.TextEditor): void { if (editor && editor.document) { statusBar.onDidChangeActiveTextEditor(editor); const ext = this.getByDocUri(editor.document.uri); @@ -206,7 +210,7 @@ export class ExtensionManager { } } } - onDidChangeTextDocument(event: vscode.TextDocumentChangeEvent) { + onDidChangeTextDocument(event: vscode.TextDocumentChangeEvent): void { const ext = this.getByDocUri(event.document.uri); if (ext) { ext.onDidChangeTextDocument(event); diff --git a/tests/Coverage/CoverageCodeLensProvider.test.ts b/tests/Coverage/CoverageCodeLensProvider.test.ts index 3308e6ca7..230d25a3d 100644 --- a/tests/Coverage/CoverageCodeLensProvider.test.ts +++ b/tests/Coverage/CoverageCodeLensProvider.test.ts @@ -1,6 +1,5 @@ jest.unmock('../../src/Coverage/CoverageCodeLensProvider'); -// tslint:disable max-classes-per-file const rangeConstructor = jest.fn(); jest.mock('vscode', () => { class CodeLens { @@ -13,9 +12,7 @@ jest.mock('vscode', () => { } } - // class EventEmitter { - // fire() {} - // } + const EventEmitter = jest.fn(); class Position { lineNumber: string; @@ -42,13 +39,12 @@ jest.mock('vscode', () => { CodeLens, Position, Range, + EventEmitter, }; }); - +import * as vscode from 'vscode'; import { CoverageCodeLensProvider } from '../../src/Coverage/CoverageCodeLensProvider'; -// import * as vscode from 'vscode' - describe('CoverageCodeLensProvider', () => { let mockJestExt; let provider; @@ -56,12 +52,21 @@ describe('CoverageCodeLensProvider', () => { beforeEach(() => { mockJestExt = { coverageMapProvider: { getFileCoverage: jest.fn() }, + coverageOverlay: { enabled: true }, }; const mockGetExt = jest.fn().mockReturnValue(mockJestExt); provider = new CoverageCodeLensProvider(mockGetExt); }); describe('provideCodeLenses', () => { const doc = { fileName: 'file.js' }; + const coverage = { + toSummary: () => ({ + toJSON: () => ({ + branches: { pct: 10 }, + lines: { pct: 46.15 }, + }), + }), + }; test('do nothing when no coverage', () => { mockJestExt.coverageMapProvider.getFileCoverage = () => null; @@ -70,18 +75,29 @@ describe('CoverageCodeLensProvider', () => { }); test('can summarize', () => { - const coverage = { - toSummary: () => ({ - toJSON: () => ({ - branches: { pct: 10 }, - lines: { pct: 46.15 }, - }), - }), - }; mockJestExt.coverageMapProvider.getFileCoverage = () => coverage; const result = provider.provideCodeLenses(doc); expect(result).toHaveLength(1); expect(result[0].command.title).toEqual('branches: 10%, lines: 46.15%'); }); + test('do nothing when coverage is disabled', () => { + mockJestExt.coverageMapProvider.getFileCoverage = () => coverage; + mockJestExt.coverageOverlay.enabled = false; + const result = provider.provideCodeLenses(doc); + expect(result).toBeUndefined(); + }); + test('provides trigger to update codeLens on demand', () => { + const fireMock = jest.fn(); + const event: any = { whatever: true }; + (vscode.EventEmitter as jest.Mocked).mockImplementation(() => ({ + event, + fire: fireMock, + })); + provider = new CoverageCodeLensProvider(mockJestExt); + expect(provider.onDidChangeCodeLenses).toEqual(event); + + provider.coverageChanged(); + expect(fireMock).toBeCalled(); + }); }); }); diff --git a/tests/Coverage/CoverageMapProvider.test.ts b/tests/Coverage/CoverageMapProvider.test.ts index e488cc58b..2fb9d0f9e 100644 --- a/tests/Coverage/CoverageMapProvider.test.ts +++ b/tests/Coverage/CoverageMapProvider.test.ts @@ -4,6 +4,8 @@ import { CoverageMapProvider } from '../../src/Coverage/CoverageMapProvider'; import { createCoverageMap } from 'istanbul-lib-coverage'; import { createSourceMapStore } from 'istanbul-lib-source-maps'; +const createSourceMapStoreMock = createSourceMapStore as jest.Mock; +const createCoverageMapMock = createCoverageMap as jest.Mock; describe('CoverageMapProvider', () => { describe('constructor()', () => { it('should initialize the coverage map', () => { @@ -16,15 +18,17 @@ describe('CoverageMapProvider', () => { }); describe('map', () => { - it('should return the coverage map', () => { - (createCoverageMap as jest.Mock).mockImplementation((map) => map); - createSourceMapStore.mockReturnValueOnce({ - transformCoverage: (map) => ({ map }), + it('should return the coverage map', async () => { + expect.hasAssertions(); + + createCoverageMapMock.mockImplementation((map) => map); + createSourceMapStoreMock.mockReturnValueOnce({ + transformCoverage: (map) => Promise.resolve(map), }); const expected: any = {}; const sut = new CoverageMapProvider(); - sut.update(expected); + await sut.update(expected); expect(sut.map).toBe(expected); }); @@ -39,74 +43,82 @@ describe('CoverageMapProvider', () => { }); describe('update()', () => { - it('should transform the coverage map', () => { + it('should transform the coverage map', async () => { + expect.hasAssertions(); + const expected: any = {}; (createCoverageMap as jest.Mock).mockImplementation((map) => map); const transformCoverage = jest.fn().mockImplementationOnce((map) => ({ map })); - createSourceMapStore.mockReturnValueOnce({ transformCoverage }); + createSourceMapStoreMock.mockReturnValueOnce({ transformCoverage }); const sut = new CoverageMapProvider(); - sut.update(expected); + await sut.update(expected); expect(transformCoverage).toBeCalledWith(expected); }); - it('should store the transformed coverage map', () => { + it('should store the transformed coverage map', async () => { const expected: any = {}; - createSourceMapStore.mockReturnValueOnce({ - transformCoverage: () => ({ map: expected }), + createSourceMapStoreMock.mockReturnValueOnce({ + transformCoverage: () => Promise.resolve(expected), }); const sut = new CoverageMapProvider(); - sut.update(expected); + await sut.update(expected); expect(sut.map).toBe(expected); }); - it('can preserve the previous maps', () => { - const map1: any = {}; - const map2: any = {}; + it('can preserve the previous maps', async () => { + expect.hasAssertions(); - const mergeFn = jest.fn(); - (createCoverageMap as jest.Mock).mockReturnValueOnce({ + const createTestMap = (mapName: string, fileNames: string[]) => ({ + files: () => fileNames, + fileCoverageFor: (name: string) => ({ name, from: mapName }), + }); + + const map1: any = createTestMap('map1', ['f1', 'f2']); + const map2: any = createTestMap('map2', ['f1', 'f3']); + createCoverageMapMock.mockReturnValueOnce({ data: {}, - merge: mergeFn, }); - createSourceMapStore.mockReturnValue({ - transformCoverage: (m) => ({ map: m }), + createSourceMapStoreMock.mockReturnValue({ + transformCoverage: (m) => Promise.resolve(m), }); const sut = new CoverageMapProvider(); - sut.update(map1); - sut.update(map2); + await sut.update(map1); + await sut.update(map2); - expect(mergeFn).toBeCalledTimes(2); + expect(sut.getFileCoverage('f1')).toEqual({ name: 'f1', from: 'map2' }); + expect(sut.getFileCoverage('f2')).toEqual({ name: 'f2', from: 'map1' }); + expect(sut.getFileCoverage('f3')).toEqual({ name: 'f3', from: 'map2' }); }); }); describe('getFileCoverage()', () => { - it('should return the file coverage if found', () => { + it('should return the file coverage if found', async () => { + expect.hasAssertions(); const filePath = 'file.js'; const expected: any = {}; - createSourceMapStore.mockReturnValueOnce({ - transformCoverage: () => ({ - map: { + createSourceMapStoreMock.mockReturnValueOnce({ + transformCoverage: () => + Promise.resolve({ data: { [filePath]: expected, }, - }, - }), + }), }); const sut = new CoverageMapProvider(); - sut.update(undefined); + await sut.update(undefined); expect(sut.getFileCoverage(filePath)).toBe(expected); }); it('should return nothing when the file path is not found', () => { - (createCoverageMap as jest.Mock).mockReturnValueOnce({ + createCoverageMapMock.mockReturnValueOnce({ data: {}, }); const sut = new CoverageMapProvider(); @@ -114,4 +126,22 @@ describe('CoverageMapProvider', () => { expect(sut.getFileCoverage('unknown')).toBeUndefined(); }); }); + describe('onVisibilityChange', () => { + it('visibility = false => the internal maps and store will be reset', () => { + const sut = new CoverageMapProvider(); + jest.clearAllMocks(); + + sut.onVisibilityChanged(false); + expect(createCoverageMapMock).toBeCalledTimes(1); + expect(createSourceMapStoreMock).toBeCalledTimes(1); + }); + it('visibility = true => no-op', () => { + const sut = new CoverageMapProvider(); + jest.clearAllMocks(); + + sut.onVisibilityChanged(true); + expect(createCoverageMapMock).toBeCalledTimes(0); + expect(createSourceMapStoreMock).toBeCalledTimes(0); + }); + }); }); diff --git a/tests/Coverage/Formatters/GutterFormatter.test.ts b/tests/Coverage/Formatters/GutterFormatter.test.ts index 5eb4ec3ad..5b4807ec5 100644 --- a/tests/Coverage/Formatters/GutterFormatter.test.ts +++ b/tests/Coverage/Formatters/GutterFormatter.test.ts @@ -238,7 +238,7 @@ describe('GutterFormatter', () => { asAbsolutePath: (path: string) => path, }; const fileCoverage: any = { - getUncoveredLines: () => ['1', '10'], + getUncoveredLines: () => [1, 10], b: {}, branchMap: {}, }; diff --git a/tests/JestExt.test.ts b/tests/JestExt.test.ts index ff19096b7..208cc8a58 100644 --- a/tests/JestExt.test.ts +++ b/tests/JestExt.test.ts @@ -26,6 +26,7 @@ import * as decorations from '../src/decorations'; import { updateCurrentDiagnostics } from '../src/diagnostics'; import { JestProcessManager, JestProcess } from '../src/JestProcessManagement'; import * as messaging from '../src/messaging'; +import { CoverageMapProvider } from '../src/Coverage'; /* eslint jest/expect-expect: ["error", { "assertFunctionNames": ["expect", "expectItTakesNoAction"] }] */ @@ -69,6 +70,7 @@ describe('JestExt', () => { debugCodeLensProvider, debugConfigurationProvider, null, + null, null ); @@ -132,6 +134,7 @@ describe('JestExt', () => { debugCodeLensProvider, debugConfigurationProvider, null, + null, null ); const editor: any = { @@ -186,6 +189,7 @@ describe('JestExt', () => { debugCodeLensProvider, debugConfigurationProvider, null, + null, null ); ((sut.debugConfigurationProvider @@ -219,6 +223,7 @@ describe('JestExt', () => { debugCodeLensProvider, debugConfigurationProvider, null, + null, null ); const document = {} as any; @@ -247,6 +252,7 @@ describe('JestExt', () => { debugCodeLensProvider, debugConfigurationProvider, null, + null, null ); sut.testResultProvider.removeCachedResults = jest.fn(); @@ -282,6 +288,7 @@ describe('JestExt', () => { debugCodeLensProvider, debugConfigurationProvider, null, + null, null ); @@ -317,6 +324,7 @@ describe('JestExt', () => { debugCodeLensProvider, debugConfigurationProvider, null, + null, null ); sut.triggerUpdateActiveEditor = jest.fn(); @@ -354,6 +362,7 @@ describe('JestExt', () => { debugCodeLensProvider, debugConfigurationProvider, null, + null, null ); }); @@ -431,6 +440,7 @@ describe('JestExt', () => { debugCodeLensProvider, debugConfigurationProvider, null, + null, null ); sut.triggerUpdateSettings = jest.fn(); @@ -450,6 +460,7 @@ describe('JestExt', () => { debugCodeLensProvider, debugConfigurationProvider, null, + null, null ); expect(projectWorkspace.collectCoverage).toBe(true); @@ -478,6 +489,7 @@ describe('JestExt', () => { debugCodeLensProvider, debugConfigurationProvider, null, + null, null ); sut.triggerUpdateActiveEditor(editor); @@ -494,6 +506,7 @@ describe('JestExt', () => { debugCodeLensProvider, debugConfigurationProvider, null, + null, null ); sut.updateDecorators = jest.fn(); @@ -534,6 +547,7 @@ describe('JestExt', () => { debugCodeLensProvider, debugConfigurationProvider, null, + null, null ); }); @@ -590,6 +604,7 @@ describe('JestExt', () => { debugCodeLensProvider, debugConfigurationProvider, null, + null, null ); @@ -663,6 +678,7 @@ describe('JestExt', () => { debugCodeLensProvider, debugConfigurationProvider, null, + null, null ); @@ -702,7 +718,8 @@ describe('JestExt', () => { debugCodeLensProvider, debugConfigurationProvider, null, - instanceSettings + instanceSettings, + null ); const mockProcessManager: any = (JestProcessManager as jest.Mock).mock.instances[0]; mockProcessManager.startJestProcess.mockReturnValue(mockProcess); @@ -785,6 +802,7 @@ describe('JestExt', () => { debugCodeLensProvider, debugConfigurationProvider, null, + null, null ); }); @@ -810,4 +828,28 @@ describe('JestExt', () => { expect(channelStub.appendLine).not.toHaveBeenCalled(); }); }); + describe('_updateCoverageMap', () => { + it('the overlay and codeLens will be updated when map updated async', async () => { + expect.hasAssertions(); + (CoverageMapProvider as jest.Mock).mockImplementation(() => ({ + update: () => Promise.resolve(), + })); + const coverageCodeLensProvider: any = { coverageChanged: jest.fn() }; + const sut = new JestExt( + null, + workspaceFolder, + projectWorkspace, + channelStub, + extensionSettings, + debugCodeLensProvider, + debugConfigurationProvider, + null, + null, + coverageCodeLensProvider + ); + await sut._updateCoverageMap({}); + expect(coverageCodeLensProvider.coverageChanged).toBeCalled(); + expect(sut.coverageOverlay.updateVisibleEditors).toBeCalled(); + }); + }); }); diff --git a/typings/istanbul-lib-coverage.d.ts b/typings/istanbul-lib-coverage.d.ts deleted file mode 100644 index 6cda31eb9..000000000 --- a/typings/istanbul-lib-coverage.d.ts +++ /dev/null @@ -1,57 +0,0 @@ -declare module 'istanbul-lib-coverage' { - class CoverageMap { - data: { [fileName: string]: FileCoverage } - fileCoverageFor(file: string): FileCoverage - files(): string[] - merge(map: CoverageMap): void - } - - class FileCoverage { - getUncoveredLines(): string[] - toSummary(): CoverageSummary - b: HitCount - branchMap: BranchMap - path: string - } - - interface HitCount { - [key: string]: number[] - } - - interface BranchMap { - [key: string]: BranchData - } - - interface BranchData { - loc: Location - locations: Location[] - } - - interface Location { - end: Position - start: Position - } - - interface Position { - line: number - column: number - } - - interface Metric { - total: number - covered: number - skipped: number - pct: number - } - - class CoverageSummary { - toJSON(): { - lines: Metric - statements: Metric - branches: Metric - functions: Metric - } - } - - function createCoverageMap(map?: CoverageMap | Object): CoverageMap -} diff --git a/yarn.lock b/yarn.lock index 44b59df7a..dcefb784c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -651,6 +651,11 @@ resolved "https://registry.yarnpkg.com/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.1.tgz#42995b446db9a48a11a07ec083499a860e9138ff" integrity sha512-hRJD2ahnnpLgsj6KWMYSrmXkM3rm2Dl1qkx6IOFD5FnuNPXJIG5L0dhgKXCYTRMGzU4n0wImQ/xfmRc4POUFlg== +"@types/istanbul-lib-coverage@^2.0.2": + version "2.0.2" + resolved "https://registry.yarnpkg.com/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.2.tgz#79d7a78bad4219f4c03d6557a1c72d9ca6ba62d5" + integrity sha512-rsZg7eL+Xcxsxk2XlBt9KcG8nOp9iYdKCOikY9x2RFJCyOdNj4MKPQty0e8oZr29vVAzKXr1BmR+kZauti3o1w== + "@types/istanbul-lib-report@*": version "3.0.0" resolved "https://registry.yarnpkg.com/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz#c14c24f18ea8190c118ee7562b7ff99a36552686" @@ -658,6 +663,14 @@ dependencies: "@types/istanbul-lib-coverage" "*" +"@types/istanbul-lib-source-maps@^4.0.1": + version "4.0.1" + resolved "https://registry.yarnpkg.com/@types/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz#8acb1f6230bf9d732e9fc30590e5ccaabbefec7b" + integrity sha512-WH6e5naLXI3vB2Px3whNeYxzDgm6S6sk3Ht8e3/BiWwEnzZi72wja3bWzWwcgbFTFp8hBLB7NT2p3lNJgxCxvA== + dependencies: + "@types/istanbul-lib-coverage" "*" + source-map "^0.6.1" + "@types/istanbul-reports@^1.1.1": version "1.1.1" resolved "https://registry.yarnpkg.com/@types/istanbul-reports/-/istanbul-reports-1.1.1.tgz#7a8cbf6a406f36c8add871625b278eaf0b0d255a" @@ -3472,11 +3485,6 @@ isstream@~0.1.2: resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" integrity sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo= -istanbul-lib-coverage@^1.1.1, istanbul-lib-coverage@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-1.2.1.tgz#ccf7edcd0a0bb9b8f729feeb0930470f9af664f0" - integrity sha512-PzITeunAgyGbtY1ibVIUiV679EFChHjoMNRibEIobvmrCRaIgwLxNucOSimtNWUhEib/oO7QY2imD75JVgCJWQ== - istanbul-lib-coverage@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-3.0.0.tgz#f5944a37c70b550b02a78a5c3b2055b280cec8ec" @@ -3504,17 +3512,6 @@ istanbul-lib-report@^3.0.0: make-dir "^3.0.0" supports-color "^7.1.0" -istanbul-lib-source-maps@^1.1.0: - version "1.2.6" - resolved "https://registry.yarnpkg.com/istanbul-lib-source-maps/-/istanbul-lib-source-maps-1.2.6.tgz#37b9ff661580f8fca11232752ee42e08c6675d8f" - integrity sha512-TtbsY5GIHgbMsMiRw35YBHGpZ1DVFEO19vxxeiDMYaeOFOCzfnYVxvl6pOUIZR4dtPhAGpSMup8OyF8ubsaqEg== - dependencies: - debug "^3.1.0" - istanbul-lib-coverage "^1.2.1" - mkdirp "^0.5.1" - rimraf "^2.6.1" - source-map "^0.5.3" - istanbul-lib-source-maps@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.0.tgz#75743ce6d96bb86dc7ee4352cf6366a23f0b1ad9" @@ -5616,7 +5613,7 @@ rimraf@2.6.3: dependencies: glob "^7.1.3" -rimraf@^2.5.4, rimraf@^2.6.1, rimraf@^2.6.3: +rimraf@^2.5.4, rimraf@^2.6.3: version "2.7.1" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec" integrity sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w== @@ -5880,7 +5877,7 @@ source-map-url@^0.4.0: resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.4.0.tgz#3e935d7ddd73631b97659956d55128e87b5084a3" integrity sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM= -source-map@^0.5.0, source-map@^0.5.3, source-map@^0.5.6: +source-map@^0.5.0, source-map@^0.5.6: version "0.5.7" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" integrity sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w= From 140523e722e8a237d13649b384f1e68415e2ad04 Mon Sep 17 00:00:00 2001 From: connectdotz Date: Mon, 25 May 2020 22:34:55 -0400 Subject: [PATCH 2/6] update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2d3f3e5f0..e1495a74a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ Bug-fixes within the same version aren't needed * improve the detection of cases in which Jest needs to be restarted with `--watchAll` - [@lordofthelake](https://github.com/lordofthelake) * upgrade all dependencies to the latest, except istanbul-lib-xxx, which requires more code change and will be handled in a separate coverage PR. - @connectdotz * code base clean up: migrate from tslint to eslint and adopted the latest recommended coding style, adopt semi-colon, added more ci check... - @connectdotz +* upgrade istanbul dependencies to the latest and move to async coverageMap update. @connectdotz --> ### 3.2.0 From 0f1eac0b4e3cfe96157a97e91236d590f78c3a4f Mon Sep 17 00:00:00 2001 From: ConnectDotz Date: Sun, 7 Jun 2020 11:48:26 -0400 Subject: [PATCH 3/6] Update src/JestExt.ts Co-authored-by: Sean Poulter --- src/JestExt.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/JestExt.ts b/src/JestExt.ts index 7b0a86c68..b0af914ce 100644 --- a/src/JestExt.ts +++ b/src/JestExt.ts @@ -419,7 +419,7 @@ export class JestExt { private generateInlineErrorDecorator( fileName: string, test: TestResult - ): { style: vscode.TextEditorDecorationType; decorator: vscode.DecorationOptions } { + ): { decorator: vscode.DecorationOptions; style: vscode.TextEditorDecorationType } { const errorMessage = test.terseMessage || test.shortMessage; const decorator = { range: new vscode.Range(test.lineNumberOfError, 0, test.lineNumberOfError, 0), From 0cd82e53e87fb7d22743b182c28263ff75b11332 Mon Sep 17 00:00:00 2001 From: ConnectDotz Date: Sun, 7 Jun 2020 11:48:41 -0400 Subject: [PATCH 4/6] Update src/Coverage/Formatters/helpers.ts Co-authored-by: Sean Poulter --- src/Coverage/Formatters/helpers.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Coverage/Formatters/helpers.ts b/src/Coverage/Formatters/helpers.ts index 8ab5dea74..2cab8973a 100644 --- a/src/Coverage/Formatters/helpers.ts +++ b/src/Coverage/Formatters/helpers.ts @@ -1,4 +1,4 @@ -import { Range, Location } from 'istanbul-lib-coverage'; +import { Location, Range } from 'istanbul-lib-coverage'; export function isValidPosition(p: Location): boolean { return (p || false) && p.line !== null && p.line >= 0; From 5a9c61e209f3ed158d7d903e865630a88791ca83 Mon Sep 17 00:00:00 2001 From: connectdotz Date: Sun, 7 Jun 2020 12:15:54 -0400 Subject: [PATCH 5/6] address review --- src/Coverage/CoverageMapProvider.ts | 6 +++--- src/Coverage/Formatters/helpers.ts | 2 +- tests/Coverage/CoverageMapProvider.test.ts | 16 ++++++++++------ 3 files changed, 14 insertions(+), 10 deletions(-) diff --git a/src/Coverage/CoverageMapProvider.ts b/src/Coverage/CoverageMapProvider.ts index 368612fa7..c480a0df2 100644 --- a/src/Coverage/CoverageMapProvider.ts +++ b/src/Coverage/CoverageMapProvider.ts @@ -15,10 +15,10 @@ export class CoverageMapProvider { private _map: CoverageMap; constructor() { - this.init(); + this.reset(); } - init(): void { + reset(): void { this._map = createCoverageMap(); this.mapStore = createSourceMapStore(); } @@ -46,7 +46,7 @@ export class CoverageMapProvider { } public onVisibilityChanged(visible: boolean): void { if (!visible) { - this.init(); + this.reset(); } } } diff --git a/src/Coverage/Formatters/helpers.ts b/src/Coverage/Formatters/helpers.ts index 8ab5dea74..2cab8973a 100644 --- a/src/Coverage/Formatters/helpers.ts +++ b/src/Coverage/Formatters/helpers.ts @@ -1,4 +1,4 @@ -import { Range, Location } from 'istanbul-lib-coverage'; +import { Location, Range } from 'istanbul-lib-coverage'; export function isValidPosition(p: Location): boolean { return (p || false) && p.line !== null && p.line >= 0; diff --git a/tests/Coverage/CoverageMapProvider.test.ts b/tests/Coverage/CoverageMapProvider.test.ts index 2fb9d0f9e..8213e3f66 100644 --- a/tests/Coverage/CoverageMapProvider.test.ts +++ b/tests/Coverage/CoverageMapProvider.test.ts @@ -7,6 +7,9 @@ import { createSourceMapStore } from 'istanbul-lib-source-maps'; const createSourceMapStoreMock = createSourceMapStore as jest.Mock; const createCoverageMapMock = createCoverageMap as jest.Mock; describe('CoverageMapProvider', () => { + beforeEach(() => { + jest.resetAllMocks(); + }); describe('constructor()', () => { it('should initialize the coverage map', () => { const expected: any = {}; @@ -79,9 +82,8 @@ describe('CoverageMapProvider', () => { const map1: any = createTestMap('map1', ['f1', 'f2']); const map2: any = createTestMap('map2', ['f1', 'f3']); - createCoverageMapMock.mockReturnValueOnce({ - data: {}, - }); + createCoverageMapMock.mockImplementation((m) => m || { data: {} }); + createSourceMapStoreMock.mockReturnValue({ transformCoverage: (m) => Promise.resolve(m), }); @@ -90,6 +92,7 @@ describe('CoverageMapProvider', () => { await sut.update(map1); await sut.update(map2); + // expect f2 is override by map2, while the f1 and f3 remains in the map as expected. expect(sut.getFileCoverage('f1')).toEqual({ name: 'f1', from: 'map2' }); expect(sut.getFileCoverage('f2')).toEqual({ name: 'f2', from: 'map1' }); expect(sut.getFileCoverage('f3')).toEqual({ name: 'f3', from: 'map2' }); @@ -129,11 +132,12 @@ describe('CoverageMapProvider', () => { describe('onVisibilityChange', () => { it('visibility = false => the internal maps and store will be reset', () => { const sut = new CoverageMapProvider(); - jest.clearAllMocks(); - - sut.onVisibilityChanged(false); expect(createCoverageMapMock).toBeCalledTimes(1); expect(createSourceMapStoreMock).toBeCalledTimes(1); + + sut.onVisibilityChanged(false); + expect(createCoverageMapMock).toBeCalledTimes(2); + expect(createSourceMapStoreMock).toBeCalledTimes(2); }); it('visibility = true => no-op', () => { const sut = new CoverageMapProvider(); From 8f5be2735f2a6bfa6f6a429e3f88b62334180470 Mon Sep 17 00:00:00 2001 From: connectdotz Date: Sun, 7 Jun 2020 12:18:53 -0400 Subject: [PATCH 6/6] update changelog --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e1495a74a..1d1733764 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,7 +9,7 @@ Bug-fixes within the same version aren't needed * improve the detection of cases in which Jest needs to be restarted with `--watchAll` - [@lordofthelake](https://github.com/lordofthelake) * upgrade all dependencies to the latest, except istanbul-lib-xxx, which requires more code change and will be handled in a separate coverage PR. - @connectdotz * code base clean up: migrate from tslint to eslint and adopted the latest recommended coding style, adopt semi-colon, added more ci check... - @connectdotz -* upgrade istanbul dependencies to the latest and move to async coverageMap update. @connectdotz +* resolve coverage map merge issue, upgrade istanbul dependencies to the latest and move to async coverageMap update. @connectdotz --> ### 3.2.0