Skip to content

Commit

Permalink
feat: provide public API to subscribe to test results.
Browse files Browse the repository at this point in the history
  • Loading branch information
rossknudsen committed Sep 28, 2020
1 parent fe6ad24 commit 622aa31
Show file tree
Hide file tree
Showing 5 changed files with 105 additions and 35 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ Bug-fixes within the same version aren't needed
## Master
* add public api to expose interface for other vscode extensions to subscribe to test results updates.
-->

Expand Down
7 changes: 6 additions & 1 deletion src/JestExt.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,8 @@ export class JestExt {
debugConfigurationProvider: DebugConfigurationProvider,
failDiagnostics: vscode.DiagnosticCollection,
instanceSettings: InstanceSettings,
coverageCodeLensProvider: CoverageCodeLensProvider
coverageCodeLensProvider: CoverageCodeLensProvider,
private onTestResultsChanged: (results: JestTotalResults) => void
) {
this.workspaceFolder = workspaceFolder;
this.jestWorkspace = jestWorkspace;
Expand Down Expand Up @@ -515,6 +516,10 @@ export class JestExt {
private updateWithData(data: JestTotalResults): void {
const noAnsiData = resultsWithoutAnsiEscapeSequence(data);
const normalizedData = resultsWithLowerCaseWindowsDriveLetters(noAnsiData);

// notify that there are new test results.
this.onTestResultsChanged(normalizedData);

this._updateCoverageMap(normalizedData.coverageMap);

const statusList = this.testResultProvider.updateTestResults(normalizedData);
Expand Down
6 changes: 5 additions & 1 deletion src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@ import { registerSnapshotCodeLens, registerSnapshotPreview } from './SnapshotCod

let extensionManager: ExtensionManager;

export function activate(context: vscode.ExtensionContext): void {
export function activate(
context: vscode.ExtensionContext
): ReturnType<typeof ExtensionManager.prototype.getPublicApi> {
extensionManager = new ExtensionManager(context);

const languages = [
Expand Down Expand Up @@ -82,6 +84,8 @@ export function activate(context: vscode.ExtensionContext): void {
extensionManager
)
);

return extensionManager.getPublicApi();
}

export function deactivate(): void {
Expand Down
72 changes: 57 additions & 15 deletions src/extensionManager.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import * as vscode from 'vscode';
import * as path from 'path';
import { ProjectWorkspace } from 'jest-editor-support';
import { JestTotalResults, ProjectWorkspace } from 'jest-editor-support';
import { pathToJest, pathToConfig } from './helpers';
import { JestExt } from './JestExt';
import { DebugCodeLensProvider, TestState } from './DebugCodeLens';
Expand Down Expand Up @@ -48,6 +48,8 @@ export class ExtensionManager {
private extByWorkspace: Map<string, JestExt> = new Map();
private context: vscode.ExtensionContext;
private commonPluginSettings: PluginWindowSettings;
// keep track of any subscribers that want to be notified when there are new test results.
private subscribers: Array<(results: JestTotalResults) => void> = [];

constructor(context: vscode.ExtensionContext) {
this.context = context;
Expand Down Expand Up @@ -97,21 +99,21 @@ export class ExtensionManager {
`Jest (${workspaceFolder.name})`
);

this.extByWorkspace.set(
workspaceFolder.name,
new JestExt(
this.context,
workspaceFolder,
jestWorkspace,
channel,
pluginSettings,
this.debugCodeLensProvider,
this.debugConfigurationProvider,
failDiagnostics,
instanceSettings,
this.coverageCodeLensProvider
)
const jestExt = new JestExt(
this.context,
workspaceFolder,
jestWorkspace,
channel,
pluginSettings,
this.debugCodeLensProvider,
this.debugConfigurationProvider,
failDiagnostics,
instanceSettings,
this.coverageCodeLensProvider,
this.onTestResultsChanged.bind(this)
);

this.extByWorkspace.set(workspaceFolder.name, jestExt);
}
registerAll(): void {
vscode.workspace.workspaceFolders.forEach(this.register, this);
Expand All @@ -131,6 +133,8 @@ export class ExtensionManager {
for (const key of keys) {
this.unregisterByName(key);
}

this.subscribers = [];
}
shouldStart(workspaceFolderName: string): boolean {
const {
Expand Down Expand Up @@ -166,6 +170,30 @@ export class ExtensionManager {
throw new Error(`No Jest instance in ${workspace.name} workspace`);
}
}

/**
* Provides the public API for this extension.
*/
// eslint-disable-next-line @typescript-eslint/explicit-function-return-type
public getPublicApi() {
return {
/**
* Provides a means to subscribe to test results events.
*
* @param callback method to be called when there are new test results.
*/
subscribeToTestResults: (callback: (results: JestTotalResults) => void): (() => void) => {
this.subscribers.push(callback);

// return an unsubscribe function.
// eslint-disable-next-line @typescript-eslint/explicit-function-return-type
return () => {
this.subscribers = this.subscribers.filter((s) => s !== callback);
};
},
};
}

registerCommand(
command: string,
callback: (extension: JestExt, ...args: unknown[]) => unknown,
Expand Down Expand Up @@ -216,4 +244,18 @@ export class ExtensionManager {
ext.onDidChangeTextDocument(event);
}
}

/**
* A handler for when there are new test results from one of the JestExt instances.
* @param results the new test results
*/
private onTestResultsChanged(results: JestTotalResults): void {
this.subscribers.forEach((subscriber) => {
try {
subscriber(results);
} catch (error) {
// swallow the error as we are not responsible for it.
}
});
}
}
54 changes: 36 additions & 18 deletions tests/JestExt.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,8 @@ describe('JestExt', () => {
debugConfigurationProvider,
null,
null,
null
null,
() => {}
);

sut.canUpdateActiveEditor = jest.fn().mockReturnValueOnce(true);
Expand Down Expand Up @@ -145,7 +146,8 @@ describe('JestExt', () => {
debugConfigurationProvider,
null,
null,
null
null,
() => {}
);
const editor: any = {
document: { fileName: 'file.js' },
Expand Down Expand Up @@ -196,7 +198,8 @@ describe('JestExt', () => {
debugConfigurationProvider,
null,
null,
null
null,
() => {}
);
((sut.debugConfigurationProvider
.provideDebugConfigurations as unknown) as jest.Mock<{}>).mockReturnValue([
Expand Down Expand Up @@ -230,7 +233,8 @@ describe('JestExt', () => {
debugConfigurationProvider,
null,
null,
null
null,
() => {}
);
const document = {} as any;
sut.removeCachedTestResults = jest.fn();
Expand Down Expand Up @@ -259,7 +263,8 @@ describe('JestExt', () => {
debugConfigurationProvider,
null,
null,
null
null,
() => {}
);
sut.testResultProvider.removeCachedResults = jest.fn();

Expand Down Expand Up @@ -295,7 +300,8 @@ describe('JestExt', () => {
debugConfigurationProvider,
null,
null,
null
null,
() => {}
);

beforeEach(() => {
Expand Down Expand Up @@ -331,7 +337,8 @@ describe('JestExt', () => {
debugConfigurationProvider,
null,
null,
null
null,
() => {}
);
sut.triggerUpdateActiveEditor = jest.fn();

Expand Down Expand Up @@ -369,7 +376,8 @@ describe('JestExt', () => {
debugConfigurationProvider,
null,
null,
null
null,
() => {}
);
});

Expand Down Expand Up @@ -447,7 +455,8 @@ describe('JestExt', () => {
debugConfigurationProvider,
null,
null,
null
null,
() => {}
);
sut.triggerUpdateSettings = jest.fn();
sut.toggleCoverageOverlay();
Expand All @@ -467,7 +476,8 @@ describe('JestExt', () => {
debugConfigurationProvider,
null,
null,
null
null,
() => {}
);
expect(projectWorkspace.collectCoverage).toBe(true);

Expand Down Expand Up @@ -496,7 +506,8 @@ describe('JestExt', () => {
debugConfigurationProvider,
null,
null,
null
null,
() => {}
);
sut.triggerUpdateActiveEditor(editor);

Expand All @@ -513,7 +524,8 @@ describe('JestExt', () => {
debugConfigurationProvider,
null,
null,
null
null,
() => {}
);
sut.updateDecorators = jest.fn();
const mockEditor: any = {
Expand Down Expand Up @@ -554,7 +566,8 @@ describe('JestExt', () => {
debugConfigurationProvider,
null,
null,
null
null,
() => {}
);
});
it('will skip if there is no document in editor', () => {
Expand Down Expand Up @@ -613,7 +626,8 @@ describe('JestExt', () => {
debugConfigurationProvider,
null,
null,
null
null,
() => {}
);

mockEditor.setDecorations = jest.fn();
Expand Down Expand Up @@ -685,7 +699,8 @@ describe('JestExt', () => {
debugConfigurationProvider,
null,
null,
null
null,
() => {}
);

mockEditor.setDecorations = jest.fn();
Expand Down Expand Up @@ -725,7 +740,8 @@ describe('JestExt', () => {
debugConfigurationProvider,
null,
instanceSettings,
null
null,
() => {}
);
const mockProcessManager: any = (JestProcessManager as jest.Mock).mock.instances[0];
mockProcessManager.startJestProcess.mockReturnValue(mockProcess);
Expand Down Expand Up @@ -809,7 +825,8 @@ describe('JestExt', () => {
debugConfigurationProvider,
null,
null,
null
null,
() => {}
);
});

Expand Down Expand Up @@ -851,7 +868,8 @@ describe('JestExt', () => {
debugConfigurationProvider,
null,
null,
coverageCodeLensProvider
coverageCodeLensProvider,
() => {}
);
await sut._updateCoverageMap({});
expect(coverageCodeLensProvider.coverageChanged).toBeCalled();
Expand Down

0 comments on commit 622aa31

Please sign in to comment.