Skip to content

Commit

Permalink
feat: status indicator in gutter (#554)
Browse files Browse the repository at this point in the history
da7eaa9 refactor: status indicator svg icons
4d54331 fix: update changelog
fa38ae8 refactor: simplify test status decorators
e115488 feat: test state indicators
eca8a9a feat: status indicator in gutter proof-of-concept
  • Loading branch information
Tymek committed Jun 29, 2020
1 parent 73de52f commit e177c64
Show file tree
Hide file tree
Showing 8 changed files with 53 additions and 78 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
* move test status indicator from editor text to gutter [@Tymek](https://github.com/Tymek)
* improve create-react-app detection logic - stephtr
* 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
Expand Down
10 changes: 6 additions & 4 deletions src/JestExt.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ export class JestExt {

private jestWorkspace: ProjectWorkspace;
private pluginSettings: PluginResourceSettings;
private context: vscode.ExtensionContext;
private workspaceFolder: vscode.WorkspaceFolder;
private instanceSettings: InstanceSettings;

Expand Down Expand Up @@ -82,6 +83,7 @@ export class JestExt {
instanceSettings: InstanceSettings,
coverageCodeLensProvider: CoverageCodeLensProvider
) {
this.context = context;
this.workspaceFolder = workspaceFolder;
this.jestWorkspace = jestWorkspace;
this.channel = outputChannel;
Expand Down Expand Up @@ -503,10 +505,10 @@ export class JestExt {
}

private setupDecorators(): void {
this.passingItStyle = decorations.passingItName();
this.failingItStyle = decorations.failingItName();
this.skipItStyle = decorations.skipItName();
this.unknownItStyle = decorations.notRanItName();
this.passingItStyle = decorations.passingItName(this.context);
this.failingItStyle = decorations.failingItName(this.context);
this.skipItStyle = decorations.skipItName(this.context);
this.unknownItStyle = decorations.notRanItName(this.context);
}

private shouldIgnoreOutput(text: string): boolean {
Expand Down
95 changes: 25 additions & 70 deletions src/decorations.ts
Original file line number Diff line number Diff line change
@@ -1,86 +1,41 @@
import { window, OverviewRulerLane, DecorationRangeBehavior } from 'vscode';
import {
window,
OverviewRulerLane,
DecorationRangeBehavior,
ExtensionContext,
TextEditorDecorationType,
} from 'vscode';

export function failingItName() {
function createTestStateDecoration(
context: ExtensionContext,
icon: string,
overviewRulerColor: string
): TextEditorDecorationType {
return window.createTextEditorDecorationType({
overviewRulerColor: 'red',
overviewRulerColor,
gutterIconPath: context.asAbsolutePath(`./src/icons/${icon}.svg`),
overviewRulerLane: OverviewRulerLane.Left,
light: {
before: {
color: '#FF564B',
contentText: '✘ ',
},
},
dark: {
before: {
color: '#AD322D',
contentText: '✘ ',
},
},
rangeBehavior: DecorationRangeBehavior.ClosedClosed,
});
}

export function skipItName() {
return window.createTextEditorDecorationType({
overviewRulerColor: 'yellow',
overviewRulerLane: OverviewRulerLane.Left,
light: {
before: {
color: '#fed37f',
contentText: '○ ',
},
},
dark: {
before: {
color: '#fed37f',
contentText: '○ ',
},
},
rangeBehavior: DecorationRangeBehavior.ClosedClosed,
});
export function passingItName(context: ExtensionContext): TextEditorDecorationType {
return createTestStateDecoration(context, 'passing', 'green');
}

export function passingItName() {
return window.createTextEditorDecorationType({
overviewRulerColor: 'green',
overviewRulerLane: OverviewRulerLane.Left,
light: {
before: {
color: '#3BB26B',
contentText: '✔ ',
},
},
dark: {
before: {
color: '#2F8F51',
contentText: '✔ ',
},
},
rangeBehavior: DecorationRangeBehavior.ClosedClosed,
});
export function failingItName(context: ExtensionContext): TextEditorDecorationType {
return createTestStateDecoration(context, 'failing', 'red');
}

export function notRanItName() {
return window.createTextEditorDecorationType({
overviewRulerColor: 'darkgrey',
overviewRulerLane: OverviewRulerLane.Left,
dark: {
before: {
color: '#9C9C9C',
contentText: '○ ',
},
},
light: {
before: {
color: '#7C7C7C',
contentText: '○ ',
},
},
rangeBehavior: DecorationRangeBehavior.ClosedClosed,
});
export function skipItName(context: ExtensionContext): TextEditorDecorationType {
return createTestStateDecoration(context, 'skip', 'yellow');
}

export function notRanItName(context: ExtensionContext): TextEditorDecorationType {
return createTestStateDecoration(context, 'unknown', 'darkgrey');
}

export function failingAssertionStyle(text: string) {
export function failingAssertionStyle(text: string): TextEditorDecorationType {
return window.createTextEditorDecorationType({
isWholeLine: true,
overviewRulerColor: 'red',
Expand Down
1 change: 1 addition & 0 deletions src/icons/failing.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions src/icons/passing.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions src/icons/skip.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions src/icons/unknown.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
21 changes: 17 additions & 4 deletions tests/decorations.test.ts
Original file line number Diff line number Diff line change
@@ -1,27 +1,40 @@
jest.unmock('../src/decorations');

jest.mock('vscode', () => {
return {
DecorationRangeBehavior: {
ClosedClosed: {},
},
OverviewRulerLane: {},
OverviewRulerLane: {
Left: {},
},
window: {
createTextEditorDecorationType: jest.fn(),
},
TextEditorDecorationType: jest.fn(),
};
});

import { passingItName, failingItName, skipItName, notRanItName } from '../src/decorations';
import * as vscode from 'vscode';

function testRangeBehavior(factoryMethod: () => void) {
function testRangeBehavior(
factoryMethod: (context: vscode.ExtensionContext) => vscode.TextEditorDecorationType
) {
it('should set the range behavior', () => {
const mock = (vscode.window.createTextEditorDecorationType as unknown) as jest.Mock<{}>;
const context = {
asAbsolutePath: (name: string) => name,
};
mock.mockReset();
factoryMethod();

expect(mock.mock.calls).toHaveLength(1);
factoryMethod((context as unknown) as vscode.ExtensionContext);

expect(mock).toHaveBeenCalledTimes(1);
expect(mock.mock.calls[0][0].rangeBehavior).toBe(vscode.DecorationRangeBehavior.ClosedClosed);
expect(mock.mock.calls[0][0].overviewRulerLane).toBe(vscode.OverviewRulerLane.Left);
expect(mock.mock.calls[0][0].overviewRulerColor).toBeTruthy();
expect(mock.mock.calls[0][0].gutterIconPath).toBeTruthy();
});
}

Expand Down

0 comments on commit e177c64

Please sign in to comment.