Skip to content

Commit

Permalink
feat: adds insert text from gist
Browse files Browse the repository at this point in the history
  • Loading branch information
Ken Howard committed Dec 21, 2018
1 parent 9965742 commit 7e7c359
Show file tree
Hide file tree
Showing 10 changed files with 346 additions and 8 deletions.
4 changes: 4 additions & 0 deletions __mocks__/vscode.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
// tslint:disable:no-any
module.exports = {
Position: jest.fn(),
Range: jest.fn(),
StatusBarAlignment: {
Left: true
},
Uri: { parse: jest.fn((url: string) => url) },
WorkspaceEdit: jest.fn(() => ({ replace: jest.fn() })),
commands: {
executeCommand: jest.fn()
},
Expand All @@ -22,6 +25,7 @@ module.exports = {
showTextDocument: jest.fn()
},
workspace: {
applyEdit: jest.fn().mockResolvedValue(true),
getConfiguration: jest.fn(() => ({ get: jest.fn(), update: jest.fn() })),
openTextDocument: jest.fn()
}
Expand Down
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,8 @@
"category": "GIST"
},
{
"command": "extension.insertCode",
"title": "Insert Code Into Current File",
"command": "extension.gist.insert",
"title": "Insert Text From Gist File",
"category": "GIST"
},
{
Expand Down
1 change: 1 addition & 0 deletions src/commands/commands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ const commandInitializers: CommandInitializer[] = [
gists.create,
gists.deleteCommand,
gists.deleteFile,
gists.insert,
gists.open,
gists.openFavorite,
gists.openInBrowser,
Expand Down
1 change: 1 addition & 0 deletions src/commands/extension-commands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ enum GistCommands {
Create = 'extension.gist.create',
Delete = 'extension.gist.delete',
DeleteFile = 'extension.gist.deleteFile',
Insert = 'extension.gist.insert',
Open = 'extension.gist.open',
OpenFavorite = 'extension.gist.openFavorite',
OpenInBrowser = 'extension.gist.openInBrowser',
Expand Down
8 changes: 8 additions & 0 deletions src/commands/gists/__tests__/delete.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,14 @@ describe('open gist', () => {
afterEach(() => {
jest.clearAllMocks();
});
test('should log error when no editor', async () => {
expect.assertions(1);

(<any>window.activeTextEditor) = undefined;

await deleteFn();
expect(errorMock.mock.calls.length).toBe(1);
});
test('what happens when errors occur', async () => {
expect.assertions(1);

Expand Down
129 changes: 129 additions & 0 deletions src/commands/gists/__tests__/insert.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
// tslint:disable:no-any no-magic-numbers
import { window } from 'vscode';

import { insert } from '../insert';

jest.mock('fs');
jest.mock('path');

const showQuickPickSpy = jest.spyOn(window, 'showQuickPick');

const getGistsMock = jest.fn(() => [
{
createdAt: new Date(),
description: 'some markdown file',
fileCount: 1,
files: { 'file-one.md': { content: 'test' } },
id: '123',
name: 'gist one',
public: true,
updatedAt: new Date()
},
{
createdAt: new Date(),
description: 'some markdown file',
fileCount: 1,
files: { 'file-two.md': { content: 'test' } },
id: '123',
name: 'gist two',
public: true,
updatedAt: new Date()
}
]);

const updateGistMock = jest.fn();
const getGistMock = jest.fn((id: string) => ({
createdAt: new Date(),
description: 'some markdown file',
fileCount: 1,
files: {
'file-one.md': { content: 'test' },
'file-two.md': { content: 'test' }
},
id,
name: 'test',
public: true,
updatedAt: new Date()
}));
const utilsMock = jest.genMockFromModule<Utils>('../../../utils');
const errorMock = jest.fn();

describe('open gist', () => {
let insertFn: CommandFn;
beforeEach(() => {
const gists = {
getGist: getGistMock,
getGists: getGistsMock,
updateGist: updateGistMock
};
const insights = { exception: jest.fn() };
const logger = { debug: jest.fn(), error: errorMock, info: jest.fn() };
insertFn = insert({ gists, insights, logger } as any, utilsMock as any)[1];
window.activeTextEditor = <any>{
document: { getText: jest.fn() },
selection: { isEmpty: true }
};
});
afterEach(() => {
jest.clearAllMocks();
});
test('should log error when no editor', async () => {
expect.assertions(1);

(<any>window.activeTextEditor) = undefined;

await insertFn();
expect(errorMock.mock.calls.length).toBe(1);
});
test('what happens when errors occur', async () => {
expect.assertions(1);

(<any>utilsMock.input.quickPick).mockRejectedValueOnce(false);

await insertFn();
expect(errorMock.mock.calls.length).toBe(1);
});
test('it should prompt the user to select a gist', async () => {
expect.assertions(1);

await insertFn();

expect(utilsMock.input.quickPick).toHaveBeenCalledWith([
expect.any(Object),
expect.any(Object)
]);
});
test('it should query for the users selected gist', async () => {
expect.assertions(1);

(<any>utilsMock.input.quickPick).mockResolvedValueOnce({
block: { id: '123' }
});

await insertFn();

expect(getGistMock).toHaveBeenCalledWith('123');
});
test('it should prompt the user to select a file if more than one is available', async () => {
expect.assertions(1);

(<any>utilsMock.input.quickPick).mockResolvedValueOnce({
block: { id: '123' }
});

await insertFn();

expect(showQuickPickSpy).toHaveBeenCalledWith([
{
description: '',
'file-one.md': expect.any(Object),
label: 'file-one.md'
},
{
description: '',
'file-two.md': expect.any(Object),
label: 'file-two.md'
}
]);
});
});
77 changes: 77 additions & 0 deletions src/commands/gists/__tests__/utils.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
// tslint:disable:no-any no-magic-numbers
import { window, workspace } from 'vscode';

import { openGist, selectFile } from '../utils';

const showQuickPickSpy = jest.spyOn(window, 'showQuickPick');
const showTextDocumentSpy = jest.spyOn(window, 'showTextDocument');
const openTextDocumentMock = jest.spyOn(workspace, 'openTextDocument');

jest.mock('path');
jest.mock('fs');

describe('Gist Command Utils Tests', () => {
afterEach(() => {
jest.clearAllMocks();
});
describe('#openGist', () => {
test('it should open a gist in an editor', async () => {
expect.assertions(3);

const mockDoc = {
getText(): string {
return 'test-file-one';
}
};

openTextDocumentMock.mockImplementationOnce((_filePath: string) =>
Promise.resolve(mockDoc)
);

await openGist({
fileCount: 1,
files: { 'file-one.md': { content: 'test-file-one' } },
id: '123test'
} as any);

expect(showTextDocumentSpy).toHaveBeenCalledTimes(1);
expect(openTextDocumentMock).toHaveBeenCalledWith(
expect.stringContaining('file-one.md')
);
expect(showTextDocumentSpy).toHaveBeenCalledWith(mockDoc);
});
});
describe('#selectFile', () => {
test('it accepts a list of gist files', async () => {
expect.assertions(1);

await selectFile({
files: {
'file-one.md': { content: 'test-content' },
'file-two.md': { content: 'test-content' }
}
} as any);

expect(showQuickPickSpy).toHaveBeenCalledTimes(1);
});
test('it returns a single file when the user selects one', async () => {
expect.assertions(2);
showQuickPickSpy.mockImplementationOnce((items: any[]) =>
Promise.resolve(items[0])
);

const file = await selectFile({
files: {
'file-one.md': { content: 'test-content-one' },
'file-two.md': { content: 'test-content-two' }
}
} as any);

expect(showQuickPickSpy).toHaveBeenCalledTimes(1);
expect(file).toStrictEqual({
content: 'test-content-one',
filename: 'file-one.md'
});
});
});
});
1 change: 1 addition & 0 deletions src/commands/gists/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ export * from './add';
export * from './create';
export * from './delete';
export * from './delete-file';
export * from './insert';
export * from './open';
export * from './open-favorite';
export * from './open-in-browser';
Expand Down
52 changes: 52 additions & 0 deletions src/commands/gists/insert.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import { window } from 'vscode';

import { GistCommands } from '../extension-commands';

import { insertText, selectFile } from './utils';

const insert: CommandInitializer = (
services: Services,
utils: Utils
): [Command, CommandFn] => {
const { gists, insights, logger } = services;

const command = GistCommands.Insert;

const commandFn = async (): Promise<void> => {
try {
const editor = window.activeTextEditor;
if (!editor) {
throw new Error('Open a file before inserting');
}

const list = await gists.getGists();
const selected = await utils.input.quickPick(list);

if (!selected) {
services.logger.debug('No gist selected');

return;
}

const gist = await gists.getGist(selected.block.id);
// selected file to insert
const file = await selectFile(gist);
if (!file) {
services.logger.debug('No file selected');

return;
}
await insertText(editor, file.content);
services.insights.track(command);
} catch (err) {
const error: Error = err as Error;
logger.error(`${command} > ${error && error.message}`);
insights.exception(command, { messsage: error.message });
utils.notify.error('Could Not Insert', `Reason: ${error.message}`);
}
};

return [command, commandFn];
};

export { insert };

0 comments on commit 7e7c359

Please sign in to comment.